compose_rust/extensions.rs
1//! Compile-time widget extensions.
2//!
3//! An extension is a pair of source files, one Rust and one Kotlin, built into both sides.
4//! It is not a runtime plugin: a deployed Renderer has no way to load a new widget.
5//!
6//! An application that builds a paired Renderer owns a patched copy of this registry. To add a
7//! widget, update the descriptor, append its wire entries in both macros as needed, then declare
8//! its Dioxus element and typed component here. Codegen consumes the resulting closed schema and
9//! regenerates `Protocol.gen.kt`. The paired Kotlin source still has to render the new kind.
10
11/// Hash input for extension property types, which the flat enum tables cannot express.
12/// Extension widget tags start at 100. Tags 1 to 29 belong to the core vocabulary, and an
13/// extension that sat inside that range would collide with a core widget the next time one
14/// was added. Extension property tags are append-only from 27, which is where the core
15/// property tags stopped when this example was written.
16pub(crate) const SCHEMA_DESCRIPTOR: &str =
17 "extension=LinearProgressIndicator#100(progress:f32#27);";
18
19macro_rules! define_widget_schema_with_extensions {
20 ($define:ident; $schema:ident, $name:ident { $($base:tt)* }) => {
21 $define!($schema, $name {
22 $($base)*
23 // Extension widget tags are append-only.
24 LinearProgressIndicator = 100,
25 });
26 };
27}
28
29macro_rules! define_property_schema_with_extensions {
30 ($define:ident; $schema:ident, $name:ident { $($base:tt)* }) => {
31 $define!($schema, $name {
32 $($base)*
33 // Extension property tags are append-only.
34 Progress = 27,
35 });
36 };
37}
38
39pub(crate) use define_property_schema_with_extensions;
40pub(crate) use define_widget_schema_with_extensions;
41
42use crate as dioxus_elements;
43use dioxus_core::Element;
44use dioxus_core_macro::{Props, component, rsx};
45
46pub mod elements {
47 #![allow(non_upper_case_globals)]
48
49 use crate::elements::AttributeDescription;
50
51 pub mod linearprogressindicator {
52 use super::AttributeDescription;
53
54 pub const TAG_NAME: &str = "LinearProgressIndicator";
55 pub const NAME_SPACE: Option<&str> = None;
56 pub const progress: AttributeDescription = ("progress", None, false);
57 }
58}
59
60/// Material 3's determinate linear progress indicator, as a worked extension example.
61#[component]
62pub fn LinearProgressIndicator(progress: f32) -> Element {
63 rsx! { linearprogressindicator { progress } }
64}