Skip to content

Instantly share code, notes, and snippets.

@rebo
Created July 25, 2020 16:43
Show Gist options
  • Save rebo/e35628c7c97b147cb54f6a326219528e to your computer and use it in GitHub Desktop.
Save rebo/e35628c7c97b147cb54f6a326219528e to your computer and use it in GitHub Desktop.
#[atom]
fn hsl_widget_status() ->Atom<HslWidgetStatus> {
HslWidgetStatus::Unpicked
}
#[derive(Clone)]
pub enum HslWidgetStatus{
Unpicked,
Open,
Picked((f64,f64,f64))
}
#[derive(Clone)]
struct Impure<T>(T) where T : Clone;
impl <T>PartialEq for Impure<T> where T:Clone{
fn eq(&self, other: &Self) -> bool {
true
}
}
impl <T>std::hash::Hash for Impure<T> where T:Clone{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
}
}
impl <T> std::cmp::Eq for Impure<T> where T:Clone{}
// impl <T>PartialEq for Impure<T> where T:Clone{
// fn eq(&self, other: &Self) -> bool {
// true
// }
// }
#[topo::nested]
pub fn color_picker<Ms:'static>(ev_handler: EventHandler<Ms>) -> Node<Ms> {
picker_ui(Impure(ev_handler)).get()
}
#[reaction]
fn picker_ui<Ms: 'static>(ev_handler: Impure<EventHandler<Ms>>) -> Reaction<Node<Ms>>{
let status = hsl_widget_status().observe();
match status {
HslWidgetStatus::Unpicked => picker_unpicked_ui(),
HslWidgetStatus::Open => picker_open_ui(ev_handler).observe(),
HslWidgetStatus::Picked(hsl) => picker_picked_ui(hsl),
}
}
fn picker_unpicked_ui<Ms: 'static>() -> Node<Ms> {
button![
s().radius(px(4)).bg_color(hsluv(120,60,60)).color("white").p(px(16)),
s().hover().bg_color(hsluv(120,50,65)),
s().active().bg_color(hsluv(120,40,50)),
"Choose Color",hsl_widget_status().on_click(|s| *s = HslWidgetStatus::Open)
]
}
fn picker_picked_ui<Ms: 'static>(hsl_value: (f64,f64,f64) ) -> Node<Ms> {
div![s().m(px(20)),
"picked color :",
div![
s().w(px(30)).h(px(30)).bg_color(hsluv::hsluv_to_hex(hsl_value).as_str()).m(px(20))
],
button![
s().radius(px(4)).bg_color(hsluv(120,60,60)).color("white").p(px(16)),
s().hover().bg_color(hsluv(120,50,65)),
s().active().bg_color(hsluv(120,40,50)),
"Choose another Color",hsl_widget_status().on_click(|s| *s = HslWidgetStatus::Open)
]
]
}
#[atom]
fn hsl() -> Atom<(f64,f64,f64)> {
(0.,60.,60.)
}
#[reaction]
fn picker_open_ui<Ms: 'static>(ev_handler: Impure<EventHandler<Ms>>) -> Reaction<Node<Ms>> {
let el_ref = use_state(||ElRef::<web_sys::HtmlElement>::new() );
let hsl_value = hsl().observe();
// log!(hsl_value);
Column![
s().p(px(20)),
padding = px(8),
s().width(px(300)).height(px(300))
.bg_color("white")
.radius(px(4))
.b_color("black").b_style_solid().b_width(px(1)),
Item![
align = ColumnAlign::MiddleCenter,
s().width(px(100)).height(px(100)).bg_color(hsluv::hsluv_to_hex(hsl_value).as_str())
],
Item![
align = ColumnAlign::MiddleRight,
label!("Hue:"),
input![
s().width(px(120)).mr(px(50)).ml(px(20)),
attrs!{At::Value => hsl_value.0 ,At::Type => "range", At::Min => 0.0, At::Max => 360},
hsl().on_input(|hsl,hue| hsl.0 = hue.parse::<f64>().unwrap())
]]
,
Item![
align = ColumnAlign::MiddleRight,
label!("Saturation:"),
input![
s().width(px(120)).mr(px(50)).ml(px(20)),
attrs!{At::Value => hsl_value.1 ,At::Type => "range", At::Min => 0.0, At::Max => 100},
hsl().on_input(|hsl,saturation| hsl.1 = saturation.parse::<f64>().unwrap())
]],
Item![
align = ColumnAlign::MiddleRight,
label!["Lightness:"],
input![
s().width(px(120)).mr(px(50)).ml(px(20)),
attrs!{At::Value => hsl_value.2 ,At::Type => "range", At::Min => 0.0, At::Max => 100},
hsl().on_input(|hsl,lightness| hsl.2 =lightness.parse::<f64>().unwrap())
]
],
Item![
align = ColumnAlign::MiddleRight,
button![
s().radius(px(4)).bg_color(hsluv(120,60,60)).color("white").p(px(16)),
s().hover().bg_color(hsluv(120,50,65)),
s().active().bg_color(hsluv(120,40,50)),
"Ok",
hsl_widget_status().on_click(move |s| {
let el = el_ref.get().get().unwrap();
let target = el.dyn_into::<web_sys::EventTarget>().unwrap();
target.dispatch_event(&web_sys::Event::new("input").unwrap());
*s = HslWidgetStatus::Picked(hsl_value);})
],
input![
s().display_hidden(),
el_ref.get(),
attrs!{At::Value=> hsluv::hsluv_to_hex(hsl_value)},
ev_handler.0
]
]
]
}
// View Entry Here, Sets up theme access, two themes are allowed access
//
// The first is the app defined theme, the second provides access to seed style presets.
// The content block also activates themed global_styles.
// ---------------
#[topo::nested] // Needed for Seed Hooks
pub fn view(_model: &Model) -> Node<Msg> {
div![
color_picker(
input_ev(
Ev::Input,|color| Msg::PickedColorChanged(color)
) // This could be any EventHandler including for instance `atom.on_input`
),
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment