adui_dioxus/components/
app.rs1use 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#[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 pub fn open(&self) {
21 let _ = self.overlay.open(OverlayKind::Modal, true);
22 }
23}
24
25#[derive(Clone, Default)]
28pub struct AppContextValue {
29 pub message: Option<MessageApi>,
30 pub notification: Option<NotificationApi>,
31 pub modal: Option<ModalApi>,
32}
33
34#[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#[component]
47pub fn App(props: AppProps) -> Element {
48 let AppProps {
49 class,
50 style,
51 children,
52 } = props;
53
54 let overlay = use_overlay_provider();
56
57 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 MessageHost {}
80 NotificationHost {}
81 }
82}
83
84pub fn use_app() -> AppContextValue {
87 try_use_context::<AppContextValue>().unwrap_or_default()
88}
89
90pub fn use_message() -> Option<MessageApi> {
92 use_app().message
93}
94
95pub fn use_notification() -> Option<NotificationApi> {
97 use_app().notification
98}
99
100pub fn use_modal() -> Option<ModalApi> {
102 use_app().modal
103}
104
105#[cfg(test)]
106mod app_tests {
107 use super::*;
108
109 #[test]
110 fn app_context_value_default() {
111 let ctx = AppContextValue::default();
112 assert!(ctx.message.is_none());
113 assert!(ctx.notification.is_none());
114 assert!(ctx.modal.is_none());
115 }
116
117 #[test]
118 fn app_context_value_clone() {
119 let ctx1 = AppContextValue::default();
120 let ctx2 = ctx1.clone();
121 assert!(ctx1.message.is_none());
123 assert!(ctx2.message.is_none());
124 assert!(ctx1.notification.is_none());
125 assert!(ctx2.notification.is_none());
126 assert!(ctx1.modal.is_none());
127 assert!(ctx2.modal.is_none());
128 }
129
130 #[test]
131 fn app_context_value_with_all_fields() {
132 let ctx = AppContextValue {
134 message: None,
135 notification: None,
136 modal: None,
137 };
138 assert!(ctx.message.is_none());
139 assert!(ctx.notification.is_none());
140 assert!(ctx.modal.is_none());
141 }
142
143 #[test]
144 fn modal_api_structure() {
145 fn assert_modal_api_methods() {
149 }
153 assert_modal_api_methods();
154 }
155
156 #[test]
157 fn app_props_structure() {
158 fn assert_app_props_structure() {
162 }
165 assert_app_props_structure();
166 }
167}