mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
feat: Switch adds rules prop
This commit is contained in:
parent
d50ff53e7e
commit
ab456c7f6f
5 changed files with 86 additions and 16 deletions
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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. |
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Add table
Reference in a new issue