Add header and event detail pages, fix copyright, rename essay

- Detail pages for all 18 HTTP headers with descriptions, example usage,
  direction badges (request/response/both), and live demos for SX-Prompt,
  SX-Trigger, SX-Retarget
- Detail pages for all 10 DOM events with descriptions, example usage,
  and live demos for beforeRequest, afterSettle, responseError,
  validationFailed
- Header and event table rows now link to their detail pages
- Fix copyright symbol on home page (was literal \u00a9, now actual ©)
- Rename "Godel, Escher, Bach" essay to "Strange Loops" with updated summary
- Remove duplicate script injection from bootstrapper page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 16:25:15 +00:00
parent 1797bd4b16
commit 5fff83ae79
11 changed files with 779 additions and 18 deletions

View File

@@ -643,3 +643,151 @@
"Connecting to SSE stream..."))
(p :class "text-xs text-stone-400"
"Server pushes time updates every 2 seconds via Server-Sent Events.")))
;; ===========================================================================
;; Header detail demos
;; ===========================================================================
;; ---------------------------------------------------------------------------
;; SX-Prompt header demo
;; ---------------------------------------------------------------------------
(defcomp ~ref-header-prompt-demo ()
(div :class "space-y-3"
(button
:sx-get "/reference/api/prompt-echo"
:sx-target "#ref-hdr-prompt-result"
:sx-swap "innerHTML"
:sx-prompt "Enter your name:"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Prompt & send")
(div :id "ref-hdr-prompt-result"
:class "p-3 rounded bg-stone-100 text-stone-400 text-sm"
"Click to enter a name via prompt — the value is sent as the SX-Prompt header.")))
;; ---------------------------------------------------------------------------
;; SX-Trigger response header demo
;; ---------------------------------------------------------------------------
(defcomp ~ref-header-trigger-demo ()
(div :class "space-y-3"
(button
:sx-get "/reference/api/trigger-event"
:sx-target "#ref-hdr-trigger-result"
:sx-swap "innerHTML"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Load with trigger")
(div :id "ref-hdr-trigger-result"
:class "p-3 rounded bg-stone-100 text-stone-400 text-sm"
:sx-on:showNotice "this.style.borderColor = '#8b5cf6'; this.style.borderWidth = '2px'"
"Click — the server response includes SX-Trigger: showNotice, which highlights this box.")))
;; ---------------------------------------------------------------------------
;; SX-Retarget response header demo
;; ---------------------------------------------------------------------------
(defcomp ~ref-header-retarget-demo ()
(div :class "space-y-3"
(button
:sx-get "/reference/api/retarget"
:sx-target "#ref-hdr-retarget-main"
:sx-swap "innerHTML"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Load (server retargets)")
(div :class "grid grid-cols-2 gap-3"
(div :class "rounded border border-stone-200 p-3"
(div :class "text-xs text-stone-400 mb-1" "Original target")
(div :id "ref-hdr-retarget-main" :class "text-sm text-stone-500" "Waiting..."))
(div :class "rounded border border-stone-200 p-3"
(div :class "text-xs text-stone-400 mb-1" "Retarget destination")
(div :id "ref-hdr-retarget-alt" :class "text-sm text-stone-500" "Waiting...")))))
;; ===========================================================================
;; Event detail demos
;; ===========================================================================
;; ---------------------------------------------------------------------------
;; sx:beforeRequest event demo
;; ---------------------------------------------------------------------------
(defcomp ~ref-event-before-request-demo ()
(div :class "space-y-3"
(div :class "flex gap-2 items-center"
(input :id "ref-evt-br-input" :type "text" :placeholder "Type something first..."
:class "flex-1 px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500")
(button
:sx-get "/reference/api/time"
:sx-target "#ref-evt-br-result"
:sx-swap "innerHTML"
:sx-on:sx:beforeRequest "if (!document.getElementById('ref-evt-br-input').value) { event.preventDefault(); document.getElementById('ref-evt-br-result').textContent = 'Cancelled — input is empty!'; }"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Load"))
(div :id "ref-evt-br-result"
:class "p-3 rounded bg-stone-100 text-stone-400 text-sm"
"Request is cancelled via preventDefault() if the input is empty.")))
;; ---------------------------------------------------------------------------
;; sx:afterSettle event demo
;; ---------------------------------------------------------------------------
(defcomp ~ref-event-after-settle-demo ()
(div :class "space-y-3"
(button
:sx-get "/reference/api/swap-item"
:sx-target "#ref-evt-settle-list"
:sx-swap "beforeend"
:sx-on:sx:afterSettle "var items = document.querySelectorAll('#ref-evt-settle-list > div'); if (items.length) items[items.length-1].scrollIntoView({behavior:'smooth'})"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Add item (scrolls after settle)")
(div :id "ref-evt-settle-list"
:class "p-3 rounded border border-stone-200 space-y-1 max-h-32 overflow-y-auto"
(div :class "text-sm text-stone-500" "Items will be appended and scrolled into view."))))
;; ---------------------------------------------------------------------------
;; sx:responseError event demo
;; ---------------------------------------------------------------------------
(defcomp ~ref-event-response-error-demo ()
(div :class "space-y-3"
(button
:sx-get "/reference/api/error-500"
:sx-target "#ref-evt-err-result"
:sx-swap "innerHTML"
:sx-on:sx:responseError "var s=document.getElementById('ref-evt-err-status'); s.style.display='block'; s.textContent='Error ' + (event.detail ? event.detail.status || '?' : '?') + ' received'"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Call failing endpoint")
(div :id "ref-evt-err-status"
:class "p-2 rounded bg-red-50 text-red-600 text-sm"
:style "display: none"
"")
(div :id "ref-evt-err-result"
:class "p-3 rounded bg-stone-100 text-stone-400 text-sm"
"Click to trigger an error — the sx:responseError event fires.")))
;; ---------------------------------------------------------------------------
;; sx:validationFailed event demo
;; ---------------------------------------------------------------------------
;; @css invalid:border-red-400
(defcomp ~ref-event-validation-failed-demo ()
(div :class "space-y-3"
(form
:sx-post "/reference/api/greet"
:sx-target "#ref-evt-vf-result"
:sx-swap "innerHTML"
:sx-validate "true"
:sx-on:sx:validationFailed "document.getElementById('ref-evt-vf-status').style.display = 'block'"
:class "flex gap-2"
(input :type "email" :name "email" :required "true"
:placeholder "Email (required)"
:class "flex-1 px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500 invalid:border-red-400")
(button :type "submit"
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
"Submit"))
(div :id "ref-evt-vf-status"
:class "p-2 rounded bg-amber-50 text-amber-700 text-sm"
:style "display: none"
"Validation failed — form was not submitted.")
(div :id "ref-evt-vf-result"
:class "p-3 rounded bg-stone-100 text-stone-400 text-sm"
"Submit with empty/invalid email to trigger the event.")))