mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
feat: Slider adds rules prop
This commit is contained in:
parent
aba7e8818a
commit
9fbf507a36
4 changed files with 78 additions and 12 deletions
|
@ -71,6 +71,22 @@ view! {
|
||||||
<Field label="Time" name="time">
|
<Field label="Time" name="time">
|
||||||
<TimePicker rules=vec![TimePickerRule::required(true.into())]/>
|
<TimePicker rules=vec![TimePickerRule::required(true.into())]/>
|
||||||
</Field>
|
</Field>
|
||||||
|
<Field label="Slider" name="slider">
|
||||||
|
<Slider
|
||||||
|
step=25.0
|
||||||
|
rules=vec![SliderRule::validator(move |v, _| {
|
||||||
|
if v % 2.0 == 0.0 {
|
||||||
|
Err(FieldValidationState::Error("It has to be odd!".to_string()))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
>
|
||||||
|
<SliderLabel value=50.0>
|
||||||
|
"50"
|
||||||
|
</SliderLabel>
|
||||||
|
</Slider>
|
||||||
|
</Field>
|
||||||
<div style="margin-top: 8px">
|
<div style="margin-top: 8px">
|
||||||
<Button
|
<Button
|
||||||
button_type=ButtonType::Submit
|
button_type=ButtonType::Submit
|
||||||
|
|
|
@ -40,14 +40,17 @@ view! {
|
||||||
|
|
||||||
### Slider Props
|
### Slider Props
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| -------- | ------------------- | -------------------- | ------------------------------------------- |
|
| --- | --- | --- | --- |
|
||||||
| class | `MaybeProp<String>` | `Default::default()` | |
|
| class | `MaybeProp<String>` | `Default::default()` | |
|
||||||
| value | `MaybeSignal<f64>` | `0` | The current value of the controlled Slider. |
|
| id | `MaybeProp<String>` | `Default::default()` | |
|
||||||
| min | `MaybeSignal<f64>` | `0` | Min value of the slider. |
|
| 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. |
|
||||||
| max | `MaybeSignal<f64>` | `100` | Max value of the slider. |
|
| rules | `Vec<InputRule>` | `vec![]` | The rules to validate Field. |
|
||||||
| step | `MaybeSignal<f64>` | `0` | The step in which value is incremented. |
|
| value | `MaybeSignal<f64>` | `0` | The current value of the controlled Slider. |
|
||||||
| children | `Option<Children>` | `None` | |
|
| min | `MaybeSignal<f64>` | `0` | Min value of the slider. |
|
||||||
|
| max | `MaybeSignal<f64>` | `100` | Max value of the slider. |
|
||||||
|
| step | `MaybeSignal<f64>` | `0` | The step in which value is incremented. |
|
||||||
|
| children | `Option<Children>` | `None` | |
|
||||||
|
|
||||||
### SliderLabel props
|
### SliderLabel props
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,23 @@ mod slider_label;
|
||||||
|
|
||||||
pub use slider_label::SliderLabel;
|
pub use slider_label::SliderLabel;
|
||||||
|
|
||||||
|
use crate::{FieldInjection, FieldValidationState, Rule};
|
||||||
use leptos::{context::Provider, ev, prelude::*};
|
use leptos::{context::Provider, ev, prelude::*};
|
||||||
|
use std::ops::Deref;
|
||||||
use thaw_components::OptionComp;
|
use thaw_components::OptionComp;
|
||||||
use thaw_utils::{class_list, mount_style, Model};
|
use thaw_utils::{class_list, mount_style, Model};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Slider(
|
pub fn Slider(
|
||||||
#[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<SliderRule>,
|
||||||
/// The current value of the controlled Slider.
|
/// The current value of the controlled Slider.
|
||||||
#[prop(optional, into)]
|
#[prop(optional, into)]
|
||||||
value: Model<f64>,
|
value: Model<f64>,
|
||||||
|
@ -24,7 +34,8 @@ pub fn Slider(
|
||||||
#[prop(optional)] children: Option<Children>,
|
#[prop(optional)] children: Option<Children>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("slider", include_str!("./slider.css"));
|
mount_style("slider", include_str!("./slider.css"));
|
||||||
|
let (id, name) = FieldInjection::use_id_and_name(id, name);
|
||||||
|
let validate = Rule::validate(rules, value, name);
|
||||||
let is_chldren = children.is_some();
|
let is_chldren = children.is_some();
|
||||||
let list_id = is_chldren.then(|| uuid::Uuid::new_v4().to_string());
|
let list_id = is_chldren.then(|| uuid::Uuid::new_v4().to_string());
|
||||||
let current_value = Memo::new(move |_| {
|
let current_value = Memo::new(move |_| {
|
||||||
|
@ -43,6 +54,7 @@ pub fn Slider(
|
||||||
let on_input = move |e: ev::Event| {
|
let on_input = move |e: ev::Event| {
|
||||||
if let Ok(range_value) = event_target_value(&e).parse::<f64>() {
|
if let Ok(range_value) = event_target_value(&e).parse::<f64>() {
|
||||||
value.set(range_value);
|
value.set(range_value);
|
||||||
|
validate.run(Some(SliderRuleTrigger::Input));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +95,8 @@ pub fn Slider(
|
||||||
step=move || step.get()
|
step=move || step.get()
|
||||||
type="range"
|
type="range"
|
||||||
class="thaw-slider__input"
|
class="thaw-slider__input"
|
||||||
|
id=id
|
||||||
|
name=name
|
||||||
on:input=on_input
|
on:input=on_input
|
||||||
value=current_value.get_untracked()
|
value=current_value.get_untracked()
|
||||||
prop:value=move || current_value.get()
|
prop:value=move || current_value.get()
|
||||||
|
@ -111,3 +125,34 @@ impl SliderInjection {
|
||||||
expect_context()
|
expect_context()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone, Copy)]
|
||||||
|
pub enum SliderRuleTrigger {
|
||||||
|
#[default]
|
||||||
|
Input,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SliderRule(Rule<f64, SliderRuleTrigger>);
|
||||||
|
|
||||||
|
impl SliderRule {
|
||||||
|
pub fn validator(
|
||||||
|
f: impl Fn(&f64, Signal<Option<String>>) -> Result<(), FieldValidationState>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) -> Self {
|
||||||
|
Self(Rule::validator(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_trigger(self, trigger: SliderRuleTrigger) -> Self {
|
||||||
|
Self(Rule::with_trigger(self.0, trigger))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for SliderRule {
|
||||||
|
type Target = Rule<f64, SliderRuleTrigger>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
Button, ButtonSize, ConfigInjection, Icon, Input, InputSuffix, Scrollbar, ScrollbarRef, FieldInjection, FieldValidationState, Rule
|
Button, ButtonSize, ConfigInjection, FieldInjection, FieldValidationState, Icon, Input,
|
||||||
|
InputSuffix, Rule, Scrollbar, ScrollbarRef,
|
||||||
};
|
};
|
||||||
use chrono::{Local, NaiveTime, Timelike};
|
use chrono::{Local, NaiveTime, Timelike};
|
||||||
use leptos::{html, prelude::*};
|
use leptos::{html, prelude::*};
|
||||||
|
use std::ops::Deref;
|
||||||
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement};
|
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement};
|
||||||
use thaw_utils::{
|
use thaw_utils::{
|
||||||
class_list, mount_style, ArcOneCallback, ComponentRef, OptionModel, OptionModelWithValue, SignalWatch
|
class_list, mount_style, ArcOneCallback, ComponentRef, OptionModel, OptionModelWithValue,
|
||||||
|
SignalWatch,
|
||||||
};
|
};
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn TimePicker(
|
pub fn TimePicker(
|
||||||
|
|
Loading…
Add table
Reference in a new issue