domma-cms 0.46.3 → 0.47.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.46.3",
3
+ "version": "0.47.0",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -81,7 +81,7 @@
81
81
  "@fastify/rate-limit": "^10.3.0",
82
82
  "@fastify/static": "9.1.1",
83
83
  "bcryptjs": "^3.0.3",
84
- "domma-js": "0.41.0",
84
+ "domma-js": "0.42.0",
85
85
  "dotenv": "^17.2.3",
86
86
  "fastify": "5.8.5",
87
87
  "gray-matter": "^4.0.3",
package/public/js/site.js CHANGED
@@ -1 +1 @@
1
- import{makeBadgeEl as M,applyColour as N,applyPill as z,applyFloat as j}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as O,markInvalidFields as P,showValidationPopup as R}from"/public/js/forms.js?v=20260821-wizard-grid";import{buildWizardSteps as B}from"/public/js/form-steps.mjs";$(()=>{const w=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let t=function(o){const e=(o||"07:00").split(":");return+e[0]*60+(+e[1]||0)},a=function(){const o=new Date,e=o.getHours()*60+o.getMinutes();return e>=t(n.dayStart)&&e<t(n.nightStart)?n.dayTheme:n.nightTheme};const n=g.autoTheme;Domma.theme.set(a()),setInterval(()=>Domma.theme.set(a()),6e4)}const x=$("#site-navbar");if(x.length&&w.brand){let a=function(r,u=0){return Array.isArray(r)?r.filter(c=>!(c&&c.type==="separator"&&u===0)).map(c=>c&&c.type==="separator"?{divider:!0}:Array.isArray(c?.items)?{...c,items:a(c.items,u+1)}:c):r},o=function(r){return Array.isArray(r)?r.filter(u=>!(u&&u.type==="separator")):[]};const n={...w.brand},t=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let r="";n.logo?r+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(r+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(r+=`<span class="navbar-brand-text${t}">${n.text}</span>`),n.tagline&&(r+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=r}else t&&n.text&&(n.html=`<span class="navbar-brand-text${t}">${n.text}</span>`);const e=w.position==="floating",d=w.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:n,items:a(w.items||[]),variant:w.variant||"dark",position:e?"static":w.position||"sticky",collapsible:!0}),Domma.icons.scan("#site-navbar"),d&&x.get(0).classList.add("dm-nav-vertical",w.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),e&&j(x.get(0),w);const h=x.get(0);if(w.appearOnHover){const r=window.matchMedia("(min-width: 993px)");h.querySelectorAll(".navbar-dropdown").forEach(u=>{u.addEventListener("mouseenter",()=>{r.matches&&u.classList.add("open")}),u.addEventListener("mouseleave",()=>{r.matches&&u.classList.remove("open")})})}const y=h.querySelector(".navbar-toggle"),f=h.querySelector(".navbar-collapse");if(y&&f){let r=null;const u=()=>{f.classList.contains("show")&&y.click()},c=()=>{r&&(r.remove(),r=null),document.body.classList.remove("dm-drawer-open")},s=()=>{r||(r=document.createElement("div"),r.className="dm-navbar-backdrop",r.addEventListener("click",u),document.body.appendChild(r),document.body.classList.add("dm-drawer-open"))};y.addEventListener("click",()=>{requestAnimationFrame(()=>{f.classList.contains("show")?s():c()})}),f.addEventListener("click",i=>{i.target.closest("a")&&requestAnimationFrame(c)}),document.addEventListener("keydown",i=>{i.key==="Escape"&&f.classList.contains("show")&&u()})}const m=o(w.items||[]);h.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(r=>{const u=m[parseInt(r.dataset.index,10)];if(!u)return;const c=r.dataset.subindex!=null,s=c&&Array.isArray(u.items)?u.items[parseInt(r.dataset.subindex,10)]:u;if(!s)return;s.colour&&N(r,s.colour),s.pill&&!c&&z(r,s.pill);const i=M(s.badge);i&&r.appendChild(i)})}const C=$("#site-footer");if(C.length){let e=function(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},d=function(s){return e(s).replace(/'/g,"&#39;")},h=function(s){if(s&&s.type==="separator")return'<li class="footer-sep"><hr></li>';const i=d(s.url||"#"),l=e(s.text||""),v=Array.isArray(s.items)&&s.items.length?`<ul>${s.items.map(h).join("")}</ul>`:"";return`<li><a href="${i}">${l}</a>${v}</li>`},y=function(s,i){return(s||[]).forEach(l=>{l&&l.type==="separator"||(i.push(l),Array.isArray(l.items)&&l.items.length&&y(l.items,i))}),i};const n=g.social||{},t={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let a='<div class="footer-inner container">';const o=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(o.copyright&&(a+=`<p>${e(o.copyright)}</p>`),o.primary.length&&(a+=`<nav class="footer-nav footer-nav--primary"><ul>${o.primary.map(h).join("")}</ul></nav>`),o.legal.length&&(a+=`<nav class="footer-nav footer-nav--legal"><ul>${o.legal.map(h).join("")}</ul></nav>`),g.footer){const s=Object.keys(t).filter(i=>n[i]);s.length&&(a+='<div class="footer-social">',s.forEach(i=>{const{label:l,svg:v}=t[i];a+=`<a href="${n[i]}" target="_blank" rel="noopener noreferrer" aria-label="${l}" class="footer-social-link">${v}</a>`}),a+="</div>")}a+="</div>",C.html(a);const f=[...y(o.primary,[]),...y(o.legal,[])];C.get(0).querySelectorAll(".footer-nav a").forEach((s,i)=>{const l=f[i];if(!l)return;l.colour&&N(s,l.colour);const v=M(l.badge);v&&s.appendChild(v)});const r=S.get("reduced_motion"),u=r!==null?!!r:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),c=C.get(0).querySelector(".footer-inner");if(c){const s=document.createElement("input");s.type="checkbox",s.className="form-switch-input",s.id="dm-motion-switch",s.checked=u,s.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const i=document.createElement("span");i.className="form-switch-label",i.textContent="Reduce motion";const l=document.createElement("label");l.className="form-switch footer-motion-switch",l.title="Reduce motion",l.appendChild(s),l.appendChild(i),c.appendChild(l)}}$("#site-sidebar").length&&Domma.elements.sidebar("#site-sidebar",{autoGenerate:!0,selector:"h2, h3",collapsible:!1,push:!0,contentSelector:".site-content"}),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const p=$(".page-body");if(p.length){p.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),p.find(".tabs").each(function(){Domma.elements.tabs(this)}),p.find(".carousel").each(function(){const n={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const t=parseInt(this.dataset.animationDuration,10);Number.isFinite(t)&&(n.animationDuration=t)}this.dataset.animationEasing&&(n.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(t=>t.cloneNode(!0)),this._dmCarouselOpts=n),this._dmCarousel=Domma.elements.carousel(this,n)}),p.find(".dm-countdown").each(function(){const n={autoStart:!0};this.dataset.to&&(n.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(n.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(n.format=this.dataset.format),Domma.elements.timer(this,n)}),p.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),p.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(o=>{const e={title:o.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:o.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return o.dataset.date&&(e.date=o.dataset.date),o.dataset.status&&(e.status=o.dataset.status),o.dataset.entryId&&(e._entryId=o.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",a=Domma.elements.progression(this,{layout:t,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});n.length&&(this._dmCtx={instance:a,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const t=n.dataset.revealMode||"stagger",a=n.dataset.revealAnimation||"slide-up",o=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,d=parseInt(n.dataset.revealDelay,10)||0,h=n.dataset.revealDirection==="rtl",y=Array.from(n.children),f={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};y.forEach((m,r)=>{m.style.opacity="0",m.style.transform=f[a]||"",m.style.transition=`opacity ${o}ms ease, transform ${o}ms ease`;const u=h?y.length-1-r:r;m.style.transitionDelay=t==="stagger"?`${d+u*e}ms`:`${d}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(r=>{r.forEach(u=>{u.isIntersecting&&(u.target.offsetWidth,u.target.style.opacity="1",u.target.style.transform="none",m.unobserve(u.target))})},{threshold:.1});y.forEach(r=>m.observe(r))}))}),p.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),p.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,t=document.getElementById(n);if(!t)return;const a=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",a.setContent(t),a.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const a=atob(t.dataset.config),o=JSON.parse(a);Object.assign(n,o)}catch{}}),Object.keys(n).length>0){const t={};for(const[a,o]of Object.entries(n)){const e=o?.events?.click,{confirm:d,toast:h,alert:y,prompt:f,...m}=e||{};d||h||y||f?($(a).on("click",async function(u){if(u.preventDefault(),d&&!await E.confirm(d))return;let c=null;if(!(f&&(c=await E.prompt(f,{inputPlaceholder:m.promptPlaceholder||"",inputValue:m.promptDefault||""}),c===null))){if(m.target){const s=$(m.target);m.toggleClass&&s.toggleClass(m.toggleClass),m.addClass&&s.addClass(m.addClass),m.removeClass&&s.removeClass(m.removeClass),c!==null&&(m.setText&&s.text(c),m.setVal&&s.val(c),m.setAttr&&s.attr(m.setAttr,c))}m.href&&(window.location.href=m.href),h&&E.toast(h,{type:m.toastType||"success"}),y&&E.alert(y)}}),Object.keys(m).length&&(t[a]={...o,events:{...o.events,click:m}})):t[a]=o}$.setup(t)}}p.length&&D(p.get(0))});function D(w){w.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const x=g.dataset.action,C=g.dataset.entry,k=g.dataset.confirm;let p=S.get("auth_token");if(!p){E.toast("Please log in to perform this action.",{type:"warning"});return}if(k&&!await E.confirm(k))return;const n=Array.from(g.childNodes).map(a=>a.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const t=a=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({entryId:C})});try{let a=await t(p);if(a.status===401){const e=S.get("auth_refresh_token");if(e){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(d.ok){const{token:h}=await d.json();S.set("auth_token",h),p=h,a=await t(p)}}}const o=await a.json().catch(()=>({}));if(!a.ok)throw new Error(o.error||o.message||`Error ${a.status}`);E.toast(o.message||"Action completed.",{type:"success"})}catch(a){E.toast(a.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",n.forEach(a=>g.appendChild(a)),Domma.icons.scan(g)}}))})}(function(){const g=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!g.length)return;const x=S.get("auth_token");function C(p,n){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const a=document.createElement("p");if(n){a.appendChild(document.createTextNode("Please "));const o=document.createElement("a");o.href="/login",o.textContent="sign in",a.appendChild(o),a.appendChild(document.createTextNode(" to view your entries."))}else a.textContent=p;return t.appendChild(a),t}function k(p,n){const t=document.createElement("template");t.innerHTML=n||"",p.replaceWith(t.content)}g.forEach(async p=>{const n=p.dataset.collectionAttrs;if(!n)return;if(!x){p.replaceChildren(C("",!0));return}const t=a=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({attrs:n})});try{let a=x,o=await t(a);if(o.status===401){const d=S.get("auth_refresh_token");if(d){const h=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(h.ok){const{token:y}=await h.json();S.set("auth_token",y),a=y,o=await t(a)}}}if(!o.ok){const{error:d}=await o.json().catch(()=>({}));p.replaceChildren(C(d||"Unable to load entries.",!1));return}const{html:e}=await o.json();k(p,e)}catch{p.replaceChildren(C("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),D(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(x=>{let C;try{C=JSON.parse(atob(x.dataset.payload))}catch{return}const{columns:k,rows:p,search:n,sortable:t,exportable:a,pageSize:o,empty:e,ctaConfig:d,slug:h,exportCfg:y}=C;if(!k?.length)return;if(d){const r=k.findIndex(u=>u.key==="_cta");r!==-1&&(k[r]={key:"_cta",title:"",render:(u,c)=>{const s=document.createElement("button");if(s.className=`btn btn-${d.style||"primary"} dm-cta-trigger`,s.dataset.action=d.action||"",s.dataset.entry=c._entryId||"",d.confirm&&(s.dataset.confirm=d.confirm),d.icon){const i=document.createElement("span");i.dataset.icon=d.icon,s.appendChild(i),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(d.label||"Run")),s}})}const f="col-table-"+Math.random().toString(36).slice(2,7),m=document.createElement("div");m.id=f,x.replaceChildren(m),T.create("#"+f,{data:p,columns:k,search:n,sortable:t,exportable:a,pageSize:o,emptyMessage:e}),d&&D(m),x._dmTable={columns:k,rows:p,slug:h,exportCfg:y,render(r){T.create("#"+f,{data:r,columns:k,search:n,sortable:t,exportable:a,pageSize:o,emptyMessage:e}),d&&D(m)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function x(t){const a=t&&t.logic;return!!(a&&(a.visibility||a.requirement))}function C(t,a){const o={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const d=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),h=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":d?"chooser":e.type,y={...e.formConfig||{}};y.span==="full"&&a&&(y.span=a);const f={type:h,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...y}};d&&(e.variant&&(f.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(f.multiple=!0),e.density&&(f.density=e.density),e.columns&&(f.columns=e.columns),e.accent&&(f.accent=e.accent),e.accentStyle&&(f.accentStyle=e.accentStyle),e.glow&&(f.glow=!0),e.glowColour&&(f.glowColour=e.glowColour),e.shadow&&(f.shadow=e.shadow),e.shadowColour&&(f.shadowColour=e.shadowColour)),o[e.name]=f}),o}function k(t){const a={};return(t||[]).forEach(o=>{if(!(!o.name||o.type==="page-break"||o.type==="spacer")&&(o.type==="select"||o.type==="multiselect")&&o.required){const e=(o.options||[])[0];e&&(a[o.name]=typeof e=="object"?e.value:e)}}),a}function p(t,a){(a||[]).forEach(o=>{if(o.type!=="date"||!o.name)return;const e=t.querySelector(`[name="${o.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(t,a,o){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=a,e.style.cssText=o?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(t=>{let a;try{a=JSON.parse(atob(t.dataset.formInline))}catch{return}const o=a.fields||[],e=a.settings||{},d=Number(e.columns)===3?3:2,h=e.layout||"grid",y=o.some(c=>c.type==="page-break"),f=async c=>{try{const s=t.querySelector(".fb-form-honeypot"),i=s?.querySelector('input[type="text"]')||null,l=s?.querySelector('[name="_t"]')||null,v=Object.assign({},c);delete v._t,s?.dataset.hpName&&delete v[s.dataset.hpName],i!==null&&(v._hp=i.value),l!==null&&(v._t=l.value);const b=await H.post(`/api/forms/submit/${a.slug}`,v);if(b&&b.error){n(t,b.error,!0);const I=new Error(b.error);throw I.formSubmitFailed=!0,I}if(b?.redirect){window.location.href=b.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);n(t,b?.message||e.successMessage||"Thank you for your submission.",!1)}catch(s){throw s.formSubmitFailed||n(t,s.message||"Submission failed. Please try again.",!0),s}},m=Date.now();function r(c){const s=c.querySelector("form");if(!s||s.querySelector(".fb-form-honeypot"))return;const i=document.createElement("div");i.className="fb-form-honeypot",i.setAttribute("aria-hidden","true");const l=document.createElement("input");l.name=s.querySelector('[name="website"]')?"_website":"website",i.dataset.hpName=l.name,l.type="text",l.tabIndex=-1,l.autocomplete="url",l.placeholder="https://",i.appendChild(l);const v=document.createElement("input");v.name="_t",v.type="hidden",v.value=m,i.appendChild(v),s.appendChild(i)}function u(c){if(!window.FormLogicEngine||!o.some(i=>i.logic))return null;const s=new window.FormLogicEngine.FormLogicRuntime(a,t,c?{baseValues:c}:void 0);if(s.init(),t._formLogicRuntime=s,t._formLogicObserved)return s;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const i=new MutationObserver(function(l){for(const v of l)for(const b of v.removedNodes)if(b===t||b.nodeType===1&&b.contains&&b.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),i.disconnect();return}});i.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=i}return s}if(y&&F.wizard){const c=B(o,a.title),s=c.map(_=>({title:_.title,description:_.description,fields:C(_.fields,d)})),i=c.map(_=>_.fields);let l=0,v=null,b=null;const I=_=>{const A=window.FormLogicEngine;if(!A||!A.validateFields)return;const L=A.validateFields(t,i[l]||[]);L.valid||(_.preventDefault(),_.stopImmediatePropagation(),P(t,L.missing),R(L))},q=()=>{const _=i[l]||o;p(t,_),O(t,_),e.honeypot!==!1&&r(t),v&&v.destroy(),v=u(b?.getStepData?b.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(A=>A.addEventListener("click",I,!0))};b=F.wizard(t,{schema:{steps:s},layout:h,columns:d,finishText:e.submitText||"Finish",onSubmit:f,onStepChange:_=>{l=_,setTimeout(q,0)}}),Promise.resolve(b).then(q)}else if(F.render){const c=F.render(t,C(o,d),k(o),{submitText:e.submitText||"Submit",layout:h,columns:d,onSubmit:f});Promise.resolve(c).then(function(){if(h==="grid"&&e.submitSpan==="full"){const s=t.querySelector(".form-buttons");s&&s.classList.add("col-span-full")}p(t,o),O(t,o),e.honeypot!==!1&&r(t),u()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
1
+ import{makeBadgeEl as M,applyColour as N,applyPill as z,applyFloat as j}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as O,markInvalidFields as P,showValidationPopup as R}from"/public/js/forms.js?v=20260821-wizard-grid";import{buildWizardSteps as B}from"/public/js/form-steps.mjs";$(()=>{const w=window.__CMS_NAV__||{},h=window.__CMS_SITE__||{};if(h.autoTheme?.enabled){let t=function(o){const e=(o||"07:00").split(":");return+e[0]*60+(+e[1]||0)},a=function(){const o=new Date,e=o.getHours()*60+o.getMinutes();return e>=t(n.dayStart)&&e<t(n.nightStart)?n.dayTheme:n.nightTheme};const n=h.autoTheme;Domma.theme.set(a()),setInterval(()=>Domma.theme.set(a()),6e4)}const x=$("#site-navbar");if(x.length&&w.brand){let a=function(r,f=0){return Array.isArray(r)?r.filter(c=>!(c&&c.type==="separator"&&f===0)).map(c=>c&&c.type==="separator"?{divider:!0}:Array.isArray(c?.items)?{...c,items:a(c.items,f+1)}:c):r},o=function(r){return Array.isArray(r)?r.filter(f=>!(f&&f.type==="separator")):[]};const n={...w.brand},t=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let r="";n.logo?r+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(r+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(r+=`<span class="navbar-brand-text${t}">${n.text}</span>`),n.tagline&&(r+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=r}else t&&n.text&&(n.html=`<span class="navbar-brand-text${t}">${n.text}</span>`);const e=w.position==="floating",d=w.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:n,items:a(w.items||[]),variant:w.variant||"dark",position:e?"static":w.position||"sticky",collapsible:!0,appearOnHover:!!w.appearOnHover}),Domma.icons.scan("#site-navbar"),d&&x.get(0).classList.add("dm-nav-vertical",w.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),e&&j(x.get(0),w);const g=x.get(0),y=g.querySelector(".navbar-toggle"),p=g.querySelector(".navbar-collapse");if(y&&p){let r=null;const f=()=>{p.classList.contains("show")&&y.click()},c=()=>{r&&(r.remove(),r=null),document.body.classList.remove("dm-drawer-open")},s=()=>{r||(r=document.createElement("div"),r.className="dm-navbar-backdrop",r.addEventListener("click",f),document.body.appendChild(r),document.body.classList.add("dm-drawer-open"))};y.addEventListener("click",()=>{requestAnimationFrame(()=>{p.classList.contains("show")?s():c()})}),p.addEventListener("click",i=>{i.target.closest("a")&&requestAnimationFrame(c)}),document.addEventListener("keydown",i=>{i.key==="Escape"&&p.classList.contains("show")&&f()})}const m=o(w.items||[]);g.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(r=>{const f=m[parseInt(r.dataset.index,10)];if(!f)return;const c=r.dataset.subindex!=null,s=c&&Array.isArray(f.items)?f.items[parseInt(r.dataset.subindex,10)]:f;if(!s)return;s.colour&&N(r,s.colour),s.pill&&!c&&z(r,s.pill);const i=M(s.badge);i&&r.appendChild(i)})}const C=$("#site-footer");if(C.length){let e=function(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},d=function(s){return e(s).replace(/'/g,"&#39;")},g=function(s){if(s&&s.type==="separator")return'<li class="footer-sep"><hr></li>';const i=d(s.url||"#"),l=e(s.text||""),v=Array.isArray(s.items)&&s.items.length?`<ul>${s.items.map(g).join("")}</ul>`:"";return`<li><a href="${i}">${l}</a>${v}</li>`},y=function(s,i){return(s||[]).forEach(l=>{l&&l.type==="separator"||(i.push(l),Array.isArray(l.items)&&l.items.length&&y(l.items,i))}),i};const n=h.social||{},t={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let a='<div class="footer-inner container">';const o=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(o.copyright&&(a+=`<p>${e(o.copyright)}</p>`),o.primary.length&&(a+=`<nav class="footer-nav footer-nav--primary"><ul>${o.primary.map(g).join("")}</ul></nav>`),o.legal.length&&(a+=`<nav class="footer-nav footer-nav--legal"><ul>${o.legal.map(g).join("")}</ul></nav>`),h.footer){const s=Object.keys(t).filter(i=>n[i]);s.length&&(a+='<div class="footer-social">',s.forEach(i=>{const{label:l,svg:v}=t[i];a+=`<a href="${n[i]}" target="_blank" rel="noopener noreferrer" aria-label="${l}" class="footer-social-link">${v}</a>`}),a+="</div>")}a+="</div>",C.html(a);const p=[...y(o.primary,[]),...y(o.legal,[])];C.get(0).querySelectorAll(".footer-nav a").forEach((s,i)=>{const l=p[i];if(!l)return;l.colour&&N(s,l.colour);const v=M(l.badge);v&&s.appendChild(v)});const r=S.get("reduced_motion"),f=r!==null?!!r:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),c=C.get(0).querySelector(".footer-inner");if(c){const s=document.createElement("input");s.type="checkbox",s.className="form-switch-input",s.id="dm-motion-switch",s.checked=f,s.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const i=document.createElement("span");i.className="form-switch-label",i.textContent="Reduce motion";const l=document.createElement("label");l.className="form-switch footer-motion-switch",l.title="Reduce motion",l.appendChild(s),l.appendChild(i),c.appendChild(l)}}$("#site-sidebar").length&&Domma.elements.sidebar("#site-sidebar",{autoGenerate:!0,selector:"h2, h3",collapsible:!1,push:!0,contentSelector:".site-content"}),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const u=$(".page-body");if(u.length){u.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),u.find(".tabs").each(function(){Domma.elements.tabs(this)}),u.find(".carousel").each(function(){const n={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const t=parseInt(this.dataset.animationDuration,10);Number.isFinite(t)&&(n.animationDuration=t)}this.dataset.animationEasing&&(n.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(t=>t.cloneNode(!0)),this._dmCarouselOpts=n),this._dmCarousel=Domma.elements.carousel(this,n)}),u.find(".dm-countdown").each(function(){const n={autoStart:!0};this.dataset.to&&(n.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(n.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(n.format=this.dataset.format),Domma.elements.timer(this,n)}),u.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),u.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(o=>{const e={title:o.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:o.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return o.dataset.date&&(e.date=o.dataset.date),o.dataset.status&&(e.status=o.dataset.status),o.dataset.entryId&&(e._entryId=o.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",a=Domma.elements.progression(this,{layout:t,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});n.length&&(this._dmCtx={instance:a,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const t=n.dataset.revealMode||"stagger",a=n.dataset.revealAnimation||"slide-up",o=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,d=parseInt(n.dataset.revealDelay,10)||0,g=n.dataset.revealDirection==="rtl",y=Array.from(n.children),p={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};y.forEach((m,r)=>{m.style.opacity="0",m.style.transform=p[a]||"",m.style.transition=`opacity ${o}ms ease, transform ${o}ms ease`;const f=g?y.length-1-r:r;m.style.transitionDelay=t==="stagger"?`${d+f*e}ms`:`${d}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(r=>{r.forEach(f=>{f.isIntersecting&&(f.target.offsetWidth,f.target.style.opacity="1",f.target.style.transform="none",m.unobserve(f.target))})},{threshold:.1});y.forEach(r=>m.observe(r))}))}),u.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),u.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,t=document.getElementById(n);if(!t)return;const a=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",a.setContent(t),a.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const a=atob(t.dataset.config),o=JSON.parse(a);Object.assign(n,o)}catch{}}),Object.keys(n).length>0){const t={};for(const[a,o]of Object.entries(n)){const e=o?.events?.click,{confirm:d,toast:g,alert:y,prompt:p,...m}=e||{};d||g||y||p?($(a).on("click",async function(f){if(f.preventDefault(),d&&!await E.confirm(d))return;let c=null;if(!(p&&(c=await E.prompt(p,{inputPlaceholder:m.promptPlaceholder||"",inputValue:m.promptDefault||""}),c===null))){if(m.target){const s=$(m.target);m.toggleClass&&s.toggleClass(m.toggleClass),m.addClass&&s.addClass(m.addClass),m.removeClass&&s.removeClass(m.removeClass),c!==null&&(m.setText&&s.text(c),m.setVal&&s.val(c),m.setAttr&&s.attr(m.setAttr,c))}m.href&&(window.location.href=m.href),g&&E.toast(g,{type:m.toastType||"success"}),y&&E.alert(y)}}),Object.keys(m).length&&(t[a]={...o,events:{...o.events,click:m}})):t[a]=o}$.setup(t)}}u.length&&D(u.get(0))});function D(w){w.querySelectorAll(".dm-cta-trigger").forEach(h=>{h.__ctaWired||(h.__ctaWired=!0,h.addEventListener("click",async()=>{const x=h.dataset.action,C=h.dataset.entry,k=h.dataset.confirm;let u=S.get("auth_token");if(!u){E.toast("Please log in to perform this action.",{type:"warning"});return}if(k&&!await E.confirm(k))return;const n=Array.from(h.childNodes).map(a=>a.cloneNode(!0));h.disabled=!0,h.textContent="Running\u2026";const t=a=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({entryId:C})});try{let a=await t(u);if(a.status===401){const e=S.get("auth_refresh_token");if(e){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(d.ok){const{token:g}=await d.json();S.set("auth_token",g),u=g,a=await t(u)}}}const o=await a.json().catch(()=>({}));if(!a.ok)throw new Error(o.error||o.message||`Error ${a.status}`);E.toast(o.message||"Action completed.",{type:"success"})}catch(a){E.toast(a.message||"Action failed.",{type:"error"})}finally{h.disabled=!1,h.textContent="",n.forEach(a=>h.appendChild(a)),Domma.icons.scan(h)}}))})}(function(){const h=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!h.length)return;const x=S.get("auth_token");function C(u,n){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const a=document.createElement("p");if(n){a.appendChild(document.createTextNode("Please "));const o=document.createElement("a");o.href="/login",o.textContent="sign in",a.appendChild(o),a.appendChild(document.createTextNode(" to view your entries."))}else a.textContent=u;return t.appendChild(a),t}function k(u,n){const t=document.createElement("template");t.innerHTML=n||"",u.replaceWith(t.content)}h.forEach(async u=>{const n=u.dataset.collectionAttrs;if(!n)return;if(!x){u.replaceChildren(C("",!0));return}const t=a=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({attrs:n})});try{let a=x,o=await t(a);if(o.status===401){const d=S.get("auth_refresh_token");if(d){const g=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(g.ok){const{token:y}=await g.json();S.set("auth_token",y),a=y,o=await t(a)}}}if(!o.ok){const{error:d}=await o.json().catch(()=>({}));u.replaceChildren(C(d||"Unable to load entries.",!1));return}const{html:e}=await o.json();k(u,e)}catch{u.replaceChildren(C("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),D(document.body)},100)})(),(function(){const h=document.querySelectorAll("[data-collection-table]");!h.length||typeof T>"u"||!T.create||h.forEach(x=>{let C;try{C=JSON.parse(atob(x.dataset.payload))}catch{return}const{columns:k,rows:u,search:n,sortable:t,exportable:a,pageSize:o,empty:e,ctaConfig:d,slug:g,exportCfg:y}=C;if(!k?.length)return;if(d){const r=k.findIndex(f=>f.key==="_cta");r!==-1&&(k[r]={key:"_cta",title:"",render:(f,c)=>{const s=document.createElement("button");if(s.className=`btn btn-${d.style||"primary"} dm-cta-trigger`,s.dataset.action=d.action||"",s.dataset.entry=c._entryId||"",d.confirm&&(s.dataset.confirm=d.confirm),d.icon){const i=document.createElement("span");i.dataset.icon=d.icon,s.appendChild(i),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(d.label||"Run")),s}})}const p="col-table-"+Math.random().toString(36).slice(2,7),m=document.createElement("div");m.id=p,x.replaceChildren(m),T.create("#"+p,{data:u,columns:k,search:n,sortable:t,exportable:a,pageSize:o,emptyMessage:e}),d&&D(m),x._dmTable={columns:k,rows:u,slug:g,exportCfg:y,render(r){T.create("#"+p,{data:r,columns:k,search:n,sortable:t,exportable:a,pageSize:o,emptyMessage:e}),d&&D(m)}}})})(),(function(){const h=document.querySelectorAll("[data-form-inline]");if(!h.length||typeof F>"u")return;function x(t){const a=t&&t.logic;return!!(a&&(a.visibility||a.requirement))}function C(t,a){const o={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const d=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),g=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":d?"chooser":e.type,y={...e.formConfig||{}};y.span==="full"&&a&&(y.span=a);const p={type:g,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...y}};d&&(e.variant&&(p.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(p.multiple=!0),e.density&&(p.density=e.density),e.columns&&(p.columns=e.columns),e.accent&&(p.accent=e.accent),e.accentStyle&&(p.accentStyle=e.accentStyle),e.glow&&(p.glow=!0),e.glowColour&&(p.glowColour=e.glowColour),e.shadow&&(p.shadow=e.shadow),e.shadowColour&&(p.shadowColour=e.shadowColour)),o[e.name]=p}),o}function k(t){const a={};return(t||[]).forEach(o=>{if(!(!o.name||o.type==="page-break"||o.type==="spacer")&&(o.type==="select"||o.type==="multiselect")&&o.required){const e=(o.options||[])[0];e&&(a[o.name]=typeof e=="object"?e.value:e)}}),a}function u(t,a){(a||[]).forEach(o=>{if(o.type!=="date"||!o.name)return;const e=t.querySelector(`[name="${o.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(t,a,o){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=a,e.style.cssText=o?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}h.forEach(t=>{let a;try{a=JSON.parse(atob(t.dataset.formInline))}catch{return}const o=a.fields||[],e=a.settings||{},d=Number(e.columns)===3?3:2,g=e.layout||"grid",y=o.some(c=>c.type==="page-break"),p=async c=>{try{const s=t.querySelector(".fb-form-honeypot"),i=s?.querySelector('input[type="text"]')||null,l=s?.querySelector('[name="_t"]')||null,v=Object.assign({},c);delete v._t,s?.dataset.hpName&&delete v[s.dataset.hpName],i!==null&&(v._hp=i.value),l!==null&&(v._t=l.value);const b=await H.post(`/api/forms/submit/${a.slug}`,v);if(b&&b.error){n(t,b.error,!0);const I=new Error(b.error);throw I.formSubmitFailed=!0,I}if(b?.redirect){window.location.href=b.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);n(t,b?.message||e.successMessage||"Thank you for your submission.",!1)}catch(s){throw s.formSubmitFailed||n(t,s.message||"Submission failed. Please try again.",!0),s}},m=Date.now();function r(c){const s=c.querySelector("form");if(!s||s.querySelector(".fb-form-honeypot"))return;const i=document.createElement("div");i.className="fb-form-honeypot",i.setAttribute("aria-hidden","true");const l=document.createElement("input");l.name=s.querySelector('[name="website"]')?"_website":"website",i.dataset.hpName=l.name,l.type="text",l.tabIndex=-1,l.autocomplete="url",l.placeholder="https://",i.appendChild(l);const v=document.createElement("input");v.name="_t",v.type="hidden",v.value=m,i.appendChild(v),s.appendChild(i)}function f(c){if(!window.FormLogicEngine||!o.some(i=>i.logic))return null;const s=new window.FormLogicEngine.FormLogicRuntime(a,t,c?{baseValues:c}:void 0);if(s.init(),t._formLogicRuntime=s,t._formLogicObserved)return s;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const i=new MutationObserver(function(l){for(const v of l)for(const b of v.removedNodes)if(b===t||b.nodeType===1&&b.contains&&b.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),i.disconnect();return}});i.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=i}return s}if(y&&F.wizard){const c=B(o,a.title),s=c.map(_=>({title:_.title,description:_.description,fields:C(_.fields,d)})),i=c.map(_=>_.fields);let l=0,v=null,b=null;const I=_=>{const A=window.FormLogicEngine;if(!A||!A.validateFields)return;const L=A.validateFields(t,i[l]||[]);L.valid||(_.preventDefault(),_.stopImmediatePropagation(),P(t,L.missing),R(L))},q=()=>{const _=i[l]||o;u(t,_),O(t,_),e.honeypot!==!1&&r(t),v&&v.destroy(),v=f(b?.getStepData?b.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(A=>A.addEventListener("click",I,!0))};b=F.wizard(t,{schema:{steps:s},layout:g,columns:d,finishText:e.submitText||"Finish",onSubmit:p,onStepChange:_=>{l=_,setTimeout(q,0)}}),Promise.resolve(b).then(q)}else if(F.render){const c=F.render(t,C(o,d),k(o),{submitText:e.submitText||"Submit",layout:g,columns:d,onSubmit:p});Promise.resolve(c).then(function(){if(g==="grid"&&e.submitSpan==="full"){const s=t.querySelector(".form-buttons");s&&s.classList.add("col-span-full")}u(t,o),O(t,o),e.honeypot!==!1&&r(t),f()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
@@ -0,0 +1 @@
1
+ export const SIZE_MAP={xs:".75rem",sm:".875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},WEIGHT_MAP={thin:"100",light:"300",normal:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},SPACING_MAP={tight:"-0.05em",normal:"0em",wide:"0.05em",wider:"0.1em"},COLOUR_TOKENS={primary:"var(--dm-color-primary)",secondary:"var(--dm-color-secondary)",muted:"var(--dm-text-muted)",danger:"var(--dm-color-danger)",success:"var(--dm-color-success)",warning:"var(--dm-color-warning)",info:"var(--dm-color-info)"},FONT_MAP={Georgia:"Georgia,serif",Arial:"Arial,sans-serif",Verdana:"Verdana,sans-serif","Courier New":"'Courier New',monospace","Times New Roman":"'Times New Roman',serif","Trebuchet MS":"'Trebuchet MS',sans-serif"},TRANSFORM_MAP={upper:"uppercase",lower:"lowercase",capitalize:"capitalize",none:"none"},DECORATION_MAP={underline:"underline","line-through":"line-through",none:"none"};function l(e){return e!=null&&e!==!1&&e!=="false"&&e!=="0"}function i(e){return String(e).replace(/["<>]/g,"").trim()}export function buildTextStyle(e={}){const o=[];if(e.size&&o.push(`font-size:${SIZE_MAP[e.size]||i(e.size)}`),e["point-size"]){const r=parseFloat(e["point-size"]);!isNaN(r)&&r>0&&o.push(`font-size:${r}pt`)}l(e.bold)?o.push("font-weight:700"):e.weight&&WEIGHT_MAP[e.weight]&&o.push(`font-weight:${WEIGHT_MAP[e.weight]}`),l(e.italic)&&o.push("font-style:italic");const n=e.colour||e.color;return n&&o.push(`color:${COLOUR_TOKENS[n]||i(n)}`),e.font&&FONT_MAP[e.font]&&o.push(`font-family:${FONT_MAP[e.font]}`),e.transform&&TRANSFORM_MAP[e.transform]&&o.push(`text-transform:${TRANSFORM_MAP[e.transform]}`),e.decoration&&DECORATION_MAP[e.decoration]&&o.push(`text-decoration:${DECORATION_MAP[e.decoration]}`),e.spacing&&o.push(`letter-spacing:${SPACING_MAP[e.spacing]||i(e.spacing)}`),e.align&&(o.push("display:block"),o.push(`text-align:${i(e.align)}`)),e.style&&o.push(i(e.style).replace(/;+$/,"")),o.join(";")}
@@ -15,6 +15,7 @@ import {getMenu, resolveLocation, resolveMenuDecorations} from './menus.js';
15
15
  import {buildMenuNav} from './menuRender.js';
16
16
  import {checkVisibility} from '../middleware/auth.js';
17
17
  import {getRoleHierarchy} from './roles.js';
18
+ import {buildTextStyle} from '../../public/js/text-style.mjs';
18
19
 
19
20
  const __dirname_md = path.dirname(fileURLToPath(import.meta.url));
20
21
  const BLOCKS_DIR = path.resolve(__dirname_md, '../../content/blocks');
@@ -3014,94 +3015,12 @@ function processBadgeBlocks(markdown) {
3014
3015
  function processTextBlocks(markdown) {
3015
3016
  const {scrubbed, restore} = scrubCodeRegions(markdown);
3016
3017
 
3017
- const SIZE_MAP = {
3018
- xs: '.75rem', sm: '.875rem', base: '1rem', lg: '1.125rem',
3019
- xl: '1.25rem', '2xl': '1.5rem', '3xl': '1.875rem', '4xl': '2.25rem',
3020
- };
3021
- const WEIGHT_MAP = {
3022
- thin: '100', light: '300', normal: '400', medium: '500',
3023
- semibold: '600', bold: '700', extrabold: '800', black: '900',
3024
- };
3025
- const SPACING_MAP = {
3026
- tight: '-0.05em', normal: '0em', wide: '0.05em', wider: '0.1em',
3027
- };
3028
- const COLOR_TOKENS = {
3029
- primary: 'var(--dm-color-primary)', secondary: 'var(--dm-color-secondary)',
3030
- muted: 'var(--dm-text-muted)', danger: 'var(--dm-color-danger)',
3031
- success: 'var(--dm-color-success)', warning: 'var(--dm-color-warning)',
3032
- info: 'var(--dm-color-info)',
3033
- };
3034
- const FONT_MAP = {
3035
- 'Georgia': 'Georgia,serif',
3036
- 'Arial': 'Arial,sans-serif',
3037
- 'Verdana': 'Verdana,sans-serif',
3038
- 'Courier New': "'Courier New',monospace",
3039
- 'Times New Roman': "'Times New Roman',serif",
3040
- 'Trebuchet MS': "'Trebuchet MS',sans-serif",
3041
- };
3042
- const TRANSFORM_MAP = {
3043
- upper: 'uppercase', lower: 'lowercase', capitalize: 'capitalize', none: 'none',
3044
- };
3045
- const DECORATION_MAP = {
3046
- underline: 'underline', 'line-through': 'line-through', none: 'none',
3047
- };
3048
-
3049
3018
  function buildText(attrStr, inner) {
3050
3019
  const attrs = parseShortcodeAttrs(attrStr || '');
3051
- const styles = [];
3052
-
3053
- if (attrs.size) {
3054
- styles.push(`font-size:${SIZE_MAP[attrs.size] || attrs.size}`);
3055
- }
3056
-
3057
- if (attrs['point-size']) {
3058
- const pt = parseFloat(attrs['point-size']);
3059
- if (!isNaN(pt) && pt > 0) styles.push(`font-size:${pt}pt`);
3060
- }
3061
-
3062
- // bold flag takes precedence over weight attr
3063
- const isBold = /\bbold\b/i.test(attrStr);
3064
- if (isBold) {
3065
- styles.push('font-weight:700');
3066
- } else if (attrs.weight && WEIGHT_MAP[attrs.weight]) {
3067
- styles.push(`font-weight:${WEIGHT_MAP[attrs.weight]}`);
3068
- }
3069
-
3070
- if (/\bitalic\b/i.test(attrStr)) {
3071
- styles.push('font-style:italic');
3072
- }
3073
-
3074
- const colourVal = attrs.colour || attrs.color;
3075
- if (colourVal) {
3076
- styles.push(`color:${COLOR_TOKENS[colourVal] || colourVal}`);
3077
- }
3078
-
3079
- if (attrs.font && FONT_MAP[attrs.font]) {
3080
- styles.push(`font-family:${FONT_MAP[attrs.font]}`);
3081
- }
3082
-
3083
- if (attrs.transform && TRANSFORM_MAP[attrs.transform]) {
3084
- styles.push(`text-transform:${TRANSFORM_MAP[attrs.transform]}`);
3085
- }
3086
-
3087
- if (attrs.decoration && DECORATION_MAP[attrs.decoration]) {
3088
- styles.push(`text-decoration:${DECORATION_MAP[attrs.decoration]}`);
3089
- }
3090
-
3091
- if (attrs.spacing) {
3092
- styles.push(`letter-spacing:${SPACING_MAP[attrs.spacing] || attrs.spacing}`);
3093
- }
3094
-
3095
- if (attrs.align) {
3096
- styles.push('display:block');
3097
- styles.push(`text-align:${escapeAttr(attrs.align)}`);
3098
- }
3099
-
3100
- if (attrs.style) {
3101
- styles.push(attrs.style.trim().replace(/;+$/, ''));
3102
- }
3103
-
3104
- const styleAttr = styles.length ? ` style="${styles.join(';')}"` : '';
3020
+ // The attribute → CSS mapping is shared with the admin editor's live
3021
+ // preview (public/js/text-style.mjs), so the two cannot disagree.
3022
+ const style = buildTextStyle(attrs);
3023
+ const styleAttr = style ? ` style="${style}"` : '';
3105
3024
  const classAttr = attrs.class ? ` class="${escapeAttr(attrs.class)}"` : '';
3106
3025
  const idAttr = attrs.id ? ` id="${escapeAttr(attrs.id)}"` : '';
3107
3026