feat: Switch adds rules prop

This commit is contained in:
luoxiao 2024-08-22 17:24:24 +08:00 committed by luoxiaozero
parent d50ff53e7e
commit ab456c7f6f
5 changed files with 86 additions and 16 deletions

View file

@ -91,8 +91,18 @@ pub fn DatePicker(
view! { view! {
<Binder target_ref=date_picker_ref> <Binder target_ref=date_picker_ref>
<div node_ref=date_picker_ref class=class_list!["thaw-date-picker", class] on:click=move |_| open_panel()> <div
<Input id name value=show_date_text on_focus=move |_| open_panel() on_blur=on_input_blur> node_ref=date_picker_ref
class=class_list!["thaw-date-picker", class]
on:click=move |_| open_panel()
>
<Input
id
name
value=show_date_text
on_focus=move |_| open_panel()
on_blur=on_input_blur
>
<InputSuffix slot> <InputSuffix slot>
<Icon icon=icondata_ai::AiCalendarOutlined style="font-size: 18px" /> <Icon icon=icondata_ai::AiCalendarOutlined style="font-size: 18px" />
</InputSuffix> </InputSuffix>

View file

@ -41,19 +41,19 @@ view! {
<Field label="Textarea" name="textarea"> <Field label="Textarea" name="textarea">
<Textarea rules=vec![TextareaRule::required(true.into())]/> <Textarea rules=vec![TextareaRule::required(true.into())]/>
</Field> </Field>
<Field name="radio"> <Field label="Radio" name="radio">
<RadioGroup rules=vec![RadioGroupRule::required(true.into())] > <RadioGroup rules=vec![RadioGroupRule::required(true.into())] >
<Radio label="0" value="false"/> <Radio label="0" value="false"/>
<Radio label="1" value="true"/> <Radio label="1" value="true"/>
</RadioGroup> </RadioGroup>
</Field> </Field>
<Field name="combobox"> <Field label="Combobox" name="combobox">
<Combobox rules=vec![ComboboxRule::required(true.into())] placeholder="Select an animal" clearable=true> <Combobox rules=vec![ComboboxRule::required(true.into())] placeholder="Select an animal" clearable=true>
<ComboboxOption value="cat" text="Cat"/> <ComboboxOption value="cat" text="Cat"/>
<ComboboxOption value="dog" text="Dog" /> <ComboboxOption value="dog" text="Dog" />
</Combobox> </Combobox>
</Field> </Field>
<Field name="spinbutton"> <Field label="SpinButton" name="spinbutton">
<SpinButton <SpinButton
step_page=1 step_page=1
rules=vec![SpinButtonRule::validator(move |v, _| { rules=vec![SpinButtonRule::validator(move |v, _| {
@ -87,6 +87,9 @@ view! {
</SliderLabel> </SliderLabel>
</Slider> </Slider>
</Field> </Field>
<Field label="Switch" name="switch">
<Switch/>
</Field>
<div style="margin-top: 8px"> <div style="margin-top: 8px">
<Button <Button
button_type=ButtonType::Submit button_type=ButtonType::Submit

View file

@ -10,8 +10,11 @@ view! {
### Switch Props ### Switch Props
| Name | Type | Default | Description | | Name | Type | Default | Description |
| ------- | ------------------- | -------------------- | --------------------------------------------------- | | --- | --- | --- | --- |
| class | `MaybeProp<String>` | `Default::default()` | | | class | `MaybeProp<String>` | `Default::default()` | |
| checked | `Model<bool>` | `false` | Defines the controlled checked state of the Switch. | | id | `MaybeProp<String>` | `Default::default()` | |
| label | `MaybeProp<String>` | `Default::default()` | The Switch's label. | | name | `MaybeProp<String>` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. |
| rules | `Vec<SwitchRule>` | `vec![]` | The rules to validate Field. |
| checked | `Model<bool>` | `false` | Defines the controlled checked state of the Switch. |
| label | `MaybeProp<String>` | `Default::default()` | The Switch's label. |

View file

@ -1,9 +1,19 @@
use crate::{FieldInjection, FieldValidationState, Rule};
use leptos::{html, prelude::*}; use leptos::{html, prelude::*};
use std::ops::Deref;
use thaw_utils::{class_list, mount_style, Model}; use thaw_utils::{class_list, mount_style, Model};
#[component] #[component]
pub fn Switch( pub fn Switch(
#[prop(optional, into)] class: MaybeProp<String>, #[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional, into)] id: MaybeProp<String>,
/// A string specifying a name for the input control.
/// This name is submitted along with the control's value when the form data is submitted.
#[prop(optional, into)]
name: MaybeProp<String>,
/// The rules to validate Field.
#[prop(optional, into)]
rules: Vec<SwitchRule>,
/// Defines the controlled checked state of the Switch. /// Defines the controlled checked state of the Switch.
#[prop(optional, into)] #[prop(optional, into)]
checked: Model<bool>, checked: Model<bool>,
@ -12,12 +22,14 @@ pub fn Switch(
label: MaybeProp<String>, label: MaybeProp<String>,
) -> impl IntoView { ) -> impl IntoView {
mount_style("switch", include_str!("./switch.css")); mount_style("switch", include_str!("./switch.css"));
let (id, name) = FieldInjection::use_id_and_name(id, name);
let id = uuid::Uuid::new_v4().to_string(); let validate = Rule::validate(rules, checked, name);
let id = Signal::derive(move || id.get().unwrap_or_else(|| uuid::Uuid::new_v4().to_string()));
let input_ref = NodeRef::<html::Input>::new(); let input_ref = NodeRef::<html::Input>::new();
let on_change = move |_| { let on_change = move |_| {
let input = input_ref.get_untracked().unwrap(); let input = input_ref.get_untracked().unwrap();
checked.set(input.checked()); checked.set(input.checked());
validate.run(Some(SwitchRuleTrigger::Change));
}; };
view! { view! {
@ -26,7 +38,8 @@ pub fn Switch(
class="thaw-switch__input" class="thaw-switch__input"
role="switch" role="switch"
type="checkbox" type="checkbox"
id=id.clone() id=id
name=name
checked=checked.get_untracked() checked=checked.get_untracked()
node_ref=input_ref node_ref=input_ref
on:change=on_change on:change=on_change
@ -45,7 +58,7 @@ pub fn Switch(
{move || { {move || {
if let Some(label) = label.get() { if let Some(label) = label.get() {
view! { view! {
<label class="thaw-switch__label" for=id.clone()> <label class="thaw-switch__label" for=id>
{label} {label}
</label> </label>
} }
@ -57,3 +70,34 @@ pub fn Switch(
</div> </div>
} }
} }
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub enum SwitchRuleTrigger {
#[default]
Change,
}
pub struct SwitchRule(Rule<bool, SwitchRuleTrigger>);
impl SwitchRule {
pub fn validator(
f: impl Fn(&bool, Signal<Option<String>>) -> Result<(), FieldValidationState>
+ Send
+ Sync
+ 'static,
) -> Self {
Self(Rule::validator(f))
}
pub fn with_trigger(self, trigger: SwitchRuleTrigger) -> Self {
Self(Rule::with_trigger(self.0, trigger))
}
}
impl Deref for SwitchRule {
type Target = Rule<bool, SwitchRuleTrigger>;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -94,8 +94,18 @@ pub fn TimePicker(
view! { view! {
<Binder target_ref=time_picker_ref> <Binder target_ref=time_picker_ref>
<div node_ref=time_picker_ref class=class_list!["thaw-time-picker", class] on:click=move |_| open_panel()> <div
<Input id name value=show_time_text on_focus=move |_| open_panel() on_blur=on_input_blur> node_ref=time_picker_ref
class=class_list!["thaw-time-picker", class]
on:click=move |_| open_panel()
>
<Input
id
name
value=show_time_text
on_focus=move |_| open_panel()
on_blur=on_input_blur
>
<InputSuffix slot> <InputSuffix slot>
<Icon icon=icondata_ai::AiClockCircleOutlined style="font-size: 18px" /> <Icon icon=icondata_ai::AiClockCircleOutlined style="font-size: 18px" />
</InputSuffix> </InputSuffix>