use super::*;
pub(crate) fn use_props_demo() -> UsePropsDemo {
UsePropsDemo::new(App::use_signal(|| "Hello from Parent!".to_string()))
}
pub(crate) fn use_two_way_demo() -> UseTwoWayDemo {
UseTwoWayDemo::new(
App::use_signal(|| "Type here...".to_string()),
App::use_signal(|| 0),
)
}
pub(crate) fn two_way_on_increment(counter: Signal<i32>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_: Event| {
let current: i32 = counter.get();
counter.set(current + 1);
}))
}
pub(crate) fn two_way_on_decrement(counter: Signal<i32>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_: Event| {
let current: i32 = counter.get();
counter.set(current - 1);
}))
}
pub(crate) fn use_cross_component_demo() -> UseCrossComponentDemo {
let state: UseCrossComponentDemo = UseCrossComponentDemo::new(
App::use_signal(|| 0.0),
App::use_signal(|| 32.0),
App::use_signal(|| 79),
App::use_signal(|| 70),
App::use_signal(|| 229),
App::use_signal(|| "#000000".to_string()),
);
let celsius: Signal<f64> = state.get_celsius();
let fahrenheit: Signal<f64> = state.get_fahrenheit();
let red: Signal<i32> = state.get_red();
let green: Signal<i32> = state.get_green();
let blue: Signal<i32> = state.get_blue();
let hex_color: Signal<String> = state.get_hex_color();
watch!(celsius, |celsius_value: f64| {
let new_fahrenheit: f64 = celsius_value * 9.0 / 5.0 + 32.0;
let rounded: f64 = (new_fahrenheit * 100.0).round() / 100.0;
fahrenheit.set(rounded);
});
watch!(fahrenheit, |fahrenheit_value: f64| {
let new_celsius: f64 = (fahrenheit_value - 32.0) * 5.0 / 9.0;
let rounded: f64 = (new_celsius * 100.0).round() / 100.0;
celsius.set(rounded);
});
watch!(
red,
green,
blue,
|red_value: i32, green_value: i32, blue_value: i32| {
let clamped_red: i32 = red_value.clamp(0, 255);
let clamped_green: i32 = green_value.clamp(0, 255);
let clamped_blue: i32 = blue_value.clamp(0, 255);
hex_color.set(format!(
"#{:02x}{:02x}{:02x}",
clamped_red, clamped_green, clamped_blue
));
}
);
state
}
pub(crate) fn cross_on_input_celsius(signal: Signal<f64>) -> Option<Rc<dyn Fn(Event)>> {
let pending_value: Rc<Cell<f64>> = Rc::new(Cell::new(0.0));
let raf_id: Rc<Cell<Option<i32>>> = Rc::new(Cell::new(None));
Some(Rc::new(move |event: Event| {
if let Some(target) = event.target()
&& let Ok(input) = target.clone().dyn_into::<HtmlInputElement>()
{
let parsed: f64 = input.value().parse().unwrap_or_default();
pending_value.set(parsed);
if raf_id.get().is_some() {
return;
}
let pending_for_raf: Rc<Cell<f64>> = pending_value.clone();
let raf_id_clone: Rc<Cell<Option<i32>>> = raf_id.clone();
let Some(window_value): Option<Window> = window() else {
return;
};
let raf_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
raf_id_clone.set(None);
signal.set(pending_for_raf.get());
}));
let id: i32 = window_value
.request_animation_frame(raf_closure.as_ref().unchecked_ref())
.unwrap_or_default();
raf_id.set(Some(id));
raf_closure.forget();
}
}))
}
pub(crate) fn cross_on_input_fahrenheit(signal: Signal<f64>) -> Option<Rc<dyn Fn(Event)>> {
let pending_value: Rc<Cell<f64>> = Rc::new(Cell::new(0.0));
let raf_id: Rc<Cell<Option<i32>>> = Rc::new(Cell::new(None));
Some(Rc::new(move |event: Event| {
if let Some(target) = event.target()
&& let Ok(input) = target.clone().dyn_into::<HtmlInputElement>()
{
let parsed: f64 = input.value().parse().unwrap_or_default();
pending_value.set(parsed);
if raf_id.get().is_some() {
return;
}
let pending_for_raf: Rc<Cell<f64>> = pending_value.clone();
let raf_id_clone: Rc<Cell<Option<i32>>> = raf_id.clone();
let Some(window_value): Option<Window> = window() else {
return;
};
let raf_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
raf_id_clone.set(None);
signal.set(pending_for_raf.get());
}));
let id: i32 = window_value
.request_animation_frame(raf_closure.as_ref().unchecked_ref())
.unwrap_or_default();
raf_id.set(Some(id));
raf_closure.forget();
}
}))
}
pub(crate) fn cross_on_input_i32(signal: Signal<i32>) -> Option<Rc<dyn Fn(Event)>> {
let pending_value: Rc<Cell<i32>> = Rc::new(Cell::new(0));
let raf_id: Rc<Cell<Option<i32>>> = Rc::new(Cell::new(None));
Some(Rc::new(move |event: Event| {
if let Some(target) = event.target()
&& let Ok(input) = target.clone().dyn_into::<HtmlInputElement>()
{
let parsed: i32 = input.value().parse().unwrap_or_default();
let clamped: i32 = parsed.clamp(0, 255);
let percent: f64 = (clamped as f64 / 255.0 * 100.0).clamp(0.0, 100.0);
input
.style()
.set_property("--value", &format!("{percent}%"))
.unwrap_or(());
pending_value.set(clamped);
if raf_id.get().is_some() {
return;
}
let pending_for_raf: Rc<Cell<i32>> = pending_value.clone();
let raf_id_clone: Rc<Cell<Option<i32>>> = raf_id.clone();
let Some(window_value): Option<Window> = window() else {
return;
};
let raf_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
raf_id_clone.set(None);
signal.set(pending_for_raf.get());
}));
let id: i32 = window_value
.request_animation_frame(raf_closure.as_ref().unchecked_ref())
.unwrap_or_default();
raf_id.set(Some(id));
raf_closure.forget();
}
}))
}
pub(crate) fn use_typed_props_demo() -> UseTypedPropsDemo {
UseTypedPropsDemo::new(
App::use_signal(|| false),
App::use_signal(|| 5),
App::use_signal(|| 0),
)
}
pub(crate) fn typed_props_on_toggle_disabled(disabled: Signal<bool>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_: Event| {
let current: bool = disabled.get();
disabled.set(!current);
}))
}
pub(crate) fn typed_props_on_increment(
count: Signal<i32>,
max_count: Signal<i32>,
disabled: Signal<bool>,
) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_: Event| {
if disabled.get() {
return;
}
let current: i32 = count.get();
let max: i32 = max_count.get();
if current < max {
count.set(current + 1);
}
}))
}
pub(crate) fn typed_props_on_reset_count(
count: Signal<i32>,
disabled: Signal<bool>,
) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_: Event| {
if disabled.get() {
return;
}
count.set(0);
}))
}