dioxus_slides/
slide_container.rs

1use dioxus::events::KeyboardEvent;
2use dioxus::html::input_data::keyboard_types::Key;
3use dioxus::prelude::*;
4use std::{marker::PhantomData, str::FromStr};
5
6use crate::Slidable;
7
8#[derive(Props)]
9pub struct SlideContainerProps<'a, S: Slidable + Clone> {
10    #[props(default)]
11    phantom: PhantomData<S>,
12
13    #[props(default = "100%")]
14    width: &'a str,
15    #[props(default = "100%")]
16    height: &'a str,
17
18    #[props(default = "#fff")]
19    background_colour: &'a str,
20
21    #[props(default = false)]
22    show_slide_no: bool,
23
24    #[props(default = true)]
25    show_slide_progress_bar: bool,
26
27    #[props(default = true)]
28    enable_keyboard_navigation: bool,
29}
30
31pub fn SlideContainer<'a, S: Slidable + Clone + Default>(
32    cx: Scope<'a, SlideContainerProps<'a, S>>,
33) -> Element
34where
35    <S as FromStr>::Err: std::fmt::Display,
36    <S as FromStr>::Err: std::fmt::Debug,
37{
38    use_shared_state_provider(cx, || S::default());
39    let deck = use_shared_state::<S>(cx).expect("Failed to get shared state");
40
41    cx.render(rsx! {
42        div {
43            tabindex: "0",
44            onkeydown: |event: KeyboardEvent| {
45                if cx.props.enable_keyboard_navigation {
46                    let a = match event.key() {
47                        Key::ArrowRight => deck.write().next(),
48                        Key::ArrowLeft => deck.write().prev(),
49                        _ => None,
50                    };
51                    if let Some(a) = a {
52                        *deck.write() = a;
53                    }
54                }
55            },
56            style: "position: relative; min-height: 99vh; min-width: 99vw;",
57            if cx.props.show_slide_progress_bar {
58                render! {
59                    progress {
60                        style: "z-index: 10; position: absolute; top: 0; left: 0; width: 100%;",
61                        max: "{deck.read().number_of_slides().to_string()}",
62                        value: "{deck.read().slide_number().to_string()}",
63                    }
64                }
65            }
66            div {
67                style: "z-index: 0; position: absolute; background-color: {cx.props.background_colour}; width: {cx.props.width}; height: {cx.props.height};",
68                deck.read().render(cx)
69            }
70            if cx.props.show_slide_no {
71                render! {
72                    div {
73                        style: "z-index: 10; position: absolute; bottom: 5%; right: 5%;",
74                        "Slide: {deck.read().slide_number().to_string()} of {deck.read().number_of_slides().to_string()}"
75                    }
76                }
77            }
78        }
79    })
80}