freya_components/theming/
hooks.rs

1use freya_core::{
2    prelude::{
3        ReadState,
4        State,
5        provide_context,
6        provide_context_for_scope_id,
7        try_consume_context,
8        use_consume,
9        use_hook,
10    },
11    scope_id::ScopeId,
12};
13
14use crate::theming::component_themes::Theme;
15
16/// Provides a custom [`Theme`].
17pub fn use_init_theme(theme_cb: impl FnOnce() -> Theme) -> State<Theme> {
18    use_hook(|| {
19        let state = State::create(theme_cb());
20        provide_context(state);
21        state
22    })
23}
24
25pub fn use_init_root_theme(theme_cb: impl FnOnce() -> Theme) -> State<Theme> {
26    use_hook(|| {
27        let state = State::create_in_scope(theme_cb(), ScopeId::ROOT);
28        provide_context_for_scope_id(state, ScopeId::ROOT);
29        state
30    })
31}
32
33/// Subscribe to [`Theme`] changes.
34pub fn use_theme() -> State<Theme> {
35    use_consume::<State<Theme>>()
36}
37
38/// Subscribe to [`Theme`] changes, default theme will be used if there is no provided [`Theme`].
39///
40/// Primarily used by built-in components that have no control of whether they will inherit a [`Theme`] or not.
41pub fn get_theme_or_default() -> ReadState<Theme> {
42    try_consume_context::<State<Theme>>()
43        .map(ReadState::State)
44        .unwrap_or_else(|| ReadState::Owned(Theme::default()))
45}
46
47/// Indicates what type of surface to use.
48#[derive(Clone, Copy, PartialEq, Debug, Default)]
49pub enum SurfaceThemeIndicator {
50    #[default]
51    Primary,
52    Opposite,
53}
54
55/// Provide a [SurfaceThemeIndicator] down to the components.
56pub fn use_init_surface_theme_indicator(theme: impl FnOnce() -> SurfaceThemeIndicator) {
57    use_hook(|| provide_context(theme()))
58}
59
60/// Get the inherited [SurfaceThemeIndicator].
61pub fn use_surface_theme_indicator() -> SurfaceThemeIndicator {
62    use_hook(|| try_consume_context().unwrap_or_default())
63}