waterui_core/components/native.rs
1//! This module provides platform-specific native views that can wrap platform-native UI components.
2
3use core::any::type_name;
4
5use crate::{AnyView, Environment, View, layout::StretchAxis};
6
7/// A wrapper for platform-specific native UI components.
8///
9/// `Native<T>` allows embedding platform-specific UI elements within the view hierarchy.
10/// The generic parameter `T` represents the platform-specific component type.
11///
12/// # Panics
13///
14/// Attempting to render a `Native<T>` view directly will panic. This type is intended
15/// to be handled by platform-specific rendering backends.
16#[derive(Debug)]
17pub struct Native<T: NativeView> {
18 native: T,
19 fallback: Option<AnyView>,
20}
21
22impl<T: NativeView> Native<T> {
23 /// Creates a new `Native<T>` view wrapping the given native component.
24 ///
25 /// # Arguments
26 ///
27 /// * `native` - The platform-specific native UI component to wrap.
28 pub const fn new(native: T) -> Self {
29 Self {
30 native,
31 fallback: None,
32 }
33 }
34
35 /// Sets a fallback view to be used if the native view cannot be rendered.
36 ///
37 /// # Arguments
38 /// * `fallback` - The fallback view to display.
39 #[must_use]
40 pub fn with_fallback(mut self, fallback: impl View) -> Self {
41 self.fallback = Some(AnyView::new(fallback));
42 self
43 }
44
45 /// Consumes the wrapper and returns the inner native component.
46 #[must_use]
47 pub fn into_inner(self) -> T {
48 self.native
49 }
50}
51
52impl<T: 'static + NativeView> View for Native<T> {
53 #[allow(unused)]
54 #[allow(clippy::needless_return)]
55 fn body(self, _env: &Environment) -> impl View {
56 self.fallback
57 .unwrap_or_else(|| panic!("Native view ({})", type_name::<T>()))
58 }
59
60 fn stretch_axis(&self) -> StretchAxis {
61 NativeView::stretch_axis(&self.native)
62 }
63}
64
65/// A trait for all views handled by the native backend.
66///
67/// This includes:
68/// - Configurable views (`TextField`, Slider, Toggle, etc.)
69/// - Raw views (Color, Spacer, Divider, Container, etc.)
70///
71/// The native backend uses this trait to query layout behavior.
72pub trait NativeView {
73 /// Which axis (or axes) this view stretches to fill available space.
74 fn stretch_axis(&self) -> StretchAxis {
75 StretchAxis::None
76 }
77}