#Svelte inspired "surgical dom updates" super rough prototype

1 messages · Page 1 of 1 (latest)

inland lotus
#

Svelte's main different to React is that it doesn't use a VDOM. it "knows" what to update from construction time.
I was wondering if I could build anything that gave the same benefits, no vdom dependency, without needing a special compiler. .svelte files need to be processed before they can be run in the browser.

I've got to something that looks like this. https://github.com/CrowdHailer/eyg-lang/blob/61746198448c86d0abb691acfa95710483222d75/eyg/src/experiment.gleam#L107-L117

  p(
    [
      class(if_(loud, value("bold underline text-red-500"), value(""))),
      attr(value("foo"), greeting),
    ],
    [
      text(value("hello ")),
      text(greeting),
      if_(loud, p([], [text(greeting)]), text(value(""))),
    ],
  )

p and text are defined in the framework. Currently only text supports memoisation but it only touches the dom if the update value is new.
https://github.com/CrowdHailer/eyg-lang/blob/61746198448c86d0abb691acfa95710483222d75/eyg/src/experiment.gleam#L56
currently this uses a mutable ref, maybe there is a way to manage without this

value is a shorthand function to to create values that are constant.

The uglies bit is greeting and loud which need to be defined for the specific state of the application. https://github.com/CrowdHailer/eyg-lang/blob/61746198448c86d0abb691acfa95710483222d75/eyg/src/experiment.gleam#L90-L102
Maybe there is a way to generate these in the future. Not sure.

Anyway looking for thoughts comments. is this useful? Is it nice that it's gleam only, i.e. not bindings to Svelte? who else has already built this?

GitHub

Getting more from data. Contribute to CrowdHailer/eyg-lang development by creating an account on GitHub.

vivid river
inland lotus
#

Made quite a bit more progress on this builder API. Currently it looks like the following

  let assert [target, ..] =
    array.to_list(document.query_selector_all("[data-easel=\"large\"]"))
  let page =
    component(fn(props) {
      let greeting = map(props, fn(props: State) { props.greeting })
      let session = map(props, fn(props: State) { props.session })

      [
        p([text(greeting), text(static(" world!"))]),
        ..option(
          session,
          some: fn(session_id) { [text(session_id), text(greeting)] },
          none: [text(static("nonee"))],
        )
      ]
    })
  let #(elements, update) =
    page(State(greeting: "hello", active: False, session: None))
  list.map(elements, document.append(target, _))
  // console.log(array.from_list(elements))
  use _ <- promise.await(promisex.wait(1000))
  update(State(greeting: "hello!", active: True, session: Some("foooo")))
#

props, greeting, session and session_id are all observables. i.e. when they change the minimum amount of html edits are made

#

static allows you to turn a regular value into an observable to pass into a component

#

Two things I wish I had were.

  1. surgar for record access so I could write let greeting = map(props, _.greeting)
  2. the ability to use .. syntax in the middle of a list i.e. [a, ..bs, c]
inland lotus
#

Essential benefits of pull based means separating updating values from running side effects so it's easy to group rendering all changes in a request animation call