impulse_thaw/tab_list/
mod.rs

1mod tab;
2
3pub use tab::*;
4
5use leptos::{context::Provider, html, prelude::*};
6use std::collections::HashMap;
7use thaw_utils::{class_list, mount_style, Model};
8
9#[component]
10pub fn TabList(
11    #[prop(optional, into)] class: MaybeProp<String>,
12    /// The value of the currently selected tab.
13    #[prop(optional, into)]
14    selected_value: Model<String>,
15    children: Children,
16) -> impl IntoView {
17    mount_style("tab-list", include_str!("./tab-list.css"));
18
19    let registered_tabs = RwSignal::new(HashMap::new());
20
21    view! {
22        <Provider value=TabListInjection {
23            previous_selected_value: StoredValue::new(selected_value.get_untracked()),
24            selected_value,
25            registered_tabs,
26        }>
27            <div class=class_list!["thaw-tab-list", class] role="tablist">
28                {children()}
29            </div>
30        </Provider>
31    }
32}
33
34#[derive(Clone)]
35pub(crate) struct TabListInjection {
36    pub previous_selected_value: StoredValue<String>,
37    pub selected_value: Model<String>,
38    pub registered_tabs: RwSignal<HashMap<String, TabRegisterData>>,
39}
40
41impl Copy for TabListInjection {}
42
43impl TabListInjection {
44    pub fn expect_context() -> Self {
45        expect_context()
46    }
47
48    pub fn register(&self, data: TabRegisterData) {
49        self.registered_tabs.update(|map| {
50            map.insert(data.value.clone(), data);
51        });
52    }
53
54    pub fn unregister(&self, value: &String) {
55        self.registered_tabs.update(|map| {
56            map.remove(value);
57        });
58    }
59
60    pub fn on_select(&self, value: String) {
61        self.previous_selected_value
62            .set_value(self.selected_value.get_untracked());
63        self.selected_value.set(value);
64    }
65}
66
67pub(crate) struct TabRegisterData {
68    pub value: String,
69    pub tab_ref: NodeRef<html::Button>,
70}