Merge worktree-typed into macros: defcomp type annotations
This commit is contained in:
@@ -1,18 +1,34 @@
|
||||
;; SX docs — home page components
|
||||
|
||||
;; YouTube embed — rendered client-side from video ID returned by /api/random-video.
|
||||
;; Marsh demo: the server picks the video (hypermedia), the island triggers the fetch (reactive).
|
||||
;; YouTube video embed — rendered client-side from video ID returned by /api/random-video.
|
||||
;; Marsh demo: server picks video (hypermedia), island controls playback (reactive).
|
||||
;; Play/pause uses YouTube postMessage API via dom-call-method — no iframe reload.
|
||||
(defcomp ~video-embed (&key video-id)
|
||||
(<>
|
||||
(button
|
||||
:sx-get "/api/clear-video" :sx-target "#video-embed"
|
||||
:sx-swap "innerHTML"
|
||||
:style "position:absolute;top:-0.5rem;right:-0.5rem;width:1.25rem;height:1.25rem;border-radius:50%;border:none;background:rgba(0,0,0,0.5);color:white;font-size:0.75rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;"
|
||||
"x")
|
||||
(iframe :src (str "https://www.youtube.com/embed/" video-id "?autoplay=1&mute=1")
|
||||
:allow "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
:allowfullscreen "true"
|
||||
:style "width:100%;aspect-ratio:16/9;border-radius:0.5rem;border:none;")))
|
||||
(let ((playing (signal true)))
|
||||
(<>
|
||||
;; Close button — clears via hypermedia
|
||||
(button
|
||||
:sx-get "/api/clear-video" :sx-target "#video-embed"
|
||||
:sx-swap "innerHTML"
|
||||
:style "position:absolute;top:-0.5rem;right:-0.5rem;width:1.25rem;height:1.25rem;border-radius:50%;border:none;background:rgba(0,0,0,0.5);color:white;font-size:0.75rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;"
|
||||
"x")
|
||||
;; Play/pause button — reactive signal toggles YouTube via postMessage
|
||||
(button
|
||||
:on-click (fn (e)
|
||||
(let ((iframe (dom-query "#video-iframe"))
|
||||
(win (dom-get-prop iframe "contentWindow"))
|
||||
(cmd (if (deref playing) "pauseVideo" "playVideo")))
|
||||
(dom-call-method win "postMessage"
|
||||
(str "{\"event\":\"command\",\"func\":\"" cmd "\",\"args\":[]}")
|
||||
"https://www.youtube.com")
|
||||
(reset! playing (not (deref playing)))))
|
||||
:style "position:absolute;top:1rem;right:-0.5rem;width:1.25rem;height:1.25rem;border-radius:50%;border:none;background:rgba(0,0,0,0.5);color:white;font-size:0.75rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;"
|
||||
(if (deref playing) "||" ">"))
|
||||
;; Iframe — stays in DOM, playback controlled via postMessage
|
||||
(iframe :id "video-iframe"
|
||||
:src (str "https://www.youtube.com/embed/" video-id "?autoplay=1&enablejsapi=1&controls=0&modestbranding=1&rel=0")
|
||||
:allow "accelerometer; autoplay; encrypted-media"
|
||||
:style "width:100%;aspect-ratio:16/9;border-radius:0.5rem;border:none;pointer-events:none;"))))
|
||||
|
||||
(defcomp ~sx-hero (&key &rest children)
|
||||
(div :class "max-w-4xl mx-auto px-6 py-16 text-center"
|
||||
|
||||
Reference in New Issue
Block a user