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>
This commit is contained in:
2026-03-12 22:00:12 +00:00
parent de80d921e9
commit b0920a1121
209 changed files with 4620 additions and 4620 deletions

View File

@@ -1,12 +1,12 @@
;; Auth page components (device auth — account-specific)
;; Login and check-email components are shared: see shared/sx/templates/auth.sx
(defcomp ~account-device-error (&key (error :as string))
(defcomp ~auth/device-error (&key (error :as string))
(when error
(div :class "bg-red-50 border border-red-200 text-red-700 p-3 rounded mb-4"
error)))
(defcomp ~account-device-form (&key error (action :as string) (csrf-token :as string) (code :as string))
(defcomp ~auth/device-form (&key error (action :as string) (csrf-token :as string) (code :as string))
(div :class "py-8 max-w-md mx-auto"
(h1 :class "text-2xl font-bold mb-6" "Authorize device")
(p :class "text-stone-600 mb-4" "Enter the code shown in your terminal to sign in.")
@@ -22,30 +22,30 @@
:class "w-full bg-stone-800 text-white py-2 px-4 rounded hover:bg-stone-700 transition"
"Authorize"))))
(defcomp ~account-device-approved ()
(defcomp ~auth/device-approved ()
(div :class "py-8 max-w-md mx-auto text-center"
(h1 :class "text-2xl font-bold mb-4" "Device authorized")
(p :class "text-stone-600" "You can close this window and return to your terminal.")))
;; Assembled auth page content — replaces Python _login_page_content etc.
(defcomp ~account-login-content (&key (error :as string?) (email :as string?))
(~auth-login-form
:error (when error (~auth-error-banner :error error))
(defcomp ~auth/login-content (&key (error :as string?) (email :as string?))
(~shared:auth/login-form
:error (when error (~shared:auth/error-banner :error error))
:action (url-for "auth.start_login")
:csrf-token (csrf-token)
:email (or email "")))
(defcomp ~account-device-content (&key (error :as string?) (code :as string?))
(~account-device-form
:error (when error (~account-device-error :error error))
(defcomp ~auth/device-content (&key (error :as string?) (code :as string?))
(~auth/device-form
:error (when error (~auth/device-error :error error))
:action (url-for "auth.device_submit")
:csrf-token (csrf-token)
:code (or code "")))
(defcomp ~account-check-email-content (&key (email :as string?) (email-error :as string?))
(~auth-check-email
(defcomp ~auth/check-email-content (&key (email :as string?) (email-error :as string?))
(~shared:auth/check-email
:email (escape (or email ""))
:error (when email-error
(~auth-check-email-error :error (escape email-error)))))
(~shared:auth/check-email-error :error (escape email-error)))))

View File

@@ -1,36 +1,36 @@
;; Account dashboard components
(defcomp ~account-error-banner (&key (error :as string))
(defcomp ~dashboard/error-banner (&key (error :as string))
(when error
(div :class "rounded-lg border border-red-200 bg-red-50 text-red-800 px-4 py-3 text-sm"
error)))
(defcomp ~account-user-email (&key (email :as string))
(defcomp ~dashboard/user-email (&key (email :as string))
(when email
(p :class "text-sm text-stone-500 mt-1" email)))
(defcomp ~account-user-name (&key (name :as string))
(defcomp ~dashboard/user-name (&key (name :as string))
(when name
(p :class "text-sm text-stone-600" name)))
(defcomp ~account-logout-form (&key (csrf-token :as string))
(defcomp ~dashboard/logout-form (&key (csrf-token :as string))
(form :action "/auth/logout/" :method "post"
(input :type "hidden" :name "csrf_token" :value csrf-token)
(button :type "submit"
:class "inline-flex items-center gap-2 rounded-full border border-stone-300 px-4 py-2 text-sm font-medium text-stone-700 hover:bg-stone-50 transition"
(i :class "fa-solid fa-right-from-bracket text-xs") " Sign out")))
(defcomp ~account-label-item (&key (name :as string))
(defcomp ~dashboard/label-item (&key (name :as string))
(span :class "inline-flex items-center rounded-full border border-stone-200 px-3 py-1 text-xs font-medium bg-white/60"
name))
(defcomp ~account-labels-section (&key items)
(defcomp ~dashboard/labels-section (&key items)
(when items
(div
(h2 :class "text-base font-semibold tracking-tight mb-3" "Labels")
(div :class "flex flex-wrap gap-2" items))))
(defcomp ~account-main-panel (&key error email name logout labels)
(defcomp ~dashboard/main-panel (&key error email name logout labels)
(div :class "w-full max-w-3xl mx-auto px-4 py-6"
(div :class "bg-white/70 backdrop-blur rounded-2xl shadow border border-stone-200 p-6 sm:p-8 space-y-8"
error
@@ -43,18 +43,18 @@
labels)))
;; Assembled dashboard content — replaces Python _account_main_panel_sx
(defcomp ~account-dashboard-content (&key (error :as string?))
(defcomp ~dashboard/content (&key (error :as string?))
(let* ((user (current-user))
(csrf (csrf-token)))
(~account-main-panel
:error (when error (~account-error-banner :error error))
(~dashboard/main-panel
:error (when error (~dashboard/error-banner :error error))
:email (when (get user "email")
(~account-user-email :email (get user "email")))
(~dashboard/user-email :email (get user "email")))
:name (when (get user "name")
(~account-user-name :name (get user "name")))
:logout (~account-logout-form :csrf-token csrf)
(~dashboard/user-name :name (get user "name")))
:logout (~dashboard/logout-form :csrf-token csrf)
:labels (when (not (empty? (or (get user "labels") (list))))
(~account-labels-section
(~dashboard/labels-section
:items (map (lambda (label)
(~account-label-item :name (get label "name")))
(~dashboard/label-item :name (get label "name")))
(get user "labels")))))))

View File

@@ -2,19 +2,19 @@
;; Registered via register_sx_layout("account", ...) in __init__.py.
;; Full page: root header + auth header row in header-child
(defcomp ~account-layout-full ()
(defcomp ~layouts/full ()
(<> (~root-header-auto)
(~header-child-sx
(~shared:layout/header-child-sx
:inner (~auth-header-row-auto))))
;; OOB (HTMX): auth row + root header, both with oob=true
(defcomp ~account-layout-oob ()
(defcomp ~layouts/oob ()
(<> (~auth-header-row-auto true)
(~root-header-auto true)))
;; Mobile menu: auth section + root nav
(defcomp ~account-layout-mobile ()
(<> (~mobile-menu-section
(defcomp ~layouts/mobile ()
(<> (~shared:layout/mobile-menu-section
:label "account" :href "/" :level 1 :colour "sky"
:items (~auth-nav-items-auto))
(~root-mobile-auto)))

View File

@@ -1,30 +1,30 @@
;; Newsletter management components
(defcomp ~account-newsletter-desc (&key (description :as string))
(defcomp ~newsletters/desc (&key (description :as string))
(when description
(p :class "text-xs text-stone-500 mt-0.5 truncate" description)))
(defcomp ~account-newsletter-toggle (&key (id :as string) (url :as string) (hdrs :as dict) (target :as string) (cls :as string) (checked :as string) (knob-cls :as string))
(defcomp ~newsletters/toggle (&key (id :as string) (url :as string) (hdrs :as dict) (target :as string) (cls :as string) (checked :as string) (knob-cls :as string))
(div :id id :class "flex items-center"
(button :sx-post url :sx-headers hdrs :sx-target target :sx-swap "outerHTML"
:class cls :role "switch" :aria-checked checked
(span :class knob-cls))))
(defcomp ~account-newsletter-item (&key (name :as string) desc toggle)
(defcomp ~newsletters/item (&key (name :as string) desc toggle)
(div :class "flex items-center justify-between py-4 first:pt-0 last:pb-0"
(div :class "min-w-0 flex-1"
(p :class "text-sm font-medium text-stone-800" name)
desc)
(div :class "ml-4 flex-shrink-0" toggle)))
(defcomp ~account-newsletter-list (&key items)
(defcomp ~newsletters/list (&key items)
(div :class "divide-y divide-stone-100" items))
(defcomp ~account-newsletter-empty ()
(defcomp ~newsletters/empty ()
(p :class "text-sm text-stone-500" "No newsletters available."))
(defcomp ~account-newsletters-panel (&key list)
(defcomp ~newsletters/panel (&key list)
(div :class "w-full max-w-3xl mx-auto px-4 py-6"
(div :class "bg-white/70 backdrop-blur rounded-2xl shadow border border-stone-200 p-6 sm:p-8 space-y-6"
(h1 :class "text-xl font-semibold tracking-tight" "Newsletters")
@@ -32,12 +32,12 @@
;; Assembled newsletters content — replaces Python _newsletters_panel_sx
;; Takes pre-fetched newsletter-list from page helper
(defcomp ~account-newsletters-content (&key (newsletter-list :as list) (account-url :as string?))
(defcomp ~newsletters/content (&key (newsletter-list :as list) (account-url :as string?))
(let* ((csrf (csrf-token)))
(if (empty? newsletter-list)
(~account-newsletter-empty)
(~account-newsletters-panel
:list (~account-newsletter-list
(~newsletters/empty)
(~newsletters/panel
:list (~newsletters/list
:items (map (lambda (item)
(let* ((nl (get item "newsletter"))
(un (get item "un"))
@@ -47,11 +47,11 @@
(bg (if subscribed "bg-emerald-500" "bg-stone-300"))
(translate (if subscribed "translate-x-6" "translate-x-1"))
(checked (if subscribed "true" "false")))
(~account-newsletter-item
(~newsletters/item
:name (get nl "name")
:desc (when (get nl "description")
(~account-newsletter-desc :description (get nl "description")))
:toggle (~account-newsletter-toggle
(~newsletters/desc :description (get nl "description")))
:toggle (~newsletters/toggle
:id (str "nl-" nid)
:url toggle-url
:hdrs {:X-CSRFToken csrf}

View File

@@ -8,7 +8,7 @@
:path "/"
:auth :login
:layout :account
:content (~account-dashboard-content))
:content (~dashboard/content))
;; ---------------------------------------------------------------------------
;; Newsletters
@@ -19,7 +19,7 @@
:auth :login
:layout :account
:data (service "account-page" "newsletters-data")
:content (~account-newsletters-content
:content (~newsletters/content
:newsletter-list newsletter-list
:account-url account-url))