freya_hooks/
use_theme.rs

1use dioxus_core::prelude::try_consume_context;
2use dioxus_hooks::{
3    use_context,
4    use_context_provider,
5};
6use dioxus_signals::{
7    Readable,
8    Signal,
9};
10
11use crate::theming::*;
12
13/// Provide a custom [`Theme`].
14pub fn use_init_theme(theme_cb: impl FnOnce() -> Theme) -> Signal<Theme> {
15    use_context_provider(|| Signal::new(theme_cb()))
16}
17
18/// Provide the default [`Theme`].
19pub fn use_init_default_theme() -> Signal<Theme> {
20    use_context_provider(|| Signal::new(Theme::default()))
21}
22
23/// Subscribe to [`Theme`] changes.
24pub fn use_theme() -> Signal<Theme> {
25    use_context::<Signal<Theme>>()
26}
27
28/// Subscribe to [`Theme`] changes, default theme will be used if there is no provided [`Theme`].
29///
30/// Primarily used by built-in components that have no control of whether they will inherit a [`Theme`] or not.
31pub fn use_get_theme() -> Theme {
32    try_consume_context::<Signal<Theme>>()
33        .map(|v| v.read().clone())
34        .unwrap_or_default()
35}
36
37/// This macro has three arguments separator by commas.
38///
39/// 1. The theme property. This should be `&cx.props.theme`.
40/// 2. The name of the theme that you want to use.
41///
42/// # Examples
43///
44/// ```rust
45/// use freya::prelude::*;
46///
47/// #[derive(Props, PartialEq, Clone)]
48/// pub struct ButtonProps {
49///     /// Theme override.
50///     pub theme: Option<ButtonThemeWith>,
51///     // ...
52/// }
53///
54/// pub fn Button(props: ButtonProps) -> Element {
55///     let ButtonTheme {
56///         padding,
57///         width,
58///         background,
59///         ..
60///     } = use_applied_theme!(&props.theme, button);
61///     // ...
62///
63///     # VNode::empty()
64/// }
65/// ```
66#[macro_export]
67macro_rules! use_applied_theme {
68    ($theme_prop:expr, $theme_name:ident) => {{
69        let mut theme = ::freya_hooks::use_get_theme();
70        let mut requested_theme = theme.$theme_name;
71
72        if let Some(theme_override) = $theme_prop {
73            requested_theme.apply_optional(theme_override);
74        }
75
76        requested_theme.apply_colors(&theme.colors);
77
78        requested_theme
79    }};
80}