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>
61 lines
3.2 KiB
Plaintext
61 lines
3.2 KiB
Plaintext
;; Menu item form and page search components
|
|
|
|
(defcomp ~menu_items/page-search-item (&key id title slug feature-image)
|
|
(div :class "flex items-center gap-3 p-3 hover:bg-stone-50 cursor-pointer border-b last:border-b-0"
|
|
:data-page-id id :data-page-title title :data-page-slug slug
|
|
:data-page-image (or feature-image "")
|
|
(if feature-image
|
|
(img :src feature-image :alt title :class "w-10 h-10 rounded-full object-cover flex-shrink-0")
|
|
(div :class "w-10 h-10 rounded-full bg-stone-200 flex-shrink-0"))
|
|
(div :class "flex-1 min-w-0"
|
|
(div :class "font-medium truncate" title)
|
|
(div :class "text-xs text-stone-500 truncate" slug))))
|
|
|
|
(defcomp ~menu_items/page-search-results (&key items sentinel)
|
|
(div :class "border border-stone-200 rounded-md max-h-64 overflow-y-auto"
|
|
items sentinel))
|
|
|
|
(defcomp ~menu_items/page-search-sentinel (&key url query next-page)
|
|
(div :sx-get url :sx-trigger "intersect once" :sx-swap "outerHTML"
|
|
:sx-vals (str "{\"q\": \"" query "\", \"page\": " next-page "}")
|
|
:class "p-3 text-center text-sm text-stone-400"
|
|
(i :class "fa fa-spinner fa-spin") " Loading more..."))
|
|
|
|
(defcomp ~menu_items/page-search-empty (&key query)
|
|
(div :class "p-3 text-center text-stone-400 border border-stone-200 rounded-md"
|
|
(str "No pages found matching \"" query "\"")))
|
|
|
|
;; Data-driven page search results (replaces Python render_page_search_results loop)
|
|
(defcomp ~menu_items/page-search-results-from-data (&key pages query has-more search-url next-page)
|
|
(if (and (not pages) query)
|
|
(~menu_items/page-search-empty :query query)
|
|
(when pages
|
|
(~menu_items/page-search-results
|
|
:items (<> (map (lambda (p)
|
|
(~menu_items/page-search-item
|
|
:id (get p "id") :title (get p "title")
|
|
:slug (get p "slug") :feature-image (get p "feature_image")))
|
|
pages))
|
|
:sentinel (when has-more
|
|
(~menu_items/page-search-sentinel :url search-url :query query :next-page next-page))))))
|
|
|
|
;; Data-driven menu nav items (replaces Python render_menu_items_nav_oob loop)
|
|
(defcomp ~menu_items/menu-nav-from-data (&key items nav-cls container-id arrow-cls scroll-hs)
|
|
(if (not items)
|
|
(~shared:nav/blog-nav-empty :wrapper-id "menu-items-nav-wrapper")
|
|
(~shared:misc/scroll-nav-wrapper :wrapper-id "menu-items-nav-wrapper" :container-id container-id
|
|
:arrow-cls arrow-cls
|
|
:left-hs (str "on click set #" container-id ".scrollLeft to #" container-id ".scrollLeft - 200")
|
|
:scroll-hs scroll-hs
|
|
:right-hs (str "on click set #" container-id ".scrollLeft to #" container-id ".scrollLeft + 200")
|
|
:items (<> (map (lambda (item)
|
|
(let* ((img (~shared:misc/img-or-placeholder :src (get item "feature_image") :alt (get item "label")
|
|
:size-cls "w-8 h-8 rounded-full object-cover flex-shrink-0")))
|
|
(if (= (get item "slug") "cart")
|
|
(~shared:nav/blog-nav-item-plain :href (get item "href") :selected (get item "selected")
|
|
:nav-cls nav-cls :img img :label (get item "label"))
|
|
(~shared:nav/blog-nav-item-link :href (get item "href") :hx-get (get item "hx_get")
|
|
:selected (get item "selected") :nav-cls nav-cls :img img :label (get item "label")))))
|
|
items))
|
|
:oob true)))
|