domma-cms 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/app.js +2 -2
- package/admin/js/lib/editor-folding.js +6 -6
- package/admin/js/lib/search-settings-arrange.js +1 -1
- package/admin/js/lib/simple-editor.js +8 -8
- package/admin/js/lib/smooth-caret.js +1 -0
- package/admin/js/templates/search.html +10 -12
- package/admin/js/views/page-editor.js +15 -8
- package/docs/screenshots/editor-caret-settings.png +0 -0
- package/package.json +2 -2
- package/plugins/_lib/admin/mail/font-controls.js +4 -0
- package/public/css/search.css +1 -1
- package/public/js/forms.js +2 -2
- package/public/js/search.js +1 -1
- package/public/js/site.js +1 -1
- package/public/js/smooth-caret.js +1 -0
- package/server/services/search.js +7 -3
- package/server/templates/page.html +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.1] - 2026-10-16
|
|
4
|
+
|
|
5
|
+
- Search display offers Icon/Text, Icon and Hidden for navbar and floating triggers. Hidden removes the button while keeping site search available through Ctrl+K or Cmd+K whenever search is enabled. Existing icon and text settings retain their appearance.
|
|
6
|
+
|
|
7
|
+
## [1.8.0] - 2026-10-15
|
|
8
|
+
|
|
9
|
+
- **Built against domma-js 0.53.0** - see [its release notes](https://github.com/pinpointzero73/domma/releases/tag/v0.53.0).
|
|
10
|
+
- **Smooth typing throughout the CMS.** Apply the shared Domma JS caret glide to editable text fields in the admin, page and code editors, email compose, and public site forms, including dynamically rendered wizard steps and dialogs. Password fields, read-only controls and native picker controls keep their native behaviour.
|
|
11
|
+
- **One browser preference.** Page editor settings offers Automatic, Smooth and Native caret movement for all editing surfaces on the same site. Automatic follows reduced motion; Smooth explicitly enables animation. Selection, undo and composition remain native, with forced-colour mode retaining the native caret.
|
|
12
|
+
- **Less work while typing.** Reuse page and code editor gutter rows when the line count and folding structure stay the same, and coalesce scroll synchronisation into one animation frame.
|
|
13
|
+
|
|
3
14
|
## [1.7.2] - 2026-10-15
|
|
4
15
|
|
|
5
16
|
- **Import from WordPress**, a free built-in Tool (Tools › Maintenance). Upload a WordPress export (Tools › Export in WordPress) and see a preview of every page, post, file and menu before anything changes. Pages keep their addresses; posts go to the Blog with categories, tags, featured images and approved comments; media comes from the old site or a zip of `wp-content/uploads`; old addresses, including `?p=123`, redirect to the new ones - and keep redirecting with the importer switched off; Yoast and Rank Math titles and descriptions carry over. Shortcodes and page-builder layouts with no equivalent are listed to rebuild. Run it again and it updates what it made, leaving pages you edited alone unless you choose Overwrite; an import stopped by a restart can be run again to finish it. Each run's report is kept (out of git). Downloads go only to the export's own site, never to private or the server's own addresses, and only on ports 80/443; SVG and anything that is HTML or script is never imported.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Domma Tools CSS v0.
|
|
2
|
+
* Domma Tools CSS v0.53.0
|
|
3
3
|
* Dynamic Object Manipulation & Modeling API
|
|
4
4
|
* (c) 2026 Darryl Waterhouse & DCBW-IT
|
|
5
|
-
* Built: 2026-10-
|
|
6
|
-
* Commit:
|
|
5
|
+
* Built: 2026-10-15T22:14:11.256Z
|
|
6
|
+
* Commit: e15cc27
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/*!
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Domma Tools v0.
|
|
2
|
+
* Domma Tools v0.53.0
|
|
3
3
|
* Developer tools: Theme Roller & Page Roller
|
|
4
4
|
* (c) 2026 Darryl Waterhouse & DCBW-IT
|
|
5
|
-
* Built: 2026-10-
|
|
6
|
-
* Commit:
|
|
5
|
+
* Built: 2026-10-15T22:13:57.322Z
|
|
6
|
+
* Commit: e15cc27
|
|
7
7
|
*
|
|
8
8
|
* Requires: domma.min.js
|
|
9
9
|
*/
|
package/admin/js/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{views as K}from"./views/index.js";import{withPluginChrome as O}from"./lib/plugin-chrome.js";import{api as c,getUser as x,isAuthenticated as m,logout as J,sendToLogin as Y}from"./api.js";import{claimDrafts as Q}from"./lib/draft-owner.js";import{isAuthScreen as b,loginHashFor as X}from"./lib/login-arrange.js";import{installHttpInterceptor as Z}from"./http-interceptor.js";import{installResizableSlideovers as tt}from"./lib/slideover-resizable.js";import{installActivityThrobber as et}from"./lib/activity-throbber.js";import{installUpdateNotice as it}from"./lib/update-notice.js";import{isPathAllowed as ot,redirectFor as at}from"./lib/admin-scope.js";import{deliverDesktop as st,desktopActive as nt,notificationSettings as rt}from"./lib/desktop-notify.js";import{avatarUrl as lt}from"./lib/avatar.js";import{installCalculator as ct}from"./lib/calculator.js";import{takeOverviewPass as mt,withDashboardStrip as _}from"./lib/dashboards-strip.js";import{installHotkeys as pt}from"./lib/hotkeys-ui.js";import{applyAdminBrand as V}from"./lib/admin-brand.js";import{installRouterCatchUp as dt}from"./lib/router-catch-up.js";$(()=>{Z(),ct(),it(),et(),tt(),(async()=>{const{applyAdminTheme:t,refreshAdminTheme:i}=await import("./lib/admin-theme.js");m()?await i(c,{init:!0}):t({dommaTheme:"charcoal-dark"},{init:!0})})();let p=null,h=null,l="/",w=!1,g=null;function D(t){if(N[t])return E.toast(`${N[t]} is switched off on this site.`,{type:"info"}),"/";if(t.split("?")[0]==="/my-dashboard")return"/dashboards";const i=y[t]||at(p,t);return i||((t.split("?")[0]||"/")==="/"&&l&&l!=="/"&&!mt()?y[l]||l:null)}const y={},N={};R.use(async(t,i,e)=>{if(b(t.path))return e();if(!m()){Y();return}const o=D(t.path);if(o){R.navigate(o);return}e()});async function f(){try{const t=await c.get("/auth/permissions");p=t.adminScope||null,h=t.adminBrand||null,V(h),l=t.adminHome||"/";const i=t.permissions||[];return w=ot(p,"/settings")&&i.some(e=>e==="settings"||e.startsWith("settings.")),g=i.some(e=>e==="notifications"||e.startsWith("notifications.")),i}catch{return p=null,l="/",h||V(null),w=!1,g=null,[]}}document.addEventListener("dm:admin-home-changed",()=>{f()});let P=null,A=!1;document.addEventListener("dm:sidebar-rebuild",()=>{if(P){A=!0;return}P=(async()=>{do{A=!1;try{await j(await f())}catch{}}while(A)})().finally(()=>{P=null})});async function j(t){const{renderAdminSidebar:i}=await import("./lib/sidebar-renderer.js");await i({mount:"#admin-sidebar",permissions:t,adminScope:p,brand:h})}M.subscribe("router:afterChange",({to:t})=>{b(t.path)&&(u&&(clearInterval(u),u=null),p=null,l="/",w=!1,g=null)});const W=[{path:"/",view:"dashboard",title:"Dashboard - Domma CMS"},{path:"/dashboards",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/my-dashboard",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/pages",view:"pages",title:"Pages - Domma CMS"},{path:"/pages/new",view:"pageEditor",title:"New Page - Domma CMS"},{path:"/pages/edit/*",view:"pageEditor",title:"Edit Page - Domma CMS"},{path:"/media",view:"media",title:"Media - Domma CMS"},{path:"/menus",view:"menus",title:"Menus - Domma CMS"},{path:"/context-menus",view:"contextMenus",title:"Context Menus - Domma CMS"},{path:"/context-menus/new",view:"contextMenuEditor",title:"New Context Menu - Domma CMS"},{path:"/context-menus/edit/:slug",view:"contextMenuEditor",title:"Edit Context Menu - Domma CMS"},{path:"/menus/new",view:"menuEditor",title:"New Menu - Domma CMS"},{path:"/menus/edit/:slug",view:"menuEditor",title:"Edit Menu - Domma CMS"},{path:"/menu-locations",view:"menuLocations",title:"Menu Locations - Domma CMS"},{path:"/navigation",view:"menusRedirect",title:"Menus - Domma CMS"},{path:"/layouts",view:"layouts",title:"Layouts - Domma CMS"},{path:"/settings",view:"settings",title:"Settings - Domma CMS"},{path:"/theme",view:"theme",title:"Theme - Domma CMS"},{path:"/users",view:"users",title:"Users - Domma CMS"},{path:"/users/new",view:"userEditor",title:"New User - Domma CMS"},{path:"/users/edit/:id",view:"userEditor",title:"Edit User - Domma CMS"},{path:"/plugins",view:"plugins",title:"Plugins - Domma CMS"},{path:"/plugins/code/:name",view:"pluginCode",title:"Plugin Code - Domma CMS"},{path:"/documentation",view:"documentation",title:"Usage - Domma CMS"},{path:"/tutorials",view:"tutorials",title:"Tutorials - Domma CMS"},{path:"/tutorials/crud",view:"tutorialCrud",title:"Building a CRUD App - Domma CMS"},{path:"/tutorials/plugin",view:"tutorialPlugin",title:"Writing a Tool - Domma CMS"},{path:"/tutorials/forms",view:"tutorialForms",title:"Form Follow-Up - Domma CMS"},{path:"/docs/components",view:"componentsReference",title:"Components Reference - Domma CMS"},{path:"/docs/components-howto",view:"componentsHowto",title:"Components How-To - Domma CMS"},{path:"/docs/components-walkthrough",view:"componentsWalkthrough",title:"Components Walkthrough - Domma CMS"},{path:"/docs/components-rules",view:"componentsRules",title:"Components Rules - Domma CMS"},{path:"/docs/usage/pages",view:"usagePages",title:"Pages - Usage - Domma CMS"},{path:"/docs/usage/media",view:"usageMedia",title:"Media - Usage - Domma CMS"},{path:"/docs/usage/navigation",view:"usageNavigation",title:"Navigation - Usage - Domma CMS"},{path:"/docs/usage/dconfig",view:"usageDconfig",title:"DConfig - Usage - Domma CMS"},{path:"/docs/usage/shortcodes",view:"usageShortcodes",title:"Shortcodes - Usage - Domma CMS"},{path:"/docs/usage/site-settings",view:"usageSiteSettings",title:"Site Settings - Usage - Domma CMS"},{path:"/docs/usage/plugins",view:"usagePlugins",title:"Plugins - Usage - Domma CMS"},{path:"/docs/usage/users-roles",view:"usageUsersRoles",title:"Users & Roles - Usage - Domma CMS"},{path:"/docs/usage/views",view:"usageViews",title:"Views - Usage - Domma CMS"},{path:"/docs/usage/actions",view:"usageActions",title:"Actions - Usage - Domma CMS"},{path:"/docs/usage/cta-shortcode",view:"usageCtaShortcode",title:"CTA Shortcode - Usage - Domma CMS"},{path:"/docs/usage/editions",view:"usageEditions",title:"Editions & Licences - Usage - Domma CMS"},{path:"/docs/usage/collections",view:"usageCollections",title:"Collections & Forms - Usage - Domma CMS"},{path:"/docs/usage/blocks",view:"usageBlocks",title:"Blocks - Usage - Domma CMS"},{path:"/docs/usage/tools",view:"usageTools",title:"Built-in Tools - Usage - Domma CMS"},{path:"/docs/usage/dashboard",view:"usageDashboard",title:"Dashboard - Usage - Domma CMS"},{path:"/docs/plugins",view:"pluginGuides",title:"Plugin Guides - Domma CMS"},{path:"/docs/plugins/*",view:"pluginGuide",title:"Plugin Guide - Domma CMS"},{path:"/docs/api/authentication",view:"apiRefAuthentication",title:"Authentication - API - Domma CMS"},{path:"/docs/api/pages",view:"apiRefPages",title:"Pages - API - Domma CMS"},{path:"/docs/api/settings",view:"apiRefSettings",title:"Settings - API - Domma CMS"},{path:"/docs/api/layouts",view:"apiRefLayouts",title:"Layouts - API - Domma CMS"},{path:"/docs/api/navigation",view:"apiRefNavigation",title:"Navigation - API - Domma CMS"},{path:"/docs/api/media",view:"apiRefMedia",title:"Media - API - Domma CMS"},{path:"/docs/api/users",view:"apiRefUsers",title:"Users - API - Domma CMS"},{path:"/docs/api/plugins",view:"apiRefPlugins",title:"Plugins - API - Domma CMS"},{path:"/docs/api/collections",view:"apiRefCollections",title:"Collections - API - Domma CMS"},{path:"/docs/api/views",view:"apiRefViews",title:"Views API - Domma CMS"},{path:"/docs/api/actions",view:"apiRefActions",title:"Actions API - Domma CMS"},{path:"/docs/api/forms",view:"apiRefForms",title:"Forms API - Domma CMS"},{path:"/docs/api/scaffold",view:"apiRefScaffold",title:"Scaffold API - Domma CMS"},{path:"/docs/api/external",view:"apiRefExternal",title:"External API & Tokens - Domma CMS"},{path:"/docs/api/content",view:"apiRefContent",title:"Content API - Domma CMS"},{path:"/docs/api/builder",view:"apiRefBuilder",title:"API Builder - Domma CMS"},{path:"/api-reference",view:"apiReference",title:"API Reference - Domma CMS"},{path:"/collections",view:"collections",title:"Collections - Domma CMS"},{path:"/collections/new",view:"collectionEditor",title:"New Collection - Domma CMS"},{path:"/collections/edit/:slug",view:"collectionEditor",title:"Edit Collection - Domma CMS"},{path:"/collections/:slug/entries",view:"collectionEntries",title:"Entries - Domma CMS"},{path:"/forms",view:"forms",title:"Forms - Domma CMS"},{path:"/forms/new",view:"formEditor",title:"New Form - Domma CMS"},{path:"/forms/edit/:slug",view:"formEditor",title:"Edit Form - Domma CMS"},{path:"/forms/:slug/submissions",view:"formSubmissions",title:"Submissions - Domma CMS"},{path:"/views",view:"viewsList",title:"Views - Domma CMS"},{path:"/views/new",view:"viewEditor",title:"New View - Domma CMS"},{path:"/views/edit/:slug",view:"viewEditor",title:"Edit View - Domma CMS"},{path:"/views/:slug/preview",view:"viewPreview",title:"View Preview - Domma CMS"},{path:"/actions",view:"actionsList",title:"Actions - Domma CMS"},{path:"/actions/new",view:"actionEditor",title:"New Action - Domma CMS"},{path:"/actions/edit/:slug",view:"actionEditor",title:"Edit Action - Domma CMS"},{path:"/pro/docs",view:"proDocs",title:"Pro Documentation - Domma CMS"},{path:"/blocks",view:"blocks",title:"Blocks - Domma CMS"},{path:"/blocks/new",view:"blockEditor",title:"New Block - Domma CMS"},{path:"/blocks/edit/:name",view:"blockEditor",title:"Edit Block - Domma CMS"},{path:"/components",view:"components",title:"Components - Domma CMS"},{path:"/components/new",view:"componentEditor",title:"New Component - Domma CMS"},{path:"/components/edit/:name",view:"componentEditor",title:"Edit Component - Domma CMS"},{path:"/my-profile",view:"myProfile",title:"My Profile - Domma CMS"},{path:"/roles",view:"roles",title:"Roles & Permissions - Domma CMS"},{path:"/roles/edit/:id",view:"roleEditor",title:"Edit Role - Domma CMS"},{path:"/effects",view:"effects",title:"Effects - Domma CMS"},{path:"/search",view:"search",title:"Search - Domma CMS"},{path:"/content-api",view:"contentApi",title:"Content API - Domma CMS"},{path:"/notes",view:"notes",title:"Notes - Domma CMS"},{path:"/todo",view:"todo",title:"Todo - Domma CMS"},{path:"/calculator",view:"calculator",title:"Calculator - Domma CMS"},{path:"/analytics",view:"analytics",title:"Analytics - Domma CMS"},{path:"/seo",view:"seo",title:"SEO - Domma CMS"},{path:"/seo/:tab",view:"seo",title:"SEO - Domma CMS"},{path:"/wordpress-import",view:"wordpressImport",title:"Import from WordPress - Domma CMS"},{path:"/contacts",view:"contacts",title:"Contacts - Domma CMS"},{path:"/calls/new",view:"callNew",title:"Call now - Domma CMS"},{path:"/system/notifications",view:"notifications",title:"Notifications - Domma CMS"},{path:"/api-tokens",view:"apiTokens",title:"API Tokens - Domma CMS"},{path:"/api-endpoints",view:"apiEndpoints",title:"API Builder - Domma CMS"},{path:"/api-endpoints/new",view:"apiEndpointEditor",title:"New API Endpoint - Domma CMS"},{path:"/api-endpoints/edit/:id",view:"apiEndpointEditor",title:"Edit API Endpoint - Domma CMS"},{path:"/projects",view:"projects",title:"Projects - Domma CMS"},{path:"/projects/new",view:"projects",title:"New Project - Domma CMS"},{path:"/projects/edit/:slug",view:"projects",title:"Edit Project - Domma CMS"},{path:"/projects/:slug/settings",view:"projectSettings",title:"Project settings - Domma CMS"},{path:"/projects/:slug/pages",view:"pages",title:"Project pages - Domma CMS"},{path:"/projects/:slug/collections",view:"collections",title:"Project collections - Domma CMS"},{path:"/projects/:slug/forms",view:"forms",title:"Project forms - Domma CMS"},{path:"/projects/:slug/actions",view:"actionsList",title:"Project actions - Domma CMS"},{path:"/projects/:slug/menus",view:"menus",title:"Project menus - Domma CMS"},{path:"/projects/:slug/blocks",view:"blocks",title:"Project blocks - Domma CMS"},{path:"/projects/:slug/components",view:"components",title:"Project components - Domma CMS"},{path:"/projects/:slug/views",view:"viewsList",title:"Project views - Domma CMS"},{path:"/projects/:slug/roles",view:"roles",title:"Project roles - Domma CMS"},{path:"/projects/:slug/users",view:"users",title:"Project users - Domma CMS"},{path:"/projects/:slug/apis",view:"apiEndpoints",title:"Project APIs - Domma CMS"},{path:"/projects/:slug",view:"projectDetail",title:"Project - Domma CMS"},{path:"/login",view:"login",title:"Sign in - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}},{path:"/reset-password",view:"login",title:"Reset Password - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}}];M.subscribe("router:afterChange",async({to:t,from:i})=>{if(!b(t.path)){if($("#admin-sidebar").show(),$("#admin-topbar").show(),b(i?.path)){$("#topbar-user-name").remove(),import("./lib/admin-theme.js").then(a=>a.refreshAdminTheme(c)),await U();const e=await f(),o=D(t.path);if(o&&R.navigate(o),j(e),rt.read().signInToasts)try{const a=await c.system.notifications.list().catch(()=>[]),n=(Array.isArray(a)?a:[]).filter(s=>s.unread&&["warning","critical"].includes(s.data?.severity)).slice(0,3);for(const s of n){const v=d(s.data?.title||""),T=d((s.data?.body||"").slice(0,120));E.toast(`${v} - ${T}`,{type:s.data?.severity==="critical"?"error":"warning",duration:0})}}catch{}}B()}}),M.subscribe("router:afterChange",()=>{setTimeout(()=>{$(".btn-primary, .btn-danger").length&&Domma.effects.reveal(".btn-primary, .btn-danger",{animation:"fade",stagger:40,duration:300})},50)});const H=["#field-project","#menu-project","#collection-project","#endpoint-project","#action-project","#view-project","#block-project","#component-project","#role-project",'[name="project"]','[name="ownedByProject"]'];function q(t){return/^\/(pages|menus|context-menus|collections|forms|actions|views|blocks|components|users|roles|api-endpoints)\/(new|edit\/)/.test(t)}M.subscribe("router:afterChange",({to:t})=>{const i=t?String(t.path).split("?")[0]:"";if(!t||!q(i))return;const o=new URLSearchParams(location.hash.split("?")[1]||"").get("project");if(!o||!/\/new$/.test(i))return;let a=0;const n=60,s=1500,v=()=>{a+=n;for(const T of H){const C=document.querySelector(T);if(!C)continue;if(Array.from(C.options||[]).find(z=>z.value===o)){C.value=o,C.dispatchEvent(new Event("change",{bubbles:!0}));return}}a<s&&setTimeout(v,n)};setTimeout(v,n)});const L="cms_card_states",k=S.get(L)||{};M.subscribe("router:afterChange",()=>{setTimeout(()=>{$("#view-container .card-collapsible").each(function(){const t=$(this).find(".card-header h2, .card-header h3").first().text().trim();t&&k[t]==="collapsed"&&$(this).addClass("card-collapsed")})},200)}),$("#view-container").on("click",".card-collapsible .card-header",function(t){if($(t.target).closest("button, a").length)return;const i=$(this).closest(".card");i.toggleClass("card-collapsed");const e=$(this).find("h2, h3").first().text().trim();e&&(k[e]=i.hasClass("card-collapsed")?"collapsed":"open",S.set(L,k))}),pt(),document.addEventListener("keydown",t=>{if(!(t.ctrlKey||t.metaKey)||t.key!=="s"||window.location.hash.startsWith("#/login")||window.location.hash.startsWith("#/reset-password"))return;const i=document.querySelector("#view-container .view-header button.btn-primary");i&&(t.preventDefault(),i.click())});const r={...K},G={notes:{displayName:"Notes",icon:"edit-3"},todo:{displayName:"Todo",icon:"check-square"},calculator:{displayName:"Calculator",icon:"calculator"},analytics:{displayName:"Analytics",icon:"chart-bar"},seo:{displayName:"SEO",icon:"search"},wordpressImport:{displayName:"Import from WordPress",icon:"download"},contacts:{displayName:"Contacts",icon:"users"},projects:{displayName:"Projects",icon:"folder"},pages:{displayName:"Pages",icon:"file-text"},media:{displayName:"Media",icon:"image"},menus:{displayName:"Site menus",icon:"menu"},contextMenus:{displayName:"Context Menus",icon:"menu"},theme:{displayName:"Theme",icon:"droplet"},collections:{displayName:"Collections",icon:"database"},forms:{displayName:"Forms",icon:"layout"},viewsList:{displayName:"Views",icon:"eye"},actionsList:{displayName:"Actions",icon:"zap"},apiEndpoints:{displayName:"API Builder",icon:"code"},blocks:{displayName:"Blocks",icon:"box"},components:{displayName:"Components",icon:"component"},notifications:{displayName:"Notifications",icon:"bell"},roles:{displayName:"Roles",icon:"shield"},users:{displayName:"Users",icon:"users"},settings:{displayName:"Site Settings",icon:"settings"},effects:{displayName:"Effects",icon:"sparkles"},layouts:{displayName:"Layouts",icon:"layout"},plugins:{displayName:"Marketplace",icon:"store"},myProfile:{displayName:"My Profile",icon:"user"},apiTokens:{displayName:"API Tokens",icon:"key"},search:{displayName:"Search",icon:"search"},contentApi:{displayName:"Content API",icon:"file-text"},dashboard:{displayName:"Dashboard",icon:"home"},dashboards:{displayName:"Dashboards",icon:"home"},pageEditor:{displayName:"Pages",section:"Edit",icon:"file-text"},menuEditor:{displayName:"Site menus",section:"Edit",icon:"menu"},menuLocations:{displayName:"Site menus",section:"Locations",icon:"map-pin"},contextMenuEditor:{displayName:"Context Menus",section:"Edit",icon:"menu"},collectionEditor:{displayName:"Collections",section:"Edit",icon:"database"},collectionEntries:{displayName:"Collections",section:"Entries",icon:"database"},formEditor:{displayName:"Forms",section:"Edit",icon:"layout"},formSubmissions:{displayName:"Forms",section:"Submissions",icon:"inbox"},viewEditor:{displayName:"Views",section:"Edit",icon:"eye"},viewPreview:{displayName:"Views",section:"Preview",icon:"eye"},actionEditor:{displayName:"Actions",section:"Edit",icon:"zap"},apiEndpointEditor:{displayName:"API Builder",section:"Edit",icon:"code"},blockEditor:{displayName:"Blocks",section:"Edit",icon:"box"},componentEditor:{displayName:"Components",section:"Edit",icon:"component"},roleEditor:{displayName:"Roles",section:"Edit",icon:"shield"},userEditor:{displayName:"Users",section:"Edit",icon:"users"},projectDetail:{displayName:"Projects",section:"Overview",icon:"folder"},projectSettings:{displayName:"Projects",section:"Settings",icon:"folder"},pluginCode:{displayName:"Marketplace",section:"Code",icon:"code"}};for(const[t,i]of Object.entries(G))r[t]&&(r[t]=O(r[t],{plugin:t,licence:"Built in",...i}));r.dashboard=_(r.dashboard);const I=[...W];async function U(){if(m())try{const t=await c.plugins.adminConfig(),i=new Set(I.map(e=>e.path));for(const e of t.routes||[])i.has(e.path)||I.push(e);for(const[e,o]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${o.entry}`);r[e]=O(a[o.exportName],(t.meta||{})[e])}catch{}r.dashboard=_(r.dashboard);for(const[e,{route:o}]of Object.entries(t.takeovers||{}))o&&(y[`/${e}`]=o);for(const[e,{enabled:o,displayName:a}]of Object.entries(t.tools||{}))o===!1&&(N[`/${e}`]=a);for(const{id:e,href:o}of t.css||[])if(!document.getElementById(e)){const a=document.createElement("link");a.id=e,a.rel="stylesheet",a.href=o,document.head.appendChild(a)}}catch{}}function B(){const t=x();if(!t||$("#topbar-user-name").length)return;const e={"super-admin":"Super Admin",admin:"Admin",user:"User"}[t.role]||t.role,o=lt(t);$("#topbar-user").html(`
|
|
1
|
+
import{installSmoothCarets as K}from"./lib/smooth-caret.js";import{views as J}from"./views/index.js";import{withPluginChrome as O}from"./lib/plugin-chrome.js";import{api as c,getUser as x,isAuthenticated as m,logout as Y,sendToLogin as Q}from"./api.js";import{claimDrafts as X}from"./lib/draft-owner.js";import{isAuthScreen as b,loginHashFor as Z}from"./lib/login-arrange.js";import{installHttpInterceptor as tt}from"./http-interceptor.js";import{installResizableSlideovers as et}from"./lib/slideover-resizable.js";import{installActivityThrobber as it}from"./lib/activity-throbber.js";import{installUpdateNotice as ot}from"./lib/update-notice.js";import{isPathAllowed as at,redirectFor as st}from"./lib/admin-scope.js";import{deliverDesktop as nt,desktopActive as rt,notificationSettings as lt}from"./lib/desktop-notify.js";import{avatarUrl as ct}from"./lib/avatar.js";import{installCalculator as mt}from"./lib/calculator.js";import{takeOverviewPass as pt,withDashboardStrip as _}from"./lib/dashboards-strip.js";import{installHotkeys as dt}from"./lib/hotkeys-ui.js";import{applyAdminBrand as V}from"./lib/admin-brand.js";import{installRouterCatchUp as ut}from"./lib/router-catch-up.js";$(()=>{K(document),tt(),mt(),ot(),it(),et(),(async()=>{const{applyAdminTheme:t,refreshAdminTheme:i}=await import("./lib/admin-theme.js");m()?await i(c,{init:!0}):t({dommaTheme:"charcoal-dark"},{init:!0})})();let p=null,h=null,l="/",w=!1,g=null;function D(t){if(N[t])return E.toast(`${N[t]} is switched off on this site.`,{type:"info"}),"/";if(t.split("?")[0]==="/my-dashboard")return"/dashboards";const i=y[t]||st(p,t);return i||((t.split("?")[0]||"/")==="/"&&l&&l!=="/"&&!pt()?y[l]||l:null)}const y={},N={};R.use(async(t,i,e)=>{if(b(t.path))return e();if(!m()){Q();return}const o=D(t.path);if(o){R.navigate(o);return}e()});async function f(){try{const t=await c.get("/auth/permissions");p=t.adminScope||null,h=t.adminBrand||null,V(h),l=t.adminHome||"/";const i=t.permissions||[];return w=at(p,"/settings")&&i.some(e=>e==="settings"||e.startsWith("settings.")),g=i.some(e=>e==="notifications"||e.startsWith("notifications.")),i}catch{return p=null,l="/",h||V(null),w=!1,g=null,[]}}document.addEventListener("dm:admin-home-changed",()=>{f()});let P=null,A=!1;document.addEventListener("dm:sidebar-rebuild",()=>{if(P){A=!0;return}P=(async()=>{do{A=!1;try{await j(await f())}catch{}}while(A)})().finally(()=>{P=null})});async function j(t){const{renderAdminSidebar:i}=await import("./lib/sidebar-renderer.js");await i({mount:"#admin-sidebar",permissions:t,adminScope:p,brand:h})}M.subscribe("router:afterChange",({to:t})=>{b(t.path)&&(u&&(clearInterval(u),u=null),p=null,l="/",w=!1,g=null)});const W=[{path:"/",view:"dashboard",title:"Dashboard - Domma CMS"},{path:"/dashboards",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/my-dashboard",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/pages",view:"pages",title:"Pages - Domma CMS"},{path:"/pages/new",view:"pageEditor",title:"New Page - Domma CMS"},{path:"/pages/edit/*",view:"pageEditor",title:"Edit Page - Domma CMS"},{path:"/media",view:"media",title:"Media - Domma CMS"},{path:"/menus",view:"menus",title:"Menus - Domma CMS"},{path:"/context-menus",view:"contextMenus",title:"Context Menus - Domma CMS"},{path:"/context-menus/new",view:"contextMenuEditor",title:"New Context Menu - Domma CMS"},{path:"/context-menus/edit/:slug",view:"contextMenuEditor",title:"Edit Context Menu - Domma CMS"},{path:"/menus/new",view:"menuEditor",title:"New Menu - Domma CMS"},{path:"/menus/edit/:slug",view:"menuEditor",title:"Edit Menu - Domma CMS"},{path:"/menu-locations",view:"menuLocations",title:"Menu Locations - Domma CMS"},{path:"/navigation",view:"menusRedirect",title:"Menus - Domma CMS"},{path:"/layouts",view:"layouts",title:"Layouts - Domma CMS"},{path:"/settings",view:"settings",title:"Settings - Domma CMS"},{path:"/theme",view:"theme",title:"Theme - Domma CMS"},{path:"/users",view:"users",title:"Users - Domma CMS"},{path:"/users/new",view:"userEditor",title:"New User - Domma CMS"},{path:"/users/edit/:id",view:"userEditor",title:"Edit User - Domma CMS"},{path:"/plugins",view:"plugins",title:"Plugins - Domma CMS"},{path:"/plugins/code/:name",view:"pluginCode",title:"Plugin Code - Domma CMS"},{path:"/documentation",view:"documentation",title:"Usage - Domma CMS"},{path:"/tutorials",view:"tutorials",title:"Tutorials - Domma CMS"},{path:"/tutorials/crud",view:"tutorialCrud",title:"Building a CRUD App - Domma CMS"},{path:"/tutorials/plugin",view:"tutorialPlugin",title:"Writing a Tool - Domma CMS"},{path:"/tutorials/forms",view:"tutorialForms",title:"Form Follow-Up - Domma CMS"},{path:"/docs/components",view:"componentsReference",title:"Components Reference - Domma CMS"},{path:"/docs/components-howto",view:"componentsHowto",title:"Components How-To - Domma CMS"},{path:"/docs/components-walkthrough",view:"componentsWalkthrough",title:"Components Walkthrough - Domma CMS"},{path:"/docs/components-rules",view:"componentsRules",title:"Components Rules - Domma CMS"},{path:"/docs/usage/pages",view:"usagePages",title:"Pages - Usage - Domma CMS"},{path:"/docs/usage/media",view:"usageMedia",title:"Media - Usage - Domma CMS"},{path:"/docs/usage/navigation",view:"usageNavigation",title:"Navigation - Usage - Domma CMS"},{path:"/docs/usage/dconfig",view:"usageDconfig",title:"DConfig - Usage - Domma CMS"},{path:"/docs/usage/shortcodes",view:"usageShortcodes",title:"Shortcodes - Usage - Domma CMS"},{path:"/docs/usage/site-settings",view:"usageSiteSettings",title:"Site Settings - Usage - Domma CMS"},{path:"/docs/usage/plugins",view:"usagePlugins",title:"Plugins - Usage - Domma CMS"},{path:"/docs/usage/users-roles",view:"usageUsersRoles",title:"Users & Roles - Usage - Domma CMS"},{path:"/docs/usage/views",view:"usageViews",title:"Views - Usage - Domma CMS"},{path:"/docs/usage/actions",view:"usageActions",title:"Actions - Usage - Domma CMS"},{path:"/docs/usage/cta-shortcode",view:"usageCtaShortcode",title:"CTA Shortcode - Usage - Domma CMS"},{path:"/docs/usage/editions",view:"usageEditions",title:"Editions & Licences - Usage - Domma CMS"},{path:"/docs/usage/collections",view:"usageCollections",title:"Collections & Forms - Usage - Domma CMS"},{path:"/docs/usage/blocks",view:"usageBlocks",title:"Blocks - Usage - Domma CMS"},{path:"/docs/usage/tools",view:"usageTools",title:"Built-in Tools - Usage - Domma CMS"},{path:"/docs/usage/dashboard",view:"usageDashboard",title:"Dashboard - Usage - Domma CMS"},{path:"/docs/plugins",view:"pluginGuides",title:"Plugin Guides - Domma CMS"},{path:"/docs/plugins/*",view:"pluginGuide",title:"Plugin Guide - Domma CMS"},{path:"/docs/api/authentication",view:"apiRefAuthentication",title:"Authentication - API - Domma CMS"},{path:"/docs/api/pages",view:"apiRefPages",title:"Pages - API - Domma CMS"},{path:"/docs/api/settings",view:"apiRefSettings",title:"Settings - API - Domma CMS"},{path:"/docs/api/layouts",view:"apiRefLayouts",title:"Layouts - API - Domma CMS"},{path:"/docs/api/navigation",view:"apiRefNavigation",title:"Navigation - API - Domma CMS"},{path:"/docs/api/media",view:"apiRefMedia",title:"Media - API - Domma CMS"},{path:"/docs/api/users",view:"apiRefUsers",title:"Users - API - Domma CMS"},{path:"/docs/api/plugins",view:"apiRefPlugins",title:"Plugins - API - Domma CMS"},{path:"/docs/api/collections",view:"apiRefCollections",title:"Collections - API - Domma CMS"},{path:"/docs/api/views",view:"apiRefViews",title:"Views API - Domma CMS"},{path:"/docs/api/actions",view:"apiRefActions",title:"Actions API - Domma CMS"},{path:"/docs/api/forms",view:"apiRefForms",title:"Forms API - Domma CMS"},{path:"/docs/api/scaffold",view:"apiRefScaffold",title:"Scaffold API - Domma CMS"},{path:"/docs/api/external",view:"apiRefExternal",title:"External API & Tokens - Domma CMS"},{path:"/docs/api/content",view:"apiRefContent",title:"Content API - Domma CMS"},{path:"/docs/api/builder",view:"apiRefBuilder",title:"API Builder - Domma CMS"},{path:"/api-reference",view:"apiReference",title:"API Reference - Domma CMS"},{path:"/collections",view:"collections",title:"Collections - Domma CMS"},{path:"/collections/new",view:"collectionEditor",title:"New Collection - Domma CMS"},{path:"/collections/edit/:slug",view:"collectionEditor",title:"Edit Collection - Domma CMS"},{path:"/collections/:slug/entries",view:"collectionEntries",title:"Entries - Domma CMS"},{path:"/forms",view:"forms",title:"Forms - Domma CMS"},{path:"/forms/new",view:"formEditor",title:"New Form - Domma CMS"},{path:"/forms/edit/:slug",view:"formEditor",title:"Edit Form - Domma CMS"},{path:"/forms/:slug/submissions",view:"formSubmissions",title:"Submissions - Domma CMS"},{path:"/views",view:"viewsList",title:"Views - Domma CMS"},{path:"/views/new",view:"viewEditor",title:"New View - Domma CMS"},{path:"/views/edit/:slug",view:"viewEditor",title:"Edit View - Domma CMS"},{path:"/views/:slug/preview",view:"viewPreview",title:"View Preview - Domma CMS"},{path:"/actions",view:"actionsList",title:"Actions - Domma CMS"},{path:"/actions/new",view:"actionEditor",title:"New Action - Domma CMS"},{path:"/actions/edit/:slug",view:"actionEditor",title:"Edit Action - Domma CMS"},{path:"/pro/docs",view:"proDocs",title:"Pro Documentation - Domma CMS"},{path:"/blocks",view:"blocks",title:"Blocks - Domma CMS"},{path:"/blocks/new",view:"blockEditor",title:"New Block - Domma CMS"},{path:"/blocks/edit/:name",view:"blockEditor",title:"Edit Block - Domma CMS"},{path:"/components",view:"components",title:"Components - Domma CMS"},{path:"/components/new",view:"componentEditor",title:"New Component - Domma CMS"},{path:"/components/edit/:name",view:"componentEditor",title:"Edit Component - Domma CMS"},{path:"/my-profile",view:"myProfile",title:"My Profile - Domma CMS"},{path:"/roles",view:"roles",title:"Roles & Permissions - Domma CMS"},{path:"/roles/edit/:id",view:"roleEditor",title:"Edit Role - Domma CMS"},{path:"/effects",view:"effects",title:"Effects - Domma CMS"},{path:"/search",view:"search",title:"Search - Domma CMS"},{path:"/content-api",view:"contentApi",title:"Content API - Domma CMS"},{path:"/notes",view:"notes",title:"Notes - Domma CMS"},{path:"/todo",view:"todo",title:"Todo - Domma CMS"},{path:"/calculator",view:"calculator",title:"Calculator - Domma CMS"},{path:"/analytics",view:"analytics",title:"Analytics - Domma CMS"},{path:"/seo",view:"seo",title:"SEO - Domma CMS"},{path:"/seo/:tab",view:"seo",title:"SEO - Domma CMS"},{path:"/wordpress-import",view:"wordpressImport",title:"Import from WordPress - Domma CMS"},{path:"/contacts",view:"contacts",title:"Contacts - Domma CMS"},{path:"/calls/new",view:"callNew",title:"Call now - Domma CMS"},{path:"/system/notifications",view:"notifications",title:"Notifications - Domma CMS"},{path:"/api-tokens",view:"apiTokens",title:"API Tokens - Domma CMS"},{path:"/api-endpoints",view:"apiEndpoints",title:"API Builder - Domma CMS"},{path:"/api-endpoints/new",view:"apiEndpointEditor",title:"New API Endpoint - Domma CMS"},{path:"/api-endpoints/edit/:id",view:"apiEndpointEditor",title:"Edit API Endpoint - Domma CMS"},{path:"/projects",view:"projects",title:"Projects - Domma CMS"},{path:"/projects/new",view:"projects",title:"New Project - Domma CMS"},{path:"/projects/edit/:slug",view:"projects",title:"Edit Project - Domma CMS"},{path:"/projects/:slug/settings",view:"projectSettings",title:"Project settings - Domma CMS"},{path:"/projects/:slug/pages",view:"pages",title:"Project pages - Domma CMS"},{path:"/projects/:slug/collections",view:"collections",title:"Project collections - Domma CMS"},{path:"/projects/:slug/forms",view:"forms",title:"Project forms - Domma CMS"},{path:"/projects/:slug/actions",view:"actionsList",title:"Project actions - Domma CMS"},{path:"/projects/:slug/menus",view:"menus",title:"Project menus - Domma CMS"},{path:"/projects/:slug/blocks",view:"blocks",title:"Project blocks - Domma CMS"},{path:"/projects/:slug/components",view:"components",title:"Project components - Domma CMS"},{path:"/projects/:slug/views",view:"viewsList",title:"Project views - Domma CMS"},{path:"/projects/:slug/roles",view:"roles",title:"Project roles - Domma CMS"},{path:"/projects/:slug/users",view:"users",title:"Project users - Domma CMS"},{path:"/projects/:slug/apis",view:"apiEndpoints",title:"Project APIs - Domma CMS"},{path:"/projects/:slug",view:"projectDetail",title:"Project - Domma CMS"},{path:"/login",view:"login",title:"Sign in - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}},{path:"/reset-password",view:"login",title:"Reset Password - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}}];M.subscribe("router:afterChange",async({to:t,from:i})=>{if(!b(t.path)){if($("#admin-sidebar").show(),$("#admin-topbar").show(),b(i?.path)){$("#topbar-user-name").remove(),import("./lib/admin-theme.js").then(a=>a.refreshAdminTheme(c)),await U();const e=await f(),o=D(t.path);if(o&&R.navigate(o),j(e),lt.read().signInToasts)try{const a=await c.system.notifications.list().catch(()=>[]),n=(Array.isArray(a)?a:[]).filter(s=>s.unread&&["warning","critical"].includes(s.data?.severity)).slice(0,3);for(const s of n){const v=d(s.data?.title||""),T=d((s.data?.body||"").slice(0,120));E.toast(`${v} - ${T}`,{type:s.data?.severity==="critical"?"error":"warning",duration:0})}}catch{}}B()}}),M.subscribe("router:afterChange",()=>{setTimeout(()=>{$(".btn-primary, .btn-danger").length&&Domma.effects.reveal(".btn-primary, .btn-danger",{animation:"fade",stagger:40,duration:300})},50)});const H=["#field-project","#menu-project","#collection-project","#endpoint-project","#action-project","#view-project","#block-project","#component-project","#role-project",'[name="project"]','[name="ownedByProject"]'];function q(t){return/^\/(pages|menus|context-menus|collections|forms|actions|views|blocks|components|users|roles|api-endpoints)\/(new|edit\/)/.test(t)}M.subscribe("router:afterChange",({to:t})=>{const i=t?String(t.path).split("?")[0]:"";if(!t||!q(i))return;const o=new URLSearchParams(location.hash.split("?")[1]||"").get("project");if(!o||!/\/new$/.test(i))return;let a=0;const n=60,s=1500,v=()=>{a+=n;for(const T of H){const C=document.querySelector(T);if(!C)continue;if(Array.from(C.options||[]).find(z=>z.value===o)){C.value=o,C.dispatchEvent(new Event("change",{bubbles:!0}));return}}a<s&&setTimeout(v,n)};setTimeout(v,n)});const L="cms_card_states",k=S.get(L)||{};M.subscribe("router:afterChange",()=>{setTimeout(()=>{$("#view-container .card-collapsible").each(function(){const t=$(this).find(".card-header h2, .card-header h3").first().text().trim();t&&k[t]==="collapsed"&&$(this).addClass("card-collapsed")})},200)}),$("#view-container").on("click",".card-collapsible .card-header",function(t){if($(t.target).closest("button, a").length)return;const i=$(this).closest(".card");i.toggleClass("card-collapsed");const e=$(this).find("h2, h3").first().text().trim();e&&(k[e]=i.hasClass("card-collapsed")?"collapsed":"open",S.set(L,k))}),dt(),document.addEventListener("keydown",t=>{if(!(t.ctrlKey||t.metaKey)||t.key!=="s"||window.location.hash.startsWith("#/login")||window.location.hash.startsWith("#/reset-password"))return;const i=document.querySelector("#view-container .view-header button.btn-primary");i&&(t.preventDefault(),i.click())});const r={...J},G={notes:{displayName:"Notes",icon:"edit-3"},todo:{displayName:"Todo",icon:"check-square"},calculator:{displayName:"Calculator",icon:"calculator"},analytics:{displayName:"Analytics",icon:"chart-bar"},seo:{displayName:"SEO",icon:"search"},wordpressImport:{displayName:"Import from WordPress",icon:"download"},contacts:{displayName:"Contacts",icon:"users"},projects:{displayName:"Projects",icon:"folder"},pages:{displayName:"Pages",icon:"file-text"},media:{displayName:"Media",icon:"image"},menus:{displayName:"Site menus",icon:"menu"},contextMenus:{displayName:"Context Menus",icon:"menu"},theme:{displayName:"Theme",icon:"droplet"},collections:{displayName:"Collections",icon:"database"},forms:{displayName:"Forms",icon:"layout"},viewsList:{displayName:"Views",icon:"eye"},actionsList:{displayName:"Actions",icon:"zap"},apiEndpoints:{displayName:"API Builder",icon:"code"},blocks:{displayName:"Blocks",icon:"box"},components:{displayName:"Components",icon:"component"},notifications:{displayName:"Notifications",icon:"bell"},roles:{displayName:"Roles",icon:"shield"},users:{displayName:"Users",icon:"users"},settings:{displayName:"Site Settings",icon:"settings"},effects:{displayName:"Effects",icon:"sparkles"},layouts:{displayName:"Layouts",icon:"layout"},plugins:{displayName:"Marketplace",icon:"store"},myProfile:{displayName:"My Profile",icon:"user"},apiTokens:{displayName:"API Tokens",icon:"key"},search:{displayName:"Search",icon:"search"},contentApi:{displayName:"Content API",icon:"file-text"},dashboard:{displayName:"Dashboard",icon:"home"},dashboards:{displayName:"Dashboards",icon:"home"},pageEditor:{displayName:"Pages",section:"Edit",icon:"file-text"},menuEditor:{displayName:"Site menus",section:"Edit",icon:"menu"},menuLocations:{displayName:"Site menus",section:"Locations",icon:"map-pin"},contextMenuEditor:{displayName:"Context Menus",section:"Edit",icon:"menu"},collectionEditor:{displayName:"Collections",section:"Edit",icon:"database"},collectionEntries:{displayName:"Collections",section:"Entries",icon:"database"},formEditor:{displayName:"Forms",section:"Edit",icon:"layout"},formSubmissions:{displayName:"Forms",section:"Submissions",icon:"inbox"},viewEditor:{displayName:"Views",section:"Edit",icon:"eye"},viewPreview:{displayName:"Views",section:"Preview",icon:"eye"},actionEditor:{displayName:"Actions",section:"Edit",icon:"zap"},apiEndpointEditor:{displayName:"API Builder",section:"Edit",icon:"code"},blockEditor:{displayName:"Blocks",section:"Edit",icon:"box"},componentEditor:{displayName:"Components",section:"Edit",icon:"component"},roleEditor:{displayName:"Roles",section:"Edit",icon:"shield"},userEditor:{displayName:"Users",section:"Edit",icon:"users"},projectDetail:{displayName:"Projects",section:"Overview",icon:"folder"},projectSettings:{displayName:"Projects",section:"Settings",icon:"folder"},pluginCode:{displayName:"Marketplace",section:"Code",icon:"code"}};for(const[t,i]of Object.entries(G))r[t]&&(r[t]=O(r[t],{plugin:t,licence:"Built in",...i}));r.dashboard=_(r.dashboard);const I=[...W];async function U(){if(m())try{const t=await c.plugins.adminConfig(),i=new Set(I.map(e=>e.path));for(const e of t.routes||[])i.has(e.path)||I.push(e);for(const[e,o]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${o.entry}`);r[e]=O(a[o.exportName],(t.meta||{})[e])}catch{}r.dashboard=_(r.dashboard);for(const[e,{route:o}]of Object.entries(t.takeovers||{}))o&&(y[`/${e}`]=o);for(const[e,{enabled:o,displayName:a}]of Object.entries(t.tools||{}))o===!1&&(N[`/${e}`]=a);for(const{id:e,href:o}of t.css||[])if(!document.getElementById(e)){const a=document.createElement("link");a.id=e,a.rel="stylesheet",a.href=o,document.head.appendChild(a)}}catch{}}function B(){const t=x();if(!t||$("#topbar-user-name").length)return;const e={"super-admin":"Super Admin",admin:"Admin",user:"User"}[t.role]||t.role,o=ct(t);$("#topbar-user").html(`
|
|
2
2
|
${o?`<img id="topbar-avatar" class="topbar-avatar" src="${d(o)}" alt="">`:""}
|
|
3
3
|
<span id="topbar-user-name" class="topbar-user-name">${d(t.name)}</span>
|
|
4
4
|
<span class="topbar-role-badge topbar-role-badge--${d(t.role)}">${e}</span>
|
|
@@ -20,4 +20,4 @@ import{views as K}from"./views/index.js";import{withPluginChrome as O}from"./lib
|
|
|
20
20
|
<span data-icon="log-out"></span>
|
|
21
21
|
<span>Sign out</span>
|
|
22
22
|
</a>
|
|
23
|
-
`);const a=$("#topbar-bell").get(0);a&&(a.hidden=!0);const n=$("#topbar-settings").get(0);n&&(n.hidden=!w),$("#topbar-logout-btn").on("click",s=>{s.preventDefault(),
|
|
23
|
+
`);const a=$("#topbar-bell").get(0);a&&(a.hidden=!0);const n=$("#topbar-settings").get(0);n&&(n.hidden=!w),$("#topbar-logout-btn").on("click",s=>{s.preventDefault(),Y()}),Domma.icons.scan("#admin-topbar"),E.tooltip("#topbar-actions [data-tooltip]",{placement:"bottom"}),F(),u||(u=setInterval(F,6e4))}function d(t){return String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}let u=null;async function F(){if(!(!m()||g===!1))try{const{count:t}=await c.system.notifications.unreadCount();$("#topbar-bell").removeAttr("hidden");const i=$("#topbar-bell-badge");t>0?i.text(t>99?"99+":String(t)).removeAttr("hidden"):i.attr("hidden","").text(""),t>0&&rt()&&nt(await c.system.notifications.list().catch(()=>[]))}catch{}}(async()=>{if(!m()&&!window.location.hash.startsWith("#/reset-password"))window.location.hash.startsWith("#/login")||(window.location.hash=Z(window.location.hash));else if(X(x()?.id),await U(),x()){const a=await f(),n=(window.location.hash||"#/").slice(1)||"/",s=D(n);s&&(window.location.hash=`#${s}`),await j(a),B()}const t=R._extractParams.bind(R);R._extractParams=function(o,a){const n=a.indexOf("?");if(n!==-1&&(a=a.slice(0,n)),o.endsWith("/*")){const s=o.slice(0,-2);return a.startsWith(s+"/")?{}:null}return t(o,a)};const i=R._renderNotFound.bind(R);let e="";R._renderNotFound=async function(o){return m()&&e!==o&&(e=o,await U(),R._matchRoute(o).route)?(e="",R._handleRouteChange()):(e="",m()&&$("#admin-sidebar").get(0)?.style.display==="none"?(E.toast("That link goes nowhere - here is your home page.",{type:"warning"}),R.navigate("/")):i(o))},ut(R),R.init({container:"#view-container",routes:I,views:r,default:"/",transitions:{enter:"fadeIn",leave:"fadeOut",duration:150}})})()});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
`)}function
|
|
3
|
-
`),
|
|
4
|
-
`)}),
|
|
5
|
-
`),
|
|
6
|
-
`)}),
|
|
1
|
+
const O=["card","box","grid","row","tabs","accordion","carousel","hero","timeline","slideover","dconfig"],b=new RegExp(`^\\[(${O.join("|")})(\\s[^\\]]*)?\\]`,"i"),j="\u2026",B="\u200B";function D(n,s,o){return`${n.trimEnd()} ${j} [/${s}]${B}${o}`}function y(n,s,o){const i=new RegExp(`^\\[\\/${o}\\]`,"i"),m=new RegExp(`^\\[${o}(\\s[^\\]]*)?\\]`,"i");let d=1;for(let a=s+1;a<n.length;a++){const h=n[a].trimStart();if(m.test(h)&&d++,i.test(h)&&(d--,d===0))return a}return-1}function R(n){const s=[];for(let o=0;o<n.length;o++){const m=n[o].trimStart().match(b);if(!m)continue;const d=m[1].toLowerCase(),a=y(n,o,d);a>o&&s.push({lineIndex:o,tag:d,closeIndex:a})}return s}function M(n){for(;n.firstChild;)n.removeChild(n.firstChild)}export function createFoldingManager(n,s,o={}){const i=new Map;let m=0,d=null;function a(e){d&&d(!0),e(),d&&d(!1)}function h(){return n.value.split(`
|
|
2
|
+
`)}let S=null,$=null;function C(){const e=h(),t=R(e),c=new Set(t.map(u=>u.lineIndex)),l=new Set;e.forEach((u,r)=>{i.has(u)&&l.add(r)});const f=JSON.stringify([e.length,t,[...l]]);f===S&&s.firstChild===$&&s.children.length===e.length||(S=f,M(s),e.forEach((u,r)=>{const p=document.createElement("span");p.className="editor-line-number-row";const g=document.createElement("span");l.has(r)?(g.className="fold-toggle fold-toggle--folded",g.setAttribute("title","Unfold block"),g.textContent="\u25B8",g.addEventListener("click",()=>L(r))):c.has(r)?(g.className="fold-toggle fold-toggle--open",g.setAttribute("title","Fold block"),g.textContent="\u25BE",g.addEventListener("click",()=>w(r))):g.className="fold-toggle fold-toggle--empty",p.appendChild(g);const E=document.createElement("span");E.className="editor-line-num",E.textContent=String(r+1),p.appendChild(E),s.appendChild(p)}),$=s.firstChild,s.scrollTop=n.scrollTop)}function w(e){const t=h(),c=t[e].trimStart().match(b);if(!c)return;const l=c[1].toLowerCase(),f=y(t,e,l);if(f<=e)return;const u=t.slice(e,f+1).join(`
|
|
3
|
+
`),r=D(t[e],l,++m);i.set(r,u);const p=[...t.slice(0,e),r,...t.slice(f+1)];a(()=>{n.value=p.join(`
|
|
4
|
+
`)}),C(),o.onFoldChange&&o.onFoldChange()}function L(e){const t=h(),c=t[e],l=i.get(c);if(!l)return;i.delete(c);const f=l.split(`
|
|
5
|
+
`),u=[...t.slice(0,e),...f,...t.slice(e+1)];a(()=>{n.value=u.join(`
|
|
6
|
+
`)}),C(),o.onFoldChange&&o.onFoldChange()}function v(){let e=0;for(;e++<200;){const t=h(),l=R(t).find(f=>!i.has(t[f.lineIndex]));if(!l)break;w(l.lineIndex)}}function F(){let e=0;for(;i.size>0&&e++<200;){const c=h().findIndex(l=>i.has(l));if(c===-1)break;L(c)}}function A(){if(i.size===0)return n.value;let e=n.value,t=!0,c=0;for(;t&&c++<20;){t=!1;for(const[l,f]of i){const u=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=e.replace(new RegExp(`^${u}$`,"m"),()=>f);r!==e&&(e=r,t=!0)}}return e}function x(e){const t=h();return t[e]!==void 0&&i.has(t[e])}function _(e){d=e}function k(){C()}function G(){F()}return C(),{foldAt:w,unfoldAt:L,foldAll:v,unfoldAll:F,getUnfoldedContent:A,isFolded:x,setGuard:_,refresh:k,destroy:G}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LIMITS={maxResults:[1,50],minQueryLength:[1,5],debounceMs:[100,1e3],offsetX:[0,500],offsetY:[0,500],iconSize:[32,96]},DEFAULTS={enabled:!0,placeholder:"Search pages...",keyboardShortcut:!0,maxResults:10,minQueryLength:2,debounceMs:300,displayMode:"navbar",position:"bottom-right",offsetX:32,offsetY:32,iconOnly:!0,iconSize:52,iconRadius:26},POSITIONS=["top-left","top-right","left-center","right-center","bottom-left","bottom-right"],POSITION_LABEL={"top-left":"Top left","top-right":"Top right","left-center":"Left side","right-center":"Right side","bottom-left":"Bottom left","bottom-right":"Bottom right"};const c={maxResults:"Max results",minQueryLength:"Minimum query length",debounceMs:"Debounce delay",offsetX:"Horizontal offset",offsetY:"Vertical offset",iconSize:"Icon size"};export const maxRadius=t=>Math.floor((Number(t)||DEFAULTS.iconSize)/2);export function radiusForSize(t,e,
|
|
1
|
+
export const LIMITS={maxResults:[1,50],minQueryLength:[1,5],debounceMs:[100,1e3],offsetX:[0,500],offsetY:[0,500],iconSize:[32,96]},DEFAULTS={enabled:!0,placeholder:"Search pages...",keyboardShortcut:!0,maxResults:10,minQueryLength:2,debounceMs:300,displayMode:"navbar",position:"bottom-right",offsetX:32,offsetY:32,iconOnly:!0,iconSize:52,iconRadius:26},POSITIONS=["top-left","top-right","left-center","right-center","bottom-left","bottom-right"],POSITION_LABEL={"top-left":"Top left","top-right":"Top right","left-center":"Left side","right-center":"Right side","bottom-left":"Bottom left","bottom-right":"Bottom right"};const c={maxResults:"Max results",minQueryLength:"Minimum query length",debounceMs:"Debounce delay",offsetX:"Horizontal offset",offsetY:"Vertical offset",iconSize:"Icon size"};export const maxRadius=t=>Math.floor((Number(t)||DEFAULTS.iconSize)/2);export function radiusForSize(t,e,n){const o=Number(t)||0,i=maxRadius(n);return o>=maxRadius(e)||o>i?i:o}const r=t=>{const e=typeof t=="number"?t:parseInt(t,10);return Number.isFinite(e)?Math.round(e):null},l=(t,[e,n])=>Math.min(n,Math.max(e,t));export function formFromSettings(t){const e={...DEFAULTS,...t&&typeof t=="object"?t:{}};return{enabled:e.enabled!==!1,placeholder:String(e.placeholder??DEFAULTS.placeholder),keyboardShortcut:!0,maxResults:String(e.maxResults),minQueryLength:String(e.minQueryLength),debounceMs:String(e.debounceMs),displayMode:e.displayMode==="floating"?"floating":"navbar",position:POSITIONS.includes(e.position)?e.position:DEFAULTS.position,offsetX:String(e.offsetX),offsetY:String(e.offsetY),triggerStyle:["icon-text","icon","hidden"].includes(e.triggerStyle)?e.triggerStyle:e.iconOnly===!1?"icon-text":"icon",iconOnly:e.triggerStyle==="icon-text"?!1:["icon","hidden"].includes(e.triggerStyle)?!0:e.iconOnly!==!1,iconSize:String(e.iconSize),iconRadius:String(e.iconRadius)}}export function payloadFromForm(t){const e={...formFromSettings(null),...t||{}},n=s=>{const a=r(e[s]);return a===null?DEFAULTS[s]:l(a,LIMITS[s])},o=n("iconSize"),i=r(e.iconRadius);return{enabled:e.enabled!==!1,placeholder:String(e.placeholder??"").trim().slice(0,120)||DEFAULTS.placeholder,keyboardShortcut:!0,maxResults:n("maxResults"),minQueryLength:n("minQueryLength"),debounceMs:n("debounceMs"),displayMode:e.displayMode==="floating"?"floating":"navbar",position:POSITIONS.includes(e.position)?e.position:DEFAULTS.position,offsetX:n("offsetX"),offsetY:n("offsetY"),triggerStyle:["icon-text","icon","hidden"].includes(e.triggerStyle)?e.triggerStyle:e.iconOnly===!1?"icon-text":"icon",iconOnly:e.triggerStyle==="icon-text"?!1:["icon","hidden"].includes(e.triggerStyle)?!0:e.iconOnly!==!1,iconSize:o,iconRadius:i===null?Math.min(DEFAULTS.iconRadius,maxRadius(o)):l(i,[0,maxRadius(o)])}}export const snapshot=t=>JSON.stringify(payloadFromForm(t));export function clampNotes(t){const e=[];for(const[n,o]of Object.entries(LIMITS)){const i=String(t?.[n]??"").trim(),s=r(i);i===""||s===null?e.push(`${c[n]} is empty - it will be saved as ${DEFAULTS[n]}.`):(s<o[0]||s>o[1])&&e.push(`${c[n]} is ${o[0]}-${o[1]} - ${s} will be saved as ${l(s,o)}.`)}return e}export function liveChips(t,e=null){const n={...DEFAULTS,...t||{}};if(!n.enabled)return[{text:"Off - nothing is added to public pages",tone:"warn"}];const o=[{text:"On",tone:"ok"}];return o.push({text:n.triggerStyle==="hidden"?"Hidden (keyboard shortcut available)":n.displayMode==="floating"?`Floating button, ${(POSITION_LABEL[n.position]||n.position).toLowerCase()}`:"Icon in the navigation bar",tone:""}),o.push({text:"Ctrl+K / \u2318K",tone:""}),o.push({text:`Up to ${n.maxResults} results`,tone:""}),e&&o.push({text:`${e.searchable} page${e.searchable===1?"":"s"} searchable`,tone:""}),o}export function previewState(t,e){const n=String(t??"").trim(),o=r(e)??DEFAULTS.minQueryLength;return n?n.length<o?{run:!0,note:`Visitors need at least ${o} characters - on the site this would not search yet.`}:{run:!0,note:""}:{run:!1,note:"Type a word or two - results appear as you type."}}export function resultRow(t,e){return{id:`${e}|${t.url}`,url:String(t.url||"/"),title:String(t.title||"Untitled"),snippet:String(t.snippet||t.description||""),meta:[t.url,(t.tags||[]).length?`tags: ${(t.tags||[]).join(", ")}`:""].filter(Boolean).join(" \xB7 "),score:`score ${Number(t.score)||0}`,rank:String(e+1)}}export const searchDraftKey=t=>t?`search.draft.${t}`:null;export function keptDraft(t,e,n){if(!n||!t||typeof t!="object"||t.owner!==n||!t.form||typeof t.form!="object")return null;const o=typeof t.was=="string"?t.was:typeof t.base=="string"?t.base:"";let i=!1;try{i=snapshot(t.form)===e}catch{}return i?null:{form:t.form,was:o,at:typeof t.at=="string"?t.at:"",stale:!!o&&o!==e}}export function draftQuestion({when:t="",stale:e=!1}={}){return{title:"Unsaved changes",text:`Throw away the search settings you left unsaved${t?` (${t})`:""}?`+(e?" Note: the saved settings have changed since you began - check before you save.":""),confirmText:"Throw away",cancelText:"Keep them"}}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{highlight as
|
|
1
|
+
import{highlight as M}from"./syntax-highlight.js";import{attachSmoothCaret as L}from"./smooth-caret.js";function A(){if(document.getElementById("dm-simple-editor-style"))return;const r=document.createElement("style");r.id="dm-simple-editor-style",r.textContent=`
|
|
2
2
|
.dm-edit-wrap {
|
|
3
3
|
display: flex;
|
|
4
4
|
flex-direction: row;
|
|
@@ -86,10 +86,10 @@ import{highlight as S}from"./syntax-highlight.js";function T(){if(document.getEl
|
|
|
86
86
|
.dm-tok-func { color: #4078f2; }
|
|
87
87
|
.dm-tok-key { color: #b8762e; }
|
|
88
88
|
.dm-tok-tag { color: #cc5c66; }
|
|
89
|
-
`,document.head.appendChild(r)}export function createSimpleEditor(r,
|
|
90
|
-
`).length||1
|
|
91
|
-
`);const o=String(t).length;s.style.minWidth=`calc(${o}ch + 1.5rem)`}function
|
|
92
|
-
`)+1)+1;k({line:n,col:o})}function
|
|
93
|
-
`,n-1)+1,d=(o.slice(i,n).match(/^[ \t]*/)||[""])[0],
|
|
94
|
-
`+d+
|
|
95
|
-
`,n-1)+1,
|
|
89
|
+
`,document.head.appendChild(r)}export function createSimpleEditor(r,E={}){if(!r)throw new Error("createSimpleEditor: mountEl is required.");const{initialValue:S="",onChange:x=null,language:y=null,autoIndent:z=!1,onCursor:k=null}=E;for(A();r.firstChild;)r.removeChild(r.firstChild);const a=document.createElement("div"),s=document.createElement("div"),e=document.createElement("textarea");a.className="dm-edit-wrap",s.className="dm-edit-gutter",e.className="dm-edit-area",e.spellcheck=!1,e.setAttribute("autocomplete","off"),e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),a.appendChild(s);let l=null;if(y){const t=document.createElement("div");t.className="dm-edit-host",l=document.createElement("pre"),l.className="dm-edit-highlight",t.appendChild(l),t.appendChild(e),a.appendChild(t)}else a.appendChild(e);r.appendChild(a);function p(){l&&(l.innerHTML=M(e.value,y))}let w=0;function g(){const t=e.value.split(`
|
|
90
|
+
`).length||1;if(t===w)return;w=t;const n=new Array(t);for(let i=0;i<t;i++)n[i]=String(i+1);s.textContent=n.join(`
|
|
91
|
+
`);const o=String(t).length;s.style.minWidth=`calc(${o}ch + 1.5rem)`}let m=null;function h(){m===null&&(m=requestAnimationFrame(()=>{m=null,s.scrollTop=e.scrollTop,l&&(l.scrollTop=e.scrollTop,l.scrollLeft=e.scrollLeft)}))}function b(){if(!k)return;const t=e.value.slice(0,e.selectionStart),n=(t.match(/\n/g)||[]).length+1,o=t.length-(t.lastIndexOf(`
|
|
92
|
+
`)+1)+1;k({line:n,col:o})}function F(t){if(t.key!=="Enter"||t.isComposing)return;t.preventDefault();const{selectionStart:n,value:o}=e,i=o.lastIndexOf(`
|
|
93
|
+
`,n-1)+1,d=(o.slice(i,n).match(/^[ \t]*/)||[""])[0],f=o.slice(0,n).trimEnd().slice(-1),u="{[(".includes(f)?" ":"";e.setRangeText(`
|
|
94
|
+
`+d+u,n,e.selectionEnd,"end"),e.dispatchEvent(new Event("input",{bubbles:!0}))}function T(t){if(t.key!=="Tab")return;t.preventDefault();const{selectionStart:n,selectionEnd:o,value:i}=e;if(!t.shiftKey)e.value=i.slice(0,n)+" "+i.slice(o),e.selectionStart=e.selectionEnd=n+2;else{const d=i.lastIndexOf(`
|
|
95
|
+
`,n-1)+1,f=i.slice(d,d+2),u=f===" "?2:f[0]===" "?1:0;u>0&&(e.value=i.slice(0,d)+i.slice(d+u),e.selectionStart=e.selectionEnd=Math.max(d,n-u))}e.dispatchEvent(new Event("input",{bubbles:!0}))}const v=[];function c(t,n,o){t.addEventListener(n,o),v.push([t,n,o])}c(e,"input",()=>{g(),p(),h(),b(),x&&x(e.value)}),c(e,"scroll",h),c(e,"keydown",T),z&&c(e,"keydown",F),c(e,"keyup",()=>{h(),b()}),c(e,"click",b),e.value=S,g(),p();const C=L(e);return{textarea:e,gutter:s,getValue(){return e.value},setValue(t){e.value!==t&&(e.value=t??"",g(),p(),h(),C.refresh())},focus(){e.focus()},destroy(){C.destroy(),m!==null&&cancelAnimationFrame(m);for(const[t,n,o]of v)t.removeEventListener(n,o);v.length=0,a.parentNode===r&&r.removeChild(a)}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{attachSmoothCaret,installSmoothCarets,getCaretPreference,setCaretPreference}from"/public/js/smooth-caret.js";
|
|
@@ -46,11 +46,7 @@
|
|
|
46
46
|
<input id="ssx-placeholder" type="text" class="form-input" maxlength="120" placeholder="Search pages..." data-model="placeholder.value">
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
|
-
<
|
|
50
|
-
<label class="form-label" for="ssx-shortcut">Keyboard shortcut (Ctrl+K / ⌘K)
|
|
51
|
-
<span data-help="Lets visitors open search from anywhere on a page with Ctrl+K (⌘K on a Mac), as well as by clicking the trigger."></span></label>
|
|
52
|
-
<input id="ssx-shortcut" type="checkbox" class="form-switch" data-model="keyboardShortcut.value">
|
|
53
|
-
</div>
|
|
49
|
+
<p class="ssx-note">Ctrl+K / ⌘K always opens search when search is enabled, including when the trigger is hidden.</p>
|
|
54
50
|
</div>
|
|
55
51
|
|
|
56
52
|
<div class="ssx-card">
|
|
@@ -80,6 +76,13 @@
|
|
|
80
76
|
<div class="ssx-card">
|
|
81
77
|
<div class="ssx-card-title">How visitors open it
|
|
82
78
|
<span data-help-title="Trigger" data-help="Navbar adds a search icon to the site's navigation bar. Floating button puts a fixed button on every page, in the corner or side you choose - useful when the navigation is busy or hidden on small screens."></span></div>
|
|
79
|
+
<label class="form-label" for="ssx-trigger-style">Search display</label>
|
|
80
|
+
<select id="ssx-trigger-style" class="form-select" data-model="triggerStyle.value">
|
|
81
|
+
<option value="icon-text">Icon/Text</option>
|
|
82
|
+
<option value="icon">Icon</option>
|
|
83
|
+
<option value="hidden">Hidden</option>
|
|
84
|
+
</select>
|
|
85
|
+
<p class="ssx-note">Ctrl+K / ⌘K is always available when search is enabled.</p>
|
|
83
86
|
<div class="ssx-seg" role="group" aria-label="Display mode">
|
|
84
87
|
<button type="button" data-on-click="useNavbar" data-bind-class="displayMode.value === 'navbar' && 'is-on'">
|
|
85
88
|
<span data-icon="menu" data-icon-size="14"></span> Navbar</button>
|
|
@@ -88,14 +91,9 @@
|
|
|
88
91
|
</div>
|
|
89
92
|
</div>
|
|
90
93
|
|
|
91
|
-
<div class="ssx-card" data-bind-hidden="displayMode.value !== 'floating'">
|
|
94
|
+
<div class="ssx-card" data-bind-hidden="displayMode.value !== 'floating' || triggerStyle.value === 'hidden'">
|
|
92
95
|
<div class="ssx-card-title">The floating button</div>
|
|
93
|
-
<div class="ssx-
|
|
94
|
-
<label class="form-label" for="ssx-icononly">Icon only
|
|
95
|
-
<span data-help="On: a round or square icon button. Off: a pill with a Search label beside the icon (size and corners then follow the label)."></span></label>
|
|
96
|
-
<input id="ssx-icononly" type="checkbox" class="form-switch" data-model="iconOnly.value">
|
|
97
|
-
</div>
|
|
98
|
-
<div class="ssx-button-row" data-bind-hidden="!iconOnly.value">
|
|
96
|
+
<div class="ssx-button-row" data-bind-hidden="triggerStyle.value !== 'icon'">
|
|
99
97
|
<div class="ssx-sliders">
|
|
100
98
|
<label class="form-label" for="ssx-size">Size <span class="ssx-readout" data-bind-text="sizeText.value"></span>
|
|
101
99
|
<span data-help="How big the button is (32-96 px). The glyph inside scales with it. 44 px and up is comfortable to tap on a phone."></span></label>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{api as
|
|
1
|
+
import{api as g}from"../api.js";import{CardBuilder as gt}from"../lib/card-builder.js";import{TimelineBuilder as bt}from"../lib/timeline-builder.js";import{attachEditorKeybindings as ht,createToolbar as yt,insertAtCursor as wt}from"../lib/markdown-toolbar.js";import{EffectsBuilder as kt}from"../lib/effects-builder.js";import{attachContextMenu as Et}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as Mt}from"../lib/shortcode-insert.js";import{populateThemeSelect as St}from"../lib/themes.js";import{createFoldingManager as Tt}from"../lib/editor-folding.js";import{openScribeComposer as Ct}from"../lib/scribe-composer.js";import{openCrudTutorial as xt}from"../lib/crud-tutorial.js";import{addBannerAction as j}from"../lib/plugin-chrome.js";import{helpPopovers as Ke}from"../lib/help-popover.js";import{onceClosed as ye,openMenuAt as Ue}from"../lib/tool-kit.js";import{pickMedia as Pt}from"../lib/media-picker.js";import{openPageClone as At}from"../lib/page-clone.js";import{openEditorReference as _e}from"../lib/page-editor-reference.js";import{cleanType as Z,DEFAULT_TYPE as Q,EDITOR_FONTS as Lt,fontHref as Ot,isDefaultType as Dt,LINE_HEIGHTS as Rt,SIZES as Nt,typeVars as Je}from"../lib/editor-type.js";import{getProjectFromHash as Ft}from"../lib/project-context.js";import{attachSmoothCaret as We,getCaretPreference as It,setCaretPreference as Bt}from"../lib/smooth-caret.js";import{SCREEN as $t,bannerSection as zt,draftIsStale as jt,draftKey as Vt,initialProject as qt,makeDraft as Ht,problems as we,readDraft as Kt,snapshot as V}from"../lib/page-editor-arrange.js";import{fmtDateTime as ee}from"../lib/dates.js";function te(o){const i=document.createElement("template");return i.innerHTML=o.trim(),i.content.firstElementChild}const Ut=ee,Ge=o=>ee(o.createdAt)+(o.label?` - ${o.label}`:""),_t=`
|
|
2
2
|
<div class="pe-share">
|
|
3
3
|
<p class="form-hint" style="margin-top:0">Anyone with the link can view this page even while it is unpublished, without
|
|
4
4
|
signing in. The link works for this page only, expires on its own, and can be revoked at any time.</p>
|
|
@@ -30,7 +30,7 @@ import{api as b}from"../api.js";import{CardBuilder as vt}from"../lib/card-builde
|
|
|
30
30
|
.pe-share [hidden] { display: none !important; }
|
|
31
31
|
.pe-share-row { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--dm-border-light); }
|
|
32
32
|
.pe-share-text { flex: 1 1 auto; min-width: 0; font-size: .82rem; }
|
|
33
|
-
</style>`;function
|
|
33
|
+
</style>`;function Ye(o){const i=Ot(o);if(!i||document.querySelector(`link[data-pe-font="${CSS.escape(o)}"]`))return;const l=Object.assign(document.createElement("link"),{rel:"stylesheet",href:i});l.dataset.peFont=o,document.head.appendChild(l)}const Jt=`
|
|
34
34
|
<div class="pe-settings">
|
|
35
35
|
<p class="pe-settings-note">How the editor looks to you - kept in this browser, for every page.</p>
|
|
36
36
|
<label class="form-label" for="pe-set-font">Font <span data-help="The lettering in the editor (not on the site). Monospace keeps every character the same width, so shortcodes and Markdown line up."></span></label>
|
|
@@ -43,6 +43,13 @@ import{api as b}from"../api.js";import{CardBuilder as vt}from"../lib/card-builde
|
|
|
43
43
|
</div>
|
|
44
44
|
<label class="pe-settings-switch"><input type="checkbox" class="form-switch" data-model="wrap.value"> Wrap long lines
|
|
45
45
|
<span data-help="Off: a long line runs on and the editor scrolls sideways - each line number is then exactly one line."></span></label>
|
|
46
|
+
<label class="form-label" for="pe-set-caret">Caret movement</label>
|
|
47
|
+
<select id="pe-set-caret" class="form-select" data-model="caret.value">
|
|
48
|
+
<option value="auto">Automatic - follow system motion preference</option>
|
|
49
|
+
<option value="smooth">Smooth</option>
|
|
50
|
+
<option value="native">Native</option>
|
|
51
|
+
</select>
|
|
52
|
+
<p class="pe-settings-note">Smooth enables caret animation across the admin and public site forms in this browser. Automatic follows your system's reduced-motion preference.</p>
|
|
46
53
|
<div class="pe-settings-sample" aria-label="Sample"># A heading
|
|
47
54
|
[card title="Shortcodes line up"]
|
|
48
55
|
The quick brown fox - 0O 1lI {} [] () => ==
|
|
@@ -61,17 +68,17 @@ The quick brown fox - 0O 1lI {} [] () => ==
|
|
|
61
68
|
.pe-settings-sample { white-space: pre-wrap; padding: .75rem 1rem; border-radius: var(--dm-radius-md); border: 1px solid var(--dm-border);
|
|
62
69
|
background: var(--dm-background-alt); font-family: var(--pe-font); font-size: var(--pe-size); line-height: var(--pe-line); }
|
|
63
70
|
.pe-settings-actions { display: flex; gap: .5rem; border-top: 1px solid var(--dm-border); padding-top: .75rem; }
|
|
64
|
-
</style>`;function
|
|
71
|
+
</style>`;function Wt(o){const i=E.slideover({title:"Editor settings",size:"sm",position:"right"}),l=te(`<div>${Jt}</div>`),s=Z(o.peek()),r={font:M.observable(s.font),size:M.observable(String(s.size)),line:M.observable(String(s.line)),wrap:M.observable(s.wrap),caret:M.observable(It())},v=M.computed(()=>Z({font:r.font.value,size:r.size.value,line:r.line.value,wrap:r.wrap.value}));r.isDefault=M.computed(()=>Dt(v.value)&&r.caret.value==="auto");const u=M.effect(()=>Bt(r.caret.value)),p=l.querySelector("#pe-set-font");for(const[b,L]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const $=Lt.filter(P=>P.kind===b),m=L?Object.assign(document.createElement("optgroup"),{label:L}):p.querySelector("optgroup:last-of-type");m.append(...$.map(P=>new Option(P.label,P.id))),L&&p.appendChild(m)}l.querySelector("#pe-set-size").append(...Nt.map(b=>new Option(`${b}px`,String(b)))),l.querySelector("#pe-set-line").append(...Rt.map(b=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[b]||String(b),String(b))));const c=l.querySelector(".pe-settings-sample"),C=M.effect(()=>{const b=v.value;Ye(b.font);for(const[L,$]of Object.entries(Je(b)))c.style.setProperty(L,$);c.style.whiteSpace=b.wrap?"pre-wrap":"pre",c.style.overflowX=b.wrap?"":"auto",JSON.stringify(b)!==JSON.stringify(Z(o.peek()))&&(o.value=b,ae("type",b))});r.reset=()=>{r.font.value=Q.font,r.size.value=String(Q.size),r.line.value=String(Q.line),r.wrap.value=Q.wrap,r.caret.value="auto"},r.done=()=>i.close(),i.element.appendChild(l);const d=M.applyBindings(r,l),h=Ke(l);return ye(i,()=>{d.dispose(),h(),C?.(),u?.()}),Domma.icons?.scan?.(l),i.open(),i}async function Gt(o){const i=E.slideover({title:"Share preview link",size:"md",position:"right"}),l=te(`<div>${_t}</div>`),s={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},r=async()=>{try{const u=await g.pages.previewLinks.list(o);s.links.value=u.filter(p=>!p.revokedAt&&!p.expired).map(p=>({id:p.id,title:p.label||"Untitled link",meta:`Expires ${Ut(p.expiresAt)} - ${p.useCount===1?"1 view":`${p.useCount||0} views`}`})),s.listError.value=""}catch(u){s.listError.value="Could not load existing links: "+(u.message||"unknown error")}finally{s.loaded.value=!0}};s.create=async()=>{s.creating.value=!0;try{const u=await g.pages.previewLinks.create(o,s.expiry.peek(),s.note.peek().trim());s.url.value=u.url,s.note.value="",E.toast("Share link created.",{type:"success"}),await r(),l.querySelector(".pe-share-url")?.select()}catch(u){E.toast("Could not create link: "+(u.message||"unknown error"),{type:"error"})}finally{s.creating.value=!1}},s.copy=async()=>{try{await navigator.clipboard.writeText(s.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{l.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},s.revoke=async u=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await g.pages.previewLinks.revoke(u),E.toast("Link revoked.",{type:"success"}),await r()}catch(p){E.toast("Could not revoke: "+(p.message||"unknown error"),{type:"error"})}};const v=M.applyBindings(s,l);ye(i,()=>v.dispose()),i.element.appendChild(l),i.open(),await r()}function Yt(o){return new Promise(i=>{const l=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),s=te(`
|
|
65
72
|
<div style="padding:1rem">
|
|
66
73
|
<label class="form-label" for="pe-version-label">Version Label</label>
|
|
67
74
|
<input id="pe-version-label" type="text" class="form-input" style="margin-bottom:.75rem"
|
|
68
75
|
placeholder="e.g. Initial design, Before restructure" data-model="label.value" data-on-keydown="key">
|
|
69
76
|
<button type="button" class="btn btn-primary" data-on-click="save" data-bind-disabled="saving.value">Save Version</button>
|
|
70
|
-
</div>`);let
|
|
71
|
-
`).map(
|
|
77
|
+
</div>`);let r=!1;const v={label:M.observable(""),saving:M.observable(!1)};v.save=async()=>{v.saving.value=!0;try{await g.versions.create(o,v.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),r=!0,l.close()}catch(p){E.toast("Failed to save version: "+p.message,{type:"error"})}finally{v.saving.value=!1}},v.key=p=>{p.key==="Enter"&&(p.preventDefault(),v.save())};const u=M.applyBindings(v,s);ye(l,()=>{u.dispose(),i(r)}),l.element.appendChild(s),l.open(),setTimeout(()=>s.querySelector("input")?.focus(),100)})}let T=null,Xe=!1;function Xt(){Xe||!window.R?.use||(Xe=!0,R.use((o,i,l)=>{const s=i?.path||"",r=o?.path||"",v=$t.test(s)&&r!==s;return v&&T?.path===s&&T.cloneTarget===r?(T.cloneTarget=null,T.keepDraft(),l()):!v||!T||T.path!==s||!T.dirty()?l():E.confirm("You have unsaved changes to this page. Leave anyway? They are kept as a draft for your next visit.").then(u=>{u?(T?.keepDraft(),l()):history.replaceState(null,"","#"+s)})}),M.subscribe("router:afterChange",({to:o}={})=>{if(T&&(o?.path||"")!==T.path){const i=T;T=null,i.dispose()}}))}function Zt(o){return o.split(`
|
|
78
|
+
`).map(i=>i.trimEnd()).join(`
|
|
72
79
|
`).replace(/\n{3,}/g,`
|
|
73
80
|
|
|
74
|
-
`)}const
|
|
81
|
+
`)}const Ze="editor_prefs";function q(){return S.get(Ze)||{viewMode:"split",fullscreen:!1}}function ae(o,i){const l=q();l[o]=i,S.set(Ze,l)}const Qt=["edit","details","seo","dconfig","live","history"],Qe=["split","write","preview"],ea=o=>o.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function et(o,i,l=()=>{}){let s=0;try{s=o.contentWindow.scrollY||0}catch{}o.addEventListener("load",()=>{try{o.contentWindow.scrollTo(0,s)}catch{}l()},{once:!0}),o.srcdoc=i}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(o){if(Xt(),T){const e=T;T=null,e.dispose()}const i=window.location.hash.replace(/^#/,""),l=[],s=e=>(l.push(e),e);let r=()=>!1,v=()=>{};const u={path:i,dirty:()=>r(),keepDraft:()=>v(),dispose:()=>{l.splice(0).forEach(e=>{try{e()}catch{}})}};T=u;const p=o.get(0),c=()=>T===u&&p.isConnected,C=window.location.hash.match(/#\/pages\/edit(\/[^?]*)/),d=C?C[1]:null,h=!!d,b=E.loader(p,{type:"dots"}),[L,$,m,P,ke,tt,at]=await Promise.all([g.layouts.get().catch(()=>({})),g.settings.get().catch(()=>({})),h?g.pages.get(d).catch(()=>null):null,h?g.pages.list().catch(()=>[]):[],g.projects.list().catch(()=>[]),g.pages.tags().catch(()=>[]),g.listTags.list("pages").then(e=>e.map(t=>t.name)).catch(()=>[])]);if(!c()){b.destroy();return}if(b.destroy(),h&&!m){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}const w=e=>p.querySelector(e);if(St(w("#field-theme"),{includeDefault:!0}),await na(w("#field-visibility"),m?.visibility),!c())return;const st=oa(w("#field-layout"),L,m?.layout||"default");for(const e of ke)w("#field-project").append(new Option(e.name||e.slug,e.slug));const Ee=[...Array.isArray(P)?P:[]].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath));for(const e of Ee)w("#quick-switch").append(new Option(`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath,!1,e.urlPath===d));const H=q(),a={urlPath:M.observable(d||""),title:M.observable(m?.title||""),description:M.observable(m?.description||""),layout:M.observable(st),status:M.observable(m?.status||"draft"),sortOrder:M.observable(String(m?.sortOrder??99)),showInNav:M.observable(!!m?.showInNav),sidebar:M.observable(!!m?.sidebar),breadcrumbs:M.observable(m?m.breadcrumbs!==!1:!0),bundled:M.observable(!!m?.bundled),tags:M.observable(Array.isArray(m?.tags)?m.tags:[]),adminTags:M.observable(Array.isArray(m?.adminTags)?m.adminTags:[]),category:M.observable(m?.category||""),visibility:M.observable(typeof m?.visibility=="string"&&m.visibility?m.visibility:"public"),project:M.observable(qt({isEdit:h,page:m,projects:ke,fromHash:Ft()||"",urlPath:d||""})),theme:M.observable(m?.theme||""),seoTitle:M.observable(m?.seo?.title||""),seoDesc:M.observable(m?.seo?.description||""),dconfig:M.observable(m?.dconfig?JSON.stringify(m.dconfig,null,2):""),css:M.observable(""),cssOpened:M.observable(!1)},n={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),tab:M.observable("edit"),viewMode:M.observable(Qe.includes(H.viewMode)?H.viewMode:"split"),fullscreen:M.observable(!!H.fullscreen),cssMode:M.observable(!1),folded:M.observable(!1),liveStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null)},k=w("#markdown-editor"),F=w("#css-editor");k.value=m?.content||"";const ot=We(k),nt=We(F);s(()=>ot.destroy()),s(()=>nt.destroy());const O=document.createElement("div");O.className="editor-line-numbers editor-line-numbers--foldable",k.parentElement.insertBefore(O,k);const x=Tt(k,O,{onFoldChange:()=>{}});let I=!1;x.setGuard(e=>{I=e});const z=()=>x.getUnfoldedContent(),Me=M.observable(Z(H.type));s(M.effect(()=>{const e=Me.value,t=w("#editor-body");if(t){Ye(e.font);for(const[f,y]of Object.entries(Je(e)))t.style.setProperty(f,y);t.classList.toggle("pe-nowrap",!e.wrap),k.wrap=e.wrap?"soft":"off",F.wrap=e.wrap?"soft":"off"}}));let Se=null;s(()=>{try{Se?.close()}catch{}});const D=()=>(n.bodyRev.value,{urlPath:a.urlPath.value.trim(),title:a.title.value,description:a.description.value,layout:a.layout.value,status:a.status.value,sortOrder:a.sortOrder.value,showInNav:a.showInNav.value,sidebar:a.sidebar.value,breadcrumbs:a.breadcrumbs.value,bundled:a.bundled.value,tags:a.tags.value,adminTags:a.adminTags.value,category:a.category.value,visibility:a.visibility.value,project:a.project.value,theme:a.theme.value,seoTitle:a.seoTitle.value,seoDesc:a.seoDesc.value,dconfig:a.dconfig.value,body:z(),css:a.cssOpened.value?a.css.value:null}),rt=M.computed(()=>V(D())!==n.base.value),it=M.computed(()=>we({urlPath:a.urlPath.value,dconfig:a.dconfig.value})[0]?.text||""),lt=M.computed(()=>n.versions.value.some(e=>e.checked.value)),ct=M.computed(()=>n.versions.value.length>0&&n.versions.value.every(e=>e.checked.value)),dt=M.computed(()=>{const e=n.versions.value.filter(t=>t.checked.value).length;return e>0&&e<n.versions.value.length});r=()=>V(D())!==n.base.peek();let Te=JSON.stringify(a.adminTags.peek());const K=e=>({title:a.title.peek().trim()||"Untitled",description:a.description.peek().trim(),layout:a.layout.peek(),status:a.status.peek(),sortOrder:parseInt(String(a.sortOrder.peek()),10)||99,showInNav:a.showInNav.peek(),sidebar:a.sidebar.peek(),...a.breadcrumbs.peek()?{}:{breadcrumbs:!1},...a.bundled.peek()?{bundled:!0}:{},tags:a.tags.peek(),...h&&JSON.stringify(a.adminTags.peek())===Te?{}:{adminTags:a.adminTags.peek()},category:a.category.peek().trim()||null,visibility:a.visibility.peek()||"public",project:a.project.peek()||"",seo:{title:a.seoTitle.peek().trim(),description:a.seoDesc.peek().trim()},dconfig:e,...a.theme.peek()?{theme:a.theme.peek()}:{}}),se=()=>{const e=a.dconfig.peek().trim();if(!e)return null;try{return JSON.parse(e)}catch{return null}},Ce=()=>a.urlPath.peek().trim()||d||"/",U=w("#markdown-preview");let xe="";g.settings.getCustomCss().then(({css:e})=>{xe=e||""}).catch(()=>{});const Pe=()=>{const e=U?.contentDocument;if(!e?.head)return;const t=a.cssOpened.peek()?a.css.peek():"";if(!t)return;let f=e.getElementById("preview-custom-css");f||(f=e.createElement("style"),f.id="preview-custom-css",e.head.appendChild(f)),f.textContent=t};let oe=null;const _=()=>{clearTimeout(oe),oe=setTimeout(async()=>{if(!(!U||n.viewMode.peek()==="write"))try{const{html:e}=await g.pages.previewFull(Ce(),K(se()),z());c()&&et(U,ea(e),Pe)}catch(e){U.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(e?.message||"unknown error").replace(/[<&]/g,t=>t==="<"?"<":"&")+"</body>"}},500)},Ae=w("#live-preview-frame");let ne=!0,re=null,ie=!1;const le=async()=>{if(!(ie||!Ae)){ie=!0,n.liveStatus.value="Rendering\u2026";try{const{html:e}=await g.pages.previewFull(Ce(),K(se()),z());if(!c())return;et(Ae,e),ne=!1,n.liveStatus.value="Showing unsaved changes"}catch(e){n.liveStatus.value="Preview failed - "+(e?.message||"unknown error")}finally{ie=!1}}},Le=()=>{ne=!0,n.tab.peek()==="live"&&(clearTimeout(re),re=setTimeout(le,600))};s(()=>{clearTimeout(oe),clearTimeout(re)});const ce=yt(o.find("#markdown-editor"),o.find("#editor-toolbar"),{spacerDefault:$?.layoutOptions?.spacerSize??40});Et(k);const de=p.querySelector(".editor-toolbar-right");de.querySelectorAll(".editor-view-btn[data-mode]").forEach(e=>{const t=e.getAttribute("data-mode");e.classList.remove("active"),e.setAttribute("data-bind-class",`viewMode.value === '${t}' && 'active'`),e.setAttribute("data-on-click",`setMode('${t}')`)}),w("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const pt=te(`
|
|
75
82
|
<span class="pe-toolbar-extras" style="display:contents">
|
|
76
83
|
<button type="button" class="editor-view-btn" data-tip="Edit Custom CSS" data-on-click="toggleCss"
|
|
77
84
|
data-bind-class="cssMode.value && 'active'"><span>CSS</span></button>
|
|
@@ -83,5 +90,5 @@ The quick brown fox - 0O 1lI {} [] () => ==
|
|
|
83
90
|
<span class="pe-fold-icon" hidden data-bind-hidden="!folded.value"><span data-icon="chevrons-right" data-icon-size="10"></span></span>
|
|
84
91
|
</button>
|
|
85
92
|
<span class="editor-toolbar-sep"></span>
|
|
86
|
-
</span>`);de.prepend(
|
|
87
|
-
`).map((
|
|
93
|
+
</span>`);de.prepend(pt);const Oe=e=>(Array.isArray(e)?e:[]).map(t=>({value:t,label:t})),De=w("#field-tags");let J=null;J=De?E.pillbox(De,{data:Oe(tt),value:a.tags.peek(),creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{J&&(a.tags.value=[...J.getValue()])}}):null;const Re=w("#field-admin-tags");let W=null;W=Re?E.pillbox(Re,{data:Oe(at),value:a.adminTags.peek(),creatable:!0,searchable:!0,placeholder:"Add admin tag\u2026",onChange:()=>{W&&(a.adminTags.value=[...W.getValue()])}}):null;let pe=!1,ue=null;const G=async()=>{pe=!0,n.histLoading.value=!0,n.histError.value="";try{const e=(await g.versions.list(d)).versions||[];if(!c())return;n.versions.value=e.map(t=>({...t,when:ee(t.createdAt),author:t.author||"",label:t.label||"",checked:M.observable(!1)}))}catch(e){n.histError.value="Failed to load versions: "+e.message}finally{n.histLoading.value=!1}},ve=e=>n.versions.peek().find(t=>t.filename===e),fe=async e=>{try{const t=await g.versions.get(d,e.filename);ue=e.filename,n.compare.value={label:Ge(e),old:t.content,current:z()}}catch(t){E.toast("Failed to load version: "+t.message,{type:"error"})}},Ne=async e=>{if(!(!e||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await g.versions.restore(d,e),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${d}`),300)}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},ut=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await g.versions.delete(d,e.filename),E.toast("Version deleted.",{type:"success"}),await G()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Fe=()=>{n.bodyRev.value=n.bodyRev.peek()+1},Ie=()=>{a.cssOpened.peek()||(a.css.value=xe,a.cssOpened.value=!0,ht(F))},Be=e=>{for(const t of["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","dconfig"])a[t].value=e[t]==null?"":String(e[t]);for(const t of["showInNav","sidebar","breadcrumbs","bundled"])a[t].value=!!e[t];a.tags.value=Array.isArray(e.tags)?e.tags:[],J?.setValue(a.tags.peek()),Array.isArray(e.adminTags)&&(a.adminTags.value=e.adminTags),W?.setValue(a.adminTags.peek()),x.unfoldAll(),I=!0,k.value=e.body==null?"":String(e.body),I=!1,x.refresh(),e.css!=null&&(Ie(),a.css.value=String(e.css)),Fe()};n.base.value=V(D());const Y=Vt(d||"");v=()=>{if(r())try{S.set(Y,Ht(D(),n.base.peek()))}catch{}};const me=()=>{try{S.remove?S.remove(Y):S.set(Y,null)}catch{}},$e=e=>{r()&&(v(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",$e),s(()=>window.removeEventListener("beforeunload",$e));const ze=async()=>{if(n.saving.peek())return;const e=D(),t=we(e);if(t.length){E.toast(t[0].text,{type:"warning"}),p.querySelectorAll("#editor-meta-tabs .tab-item")[Qt.indexOf(t[0].field==="dconfig"?"dconfig":"details")]?.click();return}const f=(e.dconfig||"").trim(),y=K(f?JSON.parse(f):null),A=a.cssOpened.peek();n.saving.value=!0;try{if(h){const N={frontmatter:y,body:e.body};e.urlPath!==d&&(N.newUrlPath=e.urlPath),await g.pages.update(d,N)}else await g.pages.create({urlPath:e.urlPath,frontmatter:y,body:e.body});A&&await g.settings.saveCustomCss(a.css.peek()),E.toast(A?"Page and CSS saved.":"Page saved.",{type:"success"}),me(),Te=JSON.stringify(a.adminTags.peek()),n.base.value=V(D()),h?e.urlPath!==d&&R.navigate(`/pages/edit${e.urlPath}`):R.navigate("/pages")}catch(N){E.toast(`Save failed: ${N.message||"Unknown error"}`,{type:"error"})}finally{n.saving.value=!1}},je=p.querySelector(".dm-plugin-body")||p,vt={...a,...n,dirty:rt,problem:it,anySelected:lt,allSelected:ct,someSelected:dt,isEdit:h,savedPath:d||"",hasPages:Ee.length>0},ft={save:()=>ze(),discard:async()=>{!r()||!await E.confirm("Discard the changes you have not saved?")||(Be(JSON.parse(n.base.peek())),me())},switchPage:e=>{const t=e?.target?.value;t&&R.navigate("/pages/edit"+t)},showTab:e=>{n.tab.value=e,e==="live"&&ne&&le(),e==="history"&&h&&!pe&&G()},setMode:e=>{n.cssMode.peek()&&(n.cssMode.value=!1),n.viewMode.value=e,ae("viewMode",e),e!=="write"&&_()},toggleFullscreen:()=>{n.fullscreen.value=!n.fullscreen.peek(),ae("fullscreen",n.fullscreen.peek())},toggleCss:()=>{n.cssMode.peek()?(n.cssMode.value=!1,n.viewMode.value=Qe.includes(q().viewMode)?q().viewMode:"split",x.refresh()):(Ie(),n.cssMode.value=!0,n.viewMode.value="split")},formatMarkdown:()=>{const e=k.selectionStart,t=Zt(z());x.unfoldAll(),I=!0,k.value=t,I=!1,k.selectionStart=k.selectionEnd=Math.min(e,t.length),k.dispatchEvent(new Event("input")),x.refresh(),E.toast("Markdown formatted.",{type:"success"})},toggleFold:()=>{n.folded.peek()?x.unfoldAll():x.foldAll(),n.folded.value=!n.folded.peek()},setWidth:e=>{n.liveWidth.value=e;const t=w("#live-preview-stage");t&&(t.scrollTop=0)},refreshLive:()=>le(),share:async()=>{if(!h){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await Gt(d)},toggleAll:e=>{const t=!!e?.target?.checked;n.versions.peek().forEach(f=>{f.checked.value=t})},deleteSelected:async()=>{const e=n.versions.peek().filter(f=>f.checked.peek()).map(f=>f.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await g.versions.bulkDelete(d,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await G()}catch(f){E.toast("Delete failed: "+f.message,{type:"error"})}},saveNamed:async()=>{await Yt(d)&&c()&&(n.tab.peek()==="history"?await G():pe=!1)},closeCompare:()=>{n.compare.value=null,ue=null},restoreCompared:()=>Ne(ue)};de.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const mt=M.applyBindings(vt,je,{methods:ft});s(()=>mt.dispose()),E.tabs(w("#editor-meta-tabs"));let ge=null;s(()=>clearTimeout(ge)),k.addEventListener("input",()=>{x.refresh(),O.scrollTop=k.scrollTop,!I&&(clearTimeout(ge),ge=setTimeout(Fe,120),_(),Le())}),k.addEventListener("scroll",()=>{O.scrollTop=k.scrollTop}),F.addEventListener("scroll",()=>{O.scrollTop=F.scrollTop});let Ve=!0;s(M.effect(()=>{for(const e of Object.keys(a))e!=="css"&&e!=="cssOpened"&&a[e].value;if(n.bodyRev.value,Ve){Ve=!1,_();return}_(),Le()}));let be=null;if(s(()=>clearTimeout(be)),s(M.effect(()=>{const e=a.css.value;n.cssMode.value&&(ta(O,e,F),clearTimeout(be),be=setTimeout(Pe,400))})),h){const e=w(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:f=>{const y=ve(f.dataset.file);return y?[{header:Ge(y)},{label:"Compare with the editor",icon:"columns",action:()=>fe(y)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>Ne(y.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>ut(y)}]:[]}});s(()=>t?.destroy?.()),e.addEventListener("click",f=>{const y=f.target.closest("tr[data-file]");if(!y||f.target.matches("input"))return;const A=f.target.closest(".pe-kebab");if(A){Ue(A);return}const N=ve(y.dataset.file);N&&fe(N)}),e.addEventListener("keydown",f=>{const y=f.target.closest("tr[data-file]");if(y){if(f.key==="F10"&&f.shiftKey)f.preventDefault(),Ue(y);else if(f.key==="Enter"&&f.target===y){const A=ve(y.dataset.file);A&&fe(A)}}})}aa(w("#editor-body"),w("#editor-divider"),s),Mt({image:e=>(n.cssMode.value=!1,sa(e)),scribe:e=>Ct(e),card:e=>gt.open(e,{onMediaBrowse:()=>g.media.list().catch(()=>[])}),timeline:e=>bt.open(e,{onPreview:async t=>{try{return await g.pages.preview(t)}catch{return null}},onListCollections:()=>g.collections.list().catch(()=>[]),onGetCollection:t=>g.collections.get(t).catch(()=>null)})}),ce.onEffects(e=>kt.open(e)),ce.onHelp(()=>_e()),ce.onTutorial(e=>xt(e));const qe=e=>{(e.ctrlKey||e.metaKey)&&!e.shiftKey&&!e.altKey&&e.key.toLowerCase()==="s"&&c()&&(e.preventDefault(),ze())};document.addEventListener("keydown",qe),s(()=>document.removeEventListener("keydown",qe));const X=p.querySelector(".dm-plugin-banner-name");s(M.effect(()=>{const e=zt(h,a.title.value,d);if(!c()||(document.title=`${e} - Domma CMS`,!X))return;const t=X.lastChild;t&&t.nodeType===3&&X.querySelector(".dm-plugin-banner-sep")?t.textContent=e:X.textContent=`Pages \u203A ${e}`})),j(o,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),j(o,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>_e()}),h&&j(o,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>window.open(a.urlPath.peek()||d,"_blank","noopener")});const he=j(o,{id:"page-editor-clone",icon:"copy",title:"Clone page",onClick:()=>{if(!h||n.saving.peek()||!c())return;const e=D(),t=we({...e,urlPath:d});if(t.length){E.toast(t[0].text,{type:"warning"});return}const f=At({page:m,frontmatter:{...K(se()),adminTags:a.adminTags.peek()},body:e.body,source:d,pages:P,onCloned:y=>{c()&&(u.cloneTarget=`/pages/edit${y}`,R.navigate(u.cloneTarget))}});s(()=>f.close())}});he&&(he.disabled=!h,h||(he.title="Save the page before cloning it")),j(o,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{Se=Wt(Me)}}),s(Ke(je,{position:"bottom"})),Domma.icons.scan();let He=null;try{He=S.get(Y)}catch{}const B=Kt(He);if(B&&(me(),V(B.state)!==n.base.peek())){const e=B.at?` (${ee(B.at)})`:"",t=jt(B,n.base.peek())?" The saved page has changed since - restoring puts your version back over it (the saved one stays in History).":"";await E.confirm(`You left unsaved changes to this page${e}. Restore them?${t}`)&&c()&&Be(B.state)}}};function ta(o,i,l){o.replaceChildren(...String(i).split(`
|
|
94
|
+
`).map((s,r)=>{const v=document.createElement("span");v.className="editor-line-number-row";const u=document.createElement("span");u.className="fold-toggle fold-toggle--empty";const p=document.createElement("span");return p.className="editor-line-num",p.textContent=String(r+1),v.append(u,p),v})),o.scrollTop=l.scrollTop}function aa(o,i,l){if(!o||!i)return;const s=15,r=85,v=d=>Math.min(r,Math.max(s,d));let u=v(parseFloat(q().splitRatio)||50);const p=d=>{o.style.setProperty("--dm-editor-split",u+"%"),i.setAttribute("aria-valuenow",String(Math.round(u))),d&&ae("splitRatio",u)};p(!1);const c=d=>{const h=o.getBoundingClientRect();h.width&&(u=v((d.clientX-h.left)/h.width*100)),p(!1)},C=()=>{document.removeEventListener("pointermove",c),document.removeEventListener("pointerup",C),o.classList.remove("is-resizing"),i.classList.remove("is-dragging"),p(!0)};l(C),i.addEventListener("pointerdown",d=>{window.matchMedia("(max-width: 768px)").matches||(d.preventDefault(),o.classList.add("is-resizing"),i.classList.add("is-dragging"),document.addEventListener("pointermove",c),document.addEventListener("pointerup",C))}),i.addEventListener("dblclick",()=>{u=50,p(!0)}),i.addEventListener("keydown",d=>{const h=d.shiftKey?10:2;let b=u;if(d.key==="ArrowLeft")b=u-h;else if(d.key==="ArrowRight")b=u+h;else if(d.key==="Home")b=s;else if(d.key==="End")b=r;else if(d.key==="Enter"||d.key===" ")b=50;else return;d.preventDefault(),u=v(b),p(!0)})}async function sa(o){const i=o.selectionStart,l=o.selectionEnd,s=await Pt({title:"Upload or insert an image"});if(!s||!o.isConnected)return;let r=s.split("/").pop().split("?")[0];try{r=decodeURIComponent(r)}catch{}const v=r.replace(/[\\[\]]/g,"\\$&"),u=s.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");o.setSelectionRange(i,l),wt(o,``),o.dispatchEvent(new Event("input",{bubbles:!0}))}function oa(o,i,l){const s=Object.entries(i||{});return o?(o.replaceChildren(...s.map(([r,v])=>new Option(v?.label||r,r))),s.some(([r])=>r===l)?l:s[0]?.[0]||l):l}async function na(o,i){if(!o)return;let l=[];try{const c=await g.get("/collections/roles/entries?limit=100");l=Array.isArray(c)?c:c?.entries||[]}catch{}const s=l.map(c=>({name:c.data?.name,label:c.data?.label||c.data?.name,level:c.data?.level??99})).filter(c=>c.name&&c.level!==0).sort((c,C)=>C.level-c.level),r=(c,C)=>Object.assign(document.createElement("option"),{value:c,textContent:C}),v=()=>{typeof i=="string"&&i&&![...o.options].some(c=>c.value===i)&&o.append(r(i,`${i} (custom)`))};if(!s.length)return v();const u=document.createElement("optgroup");u.label="Role and above",s.forEach(c=>u.append(r(c.name,`${c.label} and above`)));const p=document.createElement("optgroup");p.label="Role only",s.forEach(c=>p.append(r(`=${c.name}`,`${c.label} only`))),o.replaceChildren(r("public","Public - everyone"),u,p,r("private","Private - super-admin only")),v()}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domma-cms",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "server/server.js",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"@fastify/rate-limit": "^10.3.0",
|
|
85
85
|
"@fastify/static": "9.1.1",
|
|
86
86
|
"bcryptjs": "^3.0.3",
|
|
87
|
-
"domma-js": "0.
|
|
87
|
+
"domma-js": "0.53.0",
|
|
88
88
|
"dotenv": "^17.2.3",
|
|
89
89
|
"fastify": "5.8.5",
|
|
90
90
|
"gray-matter": "^4.0.3",
|
|
@@ -28,6 +28,8 @@ const CARET_ATTR = 'data-dm-font-caret';
|
|
|
28
28
|
* @param {object} editor - an `E.editor(..., {mode: 'rich'})` instance
|
|
29
29
|
* @returns {{destroy: Function}|null} null where the editor or E.dropdown is absent
|
|
30
30
|
*/
|
|
31
|
+
const attachSmoothCaret = (await import('/admin/js/lib/smooth-caret.js').catch(() => ({}))).attachSmoothCaret;
|
|
32
|
+
|
|
31
33
|
export function installFontControls(editor) {
|
|
32
34
|
const content = editor?._editorEl;
|
|
33
35
|
const toolbar = editor?._toolbarEl;
|
|
@@ -320,8 +322,10 @@ export function installFontControls(editor) {
|
|
|
320
322
|
};
|
|
321
323
|
window.addEventListener('keydown', onEscape, true);
|
|
322
324
|
|
|
325
|
+
const smoothCaret = attachSmoothCaret?.(content);
|
|
323
326
|
return {
|
|
324
327
|
destroy() {
|
|
328
|
+
smoothCaret?.destroy();
|
|
325
329
|
window.removeEventListener('keydown', onEscape, true);
|
|
326
330
|
scope.removeEventListener('input', tidy, true);
|
|
327
331
|
for (const menu of menus) {
|
package/public/css/search.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.site-search-trigger{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px 8px;border-radius:var(--dm-radius, 6px);color:inherit;opacity:.75;transition:opacity .15s,background .15s;font-size:var(--dm-font-size-sm, 14px)}.site-search-trigger:hover{opacity:1;background:var(--dm-hover-bg, rgba(128, 128, 128, .14))}.site-search-trigger svg,.site-search-trigger span[data-icon]{width:18px;height:18px}.site-search-shortcut-hint{display:inline-block;font-size:11px;line-height:1;padding:2px 5px;border-radius:4px;border:1px solid var(--dm-border, rgba(0, 0, 0, .15));color:var(--dm-text-muted, #888);margin-left:4px;vertical-align:middle;font-family:var(--dm-font-mono, monospace)}.site-search-overlay{position:fixed;inset:0;z-index:10000;background:#00000073;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;animation:ss-overlay-in .15s ease}@keyframes ss-overlay-in{0%{opacity:0}to{opacity:1}}.site-search-panel{width:100%;max-width:600px;margin:0 16px;border-radius:var(--dm-radius-lg, 10px);background:#1e2030;color:#e8eaf0;border:1px solid rgba(255,255,255,.1);box-shadow:0 24px 64px #0009;overflow:hidden;animation:ss-panel-in .15s ease}@keyframes ss-panel-in{0%{transform:translateY(-12px);opacity:0}to{transform:translateY(0);opacity:1}}.site-search-header{display:flex;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,.08);gap:8px}.site-search-header span[data-icon],.site-search-header svg{width:18px;height:18px;flex-shrink:0;opacity:.45;color:#e8eaf0}.site-search-input{flex:1;border:none;outline:none;background:transparent;font-size:var(--dm-font-size-lg, 16px);color:#e8eaf0;font-family:var(--dm-font-sans, sans-serif);padding:0}.site-search-input::placeholder{color:#e8eaf066;opacity:1}.site-search-close-btn{display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid rgba(255,255,255,.15);cursor:pointer;color:#e8eaf080;border-radius:var(--dm-radius, 6px);padding:4px 8px;font-size:12px;font-family:var(--dm-font-mono, monospace);transition:color .15s,border-color .15s;flex-shrink:0}.site-search-close-btn:hover{color:#e8eaf0;border-color:#ffffff4d}.site-search-results{max-height:60vh;overflow-y:auto;padding:8px 0}.site-search-result{display:block;padding:10px 16px;text-decoration:none;color:inherit;border-left:3px solid transparent;transition:background .1s,border-color .1s;cursor:pointer}.site-search-result:hover,.site-search-result.active{background:#ffffff0f;border-left-color:var(--dm-primary, #5b8cff)}.site-search-result-title{font-weight:600;font-size:var(--dm-font-size-sm, 14px);margin-bottom:2px;color:#e8eaf0}.site-search-result-snippet{font-size:12px;color:#e8eaf08c;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.site-search-result-snippet mark{background:#5b8cff40;color:#e8eaf0;border-radius:2px;padding:0 1px}.site-search-loading,.site-search-empty{padding:24px 16px;text-align:center;color:#e8eaf073;font-size:var(--dm-font-size-sm, 14px)}.site-search-loading-dots{display:inline-flex;gap:4px}.site-search-loading-dots span{width:6px;height:6px;border-radius:50%;background:#e8eaf066;animation:ss-dot-pulse 1.2s ease-in-out infinite}.site-search-loading-dots span:nth-child(2){animation-delay:.2s}.site-search-loading-dots span:nth-child(3){animation-delay:.4s}@keyframes ss-dot-pulse{0%,80%,to{transform:scale(.6);opacity:.4}40%{transform:scale(1);opacity:1}}.site-search-results:not(:empty){border-top:1px solid rgba(255,255,255,.06)}.site-search-footer{padding:6px 16px;border-top:1px solid rgba(255,255,255,.06);display:flex;gap:12px;font-size:11px;color:#e8eaf059}.site-search-footer kbd{display:inline-block;padding:1px 4px;border-radius:3px;border:1px solid rgba(255,255,255,.15);font-family:var(--dm-font-mono, monospace);font-size:10px}@media(max-width:640px){.site-search-overlay{padding-top:5vh;align-items:flex-start}.site-search-panel{margin:0 8px;border-radius:var(--dm-radius, 6px)}.site-search-results{max-height:70vh}.site-search-shortcut-hint{display:none}}.site-search-floating-trigger{position:fixed;z-index:9999;width:52px;height:52px;border-radius:50%;border:1px solid var(--dm-border, rgba(0, 0, 0, .12));cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px;background:var(--dm-surface, #fff);color:var(--dm-text, #111);box-shadow:0 4px 16px #00000024;transition:background .15s,color .15s,border-color .15s,transform .15s,box-shadow .15s;outline:none;white-space:nowrap}.site-search-floating-trigger:hover{background:var(--dm-primary, #5b8cff);color:#fff;border-color:var(--dm-primary, #5b8cff);box-shadow:0 6px 20px #00000038;transform:scale(1.05)}.site-search-floating-trigger:active{transform:scale(.97)}.site-search-floating-trigger svg,.site-search-floating-trigger [data-icon]{width:var(--ss-icon-glyph, 20px);height:var(--ss-icon-glyph, 20px);flex-shrink:0;pointer-events:none}.site-search-floating-trigger--pill{width:auto;height:44px;border-radius:999px;padding:0 18px 0 14px}.site-search-floating-label{font-size:.875rem;font-weight:500;letter-spacing:.01em;pointer-events:none}
|
|
1
|
+
.site-search-trigger{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px 8px;border-radius:var(--dm-radius, 6px);color:inherit;opacity:.75;transition:opacity .15s,background .15s;font-size:var(--dm-font-size-sm, 14px)}.site-search-trigger:hover{opacity:1;background:var(--dm-hover-bg, rgba(128, 128, 128, .14))}.site-search-trigger svg,.site-search-trigger span[data-icon]{width:18px;height:18px}.site-search-label{margin-left:6px}.site-search-shortcut-hint{display:inline-block;font-size:11px;line-height:1;padding:2px 5px;border-radius:4px;border:1px solid var(--dm-border, rgba(0, 0, 0, .15));color:var(--dm-text-muted, #888);margin-left:4px;vertical-align:middle;font-family:var(--dm-font-mono, monospace)}.site-search-overlay{position:fixed;inset:0;z-index:10000;background:#00000073;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;animation:ss-overlay-in .15s ease}@keyframes ss-overlay-in{0%{opacity:0}to{opacity:1}}.site-search-panel{width:100%;max-width:600px;margin:0 16px;border-radius:var(--dm-radius-lg, 10px);background:#1e2030;color:#e8eaf0;border:1px solid rgba(255,255,255,.1);box-shadow:0 24px 64px #0009;overflow:hidden;animation:ss-panel-in .15s ease}@keyframes ss-panel-in{0%{transform:translateY(-12px);opacity:0}to{transform:translateY(0);opacity:1}}.site-search-header{display:flex;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,.08);gap:8px}.site-search-header span[data-icon],.site-search-header svg{width:18px;height:18px;flex-shrink:0;opacity:.45;color:#e8eaf0}.site-search-input{flex:1;border:none;outline:none;background:transparent;font-size:var(--dm-font-size-lg, 16px);color:#e8eaf0;font-family:var(--dm-font-sans, sans-serif);padding:0}.site-search-input::placeholder{color:#e8eaf066;opacity:1}.site-search-close-btn{display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid rgba(255,255,255,.15);cursor:pointer;color:#e8eaf080;border-radius:var(--dm-radius, 6px);padding:4px 8px;font-size:12px;font-family:var(--dm-font-mono, monospace);transition:color .15s,border-color .15s;flex-shrink:0}.site-search-close-btn:hover{color:#e8eaf0;border-color:#ffffff4d}.site-search-results{max-height:60vh;overflow-y:auto;padding:8px 0}.site-search-result{display:block;padding:10px 16px;text-decoration:none;color:inherit;border-left:3px solid transparent;transition:background .1s,border-color .1s;cursor:pointer}.site-search-result:hover,.site-search-result.active{background:#ffffff0f;border-left-color:var(--dm-primary, #5b8cff)}.site-search-result-title{font-weight:600;font-size:var(--dm-font-size-sm, 14px);margin-bottom:2px;color:#e8eaf0}.site-search-result-snippet{font-size:12px;color:#e8eaf08c;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.site-search-result-snippet mark{background:#5b8cff40;color:#e8eaf0;border-radius:2px;padding:0 1px}.site-search-loading,.site-search-empty{padding:24px 16px;text-align:center;color:#e8eaf073;font-size:var(--dm-font-size-sm, 14px)}.site-search-loading-dots{display:inline-flex;gap:4px}.site-search-loading-dots span{width:6px;height:6px;border-radius:50%;background:#e8eaf066;animation:ss-dot-pulse 1.2s ease-in-out infinite}.site-search-loading-dots span:nth-child(2){animation-delay:.2s}.site-search-loading-dots span:nth-child(3){animation-delay:.4s}@keyframes ss-dot-pulse{0%,80%,to{transform:scale(.6);opacity:.4}40%{transform:scale(1);opacity:1}}.site-search-results:not(:empty){border-top:1px solid rgba(255,255,255,.06)}.site-search-footer{padding:6px 16px;border-top:1px solid rgba(255,255,255,.06);display:flex;gap:12px;font-size:11px;color:#e8eaf059}.site-search-footer kbd{display:inline-block;padding:1px 4px;border-radius:3px;border:1px solid rgba(255,255,255,.15);font-family:var(--dm-font-mono, monospace);font-size:10px}@media(max-width:640px){.site-search-overlay{padding-top:5vh;align-items:flex-start}.site-search-panel{margin:0 8px;border-radius:var(--dm-radius, 6px)}.site-search-results{max-height:70vh}.site-search-shortcut-hint{display:none}}.site-search-floating-trigger{position:fixed;z-index:9999;width:52px;height:52px;border-radius:50%;border:1px solid var(--dm-border, rgba(0, 0, 0, .12));cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px;background:var(--dm-surface, #fff);color:var(--dm-text, #111);box-shadow:0 4px 16px #00000024;transition:background .15s,color .15s,border-color .15s,transform .15s,box-shadow .15s;outline:none;white-space:nowrap}.site-search-floating-trigger:hover{background:var(--dm-primary, #5b8cff);color:#fff;border-color:var(--dm-primary, #5b8cff);box-shadow:0 6px 20px #00000038;transform:scale(1.05)}.site-search-floating-trigger:active{transform:scale(.97)}.site-search-floating-trigger svg,.site-search-floating-trigger [data-icon]{width:var(--ss-icon-glyph, 20px);height:var(--ss-icon-glyph, 20px);flex-shrink:0;pointer-events:none}.site-search-floating-trigger--pill{width:auto;height:44px;border-radius:999px;padding:0 18px 0 14px}.site-search-floating-label{font-size:.875rem;font-weight:500;letter-spacing:.01em;pointer-events:none}
|
package/public/js/forms.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).replace(/<[^>]+>/g,""))}function A(n){return String(n).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function q(n,o){let t=!1;n.addEventListener("dm-form-end",function(e){const i=e.detail&&e.detail.validation;if(i&&!i.valid){markInvalidFields(n,i.missing),showValidationPopup(i);return}t||(t=!0,n.classList.add("fb-form-loading"),Promise.resolve(o(e.detail&&e.detail.values||{})).catch(function(){}).finally(function(){t=!1,n.classList.remove("fb-form-loading")}))})}function C(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=t==="success"?"fb-form-success":"fb-form-error",i.textContent=o,n.appendChild(i)}function B(n,o){if(n._formLogicRuntime=o,n._formLogicObserver&&(n._formLogicObserver.disconnect(),n._formLogicObserver=null),!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const i of e)for(const r of i.removedNodes)if(r===n||r.nodeType===1&&r.contains&&r.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function $(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function R(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const i=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const s={type:r,label:e.label||e.name,required:$(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(s.minLength=e.minLength),e.maxLength!==void 0&&(s.maxLength=e.maxLength),e.min!==void 0&&(s.min=e.min),e.max!==void 0&&(s.max=e.max),i&&(e.variant&&(s.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(s.multiple=!0),e.density&&(s.density=e.density),e.columns&&(s.columns=e.columns),e.accent&&(s.accent=e.accent),e.accentStyle&&(s.accentStyle=e.accentStyle),e.glow&&(s.glow=!0),e.glowColour&&(s.glowColour=e.glowColour),e.shadow&&(s.shadow=e.shadow),e.shadowColour&&(s.shadowColour=e.shadowColour)),t[e.name]=s}),t}function G(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function O(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}const z="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function P(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const i=document.createElement("strong");i.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=z+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const s=c=>{c.key==="Escape"&&a()};function a(){document.removeEventListener("keydown",s),o.remove()}return r.addEventListener("click",a),o.addEventListener("click",c=>{c.target===o&&a()}),document.addEventListener("keydown",s),document.body.appendChild(o),{body:l,close:a}}function Q(n){const{body:o,close:t}=P("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(i);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(s=>{const a=document.createElement("button");a.type="button",a.title=s,a.dataset.iconName=s,a.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const c=document.createElement("span");return c.setAttribute("data-icon",s),c.setAttribute("data-icon-size","18"),a.appendChild(c),a.addEventListener("mouseenter",()=>{a.style.borderColor="var(--dm-border)"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="transparent"}),a.addEventListener("click",()=>{t(),n(s)}),i.appendChild(a),a});if(!r.length){const s=document.createElement("p");s.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(s)}window.I?.scan?.(i),e.addEventListener("input",()=>{const s=e.value.trim().toLowerCase();l.forEach(a=>{a.style.display=!s||a.dataset.iconName.includes(s)?"":"none"})}),e.focus()}async function X(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const i=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(i.ok){const{token:r}=await i.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function Z(n){const{body:o,close:t}=P("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),X().then(({files:i,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(s=>{const a=document.createElement("button");a.type="button",a.title=s.name||s.url,a.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const c=document.createElement("img");c.src=s.url,c.alt=s.name||"",c.loading="lazy",c.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const m=document.createElement("span");m.textContent=s.name||s.url,m.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",a.appendChild(c),a.appendChild(m),a.addEventListener("click",()=>{t(),n(s.url)}),l.appendChild(a)}),o.appendChild(l)})}function D(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function M(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function V(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=z,o}function ee(n){if(!window.I||typeof I.list!="function")return;const o=M(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=n.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>Q(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}function te(n){const o=M(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=n.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>Z(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?ee(i):te(i))})}function N(n,o){const t=document.createElement("div");t.className="fb-form-honeypot",t.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=n.querySelector('[name="website"]')?"_website":"website",t.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",t.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),t.appendChild(i),n.appendChild(t)}function W(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const s=e[i];if(s)t.insertBefore(l,s);else{const a=t.querySelector('[type="submit"]');a?t.insertBefore(l,a):t.appendChild(l)}}else r.type!=="page-break"&&i++})}function L(n,o){!n||!o||n.querySelectorAll('input[type="file"]').forEach(function(t){t.name&&t.files&&t.files.length&&o.set(t.name,Array.from(t.files))})}function x(n,o,t,e,i,r){const l=i||e,s=l.querySelector(".fb-form-honeypot"),a=s?.querySelector('input[type="text"]')?.value||"",c=s?.querySelector('[name="_t"]')?.value||"",m=Object.assign({},o);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName];const d=new Map(r||[]);L(l,d);const u=d.size>0;let p,b;if(u){const h=new FormData;for(const[g,v]of Object.entries(m))v!=null&&(d.has(g)||h.append(g,typeof v=="object"?JSON.stringify(v):String(v)));for(const[g,v]of d)for(const w of v)h.append(g,w,w.name);h.append("_hp",a),h.append("_t",c),p=h,b={}}else{const h=Object.assign({},m,{_hp:a,_t:c});p=JSON.stringify(h),b={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:b,body:p}).then(h=>h.json().then(g=>({ok:h.ok,body:g}))).then(h=>{h.ok&&h.body.ok?(e.textContent="",C(e,h.body.message||t.successMessage||"Thank you.","success")):C(e,h.body.error||"Something went wrong.","error")}).catch(()=>{C(e,"Unable to submit. Please check your connection.","error")})}function ne(n,o,t,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(a){const c=document.createElement("div");c.className="form-group",c.style.marginBottom="1.25rem",a.name&&(c.dataset.field=a.name);const m=document.createElement("label");if(m.className="form-label",m.textContent=a.label||a.name,a.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;a.type==="textarea"?(d=document.createElement("textarea"),d.rows=a.formConfig?.rows||4,d.className="form-input"):a.type==="select"?(d=document.createElement("select"),d.className="form-input",(a.options||[]).forEach(function(u){const p=document.createElement("option");p.value=typeof u=="string"?u:u.value??"",p.textContent=typeof u=="string"?u:u.label||p.value,d.appendChild(p)})):(d=document.createElement("input"),d.type=a.type==="icon"||a.type==="image"?"text":a.type||"text",d.className="form-input",a.placeholder&&(d.placeholder=a.placeholder),a.type==="file"&&(a.file?.accept&&(d.accept=a.file.accept),a.multiple&&(d.multiple=!0))),d.name=a.name,d.required=a.required||!1,c.appendChild(m),c.appendChild(d),r.appendChild(c)}),t.honeypot&&N(r);const l=document.createElement("button");if(l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",K(t,"stacked").length||H(t)){const a=document.createElement("div");a.className="form-group form-buttons",a.appendChild(l),r.appendChild(a)}else r.appendChild(l);if(r.addEventListener("submit",function(a){a.preventDefault();const c={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(c[m.name]=d.value)}),window.FormLogicEngine&&i){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(p){if(m.evaluateFieldVisibility(p,c)==="hidden"){delete c[p.name];return}const h=m.evaluateFieldRequirement(p,c),g=c[p.name];h&&(!g||!String(g).trim())&&d.push(p.label||p.name);const v=m.validateField(p,g||"",c);v.length&&u.push(v[0].message)}),d.length||u.length){const p=[];d.length&&p.push("Required: "+d.join(", ")),u.length&&p.push(u.join("; ")),C(n,p.join(". "),"error");return}}if(n.dataset.triggerBlocked==="true"){const m=n._formLogicRuntime,d=m&&m.submitBlock?m.submitBlock().reasons:[];C(n,d.join(" ")||"This form cannot be submitted yet.","error");return}n.classList.add("fb-form-loading"),l.disabled=!0,x(e,c,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),_(r,t,"stacked"),T(r,t,o),enhancePickerFields(n,o),q(n,function(a){return x(e,a,t,n,r)}),window.FormLogicEngine&&i&&F(o)){const a=new window.FormLogicEngine.FormLogicRuntime(i,n);a.init(),n._formLogicRuntime=a}}function oe(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],i=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(s=>s.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const s=Number(i.columns)===3?3:2,a=i.layout||"grid";if(l&&Domma.forms.wizard){const c=J(e,t.title),m=c.map(f=>f.fields),d=c.map(function(f){return{title:f.title,description:f.description,fields:R(f.fields,s)}});let u=0,p=null,b=null;const h=Date.now(),g=new Map,v=function(f){const y=window.FormLogicEngine;if(!y||!y.validateFields)return;const k=y.validateFields(r,m[u]||[]);k.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(r,k.missing),showValidationPopup(k))},w=function(){const f=m[u]||e;if(U(r,i),T(r,i,f),O(r,f),enhancePickerFields(r,f),f.some(y=>y.type==="spacer")&&W(r,f),i.honeypot){const y=r.querySelector("form");y&&N(y,h)}window.FormLogicEngine&&F(e)&&(p&&p.destroy(),p=new window.FormLogicEngine.FormLogicRuntime(t,r,{baseValues:b&&b.getStepData?b.getStepData():{}}),p.init(),B(r,p)),r.querySelectorAll(".wizard-next, .wizard-submit").forEach(y=>y.addEventListener("click",v,!0))};b=Domma.forms.wizard(r,{schema:{steps:d},layout:a,columns:s,finishText:i.submitText||"Finish",onStepChange:function(f){L(r,g),u=f,setTimeout(w,0)},onSubmit:function(f){return L(r,g),x(o,f,i,r,null,g)}}),q(r,function(f){return L(r,g),x(o,f,i,r,null,g)}),r.addEventListener("dm-form-trigger",function(f){if(!f.detail||f.detail.type!=="goto-step"||!b||!b.goToStep)return;const y=Number(f.detail.action.step);!isFinite(y)||y<0||y>=d.length||y!==u&&b.goToStep(y)}),Promise.resolve(b).then(w)}else if(Domma.forms.render){const c=R(e,s),m=G(e);q(r,function(u){return x(o,u,i,r,null)});const d=Domma.forms.render(r,c,m,{submitText:i.submitText||"Submit",layout:a,columns:s,onSubmit:function(u){return x(o,u,i,r,null)}});Promise.resolve(d).then(function(){if(_(r,i,a),T(r,i,e),O(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&F(e)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),B(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),i.honeypot){const u=r.querySelector("form");u&&N(u)}})}}else ne(r,e.filter(s=>s.type!=="page-break"&&s.type!=="spacer"),i,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
|
|
1
|
+
import{installSmoothCarets as J}from"/public/js/smooth-caret.js";import{buildWizardSteps as U}from"/public/js/form-steps.mjs";import{applyFormClasses as T,applySubmitButtons as _,applyWizardButtons as H,resolveSecondaryButton as K,submitWrapperClasses as Y}from"/public/js/form-submit.mjs";J(document);const j=document.querySelectorAll("[data-form]");j.length&&j.forEach(re);function F(n){return(n||[]).some(o=>o.logic||Array.isArray(o.triggers)&&o.triggers.length)}function $(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let i=t;for(;i.parentNode&&i.parentNode!==e;)i=i.parentNode;return i}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const i=$(n,e.name);i&&(i.classList.add("fb-field-invalid"),t||(t=i))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+A(e.label)+"</strong> is required.").concat((n.errors||[]).map(A)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
|
|
2
|
+
`).replace(/<[^>]+>/g,""))}function A(n){return String(n).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function q(n,o){let t=!1;n.addEventListener("dm-form-end",function(e){const i=e.detail&&e.detail.validation;if(i&&!i.valid){markInvalidFields(n,i.missing),showValidationPopup(i);return}t||(t=!0,n.classList.add("fb-form-loading"),Promise.resolve(o(e.detail&&e.detail.values||{})).catch(function(){}).finally(function(){t=!1,n.classList.remove("fb-form-loading")}))})}function C(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=t==="success"?"fb-form-success":"fb-form-error",i.textContent=o,n.appendChild(i)}function B(n,o){if(n._formLogicRuntime=o,n._formLogicObserver&&(n._formLogicObserver.disconnect(),n._formLogicObserver=null),!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const i of e)for(const r of i.removedNodes)if(r===n||r.nodeType===1&&r.contains&&r.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function G(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function R(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const i=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const s={type:r,label:e.label||e.name,required:G(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(s.minLength=e.minLength),e.maxLength!==void 0&&(s.maxLength=e.maxLength),e.min!==void 0&&(s.min=e.min),e.max!==void 0&&(s.max=e.max),i&&(e.variant&&(s.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(s.multiple=!0),e.density&&(s.density=e.density),e.columns&&(s.columns=e.columns),e.accent&&(s.accent=e.accent),e.accentStyle&&(s.accentStyle=e.accentStyle),e.glow&&(s.glow=!0),e.glowColour&&(s.glowColour=e.glowColour),e.shadow&&(s.shadow=e.shadow),e.shadowColour&&(s.shadowColour=e.shadowColour)),t[e.name]=s}),t}function Q(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function O(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}const z="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function P(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const i=document.createElement("strong");i.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=z+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const s=c=>{c.key==="Escape"&&a()};function a(){document.removeEventListener("keydown",s),o.remove()}return r.addEventListener("click",a),o.addEventListener("click",c=>{c.target===o&&a()}),document.addEventListener("keydown",s),document.body.appendChild(o),{body:l,close:a}}function X(n){const{body:o,close:t}=P("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(i);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(s=>{const a=document.createElement("button");a.type="button",a.title=s,a.dataset.iconName=s,a.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const c=document.createElement("span");return c.setAttribute("data-icon",s),c.setAttribute("data-icon-size","18"),a.appendChild(c),a.addEventListener("mouseenter",()=>{a.style.borderColor="var(--dm-border)"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="transparent"}),a.addEventListener("click",()=>{t(),n(s)}),i.appendChild(a),a});if(!r.length){const s=document.createElement("p");s.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(s)}window.I?.scan?.(i),e.addEventListener("input",()=>{const s=e.value.trim().toLowerCase();l.forEach(a=>{a.style.display=!s||a.dataset.iconName.includes(s)?"":"none"})}),e.focus()}async function Z(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const i=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(i.ok){const{token:r}=await i.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function ee(n){const{body:o,close:t}=P("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),Z().then(({files:i,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(s=>{const a=document.createElement("button");a.type="button",a.title=s.name||s.url,a.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const c=document.createElement("img");c.src=s.url,c.alt=s.name||"",c.loading="lazy",c.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const m=document.createElement("span");m.textContent=s.name||s.url,m.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",a.appendChild(c),a.appendChild(m),a.addEventListener("click",()=>{t(),n(s.url)}),l.appendChild(a)}),o.appendChild(l)})}function D(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function M(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function V(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=z,o}function te(n){if(!window.I||typeof I.list!="function")return;const o=M(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=n.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>X(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}function ne(n){const o=M(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=n.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>ee(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?te(i):ne(i))})}function N(n,o){const t=document.createElement("div");t.className="fb-form-honeypot",t.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=n.querySelector('[name="website"]')?"_website":"website",t.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",t.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),t.appendChild(i),n.appendChild(t)}function W(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const s=e[i];if(s)t.insertBefore(l,s);else{const a=t.querySelector('[type="submit"]');a?t.insertBefore(l,a):t.appendChild(l)}}else r.type!=="page-break"&&i++})}function L(n,o){!n||!o||n.querySelectorAll('input[type="file"]').forEach(function(t){t.name&&t.files&&t.files.length&&o.set(t.name,Array.from(t.files))})}function x(n,o,t,e,i,r){const l=i||e,s=l.querySelector(".fb-form-honeypot"),a=s?.querySelector('input[type="text"]')?.value||"",c=s?.querySelector('[name="_t"]')?.value||"",m=Object.assign({},o);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName];const d=new Map(r||[]);L(l,d);const u=d.size>0;let p,b;if(u){const h=new FormData;for(const[g,v]of Object.entries(m))v!=null&&(d.has(g)||h.append(g,typeof v=="object"?JSON.stringify(v):String(v)));for(const[g,v]of d)for(const w of v)h.append(g,w,w.name);h.append("_hp",a),h.append("_t",c),p=h,b={}}else{const h=Object.assign({},m,{_hp:a,_t:c});p=JSON.stringify(h),b={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:b,body:p}).then(h=>h.json().then(g=>({ok:h.ok,body:g}))).then(h=>{h.ok&&h.body.ok?(e.textContent="",C(e,h.body.message||t.successMessage||"Thank you.","success")):C(e,h.body.error||"Something went wrong.","error")}).catch(()=>{C(e,"Unable to submit. Please check your connection.","error")})}function oe(n,o,t,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(a){const c=document.createElement("div");c.className="form-group",c.style.marginBottom="1.25rem",a.name&&(c.dataset.field=a.name);const m=document.createElement("label");if(m.className="form-label",m.textContent=a.label||a.name,a.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;a.type==="textarea"?(d=document.createElement("textarea"),d.rows=a.formConfig?.rows||4,d.className="form-input"):a.type==="select"?(d=document.createElement("select"),d.className="form-input",(a.options||[]).forEach(function(u){const p=document.createElement("option");p.value=typeof u=="string"?u:u.value??"",p.textContent=typeof u=="string"?u:u.label||p.value,d.appendChild(p)})):(d=document.createElement("input"),d.type=a.type==="icon"||a.type==="image"?"text":a.type||"text",d.className="form-input",a.placeholder&&(d.placeholder=a.placeholder),a.type==="file"&&(a.file?.accept&&(d.accept=a.file.accept),a.multiple&&(d.multiple=!0))),d.name=a.name,d.required=a.required||!1,c.appendChild(m),c.appendChild(d),r.appendChild(c)}),t.honeypot&&N(r);const l=document.createElement("button");if(l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",Y(t,"stacked").length||K(t)){const a=document.createElement("div");a.className="form-group form-buttons",a.appendChild(l),r.appendChild(a)}else r.appendChild(l);if(r.addEventListener("submit",function(a){a.preventDefault();const c={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(c[m.name]=d.value)}),window.FormLogicEngine&&i){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(p){if(m.evaluateFieldVisibility(p,c)==="hidden"){delete c[p.name];return}const h=m.evaluateFieldRequirement(p,c),g=c[p.name];h&&(!g||!String(g).trim())&&d.push(p.label||p.name);const v=m.validateField(p,g||"",c);v.length&&u.push(v[0].message)}),d.length||u.length){const p=[];d.length&&p.push("Required: "+d.join(", ")),u.length&&p.push(u.join("; ")),C(n,p.join(". "),"error");return}}if(n.dataset.triggerBlocked==="true"){const m=n._formLogicRuntime,d=m&&m.submitBlock?m.submitBlock().reasons:[];C(n,d.join(" ")||"This form cannot be submitted yet.","error");return}n.classList.add("fb-form-loading"),l.disabled=!0,x(e,c,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),_(r,t,"stacked"),T(r,t,o),enhancePickerFields(n,o),q(n,function(a){return x(e,a,t,n,r)}),window.FormLogicEngine&&i&&F(o)){const a=new window.FormLogicEngine.FormLogicRuntime(i,n);a.init(),n._formLogicRuntime=a}}function re(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],i=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(s=>s.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const s=Number(i.columns)===3?3:2,a=i.layout||"grid";if(l&&Domma.forms.wizard){const c=U(e,t.title),m=c.map(f=>f.fields),d=c.map(function(f){return{title:f.title,description:f.description,fields:R(f.fields,s)}});let u=0,p=null,b=null;const h=Date.now(),g=new Map,v=function(f){const y=window.FormLogicEngine;if(!y||!y.validateFields)return;const k=y.validateFields(r,m[u]||[]);k.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(r,k.missing),showValidationPopup(k))},w=function(){const f=m[u]||e;if(H(r,i),T(r,i,f),O(r,f),enhancePickerFields(r,f),f.some(y=>y.type==="spacer")&&W(r,f),i.honeypot){const y=r.querySelector("form");y&&N(y,h)}window.FormLogicEngine&&F(e)&&(p&&p.destroy(),p=new window.FormLogicEngine.FormLogicRuntime(t,r,{baseValues:b&&b.getStepData?b.getStepData():{}}),p.init(),B(r,p)),r.querySelectorAll(".wizard-next, .wizard-submit").forEach(y=>y.addEventListener("click",v,!0))};b=Domma.forms.wizard(r,{schema:{steps:d},layout:a,columns:s,finishText:i.submitText||"Finish",onStepChange:function(f){L(r,g),u=f,setTimeout(w,0)},onSubmit:function(f){return L(r,g),x(o,f,i,r,null,g)}}),q(r,function(f){return L(r,g),x(o,f,i,r,null,g)}),r.addEventListener("dm-form-trigger",function(f){if(!f.detail||f.detail.type!=="goto-step"||!b||!b.goToStep)return;const y=Number(f.detail.action.step);!isFinite(y)||y<0||y>=d.length||y!==u&&b.goToStep(y)}),Promise.resolve(b).then(w)}else if(Domma.forms.render){const c=R(e,s),m=Q(e);q(r,function(u){return x(o,u,i,r,null)});const d=Domma.forms.render(r,c,m,{submitText:i.submitText||"Submit",layout:a,columns:s,onSubmit:function(u){return x(o,u,i,r,null)}});Promise.resolve(d).then(function(){if(_(r,i,a),T(r,i,e),O(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&F(e)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),B(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),i.honeypot){const u=r.querySelector("form");u&&N(u)}})}}else oe(r,e.filter(s=>s.type!=="page-break"&&s.type!=="spacer"),i,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
|
package/public/js/search.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(){"use strict";var l=window.__CMS_SEARCH__||window.__SITE_SEARCH__||{},N=l.placeholder||"Search pages...",
|
|
1
|
+
(function(){"use strict";var l=window.__CMS_SEARCH__||window.__SITE_SEARCH__||{},N=l.placeholder||"Search pages...",x=l.debounceMs||300,D=l.displayMode||"navbar",C=l.triggerStyle||(l.iconOnly===!1?"icon-text":"icon"),h=C!=="icon-text",L=l.iconRadius!=null?l.iconRadius:26,b=l.iconSize!=null?l.iconSize:52,p=null,c=null,s=null,g=null,m=!1;function y(){var t=document.querySelector("#site-navbar, .navbar");if(t){var e=t.querySelector(".navbar-actions");if(!e){var r=t.querySelector(".navbar-container")||t;e=document.createElement("div"),e.className="navbar-actions",r.appendChild(e)}if(!e.querySelector(".site-search-trigger")){var a=/Mac|iPhone|iPad|iPod/.test(navigator.platform||navigator.userAgent),i=a?"\u2318K":"Ctrl+K",n=document.createElement("button");n.className="navbar-action-link site-search-trigger",n.setAttribute("aria-label","Search"),n.setAttribute("type","button");var o=document.createElement("span");if(o.setAttribute("data-icon","search"),n.appendChild(o),!h){var d=document.createElement("span");d.className="site-search-label",d.textContent="Search",n.appendChild(d)}var u=document.createElement("span");u.className="site-search-shortcut-hint",u.textContent=i,n.appendChild(u),e.insertBefore(n,e.firstChild),n.addEventListener("click",f),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(n)}}}function T(){if(document.querySelector("#site-navbar .navbar-actions, .navbar .navbar-actions")){y();return}var t=new MutationObserver(function(){var e=document.querySelector("#site-navbar, .navbar");e&&(t.disconnect(),y())});t.observe(document.body,{childList:!0,subtree:!0}),setTimeout(function(){t.disconnect(),y()},5e3)}function k(){var t=document.createElement("div");t.className="site-search-overlay",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-label","Site search");var e=document.createElement("div");e.className="site-search-panel",e.setAttribute("role","search");var r=document.createElement("div");r.className="site-search-header";var a=document.createElement("span");a.setAttribute("data-icon","search"),r.appendChild(a),c=document.createElement("input"),c.className="site-search-input",c.type="search",c.setAttribute("autocomplete","off"),c.setAttribute("autocorrect","off"),c.setAttribute("spellcheck","false"),c.setAttribute("aria-label","Search"),c.placeholder=N,r.appendChild(c);var i=document.createElement("button");i.className="site-search-close-btn",i.setAttribute("type","button"),i.setAttribute("aria-label","Close search"),i.textContent="Esc",r.appendChild(i),e.appendChild(r),s=document.createElement("div"),s.className="site-search-results",s.setAttribute("role","listbox"),s.setAttribute("aria-live","polite"),e.appendChild(s);var n=document.createElement("div");return n.className="site-search-footer",n.innerHTML="<span><kbd>\u2191</kbd><kbd>\u2193</kbd> navigate</span><span><kbd>\u21B5</kbd> open</span><span><kbd>Esc</kbd> close</span>",e.appendChild(n),t.appendChild(e),t.addEventListener("click",function(o){o.target===t&&v()}),i.addEventListener("click",v),c.addEventListener("input",function(){clearTimeout(g);var o=c.value.trim();if(!o){E();return}g=setTimeout(function(){M(o)},x)}),c.addEventListener("keydown",q),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(r),t}function f(){m||(m=!0,p=k(),document.body.appendChild(p),document.body.style.overflow="hidden",setTimeout(function(){c&&c.focus()},30))}function v(){m&&(m=!1,clearTimeout(g),p&&p.parentNode&&p.parentNode.removeChild(p),p=null,c=null,s=null,document.body.style.overflow="")}function M(t){s&&(R(),fetch("/api/search?q="+encodeURIComponent(t)).then(function(e){return e.json()}).then(function(e){_(e.results||[],t)}).catch(function(){E();var e=document.createElement("div");e.className="site-search-empty",e.textContent="Search unavailable. Please try again.",s.appendChild(e)}))}function R(){s&&(s.innerHTML='<div class="site-search-loading"><div class="site-search-loading-dots"><span></span><span></span><span></span></div></div>')}function E(){s&&(s.innerHTML="")}function _(t,e){if(s){if(s.innerHTML="",!t.length){var r=document.createElement("div");r.className="site-search-empty",r.textContent='No results found for "'+e+'"',s.appendChild(r);return}for(var a=document.createDocumentFragment(),i=0;i<t.length;i++){var n=t[i],o=document.createElement("a");o.className="site-search-result",o.href=n.url||"/",o.setAttribute("role","option"),o.setAttribute("tabindex","-1"),o.setAttribute("data-index",String(i));var d=document.createElement("div");if(d.className="site-search-result-title",S(d,n.title||"Untitled",e),o.appendChild(d),n.snippet){var u=document.createElement("div");u.className="site-search-result-snippet",S(u,n.snippet,e),o.appendChild(u)}o.addEventListener("click",v),a.appendChild(o)}s.appendChild(a)}}function S(t,e,r){if(!r){t.textContent=e;return}var a=r.trim().split(/\s+/).filter(Boolean);if(!a.length){t.textContent=e;return}var i;try{i=new RegExp("("+a.map(function(u){return u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("|")+")","gi")}catch{t.textContent=e;return}for(var n=e.split(i),o=0;o<n.length;o++){if(i.test(n[o])){var d=document.createElement("mark");d.textContent=n[o],t.appendChild(d)}else t.appendChild(document.createTextNode(n[o]));i.lastIndex=0}}function q(t){if(t.key==="Escape"){t.preventDefault(),v();return}if(s){var e=s.querySelectorAll(".site-search-result");if(e.length){for(var r=s.querySelector(".site-search-result.active"),a=-1,i=0;i<e.length;i++)if(e[i]===r){a=i;break}if(t.key==="ArrowDown")t.preventDefault(),A(e,a<e.length-1?a+1:0);else if(t.key==="ArrowUp")t.preventDefault(),A(e,a>0?a-1:e.length-1);else if(t.key==="Enter"&&r){t.preventDefault();var n=r.getAttribute("href");v(),window.location.href=n}}}}function A(t,e){for(var r=0;r<t.length;r++)t[r].classList.toggle("active",r===e);t[e]&&t[e].scrollIntoView({block:"nearest"})}document.addEventListener("keydown",function(t){if((t.metaKey||t.ctrlKey)&&t.key.toLowerCase()==="k"){var e=document.activeElement&&document.activeElement.tagName;if((e==="INPUT"||e==="TEXTAREA"||e==="SELECT")&&!m)return;t.preventDefault(),m?v():f()}});function H(t,e,r,a){var i=e==="left-center"||e==="bottom-left"||e==="top-left",n=e==="bottom-left"||e==="bottom-right",o=e==="top-left"||e==="top-right";Object.assign(t.style,{right:i?"auto":r+"px",left:i?r+"px":"auto",top:o?a+"px":n?"auto":"50vh",bottom:n?a+"px":"auto",transform:o||n?"none":"translateY(-50%)"})}function O(){if(!document.querySelector(".site-search-floating-trigger")){var t=l.position||"bottom-right",e=l.offsetX!=null?l.offsetX:32,r=l.offsetY!=null?l.offsetY:32,a=document.createElement("button");a.className="site-search-floating-trigger"+(h?"":" site-search-floating-trigger--pill"),a.setAttribute("type","button"),a.setAttribute("aria-label","Search");var i=document.createElement("span");if(i.setAttribute("data-icon","search"),a.appendChild(i),h)a.style.borderRadius=L+"px",a.style.width=b+"px",a.style.height=b+"px",a.style.setProperty("--ss-icon-glyph",Math.round(b*20/52)+"px");else{var n=document.createElement("span");n.className="site-search-floating-label",n.textContent="Search",a.appendChild(n)}H(a,t,e,r),document.body.appendChild(a),a.addEventListener("click",f),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(a)}}function w(){C!=="hidden"&&(D==="floating"?O():T())}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",w):w(),window.DommaSiteSearch={open:f,close:v,isAvailable:()=>!0}})();
|
package/public/js/site.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{decodeBase64Json as P}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as J,applyColour as X,applyPill as oe,applyFloat as ne,applyHighlight as R,applyItemHighlight as ae,itemHighlightAttrs as se,isCurrentItem as U,menuAlign as ie,applyClasses as O,cssClasses as W,applyEntrance as V}from"/public/js/menu-decor.mjs?v=20261014-menu-entrance";import{initFloatingMenus as re}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as G,markInvalidFields as K,showValidationPopup as Q}from"/public/js/forms.js?v=20261009-form-classes";import{buildWizardSteps as ce}from"/public/js/form-steps.mjs";import{applyFormClasses as Z,applySubmitButtons as le,applyWizardButtons as de}from"/public/js/form-submit.mjs";document.addEventListener("click",h=>{const c=h.target?.closest?.(".dm-banner__dismiss");c&&(h.preventDefault(),c.closest(".dm-banner")?.remove())}),$(()=>{const h=window.__CMS_NAV__||{},c=window.__CMS_SITE__||{};if(c.autoTheme?.enabled){let o=function(e){const a=(e||"07:00").split(":");return+a[0]*60+(+a[1]||0)},s=function(){const e=new Date,a=e.getHours()*60+e.getMinutes();return a>=o(n.dayStart)&&a<o(n.nightStart)?n.dayTheme:n.nightTheme},t=function(e){const a=n.apply&&n.apply[e]||{theme:e,custom:""};Domma.theme.set(a.theme);for(const d of[...document.body.classList])d.startsWith("dm-custom-")&&document.body.classList.remove(d);a.custom&&document.body.classList.add(a.custom)};const n=c.autoTheme;t(s()),setInterval(()=>t(s()),6e4)}const x=$("#site-navbar");if(x.length&&h.brand){let s=function(u,p=0){return Array.isArray(u)?u.filter(m=>!(m&&(m.type==="spacer"||m.type==="theme-switcher"))).filter(m=>!(m&&m.type==="separator"&&p===0)).map(m=>m&&m.type==="separator"?{divider:!0}:Array.isArray(m?.items)?{...m,items:s(m.items,p+1)}:m):u};const n={...h.brand},o=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let u="";n.logo?u+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(u+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(u+=`<span class="navbar-brand-text${o}">${n.text}</span>`),n.tagline&&(u+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=u}else o&&n.text&&(n.html=`<span class="navbar-brand-text${o}">${n.text}</span>`);const t=s(h.items||[]),e=h.position==="floating",a=h.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:n,items:t,variant:h.variant||"dark",position:e?"static":h.position||"sticky",collapsible:!0,appearOnHover:!!h.appearOnHover}),Domma.icons.scan("#site-navbar");const d=x.get(0),f=()=>{if(!a)return;const p=d.querySelector('a[aria-current="page"]')?.closest(".navbar-dropdown");p&&!p.classList.contains("open")&&p.querySelector(":scope > .navbar-dropdown-toggle")?.click()};d.classList.add(`dm-nav-align-${ie(h)||"centre"}`),a&&x.get(0).classList.add("dm-nav-vertical",h.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left");const i=h.dock||{};a&&!e&&me(d,h.side==="right"),!a&&i.hideOnScroll&&ue(d),R(d,h),V(d,h),O(d,h.class),e&&(ne(x.get(0),h),re(x.get(0).parentNode||document));const l=d.querySelector(".navbar-toggle"),g=d.querySelector(".navbar-collapse");if(l&&g){let u=null;const p=()=>{g.classList.contains("show")&&l.click()},m=()=>{u&&(u.remove(),u=null),document.body.classList.remove("dm-drawer-open")},v=()=>{u||(u=document.createElement("div"),u.className="dm-navbar-backdrop",u.addEventListener("click",p),document.body.appendChild(u),document.body.classList.add("dm-drawer-open"))};l.addEventListener("click",()=>{requestAnimationFrame(()=>{g.classList.contains("show")?(f(),v()):m()})}),g.addEventListener("click",C=>{C.target.closest("a")&&requestAnimationFrame(m)}),document.addEventListener("keydown",C=>{C.key==="Escape"&&g.classList.contains("show")&&p()})}const b=d.querySelector(".navbar-nav");if(b){const u=Array.from(b.children);let p=0;for(const m of h.items||[])if(!(m&&m.type==="separator")){if(m&&m.type==="spacer"){const v=document.createElement("li"),C=["xs","sm","md","lg","xl","flex"].includes(m.size)?m.size:"md";v.className=`dm-menu-spacer dm-menu-spacer--${C}`,v.setAttribute("aria-hidden","true"),b.insertBefore(v,u[p]||null);continue}if(m&&m.type==="theme-switcher"){const v=document.createElement("li");v.className="dm-menu-theme-switcher";const C=document.createElement("span");C.dataset.themeSwitcher="menu",C.dataset.position="inline",v.appendChild(C),b.insertBefore(v,u[p]||null);continue}p++}window.CMSThemeSwitcher?.scan(b)}d.querySelectorAll("[data-path]").forEach(u=>{const p=u.dataset.path.split(".").map(Number),m=p.length>1,v=p.reduce((A,q)=>A?.items?.[q],{items:t});if(!v)return;v.colour&&X(u,v.colour),v.pill&&!m&&oe(u,v.pill),ae(u,v),O(u.closest("li"),v.class);const C=J(v.badge);C&&u.appendChild(C),U(v.url,location.pathname)&&(u.classList.add("active"),u.setAttribute("aria-current","page"))}),f()}const y=$("#site-footer");if(y.length){let e=function(r){return String(r??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},a=function(r){return e(r).replace(/'/g,"'")},d=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';if(r&&r.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(r.size)?r.size:"md"}" aria-hidden="true"></li>`;if(r&&r.type==="theme-switcher")return'<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';const M=a(r.url||"#"),L=e(r.text||""),D=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",N=se(r),ee=[N.hover&&` data-menu-item-hover="${a(N.hover)}"`,N.active&&` data-menu-item-active="${a(N.active)}"`].filter(Boolean).join(""),te=N.accent?` style="--dm-menu-highlight:${a(N.accent)}"`:"",Y=W(r.class).join(" ");return`<li${Y?` class="${a(Y)}"`:""}><a href="${M}"${ee}${te}>${L}</a>${D}</li>`},f=function(){if(!c.footer)return"";const r=Object.keys(o).filter(L=>n[L]);if(!r.length)return"";const M=W(c.footer.socialClass).join(" ");return`<div class="footer-social">${r.map(L=>{const{label:D,svg:N}=o[L];return`<a href="${n[L]}" target="_blank" rel="noopener noreferrer" aria-label="${D}" class="footer-social-link${M?` ${a(M)}`:""}">${N}</a>`}).join("")}</div>`},b=function(r){if(!r||r.type==="separator"||r.type==="spacer")return"";if(r.type==="theme-switcher")return`<li class="cms-footer-col">${d(r).replace(/^<li[^>]*>|<\/li>$/g,"")}</li>`;const M=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",L=g(r)?`<span class="cms-footer-col-title">${e(r.text||"")}</span>`:`<a class="cms-footer-col-title" href="${a(r.url||"#")}">${e(r.text||"")}</a>`,D=["cms-footer-col",...W(r.class)].join(" ");return`<li class="${a(D)}">${L}${M}</li>`},p=function(r,M,L=!1){return(r||[]).forEach(D=>{D&&(D.type==="separator"||D.type==="spacer"||D.type==="theme-switcher")||(L&&g(D)||M.push(D),Array.isArray(D.items)&&D.items.length&&p(D.items,M))}),M};const n=c.social||{},o={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let s='<div class="footer-inner container">';const t=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""},i=["columns","row"].includes(c.footer?.layout)?c.footer.layout:"auto",l=i==="columns"||i==="auto"&&t.primary.some(r=>Array.isArray(r?.items)&&r.items.length),g=r=>l&&!r.url&&Array.isArray(r.items)&&r.items.length>0;if(l){const r=h.brand||{},M=r.text||c.title||"",L=r.logo?`<img src="${a(r.logo)}" class="cms-footer-brand-logo" alt="">`:r.icon?'<span class="cms-footer-brand-icon"></span>':"",D=String(c.footer?.blurb||"").trim();s='<div class="footer-inner footer-inner--columns container"><div class="cms-footer-top">',s+=`<div class="cms-footer-brand">${M||L?`<a class="cms-footer-brand-name" href="${a(r.url||"/")}">${L}<span>${e(M)}</span></a>`:""}${D?`<p class="cms-footer-blurb">${e(D)}</p>`:""}${f()}</div>`,t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary footer-nav--columns" aria-label="Footer"><ul>${t.primary.map(b).join("")}</ul></nav>`),s+='</div><div class="cms-footer-bottom">',t.copyright&&(s+=`<p class="cms-footer-copyright">${e(t.copyright)}</p>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal" aria-label="Legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+="</div>"}else t.copyright&&(s+=`<p>${e(t.copyright)}</p>`),t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary"><ul>${t.primary.map(d).join("")}</ul></nav>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+=f();s+="</div>",y.html(s),window.CMSThemeSwitcher?.scan(y.get(0));const u=y.get(0).querySelector(".cms-footer-brand-icon");u&&h.brand?.icon&&u.setAttribute("data-icon",h.brand.icon),O(y.get(0),c.footer?.class);const m=[...p(t.primary,[],!0),...p(t.legal,[])];y.get(0).querySelectorAll(".footer-nav a").forEach((r,M)=>{const L=m[M];if(!L)return;L.colour&&X(r,L.colour);const D=J(L.badge);D&&r.appendChild(D),U(L.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),R(y.get(0).querySelector(".footer-nav--primary"),{highlight:t.primaryHighlight}),R(y.get(0).querySelector(".footer-nav--legal"),{highlight:t.legalHighlight}),V(y.get(0).querySelector(".footer-nav--primary"),{entrance:t.primaryEntrance}),V(y.get(0).querySelector(".footer-nav--legal"),{entrance:t.legalEntrance}),O(y.get(0).querySelector(".footer-nav--primary"),t.primaryClass),O(y.get(0).querySelector(".footer-nav--legal"),t.legalClass);const C=c.footer?.showMotionToggle!==!1,A=S.get("reduced_motion"),q=c.footer?.motionDefault,z=A!=null?!!A:q==="on"?!0:q==="off"?!1:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),B=c.footer?.motionControl==="checkbox",I=y.get(0).querySelector(".cms-footer-bottom")||y.get(0).querySelector(".footer-inner");if(C&&I){const r=document.createElement("input");r.type="checkbox",r.className=B?"footer-motion-checkbox":"form-switch-input",r.id="dm-motion-switch",r.checked=z,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const M=document.createElement("span");M.className=B?"footer-motion-label":"form-switch-label",M.textContent="Reduce motion";const L=document.createElement("label");L.className=B?"footer-motion-check":"form-switch footer-motion-switch",L.title="Reduce motion",L.appendChild(r),L.appendChild(M),I.appendChild(L)}}const k=document.getElementById("site-sidebar");k&&pe(k),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const w=$(".page-body");if(w.length){w.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),w.find(".tabs").each(function(){Domma.elements.tabs(this)}),w.find(".carousel").each(function(){const n={primary:"--dm-primary",secondary:"--dm-secondary",accent:"--dm-primary",text:"--dm-text",surface:"--dm-surface",background:"--dm-background",success:"--dm-success",warning:"--dm-warning",danger:"--dm-danger",info:"--dm-info"},o=f=>{const i=String(f||"").trim();return i?n[i.toLowerCase()]?`var(${n[i.toLowerCase()]})`:CSS.supports("color",i)?i:"":""},s=o(this.dataset.background),t=o(this.dataset.arrowBackground),e=o(this.dataset.arrowColor);s&&(this.style.setProperty("--dm-carousel-background",s),this.classList.add("dm-carousel-custom-background")),t&&this.style.setProperty("--dm-carousel-arrow-background",t),e&&this.style.setProperty("--dm-carousel-arrow-color",e);const a=["top","middle","bottom"].includes(this.dataset.arrowPosition)?this.dataset.arrowPosition:"middle";this.classList.add(`dm-carousel-arrows-${a}`);const d={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide",heightMode:this.dataset.heightMode==="average"?"average":"crop"};if(this.dataset.height){const f=Number(this.dataset.height);Number.isFinite(f)&&f>0&&(d.height=f)}if(this.dataset.animationDuration){const f=parseInt(this.dataset.animationDuration,10);Number.isFinite(f)&&(d.animationDuration=f)}this.dataset.animationEasing&&(d.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(f=>f.cloneNode(!0)),this._dmCarouselOpts=d),this._dmCarousel=Domma.elements.carousel(this,d)}),w.find(".dm-countdown").each(function(){const n={autoStart:!0},o=String(this.dataset.format||"").trim(),s=String(this.dataset.to||"").trim(),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(s),e=t?new Date(+t[1],+t[2]-1,+t[3]).getTime():s?new Date(s).getTime():NaN;Number.isFinite(e)?n.duration=Math.max(0,e-Date.now()):this.dataset.duration&&(n.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const a=/^dd:/i.test(o);n.format=a?"hh:mm:ss":o||(n.duration>=36e5?"hh:mm:ss":"mm:ss");const d=this,f=l=>String(l).padStart(2,"0"),i=l=>{const g=Math.max(0,Math.floor(l/1e3)),b=d.querySelector(".dm-timer-time");b&&(b.textContent=`${f(Math.floor(g/86400))}:${f(Math.floor(g%86400/3600))}:${f(Math.floor(g%3600/60))}:${f(g%60)}`)};a&&(n.onTick=i),Domma.elements.timer(this,n),a&&i(n.duration||0)}),w.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),w.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(t=>{const e={title:t.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:t.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return t.dataset.date&&(e.date=t.dataset.date),t.dataset.status&&(e.status=t.dataset.status),t.dataset.eventIcon&&(e.icon=t.dataset.eventIcon),t.dataset.entryId&&(e._entryId=t.dataset.entryId),e}),o=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",s=Domma.elements.progression(this,{layout:o,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});if((this.dataset.mode||"timeline")==="timeline"){const t={completed:{label:"Completed",icon:"check-circle",tone:"success"},planned:{label:"Planned",icon:"circle",tone:"secondary"},"in-progress":{label:"In progress",icon:"clock",tone:"primary"},blocked:{label:"Blocked",icon:"alert-circle",tone:"danger"}};this.querySelectorAll(".dm-progression-item").forEach((e,a)=>{const d=n[a];if(!d)return;const f=e.querySelector(".dm-progression-title");if(d.icon&&f){const l=document.createElement("span");l.dataset.icon=d.icon,l.style.cssText="display:inline-flex;vertical-align:middle;margin-right:.4em",l.setAttribute("aria-hidden","true"),f.prepend(l)}const i=t[d.status];if(i&&f){const l=document.createElement("span");l.className=`badge badge-${i.tone} cms-timeline-status`,l.style.cssText="display:inline-flex;align-items:center;gap:.35em;margin:.4rem 0";const g=document.createElement("span");g.dataset.icon=i.icon,g.dataset.iconSize="14",g.setAttribute("aria-hidden","true"),l.append(g,document.createTextNode(i.label)),f.after(l)}})}Domma.icons.scan(this),n.length&&(this._dmCtx={instance:s,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const o=n.dataset.revealMode||"stagger",s=n.dataset.revealAnimation||"slide-up",t=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,a=parseInt(n.dataset.revealDelay,10)||0,d=n.dataset.revealDirection==="rtl",f=Array.from(n.children),i={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};f.forEach((l,g)=>{l.style.opacity="0",l.style.transform=i[s]||"",l.style.transition=`opacity ${t}ms ease, transform ${t}ms ease`;const b=d?f.length-1-g:g;l.style.transitionDelay=o==="stagger"?`${a+b*e}ms`:`${a}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const l=new IntersectionObserver(g=>{g.forEach(b=>{b.isIntersecting&&(b.target.offsetWidth,b.target.style.opacity="1",b.target.style.transform="none",l.unobserve(b.target))})},{threshold:.1});f.forEach(g=>l.observe(g))}))}),w.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),w.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,o=document.getElementById(n);if(!o)return;const s=E.slideover({title:o.dataset.soTitle||"",size:o.dataset.soSize||"md",position:o.dataset.soPosition||"right"});o.style.display="",s.setContent(o),s.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(o=>{try{const s=P(o.dataset.config);Object.assign(n,s)}catch{}}),Object.keys(n).length>0){const o={};for(const[s,t]of Object.entries(n)){const e=t?.events?.click,{confirm:a,toast:d,alert:f,prompt:i,...l}=e||{};a||d||f||i?($(s).on("click",async function(b){if(b.preventDefault(),a&&!await E.confirm(a))return;let u=null;if(!(i&&(u=await E.prompt(i,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),u===null))){if(l.target){const p=$(l.target);l.toggleClass&&p.toggleClass(l.toggleClass),l.addClass&&p.addClass(l.addClass),l.removeClass&&p.removeClass(l.removeClass),u!==null&&(l.setText&&p.text(u),l.setVal&&p.val(u),l.setAttr&&p.attr(l.setAttr,u))}l.href&&(window.location.href=l.href),d&&E.toast(d,{type:l.toastType||"success"}),f&&E.alert(f)}}),Object.keys(l).length&&(o[s]={...t,events:{...t.events,click:l}})):o[s]=t}$.setup(o)}}w.length&&j(w.get(0))}),window.wireCTAButtons=j;function j(h){h.querySelectorAll(".dm-cta-trigger").forEach(c=>{c.__ctaWired||(c.__ctaWired=!0,c.addEventListener("click",async()=>{const x=c.dataset.action,y=c.dataset.entry,k=c.dataset.confirm;let w=S.get("auth_token");if(!w){E.toast("Please log in to perform this action.",{type:"warning"});return}if(k&&!await E.confirm(k))return;const n=Array.from(c.childNodes).map(s=>s.cloneNode(!0));c.disabled=!0,c.textContent="Running\u2026";const o=s=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(c.dataset.scope?{entryId:y,scope:c.dataset.scope}:{entryId:y})});try{let s=await o(w);if(s.status===401){const e=S.get("auth_refresh_token");if(e){const a=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(a.ok){const{token:d}=await a.json();S.set("auth_token",d),w=d,s=await o(w)}}}const t=await s.json().catch(()=>({}));if(!s.ok||t.success===!1)throw new Error(t.error||t.message||`Error ${s.status}`);E.toast(t.message||"Action completed.",{type:"success"})}catch(s){E.toast(s.message||"Action failed.",{type:"error"})}finally{c.disabled=!1,c.textContent="",n.forEach(s=>c.appendChild(s)),Domma.icons.scan(c)}}))})}(function(){const c=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!c.length)return;const x=S.get("auth_token");function y(w,n){const o=document.createElement("div");o.className="dm-collection-display dm-collection-empty";const s=document.createElement("p");if(n){s.appendChild(document.createTextNode("Please "));const t=document.createElement("a");t.href="/login",t.textContent="sign in",s.appendChild(t),s.appendChild(document.createTextNode(" to view your entries."))}else s.textContent=w;return o.appendChild(s),o}function k(w,n){const o=document.createElement("template");o.innerHTML=n||"",w.replaceWith(o.content)}c.forEach(async w=>{const n=w.dataset.collectionAttrs;if(!n)return;if(!x){w.replaceChildren(y("",!0));return}const o=s=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({attrs:n})});try{let s=x,t=await o(s);if(t.status===401){const a=S.get("auth_refresh_token");if(a){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:a})});if(d.ok){const{token:f}=await d.json();S.set("auth_token",f),s=f,t=await o(s)}}}if(!t.ok){const{error:a}=await t.json().catch(()=>({}));w.replaceChildren(y(a||"Unable to load entries.",!1));return}const{html:e}=await t.json();k(w,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{w.replaceChildren(y("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),j(document.body)},100)})(),(function(){const c=document.querySelectorAll("[data-collection-table]");!c.length||typeof T>"u"||!T.create||c.forEach(x=>{let y;try{y=P(x.dataset.payload)}catch{return}const{columns:k,rows:w,search:n,sortable:o,exportable:s,pageSize:t,empty:e,ctaConfig:a,slug:d,exportCfg:f}=y;if(!k?.length)return;if(a){const g=k.findIndex(b=>b.key==="_cta");g!==-1&&(k[g]={key:"_cta",title:"",render:(b,u)=>{const p=document.createElement("button");if(p.className=`btn btn-${a.style||"primary"} dm-cta-trigger`,p.dataset.action=a.action||"",a.scope&&(p.dataset.scope=a.scope),p.dataset.entry=u._entryId||"",a.confirm&&(p.dataset.confirm=a.confirm),a.icon){const m=document.createElement("span");m.dataset.icon=a.icon,p.appendChild(m),p.appendChild(document.createTextNode(" "))}return p.appendChild(document.createTextNode(a.label||"Run")),p}})}const i="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=i,x.replaceChildren(l),T.create("#"+i,{data:w,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l),x._dmTable={columns:k,rows:w,slug:d,exportCfg:f,render(g){T.create("#"+i,{data:g,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l)}}})})(),(function(){const c=document.querySelectorAll("[data-form-inline]");if(!c.length||typeof F>"u")return;function x(o){const s=o&&o.logic;return!!(s&&(s.visibility||s.requirement))}function y(o,s){const t={};return(o||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const a=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),d=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":a?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&s&&(f.span=s);const i={type:d,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...e.tooltip&&{tooltip:e.tooltip},...f}};e.minLength!==void 0&&(i.minLength=e.minLength),e.maxLength!==void 0&&(i.maxLength=e.maxLength),e.min!==void 0&&(i.min=e.min),e.max!==void 0&&(i.max=e.max),a&&(e.variant&&(i.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(i.multiple=!0),e.density&&(i.density=e.density),e.columns&&(i.columns=e.columns),e.accent&&(i.accent=e.accent),e.accentStyle&&(i.accentStyle=e.accentStyle),e.glow&&(i.glow=!0),e.glowColour&&(i.glowColour=e.glowColour),e.shadow&&(i.shadow=e.shadow),e.shadowColour&&(i.shadowColour=e.shadowColour)),t[e.name]=i}),t}function k(o){const s={};return(o||[]).forEach(t=>{if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(s[t.name]=typeof e=="object"?e.value:e)}}),s}function w(o,s){(s||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const e=o.querySelector(`[name="${t.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(o,s,t){let e=o.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",o.appendChild(e)),e.textContent=s,e.style.cssText=t?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}c.forEach(o=>{let s;try{s=P(o.dataset.formInline)}catch{return}const t=s.fields||[],e=s.settings||{},a=Number(e.columns)===3?3:2,d=e.layout||"grid",f=t.some(p=>p.type==="page-break"),i=async p=>{if(o.dataset.triggerBlocked==="true"){const m=o._formLogicRuntime,v=m&&m.submitBlock?m.submitBlock().reasons:[];n(o,v.join(" ")||"This form cannot be submitted yet.",!0);const C=new Error("Blocked by a form trigger");throw C.formSubmitFailed=!0,C}try{const m=o.querySelector(".fb-form-honeypot"),v=m?.querySelector('input[type="text"]')||null,C=m?.querySelector('[name="_t"]')||null,A=Object.assign({},p);delete A._t,m?.dataset.hpName&&delete A[m.dataset.hpName],v!==null&&(A._hp=v.value),C!==null&&(A._t=C.value);const q=await H.post(`/api/forms/submit/${s.slug}`,A);if(q&&q.error){n(o,q.error,!0);const z=new Error(q.error);throw z.formSubmitFailed=!0,z}if(q?.redirect){window.location.href=q.redirect;return}for(;o.firstChild;)o.removeChild(o.firstChild);n(o,q?.message||e.successMessage||"Thank you for your submission.",!1)}catch(m){throw m.formSubmitFailed||n(o,m.message||"Submission failed. Please try again.",!0),m}},l=Date.now();function g(p){const m=p.querySelector("form");if(!m||m.querySelector(".fb-form-honeypot"))return;const v=document.createElement("div");v.className="fb-form-honeypot",v.setAttribute("aria-hidden","true");const C=document.createElement("input");C.name=m.querySelector('[name="website"]')?"_website":"website",v.dataset.hpName=C.name,C.type="text",C.tabIndex=-1,C.autocomplete="url",C.placeholder="https://",v.appendChild(C);const A=document.createElement("input");A.name="_t",A.type="hidden",A.value=l,v.appendChild(A),m.appendChild(v)}function b(p){if(!window.FormLogicEngine||!t.some(v=>v.logic||Array.isArray(v.triggers)&&v.triggers.length))return null;const m=new window.FormLogicEngine.FormLogicRuntime(s,o,p?{baseValues:p}:void 0);if(m.init(),o._formLogicRuntime=m,o._formLogicObserved)return m;if(o._formLogicObserved=!0,o.parentNode&&typeof MutationObserver<"u"){const v=new MutationObserver(function(C){for(const A of C)for(const q of A.removedNodes)if(q===o||q.nodeType===1&&q.contains&&q.contains(o)){o._formLogicRuntime&&o._formLogicRuntime.destroy(),v.disconnect();return}});v.observe(o.parentNode,{childList:!0,subtree:!1}),o._formLogicObserver=v}return m}let u=!1;if(o.addEventListener("dm-form-end",p=>{const m=p.detail?.validation;if(m&&!m.valid){K(o,m.missing),Q(m);return}u||(u=!0,i(p.detail?.values||{}).catch(()=>{}).finally(()=>{u=!1}))}),f&&F.wizard){const p=ce(t,s.title),m=p.map(I=>({title:I.title,description:I.description,fields:y(I.fields,a)})),v=p.map(I=>I.fields);let C=0,A=null,q=null;const z=I=>{const r=window.FormLogicEngine;if(!r||!r.validateFields)return;const M=r.validateFields(o,v[C]||[]);M.valid||(I.preventDefault(),I.stopImmediatePropagation(),K(o,M.missing),Q(M))},B=()=>{const I=v[C]||t;de(o,e),Z(o,e,I),w(o,I),G(o,I),e.honeypot!==!1&&g(o),A&&A.destroy(),A=b(q?.getStepData?q.getStepData():void 0),o.querySelectorAll(".wizard-next, .wizard-submit").forEach(r=>r.addEventListener("click",z,!0))};q=F.wizard(o,{schema:{steps:m},layout:d,columns:a,finishText:e.submitText||"Finish",onSubmit:i,onStepChange:I=>{C=I,setTimeout(B,0)}}),o.addEventListener("dm-form-trigger",I=>{if(I.detail?.type!=="goto-step"||!q?.goToStep)return;const r=Number(I.detail.action.step);!Number.isFinite(r)||r<0||r>=m.length||r!==C&&q.goToStep(r)}),Promise.resolve(q).then(B)}else if(F.render){const p=F.render(o,y(t,a),k(t),{submitText:e.submitText||"Submit",layout:d,columns:a,onSubmit:i});Promise.resolve(p).then(function(){le(o,e,d),Z(o,e,t),w(o,t),G(o,t),e.honeypot!==!1&&g(o),b()})}})})();function me(h,c){const x=document.body,y=x.classList,k=new Set((x.dataset.railSite||"").split(" ").filter(Boolean)),w=()=>window.matchMedia("(min-width: 993px)").matches;h.querySelectorAll(".navbar-link, .navbar-dropdown-toggle").forEach(a=>{const d=a.textContent.trim();d&&(a.setAttribute("title",d),a.querySelector("svg, [data-icon]")||(a.dataset.initial=d.charAt(0).toUpperCase()))});const n=document.createElement("button");n.type="button",n.className="dm-nav-collapse-toggle";const o=()=>{const a=y.contains("dm-vnav-collapsed");n.setAttribute("aria-pressed",String(a)),n.setAttribute("aria-label",a?"Expand menu":"Collapse menu"),n.title=n.getAttribute("aria-label");const d=c?"chevrons-left":"chevrons-right",f=c?"chevrons-right":"chevrons-left";n.innerHTML=`<span data-icon="${a?d:f}"></span>`,window.Domma&&Domma.icons&&Domma.icons.scan(n)},s=a=>{y.toggle("dm-vnav-collapsed",a),S.set("nav_collapsed",a),o()};n.addEventListener("click",()=>s(!y.contains("dm-vnav-collapsed"))),o();const t=h.querySelector(".navbar-container")||h;t.insertBefore(n,t.firstChild?.nextSibling||null);const e=a=>{y.toggle("dm-vnav-autohide",a),y.toggle("dm-vnav-collapsible",!a&&k.has("collapsible")),a?y.remove("dm-vnav-collapsed"):k.has("collapsible")&&S.get("nav_collapsed")===!0&&y.add("dm-vnav-collapsed"),h.classList.remove("dm-nav-revealed"),o()};h.addEventListener("pointerdown",a=>{y.contains("dm-vnav-autohide")&&a.pointerType!=="mouse"&&!h.classList.contains("dm-nav-revealed")&&(h.classList.add("dm-nav-revealed"),a.preventDefault())}),document.addEventListener("pointerdown",a=>{h.contains(a.target)||h.classList.remove("dm-nav-revealed")}),window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const a=y.contains("dm-vnav-autohide"),d=y.contains("dm-vnav-collapsed"),f=S.has("nav_autohide")||S.has("nav_collapsed");return[{header:"Menu"},{label:d?"Expand menu":"Collapse to icons",icon:d?"maximize":"minimize",disabled:!w()||a||!k.has("collapsible"),action:()=>s(!d)},{label:a?"Keep on screen":"Hide when not in use",icon:a?"eye":"eye-off",disabled:!w(),action:()=>{S.set("nav_autohide",!a),e(!a)}},{type:"divider"},{label:"Reset to the site's setting",icon:"refresh",disabled:!f,action:()=>{S.remove("nav_autohide"),S.remove("nav_collapsed"),e(k.has("autohide")),y.toggle("dm-vnav-collapsed",!k.has("autohide")&&k.has("start-collapsed")),o()}}]}})}function ue(h){h.classList.add("dm-nav-scroll-hide");let c=window.scrollY,x=!1;window.addEventListener("scroll",()=>{x||(x=!0,requestAnimationFrame(()=>{x=!1;const y=window.scrollY,k=h.matches(":focus-within")||h.querySelector(".navbar-dropdown.open, .navbar-collapse.show");y>c&&y>h.offsetHeight&&!k?h.classList.add("dm-nav-scrolled-away"):y<c&&h.classList.remove("dm-nav-scrolled-away"),c=y}))},{passive:!0})}function pe(h){let c={};try{c=JSON.parse(h.dataset.contents||"{}")}catch{}const x=h.closest(".site-main"),y=document.querySelector(".site-content"),k=new Set(String(c.exclude||"").split(",").map(i=>i.trim().toLowerCase()).filter(Boolean)),w=i=>!i.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),n=i=>(y?[...y.querySelectorAll(i)]:[]).filter(w).filter(l=>!k.has(l.textContent.trim().toLowerCase())),o=c.headings==="h2"?n("h2"):c.headings==="h3"?n("h3"):c.headings==="h2h3"?n("h2, h3"):n("h2").length?n("h2"):n("h3");if(!o.length){x?.classList.add("no-sidebar-items");return}const s=new Set([...document.querySelectorAll("[id]")].map(i=>i.id)),t=document.createElement("nav");t.className="dm-contents",t.setAttribute("aria-label",c.title||"Page contents"),c.hover&&(t.dataset.menuHover=c.hover),c.selected&&(t.dataset.menuActive=c.selected),c.accent&&t.style.setProperty("--dm-menu-highlight",c.accent.startsWith("#")?c.accent:`var(--dm-${c.accent})`),c.font&&(t.style.fontFamily=c.font),c.fontSize&&(t.style.fontSize=c.fontSize),c.fontWeight&&(t.style.fontWeight=c.fontWeight);const e=document.createElement("div");e.className="dm-contents-head";const a=document.createElement("p");a.className="dm-contents-title",a.textContent=c.title||"",e.appendChild(a),t.appendChild(e);const d=document.createElement("ol");d.className="dm-contents-list"+(c.numbered?" is-numbered":"");const f=[];for(const i of o){if(!i.id){const b=(i.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let u=b;for(let p=2;s.has(u);p++)u=`${b}-${p}`;s.add(u),i.id=u}const l=document.createElement("li");l.className=`dm-contents-item dm-contents-${i.tagName.toLowerCase()}`;const g=document.createElement("a");g.href=`#${i.id}`,g.textContent=i.textContent.trim(),l.appendChild(g),d.appendChild(l),f.push([i,g])}if(t.appendChild(d),h.replaceChildren(t),c.scrollSpy!==!1&&"IntersectionObserver"in window){const i=new Map,l=()=>{const b=f.find(([u])=>i.get(u))||null;f.forEach(([,u])=>{const p=b&&u===b[1];u.classList.toggle("is-active",!!p),p?u.setAttribute("aria-current","location"):u.removeAttribute("aria-current")})},g=new IntersectionObserver(b=>{b.forEach(u=>i.set(u.target,u.isIntersecting)),l()},{rootMargin:"-80px 0px -60% 0px"});f.forEach(([b])=>g.observe(b))}if(x?.classList.contains("contents-collapsible")){const i=document.createElement("button");i.type="button",i.className="dm-contents-toggle";const l=()=>{const g=x.classList.contains("contents-collapsed");i.setAttribute("aria-expanded",String(!g)),i.setAttribute("aria-label",g?"Show the contents":"Hide the contents"),i.title=i.getAttribute("aria-label"),i.innerHTML=`<span data-icon="${g?"list":"x"}"></span>`,window.Domma?.icons&&Domma.icons.scan(i)};i.addEventListener("click",()=>{S.set("contents_collapsed",x.classList.toggle("contents-collapsed")),l()}),l(),e.insertBefore(i,e.firstChild)}if(x?.classList.contains("contents-floating")&&c.movable){t.classList.add("is-movable");const i=S.get("contents_position");i&&Number.isFinite(i.x)&&Object.assign(h.style,{left:`${i.x}px`,top:`${i.y}px`,right:"auto",bottom:"auto"}),e.addEventListener("pointerdown",l=>{if(l.target.closest("button"))return;const g=h.getBoundingClientRect(),b=l.clientX-g.left,u=l.clientY-g.top,p=v=>{const C=Math.max(0,Math.min(window.innerWidth-g.width,v.clientX-b)),A=Math.max(0,Math.min(window.innerHeight-40,v.clientY-u));Object.assign(h.style,{left:`${C}px`,top:`${A}px`,right:"auto",bottom:"auto"})},m=()=>{document.removeEventListener("pointermove",p),S.set("contents_position",{x:parseInt(h.style.left,10),y:parseInt(h.style.top,10)})};document.addEventListener("pointermove",p),document.addEventListener("pointerup",m,{once:!0})})}window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const i=x?.classList.contains("contents-collapsible"),l=x?.classList.contains("contents-collapsed"),g=f.find(([,b])=>b.classList.contains("is-active"));return[{header:"Contents"},...i?[{label:l?"Show the contents":"Collapse to a button",icon:l?"list":"minimize",action:()=>h.querySelector(".dm-contents-toggle")?.click()}]:[],{label:"Copy a link to this section",icon:"link",disabled:!g,action:async()=>{const b=`${location.origin}${location.pathname}#${g[0].id}`;try{await _.copyToClipboard(b),E.toast("Link copied.",{type:"success"})}catch{E.toast("Could not copy the link.",{type:"error"})}}},{label:"Back to the top",icon:"arrow-up",action:()=>window.scrollTo({top:0,behavior:"smooth"})}]}}),x?.classList.contains("contents-autohide")&&(h.addEventListener("pointerdown",i=>{i.pointerType!=="mouse"&&!h.classList.contains("is-revealed")&&(h.classList.add("is-revealed"),i.preventDefault())}),document.addEventListener("pointerdown",i=>{h.contains(i.target)||h.classList.remove("is-revealed")}))}
|
|
1
|
+
import{installSmoothCarets as oe}from"/public/js/smooth-caret.js";import{decodeBase64Json as P}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as J,applyColour as X,applyPill as ne,applyFloat as ae,applyHighlight as R,applyItemHighlight as se,itemHighlightAttrs as ie,isCurrentItem as U,menuAlign as re,applyClasses as O,cssClasses as W,applyEntrance as V}from"/public/js/menu-decor.mjs?v=20261014-menu-entrance";import{initFloatingMenus as ce}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as G,markInvalidFields as K,showValidationPopup as Q}from"/public/js/forms.js?v=20261015-smooth-caret";import{buildWizardSteps as le}from"/public/js/form-steps.mjs";import{applyFormClasses as Z,applySubmitButtons as de,applyWizardButtons as me}from"/public/js/form-submit.mjs";document.addEventListener("click",h=>{const c=h.target?.closest?.(".dm-banner__dismiss");c&&(h.preventDefault(),c.closest(".dm-banner")?.remove())}),$(()=>{oe(document);const h=window.__CMS_NAV__||{},c=window.__CMS_SITE__||{};if(c.autoTheme?.enabled){let o=function(e){const a=(e||"07:00").split(":");return+a[0]*60+(+a[1]||0)},s=function(){const e=new Date,a=e.getHours()*60+e.getMinutes();return a>=o(n.dayStart)&&a<o(n.nightStart)?n.dayTheme:n.nightTheme},t=function(e){const a=n.apply&&n.apply[e]||{theme:e,custom:""};Domma.theme.set(a.theme);for(const d of[...document.body.classList])d.startsWith("dm-custom-")&&document.body.classList.remove(d);a.custom&&document.body.classList.add(a.custom)};const n=c.autoTheme;t(s()),setInterval(()=>t(s()),6e4)}const x=$("#site-navbar");if(x.length&&h.brand){let s=function(u,p=0){return Array.isArray(u)?u.filter(m=>!(m&&(m.type==="spacer"||m.type==="theme-switcher"))).filter(m=>!(m&&m.type==="separator"&&p===0)).map(m=>m&&m.type==="separator"?{divider:!0}:Array.isArray(m?.items)?{...m,items:s(m.items,p+1)}:m):u};const n={...h.brand},o=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let u="";n.logo?u+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(u+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(u+=`<span class="navbar-brand-text${o}">${n.text}</span>`),n.tagline&&(u+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=u}else o&&n.text&&(n.html=`<span class="navbar-brand-text${o}">${n.text}</span>`);const t=s(h.items||[]),e=h.position==="floating",a=h.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:n,items:t,variant:h.variant||"dark",position:e?"static":h.position||"sticky",collapsible:!0,appearOnHover:!!h.appearOnHover}),Domma.icons.scan("#site-navbar");const d=x.get(0),f=()=>{if(!a)return;const p=d.querySelector('a[aria-current="page"]')?.closest(".navbar-dropdown");p&&!p.classList.contains("open")&&p.querySelector(":scope > .navbar-dropdown-toggle")?.click()};d.classList.add(`dm-nav-align-${re(h)||"centre"}`),a&&x.get(0).classList.add("dm-nav-vertical",h.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left");const i=h.dock||{};a&&!e&&ue(d,h.side==="right"),!a&&i.hideOnScroll&&pe(d),R(d,h),V(d,h),O(d,h.class),e&&(ae(x.get(0),h),ce(x.get(0).parentNode||document));const l=d.querySelector(".navbar-toggle"),g=d.querySelector(".navbar-collapse");if(l&&g){let u=null;const p=()=>{g.classList.contains("show")&&l.click()},m=()=>{u&&(u.remove(),u=null),document.body.classList.remove("dm-drawer-open")},v=()=>{u||(u=document.createElement("div"),u.className="dm-navbar-backdrop",u.addEventListener("click",p),document.body.appendChild(u),document.body.classList.add("dm-drawer-open"))};l.addEventListener("click",()=>{requestAnimationFrame(()=>{g.classList.contains("show")?(f(),v()):m()})}),g.addEventListener("click",C=>{C.target.closest("a")&&requestAnimationFrame(m)}),document.addEventListener("keydown",C=>{C.key==="Escape"&&g.classList.contains("show")&&p()})}const b=d.querySelector(".navbar-nav");if(b){const u=Array.from(b.children);let p=0;for(const m of h.items||[])if(!(m&&m.type==="separator")){if(m&&m.type==="spacer"){const v=document.createElement("li"),C=["xs","sm","md","lg","xl","flex"].includes(m.size)?m.size:"md";v.className=`dm-menu-spacer dm-menu-spacer--${C}`,v.setAttribute("aria-hidden","true"),b.insertBefore(v,u[p]||null);continue}if(m&&m.type==="theme-switcher"){const v=document.createElement("li");v.className="dm-menu-theme-switcher";const C=document.createElement("span");C.dataset.themeSwitcher="menu",C.dataset.position="inline",v.appendChild(C),b.insertBefore(v,u[p]||null);continue}p++}window.CMSThemeSwitcher?.scan(b)}d.querySelectorAll("[data-path]").forEach(u=>{const p=u.dataset.path.split(".").map(Number),m=p.length>1,v=p.reduce((A,q)=>A?.items?.[q],{items:t});if(!v)return;v.colour&&X(u,v.colour),v.pill&&!m&&ne(u,v.pill),se(u,v),O(u.closest("li"),v.class);const C=J(v.badge);C&&u.appendChild(C),U(v.url,location.pathname)&&(u.classList.add("active"),u.setAttribute("aria-current","page"))}),f()}const y=$("#site-footer");if(y.length){let e=function(r){return String(r??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},a=function(r){return e(r).replace(/'/g,"'")},d=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';if(r&&r.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(r.size)?r.size:"md"}" aria-hidden="true"></li>`;if(r&&r.type==="theme-switcher")return'<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';const M=a(r.url||"#"),L=e(r.text||""),D=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",N=ie(r),ee=[N.hover&&` data-menu-item-hover="${a(N.hover)}"`,N.active&&` data-menu-item-active="${a(N.active)}"`].filter(Boolean).join(""),te=N.accent?` style="--dm-menu-highlight:${a(N.accent)}"`:"",Y=W(r.class).join(" ");return`<li${Y?` class="${a(Y)}"`:""}><a href="${M}"${ee}${te}>${L}</a>${D}</li>`},f=function(){if(!c.footer)return"";const r=Object.keys(o).filter(L=>n[L]);if(!r.length)return"";const M=W(c.footer.socialClass).join(" ");return`<div class="footer-social">${r.map(L=>{const{label:D,svg:N}=o[L];return`<a href="${n[L]}" target="_blank" rel="noopener noreferrer" aria-label="${D}" class="footer-social-link${M?` ${a(M)}`:""}">${N}</a>`}).join("")}</div>`},b=function(r){if(!r||r.type==="separator"||r.type==="spacer")return"";if(r.type==="theme-switcher")return`<li class="cms-footer-col">${d(r).replace(/^<li[^>]*>|<\/li>$/g,"")}</li>`;const M=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",L=g(r)?`<span class="cms-footer-col-title">${e(r.text||"")}</span>`:`<a class="cms-footer-col-title" href="${a(r.url||"#")}">${e(r.text||"")}</a>`,D=["cms-footer-col",...W(r.class)].join(" ");return`<li class="${a(D)}">${L}${M}</li>`},p=function(r,M,L=!1){return(r||[]).forEach(D=>{D&&(D.type==="separator"||D.type==="spacer"||D.type==="theme-switcher")||(L&&g(D)||M.push(D),Array.isArray(D.items)&&D.items.length&&p(D.items,M))}),M};const n=c.social||{},o={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let s='<div class="footer-inner container">';const t=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""},i=["columns","row"].includes(c.footer?.layout)?c.footer.layout:"auto",l=i==="columns"||i==="auto"&&t.primary.some(r=>Array.isArray(r?.items)&&r.items.length),g=r=>l&&!r.url&&Array.isArray(r.items)&&r.items.length>0;if(l){const r=h.brand||{},M=r.text||c.title||"",L=r.logo?`<img src="${a(r.logo)}" class="cms-footer-brand-logo" alt="">`:r.icon?'<span class="cms-footer-brand-icon"></span>':"",D=String(c.footer?.blurb||"").trim();s='<div class="footer-inner footer-inner--columns container"><div class="cms-footer-top">',s+=`<div class="cms-footer-brand">${M||L?`<a class="cms-footer-brand-name" href="${a(r.url||"/")}">${L}<span>${e(M)}</span></a>`:""}${D?`<p class="cms-footer-blurb">${e(D)}</p>`:""}${f()}</div>`,t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary footer-nav--columns" aria-label="Footer"><ul>${t.primary.map(b).join("")}</ul></nav>`),s+='</div><div class="cms-footer-bottom">',t.copyright&&(s+=`<p class="cms-footer-copyright">${e(t.copyright)}</p>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal" aria-label="Legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+="</div>"}else t.copyright&&(s+=`<p>${e(t.copyright)}</p>`),t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary"><ul>${t.primary.map(d).join("")}</ul></nav>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+=f();s+="</div>",y.html(s),window.CMSThemeSwitcher?.scan(y.get(0));const u=y.get(0).querySelector(".cms-footer-brand-icon");u&&h.brand?.icon&&u.setAttribute("data-icon",h.brand.icon),O(y.get(0),c.footer?.class);const m=[...p(t.primary,[],!0),...p(t.legal,[])];y.get(0).querySelectorAll(".footer-nav a").forEach((r,M)=>{const L=m[M];if(!L)return;L.colour&&X(r,L.colour);const D=J(L.badge);D&&r.appendChild(D),U(L.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),R(y.get(0).querySelector(".footer-nav--primary"),{highlight:t.primaryHighlight}),R(y.get(0).querySelector(".footer-nav--legal"),{highlight:t.legalHighlight}),V(y.get(0).querySelector(".footer-nav--primary"),{entrance:t.primaryEntrance}),V(y.get(0).querySelector(".footer-nav--legal"),{entrance:t.legalEntrance}),O(y.get(0).querySelector(".footer-nav--primary"),t.primaryClass),O(y.get(0).querySelector(".footer-nav--legal"),t.legalClass);const C=c.footer?.showMotionToggle!==!1,A=S.get("reduced_motion"),q=c.footer?.motionDefault,z=A!=null?!!A:q==="on"?!0:q==="off"?!1:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),B=c.footer?.motionControl==="checkbox",I=y.get(0).querySelector(".cms-footer-bottom")||y.get(0).querySelector(".footer-inner");if(C&&I){const r=document.createElement("input");r.type="checkbox",r.className=B?"footer-motion-checkbox":"form-switch-input",r.id="dm-motion-switch",r.checked=z,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const M=document.createElement("span");M.className=B?"footer-motion-label":"form-switch-label",M.textContent="Reduce motion";const L=document.createElement("label");L.className=B?"footer-motion-check":"form-switch footer-motion-switch",L.title="Reduce motion",L.appendChild(r),L.appendChild(M),I.appendChild(L)}}const k=document.getElementById("site-sidebar");k&&he(k),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const w=$(".page-body");if(w.length){w.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),w.find(".tabs").each(function(){Domma.elements.tabs(this)}),w.find(".carousel").each(function(){const n={primary:"--dm-primary",secondary:"--dm-secondary",accent:"--dm-primary",text:"--dm-text",surface:"--dm-surface",background:"--dm-background",success:"--dm-success",warning:"--dm-warning",danger:"--dm-danger",info:"--dm-info"},o=f=>{const i=String(f||"").trim();return i?n[i.toLowerCase()]?`var(${n[i.toLowerCase()]})`:CSS.supports("color",i)?i:"":""},s=o(this.dataset.background),t=o(this.dataset.arrowBackground),e=o(this.dataset.arrowColor);s&&(this.style.setProperty("--dm-carousel-background",s),this.classList.add("dm-carousel-custom-background")),t&&this.style.setProperty("--dm-carousel-arrow-background",t),e&&this.style.setProperty("--dm-carousel-arrow-color",e);const a=["top","middle","bottom"].includes(this.dataset.arrowPosition)?this.dataset.arrowPosition:"middle";this.classList.add(`dm-carousel-arrows-${a}`);const d={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide",heightMode:this.dataset.heightMode==="average"?"average":"crop"};if(this.dataset.height){const f=Number(this.dataset.height);Number.isFinite(f)&&f>0&&(d.height=f)}if(this.dataset.animationDuration){const f=parseInt(this.dataset.animationDuration,10);Number.isFinite(f)&&(d.animationDuration=f)}this.dataset.animationEasing&&(d.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(f=>f.cloneNode(!0)),this._dmCarouselOpts=d),this._dmCarousel=Domma.elements.carousel(this,d)}),w.find(".dm-countdown").each(function(){const n={autoStart:!0},o=String(this.dataset.format||"").trim(),s=String(this.dataset.to||"").trim(),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(s),e=t?new Date(+t[1],+t[2]-1,+t[3]).getTime():s?new Date(s).getTime():NaN;Number.isFinite(e)?n.duration=Math.max(0,e-Date.now()):this.dataset.duration&&(n.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const a=/^dd:/i.test(o);n.format=a?"hh:mm:ss":o||(n.duration>=36e5?"hh:mm:ss":"mm:ss");const d=this,f=l=>String(l).padStart(2,"0"),i=l=>{const g=Math.max(0,Math.floor(l/1e3)),b=d.querySelector(".dm-timer-time");b&&(b.textContent=`${f(Math.floor(g/86400))}:${f(Math.floor(g%86400/3600))}:${f(Math.floor(g%3600/60))}:${f(g%60)}`)};a&&(n.onTick=i),Domma.elements.timer(this,n),a&&i(n.duration||0)}),w.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),w.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(t=>{const e={title:t.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:t.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return t.dataset.date&&(e.date=t.dataset.date),t.dataset.status&&(e.status=t.dataset.status),t.dataset.eventIcon&&(e.icon=t.dataset.eventIcon),t.dataset.entryId&&(e._entryId=t.dataset.entryId),e}),o=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",s=Domma.elements.progression(this,{layout:o,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});if((this.dataset.mode||"timeline")==="timeline"){const t={completed:{label:"Completed",icon:"check-circle",tone:"success"},planned:{label:"Planned",icon:"circle",tone:"secondary"},"in-progress":{label:"In progress",icon:"clock",tone:"primary"},blocked:{label:"Blocked",icon:"alert-circle",tone:"danger"}};this.querySelectorAll(".dm-progression-item").forEach((e,a)=>{const d=n[a];if(!d)return;const f=e.querySelector(".dm-progression-title");if(d.icon&&f){const l=document.createElement("span");l.dataset.icon=d.icon,l.style.cssText="display:inline-flex;vertical-align:middle;margin-right:.4em",l.setAttribute("aria-hidden","true"),f.prepend(l)}const i=t[d.status];if(i&&f){const l=document.createElement("span");l.className=`badge badge-${i.tone} cms-timeline-status`,l.style.cssText="display:inline-flex;align-items:center;gap:.35em;margin:.4rem 0";const g=document.createElement("span");g.dataset.icon=i.icon,g.dataset.iconSize="14",g.setAttribute("aria-hidden","true"),l.append(g,document.createTextNode(i.label)),f.after(l)}})}Domma.icons.scan(this),n.length&&(this._dmCtx={instance:s,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const o=n.dataset.revealMode||"stagger",s=n.dataset.revealAnimation||"slide-up",t=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,a=parseInt(n.dataset.revealDelay,10)||0,d=n.dataset.revealDirection==="rtl",f=Array.from(n.children),i={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};f.forEach((l,g)=>{l.style.opacity="0",l.style.transform=i[s]||"",l.style.transition=`opacity ${t}ms ease, transform ${t}ms ease`;const b=d?f.length-1-g:g;l.style.transitionDelay=o==="stagger"?`${a+b*e}ms`:`${a}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const l=new IntersectionObserver(g=>{g.forEach(b=>{b.isIntersecting&&(b.target.offsetWidth,b.target.style.opacity="1",b.target.style.transform="none",l.unobserve(b.target))})},{threshold:.1});f.forEach(g=>l.observe(g))}))}),w.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),w.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,o=document.getElementById(n);if(!o)return;const s=E.slideover({title:o.dataset.soTitle||"",size:o.dataset.soSize||"md",position:o.dataset.soPosition||"right"});o.style.display="",s.setContent(o),s.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(o=>{try{const s=P(o.dataset.config);Object.assign(n,s)}catch{}}),Object.keys(n).length>0){const o={};for(const[s,t]of Object.entries(n)){const e=t?.events?.click,{confirm:a,toast:d,alert:f,prompt:i,...l}=e||{};a||d||f||i?($(s).on("click",async function(b){if(b.preventDefault(),a&&!await E.confirm(a))return;let u=null;if(!(i&&(u=await E.prompt(i,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),u===null))){if(l.target){const p=$(l.target);l.toggleClass&&p.toggleClass(l.toggleClass),l.addClass&&p.addClass(l.addClass),l.removeClass&&p.removeClass(l.removeClass),u!==null&&(l.setText&&p.text(u),l.setVal&&p.val(u),l.setAttr&&p.attr(l.setAttr,u))}l.href&&(window.location.href=l.href),d&&E.toast(d,{type:l.toastType||"success"}),f&&E.alert(f)}}),Object.keys(l).length&&(o[s]={...t,events:{...t.events,click:l}})):o[s]=t}$.setup(o)}}w.length&&j(w.get(0))}),window.wireCTAButtons=j;function j(h){h.querySelectorAll(".dm-cta-trigger").forEach(c=>{c.__ctaWired||(c.__ctaWired=!0,c.addEventListener("click",async()=>{const x=c.dataset.action,y=c.dataset.entry,k=c.dataset.confirm;let w=S.get("auth_token");if(!w){E.toast("Please log in to perform this action.",{type:"warning"});return}if(k&&!await E.confirm(k))return;const n=Array.from(c.childNodes).map(s=>s.cloneNode(!0));c.disabled=!0,c.textContent="Running\u2026";const o=s=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(c.dataset.scope?{entryId:y,scope:c.dataset.scope}:{entryId:y})});try{let s=await o(w);if(s.status===401){const e=S.get("auth_refresh_token");if(e){const a=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(a.ok){const{token:d}=await a.json();S.set("auth_token",d),w=d,s=await o(w)}}}const t=await s.json().catch(()=>({}));if(!s.ok||t.success===!1)throw new Error(t.error||t.message||`Error ${s.status}`);E.toast(t.message||"Action completed.",{type:"success"})}catch(s){E.toast(s.message||"Action failed.",{type:"error"})}finally{c.disabled=!1,c.textContent="",n.forEach(s=>c.appendChild(s)),Domma.icons.scan(c)}}))})}(function(){const c=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!c.length)return;const x=S.get("auth_token");function y(w,n){const o=document.createElement("div");o.className="dm-collection-display dm-collection-empty";const s=document.createElement("p");if(n){s.appendChild(document.createTextNode("Please "));const t=document.createElement("a");t.href="/login",t.textContent="sign in",s.appendChild(t),s.appendChild(document.createTextNode(" to view your entries."))}else s.textContent=w;return o.appendChild(s),o}function k(w,n){const o=document.createElement("template");o.innerHTML=n||"",w.replaceWith(o.content)}c.forEach(async w=>{const n=w.dataset.collectionAttrs;if(!n)return;if(!x){w.replaceChildren(y("",!0));return}const o=s=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({attrs:n})});try{let s=x,t=await o(s);if(t.status===401){const a=S.get("auth_refresh_token");if(a){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:a})});if(d.ok){const{token:f}=await d.json();S.set("auth_token",f),s=f,t=await o(s)}}}if(!t.ok){const{error:a}=await t.json().catch(()=>({}));w.replaceChildren(y(a||"Unable to load entries.",!1));return}const{html:e}=await t.json();k(w,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{w.replaceChildren(y("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),j(document.body)},100)})(),(function(){const c=document.querySelectorAll("[data-collection-table]");!c.length||typeof T>"u"||!T.create||c.forEach(x=>{let y;try{y=P(x.dataset.payload)}catch{return}const{columns:k,rows:w,search:n,sortable:o,exportable:s,pageSize:t,empty:e,ctaConfig:a,slug:d,exportCfg:f}=y;if(!k?.length)return;if(a){const g=k.findIndex(b=>b.key==="_cta");g!==-1&&(k[g]={key:"_cta",title:"",render:(b,u)=>{const p=document.createElement("button");if(p.className=`btn btn-${a.style||"primary"} dm-cta-trigger`,p.dataset.action=a.action||"",a.scope&&(p.dataset.scope=a.scope),p.dataset.entry=u._entryId||"",a.confirm&&(p.dataset.confirm=a.confirm),a.icon){const m=document.createElement("span");m.dataset.icon=a.icon,p.appendChild(m),p.appendChild(document.createTextNode(" "))}return p.appendChild(document.createTextNode(a.label||"Run")),p}})}const i="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=i,x.replaceChildren(l),T.create("#"+i,{data:w,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l),x._dmTable={columns:k,rows:w,slug:d,exportCfg:f,render(g){T.create("#"+i,{data:g,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l)}}})})(),(function(){const c=document.querySelectorAll("[data-form-inline]");if(!c.length||typeof F>"u")return;function x(o){const s=o&&o.logic;return!!(s&&(s.visibility||s.requirement))}function y(o,s){const t={};return(o||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const a=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),d=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":a?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&s&&(f.span=s);const i={type:d,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...e.tooltip&&{tooltip:e.tooltip},...f}};e.minLength!==void 0&&(i.minLength=e.minLength),e.maxLength!==void 0&&(i.maxLength=e.maxLength),e.min!==void 0&&(i.min=e.min),e.max!==void 0&&(i.max=e.max),a&&(e.variant&&(i.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(i.multiple=!0),e.density&&(i.density=e.density),e.columns&&(i.columns=e.columns),e.accent&&(i.accent=e.accent),e.accentStyle&&(i.accentStyle=e.accentStyle),e.glow&&(i.glow=!0),e.glowColour&&(i.glowColour=e.glowColour),e.shadow&&(i.shadow=e.shadow),e.shadowColour&&(i.shadowColour=e.shadowColour)),t[e.name]=i}),t}function k(o){const s={};return(o||[]).forEach(t=>{if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(s[t.name]=typeof e=="object"?e.value:e)}}),s}function w(o,s){(s||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const e=o.querySelector(`[name="${t.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(o,s,t){let e=o.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",o.appendChild(e)),e.textContent=s,e.style.cssText=t?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}c.forEach(o=>{let s;try{s=P(o.dataset.formInline)}catch{return}const t=s.fields||[],e=s.settings||{},a=Number(e.columns)===3?3:2,d=e.layout||"grid",f=t.some(p=>p.type==="page-break"),i=async p=>{if(o.dataset.triggerBlocked==="true"){const m=o._formLogicRuntime,v=m&&m.submitBlock?m.submitBlock().reasons:[];n(o,v.join(" ")||"This form cannot be submitted yet.",!0);const C=new Error("Blocked by a form trigger");throw C.formSubmitFailed=!0,C}try{const m=o.querySelector(".fb-form-honeypot"),v=m?.querySelector('input[type="text"]')||null,C=m?.querySelector('[name="_t"]')||null,A=Object.assign({},p);delete A._t,m?.dataset.hpName&&delete A[m.dataset.hpName],v!==null&&(A._hp=v.value),C!==null&&(A._t=C.value);const q=await H.post(`/api/forms/submit/${s.slug}`,A);if(q&&q.error){n(o,q.error,!0);const z=new Error(q.error);throw z.formSubmitFailed=!0,z}if(q?.redirect){window.location.href=q.redirect;return}for(;o.firstChild;)o.removeChild(o.firstChild);n(o,q?.message||e.successMessage||"Thank you for your submission.",!1)}catch(m){throw m.formSubmitFailed||n(o,m.message||"Submission failed. Please try again.",!0),m}},l=Date.now();function g(p){const m=p.querySelector("form");if(!m||m.querySelector(".fb-form-honeypot"))return;const v=document.createElement("div");v.className="fb-form-honeypot",v.setAttribute("aria-hidden","true");const C=document.createElement("input");C.name=m.querySelector('[name="website"]')?"_website":"website",v.dataset.hpName=C.name,C.type="text",C.tabIndex=-1,C.autocomplete="url",C.placeholder="https://",v.appendChild(C);const A=document.createElement("input");A.name="_t",A.type="hidden",A.value=l,v.appendChild(A),m.appendChild(v)}function b(p){if(!window.FormLogicEngine||!t.some(v=>v.logic||Array.isArray(v.triggers)&&v.triggers.length))return null;const m=new window.FormLogicEngine.FormLogicRuntime(s,o,p?{baseValues:p}:void 0);if(m.init(),o._formLogicRuntime=m,o._formLogicObserved)return m;if(o._formLogicObserved=!0,o.parentNode&&typeof MutationObserver<"u"){const v=new MutationObserver(function(C){for(const A of C)for(const q of A.removedNodes)if(q===o||q.nodeType===1&&q.contains&&q.contains(o)){o._formLogicRuntime&&o._formLogicRuntime.destroy(),v.disconnect();return}});v.observe(o.parentNode,{childList:!0,subtree:!1}),o._formLogicObserver=v}return m}let u=!1;if(o.addEventListener("dm-form-end",p=>{const m=p.detail?.validation;if(m&&!m.valid){K(o,m.missing),Q(m);return}u||(u=!0,i(p.detail?.values||{}).catch(()=>{}).finally(()=>{u=!1}))}),f&&F.wizard){const p=le(t,s.title),m=p.map(I=>({title:I.title,description:I.description,fields:y(I.fields,a)})),v=p.map(I=>I.fields);let C=0,A=null,q=null;const z=I=>{const r=window.FormLogicEngine;if(!r||!r.validateFields)return;const M=r.validateFields(o,v[C]||[]);M.valid||(I.preventDefault(),I.stopImmediatePropagation(),K(o,M.missing),Q(M))},B=()=>{const I=v[C]||t;me(o,e),Z(o,e,I),w(o,I),G(o,I),e.honeypot!==!1&&g(o),A&&A.destroy(),A=b(q?.getStepData?q.getStepData():void 0),o.querySelectorAll(".wizard-next, .wizard-submit").forEach(r=>r.addEventListener("click",z,!0))};q=F.wizard(o,{schema:{steps:m},layout:d,columns:a,finishText:e.submitText||"Finish",onSubmit:i,onStepChange:I=>{C=I,setTimeout(B,0)}}),o.addEventListener("dm-form-trigger",I=>{if(I.detail?.type!=="goto-step"||!q?.goToStep)return;const r=Number(I.detail.action.step);!Number.isFinite(r)||r<0||r>=m.length||r!==C&&q.goToStep(r)}),Promise.resolve(q).then(B)}else if(F.render){const p=F.render(o,y(t,a),k(t),{submitText:e.submitText||"Submit",layout:d,columns:a,onSubmit:i});Promise.resolve(p).then(function(){de(o,e,d),Z(o,e,t),w(o,t),G(o,t),e.honeypot!==!1&&g(o),b()})}})})();function ue(h,c){const x=document.body,y=x.classList,k=new Set((x.dataset.railSite||"").split(" ").filter(Boolean)),w=()=>window.matchMedia("(min-width: 993px)").matches;h.querySelectorAll(".navbar-link, .navbar-dropdown-toggle").forEach(a=>{const d=a.textContent.trim();d&&(a.setAttribute("title",d),a.querySelector("svg, [data-icon]")||(a.dataset.initial=d.charAt(0).toUpperCase()))});const n=document.createElement("button");n.type="button",n.className="dm-nav-collapse-toggle";const o=()=>{const a=y.contains("dm-vnav-collapsed");n.setAttribute("aria-pressed",String(a)),n.setAttribute("aria-label",a?"Expand menu":"Collapse menu"),n.title=n.getAttribute("aria-label");const d=c?"chevrons-left":"chevrons-right",f=c?"chevrons-right":"chevrons-left";n.innerHTML=`<span data-icon="${a?d:f}"></span>`,window.Domma&&Domma.icons&&Domma.icons.scan(n)},s=a=>{y.toggle("dm-vnav-collapsed",a),S.set("nav_collapsed",a),o()};n.addEventListener("click",()=>s(!y.contains("dm-vnav-collapsed"))),o();const t=h.querySelector(".navbar-container")||h;t.insertBefore(n,t.firstChild?.nextSibling||null);const e=a=>{y.toggle("dm-vnav-autohide",a),y.toggle("dm-vnav-collapsible",!a&&k.has("collapsible")),a?y.remove("dm-vnav-collapsed"):k.has("collapsible")&&S.get("nav_collapsed")===!0&&y.add("dm-vnav-collapsed"),h.classList.remove("dm-nav-revealed"),o()};h.addEventListener("pointerdown",a=>{y.contains("dm-vnav-autohide")&&a.pointerType!=="mouse"&&!h.classList.contains("dm-nav-revealed")&&(h.classList.add("dm-nav-revealed"),a.preventDefault())}),document.addEventListener("pointerdown",a=>{h.contains(a.target)||h.classList.remove("dm-nav-revealed")}),window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const a=y.contains("dm-vnav-autohide"),d=y.contains("dm-vnav-collapsed"),f=S.has("nav_autohide")||S.has("nav_collapsed");return[{header:"Menu"},{label:d?"Expand menu":"Collapse to icons",icon:d?"maximize":"minimize",disabled:!w()||a||!k.has("collapsible"),action:()=>s(!d)},{label:a?"Keep on screen":"Hide when not in use",icon:a?"eye":"eye-off",disabled:!w(),action:()=>{S.set("nav_autohide",!a),e(!a)}},{type:"divider"},{label:"Reset to the site's setting",icon:"refresh",disabled:!f,action:()=>{S.remove("nav_autohide"),S.remove("nav_collapsed"),e(k.has("autohide")),y.toggle("dm-vnav-collapsed",!k.has("autohide")&&k.has("start-collapsed")),o()}}]}})}function pe(h){h.classList.add("dm-nav-scroll-hide");let c=window.scrollY,x=!1;window.addEventListener("scroll",()=>{x||(x=!0,requestAnimationFrame(()=>{x=!1;const y=window.scrollY,k=h.matches(":focus-within")||h.querySelector(".navbar-dropdown.open, .navbar-collapse.show");y>c&&y>h.offsetHeight&&!k?h.classList.add("dm-nav-scrolled-away"):y<c&&h.classList.remove("dm-nav-scrolled-away"),c=y}))},{passive:!0})}function he(h){let c={};try{c=JSON.parse(h.dataset.contents||"{}")}catch{}const x=h.closest(".site-main"),y=document.querySelector(".site-content"),k=new Set(String(c.exclude||"").split(",").map(i=>i.trim().toLowerCase()).filter(Boolean)),w=i=>!i.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),n=i=>(y?[...y.querySelectorAll(i)]:[]).filter(w).filter(l=>!k.has(l.textContent.trim().toLowerCase())),o=c.headings==="h2"?n("h2"):c.headings==="h3"?n("h3"):c.headings==="h2h3"?n("h2, h3"):n("h2").length?n("h2"):n("h3");if(!o.length){x?.classList.add("no-sidebar-items");return}const s=new Set([...document.querySelectorAll("[id]")].map(i=>i.id)),t=document.createElement("nav");t.className="dm-contents",t.setAttribute("aria-label",c.title||"Page contents"),c.hover&&(t.dataset.menuHover=c.hover),c.selected&&(t.dataset.menuActive=c.selected),c.accent&&t.style.setProperty("--dm-menu-highlight",c.accent.startsWith("#")?c.accent:`var(--dm-${c.accent})`),c.font&&(t.style.fontFamily=c.font),c.fontSize&&(t.style.fontSize=c.fontSize),c.fontWeight&&(t.style.fontWeight=c.fontWeight);const e=document.createElement("div");e.className="dm-contents-head";const a=document.createElement("p");a.className="dm-contents-title",a.textContent=c.title||"",e.appendChild(a),t.appendChild(e);const d=document.createElement("ol");d.className="dm-contents-list"+(c.numbered?" is-numbered":"");const f=[];for(const i of o){if(!i.id){const b=(i.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let u=b;for(let p=2;s.has(u);p++)u=`${b}-${p}`;s.add(u),i.id=u}const l=document.createElement("li");l.className=`dm-contents-item dm-contents-${i.tagName.toLowerCase()}`;const g=document.createElement("a");g.href=`#${i.id}`,g.textContent=i.textContent.trim(),l.appendChild(g),d.appendChild(l),f.push([i,g])}if(t.appendChild(d),h.replaceChildren(t),c.scrollSpy!==!1&&"IntersectionObserver"in window){const i=new Map,l=()=>{const b=f.find(([u])=>i.get(u))||null;f.forEach(([,u])=>{const p=b&&u===b[1];u.classList.toggle("is-active",!!p),p?u.setAttribute("aria-current","location"):u.removeAttribute("aria-current")})},g=new IntersectionObserver(b=>{b.forEach(u=>i.set(u.target,u.isIntersecting)),l()},{rootMargin:"-80px 0px -60% 0px"});f.forEach(([b])=>g.observe(b))}if(x?.classList.contains("contents-collapsible")){const i=document.createElement("button");i.type="button",i.className="dm-contents-toggle";const l=()=>{const g=x.classList.contains("contents-collapsed");i.setAttribute("aria-expanded",String(!g)),i.setAttribute("aria-label",g?"Show the contents":"Hide the contents"),i.title=i.getAttribute("aria-label"),i.innerHTML=`<span data-icon="${g?"list":"x"}"></span>`,window.Domma?.icons&&Domma.icons.scan(i)};i.addEventListener("click",()=>{S.set("contents_collapsed",x.classList.toggle("contents-collapsed")),l()}),l(),e.insertBefore(i,e.firstChild)}if(x?.classList.contains("contents-floating")&&c.movable){t.classList.add("is-movable");const i=S.get("contents_position");i&&Number.isFinite(i.x)&&Object.assign(h.style,{left:`${i.x}px`,top:`${i.y}px`,right:"auto",bottom:"auto"}),e.addEventListener("pointerdown",l=>{if(l.target.closest("button"))return;const g=h.getBoundingClientRect(),b=l.clientX-g.left,u=l.clientY-g.top,p=v=>{const C=Math.max(0,Math.min(window.innerWidth-g.width,v.clientX-b)),A=Math.max(0,Math.min(window.innerHeight-40,v.clientY-u));Object.assign(h.style,{left:`${C}px`,top:`${A}px`,right:"auto",bottom:"auto"})},m=()=>{document.removeEventListener("pointermove",p),S.set("contents_position",{x:parseInt(h.style.left,10),y:parseInt(h.style.top,10)})};document.addEventListener("pointermove",p),document.addEventListener("pointerup",m,{once:!0})})}window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const i=x?.classList.contains("contents-collapsible"),l=x?.classList.contains("contents-collapsed"),g=f.find(([,b])=>b.classList.contains("is-active"));return[{header:"Contents"},...i?[{label:l?"Show the contents":"Collapse to a button",icon:l?"list":"minimize",action:()=>h.querySelector(".dm-contents-toggle")?.click()}]:[],{label:"Copy a link to this section",icon:"link",disabled:!g,action:async()=>{const b=`${location.origin}${location.pathname}#${g[0].id}`;try{await _.copyToClipboard(b),E.toast("Link copied.",{type:"success"})}catch{E.toast("Could not copy the link.",{type:"error"})}}},{label:"Back to the top",icon:"arrow-up",action:()=>window.scrollTo({top:0,behavior:"smooth"})}]}}),x?.classList.contains("contents-autohide")&&(h.addEventListener("pointerdown",i=>{i.pointerType!=="mouse"&&!h.classList.contains("is-revealed")&&(h.classList.add("is-revealed"),i.preventDefault())}),document.addEventListener("pointerdown",i=>{h.contains(i.target)||h.classList.remove("is-revealed")}))}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const r=Object.freeze({refresh(){},destroy(){}}),t=()=>globalThis.Domma?.smoothCaret;export const attachSmoothCaret=e=>t()?.attach(e)||r,installSmoothCarets=e=>t()?.install(e)||r,getCaretPreference=()=>t()?.getPreference()||"auto",setCaretPreference=e=>t()?.setPreference(e);
|
|
@@ -33,6 +33,7 @@ export const SEARCH_DEFAULTS = Object.freeze({
|
|
|
33
33
|
position: 'right-center',
|
|
34
34
|
offsetX: 32,
|
|
35
35
|
offsetY: 32,
|
|
36
|
+
triggerStyle: 'icon',
|
|
36
37
|
iconOnly: true,
|
|
37
38
|
iconSize: 52,
|
|
38
39
|
iconRadius: 26
|
|
@@ -101,7 +102,7 @@ export function normaliseSearchSettings(raw = {}) {
|
|
|
101
102
|
return {
|
|
102
103
|
enabled: raw.enabled !== false,
|
|
103
104
|
placeholder,
|
|
104
|
-
keyboardShortcut:
|
|
105
|
+
keyboardShortcut: true,
|
|
105
106
|
maxResults: num(raw.maxResults, SEARCH_DEFAULTS.maxResults, 1, 50),
|
|
106
107
|
minQueryLength: num(raw.minQueryLength, SEARCH_DEFAULTS.minQueryLength, 1, 5),
|
|
107
108
|
debounceMs: num(raw.debounceMs, SEARCH_DEFAULTS.debounceMs, 100, 1000),
|
|
@@ -109,7 +110,10 @@ export function normaliseSearchSettings(raw = {}) {
|
|
|
109
110
|
position: POSITIONS.has(raw.position) ? raw.position : SEARCH_DEFAULTS.position,
|
|
110
111
|
offsetX: num(raw.offsetX, SEARCH_DEFAULTS.offsetX, 0, 500),
|
|
111
112
|
offsetY: num(raw.offsetY, SEARCH_DEFAULTS.offsetY, 0, 500),
|
|
112
|
-
|
|
113
|
+
triggerStyle: ['icon-text', 'icon', 'hidden'].includes(raw.triggerStyle)
|
|
114
|
+
? raw.triggerStyle : (raw.iconOnly === false ? 'icon-text' : 'icon'),
|
|
115
|
+
iconOnly: raw.triggerStyle === 'icon-text' ? false
|
|
116
|
+
: ['icon', 'hidden'].includes(raw.triggerStyle) ? true : raw.iconOnly !== false,
|
|
113
117
|
iconSize,
|
|
114
118
|
iconRadius: Math.min(maxRadius, num(raw.iconRadius, SEARCH_DEFAULTS.iconRadius, 0, maxRadius))
|
|
115
119
|
};
|
|
@@ -572,7 +576,7 @@ export function searchBadge(settings = SEARCH_DEFAULTS, pages = [], exclusions =
|
|
|
572
576
|
const s = normaliseSearchSettings(settings);
|
|
573
577
|
const c = searchCoverage(pages, exclusions);
|
|
574
578
|
const pl = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
575
|
-
const trigger = s.displayMode === 'floating'
|
|
579
|
+
const trigger = s.triggerStyle === 'hidden' ? 'Hidden (keyboard shortcut available)' : s.displayMode === 'floating'
|
|
576
580
|
? `Floating button, ${s.position.replace('-', ' ')}`
|
|
577
581
|
: 'Icon in the navigation bar';
|
|
578
582
|
return {
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
</script>
|
|
174
174
|
|
|
175
175
|
<!-- Site initialisation -->
|
|
176
|
-
<script src="/public/js/site.js?v=20261015-
|
|
176
|
+
<script src="/public/js/site.js?v=20261015-smooth-caret" type="module"></script>
|
|
177
177
|
<script src="/public/js/collection-context.js?v=20261010-utf8-payloads" type="module"></script>
|
|
178
178
|
{{ctxMenusModule}}
|
|
179
179
|
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
|
|
189
189
|
<!-- Core Forms (logic engine must load before renderer) -->
|
|
190
190
|
<script src="/public/js/form-logic-engine.js?v=20260927-submit-btn"></script>
|
|
191
|
-
<script src="/public/js/forms.js?v=
|
|
191
|
+
<script src="/public/js/forms.js?v=20261015-smooth-caret" type="module"></script>
|
|
192
192
|
|
|
193
193
|
<!-- Core effects runtime -->
|
|
194
194
|
<script src="/public/js/effects.js?v=20261015-occasions"></script>
|