1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! The app-facing `api` feature: builders
//! returning `impl View<State>` compositions over the platform-agnostic
//! `controls`/`runtime`/`events` machinery `crate` already carries — the
//! facade-glue half of this crate that sanctions depending on `frust`.
//!
//! # Feature-gated, not the crate's default shape
//!
//! Everything under this module compiles ONLY behind the default-on
//! `frust-api` feature — `cargo check -p frust-native-widgets
//! --no-default-features` must still hold the platform-plugin charter line
//! (`frust-plugin` + FFI crates only, `docs/ARCHITECTURE.md`'s Module
//! Structure): no `frust`/`frust-core` dependency reaches the crate at all
//! with the feature off. See `Cargo.toml`'s comment on why this crate keeps
//! `frust-core` alongside `frust` under the same gate (a downstream `View`
//! impl needs `BuildCtx`/`ChangeFlags`, which the `frust` facade does not
//! re-export).
//!
//! # The internal `NativeWidget` trait is still not the public one
//!
//! Every builder in [`builders`] is a plain data struct implementing
//! [`frust_core::Component`] (`frust-core`'s retained-local-state seam) —
//! never the crate's own `pub(crate)` [`crate::runtime::NativeWidget`] trait,
//! which stays internal permanently.
//!
//! The public form is a different trait entirely:
//! [`crate::component::NativeComponent`], with `&self` methods, already-typed
//! `Props` the app constructs directly, no `decode_props` step and no `Result`
//! returns. The eleven builders here keep riding the internal trait's wire
//! (`params_json` in, `EventPayload` callbacks out) unchanged — bridging the
//! public trait onto the same runtime (`crate::component::Bridge`) is what let
//! that stay true.
//!
//! # Two builder families, one slot shape
//!
//! The eleven built-in controls above are one family (`native_segmented`/
//! `native_stepper` on iOS/macOS only and [`native_tab_bar`] on iOS only — a
//! compile-time refusal banner elsewhere; `native_date_picker` on all three
//! arms, reporting a [`CivilDate`]); [`native_component`] is
//! the **generic** one, mounting any registered
//! [`NativeComponent`](crate::component::NativeComponent) (another plugin's
//! included — an app crate cannot implement one; see that trait's own doc)
//! into the same single `platform_view` slot, reusing the eight's
//! own factory constant, slot counter, sizing rule and refusal placeholder.
//! It is what closes *define → register → mount*; the eight are deliberately
//! not rewritten to route through it (see `src/api/mount.rs`'s module doc).
//!
//! # One `platform_view` slot per control
//!
//! Each builder composes exactly one `frust::platform_view` slot resolving to
//! this crate's one Android factory
//! (`dev.frust.nativewidgets.FrustNativeControlFactory`)
//! — N controls = N slots, within the differ's design envelope (a
//! shared-container optimization is future work).
//!
//! # Native presentations — not a slot
//!
//! [`show_native_alert`] / [`show_native_alert_into`] and
//! [`show_native_sheet`] / [`show_native_sheet_into`] are the app-facing
//! front door to `crate::present`: an alert or a sheet is an imperative
//! request answered by one outcome, never a `platform_view` slot (nor does a
//! sheet host one — its content is a constrained native schema). The `_into`
//! forms write that outcome into an `RwSignal`, the same events-as-signals
//! idiom the builders' `on_...` callbacks follow, spawned on
//! `frust::spawn_local`.
//!
//! # Theme ladder L2
//!
//! Each builder's `Component::build` reads the active theme
//! (`use_context::<Theme>()`) and folds it, via [`theme::resolve`], into the
//! same `params_json` body every other property already rides — see
//! [`theme`]'s module doc for the mapping table and `crate::android::theme`
//! for L1 (the night-qualified `Context` control creation builds against).
/// The date value `native_date_picker` shows and reports — defined beside the
/// control (`crate::controls::date_picker`) because the platform-agnostic
/// event vocabulary carries it too, and re-exported here as the builder's
/// public vocabulary.
pub use crateCivilDate;
pub use ;
pub use ;
/// The app-facing native-presentation entry points over `crate::present`:
/// for an alert and for a sheet, an awaitable form and an events-as-signals
/// form — see the `present` submodule doc.
pub use ;
/// Make sure this build's platform factory exists before the host can look it
/// up — **optional**: every builder already does this for you.
///
/// On iOS the factory a `platform_view` slot resolves to is a Rust
/// `define_class!` Objective-C class (`crate::apple::factory` — zero Swift),
/// and objc2 registers such a class with the Objective-C runtime **lazily**,
/// on the first call from live Rust code. Nothing on the platform side can
/// trigger that: `FrustViewHost` only ever asks for the class *by name*
/// (`NSClassFromString`), which returns nil for a class that was never
/// registered. Every builder in this module therefore forces registration on
/// the same rebuild that publishes its slot — a whole frame before the host's
/// post-frame command poll can resolve it — so an app that just calls
/// `native_button(...)` needs nothing from this function.
///
/// Call it anyway if you want registration to happen at a moment you choose
/// (app startup, say) rather than at first use; it is idempotent, cheap after
/// the first call, and a no-op on every non-iOS target — Android's factory is
/// a Kotlin class that exists whether or not Rust has run.
/// The number of native controls this crate's internal runtime currently
/// retains — the leak bar `registry::Registry::live_count`'s own doc comment
/// describes ("the number the leak bar every create/dispose cycle must
/// return to `0`"), surfaced app-side for exactly one reason: a
/// device-gate harness (a mount/unmount cycler plus a 50-slot stress
/// toggle, `examples/native-widgets-demo/src/pages/stress.rs`'s GATE
/// HARNESS section) needs an in-app readout to prove the teardown-retire
/// path disposes promptly rather than waiting out the differ's
/// missing-streak backstop (`crate::registry`'s module doc's Idle-deferred
/// dispose finding).
///
/// **Diagnostics/gate accessor, not a supported production API.** It leaks
/// no registry type, no `NativeWidget` trait, and no handle — just a plain
/// count. This crate's public-surface decision kept it exactly as it is,
/// for exactly that reason: it says nothing about the runtime's shape, so
/// nothing about it constrains the public
/// [`NativeComponent`](crate::component::NativeComponent) surface. It still
/// carries no compatibility promise — a future release may narrow, rename or
/// remove it outright, and a component's live count is included in the number.
/// Don't build product behavior on it.
///
/// Returns `0` on a re-entrant call (the runtime's own thread-local is
/// already borrowed on this thread — `crate::runtime::with_runtime`'s
/// documented re-entrancy tolerance) as well as on a platform with no live
/// runtime at all; either way indistinguishable from "nothing is mounted"
/// for this accessor's diagnostic purpose.