(defcomp ~search-mobile (&key current-local-href search search-count hx-select search-headers-mobile) (div :id "search-mobile-wrapper" :class "flex flex-row gap-2 items-center flex-1 min-w-0 pr-2" (input :id "search-mobile" :type "text" :name "search" :aria-label "search" :class "text-base md:text-sm col-span-5 rounded-md px-3 py-2 mb-2 w-full min-w-0 max-w-full border-2 border-stone-200 placeholder-shown:border-stone-200 [&:not(:placeholder-shown)]:border-yellow-200" :hx-preserve true :value (or search "") :placeholder "search" :hx-trigger "input changed delay:300ms" :hx-target "#main-panel" :hx-select (str (or hx-select "#main-panel") ", #search-mobile-wrapper, #search-desktop-wrapper") :hx-get current-local-href :hx-swap "outerHTML" :hx-push-url "true" :hx-headers search-headers-mobile :hx-sync "this:replace" :autocomplete "off") (div :id "search-count-mobile" :aria-label "search count" :class (if (not search-count) "text-xl text-red-500" "") (when search (raw! (str search-count)))))) (defcomp ~search-desktop (&key current-local-href search search-count hx-select search-headers-desktop) (div :id "search-desktop-wrapper" :class "flex flex-row gap-2 items-center" (input :id "search-desktop" :type "text" :name "search" :aria-label "search" :class "w-full mx-1 my-3 px-3 py-2 text-md rounded-xl border-2 shadow-sm border-white placeholder-shown:border-white [&:not(:placeholder-shown)]:border-yellow-200" :hx-preserve true :value (or search "") :placeholder "search" :hx-trigger "input changed delay:300ms" :hx-target "#main-panel" :hx-select (str (or hx-select "#main-panel") ", #search-mobile-wrapper, #search-desktop-wrapper") :hx-get current-local-href :hx-swap "outerHTML" :hx-push-url "true" :hx-headers search-headers-desktop :hx-sync "this:replace" :autocomplete "off") (div :id "search-count-desktop" :aria-label "search count" :class (if (not search-count) "text-xl text-red-500" "") (when search (raw! (str search-count)))))) (defcomp ~mobile-filter (&key filter-summary-html action-buttons-html filter-details-html) (details :class "group/filter p-2 md:hidden" :data-toggle-group "mobile-panels" (summary :class "bg-white/90" (div :class "flex flex-row items-start" (div (div :class "md:hidden mx-2 bg-stone-200 rounded" (span :class "flex items-center justify-center text-stone-600 text-lg h-12 w-12 transition-transform group-open/filter:hidden self-start" (i :class "fa-solid fa-filter")) (span (svg :aria-hidden "true" :viewBox "0 0 24 24" :class "w-12 h-12 rotate-180 transition-transform group-open/filter:block hidden self-start" (path :d "M6 9l6 6 6-6" :fill "currentColor"))))) (div :id "filter-summary-mobile" :class "flex-1 md:hidden grid grid-cols-12 items-center gap-3" (div :class "flex flex-col items-start gap-2" (raw! filter-summary-html))))) (raw! (or action-buttons-html "")) (div :id "filter-details-mobile" :style "display:contents" (raw! (or filter-details-html ""))))) (defcomp ~infinite-scroll (&key url page total-pages id-prefix colspan) (if (< page total-pages) (raw! (str " htmx.trigger(me, 'sentinel:retry'), myMs) " "end " "on htmx:beforeRequest " "set me.style.pointerEvents to 'none' " "set me.style.opacity to '0' " "end " "on htmx:afterSwap set me.dataset.retryMs to 1000 end " "on htmx:sendError call backoff() " "on htmx:responseError call backoff() " "on htmx:timeout call backoff()" "\"" " role=\"status\" aria-live=\"polite\" aria-hidden=\"true\">" "" "
" "
loading\u2026 " page " / " total-pages "
" "" "
" "
" "
loading\u2026 " page " / " total-pages "
" "" "
" "")) (raw! (str "End of results")))) (defcomp ~status-pill (&key status size) (let* ((s (or status "pending")) (lower (lower s)) (sz (or size "xs")) (colours (cond (= lower "paid") "border-emerald-300 bg-emerald-50 text-emerald-700" (= lower "confirmed") "border-emerald-300 bg-emerald-50 text-emerald-700" (= lower "checked_in") "border-blue-300 bg-blue-50 text-blue-700" (or (= lower "failed") (= lower "cancelled")) "border-rose-300 bg-rose-50 text-rose-700" (= lower "provisional") "border-amber-300 bg-amber-50 text-amber-700" (= lower "ordered") "border-blue-300 bg-blue-50 text-blue-700" true "border-stone-300 bg-stone-50 text-stone-700"))) (span :class (str "inline-flex items-center rounded-full border px-2 py-0.5 text-" sz " font-medium " colours) s)))