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>
94 lines
5.0 KiB
Plaintext
94 lines
5.0 KiB
Plaintext
;; Events calendar components
|
|
|
|
(defcomp ~calendar/nav-arrow (&key (pill-cls :as string) (href :as string) (label :as string))
|
|
(a :class (str pill-cls " text-xl") :href href
|
|
:sx-get href :sx-target "#main-panel" :sx-select "#main-panel" :sx-swap "outerHTML" :sx-push-url "true" label))
|
|
|
|
(defcomp ~calendar/month-label (&key (month-name :as string) (year :as string))
|
|
(div :class "px-3 font-medium" (str month-name " " year)))
|
|
|
|
(defcomp ~calendar/weekday (&key (name :as string))
|
|
(div :class "py-1" name))
|
|
|
|
(defcomp ~calendar/day-short (&key (day-str :as string))
|
|
(span :class "sm:hidden text-[16px] text-stone-500" day-str))
|
|
|
|
(defcomp ~calendar/day-num (&key (pill-cls :as string) (href :as string) (num :as string))
|
|
(a :class pill-cls :href href :sx-get href :sx-target "#main-panel" :sx-select "#main-panel"
|
|
:sx-swap "outerHTML" :sx-push-url "true" num))
|
|
|
|
(defcomp ~calendar/entry-badge (&key (bg-cls :as string) (name :as string) (state-label :as string))
|
|
(div :class (str "flex items-center justify-between gap-1 text-[11px] rounded px-1 py-0.5 " bg-cls)
|
|
(span :class "truncate" name)
|
|
(span :class "shrink-0 text-[10px] font-semibold uppercase tracking-tight" state-label)))
|
|
|
|
(defcomp ~calendar/cell (&key (cell-cls :as string) day-short day-num badges)
|
|
(div :class cell-cls
|
|
(div :class "flex justify-between items-center"
|
|
(div :class "flex flex-col" day-short day-num))
|
|
(div :class "mt-1 space-y-0.5" badges)))
|
|
|
|
(defcomp ~calendar/grid (&key arrows weekdays cells)
|
|
(section :class "bg-orange-100"
|
|
(header :class "flex items-center justify-center mt-2"
|
|
(nav :class "flex items-center gap-2 text-2xl" arrows))
|
|
(div :class "rounded-2xl border border-stone-200 bg-white/80 p-4"
|
|
(div :class "hidden sm:grid grid-cols-7 text-center text-md font-semibold text-stone-700 mb-2" weekdays)
|
|
(div :class "grid grid-cols-1 sm:grid-cols-7 gap-px bg-stone-200 rounded-xl overflow-hidden" cells))))
|
|
|
|
;; Calendar grid from data — all iteration in sx
|
|
(defcomp ~calendar/grid-from-data (&key (pill-cls :as string) (month-name :as string) (year :as string)
|
|
(prev-year-href :as string) (prev-month-href :as string)
|
|
(next-month-href :as string) (next-year-href :as string)
|
|
(weekday-names :as list) (cells :as list))
|
|
(~calendar/grid
|
|
:arrows (<>
|
|
(~calendar/nav-arrow :pill-cls pill-cls :href prev-year-href :label "\u00ab")
|
|
(~calendar/nav-arrow :pill-cls pill-cls :href prev-month-href :label "\u2039")
|
|
(~calendar/month-label :month-name month-name :year year)
|
|
(~calendar/nav-arrow :pill-cls pill-cls :href next-month-href :label "\u203a")
|
|
(~calendar/nav-arrow :pill-cls pill-cls :href next-year-href :label "\u00bb"))
|
|
:weekdays (<> (map (lambda (wd) (~calendar/weekday :name wd))
|
|
(or weekday-names (list))))
|
|
:cells (<> (map (lambda (cell)
|
|
(~calendar/cell
|
|
:cell-cls (get cell "cell-cls")
|
|
:day-short (when (get cell "day-str")
|
|
(~calendar/day-short :day-str (get cell "day-str")))
|
|
:day-num (when (get cell "day-href")
|
|
(~calendar/day-num :pill-cls pill-cls
|
|
:href (get cell "day-href") :num (get cell "day-num")))
|
|
:badges (when (get cell "badges")
|
|
(<> (map (lambda (b)
|
|
(~calendar/entry-badge
|
|
:bg-cls (get b "bg-cls") :name (get b "name")
|
|
:state-label (get b "state-label")))
|
|
(get cell "badges"))))))
|
|
(or cells (list))))))
|
|
|
|
(defcomp ~calendar/description-display (&key (description :as string?) (edit-url :as string))
|
|
(div :id "calendar-description"
|
|
(if description
|
|
(p :class "text-stone-700 whitespace-pre-line break-all" description)
|
|
(p :class "text-stone-400 italic" "No description yet."))
|
|
(button :type "button" :class "mt-2 text-xs underline"
|
|
:sx-get edit-url :sx-target "#calendar-description" :sx-swap "outerHTML"
|
|
(i :class "fas fa-edit"))))
|
|
|
|
(defcomp ~calendar/description-title-oob (&key (description :as string))
|
|
(div :id "calendar-description-title" :sx-swap-oob "outerHTML"
|
|
:class "text-base font-normal break-words whitespace-normal min-w-0 break-all w-full text-center block"
|
|
description))
|
|
|
|
(defcomp ~calendar/description-edit-form (&key (save-url :as string) (cancel-url :as string) (csrf :as string) (description :as string?))
|
|
(div :id "calendar-description"
|
|
(form :sx-post save-url :sx-target "#calendar-description" :sx-swap "outerHTML"
|
|
(input :type "hidden" :name "csrf_token" :value csrf)
|
|
(textarea :name "description" :autocomplete "off" :rows "4"
|
|
:class "w-full p-2 border rounded" description)
|
|
(div :class "mt-2 flex gap-2 text-xs"
|
|
(button :type "submit" :class "px-3 py-1 rounded bg-stone-800 text-white" "Save")
|
|
(button :type "button" :class "px-3 py-1 rounded border"
|
|
:sx-get cancel-url :sx-target "#calendar-description" :sx-swap "outerHTML"
|
|
"Cancel")))))
|