domma-cms 0.76.0 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +1 -1
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +2 -2
- package/admin/js/lib/action-editor-arrange.js +1 -0
- package/admin/js/lib/api-endpoint-editor-arrange.js +2 -0
- package/admin/js/lib/block-editor-arrange.js +2 -0
- package/admin/js/lib/collection-editor-arrange.js +3 -0
- package/admin/js/lib/collection-entries-arrange.js +1 -0
- package/admin/js/lib/component-editor-arrange.js +27 -0
- package/admin/js/lib/context-menu-editor-arrange.js +1 -0
- package/admin/js/lib/dashboard-arrange.js +1 -0
- package/admin/js/lib/form-editor-arrange.js +1 -0
- package/admin/js/lib/form-submissions-arrange.js +2 -0
- package/admin/js/lib/menu-editor-arrange.js +2 -0
- package/admin/js/lib/page-editor-arrange.js +1 -0
- package/admin/js/lib/plugin-code-arrange.js +1 -0
- package/admin/js/lib/project-page-arrange.js +1 -0
- package/admin/js/lib/role-editor-arrange.js +3 -0
- package/admin/js/lib/user-editor-arrange.js +1 -0
- package/admin/js/lib/view-editor-arrange.js +14 -0
- package/admin/js/templates/action-editor.html +223 -147
- package/admin/js/templates/api-endpoint-editor.html +172 -117
- package/admin/js/templates/block-editor.html +194 -203
- package/admin/js/templates/collection-editor.html +191 -113
- package/admin/js/templates/collection-entries.html +99 -36
- package/admin/js/templates/component-editor.html +128 -126
- package/admin/js/templates/context-menu-editor.html +208 -148
- package/admin/js/templates/dashboard.html +184 -22
- package/admin/js/templates/form-editor.html +41 -26
- package/admin/js/templates/form-submissions.html +78 -26
- package/admin/js/templates/menu-editor.html +57 -17
- package/admin/js/templates/menu-locations.html +54 -11
- package/admin/js/templates/page-editor.html +47 -26
- package/admin/js/templates/plugin-code.html +91 -73
- package/admin/js/templates/project-detail.html +83 -145
- package/admin/js/templates/project-settings.html +88 -53
- package/admin/js/templates/role-editor.html +158 -83
- package/admin/js/templates/user-editor.html +150 -14
- package/admin/js/templates/view-editor.html +203 -180
- package/admin/js/templates/view-preview.html +45 -45
- package/admin/js/views/action-editor.js +7 -1
- package/admin/js/views/api-endpoint-editor.js +2 -3
- package/admin/js/views/block-editor.js +14 -8
- package/admin/js/views/collection-editor.js +64 -5
- package/admin/js/views/collection-entries.js +50 -1
- package/admin/js/views/component-editor.js +2 -28
- package/admin/js/views/context-menu-editor.js +54 -55
- package/admin/js/views/dashboard.js +7 -1
- package/admin/js/views/form-editor.js +7 -7
- package/admin/js/views/form-submissions.js +11 -1
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/login.js +2 -2
- package/admin/js/views/menu-editor.js +21 -43
- package/admin/js/views/menu-locations.js +16 -1
- package/admin/js/views/page-editor.js +26 -26
- package/admin/js/views/plugin-code.js +23 -4
- package/admin/js/views/project-detail.js +9 -1
- package/admin/js/views/project-settings.js +1 -1
- package/admin/js/views/role-editor.js +11 -3
- package/admin/js/views/user-editor.js +1 -1
- package/admin/js/views/view-editor.js +1 -1
- package/admin/js/views/view-preview.js +1 -1
- package/package.json +1 -1
- package/server/routes/api/dashboard.js +32 -4
- package/server/routes/api/forms.js +104 -13
- package/server/routes/api/users.js +12 -2
- package/server/routes/api/views.js +55 -1
- package/server/services/components.js +9 -0
- package/server/services/users.js +2 -2
- package/server/services/views.js +14 -0
- package/admin/js/templates/dashboard/activity-feed.html +0 -3
- package/admin/js/templates/dashboard/cache.html +0 -32
- package/admin/js/templates/dashboard/health-detail.html +0 -2
- package/admin/js/templates/dashboard/journeys.html +0 -17
- package/admin/js/templates/dashboard/kpi-strip.html +0 -34
- package/admin/js/templates/dashboard/spike-feed.html +0 -3
- package/admin/js/templates/dashboard/top-pages.html +0 -3
- package/admin/js/templates/dashboard/traffic-chart.html +0 -3
- package/admin/js/views/block-editor-enhance.js +0 -1
- package/admin/js/views/dashboard/lib/escape.js +0 -1
- package/admin/js/views/dashboard/widgets/activity-feed.js +0 -1
- package/admin/js/views/dashboard/widgets/cache.js +0 -1
- package/admin/js/views/dashboard/widgets/health-detail.js +0 -1
- package/admin/js/views/dashboard/widgets/journeys.js +0 -1
- package/admin/js/views/dashboard/widgets/kpi-strip.js +0 -1
- package/admin/js/views/dashboard/widgets/spike-feed.js +0 -6
- package/admin/js/views/dashboard/widgets/top-pages.js +0 -1
- package/admin/js/views/dashboard/widgets/traffic-chart.js +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{apiRequest as
|
|
2
|
-
`).filter(
|
|
3
|
-
`).filter(b=>b.trim()).map(b=>{const[y,...u]=b.split(":");return{value:y.trim(),label:u.join(":").trim()||y.trim()}});t.cascade={sourceField:m,mapping:f,defaultOptions:h},l=!0}}return l?t:void 0}function B(){v=v.map((e,n)=>ze(n))}let D=null;function Be(e,n,a){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=>{D=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=>{D!=null&&(o.preventDefault(),o.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(i=>i.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"),D==null||D===n){D=null;return}B();const[i]=v.splice(D,1);v.splice(n,0,i),D=null,O(a)})}function O(e){const n=e.find("#fields-list").get(0),a=e.find("#fields-empty-msg").get(0);if(n){if(Array.from(n.querySelectorAll(".fb-field-card")).forEach(t=>t.remove()),v.length===0){a&&(a.style.display=""),te();return}a&&(a.style.display="none"),v.forEach((t,l)=>{const o=t.type==="page-break"?Re(t,l,e):t.type==="spacer"?Oe(t,l,e):_e(t,l,e);Be(o,l,e),n.appendChild(o)}),te()}}function Re(e,n,a){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 i=document.createElement("span");i.textContent=e.label||"Untitled Step",i.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(),s.style.display=s.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?")&&(B(),v.splice(n,1),O(a))}),r.appendChild(d),l.appendChild(o),l.appendChild(i),l.appendChild(r),l.addEventListener("click",()=>{s.style.display=s.style.display==="none"?"":"none"});const s=document.createElement("div");s.className="fb-field-body",s.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border,#444);display:none;";const p=N([q("Step Title",`fb-pb-label-${n}`,"text",e.label||"","Shown as the wizard step heading"),q("Step Description",`fb-pb-desc-${n}`,"text",e.description||"","Optional sub-heading")]),m=p.querySelector(`#fb-pb-label-${n}`);return m&&m.addEventListener("input",()=>{i.textContent=m.value||"Untitled Step"}),s.appendChild(p),t.appendChild(l),t.appendChild(s),t}function Oe(e,n,a){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 i=document.createElement("span");i.textContent="Spacer",i.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 s=>{s.stopPropagation(),B(),v.splice(n,1),O(a)}),c.appendChild(d),l.appendChild(o),l.appendChild(i),l.appendChild(r),l.appendChild(c),t.appendChild(l),t}function _e(e,n,a){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=me(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 i=document.createElement("span");i.textContent=e.label||"(unlabelled)",i.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(),s.style.display=s.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?")&&(B(),v.splice(n,1),O(a))}),r.appendChild(d),l.appendChild(o),l.appendChild(i),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(fe(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",()=>{s.style.display=s.style.display==="none"?"":"none"});const s=De(e,n,i);return s.style.display="none",t.appendChild(l),t.appendChild(s),t}function De(e,n,a){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=N([q("Label",`fb-label-${n}`,"text",e.label||"","Shown above the field"),q("Field Name",`fb-name-${n}`,"text",e.name||"","Used as data key")]),o=N([at("Type",`fb-type-${n}`,ce,e.type||"string"),Ne("Required",`fb-required-${n}`,e.required||!1)]),i=N([q("Placeholder",`fb-placeholder-${n}`,"text",e.placeholder||"","Hint text inside the field")]),r=N([q("Helper Text",`fb-helper-${n}`,"text",e.helper||"","Shown below the field"),q("Tooltip",`fb-tooltip-${n}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),c=e.formConfig?.span,d=N([q("Column Span",`fb-span-${n}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),Ne("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(i),t.appendChild(r),t.appendChild(d);const s=t.querySelector(`#fb-label-${n}`),p=t.querySelector(`#fb-name-${n}`);s&&s.addEventListener("input",()=>{a&&(a.textContent=s.value||"(unlabelled)"),p&&!p.dataset.manuallyEdited&&(p.value=pe(s.value))}),p&&p.addEventListener("input",()=>{p.dataset.manuallyEdited="1"});const m=t.querySelector(`#fb-type-${n}`);m&&m.addEventListener("change",()=>{const h=t.closest(".fb-field-card");if(h){const u=h.querySelector("span");u&&(u.textContent=me(m.value))}const b=t.querySelector(".fb-field-extras");b&&b.remove();const y=we(m.value,e,n);y&&t.appendChild(y)});const f=we(e.type,e,n);return f&&t.appendChild(f),t.appendChild(Ge(e,n)),t.appendChild(Ye(e,n)),t}const G=[{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"}],ne=new Set(["is_empty","is_not_empty"]),be={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 le(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function H(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 W(e,n,a,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 i=document.createElement("span");i.textContent="When",i.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(h=>{const b=document.createElement("option");b.value=h.value,b.textContent=h.label,e&&h.value===e.field&&(b.selected=!0),r.appendChild(b)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",G.forEach(h=>{const b=document.createElement("option");b.value=h.value,b.textContent=h.label,e&&h.value===e.operator&&(b.selected=!0),c.appendChild(b)});const d=()=>{const h=n.find(b=>b.value===r.value);Array.from(c.options).forEach(b=>{const y=G.find(u=>u.value===b.value);b.textContent=h?.multi&&be[b.value]||y?.label||b.value})};d(),r.addEventListener("change",d);const s=document.createElement("input");s.type="text",s.className="form-input fb-logic-cond-val",s.placeholder="value",s.style.cssText="flex:1 1 120px;min-width:100px;",s.value=e?.value||"",e&&ne.has(e.operator)&&(s.style.display="none"),c.addEventListener("change",()=>{s.style.display=ne.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 ${t}`,m.style.cssText="flex:1 1 140px;min-width:120px;",a.forEach(h=>{const b=document.createElement("option");b.value=h.value,b.textContent=h.label,h.value===l&&(b.selected=!0),m.appendChild(b)});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(i),o.appendChild(r),o.appendChild(c),o.appendChild(s),o.appendChild(p),o.appendChild(m),o.appendChild(f),o}function Me(e,n,a){const t=document.createElement("div");t.dataset.logicSection="visibility",t.appendChild(H("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 i=document.createElement("select");i.className="form-select fb-logic-vis-default",i.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(u=>{const g=document.createElement("option");g.value=u.value,g.textContent=u.label,u.value===(e.default||"visible")&&(g.selected=!0),i.appendChild(g)}),l.appendChild(o),l.appendChild(i),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 g=document.createElement("option");g.value=u.value,g.textContent=u.label,u.value===(e.transition||"none")&&(g.selected=!0),d.appendChild(g)}),r.appendChild(c),r.appendChild(d),t.appendChild(r);const s=document.createElement("div");s.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 g=document.createElement("option");g.value=u.value,g.textContent=u.label,u.value===String(e.duration??"")&&(g.selected=!0),m.appendChild(g)}),s.appendChild(p),s.appendChild(m),t.appendChild(s);const f=()=>{s.style.display=d.value==="none"?"none":""};f(),d.addEventListener("change",f);const h=document.createElement("div");h.className="fb-logic-vis-rules";const b=a.map(u=>({value:u.name,label:u.label||u.name,multi:le(u)})),y=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(u=>{const g=(u.when?.all||u.when?.any||[])[0],x=u.then==="hidden"?"hidden":"visible";b.length>0&&h.appendChild(W(g,b,y,"fb-logic-vis-then",x))}),t.appendChild(h),b.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;",_(u,"plus","Add visibility rule"),u.addEventListener("click",()=>h.appendChild(W(null,b,y,"fb-logic-vis-then","visible"))),t.appendChild(u)}return t}function Pe(e,n,a){const t=document.createElement("div");t.dataset.logicSection="requirement",t.appendChild(H("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 i=document.createElement("div");i.className="fb-logic-req-rules";const r=a.map(d=>({value:d.name,label:d.label||d.name,multi:le(d)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(d=>{const s=(d.when?.all||d.when?.any||[])[0],p=d.then===!0?"true":"false";r.length>0&&i.appendChild(W(s,r,c,"fb-logic-req-then",p))}),t.appendChild(i),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;",_(d,"plus","Add requirement rule"),d.addEventListener("click",()=>i.appendChild(W(null,r,c,"fb-logic-req-then","true"))),t.appendChild(d)}return t}function he(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 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 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"),a.addEventListener("change",()=>{l.style.display=a.value==="match"?"none":"",t.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 i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="line-height:1;opacity:.6;",w(i,"x"),i.style.flexShrink="0",i.addEventListener("click",()=>n.remove()),n.appendChild(a),n.appendChild(t),n.appendChild(l),n.appendChild(o),n.appendChild(i),n}function je(e,n,a){const t=document.createElement("div");t.dataset.logicSection="validation",t.appendChild(H("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(i=>l.appendChild(he(i))),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;",_(o,"plus","Add validation rule"),o.addEventListener("click",()=>l.appendChild(he(null))),t.appendChild(o),t}function Ve(e,n,a){const t=document.createElement("div");t.dataset.logicSection="cascade",t.appendChild(H("Cascade Options")),t.lastChild.appendChild(ee("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 i=document.createElement("select");i.className="form-select fb-logic-cascade-source",i.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",i.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),i.appendChild(f)}),l.appendChild(o),l.appendChild(i),t.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(ee(`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 s=document.createElement("p");s.textContent="Default options (one per line: value:Label)",s.appendChild(ee("Shown before the source field has a value, or when its value has no mapping entry.")),s.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
|
-
option2:Option 2`,
|
|
5
|
-
`),t.appendChild(s),t.appendChild(p),t}function Ge(e,n){const a=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 i=document.createElement("span");i.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted,#888);",i.textContent="\u26A1 Conditional Logic";const r=fe(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(i),o.appendChild(c),l.appendChild(o),d.appendChild(Me(a.visibility||{},n,t)),d.appendChild(Pe(a.requirement||{},n,t)),d.appendChild(je(a.validation||[],n,t));const s=document.getElementById(`fb-type-${n}`)?.value||e.type;return Q.has(s)&&d.appendChild(Ve(a.cascade||{},n,t)),l.appendChild(d),l}const U=[{value:"banner",label:"Show a banner",kind:"state",params:["message","level","position","dismissible"]},{value:"toast",label:"Show a toast",kind:"event",params:["message","level"]},{value:"hide-fields",label:"Hide fields",kind:"state",params:["target"]},{value:"disable-fields",label:"Disable fields",kind:"state",params:["target"]},{value:"require-fields",label:"Make fields required",kind:"state",params:["target"]},{value:"block-submit",label:"Block submission",kind:"state",params:["message"]},{value:"goto-step",label:"Jump to a wizard step",kind:"event",params:["step"]},{value:"redirect",label:"Redirect after submit",kind:"event",params:["url"]},{value:"celebrate",label:"Celebrate",kind:"event",params:["theme","intensity"]},{value:"run-action",label:"Run a CMS action",kind:"event",params:["slug"]}],He=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],We=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],Ue=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],Je=[{value:"auto",label:"Whatever is in season"},{value:"christmas",label:"Christmas"},{value:"halloween",label:"Halloween"},{value:"valentines",label:"Valentine's Day"},{value:"guy-fawkes",label:"Guy Fawkes Night"},{value:"st-patricks",label:"St Patrick's Day"},{value:"st-andrews",label:"St Andrew's Day"},{value:"st-davids",label:"St David's Day"},{value:"st-georges",label:"St George's Day"}];function ge(e){return v.map((n,a)=>({field:n,i:a})).filter(({field:n,i:a})=>a!==e&&n.type!=="page-break"&&n.type!=="spacer"&&n.name).map(({field:n})=>({value:n.name,label:n.label||n.name,multi:le(n)}))}function I(e,n,a,t){const l=document.createElement("select");return l.className=`form-select ${e}`,t&&(l.style.cssText=t),n.forEach(o=>{const i=document.createElement("option");i.value=o.value,i.textContent=o.label,o.value===a&&(i.selected=!0),l.appendChild(i)}),l}function J(e,n,a,t){const l=document.createElement("input");return l.type="text",l.className=`form-input ${e}`,l.value=n==null?"":String(n),a&&(l.placeholder=a),t&&(l.style.cssText=t),l}function ae(e,n){const a=document.createElement("button");return a.type="button",a.className="btn btn-xs btn-ghost",a.style.cssText="line-height:1;opacity:.6;flex-shrink:0;",n&&(a.title=n),w(a,"x"),a.addEventListener("click",e),a}function ye(e,n){const a=document.createElement("div");a.className="fb-trig-cond-row",a.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.5rem;flex-wrap:wrap;";const t=I("fb-trig-cond-field",n,e?.field,"flex:1 1 140px;min-width:130px;"),l=I("fb-trig-cond-op",G,e?.operator,"flex:1 1 150px;min-width:130px;"),o=J("fb-trig-cond-val",e?.value,"value","flex:1 1 110px;min-width:90px;"),i=()=>{const c=n.find(d=>d.value===t.value);Array.from(l.options).forEach(d=>{const s=G.find(p=>p.value===d.value);d.textContent=c?.multi&&be[d.value]||s?.label||d.value})},r=()=>{o.style.display=ne.has(l.value)?"none":""};return i(),r(),t.addEventListener("change",i),l.addEventListener("change",r),a.appendChild(t),a.appendChild(l),a.appendChild(o),a.appendChild(ae(()=>a.remove(),"Remove condition")),a}function ve(e,n){const a=document.createElement("div");a.className="fb-trig-params",a.style.cssText="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;flex:1 1 100%;margin:.35rem 0 0 .25rem;";const t=U.find(l=>l.value===(e.type||"banner"));if(!t)return a;for(const l of t.params)switch(l){case"message":a.appendChild(J("fb-trig-p-message",e.message,"Message shown to the visitor","flex:2 1 260px;"));break;case"level":a.appendChild(I("fb-trig-p-level",He,e.level||"info","flex:1 1 120px;"));break;case"position":a.appendChild(I("fb-trig-p-position",We,e.position||"field-below","flex:1 1 150px;"));break;case"dismissible":{const o=document.createElement("label");o.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.78rem;flex-shrink:0;";const i=document.createElement("input");i.type="checkbox",i.className="form-check fb-trig-p-dismissible",i.checked=e.dismissible!==!1,o.appendChild(i),o.appendChild(document.createTextNode("Dismissible")),a.appendChild(o);break}case"target":{const o=I("fb-trig-p-target",Ue,e.target||(e.fields?.length?"listed":"rest"),"flex:1 1 170px;"),i=document.createElement("select");i.className="form-select fb-trig-p-fields",i.multiple=!0,i.size=4,i.style.cssText="flex:2 1 200px;";const r=new Set(e.fields||[]);ge(n).forEach(d=>{const s=document.createElement("option");s.value=d.value,s.textContent=d.label,r.has(d.value)&&(s.selected=!0),i.appendChild(s)});const c=()=>{i.style.display=o.value==="listed"?"":"none"};c(),o.addEventListener("change",c),a.appendChild(o),a.appendChild(i);break}case"step":{const o=J("fb-trig-p-step",e.step,"0","flex:0 0 90px;");o.type="number",o.min="0",a.appendChild(o);const i=document.createElement("span");i.textContent="Step number, counting from 0",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted,#888);",a.appendChild(i);break}case"url":a.appendChild(J("fb-trig-p-url",e.url,"/thank-you","flex:2 1 220px;"));break;case"theme":a.appendChild(I("fb-trig-p-theme",Je,e.theme||"auto","flex:1 1 180px;"));break;case"intensity":a.appendChild(I("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium","flex:0 1 120px;"));break;case"slug":{const o=[{value:"",label:X.length?"Choose an action":"No actions available"}].concat(X.map(i=>({value:i.slug,label:i.title||i.slug})));a.appendChild(I("fb-trig-p-slug",o,e.slug||"","flex:2 1 200px;"));break}default:break}if(t.kind==="event"){const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.78rem;flex-shrink:0;";const o=document.createElement("input");o.type="checkbox",o.className="form-check fb-trig-p-once",o.checked=!!e.once,l.appendChild(o),l.appendChild(document.createTextNode("Only once")),l.title="Fire the first time only, rather than every time the answer swings back.",a.appendChild(l)}return a}function xe(e,n){const a=document.createElement("div");a.className="fb-trig-action-row",a.style.cssText="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;padding:.45rem .5rem;margin-bottom:.4rem;border:1px solid var(--dm-border,#333);border-radius:var(--dm-radius-md,4px);";const t=I("fb-trig-action-type",U,e.type||"banner","flex:1 1 190px;"),l=document.createElement("span");l.className="fb-trig-kind",l.style.cssText="font-size:.7rem;color:var(--dm-text-muted,#888);flex-shrink:0;";const o=ve(e,n),i=()=>{const r=U.find(c=>c.value===t.value);l.textContent=r?.kind==="event"?"fires once when it becomes true":"applies while it is true"};return i(),t.addEventListener("change",()=>{i();const r=ve({type:t.value},n);a.replaceChild(r,a.querySelector(".fb-trig-params")),window.I?.scan?.()}),a.appendChild(t),a.appendChild(l),a.appendChild(ae(()=>a.remove(),"Remove action")),a.appendChild(o),a}function Ce(e,n,a,t){const l=document.createElement("div");l.className="fb-trig-branch",l.dataset.branch=e,l.style.cssText="margin-top:.6rem;";const o=document.createElement("p");o.textContent=n,o.style.cssText="font-size:.73rem;font-weight:700;color:var(--dm-text-muted,#888);margin:0 0 .4rem;text-transform:uppercase;letter-spacing:.05em;",l.appendChild(o);const i=document.createElement("div");i.className="fb-trig-action-list",(a||[]).forEach(c=>i.appendChild(xe(c,t))),l.appendChild(i);const r=document.createElement("button");return r.type="button",r.className="btn btn-xs btn-ghost",_(r,"plus","Add action",12),r.addEventListener("click",()=>{i.appendChild(xe({type:"banner"},t)),window.I?.scan?.()}),l.appendChild(r),l}function Ee(e,n,a){const t=ge(n),l=document.createElement("div");l.className="fb-trig-card",l.dataset.triggerId=e.id||`trg-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,l.style.cssText="border:1px solid var(--dm-border,#333);border-radius:var(--dm-radius-md,4px);padding:.65rem .7rem;margin-bottom:.7rem;";const o=document.createElement("div");o.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.5rem;";const i=document.createElement("span");i.textContent=`Trigger ${a+1}`,i.style.cssText="font-size:.78rem;font-weight:600;",o.appendChild(i);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.5rem;";const c=document.createElement("label");c.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.75rem;cursor:pointer;";const d=document.createElement("input");if(d.type="checkbox",d.className="form-check fb-trig-enabled",d.checked=e.enabled!==!1,c.appendChild(d),c.appendChild(document.createTextNode("Enabled")),r.appendChild(c),r.appendChild(ae(()=>l.remove(),"Remove trigger")),o.appendChild(r),l.appendChild(o),!t.length){const b=document.createElement("p");return b.textContent="Add another field first - a trigger tests an answer, and this is the only field so far.",b.style.cssText="font-size:.78rem;color:var(--dm-text-muted,#888);margin:0;",l.appendChild(b),l}const s=document.createElement("div");s.style.cssText="display:flex;align-items:center;gap:.45rem;margin-bottom:.45rem;flex-wrap:wrap;";const p=document.createElement("span");p.textContent="When",p.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted,#888);",s.appendChild(p),s.appendChild(I("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all","flex:0 1 200px;")),l.appendChild(s);const m=document.createElement("div");m.className="fb-trig-cond-list";const f=e.when?.all||e.when?.any||[];(f.length?f:[{}]).forEach(b=>m.appendChild(ye(b,t))),l.appendChild(m);const h=document.createElement("button");return h.type="button",h.className="btn btn-xs btn-ghost",_(h,"plus","Add condition",12),h.addEventListener("click",()=>{m.appendChild(ye({},t)),window.I?.scan?.()}),l.appendChild(h),l.appendChild(Ce("then","Then",e.then,n)),l.appendChild(Ce("otherwise","Otherwise (optional)",e.otherwise,n)),l}function Ye(e,n){const a=Array.isArray(e.triggers)?e.triggers:[],t=document.createElement("div");t.className="fb-field-triggers",t.style.cssText="margin-top:.5rem;border-top:1px solid var(--dm-border,#333);padding-top:.5rem;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const o=document.createElement("span");o.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted,#888);",o.textContent=`\u{1F3AF} Triggers${a.length?` (${a.length})`:""}`;const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",w(i,a.length?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-triggers-body",r.style.cssText="padding:.35rem 0;"+(a.length?"":"display:none;"),l.addEventListener("click",()=>{const p=r.style.display==="none";r.style.display=p?"":"none",w(i,p?"chevron-down":"chevron-right",12)});const c=document.createElement("p");c.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, jump to a step, or celebrate.",c.style.cssText="font-size:.75rem;color:var(--dm-text-muted,#888);margin:0 0 .6rem;",r.appendChild(c);const d=document.createElement("div");d.className="fb-trig-list",a.forEach((p,m)=>d.appendChild(Ee(p,n,m))),r.appendChild(d);const s=document.createElement("button");return s.type="button",s.className="btn btn-xs btn-ghost",_(s,"plus","Add trigger",12),s.addEventListener("click",()=>{d.appendChild(Ee({enabled:!0,then:[{type:"banner"}]},n,d.children.length)),window.I?.scan?.()}),r.appendChild(s),l.appendChild(o),l.appendChild(i),t.appendChild(l),t.appendChild(r),t}function Ke(e){const n=e.querySelector(".fb-trig-action-type")?.value,a=U.find(o=>o.value===n);if(!a)return null;const t={type:n},l=o=>e.querySelector(o)?.value?.trim()||"";for(const o of a.params)switch(o){case"message":t.message=l(".fb-trig-p-message");break;case"level":t.level=l(".fb-trig-p-level")||"info";break;case"position":t.position=l(".fb-trig-p-position")||"field-below";break;case"dismissible":t.dismissible=!!e.querySelector(".fb-trig-p-dismissible")?.checked;break;case"target":{const i=l(".fb-trig-p-target")||"rest";t.target=i,i==="listed"&&(t.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(r=>r.selected).map(r=>r.value));break}case"step":{const i=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(i)&&(t.step=i);break}case"url":t.url=l(".fb-trig-p-url");break;case"theme":t.theme=l(".fb-trig-p-theme")||"auto";break;case"intensity":t.intensity=l(".fb-trig-p-intensity")||"medium";break;case"slug":t.slug=l(".fb-trig-p-slug");break;default:break}return a.kind==="event"&&e.querySelector(".fb-trig-p-once")?.checked&&(t.once=!0),a.params.includes("message")&&!t.message&&a.value!=="block-submit"||n==="redirect"&&!t.url||n==="run-action"&&!t.slug?null:t}function Qe(e){const a=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!a)return;const t=[];return a.querySelectorAll(".fb-trig-card").forEach(l=>{const o=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(p=>{const m=p.querySelector(".fb-trig-cond-field")?.value,f=p.querySelector(".fb-trig-cond-op")?.value;if(!m||!f)return null;const h=p.querySelector(".fb-trig-cond-val")?.value??"";return{field:m,operator:f,value:h}}).filter(Boolean);if(!o.length)return;const i=p=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${p}"] .fb-trig-action-row`)).map(Ke).filter(Boolean),r=i("then"),c=i("otherwise");if(!r.length&&!c.length)return;const d=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",s={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[d]:o}};r.length&&(s.then=r),c.length&&(s.otherwise=c),t.push(s)}),t.length?t:void 0}function we(e,n,a){const t=document.createElement("div");return t.className="fb-field-extras",e==="chooser"?(t.appendChild(Xe(n,a)),t.appendChild(et(n.options||[],a))):(Q.has(e)&&t.appendChild(ot(n.options||[],a)),e==="textarea"&&t.appendChild(N([q("Rows",`fb-rows-${a}`,"number",n.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&t.appendChild(N([q("Min Length",`fb-minlength-${a}`,"number",n.minLength||"",""),q("Max Length",`fb-maxlength-${a}`,"number",n.maxLength||"","")])),e==="number"&&t.appendChild(N([q("Min",`fb-min-${a}`,"number",n.min??"",""),q("Max",`fb-max-${a}`,"number",n.max??"","")]))),t.children.length?t:null}function ke(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 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,n.appendChild(a);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 Y(e,n,a,t,l){const o=document.createElement("div");o.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=n,i.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",t.forEach(([c,d])=>{const s=document.createElement("option");s.value=c,s.textContent=d,String(c)===String(a)&&(s.selected=!0),r.appendChild(s)}),o.appendChild(i),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 Se(e,n,a,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 i=document.createElement("input");if(i.id=e,i.type="checkbox",i.checked=!!a,o.appendChild(i),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 oe(e,n,a,t,l){const o=document.createElement("div");o.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=n,i.style.fontSize=".8rem",o.appendChild(i);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||"",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 s=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(d.value=s?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 Xe(e,n){const a=document.createElement("div");a.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const t=ke("Layout");t.body.appendChild(N([Y(`fb-chooser-variant-${n}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),Se(`fb-chooser-multiple-${n}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),t.body.appendChild(N([Y(`fb-chooser-density-${n}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),q("Columns",`fb-chooser-columns-${n}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),a.appendChild(t.wrap);const l=ke("Visual");return l.body.appendChild(N([oe(`fb-chooser-accent-${n}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),Y(`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(N([Se(`fb-chooser-glow-${n}`,"Glow on selected",!!e.glow,"Soft outer glow."),oe(`fb-chooser-glow-colour-${n}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(N([Y(`fb-chooser-shadow-${n}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),oe(`fb-chooser-shadow-colour-${n}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),a.appendChild(l.wrap),a}function Ze(e,n,a,t){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 i=document.createElement("div");i.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",T=>{T.preventDefault(),Te(n,a,-1,t)});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",T=>{T.preventDefault(),Te(n,a,1,t)}),i.appendChild(r),i.appendChild(c),o.appendChild(i);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 s=document.createElement("input");s.type="text",s.className="form-input fb-chooser-opt-label",s.placeholder="label (visible to users)",s.value=e.label||"",s.style.flex="2",o.appendChild(s);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",T=>{T.preventDefault(),lt(n,a,t)}),o.appendChild(p),l.appendChild(o);const m=document.createElement("div");m.style.cssText="display:flex; gap:.4rem;";const f=Ae("icon name (optional)",e.icon||"");f.input.classList.add("fb-chooser-opt-icon"),f.el.style.flex="1",m.appendChild(f.el);const h=document.createElement("input");h.type="text",h.className="form-input fb-chooser-opt-description",h.placeholder="description (card + comfortable only)",h.value=e.description||"",h.style.flex="2",m.appendChild(h),l.appendChild(m);const b=document.createElement("div");b.style.cssText="display:flex; gap:.4rem;";const y=document.createElement("input");y.type="text",y.className="form-input fb-chooser-opt-tooltip",y.placeholder="tooltip (hover hint)",y.value=e.tooltip||"",y.style.flex="2",b.appendChild(y);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",b.appendChild(u);const g=document.createElement("select");g.className="form-input fb-chooser-opt-badge-type",g.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([T,L])=>{const z=document.createElement("option");z.value=T,z.textContent=L,(e.badge?.type||"")===T&&(z.selected=!0),g.appendChild(z)}),b.appendChild(g),l.appendChild(b);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 k=document.createElement("label");k.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const A=document.createElement("input");return A.type="checkbox",A.className="fb-chooser-opt-disabled",A.checked=!!e.disabled,k.appendChild(A),k.appendChild(document.createTextNode(" Disabled")),x.appendChild(k),l.appendChild(x),l}function et(e,n){const a=document.createElement("div");a.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",_(o,"plus","Add option"),t.appendChild(o),a.appendChild(t);const i=document.createElement("div");i.className="fb-chooser-options-list",i.id=`fb-chooser-options-${n}`,i.style.cssText="display:flex; flex-direction:column; gap:.4rem;",a.appendChild(i);const r=()=>{i.replaceChildren();const c=tt(n);(c.length?c:e||[]).forEach((s,p)=>{i.appendChild(Ze(s,n,p,r))})};return o.addEventListener("click",c=>{c.preventDefault(),nt(n,r)}),r(),a}function tt(e){const n=v[e];return!n||!Array.isArray(n.options)?[]:n.options}function ie(e){return v[e]?(Array.isArray(v[e].options)||(v[e].options=[]),v[e].options):[]}function nt(e,n){K(e),ie(e).push({value:"new",label:"New option"}),n()}function lt(e,n,a){K(e),ie(e).splice(n,1),a()}function Te(e,n,a,t){K(e);const l=ie(e),o=n+a;if(o<0||o>=l.length)return;const[i]=l.splice(n,1);l.splice(o,0,i),t()}function K(e){const n=document.getElementById(`fb-chooser-options-${e}`);if(!n)return;const a=n.querySelectorAll(".fb-chooser-option-row"),t=[];a.forEach(l=>{const o={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},i=l.querySelector(".fb-chooser-opt-icon")?.value.trim();i&&(o.icon=i);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(),s=l.querySelector(".fb-chooser-opt-badge-type")?.value;(d||s)&&(o.badge={},d&&(o.badge.text=d),s&&(o.badge.type=s)),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 N(e){const n=document.createElement("div");return n.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(a=>{a&&n.appendChild(a)}),n}function q(e,n,a,t,l){const o=document.createElement("div");o.style.flex="1";const i=document.createElement("label");i.htmlFor=n,i.className="form-label",i.textContent=e,i.style.fontSize=".8rem";const r=document.createElement("input");if(r.id=n,r.type=a||"text",r.className="form-input",r.value=t??"",o.appendChild(i),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 at(e,n,a,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 i=document.createElement("select");return i.id=n,i.className="form-select",a.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===t&&(c.selected=!0),i.appendChild(c)}),l.appendChild(o),l.appendChild(i),l}function Ne(e,n,a){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=a,l.appendChild(o),l.appendChild(document.createTextNode(e)),t.appendChild(l),t}function ot(e,n){const a=document.createElement("div");a.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
|
|
1
|
+
import{apiRequest as oe}from"/admin/js/api.js";import{makeIconInput as qt}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as Ye}from"/public/js/forms.js";import{buildWizardSteps as $t}from"/public/js/form-steps.mjs";import{addBannerAction as Te}from"../lib/plugin-chrome.js";import{helpPopovers as At}from"../lib/help-popover.js";import{openMenuAt as Qe,sidebarCount as Ft}from"../lib/tool-kit.js";import{draftKey as ie,draftOf as It,duplicateField as zt,fieldTitle as Ne,fingerprint as Xe,leavingEditor as Ze,moveField as et,restoreDraft as Bt,snapshotOf as Le}from"../lib/form-editor-arrange.js";const tt=[{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"}],qe=new Set(["select","radio","checkbox-group","chooser"]);let C=[],$e=[],T=null,pe=null,ne=null,me={};function L(e,n,o=14){e.textContent="";const t=document.createElement("span");return t.setAttribute("data-icon",n),t.setAttribute("data-icon-size",String(o)),t.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(t),window.I?.scan?.(e),e}function le(e,n,o,t=14){return L(e,n,t),e.appendChild(document.createTextNode(" "+o)),e}function Ae(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 ue=null,nt=null,Fe=null,se=null;function Ie(){Fe?.(),clearTimeout(nt),nt=setTimeout(()=>{ue&&ue()},350)}function lt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function at(e){return tt.find(n=>n.value===e)?.label||e}function ot(e){return(e||[]).some(n=>n.logic||Array.isArray(n.triggers)&&n.triggers.length)}function it(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function Dt(e){const n={...C[e]};if(n.type==="spacer")return n;if(n.type==="page-break"){const u=document.getElementById(`fb-pb-label-${e}`),x=document.getElementById(`fb-pb-desc-${e}`);return u&&(n.label=u.value.trim()||n.label),x&&(n.description=x.value.trim()),n}const o=document.getElementById(`fb-label-${e}`),t=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),a=document.getElementById(`fb-required-${e}`),i=document.getElementById(`fb-placeholder-${e}`),s=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(o&&(n.label=o.value.trim()||n.label),t&&(n.name=t.value.trim()||n.name),l&&(n.type=l.value||n.type),a&&(n.required=a.checked),i&&(n.placeholder=i.value.trim()),s&&(n.helper=s.value.trim()),c&&(n.tooltip=c.value.trim()),n.type==="chooser"){const u=document.getElementById(`fb-chooser-variant-${e}`)?.value;u&&(n.variant=u);const x=document.getElementById(`fb-chooser-multiple-${e}`);x&&(n.multiple=x.checked);const N=document.getElementById(`fb-chooser-density-${e}`)?.value;N&&(n.density=N);const q=document.getElementById(`fb-chooser-columns-${e}`)?.value;q!==""&&q!==void 0&&(n.columns=parseInt(q,10)||3);const V=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();V?n.accent=V:delete n.accent;const _=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;_?n.accentStyle=_:delete n.accentStyle;const j=document.getElementById(`fb-chooser-glow-${e}`);j&&(n.glow=j.checked);const $=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();$?n.glowColour=$:delete n.glowColour;const Y=document.getElementById(`fb-chooser-shadow-${e}`)?.value;Y&&Y!=="none"?n.shadow=Y:delete n.shadow;const W=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();W?n.shadowColour=W:delete n.shadowColour,xe(e),C[e]&&Array.isArray(C[e].options)&&(n.options=C[e].options)}else if(qe.has(n.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(x=>delete n[x]),n.type!=="checkbox-group"&&n.type!=="multiselect"&&delete n.multiple;const u=document.getElementById(`fb-options-${e}`);u&&(n.options=u.value.split(`
|
|
2
|
+
`).filter(x=>x.trim()).map(x=>{const[N,...q]=x.split(":");return{value:N.trim(),label:q.join(":").trim()||N.trim()}}))}if(n.type==="textarea"){const u=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);u>0&&(n.formConfig={...n.formConfig||{},rows:u})}const r=document.getElementById(`fb-span-${e}`),p=document.getElementById(`fb-fullwidth-${e}`);if(r||p){const u={...n.formConfig||{}};if(p?.checked)u.span="full";else{const x=parseInt(r?.value,10);x>1?u.span=x:delete u.span}n.formConfig=Object.keys(u).length?u:void 0}const m=document.getElementById(`fb-minlength-${e}`)?.value;m&&(n.minLength=parseInt(m,10));const h=document.getElementById(`fb-maxlength-${e}`)?.value;h&&(n.maxLength=parseInt(h,10));const y=document.getElementById(`fb-min-${e}`)?.value;y!==""&&y!==void 0&&(n.min=parseFloat(y));const v=document.getElementById(`fb-max-${e}`)?.value;v!==""&&v!==void 0&&(n.max=parseFloat(v));const f=Ot(e);f?n.logic=f:delete n.logic;const w=en(e);return w?n.triggers=w:delete n.triggers,n}function Ot(e){const n=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!n)return;const o=n.querySelector(".fb-field-logic");if(!o)return;const t={};let l=!1;const a=o.querySelector('[data-logic-section="visibility"]');if(a){const r=a.querySelector(".fb-logic-vis-default"),p=a.querySelector(".fb-logic-vis-transition"),m=Array.from(a.querySelectorAll(".fb-logic-cond-row")).map(f=>{const w=f.querySelector(".fb-logic-cond-field"),u=f.querySelector(".fb-logic-cond-op"),x=f.querySelector(".fb-logic-cond-val"),N=f.querySelector(".fb-logic-vis-then");return w?.value?{when:{all:[{field:w.value,operator:u.value,value:x.value}]},then:N.value}:null}).filter(Boolean),h=r?.value||"visible",y=p?.value||"none",v=parseInt(a.querySelector(".fb-logic-vis-duration")?.value||"",10);(h!=="visible"||m.length>0||y!=="none")&&(t.visibility={default:h,conditions:m},y!=="none"&&(t.visibility.transition=y),y!=="none"&&Number.isFinite(v)&&(t.visibility.duration=v),l=!0)}const i=o.querySelector('[data-logic-section="requirement"]');if(i){const r=i.querySelector(".fb-logic-req-default"),p=Array.from(i.querySelectorAll(".fb-logic-cond-row")).map(m=>{const h=m.querySelector(".fb-logic-cond-field"),y=m.querySelector(".fb-logic-cond-op"),v=m.querySelector(".fb-logic-cond-val"),f=m.querySelector(".fb-logic-req-then");return h?.value?{when:{all:[{field:h.value,operator:y.value,value:v.value}]},then:f.value==="true"}:null}).filter(Boolean);p.length>0&&(t.requirement={default:r?.checked===!0,conditions:p},l=!0)}const s=o.querySelector('[data-logic-section="validation"]');if(s){const r=Array.from(s.querySelectorAll(".fb-logic-val-rule")).map(p=>{const m=p.querySelector(".fb-logic-val-type"),h=p.querySelector(".fb-logic-val-pattern"),y=p.querySelector(".fb-logic-val-flags"),v=p.querySelector(".fb-logic-val-message");if(!h?.value.trim())return null;const f=m?.value||"regex",w={type:f,message:v?.value.trim()||"Invalid value."};return f==="regex"?(w.pattern=h.value.trim(),y?.value.trim()&&(w.flags=y.value.trim())):w.field=h.value.trim(),w}).filter(Boolean);r.length>0&&(t.validation=r,l=!0)}const c=o.querySelector('[data-logic-section="cascade"]');if(c){const r=c.querySelector(".fb-logic-cascade-source"),p=c.querySelector(".fb-logic-cascade-mapping"),m=c.querySelector(".fb-logic-cascade-defaults"),h=r?.value?.trim();if(h){let y={};try{y=JSON.parse(p?.value||"{}")}catch{}const v=(m?.value||"").split(`
|
|
3
|
+
`).filter(f=>f.trim()).map(f=>{const[w,...u]=f.split(":");return{value:w.trim(),label:u.join(":").trim()||w.trim()}});t.cascade={sourceField:h,mapping:y,defaultOptions:v},l=!0}}return l?t:void 0}function B(){C=C.map((e,n)=>Dt(n))}let ae=null;function Rt(e,n,o){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",a=>{ae=n,a.dataTransfer.effectAllowed="move",e.style.opacity="0.4"}),t.addEventListener("dragend",()=>{e.style.opacity="",document.querySelectorAll("#fields-list .fb-field-card").forEach(a=>a.classList.remove("fb-drag-over"))}),e.addEventListener("dragover",a=>{ae!=null&&(a.preventDefault(),a.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(i=>i.classList.remove("fb-drag-over")),e.classList.add("fb-drag-over"))}),e.addEventListener("dragleave",()=>e.classList.remove("fb-drag-over")),e.addEventListener("drop",a=>{if(a.preventDefault(),e.classList.remove("fb-drag-over"),ae==null||ae===n){ae=null;return}B();const[i]=C.splice(ae,1);C.splice(n,0,i),ae=null,J(o)})}function J(e){const n=e.find("#fields-list").get(0),o=e.find("#fields-empty-msg").get(0);if(n){if(Array.from(n.querySelectorAll(".fb-field-card")).forEach(t=>t.remove()),C.length===0){o&&(o.style.display=""),se?.(n),Ie();return}o&&(o.style.display="none"),C.forEach((t,l)=>{const a=t.type==="page-break"?Mt(t,l,e):t.type==="spacer"?Pt(t,l,e):_t(t,l,e);Rt(a,l,e),n.appendChild(a)}),se?.(n),Ie()}}function Mt(e,n,o){const t=document.createElement("div");t.className="fb-field-card",t.dataset.index=n,t.style.cssText="border:2px dashed var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent="- Page Break -",a.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);white-space:nowrap;flex-shrink:0;font-style:italic;";const i=document.createElement("span");i.textContent=e.label||"Untitled Step",i.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);";const s=document.createElement("div");s.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",L(c,"more-horizontal"),c.addEventListener("click",y=>{y.stopPropagation(),p.style.display=p.style.display==="none"?"":"none"}),s.appendChild(c);const r=document.createElement("button");r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove page break",L(r,"x"),r.addEventListener("click",async y=>{y.stopPropagation(),await E.confirm("Remove this page break?")&&(B(),C.splice(n,1),J(o))}),s.appendChild(r),l.appendChild(a),l.appendChild(i),l.appendChild(s),l.addEventListener("click",()=>{p.style.display=p.style.display==="none"?"":"none"});const p=document.createElement("div");p.className="fb-field-body",p.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const m=O([P("Step Title",`fb-pb-label-${n}`,"text",e.label||"","Shown as the wizard step heading"),P("Step Description",`fb-pb-desc-${n}`,"text",e.description||"","Optional sub-heading")]),h=m.querySelector(`#fb-pb-label-${n}`);return h&&h.addEventListener("input",()=>{i.textContent=h.value||"Untitled Step"}),p.appendChild(m),t.appendChild(l),t.appendChild(p),t}function Pt(e,n,o){const t=document.createElement("div");t.className="fb-field-card",t.dataset.index=n,t.style.cssText="border:1px dashed var(--dm-border);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 a=document.createElement("div");a.style.cssText="flex:1;height:1px;background:var(--dm-border);";const i=document.createElement("span");i.textContent="Spacer",i.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const s=document.createElement("div");s.style.cssText="flex:1;height:1px;background:var(--dm-border);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const r=document.createElement("button");return r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove spacer",L(r,"x"),r.addEventListener("click",async p=>{p.stopPropagation(),B(),C.splice(n,1),J(o)}),c.appendChild(r),l.appendChild(a),l.appendChild(i),l.appendChild(s),l.appendChild(c),t.appendChild(l),t}function _t(e,n,o){const t=document.createElement("div");t.className="fb-field-card",t.dataset.index=n,t.style.cssText="border:1px solid var(--dm-border);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);cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent=at(e.type),a.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);white-space:nowrap;flex-shrink:0;";const i=document.createElement("span");i.textContent=e.label||"(unlabelled)",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const s=document.createElement("div");s.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",L(c,"more-horizontal"),c.addEventListener("click",m=>{m.stopPropagation(),p.style.display=p.style.display==="none"?"":"none"}),s.appendChild(c);const r=document.createElement("button");if(r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove field",L(r,"x"),r.addEventListener("click",async m=>{m.stopPropagation(),await E.confirm("Remove this field?")&&(B(),C.splice(n,1),J(o))}),s.appendChild(r),l.appendChild(a),l.appendChild(i),e.required){const m=document.createElement("span");m.textContent="required",m.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",l.appendChild(m)}if(it(e.logic)){const m=document.createElement("span");L(m,"zap"),m.title="Has conditional logic",m.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",l.appendChild(m)}l.appendChild(s),l.addEventListener("click",()=>{p.style.display=p.style.display==="none"?"":"none"});const p=jt(e,n,i);return p.style.display="none",t.appendChild(l),t.appendChild(p),t}function jt(e,n,o){const t=document.createElement("div");t.className="fb-field-body",t.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border);";const l=O([P("Label",`fb-label-${n}`,"text",e.label||"","Shown above the field"),P("Field Name",`fb-name-${n}`,"text",e.name||"","Used as data key")]),a=O([rn("Type",`fb-type-${n}`,tt,e.type||"string"),vt("Required",`fb-required-${n}`,e.required||!1)]),i=O([P("Placeholder",`fb-placeholder-${n}`,"text",e.placeholder||"","Hint text inside the field")]),s=O([P("Helper Text",`fb-helper-${n}`,"text",e.helper||"","Shown below the field"),P("Tooltip",`fb-tooltip-${n}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),c=e.formConfig?.span,r=O([P("Column Span",`fb-span-${n}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),vt("Full Width",`fb-fullwidth-${n}`,c==="full")]);r.classList.add("fb-grid-row"),r.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",t.appendChild(l),t.appendChild(a),t.appendChild(i),t.appendChild(s),t.appendChild(r);const p=t.querySelector(`#fb-label-${n}`),m=t.querySelector(`#fb-name-${n}`);p&&p.addEventListener("input",()=>{o&&(o.textContent=p.value||"(unlabelled)"),m&&!m.dataset.manuallyEdited&&(m.value=lt(p.value))}),m&&m.addEventListener("input",()=>{m.dataset.manuallyEdited="1"});const h=t.querySelector(`#fb-type-${n}`);h&&h.addEventListener("change",()=>{const v=t.closest(".fb-field-card");if(v){const u=v.querySelector("span");u&&(u.textContent=at(h.value))}const f=t.querySelector(".fb-field-extras");f&&f.remove();const w=ht(h.value,e,n);w&&t.appendChild(w)});const y=ht(e.type,e,n);return y&&t.appendChild(y),t.appendChild(Ut(e,n)),t.appendChild(Xt(e,n)),t}const fe=[{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"}],ze=new Set(["is_empty","is_not_empty"]),st={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 Be(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function he(e){const n=document.createElement("p");return n.textContent=e,n.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",n}function be(e,n,o,t,l){const a=document.createElement("div");a.className="fb-logic-cond-row",a.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const i=document.createElement("span");i.textContent="When",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-cond-field",s.style.cssText="flex:1 1 140px;min-width:140px;",n.forEach(v=>{const f=document.createElement("option");f.value=v.value,f.textContent=v.label,e&&v.value===e.field&&(f.selected=!0),s.appendChild(f)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",fe.forEach(v=>{const f=document.createElement("option");f.value=v.value,f.textContent=v.label,e&&v.value===e.operator&&(f.selected=!0),c.appendChild(f)});const r=()=>{const v=n.find(f=>f.value===s.value);Array.from(c.options).forEach(f=>{const w=fe.find(u=>u.value===f.value);f.textContent=v?.multi&&st[f.value]||w?.label||f.value})};r(),s.addEventListener("change",r);const p=document.createElement("input");p.type="text",p.className="form-input fb-logic-cond-val",p.placeholder="value",p.style.cssText="flex:1 1 120px;min-width:100px;",p.value=e?.value||"",e&&ze.has(e.operator)&&(p.style.display="none"),c.addEventListener("change",()=>{p.style.display=ze.has(c.value)?"none":""});const m=document.createElement("span");L(m,"arrow-right"),m.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const h=document.createElement("select");h.className=`form-select ${t}`,h.style.cssText="flex:1 1 140px;min-width:120px;",o.forEach(v=>{const f=document.createElement("option");f.value=v.value,f.textContent=v.label,v.value===l&&(f.selected=!0),h.appendChild(f)});const y=document.createElement("button");return y.type="button",y.className="btn btn-xs btn-ghost",y.style.cssText="line-height:1;opacity:.6;",L(y,"x"),y.style.flexShrink="0",y.addEventListener("click",()=>a.remove()),a.appendChild(i),a.appendChild(s),a.appendChild(c),a.appendChild(p),a.appendChild(m),a.appendChild(h),a.appendChild(y),a}function Vt(e,n,o){const t=document.createElement("div");t.dataset.logicSection="visibility",t.appendChild(he("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const a=document.createElement("span");a.textContent="Default:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-vis-default",i.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(u=>{const x=document.createElement("option");x.value=u.value,x.textContent=u.label,u.value===(e.default||"visible")&&(x.selected=!0),i.appendChild(x)}),l.appendChild(a),l.appendChild(i),t.appendChild(l);const s=document.createElement("div");s.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 r=document.createElement("select");r.className="form-select fb-logic-vis-transition",r.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 x=document.createElement("option");x.value=u.value,x.textContent=u.label,u.value===(e.transition||"none")&&(x.selected=!0),r.appendChild(x)}),s.appendChild(c),s.appendChild(r),t.appendChild(s);const p=document.createElement("div");p.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const m=document.createElement("span");m.textContent="Speed:",m.style.cssText="font-size:.8rem;flex-shrink:0;";const h=document.createElement("select");h.className="form-select fb-logic-vis-duration",h.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 x=document.createElement("option");x.value=u.value,x.textContent=u.label,u.value===String(e.duration??"")&&(x.selected=!0),h.appendChild(x)}),p.appendChild(m),p.appendChild(h),t.appendChild(p);const y=()=>{p.style.display=r.value==="none"?"none":""};y(),r.addEventListener("change",y);const v=document.createElement("div");v.className="fb-logic-vis-rules";const f=o.map(u=>({value:u.name,label:u.label||u.name,multi:Be(u)})),w=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(u=>{const x=(u.when?.all||u.when?.any||[])[0],N=u.then==="hidden"?"hidden":"visible";f.length>0&&v.appendChild(be(x,f,w,"fb-logic-vis-then",N))}),t.appendChild(v),f.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;",le(u,"plus","Add visibility rule"),u.addEventListener("click",()=>v.appendChild(be(null,f,w,"fb-logic-vis-then","visible"))),t.appendChild(u)}return t}function Ht(e,n,o){const t=document.createElement("div");t.dataset.logicSection="requirement",t.appendChild(he("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 a=document.createElement("input");a.type="checkbox",a.className="fb-logic-req-default",a.checked=e.default===!0,l.appendChild(a),l.appendChild(document.createTextNode("Required by default")),t.appendChild(l);const i=document.createElement("div");i.className="fb-logic-req-rules";const s=o.map(r=>({value:r.name,label:r.label||r.name,multi:Be(r)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(r=>{const p=(r.when?.all||r.when?.any||[])[0],m=r.then===!0?"true":"false";s.length>0&&i.appendChild(be(p,s,c,"fb-logic-req-then",m))}),t.appendChild(i),s.length>0){const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.style.cssText="font-size:.73rem;margin-top:.35rem;",le(r,"plus","Add requirement rule"),r.addEventListener("click",()=>i.appendChild(be(null,s,c,"fb-logic-req-then","true"))),t.appendChild(r)}return t}function rt(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 o=document.createElement("select");o.className="form-select fb-logic-val-type",o.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(s=>{const c=document.createElement("option");c.value=s.value,c.textContent=s.label,s.value===(e?.type||"regex")&&(c.selected=!0),o.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"),o.addEventListener("change",()=>{l.style.display=o.value==="match"?"none":"",t.placeholder=o.value==="match"?"field name":"pattern"});const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-message",a.placeholder="Error message",a.value=e?.message||"",a.style.cssText="flex:4;";const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="line-height:1;opacity:.6;",L(i,"x"),i.style.flexShrink="0",i.addEventListener("click",()=>n.remove()),n.appendChild(o),n.appendChild(t),n.appendChild(l),n.appendChild(a),n.appendChild(i),n}function Gt(e,n,o){const t=document.createElement("div");t.dataset.logicSection="validation",t.appendChild(he("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(i=>l.appendChild(rt(i))),t.appendChild(l);const a=document.createElement("button");return a.type="button",a.className="btn btn-xs btn-ghost",a.style.cssText="font-size:.73rem;margin-top:.35rem;",le(a,"plus","Add validation rule"),a.addEventListener("click",()=>l.appendChild(rt(null))),t.appendChild(a),t}function Wt(e,n,o){const t=document.createElement("div");t.dataset.logicSection="cascade",t.appendChild(he("Cascade Options")),t.lastChild.appendChild(Ae("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 a=document.createElement("span");a.textContent="Source field:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-cascade-source",i.style.cssText="flex:1;";const s=document.createElement("option");s.value="",s.textContent="- none -",i.appendChild(s),o.forEach(h=>{const y=document.createElement("option");y.value=h.name,y.textContent=h.label||h.name,h.name===e.sourceField&&(y.selected=!0),i.appendChild(y)}),l.appendChild(a),l.appendChild(i),t.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Ae(`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);margin:.3rem 0 .2rem;";const r=document.createElement("textarea");r.className="form-input fb-logic-cascade-mapping",r.rows=4,r.style.cssText="font-family:monospace;",r.placeholder='{"uk": [{"value": "london", "label": "London"}]}',r.value=e.mapping?JSON.stringify(e.mapping,null,2):"",t.appendChild(c),t.appendChild(r);const p=document.createElement("p");p.textContent="Default options (one per line: value:Label)",p.appendChild(Ae("Shown before the source field has a value, or when its value has no mapping entry.")),p.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const m=document.createElement("textarea");return m.className="form-input fb-logic-cascade-defaults",m.rows=3,m.style.cssText="font-family:monospace;",m.placeholder=`option1:Option 1
|
|
4
|
+
option2:Option 2`,m.value=(e.defaultOptions||[]).map(h=>{const y=typeof h=="string"?h:h.value??"",v=typeof h=="string"?h:h.label??y;return y===v?y:`${y}:${v}`}).join(`
|
|
5
|
+
`),t.appendChild(p),t.appendChild(m),t}function Ut(e,n){const o=e.logic||{},t=C.filter((m,h)=>h!==n&&m.type!=="page-break"&&m.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const i=document.createElement("span");i.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",i.textContent="\u26A1 Conditional Logic";const s=it(o),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",L(c,s?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-logic-body",r.style.cssText="padding:.25rem 0 .25rem;"+(s?"":"display:none;"),a.addEventListener("click",()=>{const m=r.style.display==="none";r.style.display=m?"":"none",L(c,m?"chevron-down":"chevron-right",12)}),a.appendChild(i),a.appendChild(c),l.appendChild(a),r.appendChild(Vt(o.visibility||{},n,t)),r.appendChild(Ht(o.requirement||{},n,t)),r.appendChild(Gt(o.validation||[],n,t));const p=document.getElementById(`fb-type-${n}`)?.value||e.type;return qe.has(p)&&r.appendChild(Wt(o.cascade||{},n,t)),l.appendChild(r),l}const ge=[{value:"banner",label:"Show a banner",kind:"state",params:["message","level","position","dismissible"]},{value:"toast",label:"Show a toast",kind:"event",params:["message","level"]},{value:"hide-fields",label:"Hide fields",kind:"state",params:["target"]},{value:"disable-fields",label:"Disable fields",kind:"state",params:["target"]},{value:"require-fields",label:"Make fields required",kind:"state",params:["target"]},{value:"block-submit",label:"Block submission",kind:"state",params:["message"]},{value:"goto-step",label:"Jump to a wizard step",kind:"event",params:["step"]},{value:"redirect",label:"Redirect after submit",kind:"event",params:["url"]},{value:"celebrate",label:"Celebrate",kind:"event",params:["theme","intensity"]},{value:"run-action",label:"Run a CMS action",kind:"event",params:["slug"]}],Jt=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],Kt=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],Yt=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],Qt=[{value:"auto",label:"Whatever is in season"},{value:"christmas",label:"Christmas"},{value:"halloween",label:"Halloween"},{value:"valentines",label:"Valentine's Day"},{value:"guy-fawkes",label:"Guy Fawkes Night"},{value:"st-patricks",label:"St Patrick's Day"},{value:"st-andrews",label:"St Andrew's Day"},{value:"st-davids",label:"St David's Day"},{value:"st-georges",label:"St George's Day"}];function ct(e){return C.map((n,o)=>({field:n,i:o})).filter(({field:n,i:o})=>o!==e&&n.type!=="page-break"&&n.type!=="spacer"&&n.name).map(({field:n})=>({value:n.name,label:n.label||n.name,multi:Be(n)}))}function K(e,n,o,t){const l=document.createElement("select");return l.className=`form-select ${e}`,t&&(l.style.cssText=t),n.forEach(a=>{const i=document.createElement("option");i.value=a.value,i.textContent=a.label,a.value===o&&(i.selected=!0),l.appendChild(i)}),l}function ye(e,n,o,t){const l=document.createElement("input");return l.type="text",l.className=`form-input ${e}`,l.value=n==null?"":String(n),o&&(l.placeholder=o),t&&(l.style.cssText=t),l}function De(e,n){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost",o.style.cssText="line-height:1;opacity:.6;flex-shrink:0;",n&&(o.title=n),L(o,"x"),o.addEventListener("click",e),o}function dt(e,n){const o=document.createElement("div");o.className="fb-trig-cond-row",o.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.5rem;flex-wrap:wrap;";const t=K("fb-trig-cond-field",n,e?.field,"flex:1 1 140px;min-width:130px;"),l=K("fb-trig-cond-op",fe,e?.operator,"flex:1 1 150px;min-width:130px;"),a=ye("fb-trig-cond-val",e?.value,"value","flex:1 1 110px;min-width:90px;"),i=()=>{const c=n.find(r=>r.value===t.value);Array.from(l.options).forEach(r=>{const p=fe.find(m=>m.value===r.value);r.textContent=c?.multi&&st[r.value]||p?.label||r.value})},s=()=>{a.style.display=ze.has(l.value)?"none":""};return i(),s(),t.addEventListener("change",i),l.addEventListener("change",s),o.appendChild(t),o.appendChild(l),o.appendChild(a),o.appendChild(De(()=>o.remove(),"Remove condition")),o}function pt(e,n){const o=document.createElement("div");o.className="fb-trig-params",o.style.cssText="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;flex:1 1 100%;margin:.35rem 0 0 .25rem;";const t=ge.find(l=>l.value===(e.type||"banner"));if(!t)return o;for(const l of t.params)switch(l){case"message":o.appendChild(ye("fb-trig-p-message",e.message,"Message shown to the visitor","flex:2 1 260px;"));break;case"level":o.appendChild(K("fb-trig-p-level",Jt,e.level||"info","flex:1 1 120px;"));break;case"position":o.appendChild(K("fb-trig-p-position",Kt,e.position||"field-below","flex:1 1 150px;"));break;case"dismissible":{const a=document.createElement("label");a.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.78rem;flex-shrink:0;";const i=document.createElement("input");i.type="checkbox",i.className="form-check fb-trig-p-dismissible",i.checked=e.dismissible!==!1,a.appendChild(i),a.appendChild(document.createTextNode("Dismissible")),o.appendChild(a);break}case"target":{const a=K("fb-trig-p-target",Yt,e.target||(e.fields?.length?"listed":"rest"),"flex:1 1 170px;"),i=document.createElement("select");i.className="form-select fb-trig-p-fields",i.multiple=!0,i.size=4,i.style.cssText="flex:2 1 200px;";const s=new Set(e.fields||[]);ct(n).forEach(r=>{const p=document.createElement("option");p.value=r.value,p.textContent=r.label,s.has(r.value)&&(p.selected=!0),i.appendChild(p)});const c=()=>{i.style.display=a.value==="listed"?"":"none"};c(),a.addEventListener("change",c),o.appendChild(a),o.appendChild(i);break}case"step":{const a=ye("fb-trig-p-step",e.step,"0","flex:0 0 90px;");a.type="number",a.min="0",o.appendChild(a);const i=document.createElement("span");i.textContent="Step number, counting from 0",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted);",o.appendChild(i);break}case"url":o.appendChild(ye("fb-trig-p-url",e.url,"/thank-you","flex:2 1 220px;"));break;case"theme":o.appendChild(K("fb-trig-p-theme",Qt,e.theme||"auto","flex:1 1 180px;"));break;case"intensity":o.appendChild(K("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium","flex:0 1 120px;"));break;case"slug":{const a=[{value:"",label:$e.length?"Choose an action":"No actions available"}].concat($e.map(i=>({value:i.slug,label:i.title||i.slug})));o.appendChild(K("fb-trig-p-slug",a,e.slug||"","flex:2 1 200px;"));break}default:break}if(t.kind==="event"){const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.78rem;flex-shrink:0;";const a=document.createElement("input");a.type="checkbox",a.className="form-check fb-trig-p-once",a.checked=!!e.once,l.appendChild(a),l.appendChild(document.createTextNode("Only once")),l.title="Fire the first time only, rather than every time the answer swings back.",o.appendChild(l)}return o}function mt(e,n){const o=document.createElement("div");o.className="fb-trig-action-row",o.style.cssText="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;padding:.45rem .5rem;margin-bottom:.4rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md);";const t=K("fb-trig-action-type",ge,e.type||"banner","flex:1 1 190px;"),l=document.createElement("span");l.className="fb-trig-kind",l.style.cssText="font-size:.7rem;color:var(--dm-text-muted);flex-shrink:0;";const a=pt(e,n),i=()=>{const s=ge.find(c=>c.value===t.value);l.textContent=s?.kind==="event"?"fires once when it becomes true":"applies while it is true"};return i(),t.addEventListener("change",()=>{i();const s=pt({type:t.value},n);o.replaceChild(s,o.querySelector(".fb-trig-params")),window.I?.scan?.()}),o.appendChild(t),o.appendChild(l),o.appendChild(De(()=>o.remove(),"Remove action")),o.appendChild(a),o}function ut(e,n,o,t){const l=document.createElement("div");l.className="fb-trig-branch",l.dataset.branch=e,l.style.cssText="margin-top:.6rem;";const a=document.createElement("p");a.textContent=n,a.style.cssText="font-size:.73rem;font-weight:700;color:var(--dm-text-muted);margin:0 0 .4rem;text-transform:uppercase;letter-spacing:.05em;",l.appendChild(a);const i=document.createElement("div");i.className="fb-trig-action-list",(o||[]).forEach(c=>i.appendChild(mt(c,t))),l.appendChild(i);const s=document.createElement("button");return s.type="button",s.className="btn btn-xs btn-ghost",le(s,"plus","Add action",12),s.addEventListener("click",()=>{i.appendChild(mt({type:"banner"},t)),window.I?.scan?.()}),l.appendChild(s),l}function ft(e,n,o){const t=ct(n),l=document.createElement("div");l.className="fb-trig-card",l.dataset.triggerId=e.id||`trg-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,l.style.cssText="border:1px solid var(--dm-border);border-radius:var(--dm-radius-md);padding:.65rem .7rem;margin-bottom:.7rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.5rem;";const i=document.createElement("span");i.textContent=`Trigger ${o+1}`,i.style.cssText="font-size:.78rem;font-weight:600;",a.appendChild(i);const s=document.createElement("div");s.style.cssText="display:flex;align-items:center;gap:.5rem;";const c=document.createElement("label");c.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.75rem;cursor:pointer;";const r=document.createElement("input");if(r.type="checkbox",r.className="form-check fb-trig-enabled",r.checked=e.enabled!==!1,c.appendChild(r),c.appendChild(document.createTextNode("Enabled")),s.appendChild(c),s.appendChild(De(()=>l.remove(),"Remove trigger")),a.appendChild(s),l.appendChild(a),!t.length){const f=document.createElement("p");return f.textContent="Add another field first - a trigger tests an answer, and this is the only field so far.",f.style.cssText="font-size:.78rem;color:var(--dm-text-muted);margin:0;",l.appendChild(f),l}const p=document.createElement("div");p.style.cssText="display:flex;align-items:center;gap:.45rem;margin-bottom:.45rem;flex-wrap:wrap;";const m=document.createElement("span");m.textContent="When",m.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted);",p.appendChild(m),p.appendChild(K("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all","flex:0 1 200px;")),l.appendChild(p);const h=document.createElement("div");h.className="fb-trig-cond-list";const y=e.when?.all||e.when?.any||[];(y.length?y:[{}]).forEach(f=>h.appendChild(dt(f,t))),l.appendChild(h);const v=document.createElement("button");return v.type="button",v.className="btn btn-xs btn-ghost",le(v,"plus","Add condition",12),v.addEventListener("click",()=>{h.appendChild(dt({},t)),window.I?.scan?.()}),l.appendChild(v),l.appendChild(ut("then","Then",e.then,n)),l.appendChild(ut("otherwise","Otherwise (optional)",e.otherwise,n)),l}function Xt(e,n){const o=Array.isArray(e.triggers)?e.triggers:[],t=document.createElement("div");t.className="fb-field-triggers",t.style.cssText="margin-top:.5rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const a=document.createElement("span");a.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",a.textContent=`\u{1F3AF} Triggers${o.length?` (${o.length})`:""}`;const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",L(i,o.length?"chevron-down":"chevron-right",12);const s=document.createElement("div");s.className="fb-triggers-body",s.style.cssText="padding:.35rem 0;"+(o.length?"":"display:none;"),l.addEventListener("click",()=>{const m=s.style.display==="none";s.style.display=m?"":"none",L(i,m?"chevron-down":"chevron-right",12)});const c=document.createElement("p");c.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, jump to a step, or celebrate.",c.style.cssText="font-size:.75rem;color:var(--dm-text-muted);margin:0 0 .6rem;",s.appendChild(c);const r=document.createElement("div");r.className="fb-trig-list",o.forEach((m,h)=>r.appendChild(ft(m,n,h))),s.appendChild(r);const p=document.createElement("button");return p.type="button",p.className="btn btn-xs btn-ghost",le(p,"plus","Add trigger",12),p.addEventListener("click",()=>{r.appendChild(ft({enabled:!0,then:[{type:"banner"}]},n,r.children.length)),window.I?.scan?.()}),s.appendChild(p),l.appendChild(a),l.appendChild(i),t.appendChild(l),t.appendChild(s),t}function Zt(e){const n=e.querySelector(".fb-trig-action-type")?.value,o=ge.find(a=>a.value===n);if(!o)return null;const t={type:n},l=a=>e.querySelector(a)?.value?.trim()||"";for(const a of o.params)switch(a){case"message":t.message=l(".fb-trig-p-message");break;case"level":t.level=l(".fb-trig-p-level")||"info";break;case"position":t.position=l(".fb-trig-p-position")||"field-below";break;case"dismissible":t.dismissible=!!e.querySelector(".fb-trig-p-dismissible")?.checked;break;case"target":{const i=l(".fb-trig-p-target")||"rest";t.target=i,i==="listed"&&(t.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(s=>s.selected).map(s=>s.value));break}case"step":{const i=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(i)&&(t.step=i);break}case"url":t.url=l(".fb-trig-p-url");break;case"theme":t.theme=l(".fb-trig-p-theme")||"auto";break;case"intensity":t.intensity=l(".fb-trig-p-intensity")||"medium";break;case"slug":t.slug=l(".fb-trig-p-slug");break;default:break}return o.kind==="event"&&e.querySelector(".fb-trig-p-once")?.checked&&(t.once=!0),o.params.includes("message")&&!t.message&&o.value!=="block-submit"||n==="redirect"&&!t.url||n==="run-action"&&!t.slug?null:t}function en(e){const o=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!o)return;const t=[];return o.querySelectorAll(".fb-trig-card").forEach(l=>{const a=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(m=>{const h=m.querySelector(".fb-trig-cond-field")?.value,y=m.querySelector(".fb-trig-cond-op")?.value;if(!h||!y)return null;const v=m.querySelector(".fb-trig-cond-val")?.value??"";return{field:h,operator:y,value:v}}).filter(Boolean);if(!a.length)return;const i=m=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${m}"] .fb-trig-action-row`)).map(Zt).filter(Boolean),s=i("then"),c=i("otherwise");if(!s.length&&!c.length)return;const r=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",p={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[r]:a}};s.length&&(p.then=s),c.length&&(p.otherwise=c),t.push(p)}),t.length?t:void 0}function ht(e,n,o){const t=document.createElement("div");return t.className="fb-field-extras",e==="chooser"?(t.appendChild(tn(n,o)),t.appendChild(ln(n.options||[],o))):(qe.has(e)&&t.appendChild(cn(n.options||[],o)),e==="textarea"&&t.appendChild(O([P("Rows",`fb-rows-${o}`,"number",n.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&t.appendChild(O([P("Min Length",`fb-minlength-${o}`,"number",n.minLength||"",""),P("Max Length",`fb-maxlength-${o}`,"number",n.maxLength||"","")])),e==="number"&&t.appendChild(O([P("Min",`fb-min-${o}`,"number",n.min??"",""),P("Max",`fb-max-${o}`,"number",n.max??"","")]))),t.children.length?t:null}function bt(e){const n=document.createElement("div");n.className="fb-chooser-section",n.style.cssText="border:1px solid var(--dm-border); border-radius:6px; margin-top:.5rem; overflow:hidden;";const o=document.createElement("div");o.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",o.textContent=e,n.appendChild(o);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 ve(e,n,o,t,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=n,i.style.fontSize=".8rem";const s=document.createElement("select");if(s.id=e,s.className="form-input",t.forEach(([c,r])=>{const p=document.createElement("option");p.value=c,p.textContent=r,String(c)===String(o)&&(p.selected=!0),s.appendChild(p)}),a.appendChild(i),a.appendChild(s),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(c)}return a}function gt(e,n,o,t){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const i=document.createElement("input");if(i.id=e,i.type="checkbox",i.checked=!!o,a.appendChild(i),a.appendChild(document.createTextNode(" "+n)),l.appendChild(a),t){const s=document.createElement("p");s.className="form-hint text-muted",s.textContent=t,s.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(s)}return l}function Oe(e,n,o,t,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=n,i.style.fontSize=".8rem",a.appendChild(i);const s=document.createElement("div");s.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=o||"",t&&(c.placeholder=t),c.style.flex="1";const r=document.createElement("input");r.type="color",r.title="Pick a colour",r.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const p=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(r.value=p?c.value:"#000000",r.addEventListener("input",()=>{c.value=r.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),s.appendChild(c),s.appendChild(r),a.appendChild(s),l){const m=document.createElement("p");m.className="form-hint text-muted",m.textContent=l,m.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(m)}return a}function tn(e,n){const o=document.createElement("div");o.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const t=bt("Layout");t.body.appendChild(O([ve(`fb-chooser-variant-${n}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),gt(`fb-chooser-multiple-${n}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),t.body.appendChild(O([ve(`fb-chooser-density-${n}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),P("Columns",`fb-chooser-columns-${n}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),o.appendChild(t.wrap);const l=bt("Visual");return l.body.appendChild(O([Oe(`fb-chooser-accent-${n}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),ve(`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(O([gt(`fb-chooser-glow-${n}`,"Glow on selected",!!e.glow,"Soft outer glow."),Oe(`fb-chooser-glow-colour-${n}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(O([ve(`fb-chooser-shadow-${n}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),Oe(`fb-chooser-shadow-colour-${n}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),o.appendChild(l.wrap),o}function nn(e,n,o,t){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(o),l.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const a=document.createElement("div");a.style.cssText="display:flex; gap:.4rem; align-items:center;";const i=document.createElement("div");i.style.cssText="display:flex; flex-direction:column; gap:1px;";const s=document.createElement("button");s.type="button",s.className="btn btn-xs btn-ghost",s.title="Move up",L(s,"arrow-up"),s.addEventListener("click",$=>{$.preventDefault(),yt(n,o,-1,t)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",L(c,"arrow-down"),c.addEventListener("click",$=>{$.preventDefault(),yt(n,o,1,t)}),i.appendChild(s),i.appendChild(c),a.appendChild(i);const r=document.createElement("input");r.type="text",r.className="form-input fb-chooser-opt-value",r.placeholder="value",r.value=e.value||"",r.style.flex="1",a.appendChild(r);const p=document.createElement("input");p.type="text",p.className="form-input fb-chooser-opt-label",p.placeholder="label (visible to users)",p.value=e.label||"",p.style.flex="2",a.appendChild(p);const m=document.createElement("button");m.type="button",m.className="btn btn-xs btn-ghost",m.style.cssText="line-height:1;opacity:.6;",m.title="Remove option",L(m,"x"),m.addEventListener("click",$=>{$.preventDefault(),sn(n,o,t)}),a.appendChild(m),l.appendChild(a);const h=document.createElement("div");h.style.cssText="display:flex; gap:.4rem;";const y=qt("icon name (optional)",e.icon||"");y.input.classList.add("fb-chooser-opt-icon"),y.el.style.flex="1",h.appendChild(y.el);const v=document.createElement("input");v.type="text",v.className="form-input fb-chooser-opt-description",v.placeholder="description (card + comfortable only)",v.value=e.description||"",v.style.flex="2",h.appendChild(v),l.appendChild(h);const f=document.createElement("div");f.style.cssText="display:flex; gap:.4rem;";const w=document.createElement("input");w.type="text",w.className="form-input fb-chooser-opt-tooltip",w.placeholder="tooltip (hover hint)",w.value=e.tooltip||"",w.style.flex="2",f.appendChild(w);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",f.appendChild(u);const x=document.createElement("select");x.className="form-input fb-chooser-opt-badge-type",x.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([$,Y])=>{const W=document.createElement("option");W.value=$,W.textContent=Y,(e.badge?.type||"")===$&&(W.selected=!0),x.appendChild(W)}),f.appendChild(x),l.appendChild(f);const N=document.createElement("div");N.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const q=document.createElement("label");q.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const V=document.createElement("input");V.type="checkbox",V.className="fb-chooser-opt-recommended",V.checked=!!e.recommended,q.appendChild(V),q.appendChild(document.createTextNode(" Recommended")),N.appendChild(q);const _=document.createElement("label");_.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const j=document.createElement("input");return j.type="checkbox",j.className="fb-chooser-opt-disabled",j.checked=!!e.disabled,_.appendChild(j),_.appendChild(document.createTextNode(" Disabled")),N.appendChild(_),l.appendChild(N),l}function ln(e,n){const o=document.createElement("div");o.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 a=document.createElement("button");a.type="button",a.className="btn btn-xs btn-ghost",le(a,"plus","Add option"),t.appendChild(a),o.appendChild(t);const i=document.createElement("div");i.className="fb-chooser-options-list",i.id=`fb-chooser-options-${n}`,i.style.cssText="display:flex; flex-direction:column; gap:.4rem;",o.appendChild(i);const s=()=>{i.replaceChildren();const c=an(n);(c.length?c:e||[]).forEach((p,m)=>{i.appendChild(nn(p,n,m,s))})};return a.addEventListener("click",c=>{c.preventDefault(),on(n,s)}),s(),o}function an(e){const n=C[e];return!n||!Array.isArray(n.options)?[]:n.options}function Re(e){return C[e]?(Array.isArray(C[e].options)||(C[e].options=[]),C[e].options):[]}function on(e,n){xe(e),Re(e).push({value:"new",label:"New option"}),n()}function sn(e,n,o){xe(e),Re(e).splice(n,1),o()}function yt(e,n,o,t){xe(e);const l=Re(e),a=n+o;if(a<0||a>=l.length)return;const[i]=l.splice(n,1);l.splice(a,0,i),t()}function xe(e){const n=document.getElementById(`fb-chooser-options-${e}`);if(!n)return;const o=n.querySelectorAll(".fb-chooser-option-row"),t=[];o.forEach(l=>{const a={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},i=l.querySelector(".fb-chooser-opt-icon")?.value.trim();i&&(a.icon=i);const s=l.querySelector(".fb-chooser-opt-description")?.value.trim();s&&(a.description=s);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(a.tooltip=c);const r=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),p=l.querySelector(".fb-chooser-opt-badge-type")?.value;(r||p)&&(a.badge={},r&&(a.badge.text=r),p&&(a.badge.type=p)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(a.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(a.disabled=!0),t.push(a)}),C[e]&&(C[e].options=t)}function O(e){const n=document.createElement("div");return n.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(o=>{o&&n.appendChild(o)}),n}function P(e,n,o,t,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=n,i.className="form-label",i.textContent=e,i.style.fontSize=".8rem";const s=document.createElement("input");if(s.id=n,s.type=o||"text",s.className="form-input",s.value=t??"",a.appendChild(i),a.appendChild(s),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",a.appendChild(c)}return a}function rn(e,n,o,t){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.htmlFor=n,a.className="form-label",a.textContent=e,a.style.fontSize=".8rem";const i=document.createElement("select");return i.id=n,i.className="form-select",o.forEach(s=>{const c=document.createElement("option");c.value=s.value,c.textContent=s.label,s.value===t&&(c.selected=!0),i.appendChild(c)}),l.appendChild(a),l.appendChild(i),l}function vt(e,n,o){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 a=document.createElement("input");return a.id=n,a.type="checkbox",a.checked=o,l.appendChild(a),l.appendChild(document.createTextNode(e)),t.appendChild(l),t}function cn(e,n){const o=document.createElement("div");o.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
|
-
maybe:Maybe`,l.value=(e||[]).map(
|
|
8
|
-
`),l.style.fontFamily="monospace",a.appendChild(t),a.appendChild(l),a}function se(e){return parseInt(e,10)===3?3:2}function qe(e){const n=e.find("#field-project").val()||"";return B(),{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:{...Z||{},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:se(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()},...P!==null&&{collection:P}}}}function Le(e,n){const a={};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)),a[t.name]=r}),a}function $e(e,n){const a=typeof e=="string"?document.querySelector(e):e;a&&(n||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const l=a.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,P=null;const n=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);$=n?n[1]:null;let a=null;const t=E.loader(e.get(0),{type:"dots"});if($)try{a=await M(`/forms/${$}`),v=a.fields||[],P=a.actions?.collection??null}catch{E.toast("Could not load form.",{type:"error"})}Z={};try{const s=await M("/projects").catch(()=>[]),p=e.find("#field-project").get(0);p&&(Array.isArray(s)?s:[]).forEach(m=>{const f=document.createElement("option");f.value=m.slug,f.textContent=m.name||m.slug,p.appendChild(f)})}catch{}if(t.destroy(),a?e.find("#editor-title").get(0).textContent=`Edit: ${a.title}`:e.find("#editor-title").get(0).textContent="New Form",$||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(pe(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),Z=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const s=a.settings||{};e.find("#setting-submit-text").val(s.submitText||"Submit"),e.find("#setting-success-message").val(s.successMessage||""),e.find("#setting-layout").val(s.layout||"grid"),e.find("#setting-columns").val(se(s.columns)),e.find("#setting-submit-span").val(s.submitSpan||""),e.find("#columns-group").get(0).style.display=(s.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",s.honeypot!==!1),e.find("#setting-rate-limit").val(s.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(s.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 s=await M("/actions").catch(()=>[]),p=e.find("#action-cms-slug").get(0);if(X=Array.isArray(s)?s:[],(Array.isArray(s)?s:[]).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)}),!s.length){const m=document.createElement("option");m.value="",m.textContent="No actions available",m.disabled=!0,p.appendChild(m)}}catch{}const o=s=>{e.find("#columns-group").get(0).style.display=s?"":"none",document.querySelectorAll(".fb-grid-row").forEach(p=>{p.style.display=s?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){o(this.value==="grid")}),o(e.find("#setting-layout").val()==="grid"),O(e);const i=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",s=>{s.stopPropagation(),i.style.display=i.style.display==="none"?"":"none"}),j&&document.removeEventListener("click",j),j=()=>{i&&(i.style.display="none")},document.addEventListener("click",j),e.find("#add-field-btn").get(0).addEventListener("click",()=>{i&&(i.style.display="none"),B();const s=v.length;v.push({name:`field_${s+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),O(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",()=>{i&&(i.style.display="none"),B(),v.push({type:"spacer"}),O(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{i&&(i.style.display="none"),B();const s=v.filter(p=>p.type==="page-break").length+2;v.push({type:"page-break",label:`Step ${s}`,description:""}),O(e)}),e.find("#save-form-btn").get(0).addEventListener("click",async()=>{const s=qe(e);if(!s.title){E.toast("Please enter a form title.",{type:"error"});return}try{$?(await M(`/forms/${$}`,{method:"PUT",body:JSON.stringify(s)}),E.toast("Form saved.",{type:"success"})):($=(await M("/forms",{method:"POST",body:JSON.stringify(s)})).slug,R.navigate(`/forms/edit/${$}`),E.toast("Form created.",{type:"success"}))}catch(p){E.toast(p.message||"Failed to save form.",{type:"error"})}}),V=()=>{const s=qe(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 h=document.createElement("div");h.id="fb-preview-form",p.appendChild(h);const b=$?async u=>{m&&(m.style.display="none",m.textContent="");try{const g=await fetch(`/api/forms/submit/${$}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}),x=await g.json();if(!g.ok)throw new Error(x.error||"Submission failed.");m&&(m.textContent=x.message||s.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(g){m&&(m.textContent=g.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(g.message,{type:"error"})}return!1}:()=>!1,y=s.fields.some(u=>u.type==="page-break");if(typeof F<"u"){const u=se(s.settings?.columns),g=s.settings?.layout||"grid";if(y&&F.wizard){const x=Fe(s.fields,s.title),S=x.map(L=>({title:L.title,description:L.description,fields:Le(L.fields,u)}));let C=0,k=null,A=null;const T=L=>{const z=(x[C]||{}).fields||[];$e("#fb-preview-form",z),re(h,z),L&&window.FormLogicEngine&&ue(s.fields)&&(k?.destroy?.(),k=new window.FormLogicEngine.FormLogicRuntime({fields:s.fields},h,{baseValues:A?.getStepData?A.getStepData():{}}),k.init())};A=F.wizard("#fb-preview-form",{schema:{steps:S},layout:g,columns:u,finishText:s.settings?.submitText||"Finish",onStepChange:L=>{C=L,queueMicrotask(()=>T(!0))},onSubmit:b}),T(!1)}else if(F.render){const x=Le(s.fields,u),S={};if(s.fields.forEach(C=>{if(!(!C.name||C.type==="page-break"||C.type==="spacer")&&(C.type==="select"||C.type==="multiselect")&&C.required){const k=(C.options||[])[0];k&&(S[C.name]=typeof k=="object"?k.value:k)}}),F.render("#fb-preview-form",x,S,{submitText:s.settings?.submitText||"Submit",layout:g,columns:u,onSubmit:b}),g==="grid"&&s.settings?.submitSpan==="full"){const C=document.querySelector("#fb-preview-form .form-buttons");C&&C.classList.add("col-span-full")}$e("#fb-preview-form",s.fields),re(h,s.fields)}window.FormLogicEngine&&ue(s.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:s.fields},h).init()})}else{const u=document.createElement("p");u.textContent=`${s.fields.filter(g=>g.type!=="page-break").length} field(s): ${s.fields.filter(g=>g.type!=="page-break").map(g=>g.label).join(", ")}`,u.style.cssText="color:var(--dm-text-muted);font-style:italic;",h.appendChild(u)}},V();const r=e.find("#editor-tabs").get(0),c=e.find("#preview-card").get(0),d=s=>{c&&c.contains(s.target)||te()};r&&(r.addEventListener("input",d),r.addEventListener("change",d))}};
|
|
7
|
+
maybe:Maybe`,l.value=(e||[]).map(a=>{const i=typeof a=="string"?a:a.value??"",s=typeof a=="string"?a:a.label??i;return i===s?i:`${i}:${s}`}).join(`
|
|
8
|
+
`),l.style.fontFamily="monospace",o.appendChild(t),o.appendChild(l),o}function Ce(e){return parseInt(e,10)===3?3:2}function Ee(e){const n=e.find("#field-project").val()||"";return B(),{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:{...me||{},project:n||null},fields:C,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:Ce(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()},...pe!==null&&{collection:pe}}}}function xt(e,n){const o={};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 a=t.type==="chooser"||!!(t.variant&&["select","radio","checkbox-group"].includes(t.type)),s={type:t.type==="checkbox"?"boolean":t.type==="date"||t.type==="icon"||t.type==="image"?"string":a?"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}};a&&(t.variant&&(s.variant=t.variant),(t.multiple||t.type==="checkbox-group")&&(s.multiple=!0),t.density&&(s.density=t.density),t.columns&&(s.columns=t.columns),t.accent&&(s.accent=t.accent),t.accentStyle&&(s.accentStyle=t.accentStyle),t.glow&&(s.glow=!0),t.glowColour&&(s.glowColour=t.glowColour),t.shadow&&(s.shadow=t.shadow),t.shadowColour&&(s.shadowColour=t.shadowColour)),o[t.name]=s}),o}function Ct(e,n){const o=typeof e=="string"?document.querySelector(e):e;o&&(n||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const l=o.querySelector(`[name="${t.name}"]`);l&&l.type!=="date"&&(l.type="date")})}function Et(e,n){const o=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(o){for(;o.nextSibling;)o.nextSibling.remove();o.after(document.createTextNode(String(n||"")))}}const dn=e=>String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");let G=null,wt=0,kt=!1;const we=e=>String(e||"").split("?")[0].replace(/\/$/,"");function pn(){kt||!window.R?.use||(kt=!0,R.use((e,n,o)=>!G||!Ze(n?.path,e?.path)||G.path!==we(n?.path)||(G.flush(),!G.dirty())?o():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(t=>{t?o():history.replaceState(null,"",`#${n.path}`)})),M.subscribe("router:afterChange",({to:e,from:n}={})=>{if(G&&G.path===we(n?.path)&&Ze(n?.path,e?.path)){const o=G;G=null,o.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(pn(),G){const d=G;G=null,d.dispose()}const n=we(location.hash.replace(/^#/,"")),o=++wt,t=()=>o!==wt||!e.get(0)?.isConnected||we(location.hash.replace(/^#/,""))!==n;C=[],T=null,pe=null;const l=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);T=l?l[1]:null;let a=null;const i=E.loader(e.get(0),{type:"dots"});if(T)try{if(a=await oe(`/forms/${T}`),t()){i.destroy();return}C=a.fields||[],pe=a.actions?.collection??null}catch{if(t()){i.destroy();return}E.toast("Could not load form.",{type:"error"})}me={};try{const d=await oe("/projects").catch(()=>[]);if(t()){i.destroy();return}const g=e.find("#field-project").get(0);g&&(Array.isArray(d)?d:[]).forEach(b=>{const k=document.createElement("option");k.value=b.slug,k.textContent=b.name||b.slug,g.appendChild(k)})}catch{}if(i.destroy(),Et(e.get(0),a?a.title||a.slug:"New form"),T||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(lt(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),me=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const d=a.settings||{};e.find("#setting-submit-text").val(d.submitText||"Submit"),e.find("#setting-success-message").val(d.successMessage||""),e.find("#setting-layout").val(d.layout||"grid"),e.find("#setting-columns").val(Ce(d.columns)),e.find("#setting-submit-span").val(d.submitSpan||""),e.find("#columns-group").get(0).style.display=(d.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",d.honeypot!==!1),e.find("#setting-rate-limit").val(d.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(d.successRedirect||"");const g=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",g.enabled||!1),e.find("#action-email-recipients").val(g.recipients||""),e.find("#action-email-subject-prefix").val(g.subjectPrefix||"");const b=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",b.enabled||!1),e.find("#action-webhook-url").val(b.url||""),e.find("#action-webhook-method").val(b.method||"POST")}const s=a?.settings?.actionSlug||"";try{const d=await oe("/actions").catch(()=>[]);if(t())return;const g=e.find("#action-cms-slug").get(0);if($e=Array.isArray(d)?d:[],(Array.isArray(d)?d:[]).forEach(b=>{const k=document.createElement("option");k.value=b.slug,k.textContent=b.title||b.slug,b.slug===s&&(k.selected=!0),g.appendChild(k)}),!d.length){const b=document.createElement("option");b.value="",b.textContent="No actions available",b.disabled=!0,g.appendChild(b)}}catch{}const c=d=>{e.find("#columns-group").get(0).style.display=d?"":"none",document.querySelectorAll(".fb-grid-row").forEach(g=>{g.style.display=d?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){c(this.value==="grid")}),c(e.find("#setting-layout").val()==="grid"),J(e);const r=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",d=>{d.stopPropagation(),r.style.display=r.style.display==="none"?"":"none"}),ne&&document.removeEventListener("click",ne),ne=()=>{r&&(r.style.display="none")},document.addEventListener("click",ne),e.find("#add-field-btn").get(0).addEventListener("click",()=>{r&&(r.style.display="none"),B();const d=C.length;C.push({name:`field_${d+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),J(e);const g=e.find("#fields-list").get(0)?.lastElementChild;if(g){const b=g.querySelector(".fb-field-body");b&&(b.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{r&&(r.style.display="none"),B(),C.push({type:"spacer"}),J(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{r&&(r.style.display="none"),B();const d=C.filter(g=>g.type==="page-break").length+2;C.push({type:"page-break",label:`Step ${d}`,description:""}),J(e)}),ue=()=>{const d=Ee(e),g=e.find("#preview-container").get(0);if(!g)return;const b=e.find("#preview-test-result").get(0),k=e.find("#preview-test-badge").get(0);b&&(b.style.display="none",b.textContent=""),k&&(k.style.display=T?"":"none"),e.find("#preview-card").get(0).style.display="",g.textContent="";const H=document.createElement("div");H.id="fb-preview-form",g.appendChild(H);const U=T?async A=>{b&&(b.style.display="none",b.textContent="");try{const I=await fetch(`/api/forms/submit/${T}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(A)}),ee=await I.json();if(!I.ok)throw new Error(ee.error||"Submission failed.");b&&(b.textContent=ee.message||d.settings?.successMessage||"Submitted successfully.",b.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);"),E.toast("Test submission stored.",{type:"success"})}catch(I){b&&(b.textContent=I.message,b.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);"),E.toast(I.message,{type:"error"})}return!1}:()=>!1,ce=d.fields.some(A=>A.type==="page-break");if(typeof F<"u"){const A=Ce(d.settings?.columns),I=d.settings?.layout||"grid";if(ce&&F.wizard){const ee=$t(d.fields,d.title),de=ee.map(te=>({title:te.title,description:te.description,fields:xt(te.fields,A)}));let z=0,Q=null,Se=null;const Je=te=>{const Ke=(ee[z]||{}).fields||[];Ct("#fb-preview-form",Ke),Ye(H,Ke),te&&window.FormLogicEngine&&ot(d.fields)&&(Q?.destroy?.(),Q=new window.FormLogicEngine.FormLogicRuntime({fields:d.fields},H,{baseValues:Se?.getStepData?Se.getStepData():{}}),Q.init())};Se=F.wizard("#fb-preview-form",{schema:{steps:de},layout:I,columns:A,finishText:d.settings?.submitText||"Finish",onStepChange:te=>{z=te,queueMicrotask(()=>Je(!0))},onSubmit:U}),Je(!1)}else if(F.render){const ee=xt(d.fields,A),de={};if(d.fields.forEach(z=>{if(!(!z.name||z.type==="page-break"||z.type==="spacer")&&(z.type==="select"||z.type==="multiselect")&&z.required){const Q=(z.options||[])[0];Q&&(de[z.name]=typeof Q=="object"?Q.value:Q)}}),F.render("#fb-preview-form",ee,de,{submitText:d.settings?.submitText||"Submit",layout:I,columns:A,onSubmit:U}),I==="grid"&&d.settings?.submitSpan==="full"){const z=document.querySelector("#fb-preview-form .form-buttons");z&&z.classList.add("col-span-full")}Ct("#fb-preview-form",d.fields),Ye(H,d.fields)}window.FormLogicEngine&&ot(d.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:d.fields},H).init()})}else{const A=document.createElement("p");A.textContent=`${d.fields.filter(I=>I.type!=="page-break").length} field(s): ${d.fields.filter(I=>I.type!=="page-break").map(I=>I.label).join(", ")}`,A.style.cssText="color:var(--dm-text-muted);font-style:italic;",H.appendChild(A)}},ue();const p=e.find("#editor-tabs").get(0),m=e.find("#preview-card").get(0),h=d=>{m&&m.contains(d.target)||Ie()};p&&(p.addEventListener("input",h),p.addEventListener("change",h));const y=e.get(0),v=[],f=d=>(v.push(d),d);let w=!1;const u=M.observable(!1),x=M.observable(!1);let N=T,q=Ee(e),V=Le(q),_=q;const j=()=>{w||!y.isConnected||(_=Ee(e),u.value=Le(_)!==V)};let $=null;Fe=()=>{clearTimeout($),$=setTimeout(j,150)},f(()=>{clearTimeout($),Fe=null,se=null});const Y=d=>{const g=d.settings||{};e.find("#field-title").val(d.title||""),e.find("#field-slug").val(d.slug||""),e.find("#field-description").val(d.description||""),e.find("#field-bundled").prop("checked",!!d.bundled),me={...d.meta||{}},e.find("#field-project").val(d.meta?.project||""),e.find("#setting-submit-text").val(g.submitText||"Submit"),e.find("#setting-success-message").val(g.successMessage||""),e.find("#setting-layout").val(g.layout||"grid"),e.find("#setting-columns").val(Ce(g.columns)),e.find("#setting-submit-span").val(g.submitSpan||""),e.find("#setting-honeypot").prop("checked",g.honeypot!==!1),e.find("#setting-rate-limit").val(g.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(g.successRedirect||""),e.find("#action-cms-slug").val(g.actionSlug||"");const b=d.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!b.enabled),e.find("#action-email-recipients").val(b.recipients||""),e.find("#action-email-subject-prefix").val(b.subjectPrefix||"");const k=d.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!k.enabled),e.find("#action-webhook-url").val(k.url||""),e.find("#action-webhook-method").val(k.method||"POST"),C=JSON.parse(JSON.stringify(d.fields||[])),c((g.layout||"grid")==="grid"),J(e)};async function W(){if(x.peek()||w)return;const d=Ee(e);if(!d.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}x.value=!0;const g=T;try{T?(await oe(`/forms/${T}`,{method:"PUT",body:JSON.stringify(d)}),E.toast("Form saved.",{type:"success"})):(T=(await oe("/forms",{method:"POST",body:JSON.stringify(d)})).slug,E.toast("Form created.",{type:"success"})),N=T,q=d,V=Le(d),_=d,u.value=!1;for(const b of new Set([ie(g),ie(T)]))try{S.remove?S.remove(b):S.set(b,null)}catch{}Et(y,d.title),Ft("#/forms"),g||R.navigate(`/forms/edit/${T}`)}catch(b){g||(T=null),E.toast(b.message||"Failed to save form.",{type:"error"})}finally{x.value=!1}}async function St(){u.peek()&&(!await E.confirm("Discard the changes you have not saved?")||w||(Y(q),j(),Ge()))}const Me=y.querySelector(".fex-bar");if(Me){const d=M.applyBindings({dirty:u,saving:x},Me,{methods:{save:W,discard:St}});f(()=>d.dispose())}f(At(y,{position:"bottom"})),Te(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>W()}),Te(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),T&&Te(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(T)}/submissions`}});const Pe=d=>{t()||!(d.ctrlKey||d.metaKey)||String(d.key).toLowerCase()!=="s"||(d.preventDefault(),d.stopImmediatePropagation(),W())};document.addEventListener("keydown",Pe,!0),f(()=>document.removeEventListener("keydown",Pe,!0));const X=e.find("#fields-list").get(0),Tt=d=>d?.closest?.(".fb-field-card"),_e=d=>Number(d?.dataset.index),je=d=>d?.querySelector(":scope > .fb-field-body"),Ve=d=>{const g=je(d);g&&(g.style.display=g.style.display==="none"?"":"none")},re=(d,g)=>{C=d,J(e),g!=null&&X?.querySelectorAll(".fb-field-card")[g]?.focus()},Nt=async d=>{try{await navigator.clipboard.writeText(d),E.toast(`Copied "${d}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${d}.`,{type:"info"})}},Lt=d=>{const g=Tt(d),b=_e(g);B();const k=C[b];if(!k)return[];const H=k.type!=="spacer"&&k.type!=="page-break",U=je(g),ce=U&&U.style.display!=="none";return[{header:Ne(k)},...U?[{label:ce?"Close":"Edit",icon:ce?"chevron-up":"edit",action:()=>Ve(g)}]:[],...H?[{label:"Logic & triggers",icon:"zap",action:()=>{U&&(U.style.display=""),(U?.querySelector(".fb-field-logic")||U)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{B(),re(zt(C,b),b+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",disabled:b===0,action:()=>{B(),re(et(C,b,-1),b-1)}},{label:"Move down",icon:"arrow-down",disabled:b>=C.length-1,action:()=>{B(),re(et(C,b,1),b+1)}},...H&&k.name?[{label:"Copy field name",icon:"clipboard",action:()=>Nt(k.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(k.type!=="spacer"&&!await E.confirm(`Remove "${dn(Ne(k))}"?`))return;B();const A=[...C];A.splice(b,1),re(A,Math.min(b,A.length-1))}}]};let He=null;if(X&&E.contextMenu&&(He=E.contextMenu(X,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:d=>Lt(d)}),f(()=>He?.destroy?.())),se=d=>{for(const g of d.querySelectorAll(".fb-field-card")){g.tabIndex=0;const b=g.firstElementChild;if(!b||b.querySelector(".fex-kebab"))continue;const k=document.createElement("button");k.type="button",k.className="fex-kebab",k.textContent="\u22EE",k.title="Actions",B(),k.setAttribute("aria-label",`Actions for ${Ne(C[_e(g)])}`),k.addEventListener("click",H=>{H.stopPropagation(),Qe(k)}),b.appendChild(k)}},X){se(X);const d=g=>{const b=g.target?.classList?.contains("fb-field-card")?g.target:null;b&&(g.key==="F10"&&g.shiftKey?(g.preventDefault(),Qe(b.firstElementChild)):g.key==="Enter"&&(g.preventDefault(),Ve(b)))};X.addEventListener("keydown",d),f(()=>X.removeEventListener("keydown",d))}const Ge=()=>{try{const d=ie(N);S.remove?S.remove(d):S.set(d,null)}catch{}},We=d=>{if(!u.peek()||!d){Ge();return}try{S.set(ie(N),{data:It(d),base:Xe(V),at:new Date().toISOString()})}catch{}},Ue=d=>{j(),u.peek()&&(We(_),d.preventDefault(),d.returnValue="")};window.addEventListener("beforeunload",Ue),f(()=>window.removeEventListener("beforeunload",Ue)),f(()=>{ne&&(document.removeEventListener("click",ne),ne=null)}),G={path:n,dirty:()=>u.peek(),flush:()=>{clearTimeout($),j()},dispose(){w||(We(_),w=!0,v.splice(0).reverse().forEach(d=>{try{d?.()}catch{}}))}};const ke=ie(T);let Z=null;try{Z=S.get(ke)}catch{}if(Z?.data){try{S.remove?S.remove(ke):S.set(ke,null)}catch{}const d=Z.base&&Z.base!==Xe(V),g=Z.at?` (${D(Z.at).format("D MMM HH:mm")})`:"";await E.confirm(`You left unsaved changes to this form${g}.${d?" The saved form has changed since then.":""} Pick up where you left off?`)&&!w&&(Y(Bt(Z.data,q)),j())}}};
|
|
@@ -1 +1,11 @@
|
|
|
1
|
-
import{apiRequest as
|
|
1
|
+
import{apiRequest as A}from"/admin/js/api.js";import{addBannerAction as V}from"/admin/js/lib/plugin-chrome.js";import{helpPopovers as re}from"/admin/js/lib/help-popover.js";import{onceClosed as ke,openMenuAt as ce,sidebarCount as z,viewLifetime as $e}from"/admin/js/lib/tool-kit.js";import{FILTERS as Se,answerFields as Ne,answerText as O,arrangeSubmissions as Me,submissionCounts as Te,submissionRow as L,submissionText as Ae}from"/admin/js/lib/form-submissions-arrange.js";const le=/^#\/forms\/[^/?#]+\/submissions\/?(\?.*)?$/,G="form-submissions.filter",De=`
|
|
2
|
+
<div class="fsx-row" data-id="{{id}}" tabindex="0" data-bind-class="rowCls">
|
|
3
|
+
<span class="fsx-dot" aria-hidden="true"></span>
|
|
4
|
+
<span class="fsx-main"><strong>{{title}}</strong><small>{{meta}}</small></span>
|
|
5
|
+
<span class="fsx-chips">
|
|
6
|
+
<span class="fsx-chip is-ok" data-bind-hidden="!fresh">New</span>
|
|
7
|
+
<span class="fsx-chip is-warn" data-bind-hidden="!spam">Spam</span>
|
|
8
|
+
</span>
|
|
9
|
+
<span class="fsx-when" title="{{whenFull}}">{{when}}</span>
|
|
10
|
+
<button type="button" class="fsx-kebab" aria-label="Actions for this submission" title="Actions">\u22EE</button>
|
|
11
|
+
</div>`,X=i=>String(i??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),U=(i,r,b=`${r}s`)=>`${i} ${i===1?r:b}`,Q=i=>i?D(i).format("DD MMM YYYY HH:mm"):"";async function me(i){try{return await navigator.clipboard.writeText(i),!0}catch{}try{const r=document.createElement("textarea");r.value=i,r.style.cssText="position:fixed;opacity:0;",document.body.appendChild(r),r.select();const b=document.execCommand("copy");return r.remove(),b}catch{return!1}}const h=$e(le);export const formSubmissionsView={templateUrl:"/admin/js/templates/form-submissions.html",async onMount(i){h.reset();const r=i.get(0).querySelector(".fsx")||i.get(0),b=()=>le.test(location.hash)&&r.isConnected,p=decodeURIComponent((location.hash.match(/^#\/forms\/([^/?#]+)\/submissions/)||[])[1]||"");if(!p){E.toast("No form selected.",{type:"error"});return}const C=encodeURIComponent(p),y=M.observable(null),c=M.observable([]),Z=M.observable(!0),q=M.observable("");let ee="inbox";try{ee=Se.includes(S.get(G))?S.get(G):"inbox"}catch{}const w=M.observable(ee),te=M.observable(""),j=M.observable(""),F=M.observable("");h.add(M.effect(()=>{const e=w.value;try{S.set(G,e)}catch{}}));const k=M.computed(()=>Ne(y.value||{})),P=M.observable([]);h.add(M.effect(()=>{const e=Date.now(),t=Me(c.value,{filter:w.value,query:te.value,from:j.value,to:F.value,now:e}),s=k.value;P.value=t.map(n=>{const a=L(n,s,e);return{...a,when:a.at?D(a.at).fromNow():"",whenFull:Q(a.at)}})}));const de=M.computed(()=>Te(c.value)),pe=M.computed(()=>{const e=P.value.length,t=c.value.length;return t?e===t?U(t,"submission"):`${e} of ${U(t,"submission")}`:""}),ue=M.computed(()=>c.value.length?w.value==="spam"?"Nothing marked as spam.":"No submissions match.":"No submissions yet - they appear here as people send the form."),fe=M.computed(()=>y.value?`What people sent through "${y.value.title||p}".`:"What people sent through this form."),R=e=>c.peek().find(t=>String(t.id)===String(e));async function he(){try{const[e,t]=await Promise.all([A(`/forms/${C}`),A(`/forms/${C}/submissions`)]);if(!b())return;y.value=e||null,c.value=Array.isArray(t)?t:[],q.value="",be(e?.title||p)}catch(e){if(!b())return;q.value=`Could not load the submissions: ${e.message||e}`}finally{Z.value=!1}}function be(e){const t=i.get(0).querySelector(".dm-plugin-banner-name"),s=t?.lastChild;s&&s.nodeType===Node.TEXT_NODE&&t.querySelector(".dm-plugin-banner-sep")&&(s.textContent=`${e} submissions`),document.title=`${e} - Submissions - Domma CMS`}async function B(e,t){try{const s=await A(`/forms/${C}/submissions/${encodeURIComponent(e.id)}/spam`,{method:"POST",body:JSON.stringify({spam:t})});return c.value=c.peek().map(n=>String(n.id)===String(e.id)?{...n,data:s?.entry?.data||{...n.data,spam:t}}:n),E.toast(t?"Marked as spam - it is under Spam now.":"Back in the inbox.",{type:"success"}),z("#/forms"),!0}catch(s){return E.toast(`Not changed: ${s.message||s}`,{type:"error"}),!1}}async function Y(e){const t=L(e,k.peek()).title;if(!await E.confirm(`Delete the submission from "${X(t)}"? This cannot be undone.`))return!1;try{return await A(`/forms/${C}/submissions/${encodeURIComponent(e.id)}`,{method:"DELETE"}),c.value=c.peek().filter(s=>String(s.id)!==String(e.id)),E.toast("Submission deleted.",{type:"success"}),z("#/forms"),!0}catch(s){return E.toast(`Not deleted: ${s.message||s}`,{type:"error"}),!1}}async function ye(){const e=c.peek().length;if(!e){E.toast("There are no submissions to clear.",{type:"info"});return}const t=y.peek()?.title||p;if(await E.confirm(`Delete all ${U(e,"submission")} to "${X(t)}", spam included? This cannot be undone - Export them first if you may need them.`))try{await A(`/forms/${C}/submissions`,{method:"DELETE"}),c.value=[],E.toast("All submissions cleared.",{type:"success"}),z("#/forms")}catch(s){E.toast(`Not cleared: ${s.message||s}`,{type:"error"})}}const se=async e=>{const t=Ae(e,k.peek(),{formTitle:y.peek()?.title||p,when:Q(e.meta?.createdAt)});E.toast(await me(t)?"Copied.":"Copy failed.",{type:"info"})},we=async e=>{E.toast(await me(e)?`Copied ${e}.`:"Copy failed.",{type:"info"})},ne=e=>{const t=L(e,k.peek()).email;if(!t)return;const s=`Re: ${y.peek()?.title||p}`;window.location.href=`mailto:${encodeURIComponent(t)}?subject=${encodeURIComponent(s)}`};async function Ee(e,t){try{const s=await fetch(`/api/forms/${C}/submissions/${e}`,{headers:{Authorization:`Bearer ${S.get("auth_token")||""}`}});if(!s.ok)throw new Error(`${s.status} ${s.statusText}`);const n=await s.blob(),a=document.createElement("a");return a.href=URL.createObjectURL(n),a.download=t,document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(a.href),1e3),!0}catch(s){return E.toast(`Export failed: ${s.message||s}`,{type:"error"}),!1}}const H=new Set;function oe(e,t,s="md"){const n=E.slideover({title:X(e),size:s,position:"right"});n.element.appendChild(t);const a=re(t);return H.add(n),ke(n,()=>{H.delete(n),a()}),I.scan(t),n.open(),n}function ve(){const e=c.peek().length,t=document.createElement("div");t.className="fsx-export";const s=document.createElement("p");s.className="fsx-note",s.textContent=e?`All ${U(e,"submission")}, spam included.`:"There are no submissions yet - the file will be empty.",t.appendChild(s);let n;const a=(N,v,_,J,$)=>{const l=document.createElement("button");l.type="button",l.className="btn btn-ghost";const x=document.createElement("span");x.setAttribute("data-icon",v),l.append(x,document.createTextNode(` ${N}`));const T=document.createElement("span");T.setAttribute("data-help",$),l.addEventListener("click",async()=>{await Ee(_,`${p}-submissions.${J}`)&&n?.close()});const o=document.createElement("div");o.append(l,T),t.appendChild(o)};a("Export as CSV","file-text","export","csv","One row per submission, one column per question - opens in Excel, Numbers or Google Sheets."),a("Export as JSON","code","export/json","json","Every submission exactly as stored, with its id and dates - for importing elsewhere or keeping a full copy."),n=oe("Export submissions",t,"sm")}function W(e){if(!e)return;const t=k.peek(),s=L(e,t),n=document.createElement("div");n.className="fsx-detail";const a=document.createElement("div");a.className="fsx-facts";const N=o=>{const m=document.createElement("span");m.textContent=o,a.appendChild(m)};e.meta?.createdAt&&N(`Sent ${Q(e.meta.createdAt)} (${D(e.meta.createdAt).fromNow()})`),e.meta?.ip&&N(`IP ${e.meta.ip}`),s.spam&&N("Marked as spam"),n.appendChild(a);const v=document.createElement("dl");v.className="fsx-answers";const _=t.filter(o=>O(e.data?.[o.name])!=="");for(const o of _){const m=document.createElement("div");m.className="fsx-answer";const f=document.createElement("dt");f.textContent=o.label;const g=document.createElement("dd");g.textContent=O(e.data[o.name]),m.append(f,g),v.appendChild(m)}const J=new Set(t.map(o=>o.name));for(const[o,m]of Object.entries(e.data||{})){if(J.has(o)||o==="spam"||O(m)==="")continue;const f=document.createElement("div");f.className="fsx-answer";const g=document.createElement("dt");g.textContent=`${o} (no longer on the form)`;const d=document.createElement("dd");d.textContent=O(m),f.append(g,d),v.appendChild(f)}if(v.children.length)n.appendChild(v);else{const o=document.createElement("p");o.className="fsx-note",o.textContent="Nothing was filled in.",n.appendChild(o)}const $=document.createElement("div");$.className="fsx-actions";const l=(o,m,f,g)=>{const d=document.createElement("button");d.type="button",d.className=`btn btn-sm ${f}`;const K=document.createElement("span");return K.setAttribute("data-icon",m),K.setAttribute("data-icon-size","13"),d.append(K,document.createTextNode(` ${o}`)),d.addEventListener("click",g),$.appendChild(d),d};let x;l("Copy","copy","btn-ghost",()=>se(e)),s.email&&l("Email them","mail","btn-ghost",()=>ne(e)),l(s.spam?"Not spam":"Mark as spam",s.spam?"inbox":"alert-triangle","btn-ghost",async()=>{await B(e,!s.spam)&&x.close()});const T=document.createElement("span");T.className="fsx-spacer",$.appendChild(T),l("Delete","trash","btn-ghost text-danger",async()=>{await Y(e)&&x.close()}),l("Close","x","btn-ghost",()=>x.close()),n.appendChild($),x=oe(s.title,n)}function xe(e){const t=R(e);if(!t)return[];const s=L(t,k.peek());return[{header:s.title},{label:"Open\u2026",icon:"eye",action:()=>W(t)},{label:"Copy submission",icon:"copy",action:()=>se(t)},{type:"divider"},{label:s.email?`Copy ${s.email}`:"Copy email",icon:"at-sign",disabled:!s.email,action:()=>we(s.email)},{label:"Email them\u2026",icon:"mail",disabled:!s.email,action:()=>ne(t)},{type:"divider"},s.spam?{label:"Not spam - back to the inbox",icon:"inbox",action:()=>B(t,!1)}:{label:"Mark as spam",icon:"alert-triangle",action:()=>B(t,!0)},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>Y(t)}]}const u=r.querySelector(".fsx-list");u.innerHTML=De;const ge=M.applyBindings({loading:Z,loadError:q,filter:w,query:te,from:j,to:F,rows:P,counts:de,summary:pe,emptyText:ue,intro:fe},r,{methods:{showInbox:()=>{w.value="inbox"},showNew:()=>{w.value="new"},showSpam:()=>{w.value="spam"},clearDates:()=>{j.value="",F.value=""}}});h.add(()=>ge.dispose()),h.add(re(r,{position:"bottom"}));const Ce=E.contextMenu(u,{cursor:"glyph",match:".fsx-row",inherit:!1,density:"compact",items:e=>xe(e.dataset.id)});h.add(()=>Ce?.destroy?.());const ae=e=>{const t=e.target.closest(".fsx-row");if(!t)return;const s=e.target.closest(".fsx-kebab");if(s){ce(s);return}W(R(t.dataset.id))},ie=e=>{const t=e.target.closest(".fsx-row");if(!(!t||e.target!==t)){if(e.key==="F10"&&e.shiftKey)e.preventDefault(),ce(t);else if(e.key==="Enter")W(R(t.dataset.id));else if(e.key==="Delete"){e.preventDefault();const s=R(t.dataset.id);s&&Y(s)}}};u.addEventListener("click",ae),u.addEventListener("keydown",ie),h.add(()=>{u.removeEventListener("click",ae),u.removeEventListener("keydown",ie)}),V(i,{id:"form-submissions-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),V(i,{id:"form-submissions-export",icon:"download",title:"Export (CSV or JSON)",onClick:ve}),V(i,{id:"form-submissions-clear",icon:"trash",title:"Clear all submissions",onClick:ye}),h.add(()=>{[...H].forEach(e=>{try{e.close()}catch{}})}),I.scan(r),await he(),b()&&requestAnimationFrame(()=>{u.isConnected&&I.scan(u)})}};
|
package/admin/js/views/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dashboardView as o}from"./dashboard.js";import{pagesView as i}from"./pages.js";import{pageEditorView as r}from"./page-editor.js";import{settingsView as t}from"./settings.js";import{themeView as e}from"./theme.js";import{navigationView as m}from"./navigation.js";import{notificationsView as p}from"./notifications.js";import{layoutsView as n}from"./layouts.js";import{mediaView as s}from"./media.js";import{loginView as f}from"./login.js";import{usersView as w}from"./users.js";import{userEditorView as c}from"./user-editor.js";import{pluginsView as V}from"./plugins.js";import{pluginCodeView as a}from"./plugin-code.js";import{documentationView as d}from"./documentation.js";import{tutorialsView as l}from"./tutorials.js";import{docViews as u}from"./doc-pages.js";import{apiReferenceView as E}from"./api-reference.js";import{collectionsView as g}from"./collections.js";import{collectionEditorView as v}from"./collection-editor.js";import{collectionEntriesView as b}from"./collection-entries.js";import{formsView as h}from"./forms.js";import{formEditorView as y}from"./form-editor.js";import{formSubmissionsView as j}from"./form-submissions.js";import{viewsListView as k}from"./views-list.js";import{viewEditorView as L}from"./view-editor.js";import{viewPreviewView as x}from"./view-preview.js";import{actionsListView as M}from"./actions-list.js";import{actionEditorView as D}from"./action-editor.js";import{proDocsView as P}from"./pro-docs.js";import{blocksView as R}from"./blocks.js";import{blockEditorView as S}from"./block-editor.js";import
|
|
1
|
+
import{dashboardView as o}from"./dashboard.js";import{pagesView as i}from"./pages.js";import{pageEditorView as r}from"./page-editor.js";import{settingsView as t}from"./settings.js";import{themeView as e}from"./theme.js";import{navigationView as m}from"./navigation.js";import{notificationsView as p}from"./notifications.js";import{layoutsView as n}from"./layouts.js";import{mediaView as s}from"./media.js";import{loginView as f}from"./login.js";import{usersView as w}from"./users.js";import{userEditorView as c}from"./user-editor.js";import{pluginsView as V}from"./plugins.js";import{pluginCodeView as a}from"./plugin-code.js";import{documentationView as d}from"./documentation.js";import{tutorialsView as l}from"./tutorials.js";import{docViews as u}from"./doc-pages.js";import{apiReferenceView as E}from"./api-reference.js";import{collectionsView as g}from"./collections.js";import{collectionEditorView as v}from"./collection-editor.js";import{collectionEntriesView as b}from"./collection-entries.js";import{formsView as h}from"./forms.js";import{formEditorView as y}from"./form-editor.js";import{formSubmissionsView as j}from"./form-submissions.js";import{viewsListView as k}from"./views-list.js";import{viewEditorView as L}from"./view-editor.js";import{viewPreviewView as x}from"./view-preview.js";import{actionsListView as M}from"./actions-list.js";import{actionEditorView as D}from"./action-editor.js";import{proDocsView as P}from"./pro-docs.js";import{blocksView as R}from"./blocks.js";import{blockEditorView as S}from"./block-editor.js";import{componentsView as C}from"./components.js";import{componentEditorView as T}from"./component-editor.js";import{myProfileView as U}from"./my-profile.js";import{rolesView as q}from"./roles.js";import{roleEditorView as z}from"./role-editor.js";import{effectsView as A}from"./effects.js";import{searchView as B}from"./search.js";import{notesView as F}from"./notes.js";import{todoView as G}from"./todo.js";import{analyticsView as H}from"./analytics.js";import{contactsView as I}from"./contacts.js";import{menusView as J}from"./menus.js";import{contextMenusView as K}from"./context-menus.js";import{contextMenuEditorView as N}from"./context-menu-editor.js";import{menuEditorView as O}from"./menu-editor.js";import{menuLocationsView as Q}from"./menu-locations.js";import{projectsView as W}from"./projects.js";import{projectDetailView as X}from"./project-detail.js";import{projectSettingsView as Y}from"./project-settings.js";import{apiTokensView as Z}from"./api-tokens.js";import{apiEndpointsView as _}from"./api-endpoints.js";import{apiEndpointEditorView as $}from"./api-endpoint-editor.js";const oo={templateUrl:"",async onMount(){location.hash="#/menus"}};export const views={projects:W,projectDetail:X,projectSettings:Y,apiTokens:Z,apiEndpoints:_,apiEndpointEditor:$,dashboard:o,pages:i,pageEditor:r,settings:t,theme:e,navigation:m,layouts:n,media:s,login:f,users:w,userEditor:c,plugins:V,pluginCode:a,documentation:d,tutorials:l,apiReference:E,collections:g,collectionEditor:v,collectionEntries:b,forms:h,formEditor:y,formSubmissions:j,viewsList:k,viewEditor:L,viewPreview:x,actionsList:M,actionEditor:D,proDocs:P,blocks:R,blockEditor:S,components:C,componentEditor:T,myProfile:U,roles:q,roleEditor:z,effects:A,search:B,notes:F,todo:G,analytics:H,contacts:I,notifications:p,menus:J,contextMenus:K,contextMenuEditor:N,menuEditor:O,menuLocations:Q,menusRedirect:oo,...u};
|
package/admin/js/views/login.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{api as o,isAuthenticated as u,setAuthData as l}from"../api.js";import{themesInDisplayOrder as
|
|
1
|
+
import{api as o,isAuthenticated as u,setAuthData as l,takePendingLogout as p}from"../api.js";import{themesInDisplayOrder as f}from"../lib/themes.js";const h={name:{type:"string",required:!0,minLength:2,label:"Full Name",formConfig:{placeholder:"Your name",autocomplete:"name"}},email:{type:"email",required:!0,label:"Email Address",formConfig:{placeholder:"admin@example.com",autocomplete:"email"}},password:{type:"password",required:!0,minLength:8,label:"Password",formConfig:{placeholder:"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",autocomplete:"new-password",tooltip:"Minimum 8 characters"}}},g={email:{type:"email",required:!0,label:"Email Address",formConfig:{placeholder:"you@example.com",autocomplete:"email"}},password:{type:"password",required:!0,label:"Password",formConfig:{placeholder:"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",autocomplete:"current-password"}}};export const loginView={templateUrl:"/admin/js/templates/login.html",async onMount(e){if(p(),u()){R.navigate("/");return}const a=window.location.hash,t=a.match(/[?&]token=([a-f0-9]{64})/);if(a.startsWith("#/reset-password")&&t){r(e,"reset"),S(e,t[1]),Domma.icons.scan();return}if(a.startsWith("#/reset-password")){R.navigate("/login");return}let s=!1;const i=E.loader(e.get(0),{type:"dots"});try{s=(await o.auth.setupStatus()).needsSetup}catch{E.toast("Could not reach the server.",{type:"error"})}finally{i.destroy()}s?(r(e,"setup"),k(e)):(r(e,"login"),C(e)),Domma.icons.scan()}};const b={email:{type:"email",required:!0,label:"Email Address",formConfig:{placeholder:"you@example.com",autocomplete:"email"}}},w={password:{type:"password",required:!0,minLength:8,label:"New Password",formConfig:{placeholder:"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",autocomplete:"new-password",tooltip:"Minimum 8 characters"}},confirmPassword:{type:"password",required:!0,label:"Confirm Password",formConfig:{placeholder:"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",autocomplete:"new-password"}}},y=["setup","onboarding-site","onboarding-theme","onboarding-done","login","forgot","forgot-success","reset"];function r(e,a){y.forEach(t=>e.find(`#${t}-panel`).hide()),e.find(`#${a}-panel`).show(),Domma.icons.scan()}function d(e,a,t){e.find(`#${a}`).text(t).show()}function k(e){F.render("#setup-form-container",h,{},{layout:"stacked",submitText:"Create admin account",onSubmit:async a=>{try{const t=await o.auth.setup(a);l(t),r(e,"onboarding-site"),v(e)}catch(t){return E.toast(t.message||"Setup failed. Please try again.",{type:"error"}),!1}}})}function v(e){e.find("#ob-site-skip").on("click",a=>{a.preventDefault(),r(e,"onboarding-theme"),c(e),m(e)}),e.find("#ob-site-btn").on("click",async()=>{e.find("#ob-site-error").hide();const a=e.find("#ob-title").val().trim(),t=e.find("#ob-tagline").val().trim(),s=e.find("#ob-site-btn").prop("disabled",!0).text("Saving\u2026");try{const i=await o.settings.get();await o.settings.save({...i,title:a||i.title,tagline:t||i.tagline,seo:{...i.seo||{},defaultTitle:a||i.seo&&i.seo.defaultTitle}});const n=await o.navigation.get();await o.navigation.save({...n,brand:{...n.brand||{},text:a||n.brand.text}}),r(e,"onboarding-theme"),c(e),m(e)}catch(i){d(e,"ob-site-error",i.message||"Could not save site details.")}finally{s.prop("disabled",!1).text("Continue")}})}function c(e){const a=e.find("#theme-grid").empty();f().forEach(t=>{const s=$(`
|
|
2
2
|
<div class="theme-swatch" data-theme="${t.id}" title="${t.id}">
|
|
3
3
|
<div class="theme-swatch-preview" style="background:${t.bg}">
|
|
4
4
|
<div class="theme-swatch-accent" style="background:${t.primary}"></div>
|
|
@@ -8,4 +8,4 @@ import{api as o,isAuthenticated as u,setAuthData as l}from"../api.js";import{the
|
|
|
8
8
|
<span class="theme-swatch-mode">${t.dark?"Dark":"Light"}</span>
|
|
9
9
|
</div>
|
|
10
10
|
</div>
|
|
11
|
-
`);
|
|
11
|
+
`);s.on("click",()=>{e.find(".theme-swatch").removeClass("selected"),s.addClass("selected")}),a.append(s)}),e.find('[data-theme="charcoal-dark"]').addClass("selected")}function m(e){e.find("#ob-theme-skip").on("click",a=>{a.preventDefault(),r(e,"onboarding-done")}),e.find("#ob-theme-btn").on("click",async()=>{e.find("#ob-theme-error").hide();const a=e.find(".theme-swatch.selected").attr("data-theme")||"charcoal-dark",t=e.find("#ob-theme-btn").prop("disabled",!0).text("Applying\u2026");try{const s=await o.settings.get();await o.settings.save({...s,theme:a}),r(e,"onboarding-done")}catch(s){d(e,"ob-theme-error",s.message||"Could not save theme.")}finally{t.prop("disabled",!1).text("Apply theme")}})}function C(e){F.render("#login-form-container",g,{},{layout:"stacked",submitText:"Sign in",onSubmit:async a=>{try{const t=await o.auth.login(a);l(t),R.navigate("/")}catch(t){return E.toast(t.message||"Invalid credentials. Please try again.",{type:"error"}),!1}}}),e.find("#forgot-link").on("click",a=>{a.preventDefault(),r(e,"forgot"),x(e)})}function x(e){F.render("#forgot-form-container",b,{},{layout:"stacked",submitText:"Send reset link",onSubmit:async t=>{try{await o.auth.forgotPassword(t.email)}catch{}r(e,"forgot-success"),Domma.icons.scan()}});const a=t=>{t.preventDefault(),r(e,"login")};e.find("#forgot-back-link").on("click",a),e.find("#forgot-success-back-link").on("click",a)}function S(e,a){F.render("#reset-form-container",w,{},{layout:"stacked",submitText:"Set new password",onSubmit:async t=>{if(t.password!==t.confirmPassword)return E.toast("Passwords do not match.",{type:"error"}),!1;try{await o.auth.resetPassword(a,t.password),E.toast("Password updated. Please sign in.",{type:"success"}),window.location.hash="#/login"}catch(s){return E.toast(s.message||"Link expired or invalid.",{type:"error"}),!1}}})}
|