Files
rose-ash/market/sx/detail.sx
giles b0920a1121 Rename all 1,169 components to path-based names with namespace support
Component names now reflect filesystem location using / as path separator
and : as namespace separator for shared components:
  ~sx-header → ~layouts/header
  ~layout-app-body → ~shared:layout/app-body
  ~blog-admin-dashboard → ~admin/dashboard

209 files, 4,941 replacements across all services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:00:12 +00:00

163 lines
7.3 KiB
Plaintext

;; Market product detail components
(defcomp ~detail/gallery-inner (&key (like :as list?) (image :as string) (alt :as string) (labels :as list?) (brand :as string))
(<> like
(figure :class "inline-block"
(div :class "relative w-full aspect-square"
(img :data-main-img "" :src image :alt alt
:class "w-full h-full object-contain object-top" :loading "eager" :decoding "async")
labels)
(figcaption :class "mt-2 text-sm text-stone-600 text-center" brand))))
(defcomp ~detail/nav-buttons ()
(<>
(button :type "button" :data-prev ""
:class "absolute left-2 top-1/2 -translate-y-1/2 z-10 grid place-items-center w-12 h-12 md:w-14 md:h-14 rounded-full bg-white/90 hover:bg-white shadow-lg text-3xl md:text-4xl"
:title "Previous" "\u2039")
(button :type "button" :data-next ""
:class "absolute right-2 top-1/2 -translate-y-1/2 z-10 grid place-items-center w-12 h-12 md:w-14 md:h-14 rounded-full bg-white/90 hover:bg-white shadow-lg text-3xl md:text-4xl"
:title "Next" "\u203a")))
(defcomp ~detail/gallery (&key (inner :as list) (nav :as list?))
(div :class "relative rounded-xl overflow-hidden bg-stone-100"
inner nav))
(defcomp ~detail/thumb (&key (title :as string) (src :as string) (alt :as string))
(<> (button :type "button" :data-thumb ""
:class "shrink-0 rounded-lg overflow-hidden bg-stone-100 hover:opacity-90 ring-offset-2"
:title title
(img :src src :class "h-16 w-16 object-contain" :alt alt :loading "lazy" :decoding "async"))
(span :data-image-src src :class "hidden")))
(defcomp ~detail/thumbs (&key (thumbs :as list))
(div :class "flex flex-row justify-center"
(div :class "mt-3 flex gap-2 overflow-x-auto no-scrollbar" thumbs)))
(defcomp ~detail/no-image (&key (like :as list?))
(div :class "relative aspect-square bg-stone-100 rounded-xl flex items-center justify-center text-stone-400"
like "No image"))
(defcomp ~detail/sticker (&key (src :as string) (name :as string))
(img :src src :alt name :class "w-10 h-10"))
(defcomp ~detail/stickers (&key (items :as list))
(div :class "p-2 flex flex-row justify-center gap-2" items))
(defcomp ~detail/unit-price (&key (price :as string))
(div (str "Unit price: " price)))
(defcomp ~detail/case-size (&key (size :as string))
(div (str "Case size: " size)))
(defcomp ~detail/extras (&key (inner :as list))
(div :class "mt-2 space-y-1 text-sm text-stone-600" inner))
(defcomp ~detail/desc-short (&key (text :as string))
(p :class "leading-relaxed text-lg" text))
(defcomp ~detail/desc-html (&key (html :as string))
(div :class "max-w-none text-sm leading-relaxed" (~rich-text :html html)))
(defcomp ~detail/desc-wrapper (&key (inner :as list))
(div :class "mt-4 text-stone-800 space-y-3" inner))
(defcomp ~detail/section (&key (title :as string) (html :as string))
(details :class "group rounded-xl border bg-white shadow-sm open:shadow p-0"
(summary :class "cursor-pointer select-none px-4 py-3 flex items-center justify-between"
(span :class "font-medium" title)
(span :class "ml-2 text-xl transition-transform group-open:rotate-180" "\u2304"))
(div :class "px-4 pb-4 max-w-none text-sm leading-relaxed" (~rich-text :html html))))
(defcomp ~detail/sections (&key (items :as list))
(div :class "mt-8 space-y-3" items))
(defcomp ~detail/right-col (&key (inner :as list))
(div :class "md:col-span-3" inner))
(defcomp ~detail/layout (&key (gallery :as list) (stickers :as list?) (details :as list))
(<> (div :class "mt-3 grid grid-cols-1 md:grid-cols-5 gap-6" :data-gallery-root ""
(div :class "md:col-span-2" gallery stickers)
details)
(div :class "pb-8")))
(defcomp ~detail/landing-excerpt (&key (text :as string))
(div :class "w-full text-center italic text-3xl p-2" text))
(defcomp ~detail/landing-image (&key (src :as string))
(div :class "mb-3 flex justify-center"
(img :src src :alt "" :class "rounded-lg w-full md:w-3/4 object-cover")))
(defcomp ~detail/landing-html (&key (html :as string))
(div :class "blog-content p-2" (~rich-text :html html)))
(defcomp ~detail/landing-content (&key (inner :as list))
(<> (article :class "relative w-full" inner) (div :class "pb-8")))
;; ---------------------------------------------------------------------------
;; Composition: product detail page from data
;; ---------------------------------------------------------------------------
;; Gallery section from pre-computed data
(defcomp ~detail/gallery-from-data (&key (images :as list?) (labels :as list?) (brand :as string) (like-data :as dict?) (has-nav-buttons :as boolean) (thumbs :as list?))
(let ((like-sx (when like-data
(~cards/like-button
:form-id (get like-data "form-id") :action (get like-data "action")
:slug (get like-data "slug") :csrf (get like-data "csrf")
:icon-cls (get like-data "icon-cls")))))
(if images
(<>
(~detail/gallery
:inner (~detail/gallery-inner
:like like-sx
:image (get (first images) "src") :alt (get (first images) "alt")
:labels (when labels
(<> (map (lambda (src) (~cards/label-overlay :src src)) labels)))
:brand brand)
:nav (when has-nav-buttons (~detail/nav-buttons)))
(when thumbs
(~detail/thumbs :thumbs
(<> (map (lambda (t)
(~detail/thumb
:title (get t "title") :src (get t "src") :alt (get t "alt")))
thumbs)))))
(~detail/no-image :like like-sx))))
;; Right column details from data
(defcomp ~detail/info-from-data (&key (extras :as list?) (desc-short :as string?) (desc-html :as string?) (sections :as list?))
(~detail/right-col :inner
(<>
(when extras
(~detail/extras :inner
(<> (map (lambda (e)
(if (= (get e "type") "unit-price")
(~detail/unit-price :price (get e "value"))
(~detail/case-size :size (get e "value"))))
extras))))
(when (or desc-short desc-html)
(~detail/desc-wrapper :inner
(<> (when desc-short (~detail/desc-short :text desc-short))
(when desc-html (~detail/desc-html :html desc-html)))))
(when sections
(~detail/sections :items
(<> (map (lambda (s)
(~detail/section :title (get s "title") :html (get s "html")))
sections)))))))
;; Full product detail layout from data
(defcomp ~detail/product-detail-from-data (&key (images :as list?) (labels :as list?) (brand :as string) (like-data :as dict?)
(has-nav-buttons :as boolean) (thumbs :as list?) (sticker-items :as list?)
(extras :as list?) (desc-short :as string?) (desc-html :as string?) (sections :as list?))
(~detail/layout
:gallery (~detail/gallery-from-data
:images images :labels labels :brand brand :like-data like-data
:has-nav-buttons has-nav-buttons :thumbs thumbs)
:stickers (when sticker-items
(~detail/stickers :items
(<> (map (lambda (s)
(~detail/sticker :src (get s "src") :name (get s "name")))
sticker-items))))
:details (~detail/info-from-data
:extras extras :desc-short desc-short :desc-html desc-html
:sections sections)))