Cookbook / Controller

Controller

display

controller() intrinsic — a ResizeObserver reactive controller with hostConnected/hostDisconnected lifecycle, writes routed through an action.

id
aihu-controller
since
0.5.0
file
aihu-controller.aihu
stateactioncontrollercontroller.describeinterpolation

Run it

source · static

This recipe doesn't have a hydrated island in the demo gallery yet. An in-browser, WASM-compiled playground (edit this source and re-render live) is planned as a follow-up — read the real source below.

Source

aihu-controller.aihu
governedaihu-controller.aihuaihu1.4 kB
// controller — controller() intrinsic wrapping a ResizeObserver reactive controller

@state {
  let width = state(0)
  let height = state(0)

  const setSize = action((w: number, h: number) => {
    width = w
    height = h
  })

  const resizeObserver = controller({ describe: 'Tracks host size via ResizeObserver' }, () => {
    let observer: ResizeObserver | null = null
    return {
      hostConnected: () => {
        observer = new ResizeObserver((entries) => {
          const rect = entries[0]?.contentRect
          setSize(Math.round(rect?.width ?? 0), Math.round(rect?.height ?? 0))
        })
        observer.observe((ctx.host as ShadowRoot).host)
      },
      hostDisconnected: () => {
        observer?.disconnect()
        observer = null
      },
    }
  })
}

@template {
  <div class="controller-demo">
    <div class="resize-box">
      <p class="dim">Width: <strong>{width}px</strong></p>
      <p class="dim">Height: <strong>{height}px</strong></p>
      <p class="hint">Resize the component to see updates.</p>
    </div>
  </div>
}

@style {
  .controller-demo { padding: 1rem; resize: both; overflow: auto; border: 2px dashed var(--border, #ccc); min-width: 200px; min-height: 100px; }
  .resize-box { display: grid; gap: 0.25rem; }
  .dim { margin: 0; font-family: monospace; font-size: 0.9rem; }
  .hint { margin: 0.5rem 0 0; font-size: 0.8rem; color: var(--muted, #888); }
}

Requires

concerns
stateevents

Anti-patterns

  • Do not write state directly inside a controller body (C561) — controllers are derivations; route writes through an action.

Related recipes