Closed JScearcy closed 6 months ago
Oh no! I think you might be in for some work refactoring this: it looks like you had a slightly stale fork 😅 I think you should not have too much trouble moving things but pretty much Everything changed/moved so it won't be a smooth rebase.
Using a DocumentFragment
is a clever idea, I didn't even know that was a real thing!
Instead of the unique identifier I think we can just check at runtime if curr.elements !== undefined
.
I'm not sure how this is going to play with keyed elements (which are new and you don't have yet), might end up being a bit of a sticking point.
Yeah, I cloned yesterday just to look and made the mistake of not pulling latest before starting 😅
Honestly, sick refactor. I actually think it simplifies things for Fragment
- I think it won't need the DocumentFragment
anymore. Keys change things too for sure but nothing too wild. If I think about React a Fragment
takes a key also, and I imagine that's the expected behavior here. Looking at the latest now though!
Spoke too soon I think 😬 tried a couple different approaches with slightly different issues - gonna think on it and try again. Though I'll open a different PR - this one might confuse things since it's a bit outdated
Ah no! 😠thank you for taking a look anyway! 💕
Add fragment support to client
Summary
This commit only considered the client runtime as a jumping off point. I'm hoping to get feedback on general direction since I want to make sure it fits stylistically and within the vision for the package.
Changes
Fragment
to theElement
typeElement
instead of its own type perhaps?Fragment
withinclient-runtime
Fragment
is the root, it creates a root div, but is that actually the best behavior?React
which I though did not allow top-level fragments, but it just places children within the root element, which is kind of what creating a root div doesTODO
client-runtime
casesserver-runtime
,components
completelyTesting App
``` import gleam/int import lustre import lustre/attribute import lustre/element.{type Element} import lustre/element/html import lustre/event import lustre/ui // MAIN ------------------------------------------------------------------------ pub fn main() { let app = lustre.simple(init, update, view) let assert Ok(_) = lustre.start(app, "#app", 0) } // MODEL ----------------------------------------------------------------------- type Model = Int fn init(initial_count: Int) -> Model { case initial_count < 0 { True -> 0 False -> initial_count } } // UPDATE ---------------------------------------------------------------------- pub opaque type Msg { Incr Decr } fn update(model: Model, msg: Msg) -> Model { case msg { Incr -> model + 1 Decr -> model - 1 } } // VIEW ------------------------------------------------------------------------ fn count_fragment(model: Model) -> Element(Msg) { let count = int.to_string(model) let count_1 = int.to_string(model + 1) let count_2 = int.to_string(model + 2) element.fragment([ html.p([attribute.style([#("text-align", "center")])], [element.text(count)]), html.p([attribute.style([#("text-align", "center")])], [ element.text(count_1), ]), html.p([attribute.style([#("text-align", "center")])], [ element.text(count_2), ]), ]) } fn view(model: Model) -> Element(Msg) { let styles = [#("width", "100vw"), #("height", "100vh"), #("padding", "1rem")] let count = int.to_string(model) element.fragment([ ui.centre( [attribute.style(styles)], ui.stack([], [ ui.button([event.on_click(Incr)], [element.text("+")]), count_fragment(model), element.fragment([ element.fragment([html.p([], [element.text("immediate fragment")])]), html.p([attribute.style([#("text-align", "center")])], [ element.text("nest fragment next"), ]), element.fragment([ html.p([], [element.text("nest count")]), html.p([], [element.text(count)]), html.p([attribute.style([#("text-align", "center")])], [ element.text("nest nest fragment"), ]), element.fragment([ html.p([], [element.text("nest nest count")]), html.p([], [element.text(count)]), ]), ]), ]), ui.button([event.on_click(Decr)], [element.text("-")]), html.p([attribute.style([#("text-align", "center")])], [ element.text("sibling fragment"), ]), element.fragment([ html.p([], [element.text("sibling fragment")]), html.p([], [element.text(count)]), ]), html.p([], [element.text("Empty fragment next")]), element.fragment([]), ]), ), ]) } ```Testing App render screenshot
![testing-app-render-screenshot](https://github.com/lustre-labs/lustre/assets/12852633/f385e81b-1dbb-498f-bfe5-b70c3710fa4f)