;; ---------------------------------------------------------------------------
;; L0: Ref
;; ---------------------------------------------------------------------------
(defcomp ()
  (~docs/page :title "Layer 0: Ref (Mutable Box)"

    (p (~tw :tokens "text-stone-500 text-sm italic mb-8")
      "A non-reactive mutable cell for DOM handles, canvas contexts, and timer IDs. "
      "Like a signal but with no subscriber tracking and no notifications.")

    (~docs/section :title "Live Demo" :id "demo"
      (p "Two patterns that refs formalize: an interval ID captured in an effect closure, and a DOM element handle stored in a dict. Neither needs reactivity — they're infrastructure state.")
      (~reactive-runtime/demo-ref)
      (~docs/code :src (highlight "(defisland ~demo-ref ()\n  (let ((input-ref (dict \"current\" nil))\n        (ticks (signal 0))\n        (running (signal false))\n        (last-value (signal \"\")))\n    ;; Timer ID captured in effect closure — the ref pattern\n    (effect (fn ()\n      (when (deref running)\n        (let ((id (set-interval (fn () (swap! ticks inc)) 500)))\n          (fn () (clear-interval id))))))\n    ;; DOM handle in a dict — also the ref pattern\n    (input :ref input-ref :type \"text\" ...)\n    (button :on-click (fn (e)\n      (reset! last-value\n        (dom-get-prop (get input-ref \"current\") \"value\")))\n      \"Read\")))" "lisp"))
      (p "The timer ID lives in a closure — nothing reads it reactively. The DOM element is a " (code "(dict \"current\" nil)") " set by " (code ":ref") ". The " (code "ref") " function formalizes both into a single primitive with auto-disposal."))

    (~docs/section :title "API" :id "ref-api"

      (~docs/code :src (highlight
        ";; Create a ref — auto-registers disposal in island scope\n(define my-ref (ref initial-value))\n\n;; Read (no tracking, no subscriptions)\n(ref-deref my-ref)\n\n;; Write (no notifications, no re-renders)\n(ref-set! my-ref new-value)\n\n;; Predicate\n(ref? my-ref)  ;; => true"
        "lisp"))

      (p "Plain dicts with a " (code "__ref") " marker key (mirrors the " (code "__signal") " pattern). "
         "On island disposal, the ref value is auto-nilled via " (code "register-in-scope") "."))

    (~docs/section :title "When to Use Ref vs Signal" :id "ref-vs-signal"

      (table (~tw :tokens "w-full mb-6 text-sm")
        (thead
          (tr (th (~tw :tokens "text-left p-2") "Use Ref") (th (~tw :tokens "text-left p-2") "Use Signal")))
        (tbody
          (tr (td (~tw :tokens "p-2") "DOM element handle") (td (~tw :tokens "p-2") "UI state that triggers re-render"))
          (tr (td (~tw :tokens "p-2") "Canvas 2D context") (td (~tw :tokens "p-2") "Form input value"))
          (tr (td (~tw :tokens "p-2") "Timer/interval ID") (td (~tw :tokens "p-2") "Counter, toggle, selection"))
          (tr (td (~tw :tokens "p-2") "WebSocket connection") (td (~tw :tokens "p-2") "Anything the UI reads via deref")))))

    (~docs/section :title "Implementation" :id "ref-impl"

      (~docs/code :src (highlight
        "(define make-ref (fn (value)\n  (dict \"__ref\" true \"value\" value)))\n\n(define ref? (fn (x)\n  (and (dict? x) (has-key? x \"__ref\"))))\n\n(define ref (fn (initial-value)\n  (let ((r (make-ref initial-value)))\n    (register-in-scope (fn () (dict-set! r \"value\" nil)))\n    r)))\n\n(define ref-deref (fn (r) (get r \"value\")))\n(define ref-set! (fn (r v) (dict-set! r \"value\" v)))"
        "lisp"))

      (p "~35 lines. No dependencies beyond " (code "register-in-scope") " from signals.sx."))))
