diff --git a/demo/src/commonmark_demo/message.gleam b/demo/src/commonmark/demo/message.gleam similarity index 91% rename from demo/src/commonmark_demo/message.gleam rename to demo/src/commonmark/demo/message.gleam index f2b42b8..2b08cc8 100644 --- a/demo/src/commonmark_demo/message.gleam +++ b/demo/src/commonmark/demo/message.gleam @@ -1,5 +1,5 @@ import commonmark -import commonmark_demo/model.{type Model, Model} +import commonmark/demo/model.{type Model, Model} import lustre/effect pub type Msg { diff --git a/demo/src/commonmark_demo/model.gleam b/demo/src/commonmark/demo/model.gleam similarity index 84% rename from demo/src/commonmark_demo/model.gleam rename to demo/src/commonmark/demo/model.gleam index dccfb97..cad9426 100644 --- a/demo/src/commonmark_demo/model.gleam +++ b/demo/src/commonmark/demo/model.gleam @@ -1,5 +1,6 @@ import commonmark import commonmark/ast.{type Document, Document} +import lustre/effect const initial_document = "Hello, Gleam! ============= @@ -31,11 +32,11 @@ fn main () { > Something someone once said " -pub fn new() -> Model { +pub fn init(_flags) -> #(Model, effect.Effect(a)) { let document = commonmark.parse(initial_document) let html = commonmark.to_html(document) - Model(Preview, initial_document, document, html) + #(Model(Preview, initial_document, document, html), effect.none()) } pub type Tab { diff --git a/demo/src/commonmark/demo/view.gleam b/demo/src/commonmark/demo/view.gleam new file mode 100644 index 0000000..11744a7 --- /dev/null +++ b/demo/src/commonmark/demo/view.gleam @@ -0,0 +1,123 @@ +import commonmark/demo/message.{type Msg} +import commonmark/demo/model.{type Model, Model} +import gleam/dynamic +import gleam/result +import lustre/attribute +import lustre/element +import lustre/element/html +import lustre/event +import lustre/ui +import lustre/ui/button +import lustre/ui/layout/aside +import pprint + +fn on_input(event: dynamic.Dynamic) -> Result(Msg, dynamic.DecodeErrors) { + use target <- result.try(dynamic.field("target", dynamic.dynamic)(event)) + use value <- result.try(dynamic.field("value", dynamic.string)(target)) + // do your stuff! + Ok(message.UpdateInput(value)) +} + +fn tab_button( + model: Model, + tab: model.Tab, + label: String, +) -> element.Element(Msg) { + ui.button( + [ + event.on_click(message.SetTab(tab)), + attribute.style([#("margin-right", "1em")]), + case model.tab == tab { + True -> button.primary() + False -> button.outline() + }, + ], + [element.text(label)], + ) +} + +fn edit_area(model: Model) -> element.Element(Msg) { + html.textarea( + [ + event.on("input", on_input), + attribute.style([ + #("padding", "0.25em"), + #("max-width", "50%"), + #("height", "100vh"), + #("background", "#eeeeee"), + #("border-right", "2px solid var(--element-border-strong)"), + #("flex-grow", "1"), + #("font-family", "var(--font-mono)"), + #("resize", "none"), + ]), + ], + model.input, + ) +} + +pub fn view(model: Model) -> element.Element(Msg) { + ui.centre( + [], + ui.aside( + [ + aside.content_first(), + aside.align_centre(), + attribute.style([ + #("width", "100vw"), + #("--gap", "0"), + #("--min", "40%"), + ]), + ], + edit_area(model), + html.div( + [ + attribute.style([ + #("max-width", "50%"), + #("height", "100vh"), + #("overflow-y", "scroll"), + ]), + ], + [ + html.div([], [ + html.div( + [ + attribute.style([ + #("padding", "0.75em 1em"), + #("width", "100%"), + #("position", "sticky"), + #("background", "var(--primary-app-background-subtle)"), + #("border-bottom", "2px solid var(--element-border-strong)"), + #("top", "0"), + ]), + ], + [ + tab_button(model, model.Preview, "Preview"), + tab_button(model, model.AST, "AST"), + ], + ), + html.div([attribute.style([#("padding", "1em")])], [ + case model.tab { + model.AST -> + html.div([], [ + html.pre([attribute.style([#("white-space", "pre-wrap")])], [ + element.text(pprint.format(model.document)), + ]), + ]) + model.Preview -> + ui.prose( + [ + attribute.attribute( + "dangerous-unescaped-html", + model.html, + ), + ], + [], + ) + }, + ]), + ]), + ], + ), + ), + ) +} diff --git a/demo/src/commonmark_demo.gleam b/demo/src/commonmark_demo.gleam index 22c0328..49e77ce 100644 --- a/demo/src/commonmark_demo.gleam +++ b/demo/src/commonmark_demo.gleam @@ -1,113 +1,12 @@ -import commonmark_demo/message.{type Msg, update} -import commonmark_demo/model.{type Model, Model} -import gleam/dynamic -import gleam/result -import lustre -import lustre/attribute -import lustre/effect -import lustre/element -import lustre/element/html -import lustre/event -import lustre/ui -import lustre/ui/button -import lustre/ui/layout/aside -import pprint - -fn init(_flags) -> #(Model, effect.Effect(Msg)) { - #(model.new(), effect.none()) -} - -fn on_input(event: dynamic.Dynamic) -> Result(Msg, dynamic.DecodeErrors) { - use target <- result.try(dynamic.field("target", dynamic.dynamic)(event)) - use value <- result.try(dynamic.field("value", dynamic.string)(target)) - // do your stuff! - Ok(message.UpdateInput(value)) -} +//// This module only exists to give lustre the hardcoded entrypoint it wants -fn tab_button( - model: Model, - tab: model.Tab, - label: String, -) -> element.Element(Msg) { - ui.button( - [ - event.on_click(message.SetTab(tab)), - attribute.style([#("margin-right", "1em")]), - case model.tab == tab { - True -> button.primary() - False -> button.outline() - }, - ], - [element.text(label)], - ) -} - -fn view(model: Model) -> element.Element(Msg) { - ui.centre( - [], - ui.aside( - [ - aside.content_first(), - aside.align_centre(), - attribute.style([ - #("width", "100vw"), - #("--gap", "1em"), - #("--min", "40%"), - ]), - ], - html.textarea( - [ - event.on("input", on_input), - attribute.style([ - #("padding", "0.25em"), - #("max-width", "50%"), - #("height", "100vh"), - #("background", "#eeeeee"), - #("flex-grow", "1"), - #( - "font-family", - "ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;", - ), - ]), - ], - model.input, - ), - html.div( - [ - attribute.style([ - #("max-width", "50%"), - #("height", "100vh"), - #("overflow-y", "scroll"), - ]), - ], - [ - html.div([], [ - html.div([attribute.style([#("margin", "0.75em 0")])], [ - tab_button(model, model.Preview, "Preview"), - tab_button(model, model.AST, "AST"), - ]), - case model.tab { - model.AST -> - html.div([], [ - html.pre([attribute.style([#("white-space", "pre-wrap")])], [ - element.text(pprint.format(model.document)), - ]), - ]) - model.Preview -> - ui.prose( - [attribute.attribute("dangerous-unescaped-html", model.html)], - [], - ) - }, - ]), - ], - ), - ), - ) -} +import commonmark/demo/message +import commonmark/demo/model +import commonmark/demo/view +import lustre pub fn main() { - let app = lustre.application(init, update, view) + let app = lustre.application(model.init, message.update, view.view) let assert Ok(_) = lustre.start(app, "#app", Nil) Nil diff --git a/demo/test/commonmark_demo_test.gleam b/demo/test/commonmark/demo/tests.gleam similarity index 100% rename from demo/test/commonmark_demo_test.gleam rename to demo/test/commonmark/demo/tests.gleam