diff --git a/Cargo.toml b/Cargo.toml index 6ca835b..52b3ee0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,10 @@ icondata = { version = "0.0.7", features = [ "AiLoadingOutlined", "AiCheckCircleFilled", "AiExclamationCircleFilled", - "AiCloseCircleFilled" + "AiCloseCircleFilled", + "AiPlusOutlined", + "AiPlusOutlined", + "AiMinusOutlined", ] } [workspace] diff --git a/demo/src/app.rs b/demo/src/app.rs index 1f4f65d..20a1c39 100644 --- a/demo/src/app.rs +++ b/demo/src/app.rs @@ -31,6 +31,7 @@ pub fn App() -> impl IntoView { + diff --git a/demo/src/pages/components.rs b/demo/src/pages/components.rs index c22e713..3c19165 100644 --- a/demo/src/pages/components.rs +++ b/demo/src/pages/components.rs @@ -117,6 +117,10 @@ fn gen_menu_data() -> Vec { value: "input".into(), label: "Input".into(), }, + MenuItemOption { + value: "input-number".into(), + label: "InputNumber".into(), + }, MenuItemOption { value: "select".into(), label: "Select".into(), diff --git a/demo/src/pages/input_number/mod.rs b/demo/src/pages/input_number/mod.rs new file mode 100644 index 0000000..2537524 --- /dev/null +++ b/demo/src/pages/input_number/mod.rs @@ -0,0 +1,40 @@ +use crate::components::{Demo, DemoCode}; +use leptos::*; +use melt_ui::*; +use prisms::highlight_str; + +#[component] +pub fn InputNumberPage() -> impl IntoView { + let value = create_rw_signal(0); + let value_f64 = create_rw_signal(0.0); + view! { +
+

"InputNumber"

+ + + + + + + + + + } + "#, + "rust" + ) + > + + "" + "" + + +
+ } +} diff --git a/demo/src/pages/mod.rs b/demo/src/pages/mod.rs index c7fcff6..6138c23 100644 --- a/demo/src/pages/mod.rs +++ b/demo/src/pages/mod.rs @@ -12,6 +12,7 @@ mod grid; mod home; mod image; mod input; +mod input_number; mod menu; mod mobile; mod modal; @@ -38,6 +39,7 @@ pub use grid::*; pub use home::*; pub use image::*; pub use input::*; +pub use input_number::*; pub use menu::*; pub use mobile::*; pub use modal::*; diff --git a/src/button/button.css b/src/button/button.css index 7e3f764..4470acf 100644 --- a/src/button/button.css +++ b/src/button/button.css @@ -36,6 +36,11 @@ background-color: #f2f2f2; } +.melt-button--link { + height: auto; + padding: inherit; +} + .melt-button--link:hover { color: var(--font-color-hover); } diff --git a/src/input/mod.rs b/src/input/mod.rs index bad71b9..d0a3df8 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -41,10 +41,12 @@ pub fn Input( let theme = use_theme(Theme::light); mount_style("input", include_str!("./input.css")); + let value_trigger = create_trigger(); let on_input = move |ev| { let input_value = event_target_value(&ev); if let Some(allow_value) = allow_value.as_ref() { if !allow_value.call(input_value.clone()) { + value_trigger.notify(); return; } } @@ -74,7 +76,10 @@ pub fn Input(
impl IntoView { +pub fn InputNumber( + #[prop(optional, into)] value: MaybeRwSignal, + #[prop(optional, into)] placeholder: MaybeSignal, + #[prop(into)] step: MaybeSignal, +) -> impl IntoView +where + T: Add + Sub, + T: Default + Clone + FromStr + ToString + 'static, +{ + let input_value = create_rw_signal(String::default()); + create_effect(move |prev| { + value.with(|value| { + let value = value.to_string(); + if let Some(prev) = prev { + if value == prev { + return prev; + } + } + input_value.set(value.clone()); + value + }) + }); + + let allow_value = move |v: String| { + let Ok(v) = v.parse::() else { return false }; + value.set(v); + true + }; + let step: StoredMaybeSignal<_> = step.into(); + + let add = move |_| { + value.set(value.get_untracked() + step.get_untracked()); + }; + let sub = move |_| { + value.set(value.get_untracked() - step.get_untracked()); + }; view! { - + + + + + + } } diff --git a/src/utils/maybe_signal_store.rs b/src/utils/maybe_signal_store.rs index 825ad2d..1d0e99c 100644 --- a/src/utils/maybe_signal_store.rs +++ b/src/utils/maybe_signal_store.rs @@ -1,4 +1,4 @@ -use leptos::{MaybeSignal, Signal, SignalGet, SignalWith, StoredValue}; +use leptos::{MaybeSignal, Signal, SignalGet, SignalGetUntracked, SignalWith, StoredValue}; #[derive(Clone)] pub enum StoredMaybeSignal @@ -29,6 +29,24 @@ impl SignalGet for StoredMaybeSignal { } } +impl SignalGetUntracked for StoredMaybeSignal { + type Value = T; + + fn get_untracked(&self) -> Self::Value { + match self { + StoredMaybeSignal::StoredValue(value) => value.get_value(), + StoredMaybeSignal::Signal(signal) => signal.get_untracked(), + } + } + + fn try_get_untracked(&self) -> Option { + match self { + StoredMaybeSignal::StoredValue(value) => value.try_get_value(), + StoredMaybeSignal::Signal(signal) => signal.try_get_untracked(), + } + } +} + impl SignalWith for StoredMaybeSignal { type Value = T;