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

Integration with other framework #17

Closed DrSensor closed 1 year ago

DrSensor commented 2 years ago

Use Case

import * as override from "wiles/integration/preact/explicit"
import * as signal from "npm:@preact/signals@10.10"
override.signal(signal) // either explicit
//////////////////////////////////////////////////////////////////
import "wiles/integration/preact" // or implicit
//////////////////////////////////////////////////////////////////
import { reactive, autorun } from "wiles/decorator" // doesn't use default implementation since it's overridden by Preact integration

import * as wiles from "wiles/std"
import { signal, effect } from "@preact/signals"

// Preact component
function App(this: Counter) {
//const counter = this
  const counter = wiles.use(Counter) // use current instance
      , disabled = signal(true)

  if (counter.count < 5) counter.autoSum() // enable autoSum if the inferred count value is < 5

  effect(() => {
    console.log(Counter.total) // not reactive
    if (counter.count >= 5) {  // reactive
      disabled.value = !(counter.button.disabled = true) // disable increment button while enable decrement button if count >= 5
    }
  })

  const decrement = () => { counter.count-- }

  effect(() => { // disable autoSum if total value is > 100 while decrement button being disabled
    if (Counter.total > 100  // not reactive
     && disable.value) {     // reactive
      wiles.clear(counter.autoSum)
    }
  })

  glitch_5s: { // doesn't disable autoSum because Counter.total is not reactive
    let prevTotal: number
    setTimeout(() => {
      prevTotal = Counter.total
      setTimeout(() => Counter.total = prevTotal, 5_000)
      Counter.total = 101
    }, 3_000)
  }

  return ( // push DOM
    <>
      <button onClick={decrement} {disabled}> - </button>
      <span slot="footer">Count: {counter.count}</span>
    </>
  )
}

// Wiles binding
export default class Counter {
  // pull DOM
  button: HTMLButtonElement // <button onclick:="increment" :ref="button">
  host: HTMLElement // <render-scope :ref="host">

  constructor() {
//  render(() => App.apply(this), this.host)
    render(App, this.host)
  } // render Preact island on slot "decrement"

  // all of 👇 will use @preact/signals as the underlying reactivity
  @autorun autoSum() { if (this.count) Counter.total += this.count }
  @reactive accessor count: number // infer value from html attribute

  static total = 0

  increment() { this.count++ }
}