Fix :ref callback bug in adapter-dom — Pretext island fully working
Root cause: adapter-dom.sx line 345 handled :ref by calling (dict-set! attr-val "current" el), assuming React-style ref objects. Callback-style refs (fn (el) ...) passed a function, not a dict, causing dict-set! to fail with "dict key val" error. Fix: (if (callable? attr-val) (attr-val el) (dict-set! attr-val "current" el)) Supports both callback refs and dict refs. Pretext island now fully working: - 3 controls: width slider, font size slider, algorithm toggle - Knuth-Plass + greedy line breaking via bytecode-compiled library - canvas.measureText for pixel-perfect browser font metrics - Effect-based imperative DOM rendering (createElement + appendChild) - Reactive: slider drag → re-measure → re-break → re-render Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
;; Test: add :ref callback
|
||||
;; Pretext island — full version with :ref (bug fix applied)
|
||||
(defisland
|
||||
~pretext-demo/live
|
||||
()
|
||||
@@ -7,38 +7,104 @@
|
||||
(mxw (signal 500))
|
||||
(font-size (signal 16))
|
||||
(use-optimal (signal true))
|
||||
(result (signal "loading..."))
|
||||
(el-ref (signal nil))
|
||||
(doc (host-global "document"))
|
||||
(canvas (host-call doc "createElement" "canvas"))
|
||||
(ctx (host-call canvas "getContext" "2d")))
|
||||
(ctx (host-call canvas "getContext" "2d"))
|
||||
(el-ref (signal nil)))
|
||||
(effect
|
||||
(fn
|
||||
()
|
||||
(let
|
||||
((w (deref mxw))
|
||||
((el (deref el-ref))
|
||||
(w (deref mxw))
|
||||
(sz (deref font-size))
|
||||
(opt (deref use-optimal)))
|
||||
(host-set! ctx "font" (str sz "px serif"))
|
||||
(let
|
||||
((widths (map (fn (wd) (host-get (host-call ctx "measureText" wd) "width")) words))
|
||||
(spw (host-get (host-call ctx "measureText" " ") "width")))
|
||||
(when
|
||||
el
|
||||
(let
|
||||
((ranges (if opt (break-lines widths spw w) (break-lines-greedy widths spw w))))
|
||||
((lh (* sz 1.5)))
|
||||
(host-set!
|
||||
ctx
|
||||
"font"
|
||||
(str sz "px 'Pretext Serif', DejaVu Serif, serif"))
|
||||
(let
|
||||
((lines (pretext-layout-lines words widths ranges spw w (* sz 1.5))))
|
||||
(reset!
|
||||
result
|
||||
(str
|
||||
(len lines)
|
||||
" lines — "
|
||||
w
|
||||
"px / "
|
||||
sz
|
||||
"px / "
|
||||
(if opt "optimal" "greedy")))))))))
|
||||
((widths (map (fn (wd) (host-get (host-call ctx "measureText" wd) "width")) words))
|
||||
(spw (host-get (host-call ctx "measureText" " ") "width")))
|
||||
(let
|
||||
((ranges (if opt (break-lines widths spw w) (break-lines-greedy widths spw w)))
|
||||
(lines
|
||||
(pretext-layout-lines
|
||||
words
|
||||
widths
|
||||
(if
|
||||
opt
|
||||
(break-lines widths spw w)
|
||||
(break-lines-greedy widths spw w))
|
||||
spw
|
||||
w
|
||||
lh)))
|
||||
(host-set! el "innerHTML" "")
|
||||
(let
|
||||
((info (host-call doc "createElement" "div")))
|
||||
(host-set! info "className" "px-4 pt-3 pb-1")
|
||||
(host-set!
|
||||
info
|
||||
"innerHTML"
|
||||
(str
|
||||
"<span class='text-xs font-medium uppercase tracking-wide text-stone-400'>"
|
||||
(len lines)
|
||||
" lines — "
|
||||
w
|
||||
"px / "
|
||||
sz
|
||||
"px / "
|
||||
(if opt "optimal" "greedy")
|
||||
"</span>"))
|
||||
(host-call el "appendChild" info))
|
||||
(let
|
||||
((container (host-call doc "createElement" "div")))
|
||||
(host-set!
|
||||
container
|
||||
"style"
|
||||
(str
|
||||
"position:relative;height:"
|
||||
(* (len lines) lh)
|
||||
"px;padding:12px 16px"))
|
||||
(let
|
||||
render-lines
|
||||
((li 0))
|
||||
(when
|
||||
(< li (len lines))
|
||||
(let
|
||||
((line (nth lines li))
|
||||
(wds (get (nth lines li) :words)))
|
||||
(let
|
||||
render-words
|
||||
((wi 0))
|
||||
(when
|
||||
(< wi (len wds))
|
||||
(let
|
||||
((pw (nth wds wi))
|
||||
(span
|
||||
(host-call doc "createElement" "span")))
|
||||
(host-set! span "textContent" (get pw :word))
|
||||
(host-set!
|
||||
span
|
||||
"style"
|
||||
(str
|
||||
"position:absolute;left:"
|
||||
(+ (get pw :x) 16)
|
||||
"px;top:"
|
||||
(+ (get line :y) 12)
|
||||
"px;font:"
|
||||
sz
|
||||
"px 'Pretext Serif',serif;white-space:nowrap"))
|
||||
(host-call container "appendChild" span)
|
||||
(render-words (+ wi 1))))))
|
||||
(render-lines (+ li 1))))
|
||||
(host-call el "appendChild" container)))))))))
|
||||
(div
|
||||
(~tw :tokens "p-4 border rounded space-y-2")
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
(~tw :tokens "flex flex-wrap gap-4 items-end")
|
||||
(div
|
||||
@@ -77,5 +143,7 @@
|
||||
(~tw :tokens "px-3 py-1 rounded border text-sm")
|
||||
:on-click (fn (e) (reset! use-optimal (not (deref use-optimal))))
|
||||
(if (deref use-optimal) "Knuth-Plass" "Greedy"))))
|
||||
(div (deref result))
|
||||
(div :ref (fn (el) (reset! el-ref el)) ""))))
|
||||
(div
|
||||
:class "rounded-lg border border-stone-200 bg-white overflow-hidden"
|
||||
:ref (fn (el) (reset! el-ref el))
|
||||
""))))
|
||||
Reference in New Issue
Block a user