Packages

An easy to use frontend framework written in Gleam.

Current section

Files

Jump to
novdom src novdom state component.gleam
Raw

src/novdom/state/component.gleam

import novdom/internals/component.{
type Component, component, hide, replace_child, show, swap_vision,
}
import novdom/internals/parameter.{type Parameter, ParameterList, set_parameter}
import novdom/internals/utils
import novdom/parameter/attribute.{class}
import novdom/state.{type State, listen, value}
const state_component_tag = "_STATE_COMPONENT_"
/// Shows or hides the given component based on the result of the *should_show* function.
///
/// This will wrap the given components in a parent component. The given `Parameter` will be apllied to the parent.
pub fn if1(
parameter: List(Parameter),
state state: State(a),
when should_show: fn(a) -> Bool,
then comp: Component,
) -> Component {
let parent =
component(state_component_tag, [comp])
|> set_parameter(
ParameterList([class("replacement-transition"), ..parameter]),
)
let id = utils.unique_id()
let callback = fn(a) {
let condition = should_show(a)
case condition, utils.get_last_value(id) {
True, False -> {
show(comp, with_modifier: True)
Nil
}
False, True -> {
hide(comp, with_modifier: True)
Nil
}
_, _ -> Nil
}
utils.set_last_value(id, condition)
}
listen(state, callback)
case should_show(value(state)) {
True -> {
utils.set_last_value(id, True)
}
False -> {
utils.set_last_value(id, False)
hide(comp, False)
}
}
parent
}
/// Switches between the two given components based on the result of the *should_show* function.
///
/// This will wrap the given components in a parent component to be able to switch between them. The given `Parameter` will be apllied to the parent.
pub fn ternary1(
parameter: List(Parameter),
state state: State(a),
when should_show: fn(a) -> Bool,
then comp1: Component,
otherwiese comp2: Component,
) -> Component {
let comp =
component(state_component_tag, [comp1, comp2])
|> set_parameter(
ParameterList([class("replacement-transition"), ..parameter]),
)
let id = utils.unique_id()
let callback = fn(a) {
let condition = should_show(a)
case condition, utils.get_last_value(id) {
True, False -> {
swap_vision(comp2, comp1)
Nil
}
False, True -> {
swap_vision(comp1, comp2)
Nil
}
_, _ -> Nil
}
utils.set_last_value(id, condition)
}
listen(state, callback)
case should_show(value(state)) {
True -> {
utils.set_last_value(id, True)
hide(comp2, False)
}
False -> {
utils.set_last_value(id, False)
hide(comp1, False)
}
}
comp
}
/// Rerenders the component using the *do* function on every state change.
///
/// This will wrap the created component in a parent component to be able to replace it. The given `Parameter` will be apllied to the parent.
///
/// **Attention:** Only use this function as a last resort. \
/// Prefer `if(..)` or `ternary(..)`. To display every item of a list, use `novdom/state/list.map(..)`. \
/// *All named alternatives are way more performant.*
pub fn utilize(
parameter: List(Parameter),
state: State(a),
do: fn(a) -> Component,
) -> Component {
let children = do(value(state))
let comp =
component(state_component_tag, [children])
|> set_parameter(
ParameterList([class("replacement-transition"), ..parameter]),
)
let callback = fn(a) {
let do = do(a)
comp
|> replace_child(do)
Nil
}
listen(state, callback)
comp
}