diff --git a/Cargo.lock b/Cargo.lock index 1cddc00..fc390fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,6 +260,8 @@ dependencies = [ "eyre", "git2", "icondata", + "magic", + "tailwind_fuse", "tokio", "tower-http", "tracing", @@ -268,6 +270,41 @@ dependencies = [ "vespid", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "derive-where" version = "1.2.7" @@ -654,6 +691,12 @@ dependencies = [ "syn", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -780,6 +823,16 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "magic" +version = "0.1.0" +dependencies = [ + "icondata", + "icondata_core", + "tailwind_fuse", + "vespid", +] + [[package]] name = "matchers" version = "0.1.0" @@ -817,6 +870,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -846,6 +905,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1225,6 +1294,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.90" @@ -1271,6 +1346,28 @@ dependencies = [ "syn", ] +[[package]] +name = "tailwind_fuse" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9d32d52c3191836fe1858b6b38442d1e536eeb11883b2041e6db080a208c2d" +dependencies = [ + "nom", + "tailwind_fuse_macro", +] + +[[package]] +name = "tailwind_fuse_macro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89fd8a13e8e105a886fe9d15aa60580602be9ee9a17235e552f19faa3d7834f4" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -1606,7 +1703,6 @@ version = "0.1.0" dependencies = [ "axum", "html-escape", - "icondata_core", "serde", "thiserror 2.0.6", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 51052e2..b88c3e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,15 @@ [workspace] members = [ - ".", + ".", "magic", "vespid", "vespid/macros" ] [workspace.dependencies] vespid.path = "vespid" +magic.path = "magic" +icondata = { version = "0.5", default-features = false, features = ["lucide"] } +tailwind_fuse = { version = "0.3.1", features = ["variant"] } axum = "0.7" tokio = { version = "1", features = ["full"] } @@ -16,7 +19,8 @@ version = "0.1.0" edition = "2021" [dependencies] -vespid = { workspace = true, features = ["icons"] } +vespid.workspace = true +magic.workspace = true tokio.workspace = true axum.workspace = true eyre = "0.6.12" @@ -25,5 +29,6 @@ tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } tracing-error = "0.2.1" git2 = "0.19.0" -icondata = { version = "0.5", default-features = false, features = ["lucide"] } +icondata.workspace = true tower-http = { version = "0.6.2", features = ["full"] } +tailwind_fuse.workspace = true diff --git a/magic/Cargo.toml b/magic/Cargo.toml new file mode 100644 index 0000000..ce46dea --- /dev/null +++ b/magic/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "magic" +version = "0.1.0" +edition = "2024" + +[dependencies] +icondata_core = "0.1" +icondata.workspace = true +vespid.workspace = true +tailwind_fuse.workspace = true diff --git a/magic/src/button.rs b/magic/src/button.rs new file mode 100644 index 0000000..c0f69eb --- /dev/null +++ b/magic/src/button.rs @@ -0,0 +1,65 @@ +use tailwind_fuse::*; + +#[derive(TwClass)] +#[tw( + class = "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" +)] +pub struct Button { + pub variant: ButtonVariant, + pub size: ButtonSize, +} + +#[derive(TwVariant)] +pub enum ButtonVariant { + #[tw( + default, + class = "bg-primary text-primary-foreground hover:bg-primary/90" + )] + Primary, + #[tw( + class = "border-primary border bg-transparent text-foreground hover:bg-primary hover:text-primary-foreground" + )] + OutlinePrimary, + #[tw(class = "bg-secondary text-secondary-foreground hover:bg-secondary/90")] + Secondary, + #[tw(class = "bg-success text-success-foreground hover:bg-success/90")] + Success, + #[tw( + class = "border-success border bg-transparent text-foreground hover:bg-success hover:text-success-foreground" + )] + OutlineSuccess, + #[tw(class = "bg-destructive text-destructive-foreground hover:bg-destructive/90")] + Destructive, + #[tw( + class = "border-destructive border bg-transparent text-foreground hover:bg-destructive hover:text-destructive-foreground" + )] + OutlineDestructive, + #[tw( + class = "border border-input bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground" + )] + Outline, + #[tw( + class = "border border-input bg-transparent text-foreground hover:bg-primary hover:text-primary-foreground flex items-center gap-1" + )] + OutlineIcon, + #[tw(class = "hover:bg-accent hover:text-accent-foreground")] + Ghost, + #[tw(class = "bg-secondary/80 text-accent-foreground hover:text-accent-foreground")] + Link, + #[tw( + class = "bg-secondary/80 text-accent-foreground hover:text-accent-foreground flex items-center gap-1" + )] + Icon, +} + +#[derive(TwVariant)] +pub enum ButtonSize { + #[tw(default, class = "h-10 px-4 py-2")] + Default, + #[tw(class = "h-9 rounded-md px-3")] + Small, + #[tw(class = "h-11 rounded-md px-8")] + Large, + #[tw(class = "h-10 w-10")] + Icon, +} diff --git a/magic/src/card.rs b/magic/src/card.rs new file mode 100644 index 0000000..89b6779 --- /dev/null +++ b/magic/src/card.rs @@ -0,0 +1,64 @@ +use tailwind_fuse::tw_merge; +use vespid::{MaybeText, component, view}; + +pub const CARD: &str = "rounded-lg border bg-card text-card-foreground shadow-sm"; +pub const CARD_HEADER: &str = "flex flex-col gap-2 p-6"; +pub const CARD_TITLE: &str = "text-lg font-semibold leading-none tracking-tight"; +pub const CARD_DESCRIPTION: &str = "text-sm text-muted-foreground"; +pub const CARD_CONTENT: &str = "p-6 pt-0"; +pub const CARD_FOOTER: &str = "flex items-center p-6 pt-0"; + +#[component] +pub async fn Card( + #[builder(default, setter(into))] class: MaybeText, + #[builder(default, setter(into))] id: MaybeText, + children: String, +) -> String { + let class = tw_merge!(CARD, class.get().unwrap_or("")); + view! {
"Index"
- - -{amount_of_refreshes.fetch_add(1, std::sync::atomic::Ordering::Relaxed)}
-{amount_of_refreshes.fetch_add(1, std::sync::atomic::Ordering::Relaxed)} " refreshes"
+