Skip to main content

plushie_widget_sdk/
lib.rs

1//! # plushie-widget-sdk
2//!
3//! The public SDK for plushie. Widget authors depend on this crate to
4//! implement the [`PlushieWidget`](registry::PlushieWidget) trait and
5//! build custom native widgets. The [`prelude`] module re-exports
6//! everything a widget author needs; [`iced`] is re-exported so widgets
7//! don't need a direct iced dependency.
8//!
9//! Beyond the public widget-author surface, this crate also re-exports
10//! the widget infrastructure that the renderer crates and the Rust SDK
11//! direct-mode runner need internally. Those re-exports live in
12//! [`runtime`] and are not part of the widget-author API.
13//!
14//! ## Dependencies
15//!
16//! Widget crates need both `plushie-widget-sdk` and `plushie-core`
17//! as direct dependencies. The widget derive macros
18//! (`#[derive(WidgetEvent)]`, `#[derive(WidgetCommand)]`,
19//! `#[derive(WidgetProps)]`, `#[derive(PlushieWidget)]`) emit code
20//! that references `::plushie_core::*` paths.
21//!
22//! ## iced stability
23//!
24//! iced is re-exported as a transitive dependency. iced surfaces may
25//! change on any plushie minor release. For stable semantics, prefer
26//! prelude names and [`iced_convert`] conversions; reach into
27//! `plushie_widget_sdk::iced::*` only for iced-specific constructs
28//! that are not in the prelude.
29//!
30//! ## Module guide
31//!
32//! **Widget-author API:**
33//! - [`prelude`] - common re-exports for widget authors
34//! - [`registry`] - `PlushieWidget` trait, `WidgetRegistry`, `WidgetSet`,
35//!   `InitCtx`, `GenerationCounter`
36//! - [`app`] - `PlushieAppBuilder` for registering widgets
37//! - [`prop_helpers`] - public prop extraction helpers
38//! - [`render_ctx`] - [`render_ctx::RenderCtx`], the core rendering context for all widgets
39//! - [`testing`] - test factory helpers
40//!
41//! **Renderer-internal support API:**
42//! - [`runtime`] - widget messages, theme resolution, built-in widget
43//!   set, validation flag, render entry point, and canvas query helpers
44//! - [`protocol`] - wire protocol facade over `plushie-core`
45//! - [`image_registry`] - image handle cache used by [`render_ctx::RenderCtx`]
46//!
47//! The renderer state engine, retained tree, and wire codec live in the
48//! sibling crate `plushie-renderer-engine`; widget authors do not
49//! depend on it.
50//!
51//! **Private implementation modules:**
52//! `message`, `widget`, and `theming`
53
54#![deny(missing_docs)]
55
56// Ensure catch_unwind works: widget panic isolation requires unwinding.
57// If this fails, remove `panic = "abort"` from your Cargo profile.
58// On WASM, catch_unwind is a no-op (panics always abort), so skip this check.
59#[cfg(all(not(test), not(target_arch = "wasm32"), panic = "abort"))]
60compile_error!(
61    "plushie-core requires panic=\"unwind\" (the default). \
62     Widget panic isolation via catch_unwind is a no-op with panic=\"abort\"."
63);
64
65// -- Public SDK modules (stable API for widget authors) --
66pub mod app;
67pub mod canvas_engine;
68pub mod prelude;
69pub mod prop_helpers;
70pub mod registry;
71pub mod render_ctx;
72pub mod testing;
73
74pub mod animation;
75
76/// Re-export of [`plushie_core::diagnostics`] for convenience so widget
77/// crates that already depend on `plushie-widget-sdk` don't need a
78/// second direct dep on `plushie-core` just for diagnostic emission.
79pub use plushie_core::diagnostics;
80
81pub mod fonts;
82
83pub mod iced_convert;
84
85pub(crate) mod a11y;
86pub mod shared_state;
87pub(crate) mod svg_guard;
88pub(crate) mod validate;
89
90// -- Renderer and direct-mode support modules --
91pub mod runtime;
92
93// -- Private implementation modules --
94pub mod image_registry;
95#[allow(missing_docs)]
96mod message;
97pub mod protocol;
98#[allow(missing_docs)]
99mod theming;
100#[allow(missing_docs)]
101mod widget;
102
103// Re-export the widget derive macros for widget authors.
104//
105// The generated code references `::plushie_core::*` paths so widget
106// crates must still add `plushie-core` as a direct dependency
107// alongside `plushie-widget-sdk`; see the crate-level "Dependencies"
108// section.
109//
110// `PlushieWidget` from plushie_core_macros is the derive macro; it
111// shares a name with the `registry::PlushieWidget` trait. Rust
112// permits the coexistence (derives and traits inhabit different
113// namespaces) but importers must take care not to glob-import only
114// the trait and then use `#[derive(PlushieWidget)]`.
115pub use plushie_core_macros::{PlushieWidget, WidgetCommand, WidgetEvent, WidgetProps};
116
117/// Sorted list of every built-in widget type name reserved by the
118/// stock renderer's iced widget set.
119///
120/// Re-exported from `plushie-core` so tooling can share the same list
121/// without depending on this SDK or iced.
122pub use plushie_core::BUILTIN_TYPE_NAMES;
123
124// Re-export iced so widget crates can use `plushie_widget_sdk::iced::*` without
125// adding a direct iced dependency. This avoids version conflicts when
126// plushie-core bumps its iced version. Widgets that use only
127// `plushie_widget_sdk::prelude::*` and `plushie_widget_sdk::iced::*` get the upgrade
128// automatically.
129pub use iced;
130
131/// Trait alias for renderer types that can be used with the plushie widget pipeline.
132///
133/// Both `iced::Renderer` (tiny-skia, used by headless and windowed modes) and
134/// `()` (null renderer, used by mock mode) satisfy these bounds.
135///
136/// This trait is sealed: only `iced::Renderer` and `()` implement it,
137/// and new super-trait bounds can be added without breaking external
138/// code (external crates cannot implement `PlushieRenderer`).
139pub trait PlushieRenderer:
140    sealed::Sealed
141    + iced::advanced::Renderer
142    + iced::advanced::text::Renderer<Font = iced::Font>
143    + iced::advanced::image::Renderer<Handle = iced::advanced::image::Handle>
144    + iced::advanced::svg::Renderer
145    + iced::advanced::renderer::Headless
146    + iced::advanced::graphics::geometry::Renderer
147    + 'static
148{
149}
150
151impl PlushieRenderer for () {}
152impl PlushieRenderer for iced::Renderer {}
153
154mod sealed {
155    /// Sealing trait for [`super::PlushieRenderer`]. Not part of the
156    /// public API; keeps `PlushieRenderer` closed to external impls.
157    pub trait Sealed {}
158    impl Sealed for () {}
159    impl Sealed for super::iced::Renderer {}
160}
161
162/// Convenience alias for the `Element` type returned by
163/// [`PlushieWidget::render`](registry::PlushieWidget::render).
164///
165/// Equivalent to `iced::Element<'a, Message, iced::Theme, R>`. Widget
166/// impls that are generic over the renderer should write
167/// `PlushieElement<'a, R>`; widgets that only ever render under the
168/// real iced renderer can omit the parameter (`PlushieElement<'a>`)
169/// and get `iced::Renderer` as the default.
170pub type PlushieElement<'a, R = iced::Renderer> =
171    iced::Element<'a, crate::runtime::Message, iced::Theme, R>;