2025-07-25 15:01:31 -07:00
|
|
|
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
|
|
|
|
|
}),
|
2025-07-25 15:01:31 -07:00
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub type ModelCommon {
|
2025-08-10 14:32:15 -07:00
|
|
|
ModelCommon(
|
|
|
|
|
root_path: String,
|
|
|
|
|
row: Int,
|
|
|
|
|
column: Int,
|
|
|
|
|
selected: Bool,
|
|
|
|
|
insertable: Bool,
|
|
|
|
|
)
|
2025-07-25 15:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub type Msg {
|
|
|
|
|
AncestorChangedRootPath(String)
|
|
|
|
|
ParentChangedRow(Int)
|
|
|
|
|
ParentChangedColumn(Int)
|
|
|
|
|
ParentChangedSelected(Bool)
|
2025-08-10 14:32:15 -07:00
|
|
|
ParentChangedInsertable(Bool)
|
2025-07-25 15:01:31 -07:00
|
|
|
UserClickedCell
|
2025-07-30 23:02:11 -07:00
|
|
|
UserDoubleClickedCell
|
2025-07-25 15:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
),
|
2025-07-25 15:01:31 -07:00
|
|
|
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(),
|
|
|
|
|
)
|
2025-07-25 15:01:31 -07:00
|
|
|
UserClickedCell -> #(
|
|
|
|
|
model,
|
|
|
|
|
event.emit(
|
|
|
|
|
"cell-click",
|
|
|
|
|
json.object([
|
|
|
|
|
#("row", json.int(model.row)),
|
|
|
|
|
#("column", json.int(model.column)),
|
|
|
|
|
]),
|
|
|
|
|
),
|
|
|
|
|
)
|
2025-07-30 23:02:11 -07:00
|
|
|
UserDoubleClickedCell -> #(
|
|
|
|
|
model,
|
|
|
|
|
event.emit(
|
|
|
|
|
"cell-dblclick",
|
|
|
|
|
json.object([
|
|
|
|
|
#("row", json.int(model.row)),
|
|
|
|
|
#("column", json.int(model.column)),
|
|
|
|
|
]),
|
|
|
|
|
),
|
|
|
|
|
)
|
2025-07-25 15:01:31 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
},
|
2025-07-30 23:02:11 -07:00
|
|
|
event.on_click(CommonMsg(UserClickedCell) |> map_msg()),
|
|
|
|
|
event.on(
|
|
|
|
|
"dblclick",
|
|
|
|
|
CommonMsg(UserDoubleClickedCell) |> map_msg() |> decode.success(),
|
|
|
|
|
),
|
2025-07-25 15:01:31 -07:00
|
|
|
],
|
|
|
|
|
[inner()],
|
|
|
|
|
),
|
|
|
|
|
])
|
|
|
|
|
}
|