ppc login works in mme main
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use crate::{Button, ButtonVariant, Dialog, DialogDescription, DialogTitle};
|
||||
|
||||
|
||||
const STYLE: &str = r#".dx-control {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 5.5rem;
|
||||
min-height: 5.5rem;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.85rem 0.65rem 0.7rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 0.375rem;
|
||||
background: var(--surface);
|
||||
box-shadow: 0 4px 16px rgb(0 0 0 / 16%);
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
gap: 0.45rem;
|
||||
outline: none;
|
||||
transition: background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease,
|
||||
transform 120ms ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dx-control:hover:not(:disabled):not([data-kind="display"]) {
|
||||
background: var(--surface-2);
|
||||
border-color: color-mix(in oklab, var(--accent) 45%, var(--border));
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.dx-control:focus-visible {
|
||||
box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 40%, transparent),
|
||||
0 4px 16px rgb(0 0 0 / 16%);
|
||||
}
|
||||
|
||||
.dx-control[data-enabled="true"] {
|
||||
border-color: color-mix(in oklab, var(--accent) 70%, var(--border));
|
||||
background: color-mix(in oklab, var(--accent) 16%, var(--surface));
|
||||
}
|
||||
|
||||
.dx-control[data-kind="display"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.dx-control:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.dx-control-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
border-radius: 0.375rem;
|
||||
background: var(--surface-2);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.dx-control[data-enabled="true"] .dx-control-icon {
|
||||
background: color-mix(in oklab, var(--accent) 28%, var(--surface-2));
|
||||
color: var(--accent-text);
|
||||
}
|
||||
|
||||
.dx-control-icon svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.dx-control-name {
|
||||
color: var(--text);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dx-control-value {
|
||||
color: var(--text-2);
|
||||
font-size: 0.7rem;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dx-control-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0.75rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
"#;
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Default)]
|
||||
#[non_exhaustive]
|
||||
pub enum ControlKind {
|
||||
/// Click toggles an on/off state (optional confirm).
|
||||
#[default]
|
||||
Toggle,
|
||||
/// Click triggers an action (optional confirm).
|
||||
Action,
|
||||
/// Read-only display of a setting/value.
|
||||
Display,
|
||||
}
|
||||
|
||||
impl ControlKind {
|
||||
fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
ControlKind::Toggle => "toggle",
|
||||
ControlKind::Action => "action",
|
||||
ControlKind::Display => "display",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Control(
|
||||
/// Visible label under the icon.
|
||||
name: String,
|
||||
#[props(default)]
|
||||
kind: ControlKind,
|
||||
/// Toggle enabled state (Toggle kind).
|
||||
#[props(default)]
|
||||
enabled: bool,
|
||||
/// Optional value line (useful for Display, also ok for others).
|
||||
value: Option<String>,
|
||||
/// If set, show a confirmation dialog before toggling/acting.
|
||||
confirm: Option<String>,
|
||||
/// Fired for Action after confirm (or immediately if no confirm).
|
||||
onclick: Option<EventHandler<()>>,
|
||||
/// Fired for Toggle with the new enabled value after confirm (or immediately).
|
||||
on_enabled_change: Option<EventHandler<bool>>,
|
||||
/// Icon element (e.g. a dioxus-icons lucide component).
|
||||
children: Element,
|
||||
) -> Element {
|
||||
let mut confirm_open = use_signal(|| false);
|
||||
let needs_confirm = confirm.is_some();
|
||||
|
||||
let do_commit = move || {
|
||||
match kind {
|
||||
ControlKind::Toggle => {
|
||||
if let Some(cb) = on_enabled_change {
|
||||
cb.call(!enabled);
|
||||
}
|
||||
}
|
||||
ControlKind::Action => {
|
||||
if let Some(cb) = onclick {
|
||||
cb.call(());
|
||||
}
|
||||
}
|
||||
ControlKind::Display => {}
|
||||
}
|
||||
};
|
||||
|
||||
rsx! {
|
||||
crate::OnceStyle { href: "dioxus-components/control", css: STYLE }
|
||||
|
||||
button {
|
||||
class: "dx-control",
|
||||
"data-slot": "control",
|
||||
"data-kind": kind.as_str(),
|
||||
"data-enabled": enabled.to_string(),
|
||||
r#type: "button",
|
||||
disabled: kind == ControlKind::Display,
|
||||
onclick: move |_| {
|
||||
if kind == ControlKind::Display {
|
||||
return;
|
||||
}
|
||||
if needs_confirm {
|
||||
confirm_open.set(true);
|
||||
} else {
|
||||
do_commit();
|
||||
}
|
||||
},
|
||||
span { class: "dx-control-icon", {children} }
|
||||
span { class: "dx-control-name", "{name}" }
|
||||
if let Some(val) = &value {
|
||||
span { class: "dx-control-value", "{val}" }
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(msg) = confirm {
|
||||
Dialog {
|
||||
open: Some(confirm_open()),
|
||||
on_open_change: move |open| confirm_open.set(open),
|
||||
DialogTitle { "Confirm" }
|
||||
DialogDescription { "{msg}" }
|
||||
div { class: "dx-control-actions",
|
||||
Button {
|
||||
variant: ButtonVariant::Ghost,
|
||||
onclick: move |_| confirm_open.set(false),
|
||||
"Cancel"
|
||||
}
|
||||
Button {
|
||||
variant: ButtonVariant::Primary,
|
||||
onclick: move |_| {
|
||||
confirm_open.set(false);
|
||||
do_commit();
|
||||
},
|
||||
"Confirm"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
mod component;
|
||||
pub use component::*;
|
||||
Reference in New Issue
Block a user