DrSensor / nusa

incremental runtime that bring both simplicity and power into webdev (buildless, cross-language, data-driven)
MIT License
4 stars 0 forks source link

Support undo/redo #71

Open DrSensor opened 1 year ago

DrSensor commented 1 year ago

This feature introduce history buffer to undo/redo data changes in class accessors/properties. There is 2 kind of history that can be enabled via attribute:

[^1]: see vim undo tree

history and autotrack=history attribute available on:

Warning: the history will be removed/renewed when using SPA navigation #12. Cache or persist them (#14) to retain history between page navigation.

(TODO) This feature also pave a way for CRDT and data synchronization between servers and/or clients over network.

Example

<render-scope history=linear>

<link cache href=counter.js>
<link persist href=naming.js>

<script let=hs type>
import * as history from "libnusa/history"
export default class {
  #index = history.branch?.length ?? 0
  undo() { history.undo() }
  redo() { history.redo() }
  cycle() {
    history.switch(history.branch[
      this.#index = this.#index < history.branch.length
        ? this.#index + 1 : 0
    ]) // maybe simplify as history.switch(-1 or +1)
  }
}
</script>

<template shadowrootmode=closed>
  <basic-example />
  <undotree-example />
</template>

<template history=tree define=undotree-example>
  <basic-example />
</template>

<template define=basic-example>
  <button ~
    @click=track:asyncIncrement
    #text=count>0</button>

  <input type=text
    value="type your name!"
  ~ .value=name
    @change=track+set:name>

  <button ~ @click=hs.undo>↩️</button>
  <button ~ @click=hs.redo>↪️</button>
  <button ~ @click=hs.cycle>🔄</button>
</template>

</render-scope>

Note that each event handler need to be specified as @event=track:methods or use @history.track decorator to track the history. Specifying as @event=untrack:methods or using @history.untrack decorator will untrack the history when using autotrack=history attribute.