adui_dioxus/components/
app.rs

1use crate::components::message::{MessageApi, MessageHost, use_message_entries_provider};
2use crate::components::notification::{
3    NotificationApi, NotificationHost, use_notification_entries_provider,
4};
5use crate::components::overlay::{OverlayHandle, OverlayKind, use_overlay_provider};
6use dioxus::prelude::*;
7
8/// Minimal modal API exposed by `App`.
9#[derive(Clone)]
10pub struct ModalApi {
11    overlay: OverlayHandle,
12}
13
14impl ModalApi {
15    pub fn new(overlay: OverlayHandle) -> Self {
16        Self { overlay }
17    }
18
19    /// Placeholder for future `confirm`/`open` helpers.
20    pub fn open(&self) {
21        let _ = self.overlay.open(OverlayKind::Modal, true);
22    }
23}
24
25/// Context value shared by `App` and consumed by `use_app` / `use_message` /
26/// `use_notification` / `use_modal`.
27#[derive(Clone, Default)]
28pub struct AppContextValue {
29    pub message: Option<MessageApi>,
30    pub notification: Option<NotificationApi>,
31    pub modal: Option<ModalApi>,
32}
33
34/// Props for the top-level `App` container.
35#[derive(Props, Clone, PartialEq)]
36pub struct AppProps {
37    #[props(optional)]
38    pub class: Option<String>,
39    #[props(optional)]
40    pub style: Option<String>,
41    pub children: Element,
42}
43
44/// Top-level App component that wires OverlayManager and exposes global
45/// feedback APIs through context.
46#[component]
47pub fn App(props: AppProps) -> Element {
48    let AppProps {
49        class,
50        style,
51        children,
52    } = props;
53
54    // Install a single overlay manager for this App subtree.
55    let overlay = use_overlay_provider();
56
57    // Install per-App message & notification queues in context.
58    let message_entries = use_message_entries_provider();
59    let notification_entries = use_notification_entries_provider();
60
61    let ctx = AppContextValue {
62        message: Some(MessageApi::new(overlay.clone(), message_entries)),
63        notification: Some(NotificationApi::new(overlay.clone(), notification_entries)),
64        modal: Some(ModalApi::new(overlay)),
65    };
66
67    use_context_provider(|| ctx.clone());
68
69    let class_attr = class.unwrap_or_default();
70    let style_attr = style.unwrap_or_default();
71
72    rsx! {
73        div {
74            class: "{class_attr}",
75            style: "{style_attr}",
76            {children}
77        }
78        // Global feedback hosts
79        MessageHost {}
80        NotificationHost {}
81    }
82}
83
84/// Access the full App context. Returns a default value when used outside of
85/// an `App` subtree so that callers can opt into a graceful fallback.
86pub fn use_app() -> AppContextValue {
87    try_use_context::<AppContextValue>().unwrap_or_default()
88}
89
90/// Convenience hook to access the message API.
91pub fn use_message() -> Option<MessageApi> {
92    use_app().message
93}
94
95/// Convenience hook to access the notification API.
96pub fn use_notification() -> Option<NotificationApi> {
97    use_app().notification
98}
99
100/// Convenience hook to access the modal API.
101pub fn use_modal() -> Option<ModalApi> {
102    use_app().modal
103}