domma-cms 1.6.15 → 1.6.17
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/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/app.js +1 -1
- package/admin/js/lib/effect-defs.js +1 -1
- package/admin/js/lib/effects-builder.js +2 -2
- package/admin/js/lib/layouts-arrange.js +1 -1
- package/admin/js/lib/page-editor-reference.js +3 -3
- package/admin/js/lib/project-page-arrange.js +1 -1
- package/admin/js/lib/scribe-composer.js +1 -4
- package/admin/js/lib/scribe-model.js +4 -0
- package/admin/js/lib/sidebar-grouping.js +1 -1
- package/admin/js/lib/sidebar-renderer.js +2 -2
- package/admin/js/templates/docs/usage-navigation.html +4 -2
- package/admin/js/templates/effects.html +10 -4
- package/admin/js/templates/layouts.html +1 -1
- package/admin/js/views/layouts.js +8 -8
- package/package.json +2 -2
- package/public/css/site.css +1 -1
- package/public/js/effects.js +1 -1
- package/server/services/markdown.js +12 -6
- package/server/services/permissionRegistry.js +1 -1
- package/server/services/sidebar-migration.js +14 -1
- package/server/templates/page.html +2 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Domma Tools CSS v0.51.
|
|
2
|
+
* Domma Tools CSS v0.51.9
|
|
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-11T10:14:37.692Z
|
|
6
|
+
* Commit: c708495
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/*!
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Domma Tools v0.51.
|
|
2
|
+
* Domma Tools v0.51.9
|
|
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-11T10:14:22.712Z
|
|
6
|
+
* Commit: c708495
|
|
7
7
|
*
|
|
8
8
|
* Requires: domma.min.js
|
|
9
9
|
*/
|
package/admin/js/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{views as G}from"./views/index.js";import{withPluginChrome as B}from"./lib/plugin-chrome.js";import{api as c,getUser as F,isAuthenticated as m,logout as z,sendToLogin as K}from"./api.js";import{isAuthScreen as C,loginHashFor as J}from"./lib/login-arrange.js";import{installHttpInterceptor as Y}from"./http-interceptor.js";import{installResizableSlideovers as Q}from"./lib/slideover-resizable.js";import{installActivityThrobber as X}from"./lib/activity-throbber.js";import{isPathAllowed as Z,redirectFor as tt}from"./lib/admin-scope.js";import{deliverDesktop as et,desktopActive as it,notificationSettings as ot}from"./lib/desktop-notify.js";import{avatarUrl as at}from"./lib/avatar.js";import{installCalculator as st}from"./lib/calculator.js";import{takeOverviewPass as nt,withDashboardStrip as O}from"./lib/dashboards-strip.js";import{installHotkeys as lt}from"./lib/hotkeys-ui.js";$(()=>{Y(),st(),X(),Q(),(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,r="/",h=!1,w=null;function b(t){if(y[t])return E.toast(`${y[t]} is switched off on this site.`,{type:"info"}),"/";if(t.split("?")[0]==="/my-dashboard")return"/dashboards";const i=D[t]||tt(p,t);return i||((t.split("?")[0]||"/")==="/"&&r&&r!=="/"&&!nt()?D[r]||r:null)}const D={},y={};R.use(async(t,i,e)=>{if(C(t.path))return e();if(!m()){K();return}const o=b(t.path);if(o){R.navigate(o);return}e()});async function g(){try{const t=await c.get("/auth/permissions");p=t.adminScope||null,r=t.adminHome||"/";const i=t.permissions||[];return h=Z(p,"/settings")&&i.some(e=>e==="settings"||e.startsWith("settings.")),w=i.some(e=>e==="notifications"||e.startsWith("notifications.")),i}catch{return p=null,r="/",h=!1,w=null,[]}}document.addEventListener("dm:admin-home-changed",()=>{g()});let P=null,N=!1;document.addEventListener("dm:sidebar-rebuild",()=>{if(P){N=!0;return}P=(async()=>{do{N=!1;try{await A(await g())}catch{}}while(N)})().finally(()=>{P=null})});async function A(t){const{renderAdminSidebar:i}=await import("./lib/sidebar-renderer.js");await i({mount:"#admin-sidebar",permissions:t,adminScope:p})}M.subscribe("router:afterChange",({to:t})=>{C(t.path)&&(u&&(clearInterval(u),u=null),p=null,r="/",h=!1,w=null)});const _=[{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 Plugin - 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/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:"/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(!C(t.path)){if($("#admin-sidebar").show(),$("#admin-topbar").show(),C(i?.path)){$("#topbar-user-name").remove(),import("./lib/admin-theme.js").then(a=>a.refreshAdminTheme(c)),await I();const e=await g(),o=b(t.path);if(o&&R.navigate(o),A(e),ot.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 f=d(s.data?.title||""),U=d((s.data?.body||"").slice(0,120));E.toast(`${f} - ${U}`,{type:s.data?.severity==="critical"?"error":"warning",duration:0})}}catch{}}T()}}),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 V=["#field-project","#menu-project","#collection-project","#endpoint-project","#action-project","#view-project","#block-project","#component-project","#role-project",'[name="project"]','[name="ownedByProject"]'];function W(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||!W(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,f=()=>{a+=n;for(const U of V){const v=document.querySelector(U);if(!v)continue;if(Array.from(v.options||[]).find(q=>q.value===o)){v.value=o,v.dispatchEvent(new Event("change",{bubbles:!0}));return}}a<s&&setTimeout(f,n)};setTimeout(f,n)});const x="cms_card_states",j=S.get(x)||{};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&&j[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&&(j[e]=i.hasClass("card-collapsed")?"collapsed":"open",S.set(x,j))}),lt(),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 l={...G},H={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"},contacts:{displayName:"Contacts",icon:"users"},projects:{displayName:"Projects",icon:"folder"},pages:{displayName:"Pages",icon:"file-text"},media:{displayName:"Media",icon:"image"},menus:{displayName:"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:"Menus",section:"Edit",icon:"menu"},menuLocations:{displayName:"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(H))l[t]&&(l[t]=B(l[t],{plugin:t,licence:"Built in",...i}));l.dashboard=O(l.dashboard);const k=[..._];async function I(){if(m())try{const t=await c.plugins.adminConfig(),i=new Set(k.map(e=>e.path));for(const e of t.routes||[])i.has(e.path)||k.push(e);for(const[e,o]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${o.entry}`);l[e]=B(a[o.exportName],(t.meta||{})[e])}catch{}l.dashboard=O(l.dashboard);for(const[e,{route:o}]of Object.entries(t.takeovers||{}))o&&(D[`/${e}`]=o);for(const[e,{enabled:o,displayName:a}]of Object.entries(t.tools||{}))o===!1&&(y[`/${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 T(){const t=F();if(!t||$("#topbar-user-name").length)return;const e={"super-admin":"Super Admin",admin:"Admin",user:"User"}[t.role]||t.role,o=at(t);$("#topbar-user").html(`
|
|
1
|
+
import{views as G}from"./views/index.js";import{withPluginChrome as B}from"./lib/plugin-chrome.js";import{api as c,getUser as F,isAuthenticated as m,logout as z,sendToLogin as K}from"./api.js";import{isAuthScreen as C,loginHashFor as J}from"./lib/login-arrange.js";import{installHttpInterceptor as Y}from"./http-interceptor.js";import{installResizableSlideovers as Q}from"./lib/slideover-resizable.js";import{installActivityThrobber as X}from"./lib/activity-throbber.js";import{isPathAllowed as Z,redirectFor as tt}from"./lib/admin-scope.js";import{deliverDesktop as et,desktopActive as it,notificationSettings as ot}from"./lib/desktop-notify.js";import{avatarUrl as at}from"./lib/avatar.js";import{installCalculator as st}from"./lib/calculator.js";import{takeOverviewPass as nt,withDashboardStrip as O}from"./lib/dashboards-strip.js";import{installHotkeys as lt}from"./lib/hotkeys-ui.js";$(()=>{Y(),st(),X(),Q(),(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,r="/",h=!1,w=null;function b(t){if(y[t])return E.toast(`${y[t]} is switched off on this site.`,{type:"info"}),"/";if(t.split("?")[0]==="/my-dashboard")return"/dashboards";const i=D[t]||tt(p,t);return i||((t.split("?")[0]||"/")==="/"&&r&&r!=="/"&&!nt()?D[r]||r:null)}const D={},y={};R.use(async(t,i,e)=>{if(C(t.path))return e();if(!m()){K();return}const o=b(t.path);if(o){R.navigate(o);return}e()});async function g(){try{const t=await c.get("/auth/permissions");p=t.adminScope||null,r=t.adminHome||"/";const i=t.permissions||[];return h=Z(p,"/settings")&&i.some(e=>e==="settings"||e.startsWith("settings.")),w=i.some(e=>e==="notifications"||e.startsWith("notifications.")),i}catch{return p=null,r="/",h=!1,w=null,[]}}document.addEventListener("dm:admin-home-changed",()=>{g()});let P=null,N=!1;document.addEventListener("dm:sidebar-rebuild",()=>{if(P){N=!0;return}P=(async()=>{do{N=!1;try{await A(await g())}catch{}}while(N)})().finally(()=>{P=null})});async function A(t){const{renderAdminSidebar:i}=await import("./lib/sidebar-renderer.js");await i({mount:"#admin-sidebar",permissions:t,adminScope:p})}M.subscribe("router:afterChange",({to:t})=>{C(t.path)&&(u&&(clearInterval(u),u=null),p=null,r="/",h=!1,w=null)});const _=[{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 Plugin - 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/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:"/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(!C(t.path)){if($("#admin-sidebar").show(),$("#admin-topbar").show(),C(i?.path)){$("#topbar-user-name").remove(),import("./lib/admin-theme.js").then(a=>a.refreshAdminTheme(c)),await I();const e=await g(),o=b(t.path);if(o&&R.navigate(o),A(e),ot.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 f=d(s.data?.title||""),U=d((s.data?.body||"").slice(0,120));E.toast(`${f} - ${U}`,{type:s.data?.severity==="critical"?"error":"warning",duration:0})}}catch{}}T()}}),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 V=["#field-project","#menu-project","#collection-project","#endpoint-project","#action-project","#view-project","#block-project","#component-project","#role-project",'[name="project"]','[name="ownedByProject"]'];function W(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||!W(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,f=()=>{a+=n;for(const U of V){const v=document.querySelector(U);if(!v)continue;if(Array.from(v.options||[]).find(q=>q.value===o)){v.value=o,v.dispatchEvent(new Event("change",{bubbles:!0}));return}}a<s&&setTimeout(f,n)};setTimeout(f,n)});const x="cms_card_states",j=S.get(x)||{};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&&j[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&&(j[e]=i.hasClass("card-collapsed")?"collapsed":"open",S.set(x,j))}),lt(),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 l={...G},H={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"},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(H))l[t]&&(l[t]=B(l[t],{plugin:t,licence:"Built in",...i}));l.dashboard=O(l.dashboard);const k=[..._];async function I(){if(m())try{const t=await c.plugins.adminConfig(),i=new Set(k.map(e=>e.path));for(const e of t.routes||[])i.has(e.path)||k.push(e);for(const[e,o]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${o.entry}`);l[e]=B(a[o.exportName],(t.meta||{})[e])}catch{}l.dashboard=O(l.dashboard);for(const[e,{route:o}]of Object.entries(t.takeovers||{}))o&&(D[`/${e}`]=o);for(const[e,{enabled:o,displayName:a}]of Object.entries(t.tools||{}))o===!1&&(y[`/${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 T(){const t=F();if(!t||$("#topbar-user-name").length)return;const e={"super-admin":"Super Admin",admin:"Admin",user:"User"}[t.role]||t.role,o=at(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>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCharacters as f}from"../../../public/js/celebrations/character-catalog.mjs";import{CELEBRATION_THEMES as i,traitAttribute as p}from"../../../public/js/celebrations/trait-data.mjs";export{i as CELEBRATION_THEMES};export const EFFECTS=[{name:"reveal",label:"Reveal",category:"Entrance",description:"Scroll-triggered entrance animation when the element enters the viewport.",attrs:[{name:"animation",label:"Animation",type:"select",default:"fade",options:[["fade","Fade"],["slide-up","Slide up"],["slide-down","Slide down"],["zoom","Zoom"],["flip","Flip"]]},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"threshold",label:"Threshold",type:"number",default:.1,step:.05,min:0,max:1},{name:"once",label:"Animate once",type:"checkbox",default:!0}],hosts:["card","box","hero","banner","col"],previewable:!0},{name:"breathe",label:"Breathe",category:"Animation",description:"Continuous gentle scaling - makes elements feel alive.",attrs:[{name:"amplitude",label:"Amplitude (px)",type:"number",default:8},{name:"duration",label:"Duration (ms)",type:"number",default:3e3}],hosts:["card","box","hero","col","button"],previewable:!0},{name:"pulse",label:"Pulse",category:"Animation",description:"A repeating scale pulse - stronger than breathe.",attrs:[{name:"scale",label:"Scale",type:"number",default:1.05,step:.01},{name:"duration",label:"Duration (ms)",type:"number",default:1e3}],hosts:["card","box","hero","banner","button"],previewable:!0},{name:"shake",label:"Shake",category:"Animation",description:"One-shot horizontal or vertical shake.",attrs:[{name:"intensity",label:"Intensity (px)",type:"number",default:5},{name:"duration",label:"Duration (ms)",type:"number",default:500},{name:"direction",label:"Direction",type:"select",default:"horizontal",options:[["horizontal","Horizontal"],["vertical","Vertical"]]}],hosts:["card","box","banner","button"],previewable:!0},{name:"animate",label:"CSS Animate",category:"Animation",description:"Applies a Domma CSS animation utility class - no JavaScript.",attrs:[{name:"type",label:"Type",type:"select",default:"fade-in-up",options:[["fade-in","fade-in"],["fade-in-up","fade-in-up"],["fade-in-down","fade-in-down"],["fade-in-left","fade-in-left"],["fade-in-right","fade-in-right"],["slide-in-up","slide-in-up"],["slide-in-down","slide-in-down"],["zoom-in","zoom-in"],["zoom-out","zoom-out"],["bounce","bounce"],["pulse","pulse"],["shake","shake"],["spin","spin"],["flip","flip"]]},{name:"duration",label:"Duration",type:"select",default:"normal",options:[["fast","fast"],["normal","normal"],["slow","slow"],["slower","slower"]]},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"repeat",label:"Repeat",type:"select",default:"once",options:[["once","Once"],["infinite","Infinite"]]}],hosts:["card","box","hero","banner","col","button"],previewable:!0},{name:"scribe",label:"Scribe (typewriter)",category:"Text",description:"Types text character by character. Simple mode only - for the action-script composer use Insert \u2192 Scribe.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"cursor",label:"Show cursor",type:"checkbox",default:!0},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"scramble",label:"Scramble",category:"Text",description:"Reveals text through a character-scramble animation.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"counter",label:"Counter",category:"Text",description:"Animates a number from a starting value to a target. Self-closing shortcode.",attrs:[{name:"to",label:"To",type:"number",default:100},{name:"from",label:"From",type:"number",default:0},{name:"duration",label:"Duration (ms)",type:"number",default:2e3},{name:"prefix",label:"Prefix",type:"text",default:""},{name:"suffix",label:"Suffix",type:"text",default:""},{name:"decimals",label:"Decimal places",type:"number",default:0},{name:"separator",label:"Thousand separator",type:"text",default:""}],hosts:[],previewable:!0,selfClosing:!0},{name:"ripple",label:"Ripple",category:"Visual",description:"Click-triggered ripple effect on the element.",attrs:[{name:"colour",label:"Colour",type:"colour",default:"#7c6af7"},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"opacity",label:"Opacity",type:"number",default:.3,step:.05,min:0,max:1}],hosts:["card","box","col","button"],previewable:!0},{name:"twinkle",label:"Twinkle",category:"Visual",description:"Generates animated particle effects inside the element.",attrs:[{name:"count",label:"Particle count",type:"number",default:80},{name:"shape",label:"Shape",type:"select",default:"star",options:[["star","Star"],["circle","Circle"],["square","Square"]]},{name:"colour",label:"Colour",type:"colour",default:"#ffffff"},{name:"min-size",label:"Min size (px)",type:"number",default:2},{name:"max-size",label:"Max size (px)",type:"number",default:6}],hosts:["card","box","hero"],previewable:!0},{name:"ambient",label:"Ambient background",category:"Visual",description:"Applies an animated CSS background class to the element.",attrs:[{name:"type",label:"Type",type:"select",default:"float-blobs",options:[["float-blobs","Float blobs"],["float-orbs","Float orbs"],["float-particles","Float particles"],["rotate-glow","Rotate glow"],["rotate-dual","Rotate dual"],["rotate-spotlight","Rotate spotlight"],["wave","Wave"],["ripple","Ripple"],["aurora","Aurora"]]},{name:"speed",label:"Speed",type:"select",default:"normal",options:[["slow","Slow"],["normal","Normal"],["fast","Fast"]]},{name:"intensity",label:"Intensity",type:"select",default:"subtle",options:[["subtle","Subtle"],["intense","Intense"]]}],hosts:["card","box","hero","banner"],previewable:!0},{name:"firework",label:"Firework",category:"Celebrations",description:"CSS-only firework particle. Self-closing or wrapping form.",attrs:[{name:"type",label:"Type",type:"select",default:"burst",options:[["burst","Burst"],["sparkle","Sparkle"],["trail","Trail"]]},{name:"colour",label:"Colour theme",type:"select",default:"rainbow",options:[["rainbow","Rainbow"],["primary","Primary"],["info","Info"],["success","Success"],["warning","Warning"],["danger","Danger"]]},{name:"size",label:"Size",type:"select",default:"md",options:[["sm","Small"],["md","Medium"],["lg","Large"]]},{name:"continuous",label:"Continuous",type:"checkbox",default:!1},{name:"hover",label:"On hover only",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"fireworks",label:"Fireworks show",category:"Celebrations",description:"A container with multiple firework particles inside.",attrs:[],hosts:[],previewable:!1},{name:"celebrate",label:"Celebrate",category:"Celebrations",description:"A full-page seasonal celebration, or one inline character at any time of year.",attrs:[{name:"theme",label:"Theme",type:"select",default:"auto",options:[["auto","Auto (date-detected)"],["christmas","Christmas"],["halloween","Halloween"],["valentines","Valentines"],["guy-fawkes","Guy Fawkes"],["st-patricks","St Patrick's"],["st-davids","St David's"],["st-georges","St George's"],["st-andrews","St Andrew's"]]},{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only (Christmas)",type:"checkbox",default:!1,hint:"Just the falling snow - every Christmas decoration off."},{name:"trees",label:"Christmas: trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"Christmas: wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"Christmas: North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"Christmas: snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Christmas: Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"Christmas: elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"Christmas: train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"Christmas: fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"Christmas: robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"christmas",label:"Christmas",category:"Celebrations",description:"Christmas on the published site: snow, trees, wreaths, snowmen, Santa's sleigh and more. Snow only for just the snow.",attrs:[{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only",type:"checkbox",default:!1,hint:"Just the falling snow - every decoration off."},{name:"trees",label:"trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"ticker-tape",label:"Ticker tape",category:"Celebrations",description:"Coloured rectangular strips fall from the top, sway, rotate, and fade. Inserted self-closing (full-page); hand-write the wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"theme",options:[["theme","Theme"],["rainbow","Rainbow"],["gold","Gold"],["silver","Silver"],["festive","Festive"],["pastel","Pastel"],["mono","Mono"]]},{name:"density",label:"Density",type:"number",default:50},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sway",label:"Sway (px)",type:"number",default:60},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:150}],hosts:["hero"],previewable:!0,selfClosing:!0},{name:"butterflies",label:"Butterflies",category:"Celebrations",description:"Procedurally drawn butterflies wander and rise with flapping wings. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"meadow",options:[["meadow","Meadow"],["theme","Theme"],["rainbow","Rainbow"],["pastel","Pastel"],["festive","Festive"],["gold","Gold"],["silver","Silver"],["mono","Mono"],["sunset","Sunset"],["ocean","Ocean"],["forest","Forest"],["bridal","Bridal"],["firefly","Firefly"]]},{name:"density",label:"Density",type:"number",default:18},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"wander",label:"Wander",type:"number",default:1,step:.1,hint:"Steering erraticness"},{name:"rise-speed",label:"Rise speed",type:"number",default:.4,step:.1,hint:"Upward drift bias"},{name:"flap-speed",label:"Flap speed",type:"number",default:1,step:.1},{name:"min-size",label:"Min wingspan (px)",type:"number",default:14},{name:"max-size",label:"Max wingspan (px)",type:"number",default:26},{name:"two-tone",label:"Two-tone wings",type:"checkbox",default:!0},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:40}],hosts:["hero"],previewable:!0},{name:"strobe",label:"Strobe lighting",category:"Celebrations",description:"Light beams sweep from the corners and brighten where they cross - club, concert, or searchlight moods. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"preset",label:"Preset",type:"select",default:"club",options:[["club","Club"],["concert","Concert"],["police","Police"],["searchlight","Searchlight"],["scanner","Scanner"],["mood","Mood"]],hint:"Other fields override the preset when changed"},{name:"motion",label:"Motion",type:"select",default:"sweep",options:[["sweep","Sweep (fan back and forth)"],["rotate","Rotate (full circle)"]]},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sweep-arc",label:"Sweep arc (deg)",type:"number",default:100},{name:"beam-width",label:"Beam width (deg)",type:"number",default:16},{name:"intensity",label:"Intensity",type:"number",default:.7,step:.05,min:0,max:1},{name:"flicker",label:"Flicker",type:"checkbox",default:!0},{name:"hz",label:"Flicker rate (Hz)",type:"number",default:10,hint:"Rates above 5 flashes/sec can trigger photosensitive seizures"},{name:"colours",label:"Colours",type:"text",default:"",placeholder:"#ffffff, #38bdf8",hint:"Comma-separated hex colours - overrides the preset palette"},{name:"duration",label:"Auto-stop (ms)",type:"number",default:"",hint:"Stop after this many ms - blank runs forever"}],hosts:["hero"],previewable:!0}];export function getEffect(e){return EFFECTS.find(t=>t.name===e)||null}export function effectsByCategory(){return["Entrance","Animation","Text","Visual","Celebrations"].map(t=>({category:t,effects:EFFECTS.filter(o=>o.category===t)}))}export function effectsInjectableInto(e){return EFFECTS.filter(t=>t.hosts.includes(e))}const n=EFFECTS.find(e=>e.name==="celebrate");for(const e of n.attrs.slice(2))e.themes=["christmas"];n.attrs.push({name:"character",label:"Standalone character",type:"select",default:"",options:[["","Full celebration"],...f().map(e=>[e.name,e.label])]},{name:"size",label:"Character height",type:"text",default:"medium",placeholder:"medium or 200",hint:"small (96px), medium (160px), large (240px), xlarge (360px), or a height in pixels."},{name:"animate",label:"Animate character",type:"checkbox",default:!0},{name:"facing",label:"Character direction",type:"select",default:"right",options:[["right","Right"],["left","Left"]]}),n.attrs.push({name:"falling-only",label:"Falling particles only",type:"checkbox",default:!1}),n.attrs.push({name:"mooning-elf",label:"Mooning elf (opt-in)",type:"checkbox",default:!1,themes:["christmas"]}),EFFECTS.find(e=>e.name==="christmas").attrs.push({name:"mooning-elf",label:"Mooning elf (opt-in)",type:"checkbox",default:!1});const s=new Map(n.attrs.map(e=>[e.name,e]));for(const[e,t]of Object.entries(i))if(e!=="christmas")for(const[o,r]of Object.entries(t.traits)){const a=p(o);let l=s.get(a);l||(l=r.enabled===!1?{name:a,label:`${r.label} (opt-in)`,type:"checkbox",default:!1,themes:[]}:{name:a,label:r.label,type:"select",default:"",options:[["","Shown"],["off","Off"]],themes:[]},s.set(a,l)),l.themes.includes(e)||l.themes.push(e),l.themes.length>1&&(l.label=l.label.replace(/^Christmas: /,""))}for(const e of s.values())n.attrs.includes(e)||n.attrs.push(e);export function getEffectAttrs(e,t={}){if(e.name!=="celebrate")return e.attrs||[];const o=["character","size","animate","facing"];if(t.character)return e.attrs.filter(a=>o.includes(a.name));const r=t.theme||"auto";return e.attrs.filter(a=>(a.name==="character"||!o.includes(a.name))&&(!a.themes||r==="auto"||a.themes.includes(r)))}
|
|
1
|
+
import{SCRIBE_FIELDS as f}from"./scribe-model.js";import{getCharacters as p}from"../../../public/js/celebrations/character-catalog.mjs";import{CELEBRATION_THEMES as i,traitAttribute as m}from"../../../public/js/celebrations/trait-data.mjs";export{i as CELEBRATION_THEMES};export const EFFECTS=[{name:"reveal",label:"Reveal",category:"Entrance",description:"Scroll-triggered entrance animation when the element enters the viewport.",attrs:[{name:"animation",label:"Animation",type:"select",default:"fade",options:[["fade","Fade"],["slide-up","Slide up"],["slide-down","Slide down"],["zoom","Zoom"],["flip","Flip"]]},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"threshold",label:"Threshold",type:"number",default:.1,step:.05,min:0,max:1},{name:"once",label:"Animate once",type:"checkbox",default:!0}],hosts:["card","box","hero","banner","col"],previewable:!0},{name:"breathe",label:"Breathe",category:"Animation",description:"Continuous gentle scaling - makes elements feel alive.",attrs:[{name:"amplitude",label:"Amplitude (px)",type:"number",default:8},{name:"duration",label:"Duration (ms)",type:"number",default:3e3}],hosts:["card","box","hero","col","button"],previewable:!0},{name:"pulse",label:"Pulse",category:"Animation",description:"A repeating scale pulse - stronger than breathe.",attrs:[{name:"scale",label:"Scale",type:"number",default:1.05,step:.01},{name:"duration",label:"Duration (ms)",type:"number",default:1e3}],hosts:["card","box","hero","banner","button"],previewable:!0},{name:"shake",label:"Shake",category:"Animation",description:"One-shot horizontal or vertical shake.",attrs:[{name:"intensity",label:"Intensity (px)",type:"number",default:5},{name:"duration",label:"Duration (ms)",type:"number",default:500},{name:"direction",label:"Direction",type:"select",default:"horizontal",options:[["horizontal","Horizontal"],["vertical","Vertical"]]}],hosts:["card","box","banner","button"],previewable:!0},{name:"animate",label:"CSS Animate",category:"Animation",description:"Applies a Domma CSS animation utility class - no JavaScript.",attrs:[{name:"type",label:"Type",type:"select",default:"fade-in-up",options:[["fade-in","fade-in"],["fade-in-up","fade-in-up"],["fade-in-down","fade-in-down"],["fade-in-left","fade-in-left"],["fade-in-right","fade-in-right"],["slide-in-up","slide-in-up"],["slide-in-down","slide-in-down"],["zoom-in","zoom-in"],["zoom-out","zoom-out"],["bounce","bounce"],["pulse","pulse"],["shake","shake"],["spin","spin"],["flip","flip"]]},{name:"duration",label:"Duration",type:"select",default:"normal",options:[["fast","fast"],["normal","normal"],["slow","slow"],["slower","slower"]]},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"repeat",label:"Repeat",type:"select",default:"once",options:[["once","Once"],["infinite","Infinite"]]}],hosts:["card","box","hero","banner","col","button"],previewable:!0},{name:"scribe",label:"Scribe (typewriter)",category:"Text",description:"Types characters, words, or sentences with entrance effects and playback options. For action scripts use Insert \u2192 Scribe.",attrs:f,hosts:[],previewable:!0},{name:"scramble",label:"Scramble",category:"Text",description:"Reveals text through a character-scramble animation.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"counter",label:"Counter",category:"Text",description:"Animates a number from a starting value to a target. Self-closing shortcode.",attrs:[{name:"to",label:"To",type:"number",default:100},{name:"from",label:"From",type:"number",default:0},{name:"duration",label:"Duration (ms)",type:"number",default:2e3},{name:"prefix",label:"Prefix",type:"text",default:""},{name:"suffix",label:"Suffix",type:"text",default:""},{name:"decimals",label:"Decimal places",type:"number",default:0},{name:"separator",label:"Thousand separator",type:"text",default:""}],hosts:[],previewable:!0,selfClosing:!0},{name:"ripple",label:"Ripple",category:"Visual",description:"Click-triggered ripple effect on the element.",attrs:[{name:"colour",label:"Colour",type:"colour",default:"#7c6af7"},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"opacity",label:"Opacity",type:"number",default:.3,step:.05,min:0,max:1}],hosts:["card","box","col","button"],previewable:!0},{name:"twinkle",label:"Twinkle",category:"Visual",description:"Generates animated particle effects inside the element.",attrs:[{name:"count",label:"Particle count",type:"number",default:80},{name:"shape",label:"Shape",type:"select",default:"star",options:[["star","Star"],["circle","Circle"],["square","Square"]]},{name:"colour",label:"Colour",type:"colour",default:"#ffffff"},{name:"min-size",label:"Min size (px)",type:"number",default:2},{name:"max-size",label:"Max size (px)",type:"number",default:6}],hosts:["card","box","hero"],previewable:!0},{name:"ambient",label:"Ambient background",category:"Visual",description:"Applies an animated CSS background class to the element.",attrs:[{name:"type",label:"Type",type:"select",default:"float-blobs",options:[["float-blobs","Float blobs"],["float-orbs","Float orbs"],["float-particles","Float particles"],["rotate-glow","Rotate glow"],["rotate-dual","Rotate dual"],["rotate-spotlight","Rotate spotlight"],["wave","Wave"],["ripple","Ripple"],["aurora","Aurora"]]},{name:"speed",label:"Speed",type:"select",default:"normal",options:[["slow","Slow"],["normal","Normal"],["fast","Fast"]]},{name:"intensity",label:"Intensity",type:"select",default:"subtle",options:[["subtle","Subtle"],["intense","Intense"]]}],hosts:["card","box","hero","banner"],previewable:!0},{name:"firework",label:"Firework",category:"Celebrations",description:"CSS-only firework particle. Self-closing or wrapping form.",attrs:[{name:"type",label:"Type",type:"select",default:"burst",options:[["burst","Burst"],["sparkle","Sparkle"],["trail","Trail"]]},{name:"colour",label:"Colour theme",type:"select",default:"rainbow",options:[["rainbow","Rainbow"],["primary","Primary"],["info","Info"],["success","Success"],["warning","Warning"],["danger","Danger"]]},{name:"size",label:"Size",type:"select",default:"md",options:[["sm","Small"],["md","Medium"],["lg","Large"]]},{name:"continuous",label:"Continuous",type:"checkbox",default:!1},{name:"hover",label:"On hover only",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"fireworks",label:"Fireworks show",category:"Celebrations",description:"A container with multiple firework particles inside.",attrs:[],hosts:[],previewable:!1},{name:"celebrate",label:"Celebrate",category:"Celebrations",description:"A full-page seasonal celebration, or one inline character at any time of year.",attrs:[{name:"theme",label:"Theme",type:"select",default:"auto",options:[["auto","Auto (date-detected)"],["christmas","Christmas"],["halloween","Halloween"],["valentines","Valentines"],["guy-fawkes","Guy Fawkes"],["st-patricks","St Patrick's"],["st-davids","St David's"],["st-georges","St George's"],["st-andrews","St Andrew's"]]},{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only (Christmas)",type:"checkbox",default:!1,hint:"Just the falling snow - every Christmas decoration off."},{name:"trees",label:"Christmas: trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"Christmas: wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"Christmas: North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"Christmas: snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Christmas: Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"Christmas: elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"Christmas: train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"Christmas: fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"Christmas: robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"christmas",label:"Christmas",category:"Celebrations",description:"Christmas on the published site: snow, trees, wreaths, snowmen, Santa's sleigh and more. Snow only for just the snow.",attrs:[{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only",type:"checkbox",default:!1,hint:"Just the falling snow - every decoration off."},{name:"trees",label:"trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"ticker-tape",label:"Ticker tape",category:"Celebrations",description:"Coloured rectangular strips fall from the top, sway, rotate, and fade. Inserted self-closing (full-page); hand-write the wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"theme",options:[["theme","Theme"],["rainbow","Rainbow"],["gold","Gold"],["silver","Silver"],["festive","Festive"],["pastel","Pastel"],["mono","Mono"]]},{name:"density",label:"Density",type:"number",default:50},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sway",label:"Sway (px)",type:"number",default:60},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:150}],hosts:["hero"],previewable:!0,selfClosing:!0},{name:"butterflies",label:"Butterflies",category:"Celebrations",description:"Procedurally drawn butterflies wander and rise with flapping wings. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"meadow",options:[["meadow","Meadow"],["theme","Theme"],["rainbow","Rainbow"],["pastel","Pastel"],["festive","Festive"],["gold","Gold"],["silver","Silver"],["mono","Mono"],["sunset","Sunset"],["ocean","Ocean"],["forest","Forest"],["bridal","Bridal"],["firefly","Firefly"]]},{name:"density",label:"Density",type:"number",default:18},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"wander",label:"Wander",type:"number",default:1,step:.1,hint:"Steering erraticness"},{name:"rise-speed",label:"Rise speed",type:"number",default:.4,step:.1,hint:"Upward drift bias"},{name:"flap-speed",label:"Flap speed",type:"number",default:1,step:.1},{name:"min-size",label:"Min wingspan (px)",type:"number",default:14},{name:"max-size",label:"Max wingspan (px)",type:"number",default:26},{name:"two-tone",label:"Two-tone wings",type:"checkbox",default:!0},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:40}],hosts:["hero"],previewable:!0},{name:"strobe",label:"Strobe lighting",category:"Celebrations",description:"Light beams sweep from the corners and brighten where they cross - club, concert, or searchlight moods. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"preset",label:"Preset",type:"select",default:"club",options:[["club","Club"],["concert","Concert"],["police","Police"],["searchlight","Searchlight"],["scanner","Scanner"],["mood","Mood"]],hint:"Other fields override the preset when changed"},{name:"motion",label:"Motion",type:"select",default:"sweep",options:[["sweep","Sweep (fan back and forth)"],["rotate","Rotate (full circle)"]]},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sweep-arc",label:"Sweep arc (deg)",type:"number",default:100},{name:"beam-width",label:"Beam width (deg)",type:"number",default:16},{name:"intensity",label:"Intensity",type:"number",default:.7,step:.05,min:0,max:1},{name:"flicker",label:"Flicker",type:"checkbox",default:!0},{name:"hz",label:"Flicker rate (Hz)",type:"number",default:10,hint:"Rates above 5 flashes/sec can trigger photosensitive seizures"},{name:"colours",label:"Colours",type:"text",default:"",placeholder:"#ffffff, #38bdf8",hint:"Comma-separated hex colours - overrides the preset palette"},{name:"duration",label:"Auto-stop (ms)",type:"number",default:"",hint:"Stop after this many ms - blank runs forever"}],hosts:["hero"],previewable:!0}];export function getEffect(e){return EFFECTS.find(t=>t.name===e)||null}export function effectsByCategory(){return["Entrance","Animation","Text","Visual","Celebrations"].map(t=>({category:t,effects:EFFECTS.filter(o=>o.category===t)}))}export function effectsInjectableInto(e){return EFFECTS.filter(t=>t.hosts.includes(e))}const n=EFFECTS.find(e=>e.name==="celebrate");for(const e of n.attrs.slice(2))e.themes=["christmas"];n.attrs.push({name:"character",label:"Standalone character",type:"select",default:"",options:[["","Full celebration"],...p().map(e=>[e.name,e.label])]},{name:"size",label:"Character height",type:"text",default:"medium",placeholder:"medium or 200",hint:"small (96px), medium (160px), large (240px), xlarge (360px), or a height in pixels."},{name:"animate",label:"Animate character",type:"checkbox",default:!0},{name:"facing",label:"Character direction",type:"select",default:"right",options:[["right","Right"],["left","Left"]]}),n.attrs.push({name:"falling-only",label:"Falling particles only",type:"checkbox",default:!1}),n.attrs.push({name:"mooning-elf",label:"Mooning elf (opt-in)",type:"checkbox",default:!1,themes:["christmas"]}),EFFECTS.find(e=>e.name==="christmas").attrs.push({name:"mooning-elf",label:"Mooning elf (opt-in)",type:"checkbox",default:!1});const r=new Map(n.attrs.map(e=>[e.name,e]));for(const[e,t]of Object.entries(i))if(e!=="christmas")for(const[o,s]of Object.entries(t.traits)){const a=m(o);let l=r.get(a);l||(l=s.enabled===!1?{name:a,label:`${s.label} (opt-in)`,type:"checkbox",default:!1,themes:[]}:{name:a,label:s.label,type:"select",default:"",options:[["","Shown"],["off","Off"]],themes:[]},r.set(a,l)),l.themes.includes(e)||l.themes.push(e),l.themes.length>1&&(l.label=l.label.replace(/^Christmas: /,""))}for(const e of r.values())n.attrs.includes(e)||n.attrs.push(e);export function getEffectAttrs(e,t={}){if(e.name!=="celebrate")return e.attrs||[];const o=["character","size","animate","facing"];if(t.character)return e.attrs.filter(a=>o.includes(a.name));const s=t.theme||"auto";return e.attrs.filter(a=>(a.name==="character"||!o.includes(a.name))&&(!a.themes||s==="auto"||a.themes.includes(s)))}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{EFFECTS as
|
|
1
|
+
import{EFFECTS as R,effectsByCategory as L,effectsInjectableInto as j,getEffect as u,getEffectAttrs as g}from"./effect-defs.js";import{scribeLoop as O}from"./scribe-model.js";import{insertAtCursor as N,replaceRange as C}from"./markdown-toolbar.js";let h=null,x=null;function B(e,t,n=14){e.textContent="";const o=document.createElement("span");return o.setAttribute("data-icon",t),o.setAttribute("data-icon-size",String(n)),o.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(o),I.scan(e),e}function q(e,t,n,o=14){return B(e,t,o),e.appendChild(document.createTextNode(" "+n)),e}export const EffectsBuilder={open(e){if(h)return;const t={textarea:e,activeEffect:S.get("effects-builder-last")||"reveal",scope:"standalone",host:null,editing:null,fieldValues:{}};if(t.host=M(e),t.host&&j(t.host.name).map(r=>r.name).includes(t.activeEffect)&&!(t.activeEffect in t.host.attrs)&&(t.scope="inject"),t.editing=H(e),t.editing){t.activeEffect=t.editing.name,t.scope="standalone";const l=u(t.editing.name);for(const r of g(l,t.fieldValues))if(r.name in t.editing.attrs){const s=t.editing.attrs[r.name];r.type==="number"?t.fieldValues[r.name]=Number(s):r.type==="checkbox"?t.fieldValues[r.name]=s==="true":t.fieldValues[r.name]=s}}const n=E.slideover({title:"Effects",size:"lg",position:"right",onClose:()=>{x?.destroy(),x=null,h=null}}),o=P(t,n);n.element.appendChild(o),n.open(),I.scan(o),h={state:t,slideover:n}},close(){h&&(h.slideover.close(),h=null)}};function P(e,t){const n=document.createElement("div");n.style.cssText="display:grid;grid-template-columns:170px 1fr;height:100%;min-height:520px;";const o=document.createElement("div");o.className="effects-rail",o.style.cssText="background:var(--dm-background-alt,#15152a);border-right:1px solid var(--dm-border,#2a2a40);padding:.5rem .35rem;font-size:.8rem;overflow-y:auto;";const l=document.createElement("div");l.className="effects-pane",l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;overflow-y:auto;";function r(){W(l,e,t)}return k(o,e,r),r(),n.appendChild(o),n.appendChild(l),n}function k(e,t,n){e.replaceChildren();for(const o of L()){const l=document.createElement("div");l.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin:.4rem .35rem .25rem;",l.textContent=o.category,e.appendChild(l);for(const r of o.effects){const s=document.createElement("button");s.type="button",s.dataset.effect=r.name,s.style.cssText="display:block;width:100%;text-align:left;padding:.3rem .5rem;border:none;background:transparent;color:var(--dm-text,#ddd);border-radius:3px;font-size:.8rem;cursor:pointer;margin-bottom:.1rem;",s.textContent=r.label,r.name===t.activeEffect&&(s.style.background="var(--dm-primary,#4338ca)",s.style.color="var(--dm-primary-text,#fff)"),s.addEventListener("click",()=>{t.activeEffect=r.name,S.set("effects-builder-last",r.name),t.fieldValues={},k(e,t,n),n()}),e.appendChild(s)}}}function F(e,t){if(e.type==="select"){const o=document.createElement("select");o.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;";for(const[l,r]of e.options){const s=document.createElement("option");s.value=l,s.textContent=r,o.appendChild(s)}return o.value=t??e.default??"",o}if(e.type==="checkbox"){const o=document.createElement("input");return o.type="checkbox",o.checked=t??e.default??!1,o}const n=document.createElement("input");return n.type=e.type==="number"?"number":e.type==="colour"?"color":"text",n.value=t??e.default??"",e.placeholder&&(n.placeholder=e.placeholder),e.type==="number"&&(e.min!=null&&(n.min=e.min),e.max!=null&&(n.max=e.max),e.step!=null&&(n.step=e.step)),n.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;",n}function T(e,t){return t.type==="checkbox"?e.checked:t.type==="number"?e.value===""?"":Number(e.value):e.value}function v(e,t,n){const o=u(t.activeEffect);if(e.replaceChildren(),o.attrs.length===0){const r=document.createElement("div");r.style.cssText="color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;",r.textContent="This effect takes no parameters.",e.appendChild(r);return}const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:.6rem .7rem;";for(const r of g(o,t.fieldValues)){const s=document.createElement("div"),d=document.createElement("label");d.style.cssText="display:block;color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.2rem;",d.textContent=r.label,s.appendChild(d);const i=F(r,t.fieldValues[r.name]);if(i.addEventListener("input",()=>{t.fieldValues[r.name]=T(i,r),n(),r.name==="theme"&&v(e,t,n)}),i.addEventListener("change",()=>{t.fieldValues[r.name]=T(i,r),n(),r.name==="theme"&&v(e,t,n)}),s.appendChild(i),r.hint){const c=document.createElement("div");c.style.cssText="color:var(--dm-text-muted,#666);font-size:.7rem;margin-top:.15rem;",c.textContent=r.hint,s.appendChild(c)}l.appendChild(s)}e.appendChild(l)}function $(e){const t={},n=/(\w[\w-]*)(?:\s*=\s*"([^"]*)"|\s*=\s*'([^']*)'|\s*=\s*(\S+))?/g;for(const o of e.matchAll(n)){const l=o[1],r=o[2]??o[3]??o[4]??"";t[l]=r}return t}const D=R.filter(e=>!e.selfClosing).map(e=>e.name);function H(e){const t=e.value,n=e.selectionStart;for(const o of D){const l=new RegExp(`\\[${o}([^\\]]*)\\]`,"g"),r=new RegExp(`\\[/${o}\\]`,"g"),s=[];for(const c of t.matchAll(l)){if(c.index>=n)break;s.push({type:"open",start:c.index,end:c.index+c[0].length,attrStr:c[1]})}for(const c of t.matchAll(r)){if(c.index>=n)break;s.push({type:"close",start:c.index,end:c.index+c[0].length})}s.sort((c,a)=>c.start-a.start);let d=0,i=null;for(const c of s)c.type==="open"?(d++,i=c):(d--,d<0&&(d=0,i=null));if(d>0&&i){const c=new RegExp(`\\[/${o}\\]`,"g"),a=t.slice(n),m=a.match(c);if(m){const f=n+a.indexOf(m[0]);return{name:o,blockStart:i.start,blockEnd:f+m[0].length,openTagEnd:i.end,attrs:$(i.attrStr)}}}}return null}const K=["card","box","hero","banner","col","button"];function M(e){const t=e.value,n=e.selectionStart;for(const o of K){const l=new RegExp(`\\[${o}([^\\]]*)\\]`,"g"),r=new RegExp(`\\[/${o}\\]`,"g"),s=[];for(const c of t.matchAll(l)){if(c.index>=n)break;s.push({type:"open",start:c.index,end:c.index+c[0].length,attrStr:c[1]})}for(const c of t.matchAll(r)){if(c.index>=n)break;s.push({type:"close",start:c.index,end:c.index+c[0].length})}s.sort((c,a)=>c.start-a.start);let d=0,i=null;for(const c of s)c.type==="open"?(d++,i=c):(d--,d<0&&(d=0,i=null));if(d>0&&i){const c=new RegExp(`\\[/${o}\\]`,"g"),a=t.slice(n),m=a.match(c);if(m){const f=n+a.indexOf(m[0]);return{name:o,openTagStart:i.start,openTagEnd:i.end,closeTagStart:f,closeTagEnd:f+m[0].length,attrs:$(i.attrStr)}}}}return null}function w(e,t){const n=[];for(const o of g(t,e.fieldValues)){const l=e.fieldValues[o.name];l===void 0||l===""||l===null||l===o.default&&!o.always||(o.type==="checkbox"?n.push(`${o.name}="${l?"true":"false"}"`):n.push(`${o.name}="${String(l).replace(/"/g,""")}"`))}return n.join(" ")}function _(e){const t=u(e.activeEffect),n=w(e,t),o=n?" ":"";if(e.scope==="inject"&&e.host){const l=e.host.attrs,r=t.name,s=[];for(const d of Object.keys(l)){if(d===r||d.startsWith(r+"-"))continue;const i=l[d];s.push(i===""?d:`${d}="${String(i).replace(/"/g,""")}"`)}s.push(r);for(const d of g(t,e.fieldValues)){const i=e.fieldValues[d.name];if(i===void 0||i===""||i===null||i===d.default)continue;const c=d.type==="checkbox"?i?"true":"false":String(i).replace(/"/g,""");s.push(`${r}-${d.name}="${c}"`)}return`[${e.host.name} ${s.join(" ")}]\u2026[/${e.host.name}]`}return t.selfClosing?`[${t.name}${o}${n} /]`:`[${t.name}${o}${n}]
|
|
2
2
|
Content
|
|
3
|
-
[/${t.name}]`}function
|
|
3
|
+
[/${t.name}]`}function z(e,t){e.replaceChildren();const n=document.createElement("div");n.style.cssText="color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",n.textContent="Shortcode (live)",e.appendChild(n);const o=document.createElement("pre");o.style.cssText="background:var(--dm-code-bg,#000);border:1px solid var(--dm-border,#333);padding:.5rem .65rem;border-radius:3px;font-family:var(--dm-font-mono,monospace);font-size:.75rem;color:var(--dm-code-text,#7c6af7);line-height:1.5;white-space:pre-wrap;word-break:break-all;margin:0;",o.textContent=_(t),e.appendChild(o)}function U(e,t,n){if(e.replaceChildren(),t.editing)return;const o=u(t.activeEffect),l=t.host&&o.hosts.includes(t.host.name),r=document.createElement("div");r.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.5rem .6rem;";const s=document.createElement("div");if(s.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin-bottom:.3rem;",s.textContent="Apply as",r.appendChild(s),!l){const c=document.createElement("div");c.style.cssText="color:var(--dm-text-muted,#888);font-size:.75rem;font-style:italic;",t.host?c.textContent=`Inserted as a standalone block (${o.label} cannot be injected into [${t.host.name}]).`:c.textContent="Inserted as a standalone block.",r.appendChild(c),e.appendChild(r),t.scope="standalone";return}const d=document.createElement("div");d.style.cssText="display:flex;gap:.3rem;";function i(c,a){const m=document.createElement("button");return m.type="button",m.style.cssText="flex:1;padding:.35rem;border:1px solid var(--dm-border,#333);border-radius:3px;font-size:.75rem;font-weight:600;cursor:pointer;",t.scope===c?(m.style.background="var(--dm-primary,#4338ca)",m.style.color="var(--dm-primary-text,#fff)",m.style.borderColor="var(--dm-primary,#4338ca)"):(m.style.background="transparent",m.style.color="var(--dm-text-muted,#bbb)"),m.textContent=a,m.addEventListener("click",()=>{t.scope=c,n()}),m}d.appendChild(i("standalone","Standalone block")),d.appendChild(i("inject",`Inject into [${t.host.name}]`)),r.appendChild(d),e.appendChild(r)}let y=0;function A(e){return e.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}function V(e,t){e.replaceChildren();const n=u(t.activeEffect),o=document.createElement("div");o.style.cssText="display:flex;justify-content:space-between;align-items:center;margin-bottom:.25rem;";const l=document.createElement("div");if(l.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;",l.textContent="Live preview",o.appendChild(l),!n.previewable){const i=document.createElement("div");i.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.6rem;color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;text-align:center;",i.textContent="Runs full-page on the published site - no inline preview.",e.appendChild(i);return}const r=document.createElement("button");r.type="button",r.style.cssText="background:transparent;border:1px solid var(--dm-border,#333);color:var(--dm-text-muted,#888);font-size:.65rem;padding:.15rem .4rem;border-radius:2px;cursor:pointer;",q(r,"refresh-cw","Replay",12),o.appendChild(r),e.appendChild(o);const s=document.createElement("div");s.style.cssText="background:var(--dm-background-alt,#1a1a2e);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:1rem;text-align:center;min-height:80px;position:relative;overflow:hidden;",e.appendChild(s);function d(i=!1){x?.destroy(),x=null,y++;const c=y;s.replaceChildren();const a=document.createElement("div");a.style.cssText="background:linear-gradient(135deg,#6366f1,#a855f7);color:#fff;padding:.6rem;border-radius:4px;font-size:.8rem;font-weight:600;",a.textContent="Sample content",s.appendChild(a);const m=window.Domma&&window.Domma.effects;if(!m)return;const f={};for(const p of g(n,t.fieldValues)){const b=t.fieldValues[p.name];b===void 0||b===""||b===null||(f[A(p.name)]=b)}n.name==="scribe"&&(f.loop=O(f.loop??!1),f.actions=[{render:a.textContent,effect:f.effect||"none"}],a.textContent="");try{const p=m[A(n.name)];if(typeof p=="function"){if(c!==y)return;x=p(a,f),i&&x?.resume()}}catch(p){console.warn("Effects preview failed:",p)}}r.addEventListener("click",()=>d(!0)),d()}function W(e,t,n){const o=u(t.activeEffect);e.replaceChildren();const l=document.createElement("h3");l.style.cssText="margin:0;font-size:1rem;color:var(--dm-text,#eee);",l.textContent=o.label,e.appendChild(l);const r=document.createElement("p");r.style.cssText="margin:0;color:var(--dm-text-muted,#999);font-size:.8rem;line-height:1.4;",r.textContent=o.description,e.appendChild(r);const s=document.createElement("div");e.appendChild(s);const d=document.createElement("div");e.appendChild(d);const i=document.createElement("div");e.appendChild(i);const c=document.createElement("div");e.appendChild(c);function a(){U(s,t,a),v(d,t,()=>{z(i,t),V(c,t)}),z(i,t),V(c,t)}a();const m=document.createElement("div");m.style.cssText="display:flex;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#2a2a40);";const f=document.createElement("button");f.type="button",f.className="btn btn-ghost",f.textContent="Cancel",f.addEventListener("click",()=>n.close()),m.appendChild(f);const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.style.flex="2",p.textContent=t.editing?"Update":"Insert effect",p.addEventListener("click",()=>X(t,n)),m.appendChild(p),e.appendChild(m)}function X(e,t){const n=e.textarea,o=_(e);if(e.editing){const l=u(e.editing.name),r=n.value,s=`[/${l.name}]`.length,d=e.editing.openTagEnd,i=e.editing.blockEnd-s,c=r.substring(d,i),a=w(e,l),m=a?" ":"",f=l.selfClosing?`[${l.name}${m}${a} /]`:`[${l.name}${m}${a}]${c}[/${l.name}]`;C(n,e.editing.blockStart,e.editing.blockEnd,f);const p=l.selfClosing?e.editing.blockStart+f.length:e.editing.blockStart+f.indexOf("]")+1;n.setSelectionRange(p,p),t.close();return}if(e.scope==="inject"&&e.host){const l=u(e.activeEffect),r=e.host.attrs,s=l.name,d=[];for(const c of Object.keys(r)){if(c===s||c.startsWith(s+"-"))continue;const a=r[c];d.push(a===""?c:`${c}="${String(a).replace(/"/g,""")}"`)}d.push(s);for(const c of g(l,e.fieldValues)){const a=e.fieldValues[c.name];if(a===void 0||a===""||a===null||a===c.default)continue;const m=c.type==="checkbox"?a?"true":"false":String(a).replace(/"/g,""");d.push(`${s}-${c.name}="${m}"`)}const i=`[${e.host.name} ${d.join(" ")}]`;C(n,e.host.openTagStart,e.host.openTagEnd,i),t.close();return}N(n,o),t.close()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const WIDTHS=["narrow","normal","wide","full"],WIDTH_LABELS={narrow:"Narrow",normal:"Normal",wide:"Wide",full:"Full width"},WIDTH_HINTS={narrow:"768px - a reading column",normal:"1100px",wide:"75% of the window, up to 2000px",full:"edge to edge"},WIDTH_SHARE={narrow:"40%",normal:"62%",wide:"82%",full:"100%"},FILTERS=["all","builtin","custom"];const b=/^[a-zA-Z0-9#(),.\s%/-]+$/;export function layoutKey(e){return String(e??"").toLowerCase().trim().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"")}const g=(e,t,l=`${t}s`)=>`${e} ${e===1?t:l}`;export function chromeText(e){const t=[e.navbar!==!1&&"navbar",e.footer!==!1&&"footer",e.sidebar===!0&&"
|
|
1
|
+
export const WIDTHS=["narrow","normal","wide","full"],WIDTH_LABELS={narrow:"Narrow",normal:"Normal",wide:"Wide",full:"Full width"},WIDTH_HINTS={narrow:"768px - a reading column",normal:"1100px",wide:"75% of the window, up to 2000px",full:"edge to edge"},WIDTH_SHARE={narrow:"40%",normal:"62%",wide:"82%",full:"100%"},FILTERS=["all","builtin","custom"];const b=/^[a-zA-Z0-9#(),.\s%/-]+$/;export function layoutKey(e){return String(e??"").toLowerCase().trim().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"")}const g=(e,t,l=`${t}s`)=>`${e} ${e===1?t:l}`;export function chromeText(e){const t=[e.navbar!==!1&&"navbar",e.footer!==!1&&"footer",e.sidebar===!0&&"page contents"].filter(Boolean);return t.length?t.join(", "):"no navbar or footer"}export function arrangeLayouts(e,t={},{filter:l="all",query:o=""}={}){const i=String(o).trim().toLowerCase(),n=Object.entries(e||{}).map(([r,s])=>({...s,key:r})),a=n.filter(r=>r.builtin),c=n.filter(r=>!r.builtin).sort((r,s)=>String(r.label||r.key).localeCompare(String(s.label||s.key)));return[...a,...c].filter(r=>l==="builtin"?r.builtin:l==="custom"?!r.builtin:!0).filter(r=>!i||[r.key,r.label,r.description,r.class].some(s=>String(s||"").toLowerCase().includes(i))).map(r=>layoutRow(r,(t.byKey||{})[r.key]||[]))}export function layoutRow(e,t=[]){const l=WIDTHS.includes(e.width)?e.width:"normal";return{key:e.key,label:e.label||e.key,meta:[e.key,e.description,chromeText(e)].filter(Boolean).join(" \xB7 "),builtin:e.builtin===!0,widthLabel:WIDTH_LABELS[l],used:t.length,usedText:t.length?g(t.length,"page"):"Unused",usedTone:t.length?"is-info":"is-muted",hasNav:e.navbar!==!1,hasFoot:e.footer!==!1,hasSide:e.sidebar===!0,sideRight:e.sidebar===!0&&e.sidebarSide==="right",share:WIDTH_SHARE[l],bg:e.bgColor&&b.test(e.bgColor)?e.bgColor:""}}export function formFromPreset(e={}){return{label:e.label||"",description:e.description||"",width:WIDTHS.includes(e.width)?e.width:"normal",navbar:e.navbar!==!1,footer:e.footer!==!1,sidebar:e.sidebar===!0,sidebarSide:e.sidebarSide==="right"?"right":"left",useBg:!!e.bgColor,bgColor:e.bgColor&&/^#[0-9a-f]{6}$/i.test(e.bgColor)?e.bgColor:e.bgColor||"#ffffff",bgImage:e.bgImage||"",cssClass:e.class||"",...contentsForm(e.contents)}}export function contentsForm(e={}){return{cWidth:e.width!=null?String(e.width):"",cSticky:e.sticky!==!1,cScrollSpy:e.scrollSpy!==!1,cFloating:e.floating===!0,cFloatAnchor:e.floatAnchor||"TR",cMovable:e.movable===!0,cCollapsible:e.collapsible===!0,cCollapsed:e.collapsed===!0,cAutohide:e.autohide===!0,cHeadings:e.headings||"auto",cNumbered:e.numbered===!0,cTitle:e.title||"",cExclude:e.exclude||"",cHover:e.hover||"",cSelected:e.selected||"",cAccent:e.accent||"",cFont:e.font||"",cFontSize:e.fontSize||"",cFontWeight:e.fontWeight||""}}export function contentsFromForm(e={}){const t={},l=parseInt(e.cWidth,10);Number.isFinite(l)&&(t.width=l),e.cSticky===!1&&(t.sticky=!1),e.cScrollSpy===!1&&(t.scrollSpy=!1),e.cFloating===!0?(t.floating=!0,t.floatAnchor=e.cFloatAnchor||"TR",e.cMovable===!0&&(t.movable=!0)):e.cAutohide===!0?t.autohide=!0:e.cCollapsible===!0&&(t.collapsible=!0,e.cCollapsed===!0&&(t.collapsed=!0)),e.cHeadings&&e.cHeadings!=="auto"&&(t.headings=e.cHeadings),e.cNumbered===!0&&(t.numbered=!0);for(const[o,i]of[["title","cTitle"],["exclude","cExclude"],["hover","cHover"],["selected","cSelected"],["accent","cAccent"],["font","cFont"],["fontSize","cFontSize"],["fontWeight","cFontWeight"]]){const n=String(e[i]??"").trim();n&&(t[o]=n)}return t}export function checkLayout(e,{isNew:t,taken:l=[]}={}){const o=e||{},i={},n=String(o.label??"").trim(),a=t?layoutKey(n):"";n?n.length>60?i.label="Up to 60 characters.":t&&!a?i.label="Needs at least one letter or number.":t&&l.includes(a)&&(i.label=`"${a}" is already a layout - choose another name.`):i.label="A layout needs a name.";const c=o.useBg?String(o.bgColor||"").trim():"";c&&!b.test(c)&&(i.bgColor="Not a colour the server accepts.");const r=String(o.bgImage??"").trim(),s=String(o.cssClass??"").trim();/[^a-zA-Z0-9\s_-]/.test(s)&&(i.cssClass="Letters, numbers, spaces, hyphens and underscores only.");const u=String(o.cWidth??"").trim();u&&!(Number(u)>=160&&Number(u)<=480)&&(i.cWidth="From 160 to 480 px, or blank for the usual 260.");const d=o.sidebar===!0?contentsFromForm(o):{},f={label:n,description:String(o.description??"").trim().slice(0,200),width:WIDTHS.includes(o.width)?o.width:"normal",navbar:o.navbar!==!1,footer:o.footer!==!1,sidebar:o.sidebar===!0,sidebarSide:o.sidebarSide==="right"?"right":"left",bgColor:c,bgImage:r,class:s,...Object.keys(d).length&&{contents:d}};return{errors:i,payload:f,key:a}}export function checkOptions(e){const t={},l=String(e?.spacerSize??"").trim(),o=Number(l);(l===""||!Number.isInteger(o)||o<0||o>500)&&(t.spacerSize="A whole number of pixels, 0 to 500.");const i=String(e?.spacerClass??"").trim();return/[^a-zA-Z0-9\s_-]/.test(i)&&(t.spacerClass="Letters, numbers, spaces, hyphens and underscores only."),{errors:t,payload:{spacerSize:Number.isInteger(o)?o:8,spacerClass:i}}}
|
|
@@ -89,7 +89,7 @@ In active development.
|
|
|
89
89
|
[/table]`,"The inner content must be a valid GFM Markdown table. The shortcode adds Domma CSS classes and wraps in a responsive scroll container.")]}),t("Slideover",{intro:"A trigger button that opens a slide-in panel with Markdown content. No plugin required.",rows:[['title="..."',"Panel header text"],['trigger="..."','Button label (default: "Open")'],['size="sm|md|lg"',"Panel width (default: md)"],['position="right|left"',"Slide direction (default: right)"]],examples:[e("Example",`[slideover title="More Info" trigger="Read more" size="md"]
|
|
90
90
|
## Details
|
|
91
91
|
Markdown content here.
|
|
92
|
-
[/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")]})],b=[t("Embedding a Form",{rows:[['name="..."',"Form slug (required). Also accepted as slug=."],['class="..."',"Extra CSS classes on the wrapper div"],['id="..."',"id attribute on the wrapper div"]],examples:[e("Basic",'[form name="contact" /]',"Forms are managed under Forms in the sidebar."),e("With wrapper styling",'[form name="newsletter" class="mt-4" id="newsletter-form" /]')]}),t("Displaying a Collection",{block:'[collection slug="enquiries" display="table" /]',rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["fields","Comma-separated field keys to show. Defaults to all."],["limit","Maximum number of entries to display."],["sort","Field key to sort by."],["order","asc or desc (default asc)."],["title-field","Field used as the card/list title (cards + list)."],["columns","Grid columns for cards display (2-4, default 3)."],["search","true/false - enable search in table mode (default true)."],["sortable","true/false - enable column sorting in table mode (default true)."],["exportable","true/false - show CSV export button in table mode (default false)."],["page-size","Rows per page in table mode (default 25)."],["empty","Text shown when there are no entries."],["cta","Action slug: enables per-entry CTA buttons."],["cta-label",'CTA button label (default: "Run").'],["cta-icon","CTA button icon name."],["cta-style","CTA button variant (default: primary)."],["cta-confirm","CTA confirmation prompt text."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],outro:"Table display uses Domma Table - search, sort, pagination, column selector, and CSV export are all built in. Cards and lists are static."}),t("View - Pro",{intro:"Renders a Collection with full filtering, pagination, and display options. Requires a Pro MongoDB collection.",rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["limit","Maximum number of entries to display."],["fields","Comma-separated field keys to show."],["title-field","Field used as the card/list title."],["columns","Grid columns for cards display (2-4, default 3)."],["empty","Text shown when there are no entries."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],examples:[e("Table display",'[view slug="products" display="table" limit="50" /]'),e("Cards display",'[view slug="team" display="cards" columns="3" title-field="name" /]')]}),t("CTA - Pro",{intro:"Renders an action button that triggers a Pro Action against an entry. Requires the Pro Actions feature.",rows:[["action","Required. The action slug."],["entry","Required. The entry id to act on."],["style","Button variant (default: primary)."],["icon","Domma icon name for the button."],["size","Button size (sm, lg)."],["confirm","Confirmation prompt text before running."],["label","Self-closing only: button label text."]],examples:[e("Wrapping form",'[cta action="approve" entry="abc123" style="success" confirm="Approve this entry?"]Approve[/cta]'),e("Self-closing",'[cta action="archive" entry="abc123" icon="archive" label="Archive" /]')]})],f=[t("Effects",{intro:"Shortcodes for scroll-triggered animations, counters, typewriter text, and more. Requires the Domma Effects plugin.",rows:[['[reveal animation="fade"]...[/reveal]',"Fade/slide/zoom on scroll"],["[breathe]...[/breathe]","Continuous gentle scale loop"],["[pulse]...[/pulse]","Repeating scale pulse"],["[shake]...[/shake]","One-shot shake"],['[scribe speed="
|
|
92
|
+
[/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")]})],b=[t("Embedding a Form",{rows:[['name="..."',"Form slug (required). Also accepted as slug=."],['class="..."',"Extra CSS classes on the wrapper div"],['id="..."',"id attribute on the wrapper div"]],examples:[e("Basic",'[form name="contact" /]',"Forms are managed under Forms in the sidebar."),e("With wrapper styling",'[form name="newsletter" class="mt-4" id="newsletter-form" /]')]}),t("Displaying a Collection",{block:'[collection slug="enquiries" display="table" /]',rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["fields","Comma-separated field keys to show. Defaults to all."],["limit","Maximum number of entries to display."],["sort","Field key to sort by."],["order","asc or desc (default asc)."],["title-field","Field used as the card/list title (cards + list)."],["columns","Grid columns for cards display (2-4, default 3)."],["search","true/false - enable search in table mode (default true)."],["sortable","true/false - enable column sorting in table mode (default true)."],["exportable","true/false - show CSV export button in table mode (default false)."],["page-size","Rows per page in table mode (default 25)."],["empty","Text shown when there are no entries."],["cta","Action slug: enables per-entry CTA buttons."],["cta-label",'CTA button label (default: "Run").'],["cta-icon","CTA button icon name."],["cta-style","CTA button variant (default: primary)."],["cta-confirm","CTA confirmation prompt text."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],outro:"Table display uses Domma Table - search, sort, pagination, column selector, and CSV export are all built in. Cards and lists are static."}),t("View - Pro",{intro:"Renders a Collection with full filtering, pagination, and display options. Requires a Pro MongoDB collection.",rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["limit","Maximum number of entries to display."],["fields","Comma-separated field keys to show."],["title-field","Field used as the card/list title."],["columns","Grid columns for cards display (2-4, default 3)."],["empty","Text shown when there are no entries."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],examples:[e("Table display",'[view slug="products" display="table" limit="50" /]'),e("Cards display",'[view slug="team" display="cards" columns="3" title-field="name" /]')]}),t("CTA - Pro",{intro:"Renders an action button that triggers a Pro Action against an entry. Requires the Pro Actions feature.",rows:[["action","Required. The action slug."],["entry","Required. The entry id to act on."],["style","Button variant (default: primary)."],["icon","Domma icon name for the button."],["size","Button size (sm, lg)."],["confirm","Confirmation prompt text before running."],["label","Self-closing only: button label text."]],examples:[e("Wrapping form",'[cta action="approve" entry="abc123" style="success" confirm="Approve this entry?"]Approve[/cta]'),e("Self-closing",'[cta action="archive" entry="abc123" icon="archive" label="Archive" /]')]})],f=[t("Effects",{intro:"Shortcodes for scroll-triggered animations, counters, typewriter text, and more. Requires the Domma Effects plugin.",rows:[['[reveal animation="fade"]...[/reveal]',"Fade/slide/zoom on scroll"],["[breathe]...[/breathe]","Continuous gentle scale loop"],["[pulse]...[/pulse]","Repeating scale pulse"],["[shake]...[/shake]","One-shot shake"],['[scribe mode="word" effect="bounce" speed="140" loop="3" cursor-blink="false" controls="true"]...[/scribe]',"Scribe - characters, words, or sentences; effects, counted loops, cursor and playback settings"],['[scribe loop="true"][render]Text[/render][wait]1500[/wait][undo /][/scribe]',"Typewriter - script mode (sequenced render/wait/undo actions)"],["[scramble]...[/scramble]","Character-scramble reveal"],['[counter to="100" /]',"Animated number counter (self-closing)"],["[ripple]...[/ripple]","Click-triggered ripple"],['[twinkle count="50"]...[/twinkle]',"Particle/star overlay"],['[animate type="fade-in-up"]...[/animate]',"CSS-only animation (no plugin needed)"],['[ambient type="aurora"]...[/ambient]',"CSS-only animated background"],['[firework type="burst" colour="rainbow" /]',"CSS firework (self-closing)"],["[fireworks]...[/fireworks]","Fireworks display container"],['[celebrate theme="auto" /]',"Seasonal canvas celebration (auto-detects date)"],["[christmas /]","Christmas - snowflakes, trees, snowmen, sleigh"],["[halloween /]","Halloween - pumpkins, ghosts, bats, spiders"],["[st-patricks /]","St Patrick's Day - shamrocks, coins, rainbows, leprechaun"],["[valentines /]","Valentine's Day - hearts, roses"],["[guy-fawkes /]","Guy Fawkes - fireworks, sparkles"],["[st-andrews /]","St Andrew's Day - heather, thistles"],["[st-davids /]","St David's Day - daffodils, dragons"],["[st-georges /]","St George's Day - roses, flags"]],examples:[e("Scribe script - looping multi-phrase typewriter",`[scribe loop="true" loop-delay="2000" delete-speed="20"]
|
|
93
93
|
[render]We build things that matter.[/render]
|
|
94
94
|
[wait]1200[/wait]
|
|
95
95
|
[undo all="true" /]
|
|
@@ -98,7 +98,7 @@ Markdown content here.
|
|
|
98
98
|
[undo all="true" /]
|
|
99
99
|
[/scribe]`,'Use [render]...[/render] to type text, [wait]Ms[/wait] to pause, and [undo /] to delete. loop="true" replays the sequence. Only [render], [wait], and [undo] shortcodes are parsed - plain text between actions is ignored.'),e("Christmas",'[christmas intensity="medium" snowmen="off" trees="off" wreaths="off" northStars="off" sleigh="off" train="off" elf="off" robin="off" firework="off" /]',"intensity: light | medium | heavy. Count-based (off disables entirely): snowmen, trees, wreaths, northStars. Probability-based specials (off prevents spawning): sleigh, train, elf, robin, firework. Snowflakes always fall."),e("Halloween",'[halloween intensity="medium" gravestones="off" jackOLanterns="off" spiders="off" scarecrows="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): gravestones, jackOLanterns, spiders, scarecrows, twinklingStars. Particles: bats, ghosts, pumpkins (always on). Fixed decorations: haunted-house, cauldron (always present)."),e("St Patrick's Day",'[st-patricks intensity="medium" pots="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): pots (pots of gold), twinklingStars. Particles: shamrocks, clover petals, gold coins, sparkles (always on). Fixed decorations: rainbow, harp, moon. Leprechaun appears randomly - more likely at higher intensity."),e("Valentine's Day",'[valentines intensity="medium" garlands="off" butterflies="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): garlands (heart garlands), butterflies. Particles: hearts, rose petals, sparkles, lips (always on). Fixed decorations: envelopes (always present). Cupid appears randomly - more likely at higher intensity."),e("Guy Fawkes Night",'[guy-fawkes intensity="medium" bonfires="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): bonfires. Particles: embers, fireworks, sparks, rockets, bursts, trails (always on). Fixed decorations: guy-effigy, catherine-wheel, roman-candle, sparkler-bundle, moon. Starts at 25% particle density and builds up gradually."),e("St Andrew's Day",'[st-andrews intensity="medium" thistles="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): thistles, twinklingStars. Particles: heather petals, saltire sparkles (always on). Fixed decorations: bagpiper, saltire-flag, tartan-pattern, highland-scene (always present). Bagpiper probability increases with intensity."),e("St David's Day",'[st-davids intensity="medium" daffodilFields="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): daffodilFields, twinklingStars. Particles: daffodil petals, spring sparkles (always on). Fixed decorations: welsh-dragon, harp, leek-bundle, flag (always present). Flying dragon appears randomly - more likely at higher intensity."),e("St George's Day",'[st-georges intensity="medium" roses="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): roses (English roses), twinklingStars. Particles: rose petals, Tudor roses, oak leaves, sparkles (always on). Fixed decorations: st-georges-cross, dragon, shield, castle (always present). Knight appears randomly - more likely at higher intensity.")],outro:"Enable the Domma Effects plugin to activate these shortcodes on your site."}),t("DConfig - Declarative Behaviour",{intro:"Define click handlers and class toggles without writing JavaScript. Use the DConfig section above or embed inline with [dconfig]...[/dconfig] in the content body. Inline shortcodes win on selector conflict.",examples:[e("Toggle a class on click",'{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }','Selector keys use standard CSS selectors. "target" is optional - defaults to the element itself.'),e("Inline shortcode syntax",`[dconfig]
|
|
100
100
|
{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }
|
|
101
|
-
[/dconfig]`)]}),t("CSS Editor",{intro:"The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page - one Save, one toast.",rows:[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]]}),t("Colour Picker",{intro:"Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss."})];export const REFERENCE=[{id:"basics",label:"Basics",sections:m},{id:"layout",label:"Layout",sections:h},{id:"components",label:"Components",sections:g},{id:"data",label:"Data",sections:b},{id:"advanced",label:"Advanced",sections:f}];const
|
|
101
|
+
[/dconfig]`)]}),t("CSS Editor",{intro:"The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page - one Save, one toast.",rows:[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]]}),t("Colour Picker",{intro:"Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss."})];export const REFERENCE=[{id:"basics",label:"Basics",sections:m},{id:"layout",label:"Layout",sections:h},{id:"components",label:"Components",sections:g},{id:"data",label:"Data",sections:b},{id:"advanced",label:"Advanced",sections:f}];const w=`
|
|
102
102
|
<div class="per">
|
|
103
103
|
<div class="per-tabs" role="tablist" data-each="tabs key=id">
|
|
104
104
|
<button type="button" class="per-tab" role="tab" data-on-click="$root.show(id)"
|
|
@@ -164,4 +164,4 @@ pre.per-block { padding-right: .75rem; margin-bottom: .5rem; }
|
|
|
164
164
|
.per-copy { position: absolute; top: .3rem; right: .3rem; background: none; border: none; cursor: pointer; opacity: .45; padding: .15rem;
|
|
165
165
|
line-height: 1; color: inherit; }
|
|
166
166
|
.per-copy:hover, .per-copy:focus-visible { opacity: 1; }
|
|
167
|
-
</style>`;async function
|
|
167
|
+
</style>`;async function y(o){try{return await navigator.clipboard.writeText(o),!0}catch{const a=document.createElement("textarea");a.value=o,a.style.cssText="position:fixed;opacity:0;",document.body.appendChild(a),a.select();let n=!1;try{n=document.execCommand("copy")}catch{}return a.remove(),n}}export function openEditorReference(){const o=E.slideover({title:"Editor Reference",size:"md",position:"right"}),a=document.createElement("div");a.innerHTML=w;const n=M.observable("basics"),s=M.applyBindings({tabs:REFERENCE,tab:n,show:r=>{n.value=r},copy:async r=>{const i=await y(r);E.toast(i?"Copied!":"Could not copy - select the code and copy it.",{type:i?"success":"warning",duration:1200})}},a);o.element.appendChild(a);const l=M.effect(()=>{n.value,requestAnimationFrame(()=>I.scan(a))});p(o,()=>{try{l()}catch{}try{s.dispose()}catch{}}),o.open()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CORE as m,checkProject as p}from"./projects-arrange.js";export const TYPES=[{key:"pages",label:"Pages",singular:"page",icon:"file-text",tone:"var(--dm-primary)",path:"/pages/new"},{key:"collections",label:"Collections",singular:"collection",icon:"database",tone:"var(--dm-secondary)",path:"/collections/new"},{key:"forms",label:"Forms",singular:"form",icon:"layout",tone:"var(--dm-success)",path:"/forms/new"},{key:"actions",label:"Actions",singular:"action",icon:"zap",tone:"var(--dm-warning, var(--dm-primary))",path:"/actions/new"},{key:"menus",label:"
|
|
1
|
+
import{CORE as m,checkProject as p}from"./projects-arrange.js";export const TYPES=[{key:"pages",label:"Pages",singular:"page",icon:"file-text",tone:"var(--dm-primary)",path:"/pages/new"},{key:"collections",label:"Collections",singular:"collection",icon:"database",tone:"var(--dm-secondary)",path:"/collections/new"},{key:"forms",label:"Forms",singular:"form",icon:"layout",tone:"var(--dm-success)",path:"/forms/new"},{key:"actions",label:"Actions",singular:"action",icon:"zap",tone:"var(--dm-warning, var(--dm-primary))",path:"/actions/new"},{key:"menus",label:"Site menus",singular:"menu",icon:"menu",tone:"var(--dm-info)",path:"/menus/new"},{key:"blocks",label:"Blocks",singular:"block",icon:"box",tone:"var(--dm-primary-hover, var(--dm-primary))",path:"/blocks/new"},{key:"components",label:"Components",singular:"component",icon:"component",tone:"var(--dm-warning-dark, var(--dm-warning, var(--dm-secondary)))",path:"/components/new"},{key:"views",label:"Views",singular:"view",icon:"eye",tone:"var(--dm-info)",path:"/views/new"},{key:"roles",label:"Roles",singular:"role",icon:"shield",tone:"var(--dm-danger)",path:"/roles"},{key:"users",label:"Users",singular:"user",icon:"users",tone:"var(--dm-secondary)",path:"/users/new"},{key:"apis",label:"APIs",singular:"API endpoint",icon:"code",tone:"var(--dm-success)",path:"/api-endpoints/new"}];export function projectFromPath(e,{settings:t=!1}={}){const r=String(e||"").replace(/^#/,"").split("?")[0].replace(/\/+$/,""),n=t?r.match(/^\/projects\/([^/]+)\/settings$/):r.match(/^\/projects\/([^/]+)$/);if(!n||!t&&(n[1]==="new"||n[1]==="edit"))return null;try{return decodeURIComponent(n[1])}catch{return null}}export function countsOf(e){return Object.fromEntries(Object.entries(e||{}).map(([t,r])=>[t,Array.isArray(r)?r.length:Number(r)||0]))}export function tilesFor(e,{slug:t,inline:r=[]}={}){const n=encodeURIComponent(t);let a=0;return{tiles:TYPES.map(o=>{const s=Number(e?.[o.key])||0;a+=s;const c=o.path.includes("?")?"&":"?";return{key:o.key,label:o.label,singular:o.singular,icon:o.icon,tone:o.tone,count:s,has:s>0,cls:s>0?"":"is-empty",inline:r.includes(o.key),listHash:`#/projects/${n}/${o.key}`,newHash:`#${o.path}${c}project=${n}`,countText:String(s)}}),total:a,totalText:`${a} artefact${a===1?"":"s"}`}}export function relTime(e,t=Date.now()){if(!e)return"";const r=new Date(e).getTime();if(Number.isNaN(r))return"";const n=Math.max(0,Math.round((t-r)/1e3)),a=Math.round(n/60),i=Math.round(a/60),o=Math.round(i/24),s=(l,u)=>`${l} ${u}${l===1?"":"s"} ago`;if(n<45)return"just now";if(a<60)return s(a,"min");if(i<24)return s(i,"hour");if(o<30)return s(o,"day");const c=Math.round(o/30);return c<12?s(c,"month"):s(Math.round(o/365),"year")}export function settingsForm(e={}){return{name:String(e.name??""),description:String(e.description??""),icon:String(e.icon||"folder"),rootUrl:String(e.rootUrl??""),sortOrder:String(e.sortOrder??0),enabled:e.enabled!==!1}}export function settingsSnapshot(e={}){return JSON.stringify({name:String(e.name??"").trim(),description:String(e.description??"").trim(),icon:String(e.icon??"").trim()||"folder",rootUrl:String(e.rootUrl??"").trim(),sortOrder:String(Number.parseInt(e.sortOrder,10)||0),enabled:e.enabled!==!1})}export function settingsPayload(e,t={}){return p(e,{isNew:!1,isProtected:t.protected===!0,slug:t.slug||""})}export function settingsRules(e={}){const t=e.slug===m,r=e.protected===!0;return{isCore:t,isProtected:r,canToggle:!t,rootLocked:r,canDelete:!r,canUntag:!r}}export const draftKey=e=>`project-settings.draft.${e}`;export function untagSummary(e){const t=TYPES.map(n=>[n,Number(e?.[n.key])||0]).filter(([,n])=>n>0).map(([n,a])=>`${a} ${a===1?n.singular:n.key==="apis"?"API endpoints":n.label.toLowerCase()}`);return{total:Object.values(e||{}).reduce((n,a)=>n+(Number(a)||0),0),text:t.length?t.join(", "):"nothing"}}
|