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
use dioxus_core::prelude::try_consume_context;
use dioxus_hooks::{
use_context,
use_context_provider,
};
use dioxus_signals::{
Readable,
Signal,
};
use crate::theming::*;
/// Provide a custom [`Theme`].
pub fn use_init_theme(theme_cb: impl FnOnce() -> Theme) -> Signal<Theme> {
use_context_provider(|| Signal::new(theme_cb()))
}
/// Provide the default [`Theme`].
pub fn use_init_default_theme() -> Signal<Theme> {
use_context_provider(|| Signal::new(Theme::default()))
}
/// Subscribe to [`Theme`] changes.
pub fn use_theme() -> Signal<Theme> {
use_context::<Signal<Theme>>()
}
/// Subscribe to [`Theme`] changes, default theme will be used if there is no provided [`Theme`].
///
/// Primarily used by built-in components that have no control of whether they will inherit a [`Theme`] or not.
pub fn use_get_theme() -> Theme {
try_consume_context::<Signal<Theme>>()
.map(|v| v.read().clone())
.unwrap_or_default()
}
/// This macro has three arguments separator by commas.
///
/// 1. The theme property. This should be `&cx.props.theme`.
/// 2. The name of the theme that you want to use.
///
/// # Examples
///
/// ```rust
/// use freya::prelude::*;
///
/// #[derive(Props, PartialEq, Clone)]
/// pub struct ButtonProps {
/// /// Theme override.
/// pub theme: Option<ButtonThemeWith>,
/// // ...
/// }
///
/// pub fn Button(props: ButtonProps) -> Element {
/// let ButtonTheme {
/// padding,
/// width,
/// background,
/// ..
/// } = use_applied_theme!(&props.theme, button);
/// // ...
///
/// # None
/// }
/// ```
#[macro_export]
macro_rules! use_applied_theme {
($theme_prop:expr, $theme_name:ident) => {{
let mut theme = ::freya_hooks::use_get_theme().$theme_name;
if let Some(theme_override) = $theme_prop {
theme.apply_optional(theme_override);
}
theme
}};
}