phonograph/webc/src/cell_common.gleam

155 lines
3.7 KiB
Gleam
Raw Normal View History

import gleam/dynamic
import gleam/dynamic/decode
import gleam/int
import gleam/json
import gleam/result
import lustre/attribute as attr
import lustre/component
import lustre/effect.{type Effect}
import lustre/element.{type Element}
import lustre/element/html
import lustre/event
import context
pub fn options_common(
map_msg: fn(CommonMsg) -> msg,
) -> List(component.Option(msg)) {
[
component.on_attribute_change("row", fn(value) {
use value <- result.map(int.parse(value))
ParentChangedRow(value) |> CommonMsg |> map_msg
}),
component.on_attribute_change("column", fn(value) {
use value <- result.map(int.parse(value))
ParentChangedColumn(value) |> CommonMsg |> map_msg
}),
component.on_attribute_change("selected", fn(value) {
ParentChangedSelected(value != "") |> CommonMsg |> map_msg |> Ok
}),
2025-08-10 14:32:15 -07:00
component.on_attribute_change("insertable", fn(value) {
ParentChangedInsertable(value != "") |> CommonMsg |> map_msg |> Ok
}),
component.on_attribute_change("has-default", fn(value) {
ParentChangedInsertable(value != "") |> CommonMsg |> map_msg |> Ok
}),
]
}
pub type ModelCommon {
2025-08-10 14:32:15 -07:00
ModelCommon(
root_path: String,
row: Int,
column: Int,
selected: Bool,
insertable: Bool,
)
}
pub type Msg {
AncestorChangedRootPath(String)
ParentChangedRow(Int)
ParentChangedColumn(Int)
ParentChangedSelected(Bool)
2025-08-10 14:32:15 -07:00
ParentChangedInsertable(Bool)
UserClickedCell
UserDoubleClickedCell
}
pub fn init(_) -> #(ModelCommon, Effect(CommonMsg)) {
#(
2025-08-10 14:32:15 -07:00
ModelCommon(
root_path: "",
selected: False,
row: -1,
column: -1,
insertable: False,
),
context.request_context(
context: dynamic.string("root_path"),
subscribe: False,
decoder: decode.string
|> decode.map(fn(value) {
value |> AncestorChangedRootPath |> CommonMsg
}),
),
)
}
pub type CommonMsg {
CommonMsg(msg: Msg)
}
pub fn update(
model: ModelCommon,
msg_common: CommonMsg,
) -> #(ModelCommon, Effect(msg)) {
case msg_common.msg {
AncestorChangedRootPath(root_path) -> #(
ModelCommon(..model, root_path:),
effect.none(),
)
ParentChangedRow(row) -> #(ModelCommon(..model, row:), effect.none())
ParentChangedColumn(column) -> #(
ModelCommon(..model, column:),
effect.none(),
)
ParentChangedSelected(selected) -> #(
ModelCommon(..model, selected:),
effect.none(),
)
2025-08-10 14:32:15 -07:00
ParentChangedInsertable(insertable) -> #(
ModelCommon(..model, insertable:),
effect.none(),
)
UserClickedCell -> #(
model,
event.emit(
"cell-click",
json.object([
#("row", json.int(model.row)),
#("column", json.int(model.column)),
]),
),
)
UserDoubleClickedCell -> #(
model,
event.emit(
"cell-dblclick",
json.object([
#("row", json.int(model.row)),
#("column", json.int(model.column)),
]),
),
)
}
}
pub fn view(
model model: ModelCommon,
map_msg map_msg: fn(CommonMsg) -> msg,
inner inner: fn() -> Element(msg),
) -> Element(msg) {
element.fragment([
html.link([
attr.rel("stylesheet"),
attr.href(model.root_path <> "/css_dist/cells.css"),
]),
html.div(
[
attr.class("cell__container"),
case model.selected {
True -> attr.class("cell__container--selected")
False -> attr.none()
},
event.on_click(CommonMsg(UserClickedCell) |> map_msg()),
event.on(
"dblclick",
CommonMsg(UserDoubleClickedCell) |> map_msg() |> decode.success(),
),
],
[inner()],
),
])
}