From 6cb133529909d203d97fb57e770aeff0780de4fb Mon Sep 17 00:00:00 2001 From: luoxiao Date: Thu, 1 Aug 2024 22:50:11 +0800 Subject: [PATCH] feat: Input adds parser and format props --- thaw/src/input/mod.rs | 105 +++++++++++++++++++++++--------- thaw_utils/src/callback.rs | 14 ++--- thaw_utils/src/optional_prop.rs | 2 + 3 files changed, 84 insertions(+), 37 deletions(-) diff --git a/thaw/src/input/mod.rs b/thaw/src/input/mod.rs index 099c3d8..b87bca2 100644 --- a/thaw/src/input/mod.rs +++ b/thaw/src/input/mod.rs @@ -1,21 +1,7 @@ use leptos::{ev, html, prelude::*}; -use thaw_utils::{class_list, mount_style, BoxOneCallback, ComponentRef, Model, OptionalProp}; - -#[derive(Default, Clone)] -pub enum InputVariant { - #[default] - Text, - Password, -} - -impl InputVariant { - pub fn as_str(&self) -> &'static str { - match self { - InputVariant::Text => "text", - InputVariant::Password => "password", - } - } -} +use thaw_utils::{ + class_list, mount_style, ArcOneCallback, BoxOneCallback, ComponentRef, Model, OptionalProp, +}; #[slot] pub struct InputPrefix { @@ -34,34 +20,58 @@ pub struct InputSuffix { #[component] pub fn Input( #[prop(optional, into)] value: Model, - #[prop(optional, into)] allow_value: Option>, - #[prop(optional, into)] variant: MaybeSignal, + #[prop(optional, into)] allow_value: Option>, + #[prop(optional, into)] input_type: MaybeSignal, /// Placeholder text for the input. - #[prop(optional, into)] placeholder: OptionalProp>, + #[prop(optional, into)] + placeholder: OptionalProp>, #[prop(optional, into)] on_focus: Option>, #[prop(optional, into)] on_blur: Option>, /// Whether the input is disabled - #[prop(optional, into)] disabled: MaybeSignal, + #[prop(optional, into)] + disabled: MaybeSignal, #[prop(optional)] input_prefix: Option, #[prop(optional)] input_suffix: Option, #[prop(optional)] comp_ref: ComponentRef, #[prop(optional, into)] class: MaybeProp, + #[prop(optional, into)] parser: OptionalProp>, + #[prop(optional, into)] format: OptionalProp>, // #[prop(attrs)] attrs: Vec<(&'static str, Attribute)>, ) -> impl IntoView { mount_style("input", include_str!("./input.css")); let value_trigger = ArcTrigger::new(); + let parser_none = parser.is_none(); let on_input = { let value_trigger = value_trigger.clone(); - move |ev| { - let input_value = event_target_value(&ev); - if let Some(allow_value) = allow_value.as_ref() { - if !allow_value(input_value.clone()) { - value_trigger.trigger(); - return; + let allow_value = allow_value.clone(); + + move |e| { + if parser_none { + let input_value = event_target_value(&e); + if let Some(allow_value) = allow_value.as_ref() { + if !allow_value(input_value.clone()) { + value_trigger.trigger(); + return; + } } + value.set(input_value); + } + } + }; + let on_change = { + let value_trigger = value_trigger.clone(); + move |e| { + if let Some(parser) = parser.as_ref() { + let parsed_input_value = parser(event_target_value(&e)); + if let Some(allow_value) = allow_value.as_ref() { + if !allow_value(parsed_input_value.clone()) { + value_trigger.trigger(); + return; + } + } + value.set(parsed_input_value); } - value.set(input_value); } }; let is_focus = RwSignal::new(false); @@ -139,14 +149,15 @@ pub fn Input( }} &'static str { + match self { + Self::Text => "text", + Self::Password => "password", + Self::Search => "search", + Self::Tel => "tel", + Self::Url => "url", + Self::Email => "email", + Self::Time => "time", + Self::Date => "date", + Self::DatetimeLocal => "datetime-local", + Self::Month => "month", + Self::Week => "week", + } + } +} + #[derive(Clone)] pub struct InputRef { input_ref: NodeRef, diff --git a/thaw_utils/src/callback.rs b/thaw_utils/src/callback.rs index 9ca008b..c8d3f5b 100644 --- a/thaw_utils/src/callback.rs +++ b/thaw_utils/src/callback.rs @@ -86,28 +86,28 @@ where } #[derive(Clone)] -pub struct ArcOneCallback(Arc); +pub struct ArcOneCallback(Arc Return + Send + Sync + 'static>); -impl ArcOneCallback { +impl ArcOneCallback { pub fn new(f: F) -> Self where - F: Fn(A) + Send + Sync + 'static, + F: Fn(A) -> Return + Send + Sync + 'static, { Self(Arc::new(f)) } } -impl Deref for ArcOneCallback { - type Target = Arc; +impl Deref for ArcOneCallback { + type Target = Arc Return + Send + Sync + 'static>; fn deref(&self) -> &Self::Target { &self.0 } } -impl From for ArcOneCallback +impl From for ArcOneCallback where - F: Fn(A) + Send + Sync + 'static, + F: Fn(A) -> Return + Send + Sync + 'static, { fn from(value: F) -> Self { Self::new(value) diff --git a/thaw_utils/src/optional_prop.rs b/thaw_utils/src/optional_prop.rs index 78c0007..711ccce 100644 --- a/thaw_utils/src/optional_prop.rs +++ b/thaw_utils/src/optional_prop.rs @@ -15,6 +15,8 @@ impl Clone for OptionalProp { } } +impl Copy for OptionalProp {} + impl OptionalProp { pub fn map(self, f: F) -> Option where