SXC content: docs/examples/home/reference pages + SX testing runner
New sxc/ content tree with 120 page files across docs, examples, home, and reference demos. sx/sx/testing/ adds page-runner.sx (317L) and index-runner.sx (394L) — SX-native test runner pages for browser-based evaluation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
17
sx/sxc/examples/active-search-demo.sx
Normal file
17
sx/sxc/examples/active-search-demo.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(input
|
||||
:type "text"
|
||||
:name "q"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.search))))"
|
||||
:sx-trigger "keyup delay:300ms changed"
|
||||
:sx-target "#search-results"
|
||||
:sx-swap "innerHTML"
|
||||
:placeholder "Search programming languages..."
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500"))
|
||||
(div
|
||||
:id "search-results"
|
||||
(~tw :tokens "border border-stone-200 rounded divide-y divide-stone-100")
|
||||
(p (~tw :tokens "p-3 text-sm text-stone-400") "Type to search..."))))
|
||||
8
sx/sxc/examples/anim-result.sx
Normal file
8
sx/sxc/examples/anim-result.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
(defcomp
|
||||
(&key color time)
|
||||
(div
|
||||
(~tw :tokens "sx-fade-in space-y-2")
|
||||
(div
|
||||
:class (str "p-4 rounded transition-colors duration-700 " color)
|
||||
(p (~tw :tokens "font-medium") "Faded in!")
|
||||
(p (~tw :tokens "text-sm mt-1") (str "Loaded at " time)))))
|
||||
14
sx/sxc/examples/animations-demo.sx
Normal file
14
sx/sxc/examples/animations-demo.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.animate))))"
|
||||
:sx-target "#anim-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Load with animation")
|
||||
(div
|
||||
:id "anim-target"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(p (~tw :tokens "text-stone-400") "Content will fade in here."))))
|
||||
17
sx/sxc/examples/bulk-row.sx
Normal file
17
sx/sxc/examples/bulk-row.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
(defcomp
|
||||
(&key id name email status)
|
||||
(tr
|
||||
(~tw :tokens "border-b border-stone-100")
|
||||
(td (~tw :tokens "px-3 py-2") (input :type "checkbox" :name "ids" :value id))
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-700") name)
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-700") email)
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2")
|
||||
(span
|
||||
:class (str
|
||||
"px-2 py-0.5 rounded text-xs font-medium "
|
||||
(if
|
||||
(= status "active")
|
||||
"bg-emerald-100 text-emerald-700"
|
||||
"bg-stone-100 text-stone-500"))
|
||||
status))))
|
||||
44
sx/sxc/examples/bulk-update-demo.sx
Normal file
44
sx/sxc/examples/bulk-update-demo.sx
Normal file
@@ -0,0 +1,44 @@
|
||||
(defcomp
|
||||
(&key users)
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(form
|
||||
:id "bulk-form"
|
||||
(div
|
||||
(~tw :tokens "flex gap-2 mb-3")
|
||||
(button
|
||||
:type "button"
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.bulk))))?action=activate"
|
||||
:sx-target "#bulk-table"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-include "#bulk-form"
|
||||
(~tw :tokens "px-3 py-1.5 bg-emerald-600 text-white rounded text-sm hover:bg-emerald-700")
|
||||
"Activate")
|
||||
(button
|
||||
:type "button"
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.bulk))))?action=deactivate"
|
||||
:sx-target "#bulk-table"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-include "#bulk-form"
|
||||
(~tw :tokens "px-3 py-1.5 bg-stone-600 text-white rounded text-sm hover:bg-stone-700")
|
||||
"Deactivate"))
|
||||
(table
|
||||
(~tw :tokens "w-full text-left text-sm")
|
||||
(thead
|
||||
(tr
|
||||
(~tw :tokens "border-b border-stone-200")
|
||||
(th (~tw :tokens "px-3 py-2 w-8") "")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Name")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Email")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Status")))
|
||||
(tbody
|
||||
:id "bulk-table"
|
||||
(map
|
||||
(fn
|
||||
(u)
|
||||
(~examples/bulk-row
|
||||
:id (nth u 0)
|
||||
:name (nth u 1)
|
||||
:email (nth u 2)
|
||||
:status (nth u 3)))
|
||||
users))))))
|
||||
9
sx/sxc/examples/card.sx
Normal file
9
sx/sxc/examples/card.sx
Normal file
@@ -0,0 +1,9 @@
|
||||
(defcomp
|
||||
(&key title description &rest children)
|
||||
(div
|
||||
(~tw :tokens "border border-stone-200 rounded-lg overflow-hidden")
|
||||
(div
|
||||
(~tw :tokens "bg-stone-100 px-4 py-3 border-b border-stone-200")
|
||||
(h3 (~tw :tokens "font-semibold text-stone-800") title)
|
||||
(when description (p (~tw :tokens "text-sm text-stone-500 mt-1") description)))
|
||||
(div (~tw :tokens "p-4") children)))
|
||||
8
sx/sxc/examples/click-result.sx
Normal file
8
sx/sxc/examples/click-result.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
(defcomp
|
||||
(&key time)
|
||||
(div
|
||||
(~tw :tokens "space-y-2")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") "Content loaded!")
|
||||
(p
|
||||
(~tw :tokens "text-stone-500 text-sm")
|
||||
(str "Fetched from the server via sx-get at " time))))
|
||||
14
sx/sxc/examples/click-to-load-demo.sx
Normal file
14
sx/sxc/examples/click-to-load-demo.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
:id "click-result"
|
||||
(~tw :tokens "p-4 rounded bg-stone-100 text-stone-500 text-center")
|
||||
"Click the button to load content.")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.click))))"
|
||||
:sx-target "#click-result"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors")
|
||||
"Load content")))
|
||||
17
sx/sxc/examples/delete-demo.sx
Normal file
17
sx/sxc/examples/delete-demo.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
(defcomp
|
||||
(&key items)
|
||||
(div
|
||||
(table
|
||||
(~tw :tokens "w-full text-left text-sm")
|
||||
(thead
|
||||
(tr
|
||||
(~tw :tokens "border-b border-stone-200")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Item")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600 w-20") "")))
|
||||
(tbody
|
||||
:id "delete-rows"
|
||||
(map
|
||||
(fn
|
||||
(item)
|
||||
(~examples/delete-row :id (nth item 0) :name (nth item 1)))
|
||||
items)))))
|
||||
15
sx/sxc/examples/delete-row.sx
Normal file
15
sx/sxc/examples/delete-row.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
(defcomp
|
||||
(&key id name)
|
||||
(tr
|
||||
:id (str "row-" id)
|
||||
(~tw :tokens "border-b border-stone-100 transition-all")
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-700") name)
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2")
|
||||
(button
|
||||
:sx-delete (str "/sx/(geography.(hypermedia.(example.(api.(delete." id ")))))")
|
||||
:sx-target (str "#row-" id)
|
||||
:sx-swap "outerHTML"
|
||||
:sx-confirm "Delete this item?"
|
||||
(~tw :tokens "text-rose-500 hover:text-rose-700 text-sm")
|
||||
"delete"))))
|
||||
5
sx/sxc/examples/demo.sx
Normal file
5
sx/sxc/examples/demo.sx
Normal file
@@ -0,0 +1,5 @@
|
||||
(defcomp
|
||||
(&key &rest children)
|
||||
(div
|
||||
(~tw :tokens "border border-dashed border-stone-300 rounded p-4 bg-stone-100")
|
||||
children))
|
||||
27
sx/sxc/examples/dialog-modal.sx
Normal file
27
sx/sxc/examples/dialog-modal.sx
Normal file
@@ -0,0 +1,27 @@
|
||||
(defcomp
|
||||
(&key title message)
|
||||
(div
|
||||
(~tw :tokens "fixed inset-0 z-50 flex items-center justify-center")
|
||||
(div
|
||||
(~tw :tokens "absolute inset-0 bg-black/50")
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dialog-close))))"
|
||||
:sx-target "#dialog-container"
|
||||
:sx-swap "innerHTML")
|
||||
(div
|
||||
(~tw :tokens "relative bg-stone-100 rounded-lg shadow-xl p-6 max-w-md w-full mx-4 space-y-4")
|
||||
(h3 (~tw :tokens "text-lg font-semibold text-stone-800") title)
|
||||
(p (~tw :tokens "text-stone-600") message)
|
||||
(div
|
||||
(~tw :tokens "flex justify-end gap-2")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dialog-close))))"
|
||||
:sx-target "#dialog-container"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-stone-200 text-stone-700 rounded text-sm hover:bg-stone-300")
|
||||
"Cancel")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dialog-close))))"
|
||||
:sx-target "#dialog-container"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"Confirm")))))
|
||||
10
sx/sxc/examples/dialogs-demo.sx
Normal file
10
sx/sxc/examples/dialogs-demo.sx
Normal file
@@ -0,0 +1,10 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dialog))))"
|
||||
:sx-target "#dialog-container"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Open Dialog")
|
||||
(div :id "dialog-container")))
|
||||
8
sx/sxc/examples/echo-result.sx
Normal file
8
sx/sxc/examples/echo-result.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
(defcomp
|
||||
(&key label items)
|
||||
(div
|
||||
(~tw :tokens "space-y-1")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") (str "Server received " label ":"))
|
||||
(map
|
||||
(fn (item) (div (~tw :tokens "text-sm text-stone-600 font-mono") item))
|
||||
items)))
|
||||
23
sx/sxc/examples/edit-row-demo.sx
Normal file
23
sx/sxc/examples/edit-row-demo.sx
Normal file
@@ -0,0 +1,23 @@
|
||||
(defcomp
|
||||
(&key rows)
|
||||
(div
|
||||
(table
|
||||
(~tw :tokens "w-full text-left text-sm")
|
||||
(thead
|
||||
(tr
|
||||
(~tw :tokens "border-b border-stone-200")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Name")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Price")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Stock")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600 w-24") "")))
|
||||
(tbody
|
||||
:id "edit-rows"
|
||||
(map
|
||||
(fn
|
||||
(row)
|
||||
(~examples/edit-row-view
|
||||
:id (nth row 0)
|
||||
:name (nth row 1)
|
||||
:price (nth row 2)
|
||||
:stock (nth row 3)))
|
||||
rows)))))
|
||||
44
sx/sxc/examples/edit-row-form.sx
Normal file
44
sx/sxc/examples/edit-row-form.sx
Normal file
@@ -0,0 +1,44 @@
|
||||
(defcomp
|
||||
(&key id name price stock)
|
||||
(tr
|
||||
:id (str "erow-" id)
|
||||
(~tw :tokens "border-b border-stone-100 bg-violet-50")
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2")
|
||||
(input
|
||||
:type "text"
|
||||
:name "name"
|
||||
:value name
|
||||
(~tw :tokens "w-full px-2 py-1 border border-stone-300 rounded text-sm")))
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2")
|
||||
(input
|
||||
:type "text"
|
||||
:name "price"
|
||||
:value price
|
||||
(~tw :tokens "w-20 px-2 py-1 border border-stone-300 rounded text-sm")))
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2")
|
||||
(input
|
||||
:type "text"
|
||||
:name "stock"
|
||||
:value stock
|
||||
(~tw :tokens "w-20 px-2 py-1 border border-stone-300 rounded text-sm")))
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 space-x-1")
|
||||
(button
|
||||
:sx-post (str "/sx/(geography.(hypermedia.(example.(api.(editrow." id ")))))")
|
||||
:sx-target (str "#erow-" id)
|
||||
:sx-swap "outerHTML"
|
||||
:sx-include (str "#erow-" id)
|
||||
(~tw :tokens "text-sm text-emerald-600 hover:text-emerald-800")
|
||||
"save")
|
||||
(button
|
||||
:sx-get (str
|
||||
"/sx/(geography.(hypermedia.(example.(api.(editrow-cancel."
|
||||
id
|
||||
")))))")
|
||||
:sx-target (str "#erow-" id)
|
||||
:sx-swap "outerHTML"
|
||||
(~tw :tokens "text-sm text-stone-500 hover:text-stone-700")
|
||||
"cancel"))))
|
||||
16
sx/sxc/examples/edit-row-view.sx
Normal file
16
sx/sxc/examples/edit-row-view.sx
Normal file
@@ -0,0 +1,16 @@
|
||||
(defcomp
|
||||
(&key id name price stock)
|
||||
(tr
|
||||
:id (str "erow-" id)
|
||||
(~tw :tokens "border-b border-stone-100")
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-700") name)
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-700") (str "$" price))
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-700") stock)
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2")
|
||||
(button
|
||||
:sx-get (str "/sx/(geography.(hypermedia.(example.(api.(editrow." id ")))))")
|
||||
:sx-target (str "#erow-" id)
|
||||
:sx-swap "outerHTML"
|
||||
(~tw :tokens "text-sm text-violet-600 hover:text-violet-800")
|
||||
"edit"))))
|
||||
24
sx/sxc/examples/form-demo.sx
Normal file
24
sx/sxc/examples/form-demo.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(form
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.form))))"
|
||||
:sx-target "#form-result"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Name")
|
||||
(input
|
||||
:type "text"
|
||||
:name "name"
|
||||
:placeholder "Enter a name"
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500")))
|
||||
(button
|
||||
:type "submit"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Submit"))
|
||||
(div
|
||||
:id "form-result"
|
||||
(~tw :tokens "p-3 rounded bg-stone-100 text-stone-500 text-sm text-center")
|
||||
"Submit the form to see the result.")))
|
||||
8
sx/sxc/examples/form-result.sx
Normal file
8
sx/sxc/examples/form-result.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
(defcomp
|
||||
(&key name)
|
||||
(div
|
||||
(~tw :tokens "text-stone-800")
|
||||
(p (str "Hello, " (if (empty? name) "stranger" name) "!"))
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-500 mt-1")
|
||||
"Submitted via sx-post. The form data was sent as a POST request.")))
|
||||
22
sx/sxc/examples/infinite-scroll-demo.sx
Normal file
22
sx/sxc/examples/infinite-scroll-demo.sx
Normal file
@@ -0,0 +1,22 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "h-64 overflow-y-auto border border-stone-200 rounded")
|
||||
:id "scroll-container"
|
||||
(div
|
||||
:id "scroll-items"
|
||||
(map-indexed
|
||||
(fn
|
||||
(i item)
|
||||
(div
|
||||
(~tw :tokens "px-4 py-3 border-b border-stone-100 text-sm text-stone-700")
|
||||
(str "Item " (+ i 1) " — loaded with the page")))
|
||||
(list 1 2 3 4 5))
|
||||
(div
|
||||
:id "scroll-sentinel"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.scroll))))?page=2"
|
||||
:sx-trigger "intersect once"
|
||||
:sx-target "#scroll-items"
|
||||
:sx-swap "beforeend"
|
||||
(~tw :tokens "p-3 text-center text-stone-400 text-sm")
|
||||
"Loading more..."))))
|
||||
6
sx/sxc/examples/inline-edit-demo.sx
Normal file
6
sx/sxc/examples/inline-edit-demo.sx
Normal file
@@ -0,0 +1,6 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
:id "edit-target"
|
||||
(~tw :tokens "space-y-3")
|
||||
(~examples/inline-view :value "Click edit to change this text")))
|
||||
25
sx/sxc/examples/inline-edit-form.sx
Normal file
25
sx/sxc/examples/inline-edit-form.sx
Normal file
@@ -0,0 +1,25 @@
|
||||
(defcomp
|
||||
(&key value)
|
||||
(form
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.edit))))"
|
||||
:sx-target "#edit-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "flex items-center gap-2 p-3 rounded border border-violet-300 bg-violet-50")
|
||||
(input
|
||||
:type "text"
|
||||
:name "value"
|
||||
:value value
|
||||
(~tw :tokens "flex-1 px-3 py-1.5 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500"))
|
||||
(button
|
||||
:type "submit"
|
||||
(~tw :tokens "px-3 py-1.5 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"save")
|
||||
(button
|
||||
:type "button"
|
||||
:sx-get (str
|
||||
"/sx/(geography.(hypermedia.(example.(api.edit-cancel))))?value="
|
||||
value)
|
||||
:sx-target "#edit-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-3 py-1.5 bg-stone-200 text-stone-700 rounded text-sm hover:bg-stone-300")
|
||||
"cancel")))
|
||||
24
sx/sxc/examples/inline-validation-demo.sx
Normal file
24
sx/sxc/examples/inline-validation-demo.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
(defcomp
|
||||
()
|
||||
(form
|
||||
(~tw :tokens "space-y-4")
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.validate-submit))))"
|
||||
:sx-target "#validation-result"
|
||||
:sx-swap "innerHTML"
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Email")
|
||||
(input
|
||||
:type "text"
|
||||
:name "email"
|
||||
:placeholder "user@example.com"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.validate))))"
|
||||
:sx-trigger "blur"
|
||||
:sx-target "#email-feedback"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500"))
|
||||
(div :id "email-feedback" (~tw :tokens "mt-1")))
|
||||
(button
|
||||
:type "submit"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Submit")
|
||||
(div :id "validation-result")))
|
||||
11
sx/sxc/examples/inline-view.sx
Normal file
11
sx/sxc/examples/inline-view.sx
Normal file
@@ -0,0 +1,11 @@
|
||||
(defcomp
|
||||
(&key value)
|
||||
(div
|
||||
(~tw :tokens "flex items-center justify-between p-3 rounded border border-stone-200")
|
||||
(span (~tw :tokens "text-stone-800") value)
|
||||
(button
|
||||
:sx-get (str "/sx/(geography.(hypermedia.(example.(api.edit))))?value=" value)
|
||||
:sx-target "#edit-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "text-sm text-violet-600 hover:text-violet-800")
|
||||
"edit")))
|
||||
32
sx/sxc/examples/json-encoding-demo.sx
Normal file
32
sx/sxc/examples/json-encoding-demo.sx
Normal file
@@ -0,0 +1,32 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(form
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.json-echo))))"
|
||||
:sx-target "#json-result"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-encoding "json"
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Name")
|
||||
(input
|
||||
:type "text"
|
||||
:name "name"
|
||||
:value "Ada Lovelace"
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm")))
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Age")
|
||||
(input
|
||||
:type "number"
|
||||
:name "age"
|
||||
:value "36"
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm")))
|
||||
(button
|
||||
:type "submit"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Submit as JSON"))
|
||||
(div
|
||||
:id "json-result"
|
||||
(~tw :tokens "p-3 rounded bg-stone-100 text-stone-500 text-sm")
|
||||
"Submit the form to see the server echo the parsed JSON.")))
|
||||
9
sx/sxc/examples/json-result.sx
Normal file
9
sx/sxc/examples/json-result.sx
Normal file
@@ -0,0 +1,9 @@
|
||||
(defcomp
|
||||
(&key body content-type)
|
||||
(div
|
||||
(~tw :tokens "space-y-2")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") "Server received:")
|
||||
(pre
|
||||
(~tw :tokens "text-sm bg-stone-100 p-3 rounded overflow-x-auto")
|
||||
(code body))
|
||||
(p (~tw :tokens "text-sm text-stone-500") (str "Content-Type: " content-type))))
|
||||
8
sx/sxc/examples/kbd-result.sx
Normal file
8
sx/sxc/examples/kbd-result.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
(defcomp
|
||||
(&key key action)
|
||||
(div
|
||||
(~tw :tokens "space-y-1")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") action)
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-500")
|
||||
(str "Triggered by pressing '" key "'"))))
|
||||
46
sx/sxc/examples/keyboard-shortcuts-demo.sx
Normal file
46
sx/sxc/examples/keyboard-shortcuts-demo.sx
Normal file
@@ -0,0 +1,46 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100")
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-600 font-medium mb-2")
|
||||
"Keyboard shortcuts:")
|
||||
(div
|
||||
(~tw :tokens "flex gap-4")
|
||||
(div
|
||||
(~tw :tokens "flex items-center gap-1")
|
||||
(kbd
|
||||
(~tw :tokens "px-2 py-0.5 bg-stone-100 border border-stone-300 rounded text-xs font-mono")
|
||||
"s")
|
||||
(span (~tw :tokens "text-sm text-stone-500") "Search"))
|
||||
(div
|
||||
(~tw :tokens "flex items-center gap-1")
|
||||
(kbd
|
||||
(~tw :tokens "px-2 py-0.5 bg-stone-100 border border-stone-300 rounded text-xs font-mono")
|
||||
"n")
|
||||
(span (~tw :tokens "text-sm text-stone-500") "New item"))
|
||||
(div
|
||||
(~tw :tokens "flex items-center gap-1")
|
||||
(kbd
|
||||
(~tw :tokens "px-2 py-0.5 bg-stone-100 border border-stone-300 rounded text-xs font-mono")
|
||||
"h")
|
||||
(span (~tw :tokens "text-sm text-stone-500") "Help"))))
|
||||
(div
|
||||
:id "kbd-target"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.keyboard))))?key=s"
|
||||
:sx-trigger "keyup[key=='s'&&!event.target.matches('input,textarea')] from:body"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(p (~tw :tokens "text-stone-400 text-sm") "Press a shortcut key..."))
|
||||
(div
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.keyboard))))?key=n"
|
||||
:sx-trigger "keyup[key=='n'&&!event.target.matches('input,textarea')] from:body"
|
||||
:sx-target "#kbd-target"
|
||||
:sx-swap "innerHTML")
|
||||
(div
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.keyboard))))?key=h"
|
||||
:sx-trigger "keyup[key=='h'&&!event.target.matches('input,textarea')] from:body"
|
||||
:sx-target "#kbd-target"
|
||||
:sx-swap "innerHTML")))
|
||||
17
sx/sxc/examples/lazy-loading-demo.sx
Normal file
17
sx/sxc/examples/lazy-loading-demo.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-500")
|
||||
"The content below loads automatically when the page renders.")
|
||||
(div
|
||||
:id "lazy-target"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.lazy))))"
|
||||
:sx-trigger "load"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "p-6 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(div
|
||||
(~tw :tokens "animate-pulse space-y-2")
|
||||
(div (~tw :tokens "h-4 bg-stone-200 rounded w-3/4 mx-auto"))
|
||||
(div (~tw :tokens "h-4 bg-stone-200 rounded w-1/2 mx-auto"))))))
|
||||
8
sx/sxc/examples/lazy-result.sx
Normal file
8
sx/sxc/examples/lazy-result.sx
Normal file
@@ -0,0 +1,8 @@
|
||||
(defcomp
|
||||
(&key time)
|
||||
(div
|
||||
(~tw :tokens "space-y-2")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") "Content loaded on page render!")
|
||||
(p
|
||||
(~tw :tokens "text-stone-500 text-sm")
|
||||
(str "Loaded via sx-trigger=\"load\" at " time))))
|
||||
5
sx/sxc/examples/loading-result.sx
Normal file
5
sx/sxc/examples/loading-result.sx
Normal file
@@ -0,0 +1,5 @@
|
||||
(defcomp
|
||||
(&key time)
|
||||
(div
|
||||
(p (~tw :tokens "text-stone-800 font-medium") "Loaded!")
|
||||
(p (~tw :tokens "text-sm text-stone-500") (str "Response arrived at " time))))
|
||||
18
sx/sxc/examples/loading-states-demo.sx
Normal file
18
sx/sxc/examples/loading-states-demo.sx
Normal file
@@ -0,0 +1,18 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.slow))))"
|
||||
:sx-target "#loading-result"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "sx-loading-btn px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm flex items-center gap-2")
|
||||
(span
|
||||
(~tw :tokens "sx-spinner w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin"))
|
||||
(span "Load slow endpoint"))
|
||||
(div
|
||||
:id "loading-result"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(p
|
||||
(~tw :tokens "text-stone-400 text-sm")
|
||||
"Click the button — it takes 2 seconds."))))
|
||||
22
sx/sxc/examples/oob-demo.sx
Normal file
22
sx/sxc/examples/oob-demo.sx
Normal file
@@ -0,0 +1,22 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
(~tw :tokens "grid grid-cols-2 gap-4")
|
||||
(div
|
||||
:id "oob-box-a"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(p (~tw :tokens "text-stone-500") "Box A")
|
||||
(p (~tw :tokens "text-sm text-stone-400") "Waiting..."))
|
||||
(div
|
||||
:id "oob-box-b"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(p (~tw :tokens "text-stone-500") "Box B")
|
||||
(p (~tw :tokens "text-sm text-stone-400") "Waiting...")))
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.oob))))"
|
||||
:sx-target "#oob-box-a"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Update both boxes")))
|
||||
17
sx/sxc/examples/poll-result.sx
Normal file
17
sx/sxc/examples/poll-result.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
(defcomp
|
||||
(&key time count)
|
||||
(div
|
||||
(p (~tw :tokens "text-stone-800 font-medium") (str "Server time: " time))
|
||||
(p (~tw :tokens "text-stone-500 text-sm mt-1") (str "Poll count: " count))
|
||||
(div
|
||||
(~tw :tokens "mt-2 flex justify-center")
|
||||
(div
|
||||
(~tw :tokens "flex gap-1")
|
||||
(map
|
||||
(fn
|
||||
(i)
|
||||
(div
|
||||
:class (str
|
||||
"w-2 h-2 rounded-full "
|
||||
(if (<= i count) "bg-violet-500" "bg-stone-200"))))
|
||||
(list 1 2 3 4 5 6 7 8 9 10))))))
|
||||
11
sx/sxc/examples/polling-demo.sx
Normal file
11
sx/sxc/examples/polling-demo.sx
Normal file
@@ -0,0 +1,11 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
:id "poll-target"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.poll))))"
|
||||
:sx-trigger "load, every 2s"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center font-mono")
|
||||
"Loading...")))
|
||||
41
sx/sxc/examples/pp-form-full.sx
Normal file
41
sx/sxc/examples/pp-form-full.sx
Normal file
@@ -0,0 +1,41 @@
|
||||
(defcomp
|
||||
(&key name email role)
|
||||
(form
|
||||
:sx-put "/sx/(geography.(hypermedia.(example.(api.putpatch))))"
|
||||
:sx-target "#pp-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Name")
|
||||
(input
|
||||
:type "text"
|
||||
:name "name"
|
||||
:value name
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm")))
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Email")
|
||||
(input
|
||||
:type "text"
|
||||
:name "email"
|
||||
:value email
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm")))
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Role")
|
||||
(input
|
||||
:type "text"
|
||||
:name "role"
|
||||
:value role
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm")))
|
||||
(div
|
||||
(~tw :tokens "flex gap-2")
|
||||
(button
|
||||
:type "submit"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"Save All (PUT)")
|
||||
(button
|
||||
:type "button"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.putpatch-cancel))))"
|
||||
:sx-target "#pp-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-stone-200 text-stone-700 rounded text-sm hover:bg-stone-300")
|
||||
"Cancel"))))
|
||||
16
sx/sxc/examples/pp-view.sx
Normal file
16
sx/sxc/examples/pp-view.sx
Normal file
@@ -0,0 +1,16 @@
|
||||
(defcomp
|
||||
(&key name email role)
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(~tw :tokens "flex justify-between items-start")
|
||||
(div
|
||||
(p (~tw :tokens "text-stone-800 font-medium") name)
|
||||
(p (~tw :tokens "text-sm text-stone-500") email)
|
||||
(p (~tw :tokens "text-sm text-stone-500") role))
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.putpatch-edit-all))))"
|
||||
:sx-target "#pp-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "text-sm text-violet-600 hover:text-violet-800")
|
||||
"Edit All (PUT)"))))
|
||||
19
sx/sxc/examples/progress-bar-demo.sx
Normal file
19
sx/sxc/examples/progress-bar-demo.sx
Normal file
@@ -0,0 +1,19 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
:id "progress-target"
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(~tw :tokens "w-full bg-stone-200 rounded-full h-4")
|
||||
(div
|
||||
(~tw :tokens "bg-violet-600 h-4 rounded-full transition-all")
|
||||
:style "width: 0%"))
|
||||
(p (~tw :tokens "text-sm text-stone-500 text-center") "Click start to begin."))
|
||||
(button
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.progress-start))))"
|
||||
:sx-target "#progress-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Start job")))
|
||||
24
sx/sxc/examples/progress-status.sx
Normal file
24
sx/sxc/examples/progress-status.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
(defcomp
|
||||
(&key percent job-id)
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(~tw :tokens "w-full bg-stone-200 rounded-full h-4")
|
||||
(div
|
||||
(~tw :tokens "bg-violet-600 h-4 rounded-full transition-all")
|
||||
:style (str "width: " percent "%")))
|
||||
(p (~tw :tokens "text-sm text-stone-500 text-center") (str percent "% complete"))
|
||||
(when
|
||||
(< percent 100)
|
||||
(div
|
||||
:sx-get (str
|
||||
"/sx/(geography.(hypermedia.(example.(api.progress-status))))?job="
|
||||
job-id)
|
||||
:sx-trigger "load delay:500ms"
|
||||
:sx-target "#progress-target"
|
||||
:sx-swap "innerHTML"))
|
||||
(when
|
||||
(= percent 100)
|
||||
(p
|
||||
(~tw :tokens "text-sm text-emerald-600 font-medium text-center")
|
||||
"Job complete!"))))
|
||||
6
sx/sxc/examples/put-patch-demo.sx
Normal file
6
sx/sxc/examples/put-patch-demo.sx
Normal file
@@ -0,0 +1,6 @@
|
||||
(defcomp
|
||||
(&key name email role)
|
||||
(div
|
||||
:id "pp-target"
|
||||
(~tw :tokens "space-y-4")
|
||||
(~examples/pp-view :name name :email email :role role)))
|
||||
5
sx/sxc/examples/reset-message.sx
Normal file
5
sx/sxc/examples/reset-message.sx
Normal file
@@ -0,0 +1,5 @@
|
||||
(defcomp
|
||||
(&key message time)
|
||||
(div
|
||||
(~tw :tokens "px-3 py-2 bg-stone-100 rounded text-sm text-stone-700")
|
||||
(str "[" time "] " message)))
|
||||
24
sx/sxc/examples/reset-on-submit-demo.sx
Normal file
24
sx/sxc/examples/reset-on-submit-demo.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(form
|
||||
:id "reset-form"
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.reset-submit))))"
|
||||
:sx-target "#reset-result"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-on:afterSwap "this.reset()"
|
||||
(~tw :tokens "flex gap-2")
|
||||
(input
|
||||
:type "text"
|
||||
:name "message"
|
||||
:placeholder "Type a message..."
|
||||
(~tw :tokens "flex-1 px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500"))
|
||||
(button
|
||||
:type "submit"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Send"))
|
||||
(div
|
||||
:id "reset-result"
|
||||
(~tw :tokens "space-y-2")
|
||||
(p (~tw :tokens "text-sm text-stone-400") "Messages will appear here."))))
|
||||
17
sx/sxc/examples/retry-demo.sx
Normal file
17
sx/sxc/examples/retry-demo.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.flaky))))"
|
||||
:sx-target "#retry-result"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-retry "exponential:1000:8000"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Call flaky endpoint")
|
||||
(div
|
||||
:id "retry-result"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100 text-center")
|
||||
(p
|
||||
(~tw :tokens "text-stone-400 text-sm")
|
||||
"Endpoint fails twice, succeeds on 3rd attempt."))))
|
||||
6
sx/sxc/examples/retry-result.sx
Normal file
6
sx/sxc/examples/retry-result.sx
Normal file
@@ -0,0 +1,6 @@
|
||||
(defcomp
|
||||
(&key attempt message)
|
||||
(div
|
||||
(~tw :tokens "space-y-1")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") message)
|
||||
(p (~tw :tokens "text-sm text-stone-500") (str "Succeeded on attempt #" attempt))))
|
||||
20
sx/sxc/examples/scroll-items.sx
Normal file
20
sx/sxc/examples/scroll-items.sx
Normal file
@@ -0,0 +1,20 @@
|
||||
(defcomp
|
||||
(&key items page)
|
||||
(<>
|
||||
(map
|
||||
(fn
|
||||
(item)
|
||||
(div
|
||||
(~tw :tokens "px-4 py-3 border-b border-stone-100 text-sm text-stone-700")
|
||||
item))
|
||||
items)
|
||||
(when
|
||||
(<= page 5)
|
||||
(div
|
||||
:id "scroll-sentinel"
|
||||
:sx-get (str "/sx/(geography.(hypermedia.(example.(api.scroll))))?page=" page)
|
||||
:sx-trigger "intersect once"
|
||||
:sx-target "#scroll-items"
|
||||
:sx-swap "beforeend"
|
||||
(~tw :tokens "p-3 text-center text-stone-400 text-sm")
|
||||
"Loading more..."))))
|
||||
11
sx/sxc/examples/search-results.sx
Normal file
11
sx/sxc/examples/search-results.sx
Normal file
@@ -0,0 +1,11 @@
|
||||
(defcomp
|
||||
(&key items query)
|
||||
(<>
|
||||
(if
|
||||
(empty? items)
|
||||
(p
|
||||
(~tw :tokens "p-3 text-sm text-stone-400")
|
||||
(str "No results for \"" query "\""))
|
||||
(map
|
||||
(fn (item) (div (~tw :tokens "px-3 py-2 text-sm text-stone-700") item))
|
||||
items))))
|
||||
30
sx/sxc/examples/select-filter-demo.sx
Normal file
30
sx/sxc/examples/select-filter-demo.sx
Normal file
@@ -0,0 +1,30 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(~tw :tokens "flex gap-2")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dashboard))))"
|
||||
:sx-target "#filter-target"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-select "#dash-stats"
|
||||
(~tw :tokens "px-3 py-1.5 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"Stats Only")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dashboard))))"
|
||||
:sx-target "#filter-target"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-select "#dash-header"
|
||||
(~tw :tokens "px-3 py-1.5 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"Header Only")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.dashboard))))"
|
||||
:sx-target "#filter-target"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "px-3 py-1.5 bg-stone-600 text-white rounded text-sm hover:bg-stone-700")
|
||||
"Full Dashboard"))
|
||||
(div
|
||||
:id "filter-target"
|
||||
(~tw :tokens "border border-stone-200 rounded p-4 bg-stone-100")
|
||||
(p (~tw :tokens "text-sm text-stone-400") "Click a button to load content."))))
|
||||
7
sx/sxc/examples/source.sx
Normal file
7
sx/sxc/examples/source.sx
Normal file
@@ -0,0 +1,7 @@
|
||||
(defcomp
|
||||
(&key src-code)
|
||||
(div
|
||||
(~tw :tokens "not-prose bg-stone-100 rounded p-5 mt-3 mx-auto max-w-3xl")
|
||||
(pre
|
||||
(~tw :tokens "text-sm leading-relaxed whitespace-pre-wrap break-words")
|
||||
(code src-code))))
|
||||
3
sx/sxc/examples/swap-entry.sx
Normal file
3
sx/sxc/examples/swap-entry.sx
Normal file
@@ -0,0 +1,3 @@
|
||||
(defcomp
|
||||
(&key time mode)
|
||||
(div (~tw :tokens "px-3 py-2 text-sm text-stone-700") (str "[" time "] " mode)))
|
||||
32
sx/sxc/examples/swap-positions-demo.sx
Normal file
32
sx/sxc/examples/swap-positions-demo.sx
Normal file
@@ -0,0 +1,32 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(~tw :tokens "flex gap-2")
|
||||
(button
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.swap-log))))?mode=beforeend"
|
||||
:sx-target "#swap-log"
|
||||
:sx-swap "beforeend"
|
||||
(~tw :tokens "px-3 py-1.5 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"Add to End")
|
||||
(button
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.swap-log))))?mode=afterbegin"
|
||||
:sx-target "#swap-log"
|
||||
:sx-swap "afterbegin"
|
||||
(~tw :tokens "px-3 py-1.5 bg-violet-600 text-white rounded text-sm hover:bg-violet-700")
|
||||
"Add to Start")
|
||||
(button
|
||||
:sx-post "/sx/(geography.(hypermedia.(example.(api.swap-log))))?mode=none"
|
||||
:sx-target "#swap-log"
|
||||
:sx-swap "none"
|
||||
(~tw :tokens "px-3 py-1.5 bg-stone-600 text-white rounded text-sm hover:bg-stone-700")
|
||||
"Silent Ping")
|
||||
(span
|
||||
:id "swap-counter"
|
||||
(~tw :tokens "self-center text-sm text-stone-500")
|
||||
"Count: 0"))
|
||||
(div
|
||||
:id "swap-log"
|
||||
(~tw :tokens "border border-stone-200 rounded h-48 overflow-y-auto divide-y divide-stone-100")
|
||||
(p (~tw :tokens "p-3 text-sm text-stone-400") "Log entries will appear here."))))
|
||||
20
sx/sxc/examples/sync-replace-demo.sx
Normal file
20
sx/sxc/examples/sync-replace-demo.sx
Normal file
@@ -0,0 +1,20 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(input
|
||||
:type "text"
|
||||
:name "q"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.slow-search))))"
|
||||
:sx-trigger "keyup delay:200ms changed"
|
||||
:sx-target "#sync-result"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-sync "replace"
|
||||
:placeholder "Type to search (random delay 0.5-2s)..."
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500"))
|
||||
(div
|
||||
:id "sync-result"
|
||||
(~tw :tokens "p-4 rounded border border-stone-200 bg-stone-100")
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-400")
|
||||
"Type to trigger requests — stale ones get aborted."))))
|
||||
7
sx/sxc/examples/sync-result.sx
Normal file
7
sx/sxc/examples/sync-result.sx
Normal file
@@ -0,0 +1,7 @@
|
||||
(defcomp
|
||||
(&key query delay)
|
||||
(div
|
||||
(p (~tw :tokens "text-stone-800 font-medium") (str "Result for: \"" query "\""))
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-500")
|
||||
(str "Server took " delay "ms to respond"))))
|
||||
14
sx/sxc/examples/tab-btn.sx
Normal file
14
sx/sxc/examples/tab-btn.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
(defcomp
|
||||
(&key tab label active)
|
||||
(button
|
||||
:sx-get (str "/sx/(geography.(hypermedia.(example.(api.(tabs." tab ")))))")
|
||||
:sx-target "#tab-content"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-push-url (str "/sx/(geography.(hypermedia.(example.tabs)))?tab=" tab)
|
||||
:class (str
|
||||
"px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors "
|
||||
(if
|
||||
(= active "true")
|
||||
"border-violet-600 text-violet-600"
|
||||
"border-transparent text-stone-500 hover:text-stone-700"))
|
||||
label))
|
||||
19
sx/sxc/examples/tabs-demo.sx
Normal file
19
sx/sxc/examples/tabs-demo.sx
Normal file
@@ -0,0 +1,19 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-0")
|
||||
(div
|
||||
(~tw :tokens "flex border-b border-stone-200")
|
||||
:id "tab-buttons"
|
||||
(~examples/tab-btn :tab "tab1" :label "Overview" :active "true")
|
||||
(~examples/tab-btn :tab "tab2" :label "Details" :active "false")
|
||||
(~examples/tab-btn :tab "tab3" :label "History" :active "false"))
|
||||
(div
|
||||
:id "tab-content"
|
||||
(~tw :tokens "p-4 border border-t-0 border-stone-200 rounded-b")
|
||||
(p
|
||||
(~tw :tokens "text-stone-700")
|
||||
"Welcome to the Overview tab. This content is loaded by default.")
|
||||
(p
|
||||
(~tw :tokens "text-stone-500 text-sm mt-2")
|
||||
"Click the tabs above to navigate. Watch the browser URL update."))))
|
||||
3
sx/sxc/examples/validation-error.sx
Normal file
3
sx/sxc/examples/validation-error.sx
Normal file
@@ -0,0 +1,3 @@
|
||||
(defcomp
|
||||
(&key message)
|
||||
(p (~tw :tokens "text-sm text-rose-600") message))
|
||||
3
sx/sxc/examples/validation-ok.sx
Normal file
3
sx/sxc/examples/validation-ok.sx
Normal file
@@ -0,0 +1,3 @@
|
||||
(defcomp
|
||||
(&key email)
|
||||
(p (~tw :tokens "text-sm text-emerald-600") (str email " is available")))
|
||||
36
sx/sxc/examples/vals-headers-demo.sx
Normal file
36
sx/sxc/examples/vals-headers-demo.sx
Normal file
@@ -0,0 +1,36 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-6")
|
||||
(div
|
||||
(~tw :tokens "space-y-2")
|
||||
(h4
|
||||
(~tw :tokens "text-sm font-semibold text-stone-700")
|
||||
"sx-vals — send extra values")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.echo-vals))))"
|
||||
:sx-target "#vals-result"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-vals "{\"source\": \"button\", \"version\": \"2.0\"}"
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Send with vals")
|
||||
(div
|
||||
:id "vals-result"
|
||||
(~tw :tokens "p-3 rounded bg-stone-100 text-sm text-stone-400")
|
||||
"Click to see server-received values."))
|
||||
(div
|
||||
(~tw :tokens "space-y-2")
|
||||
(h4
|
||||
(~tw :tokens "text-sm font-semibold text-stone-700")
|
||||
"sx-headers — send custom headers")
|
||||
(button
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.echo-headers))))"
|
||||
:sx-target "#headers-result"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-headers {:X-Request-Source "demo" :X-Custom-Token "abc123"}
|
||||
(~tw :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm")
|
||||
"Send with headers")
|
||||
(div
|
||||
:id "headers-result"
|
||||
(~tw :tokens "p-3 rounded bg-stone-100 text-sm text-stone-400")
|
||||
"Click to see server-received headers."))))
|
||||
3
sx/sxc/examples/value-options.sx
Normal file
3
sx/sxc/examples/value-options.sx
Normal file
@@ -0,0 +1,3 @@
|
||||
(defcomp
|
||||
(&key items)
|
||||
(<> (map (fn (item) (option :value item item)) items)))
|
||||
23
sx/sxc/examples/value-select-demo.sx
Normal file
23
sx/sxc/examples/value-select-demo.sx
Normal file
@@ -0,0 +1,23 @@
|
||||
(defcomp
|
||||
()
|
||||
(div
|
||||
(~tw :tokens "space-y-3")
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Category")
|
||||
(select
|
||||
:name "category"
|
||||
:sx-get "/sx/(geography.(hypermedia.(example.(api.values))))"
|
||||
:sx-trigger "change"
|
||||
:sx-target "#value-items"
|
||||
:sx-swap "innerHTML"
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500")
|
||||
(option :value "" "Pick a category...")
|
||||
(option :value "Languages" "Languages")
|
||||
(option :value "Frameworks" "Frameworks")
|
||||
(option :value "Databases" "Databases")))
|
||||
(div
|
||||
(label (~tw :tokens "block text-sm font-medium text-stone-700 mb-1") "Item")
|
||||
(select
|
||||
:id "value-items"
|
||||
(~tw :tokens "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500")
|
||||
(option :value "" "Select a category first...")))))
|
||||
Reference in New Issue
Block a user