mirror of
https://github.com/mztlive/dx-admin-template.git
synced 2025-12-22 21:59:59 +00:00
重构优化
This commit is contained in:
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn AspectRatio(
|
||||
#[props(default = 1.0f32)] ratio: f32,
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
use chrono::{Datelike, Duration, NaiveDate};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
const WEEKDAY_LABELS: [&str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
||||
|
||||
fn first_day_of_month(date: NaiveDate) -> NaiveDate {
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Card(#[props(into, default)] class: Option<String>, children: Element) -> Element {
|
||||
let classes = merge_class("ui-card", class);
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Checkbox(
|
||||
#[props(default)] checked: bool,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone)]
|
||||
struct CollapsibleContext {
|
||||
open: Signal<bool>,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct ComboboxOption {
|
||||
pub label: String,
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
use super::button::{Button, ButtonSize, ButtonVariant};
|
||||
use chrono::{Datelike, Duration, NaiveDate};
|
||||
use dioxus::prelude::*;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use super::utils::merge_class;#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::time::SystemTime;
|
||||
use crate::components::ui::PopoverHandle;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct DateRange {
|
||||
pub start: NaiveDate,
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
use dioxus::html::events::{DragEvent, FormEvent};
|
||||
use dioxus::html::{FileData, HasFileData};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct FileMetadata {
|
||||
pub name: String,
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
use crate::components::ui::Label;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum FormMessageVariant {
|
||||
Helper,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Input(
|
||||
#[props(into, default)] class: Option<String>,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Label(
|
||||
#[props(into, default)] class: Option<String>,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//! Each component mirrors the styling and API conventions of the upstream React components while
|
||||
//! remaining idiomatic to Rust and Dioxus.
|
||||
|
||||
mod utils;
|
||||
|
||||
mod accordion;
|
||||
mod alert;
|
||||
mod aspect_ratio;
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Progress(
|
||||
#[props(default = 0.0f32)] value: f32,
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
static RADIO_GROUP_IDS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
fn next_radio_group_name() -> String {
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn ScrollArea(
|
||||
#[props(into, default)] class: Option<String>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum SeparatorOrientation {
|
||||
Horizontal,
|
||||
@@ -21,14 +21,6 @@ impl Default for SeparatorOrientation {
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Separator(
|
||||
#[props(default)] orientation: SeparatorOrientation,
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn data_bool(value: bool) -> &'static str {
|
||||
if value {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::{merge_class, data_bool};
|
||||
#[component]
|
||||
pub fn Sidebar(
|
||||
#[props(default)] collapsed: bool,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Skeleton(
|
||||
#[props(into, default)] class: Option<String>,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Slider(
|
||||
#[props(default = 0.0f32)] value: f32,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Switch(
|
||||
#[props(default)] checked: bool,
|
||||
|
||||
@@ -6,15 +6,7 @@ use std::{
|
||||
|
||||
use crate::components::ui::Checkbox;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Table(#[props(into, default)] class: Option<String>, children: Element) -> Element {
|
||||
let classes = merge_class("ui-table", class);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum TabsOrientation {
|
||||
Horizontal,
|
||||
@@ -28,14 +27,6 @@ struct TabsContext {
|
||||
on_change: Option<EventHandler<String>>,
|
||||
}
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Tabs(
|
||||
#[props(into)] default_value: String,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Textarea(
|
||||
#[props(into, default)] class: Option<String>,
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[component]
|
||||
pub fn Toggle(
|
||||
#[props(default)] pressed: bool,
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
use crate::components::ui::Toggle;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
use super::utils::merge_class;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ToggleGroupMode {
|
||||
Single,
|
||||
|
||||
48
src/components/ui/utils.rs
Normal file
48
src/components/ui/utils.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
/// Merge a base CSS class with an optional extra class string.
|
||||
/// If the extra string is empty or only whitespace, returns just the base class.
|
||||
pub fn merge_class(base: &str, extra: Option<String>) -> String {
|
||||
if let Some(extra) = extra.filter(|extra| !extra.trim().is_empty()) {
|
||||
format!("{base} {}", extra.trim())
|
||||
} else {
|
||||
base.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a boolean to "true" or "false" string for data attributes.
|
||||
pub fn data_bool(value: bool) -> &'static str {
|
||||
if value {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_merge_class_with_extra() {
|
||||
assert_eq!(
|
||||
merge_class("base", Some("extra".to_string())),
|
||||
"base extra"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge_class_without_extra() {
|
||||
assert_eq!(merge_class("base", None), "base");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge_class_with_empty_extra() {
|
||||
assert_eq!(merge_class("base", Some("".to_string())), "base");
|
||||
assert_eq!(merge_class("base", Some(" ".to_string())), "base");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_bool() {
|
||||
assert_eq!(data_bool(true), "true");
|
||||
assert_eq!(data_bool(false), "false");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user