biji_ui/components/dialog/
dialog.rs

1use leptos::{ev::click, prelude::*};
2use leptos_use::use_event_listener;
3
4use crate::{
5    cn, components::dialog::context::DialogContext, custom_animated_show::CustomAnimatedShow,
6};
7
8use super::context::RootContext;
9
10#[component]
11pub fn Trigger(children: Children, #[prop(into, optional)] class: String) -> impl IntoView {
12    let dialog_ctx = expect_context::<DialogContext>();
13
14    let trigger_ref = dialog_ctx.trigger_ref;
15
16    view! {
17        <TriggerEvents>
18            <button node_ref={trigger_ref} class={class}>
19                {children()}
20            </button>
21        </TriggerEvents>
22    }
23}
24
25#[component]
26pub fn TriggerEvents(children: Children) -> impl IntoView {
27    let dialog_ctx = expect_context::<DialogContext>();
28
29    let _ = use_event_listener(dialog_ctx.trigger_ref, click, move |_| {
30        dialog_ctx.toggle();
31        if let Some(trigger_ref) = dialog_ctx.trigger_ref.get() {
32            let _ = trigger_ref.blur();
33        }
34    });
35
36    children()
37}
38
39#[component]
40pub fn Content(
41    children: ChildrenFn,
42    /// Optional CSS class to apply to both show and hide classes
43    #[prop(into, optional)]
44    class: String,
45    /// Optional CSS class to apply if `when == true`
46    #[prop(into, optional)]
47    show_class: String,
48    /// Optional CSS class to apply if `when == false`
49    #[prop(into, optional)]
50    hide_class: String,
51) -> impl IntoView {
52    let dialog_ctx = expect_context::<DialogContext>();
53
54    // let children = StoredValue::new(children);
55
56    view! {
57        <CustomAnimatedShow
58            when={dialog_ctx.open}
59            show_class={cn!(class, show_class)}
60            hide_class={cn!(class, hide_class)}
61            hide_delay={dialog_ctx.hide_delay}
62        >
63            {children()}
64        </CustomAnimatedShow>
65    }
66}
67
68#[component]
69pub fn Overlay(
70    #[prop(into, optional)] class: String,
71    /// Optional CSS class to apply if `when == true`
72    #[prop(into, optional)]
73    show_class: String,
74    /// Optional CSS class to apply if `when == false`
75    #[prop(into, optional)]
76    hide_class: String,
77) -> impl IntoView {
78    let dialog_ctx = expect_context::<DialogContext>();
79    let root_ctx = expect_context::<RootContext>();
80
81    let overlay_ref = root_ctx.overlay_ref;
82
83    view! {
84        <CustomAnimatedShow
85            when={dialog_ctx.open}
86            show_class={cn!(class, show_class)}
87            hide_class={cn!(class, hide_class)}
88            hide_delay={dialog_ctx.hide_delay}
89        >
90            <OverlayEvents>
91                <div node_ref={overlay_ref} style="inset: 0; width: 100%; height: 100%"></div>
92            </OverlayEvents>
93        </CustomAnimatedShow>
94    }
95}
96
97#[component]
98pub fn OverlayEvents(children: Children) -> impl IntoView {
99    let dialog_ctx = expect_context::<DialogContext>();
100    let root_ctx = expect_context::<RootContext>();
101
102    let _ = use_event_listener(root_ctx.overlay_ref, click, move |_| {
103        dialog_ctx.open.set(false);
104    });
105
106    children()
107}
108
109#[component]
110pub fn Close(children: Children, #[prop(into, optional)] class: String) -> impl IntoView {
111    let root_ctx = expect_context::<RootContext>();
112
113    let close_ref = root_ctx.close_ref;
114
115    view! {
116        <CloseEvents>
117            <button node_ref={close_ref} class={class}>
118                {children()}
119            </button>
120        </CloseEvents>
121    }
122}
123
124#[component]
125pub fn CloseEvents(children: Children) -> impl IntoView {
126    let dialog_ctx = expect_context::<DialogContext>();
127    let root_ctx = expect_context::<RootContext>();
128
129    let _ = use_event_listener(root_ctx.close_ref, click, move |_| {
130        dialog_ctx.open.set(false);
131    });
132
133    children()
134}