Add flush-cssx-to-dom: client-side CSSX rule injection
Islands render independently on the client, so ~cssx/tw calls
collect!("cssx", rule) but no ~cssx/flush runs. Add flush-cssx-to-dom
in boot.sx that injects collected rules into a persistent <style>
element in <head>.
Called at all lifecycle points: boot-init, sx-mount, resolve-suspense,
post-swap (navigation morph), and swap-rendered-content (client routes).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,7 +87,8 @@
|
||||
;; Process sx- attributes, hydrate data-sx and islands
|
||||
(process-elements el)
|
||||
(sx-hydrate-elements el)
|
||||
(sx-hydrate-islands el))))))
|
||||
(sx-hydrate-islands el)
|
||||
(flush-cssx-to-dom))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -119,6 +120,7 @@
|
||||
(process-elements el)
|
||||
(sx-hydrate-elements el)
|
||||
(sx-hydrate-islands el)
|
||||
(flush-cssx-to-dom)
|
||||
(dom-dispatch el "sx:resolved" {:id id})))
|
||||
(log-warn (str "resolveSuspense: no element for id=" id))))))
|
||||
|
||||
@@ -415,6 +417,32 @@
|
||||
(for-each dispose-island to-dispose))))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; CSSX live flush — inject collected CSS rules into the DOM
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; ~cssx/tw collects CSS rules via collect!("cssx" ...) during rendering.
|
||||
;; On the server, ~cssx/flush emits a batch <style> tag. On the client,
|
||||
;; islands render independently and no batch flush runs. This function
|
||||
;; injects any unflushed rules into a persistent <style> element in <head>.
|
||||
;; Called after hydration (boot + post-swap) to cover all render paths.
|
||||
|
||||
(define flush-cssx-to-dom :effects [mutation io]
|
||||
(fn ()
|
||||
(let ((rules (collected "cssx")))
|
||||
(when (not (empty? rules))
|
||||
(let ((style (or (dom-query "#sx-cssx-live")
|
||||
(let ((s (dom-create-element "style" nil)))
|
||||
(dom-set-attr s "id" "sx-cssx-live")
|
||||
(dom-set-attr s "data-cssx" "")
|
||||
(dom-append-to-head s)
|
||||
s))))
|
||||
(dom-set-prop style "textContent"
|
||||
(str (or (dom-get-prop style "textContent") "")
|
||||
(join "" rules))))
|
||||
(clear-collected! "cssx")))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Full boot sequence
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -436,6 +464,7 @@
|
||||
(process-sx-scripts nil)
|
||||
(sx-hydrate-elements nil)
|
||||
(sx-hydrate-islands nil)
|
||||
(flush-cssx-to-dom)
|
||||
(process-elements nil))))
|
||||
|
||||
|
||||
|
||||
@@ -460,6 +460,7 @@
|
||||
(sx-process-scripts root)
|
||||
(sx-hydrate root)
|
||||
(sx-hydrate-islands root)
|
||||
(flush-cssx-to-dom)
|
||||
(process-elements root)))
|
||||
|
||||
|
||||
@@ -870,6 +871,7 @@
|
||||
(hoist-head-elements-full target)
|
||||
(process-elements target)
|
||||
(sx-hydrate-elements target)
|
||||
(flush-cssx-to-dom)
|
||||
(dom-dispatch target "sx:clientRoute"
|
||||
(dict "pathname" pathname))
|
||||
(log-info (str "sx:route client " pathname)))))
|
||||
|
||||
Reference in New Issue
Block a user