Add spread + collect primitives, rewrite ~cssx/tw as defcomp
New SX primitives for child-to-parent communication in the render tree: - spread type: make-spread, spread?, spread-attrs — child injects attrs onto parent element (class joins with space, style with semicolon) - collect!/collected/clear-collected! — render-time accumulation with dedup into named buckets ~cssx/tw is now a proper defcomp returning a spread value instead of a macro wrapping children. ~cssx/flush reads collected "cssx" rules and emits a single <style data-cssx> tag. All four render adapters (html, async, dom, aser) handle spread values. Both bootstraps (Python + JS) regenerated. Also fixes length→len in cssx.sx (length was never a registered primitive). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -313,3 +313,61 @@
|
||||
:effects [mutation]
|
||||
:doc "Group multiple signal writes. Subscribers are notified once at the end,
|
||||
after all values have been updated.")
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Tier 4: Spread + Collect — render-time attribute injection and accumulation
|
||||
;;
|
||||
;; `spread` is a new type: a dict of attributes that, when returned as a child
|
||||
;; of an HTML element, merges its attrs onto the parent element rather than
|
||||
;; rendering as content. This enables components like `~cssx/tw` to inject
|
||||
;; classes and styles onto their parent from inside the child list.
|
||||
;;
|
||||
;; `collect!` / `collected` are render-time accumulators. Values are collected
|
||||
;; into named buckets (with deduplication) during rendering and retrieved at
|
||||
;; flush points (e.g. a single <style> tag for all collected CSS rules).
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(declare-tier :spread :source "render.sx")
|
||||
|
||||
(declare-spread-primitive "make-spread"
|
||||
:params (attrs)
|
||||
:returns "spread"
|
||||
:effects []
|
||||
:doc "Create a spread value from an attrs dict. When this value appears as
|
||||
a child of an HTML element, its attrs are merged onto the parent
|
||||
element (class values joined, others overwritten).")
|
||||
|
||||
(declare-spread-primitive "spread?"
|
||||
:params (x)
|
||||
:returns "boolean"
|
||||
:effects []
|
||||
:doc "Test whether a value is a spread.")
|
||||
|
||||
(declare-spread-primitive "spread-attrs"
|
||||
:params (s)
|
||||
:returns "dict"
|
||||
:effects []
|
||||
:doc "Extract the attrs dict from a spread value.")
|
||||
|
||||
(declare-spread-primitive "collect!"
|
||||
:params (bucket value)
|
||||
:returns "nil"
|
||||
:effects [mutation]
|
||||
:doc "Add value to a named render-time accumulator bucket. Values are
|
||||
deduplicated (no duplicates added). Buckets persist for the duration
|
||||
of the current render pass.")
|
||||
|
||||
(declare-spread-primitive "collected"
|
||||
:params (bucket)
|
||||
:returns "list"
|
||||
:effects []
|
||||
:doc "Return all values collected in the named bucket during the current
|
||||
render pass. Returns an empty list if the bucket doesn't exist.")
|
||||
|
||||
(declare-spread-primitive "clear-collected!"
|
||||
:params (bucket)
|
||||
:returns "nil"
|
||||
:effects [mutation]
|
||||
:doc "Clear a named render-time accumulator bucket. Used at flush points
|
||||
after emitting collected values (e.g. after writing a <style> tag).")
|
||||
|
||||
Reference in New Issue
Block a user