app: Swap to using dioxus instead of yew

This commit is contained in:
traxys 2023-07-03 23:20:19 +02:00
parent 02a4187c39
commit c80cc99255
29 changed files with 3558 additions and 3639 deletions

231
app/src/bootstrap/mod.rs Normal file
View file

@ -0,0 +1,231 @@
use dioxus::prelude::*;
use dioxus_class::prelude::*;
pub mod bs {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(js_namespace = bootstrap)]
extern "C" {
pub type Modal;
#[wasm_bindgen(static_method_of = Modal, js_name = "getInstance")]
pub fn get_instance(selector: &str) -> Modal;
#[wasm_bindgen(static_method_of = Modal, js_name = "getOrCreateInstance")]
pub fn get_or_create_instance(selector: &str) -> Modal;
#[wasm_bindgen(method)]
pub fn hide(this: &Modal);
#[wasm_bindgen(method)]
pub fn show(this: &Modal);
}
}
pub fn Spinner(cx: Scope) -> Element {
cx.render(rsx! {
div { class: "spinner-border", role: "status", span { class: "visually-hidden", "Loading" } }
})
}
#[derive(Props)]
pub struct ModalContentProps<'a> {
pub children: Element<'a>,
}
pub fn ModalHeader<'a>(cx: Scope<'a, ModalContentProps<'a>>) -> Element {
cx.render(rsx! {
div { class: "modal-header", &cx.props.children }
})
}
pub fn ModalBody<'a>(cx: Scope<'a, ModalContentProps<'a>>) -> Element {
cx.render(rsx! {
div { class: "modal-body", &cx.props.children }
})
}
pub fn ModalFooter<'a>(cx: Scope<'a, ModalContentProps<'a>>) -> Element {
cx.render(rsx! {
div { class: "modal-footer", &cx.props.children }
})
}
#[derive(Props)]
pub struct ModalProps<'a> {
#[props(into)]
pub id: String,
#[props(default = false)]
pub fade: bool,
#[props(default = false)]
pub centered: bool,
#[props(into)]
pub labeled_by: Option<String>,
pub children: Element<'a>,
}
pub fn Modal<'a>(cx: Scope<'a, ModalProps<'a>>) -> Element<'a> {
let mut classes = Class::from(vec!["modal"]);
if cx.props.fade {
classes.append("fade");
}
let mut dialog_class = Class::from(vec!["modal-dialog"]);
if cx.props.centered {
dialog_class.append("modal-dialog-centered");
}
cx.render(rsx! {
div { class: classes, id: cx.props.id.as_str(), tabindex: "-1", "aria-labelledby": cx.props.labeled_by.as_deref(), "aria-hidden": "true",
div { class: dialog_class,
div { class: "modal-content", &cx.props.children }
}
}
})
}
#[derive(Props)]
pub struct TitledModalProps<'a> {
#[props(into)]
pub id: String,
#[props(default = false)]
pub fade: bool,
#[props(default = false)]
pub centered: bool,
#[props(into)]
pub title: String,
pub children: Element<'a>,
}
pub fn TitledModal<'a>(cx: Scope<'a, TitledModalProps<'a>>) -> Element {
cx.render(rsx! {
Modal {
id: &cx.props.id,
fade: cx.props.fade,
centered: cx.props.centered,
labeled_by: "{cx.props.id}Label",
ModalHeader {
h1 { class: "modal-title fs-5", id: "{cx.props.id}Label", cx.props.title.as_str() }
button {
"type": "button",
class: "btn-close",
"data-bs-dismiss": "modal",
"aria-label": "Close"
}
}
&cx.props.children
}
})
}
#[derive(Props)]
pub struct FormModalProps<'a> {
#[props(into)]
pub id: String,
#[props(default = false)]
pub fade: bool,
#[props(default = false)]
pub centered: bool,
#[props(into)]
pub title: String,
#[props(into, default = "Submit".into())]
pub submit_label: String,
pub on_submit: EventHandler<'a, FormEvent>,
pub children: Element<'a>,
}
pub fn FormModal<'a>(cx: Scope<'a, FormModalProps<'a>>) -> Element {
cx.render(rsx! {
TitledModal {
id: &cx.props.id,
fade: cx.props.fade,
centered: cx.props.centered,
title: &cx.props.title,
ModalBody {
form {
id: "{cx.props.id}Form",
prevent_default: "onsubmit",
onsubmit: move |ev| cx.props.on_submit.call(ev),
&cx.props.children
}
}
ModalFooter {
button {
"type": "button",
class: "btn btn-danger",
"data-bs-dismiss": "modal",
"Cancel"
}
button {
"type": "submit",
class: "btn btn-primary",
form: "{cx.props.id}Form",
cx.props.submit_label.as_str()
}
}
}
})
}
#[derive(Props)]
pub struct ConfirmDangerModalProps<'a> {
#[props(into)]
pub id: String,
#[props(default = false)]
pub fade: bool,
#[props(default = false)]
pub centered: bool,
#[props(into)]
pub title: String,
pub on_confirm: EventHandler<'a, MouseEvent>,
pub children: Element<'a>,
}
pub fn ConfirmDangerModal<'a>(cx: Scope<'a, ConfirmDangerModalProps<'a>>) -> Element {
cx.render(rsx! {
TitledModal {
id: &cx.props.id,
fade: cx.props.fade,
centered: cx.props.centered,
title: &cx.props.title,
ModalBody { &cx.props.children }
ModalFooter {
button {
"type": "button",
class: "btn btn-secondary",
"data-bs-dismiss": "modal",
"Cancel"
}
button {
"type": "button",
class: "btn btn-danger",
"data-bs-dismiss": "modal",
onclick: move |ev| cx.props.on_confirm.call(ev),
"Confirm"
}
}
}
})
}
#[derive(Props)]
pub struct ModalToggleProps<'a> {
#[props(into)]
pub class: String,
#[props(into)]
pub modal_id: String,
pub children: Element<'a>,
}
pub fn ModalToggleButton<'a>(cx: Scope<'a, ModalToggleProps<'a>>) -> Element {
cx.render(rsx! {
button {
class: cx.props.class.as_str(),
"data-bs-toggle": "modal",
"data-bs-target": "#{cx.props.modal_id}",
&cx.props.children
}
})
}