From e4154d5c4b95ebcf2c782effcb74950034d4471f Mon Sep 17 00:00:00 2001 From: luoxiao Date: Tue, 28 Mar 2023 12:37:24 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 12 +++++++ src/button/button.css | 21 ++++++++++++ src/button/mod.rs | 17 ++++++++++ src/card/card.css | 30 +++++++++++++++++ src/card/mod.rs | 76 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 9 +++++ src/modal/mod.rs | 39 ++++++++++++++++++++++ src/modal/modal.css | 49 ++++++++++++++++++++++++++++ src/table/mod.rs | 12 +++++++ src/table/table.css | 16 +++++++++ src/teleport/mod.rs | 31 ++++++++++++++++++ 11 files changed, 312 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/button/button.css create mode 100644 src/button/mod.rs create mode 100644 src/card/card.css create mode 100644 src/card/mod.rs create mode 100644 src/lib.rs create mode 100644 src/modal/mod.rs create mode 100644 src/modal/modal.css create mode 100644 src/table/mod.rs create mode 100644 src/table/table.css create mode 100644 src/teleport/mod.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7a3defa --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "melt-ui" +version = "0.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +leptos = { version = "0.2.4", features = ["stable"] } +stylers = "0.3.0" +web-sys = "0.3.61" +leptos_dom = { version = "0.2.4" } diff --git a/src/button/button.css b/src/button/button.css new file mode 100644 index 0000000..a4e1327 --- /dev/null +++ b/src/button/button.css @@ -0,0 +1,21 @@ +.melt-button { + height: 34px; + padding: 0 16px; + background-color: #0000; + border: 1px solid #555a; + border-radius: 5px; + cursor: pointer; +} + +.melt-button:hover { + transition: all 0.3s; + border-color: #555; +} + +.melt-button--text { + border: none; +} + +.melt-button--text:hover { + color: #4af; +} \ No newline at end of file diff --git a/src/button/mod.rs b/src/button/mod.rs new file mode 100644 index 0000000..90ead58 --- /dev/null +++ b/src/button/mod.rs @@ -0,0 +1,17 @@ +use leptos::*; +use stylers::style_sheet; + +#[component] +pub fn Button(cx: Scope, #[prop(default = false)] text: bool, children: Children) -> impl IntoView { + let class_name = style_sheet!("./src/button/button.css"); + let class = move || if text { + "melt-button melt-button--text" + } else { + "melt-button" + }; + view! {cx, class=class_name, + + } +} diff --git a/src/card/card.css b/src/card/card.css new file mode 100644 index 0000000..cfffedb --- /dev/null +++ b/src/card/card.css @@ -0,0 +1,30 @@ +.melt-card { + display: flex; + flex-direction: column; + overflow: hidden; +} +.melt-card__header { + font-weight: 600; + display: flex; + align-items: center; +} +.melt-card__header-extra { + display: flex; + align-items: center; +} +.melt-card__header-content { + flex: 1; +} +.melt-card__header, +.melt-card__content, +.melt-card__footer { + padding: 12px 28px; + background-color: #fff; +} +.melt-card__header { + padding: 20px 28px; +} +.melt-card__header + .melt-card__content, +.melt-card__footer { + padding: 0 28px 20px; +} diff --git a/src/card/mod.rs b/src/card/mod.rs new file mode 100644 index 0000000..bc8a7b0 --- /dev/null +++ b/src/card/mod.rs @@ -0,0 +1,76 @@ +use leptos::*; +use stylers::style_sheet; + +#[component] +pub fn Card( + cx: Scope, + #[prop(default = None)] title: Option, + #[prop(default = None)] header: Option, + #[prop(default = None)] header_extra: Option, + children: Children, + #[prop(default = None)] footer: Option, +) -> impl IntoView { + let class_name = style_sheet!("./src/card/card.css"); + view! { + cx, class=class_name, +
+ { + if header.is_some() || title.is_some() { + view! { + cx, class=class_name, +
+
+ { + if let Some(header) = header { + view! { + cx, + <> + { header(cx) } + + } + } else { + view! { + cx, + <> + { title } + + } + } + } +
+ { + if let Some(header_extra) = header_extra { + view! { + cx, class=class_name, +
+ { header_extra(cx)} +
+ }.into() + } else { + None + } + } +
+ }.into() + } else { + None + } + } +
+ { children(cx) } +
+ { + if let Some(footer) = footer { + view! { + cx, class=class_name, + + }.into() + } else { + None + } + } +
+ } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ab4d10c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,9 @@ +mod button; +mod card; +mod modal; +mod table; +mod teleport; + +pub use button::*; +pub use modal::*; +pub use table::*; diff --git a/src/modal/mod.rs b/src/modal/mod.rs new file mode 100644 index 0000000..23f1d72 --- /dev/null +++ b/src/modal/mod.rs @@ -0,0 +1,39 @@ +use crate::card::*; +use crate::teleport::*; +use leptos::*; +use stylers::style_sheet; + +#[component] +pub fn Modal( + cx: Scope, + #[prop(default = None)] title: Option, + children: Children, + #[prop(default = None)] footer: Option, + open: ReadSignal, + #[prop(default = None)] on_cancel: Option>, +) -> impl IntoView { + let class_name = style_sheet!("./src/modal/modal.css"); + let header_extra = |cx| { + view! { + cx, + <> + + { "x" } + + + } + }; + view! { + cx, class=class_name, + +
+
+
+ + {children(cx)} + +
+
+
+ } +} diff --git a/src/modal/modal.css b/src/modal/modal.css new file mode 100644 index 0000000..2e3f6b9 --- /dev/null +++ b/src/modal/modal.css @@ -0,0 +1,49 @@ +.melt-modal-container { + z-index: 2001; +} +.melt-modal-mask { + position: fixed; + top: 0; + right: 0; + left: 0; + bottom: 0; + background-color: #0007; + z-index: 2000; +} +.melt-modal-body { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + min-height: 100%; + z-index: 2002; +} +.melt-model-card { + width: 600px; + margin: auto; +} +.melt-model-card__header-close { + cursor: pointer; +} +.melt-model-card__header-title { + font-size: 16px; +} +.melt-modal-body { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + min-height: 100%; + z-index: 2002; +} +.melt-modal-body .melt-card { + width: 480px; + margin: auto; +} +.melt-modal-body .melt-card__header-content { + font-size: 16px; +} diff --git a/src/table/mod.rs b/src/table/mod.rs new file mode 100644 index 0000000..e90b404 --- /dev/null +++ b/src/table/mod.rs @@ -0,0 +1,12 @@ +use leptos::*; +use stylers::style_sheet; + +#[component] +pub fn Table(cx: Scope, children: Children) -> impl IntoView { + let class_name = style_sheet!("./src/table/table.css"); + view! {cx, class=class_name, + + {children(cx)} +
+ } +} \ No newline at end of file diff --git a/src/table/table.css b/src/table/table.css new file mode 100644 index 0000000..8ba55f4 --- /dev/null +++ b/src/table/table.css @@ -0,0 +1,16 @@ +.melt-table { + width: 100%; +} + +.melt-table th { + text-align: inherit; +} + +.melt-table td, +.melt-table th { + padding: 10px 12px; +} + +.melt-table thead { + border-bottom: 1px solid #888; +} \ No newline at end of file diff --git a/src/teleport/mod.rs b/src/teleport/mod.rs new file mode 100644 index 0000000..d97c349 --- /dev/null +++ b/src/teleport/mod.rs @@ -0,0 +1,31 @@ +use leptos::*; +use web_sys::Element; + +/// https://github.com/solidjs/solid/blob/main/packages/solid/web/src/index.ts#L56 +#[component] +pub fn Teleport(cx: Scope, #[prop(optional)] to: Option, children: Children) -> impl IntoView { + let parent = if let Some(to) = to { + document().query_selector(to.as_str()).expect("element not to exist").expect("element not to exist") + } else { + Element::from(document().body().expect("body element not to exist")) + }; + + #[cfg(all(target_arch = "wasm32"))] + { + use leptos_dom::Mountable; + let node = children(cx).into_view(cx); + parent.append_child(&node.get_mountable_node()).unwrap(); + } + + #[cfg(not(target_arch = "wasm32"))] + { + _ = cx; + _ = parent; + _ = children; + } + + view! { + cx, + <> + } +} \ No newline at end of file