(defcomp ~app-shell (&key title asset-url meta-html body-html body-end-html) (<> (raw! "") (html :lang "en" (head (meta :charset "utf-8") (meta :name "viewport" :content "width=device-width, initial-scale=1") (meta :name "robots" :content "index,follow") (meta :name "theme-color" :content "#ffffff") (title title) (when meta-html (raw! meta-html)) (style "@media (min-width: 768px) { .js-mobile-sentinel { display:none !important; } }") (link :rel "stylesheet" :type "text/css" :href (str asset-url "/styles/basics.css")) (link :rel "stylesheet" :type "text/css" :href (str asset-url "/styles/cards.css")) (link :rel "stylesheet" :type "text/css" :href (str asset-url "/styles/blog-content.css")) (script :src "https://unpkg.com/htmx.org@2.0.8") (script :src "https://unpkg.com/hyperscript.org@0.9.12") (script :src "https://cdn.tailwindcss.com") (link :rel "stylesheet" :href (str asset-url "/fontawesome/css/all.min.css")) (link :rel "stylesheet" :href (str asset-url "/fontawesome/css/v4-shims.min.css")) (link :href "https://unpkg.com/prismjs/themes/prism.css" :rel "stylesheet") (script :src "https://unpkg.com/prismjs/prism.js") (script :src "https://unpkg.com/prismjs/components/prism-javascript.min.js") (script :src "https://unpkg.com/prismjs/components/prism-python.min.js") (script :src "https://unpkg.com/prismjs/components/prism-bash.min.js") (script :src "https://cdn.jsdelivr.net/npm/sweetalert2@11") (script "if(matchMedia('(hover:hover) and (pointer:fine)').matches){document.documentElement.classList.add('hover-capable')}") (script "document.addEventListener('click',function(e){var t=e.target.closest('[data-close-details]');if(!t)return;var d=t.closest('details');if(d)d.removeAttribute('open')})") (style "details[data-toggle-group=\"mobile-panels\"]>summary{list-style:none}" "details[data-toggle-group=\"mobile-panels\"]>summary::-webkit-details-marker{display:none}" "@media(min-width:768px){.nav-group:focus-within .submenu,.nav-group:hover .submenu{display:block}}" "img{max-width:100%;height:auto}" ".clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}" ".clamp-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}" ".no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}" "details.group{overflow:hidden}details.group>summary{list-style:none}details.group>summary::-webkit-details-marker{display:none}" ".htmx-indicator{display:none}.htmx-request .htmx-indicator{display:inline-flex}" ".js-wrap.open .js-pop{display:block}.js-wrap.open .js-backdrop{display:block}")) (body :class "bg-stone-50 text-stone-900" (raw! body-html) (when body-end-html (raw! body-end-html)) (script :src (str asset-url "/scripts/body.js")))))) (defcomp ~app-layout (&key title asset-url meta-html menu-colour header-rows-html menu-html filter-html aside-html content-html body-end-html) (let* ((colour (or menu-colour "sky"))) (~app-shell :title (or title "Rose Ash") :asset-url asset-url :meta-html meta-html :body-end-html body-end-html :body-html (str "
" "
" "
" "" "
" "
" "
" header-rows-html "
" "
" "
" "
" "
" (or menu-html "") "
" "
" "
" "
" (or filter-html "") "
" "
" "
" "
" "" "
" (or content-html "") "
" "
" "
" "
" "
" "
")))) (defcomp ~oob-response (&key oobs-html filter-html aside-html menu-html content-html) (<> (when oobs-html (raw! oobs-html)) (div :id "filter" :hx-swap-oob "outerHTML" (when filter-html (raw! filter-html))) (aside :id "aside" :hx-swap-oob "outerHTML" :class "hidden md:flex md:flex-col max-w-xs md:h-full md:min-h-0 mr-3" (when aside-html (raw! aside-html))) (div :id "root-menu" :hx-swap-oob "outerHTML" :class "md:hidden" (when menu-html (raw! menu-html))) (section :id "main-panel" :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport" (when content-html (raw! content-html))))) (defcomp ~header-row (&key cart-mini-html blog-url site-title nav-tree-html auth-menu-html nav-panel-html settings-url is-admin oob hamburger-html) (<> (div :id "root-row" :hx-swap-oob (if oob "outerHTML" nil) :class "flex flex-col items-center md:flex-row justify-center md:justify-between w-full p-1 bg-sky-500" (div :class "w-full flex flex-row items-top" (when cart-mini-html (raw! cart-mini-html)) (div :class "font-bold text-5xl flex-1" (a :href (or blog-url "/") :class "flex justify-center md:justify-start" (h1 (or site-title "")))) (nav :class "hidden md:flex gap-4 text-sm ml-2 justify-end items-center flex-0" (when nav-tree-html (raw! nav-tree-html)) (when auth-menu-html (raw! auth-menu-html)) (when nav-panel-html (raw! nav-panel-html)) (when (and is-admin settings-url) (a :href settings-url :class "justify-center cursor-pointer flex flex-row items-center gap-2 rounded bg-stone-200 text-black p-3" (i :class "fa fa-cog" :aria-hidden "true")))) (when hamburger-html (raw! hamburger-html)))) (div :class "block md:hidden text-md font-bold" (when auth-menu-html (raw! auth-menu-html))))) (defcomp ~menu-row (&key id level colour link-href link-label link-label-html icon hx-select nav-html child-id child-html oob) (let* ((c (or colour "sky")) (lv (or level 1)) (shade (str (- 500 (* lv 100))))) (<> (div :id id :hx-swap-oob (if oob "outerHTML" nil) :class (str "flex flex-col items-center md:flex-row justify-center md:justify-between w-full p-1 bg-" c "-" shade) (div :class "relative nav-group" (a :href link-href :hx-get link-href :hx-target "#main-panel" :hx-select (or hx-select "#main-panel") :hx-swap "outerHTML" :hx-push-url "true" :class "w-full whitespace-normal flex items-center gap-2 font-bold text-2xl px-3 py-2" (when icon (i :class icon :aria-hidden "true")) (if link-label-html (raw! link-label-html) (when link-label (div link-label))))) (when nav-html (nav :class "hidden md:flex gap-4 text-sm ml-2 justify-end items-center flex-0" (raw! nav-html)))) (when child-id (div :id child-id :class "flex flex-col w-full items-center" (when child-html (raw! child-html))))))) (defcomp ~nav-link (&key href hx-select label icon aclass select-colours) (div :class "relative nav-group" (a :href href :hx-get href :hx-target "#main-panel" :hx-select (or hx-select "#main-panel") :hx-swap "outerHTML" :hx-push-url "true" :class (or aclass (str "justify-center cursor-pointer flex flex-row items-center gap-2 rounded bg-stone-200 text-black p-3 " (or select-colours ""))) (when icon (i :class icon :aria-hidden "true")) (when label (span label)))))