radix_leptos_primitives/components/
sheet.rs1use leptos::*;
2use leptos::prelude::*;
3use crate::utils::merge_classes;
4
5#[derive(Debug, Clone, Copy, PartialEq)]
62pub enum SheetPosition {
63 Left,
64 Right,
65 Top,
66 Bottom,
67}
68
69#[derive(Debug, Clone, Copy, PartialEq)]
70pub enum SheetSize {
71 Small,
72 Medium,
73 Large,
74 ExtraLarge,
75 Full,
76}
77
78impl SheetPosition {
79 pub fn as_str(&self) -> &'static str {
80 match self {
81 SheetPosition::Left => "left",
82 SheetPosition::Right => "right",
83 SheetPosition::Top => "top",
84 SheetPosition::Bottom => "bottom",
85 }
86 }
87}
88
89impl SheetSize {
90 pub fn as_str(&self) -> &'static str {
91 match self {
92 SheetSize::Small => "sm",
93 SheetSize::Medium => "md",
94 SheetSize::Large => "lg",
95 SheetSize::ExtraLarge => "xl",
96 SheetSize::Full => "full",
97 }
98 }
99}
100
101#[component]
103pub fn Sheet(
104 #[prop(optional)] class: Option<String>,
105 #[prop(optional)] style: Option<String>,
106 #[prop(optional)] children: Option<Children>,
107 #[prop(optional)] open: Option<bool>,
108 #[prop(optional)] position: Option<SheetPosition>,
109 #[prop(optional)] size: Option<SheetSize>,
110 #[prop(optional)] on_open_change: Option<Callback<bool>>,
111) -> impl IntoView {
112 let open = open.unwrap_or(false);
113 let position = position.unwrap_or(SheetPosition::Right);
114 let size = size.unwrap_or(SheetSize::Medium);
115 let on_open_change = on_open_change.unwrap_or_else(|| Callback::new(|_| {}));
116
117 let class = merge_classes(vec![
118 "sheet",
119 position.as_str(),
120 size.as_str(),
121 if open { "open" } else { "closed" },
122 class.as_deref().unwrap_or(""),
123 ]);
124
125 view! {
126 <div
127 class=class
128 style=style
129 role="dialog"
130 aria-modal="true"
131 data-position=position.as_str()
132 data-size=size.as_str()
133 data-open=open
134 >
135 {children.map(|c| c())}
136 </div>
137 }
138}
139
140#[component]
142pub fn SheetContent(
143 #[prop(optional)] class: Option<String>,
144 #[prop(optional)] style: Option<String>,
145 #[prop(optional)] children: Option<Children>,
146) -> impl IntoView {
147 let class = merge_classes(vec![
148 "sheet-content",
149 class.as_deref().unwrap_or(""),
150 ]);
151
152 view! {
153 <div
154 class=class
155 style=style
156 >
157 {children.map(|c| c())}
158 </div>
159 }
160}
161
162#[component]
164pub fn SheetHeader(
165 #[prop(optional)] class: Option<String>,
166 #[prop(optional)] style: Option<String>,
167 #[prop(optional)] children: Option<Children>,
168) -> impl IntoView {
169 let class = merge_classes(vec![
170 "sheet-header",
171 class.as_deref().unwrap_or(""),
172 ]);
173
174 view! {
175 <div
176 class=class
177 style=style
178 >
179 {children.map(|c| c())}
180 </div>
181 }
182}
183
184#[component]
186pub fn SheetTitle(
187 #[prop(optional)] class: Option<String>,
188 #[prop(optional)] style: Option<String>,
189 #[prop(optional)] children: Option<Children>,
190) -> impl IntoView {
191 let class = merge_classes(vec![
192 "sheet-title",
193 class.as_deref().unwrap_or(""),
194 ]);
195
196 view! {
197 <h2
198 class=class
199 style=style
200 >
201 {children.map(|c| c())}
202 </h2>
203 }
204}
205
206#[component]
208pub fn SheetDescription(
209 #[prop(optional)] class: Option<String>,
210 #[prop(optional)] style: Option<String>,
211 #[prop(optional)] children: Option<Children>,
212) -> impl IntoView {
213 let class = merge_classes(vec![
214 "sheet-description",
215 class.as_deref().unwrap_or(""),
216 ]);
217
218 view! {
219 <p
220 class=class
221 style=style
222 >
223 {children.map(|c| c())}
224 </p>
225 }
226}
227
228#[component]
230pub fn SheetBody(
231 #[prop(optional)] class: Option<String>,
232 #[prop(optional)] style: Option<String>,
233 #[prop(optional)] children: Option<Children>,
234) -> impl IntoView {
235 let class = merge_classes(vec![
236 "sheet-body",
237 class.as_deref().unwrap_or(""),
238 ]);
239
240 view! {
241 <div
242 class=class
243 style=style
244 >
245 {children.map(|c| c())}
246 </div>
247 }
248}
249
250#[component]
252pub fn SheetFooter(
253 #[prop(optional)] class: Option<String>,
254 #[prop(optional)] style: Option<String>,
255 #[prop(optional)] children: Option<Children>,
256) -> impl IntoView {
257 let class = merge_classes(vec![
258 "sheet-footer",
259 class.as_deref().unwrap_or(""),
260 ]);
261
262 view! {
263 <div
264 class=class
265 style=style
266 >
267 {children.map(|c| c())}
268 </div>
269 }
270}
271
272#[component]
274pub fn SheetClose(
275 #[prop(optional)] class: Option<String>,
276 #[prop(optional)] style: Option<String>,
277 #[prop(optional)] children: Option<Children>,
278 #[prop(optional)] on_click: Option<Callback<()>>,
279) -> impl IntoView {
280 let on_click = on_click.unwrap_or_else(|| Callback::new(|_| {}));
281
282 let class = merge_classes(vec![
283 "sheet-close",
284 class.as_deref().unwrap_or(""),
285 ]);
286
287 view! {
288 <button
289 class=class
290 style=style
291 on:click=move |_| on_click.run(())
292 aria-label="Close sheet"
293 >
294 {children.map(|c| c())}
295 </button>
296 }
297}
298
299
300#[cfg(test)]
301mod tests {
302 use super::*;
303 use proptest::prelude::*;
304
305 #[test]
306 fn test_sheet_component_creation() {
307 assert!(true);
308 }
309
310 #[test]
311 fn test_sheet_with_position_component_creation() {
312 assert!(true);
313 }
314
315 proptest! {
316 #[test]
317 fn test_sheet_props(_class in ".*", _style in ".*") {
318 assert!(true);
319 }
320
321 #[test]
322 fn test_sheet_open_state(_open: bool, _position_index in 0..4usize, _size_index in 0..5usize) {
323 assert!(true);
324 }
325
326 #[test]
327 fn test_sheet_positions(_position_index in 0..4usize) {
328 assert!(true);
329 }
330
331 #[test]
332 fn test_sheet_sizes(_size_index in 0..5usize) {
333 assert!(true);
334 }
335
336 #[test]
337 fn test_sheet_content_props(_class in ".*", _style in ".*") {
338 assert!(true);
339 }
340
341 #[test]
342 fn test_sheet_header_props(_class in ".*", _style in ".*") {
343 assert!(true);
344 }
345
346 #[test]
347 fn test_sheet_title_props(_class in ".*", _style in ".*") {
348 assert!(true);
349 }
350
351 #[test]
352 fn test_sheet_description_props(_class in ".*", _style in ".*") {
353 assert!(true);
354 }
355
356 #[test]
357 fn test_sheet_body_props(_class in ".*", _style in ".*") {
358 assert!(true);
359 }
360
361 #[test]
362 fn test_sheet_footer_props(_class in ".*", _style in ".*") {
363 assert!(true);
364 }
365
366 #[test]
367 fn test_sheet_close_props(_class in ".*", _style in ".*") {
368 assert!(true);
369 }
370 }
371}