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 }), 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 { ModelCommon( root_path: String, row: Int, column: Int, selected: Bool, insertable: Bool, ) } pub type Msg { AncestorChangedRootPath(String) ParentChangedRow(Int) ParentChangedColumn(Int) ParentChangedSelected(Bool) ParentChangedInsertable(Bool) UserClickedCell UserDoubleClickedCell } pub fn init(_) -> #(ModelCommon, Effect(CommonMsg)) { #( 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(), ) 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()], ), ]) }