domma-cms 0.45.1 → 0.46.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.
@@ -146,9 +146,14 @@
146
146
  <option value="inline">Inline</option>
147
147
  </select>
148
148
  </div>
149
- <div id="columns-group" style="display:none;">
149
+ <div id="columns-group">
150
150
  <label class="form-label">Columns</label>
151
- <input id="setting-columns" type="number" class="form-input" min="1" max="6" value="2">
151
+ <select id="setting-columns" class="form-select">
152
+ <option value="2">2 columns</option>
153
+ <option value="3">3 columns</option>
154
+ </select>
155
+ <p class="form-hint text-muted" style="margin-top:.3rem;font-size:.8rem;">A grid form lays out in two
156
+ or three columns. Use a field's Column Span to make one field wider than the rest.</p>
152
157
  <div class="mt-3">
153
158
  <label class="form-label">Submit Button Span</label>
154
159
  <select id="setting-submit-span" class="form-select">
@@ -1,8 +1,8 @@
1
- import{apiRequest as A}from"/admin/js/api.js";import{makeIconInput as ge}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as Z}from"/public/js/forms.js";const ee=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"chooser",label:"Chooser (visual options)"},{value:"icon",label:"Icon (icon picker)"},{value:"image",label:"Image (media library)"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"password",label:"Password"},{value:"file",label:"File upload"},{value:"hidden",label:"Hidden field"}],J=new Set(["select","radio","checkbox-group","chooser"]);let v=[],L=null,P=null,M=null,G={};function w(e,t,a=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(a)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function j(e,t,a,n=14){return w(e,t,n),e.appendChild(document.createTextNode(" "+a)),e}function Y(e){const t=document.createElement("span");return t.setAttribute("data-icon","help-circle"),t.setAttribute("data-icon-size","12"),t.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;margin-left:.3rem;opacity:.55;cursor:help;",t.title=e,window.I?.scan?.(t),requestAnimationFrame(()=>{try{t.parentNode&&typeof E<"u"&&E.tooltip&&(t.removeAttribute("title"),E.tooltip(t,{content:e,position:"top"}))}catch{}}),t}let D=null,te=null;function Q(){clearTimeout(te),te=setTimeout(()=>{D&&D()},350)}function ne(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function le(e){return ee.find(t=>t.value===e)?.label||e}function oe(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function ye(e){const t={...v[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const g=document.getElementById(`fb-pb-label-${e}`),u=document.getElementById(`fb-pb-desc-${e}`);return g&&(t.label=g.value.trim()||t.label),u&&(t.description=u.value.trim()),t}const a=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),o=document.getElementById(`fb-required-${e}`),s=document.getElementById(`fb-placeholder-${e}`),r=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(a&&(t.label=a.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),l&&(t.type=l.value||t.type),o&&(t.required=o.checked),s&&(t.placeholder=s.value.trim()),r&&(t.helper=r.value.trim()),c&&(t.tooltip=c.value.trim()),t.type==="chooser"){const g=document.getElementById(`fb-chooser-variant-${e}`)?.value;g&&(t.variant=g);const u=document.getElementById(`fb-chooser-multiple-${e}`);u&&(t.multiple=u.checked);const y=document.getElementById(`fb-chooser-density-${e}`)?.value;y&&(t.density=y);const x=document.getElementById(`fb-chooser-columns-${e}`)?.value;x!==""&&x!==void 0&&(t.columns=parseInt(x,10)||3);const S=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();S?t.accent=S:delete t.accent;const C=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;C?t.accentStyle=C:delete t.accentStyle;const N=document.getElementById(`fb-chooser-glow-${e}`);N&&(t.glow=N.checked);const I=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();I?t.glowColour=I:delete t.glowColour;const q=document.getElementById(`fb-chooser-shadow-${e}`)?.value;q&&q!=="none"?t.shadow=q:delete t.shadow;const O=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();O?t.shadowColour=O:delete t.shadowColour,W(e),v[e]&&Array.isArray(v[e].options)&&(t.options=v[e].options)}else if(J.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(u=>delete t[u]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const g=document.getElementById(`fb-options-${e}`);g&&(t.options=g.value.split(`
2
- `).filter(u=>u.trim()).map(u=>{const[y,...x]=u.split(":");return{value:y.trim(),label:x.join(":").trim()||y.trim()}}))}if(t.type==="textarea"){const g=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);g>0&&(t.formConfig={...t.formConfig||{},rows:g})}const d=document.getElementById(`fb-span-${e}`),i=document.getElementById(`fb-fullwidth-${e}`);if(d||i){const g={...t.formConfig||{}};if(i?.checked)g.span="full";else{const u=parseInt(d?.value,10);u>1?g.span=u:delete g.span}t.formConfig=Object.keys(g).length?g:void 0}const p=document.getElementById(`fb-minlength-${e}`)?.value;p&&(t.minLength=parseInt(p,10));const m=document.getElementById(`fb-maxlength-${e}`)?.value;m&&(t.maxLength=parseInt(m,10));const f=document.getElementById(`fb-min-${e}`)?.value;f!==""&&f!==void 0&&(t.min=parseFloat(f));const b=document.getElementById(`fb-max-${e}`)?.value;b!==""&&b!==void 0&&(t.max=parseFloat(b));const h=ve(e);return h?t.logic=h:delete t.logic,t}function ve(e){const t=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!t)return;const a=t.querySelector(".fb-field-logic");if(!a)return;const n={};let l=!1;const o=a.querySelector('[data-logic-section="visibility"]');if(o){const d=o.querySelector(".fb-logic-vis-default"),i=o.querySelector(".fb-logic-vis-transition"),p=Array.from(o.querySelectorAll(".fb-logic-cond-row")).map(h=>{const g=h.querySelector(".fb-logic-cond-field"),u=h.querySelector(".fb-logic-cond-op"),y=h.querySelector(".fb-logic-cond-val"),x=h.querySelector(".fb-logic-vis-then");return g?.value?{when:{all:[{field:g.value,operator:u.value,value:y.value}]},then:x.value}:null}).filter(Boolean),m=d?.value||"visible",f=i?.value||"none",b=parseInt(o.querySelector(".fb-logic-vis-duration")?.value||"",10);(m!=="visible"||p.length>0||f!=="none")&&(n.visibility={default:m,conditions:p},f!=="none"&&(n.visibility.transition=f),f!=="none"&&Number.isFinite(b)&&(n.visibility.duration=b),l=!0)}const s=a.querySelector('[data-logic-section="requirement"]');if(s){const d=s.querySelector(".fb-logic-req-default"),i=Array.from(s.querySelectorAll(".fb-logic-cond-row")).map(p=>{const m=p.querySelector(".fb-logic-cond-field"),f=p.querySelector(".fb-logic-cond-op"),b=p.querySelector(".fb-logic-cond-val"),h=p.querySelector(".fb-logic-req-then");return m?.value?{when:{all:[{field:m.value,operator:f.value,value:b.value}]},then:h.value==="true"}:null}).filter(Boolean);i.length>0&&(n.requirement={default:d?.checked===!0,conditions:i},l=!0)}const r=a.querySelector('[data-logic-section="validation"]');if(r){const d=Array.from(r.querySelectorAll(".fb-logic-val-rule")).map(i=>{const p=i.querySelector(".fb-logic-val-type"),m=i.querySelector(".fb-logic-val-pattern"),f=i.querySelector(".fb-logic-val-flags"),b=i.querySelector(".fb-logic-val-message");if(!m?.value.trim())return null;const h=p?.value||"regex",g={type:h,message:b?.value.trim()||"Invalid value."};return h==="regex"?(g.pattern=m.value.trim(),f?.value.trim()&&(g.flags=f.value.trim())):g.field=m.value.trim(),g}).filter(Boolean);d.length>0&&(n.validation=d,l=!0)}const c=a.querySelector('[data-logic-section="cascade"]');if(c){const d=c.querySelector(".fb-logic-cascade-source"),i=c.querySelector(".fb-logic-cascade-mapping"),p=c.querySelector(".fb-logic-cascade-defaults"),m=d?.value?.trim();if(m){let f={};try{f=JSON.parse(i?.value||"{}")}catch{}const b=(p?.value||"").split(`
3
- `).filter(h=>h.trim()).map(h=>{const[g,...u]=h.split(":");return{value:g.trim(),label:u.join(":").trim()||g.trim()}});n.cascade={sourceField:m,mapping:f,defaultOptions:b},l=!0}}return l?n:void 0}function $(){v=v.map((e,t)=>ye(t))}let B=null;function xe(e,t,a){const n=e.firstElementChild;if(!n)return;const l=document.createElement("span");l.setAttribute("data-icon","menu"),l.setAttribute("data-icon-size","13"),l.title="Drag to reorder",l.style.cssText="cursor:grab;opacity:.35;flex-shrink:0;display:inline-flex;align-items:center;",n.insertBefore(l,n.firstChild),window.I?.scan?.(n),n.draggable=!0,n.addEventListener("dragstart",o=>{B=t,o.dataTransfer.effectAllowed="move",e.style.opacity="0.4"}),n.addEventListener("dragend",()=>{e.style.opacity="",document.querySelectorAll("#fields-list .fb-field-card").forEach(o=>o.classList.remove("fb-drag-over"))}),e.addEventListener("dragover",o=>{B!=null&&(o.preventDefault(),o.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(s=>s.classList.remove("fb-drag-over")),e.classList.add("fb-drag-over"))}),e.addEventListener("dragleave",()=>e.classList.remove("fb-drag-over")),e.addEventListener("drop",o=>{if(o.preventDefault(),e.classList.remove("fb-drag-over"),B==null||B===t){B=null;return}$();const[s]=v.splice(B,1);v.splice(t,0,s),B=null,z(a)})}function z(e){const t=e.find("#fields-list").get(0),a=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),v.length===0){a&&(a.style.display=""),Q();return}a&&(a.style.display="none"),v.forEach((n,l)=>{const o=n.type==="page-break"?Ce(n,l,e):n.type==="spacer"?Ee(n,l,e):we(n,l,e);xe(o,l,e),t.appendChild(o)}),Q()}}function Ce(e,t,a){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:2px dashed var(--dm-border,#444);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg,rgba(255,255,255,.02));";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const o=document.createElement("span");o.textContent="- Page Break -",o.style.cssText="font-size:.7rem;padding:.15rem .5rem;border-radius:999px;background:color-mix(in srgb, var(--dm-text-muted) 20%, transparent);color:var(--dm-text-muted,#888);white-space:nowrap;flex-shrink:0;font-style:italic;";const s=document.createElement("span");s.textContent=e.label||"Untitled Step",s.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted,#888);";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit step",w(c,"more-horizontal"),c.addEventListener("click",f=>{f.stopPropagation(),i.style.display=i.style.display==="none"?"":"none"}),r.appendChild(c);const d=document.createElement("button");d.className="btn btn-xs btn-ghost",d.style.cssText="line-height:1;opacity:.6;",d.title="Remove page break",w(d,"x"),d.addEventListener("click",async f=>{f.stopPropagation(),await E.confirm("Remove this page break?")&&($(),v.splice(t,1),z(a))}),r.appendChild(d),l.appendChild(o),l.appendChild(s),l.appendChild(r),l.addEventListener("click",()=>{i.style.display=i.style.display==="none"?"":"none"});const i=document.createElement("div");i.className="fb-field-body",i.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border,#444);display:none;";const p=k([T("Step Title",`fb-pb-label-${t}`,"text",e.label||"","Shown as the wizard step heading"),T("Step Description",`fb-pb-desc-${t}`,"text",e.description||"","Optional sub-heading")]),m=p.querySelector(`#fb-pb-label-${t}`);return m&&m.addEventListener("input",()=>{s.textContent=m.value||"Untitled Step"}),i.appendChild(p),n.appendChild(l),n.appendChild(i),n}function Ee(e,t,a){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px dashed var(--dm-border,#444);border-radius:6px;margin-bottom:.5rem;background:transparent;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.4rem .8rem;";const o=document.createElement("div");o.style.cssText="flex:1;height:1px;background:var(--dm-border,#444);";const s=document.createElement("span");s.textContent="Spacer",s.style.cssText="font-size:.7rem;color:var(--dm-text-muted,#888);white-space:nowrap;padding:0 .4rem;font-style:italic;";const r=document.createElement("div");r.style.cssText="flex:1;height:1px;background:var(--dm-border,#444);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const d=document.createElement("button");return d.className="btn btn-xs btn-ghost",d.style.cssText="line-height:1;opacity:.6;",d.title="Remove spacer",w(d,"x"),d.addEventListener("click",async i=>{i.stopPropagation(),$(),v.splice(t,1),z(a)}),c.appendChild(d),l.appendChild(o),l.appendChild(s),l.appendChild(r),l.appendChild(c),n.appendChild(l),n}function we(e,t,a){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px solid var(--dm-border,#333);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);box-shadow:var(--dm-shadow-sm);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;background:var(--dm-card-header-bg,rgba(255,255,255,.04));cursor:pointer;user-select:none;";const o=document.createElement("span");o.textContent=le(e.type),o.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary,#6366f1);white-space:nowrap;flex-shrink:0;";const s=document.createElement("span");s.textContent=e.label||"(unlabelled)",s.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit field",w(c,"more-horizontal"),c.addEventListener("click",p=>{p.stopPropagation(),i.style.display=i.style.display==="none"?"":"none"}),r.appendChild(c);const d=document.createElement("button");if(d.className="btn btn-xs btn-ghost",d.style.cssText="line-height:1;opacity:.6;",d.title="Remove field",w(d,"x"),d.addEventListener("click",async p=>{p.stopPropagation(),await E.confirm("Remove this field?")&&($(),v.splice(t,1),z(a))}),r.appendChild(d),l.appendChild(o),l.appendChild(s),e.required){const p=document.createElement("span");p.textContent="required",p.style.cssText="font-size:.7rem;color:var(--dm-danger,#ef4444);flex-shrink:0;",l.appendChild(p)}if(oe(e.logic)){const p=document.createElement("span");w(p,"zap"),p.title="Has conditional logic",p.style.cssText="font-size:.75rem;color:var(--dm-primary,#6366f1);flex-shrink:0;",l.appendChild(p)}l.appendChild(r),l.addEventListener("click",()=>{i.style.display=i.style.display==="none"?"":"none"});const i=Se(e,t,s);return i.style.display="none",n.appendChild(l),n.appendChild(i),n}function Se(e,t,a){const n=document.createElement("div");n.className="fb-field-body",n.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border,#333);";const l=k([T("Label",`fb-label-${t}`,"text",e.label||"","Shown above the field"),T("Field Name",`fb-name-${t}`,"text",e.name||"","Used as data key")]),o=k([_e("Type",`fb-type-${t}`,ee,e.type||"string"),ue("Required",`fb-required-${t}`,e.required||!1)]),s=k([T("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),r=k([T("Helper Text",`fb-helper-${t}`,"text",e.helper||"","Shown below the field"),T("Tooltip",`fb-tooltip-${t}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),c=e.formConfig?.span,d=k([T("Column Span",`fb-span-${t}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),ue("Full Width",`fb-fullwidth-${t}`,c==="full")]);d.classList.add("fb-grid-row"),d.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(l),n.appendChild(o),n.appendChild(s),n.appendChild(r),n.appendChild(d);const i=n.querySelector(`#fb-label-${t}`),p=n.querySelector(`#fb-name-${t}`);i&&i.addEventListener("input",()=>{a&&(a.textContent=i.value||"(unlabelled)"),p&&!p.dataset.manuallyEdited&&(p.value=ne(i.value))}),p&&p.addEventListener("input",()=>{p.dataset.manuallyEdited="1"});const m=n.querySelector(`#fb-type-${t}`);m&&m.addEventListener("change",()=>{const b=n.closest(".fb-field-card");if(b){const u=b.querySelector("span");u&&(u.textContent=le(m.value))}const h=n.querySelector(".fb-field-extras");h&&h.remove();const g=re(m.value,e,t);g&&n.appendChild(g)});const f=re(e.type,e,t);return f&&n.appendChild(f),n.appendChild($e(e,t)),n}const ae=[{value:"equals",label:"equals"},{value:"not_equals",label:"does not equal"},{value:"contains",label:"contains"},{value:"not_contains",label:"does not contain"},{value:"starts_with",label:"starts with"},{value:"ends_with",label:"ends with"},{value:"greater_than",label:"is greater than"},{value:"less_than",label:"is less than"},{value:"is_empty",label:"is empty"},{value:"is_not_empty",label:"is not empty"},{value:"in",label:"is one of (comma sep)"},{value:"not_in",label:"is not one of (comma sep)"},{value:"matches_regex",label:"matches regex"}],ie=new Set(["is_empty","is_not_empty"]),ke={equals:"includes",not_equals:"does not include",contains:"any value contains",not_contains:"no value contains",starts_with:"any value starts with",ends_with:"any value ends with",greater_than:"any value is greater than",less_than:"any value is less than",is_empty:"nothing selected",is_not_empty:"something selected",in:"includes one of (comma sep)",not_in:"includes none of (comma sep)",matches_regex:"any value matches regex"};function se(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function V(e){const t=document.createElement("p");return t.textContent=e,t.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted,#888);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",t}function H(e,t,a,n,l){const o=document.createElement("div");o.className="fb-logic-cond-row",o.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const s=document.createElement("span");s.textContent="When",s.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-cond-field",r.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(b=>{const h=document.createElement("option");h.value=b.value,h.textContent=b.label,e&&b.value===e.field&&(h.selected=!0),r.appendChild(h)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",ae.forEach(b=>{const h=document.createElement("option");h.value=b.value,h.textContent=b.label,e&&b.value===e.operator&&(h.selected=!0),c.appendChild(h)});const d=()=>{const b=t.find(h=>h.value===r.value);Array.from(c.options).forEach(h=>{const g=ae.find(u=>u.value===h.value);h.textContent=b?.multi&&ke[h.value]||g?.label||h.value})};d(),r.addEventListener("change",d);const i=document.createElement("input");i.type="text",i.className="form-input fb-logic-cond-val",i.placeholder="value",i.style.cssText="flex:1 1 120px;min-width:100px;",i.value=e?.value||"",e&&ie.has(e.operator)&&(i.style.display="none"),c.addEventListener("change",()=>{i.style.display=ie.has(c.value)?"none":""});const p=document.createElement("span");w(p,"arrow-right"),p.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);flex-shrink:0;";const m=document.createElement("select");m.className=`form-select ${n}`,m.style.cssText="flex:1 1 140px;min-width:120px;",a.forEach(b=>{const h=document.createElement("option");h.value=b.value,h.textContent=b.label,b.value===l&&(h.selected=!0),m.appendChild(h)});const f=document.createElement("button");return f.type="button",f.className="btn btn-xs btn-ghost",f.style.cssText="line-height:1;opacity:.6;",w(f,"x"),f.style.flexShrink="0",f.addEventListener("click",()=>o.remove()),o.appendChild(s),o.appendChild(r),o.appendChild(c),o.appendChild(i),o.appendChild(p),o.appendChild(m),o.appendChild(f),o}function Te(e,t,a){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(V("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const o=document.createElement("span");o.textContent="Default:",o.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-vis-default",s.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(u=>{const y=document.createElement("option");y.value=u.value,y.textContent=u.label,u.value===(e.default||"visible")&&(y.selected=!0),s.appendChild(y)}),l.appendChild(o),l.appendChild(s),n.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const c=document.createElement("span");c.textContent="Transition:",c.style.cssText="font-size:.8rem;flex-shrink:0;";const d=document.createElement("select");d.className="form-select fb-logic-vis-transition",d.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(u=>{const y=document.createElement("option");y.value=u.value,y.textContent=u.label,u.value===(e.transition||"none")&&(y.selected=!0),d.appendChild(y)}),r.appendChild(c),r.appendChild(d),n.appendChild(r);const i=document.createElement("div");i.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const p=document.createElement("span");p.textContent="Speed:",p.style.cssText="font-size:.8rem;flex-shrink:0;";const m=document.createElement("select");m.className="form-select fb-logic-vis-duration",m.style.cssText="max-width:240px;",[{value:"",label:"Default"},{value:"120",label:"Very fast (120ms)"},{value:"200",label:"Fast (200ms)"},{value:"350",label:"Medium (350ms)"},{value:"600",label:"Slow (600ms)"},{value:"1000",label:"Very slow (1s)"}].forEach(u=>{const y=document.createElement("option");y.value=u.value,y.textContent=u.label,u.value===String(e.duration??"")&&(y.selected=!0),m.appendChild(y)}),i.appendChild(p),i.appendChild(m),n.appendChild(i);const f=()=>{i.style.display=d.value==="none"?"none":""};f(),d.addEventListener("change",f);const b=document.createElement("div");b.className="fb-logic-vis-rules";const h=a.map(u=>({value:u.name,label:u.label||u.name,multi:se(u)})),g=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(u=>{const y=(u.when?.all||u.when?.any||[])[0],x=u.then==="hidden"?"hidden":"visible";h.length>0&&b.appendChild(H(y,h,g,"fb-logic-vis-then",x))}),n.appendChild(b),h.length>0){const u=document.createElement("button");u.type="button",u.className="btn btn-xs btn-ghost",u.style.cssText="font-size:.73rem;margin-top:.35rem;",j(u,"plus","Add visibility rule"),u.addEventListener("click",()=>b.appendChild(H(null,h,g,"fb-logic-vis-then","visible"))),n.appendChild(u)}return n}function Ne(e,t,a){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(V("Conditional Requirement"));const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8rem;cursor:pointer;margin-bottom:.65rem;";const o=document.createElement("input");o.type="checkbox",o.className="fb-logic-req-default",o.checked=e.default===!0,l.appendChild(o),l.appendChild(document.createTextNode("Required by default")),n.appendChild(l);const s=document.createElement("div");s.className="fb-logic-req-rules";const r=a.map(d=>({value:d.name,label:d.label||d.name,multi:se(d)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(d=>{const i=(d.when?.all||d.when?.any||[])[0],p=d.then===!0?"true":"false";r.length>0&&s.appendChild(H(i,r,c,"fb-logic-req-then",p))}),n.appendChild(s),r.length>0){const d=document.createElement("button");d.type="button",d.className="btn btn-xs btn-ghost",d.style.cssText="font-size:.73rem;margin-top:.35rem;",j(d,"plus","Add requirement rule"),d.addEventListener("click",()=>s.appendChild(H(null,r,c,"fb-logic-req-then","true"))),n.appendChild(d)}return n}function ce(e){const t=document.createElement("div");t.className="fb-logic-val-rule",t.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const a=document.createElement("select");a.className="form-select fb-logic-val-type",a.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===(e?.type||"regex")&&(c.selected=!0),a.appendChild(c)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),a.addEventListener("change",()=>{l.style.display=a.value==="match"?"none":"",n.placeholder=a.value==="match"?"field name":"pattern"});const o=document.createElement("input");o.type="text",o.className="form-input fb-logic-val-message",o.placeholder="Error message",o.value=e?.message||"",o.style.cssText="flex:4;";const s=document.createElement("button");return s.type="button",s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",w(s,"x"),s.style.flexShrink="0",s.addEventListener("click",()=>t.remove()),t.appendChild(a),t.appendChild(n),t.appendChild(l),t.appendChild(o),t.appendChild(s),t}function qe(e,t,a){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(V("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(s=>l.appendChild(ce(s))),n.appendChild(l);const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost",o.style.cssText="font-size:.73rem;margin-top:.35rem;",j(o,"plus","Add validation rule"),o.addEventListener("click",()=>l.appendChild(ce(null))),n.appendChild(o),n}function Le(e,t,a){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(V("Cascade Options")),n.lastChild.appendChild(Y("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const o=document.createElement("span");o.textContent="Source field:",o.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-cascade-source",s.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",s.appendChild(r),a.forEach(m=>{const f=document.createElement("option");f.value=m.name,f.textContent=m.label||m.name,m.name===e.sourceField&&(f.selected=!0),s.appendChild(f)}),l.appendChild(o),l.appendChild(s),n.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Y(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),c.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);margin:.3rem 0 .2rem;";const d=document.createElement("textarea");d.className="form-input fb-logic-cascade-mapping",d.rows=4,d.style.cssText="font-family:monospace;",d.placeholder='{"uk": [{"value": "london", "label": "London"}]}',d.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(c),n.appendChild(d);const i=document.createElement("p");i.textContent="Default options (one per line: value:Label)",i.appendChild(Y("Shown before the source field has a value, or when its value has no mapping entry.")),i.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);margin:.3rem 0 .2rem;";const p=document.createElement("textarea");return p.className="form-input fb-logic-cascade-defaults",p.rows=3,p.style.cssText="font-family:monospace;",p.placeholder=`option1:Option 1
1
+ import{apiRequest as _}from"/admin/js/api.js";import{makeIconInput as ve}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as ee}from"/public/js/forms.js";import{buildWizardSteps as xe}from"/public/js/form-steps.mjs";const te=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"chooser",label:"Chooser (visual options)"},{value:"icon",label:"Icon (icon picker)"},{value:"image",label:"Image (media library)"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"password",label:"Password"},{value:"file",label:"File upload"},{value:"hidden",label:"Hidden field"}],J=new Set(["select","radio","checkbox-group","chooser"]);let v=[],$=null,M=null,P=null,G={};function k(e,n,i=14){e.textContent="";const t=document.createElement("span");return t.setAttribute("data-icon",n),t.setAttribute("data-icon-size",String(i)),t.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(t),window.I?.scan?.(e),e}function j(e,n,i,t=14){return k(e,n,t),e.appendChild(document.createTextNode(" "+i)),e}function Y(e){const n=document.createElement("span");return n.setAttribute("data-icon","help-circle"),n.setAttribute("data-icon-size","12"),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;margin-left:.3rem;opacity:.55;cursor:help;",n.title=e,window.I?.scan?.(n),requestAnimationFrame(()=>{try{n.parentNode&&typeof E<"u"&&E.tooltip&&(n.removeAttribute("title"),E.tooltip(n,{content:e,position:"top"}))}catch{}}),n}let D=null,ne=null;function Q(){clearTimeout(ne),ne=setTimeout(()=>{D&&D()},350)}function le(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function oe(e){return te.find(n=>n.value===e)?.label||e}function ae(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function Ce(e){const n={...v[e]};if(n.type==="spacer")return n;if(n.type==="page-break"){const g=document.getElementById(`fb-pb-label-${e}`),u=document.getElementById(`fb-pb-desc-${e}`);return g&&(n.label=g.value.trim()||n.label),u&&(n.description=u.value.trim()),n}const i=document.getElementById(`fb-label-${e}`),t=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),o=document.getElementById(`fb-required-${e}`),s=document.getElementById(`fb-placeholder-${e}`),r=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(i&&(n.label=i.value.trim()||n.label),t&&(n.name=t.value.trim()||n.name),l&&(n.type=l.value||n.type),o&&(n.required=o.checked),s&&(n.placeholder=s.value.trim()),r&&(n.helper=r.value.trim()),c&&(n.tooltip=c.value.trim()),n.type==="chooser"){const g=document.getElementById(`fb-chooser-variant-${e}`)?.value;g&&(n.variant=g);const u=document.getElementById(`fb-chooser-multiple-${e}`);u&&(n.multiple=u.checked);const y=document.getElementById(`fb-chooser-density-${e}`)?.value;y&&(n.density=y);const x=document.getElementById(`fb-chooser-columns-${e}`)?.value;x!==""&&x!==void 0&&(n.columns=parseInt(x,10)||3);const N=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();N?n.accent=N:delete n.accent;const C=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;C?n.accentStyle=C:delete n.accentStyle;const w=document.getElementById(`fb-chooser-glow-${e}`);w&&(n.glow=w.checked);const z=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();z?n.glowColour=z:delete n.glowColour;const S=document.getElementById(`fb-chooser-shadow-${e}`)?.value;S&&S!=="none"?n.shadow=S:delete n.shadow;const q=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();q?n.shadowColour=q:delete n.shadowColour,W(e),v[e]&&Array.isArray(v[e].options)&&(n.options=v[e].options)}else if(J.has(n.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(u=>delete n[u]),n.type!=="checkbox-group"&&n.type!=="multiselect"&&delete n.multiple;const g=document.getElementById(`fb-options-${e}`);g&&(n.options=g.value.split(`
2
+ `).filter(u=>u.trim()).map(u=>{const[y,...x]=u.split(":");return{value:y.trim(),label:x.join(":").trim()||y.trim()}}))}if(n.type==="textarea"){const g=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);g>0&&(n.formConfig={...n.formConfig||{},rows:g})}const d=document.getElementById(`fb-span-${e}`),a=document.getElementById(`fb-fullwidth-${e}`);if(d||a){const g={...n.formConfig||{}};if(a?.checked)g.span="full";else{const u=parseInt(d?.value,10);u>1?g.span=u:delete g.span}n.formConfig=Object.keys(g).length?g:void 0}const p=document.getElementById(`fb-minlength-${e}`)?.value;p&&(n.minLength=parseInt(p,10));const m=document.getElementById(`fb-maxlength-${e}`)?.value;m&&(n.maxLength=parseInt(m,10));const f=document.getElementById(`fb-min-${e}`)?.value;f!==""&&f!==void 0&&(n.min=parseFloat(f));const b=document.getElementById(`fb-max-${e}`)?.value;b!==""&&b!==void 0&&(n.max=parseFloat(b));const h=Ee(e);return h?n.logic=h:delete n.logic,n}function Ee(e){const n=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!n)return;const i=n.querySelector(".fb-field-logic");if(!i)return;const t={};let l=!1;const o=i.querySelector('[data-logic-section="visibility"]');if(o){const d=o.querySelector(".fb-logic-vis-default"),a=o.querySelector(".fb-logic-vis-transition"),p=Array.from(o.querySelectorAll(".fb-logic-cond-row")).map(h=>{const g=h.querySelector(".fb-logic-cond-field"),u=h.querySelector(".fb-logic-cond-op"),y=h.querySelector(".fb-logic-cond-val"),x=h.querySelector(".fb-logic-vis-then");return g?.value?{when:{all:[{field:g.value,operator:u.value,value:y.value}]},then:x.value}:null}).filter(Boolean),m=d?.value||"visible",f=a?.value||"none",b=parseInt(o.querySelector(".fb-logic-vis-duration")?.value||"",10);(m!=="visible"||p.length>0||f!=="none")&&(t.visibility={default:m,conditions:p},f!=="none"&&(t.visibility.transition=f),f!=="none"&&Number.isFinite(b)&&(t.visibility.duration=b),l=!0)}const s=i.querySelector('[data-logic-section="requirement"]');if(s){const d=s.querySelector(".fb-logic-req-default"),a=Array.from(s.querySelectorAll(".fb-logic-cond-row")).map(p=>{const m=p.querySelector(".fb-logic-cond-field"),f=p.querySelector(".fb-logic-cond-op"),b=p.querySelector(".fb-logic-cond-val"),h=p.querySelector(".fb-logic-req-then");return m?.value?{when:{all:[{field:m.value,operator:f.value,value:b.value}]},then:h.value==="true"}:null}).filter(Boolean);a.length>0&&(t.requirement={default:d?.checked===!0,conditions:a},l=!0)}const r=i.querySelector('[data-logic-section="validation"]');if(r){const d=Array.from(r.querySelectorAll(".fb-logic-val-rule")).map(a=>{const p=a.querySelector(".fb-logic-val-type"),m=a.querySelector(".fb-logic-val-pattern"),f=a.querySelector(".fb-logic-val-flags"),b=a.querySelector(".fb-logic-val-message");if(!m?.value.trim())return null;const h=p?.value||"regex",g={type:h,message:b?.value.trim()||"Invalid value."};return h==="regex"?(g.pattern=m.value.trim(),f?.value.trim()&&(g.flags=f.value.trim())):g.field=m.value.trim(),g}).filter(Boolean);d.length>0&&(t.validation=d,l=!0)}const c=i.querySelector('[data-logic-section="cascade"]');if(c){const d=c.querySelector(".fb-logic-cascade-source"),a=c.querySelector(".fb-logic-cascade-mapping"),p=c.querySelector(".fb-logic-cascade-defaults"),m=d?.value?.trim();if(m){let f={};try{f=JSON.parse(a?.value||"{}")}catch{}const b=(p?.value||"").split(`
3
+ `).filter(h=>h.trim()).map(h=>{const[g,...u]=h.split(":");return{value:g.trim(),label:u.join(":").trim()||g.trim()}});t.cascade={sourceField:m,mapping:f,defaultOptions:b},l=!0}}return l?t:void 0}function I(){v=v.map((e,n)=>Ce(n))}let O=null;function we(e,n,i){const t=e.firstElementChild;if(!t)return;const l=document.createElement("span");l.setAttribute("data-icon","menu"),l.setAttribute("data-icon-size","13"),l.title="Drag to reorder",l.style.cssText="cursor:grab;opacity:.35;flex-shrink:0;display:inline-flex;align-items:center;",t.insertBefore(l,t.firstChild),window.I?.scan?.(t),t.draggable=!0,t.addEventListener("dragstart",o=>{O=n,o.dataTransfer.effectAllowed="move",e.style.opacity="0.4"}),t.addEventListener("dragend",()=>{e.style.opacity="",document.querySelectorAll("#fields-list .fb-field-card").forEach(o=>o.classList.remove("fb-drag-over"))}),e.addEventListener("dragover",o=>{O!=null&&(o.preventDefault(),o.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(s=>s.classList.remove("fb-drag-over")),e.classList.add("fb-drag-over"))}),e.addEventListener("dragleave",()=>e.classList.remove("fb-drag-over")),e.addEventListener("drop",o=>{if(o.preventDefault(),e.classList.remove("fb-drag-over"),O==null||O===n){O=null;return}I();const[s]=v.splice(O,1);v.splice(n,0,s),O=null,A(i)})}function A(e){const n=e.find("#fields-list").get(0),i=e.find("#fields-empty-msg").get(0);if(n){if(Array.from(n.querySelectorAll(".fb-field-card")).forEach(t=>t.remove()),v.length===0){i&&(i.style.display=""),Q();return}i&&(i.style.display="none"),v.forEach((t,l)=>{const o=t.type==="page-break"?Se(t,l,e):t.type==="spacer"?ke(t,l,e):Te(t,l,e);we(o,l,e),n.appendChild(o)}),Q()}}function Se(e,n,i){const t=document.createElement("div");t.className="fb-field-card",t.dataset.index=n,t.style.cssText="border:2px dashed var(--dm-border,#444);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg,rgba(255,255,255,.02));";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const o=document.createElement("span");o.textContent="- Page Break -",o.style.cssText="font-size:.7rem;padding:.15rem .5rem;border-radius:999px;background:color-mix(in srgb, var(--dm-text-muted) 20%, transparent);color:var(--dm-text-muted,#888);white-space:nowrap;flex-shrink:0;font-style:italic;";const s=document.createElement("span");s.textContent=e.label||"Untitled Step",s.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted,#888);";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit step",k(c,"more-horizontal"),c.addEventListener("click",f=>{f.stopPropagation(),a.style.display=a.style.display==="none"?"":"none"}),r.appendChild(c);const d=document.createElement("button");d.className="btn btn-xs btn-ghost",d.style.cssText="line-height:1;opacity:.6;",d.title="Remove page break",k(d,"x"),d.addEventListener("click",async f=>{f.stopPropagation(),await E.confirm("Remove this page break?")&&(I(),v.splice(n,1),A(i))}),r.appendChild(d),l.appendChild(o),l.appendChild(s),l.appendChild(r),l.addEventListener("click",()=>{a.style.display=a.style.display==="none"?"":"none"});const a=document.createElement("div");a.className="fb-field-body",a.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border,#444);display:none;";const p=T([L("Step Title",`fb-pb-label-${n}`,"text",e.label||"","Shown as the wizard step heading"),L("Step Description",`fb-pb-desc-${n}`,"text",e.description||"","Optional sub-heading")]),m=p.querySelector(`#fb-pb-label-${n}`);return m&&m.addEventListener("input",()=>{s.textContent=m.value||"Untitled Step"}),a.appendChild(p),t.appendChild(l),t.appendChild(a),t}function ke(e,n,i){const t=document.createElement("div");t.className="fb-field-card",t.dataset.index=n,t.style.cssText="border:1px dashed var(--dm-border,#444);border-radius:6px;margin-bottom:.5rem;background:transparent;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.4rem .8rem;";const o=document.createElement("div");o.style.cssText="flex:1;height:1px;background:var(--dm-border,#444);";const s=document.createElement("span");s.textContent="Spacer",s.style.cssText="font-size:.7rem;color:var(--dm-text-muted,#888);white-space:nowrap;padding:0 .4rem;font-style:italic;";const r=document.createElement("div");r.style.cssText="flex:1;height:1px;background:var(--dm-border,#444);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const d=document.createElement("button");return d.className="btn btn-xs btn-ghost",d.style.cssText="line-height:1;opacity:.6;",d.title="Remove spacer",k(d,"x"),d.addEventListener("click",async a=>{a.stopPropagation(),I(),v.splice(n,1),A(i)}),c.appendChild(d),l.appendChild(o),l.appendChild(s),l.appendChild(r),l.appendChild(c),t.appendChild(l),t}function Te(e,n,i){const t=document.createElement("div");t.className="fb-field-card",t.dataset.index=n,t.style.cssText="border:1px solid var(--dm-border,#333);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);box-shadow:var(--dm-shadow-sm);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;background:var(--dm-card-header-bg,rgba(255,255,255,.04));cursor:pointer;user-select:none;";const o=document.createElement("span");o.textContent=oe(e.type),o.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary,#6366f1);white-space:nowrap;flex-shrink:0;";const s=document.createElement("span");s.textContent=e.label||"(unlabelled)",s.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit field",k(c,"more-horizontal"),c.addEventListener("click",p=>{p.stopPropagation(),a.style.display=a.style.display==="none"?"":"none"}),r.appendChild(c);const d=document.createElement("button");if(d.className="btn btn-xs btn-ghost",d.style.cssText="line-height:1;opacity:.6;",d.title="Remove field",k(d,"x"),d.addEventListener("click",async p=>{p.stopPropagation(),await E.confirm("Remove this field?")&&(I(),v.splice(n,1),A(i))}),r.appendChild(d),l.appendChild(o),l.appendChild(s),e.required){const p=document.createElement("span");p.textContent="required",p.style.cssText="font-size:.7rem;color:var(--dm-danger,#ef4444);flex-shrink:0;",l.appendChild(p)}if(ae(e.logic)){const p=document.createElement("span");k(p,"zap"),p.title="Has conditional logic",p.style.cssText="font-size:.75rem;color:var(--dm-primary,#6366f1);flex-shrink:0;",l.appendChild(p)}l.appendChild(r),l.addEventListener("click",()=>{a.style.display=a.style.display==="none"?"":"none"});const a=Le(e,n,s);return a.style.display="none",t.appendChild(l),t.appendChild(a),t}function Le(e,n,i){const t=document.createElement("div");t.className="fb-field-body",t.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border,#333);";const l=T([L("Label",`fb-label-${n}`,"text",e.label||"","Shown above the field"),L("Field Name",`fb-name-${n}`,"text",e.name||"","Used as data key")]),o=T([Re("Type",`fb-type-${n}`,te,e.type||"string"),fe("Required",`fb-required-${n}`,e.required||!1)]),s=T([L("Placeholder",`fb-placeholder-${n}`,"text",e.placeholder||"","Hint text inside the field")]),r=T([L("Helper Text",`fb-helper-${n}`,"text",e.helper||"","Shown below the field"),L("Tooltip",`fb-tooltip-${n}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),c=e.formConfig?.span,d=T([L("Column Span",`fb-span-${n}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),fe("Full Width",`fb-fullwidth-${n}`,c==="full")]);d.classList.add("fb-grid-row"),d.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",t.appendChild(l),t.appendChild(o),t.appendChild(s),t.appendChild(r),t.appendChild(d);const a=t.querySelector(`#fb-label-${n}`),p=t.querySelector(`#fb-name-${n}`);a&&a.addEventListener("input",()=>{i&&(i.textContent=a.value||"(unlabelled)"),p&&!p.dataset.manuallyEdited&&(p.value=le(a.value))}),p&&p.addEventListener("input",()=>{p.dataset.manuallyEdited="1"});const m=t.querySelector(`#fb-type-${n}`);m&&m.addEventListener("change",()=>{const b=t.closest(".fb-field-card");if(b){const u=b.querySelector("span");u&&(u.textContent=oe(m.value))}const h=t.querySelector(".fb-field-extras");h&&h.remove();const g=de(m.value,e,n);g&&t.appendChild(g)});const f=de(e.type,e,n);return f&&t.appendChild(f),t.appendChild(Ie(e,n)),t}const ie=[{value:"equals",label:"equals"},{value:"not_equals",label:"does not equal"},{value:"contains",label:"contains"},{value:"not_contains",label:"does not contain"},{value:"starts_with",label:"starts with"},{value:"ends_with",label:"ends with"},{value:"greater_than",label:"is greater than"},{value:"less_than",label:"is less than"},{value:"is_empty",label:"is empty"},{value:"is_not_empty",label:"is not empty"},{value:"in",label:"is one of (comma sep)"},{value:"not_in",label:"is not one of (comma sep)"},{value:"matches_regex",label:"matches regex"}],se=new Set(["is_empty","is_not_empty"]),Ne={equals:"includes",not_equals:"does not include",contains:"any value contains",not_contains:"no value contains",starts_with:"any value starts with",ends_with:"any value ends with",greater_than:"any value is greater than",less_than:"any value is less than",is_empty:"nothing selected",is_not_empty:"something selected",in:"includes one of (comma sep)",not_in:"includes none of (comma sep)",matches_regex:"any value matches regex"};function ce(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function V(e){const n=document.createElement("p");return n.textContent=e,n.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted,#888);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",n}function H(e,n,i,t,l){const o=document.createElement("div");o.className="fb-logic-cond-row",o.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const s=document.createElement("span");s.textContent="When",s.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-cond-field",r.style.cssText="flex:1 1 140px;min-width:140px;",n.forEach(b=>{const h=document.createElement("option");h.value=b.value,h.textContent=b.label,e&&b.value===e.field&&(h.selected=!0),r.appendChild(h)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",ie.forEach(b=>{const h=document.createElement("option");h.value=b.value,h.textContent=b.label,e&&b.value===e.operator&&(h.selected=!0),c.appendChild(h)});const d=()=>{const b=n.find(h=>h.value===r.value);Array.from(c.options).forEach(h=>{const g=ie.find(u=>u.value===h.value);h.textContent=b?.multi&&Ne[h.value]||g?.label||h.value})};d(),r.addEventListener("change",d);const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-cond-val",a.placeholder="value",a.style.cssText="flex:1 1 120px;min-width:100px;",a.value=e?.value||"",e&&se.has(e.operator)&&(a.style.display="none"),c.addEventListener("change",()=>{a.style.display=se.has(c.value)?"none":""});const p=document.createElement("span");k(p,"arrow-right"),p.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);flex-shrink:0;";const m=document.createElement("select");m.className=`form-select ${t}`,m.style.cssText="flex:1 1 140px;min-width:120px;",i.forEach(b=>{const h=document.createElement("option");h.value=b.value,h.textContent=b.label,b.value===l&&(h.selected=!0),m.appendChild(h)});const f=document.createElement("button");return f.type="button",f.className="btn btn-xs btn-ghost",f.style.cssText="line-height:1;opacity:.6;",k(f,"x"),f.style.flexShrink="0",f.addEventListener("click",()=>o.remove()),o.appendChild(s),o.appendChild(r),o.appendChild(c),o.appendChild(a),o.appendChild(p),o.appendChild(m),o.appendChild(f),o}function qe(e,n,i){const t=document.createElement("div");t.dataset.logicSection="visibility",t.appendChild(V("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const o=document.createElement("span");o.textContent="Default:",o.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-vis-default",s.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(u=>{const y=document.createElement("option");y.value=u.value,y.textContent=u.label,u.value===(e.default||"visible")&&(y.selected=!0),s.appendChild(y)}),l.appendChild(o),l.appendChild(s),t.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const c=document.createElement("span");c.textContent="Transition:",c.style.cssText="font-size:.8rem;flex-shrink:0;";const d=document.createElement("select");d.className="form-select fb-logic-vis-transition",d.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(u=>{const y=document.createElement("option");y.value=u.value,y.textContent=u.label,u.value===(e.transition||"none")&&(y.selected=!0),d.appendChild(y)}),r.appendChild(c),r.appendChild(d),t.appendChild(r);const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const p=document.createElement("span");p.textContent="Speed:",p.style.cssText="font-size:.8rem;flex-shrink:0;";const m=document.createElement("select");m.className="form-select fb-logic-vis-duration",m.style.cssText="max-width:240px;",[{value:"",label:"Default"},{value:"120",label:"Very fast (120ms)"},{value:"200",label:"Fast (200ms)"},{value:"350",label:"Medium (350ms)"},{value:"600",label:"Slow (600ms)"},{value:"1000",label:"Very slow (1s)"}].forEach(u=>{const y=document.createElement("option");y.value=u.value,y.textContent=u.label,u.value===String(e.duration??"")&&(y.selected=!0),m.appendChild(y)}),a.appendChild(p),a.appendChild(m),t.appendChild(a);const f=()=>{a.style.display=d.value==="none"?"none":""};f(),d.addEventListener("change",f);const b=document.createElement("div");b.className="fb-logic-vis-rules";const h=i.map(u=>({value:u.name,label:u.label||u.name,multi:ce(u)})),g=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(u=>{const y=(u.when?.all||u.when?.any||[])[0],x=u.then==="hidden"?"hidden":"visible";h.length>0&&b.appendChild(H(y,h,g,"fb-logic-vis-then",x))}),t.appendChild(b),h.length>0){const u=document.createElement("button");u.type="button",u.className="btn btn-xs btn-ghost",u.style.cssText="font-size:.73rem;margin-top:.35rem;",j(u,"plus","Add visibility rule"),u.addEventListener("click",()=>b.appendChild(H(null,h,g,"fb-logic-vis-then","visible"))),t.appendChild(u)}return t}function $e(e,n,i){const t=document.createElement("div");t.dataset.logicSection="requirement",t.appendChild(V("Conditional Requirement"));const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8rem;cursor:pointer;margin-bottom:.65rem;";const o=document.createElement("input");o.type="checkbox",o.className="fb-logic-req-default",o.checked=e.default===!0,l.appendChild(o),l.appendChild(document.createTextNode("Required by default")),t.appendChild(l);const s=document.createElement("div");s.className="fb-logic-req-rules";const r=i.map(d=>({value:d.name,label:d.label||d.name,multi:ce(d)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(d=>{const a=(d.when?.all||d.when?.any||[])[0],p=d.then===!0?"true":"false";r.length>0&&s.appendChild(H(a,r,c,"fb-logic-req-then",p))}),t.appendChild(s),r.length>0){const d=document.createElement("button");d.type="button",d.className="btn btn-xs btn-ghost",d.style.cssText="font-size:.73rem;margin-top:.35rem;",j(d,"plus","Add requirement rule"),d.addEventListener("click",()=>s.appendChild(H(null,r,c,"fb-logic-req-then","true"))),t.appendChild(d)}return t}function re(e){const n=document.createElement("div");n.className="fb-logic-val-rule",n.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const i=document.createElement("select");i.className="form-select fb-logic-val-type",i.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===(e?.type||"regex")&&(c.selected=!0),i.appendChild(c)});const t=document.createElement("input");t.type="text",t.className="form-input fb-logic-val-pattern",t.placeholder=e?.type==="match"?"field name":"pattern",t.value=e?.pattern||e?.field||"",t.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),i.addEventListener("change",()=>{l.style.display=i.value==="match"?"none":"",t.placeholder=i.value==="match"?"field name":"pattern"});const o=document.createElement("input");o.type="text",o.className="form-input fb-logic-val-message",o.placeholder="Error message",o.value=e?.message||"",o.style.cssText="flex:4;";const s=document.createElement("button");return s.type="button",s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",k(s,"x"),s.style.flexShrink="0",s.addEventListener("click",()=>n.remove()),n.appendChild(i),n.appendChild(t),n.appendChild(l),n.appendChild(o),n.appendChild(s),n}function Fe(e,n,i){const t=document.createElement("div");t.dataset.logicSection="validation",t.appendChild(V("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(s=>l.appendChild(re(s))),t.appendChild(l);const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost",o.style.cssText="font-size:.73rem;margin-top:.35rem;",j(o,"plus","Add validation rule"),o.addEventListener("click",()=>l.appendChild(re(null))),t.appendChild(o),t}function ze(e,n,i){const t=document.createElement("div");t.dataset.logicSection="cascade",t.appendChild(V("Cascade Options")),t.lastChild.appendChild(Y("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const o=document.createElement("span");o.textContent="Source field:",o.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-cascade-source",s.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",s.appendChild(r),i.forEach(m=>{const f=document.createElement("option");f.value=m.name,f.textContent=m.label||m.name,m.name===e.sourceField&&(f.selected=!0),s.appendChild(f)}),l.appendChild(o),l.appendChild(s),t.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Y(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),c.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);margin:.3rem 0 .2rem;";const d=document.createElement("textarea");d.className="form-input fb-logic-cascade-mapping",d.rows=4,d.style.cssText="font-family:monospace;",d.placeholder='{"uk": [{"value": "london", "label": "London"}]}',d.value=e.mapping?JSON.stringify(e.mapping,null,2):"",t.appendChild(c),t.appendChild(d);const a=document.createElement("p");a.textContent="Default options (one per line: value:Label)",a.appendChild(Y("Shown before the source field has a value, or when its value has no mapping entry.")),a.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);margin:.3rem 0 .2rem;";const p=document.createElement("textarea");return p.className="form-input fb-logic-cascade-defaults",p.rows=3,p.style.cssText="font-family:monospace;",p.placeholder=`option1:Option 1
4
4
  option2:Option 2`,p.value=(e.defaultOptions||[]).map(m=>{const f=typeof m=="string"?m:m.value??"",b=typeof m=="string"?m:m.label??f;return f===b?f:`${f}:${b}`}).join(`
5
- `),n.appendChild(i),n.appendChild(p),n}function $e(e,t){const a=e.logic||{},n=v.filter((p,m)=>m!==t&&p.type!=="page-break"&&p.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border,#333);padding-top:.5rem;";const o=document.createElement("div");o.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const s=document.createElement("span");s.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted,#888);",s.textContent="\u26A1 Conditional Logic";const r=oe(a),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",w(c,r?"chevron-down":"chevron-right",12);const d=document.createElement("div");d.className="fb-logic-body",d.style.cssText="padding:.25rem 0 .25rem;"+(r?"":"display:none;"),o.addEventListener("click",()=>{const p=d.style.display==="none";d.style.display=p?"":"none",w(c,p?"chevron-down":"chevron-right",12)}),o.appendChild(s),o.appendChild(c),l.appendChild(o),d.appendChild(Te(a.visibility||{},t,n)),d.appendChild(Ne(a.requirement||{},t,n)),d.appendChild(qe(a.validation||[],t,n));const i=document.getElementById(`fb-type-${t}`)?.value||e.type;return J.has(i)&&d.appendChild(Le(a.cascade||{},t,n)),l.appendChild(d),l}function re(e,t,a){const n=document.createElement("div");return n.className="fb-field-extras",e==="chooser"?(n.appendChild(Fe(t,a)),n.appendChild(Ie(t.options||[],a))):(J.has(e)&&n.appendChild(Pe(t.options||[],a)),e==="textarea"&&n.appendChild(k([T("Rows",`fb-rows-${a}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(k([T("Min Length",`fb-minlength-${a}`,"number",t.minLength||"",""),T("Max Length",`fb-maxlength-${a}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(k([T("Min",`fb-min-${a}`,"number",t.min??"",""),T("Max",`fb-max-${a}`,"number",t.max??"","")]))),n.children.length?n:null}function de(e){const t=document.createElement("div");t.className="fb-chooser-section",t.style.cssText="border:1px solid var(--dm-border, #e5e7eb); border-radius:6px; margin-top:.5rem; overflow:hidden;";const a=document.createElement("div");a.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background, #f9fafb) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border, #e5e7eb);",a.textContent=e,t.appendChild(a);const n=document.createElement("div");return n.className="fb-chooser-section-body",n.style.cssText="padding:.55rem .6rem; display:flex; flex-direction:column; gap:.45rem;",t.appendChild(n),{wrap:t,body:n}}function U(e,t,a,n,l){const o=document.createElement("div");o.style.flex="1";const s=document.createElement("label");s.htmlFor=e,s.className="form-label",s.textContent=t,s.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",n.forEach(([c,d])=>{const i=document.createElement("option");i.value=c,i.textContent=d,String(c)===String(a)&&(i.selected=!0),r.appendChild(i)}),o.appendChild(s),o.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",o.appendChild(c)}return o}function pe(e,t,a,n){const l=document.createElement("div");l.style.flex="1";const o=document.createElement("label");o.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const s=document.createElement("input");if(s.id=e,s.type="checkbox",s.checked=!!a,o.appendChild(s),o.appendChild(document.createTextNode(" "+t)),l.appendChild(o),n){const r=document.createElement("p");r.className="form-hint text-muted",r.textContent=n,r.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(r)}return l}function X(e,t,a,n,l){const o=document.createElement("div");o.style.flex="1";const s=document.createElement("label");s.htmlFor=e,s.className="form-label",s.textContent=t,s.style.fontSize=".8rem",o.appendChild(s);const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const c=document.createElement("input");c.id=e,c.type="text",c.className="form-input",c.value=a||"",n&&(c.placeholder=n),c.style.flex="1";const d=document.createElement("input");d.type="color",d.title="Pick a colour",d.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border,#e5e7eb);border-radius:4px;cursor:pointer;";const i=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(d.value=i?c.value:"#000000",d.addEventListener("input",()=>{c.value=d.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),r.appendChild(c),r.appendChild(d),o.appendChild(r),l){const p=document.createElement("p");p.className="form-hint text-muted",p.textContent=l,p.style.cssText="font-size:.72rem;margin-top:.2rem;",o.appendChild(p)}return o}function Fe(e,t){const a=document.createElement("div");a.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=de("Layout");n.body.appendChild(k([U(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),pe(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(k([U(`fb-chooser-density-${t}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),T("Columns",`fb-chooser-columns-${t}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),a.appendChild(n.wrap);const l=de("Visual");return l.body.appendChild(k([X(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),U(`fb-chooser-accent-style-${t}`,"Accent style",e.accentStyle||"border",[["border","Border (default)"],["solid","Solid"],["glow","Glow"],["overlay","Overlay"],["underline","Underline"]],"Visual treatment of the selected state.")])),l.body.appendChild(k([pe(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),X(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(k([U(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),X(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),a.appendChild(l.wrap),a}function ze(e,t,a,n){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(a),l.style.cssText="border:1px solid var(--dm-border,#e5e7eb); border-radius:4px; padding:.5rem; background:var(--dm-background-alt, color-mix(in srgb, var(--dm-card-bg, #fff) 92%, var(--dm-text, #111))); display:flex; flex-direction:column; gap:.35rem;";const o=document.createElement("div");o.style.cssText="display:flex; gap:.4rem; align-items:center;";const s=document.createElement("div");s.style.cssText="display:flex; flex-direction:column; gap:1px;";const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.title="Move up",w(r,"arrow-up"),r.addEventListener("click",q=>{q.preventDefault(),me(t,a,-1,n)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",w(c,"arrow-down"),c.addEventListener("click",q=>{q.preventDefault(),me(t,a,1,n)}),s.appendChild(r),s.appendChild(c),o.appendChild(s);const d=document.createElement("input");d.type="text",d.className="form-input fb-chooser-opt-value",d.placeholder="value",d.value=e.value||"",d.style.flex="1",o.appendChild(d);const i=document.createElement("input");i.type="text",i.className="form-input fb-chooser-opt-label",i.placeholder="label (visible to users)",i.value=e.label||"",i.style.flex="2",o.appendChild(i);const p=document.createElement("button");p.type="button",p.className="btn btn-xs btn-ghost",p.style.cssText="line-height:1;opacity:.6;",p.title="Remove option",w(p,"x"),p.addEventListener("click",q=>{q.preventDefault(),Oe(t,a,n)}),o.appendChild(p),l.appendChild(o);const m=document.createElement("div");m.style.cssText="display:flex; gap:.4rem;";const f=ge("icon name (optional)",e.icon||"");f.input.classList.add("fb-chooser-opt-icon"),f.el.style.flex="1",m.appendChild(f.el);const b=document.createElement("input");b.type="text",b.className="form-input fb-chooser-opt-description",b.placeholder="description (card + comfortable only)",b.value=e.description||"",b.style.flex="2",m.appendChild(b),l.appendChild(m);const h=document.createElement("div");h.style.cssText="display:flex; gap:.4rem;";const g=document.createElement("input");g.type="text",g.className="form-input fb-chooser-opt-tooltip",g.placeholder="tooltip (hover hint)",g.value=e.tooltip||"",g.style.flex="2",h.appendChild(g);const u=document.createElement("input");u.type="text",u.className="form-input fb-chooser-opt-badge-text",u.placeholder="badge text",u.value=e.badge?.text||"",u.style.flex="1",h.appendChild(u);const y=document.createElement("select");y.className="form-input fb-chooser-opt-badge-type",y.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([q,O])=>{const _=document.createElement("option");_.value=q,_.textContent=O,(e.badge?.type||"")===q&&(_.selected=!0),y.appendChild(_)}),h.appendChild(y),l.appendChild(h);const x=document.createElement("div");x.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const S=document.createElement("label");S.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const C=document.createElement("input");C.type="checkbox",C.className="fb-chooser-opt-recommended",C.checked=!!e.recommended,S.appendChild(C),S.appendChild(document.createTextNode(" Recommended")),x.appendChild(S);const N=document.createElement("label");N.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const I=document.createElement("input");return I.type="checkbox",I.className="fb-chooser-opt-disabled",I.checked=!!e.disabled,N.appendChild(I),N.appendChild(document.createTextNode(" Disabled")),x.appendChild(N),l.appendChild(x),l}function Ie(e,t){const a=document.createElement("div");a.style.cssText="margin-top:.5rem;";const n=document.createElement("div");n.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:.4rem;";const l=document.createElement("p");l.textContent="Options",l.style.cssText="font-size:.85rem;font-weight:600;margin:0;",n.appendChild(l);const o=document.createElement("button");o.type="button",o.className="btn btn-xs btn-ghost",j(o,"plus","Add option"),n.appendChild(o),a.appendChild(n);const s=document.createElement("div");s.className="fb-chooser-options-list",s.id=`fb-chooser-options-${t}`,s.style.cssText="display:flex; flex-direction:column; gap:.4rem;",a.appendChild(s);const r=()=>{s.replaceChildren();const c=Be(t);(c.length?c:e||[]).forEach((i,p)=>{s.appendChild(ze(i,t,p,r))})};return o.addEventListener("click",c=>{c.preventDefault(),Ae(t,r)}),r(),a}function Be(e){const t=v[e];return!t||!Array.isArray(t.options)?[]:t.options}function K(e){return v[e]?(Array.isArray(v[e].options)||(v[e].options=[]),v[e].options):[]}function Ae(e,t){W(e),K(e).push({value:"new",label:"New option"}),t()}function Oe(e,t,a){W(e),K(e).splice(t,1),a()}function me(e,t,a,n){W(e);const l=K(e),o=t+a;if(o<0||o>=l.length)return;const[s]=l.splice(t,1);l.splice(o,0,s),n()}function W(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const a=t.querySelectorAll(".fb-chooser-option-row"),n=[];a.forEach(l=>{const o={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},s=l.querySelector(".fb-chooser-opt-icon")?.value.trim();s&&(o.icon=s);const r=l.querySelector(".fb-chooser-opt-description")?.value.trim();r&&(o.description=r);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(o.tooltip=c);const d=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),i=l.querySelector(".fb-chooser-opt-badge-type")?.value;(d||i)&&(o.badge={},d&&(o.badge.text=d),i&&(o.badge.type=i)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(o.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(o.disabled=!0),n.push(o)}),v[e]&&(v[e].options=n)}function k(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(a=>{a&&t.appendChild(a)}),t}function T(e,t,a,n,l){const o=document.createElement("div");o.style.flex="1";const s=document.createElement("label");s.htmlFor=t,s.className="form-label",s.textContent=e,s.style.fontSize=".8rem";const r=document.createElement("input");if(r.id=t,r.type=a||"text",r.className="form-input",r.value=n??"",o.appendChild(s),o.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",o.appendChild(c)}return o}function _e(e,t,a,n){const l=document.createElement("div");l.style.flex="1";const o=document.createElement("label");o.htmlFor=t,o.className="form-label",o.textContent=e,o.style.fontSize=".8rem";const s=document.createElement("select");return s.id=t,s.className="form-select",a.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===n&&(c.selected=!0),s.appendChild(c)}),l.appendChild(o),l.appendChild(s),l}function ue(e,t,a){const n=document.createElement("div");n.style.cssText="flex:0;min-width:80px;display:flex;flex-direction:column;justify-content:flex-end;";const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;font-size:.8rem;white-space:nowrap;";const o=document.createElement("input");return o.id=t,o.type="checkbox",o.checked=a,l.appendChild(o),l.appendChild(document.createTextNode(e)),n.appendChild(l),n}function Pe(e,t){const a=document.createElement("div");a.style.cssText="margin-top:.4rem;";const n=document.createElement("p");n.textContent="Options (one per line: value or value:Label)",n.style.cssText="font-size:.8rem;font-weight:600;margin-bottom:.3rem;";const l=document.createElement("textarea");return l.id=`fb-options-${t}`,l.className="form-input",l.rows=4,l.placeholder=`yes:Yes
5
+ `),t.appendChild(a),t.appendChild(p),t}function Ie(e,n){const i=e.logic||{},t=v.filter((p,m)=>m!==n&&p.type!=="page-break"&&p.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border,#333);padding-top:.5rem;";const o=document.createElement("div");o.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const s=document.createElement("span");s.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted,#888);",s.textContent="\u26A1 Conditional Logic";const r=ae(i),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",k(c,r?"chevron-down":"chevron-right",12);const d=document.createElement("div");d.className="fb-logic-body",d.style.cssText="padding:.25rem 0 .25rem;"+(r?"":"display:none;"),o.addEventListener("click",()=>{const p=d.style.display==="none";d.style.display=p?"":"none",k(c,p?"chevron-down":"chevron-right",12)}),o.appendChild(s),o.appendChild(c),l.appendChild(o),d.appendChild(qe(i.visibility||{},n,t)),d.appendChild($e(i.requirement||{},n,t)),d.appendChild(Fe(i.validation||[],n,t));const a=document.getElementById(`fb-type-${n}`)?.value||e.type;return J.has(a)&&d.appendChild(ze(i.cascade||{},n,t)),l.appendChild(d),l}function de(e,n,i){const t=document.createElement("div");return t.className="fb-field-extras",e==="chooser"?(t.appendChild(Ae(n,i)),t.appendChild(Oe(n.options||[],i))):(J.has(e)&&t.appendChild(je(n.options||[],i)),e==="textarea"&&t.appendChild(T([L("Rows",`fb-rows-${i}`,"number",n.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&t.appendChild(T([L("Min Length",`fb-minlength-${i}`,"number",n.minLength||"",""),L("Max Length",`fb-maxlength-${i}`,"number",n.maxLength||"","")])),e==="number"&&t.appendChild(T([L("Min",`fb-min-${i}`,"number",n.min??"",""),L("Max",`fb-max-${i}`,"number",n.max??"","")]))),t.children.length?t:null}function pe(e){const n=document.createElement("div");n.className="fb-chooser-section",n.style.cssText="border:1px solid var(--dm-border, #e5e7eb); border-radius:6px; margin-top:.5rem; overflow:hidden;";const i=document.createElement("div");i.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background, #f9fafb) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border, #e5e7eb);",i.textContent=e,n.appendChild(i);const t=document.createElement("div");return t.className="fb-chooser-section-body",t.style.cssText="padding:.55rem .6rem; display:flex; flex-direction:column; gap:.45rem;",n.appendChild(t),{wrap:n,body:t}}function U(e,n,i,t,l){const o=document.createElement("div");o.style.flex="1";const s=document.createElement("label");s.htmlFor=e,s.className="form-label",s.textContent=n,s.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",t.forEach(([c,d])=>{const a=document.createElement("option");a.value=c,a.textContent=d,String(c)===String(i)&&(a.selected=!0),r.appendChild(a)}),o.appendChild(s),o.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",o.appendChild(c)}return o}function me(e,n,i,t){const l=document.createElement("div");l.style.flex="1";const o=document.createElement("label");o.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const s=document.createElement("input");if(s.id=e,s.type="checkbox",s.checked=!!i,o.appendChild(s),o.appendChild(document.createTextNode(" "+n)),l.appendChild(o),t){const r=document.createElement("p");r.className="form-hint text-muted",r.textContent=t,r.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(r)}return l}function X(e,n,i,t,l){const o=document.createElement("div");o.style.flex="1";const s=document.createElement("label");s.htmlFor=e,s.className="form-label",s.textContent=n,s.style.fontSize=".8rem",o.appendChild(s);const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const c=document.createElement("input");c.id=e,c.type="text",c.className="form-input",c.value=i||"",t&&(c.placeholder=t),c.style.flex="1";const d=document.createElement("input");d.type="color",d.title="Pick a colour",d.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border,#e5e7eb);border-radius:4px;cursor:pointer;";const a=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(d.value=a?c.value:"#000000",d.addEventListener("input",()=>{c.value=d.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),r.appendChild(c),r.appendChild(d),o.appendChild(r),l){const p=document.createElement("p");p.className="form-hint text-muted",p.textContent=l,p.style.cssText="font-size:.72rem;margin-top:.2rem;",o.appendChild(p)}return o}function Ae(e,n){const i=document.createElement("div");i.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const t=pe("Layout");t.body.appendChild(T([U(`fb-chooser-variant-${n}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),me(`fb-chooser-multiple-${n}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),t.body.appendChild(T([U(`fb-chooser-density-${n}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),L("Columns",`fb-chooser-columns-${n}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),i.appendChild(t.wrap);const l=pe("Visual");return l.body.appendChild(T([X(`fb-chooser-accent-${n}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),U(`fb-chooser-accent-style-${n}`,"Accent style",e.accentStyle||"border",[["border","Border (default)"],["solid","Solid"],["glow","Glow"],["overlay","Overlay"],["underline","Underline"]],"Visual treatment of the selected state.")])),l.body.appendChild(T([me(`fb-chooser-glow-${n}`,"Glow on selected",!!e.glow,"Soft outer glow."),X(`fb-chooser-glow-colour-${n}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(T([U(`fb-chooser-shadow-${n}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),X(`fb-chooser-shadow-colour-${n}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),i.appendChild(l.wrap),i}function Be(e,n,i,t){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(i),l.style.cssText="border:1px solid var(--dm-border,#e5e7eb); border-radius:4px; padding:.5rem; background:var(--dm-background-alt, color-mix(in srgb, var(--dm-card-bg, #fff) 92%, var(--dm-text, #111))); display:flex; flex-direction:column; gap:.35rem;";const o=document.createElement("div");o.style.cssText="display:flex; gap:.4rem; align-items:center;";const s=document.createElement("div");s.style.cssText="display:flex; flex-direction:column; gap:1px;";const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.title="Move up",k(r,"arrow-up"),r.addEventListener("click",S=>{S.preventDefault(),ue(n,i,-1,t)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",k(c,"arrow-down"),c.addEventListener("click",S=>{S.preventDefault(),ue(n,i,1,t)}),s.appendChild(r),s.appendChild(c),o.appendChild(s);const d=document.createElement("input");d.type="text",d.className="form-input fb-chooser-opt-value",d.placeholder="value",d.value=e.value||"",d.style.flex="1",o.appendChild(d);const a=document.createElement("input");a.type="text",a.className="form-input fb-chooser-opt-label",a.placeholder="label (visible to users)",a.value=e.label||"",a.style.flex="2",o.appendChild(a);const p=document.createElement("button");p.type="button",p.className="btn btn-xs btn-ghost",p.style.cssText="line-height:1;opacity:.6;",p.title="Remove option",k(p,"x"),p.addEventListener("click",S=>{S.preventDefault(),Pe(n,i,t)}),o.appendChild(p),l.appendChild(o);const m=document.createElement("div");m.style.cssText="display:flex; gap:.4rem;";const f=ve("icon name (optional)",e.icon||"");f.input.classList.add("fb-chooser-opt-icon"),f.el.style.flex="1",m.appendChild(f.el);const b=document.createElement("input");b.type="text",b.className="form-input fb-chooser-opt-description",b.placeholder="description (card + comfortable only)",b.value=e.description||"",b.style.flex="2",m.appendChild(b),l.appendChild(m);const h=document.createElement("div");h.style.cssText="display:flex; gap:.4rem;";const g=document.createElement("input");g.type="text",g.className="form-input fb-chooser-opt-tooltip",g.placeholder="tooltip (hover hint)",g.value=e.tooltip||"",g.style.flex="2",h.appendChild(g);const u=document.createElement("input");u.type="text",u.className="form-input fb-chooser-opt-badge-text",u.placeholder="badge text",u.value=e.badge?.text||"",u.style.flex="1",h.appendChild(u);const y=document.createElement("select");y.className="form-input fb-chooser-opt-badge-type",y.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([S,q])=>{const B=document.createElement("option");B.value=S,B.textContent=q,(e.badge?.type||"")===S&&(B.selected=!0),y.appendChild(B)}),h.appendChild(y),l.appendChild(h);const x=document.createElement("div");x.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const N=document.createElement("label");N.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const C=document.createElement("input");C.type="checkbox",C.className="fb-chooser-opt-recommended",C.checked=!!e.recommended,N.appendChild(C),N.appendChild(document.createTextNode(" Recommended")),x.appendChild(N);const w=document.createElement("label");w.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const z=document.createElement("input");return z.type="checkbox",z.className="fb-chooser-opt-disabled",z.checked=!!e.disabled,w.appendChild(z),w.appendChild(document.createTextNode(" Disabled")),x.appendChild(w),l.appendChild(x),l}function Oe(e,n){const i=document.createElement("div");i.style.cssText="margin-top:.5rem;";const t=document.createElement("div");t.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:.4rem;";const l=document.createElement("p");l.textContent="Options",l.style.cssText="font-size:.85rem;font-weight:600;margin:0;",t.appendChild(l);const o=document.createElement("button");o.type="button",o.className="btn btn-xs btn-ghost",j(o,"plus","Add option"),t.appendChild(o),i.appendChild(t);const s=document.createElement("div");s.className="fb-chooser-options-list",s.id=`fb-chooser-options-${n}`,s.style.cssText="display:flex; flex-direction:column; gap:.4rem;",i.appendChild(s);const r=()=>{s.replaceChildren();const c=_e(n);(c.length?c:e||[]).forEach((a,p)=>{s.appendChild(Be(a,n,p,r))})};return o.addEventListener("click",c=>{c.preventDefault(),Me(n,r)}),r(),i}function _e(e){const n=v[e];return!n||!Array.isArray(n.options)?[]:n.options}function K(e){return v[e]?(Array.isArray(v[e].options)||(v[e].options=[]),v[e].options):[]}function Me(e,n){W(e),K(e).push({value:"new",label:"New option"}),n()}function Pe(e,n,i){W(e),K(e).splice(n,1),i()}function ue(e,n,i,t){W(e);const l=K(e),o=n+i;if(o<0||o>=l.length)return;const[s]=l.splice(n,1);l.splice(o,0,s),t()}function W(e){const n=document.getElementById(`fb-chooser-options-${e}`);if(!n)return;const i=n.querySelectorAll(".fb-chooser-option-row"),t=[];i.forEach(l=>{const o={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},s=l.querySelector(".fb-chooser-opt-icon")?.value.trim();s&&(o.icon=s);const r=l.querySelector(".fb-chooser-opt-description")?.value.trim();r&&(o.description=r);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(o.tooltip=c);const d=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),a=l.querySelector(".fb-chooser-opt-badge-type")?.value;(d||a)&&(o.badge={},d&&(o.badge.text=d),a&&(o.badge.type=a)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(o.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(o.disabled=!0),t.push(o)}),v[e]&&(v[e].options=t)}function T(e){const n=document.createElement("div");return n.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(i=>{i&&n.appendChild(i)}),n}function L(e,n,i,t,l){const o=document.createElement("div");o.style.flex="1";const s=document.createElement("label");s.htmlFor=n,s.className="form-label",s.textContent=e,s.style.fontSize=".8rem";const r=document.createElement("input");if(r.id=n,r.type=i||"text",r.className="form-input",r.value=t??"",o.appendChild(s),o.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",o.appendChild(c)}return o}function Re(e,n,i,t){const l=document.createElement("div");l.style.flex="1";const o=document.createElement("label");o.htmlFor=n,o.className="form-label",o.textContent=e,o.style.fontSize=".8rem";const s=document.createElement("select");return s.id=n,s.className="form-select",i.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===t&&(c.selected=!0),s.appendChild(c)}),l.appendChild(o),l.appendChild(s),l}function fe(e,n,i){const t=document.createElement("div");t.style.cssText="flex:0;min-width:80px;display:flex;flex-direction:column;justify-content:flex-end;";const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;font-size:.8rem;white-space:nowrap;";const o=document.createElement("input");return o.id=n,o.type="checkbox",o.checked=i,l.appendChild(o),l.appendChild(document.createTextNode(e)),t.appendChild(l),t}function je(e,n){const i=document.createElement("div");i.style.cssText="margin-top:.4rem;";const t=document.createElement("p");t.textContent="Options (one per line: value or value:Label)",t.style.cssText="font-size:.8rem;font-weight:600;margin-bottom:.3rem;";const l=document.createElement("textarea");return l.id=`fb-options-${n}`,l.className="form-input",l.rows=4,l.placeholder=`yes:Yes
6
6
  no:No
7
7
  maybe:Maybe`,l.value=(e||[]).map(o=>{const s=typeof o=="string"?o:o.value??"",r=typeof o=="string"?o:o.label??s;return s===r?s:`${s}:${r}`}).join(`
8
- `),l.style.fontFamily="monospace",a.appendChild(n),a.appendChild(l),a}function fe(e){const t=e.find("#field-project").val()||"";return $(),{title:e.find("#field-title").val().trim(),slug:e.find("#field-slug").val().trim(),description:e.find("#field-description").val().trim(),...e.find("#field-bundled").is(":checked")?{bundled:!0}:{},meta:{...G||{},project:t||null},fields:v,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"stacked",columns:parseInt(e.find("#setting-columns").val(),10)||2,submitSpan:e.find("#setting-submit-span").val()||"",honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...P!==null&&{collection:P}}}}function Me(e){const t=[];let a=[],n="Step 1",l="";return e.forEach(o=>{o.type==="page-break"?(t.push({title:n,description:l,fields:a}),a=[],n=o.label||`Step ${t.length+1}`,l=o.description||""):o.type!=="spacer"&&a.push(o)}),(a.length||t.length===0)&&t.push({title:n,description:l,fields:a}),t}function he(e,t){const a={};return e.forEach(n=>{if(n.type==="page-break"||n.type==="spacer")return;const l={...n.formConfig||{}};l.span==="full"&&t&&(l.span=t);const o=n.type==="chooser"||!!(n.variant&&["select","radio","checkbox-group"].includes(n.type)),r={type:n.type==="checkbox"?"boolean":n.type==="date"||n.type==="icon"||n.type==="image"?"string":o?"chooser":n.type,label:n.label,required:n.required,options:n.options,formConfig:{...n.placeholder&&{placeholder:n.placeholder},...n.helper&&{helperText:n.helper},...n.tooltip&&{tooltip:n.tooltip},...l}};o&&(n.variant&&(r.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(r.multiple=!0),n.density&&(r.density=n.density),n.columns&&(r.columns=n.columns),n.accent&&(r.accent=n.accent),n.accentStyle&&(r.accentStyle=n.accentStyle),n.glow&&(r.glow=!0),n.glowColour&&(r.glowColour=n.glowColour),n.shadow&&(r.shadow=n.shadow),n.shadowColour&&(r.shadowColour=n.shadowColour)),a[n.name]=r}),a}function be(e,t){const a=typeof e=="string"?document.querySelector(e):e;a&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const l=a.querySelector(`[name="${n.name}"]`);l&&l.type!=="date"&&(l.type="date")})}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){v=[],L=null,P=null;const t=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);L=t?t[1]:null;let a=null;const n=E.loader(e.get(0),{type:"dots"});if(L)try{a=await A(`/forms/${L}`),v=a.fields||[],P=a.actions?.collection??null}catch{E.toast("Could not load form.",{type:"error"})}G={};try{const i=await A("/projects").catch(()=>[]),p=e.find("#field-project").get(0);p&&(Array.isArray(i)?i:[]).forEach(m=>{const f=document.createElement("option");f.value=m.slug,f.textContent=m.name||m.slug,p.appendChild(f)})}catch{}if(n.destroy(),a?e.find("#editor-title").get(0).textContent=`Edit: ${a.title}`:e.find("#editor-title").get(0).textContent="New Form",L||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(ne(this.value))}),E.tabs(e.find("#editor-tabs").get(0)),a){e.find("#field-title").val(a.title),e.find("#field-slug").val(a.slug),e.find("#field-description").val(a.description||""),e.find("#field-bundled").prop("checked",!!a.bundled),G=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const i=a.settings||{};e.find("#setting-submit-text").val(i.submitText||"Submit"),e.find("#setting-success-message").val(i.successMessage||""),e.find("#setting-layout").val(i.layout||"stacked"),e.find("#setting-columns").val(i.columns||2),e.find("#setting-submit-span").val(i.submitSpan||""),e.find("#columns-group").get(0).style.display=i.layout==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",i.honeypot!==!1),e.find("#setting-rate-limit").val(i.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(i.successRedirect||"");const p=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",p.enabled||!1),e.find("#action-email-recipients").val(p.recipients||""),e.find("#action-email-subject-prefix").val(p.subjectPrefix||"");const m=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",m.enabled||!1),e.find("#action-webhook-url").val(m.url||""),e.find("#action-webhook-method").val(m.method||"POST")}const l=a?.settings?.actionSlug||"";try{const i=await A("/actions").catch(()=>[]),p=e.find("#action-cms-slug").get(0);if((Array.isArray(i)?i:[]).forEach(m=>{const f=document.createElement("option");f.value=m.slug,f.textContent=m.title||m.slug,m.slug===l&&(f.selected=!0),p.appendChild(f)}),!i.length){const m=document.createElement("option");m.value="",m.textContent="No actions available",m.disabled=!0,p.appendChild(m)}}catch{}const o=i=>{e.find("#columns-group").get(0).style.display=i?"":"none",document.querySelectorAll(".fb-grid-row").forEach(p=>{p.style.display=i?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){o(this.value==="grid")}),o(e.find("#setting-layout").val()==="grid"),z(e);const s=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",i=>{i.stopPropagation(),s.style.display=s.style.display==="none"?"":"none"}),M&&document.removeEventListener("click",M),M=()=>{s&&(s.style.display="none")},document.addEventListener("click",M),e.find("#add-field-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),$();const i=v.length;v.push({name:`field_${i+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),z(e);const p=e.find("#fields-list").get(0)?.lastElementChild;if(p){const m=p.querySelector(".fb-field-body");m&&(m.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),$(),v.push({type:"spacer"}),z(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),$();const i=v.filter(p=>p.type==="page-break").length+2;v.push({type:"page-break",label:`Step ${i}`,description:""}),z(e)}),e.find("#save-form-btn").get(0).addEventListener("click",async()=>{const i=fe(e);if(!i.title){E.toast("Please enter a form title.",{type:"error"});return}try{L?(await A(`/forms/${L}`,{method:"PUT",body:JSON.stringify(i)}),E.toast("Form saved.",{type:"success"})):(L=(await A("/forms",{method:"POST",body:JSON.stringify(i)})).slug,R.navigate(`/forms/edit/${L}`),E.toast("Form created.",{type:"success"}))}catch(p){E.toast(p.message||"Failed to save form.",{type:"error"})}}),D=()=>{const i=fe(e),p=e.find("#preview-container").get(0);if(!p)return;const m=e.find("#preview-test-result").get(0),f=e.find("#preview-test-badge").get(0);m&&(m.style.display="none",m.textContent=""),f&&(f.style.display=L?"":"none"),e.find("#preview-card").get(0).style.display="",p.textContent="";const b=document.createElement("div");b.id="fb-preview-form",p.appendChild(b);const h=L?async u=>{m&&(m.style.display="none",m.textContent="");try{const y=await fetch(`/api/forms/submit/${L}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}),x=await y.json();if(!y.ok)throw new Error(x.error||"Submission failed.");m&&(m.textContent=x.message||i.settings?.successMessage||"Submitted successfully.",m.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-success) 12%, transparent);color:var(--dm-success,#22c55e);"),E.toast("Test submission stored.",{type:"success"})}catch(y){m&&(m.textContent=y.message,m.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-danger) 12%, transparent);color:var(--dm-danger,#ef4444);"),E.toast(y.message,{type:"error"})}return!1}:()=>!1,g=i.fields.some(u=>u.type==="page-break");if(typeof F<"u"){const u=i.settings?.columns||2,y=i.settings?.layout||"stacked";if(g&&F.wizard){const x=Me(i.fields).map(S=>({title:S.title,description:S.description,fields:he(S.fields,u)}));F.wizard("#fb-preview-form",{schema:{steps:x},onSubmit:h}),be("#fb-preview-form",i.fields),Z(b,i.fields)}else if(F.render){const x=he(i.fields,u),S={};if(i.fields.forEach(C=>{if(!(!C.name||C.type==="page-break"||C.type==="spacer")&&(C.type==="select"||C.type==="multiselect")&&C.required){const N=(C.options||[])[0];N&&(S[C.name]=typeof N=="object"?N.value:N)}}),F.render("#fb-preview-form",x,S,{submitText:i.settings?.submitText||"Submit",layout:y,columns:u,onSubmit:h}),y==="grid"&&i.settings?.submitSpan==="full"){const C=document.querySelector("#fb-preview-form .form-buttons");C&&C.classList.add("col-span-full")}be("#fb-preview-form",i.fields),Z(b,i.fields)}window.FormLogicEngine&&i.fields.some(x=>x.logic)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:i.fields},b).init()})}else{const u=document.createElement("p");u.textContent=`${i.fields.filter(y=>y.type!=="page-break").length} field(s): ${i.fields.filter(y=>y.type!=="page-break").map(y=>y.label).join(", ")}`,u.style.cssText="color:var(--dm-text-muted);font-style:italic;",b.appendChild(u)}},D();const r=e.find("#editor-tabs").get(0),c=e.find("#preview-card").get(0),d=i=>{c&&c.contains(i.target)||Q()};r&&(r.addEventListener("input",d),r.addEventListener("change",d))}};
8
+ `),l.style.fontFamily="monospace",i.appendChild(t),i.appendChild(l),i}function Z(e){return parseInt(e,10)===3?3:2}function he(e){const n=e.find("#field-project").val()||"";return I(),{title:e.find("#field-title").val().trim(),slug:e.find("#field-slug").val().trim(),description:e.find("#field-description").val().trim(),...e.find("#field-bundled").is(":checked")?{bundled:!0}:{},meta:{...G||{},project:n||null},fields:v,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:Z(e.find("#setting-columns").val()),submitSpan:e.find("#setting-submit-span").val()||"",honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...M!==null&&{collection:M}}}}function be(e,n){const i={};return e.forEach(t=>{if(t.type==="page-break"||t.type==="spacer")return;const l={...t.formConfig||{}};l.span==="full"&&n&&(l.span=n);const o=t.type==="chooser"||!!(t.variant&&["select","radio","checkbox-group"].includes(t.type)),r={type:t.type==="checkbox"?"boolean":t.type==="date"||t.type==="icon"||t.type==="image"?"string":o?"chooser":t.type,label:t.label,required:t.required,options:t.options,formConfig:{...t.placeholder&&{placeholder:t.placeholder},...t.helper&&{helperText:t.helper},...t.tooltip&&{tooltip:t.tooltip},...l}};o&&(t.variant&&(r.variant=t.variant),(t.multiple||t.type==="checkbox-group")&&(r.multiple=!0),t.density&&(r.density=t.density),t.columns&&(r.columns=t.columns),t.accent&&(r.accent=t.accent),t.accentStyle&&(r.accentStyle=t.accentStyle),t.glow&&(r.glow=!0),t.glowColour&&(r.glowColour=t.glowColour),t.shadow&&(r.shadow=t.shadow),t.shadowColour&&(r.shadowColour=t.shadowColour)),i[t.name]=r}),i}function ge(e,n){const i=typeof e=="string"?document.querySelector(e):e;i&&(n||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const l=i.querySelector(`[name="${t.name}"]`);l&&l.type!=="date"&&(l.type="date")})}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){v=[],$=null,M=null;const n=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);$=n?n[1]:null;let i=null;const t=E.loader(e.get(0),{type:"dots"});if($)try{i=await _(`/forms/${$}`),v=i.fields||[],M=i.actions?.collection??null}catch{E.toast("Could not load form.",{type:"error"})}G={};try{const a=await _("/projects").catch(()=>[]),p=e.find("#field-project").get(0);p&&(Array.isArray(a)?a:[]).forEach(m=>{const f=document.createElement("option");f.value=m.slug,f.textContent=m.name||m.slug,p.appendChild(f)})}catch{}if(t.destroy(),i?e.find("#editor-title").get(0).textContent=`Edit: ${i.title}`:e.find("#editor-title").get(0).textContent="New Form",$||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(le(this.value))}),E.tabs(e.find("#editor-tabs").get(0)),i){e.find("#field-title").val(i.title),e.find("#field-slug").val(i.slug),e.find("#field-description").val(i.description||""),e.find("#field-bundled").prop("checked",!!i.bundled),G=i.meta||{},e.find("#field-project").val(i.meta?.project||"");const a=i.settings||{};e.find("#setting-submit-text").val(a.submitText||"Submit"),e.find("#setting-success-message").val(a.successMessage||""),e.find("#setting-layout").val(a.layout||"grid"),e.find("#setting-columns").val(Z(a.columns)),e.find("#setting-submit-span").val(a.submitSpan||""),e.find("#columns-group").get(0).style.display=(a.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",a.honeypot!==!1),e.find("#setting-rate-limit").val(a.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(a.successRedirect||"");const p=i.actions?.email||{};e.find("#action-email-enabled").prop("checked",p.enabled||!1),e.find("#action-email-recipients").val(p.recipients||""),e.find("#action-email-subject-prefix").val(p.subjectPrefix||"");const m=i.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",m.enabled||!1),e.find("#action-webhook-url").val(m.url||""),e.find("#action-webhook-method").val(m.method||"POST")}const l=i?.settings?.actionSlug||"";try{const a=await _("/actions").catch(()=>[]),p=e.find("#action-cms-slug").get(0);if((Array.isArray(a)?a:[]).forEach(m=>{const f=document.createElement("option");f.value=m.slug,f.textContent=m.title||m.slug,m.slug===l&&(f.selected=!0),p.appendChild(f)}),!a.length){const m=document.createElement("option");m.value="",m.textContent="No actions available",m.disabled=!0,p.appendChild(m)}}catch{}const o=a=>{e.find("#columns-group").get(0).style.display=a?"":"none",document.querySelectorAll(".fb-grid-row").forEach(p=>{p.style.display=a?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){o(this.value==="grid")}),o(e.find("#setting-layout").val()==="grid"),A(e);const s=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",a=>{a.stopPropagation(),s.style.display=s.style.display==="none"?"":"none"}),P&&document.removeEventListener("click",P),P=()=>{s&&(s.style.display="none")},document.addEventListener("click",P),e.find("#add-field-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),I();const a=v.length;v.push({name:`field_${a+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),A(e);const p=e.find("#fields-list").get(0)?.lastElementChild;if(p){const m=p.querySelector(".fb-field-body");m&&(m.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),I(),v.push({type:"spacer"}),A(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),I();const a=v.filter(p=>p.type==="page-break").length+2;v.push({type:"page-break",label:`Step ${a}`,description:""}),A(e)}),e.find("#save-form-btn").get(0).addEventListener("click",async()=>{const a=he(e);if(!a.title){E.toast("Please enter a form title.",{type:"error"});return}try{$?(await _(`/forms/${$}`,{method:"PUT",body:JSON.stringify(a)}),E.toast("Form saved.",{type:"success"})):($=(await _("/forms",{method:"POST",body:JSON.stringify(a)})).slug,R.navigate(`/forms/edit/${$}`),E.toast("Form created.",{type:"success"}))}catch(p){E.toast(p.message||"Failed to save form.",{type:"error"})}}),D=()=>{const a=he(e),p=e.find("#preview-container").get(0);if(!p)return;const m=e.find("#preview-test-result").get(0),f=e.find("#preview-test-badge").get(0);m&&(m.style.display="none",m.textContent=""),f&&(f.style.display=$?"":"none"),e.find("#preview-card").get(0).style.display="",p.textContent="";const b=document.createElement("div");b.id="fb-preview-form",p.appendChild(b);const h=$?async u=>{m&&(m.style.display="none",m.textContent="");try{const y=await fetch(`/api/forms/submit/${$}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}),x=await y.json();if(!y.ok)throw new Error(x.error||"Submission failed.");m&&(m.textContent=x.message||a.settings?.successMessage||"Submitted successfully.",m.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-success) 12%, transparent);color:var(--dm-success,#22c55e);"),E.toast("Test submission stored.",{type:"success"})}catch(y){m&&(m.textContent=y.message,m.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-danger) 12%, transparent);color:var(--dm-danger,#ef4444);"),E.toast(y.message,{type:"error"})}return!1}:()=>!1,g=a.fields.some(u=>u.type==="page-break");if(typeof F<"u"){const u=Z(a.settings?.columns),y=a.settings?.layout||"grid";if(g&&F.wizard){const x=xe(a.fields,a.title),N=x.map(q=>({title:q.title,description:q.description,fields:be(q.fields,u)}));let C=0,w=null,z=null;const S=q=>{const B=(x[C]||{}).fields||[];ge("#fb-preview-form",B),ee(b,B),q&&window.FormLogicEngine&&a.fields.some(ye=>ye.logic)&&(w?.destroy?.(),w=new window.FormLogicEngine.FormLogicRuntime({fields:a.fields},b,{baseValues:z?.getStepData?z.getStepData():{}}),w.init())};z=F.wizard("#fb-preview-form",{schema:{steps:N},layout:y,columns:u,finishText:a.settings?.submitText||"Finish",onStepChange:q=>{C=q,queueMicrotask(()=>S(!0))},onSubmit:h}),S(!1)}else if(F.render){const x=be(a.fields,u),N={};if(a.fields.forEach(C=>{if(!(!C.name||C.type==="page-break"||C.type==="spacer")&&(C.type==="select"||C.type==="multiselect")&&C.required){const w=(C.options||[])[0];w&&(N[C.name]=typeof w=="object"?w.value:w)}}),F.render("#fb-preview-form",x,N,{submitText:a.settings?.submitText||"Submit",layout:y,columns:u,onSubmit:h}),y==="grid"&&a.settings?.submitSpan==="full"){const C=document.querySelector("#fb-preview-form .form-buttons");C&&C.classList.add("col-span-full")}ge("#fb-preview-form",a.fields),ee(b,a.fields)}window.FormLogicEngine&&a.fields.some(x=>x.logic)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:a.fields},b).init()})}else{const u=document.createElement("p");u.textContent=`${a.fields.filter(y=>y.type!=="page-break").length} field(s): ${a.fields.filter(y=>y.type!=="page-break").map(y=>y.label).join(", ")}`,u.style.cssText="color:var(--dm-text-muted);font-style:italic;",b.appendChild(u)}},D();const r=e.find("#editor-tabs").get(0),c=e.find("#preview-card").get(0),d=a=>{c&&c.contains(a.target)||Q()};r&&(r.addEventListener("input",d),r.addEventListener("change",d))}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.45.1",
3
+ "version": "0.46.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",
@@ -1 +1 @@
1
- (function(u,f){typeof module<"u"&&module.exports?module.exports=f():u.FormLogicEngine=f()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function u(e){return e===""||e===null||e===void 0?"":String(e)}function f(e){const r=parseFloat(e);return isNaN(r)?null:r}function p(e){return e==null?!0:typeof e=="string"?e.trim()==="":Array.isArray(e)?e.length===0:!1}const F={not_equals:"equals",not_contains:"contains",not_in:"in"};function m(e,r){const n=u(r),t=u(e.value);switch(e.operator){case"equals":return n===t;case"not_equals":return n!==t;case"contains":return n.toLowerCase().includes(t.toLowerCase());case"not_contains":return!n.toLowerCase().includes(t.toLowerCase());case"starts_with":return n.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return n.toLowerCase().endsWith(t.toLowerCase());case"greater_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s>i}case"less_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s<i}case"is_empty":return p(r);case"is_not_empty":return!p(r);case"in":return(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"not_in":return!(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"matches_regex":try{const s=e.flags||"";return new RegExp(e.value,s).test(n)}catch(s){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,s&&s.message),!1}default:return!0}}function y(e,r){if(!e||!e.field||!e.operator)return!0;const n=r[e.field];if(!Array.isArray(n))return m(e,n);if(e.operator==="is_empty")return p(n);if(e.operator==="is_not_empty")return!p(n);const t=F[e.operator];if(t){const s=Object.assign({},e,{operator:t});return!n.some(i=>m(s,i))}return n.some(s=>m(e,s))}function h(e,r){return e?Array.isArray(e.all)?e.all.every(n=>n.all||n.any?h(n,r):y(n,r)):Array.isArray(e.any)?e.any.some(n=>n.all||n.any?h(n,r):y(n,r)):e.field&&e.operator?y(e,r):!0:!0}function g(e,r){const n=e.logic;if(!n||!n.visibility)return"visible";const t=n.visibility,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then==="hidden"?"hidden":"visible";return t.default==="hidden"?"hidden":"visible"}function _(e,r){const n=e.logic;if(!n||!n.requirement)return e.required||!1;const t=n.requirement,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then===!0;return t.default===!0}function v(e,r,n){const t=e.logic;if(!t||!Array.isArray(t.validation))return[];const s=[];for(const i of t.validation)switch(i.type){case"regex":{if(!p(r))try{new RegExp(i.pattern||"",i.flags||"").test(u(r))||s.push({message:i.message||"Invalid format."})}catch{}break}case"match":{const a=n[i.field];!p(r)&&u(r)!==u(a)&&s.push({message:i.message||"Fields do not match."});break}}return s}function w(e,r){const n=e.logic;if(!n||!n.cascade||!n.cascade.sourceField)return null;const t=n.cascade,s=t.mapping||{},i=r[t.sourceField];if(Array.isArray(i)){const c=new Set,l=[];return i.forEach(function(T){const q=u(T);Object.prototype.hasOwnProperty.call(s,q)&&(s[q]||[]).forEach(function(b){const x=u(b&&b.value);c.has(x)||(c.add(x),l.push(b))})}),l.length?l:t.defaultOptions||null}const a=u(i);return Object.prototype.hasOwnProperty.call(s,a)?s[a]||[]:t.defaultOptions||null}const L={fade:250,slide:300,scale:200};function A(e,r){const n=Number(r);return!isFinite(n)||n<0||n>5e3?L[e]||250:Math.round(n)}function S(e,r,n){const t=A(r,n);if(r==="fade")e.style.transition="opacity "+t+"ms ease",e.style.opacity="1",requestAnimationFrame(function(){e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight="0",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",e.style.transform="scale(1)",e.style.opacity="1",requestAnimationFrame(function(){e.style.transform="scale(0.95)",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function C(e,r,n){const t=A(r,n);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+t+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight=e.scrollHeight+"px",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function o(e,r){this._form=e,this._wrapper=r,this._fields=(e.fields||[]).filter(n=>n.type!=="page-break"),this._listeners=[],this._depMap=new Map,this._initialEval=!1}function d(e,r,n){const t=n||"",s=r||"";return t+'[name="'+e+'"]'+s+", "+t+'[name="'+e+'[]"]'+s}function k(e){return String(e||"").replace(/\[\]$/,"")}o.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(d(e))},o.prototype._fieldInput=function(e){return this._wrapper.querySelector(d(e))},o.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const n=r.logic;if(!n)return;function t(s){if(!s)return;(s.all||s.any||[]).forEach(function(a){a.field?(e._depMap.has(a.field)||e._depMap.set(a.field,new Set),e._depMap.get(a.field).add(r.name)):t(a)})}if(n.visibility&&(n.visibility.conditions||[]).forEach(function(s){t(s.when)}),n.requirement&&(n.requirement.conditions||[]).forEach(function(s){t(s.when)}),n.cascade&&n.cascade.sourceField){const s=n.cascade.sourceField;e._depMap.has(s)||e._depMap.set(s,new Set),e._depMap.get(s).add(r.name)}})};function E(e,r){const n={};return(r||[]).forEach(function(t){if(!t||!t.name)return;const s=e.querySelectorAll(d(t.name));if(!s.length)return;const i=s[0];if(i.type==="radio"){const a=e.querySelector(d(t.name,":checked"));n[t.name]=a?a.value:""}else if(i.type==="checkbox")if(s.length>1||/\[\]$/.test(i.name||"")){const a=[];s.forEach(function(c){c.checked&&a.push(c.value)}),n[t.name]=a}else n[t.name]=i.checked?i.value||"true":"";else n[t.name]=i.value}),n}function M(e,r){const n=E(e,r),t=[],s=[];return(r||[]).forEach(function(i){if(!i||!i.name||g(i,n)==="hidden")return;const a=n[i.name],c=Array.isArray(a)?a.length===0:!String(a??"").trim();if(_(i,n)&&c){t.push({name:i.name,label:i.label||i.name});return}if(c)return;const l=v(i,a,n);l.length&&s.push(l[0].message)}),{valid:t.length===0&&s.length===0,missing:t,errors:s,values:n}}return o.prototype._getValues=function(){const e={};return this._fields.forEach(function(r){const n=this._fieldInputs(r.name);if(!n.length)return;const t=n[0];if(t.type==="radio"){const s=this._wrapper.querySelector(d(r.name,":checked"));e[r.name]=s?s.value:""}else if(t.type==="checkbox")if(n.length>1||/\[\]$/.test(t.name||"")){const s=[];n.forEach(function(i){i.checked&&s.push(i.value)}),e[r.name]=s}else e[r.name]=t.checked?t.value||"true":"";else e[r.name]=t.value},this),e},o.prototype._applyVisibility=function(e,r){const t=g(e,r)==="hidden",s=this._findFieldWrapper(e.name);if(!s)return;s.setAttribute("aria-hidden",String(t));const i=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(i==="none"){s.classList.toggle("fb-field-hidden",t);return}const a=e.logic?.visibility?.duration;s.style.transition="",t?S(s,i,a):C(s,i,a)},o.prototype._applyRequirement=function(e,r){const n=_(e,r),t=this._fieldInput(e.name);if(!t)return;if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){const i=this._findFieldWrapper(e.name);t.removeAttribute("required"),i&&(i.setAttribute("aria-required",String(n)),i.classList.toggle("fb-field-required",n));return}n?t.setAttribute("required",""):t.removeAttribute("required");const s=this._findFieldWrapper(e.name);s&&(s.setAttribute("aria-required",String(n)),s.classList.toggle("fb-field-required",n))},o.prototype._applyCascade=function(e,r){const n=w(e,r);if(n===null)return;const t=this._wrapper.querySelector(d(e.name,"","select"));if(!t)return;const s=t.value;t.textContent="",n.forEach(function(i){const a=document.createElement("option");a.value=i.value,a.textContent=i.label||i.value,i.value===s&&(a.selected=!0),t.appendChild(a)})},o.prototype._applyValidation=function(e,r){const n=this._fieldInput(e.name);if(!n)return;const t=v(e,r[e.name],r);let s=n.parentNode.querySelector(".fb-validation-error");t.length?(s||(s=document.createElement("div"),s.className="fb-validation-error",n.parentNode.appendChild(s)),s.textContent=t[0].message):s&&s.remove()},o.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const n=r.closest("form")||this._wrapper;let t=r;for(;t.parentNode&&t.parentNode!==n;)t=t.parentNode;return t},o.prototype.evaluate=function(e){const r=this._getValues(),n=this;let t;if(e&&this._depMap.has(e)){const s=this._depMap.get(e);t=this._fields.filter(function(i){return s.has(i.name)})}else t=this._fields;t.forEach(function(s){s.logic&&(n._applyVisibility(s,r),n._applyRequirement(s,r),n._applyCascade(s,r))})},o.prototype.init=function(){this._buildDepMap();const e=this;this._wrapper.querySelectorAll("input, select, textarea").forEach(function(t){const s=k(t.getAttribute("name"));if(!s)return;const i=function(){e.evaluate(s)};t.addEventListener("input",i),t.addEventListener("change",i),e._listeners.push({el:t,event:"input",fn:i}),e._listeners.push({el:t,event:"change",fn:i});const a=e._fields.find(function(c){return c.name===s});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const c=function(){const l=e._getValues();e._applyValidation(a,l)};t.addEventListener("blur",c),e._listeners.push({el:t,event:"blur",fn:c})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(t){const s=t.getAttribute("data-chooser-field");if(!s)return;const i=function(){setTimeout(function(){e.evaluate(s)},0)};t.addEventListener("click",i),e._listeners.push({el:t,event:"click",fn:i})}),this._initialEval=!0,this.evaluate(),this._initialEval=!1},o.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn)}),this._listeners=[]},{evaluateCondition:y,evaluateConditionGroup:h,evaluateFieldVisibility:g,evaluateFieldRequirement:_,validateField:v,collectValues:E,validateFields:M,getCascadeOptions:w,FormLogicRuntime:o}});
1
+ (function(u,f){typeof module<"u"&&module.exports?module.exports=f():u.FormLogicEngine=f()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function u(e){return e===""||e===null||e===void 0?"":String(e)}function f(e){const r=parseFloat(e);return isNaN(r)?null:r}function p(e){return e==null?!0:typeof e=="string"?e.trim()==="":Array.isArray(e)?e.length===0:!1}const F={not_equals:"equals",not_contains:"contains",not_in:"in"};function m(e,r){const n=u(r),t=u(e.value);switch(e.operator){case"equals":return n===t;case"not_equals":return n!==t;case"contains":return n.toLowerCase().includes(t.toLowerCase());case"not_contains":return!n.toLowerCase().includes(t.toLowerCase());case"starts_with":return n.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return n.toLowerCase().endsWith(t.toLowerCase());case"greater_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s>i}case"less_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s<i}case"is_empty":return p(r);case"is_not_empty":return!p(r);case"in":return(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"not_in":return!(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"matches_regex":try{const s=e.flags||"";return new RegExp(e.value,s).test(n)}catch(s){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,s&&s.message),!1}default:return!0}}function y(e,r){if(!e||!e.field||!e.operator)return!0;const n=r[e.field];if(!Array.isArray(n))return m(e,n);if(e.operator==="is_empty")return p(n);if(e.operator==="is_not_empty")return!p(n);const t=F[e.operator];if(t){const s=Object.assign({},e,{operator:t});return!n.some(i=>m(s,i))}return n.some(s=>m(e,s))}function h(e,r){return e?Array.isArray(e.all)?e.all.every(n=>n.all||n.any?h(n,r):y(n,r)):Array.isArray(e.any)?e.any.some(n=>n.all||n.any?h(n,r):y(n,r)):e.field&&e.operator?y(e,r):!0:!0}function g(e,r){const n=e.logic;if(!n||!n.visibility)return"visible";const t=n.visibility,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then==="hidden"?"hidden":"visible";return t.default==="hidden"?"hidden":"visible"}function _(e,r){const n=e.logic;if(!n||!n.requirement)return e.required||!1;const t=n.requirement,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then===!0;return t.default===!0}function v(e,r,n){const t=e.logic;if(!t||!Array.isArray(t.validation))return[];const s=[];for(const i of t.validation)switch(i.type){case"regex":{if(!p(r))try{new RegExp(i.pattern||"",i.flags||"").test(u(r))||s.push({message:i.message||"Invalid format."})}catch{}break}case"match":{const a=n[i.field];!p(r)&&u(r)!==u(a)&&s.push({message:i.message||"Fields do not match."});break}}return s}function w(e,r){const n=e.logic;if(!n||!n.cascade||!n.cascade.sourceField)return null;const t=n.cascade,s=t.mapping||{},i=r[t.sourceField];if(Array.isArray(i)){const c=new Set,l=[];return i.forEach(function(V){const q=u(V);Object.prototype.hasOwnProperty.call(s,q)&&(s[q]||[]).forEach(function(b){const x=u(b&&b.value);c.has(x)||(c.add(x),l.push(b))})}),l.length?l:t.defaultOptions||null}const a=u(i);return Object.prototype.hasOwnProperty.call(s,a)?s[a]||[]:t.defaultOptions||null}const L={fade:250,slide:300,scale:200};function A(e,r){const n=Number(r);return!isFinite(n)||n<0||n>5e3?L[e]||250:Math.round(n)}function S(e,r,n){const t=A(r,n);if(r==="fade")e.style.transition="opacity "+t+"ms ease",e.style.opacity="1",requestAnimationFrame(function(){e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight="0",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",e.style.transform="scale(1)",e.style.opacity="1",requestAnimationFrame(function(){e.style.transform="scale(0.95)",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function C(e,r,n){const t=A(r,n);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+t+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight=e.scrollHeight+"px",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function o(e,r,n){this._form=e,this._wrapper=r,this._fields=(e.fields||[]).filter(t=>t.type!=="page-break"),this._listeners=[],this._depMap=new Map,this._initialEval=!1,this._baseValues=n&&n.baseValues||null}function d(e,r,n){const t=n||"",s=r||"";return t+'[name="'+e+'"]'+s+", "+t+'[name="'+e+'[]"]'+s}function k(e){return String(e||"").replace(/\[\]$/,"")}o.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(d(e))},o.prototype._fieldInput=function(e){return this._wrapper.querySelector(d(e))},o.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const n=r.logic;if(!n)return;function t(s){if(!s)return;(s.all||s.any||[]).forEach(function(a){a.field?(e._depMap.has(a.field)||e._depMap.set(a.field,new Set),e._depMap.get(a.field).add(r.name)):t(a)})}if(n.visibility&&(n.visibility.conditions||[]).forEach(function(s){t(s.when)}),n.requirement&&(n.requirement.conditions||[]).forEach(function(s){t(s.when)}),n.cascade&&n.cascade.sourceField){const s=n.cascade.sourceField;e._depMap.has(s)||e._depMap.set(s,new Set),e._depMap.get(s).add(r.name)}})};function E(e,r){const n={};return(r||[]).forEach(function(t){if(!t||!t.name)return;const s=e.querySelectorAll(d(t.name));if(!s.length)return;const i=s[0];if(i.type==="radio"){const a=e.querySelector(d(t.name,":checked"));n[t.name]=a?a.value:""}else if(i.type==="checkbox")if(s.length>1||/\[\]$/.test(i.name||"")){const a=[];s.forEach(function(c){c.checked&&a.push(c.value)}),n[t.name]=a}else n[t.name]=i.checked?i.value||"true":"";else n[t.name]=i.value}),n}function M(e,r){const n=E(e,r),t=[],s=[];return(r||[]).forEach(function(i){if(!i||!i.name||g(i,n)==="hidden")return;const a=n[i.name],c=Array.isArray(a)?a.length===0:!String(a??"").trim();if(_(i,n)&&c){t.push({name:i.name,label:i.label||i.name});return}if(c)return;const l=v(i,a,n);l.length&&s.push(l[0].message)}),{valid:t.length===0&&s.length===0,missing:t,errors:s,values:n}}return o.prototype._getValues=function(){const e=this._baseValues?Object.assign({},this._baseValues):{};return this._fields.forEach(function(r){const n=this._fieldInputs(r.name);if(!n.length)return;const t=n[0];if(t.type==="radio"){const s=this._wrapper.querySelector(d(r.name,":checked"));e[r.name]=s?s.value:""}else if(t.type==="checkbox")if(n.length>1||/\[\]$/.test(t.name||"")){const s=[];n.forEach(function(i){i.checked&&s.push(i.value)}),e[r.name]=s}else e[r.name]=t.checked?t.value||"true":"";else e[r.name]=t.value},this),e},o.prototype._applyVisibility=function(e,r){const t=g(e,r)==="hidden",s=this._findFieldWrapper(e.name);if(!s)return;s.setAttribute("aria-hidden",String(t));const i=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(i==="none"){s.classList.toggle("fb-field-hidden",t);return}const a=e.logic?.visibility?.duration;s.style.transition="",t?S(s,i,a):C(s,i,a)},o.prototype._applyRequirement=function(e,r){const n=_(e,r),t=this._fieldInput(e.name);if(!t)return;if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){const i=this._findFieldWrapper(e.name);t.removeAttribute("required"),i&&(i.setAttribute("aria-required",String(n)),i.classList.toggle("fb-field-required",n));return}n?t.setAttribute("required",""):t.removeAttribute("required");const s=this._findFieldWrapper(e.name);s&&(s.setAttribute("aria-required",String(n)),s.classList.toggle("fb-field-required",n))},o.prototype._applyCascade=function(e,r){const n=w(e,r);if(n===null)return;const t=this._wrapper.querySelector(d(e.name,"","select"));if(!t)return;const s=t.value;t.textContent="",n.forEach(function(i){const a=document.createElement("option");a.value=i.value,a.textContent=i.label||i.value,i.value===s&&(a.selected=!0),t.appendChild(a)})},o.prototype._applyValidation=function(e,r){const n=this._fieldInput(e.name);if(!n)return;const t=v(e,r[e.name],r);let s=n.parentNode.querySelector(".fb-validation-error");t.length?(s||(s=document.createElement("div"),s.className="fb-validation-error",n.parentNode.appendChild(s)),s.textContent=t[0].message):s&&s.remove()},o.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const n=r.closest("form")||this._wrapper;let t=r;for(;t.parentNode&&t.parentNode!==n;)t=t.parentNode;return t},o.prototype.evaluate=function(e){const r=this._getValues(),n=this;let t;if(e&&this._depMap.has(e)){const s=this._depMap.get(e);t=this._fields.filter(function(i){return s.has(i.name)})}else t=this._fields;t.forEach(function(s){s.logic&&(n._applyVisibility(s,r),n._applyRequirement(s,r),n._applyCascade(s,r))})},o.prototype.init=function(){this._buildDepMap();const e=this;this._wrapper.querySelectorAll("input, select, textarea").forEach(function(t){const s=k(t.getAttribute("name"));if(!s)return;const i=function(){e.evaluate(s)};t.addEventListener("input",i),t.addEventListener("change",i),e._listeners.push({el:t,event:"input",fn:i}),e._listeners.push({el:t,event:"change",fn:i});const a=e._fields.find(function(c){return c.name===s});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const c=function(){const l=e._getValues();e._applyValidation(a,l)};t.addEventListener("blur",c),e._listeners.push({el:t,event:"blur",fn:c})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(t){const s=t.getAttribute("data-chooser-field");if(!s)return;const i=function(){setTimeout(function(){e.evaluate(s)},0)};t.addEventListener("click",i),e._listeners.push({el:t,event:"click",fn:i})}),this._initialEval=!0,this.evaluate(),this._initialEval=!1},o.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn)}),this._listeners=[]},{evaluateCondition:y,evaluateConditionGroup:h,evaluateFieldVisibility:g,evaluateFieldRequirement:_,validateField:v,collectValues:E,validateFields:M,getCascadeOptions:w,FormLogicRuntime:o}});
@@ -0,0 +1 @@
1
+ export function buildWizardSteps(r,s){const e=[];let t=[],p=s||"Step 1",i="";return(r||[]).forEach(function(n){if(n.type!=="page-break"){t.push(n);return}t.length&&(e.push({title:p,description:i,fields:t}),t=[]),p=n.label||"Step "+(e.length+1),i=n.description||""}),(t.length||e.length===0)&&e.push({title:p,description:i,fields:t}),e}
@@ -1,2 +1,2 @@
1
- const C=document.querySelectorAll("[data-form]");C.length&&C.forEach(U);function A(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let a=t;for(;a.parentNode&&a.parentNode!==e;)a=a.parentNode;return a}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const a=A(n,e.name);a&&(a.classList.add("fb-field-invalid"),t||(t=a))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+k(e.label)+"</strong> is required.").concat((n.errors||[]).map(k)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
2
- `).replace(/<[^>]+>/g,""))}function k(n){return String(n).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function y(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const a=document.createElement("div");a.className=t==="success"?"fb-form-success":"fb-form-error",a.textContent=o,n.appendChild(a)}function L(n,o){if(n._formLogicRuntime=o,!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const a of e)for(const r of a.removedNodes)if(r===n||r.nodeType===1&&r.contains&&r.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1})}function z(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function T(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const a=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":a?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const i={type:r,label:e.label||e.name,required:z(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(i.minLength=e.minLength),e.maxLength!==void 0&&(i.maxLength=e.maxLength),e.min!==void 0&&(i.min=e.min),e.max!==void 0&&(i.max=e.max),a&&(e.variant&&(i.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(i.multiple=!0),e.density&&(i.density=e.density),e.columns&&(i.columns=e.columns),e.accent&&(i.accent=e.accent),e.accentStyle&&(i.accentStyle=e.accentStyle),e.glow&&(i.glow=!0),e.glowColour&&(i.glowColour=e.glowColour),e.shadow&&(i.shadow=e.shadow),e.shadowColour&&(i.shadowColour=e.shadowColour)),t[e.name]=i}),t}function P(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function q(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}function B(n,o){const t=[];let e=[],a=o||"Step 1",r="";return n.forEach(function(l){l.type==="page-break"?(t.push({title:a,description:r,fieldGroup:e}),e=[],a=l.label||"Step "+(t.length+1),r=l.description||""):l.type!=="spacer"&&e.push(l)}),t.push({title:a,description:r,fieldGroup:e}),t}const F="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function j(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const a=document.createElement("strong");a.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=F+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(a),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const i=m=>{m.key==="Escape"&&s()};function s(){document.removeEventListener("keydown",i),o.remove()}return r.addEventListener("click",s),o.addEventListener("click",m=>{m.target===o&&s()}),document.addEventListener("keydown",i),document.body.appendChild(o),{body:l,close:s}}function O(n){const{body:o,close:t}=j("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const a=document.createElement("div");a.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(a);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(i=>{const s=document.createElement("button");s.type="button",s.title=i,s.dataset.iconName=i,s.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const m=document.createElement("span");return m.setAttribute("data-icon",i),m.setAttribute("data-icon-size","18"),s.appendChild(m),s.addEventListener("mouseenter",()=>{s.style.borderColor="var(--dm-border)"}),s.addEventListener("mouseleave",()=>{s.style.borderColor="transparent"}),s.addEventListener("click",()=>{t(),n(i)}),a.appendChild(s),s});if(!r.length){const i=document.createElement("p");i.textContent="Icon engine unavailable - type an icon name into the field instead.",a.appendChild(i)}window.I?.scan?.(a),e.addEventListener("input",()=>{const i=e.value.trim().toLowerCase();l.forEach(s=>{s.style.display=!i||s.dataset.iconName.includes(i)?"":"none"})}),e.focus()}async function D(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=a=>fetch("/api/media",{headers:{Authorization:"Bearer "+a}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const a=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(a.ok){const{token:r}=await a.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(a=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(a.name||a.url||""))}}function M(n){const{body:o,close:t}=j("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),D().then(({files:a,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!a.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",a.forEach(i=>{const s=document.createElement("button");s.type="button",s.title=i.name||i.url,s.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const m=document.createElement("img");m.src=i.url,m.alt=i.name||"",m.loading="lazy",m.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const d=document.createElement("span");d.textContent=i.name||i.url,d.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.appendChild(m),s.appendChild(d),s.addEventListener("click",()=>{t(),n(i.url)}),l.appendChild(s)}),o.appendChild(l)})}function N(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function _(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function R(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=F,o}function V(n){if(!window.I||typeof I.list!="function")return;const o=_(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=n.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};n.addEventListener("input",e),e();const a=R("Browse");a.addEventListener("click",()=>O(r=>{N(n,r),e()})),o.appendChild(t),o.appendChild(a)}function G(n){const o=_(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=n.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};n.addEventListener("input",e),e();const a=R("Browse");a.addEventListener("click",()=>M(r=>{N(n,r),e()})),o.appendChild(t),o.appendChild(a)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const a=t.querySelector('[name="'+e.name+'"]');!a||a.dataset.pickerEnhanced||(a.dataset.pickerEnhanced="1",e.type==="icon"?V(a):G(a))})}function x(n){const o=document.createElement("div");o.className="fb-form-honeypot",o.setAttribute("aria-hidden","true");const t=document.createElement("input");t.name="website",t.type="text",t.tabIndex=-1,t.autocomplete="url",t.placeholder="https://",o.appendChild(t);const e=document.createElement("input");e.name="_t",e.type="hidden",e.value=Date.now(),o.appendChild(e),n.appendChild(o)}function W(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let a=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const i=e[a];if(i)t.insertBefore(l,i);else{const s=t.querySelector('[type="submit"]');s?t.insertBefore(l,s):t.appendChild(l)}}else r.type!=="page-break"&&a++})}function w(n,o,t,e,a){const r=a||e,l=r.querySelector('[name="website"]')?.value||"",i=r.querySelector('[name="_t"]')?.value||"",s=r?Array.from(r.querySelectorAll('input[type="file"]')):[],m=s.some(c=>c.files&&c.files.length>0);let d,u;if(m){const c=new FormData;for(const[h,f]of Object.entries(o||{}))f!=null&&(s.some(g=>g.name===h)||c.append(h,typeof f=="object"?JSON.stringify(f):String(f)));for(const h of s)for(const f of h.files)c.append(h.name,f,f.name);c.append("_hp",l),c.append("_t",i),d=c,u={}}else{const c=Object.assign({},o,{_hp:l,_t:i});d=JSON.stringify(c),u={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:u,body:d}).then(c=>c.json().then(h=>({ok:c.ok,body:h}))).then(c=>{c.ok&&c.body.ok?(e.textContent="",y(e,c.body.message||t.successMessage||"Thank you.","success")):y(e,c.body.error||"Something went wrong.","error")}).catch(()=>{y(e,"Unable to submit. Please check your connection.","error")})}function J(n,o,t,e,a){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(i){const s=document.createElement("div");s.className="form-group",s.style.marginBottom="1.25rem";const m=document.createElement("label");if(m.className="form-label",m.textContent=i.label||i.name,i.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;i.type==="textarea"?(d=document.createElement("textarea"),d.rows=i.formConfig?.rows||4,d.className="form-input"):i.type==="select"?(d=document.createElement("select"),d.className="form-input",(i.options||[]).forEach(function(u){const c=document.createElement("option");c.value=typeof u=="string"?u:u.value??"",c.textContent=typeof u=="string"?u:u.label||c.value,d.appendChild(c)})):(d=document.createElement("input"),d.type=i.type==="icon"||i.type==="image"?"text":i.type||"text",d.className="form-input",i.placeholder&&(d.placeholder=i.placeholder),i.type==="file"&&(i.file?.accept&&(d.accept=i.file.accept),i.multiple&&(d.multiple=!0))),d.name=i.name,d.required=i.required||!1,s.appendChild(m),s.appendChild(d),r.appendChild(s)}),t.honeypot&&x(r);const l=document.createElement("button");l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",r.appendChild(l),r.addEventListener("submit",function(i){i.preventDefault();const s={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(s[m.name]=d.value)}),window.FormLogicEngine&&a){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(c){if(m.evaluateFieldVisibility(c,s)==="hidden"){delete s[c.name];return}const f=m.evaluateFieldRequirement(c,s),g=s[c.name];f&&(!g||!String(g).trim())&&d.push(c.label||c.name);const p=m.validateField(c,g||"",s);p.length&&u.push(p[0].message)}),d.length||u.length){const c=[];d.length&&c.push("Required: "+d.join(", ")),u.length&&c.push(u.join("; ")),y(n,c.join(". "),"error");return}}n.classList.add("fb-form-loading"),l.disabled=!0,w(e,s,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),enhancePickerFields(n,o),window.FormLogicEngine&&a&&o.some(i=>i.logic)&&new window.FormLogicEngine.FormLogicRuntime(a,n).init()}function U(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],a=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(i=>i.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const i=a.columns||1;if(l&&Domma.forms.wizard){const s=B(e,t.title),m=s.map(p=>p.fieldGroup),d=s.map(function(p){return{title:p.title,description:p.description,fields:T(p.fieldGroup,i)}});let u=0,c=null;const h=function(p){const b=window.FormLogicEngine;if(!b||!b.validateFields)return;const v=b.validateFields(r,m[u]||[]);v.valid||(p.preventDefault(),p.stopImmediatePropagation(),markInvalidFields(r,v.missing),showValidationPopup(v))},f=function(){if(q(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&e.some(p=>p.logic)&&(c&&c.destroy(),c=new window.FormLogicEngine.FormLogicRuntime(t,r),c.init(),L(r,c)),a.honeypot){const p=r.querySelector("form");p&&x(p)}r.querySelectorAll(".wizard-next, .wizard-submit").forEach(p=>p.addEventListener("click",h,!0))},g=Domma.forms.wizard(r,{schema:{steps:d},onSubmit:function(p){return w(o,p,a,r,null)},onStepChange:function(p){u=p,setTimeout(f,0)}});Promise.resolve(g).then(f)}else if(Domma.forms.render){const s=T(e,i),m=P(e),d=Domma.forms.render(r,s,m,{submitText:a.submitText||"Submit",layout:a.layout||"stacked",columns:i,onSubmit:function(u){return w(o,u,a,r,null)}});Promise.resolve(d).then(function(){if(q(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&e.some(u=>u.logic)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),L(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),a.honeypot){const u=r.querySelector("form");u&&x(u)}})}}else J(r,e.filter(i=>i.type!=="page-break"&&i.type!=="spacer"),a,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
1
+ import{buildWizardSteps as D}from"/public/js/form-steps.mjs";const T=document.querySelectorAll("[data-form]");T.length&&T.forEach(G);function M(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let i=t;for(;i.parentNode&&i.parentNode!==e;)i=i.parentNode;return i}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const i=M(n,e.name);i&&(i.classList.add("fb-field-invalid"),t||(t=i))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+F(e.label)+"</strong> is required.").concat((n.errors||[]).map(F)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
2
+ `).replace(/<[^>]+>/g,""))}function F(n){return String(n).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function w(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=t==="success"?"fb-form-success":"fb-form-error",i.textContent=o,n.appendChild(i)}function N(n,o){if(n._formLogicRuntime=o,n._formLogicObserver&&(n._formLogicObserver.disconnect(),n._formLogicObserver=null),!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const i of e)for(const a of i.removedNodes)if(a===n||a.nodeType===1&&a.contains&&a.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function V(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function j(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const i=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),a=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,d={...e.formConfig||{}};d.span==="full"&&o&&(d.span=o);const r={type:a,label:e.label||e.name,required:V(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...d}};e.minLength!==void 0&&(r.minLength=e.minLength),e.maxLength!==void 0&&(r.maxLength=e.maxLength),e.min!==void 0&&(r.min=e.min),e.max!==void 0&&(r.max=e.max),i&&(e.variant&&(r.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(r.multiple=!0),e.density&&(r.density=e.density),e.columns&&(r.columns=e.columns),e.accent&&(r.accent=e.accent),e.accentStyle&&(r.accentStyle=e.accentStyle),e.glow&&(r.glow=!0),e.glowColour&&(r.glowColour=e.glowColour),e.shadow&&(r.shadow=e.shadow),e.shadowColour&&(r.shadowColour=e.shadowColour)),t[e.name]=r}),t}function W(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function _(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}const A="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function O(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const i=document.createElement("strong");i.textContent=n;const a=document.createElement("button");a.type="button",a.textContent="\xD7",a.setAttribute("aria-label","Close"),a.style.cssText=A+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(a),t.appendChild(e);const d=document.createElement("div");d.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(d),o.appendChild(t);const r=u=>{u.key==="Escape"&&s()};function s(){document.removeEventListener("keydown",r),o.remove()}return a.addEventListener("click",s),o.addEventListener("click",u=>{u.target===o&&s()}),document.addEventListener("keydown",r),document.body.appendChild(o),{body:d,close:s}}function J(n){const{body:o,close:t}=O("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(i);const a=window.I&&typeof I.list=="function"?I.list():[],d=a.map(r=>{const s=document.createElement("button");s.type="button",s.title=r,s.dataset.iconName=r,s.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const u=document.createElement("span");return u.setAttribute("data-icon",r),u.setAttribute("data-icon-size","18"),s.appendChild(u),s.addEventListener("mouseenter",()=>{s.style.borderColor="var(--dm-border)"}),s.addEventListener("mouseleave",()=>{s.style.borderColor="transparent"}),s.addEventListener("click",()=>{t(),n(r)}),i.appendChild(s),s});if(!a.length){const r=document.createElement("p");r.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(r)}window.I?.scan?.(i),e.addEventListener("input",()=>{const r=e.value.trim().toLowerCase();d.forEach(s=>{s.style.display=!r||s.dataset.iconName.includes(r)?"":"none"})}),e.focus()}async function U(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const i=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(i.ok){const{token:a}=await i.json();S.set("auth_token",a),t=await o(a)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function H(n){const{body:o,close:t}=O("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),U().then(({files:i,error:a})=>{if(a){e.textContent=a==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const d=document.createElement("div");d.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(r=>{const s=document.createElement("button");s.type="button",s.title=r.name||r.url,s.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const u=document.createElement("img");u.src=r.url,u.alt=r.name||"",u.loading="lazy",u.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const c=document.createElement("span");c.textContent=r.name||r.url,c.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.appendChild(u),s.appendChild(c),s.addEventListener("click",()=>{t(),n(r.url)}),d.appendChild(s)}),o.appendChild(d)})}function R(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function z(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function B(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=A,o}function K(n){if(!window.I||typeof I.list!="function")return;const o=z(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const a=n.value.trim();if(!a)return;const d=document.createElement("span");d.setAttribute("data-icon",a),d.setAttribute("data-icon-size","16"),t.appendChild(d),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=B("Browse");i.addEventListener("click",()=>J(a=>{R(n,a),e()})),o.appendChild(t),o.appendChild(i)}function Y(n){const o=z(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const a=n.value.trim();t.style.display=a?"":"none",a&&(t.src=a)};n.addEventListener("input",e),e();const i=B("Browse");i.addEventListener("click",()=>H(a=>{R(n,a),e()})),o.appendChild(t),o.appendChild(i)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?K(i):Y(i))})}function L(n,o){const t=document.createElement("div");t.className="fb-form-honeypot",t.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=n.querySelector('[name="website"]')?"_website":"website",t.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",t.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),t.appendChild(i),n.appendChild(t)}function P(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(a){if(a.type==="spacer"){const d=document.createElement("div");d.className="fb-spacer";const r=e[i];if(r)t.insertBefore(d,r);else{const s=t.querySelector('[type="submit"]');s?t.insertBefore(d,s):t.appendChild(d)}}else a.type!=="page-break"&&i++})}function k(n,o){!n||!o||n.querySelectorAll('input[type="file"]').forEach(function(t){t.name&&t.files&&t.files.length&&o.set(t.name,Array.from(t.files))})}function q(n,o,t,e,i,a){const d=i||e,r=d.querySelector(".fb-form-honeypot"),s=r?.querySelector('input[type="text"]')?.value||"",u=r?.querySelector('[name="_t"]')?.value||"",c=Object.assign({},o);delete c._t,r?.dataset.hpName&&delete c[r.dataset.hpName];const m=new Map(a||[]);k(d,m);const l=m.size>0;let b,y;if(l){const p=new FormData;for(const[h,v]of Object.entries(c))v!=null&&(m.has(h)||p.append(h,typeof v=="object"?JSON.stringify(v):String(v)));for(const[h,v]of m)for(const x of v)p.append(h,x,x.name);p.append("_hp",s),p.append("_t",u),b=p,y={}}else{const p=Object.assign({},c,{_hp:s,_t:u});b=JSON.stringify(p),y={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:y,body:b}).then(p=>p.json().then(h=>({ok:p.ok,body:h}))).then(p=>{p.ok&&p.body.ok?(e.textContent="",w(e,p.body.message||t.successMessage||"Thank you.","success")):w(e,p.body.error||"Something went wrong.","error")}).catch(()=>{w(e,"Unable to submit. Please check your connection.","error")})}function $(n,o,t,e,i){const a=document.createElement("form");a.noValidate=!0,o.forEach(function(r){const s=document.createElement("div");s.className="form-group",s.style.marginBottom="1.25rem";const u=document.createElement("label");if(u.className="form-label",u.textContent=r.label||r.name,r.required){const m=document.createElement("span");m.textContent=" *",m.style.color="var(--dm-danger)",u.appendChild(m)}let c;r.type==="textarea"?(c=document.createElement("textarea"),c.rows=r.formConfig?.rows||4,c.className="form-input"):r.type==="select"?(c=document.createElement("select"),c.className="form-input",(r.options||[]).forEach(function(m){const l=document.createElement("option");l.value=typeof m=="string"?m:m.value??"",l.textContent=typeof m=="string"?m:m.label||l.value,c.appendChild(l)})):(c=document.createElement("input"),c.type=r.type==="icon"||r.type==="image"?"text":r.type||"text",c.className="form-input",r.placeholder&&(c.placeholder=r.placeholder),r.type==="file"&&(r.file?.accept&&(c.accept=r.file.accept),r.multiple&&(c.multiple=!0))),c.name=r.name,c.required=r.required||!1,s.appendChild(u),s.appendChild(c),a.appendChild(s)}),t.honeypot&&L(a);const d=document.createElement("button");d.type="submit",d.className="btn btn-primary",d.textContent=t.submitText||"Submit",a.appendChild(d),a.addEventListener("submit",function(r){r.preventDefault();const s={};if(o.forEach(function(u){const c=a.querySelector('[name="'+u.name+'"]');c&&(s[u.name]=c.value)}),window.FormLogicEngine&&i){const u=window.FormLogicEngine,c=[],m=[];if(o.forEach(function(l){if(u.evaluateFieldVisibility(l,s)==="hidden"){delete s[l.name];return}const y=u.evaluateFieldRequirement(l,s),p=s[l.name];y&&(!p||!String(p).trim())&&c.push(l.label||l.name);const h=u.validateField(l,p||"",s);h.length&&m.push(h[0].message)}),c.length||m.length){const l=[];c.length&&l.push("Required: "+c.join(", ")),m.length&&l.push(m.join("; ")),w(n,l.join(". "),"error");return}}n.classList.add("fb-form-loading"),d.disabled=!0,q(e,s,t,n,a).finally(function(){n.classList.remove("fb-form-loading"),d.disabled=!1})}),n.appendChild(a),enhancePickerFields(n,o),window.FormLogicEngine&&i&&o.some(r=>r.logic)&&new window.FormLogicEngine.FormLogicRuntime(i,n).init()}function G(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],i=t.settings||{},a=document.createElement("div");a.className="fb-form-wrapper",n.appendChild(a);const d=e.some(r=>r.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const r=Number(i.columns)===3?3:2,s=i.layout||"grid";if(d&&Domma.forms.wizard){const u=D(e,t.title),c=u.map(f=>f.fields),m=u.map(function(f){return{title:f.title,description:f.description,fields:j(f.fields,r)}});let l=0,b=null,y=null;const p=Date.now(),h=new Map,v=function(f){const g=window.FormLogicEngine;if(!g||!g.validateFields)return;const C=g.validateFields(a,c[l]||[]);C.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(a,C.missing),showValidationPopup(C))},x=function(){const f=c[l]||e;if(_(a,f),enhancePickerFields(a,f),f.some(g=>g.type==="spacer")&&P(a,f),i.honeypot){const g=a.querySelector("form");g&&L(g,p)}window.FormLogicEngine&&e.some(g=>g.logic)&&(b&&b.destroy(),b=new window.FormLogicEngine.FormLogicRuntime(t,a,{baseValues:y&&y.getStepData?y.getStepData():{}}),b.init(),N(a,b)),a.querySelectorAll(".wizard-next, .wizard-submit").forEach(g=>g.addEventListener("click",v,!0))};y=Domma.forms.wizard(a,{schema:{steps:m},layout:s,columns:r,finishText:i.submitText||"Finish",onStepChange:function(f){k(a,h),l=f,setTimeout(x,0)},onSubmit:function(f){return k(a,h),q(o,f,i,a,null,h)}}),Promise.resolve(y).then(x)}else if(Domma.forms.render){const u=j(e,r),c=W(e),m=Domma.forms.render(a,u,c,{submitText:i.submitText||"Submit",layout:s,columns:r,onSubmit:function(l){return q(o,l,i,a,null)}});Promise.resolve(m).then(function(){if(_(a,e),enhancePickerFields(a,e),window.FormLogicEngine&&e.some(l=>l.logic)){const l=new window.FormLogicEngine.FormLogicRuntime(t,a);l.init(),N(a,l)}if(e.some(l=>l.type==="spacer")&&P(a,e),s==="grid"&&i.submitSpan==="full"){const l=a.querySelector(".form-buttons");l&&l.classList.add("col-span-full")}if(i.honeypot){const l=a.querySelector("form");l&&L(l)}})}}else $(a,e.filter(r=>r.type!=="page-break"&&r.type!=="spacer"),i,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
package/public/js/site.js CHANGED
@@ -1 +1 @@
1
- import{makeBadgeEl as M,applyColour as O,applyPill as R,applyFloat as P}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as z,markInvalidFields as B,showValidationPopup as V}from"/public/js/forms.js?v=20260821-wizard-steps";$(()=>{const v=window.__CMS_NAV__||{},h=window.__CMS_SITE__||{};if(h.autoTheme?.enabled){let t=function(a){const e=(a||"07:00").split(":");return+e[0]*60+(+e[1]||0)},o=function(){const a=new Date,e=a.getHours()*60+a.getMinutes();return e>=t(n.dayStart)&&e<t(n.nightStart)?n.dayTheme:n.nightTheme};const n=h.autoTheme;Domma.theme.set(o()),setInterval(()=>Domma.theme.set(o()),6e4)}const w=$("#site-navbar");if(w.length&&v.brand){let o=function(r,i=0){return Array.isArray(r)?r.filter(c=>!(c&&c.type==="separator"&&i===0)).map(c=>c&&c.type==="separator"?{divider:!0}:Array.isArray(c?.items)?{...c,items:o(c.items,i+1)}:c):r},a=function(r){return Array.isArray(r)?r.filter(i=>!(i&&i.type==="separator")):[]};const n={...v.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=v.position==="floating";v.orientation==="vertical"&&w.get(0).classList.add("dm-nav-vertical",v.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),Domma.elements.navbar("#site-navbar",{brand:n,items:o(v.items||[]),variant:v.variant||"dark",position:e?"static":v.position||"sticky",collapsible:!0}),Domma.icons.scan("#site-navbar"),e&&P(w.get(0),v);const g=w.get(0);if(v.appearOnHover){const r=window.matchMedia("(min-width: 993px)");g.querySelectorAll(".navbar-dropdown").forEach(i=>{i.addEventListener("mouseenter",()=>{r.matches&&i.classList.add("open")}),i.addEventListener("mouseleave",()=>{r.matches&&i.classList.remove("open")})})}const y=g.querySelector(".navbar-toggle"),f=g.querySelector(".navbar-collapse");if(y&&f){let r=null;const i=()=>{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",i),document.body.appendChild(r),document.body.classList.add("dm-drawer-open"))};y.addEventListener("click",()=>{requestAnimationFrame(()=>{f.classList.contains("show")?s():c()})}),f.addEventListener("click",l=>{l.target.closest("a")&&requestAnimationFrame(c)}),document.addEventListener("keydown",l=>{l.key==="Escape"&&f.classList.contains("show")&&i()})}const m=a(v.items||[]);g.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(r=>{const i=m[parseInt(r.dataset.index,10)];if(!i)return;const c=r.dataset.subindex!=null,s=c&&Array.isArray(i.items)?i.items[parseInt(r.dataset.subindex,10)]:i;if(!s)return;s.colour&&O(r,s.colour),s.pill&&!c&&R(r,s.pill);const l=M(s.badge);l&&r.appendChild(l)})}const b=$("#site-footer");if(b.length){let e=function(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},u=function(s){return e(s).replace(/'/g,"&#39;")},g=function(s){if(s&&s.type==="separator")return'<li class="footer-sep"><hr></li>';const l=u(s.url||"#"),d=e(s.text||""),k=Array.isArray(s.items)&&s.items.length?`<ul>${s.items.map(g).join("")}</ul>`:"";return`<li><a href="${l}">${d}</a>${k}</li>`},y=function(s,l){return(s||[]).forEach(d=>{d&&d.type==="separator"||(l.push(d),Array.isArray(d.items)&&d.items.length&&y(d.items,l))}),l};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 o='<div class="footer-inner container">';const a=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(a.copyright&&(o+=`<p>${e(a.copyright)}</p>`),a.primary.length&&(o+=`<nav class="footer-nav footer-nav--primary"><ul>${a.primary.map(g).join("")}</ul></nav>`),a.legal.length&&(o+=`<nav class="footer-nav footer-nav--legal"><ul>${a.legal.map(g).join("")}</ul></nav>`),h.footer){const s=Object.keys(t).filter(l=>n[l]);s.length&&(o+='<div class="footer-social">',s.forEach(l=>{const{label:d,svg:k}=t[l];o+=`<a href="${n[l]}" target="_blank" rel="noopener noreferrer" aria-label="${d}" class="footer-social-link">${k}</a>`}),o+="</div>")}o+="</div>",b.html(o);const f=[...y(a.primary,[]),...y(a.legal,[])];b.get(0).querySelectorAll(".footer-nav a").forEach((s,l)=>{const d=f[l];if(!d)return;d.colour&&O(s,d.colour);const k=M(d.badge);k&&s.appendChild(k)});const r=S.get("reduced_motion"),i=r!==null?!!r:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),c=b.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=i,s.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const l=document.createElement("span");l.className="form-switch-label",l.textContent="Reduce motion";const d=document.createElement("label");d.className="form-switch footer-motion-switch",d.title="Reduce motion",d.appendChild(s),d.appendChild(l),c.appendChild(d)}}$("#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(a=>{const e={title:a.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:a.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return a.dataset.date&&(e.date=a.dataset.date),a.dataset.status&&(e.status=a.dataset.status),a.dataset.entryId&&(e._entryId=a.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",o=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:o,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",o=n.dataset.revealAnimation||"slide-up",a=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,u=parseInt(n.dataset.revealDelay,10)||0,g=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[o]||"",m.style.transition=`opacity ${a}ms ease, transform ${a}ms ease`;const i=g?y.length-1-r:r;m.style.transitionDelay=t==="stagger"?`${u+i*e}ms`:`${u}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(r=>{r.forEach(i=>{i.isIntersecting&&(i.target.offsetWidth,i.target.style.opacity="1",i.target.style.transform="none",m.unobserve(i.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 o=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",o.setContent(t),o.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const o=atob(t.dataset.config),a=JSON.parse(o);Object.assign(n,a)}catch{}}),Object.keys(n).length>0){const t={};for(const[o,a]of Object.entries(n)){const e=a?.events?.click,{confirm:u,toast:g,alert:y,prompt:f,...m}=e||{};u||g||y||f?($(o).on("click",async function(i){if(i.preventDefault(),u&&!await E.confirm(u))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),g&&E.toast(g,{type:m.toastType||"success"}),y&&E.alert(y)}}),Object.keys(m).length&&(t[o]={...a,events:{...a.events,click:m}})):t[o]=a}$.setup(t)}}p.length&&_(p.get(0))});function _(v){v.querySelectorAll(".dm-cta-trigger").forEach(h=>{h.__ctaWired||(h.__ctaWired=!0,h.addEventListener("click",async()=>{const w=h.dataset.action,b=h.dataset.entry,C=h.dataset.confirm;let p=S.get("auth_token");if(!p){E.toast("Please log in to perform this action.",{type:"warning"});return}if(C&&!await E.confirm(C))return;const n=Array.from(h.childNodes).map(o=>o.cloneNode(!0));h.disabled=!0,h.textContent="Running\u2026";const t=o=>fetch(`/api/actions/${w}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({entryId:b})});try{let o=await t(p);if(o.status===401){const e=S.get("auth_refresh_token");if(e){const u=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(u.ok){const{token:g}=await u.json();S.set("auth_token",g),p=g,o=await t(p)}}}const a=await o.json().catch(()=>({}));if(!o.ok)throw new Error(a.error||a.message||`Error ${o.status}`);E.toast(a.message||"Action completed.",{type:"success"})}catch(o){E.toast(o.message||"Action failed.",{type:"error"})}finally{h.disabled=!1,h.textContent="",n.forEach(o=>h.appendChild(o)),Domma.icons.scan(h)}}))})}(function(){const h=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!h.length)return;const w=S.get("auth_token");function b(p,n){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const o=document.createElement("p");if(n){o.appendChild(document.createTextNode("Please "));const a=document.createElement("a");a.href="/login",a.textContent="sign in",o.appendChild(a),o.appendChild(document.createTextNode(" to view your entries."))}else o.textContent=p;return t.appendChild(o),t}function C(p,n){const t=document.createElement("template");t.innerHTML=n||"",p.replaceWith(t.content)}h.forEach(async p=>{const n=p.dataset.collectionAttrs;if(!n)return;if(!w){p.replaceChildren(b("",!0));return}const t=o=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({attrs:n})});try{let o=w,a=await t(o);if(a.status===401){const u=S.get("auth_refresh_token");if(u){const g=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:u})});if(g.ok){const{token:y}=await g.json();S.set("auth_token",y),o=y,a=await t(o)}}}if(!a.ok){const{error:u}=await a.json().catch(()=>({}));p.replaceChildren(b(u||"Unable to load entries.",!1));return}const{html:e}=await a.json();C(p,e)}catch{p.replaceChildren(b("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),_(document.body)},100)})(),(function(){const h=document.querySelectorAll("[data-collection-table]");!h.length||typeof T>"u"||!T.create||h.forEach(w=>{let b;try{b=JSON.parse(atob(w.dataset.payload))}catch{return}const{columns:C,rows:p,search:n,sortable:t,exportable:o,pageSize:a,empty:e,ctaConfig:u,slug:g,exportCfg:y}=b;if(!C?.length)return;if(u){const r=C.findIndex(i=>i.key==="_cta");r!==-1&&(C[r]={key:"_cta",title:"",render:(i,c)=>{const s=document.createElement("button");if(s.className=`btn btn-${u.style||"primary"} dm-cta-trigger`,s.dataset.action=u.action||"",s.dataset.entry=c._entryId||"",u.confirm&&(s.dataset.confirm=u.confirm),u.icon){const l=document.createElement("span");l.dataset.icon=u.icon,s.appendChild(l),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(u.label||"Run")),s}})}const f="col-table-"+Math.random().toString(36).slice(2,7),m=document.createElement("div");m.id=f,w.replaceChildren(m),T.create("#"+f,{data:p,columns:C,search:n,sortable:t,exportable:o,pageSize:a,emptyMessage:e}),u&&_(m),w._dmTable={columns:C,rows:p,slug:g,exportCfg:y,render(r){T.create("#"+f,{data:r,columns:C,search:n,sortable:t,exportable:o,pageSize:a,emptyMessage:e}),u&&_(m)}}})})(),(function(){const h=document.querySelectorAll("[data-form-inline]");if(!h.length||typeof F>"u")return;function w(t){const o=t&&t.logic;return!!(o&&(o.visibility||o.requirement))}function b(t,o){const a={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const u=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":u?"chooser":e.type,y={...e.formConfig||{}};y.span==="full"&&o&&(y.span=o);const f={type:g,required:w(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...y}};u&&(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)),a[e.name]=f}),a}function C(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 p(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 n(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;"}h.forEach(t=>{let o;try{o=JSON.parse(atob(t.dataset.formInline))}catch{return}const a=o.fields||[],e=o.settings||{},u=e.columns||1,g=e.layout||"stacked",y=a.some(i=>i.type==="page-break"),f=async i=>{try{const c=t.querySelector('[name="website"]'),s=t.querySelector('[name="_t"]'),l=Object.assign({},i);c!==null&&(l._hp=c.value),s!==null&&(l._t=s.value);const d=await H.post(`/api/forms/submit/${o.slug}`,l);if(d&&d.error){n(t,d.error,!0);const k=new Error(d.error);throw k.formSubmitFailed=!0,k}if(d?.redirect){window.location.href=d.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);n(t,d?.message||e.successMessage||"Thank you for your submission.",!1)}catch(c){throw c.formSubmitFailed||n(t,c.message||"Submission failed. Please try again.",!0),c}};function m(i){const c=i.querySelector("form");if(!c)return;const s=document.createElement("div");s.className="fb-form-honeypot",s.setAttribute("aria-hidden","true");const l=document.createElement("input");l.name="website",l.type="text",l.tabIndex=-1,l.autocomplete="url",l.placeholder="https://",s.appendChild(l);const d=document.createElement("input");d.name="_t",d.type="hidden",d.value=Date.now(),s.appendChild(d),c.appendChild(s)}function r(){if(!window.FormLogicEngine||!a.some(c=>c.logic))return null;const i=new window.FormLogicEngine.FormLogicRuntime(o,t);if(i.init(),t._formLogicRuntime=i,t._formLogicObserved)return i;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const c=new MutationObserver(function(s){for(const l of s)for(const d of l.removedNodes)if(d===t||d.nodeType===1&&d.contains&&d.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),c.disconnect();return}});c.observe(t.parentNode,{childList:!0,subtree:!1})}return i}if(y&&F.wizard){const i=[],c=[];let s=[],l=o.title||"Step 1",d="";const k=()=>{i.push({title:l,description:d,fields:b(s,u)}),c.push(s)};a.forEach(x=>{x.type==="page-break"?(k(),s=[],l=x.label||`Step ${i.length+1}`,d=x.description||""):x.type!=="spacer"&&s.push(x)}),k();let L=0,A=null;const N=x=>{const I=window.FormLogicEngine;if(!I||!I.validateFields)return;const D=I.validateFields(t,c[L]||[]);D.valid||(x.preventDefault(),x.stopImmediatePropagation(),B(t,D.missing),V(D))},q=()=>{p(t,a),z(t,a),e.honeypot!==!1&&m(t),A&&A.destroy(),A=r(),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(x=>x.addEventListener("click",N,!0))},j=F.wizard(t,{schema:{steps:i},onSubmit:f,onStepChange:x=>{L=x,setTimeout(q,0)}});Promise.resolve(j).then(q)}else if(F.render){const i=F.render(t,b(a,u),C(a),{submitText:e.submitText||"Submit",layout:g,columns:u,onSubmit:f});Promise.resolve(i).then(function(){if(g==="grid"&&e.submitSpan==="full"){const c=t.querySelector(".form-buttons");c&&c.classList.add("col-span-full")}p(t,a),z(t,a),e.honeypot!==!1&&m(t),r()})}}),$(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__||{},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";w.orientation==="vertical"&&x.get(0).classList.add("dm-nav-vertical",w.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),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"),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 d=o(w.items||[]);h.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(r=>{const u=d[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;")},m=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=m(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,m=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((d,r)=>{d.style.opacity="0",d.style.transform=f[a]||"",d.style.transition=`opacity ${o}ms ease, transform ${o}ms ease`;const u=h?y.length-1-r:r;d.style.transitionDelay=t==="stagger"?`${m+u*e}ms`:`${m}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const d=new IntersectionObserver(r=>{r.forEach(u=>{u.isIntersecting&&(u.target.offsetWidth,u.target.style.opacity="1",u.target.style.transform="none",d.unobserve(u.target))})},{threshold:.1});y.forEach(r=>d.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:m,toast:h,alert:y,prompt:f,...d}=e||{};m||h||y||f?($(a).on("click",async function(u){if(u.preventDefault(),m&&!await E.confirm(m))return;let c=null;if(!(f&&(c=await E.prompt(f,{inputPlaceholder:d.promptPlaceholder||"",inputValue:d.promptDefault||""}),c===null))){if(d.target){const s=$(d.target);d.toggleClass&&s.toggleClass(d.toggleClass),d.addClass&&s.addClass(d.addClass),d.removeClass&&s.removeClass(d.removeClass),c!==null&&(d.setText&&s.text(c),d.setVal&&s.val(c),d.setAttr&&s.attr(d.setAttr,c))}d.href&&(window.location.href=d.href),h&&E.toast(h,{type:d.toastType||"success"}),y&&E.alert(y)}}),Object.keys(d).length&&(t[a]={...o,events:{...o.events,click:d}})):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 m=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(m.ok){const{token:h}=await m.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 m=S.get("auth_refresh_token");if(m){const h=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:m})});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:m}=await o.json().catch(()=>({}));p.replaceChildren(C(m||"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:m,slug:h,exportCfg:y}=C;if(!k?.length)return;if(m){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-${m.style||"primary"} dm-cta-trigger`,s.dataset.action=m.action||"",s.dataset.entry=c._entryId||"",m.confirm&&(s.dataset.confirm=m.confirm),m.icon){const i=document.createElement("span");i.dataset.icon=m.icon,s.appendChild(i),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(m.label||"Run")),s}})}const f="col-table-"+Math.random().toString(36).slice(2,7),d=document.createElement("div");d.id=f,x.replaceChildren(d),T.create("#"+f,{data:p,columns:k,search:n,sortable:t,exportable:a,pageSize:o,emptyMessage:e}),m&&D(d),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}),m&&D(d)}}})})(),(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 m=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":m?"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}};m&&(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||{},m=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}},d=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=d,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,m)})),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:m,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,m),k(o),{submitText:e.submitText||"Submit",layout:h,columns:m,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()})})();
@@ -293,7 +293,8 @@ export async function formsRoutes(fastify) {
293
293
  settings: {
294
294
  submitText: 'Submit',
295
295
  successMessage: 'Thank you for your submission.',
296
- layout: 'stacked',
296
+ layout: 'grid',
297
+ columns: 2,
297
298
  honeypot: true,
298
299
  rateLimitPerMinute: 3,
299
300
  ...(body.settings || {})
@@ -124,8 +124,8 @@
124
124
  <script src="/public/js/collection-browser.js?v=20260523-browser"></script>
125
125
 
126
126
  <!-- Core Forms (logic engine must load before renderer) -->
127
- <script src="/public/js/form-logic-engine.js?v=20260821-wizard-steps"></script>
128
- <script src="/public/js/forms.js?v=20260821-wizard-steps" type="module"></script>
127
+ <script src="/public/js/form-logic-engine.js?v=20260821-wizard-grid"></script>
128
+ <script src="/public/js/forms.js?v=20260821-wizard-grid" type="module"></script>
129
129
 
130
130
  <!-- Core effects runtime -->
131
131
  <script src="/public/js/effects.js"></script>