domma-cms 0.41.1 → 0.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/public/js/site.js CHANGED
@@ -1 +1 @@
1
- import{makeBadgeEl as _,applyColour as A,applyPill as I,applyFloat as M}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as D}from"/public/js/forms.js?v=20260817-multi-chooser";$(()=>{const b=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let o=function(e){const d=(e||"07:00").split(":");return+d[0]*60+(+d[1]||0)},a=function(){const e=new Date,d=e.getHours()*60+e.getMinutes();return d>=o(t.dayStart)&&d<o(t.nightStart)?t.dayTheme:t.nightTheme};const t=g.autoTheme;Domma.theme.set(a()),setInterval(()=>Domma.theme.set(a()),6e4)}const v=$("#site-navbar");if(v.length&&b.brand){let a=function(s,n=0){return Array.isArray(s)?s.filter(i=>!(i&&i.type==="separator"&&n===0)).map(i=>i&&i.type==="separator"?{divider:!0}:Array.isArray(i?.items)?{...i,items:a(i.items,n+1)}:i):s},e=function(s){return Array.isArray(s)?s.filter(n=>!(n&&n.type==="separator")):[]};const t={...b.brand},o=t.size&&t.size!=="md"?` navbar-brand-${t.size}`:"";if(t.logo||t.icon||t.tagline){let s="";t.logo?s+=`<img src="${t.logo}" class="navbar-brand-logo" alt="${t.text||""}">`:t.icon&&(s+=`<span data-icon="${t.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),t.text&&(s+=`<span class="navbar-brand-text${o}">${t.text}</span>`),t.tagline&&(s+=`<small class="navbar-brand-tagline">${t.tagline}</small>`),t.html=s}else o&&t.text&&(t.html=`<span class="navbar-brand-text${o}">${t.text}</span>`);const d=b.position==="floating";b.orientation==="vertical"&&v.get(0).classList.add("dm-nav-vertical",b.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),Domma.elements.navbar("#site-navbar",{brand:t,items:a(b.items||[]),variant:b.variant||"dark",position:d?"static":b.position||"sticky",collapsible:!0}),Domma.icons.scan("#site-navbar"),d&&M(v.get(0),b);const f=v.get(0);if(b.appearOnHover){const s=window.matchMedia("(min-width: 993px)");f.querySelectorAll(".navbar-dropdown").forEach(n=>{n.addEventListener("mouseenter",()=>{s.matches&&n.classList.add("open")}),n.addEventListener("mouseleave",()=>{s.matches&&n.classList.remove("open")})})}const l=f.querySelector(".navbar-toggle"),y=f.querySelector(".navbar-collapse");if(l&&y){let s=null;const n=()=>{y.classList.contains("show")&&l.click()},i=()=>{s&&(s.remove(),s=null),document.body.classList.remove("dm-drawer-open")},r=()=>{s||(s=document.createElement("div"),s.className="dm-navbar-backdrop",s.addEventListener("click",n),document.body.appendChild(s),document.body.classList.add("dm-drawer-open"))};l.addEventListener("click",()=>{requestAnimationFrame(()=>{y.classList.contains("show")?r():i()})}),y.addEventListener("click",c=>{c.target.closest("a")&&requestAnimationFrame(i)}),document.addEventListener("keydown",c=>{c.key==="Escape"&&y.classList.contains("show")&&n()})}const m=e(b.items||[]);f.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(s=>{const n=m[parseInt(s.dataset.index,10)];if(!n)return;const i=s.dataset.subindex!=null,r=i&&Array.isArray(n.items)?n.items[parseInt(s.dataset.subindex,10)]:n;if(!r)return;r.colour&&A(s,r.colour),r.pill&&!i&&I(s,r.pill);const c=_(r.badge);c&&s.appendChild(c)})}const w=$("#site-footer");if(w.length){let d=function(r){return String(r??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},p=function(r){return d(r).replace(/'/g,"&#39;")},f=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';const c=p(r.url||"#"),h=d(r.text||""),k=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(f).join("")}</ul>`:"";return`<li><a href="${c}">${h}</a>${k}</li>`},l=function(r,c){return(r||[]).forEach(h=>{h&&h.type==="separator"||(c.push(h),Array.isArray(h.items)&&h.items.length&&l(h.items,c))}),c};const t=g.social||{},o={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let a='<div class="footer-inner container">';const e=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(e.copyright&&(a+=`<p>${d(e.copyright)}</p>`),e.primary.length&&(a+=`<nav class="footer-nav footer-nav--primary"><ul>${e.primary.map(f).join("")}</ul></nav>`),e.legal.length&&(a+=`<nav class="footer-nav footer-nav--legal"><ul>${e.legal.map(f).join("")}</ul></nav>`),g.footer){const r=Object.keys(o).filter(c=>t[c]);r.length&&(a+='<div class="footer-social">',r.forEach(c=>{const{label:h,svg:k}=o[c];a+=`<a href="${t[c]}" target="_blank" rel="noopener noreferrer" aria-label="${h}" class="footer-social-link">${k}</a>`}),a+="</div>")}a+="</div>",w.html(a);const y=[...l(e.primary,[]),...l(e.legal,[])];w.get(0).querySelectorAll(".footer-nav a").forEach((r,c)=>{const h=y[c];if(!h)return;h.colour&&A(r,h.colour);const k=_(h.badge);k&&r.appendChild(k)});const s=S.get("reduced_motion"),n=s!==null?!!s:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),i=w.get(0).querySelector(".footer-inner");if(i){const r=document.createElement("input");r.type="checkbox",r.className="form-switch-input",r.id="dm-motion-switch",r.checked=n,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const c=document.createElement("span");c.className="form-switch-label",c.textContent="Reduce motion";const h=document.createElement("label");h.className="form-switch footer-motion-switch",h.title="Reduce motion",h.appendChild(r),h.appendChild(c),i.appendChild(h)}}$("#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 t={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 o=parseInt(this.dataset.animationDuration,10);Number.isFinite(o)&&(t.animationDuration=o)}this.dataset.animationEasing&&(t.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(o=>o.cloneNode(!0)),this._dmCarouselOpts=t),this._dmCarousel=Domma.elements.carousel(this,t)}),u.find(".dm-countdown").each(function(){const t={autoStart:!0};this.dataset.to&&(t.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(t.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(t.format=this.dataset.format),Domma.elements.timer(this,t)}),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 t=Array.from(this.querySelectorAll(".dm-progression-item")).map(e=>{const d={title:e.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:e.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return e.dataset.date&&(d.date=e.dataset.date),e.dataset.status&&(d.status=e.dataset.status),e.dataset.entryId&&(d._entryId=e.dataset.entryId),d}),o=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",a=Domma.elements.progression(this,{layout:o,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...t.length?{items:t}:{}});t.length&&(this._dmCtx={instance:a,items:t})});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(t=>{const o=t.dataset.revealMode||"stagger",a=t.dataset.revealAnimation||"slide-up",e=parseInt(t.dataset.revealDuration,10)||400,d=parseInt(t.dataset.revealStagger,10)||60,p=parseInt(t.dataset.revealDelay,10)||0,f=t.dataset.revealDirection==="rtl",l=Array.from(t.children),y={"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)"};l.forEach((m,s)=>{m.style.opacity="0",m.style.transform=y[a]||"",m.style.transition=`opacity ${e}ms ease, transform ${e}ms ease`;const n=f?l.length-1-s:s;m.style.transitionDelay=o==="stagger"?`${p+n*d}ms`:`${p}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(s=>{s.forEach(n=>{n.isIntersecting&&(n.target.offsetWidth,n.target.style.opacity="1",n.target.style.transform="none",m.unobserve(n.target))})},{threshold:.1});l.forEach(s=>m.observe(s))}))}),u.find(".card[data-collapsible]").each(function(){const t=this.querySelector(".card-header");t&&t.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),u.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const t=this.dataset.soTarget,o=document.getElementById(t);if(!o)return;const a=E.slideover({title:o.dataset.soTitle||"",size:o.dataset.soSize||"md",position:o.dataset.soPosition||"right"});o.style.display="",a.setContent(o),a.open()})})}if(typeof $.setup=="function"){const t=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(o=>{try{const a=atob(o.dataset.config),e=JSON.parse(a);Object.assign(t,e)}catch{}}),Object.keys(t).length>0){const o={};for(const[a,e]of Object.entries(t)){const d=e?.events?.click,{confirm:p,toast:f,alert:l,prompt:y,...m}=d||{};p||f||l||y?($(a).on("click",async function(n){if(n.preventDefault(),p&&!await E.confirm(p))return;let i=null;if(!(y&&(i=await E.prompt(y,{inputPlaceholder:m.promptPlaceholder||"",inputValue:m.promptDefault||""}),i===null))){if(m.target){const r=$(m.target);m.toggleClass&&r.toggleClass(m.toggleClass),m.addClass&&r.addClass(m.addClass),m.removeClass&&r.removeClass(m.removeClass),i!==null&&(m.setText&&r.text(i),m.setVal&&r.val(i),m.setAttr&&r.attr(m.setAttr,i))}m.href&&(window.location.href=m.href),f&&E.toast(f,{type:m.toastType||"success"}),l&&E.alert(l)}}),Object.keys(m).length&&(o[a]={...e,events:{...e.events,click:m}})):o[a]=e}$.setup(o)}}u.length&&x(u.get(0))});function x(b){b.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const v=g.dataset.action,w=g.dataset.entry,C=g.dataset.confirm;let u=S.get("auth_token");if(!u){E.toast("Please log in to perform this action.",{type:"warning"});return}if(C&&!await E.confirm(C))return;const t=Array.from(g.childNodes).map(a=>a.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const o=a=>fetch(`/api/actions/${v}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({entryId:w})});try{let a=await o(u);if(a.status===401){const d=S.get("auth_refresh_token");if(d){const p=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(p.ok){const{token:f}=await p.json();S.set("auth_token",f),u=f,a=await o(u)}}}const e=await a.json().catch(()=>({}));if(!a.ok)throw new Error(e.error||e.message||`Error ${a.status}`);E.toast(e.message||"Action completed.",{type:"success"})}catch(a){E.toast(a.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",t.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 v=S.get("auth_token");function w(u,t){const o=document.createElement("div");o.className="dm-collection-display dm-collection-empty";const a=document.createElement("p");if(t){a.appendChild(document.createTextNode("Please "));const e=document.createElement("a");e.href="/login",e.textContent="sign in",a.appendChild(e),a.appendChild(document.createTextNode(" to view your entries."))}else a.textContent=u;return o.appendChild(a),o}function C(u,t){const o=document.createElement("template");o.innerHTML=t||"",u.replaceWith(o.content)}g.forEach(async u=>{const t=u.dataset.collectionAttrs;if(!t)return;if(!v){u.replaceChildren(w("",!0));return}const o=a=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({attrs:t})});try{let a=v,e=await o(a);if(e.status===401){const p=S.get("auth_refresh_token");if(p){const f=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:p})});if(f.ok){const{token:l}=await f.json();S.set("auth_token",l),a=l,e=await o(a)}}}if(!e.ok){const{error:p}=await e.json().catch(()=>({}));u.replaceChildren(w(p||"Unable to load entries.",!1));return}const{html:d}=await e.json();C(u,d)}catch{u.replaceChildren(w("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),x(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(v=>{let w;try{w=JSON.parse(atob(v.dataset.payload))}catch{return}const{columns:C,rows:u,search:t,sortable:o,exportable:a,pageSize:e,empty:d,ctaConfig:p}=w;if(!C?.length)return;if(p){const y=C.findIndex(m=>m.key==="_cta");y!==-1&&(C[y]={key:"_cta",title:"",render:(m,s)=>{const n=document.createElement("button");if(n.className=`btn btn-${p.style||"primary"} dm-cta-trigger`,n.dataset.action=p.action||"",n.dataset.entry=s._entryId||"",p.confirm&&(n.dataset.confirm=p.confirm),p.icon){const i=document.createElement("span");i.dataset.icon=p.icon,n.appendChild(i),n.appendChild(document.createTextNode(" "))}return n.appendChild(document.createTextNode(p.label||"Run")),n}})}const f="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=f,v.replaceChildren(l),T.create("#"+f,{data:u,columns:C,search:t,sortable:o,exportable:a,pageSize:e,emptyMessage:d}),p&&x(l),v._dmTable={columns:C,rows:u,render(y){T.create("#"+f,{data:y,columns:C,search:t,sortable:o,exportable:a,pageSize:e,emptyMessage:d}),p&&x(l)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function v(t,o){const a={};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)),p=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":d?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&o&&(f.span=o);const l={type:p,label:e.label,required:e.required,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...f}};d&&(e.variant&&(l.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(l.multiple=!0),e.density&&(l.density=e.density),e.columns&&(l.columns=e.columns),e.accent&&(l.accent=e.accent),e.accentStyle&&(l.accentStyle=e.accentStyle),e.glow&&(l.glow=!0),e.glowColour&&(l.glowColour=e.glowColour),e.shadow&&(l.shadow=e.shadow),e.shadowColour&&(l.shadowColour=e.shadowColour)),a[e.name]=l}),a}function w(t){const o={};return(t||[]).forEach(a=>{if(!(!a.name||a.type==="page-break"||a.type==="spacer")&&(a.type==="select"||a.type==="multiselect")&&a.required){const e=(a.options||[])[0];e&&(o[a.name]=typeof e=="object"?e.value:e)}}),o}function C(t,o){(o||[]).forEach(a=>{if(a.type!=="date"||!a.name)return;const e=t.querySelector(`[name="${a.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function u(t,o,a){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=o,e.style.cssText=a?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(t=>{let o;try{o=JSON.parse(atob(t.dataset.formInline))}catch{return}const a=o.fields||[],e=o.settings||{},d=e.columns||1,p=e.layout||"stacked",f=a.some(s=>s.type==="page-break"),l=async s=>{try{const n=t.querySelector('[name="website"]'),i=t.querySelector('[name="_t"]'),r=Object.assign({},s);n!==null&&(r._hp=n.value),i!==null&&(r._t=i.value);const c=await H.post(`/api/forms/submit/${o.slug}`,r);if(c&&c.error){u(t,c.error,!0);const h=new Error(c.error);throw h.formSubmitFailed=!0,h}if(c?.redirect){window.location.href=c.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);u(t,c?.message||e.successMessage||"Thank you for your submission.",!1)}catch(n){throw n.formSubmitFailed||u(t,n.message||"Submission failed. Please try again.",!0),n}};function y(s){const n=s.querySelector("form");if(!n)return;const i=document.createElement("div");i.className="fb-form-honeypot",i.setAttribute("aria-hidden","true");const r=document.createElement("input");r.name="website",r.type="text",r.tabIndex=-1,r.autocomplete="url",r.placeholder="https://",i.appendChild(r);const c=document.createElement("input");c.name="_t",c.type="hidden",c.value=Date.now(),i.appendChild(c),n.appendChild(i)}function m(){if(!window.FormLogicEngine||!a.some(n=>n.logic))return;const s=new window.FormLogicEngine.FormLogicRuntime(o,t);if(s.init(),t._formLogicRuntime=s,t.parentNode&&typeof MutationObserver<"u"){const n=new MutationObserver(function(i){for(const r of i)for(const c of r.removedNodes)if(c===t||c.nodeType===1&&c.contains&&c.contains(t)){s.destroy(),n.disconnect();return}});n.observe(t.parentNode,{childList:!0,subtree:!1})}}if(f&&F.wizard){const s=[];let n=[],i=o.title||"Step 1",r="";a.forEach(h=>{h.type==="page-break"?(s.push({title:i,description:r,fields:v(n,d)}),n=[],i=h.label||`Step ${s.length+1}`,r=h.description||""):h.type!=="spacer"&&n.push(h)}),s.push({title:i,description:r,fields:v(n,d)});const c=F.wizard(t,{schema:{steps:s},onSubmit:l});Promise.resolve(c).then(function(){C(t,a),D(t,a),e.honeypot!==!1&&y(t),m()})}else if(F.render){const s=F.render(t,v(a,d),w(a),{submitText:e.submitText||"Submit",layout:p,columns:d,onSubmit:l});Promise.resolve(s).then(function(){if(p==="grid"&&e.submitSpan==="full"){const n=t.querySelector(".form-buttons");n&&n.classList.add("col-span-full")}C(t,a),D(t,a),e.honeypot!==!1&&y(t),m()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
1
+ import{makeBadgeEl as _,applyColour as A,applyPill as I,applyFloat as M}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as D}from"/public/js/forms.js?v=20260817-multi-chooser";$(()=>{const b=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let n=function(e){const d=(e||"07:00").split(":");return+d[0]*60+(+d[1]||0)},a=function(){const e=new Date,d=e.getHours()*60+e.getMinutes();return d>=n(t.dayStart)&&d<n(t.nightStart)?t.dayTheme:t.nightTheme};const t=g.autoTheme;Domma.theme.set(a()),setInterval(()=>Domma.theme.set(a()),6e4)}const v=$("#site-navbar");if(v.length&&b.brand){let a=function(s,r=0){return Array.isArray(s)?s.filter(c=>!(c&&c.type==="separator"&&r===0)).map(c=>c&&c.type==="separator"?{divider:!0}:Array.isArray(c?.items)?{...c,items:a(c.items,r+1)}:c):s},e=function(s){return Array.isArray(s)?s.filter(r=>!(r&&r.type==="separator")):[]};const t={...b.brand},n=t.size&&t.size!=="md"?` navbar-brand-${t.size}`:"";if(t.logo||t.icon||t.tagline){let s="";t.logo?s+=`<img src="${t.logo}" class="navbar-brand-logo" alt="${t.text||""}">`:t.icon&&(s+=`<span data-icon="${t.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),t.text&&(s+=`<span class="navbar-brand-text${n}">${t.text}</span>`),t.tagline&&(s+=`<small class="navbar-brand-tagline">${t.tagline}</small>`),t.html=s}else n&&t.text&&(t.html=`<span class="navbar-brand-text${n}">${t.text}</span>`);const d=b.position==="floating";b.orientation==="vertical"&&v.get(0).classList.add("dm-nav-vertical",b.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),Domma.elements.navbar("#site-navbar",{brand:t,items:a(b.items||[]),variant:b.variant||"dark",position:d?"static":b.position||"sticky",collapsible:!0}),Domma.icons.scan("#site-navbar"),d&&M(v.get(0),b);const h=v.get(0);if(b.appearOnHover){const s=window.matchMedia("(min-width: 993px)");h.querySelectorAll(".navbar-dropdown").forEach(r=>{r.addEventListener("mouseenter",()=>{s.matches&&r.classList.add("open")}),r.addEventListener("mouseleave",()=>{s.matches&&r.classList.remove("open")})})}const m=h.querySelector(".navbar-toggle"),y=h.querySelector(".navbar-collapse");if(m&&y){let s=null;const r=()=>{y.classList.contains("show")&&m.click()},c=()=>{s&&(s.remove(),s=null),document.body.classList.remove("dm-drawer-open")},o=()=>{s||(s=document.createElement("div"),s.className="dm-navbar-backdrop",s.addEventListener("click",r),document.body.appendChild(s),document.body.classList.add("dm-drawer-open"))};m.addEventListener("click",()=>{requestAnimationFrame(()=>{y.classList.contains("show")?o():c()})}),y.addEventListener("click",i=>{i.target.closest("a")&&requestAnimationFrame(c)}),document.addEventListener("keydown",i=>{i.key==="Escape"&&y.classList.contains("show")&&r()})}const l=e(b.items||[]);h.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(s=>{const r=l[parseInt(s.dataset.index,10)];if(!r)return;const c=s.dataset.subindex!=null,o=c&&Array.isArray(r.items)?r.items[parseInt(s.dataset.subindex,10)]:r;if(!o)return;o.colour&&A(s,o.colour),o.pill&&!c&&I(s,o.pill);const i=_(o.badge);i&&s.appendChild(i)})}const w=$("#site-footer");if(w.length){let d=function(o){return String(o??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},p=function(o){return d(o).replace(/'/g,"&#39;")},h=function(o){if(o&&o.type==="separator")return'<li class="footer-sep"><hr></li>';const i=p(o.url||"#"),f=d(o.text||""),k=Array.isArray(o.items)&&o.items.length?`<ul>${o.items.map(h).join("")}</ul>`:"";return`<li><a href="${i}">${f}</a>${k}</li>`},m=function(o,i){return(o||[]).forEach(f=>{f&&f.type==="separator"||(i.push(f),Array.isArray(f.items)&&f.items.length&&m(f.items,i))}),i};const t=g.social||{},n={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 e=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(e.copyright&&(a+=`<p>${d(e.copyright)}</p>`),e.primary.length&&(a+=`<nav class="footer-nav footer-nav--primary"><ul>${e.primary.map(h).join("")}</ul></nav>`),e.legal.length&&(a+=`<nav class="footer-nav footer-nav--legal"><ul>${e.legal.map(h).join("")}</ul></nav>`),g.footer){const o=Object.keys(n).filter(i=>t[i]);o.length&&(a+='<div class="footer-social">',o.forEach(i=>{const{label:f,svg:k}=n[i];a+=`<a href="${t[i]}" target="_blank" rel="noopener noreferrer" aria-label="${f}" class="footer-social-link">${k}</a>`}),a+="</div>")}a+="</div>",w.html(a);const y=[...m(e.primary,[]),...m(e.legal,[])];w.get(0).querySelectorAll(".footer-nav a").forEach((o,i)=>{const f=y[i];if(!f)return;f.colour&&A(o,f.colour);const k=_(f.badge);k&&o.appendChild(k)});const s=S.get("reduced_motion"),r=s!==null?!!s:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),c=w.get(0).querySelector(".footer-inner");if(c){const o=document.createElement("input");o.type="checkbox",o.className="form-switch-input",o.id="dm-motion-switch",o.checked=r,o.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 f=document.createElement("label");f.className="form-switch footer-motion-switch",f.title="Reduce motion",f.appendChild(o),f.appendChild(i),c.appendChild(f)}}$("#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 t={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 n=parseInt(this.dataset.animationDuration,10);Number.isFinite(n)&&(t.animationDuration=n)}this.dataset.animationEasing&&(t.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(n=>n.cloneNode(!0)),this._dmCarouselOpts=t),this._dmCarousel=Domma.elements.carousel(this,t)}),u.find(".dm-countdown").each(function(){const t={autoStart:!0};this.dataset.to&&(t.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(t.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(t.format=this.dataset.format),Domma.elements.timer(this,t)}),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 t=Array.from(this.querySelectorAll(".dm-progression-item")).map(e=>{const d={title:e.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:e.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return e.dataset.date&&(d.date=e.dataset.date),e.dataset.status&&(d.status=e.dataset.status),e.dataset.entryId&&(d._entryId=e.dataset.entryId),d}),n=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",a=Domma.elements.progression(this,{layout:n,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...t.length?{items:t}:{}});t.length&&(this._dmCtx={instance:a,items:t})});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(t=>{const n=t.dataset.revealMode||"stagger",a=t.dataset.revealAnimation||"slide-up",e=parseInt(t.dataset.revealDuration,10)||400,d=parseInt(t.dataset.revealStagger,10)||60,p=parseInt(t.dataset.revealDelay,10)||0,h=t.dataset.revealDirection==="rtl",m=Array.from(t.children),y={"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)"};m.forEach((l,s)=>{l.style.opacity="0",l.style.transform=y[a]||"",l.style.transition=`opacity ${e}ms ease, transform ${e}ms ease`;const r=h?m.length-1-s:s;l.style.transitionDelay=n==="stagger"?`${p+r*d}ms`:`${p}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const l=new IntersectionObserver(s=>{s.forEach(r=>{r.isIntersecting&&(r.target.offsetWidth,r.target.style.opacity="1",r.target.style.transform="none",l.unobserve(r.target))})},{threshold:.1});m.forEach(s=>l.observe(s))}))}),u.find(".card[data-collapsible]").each(function(){const t=this.querySelector(".card-header");t&&t.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),u.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const t=this.dataset.soTarget,n=document.getElementById(t);if(!n)return;const a=E.slideover({title:n.dataset.soTitle||"",size:n.dataset.soSize||"md",position:n.dataset.soPosition||"right"});n.style.display="",a.setContent(n),a.open()})})}if(typeof $.setup=="function"){const t=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(n=>{try{const a=atob(n.dataset.config),e=JSON.parse(a);Object.assign(t,e)}catch{}}),Object.keys(t).length>0){const n={};for(const[a,e]of Object.entries(t)){const d=e?.events?.click,{confirm:p,toast:h,alert:m,prompt:y,...l}=d||{};p||h||m||y?($(a).on("click",async function(r){if(r.preventDefault(),p&&!await E.confirm(p))return;let c=null;if(!(y&&(c=await E.prompt(y,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),c===null))){if(l.target){const o=$(l.target);l.toggleClass&&o.toggleClass(l.toggleClass),l.addClass&&o.addClass(l.addClass),l.removeClass&&o.removeClass(l.removeClass),c!==null&&(l.setText&&o.text(c),l.setVal&&o.val(c),l.setAttr&&o.attr(l.setAttr,c))}l.href&&(window.location.href=l.href),h&&E.toast(h,{type:l.toastType||"success"}),m&&E.alert(m)}}),Object.keys(l).length&&(n[a]={...e,events:{...e.events,click:l}})):n[a]=e}$.setup(n)}}u.length&&x(u.get(0))});function x(b){b.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const v=g.dataset.action,w=g.dataset.entry,C=g.dataset.confirm;let u=S.get("auth_token");if(!u){E.toast("Please log in to perform this action.",{type:"warning"});return}if(C&&!await E.confirm(C))return;const t=Array.from(g.childNodes).map(a=>a.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const n=a=>fetch(`/api/actions/${v}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({entryId:w})});try{let a=await n(u);if(a.status===401){const d=S.get("auth_refresh_token");if(d){const p=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(p.ok){const{token:h}=await p.json();S.set("auth_token",h),u=h,a=await n(u)}}}const e=await a.json().catch(()=>({}));if(!a.ok)throw new Error(e.error||e.message||`Error ${a.status}`);E.toast(e.message||"Action completed.",{type:"success"})}catch(a){E.toast(a.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",t.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 v=S.get("auth_token");function w(u,t){const n=document.createElement("div");n.className="dm-collection-display dm-collection-empty";const a=document.createElement("p");if(t){a.appendChild(document.createTextNode("Please "));const e=document.createElement("a");e.href="/login",e.textContent="sign in",a.appendChild(e),a.appendChild(document.createTextNode(" to view your entries."))}else a.textContent=u;return n.appendChild(a),n}function C(u,t){const n=document.createElement("template");n.innerHTML=t||"",u.replaceWith(n.content)}g.forEach(async u=>{const t=u.dataset.collectionAttrs;if(!t)return;if(!v){u.replaceChildren(w("",!0));return}const n=a=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({attrs:t})});try{let a=v,e=await n(a);if(e.status===401){const p=S.get("auth_refresh_token");if(p){const h=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:p})});if(h.ok){const{token:m}=await h.json();S.set("auth_token",m),a=m,e=await n(a)}}}if(!e.ok){const{error:p}=await e.json().catch(()=>({}));u.replaceChildren(w(p||"Unable to load entries.",!1));return}const{html:d}=await e.json();C(u,d)}catch{u.replaceChildren(w("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),x(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(v=>{let w;try{w=JSON.parse(atob(v.dataset.payload))}catch{return}const{columns:C,rows:u,search:t,sortable:n,exportable:a,pageSize:e,empty:d,ctaConfig:p,slug:h,exportCfg:m}=w;if(!C?.length)return;if(p){const s=C.findIndex(r=>r.key==="_cta");s!==-1&&(C[s]={key:"_cta",title:"",render:(r,c)=>{const o=document.createElement("button");if(o.className=`btn btn-${p.style||"primary"} dm-cta-trigger`,o.dataset.action=p.action||"",o.dataset.entry=c._entryId||"",p.confirm&&(o.dataset.confirm=p.confirm),p.icon){const i=document.createElement("span");i.dataset.icon=p.icon,o.appendChild(i),o.appendChild(document.createTextNode(" "))}return o.appendChild(document.createTextNode(p.label||"Run")),o}})}const y="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=y,v.replaceChildren(l),T.create("#"+y,{data:u,columns:C,search:t,sortable:n,exportable:a,pageSize:e,emptyMessage:d}),p&&x(l),v._dmTable={columns:C,rows:u,slug:h,exportCfg:m,render(s){T.create("#"+y,{data:s,columns:C,search:t,sortable:n,exportable:a,pageSize:e,emptyMessage:d}),p&&x(l)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function v(t,n){const a={};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)),p=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":d?"chooser":e.type,h={...e.formConfig||{}};h.span==="full"&&n&&(h.span=n);const m={type:p,label:e.label,required:e.required,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...h}};d&&(e.variant&&(m.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(m.multiple=!0),e.density&&(m.density=e.density),e.columns&&(m.columns=e.columns),e.accent&&(m.accent=e.accent),e.accentStyle&&(m.accentStyle=e.accentStyle),e.glow&&(m.glow=!0),e.glowColour&&(m.glowColour=e.glowColour),e.shadow&&(m.shadow=e.shadow),e.shadowColour&&(m.shadowColour=e.shadowColour)),a[e.name]=m}),a}function w(t){const n={};return(t||[]).forEach(a=>{if(!(!a.name||a.type==="page-break"||a.type==="spacer")&&(a.type==="select"||a.type==="multiselect")&&a.required){const e=(a.options||[])[0];e&&(n[a.name]=typeof e=="object"?e.value:e)}}),n}function C(t,n){(n||[]).forEach(a=>{if(a.type!=="date"||!a.name)return;const e=t.querySelector(`[name="${a.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function u(t,n,a){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=n,e.style.cssText=a?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(t=>{let n;try{n=JSON.parse(atob(t.dataset.formInline))}catch{return}const a=n.fields||[],e=n.settings||{},d=e.columns||1,p=e.layout||"stacked",h=a.some(s=>s.type==="page-break"),m=async s=>{try{const r=t.querySelector('[name="website"]'),c=t.querySelector('[name="_t"]'),o=Object.assign({},s);r!==null&&(o._hp=r.value),c!==null&&(o._t=c.value);const i=await H.post(`/api/forms/submit/${n.slug}`,o);if(i&&i.error){u(t,i.error,!0);const f=new Error(i.error);throw f.formSubmitFailed=!0,f}if(i?.redirect){window.location.href=i.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);u(t,i?.message||e.successMessage||"Thank you for your submission.",!1)}catch(r){throw r.formSubmitFailed||u(t,r.message||"Submission failed. Please try again.",!0),r}};function y(s){const r=s.querySelector("form");if(!r)return;const c=document.createElement("div");c.className="fb-form-honeypot",c.setAttribute("aria-hidden","true");const o=document.createElement("input");o.name="website",o.type="text",o.tabIndex=-1,o.autocomplete="url",o.placeholder="https://",c.appendChild(o);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=Date.now(),c.appendChild(i),r.appendChild(c)}function l(){if(!window.FormLogicEngine||!a.some(r=>r.logic))return;const s=new window.FormLogicEngine.FormLogicRuntime(n,t);if(s.init(),t._formLogicRuntime=s,t.parentNode&&typeof MutationObserver<"u"){const r=new MutationObserver(function(c){for(const o of c)for(const i of o.removedNodes)if(i===t||i.nodeType===1&&i.contains&&i.contains(t)){s.destroy(),r.disconnect();return}});r.observe(t.parentNode,{childList:!0,subtree:!1})}}if(h&&F.wizard){const s=[];let r=[],c=n.title||"Step 1",o="";a.forEach(f=>{f.type==="page-break"?(s.push({title:c,description:o,fields:v(r,d)}),r=[],c=f.label||`Step ${s.length+1}`,o=f.description||""):f.type!=="spacer"&&r.push(f)}),s.push({title:c,description:o,fields:v(r,d)});const i=F.wizard(t,{schema:{steps:s},onSubmit:m});Promise.resolve(i).then(function(){C(t,a),D(t,a),e.honeypot!==!1&&y(t),l()})}else if(F.render){const s=F.render(t,v(a,d),w(a),{submitText:e.submitText||"Submit",layout:p,columns:d,onSubmit:m});Promise.resolve(s).then(function(){if(p==="grid"&&e.submitSpan==="full"){const r=t.querySelector(".form-buttons");r&&r.classList.add("col-span-full")}C(t,a),D(t,a),e.honeypot!==!1&&y(t),l()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
package/scripts/setup.js CHANGED
@@ -159,8 +159,11 @@ if (!isPlaceholder) {
159
159
  // ---------------------------------------------------------------------------
160
160
  section('2. Instance Secret');
161
161
 
162
- const existingSecret = env.INSTANCE_SECRET ?? '';
163
- const isInstanceSecretSet = existingSecret && existingSecret.length >= 32;
162
+ // Distinct name from step 1's existingSecret — both are module-scope consts,
163
+ // so reusing the identifier made the whole file a SyntaxError and setup could
164
+ // not run at all.
165
+ const existingInstanceSecret = env.INSTANCE_SECRET ?? '';
166
+ const isInstanceSecretSet = existingInstanceSecret && existingInstanceSecret.length >= 32;
164
167
 
165
168
  if (isInstanceSecretSet) {
166
169
  console.log(' ✓ INSTANCE_SECRET already configured — skipping.');
@@ -298,6 +301,24 @@ section('6. Server Port');
298
301
  console.log(` ✓ Port set to ${port}`);
299
302
  }
300
303
 
304
+ // ---------------------------------------------------------------------------
305
+ // Git hooks
306
+ // ---------------------------------------------------------------------------
307
+ // The hooks in .githooks/ are committed, but git will not run them until this
308
+ // clone points at that directory — core.hooksPath is local config, so it cannot
309
+ // travel with the repository. Every clone that misses this step silently loses
310
+ // both hooks: the commit-msg trailer strip and the pre-commit minified-source
311
+ // guard. Enable it here so a fresh clone is protected by default.
312
+ try {
313
+ const {execSync} = await import('child_process');
314
+ execSync('git rev-parse --git-dir', {stdio: 'ignore'});
315
+ execSync('git config core.hooksPath .githooks', {stdio: 'ignore'});
316
+ console.log(' ✓ Git hooks enabled (core.hooksPath = .githooks)');
317
+ } catch {
318
+ // Not a git checkout — an npm install of the published package, most
319
+ // likely. Nothing to enable, and nothing worth warning about.
320
+ }
321
+
301
322
  // ---------------------------------------------------------------------------
302
323
  // Done
303
324
  // ---------------------------------------------------------------------------
@@ -12,6 +12,7 @@ import {v4 as uuidv4} from 'uuid';
12
12
  import {config} from '../config.js';
13
13
  import {getAdapter, invalidate} from './adapterRegistry.js';
14
14
  import * as cache from './cache/index.js';
15
+ import {toCsv} from '../../public/js/collection-export.mjs';
15
16
 
16
17
  const COLLECTIONS_DIR = path.resolve(config.content.collectionsDir);
17
18
 
@@ -480,17 +481,17 @@ export async function exportEntries(slug, format = 'json') {
480
481
  const entries = await adapter.all(slug);
481
482
 
482
483
  if (format === 'csv') {
483
- const fields = schema.fields.map(f => f.name);
484
- const header = ['id', ...fields, 'createdAt'].join(',');
485
- const rows = entries.map(e => {
486
- const cells = ['id', ...fields, 'createdAt'].map(key => {
487
- const val = key === 'id' ? e.id : key === 'createdAt' ? (e.meta?.createdAt || '') : (e.data?.[key] ?? '');
488
- const str = String(val).replace(/"/g, '""');
489
- return `"${str}"`;
490
- });
491
- return cells.join(',');
492
- });
493
- return [header, ...rows].join('\n');
484
+ const columns = [
485
+ {name: 'id'},
486
+ ...schema.fields.map(f => ({name: f.name})),
487
+ {name: 'createdAt'}
488
+ ];
489
+ const rows = entries.map(e => ({
490
+ id: e.id,
491
+ ...Object.fromEntries(schema.fields.map(f => [f.name, e.data?.[f.name]])),
492
+ createdAt: e.meta?.createdAt || ''
493
+ }));
494
+ return toCsv(rows, columns);
494
495
  }
495
496
 
496
497
  return JSON.stringify(entries, null, 2);