mirror of
https://github.com/mztlive/dx-admin-template.git
synced 2025-12-22 21:59:59 +00:00
优化
This commit is contained in:
@@ -26,9 +26,7 @@ pub fn Select(
|
|||||||
#[props(optional)] on_change: Option<EventHandler<String>>,
|
#[props(optional)] on_change: Option<EventHandler<String>>,
|
||||||
) -> Element {
|
) -> Element {
|
||||||
let mut open = use_signal(|| false);
|
let mut open = use_signal(|| false);
|
||||||
let current = use_signal(move || selected.clone());
|
let mut current = use_signal(move || selected.clone());
|
||||||
let on_change_handler = on_change.clone();
|
|
||||||
let trigger_id = id.unwrap_or_default();
|
|
||||||
let mut container_ref = use_signal(|| None as Option<Rc<MountedData>>);
|
let mut container_ref = use_signal(|| None as Option<Rc<MountedData>>);
|
||||||
|
|
||||||
use_effect(move || {
|
use_effect(move || {
|
||||||
@@ -60,87 +58,94 @@ pub fn Select(
|
|||||||
onmounted: move |event| {
|
onmounted: move |event| {
|
||||||
container_ref.set(Some(event.data()));
|
container_ref.set(Some(event.data()));
|
||||||
},
|
},
|
||||||
onblur: {
|
onblur: move |_| {
|
||||||
let mut open_signal = open.clone();
|
open.set(false);
|
||||||
move |_| {
|
|
||||||
open_signal.set(false);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
button {
|
SelectTrigger {
|
||||||
class: "ui-select-trigger",
|
id: id.clone(),
|
||||||
"data-open": if open() { "true" } else { "false" },
|
open: open(),
|
||||||
disabled,
|
disabled,
|
||||||
id: trigger_id.clone(),
|
display_text,
|
||||||
"aria-haspopup": "listbox",
|
on_toggle: move |_| {
|
||||||
"aria-expanded": if open() { "true" } else { "false" },
|
if !disabled {
|
||||||
onclick: {
|
open.set(!open());
|
||||||
let mut open_signal = open.clone();
|
|
||||||
move |_| {
|
|
||||||
if !disabled {
|
|
||||||
let new_state = !open_signal();
|
|
||||||
open_signal.set(new_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
span { "{display_text}" }
|
|
||||||
span {
|
|
||||||
class: "ui-select-icon",
|
|
||||||
"aria-hidden": "true",
|
|
||||||
svg {
|
|
||||||
view_box: "0 0 16 16",
|
|
||||||
xmlns: "http://www.w3.org/2000/svg",
|
|
||||||
path {
|
|
||||||
d: "M4 6l4 4 4-4",
|
|
||||||
fill: "none",
|
|
||||||
stroke: "currentColor",
|
|
||||||
"stroke-width": "1.5",
|
|
||||||
"stroke-linecap": "round",
|
|
||||||
"stroke-linejoin": "round",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if open() {
|
if open() {
|
||||||
div {
|
SelectContent {
|
||||||
class: "ui-select-content",
|
options: options.clone(),
|
||||||
div {
|
selected_value,
|
||||||
class: "ui-select-list",
|
on_select: move |value: String| {
|
||||||
for option in options.iter().cloned() {
|
current.set(Some(value.clone()));
|
||||||
{
|
if let Some(callback) = on_change.as_ref() {
|
||||||
let is_active = selected_value
|
callback.call(value);
|
||||||
.as_ref()
|
}
|
||||||
.map(|value| value == &option.value)
|
open.set(false);
|
||||||
.unwrap_or(false);
|
}
|
||||||
let value = option.value.clone();
|
}
|
||||||
let handler = on_change_handler.clone();
|
}
|
||||||
let mut open_signal = open.clone();
|
}
|
||||||
let mut current_signal = current.clone();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rsx! {
|
#[component]
|
||||||
button {
|
fn SelectTrigger(
|
||||||
class: "ui-select-item",
|
#[props(into, default)] id: Option<String>,
|
||||||
"data-state": if is_active { "active" } else { "inactive" },
|
open: bool,
|
||||||
onmousedown: {
|
disabled: bool,
|
||||||
let value = value.clone();
|
#[props(into)] display_text: String,
|
||||||
let handler = handler.clone();
|
on_toggle: EventHandler<()>,
|
||||||
move |event| {
|
) -> Element {
|
||||||
event.prevent_default();
|
rsx! {
|
||||||
current_signal.set(Some(value.clone()));
|
button {
|
||||||
if let Some(callback) = handler.clone() {
|
class: "ui-select-trigger",
|
||||||
callback.call(value.clone());
|
"data-open": if open { "true" } else { "false" },
|
||||||
}
|
disabled,
|
||||||
open_signal.set(false);
|
id: id.unwrap_or_default(),
|
||||||
}
|
"aria-haspopup": "listbox",
|
||||||
},
|
"aria-expanded": if open { "true" } else { "false" },
|
||||||
span { "{option.label}" }
|
onclick: move |_| on_toggle.call(()),
|
||||||
if is_active {
|
span { "{display_text}" }
|
||||||
span {
|
span {
|
||||||
style: "font-size: 0.75rem; opacity: 0.7;",
|
class: "ui-select-icon",
|
||||||
"✓"
|
"aria-hidden": "true",
|
||||||
}
|
svg {
|
||||||
}
|
view_box: "0 0 16 16",
|
||||||
}
|
xmlns: "http://www.w3.org/2000/svg",
|
||||||
}
|
path {
|
||||||
|
d: "M4 6l4 4 4-4",
|
||||||
|
fill: "none",
|
||||||
|
stroke: "currentColor",
|
||||||
|
"stroke-width": "1.5",
|
||||||
|
"stroke-linecap": "round",
|
||||||
|
"stroke-linejoin": "round",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn SelectContent(
|
||||||
|
options: Vec<SelectOption>,
|
||||||
|
selected_value: Option<String>,
|
||||||
|
on_select: EventHandler<String>,
|
||||||
|
) -> Element {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
class: "ui-select-content",
|
||||||
|
div {
|
||||||
|
class: "ui-select-list",
|
||||||
|
for option in options {
|
||||||
|
{
|
||||||
|
let is_active = selected_value.as_ref().map(|v| v == &option.value).unwrap_or(false);
|
||||||
|
rsx! {
|
||||||
|
SelectItem {
|
||||||
|
option,
|
||||||
|
is_active,
|
||||||
|
on_select
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,3 +154,26 @@ pub fn Select(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn SelectItem(option: SelectOption, is_active: bool, on_select: EventHandler<String>) -> Element {
|
||||||
|
let value = option.value.clone();
|
||||||
|
|
||||||
|
rsx! {
|
||||||
|
button {
|
||||||
|
class: "ui-select-item",
|
||||||
|
"data-state": if is_active { "active" } else { "inactive" },
|
||||||
|
onmousedown: move |event| {
|
||||||
|
event.prevent_default();
|
||||||
|
on_select.call(value.clone());
|
||||||
|
},
|
||||||
|
span { "{option.label}" }
|
||||||
|
if is_active {
|
||||||
|
span {
|
||||||
|
style: "font-size: 0.75rem; opacity: 0.7;",
|
||||||
|
"✓"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user