From 930e00c70c16268c393b8e0a69878b12c71a40b8 Mon Sep 17 00:00:00 2001 From: prismiwi2015 Date: Sun, 13 Sep 2026 23:11:12 +0200 Subject: [PATCH] Fix condition dialogs and total display for 1.0.1 --- allterrain-forms.php | 4 +- assets/css/builder.css | 109 ++++++++++++++++++++----- assets/css/form.css | 10 ++- assets/js/builder.js | 53 +++++++----- assets/js/builder.min.js | 8 +- assets/js/form.js | 6 +- assets/js/form.min.js | 2 +- docs/field-types.md | 11 +++ docs/javascript.md | 11 ++- includes/field-types.php | 1 + includes/render-controls.php | 31 ++++--- includes/schema.php | 4 + package-lock.json | 4 +- package.json | 2 +- readme.txt | 11 ++- src/builder.ts | 46 +++++++---- src/field-preview.ts | 11 ++- src/form.ts | 8 +- tests/phpunit/tests/render.php | 54 ++++++++++++ tests/phpunit/tests/schema.php | 19 +++++ tests/vitest/condition-toolbar.test.ts | 33 +++++--- tests/vitest/total-display.test.ts | 57 +++++++++++++ 22 files changed, 397 insertions(+), 98 deletions(-) create mode 100644 tests/vitest/total-display.test.ts diff --git a/allterrain-forms.php b/allterrain-forms.php index ba77621..9b7ff58 100644 --- a/allterrain-forms.php +++ b/allterrain-forms.php @@ -3,7 +3,7 @@ * Plugin Name: AllTerrain Forms * Plugin URI: https://github.com/AllTerrainDeveloper/forms * Description: Forms for WordPress with every premium feature free — conditional logic, calculations, multi-page, file uploads, signatures, repeaters, entry management, ten themes — built as an OpenStation desktop app with a drag-and-drop builder. - * Version: 1.0.0 + * Version: 1.0.1 * Requires at least: 6.9 * Requires PHP: 7.4 * Requires Plugins: desktop-mode @@ -55,7 +55,7 @@ defined( 'ABSPATH' ) || exit; -define( 'ALLTFO_VERSION', '1.0.0' ); +define( 'ALLTFO_VERSION', '1.0.1' ); define( 'ALLTFO_FILE', __FILE__ ); define( 'ALLTFO_DIR', plugin_dir_path( __FILE__ ) ); define( 'ALLTFO_URL', plugin_dir_url( __FILE__ ) ); diff --git a/assets/css/builder.css b/assets/css/builder.css index f6dacde..df4281d 100644 --- a/assets/css/builder.css +++ b/assets/css/builder.css @@ -4053,6 +4053,59 @@ os-checkbox-label.atfb-check { } } +/* Condition dialogs use the shell's dialog palette, including themed textures. */ +.atfb-condition-editor, +.atfb-condition-copy { + --atfb-bg: var( --os-ui-modal-bg, var( --os-window-bg, #fff ) ); + --atfb-fg: var( --os-ui-modal-text, var( --os-ui-fg, #1e1e1e ) ); + --atfb-muted: var( --os-ui-modal-text-muted, var( --os-ui-fg-muted, #646970 ) ); + --atfb-border: var( --os-ui-modal-border, var( --os-ui-border, #dcdcde ) ); + --atfb-border-strong: var( --os-ui-modal-border-strong, var( --os-ui-border-strong, #c3c4c7 ) ); + --atfb-well: var( --os-ui-modal-field-bg, var( --os-ui-surface-sunken, #f6f7f7 ) ); + --atfb-surface: var( --os-ui-modal-surface, var( --os-ui-surface, #fff ) ); + --atfb-raised: var( --os-ui-modal-surface-elevated, var( --os-ui-surface-elevated, #f6f7f7 ) ); + --atfb-hover: var( --os-ui-modal-hover, var( --os-ui-hover, rgba( 0, 0, 0, 0.04 ) ) ); + color: var( --atfb-fg ); + background-color: var( --atfb-bg ); + background-image: var( --os-ui-dialog-bg-image, none ); + background-repeat: var( --os-ui-dialog-bg-image-repeat, repeat ); + background-size: var( --os-ui-dialog-bg-image-size, auto ); + background-position: var( --os-ui-dialog-bg-image-position, center ); + border: 1px solid var( --atfb-border ); + border-radius: var( --os-window-radius, var( --atfb-radius ) ); + box-shadow: var( --os-window-shadow-focused, 0 20px 60px rgba( 0, 0, 0, 0.35 ) ); +} + +/* Component hosts inherit the same modal palette as the native controls. */ +:is( .atfb-condition-editor, .atfb-condition-copy ) :is( os-select, os-button, os-checkbox-label ) { + --os-ui-fg: var( --atfb-fg ); + --os-ui-fg-muted: var( --atfb-muted ); + --os-ui-border: var( --atfb-border ); + --os-ui-border-strong: var( --atfb-border-strong ); + --os-window-bg: var( --atfb-well ); + --os-ui-surface: var( --atfb-surface ); + --os-ui-surface-elevated: var( --atfb-raised ); + --os-ui-hover: var( --atfb-hover ); + --os-ui-button-bg-hover: var( --os-ui-modal-button-bg-hover, var( --atfb-hover ) ); +} + +:is( .atfb-condition-editor, .atfb-condition-copy ) h2 { + color: var( --atfb-fg ); +} + +.atfb-logic-actions { + display: flex; + justify-content: flex-end; + margin-block-start: var( --atfb-gap ); +} + +.atfb-copy-condition { + display: inline-flex; + align-items: center; + gap: 6px; + white-space: nowrap; +} + /* Keep copied conditions readable even when a rule contains a long answer. */ .atfb-condition-copy__preview { padding: 12px; @@ -4241,7 +4294,7 @@ os-checkbox-label.atfb-check { .atfb-condition-editor { inline-size: min( 580px, 100% ); - padding: 24px; + padding: calc( 2 * var( --atfb-gap ) ); } .atfb-condition-editor__heading { @@ -4267,22 +4320,11 @@ os-checkbox-label.atfb-check { place-items: center; inline-size: 40px; block-size: 40px; - border-radius: 10px; + border-radius: var( --atfb-radius-ctl ); background: var( --atfb-accent-soft ); color: var( --atfb-accent ); } -.atfb-condition-editor__switch { - padding-block-end: 18px; - border-block-end: 1px solid var( --atfb-border ); -} - -.atfb-condition-editor__switch p { - margin: 6px 0 0; - font-size: 12px; - color: var( --atfb-muted ); -} - .atfb-condition-editor__sentence { display: flex; align-items: center; @@ -4293,13 +4335,6 @@ os-checkbox-label.atfb-check { color: var( --atfb-muted ); } -.atfb-condition-editor__empty { - margin-block: 20px; - font-size: 13px; - line-height: 1.6; - color: var( --atfb-muted ); -} - .atfb-condition-editor .atfb-rule { display: grid; grid-template-columns: minmax( 0, 1.2fr ) minmax( 0, 1fr ) minmax( 100px, 0.6fr ) auto; @@ -4328,12 +4363,16 @@ os-checkbox-label.atfb-check { } .atfb-condition-editor__footer .atfb-modal__actions { + flex-wrap: wrap; margin: 0; + margin-inline-start: auto; } .atfb-condition-editor .atfb-rule input { + background: var( --atfb-well ); + color: var( --atfb-fg ); border: 1px solid var( --atfb-border ); - border-radius: 6px; + border-radius: var( --atfb-radius-ctl ); min-inline-size: 100px; inline-size: 100%; } @@ -4343,3 +4382,31 @@ os-checkbox-label.atfb-check { .atfb-rule input { min-inline-size: 100px; } + +@media ( max-width: 600px ) { + .atfb-condition-editor .atfb-rule { + grid-template-columns: minmax( 0, 1fr ) auto; + } + + .atfb-condition-editor .atfb-rule__top > .atfb-card__action { + grid-column: 2; + } + + .atfb-condition-editor .atfb-rule > :not( .atfb-rule__top ) { + grid-column: 1; + } +} + +.atfb-condition-editor .atfb-card__action { + color: var( --atfb-muted ); + border-radius: var( --atfb-radius-ctl ); +} + +.atfb-condition-editor .atfb-card__action:hover { + color: var( --atfb-danger ); + background: var( --atfb-danger-soft ); +} + +.atfb-condition-editor input::placeholder { + color: var( --atfb-muted ); +} diff --git a/assets/css/form.css b/assets/css/form.css index 88f9402..f4d22f0 100644 --- a/assets/css/form.css +++ b/assets/css/form.css @@ -894,11 +894,19 @@ color: var( --atf-text-muted ); } -.atf-form .atf-total__input { +.atf-form .atf-total__input, +.atf-total__output { font-variant-numeric: tabular-nums; font-weight: 600; } +.atf-total__output { + display: block; + color: var( --atf-text ); + font-size: var( --atf-size-base ); + overflow-wrap: anywhere; +} + /* -------------------------------------------------------------------------- */ /* Composite and repeater */ /* -------------------------------------------------------------------------- */ diff --git a/assets/js/builder.js b/assets/js/builder.js index 4ec20f6..8aa9563 100644 --- a/assets/js/builder.js +++ b/assets/js/builder.js @@ -1143,7 +1143,7 @@ var allTerrainFormsBuilder = function(exports) { color: "text", name: "composite", address: "composite", - total: "text", + total: "total", hidden: "static", heading: "static", html: "static", @@ -1254,6 +1254,11 @@ var allTerrainFormsBuilder = function(exports) { } function control(field, type, shape, handlers) { switch (shape) { + case "total": + return el("div", { class: "atf-total", children: [ + field.currency ? el("span", { class: "atf-total__currency", text: String(field.currency) }) : null, + field.display === "output" ? el("output", { class: "atf-total__output", text: "0.00" }) : el("input", { class: "atf-input atf-total__input", type: "text", value: "0.00", attrs: { disabled: true } }) + ] }); case "text": return placeholderBox(field, "atf-input", handlers); case "textarea": @@ -5274,6 +5279,13 @@ var allTerrainFormsBuilder = function(exports) { row("Currency symbol", textInput(String(field.currency ?? ""), (value) => update("currency", value))) ); } + if (field.type === "total") { + this.inspector.append(row("Display total as", select( + String(field.display ?? "input"), + [{ value: "output", label: "Plain text" }, { value: "input", label: "Disabled input" }], + (value) => update("display", value) + ))); + } this.inspector.append(this.renderValidationSection(field, supports, update)); if (!parent) { this.inspector.append(this.renderLogicSection(field)); @@ -6841,7 +6853,8 @@ var allTerrainFormsBuilder = function(exports) { if (!field) { return; } - const draft = { ...field.logic, rules: field.logic.rules.map((rule) => ({ ...rule })) }; + const hadRules = field.logic.rules.length > 0; + const draft = { ...field.logic, enabled: true, rules: field.logic.rules.map((rule) => ({ ...rule })) }; const overlay = el("div", { class: "atfb-overlay" }); const dialog = el("div", { class: "atfb-modal atfb-condition-editor", @@ -6870,7 +6883,7 @@ var allTerrainFormsBuilder = function(exports) { }); match.setAttribute("aria-label", "Match rules"); const copy = el("button", { - class: "atfb-copy-condition", + class: "atfb-button atfb-copy-condition", type: "button", children: [icon("admin-page"), el("span", { text: "Copy condition" })], on: { click: () => openConditionCopy({ @@ -6881,6 +6894,7 @@ var allTerrainFormsBuilder = function(exports) { fields: this.schema.fields.map((item) => item.id === fieldId ? { ...item, logic: draft } : item) } : null, onCopy: () => { + draft.enabled = true; paint(); dialog.focus(); } @@ -6891,23 +6905,21 @@ var allTerrainFormsBuilder = function(exports) { el("span", { class: "atfb-condition-editor__icon", children: [icon("randomize")] }), el("div", { children: [el("h2", { text: "Conditional logic" }), el("p", { text: field.label || "Untitled field" })] }) ] }), - el("div", { class: "atfb-condition-editor__switch", children: [ - checkbox("Enable conditions", draft.enabled, (enabled) => { - draft.enabled = enabled; - paint(); - }), - el("p", { text: "Choose when this field appears in your form." }) - ] }), - ...draft.enabled ? [ - el("div", { class: "atfb-condition-editor__sentence", children: [action, "this field when", match, "of these rules match:"] }), - ...this.logicRulesEditor(draft, write, fieldId) - ] : [el("p", { class: "atfb-condition-editor__empty", text: "This field is always visible. Enable conditions to choose when to show or hide it." })], + el("p", { class: "atfb-hint", text: "Choose when this field appears in your form." }), + el("div", { class: "atfb-condition-editor__sentence", children: [action, "this field when", match, "of these rules match:"] }), + ...this.logicRulesEditor(draft, write, fieldId), el("div", { class: "atfb-condition-editor__footer", children: [ copy, el("div", { class: "atfb-modal__actions", children: [ - button("Cancel", close), + button("Clear", () => { + this.snapshot(); + this.editCondition(fieldId, (live) => Object.assign(live, { enabled: false, action: "show", match: "all", rules: [] })); + this.snapshot(); + close(); + }), + ...hadRules || draft.rules.length ? [button("Cancel", close)] : [], button("Save conditions", () => { - if (!this.liveField(fieldId)) { + if (!this.liveField(fieldId) || !draft.rules.length) { close(); return; } @@ -6919,6 +6931,9 @@ var allTerrainFormsBuilder = function(exports) { ] }) ] }) ); + if (!draft.rules.length) { + dialog.querySelector(".atfb-button--primary")?.setAttribute("disabled", ""); + } if (focusedIndex >= 0) { const controls = dialog.querySelectorAll(controlsSelector); controls[Math.min(focusedIndex, controls.length - 1)]?.focus(); @@ -8339,7 +8354,7 @@ var allTerrainFormsBuilder = function(exports) { /** Reuse a condition, resolving the schema when the chooser applies it. */ copyConditionButton(key) { return el("button", { - class: "atfb-copy-condition", + class: "atfb-button atfb-copy-condition", type: "button", children: [icon("admin-page"), el("span", { text: "Copy condition" })], on: { click: () => openConditionCopy({ @@ -8377,7 +8392,6 @@ var allTerrainFormsBuilder = function(exports) { `logic:${field.id}`, "Conditional logic", [ - this.copyConditionButton(`field:${field.id}`), checkbox("Only show this field sometimes", logic.enabled, (value) => { write((live) => { live.enabled = value; @@ -8414,7 +8428,8 @@ var allTerrainFormsBuilder = function(exports) { }), ...editor ] - }) : null + }) : null, + el("div", { class: "atfb-logic-actions", children: [this.copyConditionButton(`field:${field.id}`)] }) ], // A field that already has a condition opens showing it: being told a // rule governs this field and not what it says is the problem the diff --git a/assets/js/builder.min.js b/assets/js/builder.min.js index dfc09e3..bd4cfba 100644 --- a/assets/js/builder.min.js +++ b/assets/js/builder.min.js @@ -1,5 +1,5 @@ -var allTerrainFormsBuilder=function(ee){"use strict";class as{constructor(){this.targets=[],this.active=null,this.lastEndMs=0}start(e){if(this.active||e.origin.button!==0)return null;const{payload:s,origin:t}=e,a=t.clientX,i=t.clientY;let o=!1,l=!1,c=null,d=null,h=0,m=0;const g=()=>{document.removeEventListener("pointermove",x),document.removeEventListener("pointerup",F),document.removeEventListener("pointercancel",S),document.removeEventListener("keydown",j),window.removeEventListener("blur",S),c?.remove(),c=null,s.source.classList.remove("atf-is-dragging"),document.body.classList.remove("atf-drag-active"),d?.onLeave?.(f),d=null,this.active=null,this.lastEndMs=Date.now()},u=(L,b)=>{document.dispatchEvent(new CustomEvent(L,{detail:{payload:s,clientX:b?.clientX,clientY:b?.clientY}}))},f={payload:s,isFinished:()=>l,cancel:(L="caller")=>{l||(l=!0,g(),o&&u("os.drag.end"),e.onCancel?.(L))}},y=L=>{o=!0,s.source.classList.add("atf-is-dragging"),document.body.classList.add("atf-drag-active");const b=s.source.getBoundingClientRect();h=s.ghost?.offsetX??a-b.left,m=s.ghost?.offsetY??i-b.top,c=s.ghost?.element??s.source.cloneNode(!0),c.classList.add("atf-drag-ghost"),c.style.width=`${b.width}px`,document.body.appendChild(c),p(L),u("os.drag.start",L)},p=L=>{c&&(c.style.transform=`translate3d(${L.clientX-h}px, ${L.clientY-m}px, 0)`)},x=L=>{if(l)return;if(!o){if(Math.hypot(L.clientX-a,L.clientY-i)<4)return;y(L)}p(L);const b=this.hitTest(L.clientX,L.clientY);b!==d&&(d?.onLeave?.(f),d=b,d?.onEnter?.(f)),u("os.drag.move",L)},F=L=>{if(l)return;if(!o){l=!0,g(),e.onClickOnly?.();return}const b=d;if(l=!0,g(),b&&b.accept(s)){e.onCommit?.(b),b.onDrop(f,{clientX:L.clientX,clientY:L.clientY}),u("os.drag.end",L);return}u("os.drag.end",L),e.onCancel?.(b?"rejected":"no-target")},S=()=>f.cancel("pointercancel"),j=L=>{L.key==="Escape"&&f.cancel("escape")};return document.addEventListener("pointermove",x),document.addEventListener("pointerup",F),document.addEventListener("pointercancel",S),document.addEventListener("keydown",j),window.addEventListener("blur",S),this.active=f,f}registerDropTarget(e){return this.targets=this.targets.filter(s=>s.id!==e.id),this.targets.push(e),()=>{this.targets=this.targets.filter(s=>s.id!==e.id)}}isDragging(){return this.active!==null}recentlyEndedDrag(e=500){return Date.now()-this.lastEndMso.right||so.bottom)continue;const l=is(i.element);if(l>a){t=i,a=l;continue}l===a&&t&&rs(i.element,t.element)&&(t=i)}return t}}function is(n){let e=0,s=n;for(;s;)e++,s=s.parentElement;return e}function rs(n,e){return(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)!==0}function Le(){return window.wp?.os??null}let $e=null;function G(){const n=Le();return n?.dragManager?n.dragManager:($e||($e=new as),$e)}function os(n){const e=i=>{const o=i.detail?.payload;return o&&n.includes(o.type)?o.source:null},s=i=>i.preventDefault(),t=i=>{const o=e(i);o&&(o.classList.add("atf-is-dragging"),document.body.classList.add("atf-drag-active"),window.getSelection()?.removeAllRanges(),document.addEventListener("selectstart",s))},a=i=>{const o=e(i);o&&(o.classList.remove("atf-is-dragging"),document.body.classList.remove("atf-drag-active"),document.removeEventListener("selectstart",s))};return document.addEventListener("os.drag.start",t),document.addEventListener("os.drag.end",a),()=>{document.removeEventListener("os.drag.start",t),document.removeEventListener("os.drag.end",a),document.removeEventListener("selectstart",s)}}const ls=["atfb","atfe","atfs","atfm"];function Ae(n,e,s,t,a){const i=e.getBoundingClientRect();if(!a){const o=ls.find(l=>e.closest(`.${l}`));if(o){const l=e.cloneNode(!0);l.style.transition="",l.style.transform="",a=document.createElement("div"),a.className=`${o} atf-ghost-scope`,a.appendChild(l)}}return a&&(a.style.width=`${Math.round(i.width)}px`,a.style.maxWidth=`${Math.round(i.width)}px`,a.style.boxSizing="border-box"),{type:n,source:e,data:s,ghost:{element:a,offsetX:t.clientX-i.left,offsetY:t.clientY-i.top,hint:{neutral:"",accept:"",reject:"",hidden:!0}}}}function st(n,e,s,t){const a=Array.from(n.querySelectorAll(e)).filter(i=>i!==t&&!i.classList.contains("atf-drag-ghost"));for(let i=0;ia.fetch(l,c,{source:"allterrain-forms"}):(l,c)=>fetch(l,c))(s,{credentials:"same-origin",...e,headers:t});if(!o.ok){let l=`Request failed with status ${o.status}.`,c="";try{const d=await o.json();l=d.message??l,c=d.code??""}catch{}throw new he(l,o.status,c)}if(o.status!==204)return await o.json()}const z=n=>Te(n);async function cs(n){if(!U?.wpRestUrl)throw new he("AllTerrain Forms is not configured on this page.",0);const e=U.nonce?{"X-WP-Nonce":U.nonce}:{},s=Le(),t=nt(U.wpRestUrl,n),a=s?.fetch?await s.fetch(t,{credentials:"same-origin",headers:e},{source:"allterrain-forms"}):await fetch(t,{credentials:"same-origin",headers:e});if(!a.ok)throw new he(`Request failed with status ${a.status}.`,a.status);return await a.json()}function ds(n){if(!n||!n.includes("&"))return n;const e=document.createElement("textarea");return e.innerHTML=n,e.value}const X=(n,e)=>Te(n,{method:"POST",body:JSON.stringify(e)}),ue=n=>Te(n,{method:"DELETE"});function at(n){const e=new URLSearchParams;for(const[t,a]of Object.entries(n))a===void 0||a===""||a===!1||e.set(t,String(a));const s=e.toString();return s?`?${s}`:""}function pe(n){const e=n?.schema?.settings;return e&&(!e.themeOverrides||Array.isArray(e.themeOverrides))&&(e.themeOverrides={...e.themeOverrides}),n}const I={config:()=>z("/config"),mailpoet:()=>z("/mailpoet"),listForms:()=>z("/forms"),listArchivedForms:()=>z("/forms?archived=1"),archiveForm:n=>X(`/forms/${n}/archive`,{}),unarchiveForm:n=>X(`/forms/${n}/unarchive`,{}),getForm:n=>z(`/forms/${n}`).then(pe),createForm:n=>X("/forms",n).then(pe),updateForm:(n,e)=>X(`/forms/${n}`,e).then(pe),duplicateForm:n=>X(`/forms/${n}/duplicate`,{}).then(pe),deleteForm:n=>ue(`/forms/${n}`),preview:(n,e)=>X(`/forms/${n}/preview`,e),pages:()=>cs("wp/v2/pages?per_page=100&status=publish&orderby=title&order=asc&_fields=id,title").then(n=>n.map(e=>({id:e.id,title:ds(e.title?.rendered??"")||`#${e.id}`}))),mergeTags:n=>z(`/forms/${n}/merge-tags`).then(e=>e.groups),analytics:(n,e="")=>z(`/forms/${n}/analytics${e?`?dimension=${encodeURIComponent(e)}`:""}`),demoStatus:()=>z("/demo"),demoSeed:n=>X("/demo",n?{count:n}:{}),demoRemove:()=>ue("/demo"),listEntries:n=>z(`/entries${at(n)}`),getEntry:n=>z(`/entries/${n}`),updateEntry:(n,e)=>X(`/entries/${n}`,e),deleteEntry:n=>ue(`/entries/${n}`),exportEntries:n=>z(`/entries/export${at(n)}`),listThemes:()=>z("/themes"),saveTheme:n=>X("/themes",n),deleteTheme:n=>ue(`/themes/${n}`)};function it(n,e,s={}){if(!n)return null;let t;const a=(o,l)=>{const c=n[o];return c==null||!Number.isFinite(Number(c))?l:Number(c)},i=(o,l,c=1)=>Array.from({length:Math.floor((l-o)/c+1e-9)+1},(d,h)=>{const m=String(Number((o+h*c).toPrecision(12)));return{value:m,label:m}});if(n.type==="scale"){const o=Math.trunc(a("min",0));let l=Math.trunc(a("max",10));l<=o&&(l=o+10),t=i(o,Math.min(l,o+20))}else if(n.type==="rating")t=i(1,Math.max(2,Math.min(10,Math.abs(Math.trunc(a("max",5))))));else if(n.type==="switch"||n.type==="consent")t=[{value:"1",label:"Checked"},{value:"",label:"Unchecked"}];else if(n.type==="country")t=Object.entries(s).map(([o,l])=>({value:o,label:l}));else if(n.type==="range"){const o=a("min",0),l=a("max",100),c=n.step==="any"?0:a("step",1);if(c<=0||l999)return null;t=i(o,l,c)}else if(n.choices?.length||["select","multiselect","radio","checkboxes","image_choice","quiz","likert"].includes(n.type))t=(n.choices??[]).map(o=>({value:o.value,label:o.label||o.value}));else return null;return!t.some(o=>o.value===e)&&e!==""&&t.unshift({value:e,label:`${e} (stored value; unavailable)`,disabled:!0}),t.some(o=>o.value==="")||t.unshift({value:"",label:"Choose a value…",disabled:!0}),t}function r(n,e={}){const s=document.createElement(n);e.class&&(s.className=e.class),e.text!==void 0&&(s.textContent=e.text),e.html!==void 0&&(s.innerHTML=e.html),e.title&&(s.title=e.title),e.type&&"type"in s&&(s.type=e.type),e.value!==void 0&&"value"in s&&(s.value=e.value),e.placeholder!==void 0&&"placeholder"in s&&(s.placeholder=e.placeholder),e.href&&"href"in s&&(s.href=e.href);for(const[t,a]of Object.entries(e.attrs??{}))a===void 0||a===!1||s.setAttribute(t,a===!0?"":String(a));Object.assign(s.style,e.style??{});for(const[t,a]of Object.entries(e.on??{}))s.addEventListener(t,a);for(const t of e.children??[])t==null||t===!1||s.append(t);return s}function R(n){n.replaceChildren()}function B(n){return r("span",{class:`dashicons ${n.startsWith("dashicons-")?n:`dashicons-${n}`}`,attrs:{"aria-hidden":"true"}})}function w(n,e,s){const t=e.matches("input, select, textarea, button")?e:e.querySelector("input, select, textarea");if(t){const a=t.id||`atf-c-${Math.random().toString(36).slice(2,9)}`;return t.id=a,r("div",{class:"atfb-row",children:[r("label",{class:"atfb-row__label",text:n,attrs:{for:a}}),e,s?r("p",{class:"atfb-row__hint",text:s}):null]})}return r("div",{class:"atfb-row",children:[r("span",{class:"atfb-row__label",text:n}),e,s?r("p",{class:"atfb-row__hint",text:s}):null]})}function T(n,e,s=""){return r("input",{class:"atfb-input",type:"text",value:n,placeholder:s,on:{input:t=>e(t.target.value)}})}function V(n,e){if(Y("os-number-field")){const s=document.createElement("os-number-field");return s.setAttribute("value",n),s.classList.add("atfb-field"),s.addEventListener("os-input-change",t=>{e(String(t.detail?.value??""))}),s}return r("input",{class:"atfb-input",type:"number",value:n,on:{input:s=>e(s.target.value)}})}function fe(n,e,s=4){const t=r("textarea",{class:"atfb-input atfb-input--area",attrs:{rows:s},on:{input:a=>e(a.target.value)}});return t.value=n,t}function D(n,e,s){if(Y("os-select")&&Y("os-option")){const t=document.createElement("os-select");t.setAttribute("value",n),t.classList.add("atfb-field");for(const a of e){const i=document.createElement("os-option");i.setAttribute("value",a.value),a.disabled&&i.setAttribute("disabled",""),i.textContent=a.label,t.append(i)}return t.addEventListener("os-pick",a=>{s(String(a.detail?.value??""))}),t}return r("select",{class:"atfb-input atfb-select",on:{change:t=>s(t.target.value)},children:e.map(t=>r("option",{value:t.value,text:t.label,attrs:{selected:t.value===n,disabled:t.disabled}}))})}function q(n,e,s){if(Y("os-checkbox-label")){const a=document.createElement("os-checkbox-label");return a.setAttribute("label",n),a.classList.add("atfb-check"),e&&a.setAttribute("checked",""),a.addEventListener("os-checkbox-change",i=>{s(!!i.detail?.checked)}),a}const t=r("input",{type:"checkbox",on:{change:a=>s(a.target.checked)}});return t.checked=e,r("label",{class:"atfb-check",children:[t,r("span",{text:n})]})}function C(n,e,s="secondary",t){const a=[t?B(t):null,r("span",{text:n})];if(Y("os-button")){const i=document.createElement("os-button");i.setAttribute("variant",s),i.setAttribute("type","button"),i.classList.add("atfb-button",`atfb-button--${s}`),i.addEventListener("click",e);for(const o of a)o&&i.append(o);return i}return r("button",{class:`atfb-button atfb-button--${s}`,type:"button",on:{click:e},children:a})}function Y(n){return typeof customElements<"u"&&!!customElements.get(n)}const hs=["os-button","os-checkbox-label","os-number-field","os-select","os-option","os-segmented","os-segment","os-color-field","os-empty-state"];let me=null;function us(){if(me)return me;const n=window.wp?.os;return me=n?.loadComponents?n.loadComponents(hs).catch(()=>{}):Promise.resolve(),me}async function ie(n,e=""){const s=window.wp?.os;return s?.confirm?s.confirm({title:e,message:n,danger:!0}):window.confirm(n)}function N(n,e="",s="info"){const t=window.wp?.os;if(t?.notify){t.notify({title:n,body:e,type:s});return}console.info(`[AllTerrain Forms] ${n}${e?`: ${e}`:""}`)}function ps(n){let e=0,s;return(...t)=>{s=t,!e&&(e=window.requestAnimationFrame(()=>{e=0,n(...s)}))}}function Me(n,e){let s=0;return(...t)=>{window.clearTimeout(s),s=window.setTimeout(()=>n(...t),e)}}function fs(n){try{return window.localStorage.getItem(n)??""}catch{return""}}function ms(n,e){try{window.localStorage.setItem(n,e)}catch{}}function Fe(n){const e=n.closest(".os-window__body");e&&(e.addEventListener("scroll",()=>{e.scrollTop&&(e.scrollTop=0),e.scrollLeft&&(e.scrollLeft=0)},{passive:!0}),e.scrollTop=0,e.scrollLeft=0)}function rt(){const n=[window];try{window.parent&&window.parent!==window&&n.push(window.parent)}catch{}return n}function bs(n){const e=n.wp?.os?.windowManager?.getAll?.()??[];for(const s of e){const t=s.iframe??s.element?.querySelector?.("iframe");if(t&&t.contentWindow===window)return s}return null}const gs=4e3,vs=100;function ys(n,e){const s=Date.now()+gs,t=()=>{const a=bs(n);if(a&&a.id!==e){typeof a.close=="function"?a.close():n.wp?.os?.windowManager?.remove?.(a.id);return}!a&&Date.now()0?{form:s}:void 0;s>0&&ks(s);for(const a of rt())if(a.wp?.os?.openWindow?.(e,{source:"handoff",params:t})){window.setTimeout(()=>ys(a,e),0);return}}function _s(){document.addEventListener("click",n=>{const e=n.target?.closest?.("[data-atf-open-window]");if(!e)return;n.preventDefault();const s=e.getAttribute("data-atf-open-window")??"";for(const t of rt())if(t.wp?.os?.openWindow?.(s,{source:"handoff"}))return})}const xs="allterrain-forms/requested-form";function ks(n){try{window.sessionStorage.setItem(xs,String(n))}catch{}}function ot(n){return`allterrain-forms/requested-form-${n}`}function Ss(n){try{const e=window.sessionStorage.getItem(ot(n));return window.sessionStorage.removeItem(ot(n)),Number(e)||0}catch{return 0}}const Ie={is:"is",is_not:"is not",contains:"contains",not_contains:"does not contain",starts_with:"starts with",ends_with:"ends with",greater:"is more than",less:"is less than",greater_equal:"is at least",less_equal:"is at most",empty:"is empty",not_empty:"has any answer"},De=["empty","not_empty"];function lt(n,e){const s=n.find(t=>t.id===e);return s?s.label||"an untitled question":null}function ct(n,e,s){return n.find(i=>i.id===e)?.choices?.find(i=>i.value===s)?.label||s}function Cs(n,e){const s=Ie[n.operator]??String(n.operator);if(De.includes(n.operator))return s;const t=ct(e,n.field,n.value);return`${n.operator==="is"?"":`${s} `}${t!==""?t:"(nothing)"}`}function be(n,e,s=0){const t=lt(e,n.field),a=Ie[n.operator]??String(n.operator);if(t===null)return[{kind:"field",text:"a question that no longer exists",fieldId:n.field,missing:!0}];const i=[{kind:"field",text:t,fieldId:n.field,missing:!1},{kind:"operator",text:a,operator:n.operator,ruleIndex:s}];if(De.includes(n.operator))return i;const o=ct(e,n.field,n.value);return i.push({kind:"value",text:o!==""?o:"(nothing)",raw:n.value,sourceId:n.field,ruleIndex:s}),i}function Es(n,e){const s=n.logic;if(!s?.enabled||!s.rules.length)return[];const t=[{kind:"verb",text:s.action==="hide"?"Hidden when":"Shown when"}];return s.rules.forEach((a,i)=>{i>0&&t.push({kind:"join",text:s.match==="all"?"and":"or"}),t.push(...be(a,e,i))}),t}function qe(n){return n.map(e=>e.text).join(" ")}function Ls(n,e){return qe(be(n,e))}function ge(n){const e=[];for(const s of n){const t=s.logic;if(t?.enabled)for(const a of t.rules)!a.field||a.field===s.id||e.push({from:a.field,to:s.id,label:Ls(a,n),short:Cs(a,n),action:t.action,broken:lt(n,a.field)===null})}return e}function $s(n){const e=new Map,s=new Set;for(const t of ge(n)){const a=`${t.from}->${t.to}`;t.broken||s.has(a)||(s.add(a),e.set(t.from,(e.get(t.from)??0)+1))}return e}const dt=10,ht=22,ne="http://www.w3.org/2000/svg";class As{constructor(e){this.edges=[],this.teardowns=[],this.frame=0,this.host=e,this.svg=document.createElementNS(ne,"svg"),this.svg.setAttribute("class","atfb-logicmap"),this.svg.setAttribute("aria-hidden","true"),this.svg.setAttribute("focusable","false"),e.append(this.svg);const s=()=>this.schedule();window.addEventListener("resize",s),this.teardowns.push(()=>window.removeEventListener("resize",s));const t=e.closest(".atfb__canvas")??e;if(t.addEventListener("scroll",s,{passive:!0}),this.teardowns.push(()=>t.removeEventListener("scroll",s)),typeof ResizeObserver<"u"){const a=new ResizeObserver(s);a.observe(e),this.teardowns.push(()=>a.disconnect())}}setEdges(e){this.edges=e,this.schedule()}highlight(e){this.svg.classList.toggle("is-focused",!!e),this.svg.querySelectorAll("[data-from]").forEach(s=>{const t=e&&(s.dataset.from===e||s.dataset.to===e);s.classList.toggle("is-lit",!!t)})}destroy(){this.teardowns.forEach(e=>e()),this.teardowns=[],this.svg.remove(),this.frame&&cancelAnimationFrame(this.frame)}schedule(){this.frame||(this.frame=requestAnimationFrame(()=>{this.frame=0,this.draw()}))}draw(){this.svg.replaceChildren();const e=this.host.getBoundingClientRect();this.svg.setAttribute("viewBox",`0 0 ${e.width} ${e.height}`),this.svg.setAttribute("width",String(e.width)),this.svg.setAttribute("height",String(e.height));const s=new Map;for(const t of this.edges){const a=this.cardRect(t.from),i=this.cardRect(t.to);if(!a||!i)continue;const o=s.get(t.from)??0;s.set(t.from,o+1),this.drawEdge(t,a,i,e,o)}}cardRect(e){const s=this.host.querySelector(`[data-atfb-card="${CSS.escape(e)}"]`);return s?s.getBoundingClientRect():null}drawEdge(e,s,t,a,i){const o=s.right-a.left,l=s.top+s.height/2-a.top,c=t.right-a.left,d=t.top+t.height/2-a.top,h=Math.max(0,a.width-dt-Math.max(o,c)),m=22+i*11+Math.min(22,Math.abs(d-l)/8),g=Math.max(12,Math.min(m,h*.4)),u=document.createElementNS(ne,"path");u.setAttribute("d",`M ${o} ${l} C ${o+g} ${l}, ${c+g} ${d}, ${c} ${d}`),u.setAttribute("class",`atfb-logicmap__path is-${e.action}${e.broken?" is-broken":""}`),u.dataset.from=e.from,u.dataset.to=e.to;const f=document.createElementNS(ne,"title");f.textContent=e.label,u.append(f);const y=document.createElementNS(ne,"circle");y.setAttribute("cx",String(c)),y.setAttribute("cy",String(d)),y.setAttribute("r","3.5"),y.setAttribute("class",`atfb-logicmap__dot is-${e.action}${e.broken?" is-broken":""}`),y.dataset.from=e.from,y.dataset.to=e.to,this.svg.append(u,y);const p=document.createElementNS(ne,"text");p.setAttribute("x",String(a.width-dt)),p.setAttribute("y",String(d+3)),p.setAttribute("text-anchor","end"),p.setAttribute("class","atfb-logicmap__label"),p.dataset.from=e.from,p.dataset.to=e.to,p.textContent=e.short.length>ht?`${e.short.slice(0,ht-1)}…`:e.short;const x=document.createElementNS(ne,"title");x.textContent=e.label,p.append(x),this.svg.append(p)}}const Ts={text:"text",email:"text",url:"text",tel:"text",number:"text",password:"text",date:"text",time:"text",datetime:"text",date_range:"composite",textarea:"textarea",select:"select",country:"select",multiselect:"options",radio:"options",checkboxes:"options",image_choice:"options",quiz:"options",switch:"toggle",consent:"toggle",file:"file",range:"range",rating:"summary",scale:"summary",likert:"summary",signature:"summary",repeater:"repeater",color:"text",name:"composite",address:"composite",total:"text",hidden:"static",heading:"static",html:"static",divider:"static",spacer:"static",page_break:"static"};function Ms(n){return Ts[n]??"text"}function ut(n,e){const s=/^choice:(\d+):(label|value)$/.exec(e);return String(s?n.choices?.[Number(s[1])]?.[s[2]]??"":n[e]??"")}function Z(n){const{value:e,onInput:s,onCommit:t}=n,a=r("span",{class:`${n.class} atfb-editable`,text:e,attrs:{contenteditable:"plaintext-only",role:"textbox",spellcheck:"false","data-placeholder":n.placeholder}});return n.bind&&(a.dataset.atfbBind=n.bind),a.addEventListener("pointerdown",i=>i.stopPropagation()),a.addEventListener("input",()=>s(a.textContent??"")),a.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),a.blur()),i.key==="Escape"&&(a.textContent=e,a.blur()),i.stopPropagation()}),a.addEventListener("blur",()=>t?.()),a}function Fs(n){const e=r("input",{class:"atf-choice__input",type:n==="checkboxes"||n==="multiselect"?"checkbox":"radio"});return e.disabled=!0,e}function pt(n,e,s){const t=Ms(n.type),a=Z({value:n.label,placeholder:"Write the question…",class:"atf-label",bind:"label",onInput:o=>s.edit(l=>{l.label=o}),onCommit:()=>s.restructure(()=>{})}),i=[t==="static"||t==="toggle"?null:a,Ds(n,e,t,s),Is(n,e,s)];return r("div",{class:"atfb-preview atf-form",children:[r("div",{class:`atf-field atf-field--${n.type}`,children:i})]})}function Is(n,e,s){if(!e?.supports.includes("hint"))return null;const t=Z({value:n.hint??"",placeholder:"Add a hint…",class:"atf-hint",bind:"hint",onInput:a=>s.edit(i=>{i.hint=a})});return t.setAttribute("aria-label","Hint"),r("p",{class:"atfb-preview__hint",children:[t]})}function Ds(n,e,s,t){switch(s){case"text":return Oe(n,"atf-input",t);case"textarea":return Oe(n,"atf-input atf-textarea",t,!0);case"select":return r("div",{class:"atfb-preview__select",children:[Oe(n,"atf-input atf-select",t)]});case"options":return Rs(n,t);case"toggle":return r("div",{class:n.type==="switch"?"atf-toggle atf-toggle--switch":"atf-toggle",children:[(()=>{const a=r("input",{class:"atf-toggle__input",type:"checkbox"});return a.disabled=!0,a})(),Z({value:n.label||"",placeholder:n.type==="consent"?"What are they agreeing to?…":"What does this turn on?…",class:"atf-toggle__label",bind:"label",onInput:a=>t.edit(i=>{i.label=a}),onCommit:()=>t.restructure(()=>{})})]});case"file":return r("div",{class:"atf-file",children:[r("input",{class:"atf-file__input",type:"file"})]});case"range":return r("input",{class:"atf-range__input",type:"range"});case"composite":return r("div",{class:"atf-composite__parts",children:[r("span",{class:"atf-input atfb-preview__ghost",text:""}),r("span",{class:"atf-input atfb-preview__ghost",text:""})]});case"static":return Ps(n,e,t);case"repeater":return qs(n,t);default:return r("div",{class:"atfb-preview__stack",children:[r("p",{class:"atfb-preview__summary",text:`${e?.label??n.type} — set this up in the panel on the right.`})]})}}function qs(n,e){const s=n.fields??[],t=r("div",{class:"atfb-repeater__zone",attrs:{"data-atfb-repeater-zone":n.id}});return s.forEach(a=>t.append(Os(n,a,e))),s.length||t.append(r("p",{class:"atfb-repeater__empty",text:"Drag fields from the palette in here — the visitor gets a fresh copy of each with every row they add."})),r("div",{class:"atfb-repeater",attrs:{"data-atfb-repeater":n.id},children:[r("div",{class:"atf-repeater__row atfb-repeater__frame",children:[r("div",{class:"atf-repeater__row-head",children:[r("span",{class:"atf-repeater__title atfb-repeater__title",children:[Z({value:String(n.itemLabel??""),placeholder:"Row",class:"atfb-repeater__item-label",bind:"itemLabel",onInput:a=>e.edit(i=>{i.itemLabel=a})}),r("span",{class:"atfb-repeater__ordinal",text:"1",attrs:{"aria-hidden":"true"}})]})]}),t]}),Ns(n,e)]})}function Os(n,e,s){const t=e.id,a=l=>c=>{const d=(c.fields??[]).find(h=>h.id===t);d&&l(d)},i={edit:l=>s.edit(a(l)),restructure:l=>s.restructure(a(l)),types:s.types,selectedId:s.selectedId},o=s.types?.(e.type);return r("div",{class:`atfb-subcard${s.selectedId===t?" is-selected":""}`,attrs:{"data-atfb-subfield":t,"data-atfb-parent":n.id,tabindex:"0",role:"button","aria-label":`${e.label||o?.label||e.type}, inside ${n.label||"the repeater"}`},children:[r("div",{class:"atfb-subcard__head",children:[r("span",{class:"atfb-subcard__type",text:o?.label??e.type}),e.required?r("span",{class:"atfb-subcard__required",text:"Required"}):null,r("button",{class:"atfb-preview__remove",type:"button",title:"Remove this field from the repeater",attrs:{"aria-label":`Remove ${e.label||o?.label||"this field"}`},on:{pointerdown:l=>l.stopPropagation(),click:l=>{l.stopPropagation(),s.restructure(c=>{const d=c.fields??[],h=d.findIndex(m=>m.id===t);h>=0&&d.splice(h,1)})}},children:[r("span",{text:"×"})]})]}),pt(e,o,i)]})}function Oe(n,e,s,t=!1){const a=Z({value:n.placeholder??"",placeholder:n.type==="select"||n.type==="country"?"Choose…":"Placeholder…",class:`${e} atfb-preview__box${t?" atfb-preview__box--tall":""}`,bind:"placeholder",onInput:i=>s.edit(o=>{o.placeholder=i})});return a.setAttribute("aria-label","Placeholder"),a}function Ne(n,e,s,t,a,i){return r("span",{class:`atf-button ${s} atfb-preview__button`,children:[Z({value:n,placeholder:e,class:"atfb-preview__button-text",bind:t,onInput:o=>a.edit(l=>i(l,o))})]})}function Ns(n,e){return Ne(String(n.addLabel??""),"Add another","atf-button--ghost atfb-repeater__add","addLabel",e,(s,t)=>{s.addLabel=t})}function Rs(n,e){const s=r("div",{class:"atf-choices__list"});return(n.choices??[]).forEach((t,a)=>{s.append(r("div",{class:"atf-choice atfb-preview__option",children:[Fs(n.type),Z({value:t.label,placeholder:"Option…",class:"atf-choice__label",bind:`choice:${a}:label`,onInput:i=>{e.edit(o=>{const l=o.choices?.[a];if(!l)return;const c=!l.value||l.value===l.label;l.label=i,c&&(l.value=i)})}}),r("button",{class:"atfb-preview__remove",type:"button",title:"Remove this option",attrs:{"aria-label":`Remove ${t.label||"this option"}`},on:{pointerdown:i=>i.stopPropagation(),click:i=>{i.stopPropagation(),e.restructure(o=>{o.choices.splice(a,1)})}},children:[r("span",{text:"×"})]})]}))}),s.append(r("button",{class:"atfb-preview__add",type:"button",on:{pointerdown:t=>t.stopPropagation(),click:t=>{t.stopPropagation(),e.restructure(a=>{const i=a.choices.length+1;a.choices.push({label:`Option ${i}`,value:`Option ${i}`})})}},children:[r("span",{text:"+ Add option"})]})),r("fieldset",{class:"atf-choices",children:[s]})}function Ps(n,e,s){return n.type==="heading"?Z({value:n.label,placeholder:"Section heading…",class:"atf-heading",bind:"label",onInput:t=>s.edit(a=>{a.label=t}),onCommit:()=>s.restructure(()=>{})}):n.type==="divider"?r("hr",{class:"atf-divider"}):n.type==="page_break"?r("div",{class:"atfb-preview__stack",children:[r("p",{class:"atfb-progress-name",children:[Z({value:n.label,placeholder:"Name this step…",class:"atf-progress__label",bind:"label",onInput:t=>s.edit(a=>{a.label=t}),onCommit:()=>s.restructure(()=>{})})]}),r("p",{class:"atfb-preview__summary",text:"Everything after this is a new page."}),r("div",{class:"atf-nav atfb-preview__nav",children:[Ne(String(n.prevLabel??""),"Back","atf-button--secondary","prevLabel",s,(t,a)=>{t.prevLabel=a}),Ne(String(n.nextLabel??""),"Next","","nextLabel",s,(t,a)=>{t.nextLabel=a})]})]}):r("p",{class:"atfb-preview__summary",text:`${e?.label??n.type} — nothing is shown to the visitor here.`})}const Re=new Map;function ft(n){let e=Re.get(n);return e||(e=I.mergeTags(n).catch(()=>[]),Re.set(n,e)),e}function Bs(n){Re.delete(n)}function Hs(n){const e=new Map;for(const s of n)for(const t of s.items)e.set(t.tag,t);return e}function js(n,e){const s=Hs(e);return n.replace(/\{[a-z_]+(?::[^}]*)?\}/gi,t=>{const a=s.get(t.toLowerCase());return a?`{the value of ${a.label}}`:t})}function mt(n){return/\{[a-z_]+(?::[^}]*)?\}/i.test(n)}let te=null,Pe=0,re=null;function oe(n=!1){Pe++,te?.remove(),te=null,n&&re?.focus(),re=null}typeof document<"u"&&(document.addEventListener("pointerdown",n=>{const e=n.target;e?.closest(".atfb-tagpick__open")||te?.contains(e)||oe()}),window.addEventListener("keydown",n=>{if(n.key==="Escape"&&re){oe(!0),n.preventDefault(),n.stopImmediatePropagation();return}if(!te?.contains(n.target)||!["ArrowDown","ArrowUp","ArrowLeft","ArrowRight","Home","End","Enter"].includes(n.key))return;n.stopImmediatePropagation();const e=te.querySelector(".atfb-tagpick__search"),s=[...te.querySelectorAll(".atfb-tagpick__item")],t=s.indexOf(document.activeElement);if(n.key==="ArrowDown"||n.key==="ArrowUp"){n.preventDefault();const a=n.key==="ArrowDown"?t+1:t<0?s.length-1:t-1;s[(a+s.length)%s.length]?.focus()}else n.key==="Enter"&&n.target===e?(n.preventDefault(),s[0]?.click()):n.target!==e&&n.key!=="Enter"&&(n.preventDefault(),n.key==="Home"&&s[0]?.focus(),n.key==="End"&&s[s.length-1]?.focus())},!0));function bt(n,e){const s=n.selectionStart??n.value.length,t=n.selectionEnd??n.value.length;n.value=n.value.slice(0,s)+e+n.value.slice(t);const a=s+e.length;n.setSelectionRange(a,a),n.dispatchEvent(new Event("input",{bubbles:!0})),n.focus()}function Ws(n){let e=0,s=window.innerHeight,t=n.parentElement;for(;t&&t!==document.body;){if(/auto|scroll|hidden|clip/.test(getComputedStyle(t).overflowY)){const a=t.getBoundingClientRect();e=Math.max(e,a.top),s=Math.min(s,a.bottom)}t=t.parentElement}return{top:e,bottom:s}}function Us(n,e){const s=r("input",{class:"atfb-input atfb-tagpick__search",type:"search",placeholder:"Search values…",attrs:{"aria-label":"Search values"}}),t=r("div",{class:"atfb-tagpick__list"}),a=o=>{t.replaceChildren();const l=o.trim().toLowerCase();let c=0;for(const d of n){const h=d.items.filter(m=>!l||m.label.toLowerCase().includes(l)||m.tag.toLowerCase().includes(l));if(!h.length){d.empty&&!l&&!d.items.length&&t.append(r("p",{class:"atfb-tagpick__group",text:d.label}),r("p",{class:"atfb-tagpick__empty",text:d.empty}));continue}t.append(r("p",{class:"atfb-tagpick__group",text:d.label}));for(const m of h)c+=1,t.append(r("button",{class:"atfb-tagpick__item",type:"button",on:{click:()=>{oe(),e(m.tag)}},children:[r("span",{class:"atfb-tagpick__item-main",children:[r("span",{class:"atfb-tagpick__label",text:m.label}),r("code",{class:"atfb-tagpick__tag",text:m.tag})]}),m.hint||m.sample?r("span",{class:"atfb-tagpick__meta",text:`{the value of ${m.label}}`}):null]}))}!c&&l&&t.append(r("p",{class:"atfb-tagpick__empty",text:`Nothing matches “${o}”.`}))};a(""),s.addEventListener("input",()=>a(s.value));const i=r("div",{class:"atfb-tagpick",attrs:{role:"dialog","aria-label":"Insert a value"},children:[r("p",{class:"atfb-tagpick__intro",text:"Pick something to drop in. It is filled in when the form is submitted."}),s,t]});return i.addEventListener("keydown",o=>o.stopPropagation()),i}function Be(n,e){const s=()=>Promise.resolve(e.groups?e.groups():ft(e.formId??0)),t=r("button",{class:"atfb-button atfb-button--ghost atfb-tagpick__open",type:"button",title:"Insert a value from the submission",attrs:{"aria-haspopup":"dialog"},children:[B("shortcode"),r("span",{text:"Insert a value"})]}),a=r("div",{class:"atfb-taggable",children:[n,r("div",{class:"atfb-taggable__tools",children:[t]})]}),i=e.preview===!1?null:r("p",{class:"atfb-taggable__preview"});i&&a.append(i);const o=()=>{if(i){if(!mt(n.value)){i.textContent="",i.hidden=!0;return}s().then(c=>{mt(n.value)&&(i.hidden=!1,i.replaceChildren(r("span",{class:"atfb-taggable__preview-label",text:"Reads as"}),r("span",{text:js(n.value,c)})))})}};n.addEventListener("input",o),o();const l=(c,d)=>{oe();const h=Pe,m=n.value;re=n,s().then(g=>{if(h!==Pe||!a.isConnected||n.value!==m)return;const u=Us(g,S=>{n.setSelectionRange(c,d),bt(n,S)});a.append(u),te=u;const f=Ws(a);u.style.maxBlockSize=`${Math.max(0,Math.min(320,f.bottom-f.top-8))}px`;const y=a.getBoundingClientRect(),p=u.getBoundingClientRect().height,x=y.bottom+p<=f.bottom?y.bottom:y.top-p,F=Math.max(f.top+4,Math.min(x,f.bottom-p-4));u.style.insetBlockStart=`${F-y.top}px`,u.querySelector(".atfb-tagpick__search")?.focus({preventScroll:!0})})};return t.addEventListener("click",c=>{if(c.stopPropagation(),re===n){oe(!0);return}l(n.selectionStart??n.value.length,n.selectionEnd??n.value.length)}),n.addEventListener("input",c=>{const d=c,h=n.selectionStart??0;!d.isComposing&&d.data==="{"&&n.value[h-1]==="{"&&l(h-1,h+(n.value[h]==="}"?1:0))}),a}function gt(n,e){const s=parseFloat(String(n??""));return Number.isFinite(s)?s:e}function vt(n,e){let s=e[0];for(const t of e)Math.abs(t.at-n)n.accent??"#2271b1",apply:n=>({accent:n,"accent-soft":`color-mix( in srgb, ${n} 12%, transparent )`,"border-focus":n,"focus-ring-color":n,"button-bg":n,"button-bg-hover":`color-mix( in srgb, ${n} 88%, #000 )`})},{id:"roundness",label:"Roundness",hint:"Corners, everywhere at once.",kind:"scale",steps:He.map(({value:n,label:e})=>({value:n,label:e})),owns:["radius-field","radius-button","radius-card","radius-check"],read:n=>vt(gt(n["radius-field"],4),He),apply:n=>{const e=He.find(s=>s.value===n)?.at??4;return{"radius-field":`${e}px`,"radius-button":`${e}px`,"radius-card":`${Math.min(e*2,28)}px`,"radius-check":`${Math.min(e,6)}px`}}},{id:"density",label:"Density",hint:"How much air the form has.",kind:"scale",steps:je.map(({value:n,label:e})=>({value:n,label:e})),owns:["pad-field-x","pad-field-y","gap-fields","gap-label","button-pad-x","button-pad-y"],read:n=>vt(gt(n["pad-field-y"],9),je),apply:n=>{const e=je.find(s=>s.value===n)?.at??9;return{"pad-field-y":`${e}px`,"pad-field-x":`${Math.round(e*1.4)}px`,"gap-fields":`${Math.round(e*2.2)}px`,"gap-label":`${Math.max(4,Math.round(e*.7))}px`,"button-pad-y":`${e+2}px`,"button-pad-x":`${Math.round(e*2.2)}px`}}},{id:"shadow",label:"Depth",hint:"How far the form sits off the page.",kind:"scale",steps:zs,owns:["shadow-field","shadow-field-focus","shadow-button","shadow-button-hover","shadow-card"],read:n=>{const e=n["shadow-card"]??"none";return e==="none"||e.trim()===""?n["shadow-field"]&&n["shadow-field"]!=="none"?"hard":"none":e.includes("0 1px")||e.includes("2px")?"subtle":"lifted"},apply:n=>{switch(n){case"subtle":return{"shadow-field":"none","shadow-field-focus":"none","shadow-button":"0 1px 2px rgba( 0, 0, 0, 0.12 )","shadow-button-hover":"0 2px 4px rgba( 0, 0, 0, 0.16 )","shadow-card":"0 1px 3px rgba( 0, 0, 0, 0.1 )"};case"lifted":return{"shadow-field":"none","shadow-field-focus":"0 4px 12px rgba( 0, 0, 0, 0.12 )","shadow-button":"0 4px 10px rgba( 0, 0, 0, 0.16 )","shadow-button-hover":"0 8px 20px rgba( 0, 0, 0, 0.2 )","shadow-card":"0 10px 30px rgba( 0, 0, 0, 0.14 )"};case"hard":return{"shadow-field":"3px 3px 0 currentColor","shadow-field-focus":"5px 5px 0 currentColor","shadow-button":"4px 4px 0 currentColor","shadow-button-hover":"2px 2px 0 currentColor","shadow-card":"none"};default:return{"shadow-field":"none","shadow-field-focus":"none","shadow-button":"none","shadow-button-hover":"none","shadow-card":"none"}}}},{id:"field-style",label:"Fields",hint:"How an input is drawn.",kind:"choice",steps:Ys,owns:["field-style"],read:n=>n["field-style"]??"outline",apply:n=>({"field-style":n})},{id:"labels",label:"Labels",hint:"Where the question sits relative to the answer.",kind:"choice",steps:Vs,owns:["label-position"],read:n=>n["label-position"]??"top",apply:n=>({"label-position":n})}]}function Ks(n){return We().find(e=>e.owns.includes(n))??null}function yt(n){let e=n.activeSlug,s={...n.overrides},t=n.themes;const a=v=>{s=v,n.onOverridesReplaced?.({...v})},i=r("div",{class:"atfs-preview__frame"}),o=r("div",{class:"atfs-controls__body"}),l=r("div",{class:"atfs-quick"}),c=r("div",{class:"atfs-themes"}),d=Me(async()=>{try{const v=await n.previewFor(e,s),_=i.closest(".atf-studio__preview"),k=_?.scrollTop??0;i.innerHTML=v,_&&(_.scrollTop=k),document.dispatchEvent(new CustomEvent("alltfo-refresh"))}catch(v){R(i),i.append(r("p",{class:"atfb-error",text:v instanceof Error?v.message:"Preview failed."}))}},180),h={"label-position":"atf-labels-","field-style":"atf-fields-"},m=(v,_,k)=>{const E=k.replace(/[^a-z0-9_-]/gi,"");for(const A of[...v.classList])A.startsWith(_)&&v.classList.remove(A);E&&v.classList.add(_+E)},g=v=>{const _=i.querySelector(".atf-form-wrap"),k=_?.querySelector(".atf-form");if(_)for(const[E,A]of Object.entries(v))A===""?_.style.removeProperty(`--atf-${E}`):_.style.setProperty(`--atf-${E}`,A),k&&h[E]&&m(k,h[E],A||(t.find(P=>P.slug===e)?.resolved[E]??""))},u=v=>{g(v.resolved);const _=i.querySelector(".atf-form");_&&(m(_,"atf-theme-",v.slug),_.classList.toggle("atf-is-dark",!!v.dark))},f=v=>s[v.token]!==void 0?s[v.token]:t.find(k=>k.slug===e)?.resolved?.[v.token]??v.default,y=()=>{R(c);for(const v of t){const _=r("button",{class:`atfs-theme${v.slug===e?" is-active":""}`,type:"button",attrs:{"aria-pressed":v.slug===e,title:v.description},children:[r("span",{class:"atfs-theme__chip",style:{background:v.resolved.surface??"#fff",borderColor:v.resolved.border??"#ccc",borderRadius:v.resolved["radius-field"]??"4px",boxShadow:v.resolved["shadow-card"]??"none"},children:[r("span",{class:"atfs-theme__accent",style:{background:v.resolved.accent??"#2271b1",borderRadius:v.resolved["radius-button"]??"4px"}})]}),r("span",{class:"atfs-theme__name",text:v.label}),v.custom?r("span",{class:"atfb-badge",text:"yours"}):null],on:{click:()=>{e=v.slug,a({}),n.onTheme(e),u(v),y(),S(),F(),ts()}}});c.append(_)}},p=()=>{const _={...t.find(k=>k.slug===e)?.resolved??{}};for(const[k,E]of Object.entries(s))_[k]=E;return _},x=v=>{const _=l.closest(".atf-studio__controls"),k=_?.scrollTop??0;v(),_&&(_.scrollTop=k)},F=Me(()=>x(b),150),S=()=>{const v=p(),_=l.querySelectorAll(".atfs-dial");We().forEach((k,E)=>{const A=_[E];if(!A)return;const P=k.read(v);if(k.kind==="colour"){const O=A.querySelector('input[type="color"]'),K=A.querySelector("input.atfb-input");O&&document.activeElement!==O&&(O.value=ve(P)),K&&document.activeElement!==K&&(K.value=P);return}A.querySelectorAll(".atfs-segment").forEach((O,K)=>{const Q=k.steps?.[K]?.value===P;O.classList.toggle("is-on",Q),O.setAttribute("aria-pressed",String(Q))})})},j=(v,_)=>{const k=v.apply(_,p());for(const[E,A]of Object.entries(k))s[E]=A,n.onOverride(E,A);g(k),S(),F()},L=()=>{R(l);const v=p();for(const _ of We()){const k=_.read(v);let E;if(_.kind==="colour"){const A=r("input",{class:"atfs-color",type:"color",value:ve(k),attrs:{"aria-label":_.label},on:{input:P=>j(_,P.target.value)}});E=r("div",{class:"atfs-color-row",children:[A,T(k,P=>j(_,P))]})}else E=r("div",{class:`atfs-segmented atfs-segmented--${_.kind}`,attrs:{role:"group","aria-label":_.label},children:(_.steps??[]).map(A=>r("button",{class:`atfs-segment${A.value===k?" is-on":""}`,type:"button",text:A.label,attrs:{"aria-pressed":A.value===k},on:{click:()=>j(_,A.value)}}))});l.append(r("div",{class:"atfs-dial",children:[r("div",{class:"atfs-dial__head",children:[r("span",{class:"atfs-dial__label",text:_.label}),r("span",{class:"atfs-dial__hint",text:_.hint})]}),E]}))}},b=()=>{R(o);const v=new Map;for(const k of n.tokens){const E=v.get(k.group)??[];E.push(k),v.set(k.group,E)}const _={colour:"Colour",shape:"Corners and borders",shadow:"Shadows",fields:"Field style",space:"Spacing",type:"Type",labels:"Labels",button:"Buttons",focus:"Focus ring",motion:"Motion"};for(const[k,E]of v)o.append(r("details",{class:"atfs-group",attrs:{open:k==="colour"},children:[r("summary",{text:_[k]??k}),...E.map(A=>M(A))]}))},M=v=>{const _=f(v),k=O=>{O===""?delete s[v.token]:s[v.token]=O,n.onOverride(v.token,O),g({[v.token]:O})};let E;if(v.control==="color"){const O=r("input",{class:"atfs-color",type:"color",value:ve(_),attrs:{"aria-label":`${v.label} colour`},on:{input:Q=>{const de=Q.target.value;K.value=de,k(de)}}}),K=T(_,Q=>{O.value=ve(Q),k(Q)});E=r("div",{class:"atfs-color-row",children:[O,K]})}else if(v.control==="select")E=D(_,(v.options??[]).map(O=>({value:O,label:O})),k);else if(v.control==="length"){const O=parseFloat(_)||0,K=v.unit??"px",Q=v.token.includes("radius")?60:80,de=r("input",{class:"atfs-range",type:"range",value:String(O),attrs:{min:"0",max:String(Q),step:"1","aria-label":v.label},on:{input:Ee=>{const ns=`${Ee.target.value}${K}`;ss.value=ns,k(ns)}}}),ss=T(_,Ee=>{de.value=String(parseFloat(Ee)||0),k(Ee)});E=r("div",{class:"atfs-length-row",children:[de,ss]})}else E=T(_,k);const A=w(v.label,E),P=Ks(v.token);return P&&(A.classList.add("is-dialled"),A.append(r("span",{class:"atfs-owned",text:P.label}))),s[v.token]!==void 0&&(A.classList.add("is-overridden"),A.append(r("button",{class:"atfs-reset",type:"button",text:"Reset",attrs:{"aria-label":`Reset ${v.label} to the theme's value`},on:{click:()=>{k(""),x(b)}}}))),A},$=async()=>{const v=t.find(E=>E.slug===e),_=v?`${v.label} (mine)`:"My theme",k=window.prompt("Name this theme",_);if(k)try{const E={};for(const P of n.tokens){const O=f(P);O!==P.default&&(E[P.token]=O)}const A=await I.saveTheme({label:k,tokens:E});t=[...t.filter(P=>P.slug!==A.slug),A],n.onThemesChanged(t),e=A.slug,a({}),n.onTheme(e),y(),S(),x(b),N("Theme saved",A.label)}catch(E){N("Could not save the theme",E instanceof Error?E.message:"","error")}},W=async()=>{const v=t.find(_=>_.slug===e);if(v?.custom&&await ie(`Delete “${v.label}”? Forms using it fall back to Clean.`,"Delete theme"))try{await I.deleteTheme(v.id),t=t.filter(k=>k.slug!==v.slug),n.onThemesChanged(t),e="clean",a({}),n.onTheme(e),y(),S(),x(b);const _=t.find(k=>k.slug===e);_&&u(_)}catch(_){N("Could not delete the theme",_ instanceof Error?_.message:"","error")}},H=async()=>{const v=t.find(E=>E.slug===e),_={label:v?.label??e,tokens:{...v?.tokens??{},...s}},k=JSON.stringify(_,null," ");try{await navigator.clipboard.writeText(k),N("Theme copied","Paste it into another site to import it.")}catch{window.prompt("Copy this theme",k)}},ce=()=>{const v=window.prompt("Paste a theme");if(v)try{const _=JSON.parse(v);if(!_.tokens||typeof _.tokens!="object")throw new Error("That does not look like a theme.");for(const[k,E]of Object.entries(_.tokens))s[k]=String(E),n.onOverride(k,String(E));g({...s}),S(),x(b)}catch(_){N("Could not read that theme",_ instanceof Error?_.message:"","error")}},es=C("Delete",()=>void W(),"danger"),ts=()=>{const v=t.find(_=>_.slug===e);es.hidden=!v?.custom};return y(),L(),b(),d(),ts(),r("div",{class:"atf-studio",children:[r("div",{class:"atf-studio__top",children:[r("div",{class:"atf-studio__topbar",children:[r("h2",{class:"atf-studio__heading",text:"Theme"}),r("div",{class:"atfs__actions",children:[C("Save as a theme",()=>void $(),"primary"),C("Export",()=>void H()),C("Import",ce),es]})]}),c]}),r("div",{class:"atf-studio__panes",children:[r("aside",{class:"atf-studio__controls",children:[r("p",{class:"atfb-hint",text:"Changes apply to this form only, until you save them as a theme."}),l,r("details",{class:"atfs-advanced",children:[r("summary",{text:"Every setting"}),r("p",{class:"atfb-hint",text:"The full token list. The dials above write into it."}),o]})]}),r("main",{class:"atf-studio__preview",children:[r("h2",{class:"screen-reader-text",text:"Live preview"}),i]})]})]})}async function Ue(){const n=document.querySelector("[data-atfs-root]");if(!n||n.dataset.atfsMounted)return;n.dataset.atfsMounted="1",Fe(n);const e=n.querySelector("[data-atfs-bar]"),s=n.querySelector(".atfs__body")??n;try{const[t,a,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);if(!i.length){R(s),s.append(r("div",{class:"atfb-empty",children:[r("h2",{text:"No forms to preview"}),r("p",{text:"Make a form first — a theme needs something to dress."})]}));return}let o=i[0],l={},c=o.theme;const d=()=>{R(s),s.append(yt({themes:a,tokens:t.tokens,activeSlug:c,overrides:l,standalone:!0,onTheme:h=>{c=h},onOverride:(h,m)=>{m===""?delete l[h]:l[h]=m},onOverridesReplaced:h=>{l={...h}},previewFor:async(h,m)=>{const g=await I.getForm(o.id);g.schema.settings.theme=h,g.schema.settings.themeOverrides=m;const{html:u}=await I.preview(o.id,{schema:g.schema,theme:h});return u},onThemesChanged:h=>{a.length=0,a.push(...h)}}))};e&&(R(e),e.append(r("span",{class:"atfs__label",text:"Preview against"}),D(String(o.id),i.map(h=>({value:String(h.id),label:h.title||"(untitled)"})),h=>{o=i.find(m=>String(m.id)===h)??i[0],l={},d()}))),d()}catch(t){R(s),s.append(r("p",{class:"atfb-error",text:t instanceof Error?t.message:"Could not load themes."}))}}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>void Ue()):Ue(),document.addEventListener("os-window-content-loaded",()=>void Ue()));function ve(n){const e=n.trim();return/^#[0-9a-f]{6}$/i.test(e)?e:/^#[0-9a-f]{3}$/i.test(e)?`#${e[1]}${e[1]}${e[2]}${e[2]}${e[3]}${e[3]}`:"#888888"}const Gs="mailpoet",ye="",Xs=["checkbox","checkboxes","toggle","consent","gdpr"],wt=["email"];function _t(n){return n.schema.actions.find(e=>e.type==="mailpoet")}function ze(n){const e=n?.settings??{};return{lists:Array.isArray(e.lists)?e.lists.map(Number).filter(Boolean):[],email_field:typeof e.email_field=="string"?e.email_field:"",first_name_field:typeof e.first_name_field=="string"?e.first_name_field:"",last_name_field:typeof e.last_name_field=="string"?e.last_name_field:""}}function Zs(n){return n?.logic?.enabled?n.logic.rules[0]?.field??ye:ye}function xt(n,e,s){const t=n.find(a=>e.includes(a.type));return t?t.id:s?n.find(a=>s.test(a.label))?.id??"":""}function Js(n,e,s){const t=r("section",{class:"atfm-form"}),a=l=>r("span",{class:`atfm-form__mark${l?"":" atfm-form__mark--off"}`,children:[r("img",{attrs:{src:e.symbol,alt:"",width:"20",height:"20"}})]}),i=l=>{R(t),t.classList.remove("is-open"),t.append(r("div",{class:"atfm-form__head",children:[a(l.length>0),r("div",{class:"atfm-form__title",children:[r("strong",{text:n.title||`Form ${n.id}`}),l.length?r("span",{class:"atfm-form__status is-on",text:`Subscribing → ${l.join(", ")}`}):r("span",{class:"atfm-form__status",text:"Not connected"})]}),C(l.length?"Edit":"Connect",()=>void o(),"secondary")]}))},o=async()=>{t.classList.add("is-open"),R(t),t.append(r("p",{class:"atfm-hint",text:"Loading the form…"}));let l;try{l=await I.getForm(n.id)}catch{R(t),t.append(r("p",{class:"atfm-hint",text:"Could not load this form."}));return}const c=l.schema.fields.filter(b=>b.type!=="page_break"),d=_t(l),h=ze(d),m=new Set(h.lists.filter(b=>e.lists.some(M=>M.id===b)));let g=Zs(d),u=h.email_field||xt(c,wt,/mail/i),f=h.first_name_field,y=h.last_name_field;c.some(b=>b.id===u)||(u=xt(c,wt,/mail/i));const p=c.filter(b=>Xs.includes(b.type));!d&&p.length&&(g=p[0].id);const x=(b,M)=>[{value:"",label:M},...b.map($=>({value:$.id,label:$.label||$.id}))],F=r("div",{class:"atfm-lists"});(()=>{R(F);for(const b of e.lists){const M=r("input",{attrs:{type:"checkbox"}});M.checked=m.has(b.id),M.addEventListener("change",()=>{M.checked?m.add(b.id):m.delete(b.id)}),F.append(r("label",{class:"atfm-list",children:[M,r("span",{text:b.name})]}))}})();const j=async(b=!1)=>{const M=l.schema.actions.filter($=>$.type!=="mailpoet");if(!b){if(!m.size){N("Pick a list","A subscription needs at least one MailPoet list.","error");return}if(!u){N("Pick the email field","MailPoet needs to know which answer is the address.","error");return}M.push({id:Gs,type:"mailpoet",enabled:!0,logic:g===ye?{enabled:!1,action:"show",match:"all",rules:[]}:{enabled:!0,action:"show",match:"all",rules:[{field:g,operator:"not_empty",value:""}]},settings:{lists:[...m],email_field:u,first_name_field:f,last_name_field:y}})}l.schema.actions=M;try{await I.updateForm(l.id,{schema:l.schema})}catch($){N("Could not save",$ instanceof Error?$.message:"","error");return}N(b?"Disconnected":"Connected to MailPoet",b?`${n.title} no longer subscribes anyone.`:`${n.title} now subscribes opted-in visitors.`),i(b?[]:e.lists.filter($=>m.has($.id)).map($=>$.name))};R(t);const L=b=>r("span",{class:"atfm-form__section",text:b});t.append(r("div",{class:"atfm-form__head",children:[a(!!d),r("div",{class:"atfm-form__title",children:[r("strong",{text:n.title||`Form ${n.id}`})]}),C("Close",()=>i(d?e.lists.filter(b=>ze(d).lists.includes(b.id)).map(b=>b.name):[]),"ghost")]}),r("div",{class:"atfm-form__body",children:[L("Where they land"),w("Lists",F,"MailPoet sends its own confirmation email before anyone is truly on a list."),L("Who they are"),w("Email address",D(u,x(c,"— pick a field —"),b=>{u=b}),"The answer that carries their address."),w("First name",D(f,x(c,"— none —"),b=>{f=b})),w("Last name",D(y,x(c,"— none —"),b=>{y=b})),L("When to subscribe"),w("Subscribe",D(g,[...p.map(b=>({value:b.id,label:`Only when “${b.label||b.id}” is ticked`})),{value:ye,label:"Everyone who submits"}],b=>{g=b}),p.length?"Bind it to a box they tick. Subscribing everyone is rarely what visitors expect.":"Add a checkbox or toggle field to the form to offer a proper opt-in."),r("div",{class:"atfm-form__actions",children:d?[C("Save connection",()=>void j(),"primary"),C("Disconnect",()=>void j(!0),"danger")]:[C("Save connection",()=>void j(),"primary")]})]}))};return i([]),I.getForm(n.id).then(l=>{const c=_t(l);if(c&&!t.classList.contains("is-open")){const d=e.lists.filter(h=>ze(c).lists.includes(h.id)).map(h=>h.name);i(d)}}).catch(()=>{}),s.append(t),t}function Qs(n){const e=n.logo?r("span",{class:"atfm-hero__logo",children:[r("img",{attrs:{src:n.logo,alt:"MailPoet",width:"210",height:"105"}})]}):r("span",{class:"atfm-hero__logo atfm-hero__logo--glyph",text:"📬"});return r("header",{class:"atfm-hero",children:[e,r("div",{class:"atfm-hero__words",children:[r("h1",{text:"Turn submissions into subscribers"}),r("p",{text:"Every submission is someone choosing to talk to you. Connect a form to MailPoet and the ones who opt in land on your lists by themselves — named, consented, and confirmed by MailPoet’s own double opt-in."}),n.active?r("p",{class:"atfm-hero__status is-on",text:n.lists.length===1?"Connected — 1 list ready for subscribers":`Connected — ${n.lists.length} lists ready for subscribers`}):r("p",{class:"atfm-hero__status",text:"MailPoet is not installed on this site yet"})]})]})}function en(){const n=(s,t,a)=>r("div",{class:"atfm-why__card",children:[r("span",{class:"atfm-why__icon",text:s}),r("strong",{text:t}),r("p",{text:a})]}),e=(s,t)=>r("a",{text:t,attrs:{href:s,target:"_blank",rel:"noreferrer"}});return[r("div",{class:"atfm-why",children:[n("✉️","Beautiful emails, made in WordPress","Design newsletters and welcome emails in a drag-and-drop editor that lives in your own admin — no external account to juggle."),n("🤝","Consent you can stand behind","Double opt-in out of the box: every address your forms send over is confirmed by the visitor before a single campaign reaches it."),n("🚀","Free to grow with","Free up to 500 subscribers, welcome automations, WooCommerce emails and open-rate stats included — a paid addon anywhere else.")]}),r("p",{class:"atfm-links",children:[e("https://www.mailpoet.com/features/","Explore MailPoet’s features ↗"),e("https://kb.mailpoet.com/","Guides & docs ↗"),e("https://www.mailpoet.com/pricing/","Plans & the free tier ↗")]})]}function tn(){const n=(e,s)=>r("div",{class:"atfm-step",children:[r("span",{class:"atfm-step__n",text:e}),r("span",{text:s})]});return r("div",{class:"atfm-steps",children:[n("1","Pick a form below"),n("2","Choose the lists it feeds"),n("3","Bind it to an opt-in — MailPoet confirms the rest")]})}async function Ye(){const n=document.querySelector("[data-atfm-root]");if(!n||n.dataset.atfmMounted)return;n.dataset.atfmMounted="1",Fe(n);const e=n.querySelector("[data-atfm-bar]"),s=n.querySelector("[data-atfm-body]")??n;try{const[t,a]=await Promise.all([I.mailpoet(),I.listForms()]);if(e?.remove(),R(s),s.append(Qs(t),...en()),!t.active){s.append(r("div",{class:"atfm-pitch",children:[r("p",{text:"MailPoet sends newsletters from right inside WordPress — no external account, free to start. Install it and every form here gets a subscribe switch: reservations feed your announcements, signups feed your schedule, enquiries feed your news."}),r("a",{class:"atfm-pitch__cta",text:"Install MailPoet — it’s free",attrs:{href:t.adminUrl,target:"_blank",rel:"noreferrer"}})]}));return}if(!t.lists.length){s.append(r("div",{class:"atfm-pitch",children:[r("p",{text:"MailPoet is here, but it has no list yet. Make one, and your forms will have somewhere to send subscribers."}),r("a",{class:"atfm-pitch__cta",text:"Open MailPoet lists",attrs:{href:t.adminUrl,target:"_blank",rel:"noreferrer"}})]}));return}s.append(tn());const i=r("section",{class:"atfm-forms",children:[r("div",{class:"atfm-forms__head",children:[r("h2",{text:"Your forms"}),r("p",{class:"atfm-hint",text:"Connected forms wear the MailPoet mark in colour."})]})]});if(s.append(i),!a.length){i.append(r("p",{class:"atfm-hint",text:"No forms yet — make one, then come back to connect it."}));return}for(const o of a)Js(o,t,i)}catch{e&&(e.textContent="Could not reach the site — reload the window to try again.")}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>void Ye()):Ye(),document.addEventListener("os-window-content-loaded",()=>void Ye());const we={plain:"",simple:"✓",minimal:"",card:"🎉",check:"",confetti:"🎉",fireworks:"🎆",sparkles:"✨",typewriter:""};function kt(){return{style:"simple",title:"",icon:"",accent:"",intensity:"medium",showButton:!1,buttonLabel:""}}function Ve(n){const e={...kt(),...n??{}};return e.style in we||(e.style="simple"),e}function sn(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}function nn(n,e,s){const t=Ve(e),a=document.createElement("div");if(a.className=`atf-confirmation atf-success atf-success--${t.style}`,a.setAttribute("role","status"),a.setAttribute("tabindex","-1"),t.style==="plain")return a.className="atf-confirmation",a.innerHTML=n,a;t.accent&&a.style.setProperty("--atf-accent",t.accent);const i=document.createElement("div");i.className="atf-success__inner",a.append(i);const o=t.icon||we[t.style];if(t.style==="check")i.insertAdjacentHTML("beforeend",'');else if(o){const c=document.createElement("span");c.className="atf-success__icon",c.setAttribute("aria-hidden","true"),c.textContent=o,i.append(c)}if(t.title){const c=document.createElement("h2");c.className="atf-success__title",c.textContent=t.title,i.append(c)}const l=document.createElement("div");if(l.className="atf-success__message",l.innerHTML=n,i.append(l),t.style==="typewriter"&&a.setAttribute("aria-label",l.textContent??""),t.showButton){const c=document.createElement("button");c.type="button",c.className="atf-button atf-button--ghost atf-success__again",c.textContent=t.buttonLabel||"Fill it in again",c.addEventListener("click",()=>s?s():window.location.reload()),i.append(c)}return a}function an(n,e){const s=Ve(e);if(sn())return()=>{};switch(s.style){case"confetti":return rn(n,s);case"fireworks":return on(s);case"sparkles":return ln(n,s);case"typewriter":return cn(n);default:return()=>{}}}function le(n){return{low:.5,medium:1,high:1.8}[n.intensity]}function St(){const n=document.createElement("canvas");n.className="atf-success-canvas",n.setAttribute("aria-hidden","true");const e=Math.min(window.devicePixelRatio||1,2);n.width=Math.floor(window.innerWidth*e),n.height=Math.floor(window.innerHeight*e),document.body.append(n);const s=n.getContext("2d");return s?.scale(e,e),{canvas:n,ctx:s,stop:()=>n.remove()}}const Ct=["#f43f5e","#f59e0b","#10b981","#3b82f6","#8b5cf6","#ec4899","#eab308"];function rn(n,e){const{ctx:s,stop:t}=St();if(!s)return t(),()=>{};const a=e.accent?[e.accent,...Ct]:Ct,i=[],o=n.getBoundingClientRect(),l=o.left+o.width/2,c=Math.min(o.top+40,window.innerHeight-20),d=(x,F,S)=>{const j=S?Math.PI*(1.15+.7*Math.random()):0,L=S?9+Math.random()*8:0;return{x,y:F,vx:S?Math.cos(j)*L*(Math.random()<.5?1:-1):(Math.random()-.5)*1.5,vy:S?Math.sin(j)*L:1+Math.random()*2,w:6+Math.random()*5,h:8+Math.random()*7,angle:Math.random()*Math.PI,spin:(Math.random()-.5)*.3,color:a[Math.floor(Math.random()*a.length)],wobble:Math.random()*Math.PI*2}},h=Math.round(90*le(e));for(let x=0;x{if(g>=m){window.clearInterval(u);return}i.push(d(Math.random()*window.innerWidth,-20,!1)),g++},2e3/m);let f=0;const y=performance.now(),p=x=>{s.clearRect(0,0,window.innerWidth,window.innerHeight);let F=!1;for(const S of i)S.vy+=.16,S.vx*=.99,S.vy*=.985,S.wobble+=.1,S.x+=S.vx+Math.sin(S.wobble)*.8,S.y+=S.vy,S.angle+=S.spin,S.y{window.clearInterval(u),window.cancelAnimationFrame(f),t()}}function on(n){const{ctx:e,stop:s}=St();if(!e)return s(),()=>{};const t=[],a=[],i=Math.round(6*le(n))+2;let o=0;const l=()=>{t.push({x:window.innerWidth*(.15+.7*Math.random()),y:window.innerHeight,vy:-(9+Math.random()*4),targetY:window.innerHeight*(.15+.3*Math.random()),hue:Math.floor(Math.random()*360)}),o++};l();const c=window.setInterval(()=>{if(o>=i){window.clearInterval(c);return}l()},3500/i),d=u=>{const f=Math.round(70*le(n));for(let y=0;y{e.clearRect(0,0,window.innerWidth,window.innerHeight);for(let y=t.length-1;y>=0;y--){const p=t[y];p.y+=p.vy,p.vy+=.08,e.fillStyle=`hsl(${p.hue} 90% 65%)`,e.fillRect(p.x-1.5,p.y,3,10),(p.y<=p.targetY||p.vy>=-1)&&(d(p),t.splice(y,1))}for(let y=a.length-1;y>=0;y--){const p=a[y];if(p.x+=p.vx,p.y+=p.vy,p.vy+=.045,p.vx*=.985,p.vy*=.985,p.life-=p.decay,p.life<=0){a.splice(y,1);continue}const x=p.life*(.7+.3*Math.random());e.globalAlpha=Math.max(0,x),e.fillStyle=`hsl(${p.hue} 95% ${55+25*p.life}%)`,e.beginPath(),e.arc(p.x,p.y,1.1+1.6*p.life,0,Math.PI*2),e.fill()}e.globalAlpha=1,!(o>=i&&t.length===0&&a.length===0)&&u-m<9e3?h=window.requestAnimationFrame(g):s()};return h=window.requestAnimationFrame(g),()=>{window.clearInterval(c),window.cancelAnimationFrame(h),s()}}function ln(n,e){const s=e.icon||we.sparkles,t=Math.round(22*le(e)),a=[];let i=0;const o=()=>{const c=document.createElement("span");c.className="atf-success__spark",c.setAttribute("aria-hidden","true"),c.textContent=s,c.style.insetInlineStart=`${4+Math.random()*92}%`,c.style.animationDuration=`${2.6+Math.random()*1.8}s`,c.style.animationDelay=`${Math.random()*.3}s`,c.style.fontSize=`${14+Math.random()*14}px`,c.addEventListener("animationend",()=>c.remove()),n.append(c),a.push(c),i++};o();const l=window.setInterval(()=>{if(i>=t){window.clearInterval(l);return}o()},2800/t);return()=>{window.clearInterval(l),a.forEach(c=>c.remove())}}function cn(n){const e=n.querySelector(".atf-success__message");if(!e)return()=>{};const s=e.innerHTML,t=e.textContent??"";if(!t)return()=>{};e.textContent="",e.classList.add("is-typing");const a=Math.min(45,3800/t.length);let i=0;const o=window.setInterval(()=>{i++,e.textContent=t.slice(0,i),i>=t.length&&(window.clearInterval(o),e.classList.remove("is-typing"),e.innerHTML=s)},a);return()=>{window.clearInterval(o),e.classList.remove("is-typing"),e.innerHTML=s}}const dn={min:-1,max:-1,sum:-1,avg:-1,round:-1,ceil:1,floor:1,abs:1,sqrt:1,pow:2},Et={"+":{precedence:1,right:!1},"-":{precedence:1,right:!1},"*":{precedence:2,right:!1},"/":{precedence:2,right:!1},"%":{precedence:2,right:!1},"^":{precedence:4,right:!0}};function hn(n,e,s=[]){if(!n||!n.trim()||n.length>2e3)return null;const t=un(n,e,s),a=bn(t);if(!a)return null;const i=vn(a);if(!i)return null;const o=yn(i);return o===null||!Number.isFinite(o)?null:o}function un(n,e,s){return n.replace(/\{([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?\}/g,(t,a,i,o)=>pn(n,o,t.length,a,i??"",e,s))}function pn(n,e,s,t,a,i,o){const l=fn(o,t),c=Object.prototype.hasOwnProperty.call(i,t)?i[t]:null;if(a===""){const u=l?.type==="repeater"?Lt(c).length:Ke(c,l);return $t(u)}const h=(l?.fields??[]).find(u=>u.id===a)??null,m=Lt(c).map(u=>Ke(u[a]??"",h));if(!m.length)return"0";const g=m.map($t);return mn(n,e,s)?g.join(", "):g.length===1?g[0]:`( ${g.join(" + ")} )`}function fn(n,e){for(const s of n){if(s.id===e)return s;for(const t of s.fields??[])if(t.id===e)return t}return null}function mn(n,e,s){const t=n.slice(e+s).replace(/^\s+/,"");if(t===""||t[0]!==")")return!1;const a=n.slice(0,e).replace(/\s+$/,""),i=/([a-zA-Z_][a-zA-Z0-9_]*)\s*\($/.exec(a);return!!i&&["sum","avg","min","max"].includes(i[1].toLowerCase())}function Lt(n){if(!Array.isArray(n))return[];const e=[];for(const s of n){if(!s||typeof s!="object"||Array.isArray(s))continue;Object.values(s).some(a=>a!==""&&a!==null&&a!==void 0&&a!==!1&&!(Array.isArray(a)&&!a.length))&&e.push(s)}return e}function $t(n){const e=n.toFixed(10).replace(/0+$/,"").replace(/\.$/,"");return e===""||e==="-"?"0":e}function Ke(n,e){if(typeof n=="boolean")return n?1:0;if(Array.isArray(n))return n.reduce((a,i)=>a+Ke(i,e),0);if(n==null||n==="")return 0;const s=e?.choices??[];for(const a of s)if(String(a.value)===String(n)){if(typeof a.price=="number")return a.price;if(typeof a.points=="number")return a.points;break}const t=Number(n);return Number.isFinite(t)?t:0}function bn(n){const e=[];let s=0;for(;si.precedence||l.precedence===i.precedence&&!i.right){e.push(s.pop());continue}break}s.push(a);break}case"(":s.push(a);break;case")":{for(;s.length&&s[s.length-1].type!=="(";)e.push(s.pop());if(!s.length)return null;if(s.pop(),s.length&&s[s.length-1].type==="function"){const i=s.pop();i.arity=t.length?t.pop():1,e.push(i)}break}}for(;s.length;){const a=s.pop();if(a.type==="(")return null;e.push(a)}return e}function yn(n){const e=[];for(const s of n)switch(s.type){case"number":e.push(s.value);break;case"unary":{if(!e.length)return null;e.push(-e.pop());break}case"operator":{if(e.length<2)return null;const t=e.pop(),a=e.pop();switch(s.value){case"+":e.push(a+t);break;case"-":e.push(a-t);break;case"*":e.push(a*t);break;case"/":e.push(t===0?0:a/t);break;case"%":e.push(t===0?0:a%t);break;case"^":e.push(Math.pow(a,t));break;default:return null}break}case"function":{const t=s.arity??1;if(e.lengths+t,0);case"avg":return e.reduce((s,t)=>s+t,0)/e.length;case"round":{const s=Math.max(-10,Math.min(10,Math.trunc(e[1]??0))),t=Math.pow(10,s);return Math.round(e[0]*t)/t}case"ceil":return Math.ceil(e[0]);case"floor":return Math.floor(e[0]);case"abs":return Math.abs(e[0]);case"sqrt":return e[0]<0?0:Math.sqrt(e[0]);case"pow":return Math.pow(e[0],e[1]??2);default:return null}}const _n=["sum","min","max","avg","round","ceil","floor","abs","sqrt","pow"],At=["number","range","scale","rating","total","select","multiselect","radio","checkboxes","switch","quiz"];function _e(n,e){return n.filter(s=>s.id!==e&&At.includes(s.type))}function Tt(n){const e=[];for(const s of n){if(s.type!=="repeater")continue;const t=s.label||s.id;e.push({label:`${t} (how many)`,insert:`{${s.id}}`});for(const a of s.fields??[])At.includes(a.type)&&e.push({label:`${t} · ${a.label||a.id}`,insert:`{${s.id}.${a.id}}`})}return e}function xn(n,e){const s={};_e(n,e).forEach((t,a)=>{s[t.id]=a+1});for(const t of n){if(t.type!=="repeater"||t.id===e)continue;const a=t.fields??[],i=o=>Object.fromEntries(a.map((l,c)=>[l.id,c+1+o]));s[t.id]=[i(0),i(1)]}return s}function Mt(n,e,s){return Be(n,{preview:!1,groups:()=>[{id:"references",label:"Your questions",items:[..._e(e,s).map(t=>({label:t.label||t.id,tag:`{${t.id}}`,sample:"",hint:""})),...Tt(e.filter(t=>t.id!==s)).map(t=>({label:t.label,tag:t.insert,sample:"",hint:""}))],empty:"Add a number, scale or priced choice question to reference it here."}]})}function kn(n){const e=r("div",{class:"atfb-overlay"}),s=()=>{e.remove(),document.removeEventListener("keydown",t)},t=u=>{u.key==="Escape"&&s()},a=r("textarea",{class:"atfb-input atfb-formula__input",attrs:{rows:"3","aria-label":"Formula"}});a.value=String(n.field.formula??"");const i=r("p",{class:"atfb-formula__result",attrs:{"aria-live":"polite"}}),o=xn(n.fields,n.field.id),l=()=>{const u=a.value.trim();if(u===""){i.textContent="Empty. Reference a question below to start.",i.classList.remove("is-error");return}const f=hn(u,o,n.fields);if(f===null){i.textContent="This does not compute yet — check the braces and parentheses.",i.classList.add("is-error");return}const y=_e(n.fields,n.field.id).map((p,x)=>`${p.label||p.id} = ${x+1}`).concat(n.fields.filter(p=>p.type==="repeater"&&p.id!==n.field.id).map(p=>`${p.label||p.id} = 2 sample rows`)).join(", ");i.textContent=`With sample answers (${y}): ${f}`,i.classList.remove("is-error")};a.addEventListener("input",l);const c=(u,f,y=0)=>r("button",{class:"atfb-formula__chip",type:"button",text:u,on:{click:()=>{if(bt(a,f),y>0){const p=(a.selectionStart??a.value.length)-y;a.setSelectionRange(p,p)}}}}),d=_e(n.fields,n.field.id),h=Tt(n.fields.filter(u=>u.id!==n.field.id)),m=r("div",{class:"atfb-formula__chips",children:d.length||h.length?[...d.map(u=>c(u.label||u.id,`{${u.id}}`)),...h.map(u=>c(u.label,u.insert))]:[r("p",{class:"atfb-hint",text:"No number-shaped questions yet — add a number, scale or priced choice field and it appears here."})]}),g=r("div",{class:"atfb-formula__chips",children:_n.map(u=>c(`${u}()`,`${u}()`,1))});e.append(r("div",{class:"atfb-modal atfb-formula",attrs:{role:"dialog","aria-label":"Formula editor"},children:[r("h2",{text:"Formula"}),Mt(a,n.fields,n.field.id),i,w("Your questions",m,"Click one to reference its answer."),w("Functions",g),r("div",{class:"atfb-modal__actions",children:[C("Cancel",s),C("Save formula",()=>{n.onSave(a.value.trim()),s()},"primary")]})]})),e.addEventListener("click",u=>{u.target===e&&s()}),document.addEventListener("keydown",t),n.root.append(e),l(),a.focus(),a.setSelectionRange(a.value.length,a.value.length)}function Ft(n){return[...n.fields.filter(e=>e.type!=="page_break").map(e=>({key:`field:${e.id}`,label:`Field: ${e.label||e.id}`,fieldId:e.id,logic:e.logic})),...n.notifications.map(e=>({key:`notification:${e.id}`,label:`Notification: ${e.name||e.id}`,logic:e.logic})),...n.confirmations.map(e=>({key:`confirmation:${e.id}`,label:`Confirmation: ${e.name||e.id}`,logic:e.logic}))]}function It(n,e,s){return n.key!==e.key&&n.logic.rules.length>0&&n.logic.rules.every(t=>t.field!==e.fieldId&&s.fields.some(a=>a.id===t.field&&a.type!=="page_break"))}function Sn(n,e,s,t){const a=Ft(n),i=a.find(l=>l.key===e),o=a.find(l=>l.key===s);return!i||!o||!It(i,o,n)?!1:(t?.(),Object.assign(o.logic,i.logic,{rules:i.logic.rules.map(l=>({...l}))}),!0)}function Dt(n){const e=document.activeElement,s=r("div",{class:"atfb-overlay"}),t=r("div",{class:"atfb-modal atfb-condition-copy",attrs:{role:"dialog","aria-modal":"true","aria-label":"Copy condition",tabindex:"-1"}});let a="";const i=n.to,o=()=>{s.remove(),e?.focus()},l=()=>{const c=n.schema();if(!c){o();return}const d=Ft(c),h=d.find(p=>p.key===i),m=d.filter(p=>p.logic.rules.length&&h&&It(p,h,c)),g=m.find(p=>p.key===a),u=D(a,[{value:"",label:"Choose a section…"},...m.map(p=>({value:p.key,label:p.label}))],p=>{a=p,l(),t.querySelector('[aria-label="Copy from"]')?.focus()});u.setAttribute("aria-label","Copy from");const f=C("Copy condition",()=>{const p=n.schema();p&&Sn(p,a,i,n.beforeCopy)&&(o(),n.onCopy())},"primary");(!g||!i)&&f.setAttribute("disabled","");const y=d.find(p=>p.key===i);t.replaceChildren(r("h2",{text:"Copy condition"}),w("Copy from",u),r("p",{class:"atfb-hint",text:`Apply to ${y?.label??"this section"}.`}),r("p",{class:"atfb-condition-copy__preview",attrs:{"aria-live":"polite"},text:g?`${g.logic.enabled?"Enabled":"Disabled"} · ${g.logic.action==="hide"?"Hide":"Show"} · Match ${g.logic.match}: `+g.logic.rules.map(p=>qe(be(p,c.fields))).join(g.logic.match==="all"?" and ":" or "):m.length?"Choose the section whose condition you want to reuse.":"No conditions are available to copy here yet."}),r("p",{class:"atfb-hint",text:y?.logic.rules.length?"This replaces the destination’s entire condition. You can edit the copy independently.":"Copies every rule, all/any matching, show/hide and enabled state. You can edit the copy independently."}),r("div",{class:"atfb-modal__actions",children:[C("Cancel",o),f]}))};s.append(t),s.addEventListener("click",c=>{c.target===s&&o()}),s.addEventListener("keydown",c=>{if(c.key==="Escape"&&(c.preventDefault(),o()),c.key==="Tab"){const d=[...t.querySelectorAll("button:not([disabled]), select, os-select, os-button:not([disabled])")],h=d[0],m=d[d.length-1];c.shiftKey&&(document.activeElement===h||document.activeElement===t)?(c.preventDefault(),m?.focus()):!c.shiftKey&&document.activeElement===m&&(c.preventDefault(),h?.focus())}c.stopPropagation()}),n.root.append(s),l(),t.focus()}const Cn="allterrain-forms/form";function En(){return window.wp?.os?.relations??null}function qt(n){const e=n.closest("[data-window-id], .os-window");if(!e)return null;const s=e.getAttribute("data-window-id");if(s)return s;const t=e.id??"";return t?t.replace(/^wp-window-/,""):null}const Ln=6e3,Ot=120;function Nt(n,e){const s=En();if(Ge.set(n,e),!s?.set)return;const t=i=>{if(xe.get(n)!==a)return;const o=qt(n);if(!o){Date.now()t(i),Ot);return}try{s.set(o,e)}catch(c){Rt||(Rt=!0,console.error("[AllTerrain Forms] The shell refused a window identity.",c,e)),xe.delete(n);return}if(!e||s.get?.(o)?.id===e.id||Date.now()>=i){xe.delete(n);return}window.setTimeout(()=>t(i),Ot)},a=Symbol("atf-identity");xe.set(n,a),t(Date.now()+Ln)}let Rt=!1;const xe=new WeakMap,Ge=new Map;function $n(){for(const[n,e]of Ge){if(!n.isConnected){Ge.delete(n);continue}Nt(n,e)}}if(typeof document<"u")for(const n of["os-window-content-loaded","os-window-opened"])document.addEventListener(n,()=>$n());function An(n,e){return{type:Cn,id:n.id,label:n.title||"Untitled form",related:[{id:`allterrain-forms/entries-${n.id}`,label:"Entries for this form",url:`${e}admin.php?page=allterrain-forms-entries&form=${n.id}`,group:"allterrain-forms",groupLabel:"Forms",icon:"dashicons-list-view"}]}}const ke={letters:{label:"Letters",chars:"A-Za-zÀ-ÖØ-öø-ÿ"},numbers:{label:"Numbers",chars:"0-9"},spaces:{label:"Spaces",chars:" "},punctuation:{label:`Punctuation ( . , ! ? ' " - )`,chars:`.,!?'"()\\-:;`},symbols:{label:"Symbols ( @ # & _ / + )",chars:"@#&_/+*%="}};function Tn(){return{mode:"blocks",starts:"",ends:"",contains:"",notContains:"",chars:[],minLen:"",maxLen:"",regex:"",message:"",tests:[]}}function Pt(n){const e=Tn();let s;try{s=JSON.parse(n)}catch{return e}if(!s||typeof s!="object")return e;const t=s;e.mode=t.mode==="regex"?"regex":"blocks";for(const a of["starts","ends","contains","notContains","minLen","maxLen","regex","message"])typeof t[a]=="string"&&(e[a]=t[a]);return Array.isArray(t.chars)&&(e.chars=t.chars.filter(a=>typeof a=="string"&&a in ke)),Array.isArray(t.tests)&&(e.tests=t.tests.filter(a=>typeof a=="string").slice(0,10)),e}function Se(n){return n.replace(/[.*+?^${}()|[\]\\/]/g,"\\$&")}function Ce(n){if(n.mode==="regex")return n.regex.trim();const e=[],s=n.minLen.trim(),t=n.maxLen.trim();(s!==""||t!=="")&&e.push(`(?=.{${s===""?"0":parseInt(s,10)||0},${t===""?"":parseInt(t,10)||""}}$)`),n.contains!==""&&e.push(`(?=.*${Se(n.contains)})`),n.notContains!==""&&e.push(`(?!.*${Se(n.notContains)})`),n.starts!==""&&e.push(`(?=${Se(n.starts)})`),n.ends!==""&&e.push(`(?=.*${Se(n.ends)}$)`);const a=n.chars.map(o=>ke[o]?.chars??"").join(""),i=a?`[${a}]*$`:".*$";return!e.length&&!a?"":`^${e.join("")}${i}`}function Bt(n){if(n.mode==="regex")return n.regex.trim()?`Matches the expression ${n.regex.trim()}`:"";const e=[];if(n.starts&&e.push(`starts with “${n.starts}”`),n.ends&&e.push(`ends with “${n.ends}”`),n.contains&&e.push(`contains “${n.contains}”`),n.notContains&&e.push(`never contains “${n.notContains}”`),n.chars.length){const i=n.chars.map(o=>(ke[o]?.label??o).split(" (")[0].toLowerCase());e.push(`uses only ${i.join(" and ")}`)}const s=n.minLen.trim(),t=n.maxLen.trim();return s&&t?e.push(`is ${s}–${t} characters long`):s?e.push(`is at least ${s} characters long`):t&&e.push(`is at most ${t} characters long`),e.length?`The answer ${e.length>1?`${e.slice(0,-1).join(", ")}, and ${e[e.length-1]}`:e[0]}.`:""}function Mn(n,e){const s=Ce(n);if(s==="")return null;try{return new RegExp(s).test(e)}catch{return null}}function Fn(){return window.wp?.os?.windowManager??null}const Ht="allterrain-forms-validation";function In(n){const e=Fn(),s=qt(n.root);if(e?.openChild&&s){Dn(e,s,n);return}qn(n)}function Dn(n,e,s){const t=`${Ht}-${s.field.id}`;n.getById?.(t)&&n.remove?.(t);const a={saved:!1},i=()=>{const o=n.getById?.(t);o?.close?o.close():n.remove?.(t)};n.openChild?.(e,{id:t,baseId:Ht,url:`#${t}`,title:`Custom rule — ${s.field.label||"this question"}`,icon:"dashicons-yes-alt",native:!0,width:560,height:700,minWidth:440,minHeight:480,ephemeral:!0,autofocus:".atfb-valwin__pane:not([hidden]) input, .atfb-valwin__pane:not([hidden]) textarea",render:o=>{const l=r("div",{class:"atfa atfb-valwin atfb-valwin--window"}),c=r("div",{class:"atfb-valwin__scroll"});l.append(c),jt(c,s,a,i,"window");const d=c.querySelector(".atfb-modal__actions");d&&l.append(d),o.append(l)},onClose:()=>{a.saved||s.onCancel?.()}})}function qn(n){const e=r("div",{class:"atfb-overlay"}),s={saved:!1},t=()=>{e.remove(),document.removeEventListener("keydown",a),s.saved||n.onCancel?.()},a=o=>{o.key==="Escape"&&t()},i=r("div",{class:"atfb-modal atfb-valwin",attrs:{role:"dialog","aria-label":"Custom validation rule"},children:[r("h2",{text:"Custom rule"})]});jt(i,n,s,t,"overlay"),e.append(i),e.addEventListener("click",o=>{o.target===e&&t()}),document.addEventListener("keydown",a),n.root.append(e),e.querySelector(".atfb-valwin__pane:not([hidden]) input, .atfb-valwin__pane:not([hidden]) textarea")?.focus()}function jt(n,e,s,t,a){const i=Pt(String(e.field.validationRecipe??""));i.mode==="blocks"&&Ce(i)===""&&e.field.pattern&&(i.mode="regex",i.regex=String(e.field.pattern)),i.message||(i.message=String(e.field.messages?.invalid??""));const o=(b,M)=>{const $=r("input",{class:"atfb-input",value:i[b],placeholder:M,attrs:{type:"text"}});return $.addEventListener("input",()=>{i[b]=$.value,L()}),$},l=(b,M)=>{const $=r("input",{class:"atfb-input atfb-valwin__len",value:i[b],attrs:{type:"number",min:"0","aria-label":M}});return $.addEventListener("input",()=>{i[b]=$.value,L()}),$},c=r("div",{class:"atfb-valwin__chars",children:Object.entries(ke).map(([b,M])=>q(M.label,i.chars.includes(b),$=>{i.chars=$?[...i.chars,b]:i.chars.filter(W=>W!==b),L()}))}),d=r("div",{class:"atfb-valwin__pane",children:[w("Starts with",o("starts","e.g. AT-")),w("Ends with",o("ends","e.g. -2026")),w("Must contain",o("contains","e.g. @")),w("Must not contain",o("notContains","e.g. spaces? type one")),w("Only these characters",c,"Leave every box unticked to allow anything."),w("Length",r("div",{class:"atfb-valwin__lengths",children:[r("span",{text:"between"}),l("minLen","Minimum length"),r("span",{text:"and"}),l("maxLen","Maximum length"),r("span",{text:"characters"})]}),"Leave a box empty for no limit.")]}),h=r("textarea",{class:"atfb-input atfb-valwin__regex",attrs:{rows:"2","aria-label":"Regular expression",placeholder:"^AT-[0-9]{4}$"}});h.value=i.regex,h.addEventListener("input",()=>{i.regex=h.value,L()});const m=r("div",{class:"atfb-valwin__pane",children:[w("Expression",h,"A regular expression, without slashes. Checked against the whole answer only if you anchor it with ^ and $.")]}),g=[["blocks","Easy blocks"],["regex","Expression (advanced)"]],u=b=>{i.mode=b,d.hidden=b!=="blocks",m.hidden=b!=="regex",L()},y=(()=>{if(Y("os-segmented")&&Y("os-segment")){const $=document.createElement("os-segmented");$.setAttribute("value",i.mode),$.setAttribute("label","How to write the rule"),$.classList.add("atfb-valwin__tabs");for(const[W,H]of g){const ce=document.createElement("os-segment");ce.setAttribute("value",W),ce.textContent=H,$.append(ce)}return $.addEventListener("os-pick",W=>{const H=W.detail?.value;(H==="blocks"||H==="regex")&&($.setAttribute("value",H),u(H))}),$}const b=r("div",{class:"atfb-valwin__tabs",attrs:{role:"tablist"}}),M=()=>{b.replaceChildren(...g.map(([$,W])=>{const H=i.mode===$;return r("button",{class:`atfb-valwin__tab${H?" is-active":""}`,type:"button",text:W,attrs:{role:"tab","aria-selected":H?"true":"false"},on:{click:()=>{u($),M()}}})}))};return M(),b})();d.hidden=i.mode!=="blocks",m.hidden=i.mode!=="regex";const p=r("input",{class:"atfb-input",value:i.message,placeholder:"That is not in the expected format.",attrs:{type:"text"}});p.addEventListener("input",()=>{i.message=p.value});const x=r("p",{class:"atfb-valwin__summary",attrs:{"aria-live":"polite"}}),F=r("div",{class:"atfb-valwin__samples"}),S=b=>{const M=r("span",{class:"atfb-valwin__verdict",attrs:{"aria-live":"polite"}}),$=r("input",{class:"atfb-input",value:b,placeholder:"Type a sample answer…",attrs:{type:"text"}});$.addEventListener("input",()=>L()),F.append(r("div",{class:"atfb-valwin__sample",children:[$,M]}))};for(const b of i.tests.length?i.tests:["","",""])S(b);const j=()=>Array.from(F.querySelectorAll("input")).map(b=>b.value),L=()=>{const b=Bt(i);x.textContent=b||"Nothing yet — fill in a block above and the rule appears here in plain words.";for(const M of Array.from(F.querySelectorAll(".atfb-valwin__sample"))){const $=M.querySelector("input"),W=M.querySelector(".atfb-valwin__verdict");if(!$||!W)continue;const H=$.value===""?null:Mn(i,$.value);W.textContent=H===null?"·":H?"✓ passes":"✗ fails",W.classList.toggle("is-pass",H===!0),W.classList.toggle("is-fail",H===!1)}};n.append(r("p",{class:"atfb-hint",text:`Describe what a good answer to “${e.field.label||"this question"}” looks like — no code needed.`}),y,d,m,r("div",{class:"atfb-valwin__try",children:[r("h3",{text:"Try it out"}),x,F,C("Add another sample",()=>{S(""),L()},"ghost","plus-alt2")]}),w("When it fails, say",p,"Shown to the visitor when their answer breaks the rule. Leave empty for the default wording."),r("div",{class:"atfb-modal__actions",children:[C(a==="window"?"Close without saving":"Cancel",t),C("Save rule",()=>{const b=Ce(i);i.tests=j().filter(M=>M!=="").slice(0,10),s.saved=!0,e.onSave({pattern:b,recipe:i,message:i.message.trim()}),t()},"primary")]})),L()}const On=["Contact","Numbers & codes","Text shape","Web"],Wt=[{slug:"email",label:"An email address",group:"Contact",example:"jane@example.com",pattern:"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",message:"That does not look like an email address."},{slug:"phone",label:"A phone number",group:"Contact",example:"+34 612 345 678",pattern:"^(?=(?:[^0-9]*[0-9]){5,})\\+?[0-9 ().-]{5,24}$",message:"That does not look like a phone number."},{slug:"handle",label:"A username or @handle",group:"Contact",example:"@yourname",pattern:"^@?[A-Za-z0-9_]{2,30}$",message:"That does not look like a username."},{slug:"digits",label:"Numbers only",group:"Numbers & codes",example:"12345",pattern:"^[0-9]+$",message:"Numbers only, please."},{slug:"decimal",label:"A number, decimals allowed",group:"Numbers & codes",example:"3.14",pattern:"^-?[0-9]+([.,][0-9]+)?$",message:"That does not look like a number."},{slug:"price",label:"A price",group:"Numbers & codes",example:"19.99",pattern:"^[0-9]+([.,][0-9]{1,2})?$",message:"That does not look like a price."},{slug:"zip_us",label:"A ZIP code (US)",group:"Numbers & codes",example:"90210",pattern:"^[0-9]{5}(-[0-9]{4})?$",message:"That does not look like a ZIP code."},{slug:"postcode_uk",label:"A postcode (UK)",group:"Numbers & codes",example:"SW1A 1AA",pattern:"^[A-Za-z]{1,2}[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}$",message:"That does not look like a postcode."},{slug:"iban",label:"An IBAN",group:"Numbers & codes",example:"DE89 3704 0044 0532 0130 00",pattern:"^[A-Za-z]{2}[0-9]{2}(?: ?[A-Za-z0-9]){10,32}$",message:"That does not look like an IBAN."},{slug:"credit_card",label:"A card number",group:"Numbers & codes",example:"4242 4242 4242 4242",pattern:"^[0-9](?:[0-9 -]{9,21})?[0-9]$",message:"That does not look like a card number.",luhn:!0},{slug:"letters",label:"Letters only",group:"Text shape",example:"María López",pattern:"^[\\p{L}\\p{M} .'’-]+$",message:"Letters only, please."},{slug:"alphanumeric",label:"Letters and numbers only",group:"Text shape",example:"abc123",pattern:"^[A-Za-z0-9]+$",message:"Letters and numbers only, please."},{slug:"no_spaces",label:"One word, no spaces",group:"Text shape",example:"one-word",pattern:"^\\S+$",message:"No spaces allowed."},{slug:"url",label:"A web address",group:"Web",example:"https://example.com",pattern:"^(https?://)?([A-Za-z0-9-]+\\.)+[A-Za-z]{2,}([/?#]\\S*)?$",message:"That does not look like a web address."},{slug:"ip",label:"An IP address",group:"Web",example:"192.168.0.1",pattern:"^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",message:"That does not look like an IP address."},{slug:"slug",label:"A URL slug",group:"Web",example:"my-page-title",pattern:"^[a-z0-9]+(-[a-z0-9]+)*$",message:"Lowercase letters, numbers and dashes only."},{slug:"hex_color",label:"A hex colour",group:"Web",example:"#3366ff",pattern:"^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",message:"That does not look like a colour code."}];function Nn(n){return Wt.find(e=>e.slug===n)??null}function Xe(){return window.wp?.os??null}const Ut="allterrain-forms/preview",Ze="allterrain-forms-preview";function Rn(n){const e=Xe();if(!e?.registerTitleBarButton)return()=>{};const s=()=>{try{e.registerTitleBarButton({id:Ut,label:"Preview this form",icon:"dashicons-visibility",placement:"right",order:90,match:t=>{const a=t?.id??t?.config?.id??"";return a==="allterrain-forms"||a.startsWith("allterrain-forms#")},onClick:()=>void zt(n),owner:"allterrain-forms-builder"})}catch{}};return e.ready?e.ready(s):s(),()=>{try{e.unregisterTitleBarButton?.(Ut)}catch{}}}async function zt(n){n.isDirty()&&await n.save();const e=n.current();e&&Yt(e.id,e.title,e.previewUrl)}function Yt(n,e,s){const t=Xe();if(!t?.windowManager?.open){window.open(s,"_blank","noopener");return}t.windowManager.open({id:`${Ze}-${n}`,baseId:Ze,url:s,title:`Preview: ${e}`,icon:"dashicons-visibility"})}function Pn(n,e,s){if(!Xe()?.windowManager?.open||!document.querySelector(`[data-window-id="${Ze}-${n}"]`))return;const i=s.includes("?")?"&":"?";Yt(n,e,`${s}${i}alltfo_r=${Date.now()}`)}const se="allterrain-forms/field",Bn=["openstation/file","desktop-mode/file","openstation/attachment"],Vt="allterrain-forms/logic-map-v2";function J(n,e){return n.dataset.atfbBind=e,n}const Kt={level:{key:"level",label:"Heading level",control:"select",hint:"Headings should step down one at a time.",options:[{value:"2",label:"Heading 2"},{value:"3",label:"Heading 3"},{value:"4",label:"Heading 4"},{value:"5",label:"Heading 5"},{value:"6",label:"Heading 6"}]},content:{key:"content",label:"HTML",control:"textarea",hint:"Shown as written. Scripts are stripped when the form is saved."},consenttext:{key:"consentText",label:"What they are agreeing to",control:"textarea",hint:"Shown beside the tick box. Links are allowed."},height:{key:"height",label:"Height",control:"number",hint:"In pixels."},columns:{key:"columns",label:"Columns",control:"number",hint:"How many pictures sit side by side."},multiple:{key:"multiple",label:"Let them choose more than one",control:"checkbox"},inline:{key:"inline",label:"Lay the options out in a row",control:"checkbox"},other:{key:"other",label:"Offer an “Other” box",control:"checkbox",hint:"Adds a final option with a box to type in."},filetypes:{key:"filetypes",label:"Accepted file types",control:"commas",hint:"Extensions, separated by commas. Empty accepts anything the site allows."},maxsize:{key:"maxsize",label:"Largest file",control:"number",hint:"In megabytes."},maxfiles:{key:"maxfiles",label:"How many files",control:"number"},minrows:{key:"minRows",label:"Fewest rows",control:"number",also:{key:"maxRows",label:"Most rows"}},itemlabel:{key:"itemLabel",label:"What is one row called?",control:"text",hint:"Names each card — “Attendee 1”, “Attendee 2” — and the Remove button. Also editable on the card itself."},endlabels:{key:"minLabel",label:"Label at the low end",control:"text",also:{key:"maxLabel",label:"Label at the high end"}},points:{key:"points",label:"Points if correct",control:"number"},minchoices:{key:"minChoices",label:"Fewest they may pick",control:"number",also:{key:"maxChoices",label:"Most they may pick"}}},Hn={label:"the canvas edits it in place, and the inspector mirrors it",placeholder:"edited by typing into the control on the canvas",hint:"edited under the control on the canvas",nextlabel:"edited on the page break’s own Next button",prevlabel:"edited on the page break’s own Back button",addlabel:"edited on the repeater’s own Add button",choices:"the choices editor, and the option list on the canvas",required:"the toggle on the card",width:"its own row",css:"its own row",prefill:"its own section",logic:"the conditional logic section",formula:"its own row, with the currency that goes with it",currency:"rendered with the formula",correct:"the choices editor marks the right answer",default:"its own row, typed to match what the field stores",rows:"a row count on a textarea; the statement list on a Likert matrix",parts:"a tick box per part, listed by the server",min:"the validation section, paired with max",max:"the validation section, paired with min",step:"the validation section",minlength:"the validation section, paired with maxlength",maxlength:"the validation section, paired with minlength",mindate:"the validation section, paired with maxdate",maxdate:"the validation section, paired with mindate",mintime:"the validation section, paired with maxtime",maxtime:"the validation section, paired with mintime",pattern:"the validation section",unique:"the validation section",maxchoices:"rendered with minchoices",maxrows:"rendered with minrows"};function Gt(n,e,s){const t=n[e.key],a=i=>s(e.key,i);if(e.control==="checkbox")return q(e.label,!!t,a);if(e.control==="commas"){const i=Array.isArray(t)?t:[];return w(e.label,T(i.join(", "),o=>{a(o.split(",").map(l=>l.trim().replace(/^\./,"").toLowerCase()).filter(Boolean))}),e.hint)}return e.control==="select"?w(e.label,D(String(t??""),e.options??[],a),e.hint):e.control==="textarea"?w(e.label,fe(String(t??""),a),e.hint):e.control==="number"?w(e.label,V(String(t??""),a),e.hint):w(e.label,J(T(String(t??""),a),e.key),e.hint)}function Xt(n,e){const s=new Set(n.map(a=>a.key).filter(Boolean));let t=n.length+1;return e.split(` -`).map(a=>a.trim()).filter(Boolean).map((a,i)=>{const o=n[i]?.key;if(o)return{key:o,label:a};for(;s.has(`r${t}`);)t+=1;return s.add(`r${t}`),{key:`r${t}`,label:a}})}function Zt(n,e,s){const t=n.findIndex(i=>i.id===e);if(t<0)return null;const a=Math.max(0,Math.min(s,n.length-1));return a===t?null:{from:t,to:a}}const Je=[{value:"user:email",label:"Their email address",group:"About the person filling it in",tag:"{user:email}"},{value:"user:display_name",label:"Their name",group:"About the person filling it in",tag:"{user:display_name}"},{value:"user:first_name",label:"Their first name",group:"About the person filling it in"},{value:"user:last_name",label:"Their last name",group:"About the person filling it in"},{value:"user:login",label:"Their username",group:"About the person filling it in"},{value:"date:today",label:"Today’s date",group:"The date and time",tag:"{date}"},{value:"date:now",label:"The time right now",group:"The date and time",tag:"{time}"},{value:"site",label:"This site’s name",group:"About this site",tag:"{site}"},{value:"site:url",label:"This site’s address",group:"About this site",tag:"{site:url}"},{value:"site:admin_email",label:"The site administrator’s email",group:"About this site",tag:"{admin_email}"}],jn=["About the person filling it in","The date and time","About this site"],Qe=(n,e)=>U?.i18n?.[n]??e;class Jt{constructor(e){this.config=null,this.themes=[],this.forms=[],this.form=null,this.schema=null,this.selected=null,this.tab="build",this.logicMap=null,this.canvasTheme=r("style"),this.canvasThemeSignature="",this.openSections=new Map,this.logicMapOn=fs(Vt)!=="off",this.dirty=!1,this.editGeneration=0,this.saveInFlight=!1,this.queuedSave=null,this.teardowns=[],this.canvasTarget=null,this.history=[],this.historyAt=-1,this.autosave=Me(()=>{this.save(!0)},2500),this.renderInspector=ps(()=>{if(R(this.inspector),!this.schema||(this.root.classList.toggle("atfb--build-only-panes",this.tab!=="build"),this.tab!=="build"))return;const s=this.selected?this.locateField(this.selected):void 0,t=s?.field,a=s?.parent??null;if(this.root.classList.toggle("atfb--has-selection",!!t),!t){this.inspector.append(r("div",{class:"atfb-placeholder",children:[r("p",{text:"Select a field to change it."}),r("p",{class:"atfb-hint",text:"Drag a field from the palette, or press one to add it to the end."})]}));return}const i=this.config?.fieldTypes.find(c=>c.type===t.type),o=i?.supports??[],l=(c,d)=>{const h=this.liveField(t.id);h&&(h[c]=d,this.markDirty(),this.renderCanvas())};this.inspector.append(r("h3",{class:"atfb-inspector__title",text:i?.label??t.type})),a?this.inspector.append(r("p",{class:"atfb-hint atfb-inspector__crumb",text:`Inside ${a.label||"a repeater"} — the visitor answers this once per ${String(a.itemLabel??"")||"row"}.`}),r("p",{class:"atfb-hint",text:`Formulas aggregate it as {${a.id}.${t.id}} — e.g. sum( {${a.id}.${t.id}} ).`})):this.inspector.append(r("p",{class:"atfb-hint",text:`Reference this field as {field:${t.id}}`})),o.includes("label")&&this.inspector.append(w("Label",J(T(t.label,c=>l("label",c)),"label"))),o.includes("placeholder")&&this.inspector.append(w("Placeholder",J(T(t.placeholder,c=>l("placeholder",c)),"placeholder"))),o.includes("hint")&&this.inspector.append(w("Hint",J(T(t.hint,c=>l("hint",c)),"hint"),"Shown under the field, and read out with it.")),o.includes("nextlabel")&&this.inspector.append(w("Next button",J(T(String(t.nextLabel??""),c=>l("nextLabel",c)),"nextLabel"),"Leave empty for “Next”.")),o.includes("prevlabel")&&this.inspector.append(w("Back button",J(T(String(t.prevLabel??""),c=>l("prevLabel",c)),"prevLabel"),"Leave empty for “Back”.")),o.includes("addlabel")&&this.inspector.append(w("Add button",J(T(String(t.addLabel??""),c=>l("addLabel",c)),"addLabel"),"Leave empty for “Add another”.")),o.includes("required")&&this.inspector.append(q("Required",t.required,c=>l("required",c))),o.includes("width")&&this.inspector.append(w("Width",D(t.width,[{value:"full",label:"Full width"},{value:"two-thirds",label:"Two thirds"},{value:"half",label:"Half"},{value:"third",label:"One third"},{value:"quarter",label:"One quarter"}],c=>l("width",c)))),i?.choices&&this.inspector.append(this.renderChoicesEditor(t,l)),this.renderTypeSettings(t,i,o,l),(t.type==="total"||o.includes("formula"))&&this.inspector.append(w("Formula",r("div",{class:"atfb-formula__row",children:[Mt(T(String(t.formula??""),c=>l("formula",c)),this.schema?.fields??[],t.id),C("Formula editor",()=>kn({root:this.root,fields:this.schema?.fields??[],field:this.liveField(t.id)??t,onSave:c=>{l("formula",c),this.renderInspector()}}))]}),"Reference answers with braces — {f1} * {f2} + 10 — or open the editor and click them in."),w("Currency symbol",T(String(t.currency??""),c=>l("currency",c)))),this.inspector.append(this.renderValidationSection(t,o,l)),a||(this.inspector.append(this.renderLogicSection(t)),o.includes("prefill")&&this.inspector.append(this.prefillControl(t,l))),o.includes("css")&&this.inspector.append(w("CSS class",T(t.cssClass,c=>l("cssClass",c))))}),this.root=e,this.bar=e.querySelector("[data-atfb-bar]")??r("div"),this.palette=e.querySelector("[data-atfb-palette]")??r("div"),this.canvas=e.querySelector("[data-atfb-canvas]")??r("div"),this.inspector=e.querySelector("[data-atfb-inspector]")??r("div"),this.canvas.addEventListener("click",s=>{const t=s.target;if(!(this.tab!=="build"||!this.selected||t.closest("[data-atfb-card], button, os-button, a, input, textarea, select, os-select, label, [contenteditable]"))){this.selected=null;for(const a of this.canvas.querySelectorAll(".atfb-card.is-selected"))a.classList.remove("is-selected");this.renderInspector()}})}async start(){try{const[t,a,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);this.config=t,this.themes=a,this.forms=i}catch(t){this.fail(t);return}this.teardowns.push(os([se])),this.teardowns.push(Rn({current:()=>this.form?{id:this.form.id,title:this.form.title,previewUrl:this.form.previewUrl}:null,isDirty:()=>this.dirty,save:()=>this.save(!0)}));const e=t=>{this.dirty&&(t.preventDefault(),t.returnValue="")};window.addEventListener("beforeunload",e),this.teardowns.push(()=>window.removeEventListener("beforeunload",e));const s=t=>{!(t.metaKey||t.ctrlKey)||t.key.toLowerCase()!=="z"||t.target?.closest("input, textarea, [contenteditable]")||(t.preventDefault(),this.travel(t.shiftKey?1:-1))};if(this.root.addEventListener("keydown",s),this.teardowns.push(()=>this.root.removeEventListener("keydown",s)),this.renderBar(),this.renderPalette(),this.forms.length){const t=Ss("builder");await this.open(t&&this.forms.some(a=>a.id===t)?t:this.forms[0].id)}else this.renderFormsList()}destroy(){this.canvasTarget?.(),this.canvasTarget=null,this.teardowns.forEach(e=>e()),this.teardowns=[]}fail(e){R(this.bar),this.bar.append(r("p",{class:"atfb-error",text:e instanceof Error?e.message:"Something went wrong loading your forms."}))}renderBar(){R(this.bar);const e=D(String(this.form?.id??""),[...this.forms.map(a=>({value:String(a.id),label:a.title||"(untitled)"}))],a=>void this.open(Number(a)));e.setAttribute("aria-label","Choose a form");const s=r("input",{class:"atfb-title",type:"text",value:this.form?.title??"",placeholder:"Untitled form",attrs:{"aria-label":"Form title"},on:{input:a=>{this.form&&(this.form.title=a.target.value,this.markDirty())}}}),t=r("div",{class:"atfb-tabs",attrs:{role:"tablist"},children:[["build","Build"],["theme","Theme"],["settings","Settings"],["notify","Notifications"],["confirm","Confirmations"]].map(([a,i])=>r("button",{class:`atfb-tab${this.tab===a?" is-active":""}`,type:"button",text:i,attrs:{role:"tab","aria-selected":this.tab===a},on:{click:()=>{this.tab=a,this.renderBar(),this.renderInspector(),this.renderCanvas()}}}))});this.bar.append(r("div",{class:"atfb-bar__left",children:[this.forms.length>1?e:null,s]}),t,r("div",{class:"atfb-bar__right",children:[this.historyButton("undo","Undo",-1),this.historyButton("redo","Redo",1),C("New",()=>void this.showTemplates(),"secondary","plus-alt2"),C("Export",()=>void this.exportForm(),"secondary","download"),C("Import",()=>void this.importForm(),"secondary","upload"),C("Preview",()=>void this.preview(),"secondary","visibility"),C("Entries",()=>this.openEntries(),"secondary","list-view"),this.logicMapButton(),this.saveButton()]}))}liveField(e){return this.locateField(e)?.field}locateField(e){const s=this.schema?.fields??[];for(let t=0;tqueueMicrotask(()=>this.rebindCanvas()),{once:!0});return}if(this.canvas.matches(":hover")){this.canvas.addEventListener("pointerleave",()=>this.rebindCanvas(),{once:!0});return}this.renderCanvas()}snapshot(){if(!this.schema)return;const e=JSON.stringify(this.schema);this.history[this.historyAt]!==e&&(this.history=this.history.slice(0,this.historyAt+1),this.history.push(e),this.history.length>60&&this.history.shift(),this.historyAt=this.history.length-1,this.syncHistoryButtons())}travel(e){const s=this.historyAt+e;!this.schema||s<0||s>=this.history.length||(this.historyAt=s,this.schema=JSON.parse(this.history[s]),this.schema.fields.some(t=>t.id===this.selected)||(this.selected=null),this.markDirty(),this.renderBar(),this.renderCanvas(),this.renderInspector())}historyButton(e,s,t){const a=C(s,()=>this.travel(t),"secondary",e);return a.setAttribute("data-atfb-history",String(t)),a.disabled=!this.canTravel(t),a}canTravel(e){const s=this.historyAt+e;return s>=0&&sURL.revokeObjectURL(t),1e3)}async importForm(){const e=r("input",{type:"file",attrs:{accept:"application/json,.json"}});e.addEventListener("change",async()=>{const s=e.files?.[0];if(s)try{const t=JSON.parse(await s.text());if(!t.schema)throw new Error("That file does not contain a form.");const a=await I.createForm({title:t.title??s.name.replace(/\.json$/i,""),schema:t.schema});this.forms.unshift({id:a.id,title:a.title,status:a.status,modified:a.modified,fields:a.schema.fields.length,theme:a.schema.settings.theme,entries:0,unread:0,views:0,submissions:0,shortcode:a.shortcode}),this.form=a,this.schema=a.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot(),this.renderBar(),this.renderCanvas(),this.renderInspector(),N("Form imported",a.title)}catch(t){N("Could not import that file",t instanceof Error?t.message:"","error")}}),e.click()}saveButton(){const e=C("Save",()=>void this.save(),"primary");return e.disabled=!this.dirty,e.setAttribute("data-atfb-save",""),e}markDirty(){this.dirty=!0,this.editGeneration+=1;const e=this.bar.querySelector("[data-atfb-save]");e&&(e.disabled=!1),this.autosave()}async save(e=!1){if(!this.form||!this.schema)return;if(this.saveInFlight){this.queuedSave={silent:e&&(this.queuedSave?.silent??!0)};return}this.saveInFlight=!0;const s=this.editGeneration;try{const t=await I.updateForm(this.form.id,{title:this.form.title,schema:this.schema});if(s===this.editGeneration){this.form=t,this.schema=t.schema,this.dirty=!1,this.rebindCanvas();const i=this.bar.querySelector("[data-atfb-save]");i&&(i.disabled=!0)}Bs(t.id);const a=this.forms.find(i=>i.id===t.id);a&&(a.title=t.title),Pn(t.id,t.title,t.previewUrl),e||N("Form saved",t.title)}catch(t){N(Qe("saveFailed","Could not save"),t instanceof Error?t.message:"","error")}finally{this.saveInFlight=!1;const t=this.queuedSave;this.queuedSave=null,t&&this.save(t.silent)}}async openFormById(e){await this.open(e)}async open(e){if(!(this.dirty&&!await ie("You have unsaved changes. Discard them?"))){try{this.form=await I.getForm(e),this.schema=this.form.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot()}catch(s){this.fail(s);return}this.renderBar(),this.renderCanvas(),this.renderInspector(),this.announceIdentity()}}announceIdentity(){this.form&&Nt(this.root,An(this.form,U?.adminUrl??""))}async showTemplates(){if(!this.config)return;const e=r("div",{class:"atfb-overlay"}),s=i=>{i.key==="Escape"&&t()},t=()=>{e.remove(),document.removeEventListener("keydown",s)},a=r("div",{class:"atfb-templates",children:this.config.templates.map(i=>r("button",{class:"atfb-template",type:"button",on:{click:async()=>{t();try{const o=await I.createForm({template:i.slug});this.forms.unshift({id:o.id,title:o.title,status:o.status,modified:o.modified,fields:o.schema.fields.length,theme:o.schema.settings.theme,entries:0,unread:0,views:0,submissions:0,shortcode:o.shortcode}),this.form=o,this.schema=o.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot(),this.renderBar(),this.renderCanvas(),this.renderInspector(),this.announceIdentity()}catch(o){N("Could not create the form",o instanceof Error?o.message:"","error")}}},children:[B(i.icon),r("strong",{text:i.label}),r("span",{text:i.description})]}))});e.append(r("div",{class:"atfb-modal",attrs:{role:"dialog","aria-label":"Start a new form"},children:[r("h2",{text:"Start a new form"}),a,this.archivedFormsSection(t),r("div",{class:"atfb-modal__actions",children:[C("Cancel",t)]})]})),e.addEventListener("click",i=>{i.target===e&&t()}),document.addEventListener("keydown",s),this.root.append(e),a.querySelector("button")?.focus()}archivedFormsSection(e){const s=r("div",{class:"atfb-archived"});return I.listArchivedForms().then(t=>{t.length&&s.append(r("h3",{class:"atfb-archived__title",text:"Or bring one back from the archive"}),...t.map(a=>r("div",{class:"atfb-archived__row",children:[r("div",{class:"atfb-archived__meta",children:[r("strong",{text:a.title||"(untitled)"}),r("span",{class:"atfb-hint",text:`${a.entries} ${a.entries===1?"entry":"entries"} · ${a.submissions} submissions · ${a.views} views`})]}),C("Restore",async()=>{try{const i=await I.unarchiveForm(a.id);e(),this.forms.unshift(i),N("Form restored",`${i.title||"(untitled)"} is back, with its entries and stats.`),await this.open(i.id)}catch(i){N("Could not restore the form",i instanceof Error?i.message:"","error")}},"secondary","undo")]})))}).catch(()=>{}),s}renderFormsList(){R(this.canvas),this.canvas.append(r("div",{class:"atfb-empty",children:[r("h2",{text:"No forms yet"}),r("p",{text:"Start from a template, or build one from nothing."}),C("New form",()=>void this.showTemplates(),"primary","plus-alt2")]}))}openEntries(){const e=window.wp?.os;if(e?.openWindow){e.openWindow("allterrain-forms-entries");return}window.location.assign(`${U?.adminUrl??""}admin.php?page=allterrain-forms-entries`)}renderPalette(){if(!this.config)return;R(this.palette);const e=new Map;for(const t of this.config.fieldTypes){const a=e.get(t.group)??[];a.push(t),e.set(t.group,a)}const s=r("input",{class:"atfb-input atfb-palette__search",type:"search",placeholder:"Search fields",attrs:{"aria-label":"Search field types"},on:{input:t=>{const a=t.target.value.toLowerCase().trim();this.palette.querySelectorAll(".atfb-chip").forEach(i=>{const o=(i.textContent??"").toLowerCase();i.hidden=a!==""&&!o.includes(a)}),this.palette.querySelectorAll(".atfb-group").forEach(i=>{const o=Array.from(i.querySelectorAll(".atfb-chip")).some(l=>!l.hidden);i.hidden=!o})}}});this.palette.append(s);for(const[t,a]of Object.entries(this.config.groups)){const i=e.get(t);i?.length&&this.palette.append(r("div",{class:"atfb-group",children:[r("h3",{class:"atfb-group__title",text:a}),r("div",{class:"atfb-group__items",children:i.map(o=>this.paletteChip(o))})]}))}}paletteChip(e){const s=r("button",{class:"atfb-chip",type:"button",title:e.description,attrs:{"data-atf-type":e.type},children:[B(e.icon),r("span",{text:e.label})]});return s.addEventListener("pointerdown",t=>{const a=r("div",{class:"atfb-chip atfb-chip--ghost",children:[B(e.icon),r("span",{text:e.label})]});G().start({payload:Ae(se,s,{fieldType:e.type,isNew:!0},t,a),origin:t,onClickOnly:()=>this.addField(e.type)})}),s.addEventListener("click",t=>{G().recentlyEndedDrag()&&t.preventDefault()}),s}renderCanvas(){if(R(this.canvas),!this.schema||!this.form){this.renderFormsList();return}if(this.tab!=="build"){this.canvas.append(this.renderTabCanvas());return}const e=r("div",{class:"atfb-canvas__list",attrs:{"data-atfb-list":""}});this.schema.fields.length||e.append(r("div",{class:"atfb-placeholder",text:Qe("emptyCanvas","Drag a field from the left to begin.")})),this.schema.fields.forEach((t,a)=>{e.append(this.renderFieldCard(t,a))});const s=r("div",{class:"atfb-canvas__inner",children:[r("p",{class:"atfb-shortcode",text:this.form.shortcode,title:"Paste this anywhere to place the form"}),e]});this.canvas.append(s),this.registerCanvasTarget(e),this.paintLogicMap(s),this.paintCanvasTheme()}prefillControl(e,s){const t=e.prefill.startsWith("query:"),a=Je.some(g=>g.value===e.prefill),i=t?"query":a&&e.prefill||(e.prefill?"custom":""),o=r("div",{class:"atfb-prefill__detail"}),l=r("p",{class:"atfb-row__hint atfb-prefill__preview"}),c=g=>{if(o.replaceChildren(),l.replaceChildren(),g==="query"){const u=e.prefill.startsWith("query:")?e.prefill.slice(6):"";o.append(T(u,f=>{const y=f.trim();s("prefill",y?`query:${y}`:""),d(`query:${y}`)},"utm_source"),r("p",{class:"atfb-row__hint",text:"The name of the parameter in the link people arrive on."}))}g==="custom"&&o.append(T(e.prefill,u=>{s("prefill",u),d(u)},"myplugin:something"),r("p",{class:"atfb-row__hint",text:"For a source another plugin has added through alltfo_resolve_prefill."})),d(e.prefill)},d=g=>{if(l.replaceChildren(),!g)return;if(g.startsWith("query:")){const f=g.slice(6);f&&(l.textContent=`A visit to …/your-page/?${f}=abc opens the form with “abc” in it.`);return}const u=Je.find(f=>f.value===g)?.tag;u&&ft(this.form?.id??0).then(f=>{for(const y of f)for(const p of y.items)if(p.tag===u){const x=g.startsWith("user:");if(!p.sample){l.textContent="Empty unless the visitor is signed in.";return}l.textContent=x?`Opens with “${p.sample}” for you — empty for a visitor who is not signed in.`:`Opens with “${p.sample}”.`;return}})};c(i);const h=r("select",{class:"atfb-input atfb-select",on:{change:g=>{const u=g.target.value;s("prefill",u==="query"||u==="custom"?"":u),c(u)}}});h.append(r("option",{value:"",text:"Nothing — leave it empty",attrs:{selected:i===""}}));for(const g of jn){const u=document.createElement("optgroup");u.label=g;for(const f of Je.filter(y=>y.group===g))u.append(r("option",{value:f.value,text:f.label,attrs:{selected:f.value===i}}));h.append(u)}const m=document.createElement("optgroup");return m.label="From the link they arrived on",m.append(r("option",{value:"query",text:"A parameter in the web address",attrs:{selected:i==="query"}})),h.append(m,r("option",{value:"custom",text:"Something else (advanced)",attrs:{selected:i==="custom"}})),w("Pre-fill this with",r("div",{class:"atfb-prefill",children:[h,o,l]}),"What the box already contains when the form opens. They can still change it.")}renderCondition(e,s){const t=s.some(l=>l.kind==="field"&&l.missing),a=r("div",{class:`atfb-cond${t?" is-broken":""}`,attrs:{"aria-label":s.length?qe(s):"Conditional rules"}});a.append(r("div",{class:"atfb-cond__heading",children:[r("span",{class:"atfb-cond__label",children:[B("randomize"),"Conditions"]}),this.copyConditionButton(`field:${e.id}`)]})),e.logic.rules.forEach((l,c)=>{const d=be(l,this.schema?.fields??[],c),h=r("button",{class:"atfb-cond__delete",type:"button",title:"Delete this rule",attrs:{"aria-label":`Delete rule ${c+1}`},children:[B("trash")],on:{click:()=>{this.snapshot(),this.editCondition(e.id,m=>{m.rules.splice(c,1)},!0,`${e.id}:add`),this.snapshot()}}});a.append(r("div",{class:"atfb-cond__rule",children:[c===0?this.renderConditionToken(e,{kind:"verb",text:e.logic.action==="hide"?"Hidden when":"Shown when"}):this.renderConditionToken(e,{kind:"join",text:e.logic.match==="all"?"and":"or"}),...d.map(m=>this.renderConditionToken(e,m,c)),h]}))}),e.logic.rules.length||a.append(r("span",{class:"atfb-hint",text:"No rules yet. Add one or copy a condition."}));const i=r("button",{class:"atfb-cond__add",type:"button",text:"+ Add rule",title:"Add rule",attrs:{"aria-label":"Add rule","data-cond":`${e.id}:add`},on:{click:()=>this.addConditionRule(e.id)}}),o=r("button",{class:"atfb-cond__clear",type:"button",text:"Clear",title:"Delete all rules",attrs:{"aria-label":"Clear all rules",disabled:!e.logic.rules.length},on:{click:()=>{this.snapshot(),this.editCondition(e.id,l=>{l.rules=[]},!0,`${e.id}:add`),this.snapshot()}}});return a.append(r("div",{class:"atfb-cond__actions",children:[i,o]})),a.addEventListener("pointerdown",l=>l.stopPropagation()),a.addEventListener("click",l=>l.stopPropagation()),a.addEventListener("keydown",l=>l.stopPropagation()),a}editCondition(e,s,t=!0,a=""){const i=this.liveField(e)?.logic;if(i){if(s(i),this.markDirty(),!t){this.logicMap?.setEdges(ge(this.schema?.fields??[]));return}this.renderCanvas(),this.renderInspector(),a&&window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-cond="${CSS.escape(a)}"]`)?.focus()})}}condSelect(e,s,t,a,i){if(Y("os-select")&&Y("os-option")){const o=document.createElement("os-select");o.setAttribute("value",e),o.setAttribute("aria-label",a),o.setAttribute("data-cond",t),o.className="atfb-cond__control",o.setAttribute("plain",""),o.title=a;for(const l of s){const c=document.createElement("os-option");c.setAttribute("value",l.value),l.disabled&&c.setAttribute("disabled",""),c.textContent=l.label,o.append(c)}return o.addEventListener("os-pick",l=>{i(String(l.detail?.value??""))}),o}return r("select",{class:"atfb-cond__control atfb-cond__control--native",title:a,attrs:{"aria-label":a,"data-cond":t},on:{change:o=>i(o.target.value)},children:s.map(o=>r("option",{value:o.value,text:o.label,attrs:{selected:o.value===e,disabled:o.disabled}}))})}renderConditionToken(e,s,t=0){if(s.kind==="field"){const a=`${e.id}:source:${t}`,i=(this.schema?.fields??[]).filter(o=>o.id!==e.id&&o.type!=="page_break");return this.condSelect(s.fieldId,[...s.missing?[{value:s.fieldId,label:"Choose a question…"}]:[],...i.map(o=>({value:o.id,label:o.label||o.id}))],a,"Question used by this rule",o=>this.editCondition(e.id,l=>{const c=l.rules[t];c&&(c.field=o,c.value="")},!0,a))}if(s.kind==="verb")return r("button",{class:"atfb-cond__verb",type:"button",text:s.text,title:"Switch between showing and hiding this field when the condition matches.",attrs:{"data-cond":`${e.id}:verb`},on:{click:()=>this.editCondition(e.id,a=>{a.action=a.action==="hide"?"show":"hide"},!0,`${e.id}:verb`)}});if(s.kind==="join")return r("button",{class:"atfb-cond__join",type:"button",text:s.text,title:"Switch between needing every rule (and) or any one of them (or).",attrs:{"data-cond":`${e.id}:join`},on:{click:()=>this.editCondition(e.id,a=>{a.match=a.match==="all"?"any":"all"},!0,`${e.id}:join`)}});if(s.kind==="operator"){const a=`${e.id}:op:${s.ruleIndex}`;return this.condSelect(s.operator,Object.entries(Ie).map(([i,o])=>({value:i,label:o})),a,"How the answer is compared",i=>this.editCondition(e.id,o=>{const l=o.rules[s.ruleIndex];l&&(l.operator=i)},!0,a))}return s.kind==="value"?this.renderConditionValue(e,s):r("span")}renderConditionValue(e,s){const t=`${e.id}:value:${s.ruleIndex}`,a=this.schema?.fields.find(d=>d.id===s.sourceId),i=(d,h)=>this.editCondition(e.id,m=>{const g=m.rules[s.ruleIndex];g&&(g.value=d)},h,t),o=it(a,s.raw,this.config?.countries);if(o){const d=this.condSelect(s.raw,o,t,"The answer that triggers this",h=>i(h,!0));return d.classList.add("atfb-cond__value-select"),d.removeAttribute("plain"),d}const l=["number","range","scale","rating","total"].includes(a?.type??""),c=r("input",{class:"atfb-cond__chip atfb-cond__chip--value atfb-cond__value",value:s.raw,title:"The answer that triggers this. Edit it here.",attrs:{type:"text","aria-label":"The answer that triggers this","data-cond":t,inputmode:l?"decimal":void 0,size:String(Math.max(2,Math.min(24,s.raw.length||2)))}});return c.addEventListener("input",()=>{c.size=Math.max(2,Math.min(24,c.value.length||2)),i(c.value,!1)}),c.addEventListener("change",()=>i(c.value,!0)),c.addEventListener("keydown",d=>{d.key==="Enter"&&(d.preventDefault(),i(c.value,!0))}),c}section(e,s,t,a=!1){const i=r("details",{class:"atfb-section",attrs:{open:this.openSections.get(e)??a},children:[r("summary",{text:s}),...t]});return i.addEventListener("toggle",()=>this.openSections.set(e,i.open)),i}logicMapButton(){const e=ge(this.schema?.fields??[]).length>0,s=C(this.logicMapOn?"Hide logic":"Show logic",()=>{this.logicMapOn=!this.logicMapOn,ms(Vt,this.logicMapOn?"on":"off"),this.renderBar(),this.renderCanvas()},this.logicMapOn?"primary":"secondary","randomize");return s.title="Draw a line from each question to the ones it decides.",s.hidden=!e,s}paintLogicMap(e){this.logicMap?.destroy(),this.logicMap=null;const s=this.schema?.fields??[],t=ge(s);if(!t.length||!this.logicMapOn)return;e.classList.add("has-logicmap");const a=new As(e);a.setEdges(t),a.highlight(this.selected??""),this.logicMap=a,e.addEventListener("pointerover",i=>{const o=i.target.closest("[data-atfb-card]");a.highlight(o?.dataset.atfbCard??this.selected??"")}),e.addEventListener("pointerleave",()=>a.highlight(this.selected??""))}renderFieldCard(e,s){const t=this.config?.fieldTypes.find(d=>d.type===e.type),a=this.selected===e.id,i=this.schema?.fields??[],o=Es(e,i),l=$s(i).get(e.id)??0,c=r("div",{class:`atfb-card${a?" is-selected":""}`,attrs:{"data-atfb-card":e.id,"data-index":s,tabindex:"0",role:"button","aria-pressed":a,"aria-label":`${e.label||t?.label||e.type}, ${s+1} of ${this.schema?.fields.length??0}`},children:[r("div",{class:"atfb-card__bar",children:[r("div",{class:"atfb-card__grip",attrs:{"aria-hidden":"true"},children:[B("menu")]}),r("div",{class:"atfb-card__head",children:[B(t?.icon??"dashicons-forms"),r("span",{class:"atfb-card__type",text:t?.label??e.type}),this.requiredToggle(e),e.type!=="page_break"?this.conditionToolbar(e):null,l?r("span",{class:"atfb-badge atfb-badge--controls",text:l===1?"controls 1 field":`controls ${l} fields`,title:"Other questions appear or disappear based on this answer."}):null]}),r("div",{class:"atfb-card__actions",children:[this.cardAction("admin-page","Duplicate",()=>this.duplicateField(e.id)),this.cardAction("trash","Delete",()=>void this.deleteField(e.id))]})]}),r("div",{class:"atfb-card__body",children:[pt(e,t,{edit:d=>{const h=this.liveField(e.id);if(!h)return;d(h),this.markDirty(),this.syncInspector(h);const m=this.selected?this.locateField(this.selected):void 0;m?.parent&&m.parent.id===h.id&&this.syncInspector(m.field)},restructure:d=>{const h=this.liveField(e.id);h&&(this.snapshot(),d(h),this.markDirty(),this.renderCanvas(),this.renderInspector())},types:d=>this.config?.fieldTypes.find(h=>h.type===d),selectedId:this.selected}),e.logic.enabled?this.renderCondition(e,o):null]})]});return c.addEventListener("click",d=>{d.target.closest(".atfb-card__actions")||G().recentlyEndedDrag()||this.selectField(e.id)}),c.addEventListener("keydown",d=>{if(d.key==="Enter"||d.key===" "){d.preventDefault(),this.selectField(e.id);return}d.altKey&&(d.key==="ArrowUp"||d.key==="ArrowDown")&&(d.preventDefault(),this.moveField(e.id,d.key==="ArrowUp"?s-1:s+1),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-card="${CSS.escape(e.id)}"]`)?.focus()})),(d.key==="Delete"||d.key==="Backspace")&&(d.preventDefault(),this.deleteField(e.id))}),c.addEventListener("pointerdown",d=>{d.target.closest(".atfb-card__actions")||G().start({payload:Ae(se,c,{fieldId:e.id,field:e,isNew:!1},d),origin:d})}),c}addConditionRule(e){this.snapshot(),this.editCondition(e,s=>{const t=this.schema?.fields.find(a=>a.id!==e&&a.type!=="page_break");s.rules.push({field:t?.id??"",operator:"is",value:""})},!0,`${e}:source:${this.liveField(e)?.logic.rules.length??0}`),this.snapshot()}conditionToolbar(e){const s=r("button",{class:`atfb-req atfb-condition-toggle${e.logic.enabled?" is-on":""}`,type:"button",title:e.logic.enabled?"Edit conditional logic":"Set up conditional logic",attrs:{"aria-haspopup":"dialog","data-cond":`${e.id}:enabled`},children:[r("span",{class:"atfb-condition-dot",attrs:{"aria-hidden":"true"}}),r("span",{text:"Conditional"})],on:{click:()=>this.openConditionEditor(e.id)}});for(const t of["pointerdown","click","keydown"])s.addEventListener(t,a=>a.stopPropagation());return s}openConditionEditor(e){const s=this.liveField(e);if(!s)return;const t={...s.logic,rules:s.logic.rules.map(d=>({...d}))},a=r("div",{class:"atfb-overlay"}),i=r("div",{class:"atfb-modal atfb-condition-editor",attrs:{role:"dialog","aria-modal":"true","aria-label":"Conditional logic",tabindex:"-1"}}),o=()=>{a.remove(),this.root.querySelector(`[data-cond="${CSS.escape(e)}:enabled"]`)?.focus()},l="button:not([disabled]), input, select, os-select, os-checkbox-label, os-button:not([disabled])",c=()=>{const d=[...i.querySelectorAll(l)].indexOf(document.activeElement),h=(f,y=!1)=>{f(t),y&&c()},m=D(t.action,[{value:"show",label:"Show"},{value:"hide",label:"Hide"}],f=>{t.action=f});m.setAttribute("aria-label","Conditional action");const g=D(t.match,[{value:"all",label:"all"},{value:"any",label:"any"}],f=>{t.match=f,c()});g.setAttribute("aria-label","Match rules");const u=r("button",{class:"atfb-copy-condition",type:"button",children:[B("admin-page"),r("span",{text:"Copy condition"})],on:{click:()=>Dt({root:a,to:`field:${e}`,schema:()=>this.schema?{...this.schema,fields:this.schema.fields.map(f=>f.id===e?{...f,logic:t}:f)}:null,onCopy:()=>{c(),i.focus()}})}});if(i.replaceChildren(r("div",{class:"atfb-condition-editor__heading",children:[r("span",{class:"atfb-condition-editor__icon",children:[B("randomize")]}),r("div",{children:[r("h2",{text:"Conditional logic"}),r("p",{text:s.label||"Untitled field"})]})]}),r("div",{class:"atfb-condition-editor__switch",children:[q("Enable conditions",t.enabled,f=>{t.enabled=f,c()}),r("p",{text:"Choose when this field appears in your form."})]}),...t.enabled?[r("div",{class:"atfb-condition-editor__sentence",children:[m,"this field when",g,"of these rules match:"]}),...this.logicRulesEditor(t,h,e)]:[r("p",{class:"atfb-condition-editor__empty",text:"This field is always visible. Enable conditions to choose when to show or hide it."})],r("div",{class:"atfb-condition-editor__footer",children:[u,r("div",{class:"atfb-modal__actions",children:[C("Cancel",o),C("Save conditions",()=>{if(!this.liveField(e)){o();return}this.snapshot(),this.editCondition(e,f=>Object.assign(f,t,{rules:t.rules.map(y=>({...y}))})),this.snapshot(),o()},"primary")]})]})),d>=0){const f=i.querySelectorAll(l);f[Math.min(d,f.length-1)]?.focus()}};a.append(i),a.addEventListener("click",d=>{d.target===a&&o()}),a.addEventListener("keydown",d=>{if(d.key==="Escape"&&(d.preventDefault(),o()),d.key==="Tab"){const h=[...i.querySelectorAll(l)],m=h[0],g=h[h.length-1];d.shiftKey&&(document.activeElement===m||document.activeElement===i)?(d.preventDefault(),g?.focus()):!d.shiftKey&&document.activeElement===g&&(d.preventDefault(),m?.focus())}d.stopPropagation()}),this.root.append(a),c(),i.focus()}requiredToggle(e){return r("button",{class:`atfb-req${e.required?" is-on":""}`,type:"button",text:e.required?"Required":"Optional",title:e.required?"This must be answered. Click to make it optional.":"Click to make this required.",attrs:{"aria-pressed":e.required?"true":"false"},on:{pointerdown:t=>t.stopPropagation(),click:t=>{t.stopPropagation(),e.required=!e.required,this.markDirty(),this.renderCanvas(),this.renderInspector()}}})}cardAction(e,s,t){return r("button",{class:"atfb-card__action",type:"button",title:s,attrs:{"aria-label":s},on:{click:a=>{a.stopPropagation(),t()}},children:[B(e)]})}gapAnimator(e,s,t,a){const i=r("div",{class:"atfb-marker",attrs:{"aria-hidden":"true"}});let o=null,l=null,c=0;const d=()=>{i.remove(),l?.classList.remove("atfb-lifted"),l=null,o=null},h=u=>{const f=Array.from(e.querySelectorAll(s)),y=new Map(f.filter(x=>!x.classList.contains("atfb-lifted")).map(x=>[x,x.getBoundingClientRect().top]));u();for(const x of f)x.style.transition="none",x.style.transform="";const p=f.filter(x=>{const F=y.get(x);if(F===void 0||!x.isConnected||x.classList.contains("atfb-lifted"))return!1;const S=F-x.getBoundingClientRect().top;return Math.abs(S)<.5?!1:(x.style.transform=`translateY(${S}px)`,!0)});e.offsetHeight;for(const x of f){if(!p.includes(x)){x.style.transition="";continue}x.style.transition="transform 160ms ease",x.style.transform="",x.addEventListener("transitionend",()=>{x.style.transition=""},{once:!0})}},m=u=>{const f=u.detail;if(f?.payload?.type!==se||!e.classList.contains("is-dropping")||a&&!a(f.payload.data??{}))return;const y=f.payload.data?.fieldId,p=typeof y=="string"?t(y):null,x=st(e,s,f.clientY??0,p??void 0);x===o&&i.isConnected||(o=x,h(()=>{p&&p!==l&&(l?.classList.remove("atfb-lifted"),p.classList.add("atfb-lifted"),l=p),i.style.blockSize=`${Math.max(8,Math.round(c))}px`;const F=Array.from(e.querySelectorAll(s)).filter(S=>S!==p);x>=F.length?e.append(i):F[x].before(i)}))},g=()=>{e.classList.remove("is-dropping"),window.setTimeout(()=>h(d),0)};return document.addEventListener("os.drag.move",m),document.addEventListener("os.drag.end",g),{enter:u=>{const f=u?t(u):null;c=f&&!f.classList.contains("atfb-lifted")?f.getBoundingClientRect().height:c||44},leave:()=>h(d),drop:(u,f)=>{const y=o??st(e,s,u,f??void 0);return d(),y},teardown:()=>{document.removeEventListener("os.drag.move",m),document.removeEventListener("os.drag.end",g),d()}}}registerCanvasTarget(e){this.canvasTarget?.(),this.canvasTarget=null;const s=this.gapAnimator(e,".atfb-card",i=>this.canvas.querySelector(`[data-atfb-card="${CSS.escape(i)}"]`)),t=G().registerDropTarget({id:`atfb-canvas-${this.form?.id??0}`,element:e,accept:i=>i.type===se,onEnter:i=>{e.classList.add("is-dropping"),s.enter(i.payload.data.fieldId)},onLeave:()=>{e.classList.remove("is-dropping"),s.leave()},onDrop:(i,o)=>{e.classList.remove("is-dropping");const l=i.payload.data,c=l.fieldId?this.canvas.querySelector(`[data-atfb-card="${CSS.escape(l.fieldId)}"]`):null,d=s.drop(o.clientY,c);if(l.isNew&&l.fieldType){this.addField(l.fieldType,d);return}if(l.fieldId&&this.locateField(l.fieldId)){this.relocateField(l.fieldId,null,d);return}l.field&&this.insertField({...l.field,id:""},d)}}),a=this.wireRepeaterZones(e);this.canvasTarget=()=>{t(),a.forEach(i=>i()),s.teardown()}}wireRepeaterZones(e){const s=[];return e.querySelectorAll("[data-atfb-repeater-zone]").forEach(t=>{const a=t.dataset.atfbRepeaterZone??"",i=l=>{const c=l;if(c.fieldId===a)return!1;const d=c.isNew?c.fieldType:this.locateField(c.fieldId??"")?.field.type??c.field?.type;return!!d&&this.allowedInRepeater(d)},o=this.gapAnimator(t,".atfb-subcard",l=>e.querySelector(`[data-atfb-subfield="${CSS.escape(l)}"]`),i);s.push(()=>o.teardown()),s.push(G().registerDropTarget({id:`atfb-repzone-${this.form?.id??0}-${a}`,element:t,accept:l=>l.type===se&&i(l.data),onEnter:l=>{t.classList.add("is-dropping"),o.enter(l.payload.data.fieldId)},onLeave:()=>{t.classList.remove("is-dropping"),o.leave()},onDrop:(l,c)=>{t.classList.remove("is-dropping");const d=l.payload.data,h=d.fieldId?e.querySelector(`[data-atfb-subfield="${CSS.escape(d.fieldId)}"]`):null,m=o.drop(c.clientY,h);if(d.isNew&&d.fieldType){this.addFieldToRepeater(d.fieldType,a,m);return}if(d.fieldId&&this.locateField(d.fieldId)){this.relocateField(d.fieldId,a,m);return}d.field&&this.insertFieldIntoRepeater({...d.field,id:""},a,m)}})),t.querySelectorAll(".atfb-subcard").forEach(l=>{const c=l.dataset.atfbSubfield??"";l.addEventListener("click",d=>{d.target.closest(".atfb-preview__remove")||(d.stopPropagation(),!G().recentlyEndedDrag()&&this.selectField(c))}),l.addEventListener("keydown",d=>{if(d.stopPropagation(),d.key==="Enter"||d.key===" "){d.preventDefault(),this.selectField(c);return}if(d.altKey&&(d.key==="ArrowUp"||d.key==="ArrowDown")){d.preventDefault();const h=this.locateField(c);h&&(this.relocateField(c,a,d.key==="ArrowUp"?h.index-1:h.index+1),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-subfield="${CSS.escape(c)}"]`)?.focus()}));return}(d.key==="Delete"||d.key==="Backspace")&&(d.preventDefault(),this.deleteField(c))}),l.addEventListener("pointerdown",d=>{if(d.stopPropagation(),d.target.closest(".atfb-preview__remove"))return;const h=this.locateField(c);h&&G().start({payload:Ae(se,l,{fieldId:c,parentId:a,field:h.field,isNew:!1},d),origin:d})})})}),s}addField(e,s){const t=this.buildField(e);t&&this.insertField(t,s)}buildField(e){const s=this.config?.fieldTypes.find(a=>a.type===e);return!s||!this.schema?void 0:{id:this.nextFieldId(),type:e,label:s.input?s.label:"",placeholder:"",hint:"",required:!1,width:"full",cssClass:"",default:"",choices:s.choices?[{label:"First choice",value:"first"},{label:"Second choice",value:"second"}]:[],logic:{enabled:!1,action:"show",match:"all",rules:[]},messages:{},prefill:"",...s.settings}}allowedInRepeater(e){const s=this.config?.fieldTypes.find(t=>t.type===e);return!s||!s.input?!1:!["repeater","page_break","file","signature","total"].includes(e)}addFieldToRepeater(e,s,t){if(!this.allowedInRepeater(e))return;const a=this.buildField(e);a&&this.insertFieldIntoRepeater(a,s,t)}insertFieldIntoRepeater(e,s,t){const a=this.liveField(s);if(!this.schema||!a||a.type!=="repeater")return;e.id||(e.id=this.nextFieldId()),this.snapshot(),Array.isArray(a.fields)||(a.fields=[]);const i=a.fields,o=t===void 0?i.length:Math.max(0,Math.min(t,i.length));i.splice(o,0,e),this.selected=e.id,this.markDirty(),this.renderCanvas(),this.renderInspector(),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-subfield="${CSS.escape(e.id)}"]`)?.focus()})}relocateField(e,s,t){if(!this.schema)return;const a=this.locateField(e);if(!a)return;if(!a.parent&&!s){this.moveField(e,t);return}const i=s?this.liveField(s):null;if(s&&(!i||i.type!=="repeater"||e===s))return;i&&!Array.isArray(i.fields)&&(i.fields=[]);const o=i?i.fields:this.schema.fields;this.snapshot(),a.list.splice(a.index,1);const l=Math.max(0,Math.min(t,o.length));o.splice(l,0,a.field),this.selected=a.field.id,this.markDirty(),this.renderCanvas(),this.renderInspector()}insertField(e,s){if(!this.schema)return;e.id||(e.id=this.nextFieldId()),this.snapshot();const t=s===void 0?this.schema.fields.length:Math.max(0,Math.min(s,this.schema.fields.length));this.schema.fields.splice(t,0,e),this.selected=e.id,this.markDirty(),this.renderCanvas(),this.renderInspector(),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-card="${CSS.escape(e.id)}"]`)?.focus()})}moveField(e,s){if(!this.schema)return;const t=Zt(this.schema.fields,e,s);if(!t)return;this.snapshot();const[a]=this.schema.fields.splice(t.from,1);this.schema.fields.splice(t.to,0,a),this.markDirty(),this.renderCanvas()}duplicateField(e){if(!this.schema)return;const s=this.locateField(e);if(!s)return;const t=JSON.parse(JSON.stringify(s.field)),a=this.usedFieldIds(),i=()=>{let o=a.size+1;for(;a.has(`f${o}`);)o++;const l=`f${o}`;return a.add(l),l};t.id=i();for(const o of t.fields??[])o.id=i();if(s.parent){this.snapshot(),s.list.splice(s.index+1,0,t),this.selected=t.id,this.markDirty(),this.renderCanvas(),this.renderInspector();return}this.insertField(t,s.index+1)}async deleteField(e){if(!this.schema)return;const s=this.locateField(e);if(!s)return;const t=this.schema.fields.filter(i=>i.logic?.rules?.some(o=>o.field===e)),a=t.length?`Delete this field? ${t.length} other field${t.length===1?"":"s"} use it in a condition, and those conditions will stop working.`:Qe("confirmDelete","Delete this? It cannot be undone.");await ie(a,"Delete field")&&(this.snapshot(),s.list.splice(s.index,1),this.selected===e&&(this.selected=null),this.markDirty(),this.renderCanvas(),this.renderInspector())}selectField(e){this.selected=e;for(const s of this.canvas.querySelectorAll("[data-atfb-card]")){const t=s.dataset.atfbCard===e;s.classList.toggle("is-selected",t),s.setAttribute("aria-pressed",t?"true":"false")}for(const s of this.canvas.querySelectorAll("[data-atfb-subfield]"))s.classList.toggle("is-selected",s.dataset.atfbSubfield===e);this.logicMap?.highlight(e),this.renderInspector()}nextFieldId(){const e=this.usedFieldIds();let s=e.size+1;for(;e.has(`f${s}`);)s++;return`f${s}`}usedFieldIds(){const e=new Set;for(const s of this.schema?.fields??[]){e.add(s.id);for(const t of s.fields??[])e.add(t.id)}return e}nextEntryId(e,s){const t=new Set(s.map(i=>i.id));let a=s.length+1;for(;t.has(`${e}${a}`);)a++;return`${e}${a}`}renderTypeSettings(e,s,t,a){for(const i of t){const o=Kt[i];o&&(this.inspector.append(Gt(e,o,a)),o.also&&this.inspector.append(Gt(e,{...o,key:o.also.key,label:o.also.label,hint:o.also.hint},a)))}t.includes("rows")&&e.type!=="likert"&&this.inspector.append(w("Lines tall",V(String(e.rows??""),i=>a("rows",i)))),t.includes("rows")&&e.type==="likert"&&this.inspector.append(this.renderStatementList(e,a)),t.includes("parts")&&this.inspector.append(this.renderPartsEditor(e,s,a)),t.includes("default")&&!["files","object"].includes(s?.value??"")&&this.inspector.append(this.renderDefaultControl(e,s,a))}renderStatementList(e,s){const t=Array.isArray(e.rows)?e.rows:[];return w("Statements",fe(t.map(a=>a.label??"").join(` -`),a=>s("rows",Xt(t,a)),5),"One per line. Each becomes a row of the matrix.")}renderPartsEditor(e,s,t){const a=s?.parts??[],i=Array.isArray(e.parts)?e.parts:a.map(l=>l.key),o=a.map(l=>q(l.label,i.includes(l.key),c=>{const d=a.map(h=>h.key).filter(h=>h===l.key?c:i.includes(h));t("parts",d.length?d:[l.key])}));return r("div",{class:"atfb-section",children:[r("h4",{class:"atfb-section__title",text:"Parts to ask for"}),...o]})}renderDefaultControl(e,s,t){const a="Filled in before they start. They can change it.";return e.type==="switch"||e.type==="consent"?q("On by default",!!e.default,i=>t("default",i)):s?.choices&&(e.choices??[]).length?w("Default answer",D(String(e.default??""),[{value:"",label:"Nothing chosen"},...(e.choices??[]).map(i=>({value:String(i.value),label:i.label||String(i.value)}))],i=>t("default",i)),a):w("Default answer",T(String(e.default??""),i=>t("default",i)),a)}renderChoicesEditor(e,s){const t=e.choices??[],a=o=>this.liveField(e.id)?.choices?.[o],i=r("div",{class:"atfb-choices"});return t.forEach((o,l)=>{const c=r("div",{class:"atfb-choice-row",children:[e.type==="image_choice"?this.choiceImageWell(o,l,e):null,J(T(o.label,d=>{const h=a(l);if(!h)return;const m=!h.value||h.value===h.label;h.label=d,m&&(h.value=d),this.markDirty();const g=this.liveField(e.id);g&&this.syncCanvas(g)}),`choice:${l}:label`),J(T(o.value,d=>{const h=a(l);h&&(h.value=d,this.markDirty())},"value"),`choice:${l}:value`),e.type==="quiz"||o.points!==void 0?V(String(o.points??""),d=>{const h=a(l);h&&(h.points=d===""?void 0:Number(d),this.markDirty())}):V(String(o.price??""),d=>{const h=a(l);h&&(h.price=d===""?void 0:Number(d),this.markDirty())}),r("button",{class:"atfb-card__action",type:"button",attrs:{"aria-label":`Remove ${o.label}`},on:{click:()=>{const d=this.liveField(e.id);d&&((d.choices??[]).splice(l,1),s("choices",d.choices),this.renderInspector())}},children:[B("trash")]})]});i.append(c)}),r("div",{class:"atfb-section",children:[r("h4",{text:"Choices"}),r("p",{class:"atfb-hint",text:e.type==="quiz"?"Label, value, points.":"Label, value, and a price for calculations."}),i,C("Add choice",()=>{const o=this.liveField(e.id);if(!o)return;const l=o.choices??[];l.push({label:"",value:""}),s("choices",l),this.renderInspector()},"ghost","plus-alt2"),e.type==="quiz"?w("Correct answer",D(String(e.correct??""),[{value:"",label:"—"},...t.map(o=>({value:o.value,label:o.label}))],o=>s("correct",o))):null]})}choiceImageWell(e,s,t){const a=r("div",{class:`atfb-well${e.image?" has-image":""}`,attrs:{"data-choice":s,"aria-label":`Image for ${e.label||`choice ${s+1}`}`},children:[e.image?r("span",{class:"atfb-well__id",text:`#${e.image}`}):B("format-image")]}),i=G().registerDropTarget({id:`atfb-well-${t.id}-${s}`,element:a,accept:o=>Bn.includes(o.type),onEnter:()=>a.classList.add("is-dropping"),onLeave:()=>a.classList.remove("is-dropping"),onDrop:o=>{a.classList.remove("is-dropping");const l=o.payload.data,c=Number(l.attachmentId??l.id??l.file?.id??0);if(!c){N("That is not an image this field can use","","error");return}const d=this.liveField(t.id)?.choices?.[s];d&&(d.image=c,this.markDirty(),this.renderInspector())}});return this.teardowns.push(i),a.addEventListener("click",()=>{const o=this.liveField(t.id)?.choices?.[s];o?.image&&(o.image=void 0,this.markDirty(),this.renderInspector())}),a}renderValidationSection(e,s,t){const a=[],i=[];s.includes("minlength")&&i.push(["minlength","Minimum characters"],["maxlength","Maximum characters"]),s.includes("min")?i.push(["min","Minimum"],["max","Maximum"]):s.includes("max")&&i.push(["max","Highest"]),s.includes("step")&&i.push(["step","Steps of"]),s.includes("mindate")&&i.push(["minDate","Earliest date"],["maxDate","Latest date"]),s.includes("mintime")&&i.push(["minTime","Earliest time"],["maxTime","Latest time"]);for(const[l,c]of i)a.push(w(c,T(String(e[l]??""),d=>t(l,d))));s.includes("pattern")&&a.push(...this.renderAnswerShapeRows(e,t)),s.includes("unique")&&a.push(q("No two people may submit the same value",!!e.unique,l=>t("unique",l)));const o=e.messages??{};return s.includes("required")&&a.push(w("Message when required",T(o.required??"",l=>{o.required=l,t("messages",o)}),"Leave empty for the default wording.")),a.length?this.section(`validation:${e.id}`,"Validation",a):r("div",{class:"atfb-section is-empty"})}buildShapePicker(e,s){const t=[{heading:null,options:[{value:"",label:"Anything at all"}]},...On.map(i=>({heading:i,options:Wt.filter(o=>o.group===i).map(o=>({value:o.slug,label:o.label}))})),{heading:"Your own",options:[{value:"custom",label:"A custom rule…"}]}];if(Y("os-select")&&Y("os-option")){const i=document.createElement("os-select");i.setAttribute("value",e),i.setAttribute("aria-label","What the answer should look like"),i.classList.add("atfb-field");for(const o of t){if(o.heading){const l=document.createElement("os-option");l.setAttribute("value",`__heading:${o.heading}`),l.setAttribute("disabled",""),l.textContent=o.heading,i.append(l)}for(const l of o.options){const c=document.createElement("os-option");c.setAttribute("value",l.value),c.textContent=l.label,i.append(c)}}return i.addEventListener("os-pick",o=>{s(String(o.detail?.value??""))}),i}const a=r("select",{class:"atfb-input atfb-select",attrs:{"aria-label":"What the answer should look like"},on:{change:i=>s(i.target.value)}});for(const i of t){const o=i.heading?(()=>{const l=document.createElement("optgroup");return l.label=i.heading,a.append(l),l})():a;for(const l of i.options)o.append(r("option",{value:l.value,text:l.label,attrs:{selected:l.value===e}}))}return a}renderAnswerShapeRows(e,s){const a=(typeof e.validation=="string"?e.validation:"")||(e.pattern?"custom":""),i=()=>In({root:this.root,field:this.liveField(e.id)??e,onSave:h=>{s("validation","custom"),s("pattern",h.pattern),s("validationRecipe",JSON.stringify(h.recipe));const m={...this.liveField(e.id)?.messages??{}};m.invalid=h.message,s("messages",m),this.renderInspector()},onCancel:()=>this.renderInspector()}),o=h=>{if(h==="custom"){i();return}s("validation",h),s("pattern",""),s("validationRecipe",""),this.renderInspector()},l=this.buildShapePicker(a,o),c=Nn(a),d=[w("The answer should be",l,c?`e.g. ${c.example}`:"Checked as they type, and again on the server.")];if(a==="custom"){const h=Pt(String(e.validationRecipe??"")),m=Bt(h)||(e.pattern?`Matches the expression ${String(e.pattern)}`:"No rule yet — open the builder.");d.push(w("Your rule",r("div",{class:"atfb-valrule",children:[r("p",{class:"atfb-valrule__words",text:m}),C("Edit the rule…",i,"secondary","edit")]}),Ce(h)||e.pattern?"Built in the rule builder, with a playground to test it.":void 0))}return d}logicRulesEditor(e,s,t=""){const a=(this.schema?.fields??[]).filter(d=>d.id!==t&&d.type!=="page_break"),i=()=>r("div",{class:"atfb-rule-join",children:[r("button",{class:"atfb-rule-join__chip",type:"button",text:e.match==="all"?"and":"or",title:"Switch between needing every rule (and) or any one of them (or).",on:{click:()=>s(d=>{d.match=d.match==="all"?"any":"all"},!0)}})]}),o=(d,h)=>{const m=r("button",{class:"atfb-card__action",type:"button",attrs:{"aria-label":"Remove this rule"},title:"Remove this rule",on:{click:()=>s(u=>{u.rules.splice(h,1)},!0)},children:[B("trash")]}),g=[r("div",{class:"atfb-rule__top",children:[D(d.field,a.map(u=>({value:u.id,label:u.label||u.id})),u=>s(f=>{const y=f.rules[h];y&&(y.field=u,y.value="")},!0)),m]}),D(d.operator,Object.entries(this.config?.operators??{}).map(([u,f])=>({value:u,label:f})),u=>s(f=>{const y=f.rules[h];y&&(y.operator=u)},!0))];if(!De.includes(d.operator)){const u=this.schema?.fields.find(y=>y.id===d.field),f=it(u,d.value,this.config?.countries);f?g.push(D(d.value,f,y=>s(p=>{const x=p.rules[h];x&&(x.value=y)}))):g.push(T(d.value,y=>s(p=>{const x=p.rules[h];x&&(x.value=y)}),"The answer to compare against"))}return g[0].querySelector("select, os-select")?.setAttribute("aria-label","Question used by this rule"),g[1].setAttribute("aria-label","How the answer is compared"),g[2]?.setAttribute("aria-label","The answer that triggers this"),g[2]?.matches("select, os-select")&&g[2].classList.add("atfb-cond__value-select"),r("div",{class:"atfb-rule",children:g})},l=r("div",{class:"atfb-rules"});e.rules.forEach((d,h)=>{h>0&&l.append(i()),l.append(o(d,h))});const c=C("Add rule",()=>{s(d=>{d.rules.push({field:a[0]?.id??"",operator:"is",value:""})},!0)},"ghost","plus-alt2");return[l,c]}conditionsSection(e,s,t){const a=(o,l=!1)=>{o(t),this.markDirty(),l&&this.renderCanvas()},i=s==="confirmation"?"Use":"Send";return this.section(`conditions:${e}`,"Conditions",[this.copyConditionButton(`${s}:${e}`),q(`Only ${i.toLowerCase()} this ${s} sometimes`,t.enabled,o=>a(l=>{l.enabled=o},!0)),t.enabled?r("div",{children:[r("div",{class:"atfb-rule-head",children:[r("span",{text:`${i} it when`}),D(t.match,[{value:"all",label:"all"},{value:"any",label:"any"}],o=>a(l=>{l.match=o},!0)),r("span",{text:"of these match:"})]}),...this.logicRulesEditor(t,a)]}):null],t.enabled)}copyConditionButton(e){return r("button",{class:"atfb-copy-condition",type:"button",children:[B("admin-page"),r("span",{text:"Copy condition"})],on:{click:()=>Dt({root:this.root,schema:()=>this.schema,to:e,beforeCopy:()=>this.snapshot(),onCopy:()=>{this.snapshot(),this.markDirty(),this.renderCanvas(),this.renderInspector()}})}})}renderLogicSection(e){const s=e.logic,t=()=>this.liveField(e.id)?.logic,a=(o,l=!1)=>{const c=t();c&&(o(c),this.markDirty(),this.renderCanvas(),l&&this.renderInspector())},i=this.logicRulesEditor(s,a,e.id);return this.section(`logic:${e.id}`,"Conditional logic",[this.copyConditionButton(`field:${e.id}`),q("Only show this field sometimes",s.enabled,o=>{a(l=>{l.enabled=o},!0)}),s.enabled?r("div",{children:[r("div",{class:"atfb-rule-head",children:[D(s.action,[{value:"show",label:"Show"},{value:"hide",label:"Hide"}],o=>a(l=>{l.action=o},!0)),r("span",{text:"this field when"}),D(s.match,[{value:"all",label:"all"},{value:"any",label:"any"}],o=>a(l=>{l.match=o},!0)),r("span",{text:"of these match:"})]}),...i]}):null],s.enabled)}renderTabCanvas(){return this.schema?this.tab==="theme"?yt({themes:this.themes,tokens:this.config?.tokens??[],activeSlug:this.schema.settings.theme,overrides:this.schema.settings.themeOverrides,onTheme:e=>{this.schema.settings.theme=e,this.markDirty()},onOverride:(e,s)=>{s===""?delete this.schema.settings.themeOverrides[e]:this.schema.settings.themeOverrides[e]=s,this.markDirty()},onOverridesReplaced:e=>{this.schema.settings.themeOverrides={...e},this.markDirty()},previewFor:(e,s)=>this.previewHtml(e,s),onThemesChanged:e=>{this.themes=e}}):this.tab==="settings"?this.renderSettingsPane():this.tab==="notify"?this.renderNotificationsPane():this.renderConfirmationsPane():r("div")}async paintCanvasTheme(){if(!this.form||!this.schema)return;const e=this.schema.settings.theme,s=JSON.stringify([e,this.schema.settings.themeOverrides]);if(s!==this.canvasThemeSignature){this.canvasThemeSignature=s;try{const t=await this.previewHtml(e,this.schema.settings.themeOverrides??{});this.root.classList.toggle("atfb--dark-form",/atf-is-dark/.test(t));const a=/class="atf-form-wrap"[^>]*\sstyle="([^"]*)"/.exec(t);if(!a)return;const i=a[1].replace(/"/g,'"').replace(/�?39;/g,"'").replace(/&/g,"&");this.canvasTheme.textContent=`.atfb .atfb-preview { +var allTerrainFormsBuilder=function(ee){"use strict";class as{constructor(){this.targets=[],this.active=null,this.lastEndMs=0}start(e){if(this.active||e.origin.button!==0)return null;const{payload:s,origin:t}=e,a=t.clientX,i=t.clientY;let o=!1,l=!1,c=null,d=null,u=0,f=0;const g=()=>{document.removeEventListener("pointermove",x),document.removeEventListener("pointerup",F),document.removeEventListener("pointercancel",S),document.removeEventListener("keydown",H),window.removeEventListener("blur",S),c?.remove(),c=null,s.source.classList.remove("atf-is-dragging"),document.body.classList.remove("atf-drag-active"),d?.onLeave?.(y),d=null,this.active=null,this.lastEndMs=Date.now()},h=(L,b)=>{document.dispatchEvent(new CustomEvent(L,{detail:{payload:s,clientX:b?.clientX,clientY:b?.clientY}}))},y={payload:s,isFinished:()=>l,cancel:(L="caller")=>{l||(l=!0,g(),o&&h("os.drag.end"),e.onCancel?.(L))}},m=L=>{o=!0,s.source.classList.add("atf-is-dragging"),document.body.classList.add("atf-drag-active");const b=s.source.getBoundingClientRect();u=s.ghost?.offsetX??a-b.left,f=s.ghost?.offsetY??i-b.top,c=s.ghost?.element??s.source.cloneNode(!0),c.classList.add("atf-drag-ghost"),c.style.width=`${b.width}px`,document.body.appendChild(c),p(L),h("os.drag.start",L)},p=L=>{c&&(c.style.transform=`translate3d(${L.clientX-u}px, ${L.clientY-f}px, 0)`)},x=L=>{if(l)return;if(!o){if(Math.hypot(L.clientX-a,L.clientY-i)<4)return;m(L)}p(L);const b=this.hitTest(L.clientX,L.clientY);b!==d&&(d?.onLeave?.(y),d=b,d?.onEnter?.(y)),h("os.drag.move",L)},F=L=>{if(l)return;if(!o){l=!0,g(),e.onClickOnly?.();return}const b=d;if(l=!0,g(),b&&b.accept(s)){e.onCommit?.(b),b.onDrop(y,{clientX:L.clientX,clientY:L.clientY}),h("os.drag.end",L);return}h("os.drag.end",L),e.onCancel?.(b?"rejected":"no-target")},S=()=>y.cancel("pointercancel"),H=L=>{L.key==="Escape"&&y.cancel("escape")};return document.addEventListener("pointermove",x),document.addEventListener("pointerup",F),document.addEventListener("pointercancel",S),document.addEventListener("keydown",H),window.addEventListener("blur",S),this.active=y,y}registerDropTarget(e){return this.targets=this.targets.filter(s=>s.id!==e.id),this.targets.push(e),()=>{this.targets=this.targets.filter(s=>s.id!==e.id)}}isDragging(){return this.active!==null}recentlyEndedDrag(e=500){return Date.now()-this.lastEndMso.right||so.bottom)continue;const l=is(i.element);if(l>a){t=i,a=l;continue}l===a&&t&&rs(i.element,t.element)&&(t=i)}return t}}function is(n){let e=0,s=n;for(;s;)e++,s=s.parentElement;return e}function rs(n,e){return(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)!==0}function Le(){return window.wp?.os??null}let $e=null;function G(){const n=Le();return n?.dragManager?n.dragManager:($e||($e=new as),$e)}function os(n){const e=i=>{const o=i.detail?.payload;return o&&n.includes(o.type)?o.source:null},s=i=>i.preventDefault(),t=i=>{const o=e(i);o&&(o.classList.add("atf-is-dragging"),document.body.classList.add("atf-drag-active"),window.getSelection()?.removeAllRanges(),document.addEventListener("selectstart",s))},a=i=>{const o=e(i);o&&(o.classList.remove("atf-is-dragging"),document.body.classList.remove("atf-drag-active"),document.removeEventListener("selectstart",s))};return document.addEventListener("os.drag.start",t),document.addEventListener("os.drag.end",a),()=>{document.removeEventListener("os.drag.start",t),document.removeEventListener("os.drag.end",a),document.removeEventListener("selectstart",s)}}const ls=["atfb","atfe","atfs","atfm"];function Ae(n,e,s,t,a){const i=e.getBoundingClientRect();if(!a){const o=ls.find(l=>e.closest(`.${l}`));if(o){const l=e.cloneNode(!0);l.style.transition="",l.style.transform="",a=document.createElement("div"),a.className=`${o} atf-ghost-scope`,a.appendChild(l)}}return a&&(a.style.width=`${Math.round(i.width)}px`,a.style.maxWidth=`${Math.round(i.width)}px`,a.style.boxSizing="border-box"),{type:n,source:e,data:s,ghost:{element:a,offsetX:t.clientX-i.left,offsetY:t.clientY-i.top,hint:{neutral:"",accept:"",reject:"",hidden:!0}}}}function st(n,e,s,t){const a=Array.from(n.querySelectorAll(e)).filter(i=>i!==t&&!i.classList.contains("atf-drag-ghost"));for(let i=0;ia.fetch(l,c,{source:"allterrain-forms"}):(l,c)=>fetch(l,c))(s,{credentials:"same-origin",...e,headers:t});if(!o.ok){let l=`Request failed with status ${o.status}.`,c="";try{const d=await o.json();l=d.message??l,c=d.code??""}catch{}throw new ue(l,o.status,c)}if(o.status!==204)return await o.json()}const z=n=>Te(n);async function cs(n){if(!U?.wpRestUrl)throw new ue("AllTerrain Forms is not configured on this page.",0);const e=U.nonce?{"X-WP-Nonce":U.nonce}:{},s=Le(),t=nt(U.wpRestUrl,n),a=s?.fetch?await s.fetch(t,{credentials:"same-origin",headers:e},{source:"allterrain-forms"}):await fetch(t,{credentials:"same-origin",headers:e});if(!a.ok)throw new ue(`Request failed with status ${a.status}.`,a.status);return await a.json()}function ds(n){if(!n||!n.includes("&"))return n;const e=document.createElement("textarea");return e.innerHTML=n,e.value}const X=(n,e)=>Te(n,{method:"POST",body:JSON.stringify(e)}),he=n=>Te(n,{method:"DELETE"});function at(n){const e=new URLSearchParams;for(const[t,a]of Object.entries(n))a===void 0||a===""||a===!1||e.set(t,String(a));const s=e.toString();return s?`?${s}`:""}function pe(n){const e=n?.schema?.settings;return e&&(!e.themeOverrides||Array.isArray(e.themeOverrides))&&(e.themeOverrides={...e.themeOverrides}),n}const I={config:()=>z("/config"),mailpoet:()=>z("/mailpoet"),listForms:()=>z("/forms"),listArchivedForms:()=>z("/forms?archived=1"),archiveForm:n=>X(`/forms/${n}/archive`,{}),unarchiveForm:n=>X(`/forms/${n}/unarchive`,{}),getForm:n=>z(`/forms/${n}`).then(pe),createForm:n=>X("/forms",n).then(pe),updateForm:(n,e)=>X(`/forms/${n}`,e).then(pe),duplicateForm:n=>X(`/forms/${n}/duplicate`,{}).then(pe),deleteForm:n=>he(`/forms/${n}`),preview:(n,e)=>X(`/forms/${n}/preview`,e),pages:()=>cs("wp/v2/pages?per_page=100&status=publish&orderby=title&order=asc&_fields=id,title").then(n=>n.map(e=>({id:e.id,title:ds(e.title?.rendered??"")||`#${e.id}`}))),mergeTags:n=>z(`/forms/${n}/merge-tags`).then(e=>e.groups),analytics:(n,e="")=>z(`/forms/${n}/analytics${e?`?dimension=${encodeURIComponent(e)}`:""}`),demoStatus:()=>z("/demo"),demoSeed:n=>X("/demo",n?{count:n}:{}),demoRemove:()=>he("/demo"),listEntries:n=>z(`/entries${at(n)}`),getEntry:n=>z(`/entries/${n}`),updateEntry:(n,e)=>X(`/entries/${n}`,e),deleteEntry:n=>he(`/entries/${n}`),exportEntries:n=>z(`/entries/export${at(n)}`),listThemes:()=>z("/themes"),saveTheme:n=>X("/themes",n),deleteTheme:n=>he(`/themes/${n}`)};function it(n,e,s={}){if(!n)return null;let t;const a=(o,l)=>{const c=n[o];return c==null||!Number.isFinite(Number(c))?l:Number(c)},i=(o,l,c=1)=>Array.from({length:Math.floor((l-o)/c+1e-9)+1},(d,u)=>{const f=String(Number((o+u*c).toPrecision(12)));return{value:f,label:f}});if(n.type==="scale"){const o=Math.trunc(a("min",0));let l=Math.trunc(a("max",10));l<=o&&(l=o+10),t=i(o,Math.min(l,o+20))}else if(n.type==="rating")t=i(1,Math.max(2,Math.min(10,Math.abs(Math.trunc(a("max",5))))));else if(n.type==="switch"||n.type==="consent")t=[{value:"1",label:"Checked"},{value:"",label:"Unchecked"}];else if(n.type==="country")t=Object.entries(s).map(([o,l])=>({value:o,label:l}));else if(n.type==="range"){const o=a("min",0),l=a("max",100),c=n.step==="any"?0:a("step",1);if(c<=0||l999)return null;t=i(o,l,c)}else if(n.choices?.length||["select","multiselect","radio","checkboxes","image_choice","quiz","likert"].includes(n.type))t=(n.choices??[]).map(o=>({value:o.value,label:o.label||o.value}));else return null;return!t.some(o=>o.value===e)&&e!==""&&t.unshift({value:e,label:`${e} (stored value; unavailable)`,disabled:!0}),t.some(o=>o.value==="")||t.unshift({value:"",label:"Choose a value…",disabled:!0}),t}function r(n,e={}){const s=document.createElement(n);e.class&&(s.className=e.class),e.text!==void 0&&(s.textContent=e.text),e.html!==void 0&&(s.innerHTML=e.html),e.title&&(s.title=e.title),e.type&&"type"in s&&(s.type=e.type),e.value!==void 0&&"value"in s&&(s.value=e.value),e.placeholder!==void 0&&"placeholder"in s&&(s.placeholder=e.placeholder),e.href&&"href"in s&&(s.href=e.href);for(const[t,a]of Object.entries(e.attrs??{}))a===void 0||a===!1||s.setAttribute(t,a===!0?"":String(a));Object.assign(s.style,e.style??{});for(const[t,a]of Object.entries(e.on??{}))s.addEventListener(t,a);for(const t of e.children??[])t==null||t===!1||s.append(t);return s}function R(n){n.replaceChildren()}function B(n){return r("span",{class:`dashicons ${n.startsWith("dashicons-")?n:`dashicons-${n}`}`,attrs:{"aria-hidden":"true"}})}function w(n,e,s){const t=e.matches("input, select, textarea, button")?e:e.querySelector("input, select, textarea");if(t){const a=t.id||`atf-c-${Math.random().toString(36).slice(2,9)}`;return t.id=a,r("div",{class:"atfb-row",children:[r("label",{class:"atfb-row__label",text:n,attrs:{for:a}}),e,s?r("p",{class:"atfb-row__hint",text:s}):null]})}return r("div",{class:"atfb-row",children:[r("span",{class:"atfb-row__label",text:n}),e,s?r("p",{class:"atfb-row__hint",text:s}):null]})}function T(n,e,s=""){return r("input",{class:"atfb-input",type:"text",value:n,placeholder:s,on:{input:t=>e(t.target.value)}})}function V(n,e){if(Y("os-number-field")){const s=document.createElement("os-number-field");return s.setAttribute("value",n),s.classList.add("atfb-field"),s.addEventListener("os-input-change",t=>{e(String(t.detail?.value??""))}),s}return r("input",{class:"atfb-input",type:"number",value:n,on:{input:s=>e(s.target.value)}})}function fe(n,e,s=4){const t=r("textarea",{class:"atfb-input atfb-input--area",attrs:{rows:s},on:{input:a=>e(a.target.value)}});return t.value=n,t}function D(n,e,s){if(Y("os-select")&&Y("os-option")){const t=document.createElement("os-select");t.setAttribute("value",n),t.classList.add("atfb-field");for(const a of e){const i=document.createElement("os-option");i.setAttribute("value",a.value),a.disabled&&i.setAttribute("disabled",""),i.textContent=a.label,t.append(i)}return t.addEventListener("os-pick",a=>{s(String(a.detail?.value??""))}),t}return r("select",{class:"atfb-input atfb-select",on:{change:t=>s(t.target.value)},children:e.map(t=>r("option",{value:t.value,text:t.label,attrs:{selected:t.value===n,disabled:t.disabled}}))})}function O(n,e,s){if(Y("os-checkbox-label")){const a=document.createElement("os-checkbox-label");return a.setAttribute("label",n),a.classList.add("atfb-check"),e&&a.setAttribute("checked",""),a.addEventListener("os-checkbox-change",i=>{s(!!i.detail?.checked)}),a}const t=r("input",{type:"checkbox",on:{change:a=>s(a.target.checked)}});return t.checked=e,r("label",{class:"atfb-check",children:[t,r("span",{text:n})]})}function C(n,e,s="secondary",t){const a=[t?B(t):null,r("span",{text:n})];if(Y("os-button")){const i=document.createElement("os-button");i.setAttribute("variant",s),i.setAttribute("type","button"),i.classList.add("atfb-button",`atfb-button--${s}`),i.addEventListener("click",e);for(const o of a)o&&i.append(o);return i}return r("button",{class:`atfb-button atfb-button--${s}`,type:"button",on:{click:e},children:a})}function Y(n){return typeof customElements<"u"&&!!customElements.get(n)}const us=["os-button","os-checkbox-label","os-number-field","os-select","os-option","os-segmented","os-segment","os-color-field","os-empty-state"];let me=null;function hs(){if(me)return me;const n=window.wp?.os;return me=n?.loadComponents?n.loadComponents(us).catch(()=>{}):Promise.resolve(),me}async function ie(n,e=""){const s=window.wp?.os;return s?.confirm?s.confirm({title:e,message:n,danger:!0}):window.confirm(n)}function N(n,e="",s="info"){const t=window.wp?.os;if(t?.notify){t.notify({title:n,body:e,type:s});return}console.info(`[AllTerrain Forms] ${n}${e?`: ${e}`:""}`)}function ps(n){let e=0,s;return(...t)=>{s=t,!e&&(e=window.requestAnimationFrame(()=>{e=0,n(...s)}))}}function Me(n,e){let s=0;return(...t)=>{window.clearTimeout(s),s=window.setTimeout(()=>n(...t),e)}}function fs(n){try{return window.localStorage.getItem(n)??""}catch{return""}}function ms(n,e){try{window.localStorage.setItem(n,e)}catch{}}function Fe(n){const e=n.closest(".os-window__body");e&&(e.addEventListener("scroll",()=>{e.scrollTop&&(e.scrollTop=0),e.scrollLeft&&(e.scrollLeft=0)},{passive:!0}),e.scrollTop=0,e.scrollLeft=0)}function rt(){const n=[window];try{window.parent&&window.parent!==window&&n.push(window.parent)}catch{}return n}function bs(n){const e=n.wp?.os?.windowManager?.getAll?.()??[];for(const s of e){const t=s.iframe??s.element?.querySelector?.("iframe");if(t&&t.contentWindow===window)return s}return null}const gs=4e3,vs=100;function ys(n,e){const s=Date.now()+gs,t=()=>{const a=bs(n);if(a&&a.id!==e){typeof a.close=="function"?a.close():n.wp?.os?.windowManager?.remove?.(a.id);return}!a&&Date.now()0?{form:s}:void 0;s>0&&ks(s);for(const a of rt())if(a.wp?.os?.openWindow?.(e,{source:"handoff",params:t})){window.setTimeout(()=>ys(a,e),0);return}}function _s(){document.addEventListener("click",n=>{const e=n.target?.closest?.("[data-atf-open-window]");if(!e)return;n.preventDefault();const s=e.getAttribute("data-atf-open-window")??"";for(const t of rt())if(t.wp?.os?.openWindow?.(s,{source:"handoff"}))return})}const xs="allterrain-forms/requested-form";function ks(n){try{window.sessionStorage.setItem(xs,String(n))}catch{}}function ot(n){return`allterrain-forms/requested-form-${n}`}function Ss(n){try{const e=window.sessionStorage.getItem(ot(n));return window.sessionStorage.removeItem(ot(n)),Number(e)||0}catch{return 0}}const Ie={is:"is",is_not:"is not",contains:"contains",not_contains:"does not contain",starts_with:"starts with",ends_with:"ends with",greater:"is more than",less:"is less than",greater_equal:"is at least",less_equal:"is at most",empty:"is empty",not_empty:"has any answer"},De=["empty","not_empty"];function lt(n,e){const s=n.find(t=>t.id===e);return s?s.label||"an untitled question":null}function ct(n,e,s){return n.find(i=>i.id===e)?.choices?.find(i=>i.value===s)?.label||s}function Cs(n,e){const s=Ie[n.operator]??String(n.operator);if(De.includes(n.operator))return s;const t=ct(e,n.field,n.value);return`${n.operator==="is"?"":`${s} `}${t!==""?t:"(nothing)"}`}function be(n,e,s=0){const t=lt(e,n.field),a=Ie[n.operator]??String(n.operator);if(t===null)return[{kind:"field",text:"a question that no longer exists",fieldId:n.field,missing:!0}];const i=[{kind:"field",text:t,fieldId:n.field,missing:!1},{kind:"operator",text:a,operator:n.operator,ruleIndex:s}];if(De.includes(n.operator))return i;const o=ct(e,n.field,n.value);return i.push({kind:"value",text:o!==""?o:"(nothing)",raw:n.value,sourceId:n.field,ruleIndex:s}),i}function Es(n,e){const s=n.logic;if(!s?.enabled||!s.rules.length)return[];const t=[{kind:"verb",text:s.action==="hide"?"Hidden when":"Shown when"}];return s.rules.forEach((a,i)=>{i>0&&t.push({kind:"join",text:s.match==="all"?"and":"or"}),t.push(...be(a,e,i))}),t}function qe(n){return n.map(e=>e.text).join(" ")}function Ls(n,e){return qe(be(n,e))}function ge(n){const e=[];for(const s of n){const t=s.logic;if(t?.enabled)for(const a of t.rules)!a.field||a.field===s.id||e.push({from:a.field,to:s.id,label:Ls(a,n),short:Cs(a,n),action:t.action,broken:lt(n,a.field)===null})}return e}function $s(n){const e=new Map,s=new Set;for(const t of ge(n)){const a=`${t.from}->${t.to}`;t.broken||s.has(a)||(s.add(a),e.set(t.from,(e.get(t.from)??0)+1))}return e}const dt=10,ut=22,ne="http://www.w3.org/2000/svg";class As{constructor(e){this.edges=[],this.teardowns=[],this.frame=0,this.host=e,this.svg=document.createElementNS(ne,"svg"),this.svg.setAttribute("class","atfb-logicmap"),this.svg.setAttribute("aria-hidden","true"),this.svg.setAttribute("focusable","false"),e.append(this.svg);const s=()=>this.schedule();window.addEventListener("resize",s),this.teardowns.push(()=>window.removeEventListener("resize",s));const t=e.closest(".atfb__canvas")??e;if(t.addEventListener("scroll",s,{passive:!0}),this.teardowns.push(()=>t.removeEventListener("scroll",s)),typeof ResizeObserver<"u"){const a=new ResizeObserver(s);a.observe(e),this.teardowns.push(()=>a.disconnect())}}setEdges(e){this.edges=e,this.schedule()}highlight(e){this.svg.classList.toggle("is-focused",!!e),this.svg.querySelectorAll("[data-from]").forEach(s=>{const t=e&&(s.dataset.from===e||s.dataset.to===e);s.classList.toggle("is-lit",!!t)})}destroy(){this.teardowns.forEach(e=>e()),this.teardowns=[],this.svg.remove(),this.frame&&cancelAnimationFrame(this.frame)}schedule(){this.frame||(this.frame=requestAnimationFrame(()=>{this.frame=0,this.draw()}))}draw(){this.svg.replaceChildren();const e=this.host.getBoundingClientRect();this.svg.setAttribute("viewBox",`0 0 ${e.width} ${e.height}`),this.svg.setAttribute("width",String(e.width)),this.svg.setAttribute("height",String(e.height));const s=new Map;for(const t of this.edges){const a=this.cardRect(t.from),i=this.cardRect(t.to);if(!a||!i)continue;const o=s.get(t.from)??0;s.set(t.from,o+1),this.drawEdge(t,a,i,e,o)}}cardRect(e){const s=this.host.querySelector(`[data-atfb-card="${CSS.escape(e)}"]`);return s?s.getBoundingClientRect():null}drawEdge(e,s,t,a,i){const o=s.right-a.left,l=s.top+s.height/2-a.top,c=t.right-a.left,d=t.top+t.height/2-a.top,u=Math.max(0,a.width-dt-Math.max(o,c)),f=22+i*11+Math.min(22,Math.abs(d-l)/8),g=Math.max(12,Math.min(f,u*.4)),h=document.createElementNS(ne,"path");h.setAttribute("d",`M ${o} ${l} C ${o+g} ${l}, ${c+g} ${d}, ${c} ${d}`),h.setAttribute("class",`atfb-logicmap__path is-${e.action}${e.broken?" is-broken":""}`),h.dataset.from=e.from,h.dataset.to=e.to;const y=document.createElementNS(ne,"title");y.textContent=e.label,h.append(y);const m=document.createElementNS(ne,"circle");m.setAttribute("cx",String(c)),m.setAttribute("cy",String(d)),m.setAttribute("r","3.5"),m.setAttribute("class",`atfb-logicmap__dot is-${e.action}${e.broken?" is-broken":""}`),m.dataset.from=e.from,m.dataset.to=e.to,this.svg.append(h,m);const p=document.createElementNS(ne,"text");p.setAttribute("x",String(a.width-dt)),p.setAttribute("y",String(d+3)),p.setAttribute("text-anchor","end"),p.setAttribute("class","atfb-logicmap__label"),p.dataset.from=e.from,p.dataset.to=e.to,p.textContent=e.short.length>ut?`${e.short.slice(0,ut-1)}…`:e.short;const x=document.createElementNS(ne,"title");x.textContent=e.label,p.append(x),this.svg.append(p)}}const Ts={text:"text",email:"text",url:"text",tel:"text",number:"text",password:"text",date:"text",time:"text",datetime:"text",date_range:"composite",textarea:"textarea",select:"select",country:"select",multiselect:"options",radio:"options",checkboxes:"options",image_choice:"options",quiz:"options",switch:"toggle",consent:"toggle",file:"file",range:"range",rating:"summary",scale:"summary",likert:"summary",signature:"summary",repeater:"repeater",color:"text",name:"composite",address:"composite",total:"total",hidden:"static",heading:"static",html:"static",divider:"static",spacer:"static",page_break:"static"};function Ms(n){return Ts[n]??"text"}function ht(n,e){const s=/^choice:(\d+):(label|value)$/.exec(e);return String(s?n.choices?.[Number(s[1])]?.[s[2]]??"":n[e]??"")}function Z(n){const{value:e,onInput:s,onCommit:t}=n,a=r("span",{class:`${n.class} atfb-editable`,text:e,attrs:{contenteditable:"plaintext-only",role:"textbox",spellcheck:"false","data-placeholder":n.placeholder}});return n.bind&&(a.dataset.atfbBind=n.bind),a.addEventListener("pointerdown",i=>i.stopPropagation()),a.addEventListener("input",()=>s(a.textContent??"")),a.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),a.blur()),i.key==="Escape"&&(a.textContent=e,a.blur()),i.stopPropagation()}),a.addEventListener("blur",()=>t?.()),a}function Fs(n){const e=r("input",{class:"atf-choice__input",type:n==="checkboxes"||n==="multiselect"?"checkbox":"radio"});return e.disabled=!0,e}function pt(n,e,s){const t=Ms(n.type),a=Z({value:n.label,placeholder:"Write the question…",class:"atf-label",bind:"label",onInput:o=>s.edit(l=>{l.label=o}),onCommit:()=>s.restructure(()=>{})}),i=[t==="static"||t==="toggle"?null:a,Ds(n,e,t,s),Is(n,e,s)];return r("div",{class:"atfb-preview atf-form",children:[r("div",{class:`atf-field atf-field--${n.type}`,children:i})]})}function Is(n,e,s){if(!e?.supports.includes("hint"))return null;const t=Z({value:n.hint??"",placeholder:"Add a hint…",class:"atf-hint",bind:"hint",onInput:a=>s.edit(i=>{i.hint=a})});return t.setAttribute("aria-label","Hint"),r("p",{class:"atfb-preview__hint",children:[t]})}function Ds(n,e,s,t){switch(s){case"total":return r("div",{class:"atf-total",children:[n.currency?r("span",{class:"atf-total__currency",text:String(n.currency)}):null,n.display==="output"?r("output",{class:"atf-total__output",text:"0.00"}):r("input",{class:"atf-input atf-total__input",type:"text",value:"0.00",attrs:{disabled:!0}})]});case"text":return Oe(n,"atf-input",t);case"textarea":return Oe(n,"atf-input atf-textarea",t,!0);case"select":return r("div",{class:"atfb-preview__select",children:[Oe(n,"atf-input atf-select",t)]});case"options":return Rs(n,t);case"toggle":return r("div",{class:n.type==="switch"?"atf-toggle atf-toggle--switch":"atf-toggle",children:[(()=>{const a=r("input",{class:"atf-toggle__input",type:"checkbox"});return a.disabled=!0,a})(),Z({value:n.label||"",placeholder:n.type==="consent"?"What are they agreeing to?…":"What does this turn on?…",class:"atf-toggle__label",bind:"label",onInput:a=>t.edit(i=>{i.label=a}),onCommit:()=>t.restructure(()=>{})})]});case"file":return r("div",{class:"atf-file",children:[r("input",{class:"atf-file__input",type:"file"})]});case"range":return r("input",{class:"atf-range__input",type:"range"});case"composite":return r("div",{class:"atf-composite__parts",children:[r("span",{class:"atf-input atfb-preview__ghost",text:""}),r("span",{class:"atf-input atfb-preview__ghost",text:""})]});case"static":return Ps(n,e,t);case"repeater":return qs(n,t);default:return r("div",{class:"atfb-preview__stack",children:[r("p",{class:"atfb-preview__summary",text:`${e?.label??n.type} — set this up in the panel on the right.`})]})}}function qs(n,e){const s=n.fields??[],t=r("div",{class:"atfb-repeater__zone",attrs:{"data-atfb-repeater-zone":n.id}});return s.forEach(a=>t.append(Os(n,a,e))),s.length||t.append(r("p",{class:"atfb-repeater__empty",text:"Drag fields from the palette in here — the visitor gets a fresh copy of each with every row they add."})),r("div",{class:"atfb-repeater",attrs:{"data-atfb-repeater":n.id},children:[r("div",{class:"atf-repeater__row atfb-repeater__frame",children:[r("div",{class:"atf-repeater__row-head",children:[r("span",{class:"atf-repeater__title atfb-repeater__title",children:[Z({value:String(n.itemLabel??""),placeholder:"Row",class:"atfb-repeater__item-label",bind:"itemLabel",onInput:a=>e.edit(i=>{i.itemLabel=a})}),r("span",{class:"atfb-repeater__ordinal",text:"1",attrs:{"aria-hidden":"true"}})]})]}),t]}),Ns(n,e)]})}function Os(n,e,s){const t=e.id,a=l=>c=>{const d=(c.fields??[]).find(u=>u.id===t);d&&l(d)},i={edit:l=>s.edit(a(l)),restructure:l=>s.restructure(a(l)),types:s.types,selectedId:s.selectedId},o=s.types?.(e.type);return r("div",{class:`atfb-subcard${s.selectedId===t?" is-selected":""}`,attrs:{"data-atfb-subfield":t,"data-atfb-parent":n.id,tabindex:"0",role:"button","aria-label":`${e.label||o?.label||e.type}, inside ${n.label||"the repeater"}`},children:[r("div",{class:"atfb-subcard__head",children:[r("span",{class:"atfb-subcard__type",text:o?.label??e.type}),e.required?r("span",{class:"atfb-subcard__required",text:"Required"}):null,r("button",{class:"atfb-preview__remove",type:"button",title:"Remove this field from the repeater",attrs:{"aria-label":`Remove ${e.label||o?.label||"this field"}`},on:{pointerdown:l=>l.stopPropagation(),click:l=>{l.stopPropagation(),s.restructure(c=>{const d=c.fields??[],u=d.findIndex(f=>f.id===t);u>=0&&d.splice(u,1)})}},children:[r("span",{text:"×"})]})]}),pt(e,o,i)]})}function Oe(n,e,s,t=!1){const a=Z({value:n.placeholder??"",placeholder:n.type==="select"||n.type==="country"?"Choose…":"Placeholder…",class:`${e} atfb-preview__box${t?" atfb-preview__box--tall":""}`,bind:"placeholder",onInput:i=>s.edit(o=>{o.placeholder=i})});return a.setAttribute("aria-label","Placeholder"),a}function Ne(n,e,s,t,a,i){return r("span",{class:`atf-button ${s} atfb-preview__button`,children:[Z({value:n,placeholder:e,class:"atfb-preview__button-text",bind:t,onInput:o=>a.edit(l=>i(l,o))})]})}function Ns(n,e){return Ne(String(n.addLabel??""),"Add another","atf-button--ghost atfb-repeater__add","addLabel",e,(s,t)=>{s.addLabel=t})}function Rs(n,e){const s=r("div",{class:"atf-choices__list"});return(n.choices??[]).forEach((t,a)=>{s.append(r("div",{class:"atf-choice atfb-preview__option",children:[Fs(n.type),Z({value:t.label,placeholder:"Option…",class:"atf-choice__label",bind:`choice:${a}:label`,onInput:i=>{e.edit(o=>{const l=o.choices?.[a];if(!l)return;const c=!l.value||l.value===l.label;l.label=i,c&&(l.value=i)})}}),r("button",{class:"atfb-preview__remove",type:"button",title:"Remove this option",attrs:{"aria-label":`Remove ${t.label||"this option"}`},on:{pointerdown:i=>i.stopPropagation(),click:i=>{i.stopPropagation(),e.restructure(o=>{o.choices.splice(a,1)})}},children:[r("span",{text:"×"})]})]}))}),s.append(r("button",{class:"atfb-preview__add",type:"button",on:{pointerdown:t=>t.stopPropagation(),click:t=>{t.stopPropagation(),e.restructure(a=>{const i=a.choices.length+1;a.choices.push({label:`Option ${i}`,value:`Option ${i}`})})}},children:[r("span",{text:"+ Add option"})]})),r("fieldset",{class:"atf-choices",children:[s]})}function Ps(n,e,s){return n.type==="heading"?Z({value:n.label,placeholder:"Section heading…",class:"atf-heading",bind:"label",onInput:t=>s.edit(a=>{a.label=t}),onCommit:()=>s.restructure(()=>{})}):n.type==="divider"?r("hr",{class:"atf-divider"}):n.type==="page_break"?r("div",{class:"atfb-preview__stack",children:[r("p",{class:"atfb-progress-name",children:[Z({value:n.label,placeholder:"Name this step…",class:"atf-progress__label",bind:"label",onInput:t=>s.edit(a=>{a.label=t}),onCommit:()=>s.restructure(()=>{})})]}),r("p",{class:"atfb-preview__summary",text:"Everything after this is a new page."}),r("div",{class:"atf-nav atfb-preview__nav",children:[Ne(String(n.prevLabel??""),"Back","atf-button--secondary","prevLabel",s,(t,a)=>{t.prevLabel=a}),Ne(String(n.nextLabel??""),"Next","","nextLabel",s,(t,a)=>{t.nextLabel=a})]})]}):r("p",{class:"atfb-preview__summary",text:`${e?.label??n.type} — nothing is shown to the visitor here.`})}const Re=new Map;function ft(n){let e=Re.get(n);return e||(e=I.mergeTags(n).catch(()=>[]),Re.set(n,e)),e}function Bs(n){Re.delete(n)}function js(n){const e=new Map;for(const s of n)for(const t of s.items)e.set(t.tag,t);return e}function Hs(n,e){const s=js(e);return n.replace(/\{[a-z_]+(?::[^}]*)?\}/gi,t=>{const a=s.get(t.toLowerCase());return a?`{the value of ${a.label}}`:t})}function mt(n){return/\{[a-z_]+(?::[^}]*)?\}/i.test(n)}let te=null,Pe=0,re=null;function oe(n=!1){Pe++,te?.remove(),te=null,n&&re?.focus(),re=null}typeof document<"u"&&(document.addEventListener("pointerdown",n=>{const e=n.target;e?.closest(".atfb-tagpick__open")||te?.contains(e)||oe()}),window.addEventListener("keydown",n=>{if(n.key==="Escape"&&re){oe(!0),n.preventDefault(),n.stopImmediatePropagation();return}if(!te?.contains(n.target)||!["ArrowDown","ArrowUp","ArrowLeft","ArrowRight","Home","End","Enter"].includes(n.key))return;n.stopImmediatePropagation();const e=te.querySelector(".atfb-tagpick__search"),s=[...te.querySelectorAll(".atfb-tagpick__item")],t=s.indexOf(document.activeElement);if(n.key==="ArrowDown"||n.key==="ArrowUp"){n.preventDefault();const a=n.key==="ArrowDown"?t+1:t<0?s.length-1:t-1;s[(a+s.length)%s.length]?.focus()}else n.key==="Enter"&&n.target===e?(n.preventDefault(),s[0]?.click()):n.target!==e&&n.key!=="Enter"&&(n.preventDefault(),n.key==="Home"&&s[0]?.focus(),n.key==="End"&&s[s.length-1]?.focus())},!0));function bt(n,e){const s=n.selectionStart??n.value.length,t=n.selectionEnd??n.value.length;n.value=n.value.slice(0,s)+e+n.value.slice(t);const a=s+e.length;n.setSelectionRange(a,a),n.dispatchEvent(new Event("input",{bubbles:!0})),n.focus()}function Ws(n){let e=0,s=window.innerHeight,t=n.parentElement;for(;t&&t!==document.body;){if(/auto|scroll|hidden|clip/.test(getComputedStyle(t).overflowY)){const a=t.getBoundingClientRect();e=Math.max(e,a.top),s=Math.min(s,a.bottom)}t=t.parentElement}return{top:e,bottom:s}}function Us(n,e){const s=r("input",{class:"atfb-input atfb-tagpick__search",type:"search",placeholder:"Search values…",attrs:{"aria-label":"Search values"}}),t=r("div",{class:"atfb-tagpick__list"}),a=o=>{t.replaceChildren();const l=o.trim().toLowerCase();let c=0;for(const d of n){const u=d.items.filter(f=>!l||f.label.toLowerCase().includes(l)||f.tag.toLowerCase().includes(l));if(!u.length){d.empty&&!l&&!d.items.length&&t.append(r("p",{class:"atfb-tagpick__group",text:d.label}),r("p",{class:"atfb-tagpick__empty",text:d.empty}));continue}t.append(r("p",{class:"atfb-tagpick__group",text:d.label}));for(const f of u)c+=1,t.append(r("button",{class:"atfb-tagpick__item",type:"button",on:{click:()=>{oe(),e(f.tag)}},children:[r("span",{class:"atfb-tagpick__item-main",children:[r("span",{class:"atfb-tagpick__label",text:f.label}),r("code",{class:"atfb-tagpick__tag",text:f.tag})]}),f.hint||f.sample?r("span",{class:"atfb-tagpick__meta",text:`{the value of ${f.label}}`}):null]}))}!c&&l&&t.append(r("p",{class:"atfb-tagpick__empty",text:`Nothing matches “${o}”.`}))};a(""),s.addEventListener("input",()=>a(s.value));const i=r("div",{class:"atfb-tagpick",attrs:{role:"dialog","aria-label":"Insert a value"},children:[r("p",{class:"atfb-tagpick__intro",text:"Pick something to drop in. It is filled in when the form is submitted."}),s,t]});return i.addEventListener("keydown",o=>o.stopPropagation()),i}function Be(n,e){const s=()=>Promise.resolve(e.groups?e.groups():ft(e.formId??0)),t=r("button",{class:"atfb-button atfb-button--ghost atfb-tagpick__open",type:"button",title:"Insert a value from the submission",attrs:{"aria-haspopup":"dialog"},children:[B("shortcode"),r("span",{text:"Insert a value"})]}),a=r("div",{class:"atfb-taggable",children:[n,r("div",{class:"atfb-taggable__tools",children:[t]})]}),i=e.preview===!1?null:r("p",{class:"atfb-taggable__preview"});i&&a.append(i);const o=()=>{if(i){if(!mt(n.value)){i.textContent="",i.hidden=!0;return}s().then(c=>{mt(n.value)&&(i.hidden=!1,i.replaceChildren(r("span",{class:"atfb-taggable__preview-label",text:"Reads as"}),r("span",{text:Hs(n.value,c)})))})}};n.addEventListener("input",o),o();const l=(c,d)=>{oe();const u=Pe,f=n.value;re=n,s().then(g=>{if(u!==Pe||!a.isConnected||n.value!==f)return;const h=Us(g,S=>{n.setSelectionRange(c,d),bt(n,S)});a.append(h),te=h;const y=Ws(a);h.style.maxBlockSize=`${Math.max(0,Math.min(320,y.bottom-y.top-8))}px`;const m=a.getBoundingClientRect(),p=h.getBoundingClientRect().height,x=m.bottom+p<=y.bottom?m.bottom:m.top-p,F=Math.max(y.top+4,Math.min(x,y.bottom-p-4));h.style.insetBlockStart=`${F-m.top}px`,h.querySelector(".atfb-tagpick__search")?.focus({preventScroll:!0})})};return t.addEventListener("click",c=>{if(c.stopPropagation(),re===n){oe(!0);return}l(n.selectionStart??n.value.length,n.selectionEnd??n.value.length)}),n.addEventListener("input",c=>{const d=c,u=n.selectionStart??0;!d.isComposing&&d.data==="{"&&n.value[u-1]==="{"&&l(u-1,u+(n.value[u]==="}"?1:0))}),a}function gt(n,e){const s=parseFloat(String(n??""));return Number.isFinite(s)?s:e}function vt(n,e){let s=e[0];for(const t of e)Math.abs(t.at-n)n.accent??"#2271b1",apply:n=>({accent:n,"accent-soft":`color-mix( in srgb, ${n} 12%, transparent )`,"border-focus":n,"focus-ring-color":n,"button-bg":n,"button-bg-hover":`color-mix( in srgb, ${n} 88%, #000 )`})},{id:"roundness",label:"Roundness",hint:"Corners, everywhere at once.",kind:"scale",steps:je.map(({value:n,label:e})=>({value:n,label:e})),owns:["radius-field","radius-button","radius-card","radius-check"],read:n=>vt(gt(n["radius-field"],4),je),apply:n=>{const e=je.find(s=>s.value===n)?.at??4;return{"radius-field":`${e}px`,"radius-button":`${e}px`,"radius-card":`${Math.min(e*2,28)}px`,"radius-check":`${Math.min(e,6)}px`}}},{id:"density",label:"Density",hint:"How much air the form has.",kind:"scale",steps:He.map(({value:n,label:e})=>({value:n,label:e})),owns:["pad-field-x","pad-field-y","gap-fields","gap-label","button-pad-x","button-pad-y"],read:n=>vt(gt(n["pad-field-y"],9),He),apply:n=>{const e=He.find(s=>s.value===n)?.at??9;return{"pad-field-y":`${e}px`,"pad-field-x":`${Math.round(e*1.4)}px`,"gap-fields":`${Math.round(e*2.2)}px`,"gap-label":`${Math.max(4,Math.round(e*.7))}px`,"button-pad-y":`${e+2}px`,"button-pad-x":`${Math.round(e*2.2)}px`}}},{id:"shadow",label:"Depth",hint:"How far the form sits off the page.",kind:"scale",steps:zs,owns:["shadow-field","shadow-field-focus","shadow-button","shadow-button-hover","shadow-card"],read:n=>{const e=n["shadow-card"]??"none";return e==="none"||e.trim()===""?n["shadow-field"]&&n["shadow-field"]!=="none"?"hard":"none":e.includes("0 1px")||e.includes("2px")?"subtle":"lifted"},apply:n=>{switch(n){case"subtle":return{"shadow-field":"none","shadow-field-focus":"none","shadow-button":"0 1px 2px rgba( 0, 0, 0, 0.12 )","shadow-button-hover":"0 2px 4px rgba( 0, 0, 0, 0.16 )","shadow-card":"0 1px 3px rgba( 0, 0, 0, 0.1 )"};case"lifted":return{"shadow-field":"none","shadow-field-focus":"0 4px 12px rgba( 0, 0, 0, 0.12 )","shadow-button":"0 4px 10px rgba( 0, 0, 0, 0.16 )","shadow-button-hover":"0 8px 20px rgba( 0, 0, 0, 0.2 )","shadow-card":"0 10px 30px rgba( 0, 0, 0, 0.14 )"};case"hard":return{"shadow-field":"3px 3px 0 currentColor","shadow-field-focus":"5px 5px 0 currentColor","shadow-button":"4px 4px 0 currentColor","shadow-button-hover":"2px 2px 0 currentColor","shadow-card":"none"};default:return{"shadow-field":"none","shadow-field-focus":"none","shadow-button":"none","shadow-button-hover":"none","shadow-card":"none"}}}},{id:"field-style",label:"Fields",hint:"How an input is drawn.",kind:"choice",steps:Ys,owns:["field-style"],read:n=>n["field-style"]??"outline",apply:n=>({"field-style":n})},{id:"labels",label:"Labels",hint:"Where the question sits relative to the answer.",kind:"choice",steps:Vs,owns:["label-position"],read:n=>n["label-position"]??"top",apply:n=>({"label-position":n})}]}function Ks(n){return We().find(e=>e.owns.includes(n))??null}function yt(n){let e=n.activeSlug,s={...n.overrides},t=n.themes;const a=v=>{s=v,n.onOverridesReplaced?.({...v})},i=r("div",{class:"atfs-preview__frame"}),o=r("div",{class:"atfs-controls__body"}),l=r("div",{class:"atfs-quick"}),c=r("div",{class:"atfs-themes"}),d=Me(async()=>{try{const v=await n.previewFor(e,s),_=i.closest(".atf-studio__preview"),k=_?.scrollTop??0;i.innerHTML=v,_&&(_.scrollTop=k),document.dispatchEvent(new CustomEvent("alltfo-refresh"))}catch(v){R(i),i.append(r("p",{class:"atfb-error",text:v instanceof Error?v.message:"Preview failed."}))}},180),u={"label-position":"atf-labels-","field-style":"atf-fields-"},f=(v,_,k)=>{const E=k.replace(/[^a-z0-9_-]/gi,"");for(const A of[...v.classList])A.startsWith(_)&&v.classList.remove(A);E&&v.classList.add(_+E)},g=v=>{const _=i.querySelector(".atf-form-wrap"),k=_?.querySelector(".atf-form");if(_)for(const[E,A]of Object.entries(v))A===""?_.style.removeProperty(`--atf-${E}`):_.style.setProperty(`--atf-${E}`,A),k&&u[E]&&f(k,u[E],A||(t.find(P=>P.slug===e)?.resolved[E]??""))},h=v=>{g(v.resolved);const _=i.querySelector(".atf-form");_&&(f(_,"atf-theme-",v.slug),_.classList.toggle("atf-is-dark",!!v.dark))},y=v=>s[v.token]!==void 0?s[v.token]:t.find(k=>k.slug===e)?.resolved?.[v.token]??v.default,m=()=>{R(c);for(const v of t){const _=r("button",{class:`atfs-theme${v.slug===e?" is-active":""}`,type:"button",attrs:{"aria-pressed":v.slug===e,title:v.description},children:[r("span",{class:"atfs-theme__chip",style:{background:v.resolved.surface??"#fff",borderColor:v.resolved.border??"#ccc",borderRadius:v.resolved["radius-field"]??"4px",boxShadow:v.resolved["shadow-card"]??"none"},children:[r("span",{class:"atfs-theme__accent",style:{background:v.resolved.accent??"#2271b1",borderRadius:v.resolved["radius-button"]??"4px"}})]}),r("span",{class:"atfs-theme__name",text:v.label}),v.custom?r("span",{class:"atfb-badge",text:"yours"}):null],on:{click:()=>{e=v.slug,a({}),n.onTheme(e),h(v),m(),S(),F(),ts()}}});c.append(_)}},p=()=>{const _={...t.find(k=>k.slug===e)?.resolved??{}};for(const[k,E]of Object.entries(s))_[k]=E;return _},x=v=>{const _=l.closest(".atf-studio__controls"),k=_?.scrollTop??0;v(),_&&(_.scrollTop=k)},F=Me(()=>x(b),150),S=()=>{const v=p(),_=l.querySelectorAll(".atfs-dial");We().forEach((k,E)=>{const A=_[E];if(!A)return;const P=k.read(v);if(k.kind==="colour"){const q=A.querySelector('input[type="color"]'),K=A.querySelector("input.atfb-input");q&&document.activeElement!==q&&(q.value=ve(P)),K&&document.activeElement!==K&&(K.value=P);return}A.querySelectorAll(".atfs-segment").forEach((q,K)=>{const Q=k.steps?.[K]?.value===P;q.classList.toggle("is-on",Q),q.setAttribute("aria-pressed",String(Q))})})},H=(v,_)=>{const k=v.apply(_,p());for(const[E,A]of Object.entries(k))s[E]=A,n.onOverride(E,A);g(k),S(),F()},L=()=>{R(l);const v=p();for(const _ of We()){const k=_.read(v);let E;if(_.kind==="colour"){const A=r("input",{class:"atfs-color",type:"color",value:ve(k),attrs:{"aria-label":_.label},on:{input:P=>H(_,P.target.value)}});E=r("div",{class:"atfs-color-row",children:[A,T(k,P=>H(_,P))]})}else E=r("div",{class:`atfs-segmented atfs-segmented--${_.kind}`,attrs:{role:"group","aria-label":_.label},children:(_.steps??[]).map(A=>r("button",{class:`atfs-segment${A.value===k?" is-on":""}`,type:"button",text:A.label,attrs:{"aria-pressed":A.value===k},on:{click:()=>H(_,A.value)}}))});l.append(r("div",{class:"atfs-dial",children:[r("div",{class:"atfs-dial__head",children:[r("span",{class:"atfs-dial__label",text:_.label}),r("span",{class:"atfs-dial__hint",text:_.hint})]}),E]}))}},b=()=>{R(o);const v=new Map;for(const k of n.tokens){const E=v.get(k.group)??[];E.push(k),v.set(k.group,E)}const _={colour:"Colour",shape:"Corners and borders",shadow:"Shadows",fields:"Field style",space:"Spacing",type:"Type",labels:"Labels",button:"Buttons",focus:"Focus ring",motion:"Motion"};for(const[k,E]of v)o.append(r("details",{class:"atfs-group",attrs:{open:k==="colour"},children:[r("summary",{text:_[k]??k}),...E.map(A=>M(A))]}))},M=v=>{const _=y(v),k=q=>{q===""?delete s[v.token]:s[v.token]=q,n.onOverride(v.token,q),g({[v.token]:q})};let E;if(v.control==="color"){const q=r("input",{class:"atfs-color",type:"color",value:ve(_),attrs:{"aria-label":`${v.label} colour`},on:{input:Q=>{const de=Q.target.value;K.value=de,k(de)}}}),K=T(_,Q=>{q.value=ve(Q),k(Q)});E=r("div",{class:"atfs-color-row",children:[q,K]})}else if(v.control==="select")E=D(_,(v.options??[]).map(q=>({value:q,label:q})),k);else if(v.control==="length"){const q=parseFloat(_)||0,K=v.unit??"px",Q=v.token.includes("radius")?60:80,de=r("input",{class:"atfs-range",type:"range",value:String(q),attrs:{min:"0",max:String(Q),step:"1","aria-label":v.label},on:{input:Ee=>{const ns=`${Ee.target.value}${K}`;ss.value=ns,k(ns)}}}),ss=T(_,Ee=>{de.value=String(parseFloat(Ee)||0),k(Ee)});E=r("div",{class:"atfs-length-row",children:[de,ss]})}else E=T(_,k);const A=w(v.label,E),P=Ks(v.token);return P&&(A.classList.add("is-dialled"),A.append(r("span",{class:"atfs-owned",text:P.label}))),s[v.token]!==void 0&&(A.classList.add("is-overridden"),A.append(r("button",{class:"atfs-reset",type:"button",text:"Reset",attrs:{"aria-label":`Reset ${v.label} to the theme's value`},on:{click:()=>{k(""),x(b)}}}))),A},$=async()=>{const v=t.find(E=>E.slug===e),_=v?`${v.label} (mine)`:"My theme",k=window.prompt("Name this theme",_);if(k)try{const E={};for(const P of n.tokens){const q=y(P);q!==P.default&&(E[P.token]=q)}const A=await I.saveTheme({label:k,tokens:E});t=[...t.filter(P=>P.slug!==A.slug),A],n.onThemesChanged(t),e=A.slug,a({}),n.onTheme(e),m(),S(),x(b),N("Theme saved",A.label)}catch(E){N("Could not save the theme",E instanceof Error?E.message:"","error")}},W=async()=>{const v=t.find(_=>_.slug===e);if(v?.custom&&await ie(`Delete “${v.label}”? Forms using it fall back to Clean.`,"Delete theme"))try{await I.deleteTheme(v.id),t=t.filter(k=>k.slug!==v.slug),n.onThemesChanged(t),e="clean",a({}),n.onTheme(e),m(),S(),x(b);const _=t.find(k=>k.slug===e);_&&h(_)}catch(_){N("Could not delete the theme",_ instanceof Error?_.message:"","error")}},j=async()=>{const v=t.find(E=>E.slug===e),_={label:v?.label??e,tokens:{...v?.tokens??{},...s}},k=JSON.stringify(_,null," ");try{await navigator.clipboard.writeText(k),N("Theme copied","Paste it into another site to import it.")}catch{window.prompt("Copy this theme",k)}},ce=()=>{const v=window.prompt("Paste a theme");if(v)try{const _=JSON.parse(v);if(!_.tokens||typeof _.tokens!="object")throw new Error("That does not look like a theme.");for(const[k,E]of Object.entries(_.tokens))s[k]=String(E),n.onOverride(k,String(E));g({...s}),S(),x(b)}catch(_){N("Could not read that theme",_ instanceof Error?_.message:"","error")}},es=C("Delete",()=>void W(),"danger"),ts=()=>{const v=t.find(_=>_.slug===e);es.hidden=!v?.custom};return m(),L(),b(),d(),ts(),r("div",{class:"atf-studio",children:[r("div",{class:"atf-studio__top",children:[r("div",{class:"atf-studio__topbar",children:[r("h2",{class:"atf-studio__heading",text:"Theme"}),r("div",{class:"atfs__actions",children:[C("Save as a theme",()=>void $(),"primary"),C("Export",()=>void j()),C("Import",ce),es]})]}),c]}),r("div",{class:"atf-studio__panes",children:[r("aside",{class:"atf-studio__controls",children:[r("p",{class:"atfb-hint",text:"Changes apply to this form only, until you save them as a theme."}),l,r("details",{class:"atfs-advanced",children:[r("summary",{text:"Every setting"}),r("p",{class:"atfb-hint",text:"The full token list. The dials above write into it."}),o]})]}),r("main",{class:"atf-studio__preview",children:[r("h2",{class:"screen-reader-text",text:"Live preview"}),i]})]})]})}async function Ue(){const n=document.querySelector("[data-atfs-root]");if(!n||n.dataset.atfsMounted)return;n.dataset.atfsMounted="1",Fe(n);const e=n.querySelector("[data-atfs-bar]"),s=n.querySelector(".atfs__body")??n;try{const[t,a,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);if(!i.length){R(s),s.append(r("div",{class:"atfb-empty",children:[r("h2",{text:"No forms to preview"}),r("p",{text:"Make a form first — a theme needs something to dress."})]}));return}let o=i[0],l={},c=o.theme;const d=()=>{R(s),s.append(yt({themes:a,tokens:t.tokens,activeSlug:c,overrides:l,standalone:!0,onTheme:u=>{c=u},onOverride:(u,f)=>{f===""?delete l[u]:l[u]=f},onOverridesReplaced:u=>{l={...u}},previewFor:async(u,f)=>{const g=await I.getForm(o.id);g.schema.settings.theme=u,g.schema.settings.themeOverrides=f;const{html:h}=await I.preview(o.id,{schema:g.schema,theme:u});return h},onThemesChanged:u=>{a.length=0,a.push(...u)}}))};e&&(R(e),e.append(r("span",{class:"atfs__label",text:"Preview against"}),D(String(o.id),i.map(u=>({value:String(u.id),label:u.title||"(untitled)"})),u=>{o=i.find(f=>String(f.id)===u)??i[0],l={},d()}))),d()}catch(t){R(s),s.append(r("p",{class:"atfb-error",text:t instanceof Error?t.message:"Could not load themes."}))}}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>void Ue()):Ue(),document.addEventListener("os-window-content-loaded",()=>void Ue()));function ve(n){const e=n.trim();return/^#[0-9a-f]{6}$/i.test(e)?e:/^#[0-9a-f]{3}$/i.test(e)?`#${e[1]}${e[1]}${e[2]}${e[2]}${e[3]}${e[3]}`:"#888888"}const Gs="mailpoet",ye="",Xs=["checkbox","checkboxes","toggle","consent","gdpr"],wt=["email"];function _t(n){return n.schema.actions.find(e=>e.type==="mailpoet")}function ze(n){const e=n?.settings??{};return{lists:Array.isArray(e.lists)?e.lists.map(Number).filter(Boolean):[],email_field:typeof e.email_field=="string"?e.email_field:"",first_name_field:typeof e.first_name_field=="string"?e.first_name_field:"",last_name_field:typeof e.last_name_field=="string"?e.last_name_field:""}}function Zs(n){return n?.logic?.enabled?n.logic.rules[0]?.field??ye:ye}function xt(n,e,s){const t=n.find(a=>e.includes(a.type));return t?t.id:s?n.find(a=>s.test(a.label))?.id??"":""}function Js(n,e,s){const t=r("section",{class:"atfm-form"}),a=l=>r("span",{class:`atfm-form__mark${l?"":" atfm-form__mark--off"}`,children:[r("img",{attrs:{src:e.symbol,alt:"",width:"20",height:"20"}})]}),i=l=>{R(t),t.classList.remove("is-open"),t.append(r("div",{class:"atfm-form__head",children:[a(l.length>0),r("div",{class:"atfm-form__title",children:[r("strong",{text:n.title||`Form ${n.id}`}),l.length?r("span",{class:"atfm-form__status is-on",text:`Subscribing → ${l.join(", ")}`}):r("span",{class:"atfm-form__status",text:"Not connected"})]}),C(l.length?"Edit":"Connect",()=>void o(),"secondary")]}))},o=async()=>{t.classList.add("is-open"),R(t),t.append(r("p",{class:"atfm-hint",text:"Loading the form…"}));let l;try{l=await I.getForm(n.id)}catch{R(t),t.append(r("p",{class:"atfm-hint",text:"Could not load this form."}));return}const c=l.schema.fields.filter(b=>b.type!=="page_break"),d=_t(l),u=ze(d),f=new Set(u.lists.filter(b=>e.lists.some(M=>M.id===b)));let g=Zs(d),h=u.email_field||xt(c,wt,/mail/i),y=u.first_name_field,m=u.last_name_field;c.some(b=>b.id===h)||(h=xt(c,wt,/mail/i));const p=c.filter(b=>Xs.includes(b.type));!d&&p.length&&(g=p[0].id);const x=(b,M)=>[{value:"",label:M},...b.map($=>({value:$.id,label:$.label||$.id}))],F=r("div",{class:"atfm-lists"});(()=>{R(F);for(const b of e.lists){const M=r("input",{attrs:{type:"checkbox"}});M.checked=f.has(b.id),M.addEventListener("change",()=>{M.checked?f.add(b.id):f.delete(b.id)}),F.append(r("label",{class:"atfm-list",children:[M,r("span",{text:b.name})]}))}})();const H=async(b=!1)=>{const M=l.schema.actions.filter($=>$.type!=="mailpoet");if(!b){if(!f.size){N("Pick a list","A subscription needs at least one MailPoet list.","error");return}if(!h){N("Pick the email field","MailPoet needs to know which answer is the address.","error");return}M.push({id:Gs,type:"mailpoet",enabled:!0,logic:g===ye?{enabled:!1,action:"show",match:"all",rules:[]}:{enabled:!0,action:"show",match:"all",rules:[{field:g,operator:"not_empty",value:""}]},settings:{lists:[...f],email_field:h,first_name_field:y,last_name_field:m}})}l.schema.actions=M;try{await I.updateForm(l.id,{schema:l.schema})}catch($){N("Could not save",$ instanceof Error?$.message:"","error");return}N(b?"Disconnected":"Connected to MailPoet",b?`${n.title} no longer subscribes anyone.`:`${n.title} now subscribes opted-in visitors.`),i(b?[]:e.lists.filter($=>f.has($.id)).map($=>$.name))};R(t);const L=b=>r("span",{class:"atfm-form__section",text:b});t.append(r("div",{class:"atfm-form__head",children:[a(!!d),r("div",{class:"atfm-form__title",children:[r("strong",{text:n.title||`Form ${n.id}`})]}),C("Close",()=>i(d?e.lists.filter(b=>ze(d).lists.includes(b.id)).map(b=>b.name):[]),"ghost")]}),r("div",{class:"atfm-form__body",children:[L("Where they land"),w("Lists",F,"MailPoet sends its own confirmation email before anyone is truly on a list."),L("Who they are"),w("Email address",D(h,x(c,"— pick a field —"),b=>{h=b}),"The answer that carries their address."),w("First name",D(y,x(c,"— none —"),b=>{y=b})),w("Last name",D(m,x(c,"— none —"),b=>{m=b})),L("When to subscribe"),w("Subscribe",D(g,[...p.map(b=>({value:b.id,label:`Only when “${b.label||b.id}” is ticked`})),{value:ye,label:"Everyone who submits"}],b=>{g=b}),p.length?"Bind it to a box they tick. Subscribing everyone is rarely what visitors expect.":"Add a checkbox or toggle field to the form to offer a proper opt-in."),r("div",{class:"atfm-form__actions",children:d?[C("Save connection",()=>void H(),"primary"),C("Disconnect",()=>void H(!0),"danger")]:[C("Save connection",()=>void H(),"primary")]})]}))};return i([]),I.getForm(n.id).then(l=>{const c=_t(l);if(c&&!t.classList.contains("is-open")){const d=e.lists.filter(u=>ze(c).lists.includes(u.id)).map(u=>u.name);i(d)}}).catch(()=>{}),s.append(t),t}function Qs(n){const e=n.logo?r("span",{class:"atfm-hero__logo",children:[r("img",{attrs:{src:n.logo,alt:"MailPoet",width:"210",height:"105"}})]}):r("span",{class:"atfm-hero__logo atfm-hero__logo--glyph",text:"📬"});return r("header",{class:"atfm-hero",children:[e,r("div",{class:"atfm-hero__words",children:[r("h1",{text:"Turn submissions into subscribers"}),r("p",{text:"Every submission is someone choosing to talk to you. Connect a form to MailPoet and the ones who opt in land on your lists by themselves — named, consented, and confirmed by MailPoet’s own double opt-in."}),n.active?r("p",{class:"atfm-hero__status is-on",text:n.lists.length===1?"Connected — 1 list ready for subscribers":`Connected — ${n.lists.length} lists ready for subscribers`}):r("p",{class:"atfm-hero__status",text:"MailPoet is not installed on this site yet"})]})]})}function en(){const n=(s,t,a)=>r("div",{class:"atfm-why__card",children:[r("span",{class:"atfm-why__icon",text:s}),r("strong",{text:t}),r("p",{text:a})]}),e=(s,t)=>r("a",{text:t,attrs:{href:s,target:"_blank",rel:"noreferrer"}});return[r("div",{class:"atfm-why",children:[n("✉️","Beautiful emails, made in WordPress","Design newsletters and welcome emails in a drag-and-drop editor that lives in your own admin — no external account to juggle."),n("🤝","Consent you can stand behind","Double opt-in out of the box: every address your forms send over is confirmed by the visitor before a single campaign reaches it."),n("🚀","Free to grow with","Free up to 500 subscribers, welcome automations, WooCommerce emails and open-rate stats included — a paid addon anywhere else.")]}),r("p",{class:"atfm-links",children:[e("https://www.mailpoet.com/features/","Explore MailPoet’s features ↗"),e("https://kb.mailpoet.com/","Guides & docs ↗"),e("https://www.mailpoet.com/pricing/","Plans & the free tier ↗")]})]}function tn(){const n=(e,s)=>r("div",{class:"atfm-step",children:[r("span",{class:"atfm-step__n",text:e}),r("span",{text:s})]});return r("div",{class:"atfm-steps",children:[n("1","Pick a form below"),n("2","Choose the lists it feeds"),n("3","Bind it to an opt-in — MailPoet confirms the rest")]})}async function Ye(){const n=document.querySelector("[data-atfm-root]");if(!n||n.dataset.atfmMounted)return;n.dataset.atfmMounted="1",Fe(n);const e=n.querySelector("[data-atfm-bar]"),s=n.querySelector("[data-atfm-body]")??n;try{const[t,a]=await Promise.all([I.mailpoet(),I.listForms()]);if(e?.remove(),R(s),s.append(Qs(t),...en()),!t.active){s.append(r("div",{class:"atfm-pitch",children:[r("p",{text:"MailPoet sends newsletters from right inside WordPress — no external account, free to start. Install it and every form here gets a subscribe switch: reservations feed your announcements, signups feed your schedule, enquiries feed your news."}),r("a",{class:"atfm-pitch__cta",text:"Install MailPoet — it’s free",attrs:{href:t.adminUrl,target:"_blank",rel:"noreferrer"}})]}));return}if(!t.lists.length){s.append(r("div",{class:"atfm-pitch",children:[r("p",{text:"MailPoet is here, but it has no list yet. Make one, and your forms will have somewhere to send subscribers."}),r("a",{class:"atfm-pitch__cta",text:"Open MailPoet lists",attrs:{href:t.adminUrl,target:"_blank",rel:"noreferrer"}})]}));return}s.append(tn());const i=r("section",{class:"atfm-forms",children:[r("div",{class:"atfm-forms__head",children:[r("h2",{text:"Your forms"}),r("p",{class:"atfm-hint",text:"Connected forms wear the MailPoet mark in colour."})]})]});if(s.append(i),!a.length){i.append(r("p",{class:"atfm-hint",text:"No forms yet — make one, then come back to connect it."}));return}for(const o of a)Js(o,t,i)}catch{e&&(e.textContent="Could not reach the site — reload the window to try again.")}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>void Ye()):Ye(),document.addEventListener("os-window-content-loaded",()=>void Ye());const we={plain:"",simple:"✓",minimal:"",card:"🎉",check:"",confetti:"🎉",fireworks:"🎆",sparkles:"✨",typewriter:""};function kt(){return{style:"simple",title:"",icon:"",accent:"",intensity:"medium",showButton:!1,buttonLabel:""}}function Ve(n){const e={...kt(),...n??{}};return e.style in we||(e.style="simple"),e}function sn(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}function nn(n,e,s){const t=Ve(e),a=document.createElement("div");if(a.className=`atf-confirmation atf-success atf-success--${t.style}`,a.setAttribute("role","status"),a.setAttribute("tabindex","-1"),t.style==="plain")return a.className="atf-confirmation",a.innerHTML=n,a;t.accent&&a.style.setProperty("--atf-accent",t.accent);const i=document.createElement("div");i.className="atf-success__inner",a.append(i);const o=t.icon||we[t.style];if(t.style==="check")i.insertAdjacentHTML("beforeend",'');else if(o){const c=document.createElement("span");c.className="atf-success__icon",c.setAttribute("aria-hidden","true"),c.textContent=o,i.append(c)}if(t.title){const c=document.createElement("h2");c.className="atf-success__title",c.textContent=t.title,i.append(c)}const l=document.createElement("div");if(l.className="atf-success__message",l.innerHTML=n,i.append(l),t.style==="typewriter"&&a.setAttribute("aria-label",l.textContent??""),t.showButton){const c=document.createElement("button");c.type="button",c.className="atf-button atf-button--ghost atf-success__again",c.textContent=t.buttonLabel||"Fill it in again",c.addEventListener("click",()=>s?s():window.location.reload()),i.append(c)}return a}function an(n,e){const s=Ve(e);if(sn())return()=>{};switch(s.style){case"confetti":return rn(n,s);case"fireworks":return on(s);case"sparkles":return ln(n,s);case"typewriter":return cn(n);default:return()=>{}}}function le(n){return{low:.5,medium:1,high:1.8}[n.intensity]}function St(){const n=document.createElement("canvas");n.className="atf-success-canvas",n.setAttribute("aria-hidden","true");const e=Math.min(window.devicePixelRatio||1,2);n.width=Math.floor(window.innerWidth*e),n.height=Math.floor(window.innerHeight*e),document.body.append(n);const s=n.getContext("2d");return s?.scale(e,e),{canvas:n,ctx:s,stop:()=>n.remove()}}const Ct=["#f43f5e","#f59e0b","#10b981","#3b82f6","#8b5cf6","#ec4899","#eab308"];function rn(n,e){const{ctx:s,stop:t}=St();if(!s)return t(),()=>{};const a=e.accent?[e.accent,...Ct]:Ct,i=[],o=n.getBoundingClientRect(),l=o.left+o.width/2,c=Math.min(o.top+40,window.innerHeight-20),d=(x,F,S)=>{const H=S?Math.PI*(1.15+.7*Math.random()):0,L=S?9+Math.random()*8:0;return{x,y:F,vx:S?Math.cos(H)*L*(Math.random()<.5?1:-1):(Math.random()-.5)*1.5,vy:S?Math.sin(H)*L:1+Math.random()*2,w:6+Math.random()*5,h:8+Math.random()*7,angle:Math.random()*Math.PI,spin:(Math.random()-.5)*.3,color:a[Math.floor(Math.random()*a.length)],wobble:Math.random()*Math.PI*2}},u=Math.round(90*le(e));for(let x=0;x{if(g>=f){window.clearInterval(h);return}i.push(d(Math.random()*window.innerWidth,-20,!1)),g++},2e3/f);let y=0;const m=performance.now(),p=x=>{s.clearRect(0,0,window.innerWidth,window.innerHeight);let F=!1;for(const S of i)S.vy+=.16,S.vx*=.99,S.vy*=.985,S.wobble+=.1,S.x+=S.vx+Math.sin(S.wobble)*.8,S.y+=S.vy,S.angle+=S.spin,S.y{window.clearInterval(h),window.cancelAnimationFrame(y),t()}}function on(n){const{ctx:e,stop:s}=St();if(!e)return s(),()=>{};const t=[],a=[],i=Math.round(6*le(n))+2;let o=0;const l=()=>{t.push({x:window.innerWidth*(.15+.7*Math.random()),y:window.innerHeight,vy:-(9+Math.random()*4),targetY:window.innerHeight*(.15+.3*Math.random()),hue:Math.floor(Math.random()*360)}),o++};l();const c=window.setInterval(()=>{if(o>=i){window.clearInterval(c);return}l()},3500/i),d=h=>{const y=Math.round(70*le(n));for(let m=0;m{e.clearRect(0,0,window.innerWidth,window.innerHeight);for(let m=t.length-1;m>=0;m--){const p=t[m];p.y+=p.vy,p.vy+=.08,e.fillStyle=`hsl(${p.hue} 90% 65%)`,e.fillRect(p.x-1.5,p.y,3,10),(p.y<=p.targetY||p.vy>=-1)&&(d(p),t.splice(m,1))}for(let m=a.length-1;m>=0;m--){const p=a[m];if(p.x+=p.vx,p.y+=p.vy,p.vy+=.045,p.vx*=.985,p.vy*=.985,p.life-=p.decay,p.life<=0){a.splice(m,1);continue}const x=p.life*(.7+.3*Math.random());e.globalAlpha=Math.max(0,x),e.fillStyle=`hsl(${p.hue} 95% ${55+25*p.life}%)`,e.beginPath(),e.arc(p.x,p.y,1.1+1.6*p.life,0,Math.PI*2),e.fill()}e.globalAlpha=1,!(o>=i&&t.length===0&&a.length===0)&&h-f<9e3?u=window.requestAnimationFrame(g):s()};return u=window.requestAnimationFrame(g),()=>{window.clearInterval(c),window.cancelAnimationFrame(u),s()}}function ln(n,e){const s=e.icon||we.sparkles,t=Math.round(22*le(e)),a=[];let i=0;const o=()=>{const c=document.createElement("span");c.className="atf-success__spark",c.setAttribute("aria-hidden","true"),c.textContent=s,c.style.insetInlineStart=`${4+Math.random()*92}%`,c.style.animationDuration=`${2.6+Math.random()*1.8}s`,c.style.animationDelay=`${Math.random()*.3}s`,c.style.fontSize=`${14+Math.random()*14}px`,c.addEventListener("animationend",()=>c.remove()),n.append(c),a.push(c),i++};o();const l=window.setInterval(()=>{if(i>=t){window.clearInterval(l);return}o()},2800/t);return()=>{window.clearInterval(l),a.forEach(c=>c.remove())}}function cn(n){const e=n.querySelector(".atf-success__message");if(!e)return()=>{};const s=e.innerHTML,t=e.textContent??"";if(!t)return()=>{};e.textContent="",e.classList.add("is-typing");const a=Math.min(45,3800/t.length);let i=0;const o=window.setInterval(()=>{i++,e.textContent=t.slice(0,i),i>=t.length&&(window.clearInterval(o),e.classList.remove("is-typing"),e.innerHTML=s)},a);return()=>{window.clearInterval(o),e.classList.remove("is-typing"),e.innerHTML=s}}const dn={min:-1,max:-1,sum:-1,avg:-1,round:-1,ceil:1,floor:1,abs:1,sqrt:1,pow:2},Et={"+":{precedence:1,right:!1},"-":{precedence:1,right:!1},"*":{precedence:2,right:!1},"/":{precedence:2,right:!1},"%":{precedence:2,right:!1},"^":{precedence:4,right:!0}};function un(n,e,s=[]){if(!n||!n.trim()||n.length>2e3)return null;const t=hn(n,e,s),a=bn(t);if(!a)return null;const i=vn(a);if(!i)return null;const o=yn(i);return o===null||!Number.isFinite(o)?null:o}function hn(n,e,s){return n.replace(/\{([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?\}/g,(t,a,i,o)=>pn(n,o,t.length,a,i??"",e,s))}function pn(n,e,s,t,a,i,o){const l=fn(o,t),c=Object.prototype.hasOwnProperty.call(i,t)?i[t]:null;if(a===""){const h=l?.type==="repeater"?Lt(c).length:Ke(c,l);return $t(h)}const u=(l?.fields??[]).find(h=>h.id===a)??null,f=Lt(c).map(h=>Ke(h[a]??"",u));if(!f.length)return"0";const g=f.map($t);return mn(n,e,s)?g.join(", "):g.length===1?g[0]:`( ${g.join(" + ")} )`}function fn(n,e){for(const s of n){if(s.id===e)return s;for(const t of s.fields??[])if(t.id===e)return t}return null}function mn(n,e,s){const t=n.slice(e+s).replace(/^\s+/,"");if(t===""||t[0]!==")")return!1;const a=n.slice(0,e).replace(/\s+$/,""),i=/([a-zA-Z_][a-zA-Z0-9_]*)\s*\($/.exec(a);return!!i&&["sum","avg","min","max"].includes(i[1].toLowerCase())}function Lt(n){if(!Array.isArray(n))return[];const e=[];for(const s of n){if(!s||typeof s!="object"||Array.isArray(s))continue;Object.values(s).some(a=>a!==""&&a!==null&&a!==void 0&&a!==!1&&!(Array.isArray(a)&&!a.length))&&e.push(s)}return e}function $t(n){const e=n.toFixed(10).replace(/0+$/,"").replace(/\.$/,"");return e===""||e==="-"?"0":e}function Ke(n,e){if(typeof n=="boolean")return n?1:0;if(Array.isArray(n))return n.reduce((a,i)=>a+Ke(i,e),0);if(n==null||n==="")return 0;const s=e?.choices??[];for(const a of s)if(String(a.value)===String(n)){if(typeof a.price=="number")return a.price;if(typeof a.points=="number")return a.points;break}const t=Number(n);return Number.isFinite(t)?t:0}function bn(n){const e=[];let s=0;for(;si.precedence||l.precedence===i.precedence&&!i.right){e.push(s.pop());continue}break}s.push(a);break}case"(":s.push(a);break;case")":{for(;s.length&&s[s.length-1].type!=="(";)e.push(s.pop());if(!s.length)return null;if(s.pop(),s.length&&s[s.length-1].type==="function"){const i=s.pop();i.arity=t.length?t.pop():1,e.push(i)}break}}for(;s.length;){const a=s.pop();if(a.type==="(")return null;e.push(a)}return e}function yn(n){const e=[];for(const s of n)switch(s.type){case"number":e.push(s.value);break;case"unary":{if(!e.length)return null;e.push(-e.pop());break}case"operator":{if(e.length<2)return null;const t=e.pop(),a=e.pop();switch(s.value){case"+":e.push(a+t);break;case"-":e.push(a-t);break;case"*":e.push(a*t);break;case"/":e.push(t===0?0:a/t);break;case"%":e.push(t===0?0:a%t);break;case"^":e.push(Math.pow(a,t));break;default:return null}break}case"function":{const t=s.arity??1;if(e.lengths+t,0);case"avg":return e.reduce((s,t)=>s+t,0)/e.length;case"round":{const s=Math.max(-10,Math.min(10,Math.trunc(e[1]??0))),t=Math.pow(10,s);return Math.round(e[0]*t)/t}case"ceil":return Math.ceil(e[0]);case"floor":return Math.floor(e[0]);case"abs":return Math.abs(e[0]);case"sqrt":return e[0]<0?0:Math.sqrt(e[0]);case"pow":return Math.pow(e[0],e[1]??2);default:return null}}const _n=["sum","min","max","avg","round","ceil","floor","abs","sqrt","pow"],At=["number","range","scale","rating","total","select","multiselect","radio","checkboxes","switch","quiz"];function _e(n,e){return n.filter(s=>s.id!==e&&At.includes(s.type))}function Tt(n){const e=[];for(const s of n){if(s.type!=="repeater")continue;const t=s.label||s.id;e.push({label:`${t} (how many)`,insert:`{${s.id}}`});for(const a of s.fields??[])At.includes(a.type)&&e.push({label:`${t} · ${a.label||a.id}`,insert:`{${s.id}.${a.id}}`})}return e}function xn(n,e){const s={};_e(n,e).forEach((t,a)=>{s[t.id]=a+1});for(const t of n){if(t.type!=="repeater"||t.id===e)continue;const a=t.fields??[],i=o=>Object.fromEntries(a.map((l,c)=>[l.id,c+1+o]));s[t.id]=[i(0),i(1)]}return s}function Mt(n,e,s){return Be(n,{preview:!1,groups:()=>[{id:"references",label:"Your questions",items:[..._e(e,s).map(t=>({label:t.label||t.id,tag:`{${t.id}}`,sample:"",hint:""})),...Tt(e.filter(t=>t.id!==s)).map(t=>({label:t.label,tag:t.insert,sample:"",hint:""}))],empty:"Add a number, scale or priced choice question to reference it here."}]})}function kn(n){const e=r("div",{class:"atfb-overlay"}),s=()=>{e.remove(),document.removeEventListener("keydown",t)},t=h=>{h.key==="Escape"&&s()},a=r("textarea",{class:"atfb-input atfb-formula__input",attrs:{rows:"3","aria-label":"Formula"}});a.value=String(n.field.formula??"");const i=r("p",{class:"atfb-formula__result",attrs:{"aria-live":"polite"}}),o=xn(n.fields,n.field.id),l=()=>{const h=a.value.trim();if(h===""){i.textContent="Empty. Reference a question below to start.",i.classList.remove("is-error");return}const y=un(h,o,n.fields);if(y===null){i.textContent="This does not compute yet — check the braces and parentheses.",i.classList.add("is-error");return}const m=_e(n.fields,n.field.id).map((p,x)=>`${p.label||p.id} = ${x+1}`).concat(n.fields.filter(p=>p.type==="repeater"&&p.id!==n.field.id).map(p=>`${p.label||p.id} = 2 sample rows`)).join(", ");i.textContent=`With sample answers (${m}): ${y}`,i.classList.remove("is-error")};a.addEventListener("input",l);const c=(h,y,m=0)=>r("button",{class:"atfb-formula__chip",type:"button",text:h,on:{click:()=>{if(bt(a,y),m>0){const p=(a.selectionStart??a.value.length)-m;a.setSelectionRange(p,p)}}}}),d=_e(n.fields,n.field.id),u=Tt(n.fields.filter(h=>h.id!==n.field.id)),f=r("div",{class:"atfb-formula__chips",children:d.length||u.length?[...d.map(h=>c(h.label||h.id,`{${h.id}}`)),...u.map(h=>c(h.label,h.insert))]:[r("p",{class:"atfb-hint",text:"No number-shaped questions yet — add a number, scale or priced choice field and it appears here."})]}),g=r("div",{class:"atfb-formula__chips",children:_n.map(h=>c(`${h}()`,`${h}()`,1))});e.append(r("div",{class:"atfb-modal atfb-formula",attrs:{role:"dialog","aria-label":"Formula editor"},children:[r("h2",{text:"Formula"}),Mt(a,n.fields,n.field.id),i,w("Your questions",f,"Click one to reference its answer."),w("Functions",g),r("div",{class:"atfb-modal__actions",children:[C("Cancel",s),C("Save formula",()=>{n.onSave(a.value.trim()),s()},"primary")]})]})),e.addEventListener("click",h=>{h.target===e&&s()}),document.addEventListener("keydown",t),n.root.append(e),l(),a.focus(),a.setSelectionRange(a.value.length,a.value.length)}function Ft(n){return[...n.fields.filter(e=>e.type!=="page_break").map(e=>({key:`field:${e.id}`,label:`Field: ${e.label||e.id}`,fieldId:e.id,logic:e.logic})),...n.notifications.map(e=>({key:`notification:${e.id}`,label:`Notification: ${e.name||e.id}`,logic:e.logic})),...n.confirmations.map(e=>({key:`confirmation:${e.id}`,label:`Confirmation: ${e.name||e.id}`,logic:e.logic}))]}function It(n,e,s){return n.key!==e.key&&n.logic.rules.length>0&&n.logic.rules.every(t=>t.field!==e.fieldId&&s.fields.some(a=>a.id===t.field&&a.type!=="page_break"))}function Sn(n,e,s,t){const a=Ft(n),i=a.find(l=>l.key===e),o=a.find(l=>l.key===s);return!i||!o||!It(i,o,n)?!1:(t?.(),Object.assign(o.logic,i.logic,{rules:i.logic.rules.map(l=>({...l}))}),!0)}function Dt(n){const e=document.activeElement,s=r("div",{class:"atfb-overlay"}),t=r("div",{class:"atfb-modal atfb-condition-copy",attrs:{role:"dialog","aria-modal":"true","aria-label":"Copy condition",tabindex:"-1"}});let a="";const i=n.to,o=()=>{s.remove(),e?.focus()},l=()=>{const c=n.schema();if(!c){o();return}const d=Ft(c),u=d.find(p=>p.key===i),f=d.filter(p=>p.logic.rules.length&&u&&It(p,u,c)),g=f.find(p=>p.key===a),h=D(a,[{value:"",label:"Choose a section…"},...f.map(p=>({value:p.key,label:p.label}))],p=>{a=p,l(),t.querySelector('[aria-label="Copy from"]')?.focus()});h.setAttribute("aria-label","Copy from");const y=C("Copy condition",()=>{const p=n.schema();p&&Sn(p,a,i,n.beforeCopy)&&(o(),n.onCopy())},"primary");(!g||!i)&&y.setAttribute("disabled","");const m=d.find(p=>p.key===i);t.replaceChildren(r("h2",{text:"Copy condition"}),w("Copy from",h),r("p",{class:"atfb-hint",text:`Apply to ${m?.label??"this section"}.`}),r("p",{class:"atfb-condition-copy__preview",attrs:{"aria-live":"polite"},text:g?`${g.logic.enabled?"Enabled":"Disabled"} · ${g.logic.action==="hide"?"Hide":"Show"} · Match ${g.logic.match}: `+g.logic.rules.map(p=>qe(be(p,c.fields))).join(g.logic.match==="all"?" and ":" or "):f.length?"Choose the section whose condition you want to reuse.":"No conditions are available to copy here yet."}),r("p",{class:"atfb-hint",text:m?.logic.rules.length?"This replaces the destination’s entire condition. You can edit the copy independently.":"Copies every rule, all/any matching, show/hide and enabled state. You can edit the copy independently."}),r("div",{class:"atfb-modal__actions",children:[C("Cancel",o),y]}))};s.append(t),s.addEventListener("click",c=>{c.target===s&&o()}),s.addEventListener("keydown",c=>{if(c.key==="Escape"&&(c.preventDefault(),o()),c.key==="Tab"){const d=[...t.querySelectorAll("button:not([disabled]), select, os-select, os-button:not([disabled])")],u=d[0],f=d[d.length-1];c.shiftKey&&(document.activeElement===u||document.activeElement===t)?(c.preventDefault(),f?.focus()):!c.shiftKey&&document.activeElement===f&&(c.preventDefault(),u?.focus())}c.stopPropagation()}),n.root.append(s),l(),t.focus()}const Cn="allterrain-forms/form";function En(){return window.wp?.os?.relations??null}function qt(n){const e=n.closest("[data-window-id], .os-window");if(!e)return null;const s=e.getAttribute("data-window-id");if(s)return s;const t=e.id??"";return t?t.replace(/^wp-window-/,""):null}const Ln=6e3,Ot=120;function Nt(n,e){const s=En();if(Ge.set(n,e),!s?.set)return;const t=i=>{if(xe.get(n)!==a)return;const o=qt(n);if(!o){Date.now()t(i),Ot);return}try{s.set(o,e)}catch(c){Rt||(Rt=!0,console.error("[AllTerrain Forms] The shell refused a window identity.",c,e)),xe.delete(n);return}if(!e||s.get?.(o)?.id===e.id||Date.now()>=i){xe.delete(n);return}window.setTimeout(()=>t(i),Ot)},a=Symbol("atf-identity");xe.set(n,a),t(Date.now()+Ln)}let Rt=!1;const xe=new WeakMap,Ge=new Map;function $n(){for(const[n,e]of Ge){if(!n.isConnected){Ge.delete(n);continue}Nt(n,e)}}if(typeof document<"u")for(const n of["os-window-content-loaded","os-window-opened"])document.addEventListener(n,()=>$n());function An(n,e){return{type:Cn,id:n.id,label:n.title||"Untitled form",related:[{id:`allterrain-forms/entries-${n.id}`,label:"Entries for this form",url:`${e}admin.php?page=allterrain-forms-entries&form=${n.id}`,group:"allterrain-forms",groupLabel:"Forms",icon:"dashicons-list-view"}]}}const ke={letters:{label:"Letters",chars:"A-Za-zÀ-ÖØ-öø-ÿ"},numbers:{label:"Numbers",chars:"0-9"},spaces:{label:"Spaces",chars:" "},punctuation:{label:`Punctuation ( . , ! ? ' " - )`,chars:`.,!?'"()\\-:;`},symbols:{label:"Symbols ( @ # & _ / + )",chars:"@#&_/+*%="}};function Tn(){return{mode:"blocks",starts:"",ends:"",contains:"",notContains:"",chars:[],minLen:"",maxLen:"",regex:"",message:"",tests:[]}}function Pt(n){const e=Tn();let s;try{s=JSON.parse(n)}catch{return e}if(!s||typeof s!="object")return e;const t=s;e.mode=t.mode==="regex"?"regex":"blocks";for(const a of["starts","ends","contains","notContains","minLen","maxLen","regex","message"])typeof t[a]=="string"&&(e[a]=t[a]);return Array.isArray(t.chars)&&(e.chars=t.chars.filter(a=>typeof a=="string"&&a in ke)),Array.isArray(t.tests)&&(e.tests=t.tests.filter(a=>typeof a=="string").slice(0,10)),e}function Se(n){return n.replace(/[.*+?^${}()|[\]\\/]/g,"\\$&")}function Ce(n){if(n.mode==="regex")return n.regex.trim();const e=[],s=n.minLen.trim(),t=n.maxLen.trim();(s!==""||t!=="")&&e.push(`(?=.{${s===""?"0":parseInt(s,10)||0},${t===""?"":parseInt(t,10)||""}}$)`),n.contains!==""&&e.push(`(?=.*${Se(n.contains)})`),n.notContains!==""&&e.push(`(?!.*${Se(n.notContains)})`),n.starts!==""&&e.push(`(?=${Se(n.starts)})`),n.ends!==""&&e.push(`(?=.*${Se(n.ends)}$)`);const a=n.chars.map(o=>ke[o]?.chars??"").join(""),i=a?`[${a}]*$`:".*$";return!e.length&&!a?"":`^${e.join("")}${i}`}function Bt(n){if(n.mode==="regex")return n.regex.trim()?`Matches the expression ${n.regex.trim()}`:"";const e=[];if(n.starts&&e.push(`starts with “${n.starts}”`),n.ends&&e.push(`ends with “${n.ends}”`),n.contains&&e.push(`contains “${n.contains}”`),n.notContains&&e.push(`never contains “${n.notContains}”`),n.chars.length){const i=n.chars.map(o=>(ke[o]?.label??o).split(" (")[0].toLowerCase());e.push(`uses only ${i.join(" and ")}`)}const s=n.minLen.trim(),t=n.maxLen.trim();return s&&t?e.push(`is ${s}–${t} characters long`):s?e.push(`is at least ${s} characters long`):t&&e.push(`is at most ${t} characters long`),e.length?`The answer ${e.length>1?`${e.slice(0,-1).join(", ")}, and ${e[e.length-1]}`:e[0]}.`:""}function Mn(n,e){const s=Ce(n);if(s==="")return null;try{return new RegExp(s).test(e)}catch{return null}}function Fn(){return window.wp?.os?.windowManager??null}const jt="allterrain-forms-validation";function In(n){const e=Fn(),s=qt(n.root);if(e?.openChild&&s){Dn(e,s,n);return}qn(n)}function Dn(n,e,s){const t=`${jt}-${s.field.id}`;n.getById?.(t)&&n.remove?.(t);const a={saved:!1},i=()=>{const o=n.getById?.(t);o?.close?o.close():n.remove?.(t)};n.openChild?.(e,{id:t,baseId:jt,url:`#${t}`,title:`Custom rule — ${s.field.label||"this question"}`,icon:"dashicons-yes-alt",native:!0,width:560,height:700,minWidth:440,minHeight:480,ephemeral:!0,autofocus:".atfb-valwin__pane:not([hidden]) input, .atfb-valwin__pane:not([hidden]) textarea",render:o=>{const l=r("div",{class:"atfa atfb-valwin atfb-valwin--window"}),c=r("div",{class:"atfb-valwin__scroll"});l.append(c),Ht(c,s,a,i,"window");const d=c.querySelector(".atfb-modal__actions");d&&l.append(d),o.append(l)},onClose:()=>{a.saved||s.onCancel?.()}})}function qn(n){const e=r("div",{class:"atfb-overlay"}),s={saved:!1},t=()=>{e.remove(),document.removeEventListener("keydown",a),s.saved||n.onCancel?.()},a=o=>{o.key==="Escape"&&t()},i=r("div",{class:"atfb-modal atfb-valwin",attrs:{role:"dialog","aria-label":"Custom validation rule"},children:[r("h2",{text:"Custom rule"})]});Ht(i,n,s,t,"overlay"),e.append(i),e.addEventListener("click",o=>{o.target===e&&t()}),document.addEventListener("keydown",a),n.root.append(e),e.querySelector(".atfb-valwin__pane:not([hidden]) input, .atfb-valwin__pane:not([hidden]) textarea")?.focus()}function Ht(n,e,s,t,a){const i=Pt(String(e.field.validationRecipe??""));i.mode==="blocks"&&Ce(i)===""&&e.field.pattern&&(i.mode="regex",i.regex=String(e.field.pattern)),i.message||(i.message=String(e.field.messages?.invalid??""));const o=(b,M)=>{const $=r("input",{class:"atfb-input",value:i[b],placeholder:M,attrs:{type:"text"}});return $.addEventListener("input",()=>{i[b]=$.value,L()}),$},l=(b,M)=>{const $=r("input",{class:"atfb-input atfb-valwin__len",value:i[b],attrs:{type:"number",min:"0","aria-label":M}});return $.addEventListener("input",()=>{i[b]=$.value,L()}),$},c=r("div",{class:"atfb-valwin__chars",children:Object.entries(ke).map(([b,M])=>O(M.label,i.chars.includes(b),$=>{i.chars=$?[...i.chars,b]:i.chars.filter(W=>W!==b),L()}))}),d=r("div",{class:"atfb-valwin__pane",children:[w("Starts with",o("starts","e.g. AT-")),w("Ends with",o("ends","e.g. -2026")),w("Must contain",o("contains","e.g. @")),w("Must not contain",o("notContains","e.g. spaces? type one")),w("Only these characters",c,"Leave every box unticked to allow anything."),w("Length",r("div",{class:"atfb-valwin__lengths",children:[r("span",{text:"between"}),l("minLen","Minimum length"),r("span",{text:"and"}),l("maxLen","Maximum length"),r("span",{text:"characters"})]}),"Leave a box empty for no limit.")]}),u=r("textarea",{class:"atfb-input atfb-valwin__regex",attrs:{rows:"2","aria-label":"Regular expression",placeholder:"^AT-[0-9]{4}$"}});u.value=i.regex,u.addEventListener("input",()=>{i.regex=u.value,L()});const f=r("div",{class:"atfb-valwin__pane",children:[w("Expression",u,"A regular expression, without slashes. Checked against the whole answer only if you anchor it with ^ and $.")]}),g=[["blocks","Easy blocks"],["regex","Expression (advanced)"]],h=b=>{i.mode=b,d.hidden=b!=="blocks",f.hidden=b!=="regex",L()},m=(()=>{if(Y("os-segmented")&&Y("os-segment")){const $=document.createElement("os-segmented");$.setAttribute("value",i.mode),$.setAttribute("label","How to write the rule"),$.classList.add("atfb-valwin__tabs");for(const[W,j]of g){const ce=document.createElement("os-segment");ce.setAttribute("value",W),ce.textContent=j,$.append(ce)}return $.addEventListener("os-pick",W=>{const j=W.detail?.value;(j==="blocks"||j==="regex")&&($.setAttribute("value",j),h(j))}),$}const b=r("div",{class:"atfb-valwin__tabs",attrs:{role:"tablist"}}),M=()=>{b.replaceChildren(...g.map(([$,W])=>{const j=i.mode===$;return r("button",{class:`atfb-valwin__tab${j?" is-active":""}`,type:"button",text:W,attrs:{role:"tab","aria-selected":j?"true":"false"},on:{click:()=>{h($),M()}}})}))};return M(),b})();d.hidden=i.mode!=="blocks",f.hidden=i.mode!=="regex";const p=r("input",{class:"atfb-input",value:i.message,placeholder:"That is not in the expected format.",attrs:{type:"text"}});p.addEventListener("input",()=>{i.message=p.value});const x=r("p",{class:"atfb-valwin__summary",attrs:{"aria-live":"polite"}}),F=r("div",{class:"atfb-valwin__samples"}),S=b=>{const M=r("span",{class:"atfb-valwin__verdict",attrs:{"aria-live":"polite"}}),$=r("input",{class:"atfb-input",value:b,placeholder:"Type a sample answer…",attrs:{type:"text"}});$.addEventListener("input",()=>L()),F.append(r("div",{class:"atfb-valwin__sample",children:[$,M]}))};for(const b of i.tests.length?i.tests:["","",""])S(b);const H=()=>Array.from(F.querySelectorAll("input")).map(b=>b.value),L=()=>{const b=Bt(i);x.textContent=b||"Nothing yet — fill in a block above and the rule appears here in plain words.";for(const M of Array.from(F.querySelectorAll(".atfb-valwin__sample"))){const $=M.querySelector("input"),W=M.querySelector(".atfb-valwin__verdict");if(!$||!W)continue;const j=$.value===""?null:Mn(i,$.value);W.textContent=j===null?"·":j?"✓ passes":"✗ fails",W.classList.toggle("is-pass",j===!0),W.classList.toggle("is-fail",j===!1)}};n.append(r("p",{class:"atfb-hint",text:`Describe what a good answer to “${e.field.label||"this question"}” looks like — no code needed.`}),m,d,f,r("div",{class:"atfb-valwin__try",children:[r("h3",{text:"Try it out"}),x,F,C("Add another sample",()=>{S(""),L()},"ghost","plus-alt2")]}),w("When it fails, say",p,"Shown to the visitor when their answer breaks the rule. Leave empty for the default wording."),r("div",{class:"atfb-modal__actions",children:[C(a==="window"?"Close without saving":"Cancel",t),C("Save rule",()=>{const b=Ce(i);i.tests=H().filter(M=>M!=="").slice(0,10),s.saved=!0,e.onSave({pattern:b,recipe:i,message:i.message.trim()}),t()},"primary")]})),L()}const On=["Contact","Numbers & codes","Text shape","Web"],Wt=[{slug:"email",label:"An email address",group:"Contact",example:"jane@example.com",pattern:"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",message:"That does not look like an email address."},{slug:"phone",label:"A phone number",group:"Contact",example:"+34 612 345 678",pattern:"^(?=(?:[^0-9]*[0-9]){5,})\\+?[0-9 ().-]{5,24}$",message:"That does not look like a phone number."},{slug:"handle",label:"A username or @handle",group:"Contact",example:"@yourname",pattern:"^@?[A-Za-z0-9_]{2,30}$",message:"That does not look like a username."},{slug:"digits",label:"Numbers only",group:"Numbers & codes",example:"12345",pattern:"^[0-9]+$",message:"Numbers only, please."},{slug:"decimal",label:"A number, decimals allowed",group:"Numbers & codes",example:"3.14",pattern:"^-?[0-9]+([.,][0-9]+)?$",message:"That does not look like a number."},{slug:"price",label:"A price",group:"Numbers & codes",example:"19.99",pattern:"^[0-9]+([.,][0-9]{1,2})?$",message:"That does not look like a price."},{slug:"zip_us",label:"A ZIP code (US)",group:"Numbers & codes",example:"90210",pattern:"^[0-9]{5}(-[0-9]{4})?$",message:"That does not look like a ZIP code."},{slug:"postcode_uk",label:"A postcode (UK)",group:"Numbers & codes",example:"SW1A 1AA",pattern:"^[A-Za-z]{1,2}[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}$",message:"That does not look like a postcode."},{slug:"iban",label:"An IBAN",group:"Numbers & codes",example:"DE89 3704 0044 0532 0130 00",pattern:"^[A-Za-z]{2}[0-9]{2}(?: ?[A-Za-z0-9]){10,32}$",message:"That does not look like an IBAN."},{slug:"credit_card",label:"A card number",group:"Numbers & codes",example:"4242 4242 4242 4242",pattern:"^[0-9](?:[0-9 -]{9,21})?[0-9]$",message:"That does not look like a card number.",luhn:!0},{slug:"letters",label:"Letters only",group:"Text shape",example:"María López",pattern:"^[\\p{L}\\p{M} .'’-]+$",message:"Letters only, please."},{slug:"alphanumeric",label:"Letters and numbers only",group:"Text shape",example:"abc123",pattern:"^[A-Za-z0-9]+$",message:"Letters and numbers only, please."},{slug:"no_spaces",label:"One word, no spaces",group:"Text shape",example:"one-word",pattern:"^\\S+$",message:"No spaces allowed."},{slug:"url",label:"A web address",group:"Web",example:"https://example.com",pattern:"^(https?://)?([A-Za-z0-9-]+\\.)+[A-Za-z]{2,}([/?#]\\S*)?$",message:"That does not look like a web address."},{slug:"ip",label:"An IP address",group:"Web",example:"192.168.0.1",pattern:"^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",message:"That does not look like an IP address."},{slug:"slug",label:"A URL slug",group:"Web",example:"my-page-title",pattern:"^[a-z0-9]+(-[a-z0-9]+)*$",message:"Lowercase letters, numbers and dashes only."},{slug:"hex_color",label:"A hex colour",group:"Web",example:"#3366ff",pattern:"^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",message:"That does not look like a colour code."}];function Nn(n){return Wt.find(e=>e.slug===n)??null}function Xe(){return window.wp?.os??null}const Ut="allterrain-forms/preview",Ze="allterrain-forms-preview";function Rn(n){const e=Xe();if(!e?.registerTitleBarButton)return()=>{};const s=()=>{try{e.registerTitleBarButton({id:Ut,label:"Preview this form",icon:"dashicons-visibility",placement:"right",order:90,match:t=>{const a=t?.id??t?.config?.id??"";return a==="allterrain-forms"||a.startsWith("allterrain-forms#")},onClick:()=>void zt(n),owner:"allterrain-forms-builder"})}catch{}};return e.ready?e.ready(s):s(),()=>{try{e.unregisterTitleBarButton?.(Ut)}catch{}}}async function zt(n){n.isDirty()&&await n.save();const e=n.current();e&&Yt(e.id,e.title,e.previewUrl)}function Yt(n,e,s){const t=Xe();if(!t?.windowManager?.open){window.open(s,"_blank","noopener");return}t.windowManager.open({id:`${Ze}-${n}`,baseId:Ze,url:s,title:`Preview: ${e}`,icon:"dashicons-visibility"})}function Pn(n,e,s){if(!Xe()?.windowManager?.open||!document.querySelector(`[data-window-id="${Ze}-${n}"]`))return;const i=s.includes("?")?"&":"?";Yt(n,e,`${s}${i}alltfo_r=${Date.now()}`)}const se="allterrain-forms/field",Bn=["openstation/file","desktop-mode/file","openstation/attachment"],Vt="allterrain-forms/logic-map-v2";function J(n,e){return n.dataset.atfbBind=e,n}const Kt={level:{key:"level",label:"Heading level",control:"select",hint:"Headings should step down one at a time.",options:[{value:"2",label:"Heading 2"},{value:"3",label:"Heading 3"},{value:"4",label:"Heading 4"},{value:"5",label:"Heading 5"},{value:"6",label:"Heading 6"}]},content:{key:"content",label:"HTML",control:"textarea",hint:"Shown as written. Scripts are stripped when the form is saved."},consenttext:{key:"consentText",label:"What they are agreeing to",control:"textarea",hint:"Shown beside the tick box. Links are allowed."},height:{key:"height",label:"Height",control:"number",hint:"In pixels."},columns:{key:"columns",label:"Columns",control:"number",hint:"How many pictures sit side by side."},multiple:{key:"multiple",label:"Let them choose more than one",control:"checkbox"},inline:{key:"inline",label:"Lay the options out in a row",control:"checkbox"},other:{key:"other",label:"Offer an “Other” box",control:"checkbox",hint:"Adds a final option with a box to type in."},filetypes:{key:"filetypes",label:"Accepted file types",control:"commas",hint:"Extensions, separated by commas. Empty accepts anything the site allows."},maxsize:{key:"maxsize",label:"Largest file",control:"number",hint:"In megabytes."},maxfiles:{key:"maxfiles",label:"How many files",control:"number"},minrows:{key:"minRows",label:"Fewest rows",control:"number",also:{key:"maxRows",label:"Most rows"}},itemlabel:{key:"itemLabel",label:"What is one row called?",control:"text",hint:"Names each card — “Attendee 1”, “Attendee 2” — and the Remove button. Also editable on the card itself."},endlabels:{key:"minLabel",label:"Label at the low end",control:"text",also:{key:"maxLabel",label:"Label at the high end"}},points:{key:"points",label:"Points if correct",control:"number"},minchoices:{key:"minChoices",label:"Fewest they may pick",control:"number",also:{key:"maxChoices",label:"Most they may pick"}}},jn={label:"the canvas edits it in place, and the inspector mirrors it",placeholder:"edited by typing into the control on the canvas",hint:"edited under the control on the canvas",nextlabel:"edited on the page break’s own Next button",prevlabel:"edited on the page break’s own Back button",addlabel:"edited on the repeater’s own Add button",choices:"the choices editor, and the option list on the canvas",required:"the toggle on the card",width:"its own row",css:"its own row",prefill:"its own section",logic:"the conditional logic section",formula:"its own row, with the currency that goes with it",currency:"rendered with the formula",correct:"the choices editor marks the right answer",default:"its own row, typed to match what the field stores",rows:"a row count on a textarea; the statement list on a Likert matrix",parts:"a tick box per part, listed by the server",min:"the validation section, paired with max",max:"the validation section, paired with min",step:"the validation section",minlength:"the validation section, paired with maxlength",maxlength:"the validation section, paired with minlength",mindate:"the validation section, paired with maxdate",maxdate:"the validation section, paired with mindate",mintime:"the validation section, paired with maxtime",maxtime:"the validation section, paired with mintime",pattern:"the validation section",unique:"the validation section",maxchoices:"rendered with minchoices",maxrows:"rendered with minrows"};function Gt(n,e,s){const t=n[e.key],a=i=>s(e.key,i);if(e.control==="checkbox")return O(e.label,!!t,a);if(e.control==="commas"){const i=Array.isArray(t)?t:[];return w(e.label,T(i.join(", "),o=>{a(o.split(",").map(l=>l.trim().replace(/^\./,"").toLowerCase()).filter(Boolean))}),e.hint)}return e.control==="select"?w(e.label,D(String(t??""),e.options??[],a),e.hint):e.control==="textarea"?w(e.label,fe(String(t??""),a),e.hint):e.control==="number"?w(e.label,V(String(t??""),a),e.hint):w(e.label,J(T(String(t??""),a),e.key),e.hint)}function Xt(n,e){const s=new Set(n.map(a=>a.key).filter(Boolean));let t=n.length+1;return e.split(` +`).map(a=>a.trim()).filter(Boolean).map((a,i)=>{const o=n[i]?.key;if(o)return{key:o,label:a};for(;s.has(`r${t}`);)t+=1;return s.add(`r${t}`),{key:`r${t}`,label:a}})}function Zt(n,e,s){const t=n.findIndex(i=>i.id===e);if(t<0)return null;const a=Math.max(0,Math.min(s,n.length-1));return a===t?null:{from:t,to:a}}const Je=[{value:"user:email",label:"Their email address",group:"About the person filling it in",tag:"{user:email}"},{value:"user:display_name",label:"Their name",group:"About the person filling it in",tag:"{user:display_name}"},{value:"user:first_name",label:"Their first name",group:"About the person filling it in"},{value:"user:last_name",label:"Their last name",group:"About the person filling it in"},{value:"user:login",label:"Their username",group:"About the person filling it in"},{value:"date:today",label:"Today’s date",group:"The date and time",tag:"{date}"},{value:"date:now",label:"The time right now",group:"The date and time",tag:"{time}"},{value:"site",label:"This site’s name",group:"About this site",tag:"{site}"},{value:"site:url",label:"This site’s address",group:"About this site",tag:"{site:url}"},{value:"site:admin_email",label:"The site administrator’s email",group:"About this site",tag:"{admin_email}"}],Hn=["About the person filling it in","The date and time","About this site"],Qe=(n,e)=>U?.i18n?.[n]??e;class Jt{constructor(e){this.config=null,this.themes=[],this.forms=[],this.form=null,this.schema=null,this.selected=null,this.tab="build",this.logicMap=null,this.canvasTheme=r("style"),this.canvasThemeSignature="",this.openSections=new Map,this.logicMapOn=fs(Vt)!=="off",this.dirty=!1,this.editGeneration=0,this.saveInFlight=!1,this.queuedSave=null,this.teardowns=[],this.canvasTarget=null,this.history=[],this.historyAt=-1,this.autosave=Me(()=>{this.save(!0)},2500),this.renderInspector=ps(()=>{if(R(this.inspector),!this.schema||(this.root.classList.toggle("atfb--build-only-panes",this.tab!=="build"),this.tab!=="build"))return;const s=this.selected?this.locateField(this.selected):void 0,t=s?.field,a=s?.parent??null;if(this.root.classList.toggle("atfb--has-selection",!!t),!t){this.inspector.append(r("div",{class:"atfb-placeholder",children:[r("p",{text:"Select a field to change it."}),r("p",{class:"atfb-hint",text:"Drag a field from the palette, or press one to add it to the end."})]}));return}const i=this.config?.fieldTypes.find(c=>c.type===t.type),o=i?.supports??[],l=(c,d)=>{const u=this.liveField(t.id);u&&(u[c]=d,this.markDirty(),this.renderCanvas())};this.inspector.append(r("h3",{class:"atfb-inspector__title",text:i?.label??t.type})),a?this.inspector.append(r("p",{class:"atfb-hint atfb-inspector__crumb",text:`Inside ${a.label||"a repeater"} — the visitor answers this once per ${String(a.itemLabel??"")||"row"}.`}),r("p",{class:"atfb-hint",text:`Formulas aggregate it as {${a.id}.${t.id}} — e.g. sum( {${a.id}.${t.id}} ).`})):this.inspector.append(r("p",{class:"atfb-hint",text:`Reference this field as {field:${t.id}}`})),o.includes("label")&&this.inspector.append(w("Label",J(T(t.label,c=>l("label",c)),"label"))),o.includes("placeholder")&&this.inspector.append(w("Placeholder",J(T(t.placeholder,c=>l("placeholder",c)),"placeholder"))),o.includes("hint")&&this.inspector.append(w("Hint",J(T(t.hint,c=>l("hint",c)),"hint"),"Shown under the field, and read out with it.")),o.includes("nextlabel")&&this.inspector.append(w("Next button",J(T(String(t.nextLabel??""),c=>l("nextLabel",c)),"nextLabel"),"Leave empty for “Next”.")),o.includes("prevlabel")&&this.inspector.append(w("Back button",J(T(String(t.prevLabel??""),c=>l("prevLabel",c)),"prevLabel"),"Leave empty for “Back”.")),o.includes("addlabel")&&this.inspector.append(w("Add button",J(T(String(t.addLabel??""),c=>l("addLabel",c)),"addLabel"),"Leave empty for “Add another”.")),o.includes("required")&&this.inspector.append(O("Required",t.required,c=>l("required",c))),o.includes("width")&&this.inspector.append(w("Width",D(t.width,[{value:"full",label:"Full width"},{value:"two-thirds",label:"Two thirds"},{value:"half",label:"Half"},{value:"third",label:"One third"},{value:"quarter",label:"One quarter"}],c=>l("width",c)))),i?.choices&&this.inspector.append(this.renderChoicesEditor(t,l)),this.renderTypeSettings(t,i,o,l),(t.type==="total"||o.includes("formula"))&&this.inspector.append(w("Formula",r("div",{class:"atfb-formula__row",children:[Mt(T(String(t.formula??""),c=>l("formula",c)),this.schema?.fields??[],t.id),C("Formula editor",()=>kn({root:this.root,fields:this.schema?.fields??[],field:this.liveField(t.id)??t,onSave:c=>{l("formula",c),this.renderInspector()}}))]}),"Reference answers with braces — {f1} * {f2} + 10 — or open the editor and click them in."),w("Currency symbol",T(String(t.currency??""),c=>l("currency",c)))),t.type==="total"&&this.inspector.append(w("Display total as",D(String(t.display??"input"),[{value:"output",label:"Plain text"},{value:"input",label:"Disabled input"}],c=>l("display",c)))),this.inspector.append(this.renderValidationSection(t,o,l)),a||(this.inspector.append(this.renderLogicSection(t)),o.includes("prefill")&&this.inspector.append(this.prefillControl(t,l))),o.includes("css")&&this.inspector.append(w("CSS class",T(t.cssClass,c=>l("cssClass",c))))}),this.root=e,this.bar=e.querySelector("[data-atfb-bar]")??r("div"),this.palette=e.querySelector("[data-atfb-palette]")??r("div"),this.canvas=e.querySelector("[data-atfb-canvas]")??r("div"),this.inspector=e.querySelector("[data-atfb-inspector]")??r("div"),this.canvas.addEventListener("click",s=>{const t=s.target;if(!(this.tab!=="build"||!this.selected||t.closest("[data-atfb-card], button, os-button, a, input, textarea, select, os-select, label, [contenteditable]"))){this.selected=null;for(const a of this.canvas.querySelectorAll(".atfb-card.is-selected"))a.classList.remove("is-selected");this.renderInspector()}})}async start(){try{const[t,a,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);this.config=t,this.themes=a,this.forms=i}catch(t){this.fail(t);return}this.teardowns.push(os([se])),this.teardowns.push(Rn({current:()=>this.form?{id:this.form.id,title:this.form.title,previewUrl:this.form.previewUrl}:null,isDirty:()=>this.dirty,save:()=>this.save(!0)}));const e=t=>{this.dirty&&(t.preventDefault(),t.returnValue="")};window.addEventListener("beforeunload",e),this.teardowns.push(()=>window.removeEventListener("beforeunload",e));const s=t=>{!(t.metaKey||t.ctrlKey)||t.key.toLowerCase()!=="z"||t.target?.closest("input, textarea, [contenteditable]")||(t.preventDefault(),this.travel(t.shiftKey?1:-1))};if(this.root.addEventListener("keydown",s),this.teardowns.push(()=>this.root.removeEventListener("keydown",s)),this.renderBar(),this.renderPalette(),this.forms.length){const t=Ss("builder");await this.open(t&&this.forms.some(a=>a.id===t)?t:this.forms[0].id)}else this.renderFormsList()}destroy(){this.canvasTarget?.(),this.canvasTarget=null,this.teardowns.forEach(e=>e()),this.teardowns=[]}fail(e){R(this.bar),this.bar.append(r("p",{class:"atfb-error",text:e instanceof Error?e.message:"Something went wrong loading your forms."}))}renderBar(){R(this.bar);const e=D(String(this.form?.id??""),[...this.forms.map(a=>({value:String(a.id),label:a.title||"(untitled)"}))],a=>void this.open(Number(a)));e.setAttribute("aria-label","Choose a form");const s=r("input",{class:"atfb-title",type:"text",value:this.form?.title??"",placeholder:"Untitled form",attrs:{"aria-label":"Form title"},on:{input:a=>{this.form&&(this.form.title=a.target.value,this.markDirty())}}}),t=r("div",{class:"atfb-tabs",attrs:{role:"tablist"},children:[["build","Build"],["theme","Theme"],["settings","Settings"],["notify","Notifications"],["confirm","Confirmations"]].map(([a,i])=>r("button",{class:`atfb-tab${this.tab===a?" is-active":""}`,type:"button",text:i,attrs:{role:"tab","aria-selected":this.tab===a},on:{click:()=>{this.tab=a,this.renderBar(),this.renderInspector(),this.renderCanvas()}}}))});this.bar.append(r("div",{class:"atfb-bar__left",children:[this.forms.length>1?e:null,s]}),t,r("div",{class:"atfb-bar__right",children:[this.historyButton("undo","Undo",-1),this.historyButton("redo","Redo",1),C("New",()=>void this.showTemplates(),"secondary","plus-alt2"),C("Export",()=>void this.exportForm(),"secondary","download"),C("Import",()=>void this.importForm(),"secondary","upload"),C("Preview",()=>void this.preview(),"secondary","visibility"),C("Entries",()=>this.openEntries(),"secondary","list-view"),this.logicMapButton(),this.saveButton()]}))}liveField(e){return this.locateField(e)?.field}locateField(e){const s=this.schema?.fields??[];for(let t=0;tqueueMicrotask(()=>this.rebindCanvas()),{once:!0});return}if(this.canvas.matches(":hover")){this.canvas.addEventListener("pointerleave",()=>this.rebindCanvas(),{once:!0});return}this.renderCanvas()}snapshot(){if(!this.schema)return;const e=JSON.stringify(this.schema);this.history[this.historyAt]!==e&&(this.history=this.history.slice(0,this.historyAt+1),this.history.push(e),this.history.length>60&&this.history.shift(),this.historyAt=this.history.length-1,this.syncHistoryButtons())}travel(e){const s=this.historyAt+e;!this.schema||s<0||s>=this.history.length||(this.historyAt=s,this.schema=JSON.parse(this.history[s]),this.schema.fields.some(t=>t.id===this.selected)||(this.selected=null),this.markDirty(),this.renderBar(),this.renderCanvas(),this.renderInspector())}historyButton(e,s,t){const a=C(s,()=>this.travel(t),"secondary",e);return a.setAttribute("data-atfb-history",String(t)),a.disabled=!this.canTravel(t),a}canTravel(e){const s=this.historyAt+e;return s>=0&&sURL.revokeObjectURL(t),1e3)}async importForm(){const e=r("input",{type:"file",attrs:{accept:"application/json,.json"}});e.addEventListener("change",async()=>{const s=e.files?.[0];if(s)try{const t=JSON.parse(await s.text());if(!t.schema)throw new Error("That file does not contain a form.");const a=await I.createForm({title:t.title??s.name.replace(/\.json$/i,""),schema:t.schema});this.forms.unshift({id:a.id,title:a.title,status:a.status,modified:a.modified,fields:a.schema.fields.length,theme:a.schema.settings.theme,entries:0,unread:0,views:0,submissions:0,shortcode:a.shortcode}),this.form=a,this.schema=a.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot(),this.renderBar(),this.renderCanvas(),this.renderInspector(),N("Form imported",a.title)}catch(t){N("Could not import that file",t instanceof Error?t.message:"","error")}}),e.click()}saveButton(){const e=C("Save",()=>void this.save(),"primary");return e.disabled=!this.dirty,e.setAttribute("data-atfb-save",""),e}markDirty(){this.dirty=!0,this.editGeneration+=1;const e=this.bar.querySelector("[data-atfb-save]");e&&(e.disabled=!1),this.autosave()}async save(e=!1){if(!this.form||!this.schema)return;if(this.saveInFlight){this.queuedSave={silent:e&&(this.queuedSave?.silent??!0)};return}this.saveInFlight=!0;const s=this.editGeneration;try{const t=await I.updateForm(this.form.id,{title:this.form.title,schema:this.schema});if(s===this.editGeneration){this.form=t,this.schema=t.schema,this.dirty=!1,this.rebindCanvas();const i=this.bar.querySelector("[data-atfb-save]");i&&(i.disabled=!0)}Bs(t.id);const a=this.forms.find(i=>i.id===t.id);a&&(a.title=t.title),Pn(t.id,t.title,t.previewUrl),e||N("Form saved",t.title)}catch(t){N(Qe("saveFailed","Could not save"),t instanceof Error?t.message:"","error")}finally{this.saveInFlight=!1;const t=this.queuedSave;this.queuedSave=null,t&&this.save(t.silent)}}async openFormById(e){await this.open(e)}async open(e){if(!(this.dirty&&!await ie("You have unsaved changes. Discard them?"))){try{this.form=await I.getForm(e),this.schema=this.form.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot()}catch(s){this.fail(s);return}this.renderBar(),this.renderCanvas(),this.renderInspector(),this.announceIdentity()}}announceIdentity(){this.form&&Nt(this.root,An(this.form,U?.adminUrl??""))}async showTemplates(){if(!this.config)return;const e=r("div",{class:"atfb-overlay"}),s=i=>{i.key==="Escape"&&t()},t=()=>{e.remove(),document.removeEventListener("keydown",s)},a=r("div",{class:"atfb-templates",children:this.config.templates.map(i=>r("button",{class:"atfb-template",type:"button",on:{click:async()=>{t();try{const o=await I.createForm({template:i.slug});this.forms.unshift({id:o.id,title:o.title,status:o.status,modified:o.modified,fields:o.schema.fields.length,theme:o.schema.settings.theme,entries:0,unread:0,views:0,submissions:0,shortcode:o.shortcode}),this.form=o,this.schema=o.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot(),this.renderBar(),this.renderCanvas(),this.renderInspector(),this.announceIdentity()}catch(o){N("Could not create the form",o instanceof Error?o.message:"","error")}}},children:[B(i.icon),r("strong",{text:i.label}),r("span",{text:i.description})]}))});e.append(r("div",{class:"atfb-modal",attrs:{role:"dialog","aria-label":"Start a new form"},children:[r("h2",{text:"Start a new form"}),a,this.archivedFormsSection(t),r("div",{class:"atfb-modal__actions",children:[C("Cancel",t)]})]})),e.addEventListener("click",i=>{i.target===e&&t()}),document.addEventListener("keydown",s),this.root.append(e),a.querySelector("button")?.focus()}archivedFormsSection(e){const s=r("div",{class:"atfb-archived"});return I.listArchivedForms().then(t=>{t.length&&s.append(r("h3",{class:"atfb-archived__title",text:"Or bring one back from the archive"}),...t.map(a=>r("div",{class:"atfb-archived__row",children:[r("div",{class:"atfb-archived__meta",children:[r("strong",{text:a.title||"(untitled)"}),r("span",{class:"atfb-hint",text:`${a.entries} ${a.entries===1?"entry":"entries"} · ${a.submissions} submissions · ${a.views} views`})]}),C("Restore",async()=>{try{const i=await I.unarchiveForm(a.id);e(),this.forms.unshift(i),N("Form restored",`${i.title||"(untitled)"} is back, with its entries and stats.`),await this.open(i.id)}catch(i){N("Could not restore the form",i instanceof Error?i.message:"","error")}},"secondary","undo")]})))}).catch(()=>{}),s}renderFormsList(){R(this.canvas),this.canvas.append(r("div",{class:"atfb-empty",children:[r("h2",{text:"No forms yet"}),r("p",{text:"Start from a template, or build one from nothing."}),C("New form",()=>void this.showTemplates(),"primary","plus-alt2")]}))}openEntries(){const e=window.wp?.os;if(e?.openWindow){e.openWindow("allterrain-forms-entries");return}window.location.assign(`${U?.adminUrl??""}admin.php?page=allterrain-forms-entries`)}renderPalette(){if(!this.config)return;R(this.palette);const e=new Map;for(const t of this.config.fieldTypes){const a=e.get(t.group)??[];a.push(t),e.set(t.group,a)}const s=r("input",{class:"atfb-input atfb-palette__search",type:"search",placeholder:"Search fields",attrs:{"aria-label":"Search field types"},on:{input:t=>{const a=t.target.value.toLowerCase().trim();this.palette.querySelectorAll(".atfb-chip").forEach(i=>{const o=(i.textContent??"").toLowerCase();i.hidden=a!==""&&!o.includes(a)}),this.palette.querySelectorAll(".atfb-group").forEach(i=>{const o=Array.from(i.querySelectorAll(".atfb-chip")).some(l=>!l.hidden);i.hidden=!o})}}});this.palette.append(s);for(const[t,a]of Object.entries(this.config.groups)){const i=e.get(t);i?.length&&this.palette.append(r("div",{class:"atfb-group",children:[r("h3",{class:"atfb-group__title",text:a}),r("div",{class:"atfb-group__items",children:i.map(o=>this.paletteChip(o))})]}))}}paletteChip(e){const s=r("button",{class:"atfb-chip",type:"button",title:e.description,attrs:{"data-atf-type":e.type},children:[B(e.icon),r("span",{text:e.label})]});return s.addEventListener("pointerdown",t=>{const a=r("div",{class:"atfb-chip atfb-chip--ghost",children:[B(e.icon),r("span",{text:e.label})]});G().start({payload:Ae(se,s,{fieldType:e.type,isNew:!0},t,a),origin:t,onClickOnly:()=>this.addField(e.type)})}),s.addEventListener("click",t=>{G().recentlyEndedDrag()&&t.preventDefault()}),s}renderCanvas(){if(R(this.canvas),!this.schema||!this.form){this.renderFormsList();return}if(this.tab!=="build"){this.canvas.append(this.renderTabCanvas());return}const e=r("div",{class:"atfb-canvas__list",attrs:{"data-atfb-list":""}});this.schema.fields.length||e.append(r("div",{class:"atfb-placeholder",text:Qe("emptyCanvas","Drag a field from the left to begin.")})),this.schema.fields.forEach((t,a)=>{e.append(this.renderFieldCard(t,a))});const s=r("div",{class:"atfb-canvas__inner",children:[r("p",{class:"atfb-shortcode",text:this.form.shortcode,title:"Paste this anywhere to place the form"}),e]});this.canvas.append(s),this.registerCanvasTarget(e),this.paintLogicMap(s),this.paintCanvasTheme()}prefillControl(e,s){const t=e.prefill.startsWith("query:"),a=Je.some(g=>g.value===e.prefill),i=t?"query":a&&e.prefill||(e.prefill?"custom":""),o=r("div",{class:"atfb-prefill__detail"}),l=r("p",{class:"atfb-row__hint atfb-prefill__preview"}),c=g=>{if(o.replaceChildren(),l.replaceChildren(),g==="query"){const h=e.prefill.startsWith("query:")?e.prefill.slice(6):"";o.append(T(h,y=>{const m=y.trim();s("prefill",m?`query:${m}`:""),d(`query:${m}`)},"utm_source"),r("p",{class:"atfb-row__hint",text:"The name of the parameter in the link people arrive on."}))}g==="custom"&&o.append(T(e.prefill,h=>{s("prefill",h),d(h)},"myplugin:something"),r("p",{class:"atfb-row__hint",text:"For a source another plugin has added through alltfo_resolve_prefill."})),d(e.prefill)},d=g=>{if(l.replaceChildren(),!g)return;if(g.startsWith("query:")){const y=g.slice(6);y&&(l.textContent=`A visit to …/your-page/?${y}=abc opens the form with “abc” in it.`);return}const h=Je.find(y=>y.value===g)?.tag;h&&ft(this.form?.id??0).then(y=>{for(const m of y)for(const p of m.items)if(p.tag===h){const x=g.startsWith("user:");if(!p.sample){l.textContent="Empty unless the visitor is signed in.";return}l.textContent=x?`Opens with “${p.sample}” for you — empty for a visitor who is not signed in.`:`Opens with “${p.sample}”.`;return}})};c(i);const u=r("select",{class:"atfb-input atfb-select",on:{change:g=>{const h=g.target.value;s("prefill",h==="query"||h==="custom"?"":h),c(h)}}});u.append(r("option",{value:"",text:"Nothing — leave it empty",attrs:{selected:i===""}}));for(const g of Hn){const h=document.createElement("optgroup");h.label=g;for(const y of Je.filter(m=>m.group===g))h.append(r("option",{value:y.value,text:y.label,attrs:{selected:y.value===i}}));u.append(h)}const f=document.createElement("optgroup");return f.label="From the link they arrived on",f.append(r("option",{value:"query",text:"A parameter in the web address",attrs:{selected:i==="query"}})),u.append(f,r("option",{value:"custom",text:"Something else (advanced)",attrs:{selected:i==="custom"}})),w("Pre-fill this with",r("div",{class:"atfb-prefill",children:[u,o,l]}),"What the box already contains when the form opens. They can still change it.")}renderCondition(e,s){const t=s.some(l=>l.kind==="field"&&l.missing),a=r("div",{class:`atfb-cond${t?" is-broken":""}`,attrs:{"aria-label":s.length?qe(s):"Conditional rules"}});a.append(r("div",{class:"atfb-cond__heading",children:[r("span",{class:"atfb-cond__label",children:[B("randomize"),"Conditions"]}),this.copyConditionButton(`field:${e.id}`)]})),e.logic.rules.forEach((l,c)=>{const d=be(l,this.schema?.fields??[],c),u=r("button",{class:"atfb-cond__delete",type:"button",title:"Delete this rule",attrs:{"aria-label":`Delete rule ${c+1}`},children:[B("trash")],on:{click:()=>{this.snapshot(),this.editCondition(e.id,f=>{f.rules.splice(c,1)},!0,`${e.id}:add`),this.snapshot()}}});a.append(r("div",{class:"atfb-cond__rule",children:[c===0?this.renderConditionToken(e,{kind:"verb",text:e.logic.action==="hide"?"Hidden when":"Shown when"}):this.renderConditionToken(e,{kind:"join",text:e.logic.match==="all"?"and":"or"}),...d.map(f=>this.renderConditionToken(e,f,c)),u]}))}),e.logic.rules.length||a.append(r("span",{class:"atfb-hint",text:"No rules yet. Add one or copy a condition."}));const i=r("button",{class:"atfb-cond__add",type:"button",text:"+ Add rule",title:"Add rule",attrs:{"aria-label":"Add rule","data-cond":`${e.id}:add`},on:{click:()=>this.addConditionRule(e.id)}}),o=r("button",{class:"atfb-cond__clear",type:"button",text:"Clear",title:"Delete all rules",attrs:{"aria-label":"Clear all rules",disabled:!e.logic.rules.length},on:{click:()=>{this.snapshot(),this.editCondition(e.id,l=>{l.rules=[]},!0,`${e.id}:add`),this.snapshot()}}});return a.append(r("div",{class:"atfb-cond__actions",children:[i,o]})),a.addEventListener("pointerdown",l=>l.stopPropagation()),a.addEventListener("click",l=>l.stopPropagation()),a.addEventListener("keydown",l=>l.stopPropagation()),a}editCondition(e,s,t=!0,a=""){const i=this.liveField(e)?.logic;if(i){if(s(i),this.markDirty(),!t){this.logicMap?.setEdges(ge(this.schema?.fields??[]));return}this.renderCanvas(),this.renderInspector(),a&&window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-cond="${CSS.escape(a)}"]`)?.focus()})}}condSelect(e,s,t,a,i){if(Y("os-select")&&Y("os-option")){const o=document.createElement("os-select");o.setAttribute("value",e),o.setAttribute("aria-label",a),o.setAttribute("data-cond",t),o.className="atfb-cond__control",o.setAttribute("plain",""),o.title=a;for(const l of s){const c=document.createElement("os-option");c.setAttribute("value",l.value),l.disabled&&c.setAttribute("disabled",""),c.textContent=l.label,o.append(c)}return o.addEventListener("os-pick",l=>{i(String(l.detail?.value??""))}),o}return r("select",{class:"atfb-cond__control atfb-cond__control--native",title:a,attrs:{"aria-label":a,"data-cond":t},on:{change:o=>i(o.target.value)},children:s.map(o=>r("option",{value:o.value,text:o.label,attrs:{selected:o.value===e,disabled:o.disabled}}))})}renderConditionToken(e,s,t=0){if(s.kind==="field"){const a=`${e.id}:source:${t}`,i=(this.schema?.fields??[]).filter(o=>o.id!==e.id&&o.type!=="page_break");return this.condSelect(s.fieldId,[...s.missing?[{value:s.fieldId,label:"Choose a question…"}]:[],...i.map(o=>({value:o.id,label:o.label||o.id}))],a,"Question used by this rule",o=>this.editCondition(e.id,l=>{const c=l.rules[t];c&&(c.field=o,c.value="")},!0,a))}if(s.kind==="verb")return r("button",{class:"atfb-cond__verb",type:"button",text:s.text,title:"Switch between showing and hiding this field when the condition matches.",attrs:{"data-cond":`${e.id}:verb`},on:{click:()=>this.editCondition(e.id,a=>{a.action=a.action==="hide"?"show":"hide"},!0,`${e.id}:verb`)}});if(s.kind==="join")return r("button",{class:"atfb-cond__join",type:"button",text:s.text,title:"Switch between needing every rule (and) or any one of them (or).",attrs:{"data-cond":`${e.id}:join`},on:{click:()=>this.editCondition(e.id,a=>{a.match=a.match==="all"?"any":"all"},!0,`${e.id}:join`)}});if(s.kind==="operator"){const a=`${e.id}:op:${s.ruleIndex}`;return this.condSelect(s.operator,Object.entries(Ie).map(([i,o])=>({value:i,label:o})),a,"How the answer is compared",i=>this.editCondition(e.id,o=>{const l=o.rules[s.ruleIndex];l&&(l.operator=i)},!0,a))}return s.kind==="value"?this.renderConditionValue(e,s):r("span")}renderConditionValue(e,s){const t=`${e.id}:value:${s.ruleIndex}`,a=this.schema?.fields.find(d=>d.id===s.sourceId),i=(d,u)=>this.editCondition(e.id,f=>{const g=f.rules[s.ruleIndex];g&&(g.value=d)},u,t),o=it(a,s.raw,this.config?.countries);if(o){const d=this.condSelect(s.raw,o,t,"The answer that triggers this",u=>i(u,!0));return d.classList.add("atfb-cond__value-select"),d.removeAttribute("plain"),d}const l=["number","range","scale","rating","total"].includes(a?.type??""),c=r("input",{class:"atfb-cond__chip atfb-cond__chip--value atfb-cond__value",value:s.raw,title:"The answer that triggers this. Edit it here.",attrs:{type:"text","aria-label":"The answer that triggers this","data-cond":t,inputmode:l?"decimal":void 0,size:String(Math.max(2,Math.min(24,s.raw.length||2)))}});return c.addEventListener("input",()=>{c.size=Math.max(2,Math.min(24,c.value.length||2)),i(c.value,!1)}),c.addEventListener("change",()=>i(c.value,!0)),c.addEventListener("keydown",d=>{d.key==="Enter"&&(d.preventDefault(),i(c.value,!0))}),c}section(e,s,t,a=!1){const i=r("details",{class:"atfb-section",attrs:{open:this.openSections.get(e)??a},children:[r("summary",{text:s}),...t]});return i.addEventListener("toggle",()=>this.openSections.set(e,i.open)),i}logicMapButton(){const e=ge(this.schema?.fields??[]).length>0,s=C(this.logicMapOn?"Hide logic":"Show logic",()=>{this.logicMapOn=!this.logicMapOn,ms(Vt,this.logicMapOn?"on":"off"),this.renderBar(),this.renderCanvas()},this.logicMapOn?"primary":"secondary","randomize");return s.title="Draw a line from each question to the ones it decides.",s.hidden=!e,s}paintLogicMap(e){this.logicMap?.destroy(),this.logicMap=null;const s=this.schema?.fields??[],t=ge(s);if(!t.length||!this.logicMapOn)return;e.classList.add("has-logicmap");const a=new As(e);a.setEdges(t),a.highlight(this.selected??""),this.logicMap=a,e.addEventListener("pointerover",i=>{const o=i.target.closest("[data-atfb-card]");a.highlight(o?.dataset.atfbCard??this.selected??"")}),e.addEventListener("pointerleave",()=>a.highlight(this.selected??""))}renderFieldCard(e,s){const t=this.config?.fieldTypes.find(d=>d.type===e.type),a=this.selected===e.id,i=this.schema?.fields??[],o=Es(e,i),l=$s(i).get(e.id)??0,c=r("div",{class:`atfb-card${a?" is-selected":""}`,attrs:{"data-atfb-card":e.id,"data-index":s,tabindex:"0",role:"button","aria-pressed":a,"aria-label":`${e.label||t?.label||e.type}, ${s+1} of ${this.schema?.fields.length??0}`},children:[r("div",{class:"atfb-card__bar",children:[r("div",{class:"atfb-card__grip",attrs:{"aria-hidden":"true"},children:[B("menu")]}),r("div",{class:"atfb-card__head",children:[B(t?.icon??"dashicons-forms"),r("span",{class:"atfb-card__type",text:t?.label??e.type}),this.requiredToggle(e),e.type!=="page_break"?this.conditionToolbar(e):null,l?r("span",{class:"atfb-badge atfb-badge--controls",text:l===1?"controls 1 field":`controls ${l} fields`,title:"Other questions appear or disappear based on this answer."}):null]}),r("div",{class:"atfb-card__actions",children:[this.cardAction("admin-page","Duplicate",()=>this.duplicateField(e.id)),this.cardAction("trash","Delete",()=>void this.deleteField(e.id))]})]}),r("div",{class:"atfb-card__body",children:[pt(e,t,{edit:d=>{const u=this.liveField(e.id);if(!u)return;d(u),this.markDirty(),this.syncInspector(u);const f=this.selected?this.locateField(this.selected):void 0;f?.parent&&f.parent.id===u.id&&this.syncInspector(f.field)},restructure:d=>{const u=this.liveField(e.id);u&&(this.snapshot(),d(u),this.markDirty(),this.renderCanvas(),this.renderInspector())},types:d=>this.config?.fieldTypes.find(u=>u.type===d),selectedId:this.selected}),e.logic.enabled?this.renderCondition(e,o):null]})]});return c.addEventListener("click",d=>{d.target.closest(".atfb-card__actions")||G().recentlyEndedDrag()||this.selectField(e.id)}),c.addEventListener("keydown",d=>{if(d.key==="Enter"||d.key===" "){d.preventDefault(),this.selectField(e.id);return}d.altKey&&(d.key==="ArrowUp"||d.key==="ArrowDown")&&(d.preventDefault(),this.moveField(e.id,d.key==="ArrowUp"?s-1:s+1),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-card="${CSS.escape(e.id)}"]`)?.focus()})),(d.key==="Delete"||d.key==="Backspace")&&(d.preventDefault(),this.deleteField(e.id))}),c.addEventListener("pointerdown",d=>{d.target.closest(".atfb-card__actions")||G().start({payload:Ae(se,c,{fieldId:e.id,field:e,isNew:!1},d),origin:d})}),c}addConditionRule(e){this.snapshot(),this.editCondition(e,s=>{const t=this.schema?.fields.find(a=>a.id!==e&&a.type!=="page_break");s.rules.push({field:t?.id??"",operator:"is",value:""})},!0,`${e}:source:${this.liveField(e)?.logic.rules.length??0}`),this.snapshot()}conditionToolbar(e){const s=r("button",{class:`atfb-req atfb-condition-toggle${e.logic.enabled?" is-on":""}`,type:"button",title:e.logic.enabled?"Edit conditional logic":"Set up conditional logic",attrs:{"aria-haspopup":"dialog","data-cond":`${e.id}:enabled`},children:[r("span",{class:"atfb-condition-dot",attrs:{"aria-hidden":"true"}}),r("span",{text:"Conditional"})],on:{click:()=>this.openConditionEditor(e.id)}});for(const t of["pointerdown","click","keydown"])s.addEventListener(t,a=>a.stopPropagation());return s}openConditionEditor(e){const s=this.liveField(e);if(!s)return;const t=s.logic.rules.length>0,a={...s.logic,enabled:!0,rules:s.logic.rules.map(u=>({...u}))},i=r("div",{class:"atfb-overlay"}),o=r("div",{class:"atfb-modal atfb-condition-editor",attrs:{role:"dialog","aria-modal":"true","aria-label":"Conditional logic",tabindex:"-1"}}),l=()=>{i.remove(),this.root.querySelector(`[data-cond="${CSS.escape(e)}:enabled"]`)?.focus()},c="button:not([disabled]), input, select, os-select, os-checkbox-label, os-button:not([disabled])",d=()=>{const u=[...o.querySelectorAll(c)].indexOf(document.activeElement),f=(m,p=!1)=>{m(a),p&&d()},g=D(a.action,[{value:"show",label:"Show"},{value:"hide",label:"Hide"}],m=>{a.action=m});g.setAttribute("aria-label","Conditional action");const h=D(a.match,[{value:"all",label:"all"},{value:"any",label:"any"}],m=>{a.match=m,d()});h.setAttribute("aria-label","Match rules");const y=r("button",{class:"atfb-button atfb-copy-condition",type:"button",children:[B("admin-page"),r("span",{text:"Copy condition"})],on:{click:()=>Dt({root:i,to:`field:${e}`,schema:()=>this.schema?{...this.schema,fields:this.schema.fields.map(m=>m.id===e?{...m,logic:a}:m)}:null,onCopy:()=>{a.enabled=!0,d(),o.focus()}})}});if(o.replaceChildren(r("div",{class:"atfb-condition-editor__heading",children:[r("span",{class:"atfb-condition-editor__icon",children:[B("randomize")]}),r("div",{children:[r("h2",{text:"Conditional logic"}),r("p",{text:s.label||"Untitled field"})]})]}),r("p",{class:"atfb-hint",text:"Choose when this field appears in your form."}),r("div",{class:"atfb-condition-editor__sentence",children:[g,"this field when",h,"of these rules match:"]}),...this.logicRulesEditor(a,f,e),r("div",{class:"atfb-condition-editor__footer",children:[y,r("div",{class:"atfb-modal__actions",children:[C("Clear",()=>{this.snapshot(),this.editCondition(e,m=>Object.assign(m,{enabled:!1,action:"show",match:"all",rules:[]})),this.snapshot(),l()}),...t||a.rules.length?[C("Cancel",l)]:[],C("Save conditions",()=>{if(!this.liveField(e)||!a.rules.length){l();return}this.snapshot(),this.editCondition(e,m=>Object.assign(m,a,{rules:a.rules.map(p=>({...p}))})),this.snapshot(),l()},"primary")]})]})),a.rules.length||o.querySelector(".atfb-button--primary")?.setAttribute("disabled",""),u>=0){const m=o.querySelectorAll(c);m[Math.min(u,m.length-1)]?.focus()}};i.append(o),i.addEventListener("click",u=>{u.target===i&&l()}),i.addEventListener("keydown",u=>{if(u.key==="Escape"&&(u.preventDefault(),l()),u.key==="Tab"){const f=[...o.querySelectorAll(c)],g=f[0],h=f[f.length-1];u.shiftKey&&(document.activeElement===g||document.activeElement===o)?(u.preventDefault(),h?.focus()):!u.shiftKey&&document.activeElement===h&&(u.preventDefault(),g?.focus())}u.stopPropagation()}),this.root.append(i),d(),o.focus()}requiredToggle(e){return r("button",{class:`atfb-req${e.required?" is-on":""}`,type:"button",text:e.required?"Required":"Optional",title:e.required?"This must be answered. Click to make it optional.":"Click to make this required.",attrs:{"aria-pressed":e.required?"true":"false"},on:{pointerdown:t=>t.stopPropagation(),click:t=>{t.stopPropagation(),e.required=!e.required,this.markDirty(),this.renderCanvas(),this.renderInspector()}}})}cardAction(e,s,t){return r("button",{class:"atfb-card__action",type:"button",title:s,attrs:{"aria-label":s},on:{click:a=>{a.stopPropagation(),t()}},children:[B(e)]})}gapAnimator(e,s,t,a){const i=r("div",{class:"atfb-marker",attrs:{"aria-hidden":"true"}});let o=null,l=null,c=0;const d=()=>{i.remove(),l?.classList.remove("atfb-lifted"),l=null,o=null},u=h=>{const y=Array.from(e.querySelectorAll(s)),m=new Map(y.filter(x=>!x.classList.contains("atfb-lifted")).map(x=>[x,x.getBoundingClientRect().top]));h();for(const x of y)x.style.transition="none",x.style.transform="";const p=y.filter(x=>{const F=m.get(x);if(F===void 0||!x.isConnected||x.classList.contains("atfb-lifted"))return!1;const S=F-x.getBoundingClientRect().top;return Math.abs(S)<.5?!1:(x.style.transform=`translateY(${S}px)`,!0)});e.offsetHeight;for(const x of y){if(!p.includes(x)){x.style.transition="";continue}x.style.transition="transform 160ms ease",x.style.transform="",x.addEventListener("transitionend",()=>{x.style.transition=""},{once:!0})}},f=h=>{const y=h.detail;if(y?.payload?.type!==se||!e.classList.contains("is-dropping")||a&&!a(y.payload.data??{}))return;const m=y.payload.data?.fieldId,p=typeof m=="string"?t(m):null,x=st(e,s,y.clientY??0,p??void 0);x===o&&i.isConnected||(o=x,u(()=>{p&&p!==l&&(l?.classList.remove("atfb-lifted"),p.classList.add("atfb-lifted"),l=p),i.style.blockSize=`${Math.max(8,Math.round(c))}px`;const F=Array.from(e.querySelectorAll(s)).filter(S=>S!==p);x>=F.length?e.append(i):F[x].before(i)}))},g=()=>{e.classList.remove("is-dropping"),window.setTimeout(()=>u(d),0)};return document.addEventListener("os.drag.move",f),document.addEventListener("os.drag.end",g),{enter:h=>{const y=h?t(h):null;c=y&&!y.classList.contains("atfb-lifted")?y.getBoundingClientRect().height:c||44},leave:()=>u(d),drop:(h,y)=>{const m=o??st(e,s,h,y??void 0);return d(),m},teardown:()=>{document.removeEventListener("os.drag.move",f),document.removeEventListener("os.drag.end",g),d()}}}registerCanvasTarget(e){this.canvasTarget?.(),this.canvasTarget=null;const s=this.gapAnimator(e,".atfb-card",i=>this.canvas.querySelector(`[data-atfb-card="${CSS.escape(i)}"]`)),t=G().registerDropTarget({id:`atfb-canvas-${this.form?.id??0}`,element:e,accept:i=>i.type===se,onEnter:i=>{e.classList.add("is-dropping"),s.enter(i.payload.data.fieldId)},onLeave:()=>{e.classList.remove("is-dropping"),s.leave()},onDrop:(i,o)=>{e.classList.remove("is-dropping");const l=i.payload.data,c=l.fieldId?this.canvas.querySelector(`[data-atfb-card="${CSS.escape(l.fieldId)}"]`):null,d=s.drop(o.clientY,c);if(l.isNew&&l.fieldType){this.addField(l.fieldType,d);return}if(l.fieldId&&this.locateField(l.fieldId)){this.relocateField(l.fieldId,null,d);return}l.field&&this.insertField({...l.field,id:""},d)}}),a=this.wireRepeaterZones(e);this.canvasTarget=()=>{t(),a.forEach(i=>i()),s.teardown()}}wireRepeaterZones(e){const s=[];return e.querySelectorAll("[data-atfb-repeater-zone]").forEach(t=>{const a=t.dataset.atfbRepeaterZone??"",i=l=>{const c=l;if(c.fieldId===a)return!1;const d=c.isNew?c.fieldType:this.locateField(c.fieldId??"")?.field.type??c.field?.type;return!!d&&this.allowedInRepeater(d)},o=this.gapAnimator(t,".atfb-subcard",l=>e.querySelector(`[data-atfb-subfield="${CSS.escape(l)}"]`),i);s.push(()=>o.teardown()),s.push(G().registerDropTarget({id:`atfb-repzone-${this.form?.id??0}-${a}`,element:t,accept:l=>l.type===se&&i(l.data),onEnter:l=>{t.classList.add("is-dropping"),o.enter(l.payload.data.fieldId)},onLeave:()=>{t.classList.remove("is-dropping"),o.leave()},onDrop:(l,c)=>{t.classList.remove("is-dropping");const d=l.payload.data,u=d.fieldId?e.querySelector(`[data-atfb-subfield="${CSS.escape(d.fieldId)}"]`):null,f=o.drop(c.clientY,u);if(d.isNew&&d.fieldType){this.addFieldToRepeater(d.fieldType,a,f);return}if(d.fieldId&&this.locateField(d.fieldId)){this.relocateField(d.fieldId,a,f);return}d.field&&this.insertFieldIntoRepeater({...d.field,id:""},a,f)}})),t.querySelectorAll(".atfb-subcard").forEach(l=>{const c=l.dataset.atfbSubfield??"";l.addEventListener("click",d=>{d.target.closest(".atfb-preview__remove")||(d.stopPropagation(),!G().recentlyEndedDrag()&&this.selectField(c))}),l.addEventListener("keydown",d=>{if(d.stopPropagation(),d.key==="Enter"||d.key===" "){d.preventDefault(),this.selectField(c);return}if(d.altKey&&(d.key==="ArrowUp"||d.key==="ArrowDown")){d.preventDefault();const u=this.locateField(c);u&&(this.relocateField(c,a,d.key==="ArrowUp"?u.index-1:u.index+1),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-subfield="${CSS.escape(c)}"]`)?.focus()}));return}(d.key==="Delete"||d.key==="Backspace")&&(d.preventDefault(),this.deleteField(c))}),l.addEventListener("pointerdown",d=>{if(d.stopPropagation(),d.target.closest(".atfb-preview__remove"))return;const u=this.locateField(c);u&&G().start({payload:Ae(se,l,{fieldId:c,parentId:a,field:u.field,isNew:!1},d),origin:d})})})}),s}addField(e,s){const t=this.buildField(e);t&&this.insertField(t,s)}buildField(e){const s=this.config?.fieldTypes.find(a=>a.type===e);return!s||!this.schema?void 0:{id:this.nextFieldId(),type:e,label:s.input?s.label:"",placeholder:"",hint:"",required:!1,width:"full",cssClass:"",default:"",choices:s.choices?[{label:"First choice",value:"first"},{label:"Second choice",value:"second"}]:[],logic:{enabled:!1,action:"show",match:"all",rules:[]},messages:{},prefill:"",...s.settings}}allowedInRepeater(e){const s=this.config?.fieldTypes.find(t=>t.type===e);return!s||!s.input?!1:!["repeater","page_break","file","signature","total"].includes(e)}addFieldToRepeater(e,s,t){if(!this.allowedInRepeater(e))return;const a=this.buildField(e);a&&this.insertFieldIntoRepeater(a,s,t)}insertFieldIntoRepeater(e,s,t){const a=this.liveField(s);if(!this.schema||!a||a.type!=="repeater")return;e.id||(e.id=this.nextFieldId()),this.snapshot(),Array.isArray(a.fields)||(a.fields=[]);const i=a.fields,o=t===void 0?i.length:Math.max(0,Math.min(t,i.length));i.splice(o,0,e),this.selected=e.id,this.markDirty(),this.renderCanvas(),this.renderInspector(),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-subfield="${CSS.escape(e.id)}"]`)?.focus()})}relocateField(e,s,t){if(!this.schema)return;const a=this.locateField(e);if(!a)return;if(!a.parent&&!s){this.moveField(e,t);return}const i=s?this.liveField(s):null;if(s&&(!i||i.type!=="repeater"||e===s))return;i&&!Array.isArray(i.fields)&&(i.fields=[]);const o=i?i.fields:this.schema.fields;this.snapshot(),a.list.splice(a.index,1);const l=Math.max(0,Math.min(t,o.length));o.splice(l,0,a.field),this.selected=a.field.id,this.markDirty(),this.renderCanvas(),this.renderInspector()}insertField(e,s){if(!this.schema)return;e.id||(e.id=this.nextFieldId()),this.snapshot();const t=s===void 0?this.schema.fields.length:Math.max(0,Math.min(s,this.schema.fields.length));this.schema.fields.splice(t,0,e),this.selected=e.id,this.markDirty(),this.renderCanvas(),this.renderInspector(),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-card="${CSS.escape(e.id)}"]`)?.focus()})}moveField(e,s){if(!this.schema)return;const t=Zt(this.schema.fields,e,s);if(!t)return;this.snapshot();const[a]=this.schema.fields.splice(t.from,1);this.schema.fields.splice(t.to,0,a),this.markDirty(),this.renderCanvas()}duplicateField(e){if(!this.schema)return;const s=this.locateField(e);if(!s)return;const t=JSON.parse(JSON.stringify(s.field)),a=this.usedFieldIds(),i=()=>{let o=a.size+1;for(;a.has(`f${o}`);)o++;const l=`f${o}`;return a.add(l),l};t.id=i();for(const o of t.fields??[])o.id=i();if(s.parent){this.snapshot(),s.list.splice(s.index+1,0,t),this.selected=t.id,this.markDirty(),this.renderCanvas(),this.renderInspector();return}this.insertField(t,s.index+1)}async deleteField(e){if(!this.schema)return;const s=this.locateField(e);if(!s)return;const t=this.schema.fields.filter(i=>i.logic?.rules?.some(o=>o.field===e)),a=t.length?`Delete this field? ${t.length} other field${t.length===1?"":"s"} use it in a condition, and those conditions will stop working.`:Qe("confirmDelete","Delete this? It cannot be undone.");await ie(a,"Delete field")&&(this.snapshot(),s.list.splice(s.index,1),this.selected===e&&(this.selected=null),this.markDirty(),this.renderCanvas(),this.renderInspector())}selectField(e){this.selected=e;for(const s of this.canvas.querySelectorAll("[data-atfb-card]")){const t=s.dataset.atfbCard===e;s.classList.toggle("is-selected",t),s.setAttribute("aria-pressed",t?"true":"false")}for(const s of this.canvas.querySelectorAll("[data-atfb-subfield]"))s.classList.toggle("is-selected",s.dataset.atfbSubfield===e);this.logicMap?.highlight(e),this.renderInspector()}nextFieldId(){const e=this.usedFieldIds();let s=e.size+1;for(;e.has(`f${s}`);)s++;return`f${s}`}usedFieldIds(){const e=new Set;for(const s of this.schema?.fields??[]){e.add(s.id);for(const t of s.fields??[])e.add(t.id)}return e}nextEntryId(e,s){const t=new Set(s.map(i=>i.id));let a=s.length+1;for(;t.has(`${e}${a}`);)a++;return`${e}${a}`}renderTypeSettings(e,s,t,a){for(const i of t){const o=Kt[i];o&&(this.inspector.append(Gt(e,o,a)),o.also&&this.inspector.append(Gt(e,{...o,key:o.also.key,label:o.also.label,hint:o.also.hint},a)))}t.includes("rows")&&e.type!=="likert"&&this.inspector.append(w("Lines tall",V(String(e.rows??""),i=>a("rows",i)))),t.includes("rows")&&e.type==="likert"&&this.inspector.append(this.renderStatementList(e,a)),t.includes("parts")&&this.inspector.append(this.renderPartsEditor(e,s,a)),t.includes("default")&&!["files","object"].includes(s?.value??"")&&this.inspector.append(this.renderDefaultControl(e,s,a))}renderStatementList(e,s){const t=Array.isArray(e.rows)?e.rows:[];return w("Statements",fe(t.map(a=>a.label??"").join(` +`),a=>s("rows",Xt(t,a)),5),"One per line. Each becomes a row of the matrix.")}renderPartsEditor(e,s,t){const a=s?.parts??[],i=Array.isArray(e.parts)?e.parts:a.map(l=>l.key),o=a.map(l=>O(l.label,i.includes(l.key),c=>{const d=a.map(u=>u.key).filter(u=>u===l.key?c:i.includes(u));t("parts",d.length?d:[l.key])}));return r("div",{class:"atfb-section",children:[r("h4",{class:"atfb-section__title",text:"Parts to ask for"}),...o]})}renderDefaultControl(e,s,t){const a="Filled in before they start. They can change it.";return e.type==="switch"||e.type==="consent"?O("On by default",!!e.default,i=>t("default",i)):s?.choices&&(e.choices??[]).length?w("Default answer",D(String(e.default??""),[{value:"",label:"Nothing chosen"},...(e.choices??[]).map(i=>({value:String(i.value),label:i.label||String(i.value)}))],i=>t("default",i)),a):w("Default answer",T(String(e.default??""),i=>t("default",i)),a)}renderChoicesEditor(e,s){const t=e.choices??[],a=o=>this.liveField(e.id)?.choices?.[o],i=r("div",{class:"atfb-choices"});return t.forEach((o,l)=>{const c=r("div",{class:"atfb-choice-row",children:[e.type==="image_choice"?this.choiceImageWell(o,l,e):null,J(T(o.label,d=>{const u=a(l);if(!u)return;const f=!u.value||u.value===u.label;u.label=d,f&&(u.value=d),this.markDirty();const g=this.liveField(e.id);g&&this.syncCanvas(g)}),`choice:${l}:label`),J(T(o.value,d=>{const u=a(l);u&&(u.value=d,this.markDirty())},"value"),`choice:${l}:value`),e.type==="quiz"||o.points!==void 0?V(String(o.points??""),d=>{const u=a(l);u&&(u.points=d===""?void 0:Number(d),this.markDirty())}):V(String(o.price??""),d=>{const u=a(l);u&&(u.price=d===""?void 0:Number(d),this.markDirty())}),r("button",{class:"atfb-card__action",type:"button",attrs:{"aria-label":`Remove ${o.label}`},on:{click:()=>{const d=this.liveField(e.id);d&&((d.choices??[]).splice(l,1),s("choices",d.choices),this.renderInspector())}},children:[B("trash")]})]});i.append(c)}),r("div",{class:"atfb-section",children:[r("h4",{text:"Choices"}),r("p",{class:"atfb-hint",text:e.type==="quiz"?"Label, value, points.":"Label, value, and a price for calculations."}),i,C("Add choice",()=>{const o=this.liveField(e.id);if(!o)return;const l=o.choices??[];l.push({label:"",value:""}),s("choices",l),this.renderInspector()},"ghost","plus-alt2"),e.type==="quiz"?w("Correct answer",D(String(e.correct??""),[{value:"",label:"—"},...t.map(o=>({value:o.value,label:o.label}))],o=>s("correct",o))):null]})}choiceImageWell(e,s,t){const a=r("div",{class:`atfb-well${e.image?" has-image":""}`,attrs:{"data-choice":s,"aria-label":`Image for ${e.label||`choice ${s+1}`}`},children:[e.image?r("span",{class:"atfb-well__id",text:`#${e.image}`}):B("format-image")]}),i=G().registerDropTarget({id:`atfb-well-${t.id}-${s}`,element:a,accept:o=>Bn.includes(o.type),onEnter:()=>a.classList.add("is-dropping"),onLeave:()=>a.classList.remove("is-dropping"),onDrop:o=>{a.classList.remove("is-dropping");const l=o.payload.data,c=Number(l.attachmentId??l.id??l.file?.id??0);if(!c){N("That is not an image this field can use","","error");return}const d=this.liveField(t.id)?.choices?.[s];d&&(d.image=c,this.markDirty(),this.renderInspector())}});return this.teardowns.push(i),a.addEventListener("click",()=>{const o=this.liveField(t.id)?.choices?.[s];o?.image&&(o.image=void 0,this.markDirty(),this.renderInspector())}),a}renderValidationSection(e,s,t){const a=[],i=[];s.includes("minlength")&&i.push(["minlength","Minimum characters"],["maxlength","Maximum characters"]),s.includes("min")?i.push(["min","Minimum"],["max","Maximum"]):s.includes("max")&&i.push(["max","Highest"]),s.includes("step")&&i.push(["step","Steps of"]),s.includes("mindate")&&i.push(["minDate","Earliest date"],["maxDate","Latest date"]),s.includes("mintime")&&i.push(["minTime","Earliest time"],["maxTime","Latest time"]);for(const[l,c]of i)a.push(w(c,T(String(e[l]??""),d=>t(l,d))));s.includes("pattern")&&a.push(...this.renderAnswerShapeRows(e,t)),s.includes("unique")&&a.push(O("No two people may submit the same value",!!e.unique,l=>t("unique",l)));const o=e.messages??{};return s.includes("required")&&a.push(w("Message when required",T(o.required??"",l=>{o.required=l,t("messages",o)}),"Leave empty for the default wording.")),a.length?this.section(`validation:${e.id}`,"Validation",a):r("div",{class:"atfb-section is-empty"})}buildShapePicker(e,s){const t=[{heading:null,options:[{value:"",label:"Anything at all"}]},...On.map(i=>({heading:i,options:Wt.filter(o=>o.group===i).map(o=>({value:o.slug,label:o.label}))})),{heading:"Your own",options:[{value:"custom",label:"A custom rule…"}]}];if(Y("os-select")&&Y("os-option")){const i=document.createElement("os-select");i.setAttribute("value",e),i.setAttribute("aria-label","What the answer should look like"),i.classList.add("atfb-field");for(const o of t){if(o.heading){const l=document.createElement("os-option");l.setAttribute("value",`__heading:${o.heading}`),l.setAttribute("disabled",""),l.textContent=o.heading,i.append(l)}for(const l of o.options){const c=document.createElement("os-option");c.setAttribute("value",l.value),c.textContent=l.label,i.append(c)}}return i.addEventListener("os-pick",o=>{s(String(o.detail?.value??""))}),i}const a=r("select",{class:"atfb-input atfb-select",attrs:{"aria-label":"What the answer should look like"},on:{change:i=>s(i.target.value)}});for(const i of t){const o=i.heading?(()=>{const l=document.createElement("optgroup");return l.label=i.heading,a.append(l),l})():a;for(const l of i.options)o.append(r("option",{value:l.value,text:l.label,attrs:{selected:l.value===e}}))}return a}renderAnswerShapeRows(e,s){const a=(typeof e.validation=="string"?e.validation:"")||(e.pattern?"custom":""),i=()=>In({root:this.root,field:this.liveField(e.id)??e,onSave:u=>{s("validation","custom"),s("pattern",u.pattern),s("validationRecipe",JSON.stringify(u.recipe));const f={...this.liveField(e.id)?.messages??{}};f.invalid=u.message,s("messages",f),this.renderInspector()},onCancel:()=>this.renderInspector()}),o=u=>{if(u==="custom"){i();return}s("validation",u),s("pattern",""),s("validationRecipe",""),this.renderInspector()},l=this.buildShapePicker(a,o),c=Nn(a),d=[w("The answer should be",l,c?`e.g. ${c.example}`:"Checked as they type, and again on the server.")];if(a==="custom"){const u=Pt(String(e.validationRecipe??"")),f=Bt(u)||(e.pattern?`Matches the expression ${String(e.pattern)}`:"No rule yet — open the builder.");d.push(w("Your rule",r("div",{class:"atfb-valrule",children:[r("p",{class:"atfb-valrule__words",text:f}),C("Edit the rule…",i,"secondary","edit")]}),Ce(u)||e.pattern?"Built in the rule builder, with a playground to test it.":void 0))}return d}logicRulesEditor(e,s,t=""){const a=(this.schema?.fields??[]).filter(d=>d.id!==t&&d.type!=="page_break"),i=()=>r("div",{class:"atfb-rule-join",children:[r("button",{class:"atfb-rule-join__chip",type:"button",text:e.match==="all"?"and":"or",title:"Switch between needing every rule (and) or any one of them (or).",on:{click:()=>s(d=>{d.match=d.match==="all"?"any":"all"},!0)}})]}),o=(d,u)=>{const f=r("button",{class:"atfb-card__action",type:"button",attrs:{"aria-label":"Remove this rule"},title:"Remove this rule",on:{click:()=>s(h=>{h.rules.splice(u,1)},!0)},children:[B("trash")]}),g=[r("div",{class:"atfb-rule__top",children:[D(d.field,a.map(h=>({value:h.id,label:h.label||h.id})),h=>s(y=>{const m=y.rules[u];m&&(m.field=h,m.value="")},!0)),f]}),D(d.operator,Object.entries(this.config?.operators??{}).map(([h,y])=>({value:h,label:y})),h=>s(y=>{const m=y.rules[u];m&&(m.operator=h)},!0))];if(!De.includes(d.operator)){const h=this.schema?.fields.find(m=>m.id===d.field),y=it(h,d.value,this.config?.countries);y?g.push(D(d.value,y,m=>s(p=>{const x=p.rules[u];x&&(x.value=m)}))):g.push(T(d.value,m=>s(p=>{const x=p.rules[u];x&&(x.value=m)}),"The answer to compare against"))}return g[0].querySelector("select, os-select")?.setAttribute("aria-label","Question used by this rule"),g[1].setAttribute("aria-label","How the answer is compared"),g[2]?.setAttribute("aria-label","The answer that triggers this"),g[2]?.matches("select, os-select")&&g[2].classList.add("atfb-cond__value-select"),r("div",{class:"atfb-rule",children:g})},l=r("div",{class:"atfb-rules"});e.rules.forEach((d,u)=>{u>0&&l.append(i()),l.append(o(d,u))});const c=C("Add rule",()=>{s(d=>{d.rules.push({field:a[0]?.id??"",operator:"is",value:""})},!0)},"ghost","plus-alt2");return[l,c]}conditionsSection(e,s,t){const a=(o,l=!1)=>{o(t),this.markDirty(),l&&this.renderCanvas()},i=s==="confirmation"?"Use":"Send";return this.section(`conditions:${e}`,"Conditions",[this.copyConditionButton(`${s}:${e}`),O(`Only ${i.toLowerCase()} this ${s} sometimes`,t.enabled,o=>a(l=>{l.enabled=o},!0)),t.enabled?r("div",{children:[r("div",{class:"atfb-rule-head",children:[r("span",{text:`${i} it when`}),D(t.match,[{value:"all",label:"all"},{value:"any",label:"any"}],o=>a(l=>{l.match=o},!0)),r("span",{text:"of these match:"})]}),...this.logicRulesEditor(t,a)]}):null],t.enabled)}copyConditionButton(e){return r("button",{class:"atfb-button atfb-copy-condition",type:"button",children:[B("admin-page"),r("span",{text:"Copy condition"})],on:{click:()=>Dt({root:this.root,schema:()=>this.schema,to:e,beforeCopy:()=>this.snapshot(),onCopy:()=>{this.snapshot(),this.markDirty(),this.renderCanvas(),this.renderInspector()}})}})}renderLogicSection(e){const s=e.logic,t=()=>this.liveField(e.id)?.logic,a=(o,l=!1)=>{const c=t();c&&(o(c),this.markDirty(),this.renderCanvas(),l&&this.renderInspector())},i=this.logicRulesEditor(s,a,e.id);return this.section(`logic:${e.id}`,"Conditional logic",[O("Only show this field sometimes",s.enabled,o=>{a(l=>{l.enabled=o},!0)}),s.enabled?r("div",{children:[r("div",{class:"atfb-rule-head",children:[D(s.action,[{value:"show",label:"Show"},{value:"hide",label:"Hide"}],o=>a(l=>{l.action=o},!0)),r("span",{text:"this field when"}),D(s.match,[{value:"all",label:"all"},{value:"any",label:"any"}],o=>a(l=>{l.match=o},!0)),r("span",{text:"of these match:"})]}),...i]}):null,r("div",{class:"atfb-logic-actions",children:[this.copyConditionButton(`field:${e.id}`)]})],s.enabled)}renderTabCanvas(){return this.schema?this.tab==="theme"?yt({themes:this.themes,tokens:this.config?.tokens??[],activeSlug:this.schema.settings.theme,overrides:this.schema.settings.themeOverrides,onTheme:e=>{this.schema.settings.theme=e,this.markDirty()},onOverride:(e,s)=>{s===""?delete this.schema.settings.themeOverrides[e]:this.schema.settings.themeOverrides[e]=s,this.markDirty()},onOverridesReplaced:e=>{this.schema.settings.themeOverrides={...e},this.markDirty()},previewFor:(e,s)=>this.previewHtml(e,s),onThemesChanged:e=>{this.themes=e}}):this.tab==="settings"?this.renderSettingsPane():this.tab==="notify"?this.renderNotificationsPane():this.renderConfirmationsPane():r("div")}async paintCanvasTheme(){if(!this.form||!this.schema)return;const e=this.schema.settings.theme,s=JSON.stringify([e,this.schema.settings.themeOverrides]);if(s!==this.canvasThemeSignature){this.canvasThemeSignature=s;try{const t=await this.previewHtml(e,this.schema.settings.themeOverrides??{});this.root.classList.toggle("atfb--dark-form",/atf-is-dark/.test(t));const a=/class="atf-form-wrap"[^>]*\sstyle="([^"]*)"/.exec(t);if(!a)return;const i=a[1].replace(/"/g,'"').replace(/�?39;/g,"'").replace(/&/g,"&");this.canvasTheme.textContent=`.atfb .atfb-preview { ${i} -}`,this.canvasTheme.isConnected||this.root.append(this.canvasTheme)}catch{}}}async previewHtml(e,s){if(!this.form||!this.schema)return"";const t=JSON.parse(JSON.stringify(this.schema));t.settings.theme=e,t.settings.themeOverrides=s;const{html:a}=await I.preview(this.form.id,{schema:t,theme:e});return a}renderSettingsPane(){const e=this.schema.settings,s=(t,a)=>{const i=t.split(".");let o=e;for(let l=0;ls("submitLabel",t))),q("Submit without reloading the page",e.ajax,t=>s("ajax",t)),w("Progress indicator",D(e.progressBar,[{value:"steps",label:"Numbered steps"},{value:"bar",label:"A bar"},{value:"none",label:"None"}],t=>s("progressBar",t)),"Only shown on forms with a page break.")]}),r("section",{children:[r("h3",{text:"Who can fill this in"}),q("Only logged-in users",e.requireLogin,t=>s("requireLogin",t)),w("Message for everyone else",T(e.loginMessage,t=>s("loginMessage",t))),w("Open from",r("input",{class:"atfb-input",type:"datetime-local",value:e.schedule.start,on:{input:t=>s("schedule.start",t.target.value)}})),w("Closes",r("input",{class:"atfb-input",type:"datetime-local",value:e.schedule.end,on:{input:t=>s("schedule.end",t.target.value)}})),w("Message when closed",T(e.schedule.message,t=>s("schedule.message",t))),w("Stop after this many submissions",V(String(e.limit.total||""),t=>s("limit.total",Number(t)||0)),"0 means no limit."),w("Submissions per logged-in user",V(String(e.limit.perUser||""),t=>s("limit.perUser",Number(t)||0)))]}),r("section",{children:[r("h3",{text:"Spam"}),r("p",{class:"atfb-hint",text:"No captcha. Nothing here asks the visitor to prove anything."}),q("Honeypot field",e.spam.honeypot,t=>s("spam.honeypot",t)),w("Reject submissions faster than (seconds)",V(String(e.spam.timeTrap),t=>s("spam.timeTrap",Number(t)||0)),"A human cannot fill in a form in under a second. A script can."),w("Submissions allowed per hour, per address",V(String(e.spam.rateLimit),t=>s("spam.rateLimit",Number(t)||0))),w("Blocked words",fe(e.spam.blocklist,t=>s("spam.blocklist",t),4),"One per line."),q("Check submissions with Akismet",e.spam.akismet,t=>s("spam.akismet",t)),r("p",{class:"atfb-hint",text:"Off unless you switch it on. When on, each submission — the answers, plus the sender’s IP address and user agent — is sent to Akismet’s servers for a spam verdict. Needs the Akismet plugin installed and configured."}),q("Ask a simple sum before sending",e.spam.challenge,t=>s("spam.challenge",t)),r("p",{class:"atfb-hint",text:"Only for a form under sustained attack — it is the one check here that asks the visitor to do something. Still kinder than an image captcha: it is answerable by a screen reader, and it hands no data to anyone."})]}),r("section",{children:[r("h3",{text:"Storage and privacy"}),q("Keep entries",e.storage.entries,t=>s("storage.entries",t)),q("Record IP addresses",e.storage.ip,t=>s("storage.ip",t)),q("Anonymise recorded IP addresses",e.storage.anonymise,t=>s("storage.anonymise",t)),w("Delete entries after (days)",V(String(e.storage.retention||""),t=>s("storage.retention",Number(t)||0)),"0 keeps them forever. Anything else deletes automatically, every day.")]}),r("section",{children:[r("h3",{text:"Analytics"}),q("Count views and starts",e.analytics.enabled,t=>s("analytics.enabled",t)),q("Tally device, browser and system",e.analytics.tech,t=>s("analytics.tech",t)),r("p",{class:"atfb-hint",text:"Counters, never people: no cookie, no fingerprint, no per-visitor record — the tallies keep coarse classes like “phone” and “Chrome”, not the visitor’s user-agent string. Nothing here needs a consent banner. Turning the first switch off stops view and start counting entirely."})]}),r("section",{children:[r("h3",{text:"Save and continue later"}),q("Let people save a half-finished form",e.resume.enabled,t=>s("resume.enabled",t)),w("Keep a saved form for (days)",V(String(e.resume.days),t=>s("resume.days",Math.max(1,Number(t)||30)))),r("p",{class:"atfb-hint",text:"The link this creates is the only key to those answers — anyone holding it can read them. For genuinely sensitive questions, require login instead."})]}),r("section",{children:[r("h3",{text:"Archive"}),r("p",{class:"atfb-hint",text:"Retire the form when its moment has passed. It stops accepting responses and leaves every list, and its entries and stats go with it — nothing is deleted, and restoring it brings all of it back exactly as it was."}),C("Archive this form",()=>void this.archiveCurrentForm(),"secondary","archive")]}),r("section",{children:[r("h3",{text:"Delete"}),r("p",{class:"atfb-hint",text:"Deleting is for a form that should never have existed. It moves to the desktop’s Trash, disappears from every list, and any page still carrying its shortcode shows nothing at all. Its entries stay in Entries, and until the Trash is emptied you can bring it back from there. If the form simply had its day, archive it instead."}),C("Delete this form",()=>void this.deleteCurrentForm(),"danger","trash")]})]})}async archiveCurrentForm(){if(!this.form)return;const e=this.form.title||"(untitled)",s=this.forms.find(a=>a.id===this.form.id)?.entries??0;if(await ie(`Archive “${e}”? It stops accepting responses and leaves every list — its ${s} ${s===1?"entry":"entries"} and its stats go with it. Nothing is deleted: restore it any time from “Start a new form”.`,"Archive form"))try{this.dirty&&await this.save(!0),await I.archiveForm(this.form.id),N("Form archived",`${e} — restore it any time from the New form dialog.`),await this.releaseCurrentForm()}catch(a){N("Could not archive the form",a instanceof Error?a.message:"","error")}}async deleteCurrentForm(){if(!this.form)return;const e=this.form.title||"(untitled)",s=this.forms.find(a=>a.id===this.form.id)?.entries??0;if(await ie(`Delete “${e}”? Every page showing it goes blank. ${s?`Its ${s} ${s===1?"entry stays":"entries stay"} in Entries. `:""}It moves to the desktop’s Trash — restore it from there if you change your mind.`,"Delete form"))try{const a=this.form.id;await I.deleteForm(a),window.wp?.os?.announceContentChange?.("alltfo_form","trashed",a,"allterrain-forms"),N("Form deleted",`${e} moved to the desktop’s Trash.`),await this.releaseCurrentForm()}catch(a){N("Could not delete the form",a instanceof Error?a.message:"","error")}}async releaseCurrentForm(){if(this.forms=this.forms.filter(e=>e.id!==this.form.id),this.form=null,this.schema=null,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.forms.length){await this.open(this.forms[0].id);return}this.renderBar(),this.renderCanvas(),this.renderInspector()}writeTagValue(e,s,t,a){const i=e==="notification"?this.schema?.notifications.find(o=>o.id===s):this.schema?.confirmations.find(o=>o.id===s);i&&(t==="successTitle"&&"success"in i?i.success.title=a:Object.assign(i,{[t]:a}),this.markDirty())}taggableInput(e,s,t=""){return Be(T(e,s,t),{formId:this.form.id})}taggableArea(e,s,t=6){return Be(fe(e,s,t),{formId:this.form.id})}recipientControl(e){const s=this.schema.fields.filter(c=>c.type==="email"),t=c=>{if(c.trim()==="{admin_email}")return"admin";const d=c.trim().match(/^\{field:([a-z0-9_-]+)\}$/i);return d&&s.some(h=>h.id===d[1])?`field:${d[1]}`:/\{/.test(c)?"custom":"address"},a=[{value:"admin",label:"Whoever runs this site"},...s.map(c=>({value:`field:${c.id}`,label:`The person who filled it in — ${c.label||"their email answer"}`})),{value:"address",label:"A specific email address"},{value:"custom",label:"Something else (advanced)"}],i=t(e.to),o=r("div",{class:"atfb-recipient__detail"}),l=c=>{if(o.replaceChildren(),c==="address"){o.append(T(/\{/.test(e.to)?"":e.to,d=>{this.writeTagValue("notification",e.id,"to",d)},"name@example.com"));return}c==="custom"&&o.append(this.taggableInput(e.to,d=>{this.writeTagValue("notification",e.id,"to",d)},"{admin_email}, sales@example.com"),r("p",{class:"atfb-row__hint",text:"Separate several addresses with commas."}))};return l(i),w("Send it to",r("div",{class:"atfb-recipient",children:[D(i,a,c=>{c==="admin"?e.to="{admin_email}":c.startsWith("field:")?e.to=`{${c}}`:c==="address"&&(e.to=/\{/.test(e.to)?"":e.to),this.markDirty(),l(c)}),o]}),s.length?void 0:"Add an Email question on the Build tab to reply straight back to the visitor.")}renderNotificationsPane(){const e=this.schema.notifications,s=r("div",{class:"atfb-list"});return e.length||s.append(r("p",{class:"atfb-hint",text:"With none set up, one email goes to the site administrator with every answer in it."})),e.forEach((t,a)=>{s.append(this.section(`notification:${t.id}`,t.name||`Notification ${a+1}`,[w("Name",T(t.name,i=>{t.name=i,this.markDirty()})),this.recipientControl(t),w("Reply to",this.taggableInput(t.replyTo,i=>{this.writeTagValue("notification",t.id,"replyTo",i)},"Leave empty to reply to you"),"Set this to the visitor’s email address and hitting Reply answers them directly."),w("Subject",this.taggableInput(t.subject,i=>{this.writeTagValue("notification",t.id,"subject",i)})),w("Message",this.taggableArea(t.message,i=>{this.writeTagValue("notification",t.id,"message",i)},8)),q("Attach uploaded files",t.attachFiles,i=>{t.attachFiles=i,this.markDirty()}),this.conditionsSection(t.id,"notification",t.logic),C("Delete this notification",()=>{e.splice(a,1),this.markDirty(),this.renderCanvas()},"danger")]))}),r("div",{class:"atfb-pane",children:[r("h2",{text:"Notifications"}),s,C("Add a notification",()=>{e.push({id:this.nextEntryId("n",e),enabled:!0,name:"Notification",to:"{admin_email}",cc:"",bcc:"",replyTo:"",fromName:"",fromEmail:"",subject:"New submission",message:"{all_fields}",attachFiles:!1,logic:{enabled:!1,action:"show",match:"all",rules:[]}}),this.markDirty(),this.renderCanvas()},"primary","plus-alt2")]})}confirmationDetail(e){if(e.type==="message")return r("div",{children:[w("Message",this.taggableArea(e.message,i=>{this.writeTagValue("confirmation",e.id,"message",i)},5),"Insert an answer to greet them by name, or show back what they sent."),this.successDesigner(e)]});const s=w("Extra query parameters",this.taggableInput(e.query,i=>{this.writeTagValue("confirmation",e.id,"query",i)},"ref={entry:id}&name={field:f1}"),"Added to the address, so the page they land on can read them. Leave empty for none.");if(e.type==="redirect")return r("div",{children:[w("Web address",this.taggableInput(e.url,i=>{this.writeTagValue("confirmation",e.id,"url",i)},"https://example.com/thank-you"),"A full address, starting with https://."),s]});const t=r("div",{class:"atfb-pagepicker"}),a=i=>{t.replaceChildren(D(String(e.pageId||0),i,o=>{e.pageId=Number(o)||0,this.markDirty()}))};return a([{value:"0",label:"Loading pages…"}]),I.pages().then(i=>{a([{value:"0",label:"Choose a page…"},...i.map(o=>({value:String(o.id),label:o.title}))])}).catch(()=>{a([{value:"0",label:"Could not load the pages"}])}),w("Page",t,"They are sent to this page after submitting. Its own content is shown, not the form’s message.")}successDesigner(e){e.success=Ve(e.success);const s=e.success,t=r("div",{class:"atfb-success"}),a=[{key:"plain",label:"Plain",glyph:"¶",blurb:"Just the message."},{key:"simple",label:"Simple",glyph:"✓",blurb:"Check mark and a gentle fade."},{key:"minimal",label:"Minimalistic",glyph:"—",blurb:"Quiet type, generous space."},{key:"card",label:"Card",glyph:"🎫",blurb:"An elevated card that pops in."},{key:"check",label:"Check mark",glyph:"✔",blurb:"A big check draws itself."},{key:"confetti",label:"Confetti",glyph:"🎉",blurb:"Paper rains over the page."},{key:"fireworks",label:"Fireworks",glyph:"🎆",blurb:"The full night-sky show."},{key:"sparkles",label:"Sparkles",glyph:"✨",blurb:"Your emoji floats up around it."},{key:"typewriter",label:"Typewriter",glyph:"⌨",blurb:"Types itself out, letter by letter."}],i=()=>{const o=r("div",{class:"atfb-success__styles",attrs:{role:"radiogroup","aria-label":"Success screen style"},children:a.map(c=>r("button",{class:`atfb-success__style${s.style===c.key?" is-selected":""}`,type:"button",attrs:{role:"radio","aria-checked":s.style===c.key?"true":"false",title:c.blurb},children:[r("span",{class:"atfb-success__style-glyph",text:c.glyph}),r("span",{class:"atfb-success__style-label",text:c.label})],on:{click:()=>{s.style=c.key,this.markDirty(),i(),c.key!=="plain"&&this.previewSuccessScreen(e)}}}))}),l=[];s.style!=="plain"&&(l.push(w("Heading",this.taggableInput(s.title,c=>{this.writeTagValue("confirmation",e.id,"successTitle",c)},"Thank you, {field:name}!"),"Shown above the message. Leave empty for none.")),["simple","card","confetti","fireworks","sparkles"].includes(s.style)&&l.push(w("Emoji",T(s.icon,c=>{s.icon=c,this.markDirty()},we[s.style]||"🎉"),s.style==="sparkles"?"Also the particle that floats up — try 🎈 or ❤️.":"The badge above the heading.")),l.push(this.successAccentRow(s)),["confetti","fireworks","sparkles"].includes(s.style)&&l.push(w("Intensity",D(s.intensity,[{value:"low",label:"Calm"},{value:"medium",label:"Festive"},{value:"high",label:"Over the top"}],c=>{s.intensity=c,this.markDirty()}))),l.push(q("Offer to fill it in again",s.showButton,c=>{s.showButton=c,this.markDirty(),i()})),s.showButton&&l.push(w("Button label",T(s.buttonLabel,c=>{s.buttonLabel=c,this.markDirty()},"Fill it in again")))),t.replaceChildren(r("div",{class:"atfb-success__head",children:[r("h4",{text:"Success screen"}),C("Preview",()=>this.previewSuccessScreen(e),"ghost","controls-play")]}),o,...l)};return i(),t}successAccentRow(e){const s=r("input",{class:"atfb-success__accent",attrs:{type:"color","aria-label":"Accent colour"}});s.value=e.accent||"#3858e9";const t=C("Use the theme accent",()=>{e.accent="",s.value="#3858e9",t.style.display="none",this.markDirty()},"ghost");return t.style.display=e.accent?"":"none",s.addEventListener("input",()=>{e.accent=s.value,t.style.display="",this.markDirty()}),w("Accent",r("div",{class:"atfb-success__accent-row",children:[s,t]}),"Recolours the screen; the theme decides when left alone.")}previewSuccessScreen(e){const s=e.message||"Thank you. Your submission has been received.";let t=()=>{};const a=r("div",{class:"atfb-success-preview",attrs:{role:"dialog","aria-label":"Success screen preview","aria-modal":"true"}}),i=()=>{t(),a.remove(),document.removeEventListener("keydown",o)},o=h=>{h.key==="Escape"&&(h.stopPropagation(),i())},l=nn(s,e.success,i),c=r("div",{class:"atfb-success-preview__stage atfb-preview atf-form",children:[l]}),d=()=>{t(),t=an(l,e.success)};a.append(c,r("div",{class:"atfb-success-preview__bar",children:[C("Replay",d,"secondary","controls-repeat"),C("Close",i,"primary")]})),a.addEventListener("click",h=>{h.target===a&&i()}),document.addEventListener("keydown",o),this.root.append(a),window.requestAnimationFrame(d)}renderConfirmationsPane(){const e=this.schema.confirmations,s=r("div",{class:"atfb-list"});return e.length||s.append(r("p",{class:"atfb-hint",text:"With none set up, the form says thank you and stops."})),e.forEach((t,a)=>{const i=r("div",{class:"atfb-confirm__detail"}),o=()=>{i.replaceChildren(this.confirmationDetail(t))};o(),s.append(this.section(`confirmation:${t.id}`,t.name||`Confirmation ${a+1}`,[w("Name",T(t.name,l=>{t.name=l,this.markDirty()})),w("What happens",D(t.type,[{value:"message",label:"Show a message"},{value:"redirect",label:"Send them to a URL"},{value:"page",label:"Send them to a page"}],l=>{t.type=l,this.markDirty(),o()})),i,this.conditionsSection(t.id,"confirmation",t.logic),C("Delete this confirmation",()=>{e.splice(a,1),this.markDirty(),this.renderCanvas()},"danger")]))}),r("div",{class:"atfb-pane",children:[r("h2",{text:"Confirmations"}),r("p",{class:"atfb-hint",text:"The first one whose conditions match is the one they see."}),s,C("Add a confirmation",()=>{e.push({id:this.nextEntryId("c",e),enabled:!0,name:"Confirmation",type:"message",message:"Thank you. Your submission has been received.",url:"",pageId:0,query:"",success:kt(),logic:{enabled:!1,action:"show",match:"all",rules:[]}}),this.markDirty(),this.renderCanvas()},"primary","plus-alt2")]})}async preview(){await zt({current:()=>this.form?{id:this.form.id,title:this.form.title,previewUrl:this.form.previewUrl}:null,isDirty:()=>this.dirty,save:()=>this.save(!0)})}}let ae=null,et=null;document.addEventListener("alltfo-open-form",n=>{const e=Number(n.detail?.formId??0);e&&ae?.openFormById(e)});function tt(){if(et?.isConnected)return;ae&&(ae.destroy(),ae=null,et=null);const n=document.querySelector("[data-atfb-root]:not([data-atfb-mounted])");n&&(n.dataset.atfbMounted="1",et=n,Fe(n),us().then(()=>{n.isConnected&&(ae=new Jt(n),ae.start())}))}function Qt(){tt(),ws()}return _s(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Qt):Qt(),document.addEventListener("os-window-content-loaded",tt),ee.Builder=Jt,ee.SETTINGS_HANDLED_ELSEWHERE=Hn,ee.SETTING_CONTROLS=Kt,ee.fieldMove=Zt,ee.mountBuilder=tt,ee.restatement=Xt,Object.defineProperty(ee,Symbol.toStringTag,{value:"Module"}),ee}({}); +}`,this.canvasTheme.isConnected||this.root.append(this.canvasTheme)}catch{}}}async previewHtml(e,s){if(!this.form||!this.schema)return"";const t=JSON.parse(JSON.stringify(this.schema));t.settings.theme=e,t.settings.themeOverrides=s;const{html:a}=await I.preview(this.form.id,{schema:t,theme:e});return a}renderSettingsPane(){const e=this.schema.settings,s=(t,a)=>{const i=t.split(".");let o=e;for(let l=0;ls("submitLabel",t))),O("Submit without reloading the page",e.ajax,t=>s("ajax",t)),w("Progress indicator",D(e.progressBar,[{value:"steps",label:"Numbered steps"},{value:"bar",label:"A bar"},{value:"none",label:"None"}],t=>s("progressBar",t)),"Only shown on forms with a page break.")]}),r("section",{children:[r("h3",{text:"Who can fill this in"}),O("Only logged-in users",e.requireLogin,t=>s("requireLogin",t)),w("Message for everyone else",T(e.loginMessage,t=>s("loginMessage",t))),w("Open from",r("input",{class:"atfb-input",type:"datetime-local",value:e.schedule.start,on:{input:t=>s("schedule.start",t.target.value)}})),w("Closes",r("input",{class:"atfb-input",type:"datetime-local",value:e.schedule.end,on:{input:t=>s("schedule.end",t.target.value)}})),w("Message when closed",T(e.schedule.message,t=>s("schedule.message",t))),w("Stop after this many submissions",V(String(e.limit.total||""),t=>s("limit.total",Number(t)||0)),"0 means no limit."),w("Submissions per logged-in user",V(String(e.limit.perUser||""),t=>s("limit.perUser",Number(t)||0)))]}),r("section",{children:[r("h3",{text:"Spam"}),r("p",{class:"atfb-hint",text:"No captcha. Nothing here asks the visitor to prove anything."}),O("Honeypot field",e.spam.honeypot,t=>s("spam.honeypot",t)),w("Reject submissions faster than (seconds)",V(String(e.spam.timeTrap),t=>s("spam.timeTrap",Number(t)||0)),"A human cannot fill in a form in under a second. A script can."),w("Submissions allowed per hour, per address",V(String(e.spam.rateLimit),t=>s("spam.rateLimit",Number(t)||0))),w("Blocked words",fe(e.spam.blocklist,t=>s("spam.blocklist",t),4),"One per line."),O("Check submissions with Akismet",e.spam.akismet,t=>s("spam.akismet",t)),r("p",{class:"atfb-hint",text:"Off unless you switch it on. When on, each submission — the answers, plus the sender’s IP address and user agent — is sent to Akismet’s servers for a spam verdict. Needs the Akismet plugin installed and configured."}),O("Ask a simple sum before sending",e.spam.challenge,t=>s("spam.challenge",t)),r("p",{class:"atfb-hint",text:"Only for a form under sustained attack — it is the one check here that asks the visitor to do something. Still kinder than an image captcha: it is answerable by a screen reader, and it hands no data to anyone."})]}),r("section",{children:[r("h3",{text:"Storage and privacy"}),O("Keep entries",e.storage.entries,t=>s("storage.entries",t)),O("Record IP addresses",e.storage.ip,t=>s("storage.ip",t)),O("Anonymise recorded IP addresses",e.storage.anonymise,t=>s("storage.anonymise",t)),w("Delete entries after (days)",V(String(e.storage.retention||""),t=>s("storage.retention",Number(t)||0)),"0 keeps them forever. Anything else deletes automatically, every day.")]}),r("section",{children:[r("h3",{text:"Analytics"}),O("Count views and starts",e.analytics.enabled,t=>s("analytics.enabled",t)),O("Tally device, browser and system",e.analytics.tech,t=>s("analytics.tech",t)),r("p",{class:"atfb-hint",text:"Counters, never people: no cookie, no fingerprint, no per-visitor record — the tallies keep coarse classes like “phone” and “Chrome”, not the visitor’s user-agent string. Nothing here needs a consent banner. Turning the first switch off stops view and start counting entirely."})]}),r("section",{children:[r("h3",{text:"Save and continue later"}),O("Let people save a half-finished form",e.resume.enabled,t=>s("resume.enabled",t)),w("Keep a saved form for (days)",V(String(e.resume.days),t=>s("resume.days",Math.max(1,Number(t)||30)))),r("p",{class:"atfb-hint",text:"The link this creates is the only key to those answers — anyone holding it can read them. For genuinely sensitive questions, require login instead."})]}),r("section",{children:[r("h3",{text:"Archive"}),r("p",{class:"atfb-hint",text:"Retire the form when its moment has passed. It stops accepting responses and leaves every list, and its entries and stats go with it — nothing is deleted, and restoring it brings all of it back exactly as it was."}),C("Archive this form",()=>void this.archiveCurrentForm(),"secondary","archive")]}),r("section",{children:[r("h3",{text:"Delete"}),r("p",{class:"atfb-hint",text:"Deleting is for a form that should never have existed. It moves to the desktop’s Trash, disappears from every list, and any page still carrying its shortcode shows nothing at all. Its entries stay in Entries, and until the Trash is emptied you can bring it back from there. If the form simply had its day, archive it instead."}),C("Delete this form",()=>void this.deleteCurrentForm(),"danger","trash")]})]})}async archiveCurrentForm(){if(!this.form)return;const e=this.form.title||"(untitled)",s=this.forms.find(a=>a.id===this.form.id)?.entries??0;if(await ie(`Archive “${e}”? It stops accepting responses and leaves every list — its ${s} ${s===1?"entry":"entries"} and its stats go with it. Nothing is deleted: restore it any time from “Start a new form”.`,"Archive form"))try{this.dirty&&await this.save(!0),await I.archiveForm(this.form.id),N("Form archived",`${e} — restore it any time from the New form dialog.`),await this.releaseCurrentForm()}catch(a){N("Could not archive the form",a instanceof Error?a.message:"","error")}}async deleteCurrentForm(){if(!this.form)return;const e=this.form.title||"(untitled)",s=this.forms.find(a=>a.id===this.form.id)?.entries??0;if(await ie(`Delete “${e}”? Every page showing it goes blank. ${s?`Its ${s} ${s===1?"entry stays":"entries stay"} in Entries. `:""}It moves to the desktop’s Trash — restore it from there if you change your mind.`,"Delete form"))try{const a=this.form.id;await I.deleteForm(a),window.wp?.os?.announceContentChange?.("alltfo_form","trashed",a,"allterrain-forms"),N("Form deleted",`${e} moved to the desktop’s Trash.`),await this.releaseCurrentForm()}catch(a){N("Could not delete the form",a instanceof Error?a.message:"","error")}}async releaseCurrentForm(){if(this.forms=this.forms.filter(e=>e.id!==this.form.id),this.form=null,this.schema=null,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.forms.length){await this.open(this.forms[0].id);return}this.renderBar(),this.renderCanvas(),this.renderInspector()}writeTagValue(e,s,t,a){const i=e==="notification"?this.schema?.notifications.find(o=>o.id===s):this.schema?.confirmations.find(o=>o.id===s);i&&(t==="successTitle"&&"success"in i?i.success.title=a:Object.assign(i,{[t]:a}),this.markDirty())}taggableInput(e,s,t=""){return Be(T(e,s,t),{formId:this.form.id})}taggableArea(e,s,t=6){return Be(fe(e,s,t),{formId:this.form.id})}recipientControl(e){const s=this.schema.fields.filter(c=>c.type==="email"),t=c=>{if(c.trim()==="{admin_email}")return"admin";const d=c.trim().match(/^\{field:([a-z0-9_-]+)\}$/i);return d&&s.some(u=>u.id===d[1])?`field:${d[1]}`:/\{/.test(c)?"custom":"address"},a=[{value:"admin",label:"Whoever runs this site"},...s.map(c=>({value:`field:${c.id}`,label:`The person who filled it in — ${c.label||"their email answer"}`})),{value:"address",label:"A specific email address"},{value:"custom",label:"Something else (advanced)"}],i=t(e.to),o=r("div",{class:"atfb-recipient__detail"}),l=c=>{if(o.replaceChildren(),c==="address"){o.append(T(/\{/.test(e.to)?"":e.to,d=>{this.writeTagValue("notification",e.id,"to",d)},"name@example.com"));return}c==="custom"&&o.append(this.taggableInput(e.to,d=>{this.writeTagValue("notification",e.id,"to",d)},"{admin_email}, sales@example.com"),r("p",{class:"atfb-row__hint",text:"Separate several addresses with commas."}))};return l(i),w("Send it to",r("div",{class:"atfb-recipient",children:[D(i,a,c=>{c==="admin"?e.to="{admin_email}":c.startsWith("field:")?e.to=`{${c}}`:c==="address"&&(e.to=/\{/.test(e.to)?"":e.to),this.markDirty(),l(c)}),o]}),s.length?void 0:"Add an Email question on the Build tab to reply straight back to the visitor.")}renderNotificationsPane(){const e=this.schema.notifications,s=r("div",{class:"atfb-list"});return e.length||s.append(r("p",{class:"atfb-hint",text:"With none set up, one email goes to the site administrator with every answer in it."})),e.forEach((t,a)=>{s.append(this.section(`notification:${t.id}`,t.name||`Notification ${a+1}`,[w("Name",T(t.name,i=>{t.name=i,this.markDirty()})),this.recipientControl(t),w("Reply to",this.taggableInput(t.replyTo,i=>{this.writeTagValue("notification",t.id,"replyTo",i)},"Leave empty to reply to you"),"Set this to the visitor’s email address and hitting Reply answers them directly."),w("Subject",this.taggableInput(t.subject,i=>{this.writeTagValue("notification",t.id,"subject",i)})),w("Message",this.taggableArea(t.message,i=>{this.writeTagValue("notification",t.id,"message",i)},8)),O("Attach uploaded files",t.attachFiles,i=>{t.attachFiles=i,this.markDirty()}),this.conditionsSection(t.id,"notification",t.logic),C("Delete this notification",()=>{e.splice(a,1),this.markDirty(),this.renderCanvas()},"danger")]))}),r("div",{class:"atfb-pane",children:[r("h2",{text:"Notifications"}),s,C("Add a notification",()=>{e.push({id:this.nextEntryId("n",e),enabled:!0,name:"Notification",to:"{admin_email}",cc:"",bcc:"",replyTo:"",fromName:"",fromEmail:"",subject:"New submission",message:"{all_fields}",attachFiles:!1,logic:{enabled:!1,action:"show",match:"all",rules:[]}}),this.markDirty(),this.renderCanvas()},"primary","plus-alt2")]})}confirmationDetail(e){if(e.type==="message")return r("div",{children:[w("Message",this.taggableArea(e.message,i=>{this.writeTagValue("confirmation",e.id,"message",i)},5),"Insert an answer to greet them by name, or show back what they sent."),this.successDesigner(e)]});const s=w("Extra query parameters",this.taggableInput(e.query,i=>{this.writeTagValue("confirmation",e.id,"query",i)},"ref={entry:id}&name={field:f1}"),"Added to the address, so the page they land on can read them. Leave empty for none.");if(e.type==="redirect")return r("div",{children:[w("Web address",this.taggableInput(e.url,i=>{this.writeTagValue("confirmation",e.id,"url",i)},"https://example.com/thank-you"),"A full address, starting with https://."),s]});const t=r("div",{class:"atfb-pagepicker"}),a=i=>{t.replaceChildren(D(String(e.pageId||0),i,o=>{e.pageId=Number(o)||0,this.markDirty()}))};return a([{value:"0",label:"Loading pages…"}]),I.pages().then(i=>{a([{value:"0",label:"Choose a page…"},...i.map(o=>({value:String(o.id),label:o.title}))])}).catch(()=>{a([{value:"0",label:"Could not load the pages"}])}),w("Page",t,"They are sent to this page after submitting. Its own content is shown, not the form’s message.")}successDesigner(e){e.success=Ve(e.success);const s=e.success,t=r("div",{class:"atfb-success"}),a=[{key:"plain",label:"Plain",glyph:"¶",blurb:"Just the message."},{key:"simple",label:"Simple",glyph:"✓",blurb:"Check mark and a gentle fade."},{key:"minimal",label:"Minimalistic",glyph:"—",blurb:"Quiet type, generous space."},{key:"card",label:"Card",glyph:"🎫",blurb:"An elevated card that pops in."},{key:"check",label:"Check mark",glyph:"✔",blurb:"A big check draws itself."},{key:"confetti",label:"Confetti",glyph:"🎉",blurb:"Paper rains over the page."},{key:"fireworks",label:"Fireworks",glyph:"🎆",blurb:"The full night-sky show."},{key:"sparkles",label:"Sparkles",glyph:"✨",blurb:"Your emoji floats up around it."},{key:"typewriter",label:"Typewriter",glyph:"⌨",blurb:"Types itself out, letter by letter."}],i=()=>{const o=r("div",{class:"atfb-success__styles",attrs:{role:"radiogroup","aria-label":"Success screen style"},children:a.map(c=>r("button",{class:`atfb-success__style${s.style===c.key?" is-selected":""}`,type:"button",attrs:{role:"radio","aria-checked":s.style===c.key?"true":"false",title:c.blurb},children:[r("span",{class:"atfb-success__style-glyph",text:c.glyph}),r("span",{class:"atfb-success__style-label",text:c.label})],on:{click:()=>{s.style=c.key,this.markDirty(),i(),c.key!=="plain"&&this.previewSuccessScreen(e)}}}))}),l=[];s.style!=="plain"&&(l.push(w("Heading",this.taggableInput(s.title,c=>{this.writeTagValue("confirmation",e.id,"successTitle",c)},"Thank you, {field:name}!"),"Shown above the message. Leave empty for none.")),["simple","card","confetti","fireworks","sparkles"].includes(s.style)&&l.push(w("Emoji",T(s.icon,c=>{s.icon=c,this.markDirty()},we[s.style]||"🎉"),s.style==="sparkles"?"Also the particle that floats up — try 🎈 or ❤️.":"The badge above the heading.")),l.push(this.successAccentRow(s)),["confetti","fireworks","sparkles"].includes(s.style)&&l.push(w("Intensity",D(s.intensity,[{value:"low",label:"Calm"},{value:"medium",label:"Festive"},{value:"high",label:"Over the top"}],c=>{s.intensity=c,this.markDirty()}))),l.push(O("Offer to fill it in again",s.showButton,c=>{s.showButton=c,this.markDirty(),i()})),s.showButton&&l.push(w("Button label",T(s.buttonLabel,c=>{s.buttonLabel=c,this.markDirty()},"Fill it in again")))),t.replaceChildren(r("div",{class:"atfb-success__head",children:[r("h4",{text:"Success screen"}),C("Preview",()=>this.previewSuccessScreen(e),"ghost","controls-play")]}),o,...l)};return i(),t}successAccentRow(e){const s=r("input",{class:"atfb-success__accent",attrs:{type:"color","aria-label":"Accent colour"}});s.value=e.accent||"#3858e9";const t=C("Use the theme accent",()=>{e.accent="",s.value="#3858e9",t.style.display="none",this.markDirty()},"ghost");return t.style.display=e.accent?"":"none",s.addEventListener("input",()=>{e.accent=s.value,t.style.display="",this.markDirty()}),w("Accent",r("div",{class:"atfb-success__accent-row",children:[s,t]}),"Recolours the screen; the theme decides when left alone.")}previewSuccessScreen(e){const s=e.message||"Thank you. Your submission has been received.";let t=()=>{};const a=r("div",{class:"atfb-success-preview",attrs:{role:"dialog","aria-label":"Success screen preview","aria-modal":"true"}}),i=()=>{t(),a.remove(),document.removeEventListener("keydown",o)},o=u=>{u.key==="Escape"&&(u.stopPropagation(),i())},l=nn(s,e.success,i),c=r("div",{class:"atfb-success-preview__stage atfb-preview atf-form",children:[l]}),d=()=>{t(),t=an(l,e.success)};a.append(c,r("div",{class:"atfb-success-preview__bar",children:[C("Replay",d,"secondary","controls-repeat"),C("Close",i,"primary")]})),a.addEventListener("click",u=>{u.target===a&&i()}),document.addEventListener("keydown",o),this.root.append(a),window.requestAnimationFrame(d)}renderConfirmationsPane(){const e=this.schema.confirmations,s=r("div",{class:"atfb-list"});return e.length||s.append(r("p",{class:"atfb-hint",text:"With none set up, the form says thank you and stops."})),e.forEach((t,a)=>{const i=r("div",{class:"atfb-confirm__detail"}),o=()=>{i.replaceChildren(this.confirmationDetail(t))};o(),s.append(this.section(`confirmation:${t.id}`,t.name||`Confirmation ${a+1}`,[w("Name",T(t.name,l=>{t.name=l,this.markDirty()})),w("What happens",D(t.type,[{value:"message",label:"Show a message"},{value:"redirect",label:"Send them to a URL"},{value:"page",label:"Send them to a page"}],l=>{t.type=l,this.markDirty(),o()})),i,this.conditionsSection(t.id,"confirmation",t.logic),C("Delete this confirmation",()=>{e.splice(a,1),this.markDirty(),this.renderCanvas()},"danger")]))}),r("div",{class:"atfb-pane",children:[r("h2",{text:"Confirmations"}),r("p",{class:"atfb-hint",text:"The first one whose conditions match is the one they see."}),s,C("Add a confirmation",()=>{e.push({id:this.nextEntryId("c",e),enabled:!0,name:"Confirmation",type:"message",message:"Thank you. Your submission has been received.",url:"",pageId:0,query:"",success:kt(),logic:{enabled:!1,action:"show",match:"all",rules:[]}}),this.markDirty(),this.renderCanvas()},"primary","plus-alt2")]})}async preview(){await zt({current:()=>this.form?{id:this.form.id,title:this.form.title,previewUrl:this.form.previewUrl}:null,isDirty:()=>this.dirty,save:()=>this.save(!0)})}}let ae=null,et=null;document.addEventListener("alltfo-open-form",n=>{const e=Number(n.detail?.formId??0);e&&ae?.openFormById(e)});function tt(){if(et?.isConnected)return;ae&&(ae.destroy(),ae=null,et=null);const n=document.querySelector("[data-atfb-root]:not([data-atfb-mounted])");n&&(n.dataset.atfbMounted="1",et=n,Fe(n),hs().then(()=>{n.isConnected&&(ae=new Jt(n),ae.start())}))}function Qt(){tt(),ws()}return _s(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Qt):Qt(),document.addEventListener("os-window-content-loaded",tt),ee.Builder=Jt,ee.SETTINGS_HANDLED_ELSEWHERE=jn,ee.SETTING_CONTROLS=Kt,ee.fieldMove=Zt,ee.mountBuilder=tt,ee.restatement=Xt,Object.defineProperty(ee,Symbol.toStringTag,{value:"Module"}),ee}({}); diff --git a/assets/js/form.js b/assets/js/form.js index ceddfea..7f6e77a 100644 --- a/assets/js/form.js +++ b/assets/js/form.js @@ -1280,7 +1280,7 @@ var allTerrainFormsFront = function(exports) { } return; } - input.disabled = !show; + input.disabled = !show || input.hasAttribute("data-atf-total"); }); } const calculated = applyCalculations(this.schema.fields, values); @@ -1295,6 +1295,10 @@ var allTerrainFormsFront = function(exports) { const value = calculated[field.id]; const decimals = typeof field.decimals === "number" ? field.decimals : 2; input.value = typeof value === "number" ? value.toFixed(decimals) : ""; + const submitted = this.fieldElement(field.id)?.querySelector("[data-atf-total-value]"); + if (submitted) { + submitted.value = input.value; + } } } /* ---------------------------------------------------------------- Steps */ diff --git a/assets/js/form.min.js b/assets/js/form.min.js index 8bff336..0c49633 100644 --- a/assets/js/form.min.js +++ b/assets/js/form.min.js @@ -1 +1 @@ -var allTerrainFormsFront=function(S){"use strict";const D={min:-1,max:-1,sum:-1,avg:-1,round:-1,ceil:1,floor:1,abs:1,sqrt:1,pow:2},T={"+":{precedence:1,right:!1},"-":{precedence:1,right:!1},"*":{precedence:2,right:!1},"/":{precedence:2,right:!1},"%":{precedence:2,right:!1},"^":{precedence:4,right:!0}};function W(a,e,t=[]){if(!a||!a.trim()||a.length>2e3)return null;const r=Z(a,e,t),n=V(r);if(!n)return null;const s=J(n);if(!s)return null;const i=K(s);return i===null||!Number.isFinite(i)?null:i}function Z(a,e,t){return a.replace(/\{([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?\}/g,(r,n,s,i)=>B(a,i,r.length,n,s??"",e,t))}function B(a,e,t,r,n,s,i){const o=U(i,r),l=Object.prototype.hasOwnProperty.call(s,r)?s[r]:null;if(n===""){const h=o?.type==="repeater"?C(l).length:M(l,o);return N(h)}const f=(o?.fields??[]).find(h=>h.id===n)??null,m=C(l).map(h=>M(h[n]??"",f));if(!m.length)return"0";const b=m.map(N);return X(a,e,t)?b.join(", "):b.length===1?b[0]:`( ${b.join(" + ")} )`}function U(a,e){for(const t of a){if(t.id===e)return t;for(const r of t.fields??[])if(r.id===e)return r}return null}function X(a,e,t){const r=a.slice(e+t).replace(/^\s+/,"");if(r===""||r[0]!==")")return!1;const n=a.slice(0,e).replace(/\s+$/,""),s=/([a-zA-Z_][a-zA-Z0-9_]*)\s*\($/.exec(n);return!!s&&["sum","avg","min","max"].includes(s[1].toLowerCase())}function C(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(!t||typeof t!="object"||Array.isArray(t))continue;Object.values(t).some(n=>n!==""&&n!==null&&n!==void 0&&n!==!1&&!(Array.isArray(n)&&!n.length))&&e.push(t)}return e}function N(a){const e=a.toFixed(10).replace(/0+$/,"").replace(/\.$/,"");return e===""||e==="-"?"0":e}function M(a,e){if(typeof a=="boolean")return a?1:0;if(Array.isArray(a))return a.reduce((n,s)=>n+M(s,e),0);if(a==null||a==="")return 0;const t=e?.choices??[];for(const n of t)if(String(n.value)===String(a)){if(typeof n.price=="number")return n.price;if(typeof n.points=="number")return n.points;break}const r=Number(a);return Number.isFinite(r)?r:0}function V(a){const e=[];let t=0;for(;ts.precedence||o.precedence===s.precedence&&!s.right){e.push(t.pop());continue}break}t.push(n);break}case"(":t.push(n);break;case")":{for(;t.length&&t[t.length-1].type!=="(";)e.push(t.pop());if(!t.length)return null;if(t.pop(),t.length&&t[t.length-1].type==="function"){const s=t.pop();s.arity=r.length?r.pop():1,e.push(s)}break}}for(;t.length;){const n=t.pop();if(n.type==="(")return null;e.push(n)}return e}function K(a){const e=[];for(const t of a)switch(t.type){case"number":e.push(t.value);break;case"unary":{if(!e.length)return null;e.push(-e.pop());break}case"operator":{if(e.length<2)return null;const r=e.pop(),n=e.pop();switch(t.value){case"+":e.push(n+r);break;case"-":e.push(n-r);break;case"*":e.push(n*r);break;case"/":e.push(r===0?0:n/r);break;case"%":e.push(r===0?0:n%r);break;case"^":e.push(Math.pow(n,r));break;default:return null}break}case"function":{const r=t.arity??1;if(e.lengtht+r,0);case"avg":return e.reduce((t,r)=>t+r,0)/e.length;case"round":{const t=Math.max(-10,Math.min(10,Math.trunc(e[1]??0))),r=Math.pow(10,t);return Math.round(e[0]*r)/r}case"ceil":return Math.ceil(e[0]);case"floor":return Math.floor(e[0]);case"abs":return Math.abs(e[0]);case"sqrt":return e[0]<0?0:Math.sqrt(e[0]);case"pow":return Math.pow(e[0],e[1]??2);default:return null}}function Q(a,e){const t={...e};for(const r of a){const n=r.formula;if(!n)continue;const s=W(n,t,a);if(s===null){t[r.id]="";continue}const i=typeof r.decimals=="number"?r.decimals:2,o=Math.pow(10,i);t[r.id]=Math.round(s*o)/o}return t}const L={plain:"",simple:"✓",minimal:"",card:"🎉",check:"",confetti:"🎉",fireworks:"🎆",sparkles:"✨",typewriter:""};function ee(){return{style:"simple",title:"",icon:"",accent:"",intensity:"medium",showButton:!1,buttonLabel:""}}function F(a){const e={...ee(),...a??{}};return e.style in L||(e.style="simple"),e}function te(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}function re(a,e,t){const r=F(e),n=document.createElement("div");if(n.className=`atf-confirmation atf-success atf-success--${r.style}`,n.setAttribute("role","status"),n.setAttribute("tabindex","-1"),r.style==="plain")return n.className="atf-confirmation",n.innerHTML=a,n;r.accent&&n.style.setProperty("--atf-accent",r.accent);const s=document.createElement("div");s.className="atf-success__inner",n.append(s);const i=r.icon||L[r.style];if(r.style==="check")s.insertAdjacentHTML("beforeend",'');else if(i){const l=document.createElement("span");l.className="atf-success__icon",l.setAttribute("aria-hidden","true"),l.textContent=i,s.append(l)}if(r.title){const l=document.createElement("h2");l.className="atf-success__title",l.textContent=r.title,s.append(l)}const o=document.createElement("div");if(o.className="atf-success__message",o.innerHTML=a,s.append(o),r.style==="typewriter"&&n.setAttribute("aria-label",o.textContent??""),r.showButton){const l=document.createElement("button");l.type="button",l.className="atf-button atf-button--ghost atf-success__again",l.textContent=r.buttonLabel||"Fill it in again",l.addEventListener("click",()=>window.location.reload()),s.append(l)}return n}function ne(a,e){const t=F(e);if(te())return()=>{};switch(t.style){case"confetti":return se(a,t);case"fireworks":return ae(t);case"sparkles":return oe(a,t);case"typewriter":return ie(a);default:return()=>{}}}function x(a){return{low:.5,medium:1,high:1.8}[a.intensity]}function $(){const a=document.createElement("canvas");a.className="atf-success-canvas",a.setAttribute("aria-hidden","true");const e=Math.min(window.devicePixelRatio||1,2);a.width=Math.floor(window.innerWidth*e),a.height=Math.floor(window.innerHeight*e),document.body.append(a);const t=a.getContext("2d");return t?.scale(e,e),{canvas:a,ctx:t,stop:()=>a.remove()}}const I=["#f43f5e","#f59e0b","#10b981","#3b82f6","#8b5cf6","#ec4899","#eab308"];function se(a,e){const{ctx:t,stop:r}=$();if(!t)return r(),()=>{};const n=e.accent?[e.accent,...I]:I,s=[],i=a.getBoundingClientRect(),o=i.left+i.width/2,l=Math.min(i.top+40,window.innerHeight-20),u=(w,E,d)=>{const z=d?Math.PI*(1.15+.7*Math.random()):0,j=d?9+Math.random()*8:0;return{x:w,y:E,vx:d?Math.cos(z)*j*(Math.random()<.5?1:-1):(Math.random()-.5)*1.5,vy:d?Math.sin(z)*j:1+Math.random()*2,w:6+Math.random()*5,h:8+Math.random()*7,angle:Math.random()*Math.PI,spin:(Math.random()-.5)*.3,color:n[Math.floor(Math.random()*n.length)],wobble:Math.random()*Math.PI*2}},f=Math.round(90*x(e));for(let w=0;w{if(b>=m){window.clearInterval(h);return}s.push(u(Math.random()*window.innerWidth,-20,!1)),b++},2e3/m);let y=0;const p=performance.now(),c=w=>{t.clearRect(0,0,window.innerWidth,window.innerHeight);let E=!1;for(const d of s)d.vy+=.16,d.vx*=.99,d.vy*=.985,d.wobble+=.1,d.x+=d.vx+Math.sin(d.wobble)*.8,d.y+=d.vy,d.angle+=d.spin,d.y{window.clearInterval(h),window.cancelAnimationFrame(y),r()}}function ae(a){const{ctx:e,stop:t}=$();if(!e)return t(),()=>{};const r=[],n=[],s=Math.round(6*x(a))+2;let i=0;const o=()=>{r.push({x:window.innerWidth*(.15+.7*Math.random()),y:window.innerHeight,vy:-(9+Math.random()*4),targetY:window.innerHeight*(.15+.3*Math.random()),hue:Math.floor(Math.random()*360)}),i++};o();const l=window.setInterval(()=>{if(i>=s){window.clearInterval(l);return}o()},3500/s),u=h=>{const y=Math.round(70*x(a));for(let p=0;p{e.clearRect(0,0,window.innerWidth,window.innerHeight);for(let p=r.length-1;p>=0;p--){const c=r[p];c.y+=c.vy,c.vy+=.08,e.fillStyle=`hsl(${c.hue} 90% 65%)`,e.fillRect(c.x-1.5,c.y,3,10),(c.y<=c.targetY||c.vy>=-1)&&(u(c),r.splice(p,1))}for(let p=n.length-1;p>=0;p--){const c=n[p];if(c.x+=c.vx,c.y+=c.vy,c.vy+=.045,c.vx*=.985,c.vy*=.985,c.life-=c.decay,c.life<=0){n.splice(p,1);continue}const w=c.life*(.7+.3*Math.random());e.globalAlpha=Math.max(0,w),e.fillStyle=`hsl(${c.hue} 95% ${55+25*c.life}%)`,e.beginPath(),e.arc(c.x,c.y,1.1+1.6*c.life,0,Math.PI*2),e.fill()}e.globalAlpha=1,!(i>=s&&r.length===0&&n.length===0)&&h-m<9e3?f=window.requestAnimationFrame(b):t()};return f=window.requestAnimationFrame(b),()=>{window.clearInterval(l),window.cancelAnimationFrame(f),t()}}function oe(a,e){const t=e.icon||L.sparkles,r=Math.round(22*x(e)),n=[];let s=0;const i=()=>{const l=document.createElement("span");l.className="atf-success__spark",l.setAttribute("aria-hidden","true"),l.textContent=t,l.style.insetInlineStart=`${4+Math.random()*92}%`,l.style.animationDuration=`${2.6+Math.random()*1.8}s`,l.style.animationDelay=`${Math.random()*.3}s`,l.style.fontSize=`${14+Math.random()*14}px`,l.addEventListener("animationend",()=>l.remove()),a.append(l),n.push(l),s++};i();const o=window.setInterval(()=>{if(s>=r){window.clearInterval(o);return}i()},2800/r);return()=>{window.clearInterval(o),n.forEach(l=>l.remove())}}function ie(a){const e=a.querySelector(".atf-success__message");if(!e)return()=>{};const t=e.innerHTML,r=e.textContent??"";if(!r)return()=>{};e.textContent="",e.classList.add("is-typing");const n=Math.min(45,3800/r.length);let s=0;const i=window.setInterval(()=>{s++,e.textContent=r.slice(0,s),s>=r.length&&(window.clearInterval(i),e.classList.remove("is-typing"),e.innerHTML=t)},n);return()=>{window.clearInterval(i),e.classList.remove("is-typing"),e.innerHTML=t}}function le(a,e){if(!a?.enabled||!a.rules?.length)return!0;const t=a.match==="any"?"any":"all";for(const r of a.rules){const n=Object.prototype.hasOwnProperty.call(e,r.field)?e[r.field]:null,s=ue(r,n);if(t==="any"&&s)return!0;if(t==="all"&&!s)return!1}return t==="all"}function ce(a,e){if(!a?.enabled)return!0;const t=le(a,e);return a.action==="hide"?!t:t}function ue(a,e){const t=a.operator??"is",r=a.value??"";if(Array.isArray(e)){const n=e.filter(s=>s!==""&&s!==null&&s!==void 0);return t==="empty"?n.length===0:t==="not_empty"?n.length>0:t==="is_not"||t==="not_contains"?e.every(s=>_(t,s,r)):e.some(s=>_(t,s,r))}return _(t,e,r)}function _(a,e,t){typeof e=="boolean"&&(e=e?"1":"");const r=e==null?"":String(e);switch(a){case"is":return r===t;case"is_not":return r!==t;case"contains":return t!==""&&r.toLowerCase().includes(t.toLowerCase());case"not_contains":return t===""||!r.toLowerCase().includes(t.toLowerCase());case"starts_with":return t!==""&&r.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return t!==""&&r.toLowerCase().endsWith(t.toLowerCase());case"empty":return r.trim()==="";case"not_empty":return r.trim()!=="";case"greater":case"less":case"greater_equal":case"less_equal":{if(!P(r)||!P(t))return!1;const n=parseFloat(r),s=parseFloat(t);return a==="greater"?n>s:a==="less"?n=s:n<=s}default:return!1}}function fe(a,e){const t={};for(const n of a)t[n.id]=!0;const r=10;for(let n=0;nA(e)):a!==null&&typeof a=="object"?Object.values(a).every(e=>A(e)):a===""||a===null||a===void 0}const de=[{slug:"email",label:"An email address",group:"Contact",example:"jane@example.com",pattern:"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",message:"That does not look like an email address."},{slug:"phone",label:"A phone number",group:"Contact",example:"+34 612 345 678",pattern:"^(?=(?:[^0-9]*[0-9]){5,})\\+?[0-9 ().-]{5,24}$",message:"That does not look like a phone number."},{slug:"handle",label:"A username or @handle",group:"Contact",example:"@yourname",pattern:"^@?[A-Za-z0-9_]{2,30}$",message:"That does not look like a username."},{slug:"digits",label:"Numbers only",group:"Numbers & codes",example:"12345",pattern:"^[0-9]+$",message:"Numbers only, please."},{slug:"decimal",label:"A number, decimals allowed",group:"Numbers & codes",example:"3.14",pattern:"^-?[0-9]+([.,][0-9]+)?$",message:"That does not look like a number."},{slug:"price",label:"A price",group:"Numbers & codes",example:"19.99",pattern:"^[0-9]+([.,][0-9]{1,2})?$",message:"That does not look like a price."},{slug:"zip_us",label:"A ZIP code (US)",group:"Numbers & codes",example:"90210",pattern:"^[0-9]{5}(-[0-9]{4})?$",message:"That does not look like a ZIP code."},{slug:"postcode_uk",label:"A postcode (UK)",group:"Numbers & codes",example:"SW1A 1AA",pattern:"^[A-Za-z]{1,2}[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}$",message:"That does not look like a postcode."},{slug:"iban",label:"An IBAN",group:"Numbers & codes",example:"DE89 3704 0044 0532 0130 00",pattern:"^[A-Za-z]{2}[0-9]{2}(?: ?[A-Za-z0-9]){10,32}$",message:"That does not look like an IBAN."},{slug:"credit_card",label:"A card number",group:"Numbers & codes",example:"4242 4242 4242 4242",pattern:"^[0-9](?:[0-9 -]{9,21})?[0-9]$",message:"That does not look like a card number.",luhn:!0},{slug:"letters",label:"Letters only",group:"Text shape",example:"María López",pattern:"^[\\p{L}\\p{M} .'’-]+$",message:"Letters only, please."},{slug:"alphanumeric",label:"Letters and numbers only",group:"Text shape",example:"abc123",pattern:"^[A-Za-z0-9]+$",message:"Letters and numbers only, please."},{slug:"no_spaces",label:"One word, no spaces",group:"Text shape",example:"one-word",pattern:"^\\S+$",message:"No spaces allowed."},{slug:"url",label:"A web address",group:"Web",example:"https://example.com",pattern:"^(https?://)?([A-Za-z0-9-]+\\.)+[A-Za-z]{2,}([/?#]\\S*)?$",message:"That does not look like a web address."},{slug:"ip",label:"An IP address",group:"Web",example:"192.168.0.1",pattern:"^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",message:"That does not look like an IP address."},{slug:"slug",label:"A URL slug",group:"Web",example:"my-page-title",pattern:"^[a-z0-9]+(-[a-z0-9]+)*$",message:"Lowercase letters, numbers and dashes only."},{slug:"hex_color",label:"A hex colour",group:"Web",example:"#3366ff",pattern:"^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",message:"That does not look like a colour code."}];function R(a){return de.find(e=>e.slug===a)??null}function he(a){const e=a.replace(/[^0-9]/g,"");if(e.length<12)return!1;let t=0,r=!1;for(let n=e.length-1;n>=0;n--){let s=e.charCodeAt(n)-48;r&&(s*=2,s>9&&(s-=9)),t+=s,r=!r}return t%10===0}function pe(a,e){const t=R(a);if(!t)return null;let r;try{r=new RegExp(t.pattern,"u")}catch{return!0}return!(!r.test(e)||t.luhn&&!he(e))}const v=window.allTerrainForms,g=(a,e)=>v?.i18n?.[a]??e;class O{constructor(e,t){this.step=0,this.started=!1,this.submitting=!1,this.form=e,this.schema=t,this.pages=Array.from(e.querySelectorAll("[data-atf-page]")),this.errorSummary=e.querySelector(".atf-errors"),this.bind(),this.showStep(0,!1),this.update()}bind(){this.form.addEventListener("input",e=>this.onInput(e)),this.form.addEventListener("change",e=>this.onInput(e)),this.form.addEventListener("submit",e=>void this.onSubmit(e)),this.form.addEventListener("click",e=>{const t=e.target;t.closest("[data-atf-next]")&&(e.preventDefault(),this.next()),t.closest("[data-atf-prev]")&&(e.preventDefault(),this.previous()),t.closest("[data-atf-repeater-add]")&&(e.preventDefault(),this.addRepeaterRow(t.closest("[data-atf-repeater]"))),t.closest("[data-atf-repeater-remove]")&&(e.preventDefault(),this.removeRepeaterRow(t.closest("[data-atf-repeater-row]"))),t.closest("[data-atf-resume]")&&(e.preventDefault(),this.saveForLater())}),this.form.addEventListener("blur",e=>{const t=e.target?.closest?.("[data-atf-field]");t&&this.validateField(t)},!0),this.form.querySelectorAll("[data-atf-signature]").forEach(e=>{this.initSignature(e)}),this.form.querySelectorAll(".atf-range__input").forEach(e=>{const t=e.parentElement?.querySelector(".atf-range__output");e.addEventListener("input",()=>{t&&(t.textContent=e.value)})}),this.initOtherToggles()}values(){const e={};for(const t of this.schema.fields)e[t.id]=this.readField(t);return e}readField(e){const t=this.fieldElement(e.id);if(!t)return null;if(e.type==="repeater")return this.readRepeater(e,t);const r=Array.from(t.querySelectorAll("input, select, textarea")).filter(o=>!o.disabled&&!o.closest("template"));if(!r.length)return null;if(["name","address","date_range","likert"].includes(e.type)){const o={};for(const l of r){const u=l.name.match(/\[([^\]]+)\]$/)?.[1];if(u){if(l instanceof HTMLInputElement&&(l.type==="radio"||l.type==="checkbox")){l.checked&&(o[u]=l.value);continue}o[u]=l.value}}return o}const n=r.filter(o=>o instanceof HTMLInputElement&&o.type==="checkbox");if(n.length)return n.length===1&&!n[0].name.endsWith("[]")?n[0].checked:n.filter(o=>o.checked).map(o=>o.value);const s=r.filter(o=>o instanceof HTMLInputElement&&o.type==="radio");if(s.length)return s.find(o=>o.checked)?.value??"";const i=r[0];return i instanceof HTMLSelectElement&&i.multiple?Array.from(i.selectedOptions).map(o=>o.value):i instanceof HTMLInputElement&&i.type==="file"?i.files&&i.files.length?[String(i.files.length)]:[]:i.value}readRepeater(e,t){const r=e.fields??[],n=[];return t.querySelectorAll("[data-atf-repeater-row]").forEach(s=>{const i={};for(const o of r)i[o.id]="";s.querySelectorAll("input, select, textarea").forEach(o=>{if(o.disabled)return;const l=o.name.match(/\[\d+\]\[([^\]]+)\]/);if(!l)return;const u=l[1];if(o instanceof HTMLInputElement&&o.type==="checkbox"){if(o.name.endsWith("[]")){const f=Array.isArray(i[u])?i[u]:[];o.checked&&f.push(o.value),i[u]=f;return}i[u]=o.checked;return}if(o instanceof HTMLInputElement&&o.type==="radio"){o.checked&&(i[u]=o.value);return}if(o instanceof HTMLSelectElement&&o.multiple){i[u]=Array.from(o.selectedOptions).map(f=>f.value);return}i[u]=o.value}),n.push(i)}),n}fieldElement(e){return this.form.querySelector(`[data-atf-field="${CSS.escape(e)}"]`)}onInput(e){const t=e.target;if(t?.closest("template"))return;this.started||(this.started=!0,this.reportStart()),this.update();const r=t?.closest("[data-atf-field]");r?.classList.contains("has-error")&&this.validateField(r)}update(){const e=this.values(),t=fe(this.schema.fields,e);for(const n of this.schema.fields){const s=this.fieldElement(n.id);if(!s)continue;const i=t[n.id]!==!1;s.hidden===i&&(s.hidden=!i),s.querySelectorAll("input, select, textarea").forEach(o=>{if(!o.closest("template")){if(o.hasAttribute("data-atf-other-input")){i||(o.disabled=!0);return}o.disabled=!i}})}const r=Q(this.schema.fields,e);for(const n of this.schema.fields){if(!n.formula)continue;const s=this.fieldElement(n.id)?.querySelector("[data-atf-total]");if(!s)continue;const i=r[n.id],o=typeof n.decimals=="number"?n.decimals:2;s.value=typeof i=="number"?i.toFixed(o):""}}showStep(e,t=!0){if(!(this.pages.length<2)&&(this.step=Math.max(0,Math.min(this.pages.length-1,e)),this.pages.forEach((r,n)=>{r.hidden=n!==this.step,delete r.dataset.atfPageHidden}),this.updateProgress(),t)){const r=this.pages[this.step];r.setAttribute("tabindex","-1"),r.focus({preventScroll:!0}),r.scrollIntoView({behavior:"smooth",block:"start"})}}updateProgress(){const e=this.form.querySelector(".atf-progress--bar");if(e){const t=e.querySelector(".atf-progress__fill"),r=(this.step+1)/this.pages.length*100;t&&(t.style.width=`${r}%`),e.setAttribute("aria-valuenow",String(this.step+1))}this.form.querySelectorAll(".atf-progress__step").forEach((t,r)=>{t.classList.toggle("is-current",r===this.step),t.classList.toggle("is-done",ri.id===t);if(!r)return!0;if(r.type==="repeater")return this.validateRepeater(e,r);const n=this.readField(r),s=this.checkField(r,n);return this.setFieldError(e,s),s===""}validateRepeater(e,t){const r=t.fields??[],n=this.readField(t),s=Array.isArray(n)?n:[],i=Array.from(e.querySelectorAll("[data-atf-repeater-row]")),o=e.querySelector("[data-atf-repeater]")?.dataset.atfItemLabel||"";let l="";return i.forEach((u,f)=>{const m=s[f]??{},b=r.every(y=>A(m[y.id]??""));let h=!1;for(const y of r){const p=u.querySelector(`[data-atf-sub="${y.id}"]`);if(!p)continue;const c=b?"":this.checkField(y,m[y.id]??"");this.setFieldError(p,c),c!==""&&(h=!0,l===""&&(l=`${o} ${f+1}: ${c}`))}u.classList.toggle("has-error",h)}),this.setFieldError(e,l),l===""}checkField(e,t){const r=e.messages??{},n=A(t);if(e.required&&n)return r.required||g("required","This is required.");if(n)return"";if(typeof t=="string"){if(e.type==="email"&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t))return r.invalid||g("invalidEmail","That does not look like an email address.");if(e.type==="url"&&!/^https?:\/\/[^\s]+$/i.test(t))return r.invalid||g("invalidUrl","That does not look like a web address.");const s=Number(e.minlength),i=Number(e.maxlength);if(e.minlength&&t.lengthi)return r.max||g("tooLong","That is too long.");const o=typeof e.validation=="string"&&e.validation!==""&&e.validation!=="custom"?e.validation:"";if(o&&pe(o,t)===!1)return r.invalid||R(o)?.message||g("badFormat","That is not in the expected format.");if(e.pattern)try{if(!new RegExp(String(e.pattern)).test(t))return r.invalid||g("badFormat","That is not in the expected format.")}catch{}}if(t!==""&&!Number.isNaN(Number(t))&&typeof t!="boolean"&&!Array.isArray(t)){const s=Number(t);if(e.min!==void 0&&e.min!==""&&sNumber(e.max))return r.max||g("tooBig","That number is too large.")}if(Array.isArray(t)){const s=t.filter(i=>i!=="").length;if(e.minChoices&&sNumber(e.maxChoices))return r.max||g("tooBig","That is too many.")}return""}setFieldError(e,t){const r=e.querySelector(":scope > .atf-error")??e.querySelector(".atf-error");e.classList.toggle("has-error",t!==""),r&&(r.textContent=t,r.hidden=t===""),e.dataset.atfType!=="repeater"&&e.querySelectorAll("input, select, textarea").forEach(n=>{t===""?n.removeAttribute("aria-invalid"):n.setAttribute("aria-invalid","true")})}repeaterSubElement(e){const t=e.split(".");if(t.length!==3)return null;const[r,n,s]=t,i=this.fieldElement(r),o=this.schema.fields.find(y=>y.id===r);if(!i||!o||o.type!=="repeater")return null;const l=o.fields??[],u=this.readField(o),f=Array.isArray(u)?u:[],b=Array.from(i.querySelectorAll("[data-atf-repeater-row]")).filter((y,p)=>y&&!l.every(c=>A(f[p]?.[c.id]??"")))[Number(n)],h=b?.querySelector(`[data-atf-sub="${s}"]`)??null;return h&&b&&b.classList.add("has-error"),h}focusField(e){(e.querySelector("input, select, textarea")??e).focus?.({preventScroll:!0}),e.scrollIntoView({behavior:"smooth",block:"center"})}async onSubmit(e){if(this.pages.length>1&&this.stepl.contains(o))))}this.announceErrors(e.message),r&&(n>=0&&this.showStep(n,!1),this.focusField(r))}announceErrors(e=""){if(!this.errorSummary)return;const t=Array.from(this.form.querySelectorAll(".atf-field.has-error")).filter(s=>!s.closest("[data-atf-repeater]"));if(!t.length&&!e){this.errorSummary.hidden=!0;return}const r=(s,i="")=>{const o=this.labelTextOf(s),l=(s.querySelector(":scope > .atf-error")??s.querySelector(".atf-error"))?.textContent?.trim()??"";return`
  • ${q(i+(o?`${o}: ${l}`:l))}
  • `},n=t.map(s=>{const i=Array.from(s.querySelectorAll(".atf-repeater__field.has-error"));if(i.length){const o=this.labelTextOf(s),l=i[0].querySelector("input, select, textarea")?.id??"",u=i.map(f=>{const m=f.closest("[data-atf-repeater-row]")?.querySelector("[data-atf-repeater-title]")?.textContent?.trim();return r(f,m?`${m} — `:"")}).join("");return`
  • ${q(o)}
      ${u}
  • `}return r(s)}).join("");this.errorSummary.innerHTML=`

    ${q(e||g("errorsFound","There are problems to fix."))}

      ${n}
    `,this.errorSummary.hidden=!1,this.errorSummary.focus()}labelTextOf(e){const t=e.querySelector(".atf-label, legend, .atf-toggle__label");if(!t)return"";const r=t.cloneNode(!0);return r.querySelectorAll('.atf-required, [aria-hidden="true"]').forEach(n=>n.remove()),(r.textContent??"").replace(/\s+/g," ").trim().replace(/[.:;,]+$/,"")}showConfirmation(e){const t=e.confirmation??{};if(t.url){window.location.assign(t.url);return}if(!this.form.parentElement)return;const n=re(t.message??"",t.success);this.form.replaceWith(n),ne(n,t.success),n.focus(),n.scrollIntoView({behavior:"smooth",block:"center"}),document.dispatchEvent(new CustomEvent("alltfo-submitted",{detail:{formId:Number(this.form.dataset.atfForm),entryId:e.entry_id},bubbles:!0}))}async saveForLater(){const e=this.form.querySelector("[data-atf-resume]"),t=this.form.querySelector("[data-atf-resume-token]");e&&(e.disabled=!0);try{const r=new FormData(this.form),s=await(await fetch(`${v?.restUrl??""}/resume`,{method:"POST",body:r,credentials:"same-origin",headers:v?.nonce?{"X-WP-Nonce":v.nonce}:{}})).json();if(!s.success||!s.url){this.showResumeMessage(s.message??g("failed","That did not save. Please try again."),"");return}t&&s.token&&(t.value=s.token),this.showResumeMessage(s.days?`Saved. Come back to this within ${s.days} days using the link below.`:"Saved. Come back using the link below.",s.url)}catch{this.showResumeMessage(g("failed","That did not save. Please try again."),"")}finally{e&&(e.disabled=!1)}}showResumeMessage(e,t){this.form.querySelector(".atf-resume-panel")?.remove();const r=document.createElement("div");r.className="atf-resume-panel",r.setAttribute("role","status"),r.setAttribute("tabindex","-1");const n=document.createElement("p");if(n.textContent=e,r.append(n),t){const s=document.createElement("input");s.type="text",s.className="atf-input",s.readOnly=!0,s.value=t,s.setAttribute("aria-label","Your link back to this form"),s.addEventListener("focus",()=>s.select()),r.append(s)}this.form.querySelector(".atf-actions")?.after(r),r.focus()}reportStart(){const e=Number(this.form.dataset.atfForm);!e||!v?.restUrl||fetch(`${v.restUrl}/track`,{method:"POST",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({form_id:e,event:"start"})}).catch(()=>{})}addRepeaterRow(e){if(!e)return;const t=e.querySelector(".atf-repeater__rows"),r=e.querySelector("[data-atf-repeater-template]"),n=Number(e.dataset.atfMax??10);if(!t||!r||t.querySelectorAll("[data-atf-repeater-row]").length>=n)return;const s=H(t),i=r.content.cloneNode(!0);i.querySelectorAll("[name], [id], [for]").forEach(l=>{for(const u of["name","id","for"]){const f=l.getAttribute(u);f?.includes("__INDEX__")&&l.setAttribute(u,f.replace(/__INDEX__/g,String(s)))}}),t.appendChild(i),t.lastElementChild?.querySelector("input, select, textarea")?.focus(),this.renumberRepeater(e),this.update()}renumberRepeater(e){const t=e.dataset.atfItemLabel??"";e.querySelectorAll("[data-atf-repeater-row]").forEach((r,n)=>{const s=`${t} ${n+1}`.trim(),i=r.querySelector("[data-atf-repeater-title]");i&&(i.textContent=s),r.setAttribute("aria-label",s)})}removeRepeaterRow(e){const t=e?.closest("[data-atf-repeater]");if(!e||!t)return;const r=t.querySelectorAll("[data-atf-repeater-row]"),n=Number(t.dataset.atfMin??1);if(r.length<=n){e.querySelectorAll("input, select, textarea").forEach(i=>{i.value=""}),this.update();return}const s=e.nextElementSibling??e.previousElementSibling;e.remove(),s?.querySelector("input, select, textarea")?.focus(),this.renumberRepeater(t),this.update()}initSignature(e){const t=e.querySelector("canvas"),r=e.querySelector('input[type="hidden"]'),n=e.querySelector("[data-atf-signature-clear]"),s=t?.getContext("2d");if(!t||!r||!s)return;s.lineWidth=2,s.lineCap="round",s.lineJoin="round",s.strokeStyle=getComputedStyle(e).color||"#000";let i=!1;const o=u=>{const f=t.getBoundingClientRect();return{x:(u.clientX-f.left)/f.width*t.width,y:(u.clientY-f.top)/f.height*t.height}};t.addEventListener("pointerdown",u=>{i=!0,t.setPointerCapture(u.pointerId);const{x:f,y:m}=o(u);s.beginPath(),s.moveTo(f,m)}),t.addEventListener("pointermove",u=>{if(!i)return;const{x:f,y:m}=o(u);s.lineTo(f,m),s.stroke()});const l=()=>{i&&(i=!1,r.value=t.toDataURL("image/png"),r.dispatchEvent(new Event("change",{bubbles:!0})))};t.addEventListener("pointerup",l),t.addEventListener("pointercancel",l),t.addEventListener("pointerleave",l),n?.addEventListener("click",()=>{s.clearRect(0,0,t.width,t.height),r.value="",r.dispatchEvent(new Event("change",{bubbles:!0}))})}initOtherToggles(){const e=()=>{this.form.querySelectorAll(".atf-choice--other").forEach(t=>{const r=t.querySelector("[data-atf-other-toggle]"),n=t.querySelector("[data-atf-other-input]");!r||!n||(n.disabled=!r.checked,n.hidden=!r.checked)})};this.form.addEventListener("change",e),e()}}function q(a){const e=document.createElement("div");return e.textContent=a,e.innerHTML}function H(a){let e=-1;return a.querySelectorAll("[data-atf-repeater-row] [name]").forEach(t=>{const r=/^atf\[[^\]]*\]\[(\d+)\]/.exec(t.getAttribute("name")??"");r&&(e=Math.max(e,Number(r[1])))}),e+1}function me(a){const e=a.dataset.atfInstance??"",t=document.getElementById(`${e}-schema`);if(!t?.textContent)return null;try{return JSON.parse(t.textContent)}catch{return null}}function k(){document.querySelectorAll("form[data-atf-form]").forEach(a=>{if(a.dataset.atfBooted)return;const e=me(a);if(e){a.dataset.atfBooted="1";try{new O(a,e)}catch(t){console.error("[AllTerrain Forms] Could not enhance a form.",t)}}})}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",k):k(),document.addEventListener("alltfo-refresh",k),S.AllTerrainForm=O,S.boot=k,S.nextRepeaterIndex=H,Object.defineProperty(S,Symbol.toStringTag,{value:"Module"}),S}({}); +var allTerrainFormsFront=function(S){"use strict";const D={min:-1,max:-1,sum:-1,avg:-1,round:-1,ceil:1,floor:1,abs:1,sqrt:1,pow:2},T={"+":{precedence:1,right:!1},"-":{precedence:1,right:!1},"*":{precedence:2,right:!1},"/":{precedence:2,right:!1},"%":{precedence:2,right:!1},"^":{precedence:4,right:!0}};function W(a,e,t=[]){if(!a||!a.trim()||a.length>2e3)return null;const r=Z(a,e,t),n=V(r);if(!n)return null;const s=J(n);if(!s)return null;const i=K(s);return i===null||!Number.isFinite(i)?null:i}function Z(a,e,t){return a.replace(/\{([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?\}/g,(r,n,s,i)=>B(a,i,r.length,n,s??"",e,t))}function B(a,e,t,r,n,s,i){const o=U(i,r),l=Object.prototype.hasOwnProperty.call(s,r)?s[r]:null;if(n===""){const h=o?.type==="repeater"?C(l).length:M(l,o);return N(h)}const f=(o?.fields??[]).find(h=>h.id===n)??null,m=C(l).map(h=>M(h[n]??"",f));if(!m.length)return"0";const b=m.map(N);return X(a,e,t)?b.join(", "):b.length===1?b[0]:`( ${b.join(" + ")} )`}function U(a,e){for(const t of a){if(t.id===e)return t;for(const r of t.fields??[])if(r.id===e)return r}return null}function X(a,e,t){const r=a.slice(e+t).replace(/^\s+/,"");if(r===""||r[0]!==")")return!1;const n=a.slice(0,e).replace(/\s+$/,""),s=/([a-zA-Z_][a-zA-Z0-9_]*)\s*\($/.exec(n);return!!s&&["sum","avg","min","max"].includes(s[1].toLowerCase())}function C(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(!t||typeof t!="object"||Array.isArray(t))continue;Object.values(t).some(n=>n!==""&&n!==null&&n!==void 0&&n!==!1&&!(Array.isArray(n)&&!n.length))&&e.push(t)}return e}function N(a){const e=a.toFixed(10).replace(/0+$/,"").replace(/\.$/,"");return e===""||e==="-"?"0":e}function M(a,e){if(typeof a=="boolean")return a?1:0;if(Array.isArray(a))return a.reduce((n,s)=>n+M(s,e),0);if(a==null||a==="")return 0;const t=e?.choices??[];for(const n of t)if(String(n.value)===String(a)){if(typeof n.price=="number")return n.price;if(typeof n.points=="number")return n.points;break}const r=Number(a);return Number.isFinite(r)?r:0}function V(a){const e=[];let t=0;for(;ts.precedence||o.precedence===s.precedence&&!s.right){e.push(t.pop());continue}break}t.push(n);break}case"(":t.push(n);break;case")":{for(;t.length&&t[t.length-1].type!=="(";)e.push(t.pop());if(!t.length)return null;if(t.pop(),t.length&&t[t.length-1].type==="function"){const s=t.pop();s.arity=r.length?r.pop():1,e.push(s)}break}}for(;t.length;){const n=t.pop();if(n.type==="(")return null;e.push(n)}return e}function K(a){const e=[];for(const t of a)switch(t.type){case"number":e.push(t.value);break;case"unary":{if(!e.length)return null;e.push(-e.pop());break}case"operator":{if(e.length<2)return null;const r=e.pop(),n=e.pop();switch(t.value){case"+":e.push(n+r);break;case"-":e.push(n-r);break;case"*":e.push(n*r);break;case"/":e.push(r===0?0:n/r);break;case"%":e.push(r===0?0:n%r);break;case"^":e.push(Math.pow(n,r));break;default:return null}break}case"function":{const r=t.arity??1;if(e.lengtht+r,0);case"avg":return e.reduce((t,r)=>t+r,0)/e.length;case"round":{const t=Math.max(-10,Math.min(10,Math.trunc(e[1]??0))),r=Math.pow(10,t);return Math.round(e[0]*r)/r}case"ceil":return Math.ceil(e[0]);case"floor":return Math.floor(e[0]);case"abs":return Math.abs(e[0]);case"sqrt":return e[0]<0?0:Math.sqrt(e[0]);case"pow":return Math.pow(e[0],e[1]??2);default:return null}}function Q(a,e){const t={...e};for(const r of a){const n=r.formula;if(!n)continue;const s=W(n,t,a);if(s===null){t[r.id]="";continue}const i=typeof r.decimals=="number"?r.decimals:2,o=Math.pow(10,i);t[r.id]=Math.round(s*o)/o}return t}const L={plain:"",simple:"✓",minimal:"",card:"🎉",check:"",confetti:"🎉",fireworks:"🎆",sparkles:"✨",typewriter:""};function ee(){return{style:"simple",title:"",icon:"",accent:"",intensity:"medium",showButton:!1,buttonLabel:""}}function F(a){const e={...ee(),...a??{}};return e.style in L||(e.style="simple"),e}function te(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}function re(a,e,t){const r=F(e),n=document.createElement("div");if(n.className=`atf-confirmation atf-success atf-success--${r.style}`,n.setAttribute("role","status"),n.setAttribute("tabindex","-1"),r.style==="plain")return n.className="atf-confirmation",n.innerHTML=a,n;r.accent&&n.style.setProperty("--atf-accent",r.accent);const s=document.createElement("div");s.className="atf-success__inner",n.append(s);const i=r.icon||L[r.style];if(r.style==="check")s.insertAdjacentHTML("beforeend",'');else if(i){const l=document.createElement("span");l.className="atf-success__icon",l.setAttribute("aria-hidden","true"),l.textContent=i,s.append(l)}if(r.title){const l=document.createElement("h2");l.className="atf-success__title",l.textContent=r.title,s.append(l)}const o=document.createElement("div");if(o.className="atf-success__message",o.innerHTML=a,s.append(o),r.style==="typewriter"&&n.setAttribute("aria-label",o.textContent??""),r.showButton){const l=document.createElement("button");l.type="button",l.className="atf-button atf-button--ghost atf-success__again",l.textContent=r.buttonLabel||"Fill it in again",l.addEventListener("click",()=>window.location.reload()),s.append(l)}return n}function ne(a,e){const t=F(e);if(te())return()=>{};switch(t.style){case"confetti":return se(a,t);case"fireworks":return ae(t);case"sparkles":return oe(a,t);case"typewriter":return ie(a);default:return()=>{}}}function x(a){return{low:.5,medium:1,high:1.8}[a.intensity]}function $(){const a=document.createElement("canvas");a.className="atf-success-canvas",a.setAttribute("aria-hidden","true");const e=Math.min(window.devicePixelRatio||1,2);a.width=Math.floor(window.innerWidth*e),a.height=Math.floor(window.innerHeight*e),document.body.append(a);const t=a.getContext("2d");return t?.scale(e,e),{canvas:a,ctx:t,stop:()=>a.remove()}}const I=["#f43f5e","#f59e0b","#10b981","#3b82f6","#8b5cf6","#ec4899","#eab308"];function se(a,e){const{ctx:t,stop:r}=$();if(!t)return r(),()=>{};const n=e.accent?[e.accent,...I]:I,s=[],i=a.getBoundingClientRect(),o=i.left+i.width/2,l=Math.min(i.top+40,window.innerHeight-20),u=(w,E,d)=>{const z=d?Math.PI*(1.15+.7*Math.random()):0,j=d?9+Math.random()*8:0;return{x:w,y:E,vx:d?Math.cos(z)*j*(Math.random()<.5?1:-1):(Math.random()-.5)*1.5,vy:d?Math.sin(z)*j:1+Math.random()*2,w:6+Math.random()*5,h:8+Math.random()*7,angle:Math.random()*Math.PI,spin:(Math.random()-.5)*.3,color:n[Math.floor(Math.random()*n.length)],wobble:Math.random()*Math.PI*2}},f=Math.round(90*x(e));for(let w=0;w{if(b>=m){window.clearInterval(h);return}s.push(u(Math.random()*window.innerWidth,-20,!1)),b++},2e3/m);let y=0;const p=performance.now(),c=w=>{t.clearRect(0,0,window.innerWidth,window.innerHeight);let E=!1;for(const d of s)d.vy+=.16,d.vx*=.99,d.vy*=.985,d.wobble+=.1,d.x+=d.vx+Math.sin(d.wobble)*.8,d.y+=d.vy,d.angle+=d.spin,d.y{window.clearInterval(h),window.cancelAnimationFrame(y),r()}}function ae(a){const{ctx:e,stop:t}=$();if(!e)return t(),()=>{};const r=[],n=[],s=Math.round(6*x(a))+2;let i=0;const o=()=>{r.push({x:window.innerWidth*(.15+.7*Math.random()),y:window.innerHeight,vy:-(9+Math.random()*4),targetY:window.innerHeight*(.15+.3*Math.random()),hue:Math.floor(Math.random()*360)}),i++};o();const l=window.setInterval(()=>{if(i>=s){window.clearInterval(l);return}o()},3500/s),u=h=>{const y=Math.round(70*x(a));for(let p=0;p{e.clearRect(0,0,window.innerWidth,window.innerHeight);for(let p=r.length-1;p>=0;p--){const c=r[p];c.y+=c.vy,c.vy+=.08,e.fillStyle=`hsl(${c.hue} 90% 65%)`,e.fillRect(c.x-1.5,c.y,3,10),(c.y<=c.targetY||c.vy>=-1)&&(u(c),r.splice(p,1))}for(let p=n.length-1;p>=0;p--){const c=n[p];if(c.x+=c.vx,c.y+=c.vy,c.vy+=.045,c.vx*=.985,c.vy*=.985,c.life-=c.decay,c.life<=0){n.splice(p,1);continue}const w=c.life*(.7+.3*Math.random());e.globalAlpha=Math.max(0,w),e.fillStyle=`hsl(${c.hue} 95% ${55+25*c.life}%)`,e.beginPath(),e.arc(c.x,c.y,1.1+1.6*c.life,0,Math.PI*2),e.fill()}e.globalAlpha=1,!(i>=s&&r.length===0&&n.length===0)&&h-m<9e3?f=window.requestAnimationFrame(b):t()};return f=window.requestAnimationFrame(b),()=>{window.clearInterval(l),window.cancelAnimationFrame(f),t()}}function oe(a,e){const t=e.icon||L.sparkles,r=Math.round(22*x(e)),n=[];let s=0;const i=()=>{const l=document.createElement("span");l.className="atf-success__spark",l.setAttribute("aria-hidden","true"),l.textContent=t,l.style.insetInlineStart=`${4+Math.random()*92}%`,l.style.animationDuration=`${2.6+Math.random()*1.8}s`,l.style.animationDelay=`${Math.random()*.3}s`,l.style.fontSize=`${14+Math.random()*14}px`,l.addEventListener("animationend",()=>l.remove()),a.append(l),n.push(l),s++};i();const o=window.setInterval(()=>{if(s>=r){window.clearInterval(o);return}i()},2800/r);return()=>{window.clearInterval(o),n.forEach(l=>l.remove())}}function ie(a){const e=a.querySelector(".atf-success__message");if(!e)return()=>{};const t=e.innerHTML,r=e.textContent??"";if(!r)return()=>{};e.textContent="",e.classList.add("is-typing");const n=Math.min(45,3800/r.length);let s=0;const i=window.setInterval(()=>{s++,e.textContent=r.slice(0,s),s>=r.length&&(window.clearInterval(i),e.classList.remove("is-typing"),e.innerHTML=t)},n);return()=>{window.clearInterval(i),e.classList.remove("is-typing"),e.innerHTML=t}}function le(a,e){if(!a?.enabled||!a.rules?.length)return!0;const t=a.match==="any"?"any":"all";for(const r of a.rules){const n=Object.prototype.hasOwnProperty.call(e,r.field)?e[r.field]:null,s=ue(r,n);if(t==="any"&&s)return!0;if(t==="all"&&!s)return!1}return t==="all"}function ce(a,e){if(!a?.enabled)return!0;const t=le(a,e);return a.action==="hide"?!t:t}function ue(a,e){const t=a.operator??"is",r=a.value??"";if(Array.isArray(e)){const n=e.filter(s=>s!==""&&s!==null&&s!==void 0);return t==="empty"?n.length===0:t==="not_empty"?n.length>0:t==="is_not"||t==="not_contains"?e.every(s=>q(t,s,r)):e.some(s=>q(t,s,r))}return q(t,e,r)}function q(a,e,t){typeof e=="boolean"&&(e=e?"1":"");const r=e==null?"":String(e);switch(a){case"is":return r===t;case"is_not":return r!==t;case"contains":return t!==""&&r.toLowerCase().includes(t.toLowerCase());case"not_contains":return t===""||!r.toLowerCase().includes(t.toLowerCase());case"starts_with":return t!==""&&r.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return t!==""&&r.toLowerCase().endsWith(t.toLowerCase());case"empty":return r.trim()==="";case"not_empty":return r.trim()!=="";case"greater":case"less":case"greater_equal":case"less_equal":{if(!P(r)||!P(t))return!1;const n=parseFloat(r),s=parseFloat(t);return a==="greater"?n>s:a==="less"?n=s:n<=s}default:return!1}}function fe(a,e){const t={};for(const n of a)t[n.id]=!0;const r=10;for(let n=0;nA(e)):a!==null&&typeof a=="object"?Object.values(a).every(e=>A(e)):a===""||a===null||a===void 0}const de=[{slug:"email",label:"An email address",group:"Contact",example:"jane@example.com",pattern:"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",message:"That does not look like an email address."},{slug:"phone",label:"A phone number",group:"Contact",example:"+34 612 345 678",pattern:"^(?=(?:[^0-9]*[0-9]){5,})\\+?[0-9 ().-]{5,24}$",message:"That does not look like a phone number."},{slug:"handle",label:"A username or @handle",group:"Contact",example:"@yourname",pattern:"^@?[A-Za-z0-9_]{2,30}$",message:"That does not look like a username."},{slug:"digits",label:"Numbers only",group:"Numbers & codes",example:"12345",pattern:"^[0-9]+$",message:"Numbers only, please."},{slug:"decimal",label:"A number, decimals allowed",group:"Numbers & codes",example:"3.14",pattern:"^-?[0-9]+([.,][0-9]+)?$",message:"That does not look like a number."},{slug:"price",label:"A price",group:"Numbers & codes",example:"19.99",pattern:"^[0-9]+([.,][0-9]{1,2})?$",message:"That does not look like a price."},{slug:"zip_us",label:"A ZIP code (US)",group:"Numbers & codes",example:"90210",pattern:"^[0-9]{5}(-[0-9]{4})?$",message:"That does not look like a ZIP code."},{slug:"postcode_uk",label:"A postcode (UK)",group:"Numbers & codes",example:"SW1A 1AA",pattern:"^[A-Za-z]{1,2}[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}$",message:"That does not look like a postcode."},{slug:"iban",label:"An IBAN",group:"Numbers & codes",example:"DE89 3704 0044 0532 0130 00",pattern:"^[A-Za-z]{2}[0-9]{2}(?: ?[A-Za-z0-9]){10,32}$",message:"That does not look like an IBAN."},{slug:"credit_card",label:"A card number",group:"Numbers & codes",example:"4242 4242 4242 4242",pattern:"^[0-9](?:[0-9 -]{9,21})?[0-9]$",message:"That does not look like a card number.",luhn:!0},{slug:"letters",label:"Letters only",group:"Text shape",example:"María López",pattern:"^[\\p{L}\\p{M} .'’-]+$",message:"Letters only, please."},{slug:"alphanumeric",label:"Letters and numbers only",group:"Text shape",example:"abc123",pattern:"^[A-Za-z0-9]+$",message:"Letters and numbers only, please."},{slug:"no_spaces",label:"One word, no spaces",group:"Text shape",example:"one-word",pattern:"^\\S+$",message:"No spaces allowed."},{slug:"url",label:"A web address",group:"Web",example:"https://example.com",pattern:"^(https?://)?([A-Za-z0-9-]+\\.)+[A-Za-z]{2,}([/?#]\\S*)?$",message:"That does not look like a web address."},{slug:"ip",label:"An IP address",group:"Web",example:"192.168.0.1",pattern:"^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",message:"That does not look like an IP address."},{slug:"slug",label:"A URL slug",group:"Web",example:"my-page-title",pattern:"^[a-z0-9]+(-[a-z0-9]+)*$",message:"Lowercase letters, numbers and dashes only."},{slug:"hex_color",label:"A hex colour",group:"Web",example:"#3366ff",pattern:"^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",message:"That does not look like a colour code."}];function R(a){return de.find(e=>e.slug===a)??null}function he(a){const e=a.replace(/[^0-9]/g,"");if(e.length<12)return!1;let t=0,r=!1;for(let n=e.length-1;n>=0;n--){let s=e.charCodeAt(n)-48;r&&(s*=2,s>9&&(s-=9)),t+=s,r=!r}return t%10===0}function pe(a,e){const t=R(a);if(!t)return null;let r;try{r=new RegExp(t.pattern,"u")}catch{return!0}return!(!r.test(e)||t.luhn&&!he(e))}const v=window.allTerrainForms,g=(a,e)=>v?.i18n?.[a]??e;class O{constructor(e,t){this.step=0,this.started=!1,this.submitting=!1,this.form=e,this.schema=t,this.pages=Array.from(e.querySelectorAll("[data-atf-page]")),this.errorSummary=e.querySelector(".atf-errors"),this.bind(),this.showStep(0,!1),this.update()}bind(){this.form.addEventListener("input",e=>this.onInput(e)),this.form.addEventListener("change",e=>this.onInput(e)),this.form.addEventListener("submit",e=>void this.onSubmit(e)),this.form.addEventListener("click",e=>{const t=e.target;t.closest("[data-atf-next]")&&(e.preventDefault(),this.next()),t.closest("[data-atf-prev]")&&(e.preventDefault(),this.previous()),t.closest("[data-atf-repeater-add]")&&(e.preventDefault(),this.addRepeaterRow(t.closest("[data-atf-repeater]"))),t.closest("[data-atf-repeater-remove]")&&(e.preventDefault(),this.removeRepeaterRow(t.closest("[data-atf-repeater-row]"))),t.closest("[data-atf-resume]")&&(e.preventDefault(),this.saveForLater())}),this.form.addEventListener("blur",e=>{const t=e.target?.closest?.("[data-atf-field]");t&&this.validateField(t)},!0),this.form.querySelectorAll("[data-atf-signature]").forEach(e=>{this.initSignature(e)}),this.form.querySelectorAll(".atf-range__input").forEach(e=>{const t=e.parentElement?.querySelector(".atf-range__output");e.addEventListener("input",()=>{t&&(t.textContent=e.value)})}),this.initOtherToggles()}values(){const e={};for(const t of this.schema.fields)e[t.id]=this.readField(t);return e}readField(e){const t=this.fieldElement(e.id);if(!t)return null;if(e.type==="repeater")return this.readRepeater(e,t);const r=Array.from(t.querySelectorAll("input, select, textarea")).filter(o=>!o.disabled&&!o.closest("template"));if(!r.length)return null;if(["name","address","date_range","likert"].includes(e.type)){const o={};for(const l of r){const u=l.name.match(/\[([^\]]+)\]$/)?.[1];if(u){if(l instanceof HTMLInputElement&&(l.type==="radio"||l.type==="checkbox")){l.checked&&(o[u]=l.value);continue}o[u]=l.value}}return o}const n=r.filter(o=>o instanceof HTMLInputElement&&o.type==="checkbox");if(n.length)return n.length===1&&!n[0].name.endsWith("[]")?n[0].checked:n.filter(o=>o.checked).map(o=>o.value);const s=r.filter(o=>o instanceof HTMLInputElement&&o.type==="radio");if(s.length)return s.find(o=>o.checked)?.value??"";const i=r[0];return i instanceof HTMLSelectElement&&i.multiple?Array.from(i.selectedOptions).map(o=>o.value):i instanceof HTMLInputElement&&i.type==="file"?i.files&&i.files.length?[String(i.files.length)]:[]:i.value}readRepeater(e,t){const r=e.fields??[],n=[];return t.querySelectorAll("[data-atf-repeater-row]").forEach(s=>{const i={};for(const o of r)i[o.id]="";s.querySelectorAll("input, select, textarea").forEach(o=>{if(o.disabled)return;const l=o.name.match(/\[\d+\]\[([^\]]+)\]/);if(!l)return;const u=l[1];if(o instanceof HTMLInputElement&&o.type==="checkbox"){if(o.name.endsWith("[]")){const f=Array.isArray(i[u])?i[u]:[];o.checked&&f.push(o.value),i[u]=f;return}i[u]=o.checked;return}if(o instanceof HTMLInputElement&&o.type==="radio"){o.checked&&(i[u]=o.value);return}if(o instanceof HTMLSelectElement&&o.multiple){i[u]=Array.from(o.selectedOptions).map(f=>f.value);return}i[u]=o.value}),n.push(i)}),n}fieldElement(e){return this.form.querySelector(`[data-atf-field="${CSS.escape(e)}"]`)}onInput(e){const t=e.target;if(t?.closest("template"))return;this.started||(this.started=!0,this.reportStart()),this.update();const r=t?.closest("[data-atf-field]");r?.classList.contains("has-error")&&this.validateField(r)}update(){const e=this.values(),t=fe(this.schema.fields,e);for(const n of this.schema.fields){const s=this.fieldElement(n.id);if(!s)continue;const i=t[n.id]!==!1;s.hidden===i&&(s.hidden=!i),s.querySelectorAll("input, select, textarea").forEach(o=>{if(!o.closest("template")){if(o.hasAttribute("data-atf-other-input")){i||(o.disabled=!0);return}o.disabled=!i||o.hasAttribute("data-atf-total")}})}const r=Q(this.schema.fields,e);for(const n of this.schema.fields){if(!n.formula)continue;const s=this.fieldElement(n.id)?.querySelector("[data-atf-total]");if(!s)continue;const i=r[n.id],o=typeof n.decimals=="number"?n.decimals:2;s.value=typeof i=="number"?i.toFixed(o):"";const l=this.fieldElement(n.id)?.querySelector("[data-atf-total-value]");l&&(l.value=s.value)}}showStep(e,t=!0){if(!(this.pages.length<2)&&(this.step=Math.max(0,Math.min(this.pages.length-1,e)),this.pages.forEach((r,n)=>{r.hidden=n!==this.step,delete r.dataset.atfPageHidden}),this.updateProgress(),t)){const r=this.pages[this.step];r.setAttribute("tabindex","-1"),r.focus({preventScroll:!0}),r.scrollIntoView({behavior:"smooth",block:"start"})}}updateProgress(){const e=this.form.querySelector(".atf-progress--bar");if(e){const t=e.querySelector(".atf-progress__fill"),r=(this.step+1)/this.pages.length*100;t&&(t.style.width=`${r}%`),e.setAttribute("aria-valuenow",String(this.step+1))}this.form.querySelectorAll(".atf-progress__step").forEach((t,r)=>{t.classList.toggle("is-current",r===this.step),t.classList.toggle("is-done",ri.id===t);if(!r)return!0;if(r.type==="repeater")return this.validateRepeater(e,r);const n=this.readField(r),s=this.checkField(r,n);return this.setFieldError(e,s),s===""}validateRepeater(e,t){const r=t.fields??[],n=this.readField(t),s=Array.isArray(n)?n:[],i=Array.from(e.querySelectorAll("[data-atf-repeater-row]")),o=e.querySelector("[data-atf-repeater]")?.dataset.atfItemLabel||"";let l="";return i.forEach((u,f)=>{const m=s[f]??{},b=r.every(y=>A(m[y.id]??""));let h=!1;for(const y of r){const p=u.querySelector(`[data-atf-sub="${y.id}"]`);if(!p)continue;const c=b?"":this.checkField(y,m[y.id]??"");this.setFieldError(p,c),c!==""&&(h=!0,l===""&&(l=`${o} ${f+1}: ${c}`))}u.classList.toggle("has-error",h)}),this.setFieldError(e,l),l===""}checkField(e,t){const r=e.messages??{},n=A(t);if(e.required&&n)return r.required||g("required","This is required.");if(n)return"";if(typeof t=="string"){if(e.type==="email"&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t))return r.invalid||g("invalidEmail","That does not look like an email address.");if(e.type==="url"&&!/^https?:\/\/[^\s]+$/i.test(t))return r.invalid||g("invalidUrl","That does not look like a web address.");const s=Number(e.minlength),i=Number(e.maxlength);if(e.minlength&&t.lengthi)return r.max||g("tooLong","That is too long.");const o=typeof e.validation=="string"&&e.validation!==""&&e.validation!=="custom"?e.validation:"";if(o&&pe(o,t)===!1)return r.invalid||R(o)?.message||g("badFormat","That is not in the expected format.");if(e.pattern)try{if(!new RegExp(String(e.pattern)).test(t))return r.invalid||g("badFormat","That is not in the expected format.")}catch{}}if(t!==""&&!Number.isNaN(Number(t))&&typeof t!="boolean"&&!Array.isArray(t)){const s=Number(t);if(e.min!==void 0&&e.min!==""&&sNumber(e.max))return r.max||g("tooBig","That number is too large.")}if(Array.isArray(t)){const s=t.filter(i=>i!=="").length;if(e.minChoices&&sNumber(e.maxChoices))return r.max||g("tooBig","That is too many.")}return""}setFieldError(e,t){const r=e.querySelector(":scope > .atf-error")??e.querySelector(".atf-error");e.classList.toggle("has-error",t!==""),r&&(r.textContent=t,r.hidden=t===""),e.dataset.atfType!=="repeater"&&e.querySelectorAll("input, select, textarea").forEach(n=>{t===""?n.removeAttribute("aria-invalid"):n.setAttribute("aria-invalid","true")})}repeaterSubElement(e){const t=e.split(".");if(t.length!==3)return null;const[r,n,s]=t,i=this.fieldElement(r),o=this.schema.fields.find(y=>y.id===r);if(!i||!o||o.type!=="repeater")return null;const l=o.fields??[],u=this.readField(o),f=Array.isArray(u)?u:[],b=Array.from(i.querySelectorAll("[data-atf-repeater-row]")).filter((y,p)=>y&&!l.every(c=>A(f[p]?.[c.id]??"")))[Number(n)],h=b?.querySelector(`[data-atf-sub="${s}"]`)??null;return h&&b&&b.classList.add("has-error"),h}focusField(e){(e.querySelector("input, select, textarea")??e).focus?.({preventScroll:!0}),e.scrollIntoView({behavior:"smooth",block:"center"})}async onSubmit(e){if(this.pages.length>1&&this.stepl.contains(o))))}this.announceErrors(e.message),r&&(n>=0&&this.showStep(n,!1),this.focusField(r))}announceErrors(e=""){if(!this.errorSummary)return;const t=Array.from(this.form.querySelectorAll(".atf-field.has-error")).filter(s=>!s.closest("[data-atf-repeater]"));if(!t.length&&!e){this.errorSummary.hidden=!0;return}const r=(s,i="")=>{const o=this.labelTextOf(s),l=(s.querySelector(":scope > .atf-error")??s.querySelector(".atf-error"))?.textContent?.trim()??"";return`
  • ${_(i+(o?`${o}: ${l}`:l))}
  • `},n=t.map(s=>{const i=Array.from(s.querySelectorAll(".atf-repeater__field.has-error"));if(i.length){const o=this.labelTextOf(s),l=i[0].querySelector("input, select, textarea")?.id??"",u=i.map(f=>{const m=f.closest("[data-atf-repeater-row]")?.querySelector("[data-atf-repeater-title]")?.textContent?.trim();return r(f,m?`${m} — `:"")}).join("");return`
  • ${_(o)}
      ${u}
  • `}return r(s)}).join("");this.errorSummary.innerHTML=`

    ${_(e||g("errorsFound","There are problems to fix."))}

      ${n}
    `,this.errorSummary.hidden=!1,this.errorSummary.focus()}labelTextOf(e){const t=e.querySelector(".atf-label, legend, .atf-toggle__label");if(!t)return"";const r=t.cloneNode(!0);return r.querySelectorAll('.atf-required, [aria-hidden="true"]').forEach(n=>n.remove()),(r.textContent??"").replace(/\s+/g," ").trim().replace(/[.:;,]+$/,"")}showConfirmation(e){const t=e.confirmation??{};if(t.url){window.location.assign(t.url);return}if(!this.form.parentElement)return;const n=re(t.message??"",t.success);this.form.replaceWith(n),ne(n,t.success),n.focus(),n.scrollIntoView({behavior:"smooth",block:"center"}),document.dispatchEvent(new CustomEvent("alltfo-submitted",{detail:{formId:Number(this.form.dataset.atfForm),entryId:e.entry_id},bubbles:!0}))}async saveForLater(){const e=this.form.querySelector("[data-atf-resume]"),t=this.form.querySelector("[data-atf-resume-token]");e&&(e.disabled=!0);try{const r=new FormData(this.form),s=await(await fetch(`${v?.restUrl??""}/resume`,{method:"POST",body:r,credentials:"same-origin",headers:v?.nonce?{"X-WP-Nonce":v.nonce}:{}})).json();if(!s.success||!s.url){this.showResumeMessage(s.message??g("failed","That did not save. Please try again."),"");return}t&&s.token&&(t.value=s.token),this.showResumeMessage(s.days?`Saved. Come back to this within ${s.days} days using the link below.`:"Saved. Come back using the link below.",s.url)}catch{this.showResumeMessage(g("failed","That did not save. Please try again."),"")}finally{e&&(e.disabled=!1)}}showResumeMessage(e,t){this.form.querySelector(".atf-resume-panel")?.remove();const r=document.createElement("div");r.className="atf-resume-panel",r.setAttribute("role","status"),r.setAttribute("tabindex","-1");const n=document.createElement("p");if(n.textContent=e,r.append(n),t){const s=document.createElement("input");s.type="text",s.className="atf-input",s.readOnly=!0,s.value=t,s.setAttribute("aria-label","Your link back to this form"),s.addEventListener("focus",()=>s.select()),r.append(s)}this.form.querySelector(".atf-actions")?.after(r),r.focus()}reportStart(){const e=Number(this.form.dataset.atfForm);!e||!v?.restUrl||fetch(`${v.restUrl}/track`,{method:"POST",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({form_id:e,event:"start"})}).catch(()=>{})}addRepeaterRow(e){if(!e)return;const t=e.querySelector(".atf-repeater__rows"),r=e.querySelector("[data-atf-repeater-template]"),n=Number(e.dataset.atfMax??10);if(!t||!r||t.querySelectorAll("[data-atf-repeater-row]").length>=n)return;const s=H(t),i=r.content.cloneNode(!0);i.querySelectorAll("[name], [id], [for]").forEach(l=>{for(const u of["name","id","for"]){const f=l.getAttribute(u);f?.includes("__INDEX__")&&l.setAttribute(u,f.replace(/__INDEX__/g,String(s)))}}),t.appendChild(i),t.lastElementChild?.querySelector("input, select, textarea")?.focus(),this.renumberRepeater(e),this.update()}renumberRepeater(e){const t=e.dataset.atfItemLabel??"";e.querySelectorAll("[data-atf-repeater-row]").forEach((r,n)=>{const s=`${t} ${n+1}`.trim(),i=r.querySelector("[data-atf-repeater-title]");i&&(i.textContent=s),r.setAttribute("aria-label",s)})}removeRepeaterRow(e){const t=e?.closest("[data-atf-repeater]");if(!e||!t)return;const r=t.querySelectorAll("[data-atf-repeater-row]"),n=Number(t.dataset.atfMin??1);if(r.length<=n){e.querySelectorAll("input, select, textarea").forEach(i=>{i.value=""}),this.update();return}const s=e.nextElementSibling??e.previousElementSibling;e.remove(),s?.querySelector("input, select, textarea")?.focus(),this.renumberRepeater(t),this.update()}initSignature(e){const t=e.querySelector("canvas"),r=e.querySelector('input[type="hidden"]'),n=e.querySelector("[data-atf-signature-clear]"),s=t?.getContext("2d");if(!t||!r||!s)return;s.lineWidth=2,s.lineCap="round",s.lineJoin="round",s.strokeStyle=getComputedStyle(e).color||"#000";let i=!1;const o=u=>{const f=t.getBoundingClientRect();return{x:(u.clientX-f.left)/f.width*t.width,y:(u.clientY-f.top)/f.height*t.height}};t.addEventListener("pointerdown",u=>{i=!0,t.setPointerCapture(u.pointerId);const{x:f,y:m}=o(u);s.beginPath(),s.moveTo(f,m)}),t.addEventListener("pointermove",u=>{if(!i)return;const{x:f,y:m}=o(u);s.lineTo(f,m),s.stroke()});const l=()=>{i&&(i=!1,r.value=t.toDataURL("image/png"),r.dispatchEvent(new Event("change",{bubbles:!0})))};t.addEventListener("pointerup",l),t.addEventListener("pointercancel",l),t.addEventListener("pointerleave",l),n?.addEventListener("click",()=>{s.clearRect(0,0,t.width,t.height),r.value="",r.dispatchEvent(new Event("change",{bubbles:!0}))})}initOtherToggles(){const e=()=>{this.form.querySelectorAll(".atf-choice--other").forEach(t=>{const r=t.querySelector("[data-atf-other-toggle]"),n=t.querySelector("[data-atf-other-input]");!r||!n||(n.disabled=!r.checked,n.hidden=!r.checked)})};this.form.addEventListener("change",e),e()}}function _(a){const e=document.createElement("div");return e.textContent=a,e.innerHTML}function H(a){let e=-1;return a.querySelectorAll("[data-atf-repeater-row] [name]").forEach(t=>{const r=/^atf\[[^\]]*\]\[(\d+)\]/.exec(t.getAttribute("name")??"");r&&(e=Math.max(e,Number(r[1])))}),e+1}function me(a){const e=a.dataset.atfInstance??"",t=document.getElementById(`${e}-schema`);if(!t?.textContent)return null;try{return JSON.parse(t.textContent)}catch{return null}}function k(){document.querySelectorAll("form[data-atf-form]").forEach(a=>{if(a.dataset.atfBooted)return;const e=me(a);if(e){a.dataset.atfBooted="1";try{new O(a,e)}catch(t){console.error("[AllTerrain Forms] Could not enhance a form.",t)}}})}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",k):k(),document.addEventListener("alltfo-refresh",k),S.AllTerrainForm=O,S.boot=k,S.nextRepeaterIndex=H,Object.defineProperty(S,Symbol.toStringTag,{value:"Module"}),S}({}); diff --git a/docs/field-types.md b/docs/field-types.md index 02e1c2b..af6fb24 100644 --- a/docs/field-types.md +++ b/docs/field-types.md @@ -322,3 +322,14 @@ add_filter( 'alltfo_client_schema', function ( $payload, $schema ) { return $payload; }, 10, 2 ); ``` + +### Total display + +The Total inspector offers **Display total as**: **Plain text** or **Disabled +input**. The `display` setting accepts `output` or `input` (the default, also used +for older forms and invalid values). Plain text renders a semantic `` +with the field label attached; input mode renders a disabled text input. Both +use the form theme, currency symbol and decimal precision and update live. +A hidden `atf[field_id]` input preserves the calculated value for submission and +integrations. The server recomputes it from the source answers in both modes. +The builder canvas reflects the selected presentation. diff --git a/docs/javascript.md b/docs/javascript.md index b9936ca..c801630 100644 --- a/docs/javascript.md +++ b/docs/javascript.md @@ -318,10 +318,13 @@ editor continues to calculate its numeric result using the displayed sample answers. **Conditional** is a compact button beside Required/Optional in each field -card’s title bar. It opens a dialog with an enable switch, Show/Hide, all/any, -and the full rule editor. Changes stay in a draft until **Save conditions**; -Cancel or Escape discards them. Copy condition inside the dialog also edits -only this draft. An active condition is indicated by the button’s filled dot. +card’s title bar. It opens a dialog with Show/Hide, all/any, +and the full rule editor, ready to add conditions without an enable checkbox. +Changes stay in a draft until **Save conditions**, which enables the condition; +Cancel or Escape discards them. **Clear** removes the saved rules, disables the +condition, and closes the dialog. Cancel is absent when neither the saved +condition nor the draft has rules; Save is disabled for an empty draft. Copy condition inside the dialog also edits +only this draft and enables the copied rules when saved. An active condition is indicated by the button’s filled dot. The bottom condition strip remains directly editable. The `+ Add rule` button adds a rule, each rule has a Delete button, and Clear removes all rules while diff --git a/includes/field-types.php b/includes/field-types.php index 2b2312c..474e930 100644 --- a/includes/field-types.php +++ b/includes/field-types.php @@ -687,6 +687,7 @@ static function ( $item ) { 'formula' => '', 'currency' => '', 'decimals' => 2, + 'display' => 'input', ), 'format' => 'alltfo_format_total_value', 'position' => 20, diff --git a/includes/render-controls.php b/includes/render-controls.php index b68efcc..6b8bd9d 100644 --- a/includes/render-controls.php +++ b/includes/render-controls.php @@ -1087,10 +1087,8 @@ function alltfo_render_repeater_row( $field, $sub_fields, $row, $index, $context /** * A calculated total. * - * `readonly` rather than `disabled`, because a disabled input is not submitted - * and the value would never reach the entry. The server recomputes it anyway, - * so a tampered value is discarded -- but a missing one would look like a form - * that forgot to collect its own total. + * The display is an output or a disabled input. A hidden input carries the + * browser's value for integrations; the server always recomputes the total. * * @since 0.1.0 * @@ -1100,16 +1098,29 @@ function alltfo_render_repeater_row( $field, $sub_fields, $row, $index, $context * @return string */ function alltfo_render_total( $field, $value, $context ) { - return alltfo_render_label( $field, $context['id'] ) . sprintf( - '
    %s
    ', - ! empty( $field['currency'] ) ? sprintf( '', esc_html( $field['currency'] ) ) : '', + $text = is_scalar( $value ) ? (string) $value : ''; + $output = isset( $field['display'] ) && 'output' === $field['display']; + $attrs = sprintf( + ' id="%s" data-atf-total data-atf-formula="%s" data-atf-decimals="%d"', esc_attr( $context['id'] ), - esc_attr( 'atf[' . $field['id'] . ']' ), - esc_attr( is_scalar( $value ) ? (string) $value : '' ), esc_attr( isset( $field['formula'] ) ? $field['formula'] : '' ), isset( $field['decimals'] ) ? absint( $field['decimals'] ) : 2 ); + if ( ! empty( $context['describedby'] ) ) { + $attrs .= sprintf( ' aria-describedby="%s"', esc_attr( $context['describedby'] ) ); + } + + $control = $output + ? '' . esc_html( $text ) . '' + : ''; + + return alltfo_render_label( $field, $context['id'] ) . sprintf( + '
    %s%s
    ', + ! empty( $field['currency'] ) ? sprintf( '%s', esc_html( $field['currency'] ) ) : '', + $control, + esc_attr( 'atf[' . $field['id'] . ']' ), + esc_attr( $text ) + ); } /** diff --git a/includes/schema.php b/includes/schema.php index f0b332b..fa73f5a 100644 --- a/includes/schema.php +++ b/includes/schema.php @@ -264,6 +264,10 @@ function alltfo_normalize_field( $raw, $seen = array() ) { $field[ $key ] = alltfo_coerce_setting( $raw[ $key ], $fallback ); } + if ( 'total' === $type ) { + $field['display'] = isset( $field['display'] ) && 'output' === $field['display'] ? 'output' : 'input'; + } + // Validation bounds are common enough to live on the field rather than in // every type's settings, and they are all optional: an empty string means // "no bound", which is why they are not cast to int here. diff --git a/package-lock.json b/package-lock.json index d3d2de9..d5ebb59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "allterrain-forms", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "allterrain-forms", - "version": "1.0.0", + "version": "1.0.1", "license": "GPL-2.0-or-later", "devDependencies": { "@wordpress/env": "^10.0.0", diff --git a/package.json b/package.json index ecee649..c9530f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "allterrain-forms", - "version": "1.0.0", + "version": "1.0.1", "private": true, "description": "Forms for WordPress with every premium feature free, as an OpenStation desktop app.", "license": "GPL-2.0-or-later", diff --git a/readme.txt b/readme.txt index 2688775..9d484bf 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Requires at least: 6.9 Tested up to: 7.1 Requires PHP: 7.4 Requires Plugins: desktop-mode -Stable tag: 1.0.0 +Stable tag: 1.0.1 License: GPL-2.0-or-later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -325,6 +325,12 @@ API, importer hooks, and a REST namespace. Full reference in the repository. == Changelog == += 1.0.1 = +* Align Copy condition with the condition settings and use the desktop theme's dialog palette and textures. +* Open conditional logic directly into rule editing, without a separate enable checkbox. +* Add Clear to remove and disable conditions, and hide Cancel for new conditions with no rules. +* Display calculated totals as plain text or disabled inputs while preserving live calculations and submitted values. + = 1.0.0 = * Open the searchable value selector by typing { in calculation and merge-tag inputs. * Preview references as descriptive values instead of invented answers. @@ -340,6 +346,9 @@ API, importer hooks, and a REST namespace. Full reference in the repository. == Upgrade Notice == += 1.0.1 = +Improved conditional dialogs and theme support. Totals can display as plain text or disabled inputs; existing totals keep their input presentation. + = 1.0.0 = Improved formula selection and conditional editing. Existing forms and saved conditions retain their format and behavior. diff --git a/src/builder.ts b/src/builder.ts index fd2e019..db8d671 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -2610,7 +2610,8 @@ export class Builder { if ( ! field ) { return; } - const draft: Logic = { ...field.logic, rules: field.logic.rules.map( ( rule ) => ( { ...rule } ) ) }; + const hadRules = field.logic.rules.length > 0; + const draft: Logic = { ...field.logic, enabled: true, rules: field.logic.rules.map( ( rule ) => ( { ...rule } ) ) }; const overlay = el( 'div', { class: 'atfb-overlay' } ); const dialog = el( 'div', { class: 'atfb-modal atfb-condition-editor', @@ -2637,7 +2638,7 @@ export class Builder { } ); match.setAttribute( 'aria-label', 'Match rules' ); const copy = el( 'button', { - class: 'atfb-copy-condition', type: 'button', + class: 'atfb-button atfb-copy-condition', type: 'button', children: [ icon( 'admin-page' ), el( 'span', { text: 'Copy condition' } ) ], on: { click: () => openConditionCopy( { root: overlay, @@ -2646,7 +2647,7 @@ export class Builder { ...this.schema, fields: this.schema.fields.map( ( item ) => item.id === fieldId ? { ...item, logic: draft } : item ), } : null, - onCopy: () => { paint(); dialog.focus(); }, + onCopy: () => { draft.enabled = true; paint(); dialog.focus(); }, } ) }, } ); dialog.replaceChildren( @@ -2654,23 +2655,21 @@ export class Builder { el( 'span', { class: 'atfb-condition-editor__icon', children: [ icon( 'randomize' ) ] } ), el( 'div', { children: [ el( 'h2', { text: 'Conditional logic' } ), el( 'p', { text: field.label || 'Untitled field' } ) ] } ), ] } ), - el( 'div', { class: 'atfb-condition-editor__switch', children: [ - checkbox( 'Enable conditions', draft.enabled, ( enabled ) => { - draft.enabled = enabled; - paint(); - } ), - el( 'p', { text: 'Choose when this field appears in your form.' } ), - ] } ), - ...( draft.enabled ? [ - el( 'div', { class: 'atfb-condition-editor__sentence', children: [ action, 'this field when', match, 'of these rules match:' ] } ), - ...this.logicRulesEditor( draft, write, fieldId ), - ] : [ el( 'p', { class: 'atfb-condition-editor__empty', text: 'This field is always visible. Enable conditions to choose when to show or hide it.' } ) ] ), + el( 'p', { class: 'atfb-hint', text: 'Choose when this field appears in your form.' } ), + el( 'div', { class: 'atfb-condition-editor__sentence', children: [ action, 'this field when', match, 'of these rules match:' ] } ), + ...this.logicRulesEditor( draft, write, fieldId ), el( 'div', { class: 'atfb-condition-editor__footer', children: [ copy, el( 'div', { class: 'atfb-modal__actions', children: [ - button( 'Cancel', close ), + button( 'Clear', () => { + this.snapshot(); + this.editCondition( fieldId, ( live ) => Object.assign( live, { enabled: false, action: 'show', match: 'all', rules: [] } ) ); + this.snapshot(); + close(); + } ), + ...( hadRules || draft.rules.length ? [ button( 'Cancel', close ) ] : [] ), button( 'Save conditions', () => { - if ( ! this.liveField( fieldId ) ) { + if ( ! this.liveField( fieldId ) || ! draft.rules.length ) { close(); return; } @@ -2682,6 +2681,9 @@ export class Builder { ] } ), ] } ) ); + if ( ! draft.rules.length ) { + dialog.querySelector( '.atfb-button--primary' )?.setAttribute( 'disabled', '' ); + } if ( focusedIndex >= 0 ) { const controls = dialog.querySelectorAll< HTMLElement >( controlsSelector ); controls[ Math.min( focusedIndex, controls.length - 1 ) ]?.focus(); @@ -3879,6 +3881,14 @@ export class Builder { ); } + if ( field.type === 'total' ) { + this.inspector.append( row( 'Display total as', select( + String( field.display ?? 'input' ), + [ { value: 'output', label: 'Plain text' }, { value: 'input', label: 'Disabled input' } ], + ( value ) => update( 'display', value ) + ) ) ); + } + this.inspector.append( this.renderValidationSection( field, supports, update ) ); // Conditional logic and prefill act on top-level answers: the logic @@ -4867,7 +4877,7 @@ export class Builder { /** Reuse a condition, resolving the schema when the chooser applies it. */ private copyConditionButton( key: string ): HTMLElement { return el( 'button', { - class: 'atfb-copy-condition', type: 'button', + class: 'atfb-button atfb-copy-condition', type: 'button', children: [ icon( 'admin-page' ), el( 'span', { text: 'Copy condition' } ) ], on: { click: () => openConditionCopy( { root: this.root, @@ -4925,7 +4935,6 @@ export class Builder { `logic:${ field.id }`, 'Conditional logic', [ - this.copyConditionButton( `field:${ field.id }` ), checkbox( 'Only show this field sometimes', logic.enabled, ( value ) => { write( ( live ) => { live.enabled = value; @@ -4967,6 +4976,7 @@ export class Builder { ], } ) : null, + el( 'div', { class: 'atfb-logic-actions', children: [ this.copyConditionButton( `field:${ field.id }` ) ] } ), ], // A field that already has a condition opens showing it: being told a // rule governs this field and not what it says is the problem the diff --git a/src/field-preview.ts b/src/field-preview.ts index dafc7c4..566c490 100644 --- a/src/field-preview.ts +++ b/src/field-preview.ts @@ -44,6 +44,7 @@ import type { Field, FieldType } from './types'; /** The visual families a field can be drawn as. */ export type PreviewShape = + | 'total' | 'text' | 'textarea' | 'select' @@ -94,7 +95,7 @@ const SHAPES: Record< string, PreviewShape > = { color: 'text', name: 'composite', address: 'composite', - total: 'text', + total: 'total', hidden: 'static', heading: 'static', html: 'static', @@ -347,6 +348,14 @@ function control( handlers: PreviewHandlers ): HTMLElement | null { switch ( shape ) { + case 'total': + return el( 'div', { class: 'atf-total', children: [ + field.currency ? el( 'span', { class: 'atf-total__currency', text: String( field.currency ) } ) : null, + field.display === 'output' + ? el( 'output', { class: 'atf-total__output', text: '0.00' } ) + : el( 'input', { class: 'atf-input atf-total__input', type: 'text', value: '0.00', attrs: { disabled: true } } ), + ] } ); + case 'text': return placeholderBox( field, 'atf-input', handlers ); diff --git a/src/form.ts b/src/form.ts index 8b19eee..71d26ac 100644 --- a/src/form.ts +++ b/src/form.ts @@ -379,7 +379,7 @@ class AllTerrainForm { return; } - input.disabled = ! show; + input.disabled = ! show || input.hasAttribute( 'data-atf-total' ); } ); } @@ -390,7 +390,7 @@ class AllTerrainForm { continue; } - const input = this.fieldElement( field.id )?.querySelector< HTMLInputElement >( '[data-atf-total]' ); + const input = this.fieldElement( field.id )?.querySelector< HTMLInputElement | HTMLOutputElement >( '[data-atf-total]' ); if ( ! input ) { continue; @@ -400,6 +400,10 @@ class AllTerrainForm { const decimals = typeof field.decimals === 'number' ? field.decimals : 2; input.value = typeof value === 'number' ? value.toFixed( decimals ) : ''; + const submitted = this.fieldElement( field.id )?.querySelector< HTMLInputElement >( '[data-atf-total-value]' ); + if ( submitted ) { + submitted.value = input.value; + } } } diff --git a/tests/phpunit/tests/render.php b/tests/phpunit/tests/render.php index 231ff08..3c5a72e 100644 --- a/tests/phpunit/tests/render.php +++ b/tests/phpunit/tests/render.php @@ -46,6 +46,60 @@ private function render_field( $field ) { return alltfo_render_form( $form_id ); } + /** + * Totals offer a labelled output or disabled input with one submitted value. + * + * @covers ::alltfo_render_total + */ + public function test_total_display_modes() { + foreach ( array( 'input', 'output' ) as $display ) { + $html = $this->render_field( + array( + 'type' => 'total', + 'display' => $display, + 'formula' => '2 + 3', + 'currency' => '€', + ) + ); + $dom = new DOMDocument(); + $previous = libxml_use_internal_errors( true ); + $dom->loadHTML( $html ); + libxml_clear_errors(); + libxml_use_internal_errors( $previous ); + $xpath = new DOMXPath( $dom ); + $node = $xpath->query( '//*[@data-atf-total]' )->item( 0 ); + $this->assertSame( 1, $xpath->query( '//' . $display . '[@data-atf-total]' )->length ); + $this->assertSame( 1, $xpath->query( '//label[@for="' . $node->getAttribute( 'id' ) . '"]' )->length ); + $this->assertSame( 1, $xpath->query( '//input[@name="atf[f1]"]' )->length ); + $this->assertSame( 1, $xpath->query( '//input[@type="hidden"][@data-atf-total-value]' )->length ); + if ( 'input' === $display ) { + $this->assertTrue( $node->hasAttribute( 'disabled' ) ); + } + } + } + + /** + * Rendered amounts and currency cannot inject HTML. + * + * @covers ::alltfo_render_total + */ + public function test_total_escapes_display_values() { + foreach ( array( 'input', 'output' ) as $display ) { + $field = alltfo_normalize_field( + array( + 'id' => 'total', + 'type' => 'total', + 'display' => $display, + ), + array() + ); + $field['currency'] = ''; + $html = alltfo_render_total( $field, '', array( 'id' => 'total' ) ); + $this->assertStringNotContainsString( '`; + boot(); + const form = document.querySelector( 'form' )!; + const output = form.querySelector< HTMLInputElement | HTMLOutputElement >( '[data-atf-total]' )!; + expect( output.value ).toBe( '5.00' ); + expect( new FormData( form ).getAll( 'atf[total]' ) ).toEqual( [ '5.00' ] ); + expect( new FormData( form ).get( 'atf[grand]' ) ).toBe( '6.00' ); + const qty = form.querySelector< HTMLInputElement >( '[name="atf[qty]"]' )!; + qty.value = '0'; + qty.dispatchEvent( new Event( 'input', { bubbles: true } ) ); + expect( new FormData( form ).has( 'atf[total]' ) ).toBe( false ); + qty.value = '3'; + qty.dispatchEvent( new Event( 'input', { bubbles: true } ) ); + expect( output.value ).toBe( '7.50' ); + expect( new FormData( form ).getAll( 'atf[total]' ) ).toEqual( [ '7.50' ] ); + expect( new FormData( form ).get( 'atf[grand]' ) ).toBe( '8.50' ); + if ( output instanceof HTMLInputElement ) expect( output.disabled ).toBe( true ); + else expect( output.textContent ).toBe( '7.50' ); + } ); + + it( 'reflects the display and currency on the builder canvas', () => { + const field: Field = { + id: 'total', type: 'total', label: 'Total', currency: '€', display, + placeholder: '', hint: '', required: false, width: 'full', cssClass: '', default: '', choices: [], + logic: { enabled: false, action: 'show', match: 'all', rules: [] }, messages: {}, prefill: '', + }; + const preview = renderFieldPreview( field, undefined, { edit: () => {}, restructure: () => {} } ); + expect( preview.querySelector( '.atf-total__currency' )!.textContent ).toBe( '€' ); + expect( preview.querySelector( display === 'output' ? 'output.atf-total__output' : 'input.atf-total__input:disabled' ) ).not.toBeNull(); + expect( preview.querySelector( '[data-atfb-bind="placeholder"]' ) ).toBeNull(); + } ); +} );