-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: adds Rating component * feat: Improve Rating * feat: adds RatingDisplay component * feat: Rating adds rules prop * fix: build nightly
- Loading branch information
1 parent
af87d61
commit 6ffc1d2
Showing
14 changed files
with
702 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# Rating | ||
|
||
```rust demo | ||
let value = RwSignal::new(0.0); | ||
|
||
view! { | ||
{move || value.get()} | ||
<Rating value /> | ||
} | ||
``` | ||
|
||
### Step | ||
|
||
```rust demo | ||
let value = RwSignal::new(3.5); | ||
|
||
view! { | ||
{move || value.get()} | ||
<Rating value step=0.5 /> | ||
} | ||
``` | ||
|
||
### Max | ||
|
||
```rust demo | ||
let value = RwSignal::new(5.0); | ||
|
||
view! { | ||
<Rating value max=10 /> | ||
} | ||
``` | ||
|
||
### Size | ||
|
||
```rust demo | ||
view! { | ||
<Flex vertical=true inline=true> | ||
<Rating value=3.0 size=RatingSize::Small/> | ||
<Rating value=3.0 size=RatingSize::Medium/> | ||
<Rating value=3.0 size=RatingSize::Large/> | ||
<Rating value=3.0 size=RatingSize::ExtraLarge/> | ||
</Flex> | ||
} | ||
``` | ||
|
||
### Color | ||
|
||
```rust demo | ||
view! { | ||
<Flex vertical=true inline=true> | ||
<Rating /> | ||
<Rating color=RatingColor::Brand/> | ||
</Flex> | ||
} | ||
``` | ||
|
||
### Rating Props | ||
|
||
| Name | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| class | `MaybeProp<String>` | `Default::default()` | | | ||
| id | `MaybeProp<String>` | `Default::default()` | | | ||
| name | `MaybeProp<String>` | `Default::default()` | Name for the Radio inputs. If not provided, one will be automatically generated. | | ||
| rules | `Vec<RatingRule>` | `vec![]` | The rules to validate Field. | | ||
| value | `OptionModel<f32>` | `None` | The value of the rating. | | ||
| max | `Signal<u8>` | `5` | The max value of the rating. This controls the number of rating items displayed. Must be a whole number greater than 1. | | ||
| step | `Signal<f32>` | `1.0` | Sets the precision to allow half-filled shapes in Rating. | | ||
| size | `Signal<RatingSize>` | `RatingSize::ExtraLarge` | Sets the size of the Rating items. | | ||
| color | `Signal<RatingColor>` | `RatingColor::Neutral` | Rating color. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# RatingDisplay | ||
|
||
The value controls the number of filled stars, and is written out next to the RatingDisplay. The number of filled stars is rounded to the nearest half-star. | ||
|
||
```rust demo | ||
view! { | ||
<Flex vertical=true inline=true> | ||
<RatingDisplay value=1.0 /> | ||
<RatingDisplay value=3.7 /> | ||
<RatingDisplay value=3.9 /> | ||
<RatingDisplay value=4.0 /> | ||
<RatingDisplay value=5.0 /> | ||
</Flex> | ||
} | ||
``` | ||
|
||
### Max | ||
|
||
```rust demo | ||
let value = RwSignal::new(5.0); | ||
|
||
view! { | ||
<RatingDisplay value max=10 /> | ||
} | ||
``` | ||
|
||
### Size | ||
|
||
```rust demo | ||
view! { | ||
<Flex vertical=true inline=true> | ||
<RatingDisplay value=3.0 size=RatingSize::Small/> | ||
<RatingDisplay value=3.0 size=RatingSize::Medium/> | ||
<RatingDisplay value=3.0 size=RatingSize::Large/> | ||
<RatingDisplay value=3.0 size=RatingSize::ExtraLarge/> | ||
</Flex> | ||
} | ||
``` | ||
|
||
### Color | ||
|
||
```rust demo | ||
view! { | ||
<Flex vertical=true inline=true> | ||
<RatingDisplay value=3.0/> | ||
<RatingDisplay color=RatingColor::Brand value=3.0/> | ||
</Flex> | ||
} | ||
``` | ||
|
||
### Rating Props | ||
|
||
| Name | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| class | `MaybeProp<String>` | `Default::default()` | | | ||
| value | `Signal<f32>` | `0.0` | The value of the rating. | | ||
| max | `Signal<u8>` | `5` | The max value of the rating. This controls the number of rating items displayed. Must be a whole number greater than 1. | | ||
| size | `Signal<RatingSize>` | `RatingSize::Medium` | Sets the size of the Rating items. | | ||
| color | `Signal<RatingColor>` | `RatingColor::Neutral` | Rating color. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
mod rating; | ||
mod rating_display; | ||
mod rating_item; | ||
|
||
pub use rating::*; | ||
pub use rating_display::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
mod types; | ||
|
||
pub use types::*; | ||
|
||
use super::rating_item::RatingItem; | ||
use crate::{FieldInjection, Rule}; | ||
use leptos::{context::Provider, prelude::*}; | ||
use thaw_utils::{class_list, mount_style, OptionModel}; | ||
use wasm_bindgen::JsCast; | ||
use web_sys::{Event, EventTarget, HtmlInputElement, MouseEvent}; | ||
|
||
#[component] | ||
pub fn Rating( | ||
#[prop(optional, into)] class: MaybeProp<String>, | ||
#[prop(optional, into)] id: MaybeProp<String>, | ||
#[prop(optional, into)] rules: Vec<RatingRule>, | ||
/// Name for the Radio inputs. If not provided, one will be automatically generated. | ||
#[prop(optional, into)] | ||
name: MaybeProp<String>, | ||
/// The value of the rating. | ||
#[prop(optional, into)] | ||
value: OptionModel<f32>, | ||
/// The max value of the rating. This controls the number of rating items displayed. | ||
/// Must be a whole number greater than 1. | ||
#[prop(default = 5.into(), into)] | ||
max: Signal<u8>, | ||
/// Sets the precision to allow half-filled shapes in Rating. | ||
#[prop(default = 1.0.into(), into)] | ||
step: Signal<f32>, | ||
/// Sets the size of the Rating items. | ||
#[prop(default = RatingSize::ExtraLarge.into(), into)] | ||
size: Signal<RatingSize>, | ||
/// Rating color. | ||
#[prop(optional, into)] | ||
color: Signal<RatingColor>, | ||
) -> impl IntoView { | ||
mount_style("rating", include_str!("./rating.css")); | ||
let (id, name) = FieldInjection::use_id_and_name(id, name); | ||
let validate = Rule::validate(rules, value, name); | ||
|
||
let name = Memo::new(move |_| { | ||
name.get() | ||
.unwrap_or_else(|| uuid::Uuid::new_v4().to_string()) | ||
}); | ||
let hovered_value = RwSignal::new(None::<f32>); | ||
|
||
let on_change = move |e: Event| { | ||
if let Some(el) = is_rating_radio_item(e.target().unwrap(), &name.read()) { | ||
if let Ok(new_value) = el.value().parse::<f32>() { | ||
value.set(Some(new_value)); | ||
validate.run(Some(RatingRuleTrigger::Change)); | ||
} | ||
} | ||
}; | ||
|
||
let on_mouseover = move |e: MouseEvent| { | ||
if let Some(el) = is_rating_radio_item(e.target().unwrap(), &name.read()) { | ||
if let Ok(new_value) = el.value().parse::<f32>() { | ||
hovered_value.set(Some(new_value)); | ||
} | ||
} | ||
}; | ||
|
||
let on_mouseleave = move |_| { | ||
hovered_value.set(None); | ||
}; | ||
|
||
view! { | ||
<div | ||
role="radiogroup" | ||
class=class_list!["thaw-rating", class] | ||
id=id | ||
on:change=on_change | ||
on:mouseover=on_mouseover | ||
on:mouseleave=on_mouseleave | ||
> | ||
<Provider value=RatingInjection { | ||
value, | ||
hovered_value, | ||
name, | ||
step, | ||
size, | ||
color, | ||
interactive: true, | ||
}> | ||
{move || { | ||
let mut max = max.get(); | ||
if max < 2 { | ||
max = 2; | ||
} | ||
(0..max) | ||
.into_iter() | ||
.map(|i| { | ||
view! { <RatingItem value=i + 1 /> } | ||
}) | ||
.collect_view() | ||
}} | ||
</Provider> | ||
</div> | ||
} | ||
} | ||
|
||
fn is_rating_radio_item(target: EventTarget, name: &String) -> Option<HtmlInputElement> { | ||
target | ||
.dyn_into::<HtmlInputElement>() | ||
.ok() | ||
.filter(|el| el.type_() == "radio" && &el.name() == name) | ||
} |
Oops, something went wrong.