diff --git a/assets/css/builder.css b/assets/css/builder.css index 03d67fe..f47f6b8 100644 --- a/assets/css/builder.css +++ b/assets/css/builder.css @@ -482,14 +482,21 @@ background: var( --atfb-accent-soft ); } +/* A field card is a miniature of the window that contains it: the shell's own + window chrome — radius, border, shadow, title bar — at card scale. Selecting + a card focuses it the way clicking a window focuses one: its title bar takes + the focused titlebar surface and ink, the rest stay back. Every value reads + the same `--os-window-*` / `--os-titlebar-*` tokens the real chrome reads, + with the old flat-card values as the no-shell fallbacks. */ .atfb-card { + --atfb-card-r: var( --os-window-radius, var( --atfb-radius ) ); + display: flex; - align-items: center; - gap: 10px; - padding: 10px 12px; - border: 1px solid var( --atfb-card-border ); - border-radius: var( --atfb-radius ); - background: var( --atfb-bg ); + flex-direction: column; + border: 1px solid var( --os-window-border, var( --atfb-card-border ) ); + border-radius: var( --atfb-card-r ); + background: var( --os-window-bg, var( --atfb-bg ) ); + box-shadow: var( --os-window-shadow, none ); cursor: grab; touch-action: none; transition: border-color 120ms ease, box-shadow 120ms ease; @@ -497,15 +504,11 @@ .atfb-card:hover { border-color: var( --atfb-accent ); - - /* The shell's own card lift, so a card rising under the pointer here rises - exactly as far as a card anywhere else on the desktop. */ - box-shadow: var( --os-ui-card-shadow-hover, 0 4px 16px rgba( 0, 0, 0, 0.08 ) ); } .atfb-card.is-selected { border-color: var( --atfb-accent ); - box-shadow: 0 0 0 2px var( --atfb-accent-soft ); + box-shadow: var( --os-window-shadow-focused, 0 0 0 2px var( --atfb-accent-soft ) ); } .atfb-card:focus-visible { @@ -513,14 +516,41 @@ outline-offset: 2px; } +/* The card's title bar. Unselected cards wear the unfocused titlebar surface, + the selected one wears the focused surface — the same reading the desktop + gives a stack of windows. Corners are rounded to sit inside the card's own + border rather than clipping the whole card with `overflow`, which would + shave the preview's halo below. */ +.atfb-card__bar { + display: flex; + align-items: center; + gap: 8px; + padding: 5px 8px 5px 10px; + min-block-size: 30px; + border-start-start-radius: calc( var( --atfb-card-r ) - 1px ); + border-start-end-radius: calc( var( --atfb-card-r ) - 1px ); + border-block-end: 1px solid var( --os-window-border, var( --atfb-border ) ); + background: var( --os-titlebar-bg, var( --atfb-raised ) ); + color: var( --os-titlebar-color, var( --atfb-muted ) ); +} + +.atfb-card.is-selected .atfb-card__bar { + background: var( --os-titlebar-bg-focused, var( --atfb-accent ) ); + color: var( --os-titlebar-color-focused, var( --atfb-accent-ink ) ); + border-block-end-color: transparent; +} + .atfb-card__grip { - color: var( --atfb-muted ); + color: inherit; + opacity: 0.75; flex: 0 0 auto; + display: inline-flex; } .atfb-card__body { flex: 1 1 auto; min-inline-size: 0; + padding: 2px 12px 8px; } .atfb-card__head { @@ -528,6 +558,7 @@ align-items: center; gap: 6px; min-inline-size: 0; + flex: 1 1 auto; } .atfb-card__head strong { @@ -539,12 +570,44 @@ .atfb-card__type { display: block; font-size: 11px; - color: var( --atfb-muted ); + color: inherit; +} + +/* On the bar, the switch and the badge draw with the bar's own ink — a + translucent wash of whatever colour the titlebar text is — because the + accent washes they normally wear vanish against the focused titlebar, + which may itself be the accent. */ +.atfb-card__bar .atfb-req { + border-color: color-mix( in srgb, currentColor 35%, transparent ); + color: inherit; +} + +.atfb-card__bar .atfb-req:hover { + border-color: currentColor; + color: inherit; +} + +.atfb-card__bar .atfb-req.is-on { + background: color-mix( in srgb, currentColor 18%, transparent ); + border-color: transparent; + color: inherit; + font-weight: 700; +} + +.atfb-card__bar .atfb-req:focus-visible { + outline: 2px solid currentColor; + outline-offset: 1px; +} + +.atfb-card__bar .atfb-badge { + background: color-mix( in srgb, currentColor 14%, transparent ); + color: inherit; } .atfb-card__actions { display: flex; gap: 2px; + flex: 0 0 auto; opacity: 0; transition: opacity 120ms ease; } @@ -555,30 +618,42 @@ } /* Never hidden from the keyboard. `opacity: 0` keeps the buttons focusable, - where `display: none` would make them unreachable without a pointer. */ + where `display: none` would make them unreachable without a pointer. + + Colour and hover are the titlebar-button tokens, because these sit where a + window's controls sit and should press like them. */ .atfb-card__action { border: 0; background: transparent; - color: var( --atfb-muted ); + color: var( --os-titlebar-btn-color, currentColor ); padding: 4px; border-radius: 4px; cursor: pointer; line-height: 1; } +.atfb-card.is-selected .atfb-card__action { + color: var( --os-titlebar-btn-focused-color, currentColor ); +} + .atfb-card__action:hover { - background: var( --atfb-accent-soft ); - color: var( --atfb-fg ); + background: var( --os-titlebar-btn-bg-hover, var( --atfb-accent-soft ) ); + color: var( --os-titlebar-btn-color-hover, var( --atfb-fg ) ); +} + +.atfb-card.is-selected .atfb-card__action:hover { + background: var( --os-titlebar-btn-focused-bg-hover, color-mix( in srgb, currentColor 18%, transparent ) ); + color: var( --os-titlebar-btn-focused-color-hover, inherit ); } /* Deleting is the one card action that should look like what it does. */ .atfb-card__action[ aria-label="Delete" ]:hover { - background: var( --atfb-danger-soft ); - color: var( --atfb-danger ); + background: var( --atfb-danger ); + color: #fff; } .atfb-card__action:focus-visible { - outline: 2px solid var( --atfb-accent ); + outline: 2px solid currentColor; opacity: 1; } @@ -2698,21 +2773,8 @@ os-checkbox-label.atfb-check { } } -/* The card is now as tall as the field it draws, so its furniture aligns to the - top rather than floating at the middle of a five-option list. */ -.atfb-card { - align-items: flex-start; -} - -.atfb-card__grip, -.atfb-card__actions { - margin-block-start: 2px; -} - -.atfb-card__body { - min-inline-size: 0; - flex: 1 1 auto; -} +/* The furniture that used to float beside the field lives in the card's title + bar now — the bar handles its own alignment, so nothing to correct here. */ /* -------------------------------------------------------------------------- */ /* The window body never scrolls */ diff --git a/assets/js/builder.js b/assets/js/builder.js index fb827ec..3756d9c 100644 --- a/assets/js/builder.js +++ b/assets/js/builder.js @@ -5955,14 +5955,19 @@ var allTerrainFormsBuilder = function(exports) { "aria-label": `${field.label || type?.label || field.type}, ${index + 1} of ${this.schema?.fields.length ?? 0}` }, children: [ + // The card is a miniature of the window that contains it: a title + // bar carrying the grip, the field's identity and the actions, + // with the field itself as the window body below. The bar is one + // element rather than three floated ones so the shell's titlebar + // surface can paint across it edge to edge. el("div", { - class: "atfb-card__grip", - attrs: { "aria-hidden": "true" }, - children: [icon("menu")] - }), - el("div", { - class: "atfb-card__body", + class: "atfb-card__bar", children: [ + el("div", { + class: "atfb-card__grip", + attrs: { "aria-hidden": "true" }, + children: [icon("menu")] + }), el("div", { class: "atfb-card__head", children: [ @@ -5976,6 +5981,18 @@ var allTerrainFormsBuilder = function(exports) { }) : null ] }), + el("div", { + class: "atfb-card__actions", + children: [ + this.cardAction("admin-page", "Duplicate", () => this.duplicateField(field.id)), + this.cardAction("trash", "Delete", () => void this.deleteField(field.id)) + ] + }) + ] + }), + el("div", { + class: "atfb-card__body", + children: [ // The field itself, drawn with the real front-end classes and the // form's own theme, with its text editable where it sits. renderFieldPreview(field, type, { @@ -6015,13 +6032,6 @@ var allTerrainFormsBuilder = function(exports) { }), condition.length ? this.renderCondition(field, condition) : null ] - }), - el("div", { - class: "atfb-card__actions", - children: [ - this.cardAction("admin-page", "Duplicate", () => this.duplicateField(field.id)), - this.cardAction("trash", "Delete", () => void this.deleteField(field.id)) - ] }) ] }); diff --git a/assets/js/builder.min.js b/assets/js/builder.min.js index 66d78ba..65b31ed 100644 --- a/assets/js/builder.min.js +++ b/assets/js/builder.min.js @@ -1,3 +1,3 @@ var allTerrainFormsBuilder=function(ee){"use strict";class Wt{constructor(){this.targets=[],this.active=null,this.lastEndMs=0}start(e){if(this.active||e.origin.button!==0)return null;const{payload:t,origin:s}=e,n=s.clientX,i=s.clientY;let o=!1,l=!1,c=null,d=null,h=0,v=0;const y=()=>{document.removeEventListener("pointermove",f),document.removeEventListener("pointerup",E),document.removeEventListener("pointercancel",N),document.removeEventListener("keydown",k),window.removeEventListener("blur",N),c?.remove(),c=null,t.source.classList.remove("atf-is-dragging"),d?.onLeave?.(u),d=null,this.active=null,this.lastEndMs=Date.now()},u={payload:t,isFinished:()=>l,cancel:(T="caller")=>{l||(l=!0,y(),e.onCancel?.(T))}},x=T=>{o=!0,t.source.classList.add("atf-is-dragging");const M=t.source.getBoundingClientRect();h=t.ghost?.offsetX??n-M.left,v=t.ghost?.offsetY??i-M.top,c=t.ghost?.element??t.source.cloneNode(!0),c.classList.add("atf-drag-ghost"),c.style.width=`${M.width}px`,document.body.appendChild(c),g(T)},g=T=>{c&&(c.style.transform=`translate3d(${T.clientX-h}px, ${T.clientY-v}px, 0)`)},f=T=>{if(l)return;if(!o){if(Math.hypot(T.clientX-n,T.clientY-i)<4)return;x(T)}g(T);const M=this.hitTest(T.clientX,T.clientY);M!==d&&(d?.onLeave?.(u),d=M,d?.onEnter?.(u))},E=T=>{if(l)return;if(!o){l=!0,y(),e.onClickOnly?.();return}const M=d;if(l=!0,y(),M&&M.accept(t)){e.onCommit?.(M),M.onDrop(u,{clientX:T.clientX,clientY:T.clientY});return}e.onCancel?.(M?"rejected":"no-target")},N=()=>u.cancel("pointercancel"),k=T=>{T.key==="Escape"&&u.cancel("escape")};return document.addEventListener("pointermove",f),document.addEventListener("pointerup",E),document.addEventListener("pointercancel",N),document.addEventListener("keydown",k),window.addEventListener("blur",N),this.active=u,u}registerDropTarget(e){return this.targets=this.targets.filter(t=>t.id!==e.id),this.targets.push(e),()=>{this.targets=this.targets.filter(t=>t.id!==e.id)}}isDragging(){return this.active!==null}recentlyEndedDrag(e=500){return Date.now()-this.lastEndMso.right||to.bottom)continue;const l=Ut(i.element);if(l>n){s=i,n=l;continue}l===n&&s&&zt(i.element,s.element)&&(s=i)}return s}}function Ut(a){let e=0,t=a;for(;t;)e++,t=t.parentElement;return e}function zt(a,e){return(e.compareDocumentPosition(a)&Node.DOCUMENT_POSITION_FOLLOWING)!==0}function ke(){return window.wp?.os??null}let Se=null;function K(){const a=ke();return a?.dragManager?a.dragManager:(Se||(Se=new Wt),Se)}function Yt(a){const e=n=>{const i=n.detail?.payload;return i&&a.includes(i.type)?i.source:null},t=n=>e(n)?.classList.add("atf-is-dragging"),s=n=>e(n)?.classList.remove("atf-is-dragging");return document.addEventListener("os.drag.start",t),document.addEventListener("os.drag.end",s),()=>{document.removeEventListener("os.drag.start",t),document.removeEventListener("os.drag.end",s)}}function Le(a,e,t,s,n){const i=e.getBoundingClientRect();return n&&(n.style.width=`${Math.round(i.width)}px`,n.style.maxWidth=`${Math.round(i.width)}px`,n.style.boxSizing="border-box"),{type:a,source:e,data:t,ghost:{element:n,offsetX:s.clientX-i.left,offsetY:s.clientY-i.top,hint:{neutral:"",accept:"",reject:"",hidden:!0}}}}function Ee(a,e,t,s){const n=Array.from(a.querySelectorAll(e)).filter(i=>i!==s&&!i.classList.contains("atf-drag-ghost"));for(let i=0;in.fetch(l,c,{source:"allterrain-forms"}):(l,c)=>fetch(l,c))(t,{credentials:"same-origin",...e,headers:s});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 ce(l,o.status,c)}if(o.status!==204)return await o.json()}const z=a=>$e(a);async function Gt(a){if(!W?.wpRestUrl)throw new ce("AllTerrain Forms is not configured on this page.",0);const e=W.nonce?{"X-WP-Nonce":W.nonce}:{},t=ke(),s=Ke(W.wpRestUrl,a),n=t?.fetch?await t.fetch(s,{credentials:"same-origin",headers:e},{source:"allterrain-forms"}):await fetch(s,{credentials:"same-origin",headers:e});if(!n.ok)throw new ce(`Request failed with status ${n.status}.`,n.status);return await n.json()}function Zt(a){if(!a||!a.includes("&"))return a;const e=document.createElement("textarea");return e.innerHTML=a,e.value}const X=(a,e)=>$e(a,{method:"POST",body:JSON.stringify(e)}),de=a=>$e(a,{method:"DELETE"});function Xe(a){const e=new URLSearchParams;for(const[s,n]of Object.entries(a))n===void 0||n===""||n===!1||e.set(s,String(n));const t=e.toString();return t?`?${t}`:""}function he(a){const e=a?.schema?.settings;return e&&(!e.themeOverrides||Array.isArray(e.themeOverrides))&&(e.themeOverrides={...e.themeOverrides}),a}const I={config:()=>z("/config"),listForms:()=>z("/forms"),listArchivedForms:()=>z("/forms?archived=1"),archiveForm:a=>X(`/forms/${a}/archive`,{}),unarchiveForm:a=>X(`/forms/${a}/unarchive`,{}),getForm:a=>z(`/forms/${a}`).then(he),createForm:a=>X("/forms",a).then(he),updateForm:(a,e)=>X(`/forms/${a}`,e).then(he),duplicateForm:a=>X(`/forms/${a}/duplicate`,{}).then(he),deleteForm:a=>de(`/forms/${a}`),preview:(a,e)=>X(`/forms/${a}/preview`,e),pages:()=>Gt("wp/v2/pages?per_page=100&status=publish&orderby=title&order=asc&_fields=id,title").then(a=>a.map(e=>({id:e.id,title:Zt(e.title?.rendered??"")||`#${e.id}`}))),mergeTags:a=>z(`/forms/${a}/merge-tags`).then(e=>e.groups),analytics:(a,e="")=>z(`/forms/${a}/analytics${e?`?dimension=${encodeURIComponent(e)}`:""}`),demoStatus:()=>z("/demo"),demoSeed:a=>X("/demo",a?{count:a}:{}),demoRemove:()=>de("/demo"),listEntries:a=>z(`/entries${Xe(a)}`),getEntry:a=>z(`/entries/${a}`),updateEntry:(a,e)=>X(`/entries/${a}`,e),deleteEntry:a=>de(`/entries/${a}`),exportEntries:a=>z(`/entries/export${Xe(a)}`),listThemes:()=>z("/themes"),saveTheme:a=>X("/themes",a),deleteTheme:a=>de(`/themes/${a}`)};function r(a,e={}){const t=document.createElement(a);e.class&&(t.className=e.class),e.text!==void 0&&(t.textContent=e.text),e.html!==void 0&&(t.innerHTML=e.html),e.title&&(t.title=e.title),e.type&&"type"in t&&(t.type=e.type),e.value!==void 0&&"value"in t&&(t.value=e.value),e.placeholder!==void 0&&"placeholder"in t&&(t.placeholder=e.placeholder),e.href&&"href"in t&&(t.href=e.href);for(const[s,n]of Object.entries(e.attrs??{}))n===void 0||n===!1||t.setAttribute(s,n===!0?"":String(n));Object.assign(t.style,e.style??{});for(const[s,n]of Object.entries(e.on??{}))t.addEventListener(s,n);for(const s of e.children??[])s==null||s===!1||t.append(s);return t}function H(a){a.replaceChildren()}function U(a){return r("span",{class:`dashicons ${a.startsWith("dashicons-")?a:`dashicons-${a}`}`,attrs:{"aria-hidden":"true"}})}function b(a,e,t){const s=e.matches("input, select, textarea, button")?e:e.querySelector("input, select, textarea");if(s){const n=s.id||`atf-c-${Math.random().toString(36).slice(2,9)}`;return s.id=n,r("div",{class:"atfb-row",children:[r("label",{class:"atfb-row__label",text:a,attrs:{for:n}}),e,t?r("p",{class:"atfb-row__hint",text:t}):null]})}return r("div",{class:"atfb-row",children:[r("span",{class:"atfb-row__label",text:a}),e,t?r("p",{class:"atfb-row__hint",text:t}):null]})}function C(a,e,t=""){return r("input",{class:"atfb-input",type:"text",value:a,placeholder:t,on:{input:s=>e(s.target.value)}})}function G(a,e){if(Y("os-number-field")){const t=document.createElement("os-number-field");return t.setAttribute("value",a),t.classList.add("atfb-field"),t.addEventListener("os-input-change",s=>{e(String(s.detail?.value??""))}),t}return r("input",{class:"atfb-input",type:"number",value:a,on:{input:t=>e(t.target.value)}})}function ue(a,e,t=4){const s=r("textarea",{class:"atfb-input atfb-input--area",attrs:{rows:t},on:{input:n=>e(n.target.value)}});return s.value=a,s}function O(a,e,t){if(Y("os-select")&&Y("os-option")){const s=document.createElement("os-select");s.setAttribute("value",a),s.classList.add("atfb-field");for(const n of e){const i=document.createElement("os-option");i.setAttribute("value",n.value),i.textContent=n.label,s.append(i)}return s.addEventListener("os-pick",n=>{t(String(n.detail?.value??""))}),s}return r("select",{class:"atfb-input atfb-select",on:{change:s=>t(s.target.value)},children:e.map(s=>r("option",{value:s.value,text:s.label,attrs:{selected:s.value===a}}))})}function D(a,e,t){if(Y("os-checkbox-label")){const n=document.createElement("os-checkbox-label");return n.setAttribute("label",a),n.classList.add("atfb-check"),e&&n.setAttribute("checked",""),n.addEventListener("os-checkbox-change",i=>{t(!!i.detail?.checked)}),n}const s=r("input",{type:"checkbox",on:{change:n=>t(n.target.checked)}});return s.checked=e,r("label",{class:"atfb-check",children:[s,r("span",{text:a})]})}function L(a,e,t="secondary",s){const n=[s?U(s):null,r("span",{text:a})];if(Y("os-button")){const i=document.createElement("os-button");i.setAttribute("variant",t),i.setAttribute("type","button"),i.classList.add("atfb-button",`atfb-button--${t}`),i.addEventListener("click",e);for(const o of n)o&&i.append(o);return i}return r("button",{class:`atfb-button atfb-button--${t}`,type:"button",on:{click:e},children:n})}function Y(a){return typeof customElements<"u"&&!!customElements.get(a)}const Kt=["os-button","os-checkbox-label","os-number-field","os-select","os-option","os-segmented","os-segment","os-color-field","os-empty-state"];let pe=null;function Xt(){if(pe)return pe;const a=window.wp?.os;return pe=a?.loadComponents?a.loadComponents(Kt).catch(()=>{}):Promise.resolve(),pe}async function fe(a,e=""){const t=window.wp?.os;return t?.confirm?t.confirm({title:e,message:a,danger:!0}):window.confirm(a)}function B(a,e="",t="info"){const s=window.wp?.os;if(s?.notify){s.notify({title:a,body:e,type:t});return}console.info(`[AllTerrain Forms] ${a}${e?`: ${e}`:""}`)}function Vt(a){let e=0,t;return(...s)=>{t=s,!e&&(e=window.requestAnimationFrame(()=>{e=0,a(...t)}))}}function Ce(a,e){let t=0;return(...s)=>{window.clearTimeout(t),t=window.setTimeout(()=>a(...s),e)}}function Jt(a){try{return window.localStorage.getItem(a)??""}catch{return""}}function Qt(a,e){try{window.localStorage.setItem(a,e)}catch{}}function Ve(a){const e=a.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 Je(){const a=[window];try{window.parent&&window.parent!==window&&a.push(window.parent)}catch{}return a}function es(a){const e=a.wp?.os?.windowManager?.getAll?.()??[];for(const t of e){const s=t.iframe??t.element?.querySelector?.("iframe");if(s&&s.contentWindow===window)return t}return null}const ts=4e3,ss=100;function ns(a,e){const t=Date.now()+ts,s=()=>{const n=es(a);if(n&&n.id!==e){typeof n.close=="function"?n.close():a.wp?.os?.windowManager?.remove?.(n.id);return}!n&&Date.now()0?{form:t}:void 0;t>0&&os(t);for(const n of Je())if(n.wp?.os?.openWindow?.(e,{source:"handoff",params:s})){window.setTimeout(()=>ns(n,e),0);return}}function is(){document.addEventListener("click",a=>{const e=a.target?.closest?.("[data-atf-open-window]");if(!e)return;a.preventDefault();const t=e.getAttribute("data-atf-open-window")??"";for(const s of Je())if(s.wp?.os?.openWindow?.(t,{source:"handoff"}))return})}const rs="allterrain-forms/requested-form";function os(a){try{window.sessionStorage.setItem(rs,String(a))}catch{}}function Qe(a){return`allterrain-forms/requested-form-${a}`}function ls(a){try{const e=window.sessionStorage.getItem(Qe(a));return window.sessionStorage.removeItem(Qe(a)),Number(e)||0}catch{return 0}}const Ae={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"},Te=["empty","not_empty"];function et(a,e){const t=a.find(s=>s.id===e);return t?t.label||"an untitled question":null}function tt(a,e,t){return a.find(i=>i.id===e)?.choices?.find(i=>i.value===t)?.label||t}function cs(a,e){const t=Ae[a.operator]??String(a.operator);if(Te.includes(a.operator))return t;const s=tt(e,a.field,a.value);return`${a.operator==="is"?"":`${t} `}${s!==""?s:"(nothing)"}`}function st(a,e,t=0){const s=et(e,a.field),n=Ae[a.operator]??String(a.operator);if(s===null)return[{kind:"field",text:"a question that no longer exists",fieldId:a.field,missing:!0}];const i=[{kind:"field",text:s,fieldId:a.field,missing:!1},{kind:"operator",text:n,operator:a.operator,ruleIndex:t}];if(Te.includes(a.operator))return i;const o=tt(e,a.field,a.value);return i.push({kind:"value",text:o!==""?o:"(nothing)",raw:a.value,sourceId:a.field,ruleIndex:t}),i}function ds(a,e){const t=a.logic;if(!t?.enabled||!t.rules.length)return[];const s=[{kind:"verb",text:t.action==="hide"?"Hidden when":"Shown when"}];return t.rules.forEach((n,i)=>{i>0&&s.push({kind:"join",text:t.match==="all"?"and":"or"}),s.push(...st(n,e,i))}),s}function nt(a){return a.map(e=>e.text).join(" ")}function hs(a,e){return nt(st(a,e))}function me(a){const e=[];for(const t of a){const s=t.logic;if(s?.enabled)for(const n of s.rules)!n.field||n.field===t.id||e.push({from:n.field,to:t.id,label:hs(n,a),short:cs(n,a),action:s.action,broken:et(a,n.field)===null})}return e}function us(a){const e=new Map,t=new Set;for(const s of me(a)){const n=`${s.from}->${s.to}`;s.broken||t.has(n)||(t.add(n),e.set(s.from,(e.get(s.from)??0)+1))}return e}const at=10,it=22,ne="http://www.w3.org/2000/svg";class ps{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 t=()=>this.schedule();window.addEventListener("resize",t),this.teardowns.push(()=>window.removeEventListener("resize",t));const s=e.closest(".atfb__canvas")??e;if(s.addEventListener("scroll",t,{passive:!0}),this.teardowns.push(()=>s.removeEventListener("scroll",t)),typeof ResizeObserver<"u"){const n=new ResizeObserver(t);n.observe(e),this.teardowns.push(()=>n.disconnect())}}setEdges(e){this.edges=e,this.schedule()}highlight(e){this.svg.classList.toggle("is-focused",!!e),this.svg.querySelectorAll("[data-from]").forEach(t=>{const s=e&&(t.dataset.from===e||t.dataset.to===e);t.classList.toggle("is-lit",!!s)})}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 t=new Map;for(const s of this.edges){const n=this.cardRect(s.from),i=this.cardRect(s.to);if(!n||!i)continue;const o=t.get(s.from)??0;t.set(s.from,o+1),this.drawEdge(s,n,i,e,o)}}cardRect(e){const t=this.host.querySelector(`[data-atfb-card="${CSS.escape(e)}"]`);return t?t.getBoundingClientRect():null}drawEdge(e,t,s,n,i){const o=t.right-n.left,l=t.top+t.height/2-n.top,c=s.right-n.left,d=s.top+s.height/2-n.top,h=Math.max(0,n.width-at-Math.max(o,c)),v=22+i*11+Math.min(22,Math.abs(d-l)/8),y=Math.max(12,Math.min(v,h*.4)),u=document.createElementNS(ne,"path");u.setAttribute("d",`M ${o} ${l} C ${o+y} ${l}, ${c+y} ${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 x=document.createElementNS(ne,"title");x.textContent=e.label,u.append(x);const g=document.createElementNS(ne,"circle");g.setAttribute("cx",String(c)),g.setAttribute("cy",String(d)),g.setAttribute("r","3.5"),g.setAttribute("class",`atfb-logicmap__dot is-${e.action}${e.broken?" is-broken":""}`),g.dataset.from=e.from,g.dataset.to=e.to,this.svg.append(u,g);const f=document.createElementNS(ne,"text");f.setAttribute("x",String(n.width-at)),f.setAttribute("y",String(d+3)),f.setAttribute("text-anchor","end"),f.setAttribute("class","atfb-logicmap__label"),f.dataset.from=e.from,f.dataset.to=e.to,f.textContent=e.short.length>it?`${e.short.slice(0,it-1)}…`:e.short;const E=document.createElementNS(ne,"title");E.textContent=e.label,f.append(E),this.svg.append(f)}}const fs={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(a){return fs[a]??"text"}function rt(a,e){const t=/^choice:(\d+):(label|value)$/.exec(e);return String(t?a.choices?.[Number(t[1])]?.[t[2]]??"":a[e]??"")}function V(a){const{value:e,onInput:t,onCommit:s}=a,n=r("span",{class:`${a.class} atfb-editable`,text:e,attrs:{contenteditable:"plaintext-only",role:"textbox",spellcheck:"false","data-placeholder":a.placeholder}});return a.bind&&(n.dataset.atfbBind=a.bind),n.addEventListener("pointerdown",i=>i.stopPropagation()),n.addEventListener("input",()=>t(n.textContent??"")),n.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),n.blur()),i.key==="Escape"&&(n.textContent=e,n.blur()),i.stopPropagation()}),n.addEventListener("blur",()=>s?.()),n}function bs(a){const e=r("input",{class:"atf-choice__input",type:a==="checkboxes"||a==="multiselect"?"checkbox":"radio"});return e.disabled=!0,e}function ot(a,e,t){const s=ms(a.type),n=V({value:a.label,placeholder:"Write the question…",class:"atf-label",bind:"label",onInput:o=>t.edit(l=>{l.label=o}),onCommit:()=>t.restructure(()=>{})}),i=[s==="static"||s==="toggle"?null:n,vs(a,e,s,t),gs(a,e,t)];return r("div",{class:"atfb-preview atf-form",children:[r("div",{class:`atf-field atf-field--${a.type}`,children:i})]})}function gs(a,e,t){if(!e?.supports.includes("hint"))return null;const s=V({value:a.hint??"",placeholder:"Add a hint…",class:"atf-hint",bind:"hint",onInput:n=>t.edit(i=>{i.hint=n})});return s.setAttribute("aria-label","Hint"),r("p",{class:"atfb-preview__hint",children:[s]})}function vs(a,e,t,s){switch(t){case"text":return Me(a,"atf-input",s);case"textarea":return Me(a,"atf-input atf-textarea",s,!0);case"select":return r("div",{class:"atfb-preview__select",children:[Me(a,"atf-input atf-select",s)]});case"options":return _s(a,s);case"toggle":return r("div",{class:a.type==="switch"?"atf-toggle atf-toggle--switch":"atf-toggle",children:[(()=>{const n=r("input",{class:"atf-toggle__input",type:"checkbox"});return n.disabled=!0,n})(),V({value:a.label||"",placeholder:a.type==="consent"?"What are they agreeing to?…":"What does this turn on?…",class:"atf-toggle__label",bind:"label",onInput:n=>s.edit(i=>{i.label=n}),onCommit:()=>s.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 ks(a,e,s);case"repeater":return ys(a,s);default:return r("div",{class:"atfb-preview__stack",children:[r("p",{class:"atfb-preview__summary",text:`${e?.label??a.type} — set this up in the panel on the right.`})]})}}function ys(a,e){const t=a.fields??[],s=r("div",{class:"atfb-repeater__zone",attrs:{"data-atfb-repeater-zone":a.id}});return t.forEach(n=>s.append(ws(a,n,e))),t.length||s.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":a.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:[V({value:String(a.itemLabel??""),placeholder:"Row",class:"atfb-repeater__item-label",bind:"itemLabel",onInput:n=>e.edit(i=>{i.itemLabel=n})}),r("span",{class:"atfb-repeater__ordinal",text:"1",attrs:{"aria-hidden":"true"}})]})]}),s]}),xs(a,e)]})}function ws(a,e,t){const s=e.id,n=l=>c=>{const d=(c.fields??[]).find(h=>h.id===s);d&&l(d)},i={edit:l=>t.edit(n(l)),restructure:l=>t.restructure(n(l)),types:t.types,selectedId:t.selectedId},o=t.types?.(e.type);return r("div",{class:`atfb-subcard${t.selectedId===s?" is-selected":""}`,attrs:{"data-atfb-subfield":s,"data-atfb-parent":a.id,tabindex:"0",role:"button","aria-label":`${e.label||o?.label||e.type}, inside ${a.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(),t.restructure(c=>{const d=c.fields??[],h=d.findIndex(v=>v.id===s);h>=0&&d.splice(h,1)})}},children:[r("span",{text:"×"})]})]}),ot(e,o,i)]})}function Me(a,e,t,s=!1){const n=V({value:a.placeholder??"",placeholder:a.type==="select"||a.type==="country"?"Choose…":"Placeholder…",class:`${e} atfb-preview__box${s?" atfb-preview__box--tall":""}`,bind:"placeholder",onInput:i=>t.edit(o=>{o.placeholder=i})});return n.setAttribute("aria-label","Placeholder"),n}function Fe(a,e,t,s,n,i){return r("span",{class:`atf-button ${t} atfb-preview__button`,children:[V({value:a,placeholder:e,class:"atfb-preview__button-text",bind:s,onInput:o=>n.edit(l=>i(l,o))})]})}function xs(a,e){return Fe(String(a.addLabel??""),"Add another","atf-button--ghost atfb-repeater__add","addLabel",e,(t,s)=>{t.addLabel=s})}function _s(a,e){const t=r("div",{class:"atf-choices__list"});return(a.choices??[]).forEach((s,n)=>{t.append(r("div",{class:"atf-choice atfb-preview__option",children:[bs(a.type),V({value:s.label,placeholder:"Option…",class:"atf-choice__label",bind:`choice:${n}:label`,onInput:i=>{e.edit(o=>{const l=o.choices?.[n];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 ${s.label||"this option"}`},on:{pointerdown:i=>i.stopPropagation(),click:i=>{i.stopPropagation(),e.restructure(o=>{o.choices.splice(n,1)})}},children:[r("span",{text:"×"})]})]}))}),t.append(r("button",{class:"atfb-preview__add",type:"button",on:{pointerdown:s=>s.stopPropagation(),click:s=>{s.stopPropagation(),e.restructure(n=>{const i=n.choices.length+1;n.choices.push({label:`Option ${i}`,value:`Option ${i}`})})}},children:[r("span",{text:"+ Add option"})]})),r("fieldset",{class:"atf-choices",children:[t]})}function ks(a,e,t){return a.type==="heading"?V({value:a.label,placeholder:"Section heading…",class:"atf-heading",bind:"label",onInput:s=>t.edit(n=>{n.label=s}),onCommit:()=>t.restructure(()=>{})}):a.type==="divider"?r("hr",{class:"atf-divider"}):a.type==="page_break"?r("div",{class:"atfb-preview__stack",children:[r("p",{class:"atfb-progress-name",children:[V({value:a.label,placeholder:"Name this step…",class:"atf-progress__label",bind:"label",onInput:s=>t.edit(n=>{n.label=s}),onCommit:()=>t.restructure(()=>{})})]}),r("p",{class:"atfb-preview__summary",text:"Everything after this is a new page."}),r("div",{class:"atf-nav atfb-preview__nav",children:[Fe(String(a.prevLabel??""),"Back","atf-button--secondary","prevLabel",t,(s,n)=>{s.prevLabel=n}),Fe(String(a.nextLabel??""),"Next","","nextLabel",t,(s,n)=>{s.nextLabel=n})]})]}):r("p",{class:"atfb-preview__summary",text:`${e?.label??a.type} — nothing is shown to the visitor here.`})}const Ie=new Map;function De(a){let e=Ie.get(a);return e||(e=I.mergeTags(a).catch(()=>[]),Ie.set(a,e)),e}function Ss(a){Ie.delete(a)}function Ls(a){const e=new Map;for(const t of a)for(const s of t.items)e.set(s.tag,s);return e}function Es(a,e){const t=Ls(e);return a.replace(/\{[a-z_]+(?::[^}]*)?\}/gi,s=>{const n=t.get(s.toLowerCase());return n?n.sample:s})}function $s(a){return/\{[a-z_]+(?::[^}]*)?\}/i.test(a)}let te=null;function ie(){te?.remove(),te=null}typeof document<"u"&&(document.addEventListener("pointerdown",a=>{const e=a.target;e?.closest(".atfb-tagpick__open")||te&&!te.contains(e)&&ie()}),document.addEventListener("keydown",a=>{a.key==="Escape"&&te&&(ie(),a.stopPropagation())}));function lt(a,e){const t=a.selectionStart??a.value.length,s=a.selectionEnd??a.value.length;a.value=a.value.slice(0,t)+e+a.value.slice(s);const n=t+e.length;a.setSelectionRange(n,n),a.focus(),a.dispatchEvent(new Event("input",{bubbles:!0}))}function Cs(a){let e=a.parentElement;for(;e&&e!==document.body;){const t=getComputedStyle(e).overflowY;if(t==="auto"||t==="scroll"||t==="hidden")return e.getBoundingClientRect().bottom;e=e.parentElement}return window.innerHeight}function As(a,e){const t=r("input",{class:"atfb-input atfb-tagpick__search",type:"search",placeholder:"Search values…",attrs:{"aria-label":"Search values"}}),s=r("div",{class:"atfb-tagpick__list"}),n=i=>{s.replaceChildren();const o=i.trim().toLowerCase();let l=0;for(const c of a){const d=c.items.filter(h=>!o||h.label.toLowerCase().includes(o)||h.tag.toLowerCase().includes(o));if(!d.length){c.empty&&!o&&!c.items.length&&s.append(r("p",{class:"atfb-tagpick__group",text:c.label}),r("p",{class:"atfb-tagpick__empty",text:c.empty}));continue}s.append(r("p",{class:"atfb-tagpick__group",text:c.label}));for(const h of d)l+=1,s.append(r("button",{class:"atfb-tagpick__item",type:"button",on:{click:()=>{e(h.tag),ie()}},children:[r("span",{class:"atfb-tagpick__item-main",children:[r("span",{class:"atfb-tagpick__label",text:h.label}),r("code",{class:"atfb-tagpick__tag",text:h.tag})]}),h.hint||h.sample?r("span",{class:"atfb-tagpick__meta",text:h.sample?`e.g. ${h.sample}`:h.hint}):null]}))}!l&&o&&s.append(r("p",{class:"atfb-tagpick__empty",text:`Nothing matches “${i}”.`}))};return n(""),t.addEventListener("input",()=>n(t.value)),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."}),t,s]})}function ct(a,e){const t=r("button",{class:"atfb-button atfb-button--ghost atfb-tagpick__open",type:"button",title:"Insert a value from the submission",children:[U("shortcode"),r("span",{text:"Insert a value"})]}),s=r("div",{class:"atfb-taggable",children:[a,r("div",{class:"atfb-taggable__tools",children:[t]})]}),n=e.preview===!1?null:r("p",{class:"atfb-taggable__preview"});n&&s.append(n);const i=()=>{if(n){if(!$s(a.value)){n.textContent="",n.hidden=!0;return}De(e.formId).then(o=>{n.hidden=!1,n.replaceChildren(r("span",{class:"atfb-taggable__preview-label",text:"Reads as"}),r("span",{text:Es(a.value,o)}))})}};return a.addEventListener("input",i),i(),t.addEventListener("click",o=>{if(o.stopPropagation(),te&&s.contains(te)){ie();return}ie(),De(e.formId).then(l=>{const c=As(l,d=>{lt(a,d),i()});s.append(c),te=c,(window.innerHeight-c.getBoundingClientRect().topCs(s))&&c.classList.add("atfb-tagpick--above"),c.querySelector(".atfb-tagpick__search")?.focus()})}),s}function dt(a,e){const t=parseFloat(String(a??""));return Number.isFinite(t)?t:e}function ht(a,e){let t=e[0];for(const s of e)Math.abs(s.at-a)a.accent??"#2271b1",apply:a=>({accent:a,"accent-soft":`color-mix( in srgb, ${a} 12%, transparent )`,"border-focus":a,"focus-ring-color":a,"button-bg":a,"button-bg-hover":`color-mix( in srgb, ${a} 88%, #000 )`})},{id:"roundness",label:"Roundness",hint:"Corners, everywhere at once.",kind:"scale",steps:qe.map(({value:a,label:e})=>({value:a,label:e})),owns:["radius-field","radius-button","radius-card","radius-check"],read:a=>ht(dt(a["radius-field"],4),qe),apply:a=>{const e=qe.find(t=>t.value===a)?.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:Oe.map(({value:a,label:e})=>({value:a,label:e})),owns:["pad-field-x","pad-field-y","gap-fields","gap-label","button-pad-x","button-pad-y"],read:a=>ht(dt(a["pad-field-y"],9),Oe),apply:a=>{const e=Oe.find(t=>t.value===a)?.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:Ts,owns:["shadow-field","shadow-field-focus","shadow-button","shadow-button-hover","shadow-card"],read:a=>{const e=a["shadow-card"]??"none";return e==="none"||e.trim()===""?a["shadow-field"]&&a["shadow-field"]!=="none"?"hard":"none":e.includes("0 1px")||e.includes("2px")?"subtle":"lifted"},apply:a=>{switch(a){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:Ms,owns:["field-style"],read:a=>a["field-style"]??"outline",apply:a=>({"field-style":a})},{id:"labels",label:"Labels",hint:"Where the question sits relative to the answer.",kind:"choice",steps:Fs,owns:["label-position"],read:a=>a["label-position"]??"top",apply:a=>({"label-position":a})}]}function Is(a){return Ne().find(e=>e.owns.includes(a))??null}function ut(a){let e=a.activeSlug,t={...a.overrides},s=a.themes;const n=p=>{t=p,a.onOverridesReplaced?.({...p})},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=Ce(async()=>{try{const p=await a.previewFor(e,t),m=i.closest(".atf-studio__preview"),w=m?.scrollTop??0;i.innerHTML=p,m&&(m.scrollTop=w),document.dispatchEvent(new CustomEvent("atf-refresh"))}catch(p){H(i),i.append(r("p",{class:"atfb-error",text:p instanceof Error?p.message:"Preview failed."}))}},180),h={"label-position":"atf-labels-","field-style":"atf-fields-"},v=(p,m,w)=>{const _=w.replace(/[^a-z0-9_-]/gi,"");for(const S of[...p.classList])S.startsWith(m)&&p.classList.remove(S);_&&p.classList.add(m+_)},y=p=>{const m=i.querySelector(".atf-form-wrap"),w=m?.querySelector(".atf-form");if(m)for(const[_,S]of Object.entries(p))S===""?m.style.removeProperty(`--atf-${_}`):m.style.setProperty(`--atf-${_}`,S),w&&h[_]&&v(w,h[_],S||(s.find(q=>q.slug===e)?.resolved[_]??""))},u=p=>{y(p.resolved);const m=i.querySelector(".atf-form");m&&(v(m,"atf-theme-",p.slug),m.classList.toggle("atf-is-dark",!!p.dark))},x=p=>t[p.token]!==void 0?t[p.token]:s.find(w=>w.slug===e)?.resolved?.[p.token]??p.default,g=()=>{H(c);for(const p of s){const m=r("button",{class:`atfs-theme${p.slug===e?" is-active":""}`,type:"button",attrs:{"aria-pressed":p.slug===e,title:p.description},children:[r("span",{class:"atfs-theme__chip",style:{background:p.resolved.surface??"#fff",borderColor:p.resolved.border??"#ccc",borderRadius:p.resolved["radius-field"]??"4px",boxShadow:p.resolved["shadow-card"]??"none"},children:[r("span",{class:"atfs-theme__accent",style:{background:p.resolved.accent??"#2271b1",borderRadius:p.resolved["radius-button"]??"4px"}})]}),r("span",{class:"atfs-theme__name",text:p.label}),p.custom?r("span",{class:"atfb-badge",text:"yours"}):null],on:{click:()=>{e=p.slug,n({}),a.onTheme(e),u(p),g(),k(),N(),Bt()}}});c.append(m)}},f=()=>{const m={...s.find(w=>w.slug===e)?.resolved??{}};for(const[w,_]of Object.entries(t))m[w]=_;return m},E=p=>{const m=l.closest(".atf-studio__controls"),w=m?.scrollTop??0;p(),m&&(m.scrollTop=w)},N=Ce(()=>E($),150),k=()=>{const p=f(),m=l.querySelectorAll(".atfs-dial");Ne().forEach((w,_)=>{const S=m[_];if(!S)return;const q=w.read(p);if(w.kind==="colour"){const F=S.querySelector('input[type="color"]'),Z=S.querySelector("input.atfb-input");F&&document.activeElement!==F&&(F.value=be(q)),Z&&document.activeElement!==Z&&(Z.value=q);return}S.querySelectorAll(".atfs-segment").forEach((F,Z)=>{const Q=w.steps?.[Z]?.value===q;F.classList.toggle("is-on",Q),F.setAttribute("aria-pressed",String(Q))})})},T=(p,m)=>{const w=p.apply(m,f());for(const[_,S]of Object.entries(w))t[_]=S,a.onOverride(_,S);y(w),k(),N()},M=()=>{H(l);const p=f();for(const m of Ne()){const w=m.read(p);let _;if(m.kind==="colour"){const S=r("input",{class:"atfs-color",type:"color",value:be(w),attrs:{"aria-label":m.label},on:{input:q=>T(m,q.target.value)}});_=r("div",{class:"atfs-color-row",children:[S,C(w,q=>T(m,q))]})}else _=r("div",{class:`atfs-segmented atfs-segmented--${m.kind}`,attrs:{role:"group","aria-label":m.label},children:(m.steps??[]).map(S=>r("button",{class:`atfs-segment${S.value===w?" is-on":""}`,type:"button",text:S.label,attrs:{"aria-pressed":S.value===w},on:{click:()=>T(m,S.value)}}))});l.append(r("div",{class:"atfs-dial",children:[r("div",{class:"atfs-dial__head",children:[r("span",{class:"atfs-dial__label",text:m.label}),r("span",{class:"atfs-dial__hint",text:m.hint})]}),_]}))}},$=()=>{H(o);const p=new Map;for(const w of a.tokens){const _=p.get(w.group)??[];_.push(w),p.set(w.group,_)}const m={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[w,_]of p)o.append(r("details",{class:"atfs-group",attrs:{open:w==="colour"},children:[r("summary",{text:m[w]??w}),..._.map(S=>R(S))]}))},R=p=>{const m=x(p),w=F=>{F===""?delete t[p.token]:t[p.token]=F,a.onOverride(p.token,F),y({[p.token]:F})};let _;if(p.control==="color"){const F=r("input",{class:"atfs-color",type:"color",value:be(m),attrs:{"aria-label":`${p.label} colour`},on:{input:Q=>{const le=Q.target.value;Z.value=le,w(le)}}}),Z=C(m,Q=>{F.value=be(Q),w(Q)});_=r("div",{class:"atfs-color-row",children:[F,Z]})}else if(p.control==="select")_=O(m,(p.options??[]).map(F=>({value:F,label:F})),w);else if(p.control==="length"){const F=parseFloat(m)||0,Z=p.unit??"px",Q=p.token.includes("radius")?60:80,le=r("input",{class:"atfs-range",type:"range",value:String(F),attrs:{min:"0",max:String(Q),step:"1","aria-label":p.label},on:{input:_e=>{const jt=`${_e.target.value}${Z}`;Ht.value=jt,w(jt)}}}),Ht=C(m,_e=>{le.value=String(parseFloat(_e)||0),w(_e)});_=r("div",{class:"atfs-length-row",children:[le,Ht]})}else _=C(m,w);const S=b(p.label,_),q=Is(p.token);return q&&(S.classList.add("is-dialled"),S.append(r("span",{class:"atfs-owned",text:q.label}))),t[p.token]!==void 0&&(S.classList.add("is-overridden"),S.append(r("button",{class:"atfs-reset",type:"button",text:"Reset",attrs:{"aria-label":`Reset ${p.label} to the theme's value`},on:{click:()=>{w(""),E($)}}}))),S},A=async()=>{const p=s.find(_=>_.slug===e),m=p?`${p.label} (mine)`:"My theme",w=window.prompt("Name this theme",m);if(w)try{const _={};for(const q of a.tokens){const F=x(q);F!==q.default&&(_[q.token]=F)}const S=await I.saveTheme({label:w,tokens:_});s=[...s.filter(q=>q.slug!==S.slug),S],a.onThemesChanged(s),e=S.slug,n({}),a.onTheme(e),g(),k(),E($),B("Theme saved",S.label)}catch(_){B("Could not save the theme",_ instanceof Error?_.message:"","error")}},j=async()=>{const p=s.find(m=>m.slug===e);if(p?.custom&&await fe(`Delete “${p.label}”? Forms using it fall back to Clean.`,"Delete theme"))try{await I.deleteTheme(p.id),s=s.filter(w=>w.slug!==p.slug),a.onThemesChanged(s),e="clean",n({}),a.onTheme(e),g(),k(),E($);const m=s.find(w=>w.slug===e);m&&u(m)}catch(m){B("Could not delete the theme",m instanceof Error?m.message:"","error")}},P=async()=>{const p=s.find(_=>_.slug===e),m={label:p?.label??e,tokens:{...p?.tokens??{},...t}},w=JSON.stringify(m,null," ");try{await navigator.clipboard.writeText(w),B("Theme copied","Paste it into another site to import it.")}catch{window.prompt("Copy this theme",w)}},oe=()=>{const p=window.prompt("Paste a theme");if(p)try{const m=JSON.parse(p);if(!m.tokens||typeof m.tokens!="object")throw new Error("That does not look like a theme.");for(const[w,_]of Object.entries(m.tokens))t[w]=String(_),a.onOverride(w,String(_));y({...t}),k(),E($)}catch(m){B("Could not read that theme",m instanceof Error?m.message:"","error")}},Pt=L("Delete",()=>void j(),"danger"),Bt=()=>{const p=s.find(m=>m.slug===e);Pt.hidden=!p?.custom};return g(),M(),$(),d(),Bt(),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:[L("Save as a theme",()=>void A(),"primary"),L("Export",()=>void P()),L("Import",oe),Pt]})]}),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 Re(){const a=document.querySelector("[data-atfs-root]");if(!a||a.dataset.atfsMounted)return;a.dataset.atfsMounted="1",Ve(a);const e=a.querySelector("[data-atfs-bar]"),t=a.querySelector(".atfs__body")??a;try{const[s,n,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);if(!i.length){H(t),t.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=()=>{H(t),t.append(ut({themes:n,tokens:s.tokens,activeSlug:c,overrides:l,standalone:!0,onTheme:h=>{c=h},onOverride:(h,v)=>{v===""?delete l[h]:l[h]=v},onOverridesReplaced:h=>{l={...h}},previewFor:async(h,v)=>{const y=await I.getForm(o.id);y.schema.settings.theme=h,y.schema.settings.themeOverrides=v;const{html:u}=await I.preview(o.id,{schema:y.schema,theme:h});return u},onThemesChanged:h=>{n.length=0,n.push(...h)}}))};e&&(H(e),e.append(r("span",{class:"atfs__label",text:"Preview against"}),O(String(o.id),i.map(h=>({value:String(h.id),label:h.title||"(untitled)"})),h=>{o=i.find(v=>String(v.id)===h)??i[0],l={},d()}))),d()}catch(s){H(t),t.append(r("p",{class:"atfb-error",text:s instanceof Error?s.message:"Could not load themes."}))}}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>void Re()):Re(),document.addEventListener("os-window-content-loaded",()=>void Re()));function be(a){const e=a.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 ge={plain:"",simple:"✓",minimal:"",card:"🎉",check:"",confetti:"🎉",fireworks:"🎆",sparkles:"✨",typewriter:""};function pt(){return{style:"simple",title:"",icon:"",accent:"",intensity:"medium",showButton:!1,buttonLabel:""}}function Pe(a){const e={...pt(),...a??{}};return e.style in ge||(e.style="simple"),e}function Ds(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}function qs(a,e,t){const s=Pe(e),n=document.createElement("div");if(n.className=`atf-confirmation atf-success atf-success--${s.style}`,n.setAttribute("role","status"),n.setAttribute("tabindex","-1"),s.style==="plain")return n.className="atf-confirmation",n.innerHTML=a,n;s.accent&&n.style.setProperty("--atf-accent",s.accent);const i=document.createElement("div");i.className="atf-success__inner",n.append(i);const o=s.icon||ge[s.style];if(s.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(s.title){const c=document.createElement("h2");c.className="atf-success__title",c.textContent=s.title,i.append(c)}const l=document.createElement("div");if(l.className="atf-success__message",l.innerHTML=a,i.append(l),s.style==="typewriter"&&n.setAttribute("aria-label",l.textContent??""),s.showButton){const c=document.createElement("button");c.type="button",c.className="atf-button atf-button--ghost atf-success__again",c.textContent=s.buttonLabel||"Fill it in again",c.addEventListener("click",()=>t?t():window.location.reload()),i.append(c)}return n}function Os(a,e){const t=Pe(e);if(Ds())return()=>{};switch(t.style){case"confetti":return Ns(a,t);case"fireworks":return Rs(t);case"sparkles":return Ps(a,t);case"typewriter":return Bs(a);default:return()=>{}}}function re(a){return{low:.5,medium:1,high:1.8}[a.intensity]}function ft(){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 mt=["#f43f5e","#f59e0b","#10b981","#3b82f6","#8b5cf6","#ec4899","#eab308"];function Ns(a,e){const{ctx:t,stop:s}=ft();if(!t)return s(),()=>{};const n=e.accent?[e.accent,...mt]:mt,i=[],o=a.getBoundingClientRect(),l=o.left+o.width/2,c=Math.min(o.top+40,window.innerHeight-20),d=(E,N,k)=>{const T=k?Math.PI*(1.15+.7*Math.random()):0,M=k?9+Math.random()*8:0;return{x:E,y:N,vx:k?Math.cos(T)*M*(Math.random()<.5?1:-1):(Math.random()-.5)*1.5,vy:k?Math.sin(T)*M: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}},h=Math.round(90*re(e));for(let E=0;E{if(y>=v){window.clearInterval(u);return}i.push(d(Math.random()*window.innerWidth,-20,!1)),y++},2e3/v);let x=0;const g=performance.now(),f=E=>{t.clearRect(0,0,window.innerWidth,window.innerHeight);let N=!1;for(const k of i)k.vy+=.16,k.vx*=.99,k.vy*=.985,k.wobble+=.1,k.x+=k.vx+Math.sin(k.wobble)*.8,k.y+=k.vy,k.angle+=k.spin,k.y{window.clearInterval(u),window.cancelAnimationFrame(x),s()}}function Rs(a){const{ctx:e,stop:t}=ft();if(!e)return t(),()=>{};const s=[],n=[],i=Math.round(6*re(a))+2;let o=0;const l=()=>{s.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 x=Math.round(70*re(a));for(let g=0;g{e.clearRect(0,0,window.innerWidth,window.innerHeight);for(let g=s.length-1;g>=0;g--){const f=s[g];f.y+=f.vy,f.vy+=.08,e.fillStyle=`hsl(${f.hue} 90% 65%)`,e.fillRect(f.x-1.5,f.y,3,10),(f.y<=f.targetY||f.vy>=-1)&&(d(f),s.splice(g,1))}for(let g=n.length-1;g>=0;g--){const f=n[g];if(f.x+=f.vx,f.y+=f.vy,f.vy+=.045,f.vx*=.985,f.vy*=.985,f.life-=f.decay,f.life<=0){n.splice(g,1);continue}const E=f.life*(.7+.3*Math.random());e.globalAlpha=Math.max(0,E),e.fillStyle=`hsl(${f.hue} 95% ${55+25*f.life}%)`,e.beginPath(),e.arc(f.x,f.y,1.1+1.6*f.life,0,Math.PI*2),e.fill()}e.globalAlpha=1,!(o>=i&&s.length===0&&n.length===0)&&u-v<9e3?h=window.requestAnimationFrame(y):t()};return h=window.requestAnimationFrame(y),()=>{window.clearInterval(c),window.cancelAnimationFrame(h),t()}}function Ps(a,e){const t=e.icon||ge.sparkles,s=Math.round(22*re(e)),n=[];let i=0;const o=()=>{const c=document.createElement("span");c.className="atf-success__spark",c.setAttribute("aria-hidden","true"),c.textContent=t,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()),a.append(c),n.push(c),i++};o();const l=window.setInterval(()=>{if(i>=s){window.clearInterval(l);return}o()},2800/s);return()=>{window.clearInterval(l),n.forEach(c=>c.remove())}}function Bs(a){const e=a.querySelector(".atf-success__message");if(!e)return()=>{};const t=e.innerHTML,s=e.textContent??"";if(!s)return()=>{};e.textContent="",e.classList.add("is-typing");const n=Math.min(45,3800/s.length);let i=0;const o=window.setInterval(()=>{i++,e.textContent=s.slice(0,i),i>=s.length&&(window.clearInterval(o),e.classList.remove("is-typing"),e.innerHTML=t)},n);return()=>{window.clearInterval(o),e.classList.remove("is-typing"),e.innerHTML=t}}const Hs={min:-1,max:-1,sum:-1,avg:-1,round:-1,ceil:1,floor:1,abs:1,sqrt:1,pow:2},bt={"+":{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 js(a,e,t=[]){if(!a||!a.trim()||a.length>2e3)return null;const s=Ws(a,e,t),n=Gs(s);if(!n)return null;const i=Ks(n);if(!i)return null;const o=Xs(i);return o===null||!Number.isFinite(o)?null:o}function Ws(a,e,t){return a.replace(/\{([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?\}/g,(s,n,i,o)=>Us(a,o,s.length,n,i??"",e,t))}function Us(a,e,t,s,n,i,o){const l=zs(o,s),c=Object.prototype.hasOwnProperty.call(i,s)?i[s]:null;if(n===""){const u=l?.type==="repeater"?gt(c).length:Be(c,l);return vt(u)}const h=(l?.fields??[]).find(u=>u.id===n)??null,v=gt(c).map(u=>Be(u[n]??"",h));if(!v.length)return"0";const y=v.map(vt);return Ys(a,e,t)?y.join(", "):y.length===1?y[0]:`( ${y.join(" + ")} )`}function zs(a,e){for(const t of a){if(t.id===e)return t;for(const s of t.fields??[])if(s.id===e)return s}return null}function Ys(a,e,t){const s=a.slice(e+t).replace(/^\s+/,"");if(s===""||s[0]!==")")return!1;const n=a.slice(0,e).replace(/\s+$/,""),i=/([a-zA-Z_][a-zA-Z0-9_]*)\s*\($/.exec(n);return!!i&&["sum","avg","min","max"].includes(i[1].toLowerCase())}function gt(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 vt(a){const e=a.toFixed(10).replace(/0+$/,"").replace(/\.$/,"");return e===""||e==="-"?"0":e}function Be(a,e){if(typeof a=="boolean")return a?1:0;if(Array.isArray(a))return a.reduce((n,i)=>n+Be(i,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 s=Number(a);return Number.isFinite(s)?s:0}function Gs(a){const e=[];let t=0;for(;ti.precedence||l.precedence===i.precedence&&!i.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 i=t.pop();i.arity=s.length?s.pop():1,e.push(i)}break}}for(;t.length;){const n=t.pop();if(n.type==="(")return null;e.push(n)}return e}function Xs(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 s=e.pop(),n=e.pop();switch(t.value){case"+":e.push(n+s);break;case"-":e.push(n-s);break;case"*":e.push(n*s);break;case"/":e.push(s===0?0:n/s);break;case"%":e.push(s===0?0:n%s);break;case"^":e.push(Math.pow(n,s));break;default:return null}break}case"function":{const s=t.arity??1;if(e.lengtht+s,0);case"avg":return e.reduce((t,s)=>t+s,0)/e.length;case"round":{const t=Math.max(-10,Math.min(10,Math.trunc(e[1]??0))),s=Math.pow(10,t);return Math.round(e[0]*s)/s}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 Js=["sum","min","max","avg","round","ceil","floor","abs","sqrt","pow"],yt=["number","range","scale","rating","total","select","multiselect","radio","checkboxes","switch","quiz"];function He(a,e){return a.filter(t=>t.id!==e&&yt.includes(t.type))}function Qs(a){const e=[];for(const t of a){if(t.type!=="repeater")continue;const s=t.label||t.id;e.push({label:`${s} (how many)`,insert:`{${t.id}}`});for(const n of t.fields??[])yt.includes(n.type)&&e.push({label:`${s} · ${n.label||n.id}`,insert:`{${t.id}.${n.id}}`})}return e}function en(a,e){const t={};He(a,e).forEach((s,n)=>{t[s.id]=n+1});for(const s of a){if(s.type!=="repeater"||s.id===e)continue;const n=s.fields??[],i=o=>Object.fromEntries(n.map((l,c)=>[l.id,c+1+o]));t[s.id]=[i(0),i(1)]}return t}function tn(a){const e=r("div",{class:"atfb-overlay"}),t=()=>{e.remove(),document.removeEventListener("keydown",s)},s=u=>{u.key==="Escape"&&t()},n=r("textarea",{class:"atfb-input atfb-formula__input",attrs:{rows:"3","aria-label":"Formula"}});n.value=String(a.field.formula??"");const i=r("p",{class:"atfb-formula__result",attrs:{"aria-live":"polite"}}),o=en(a.fields,a.field.id),l=()=>{const u=n.value.trim();if(u===""){i.textContent="Empty. Reference a question below to start.",i.classList.remove("is-error");return}const x=js(u,o,a.fields);if(x===null){i.textContent="This does not compute yet — check the braces and parentheses.",i.classList.add("is-error");return}const g=He(a.fields,a.field.id).map((f,E)=>`${f.label||f.id} = ${E+1}`).concat(a.fields.filter(f=>f.type==="repeater"&&f.id!==a.field.id).map(f=>`${f.label||f.id} = 2 sample rows`)).join(", ");i.textContent=`With sample answers (${g}): ${x}`,i.classList.remove("is-error")};n.addEventListener("input",l);const c=(u,x,g=0)=>r("button",{class:"atfb-formula__chip",type:"button",text:u,on:{click:()=>{if(lt(n,x),g>0){const f=(n.selectionStart??n.value.length)-g;n.setSelectionRange(f,f)}}}}),d=He(a.fields,a.field.id),h=Qs(a.fields),v=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."})]}),y=r("div",{class:"atfb-formula__chips",children:Js.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"}),n,i,b("Your questions",v,"Click one to reference its answer."),b("Functions",y),r("div",{class:"atfb-modal__actions",children:[L("Cancel",t),L("Save formula",()=>{a.onSave(n.value.trim()),t()},"primary")]})]})),e.addEventListener("click",u=>{u.target===e&&t()}),document.addEventListener("keydown",s),a.root.append(e),l(),n.focus(),n.setSelectionRange(n.value.length,n.value.length)}const sn="allterrain-forms/form";function nn(){return window.wp?.os?.relations??null}function wt(a){const e=a.closest("[data-window-id], .os-window");if(!e)return null;const t=e.getAttribute("data-window-id");if(t)return t;const s=e.id??"";return s?s.replace(/^wp-window-/,""):null}const an=6e3,xt=120;function _t(a,e){const t=nn();if(je.set(a,e),!t?.set)return;const s=i=>{if(ve.get(a)!==n)return;const o=wt(a);if(!o){Date.now()s(i),xt);return}try{t.set(o,e)}catch(c){kt||(kt=!0,console.error("[AllTerrain Forms] The shell refused a window identity.",c,e)),ve.delete(a);return}if(!e||t.get?.(o)?.id===e.id||Date.now()>=i){ve.delete(a);return}window.setTimeout(()=>s(i),xt)},n=Symbol("atf-identity");ve.set(a,n),s(Date.now()+an)}let kt=!1;const ve=new WeakMap,je=new Map;function rn(){for(const[a,e]of je){if(!a.isConnected){je.delete(a);continue}_t(a,e)}}if(typeof document<"u")for(const a of["os-window-content-loaded","os-window-opened"])document.addEventListener(a,()=>rn());function on(a,e){return{type:sn,id:a.id,label:a.title||"Untitled form",related:[{id:`allterrain-forms/entries-${a.id}`,label:"Entries for this form",url:`${e}admin.php?page=allterrain-forms-entries&form=${a.id}`,group:"allterrain-forms",groupLabel:"Forms",icon:"dashicons-list-view"}]}}const ye={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 ln(){return{mode:"blocks",starts:"",ends:"",contains:"",notContains:"",chars:[],minLen:"",maxLen:"",regex:"",message:"",tests:[]}}function St(a){const e=ln();let t;try{t=JSON.parse(a)}catch{return e}if(!t||typeof t!="object")return e;const s=t;e.mode=s.mode==="regex"?"regex":"blocks";for(const n of["starts","ends","contains","notContains","minLen","maxLen","regex","message"])typeof s[n]=="string"&&(e[n]=s[n]);return Array.isArray(s.chars)&&(e.chars=s.chars.filter(n=>typeof n=="string"&&n in ye)),Array.isArray(s.tests)&&(e.tests=s.tests.filter(n=>typeof n=="string").slice(0,10)),e}function we(a){return a.replace(/[.*+?^${}()|[\]\\/]/g,"\\$&")}function xe(a){if(a.mode==="regex")return a.regex.trim();const e=[],t=a.minLen.trim(),s=a.maxLen.trim();(t!==""||s!=="")&&e.push(`(?=.{${t===""?"0":parseInt(t,10)||0},${s===""?"":parseInt(s,10)||""}}$)`),a.contains!==""&&e.push(`(?=.*${we(a.contains)})`),a.notContains!==""&&e.push(`(?!.*${we(a.notContains)})`),a.starts!==""&&e.push(`(?=${we(a.starts)})`),a.ends!==""&&e.push(`(?=.*${we(a.ends)}$)`);const n=a.chars.map(o=>ye[o]?.chars??"").join(""),i=n?`[${n}]*$`:".*$";return!e.length&&!n?"":`^${e.join("")}${i}`}function Lt(a){if(a.mode==="regex")return a.regex.trim()?`Matches the expression ${a.regex.trim()}`:"";const e=[];if(a.starts&&e.push(`starts with “${a.starts}”`),a.ends&&e.push(`ends with “${a.ends}”`),a.contains&&e.push(`contains “${a.contains}”`),a.notContains&&e.push(`never contains “${a.notContains}”`),a.chars.length){const i=a.chars.map(o=>(ye[o]?.label??o).split(" (")[0].toLowerCase());e.push(`uses only ${i.join(" and ")}`)}const t=a.minLen.trim(),s=a.maxLen.trim();return t&&s?e.push(`is ${t}–${s} characters long`):t?e.push(`is at least ${t} characters long`):s&&e.push(`is at most ${s} characters long`),e.length?`The answer ${e.length>1?`${e.slice(0,-1).join(", ")}, and ${e[e.length-1]}`:e[0]}.`:""}function cn(a,e){const t=xe(a);if(t==="")return null;try{return new RegExp(t).test(e)}catch{return null}}function dn(){return window.wp?.os?.windowManager??null}const Et="allterrain-forms-validation";function hn(a){const e=dn(),t=wt(a.root);if(e?.openChild&&t){un(e,t,a);return}pn(a)}function un(a,e,t){const s=`${Et}-${t.field.id}`;a.getById?.(s)&&a.remove?.(s);const n={saved:!1},i=()=>{const o=a.getById?.(s);o?.close?o.close():a.remove?.(s)};a.openChild?.(e,{id:s,baseId:Et,url:`#${s}`,title:`Custom rule — ${t.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),$t(c,t,n,i,"window");const d=c.querySelector(".atfb-modal__actions");d&&l.append(d),o.append(l)},onClose:()=>{n.saved||t.onCancel?.()}})}function pn(a){const e=r("div",{class:"atfb-overlay"}),t={saved:!1},s=()=>{e.remove(),document.removeEventListener("keydown",n),t.saved||a.onCancel?.()},n=o=>{o.key==="Escape"&&s()},i=r("div",{class:"atfb-modal atfb-valwin",attrs:{role:"dialog","aria-label":"Custom validation rule"},children:[r("h2",{text:"Custom rule"})]});$t(i,a,t,s,"overlay"),e.append(i),e.addEventListener("click",o=>{o.target===e&&s()}),document.addEventListener("keydown",n),a.root.append(e),e.querySelector(".atfb-valwin__pane:not([hidden]) input, .atfb-valwin__pane:not([hidden]) textarea")?.focus()}function $t(a,e,t,s,n){const i=St(String(e.field.validationRecipe??""));i.mode==="blocks"&&xe(i)===""&&e.field.pattern&&(i.mode="regex",i.regex=String(e.field.pattern)),i.message||(i.message=String(e.field.messages?.invalid??""));const o=($,R)=>{const A=r("input",{class:"atfb-input",value:i[$],placeholder:R,attrs:{type:"text"}});return A.addEventListener("input",()=>{i[$]=A.value,M()}),A},l=($,R)=>{const A=r("input",{class:"atfb-input atfb-valwin__len",value:i[$],attrs:{type:"number",min:"0","aria-label":R}});return A.addEventListener("input",()=>{i[$]=A.value,M()}),A},c=r("div",{class:"atfb-valwin__chars",children:Object.entries(ye).map(([$,R])=>D(R.label,i.chars.includes($),A=>{i.chars=A?[...i.chars,$]:i.chars.filter(j=>j!==$),M()}))}),d=r("div",{class:"atfb-valwin__pane",children:[b("Starts with",o("starts","e.g. AT-")),b("Ends with",o("ends","e.g. -2026")),b("Must contain",o("contains","e.g. @")),b("Must not contain",o("notContains","e.g. spaces? type one")),b("Only these characters",c,"Leave every box unticked to allow anything."),b("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,M()});const v=r("div",{class:"atfb-valwin__pane",children:[b("Expression",h,"A regular expression, without slashes. Checked against the whole answer only if you anchor it with ^ and $.")]}),y=[["blocks","Easy blocks"],["regex","Expression (advanced)"]],u=$=>{i.mode=$,d.hidden=$!=="blocks",v.hidden=$!=="regex",M()},g=(()=>{if(Y("os-segmented")&&Y("os-segment")){const A=document.createElement("os-segmented");A.setAttribute("value",i.mode),A.setAttribute("label","How to write the rule"),A.classList.add("atfb-valwin__tabs");for(const[j,P]of y){const oe=document.createElement("os-segment");oe.setAttribute("value",j),oe.textContent=P,A.append(oe)}return A.addEventListener("os-pick",j=>{const P=j.detail?.value;(P==="blocks"||P==="regex")&&(A.setAttribute("value",P),u(P))}),A}const $=r("div",{class:"atfb-valwin__tabs",attrs:{role:"tablist"}}),R=()=>{$.replaceChildren(...y.map(([A,j])=>{const P=i.mode===A;return r("button",{class:`atfb-valwin__tab${P?" is-active":""}`,type:"button",text:j,attrs:{role:"tab","aria-selected":P?"true":"false"},on:{click:()=>{u(A),R()}}})}))};return R(),$})();d.hidden=i.mode!=="blocks",v.hidden=i.mode!=="regex";const f=r("input",{class:"atfb-input",value:i.message,placeholder:"That is not in the expected format.",attrs:{type:"text"}});f.addEventListener("input",()=>{i.message=f.value});const E=r("p",{class:"atfb-valwin__summary",attrs:{"aria-live":"polite"}}),N=r("div",{class:"atfb-valwin__samples"}),k=$=>{const R=r("span",{class:"atfb-valwin__verdict",attrs:{"aria-live":"polite"}}),A=r("input",{class:"atfb-input",value:$,placeholder:"Type a sample answer…",attrs:{type:"text"}});A.addEventListener("input",()=>M()),N.append(r("div",{class:"atfb-valwin__sample",children:[A,R]}))};for(const $ of i.tests.length?i.tests:["","",""])k($);const T=()=>Array.from(N.querySelectorAll("input")).map($=>$.value),M=()=>{const $=Lt(i);E.textContent=$||"Nothing yet — fill in a block above and the rule appears here in plain words.";for(const R of Array.from(N.querySelectorAll(".atfb-valwin__sample"))){const A=R.querySelector("input"),j=R.querySelector(".atfb-valwin__verdict");if(!A||!j)continue;const P=A.value===""?null:cn(i,A.value);j.textContent=P===null?"·":P?"✓ passes":"✗ fails",j.classList.toggle("is-pass",P===!0),j.classList.toggle("is-fail",P===!1)}};a.append(r("p",{class:"atfb-hint",text:`Describe what a good answer to “${e.field.label||"this question"}” looks like — no code needed.`}),g,d,v,r("div",{class:"atfb-valwin__try",children:[r("h3",{text:"Try it out"}),E,N,L("Add another sample",()=>{k(""),M()},"ghost","plus-alt2")]}),b("When it fails, say",f,"Shown to the visitor when their answer breaks the rule. Leave empty for the default wording."),r("div",{class:"atfb-modal__actions",children:[L(n==="window"?"Close without saving":"Cancel",s),L("Save rule",()=>{const $=xe(i);i.tests=T().filter(R=>R!=="").slice(0,10),t.saved=!0,e.onSave({pattern:$,recipe:i,message:i.message.trim()}),s()},"primary")]})),M()}const fn=["Contact","Numbers & codes","Text shape","Web"],Ct=[{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 mn(a){return Ct.find(e=>e.slug===a)??null}function We(){return window.wp?.os??null}const At="allterrain-forms/preview",Ue="allterrain-forms-preview";function bn(a){const e=We();if(!e?.registerTitleBarButton)return()=>{};const t=()=>{try{e.registerTitleBarButton({id:At,label:"Preview this form",icon:"dashicons-visibility",placement:"right",order:90,match:s=>{const n=s?.id??s?.config?.id??"";return n==="allterrain-forms"||n.startsWith("allterrain-forms#")},onClick:()=>void Tt(a),owner:"allterrain-forms-builder"})}catch{}};return e.ready?e.ready(t):t(),()=>{try{e.unregisterTitleBarButton?.(At)}catch{}}}async function Tt(a){a.isDirty()&&await a.save();const e=a.current();e&&Mt(e.id,e.title,e.previewUrl)}function Mt(a,e,t){const s=We();if(!s?.windowManager?.open){window.open(t,"_blank","noopener");return}s.windowManager.open({id:`${Ue}-${a}`,baseId:Ue,url:t,title:`Preview: ${e}`,icon:"dashicons-visibility"})}function gn(a,e,t){if(!We()?.windowManager?.open||!document.querySelector(`[data-window-id="${Ue}-${a}"]`))return;const i=t.includes("?")?"&":"?";Mt(a,e,`${t}${i}atf_r=${Date.now()}`)}const se="allterrain-forms/field",vn=["openstation/file","desktop-mode/file","openstation/attachment"],Ft="allterrain-forms/logic-map-v2";function J(a,e){return a.dataset.atfbBind=e,a}const It={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"}}},yn={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 Dt(a,e,t){const s=a[e.key],n=i=>t(e.key,i);if(e.control==="checkbox")return D(e.label,!!s,n);if(e.control==="commas"){const i=Array.isArray(s)?s:[];return b(e.label,C(i.join(", "),o=>{n(o.split(",").map(l=>l.trim().replace(/^\./,"").toLowerCase()).filter(Boolean))}),e.hint)}return e.control==="select"?b(e.label,O(String(s??""),e.options??[],n),e.hint):e.control==="textarea"?b(e.label,ue(String(s??""),n),e.hint):e.control==="number"?b(e.label,G(String(s??""),n),e.hint):b(e.label,J(C(String(s??""),n),e.key),e.hint)}function qt(a,e){const t=new Set(a.map(n=>n.key).filter(Boolean));let s=a.length+1;return e.split(` -`).map(n=>n.trim()).filter(Boolean).map((n,i)=>{const o=a[i]?.key;if(o)return{key:o,label:n};for(;t.has(`r${s}`);)s+=1;return t.add(`r${s}`),{key:`r${s}`,label:n}})}function Ot(a,e,t){const s=a.findIndex(i=>i.id===e);if(s<0)return null;const n=Math.max(0,Math.min(t,a.length-1));return n===s?null:{from:s,to:n}}const ze=[{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}"}],wn=["About the person filling it in","The date and time","About this site"],Ye=(a,e)=>W?.i18n?.[a]??e;class Nt{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=Jt(Ft)!=="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=Ce(()=>{this.save(!0)},2500),this.renderInspector=Vt(()=>{if(H(this.inspector),!this.schema||(this.root.classList.toggle("atfb--build-only-panes",this.tab!=="build"),this.tab!=="build"))return;const t=this.selected?this.locateField(this.selected):void 0,s=t?.field,n=t?.parent??null;if(this.root.classList.toggle("atfb--has-selection",!!s),!s){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===s.type),o=i?.supports??[],l=(c,d)=>{const h=this.liveField(s.id);h&&(h[c]=d,this.markDirty(),this.renderCanvas())};this.inspector.append(r("h3",{class:"atfb-inspector__title",text:i?.label??s.type})),n?this.inspector.append(r("p",{class:"atfb-hint atfb-inspector__crumb",text:`Inside ${n.label||"a repeater"} — the visitor answers this once per ${String(n.itemLabel??"")||"row"}.`}),r("p",{class:"atfb-hint",text:`Formulas aggregate it as {${n.id}.${s.id}} — e.g. sum( {${n.id}.${s.id}} ).`})):this.inspector.append(r("p",{class:"atfb-hint",text:`Reference this field as {field:${s.id}}`})),o.includes("label")&&this.inspector.append(b("Label",J(C(s.label,c=>l("label",c)),"label"))),o.includes("placeholder")&&this.inspector.append(b("Placeholder",J(C(s.placeholder,c=>l("placeholder",c)),"placeholder"))),o.includes("hint")&&this.inspector.append(b("Hint",J(C(s.hint,c=>l("hint",c)),"hint"),"Shown under the field, and read out with it.")),o.includes("nextlabel")&&this.inspector.append(b("Next button",J(C(String(s.nextLabel??""),c=>l("nextLabel",c)),"nextLabel"),"Leave empty for “Next”.")),o.includes("prevlabel")&&this.inspector.append(b("Back button",J(C(String(s.prevLabel??""),c=>l("prevLabel",c)),"prevLabel"),"Leave empty for “Back”.")),o.includes("addlabel")&&this.inspector.append(b("Add button",J(C(String(s.addLabel??""),c=>l("addLabel",c)),"addLabel"),"Leave empty for “Add another”.")),o.includes("required")&&this.inspector.append(D("Required",s.required,c=>l("required",c))),o.includes("width")&&this.inspector.append(b("Width",O(s.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(s,l)),this.renderTypeSettings(s,i,o,l),(s.type==="total"||o.includes("formula"))&&this.inspector.append(b("Formula",r("div",{class:"atfb-formula__row",children:[C(String(s.formula??""),c=>l("formula",c)),L("Formula editor",()=>tn({root:this.root,fields:this.schema?.fields??[],field:s,onSave:c=>{l("formula",c),this.renderInspector()}}))]}),"Reference answers with braces — {f1} * {f2} + 10 — or open the editor and click them in."),b("Currency symbol",C(String(s.currency??""),c=>l("currency",c)))),this.inspector.append(this.renderValidationSection(s,o,l)),n||(this.inspector.append(this.renderLogicSection(s)),o.includes("prefill")&&this.inspector.append(this.prefillControl(s,l))),o.includes("css")&&this.inspector.append(b("CSS class",C(s.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",t=>{const s=t.target;if(!(this.tab!=="build"||!this.selected||s.closest("[data-atfb-card], button, os-button, a, input, textarea, select, os-select, label, [contenteditable]"))){this.selected=null;for(const n of this.canvas.querySelectorAll(".atfb-card.is-selected"))n.classList.remove("is-selected");this.renderInspector()}})}async start(){try{const[s,n,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);this.config=s,this.themes=n,this.forms=i}catch(s){this.fail(s);return}this.teardowns.push(Yt([se])),this.teardowns.push(bn({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=s=>{this.dirty&&(s.preventDefault(),s.returnValue="")};window.addEventListener("beforeunload",e),this.teardowns.push(()=>window.removeEventListener("beforeunload",e));const t=s=>{!(s.metaKey||s.ctrlKey)||s.key.toLowerCase()!=="z"||s.target?.closest("input, textarea, [contenteditable]")||(s.preventDefault(),this.travel(s.shiftKey?1:-1))};if(this.root.addEventListener("keydown",t),this.teardowns.push(()=>this.root.removeEventListener("keydown",t)),this.renderBar(),this.renderPalette(),this.forms.length){const s=ls("builder");await this.open(s&&this.forms.some(n=>n.id===s)?s:this.forms[0].id)}else this.renderFormsList()}destroy(){this.canvasTarget?.(),this.canvasTarget=null,this.teardowns.forEach(e=>e()),this.teardowns=[]}fail(e){H(this.bar),this.bar.append(r("p",{class:"atfb-error",text:e instanceof Error?e.message:"Something went wrong loading your forms."}))}renderBar(){H(this.bar);const e=O(String(this.form?.id??""),[...this.forms.map(n=>({value:String(n.id),label:n.title||"(untitled)"}))],n=>void this.open(Number(n)));e.setAttribute("aria-label","Choose a form");const t=r("input",{class:"atfb-title",type:"text",value:this.form?.title??"",placeholder:"Untitled form",attrs:{"aria-label":"Form title"},on:{input:n=>{this.form&&(this.form.title=n.target.value,this.markDirty())}}}),s=r("div",{class:"atfb-tabs",attrs:{role:"tablist"},children:[["build","Build"],["theme","Theme"],["settings","Settings"],["notify","Notifications"],["confirm","Confirmations"]].map(([n,i])=>r("button",{class:`atfb-tab${this.tab===n?" is-active":""}`,type:"button",text:i,attrs:{role:"tab","aria-selected":this.tab===n},on:{click:()=>{this.tab=n,this.renderBar(),this.renderInspector(),this.renderCanvas()}}}))});this.bar.append(r("div",{class:"atfb-bar__left",children:[this.forms.length>1?e:null,t]}),s,r("div",{class:"atfb-bar__right",children:[this.historyButton("undo","Undo",-1),this.historyButton("redo","Redo",1),L("New",()=>void this.showTemplates(),"secondary","plus-alt2"),L("Export",()=>void this.exportForm(),"secondary","download"),L("Import",()=>void this.importForm(),"secondary","upload"),L("Preview",()=>void this.preview(),"secondary","visibility"),L("Entries",()=>this.openEntries(),"secondary","list-view"),this.logicMapButton(),this.saveButton()]}))}liveField(e){return this.locateField(e)?.field}locateField(e){const t=this.schema?.fields??[];for(let s=0;sthis.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 t=this.historyAt+e;!this.schema||t<0||t>=this.history.length||(this.historyAt=t,this.schema=JSON.parse(this.history[t]),this.schema.fields.some(s=>s.id===this.selected)||(this.selected=null),this.markDirty(),this.renderBar(),this.renderCanvas(),this.renderInspector())}historyButton(e,t,s){const n=L(t,()=>this.travel(s),"secondary",e);return n.setAttribute("data-atfb-history",String(s)),n.disabled=!this.canTravel(s),n}canTravel(e){const t=this.historyAt+e;return t>=0&&tURL.revokeObjectURL(s),1e3)}async importForm(){const e=r("input",{type:"file",attrs:{accept:"application/json,.json"}});e.addEventListener("change",async()=>{const t=e.files?.[0];if(t)try{const s=JSON.parse(await t.text());if(!s.schema)throw new Error("That file does not contain a form.");const n=await I.createForm({title:s.title??t.name.replace(/\.json$/i,""),schema:s.schema});this.forms.unshift({id:n.id,title:n.title,status:n.status,modified:n.modified,fields:n.schema.fields.length,theme:n.schema.settings.theme,entries:0,unread:0,views:0,submissions:0,shortcode:n.shortcode}),this.form=n,this.schema=n.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot(),this.renderBar(),this.renderCanvas(),this.renderInspector(),B("Form imported",n.title)}catch(s){B("Could not import that file",s instanceof Error?s.message:"","error")}}),e.click()}saveButton(){const e=L("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 t=this.editGeneration;try{const s=await I.updateForm(this.form.id,{title:this.form.title,schema:this.schema});if(t===this.editGeneration){this.form=s,this.schema=s.schema,this.dirty=!1,this.rebindCanvas();const i=this.bar.querySelector("[data-atfb-save]");i&&(i.disabled=!0)}Ss(s.id);const n=this.forms.find(i=>i.id===s.id);n&&(n.title=s.title),gn(s.id,s.title,s.previewUrl),e||B("Form saved",s.title)}catch(s){B(Ye("saveFailed","Could not save"),s instanceof Error?s.message:"","error")}finally{this.saveInFlight=!1;const s=this.queuedSave;this.queuedSave=null,s&&this.save(s.silent)}}async openFormById(e){await this.open(e)}async open(e){if(!(this.dirty&&!await fe("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(t){this.fail(t);return}this.renderBar(),this.renderCanvas(),this.renderInspector(),this.announceIdentity()}}announceIdentity(){this.form&&_t(this.root,on(this.form,W?.adminUrl??""))}async showTemplates(){if(!this.config)return;const e=r("div",{class:"atfb-overlay"}),t=i=>{i.key==="Escape"&&s()},s=()=>{e.remove(),document.removeEventListener("keydown",t)},n=r("div",{class:"atfb-templates",children:this.config.templates.map(i=>r("button",{class:"atfb-template",type:"button",on:{click:async()=>{s();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){B("Could not create the form",o instanceof Error?o.message:"","error")}}},children:[U(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"}),n,this.archivedFormsSection(s),r("div",{class:"atfb-modal__actions",children:[L("Cancel",s)]})]})),e.addEventListener("click",i=>{i.target===e&&s()}),document.addEventListener("keydown",t),this.root.append(e),n.querySelector("button")?.focus()}archivedFormsSection(e){const t=r("div",{class:"atfb-archived"});return I.listArchivedForms().then(s=>{s.length&&t.append(r("h3",{class:"atfb-archived__title",text:"Or bring one back from the archive"}),...s.map(n=>r("div",{class:"atfb-archived__row",children:[r("div",{class:"atfb-archived__meta",children:[r("strong",{text:n.title||"(untitled)"}),r("span",{class:"atfb-hint",text:`${n.entries} ${n.entries===1?"entry":"entries"} · ${n.submissions} submissions · ${n.views} views`})]}),L("Restore",async()=>{try{const i=await I.unarchiveForm(n.id);e(),this.forms.unshift(i),B("Form restored",`${i.title||"(untitled)"} is back, with its entries and stats.`),await this.open(i.id)}catch(i){B("Could not restore the form",i instanceof Error?i.message:"","error")}},"secondary","undo")]})))}).catch(()=>{}),t}renderFormsList(){H(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."}),L("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(`${W?.adminUrl??""}admin.php?page=allterrain-forms-entries`)}renderPalette(){if(!this.config)return;H(this.palette);const e=new Map;for(const s of this.config.fieldTypes){const n=e.get(s.group)??[];n.push(s),e.set(s.group,n)}const t=r("input",{class:"atfb-input atfb-palette__search",type:"search",placeholder:"Search fields",attrs:{"aria-label":"Search field types"},on:{input:s=>{const n=s.target.value.toLowerCase().trim();this.palette.querySelectorAll(".atfb-chip").forEach(i=>{const o=(i.textContent??"").toLowerCase();i.hidden=n!==""&&!o.includes(n)}),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(t);for(const[s,n]of Object.entries(this.config.groups)){const i=e.get(s);i?.length&&this.palette.append(r("div",{class:"atfb-group",children:[r("h3",{class:"atfb-group__title",text:n}),r("div",{class:"atfb-group__items",children:i.map(o=>this.paletteChip(o))})]}))}}paletteChip(e){const t=r("button",{class:"atfb-chip",type:"button",title:e.description,attrs:{"data-atf-type":e.type},children:[U(e.icon),r("span",{text:e.label})]});return t.addEventListener("pointerdown",s=>{const n=r("div",{class:"atfb-chip atfb-chip--ghost",children:[U(e.icon),r("span",{text:e.label})]});K().start({payload:Le(se,t,{fieldType:e.type,isNew:!0},s,n),origin:s,onClickOnly:()=>this.addField(e.type)})}),t.addEventListener("click",s=>{K().recentlyEndedDrag()&&s.preventDefault()}),t}renderCanvas(){if(H(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:Ye("emptyCanvas","Drag a field from the left to begin.")})),this.schema.fields.forEach((s,n)=>{e.append(this.renderFieldCard(s,n))});const t=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(t),this.registerCanvasTarget(e),this.paintLogicMap(t),this.paintCanvasTheme()}prefillControl(e,t){const s=e.prefill.startsWith("query:"),n=ze.some(y=>y.value===e.prefill),i=s?"query":n&&e.prefill||(e.prefill?"custom":""),o=r("div",{class:"atfb-prefill__detail"}),l=r("p",{class:"atfb-row__hint atfb-prefill__preview"}),c=y=>{if(o.replaceChildren(),l.replaceChildren(),y==="query"){const u=e.prefill.startsWith("query:")?e.prefill.slice(6):"";o.append(C(u,x=>{const g=x.trim();t("prefill",g?`query:${g}`:""),d(`query:${g}`)},"utm_source"),r("p",{class:"atfb-row__hint",text:"The name of the parameter in the link people arrive on."}))}y==="custom"&&o.append(C(e.prefill,u=>{t("prefill",u),d(u)},"myplugin:something"),r("p",{class:"atfb-row__hint",text:"For a source another plugin has added through atf_resolve_prefill."})),d(e.prefill)},d=y=>{if(l.replaceChildren(),!y)return;if(y.startsWith("query:")){const x=y.slice(6);x&&(l.textContent=`A visit to …/your-page/?${x}=abc opens the form with “abc” in it.`);return}const u=ze.find(x=>x.value===y)?.tag;u&&De(this.form?.id??0).then(x=>{for(const g of x)for(const f of g.items)if(f.tag===u){const E=y.startsWith("user:");if(!f.sample){l.textContent="Empty unless the visitor is signed in.";return}l.textContent=E?`Opens with “${f.sample}” for you — empty for a visitor who is not signed in.`:`Opens with “${f.sample}”.`;return}})};c(i);const h=r("select",{class:"atfb-input atfb-select",on:{change:y=>{const u=y.target.value;t("prefill",u==="query"||u==="custom"?"":u),c(u)}}});h.append(r("option",{value:"",text:"Nothing — leave it empty",attrs:{selected:i===""}}));for(const y of wn){const u=document.createElement("optgroup");u.label=y;for(const x of ze.filter(g=>g.group===y))u.append(r("option",{value:x.value,text:x.label,attrs:{selected:x.value===i}}));h.append(u)}const v=document.createElement("optgroup");return v.label="From the link they arrived on",v.append(r("option",{value:"query",text:"A parameter in the web address",attrs:{selected:i==="query"}})),h.append(v,r("option",{value:"custom",text:"Something else (advanced)",attrs:{selected:i==="custom"}})),b("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,t){const s=t.some(i=>i.kind==="field"&&i.missing),n=r("span",{class:`atfb-cond${s?" is-broken":""}`,attrs:{"aria-label":nt(t)},children:[U("randomize"),...t.map(i=>this.renderConditionToken(e,i))]});return n.addEventListener("pointerdown",i=>i.stopPropagation()),n.addEventListener("click",i=>i.stopPropagation()),n.addEventListener("keydown",i=>i.stopPropagation()),n}editCondition(e,t,s=!0,n=""){const i=this.liveField(e)?.logic;if(i){if(t(i),this.markDirty(),!s){this.logicMap?.setEdges(me(this.schema?.fields??[]));return}this.renderCanvas(),this.renderInspector(),n&&window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-cond="${CSS.escape(n)}"]`)?.focus()})}}condSelect(e,t,s,n,i){if(Y("os-select")&&Y("os-option")){const o=document.createElement("os-select");o.setAttribute("value",e),o.setAttribute("aria-label",n),o.setAttribute("data-cond",s),o.className="atfb-cond__control",o.title=n;for(const l of t){const c=document.createElement("os-option");c.setAttribute("value",l.value),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:n,attrs:{"aria-label":n,"data-cond":s},on:{change:o=>i(o.target.value)},children:t.map(o=>r("option",{value:o.value,text:o.label,attrs:{selected:o.value===e}}))})}renderConditionToken(e,t){if(t.kind==="field"&&!t.missing)return r("button",{class:"atfb-cond__chip atfb-cond__chip--field",type:"button",text:t.text,title:"Go to this question",on:{click:n=>{n.stopPropagation(),this.selectField(t.fieldId),this.canvas.querySelector(`[data-atfb-card="${CSS.escape(t.fieldId)}"]`)?.scrollIntoView({block:"nearest",behavior:"smooth"})}}});if(t.kind==="verb")return r("button",{class:"atfb-cond__verb",type:"button",text:t.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,s=>{s.action=s.action==="hide"?"show":"hide"},!0,`${e.id}:verb`)}});if(t.kind==="join")return r("button",{class:"atfb-cond__join",type:"button",text:t.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,s=>{s.match=s.match==="all"?"any":"all"},!0,`${e.id}:join`)}});if(t.kind==="operator"){const s=`${e.id}:op:${t.ruleIndex}`;return this.condSelect(t.operator,Object.entries(Ae).map(([n,i])=>({value:n,label:i})),s,"How the answer is compared",n=>this.editCondition(e.id,i=>{const o=i.rules[t.ruleIndex];o&&(o.operator=n)},!0,s))}return t.kind==="value"?this.renderConditionValue(e,t):r("span",{class:"atfb-cond__chip atfb-cond__chip--missing",text:t.text})}renderConditionValue(e,t){const s=`${e.id}:value:${t.ruleIndex}`,n=this.schema?.fields.find(c=>c.id===t.sourceId),i=(c,d)=>this.editCondition(e.id,h=>{const v=h.rules[t.ruleIndex];v&&(v.value=c)},d,s);if(n?.choices?.length){const c=n.choices.map(d=>({value:d.value,label:d.label||d.value}));return t.raw!==""&&!n.choices.some(d=>d.value===t.raw)&&c.unshift({value:t.raw,label:t.text}),this.condSelect(t.raw,c,s,"The answer that triggers this",d=>i(d,!0))}const o=["number","range","scale","rating","total"].includes(n?.type??""),l=r("input",{class:"atfb-cond__chip atfb-cond__chip--value atfb-cond__value",value:t.raw,title:"The answer that triggers this. Edit it here.",attrs:{type:"text","aria-label":"The answer that triggers this","data-cond":s,inputmode:o?"decimal":void 0,size:String(Math.max(2,Math.min(24,t.raw.length||2)))}});return l.addEventListener("input",()=>{l.size=Math.max(2,Math.min(24,l.value.length||2)),i(l.value,!1)}),l.addEventListener("change",()=>i(l.value,!0)),l.addEventListener("keydown",c=>{c.key==="Enter"&&(c.preventDefault(),i(l.value,!0))}),l}section(e,t,s,n=!1){const i=r("details",{class:"atfb-section",attrs:{open:this.openSections.get(e)??n},children:[r("summary",{text:t}),...s]});return i.addEventListener("toggle",()=>this.openSections.set(e,i.open)),i}logicMapButton(){const e=me(this.schema?.fields??[]).length>0,t=L(this.logicMapOn?"Hide logic":"Show logic",()=>{this.logicMapOn=!this.logicMapOn,Qt(Ft,this.logicMapOn?"on":"off"),this.renderBar(),this.renderCanvas()},this.logicMapOn?"primary":"secondary","randomize");return t.title="Draw a line from each question to the ones it decides.",t.hidden=!e,t}paintLogicMap(e){this.logicMap?.destroy(),this.logicMap=null;const t=this.schema?.fields??[],s=me(t);if(!s.length||!this.logicMapOn)return;e.classList.add("has-logicmap");const n=new ps(e);n.setEdges(s),n.highlight(this.selected??""),this.logicMap=n,e.addEventListener("pointerover",i=>{const o=i.target.closest("[data-atfb-card]");n.highlight(o?.dataset.atfbCard??this.selected??"")}),e.addEventListener("pointerleave",()=>n.highlight(this.selected??""))}renderFieldCard(e,t){const s=this.config?.fieldTypes.find(d=>d.type===e.type),n=this.selected===e.id,i=this.schema?.fields??[],o=ds(e,i),l=us(i).get(e.id)??0,c=r("div",{class:`atfb-card${n?" is-selected":""}`,attrs:{"data-atfb-card":e.id,"data-index":t,tabindex:"0",role:"button","aria-pressed":n,"aria-label":`${e.label||s?.label||e.type}, ${t+1} of ${this.schema?.fields.length??0}`},children:[r("div",{class:"atfb-card__grip",attrs:{"aria-hidden":"true"},children:[U("menu")]}),r("div",{class:"atfb-card__body",children:[r("div",{class:"atfb-card__head",children:[U(s?.icon??"dashicons-forms"),r("span",{class:"atfb-card__type",text:s?.label??e.type}),this.requiredToggle(e),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]}),ot(e,s,{edit:d=>{const h=this.liveField(e.id);if(!h)return;d(h),this.markDirty(),this.syncInspector(h);const v=this.selected?this.locateField(this.selected):void 0;v?.parent&&v.parent.id===h.id&&this.syncInspector(v.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}),o.length?this.renderCondition(e,o):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))]})]});return c.addEventListener("click",d=>{d.target.closest(".atfb-card__actions")||K().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"?t-1:t+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")||K().start({payload:Le(se,c,{fieldId:e.id,field:e,isNew:!1},d),origin:d})}),c}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:s=>s.stopPropagation(),click:s=>{s.stopPropagation(),e.required=!e.required,this.markDirty(),this.renderCanvas(),this.renderInspector()}}})}cardAction(e,t,s){return r("button",{class:"atfb-card__action",type:"button",title:t,attrs:{"aria-label":t},on:{click:n=>{n.stopPropagation(),s()}},children:[U(e)]})}registerCanvasTarget(e){this.canvasTarget?.(),this.canvasTarget=null;const t=r("div",{class:"atfb-marker",attrs:{"aria-hidden":"true"}}),s=K().registerDropTarget({id:`atfb-canvas-${this.form?.id??0}`,element:e,accept:o=>o.type===se,onEnter:()=>e.classList.add("is-dropping"),onLeave:()=>{e.classList.remove("is-dropping"),t.remove()},onDrop:(o,l)=>{e.classList.remove("is-dropping"),t.remove();const c=o.payload.data,d=c.fieldId?this.canvas.querySelector(`[data-atfb-card="${CSS.escape(c.fieldId)}"]`):null,h=Ee(e,".atfb-card",l.clientY,d??void 0);if(c.isNew&&c.fieldType){this.addField(c.fieldType,h);return}if(c.fieldId&&this.locateField(c.fieldId)){this.relocateField(c.fieldId,null,h);return}c.field&&this.insertField({...c.field,id:""},h)}}),n=this.wireRepeaterZones(e),i=o=>{const l=o.detail;if(l?.payload?.type!==se||!e.classList.contains("is-dropping"))return;const c=l.payload.data?.fieldId?this.canvas.querySelector(`[data-atfb-card="${CSS.escape(l.payload.data.fieldId)}"]`):null,d=l.clientY??0,h=Ee(e,".atfb-card",d,c??void 0),v=Array.from(e.querySelectorAll(".atfb-card")).filter(y=>y!==c);h>=v.length?e.append(t):v[h].before(t)};document.addEventListener("os.drag.move",i),this.canvasTarget=()=>{s(),n.forEach(o=>o()),document.removeEventListener("os.drag.move",i)}}wireRepeaterZones(e){const t=[];return e.querySelectorAll("[data-atfb-repeater-zone]").forEach(s=>{const n=s.dataset.atfbRepeaterZone??"";t.push(K().registerDropTarget({id:`atfb-repzone-${this.form?.id??0}-${n}`,element:s,accept:i=>{if(i.type!==se)return!1;const o=i.data;if(o.fieldId===n)return!1;const l=o.isNew?o.fieldType:this.locateField(o.fieldId??"")?.field.type??o.field?.type;return!!l&&this.allowedInRepeater(l)},onEnter:()=>s.classList.add("is-dropping"),onLeave:()=>s.classList.remove("is-dropping"),onDrop:(i,o)=>{s.classList.remove("is-dropping");const l=i.payload.data,c=l.fieldId?e.querySelector(`[data-atfb-subfield="${CSS.escape(l.fieldId)}"]`):null,d=Ee(s,".atfb-subcard",o.clientY,c??void 0);if(l.isNew&&l.fieldType){this.addFieldToRepeater(l.fieldType,n,d);return}if(l.fieldId&&this.locateField(l.fieldId)){this.relocateField(l.fieldId,n,d);return}l.field&&this.insertFieldIntoRepeater({...l.field,id:""},n,d)}})),s.querySelectorAll(".atfb-subcard").forEach(i=>{const o=i.dataset.atfbSubfield??"";i.addEventListener("click",l=>{l.target.closest(".atfb-preview__remove")||(l.stopPropagation(),!K().recentlyEndedDrag()&&this.selectField(o))}),i.addEventListener("keydown",l=>{if(l.stopPropagation(),l.key==="Enter"||l.key===" "){l.preventDefault(),this.selectField(o);return}if(l.altKey&&(l.key==="ArrowUp"||l.key==="ArrowDown")){l.preventDefault();const c=this.locateField(o);c&&(this.relocateField(o,n,l.key==="ArrowUp"?c.index-1:c.index+1),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-subfield="${CSS.escape(o)}"]`)?.focus()}));return}(l.key==="Delete"||l.key==="Backspace")&&(l.preventDefault(),this.deleteField(o))}),i.addEventListener("pointerdown",l=>{if(l.stopPropagation(),l.target.closest(".atfb-preview__remove"))return;const c=this.locateField(o);c&&K().start({payload:Le(se,i,{fieldId:o,parentId:n,field:c.field,isNew:!1},l),origin:l})})})}),t}addField(e,t){const s=this.buildField(e);s&&this.insertField(s,t)}buildField(e){const t=this.config?.fieldTypes.find(n=>n.type===e);return!t||!this.schema?void 0:{id:this.nextFieldId(),type:e,label:t.input?t.label:"",placeholder:"",hint:"",required:!1,width:"full",cssClass:"",default:"",choices:t.choices?[{label:"First choice",value:"first"},{label:"Second choice",value:"second"}]:[],logic:{enabled:!1,action:"show",match:"all",rules:[]},messages:{},prefill:"",...t.settings}}allowedInRepeater(e){const t=this.config?.fieldTypes.find(s=>s.type===e);return!t||!t.input?!1:!["repeater","page_break","file","signature","total"].includes(e)}addFieldToRepeater(e,t,s){if(!this.allowedInRepeater(e))return;const n=this.buildField(e);n&&this.insertFieldIntoRepeater(n,t,s)}insertFieldIntoRepeater(e,t,s){const n=this.liveField(t);if(!this.schema||!n||n.type!=="repeater")return;e.id||(e.id=this.nextFieldId()),this.snapshot(),Array.isArray(n.fields)||(n.fields=[]);const i=n.fields,o=s===void 0?i.length:Math.max(0,Math.min(s,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,t,s){if(!this.schema)return;const n=this.locateField(e);if(!n)return;if(!n.parent&&!t){this.moveField(e,s);return}const i=t?this.liveField(t):null;if(t&&(!i||i.type!=="repeater"||e===t))return;i&&!Array.isArray(i.fields)&&(i.fields=[]);const o=i?i.fields:this.schema.fields;this.snapshot(),n.list.splice(n.index,1);const l=Math.max(0,Math.min(s,o.length));o.splice(l,0,n.field),this.selected=n.field.id,this.markDirty(),this.renderCanvas(),this.renderInspector()}insertField(e,t){if(!this.schema)return;e.id||(e.id=this.nextFieldId()),this.snapshot();const s=t===void 0?this.schema.fields.length:Math.max(0,Math.min(t,this.schema.fields.length));this.schema.fields.splice(s,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,t){if(!this.schema)return;const s=Ot(this.schema.fields,e,t);if(!s)return;this.snapshot();const[n]=this.schema.fields.splice(s.from,1);this.schema.fields.splice(s.to,0,n),this.markDirty(),this.renderCanvas()}duplicateField(e){if(!this.schema)return;const t=this.locateField(e);if(!t)return;const s=JSON.parse(JSON.stringify(t.field)),n=this.usedFieldIds(),i=()=>{let o=n.size+1;for(;n.has(`f${o}`);)o++;const l=`f${o}`;return n.add(l),l};s.id=i();for(const o of s.fields??[])o.id=i();if(t.parent){this.snapshot(),t.list.splice(t.index+1,0,s),this.selected=s.id,this.markDirty(),this.renderCanvas(),this.renderInspector();return}this.insertField(s,t.index+1)}async deleteField(e){if(!this.schema)return;const t=this.locateField(e);if(!t)return;const s=this.schema.fields.filter(i=>i.logic?.rules?.some(o=>o.field===e)),n=s.length?`Delete this field? ${s.length} other field${s.length===1?"":"s"} use it in a condition, and those conditions will stop working.`:Ye("confirmDelete","Delete this? It cannot be undone.");await fe(n,"Delete field")&&(this.snapshot(),t.list.splice(t.index,1),this.selected===e&&(this.selected=null),this.markDirty(),this.renderCanvas(),this.renderInspector())}selectField(e){this.selected=e;for(const t of this.canvas.querySelectorAll("[data-atfb-card]")){const s=t.dataset.atfbCard===e;t.classList.toggle("is-selected",s),t.setAttribute("aria-pressed",s?"true":"false")}for(const t of this.canvas.querySelectorAll("[data-atfb-subfield]"))t.classList.toggle("is-selected",t.dataset.atfbSubfield===e);this.logicMap?.highlight(e),this.renderInspector()}nextFieldId(){const e=this.usedFieldIds();let t=e.size+1;for(;e.has(`f${t}`);)t++;return`f${t}`}usedFieldIds(){const e=new Set;for(const t of this.schema?.fields??[]){e.add(t.id);for(const s of t.fields??[])e.add(s.id)}return e}nextEntryId(e,t){const s=new Set(t.map(i=>i.id));let n=t.length+1;for(;s.has(`${e}${n}`);)n++;return`${e}${n}`}renderTypeSettings(e,t,s,n){for(const i of s){const o=It[i];o&&(this.inspector.append(Dt(e,o,n)),o.also&&this.inspector.append(Dt(e,{...o,key:o.also.key,label:o.also.label,hint:o.also.hint},n)))}s.includes("rows")&&e.type!=="likert"&&this.inspector.append(b("Lines tall",G(String(e.rows??""),i=>n("rows",i)))),s.includes("rows")&&e.type==="likert"&&this.inspector.append(this.renderStatementList(e,n)),s.includes("parts")&&this.inspector.append(this.renderPartsEditor(e,t,n)),s.includes("default")&&!["files","object"].includes(t?.value??"")&&this.inspector.append(this.renderDefaultControl(e,t,n))}renderStatementList(e,t){const s=Array.isArray(e.rows)?e.rows:[];return b("Statements",ue(s.map(n=>n.label??"").join(` +`).map(n=>n.trim()).filter(Boolean).map((n,i)=>{const o=a[i]?.key;if(o)return{key:o,label:n};for(;t.has(`r${s}`);)s+=1;return t.add(`r${s}`),{key:`r${s}`,label:n}})}function Ot(a,e,t){const s=a.findIndex(i=>i.id===e);if(s<0)return null;const n=Math.max(0,Math.min(t,a.length-1));return n===s?null:{from:s,to:n}}const ze=[{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}"}],wn=["About the person filling it in","The date and time","About this site"],Ye=(a,e)=>W?.i18n?.[a]??e;class Nt{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=Jt(Ft)!=="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=Ce(()=>{this.save(!0)},2500),this.renderInspector=Vt(()=>{if(H(this.inspector),!this.schema||(this.root.classList.toggle("atfb--build-only-panes",this.tab!=="build"),this.tab!=="build"))return;const t=this.selected?this.locateField(this.selected):void 0,s=t?.field,n=t?.parent??null;if(this.root.classList.toggle("atfb--has-selection",!!s),!s){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===s.type),o=i?.supports??[],l=(c,d)=>{const h=this.liveField(s.id);h&&(h[c]=d,this.markDirty(),this.renderCanvas())};this.inspector.append(r("h3",{class:"atfb-inspector__title",text:i?.label??s.type})),n?this.inspector.append(r("p",{class:"atfb-hint atfb-inspector__crumb",text:`Inside ${n.label||"a repeater"} — the visitor answers this once per ${String(n.itemLabel??"")||"row"}.`}),r("p",{class:"atfb-hint",text:`Formulas aggregate it as {${n.id}.${s.id}} — e.g. sum( {${n.id}.${s.id}} ).`})):this.inspector.append(r("p",{class:"atfb-hint",text:`Reference this field as {field:${s.id}}`})),o.includes("label")&&this.inspector.append(b("Label",J(C(s.label,c=>l("label",c)),"label"))),o.includes("placeholder")&&this.inspector.append(b("Placeholder",J(C(s.placeholder,c=>l("placeholder",c)),"placeholder"))),o.includes("hint")&&this.inspector.append(b("Hint",J(C(s.hint,c=>l("hint",c)),"hint"),"Shown under the field, and read out with it.")),o.includes("nextlabel")&&this.inspector.append(b("Next button",J(C(String(s.nextLabel??""),c=>l("nextLabel",c)),"nextLabel"),"Leave empty for “Next”.")),o.includes("prevlabel")&&this.inspector.append(b("Back button",J(C(String(s.prevLabel??""),c=>l("prevLabel",c)),"prevLabel"),"Leave empty for “Back”.")),o.includes("addlabel")&&this.inspector.append(b("Add button",J(C(String(s.addLabel??""),c=>l("addLabel",c)),"addLabel"),"Leave empty for “Add another”.")),o.includes("required")&&this.inspector.append(D("Required",s.required,c=>l("required",c))),o.includes("width")&&this.inspector.append(b("Width",O(s.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(s,l)),this.renderTypeSettings(s,i,o,l),(s.type==="total"||o.includes("formula"))&&this.inspector.append(b("Formula",r("div",{class:"atfb-formula__row",children:[C(String(s.formula??""),c=>l("formula",c)),L("Formula editor",()=>tn({root:this.root,fields:this.schema?.fields??[],field:s,onSave:c=>{l("formula",c),this.renderInspector()}}))]}),"Reference answers with braces — {f1} * {f2} + 10 — or open the editor and click them in."),b("Currency symbol",C(String(s.currency??""),c=>l("currency",c)))),this.inspector.append(this.renderValidationSection(s,o,l)),n||(this.inspector.append(this.renderLogicSection(s)),o.includes("prefill")&&this.inspector.append(this.prefillControl(s,l))),o.includes("css")&&this.inspector.append(b("CSS class",C(s.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",t=>{const s=t.target;if(!(this.tab!=="build"||!this.selected||s.closest("[data-atfb-card], button, os-button, a, input, textarea, select, os-select, label, [contenteditable]"))){this.selected=null;for(const n of this.canvas.querySelectorAll(".atfb-card.is-selected"))n.classList.remove("is-selected");this.renderInspector()}})}async start(){try{const[s,n,i]=await Promise.all([I.config(),I.listThemes(),I.listForms()]);this.config=s,this.themes=n,this.forms=i}catch(s){this.fail(s);return}this.teardowns.push(Yt([se])),this.teardowns.push(bn({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=s=>{this.dirty&&(s.preventDefault(),s.returnValue="")};window.addEventListener("beforeunload",e),this.teardowns.push(()=>window.removeEventListener("beforeunload",e));const t=s=>{!(s.metaKey||s.ctrlKey)||s.key.toLowerCase()!=="z"||s.target?.closest("input, textarea, [contenteditable]")||(s.preventDefault(),this.travel(s.shiftKey?1:-1))};if(this.root.addEventListener("keydown",t),this.teardowns.push(()=>this.root.removeEventListener("keydown",t)),this.renderBar(),this.renderPalette(),this.forms.length){const s=ls("builder");await this.open(s&&this.forms.some(n=>n.id===s)?s:this.forms[0].id)}else this.renderFormsList()}destroy(){this.canvasTarget?.(),this.canvasTarget=null,this.teardowns.forEach(e=>e()),this.teardowns=[]}fail(e){H(this.bar),this.bar.append(r("p",{class:"atfb-error",text:e instanceof Error?e.message:"Something went wrong loading your forms."}))}renderBar(){H(this.bar);const e=O(String(this.form?.id??""),[...this.forms.map(n=>({value:String(n.id),label:n.title||"(untitled)"}))],n=>void this.open(Number(n)));e.setAttribute("aria-label","Choose a form");const t=r("input",{class:"atfb-title",type:"text",value:this.form?.title??"",placeholder:"Untitled form",attrs:{"aria-label":"Form title"},on:{input:n=>{this.form&&(this.form.title=n.target.value,this.markDirty())}}}),s=r("div",{class:"atfb-tabs",attrs:{role:"tablist"},children:[["build","Build"],["theme","Theme"],["settings","Settings"],["notify","Notifications"],["confirm","Confirmations"]].map(([n,i])=>r("button",{class:`atfb-tab${this.tab===n?" is-active":""}`,type:"button",text:i,attrs:{role:"tab","aria-selected":this.tab===n},on:{click:()=>{this.tab=n,this.renderBar(),this.renderInspector(),this.renderCanvas()}}}))});this.bar.append(r("div",{class:"atfb-bar__left",children:[this.forms.length>1?e:null,t]}),s,r("div",{class:"atfb-bar__right",children:[this.historyButton("undo","Undo",-1),this.historyButton("redo","Redo",1),L("New",()=>void this.showTemplates(),"secondary","plus-alt2"),L("Export",()=>void this.exportForm(),"secondary","download"),L("Import",()=>void this.importForm(),"secondary","upload"),L("Preview",()=>void this.preview(),"secondary","visibility"),L("Entries",()=>this.openEntries(),"secondary","list-view"),this.logicMapButton(),this.saveButton()]}))}liveField(e){return this.locateField(e)?.field}locateField(e){const t=this.schema?.fields??[];for(let s=0;sthis.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 t=this.historyAt+e;!this.schema||t<0||t>=this.history.length||(this.historyAt=t,this.schema=JSON.parse(this.history[t]),this.schema.fields.some(s=>s.id===this.selected)||(this.selected=null),this.markDirty(),this.renderBar(),this.renderCanvas(),this.renderInspector())}historyButton(e,t,s){const n=L(t,()=>this.travel(s),"secondary",e);return n.setAttribute("data-atfb-history",String(s)),n.disabled=!this.canTravel(s),n}canTravel(e){const t=this.historyAt+e;return t>=0&&tURL.revokeObjectURL(s),1e3)}async importForm(){const e=r("input",{type:"file",attrs:{accept:"application/json,.json"}});e.addEventListener("change",async()=>{const t=e.files?.[0];if(t)try{const s=JSON.parse(await t.text());if(!s.schema)throw new Error("That file does not contain a form.");const n=await I.createForm({title:s.title??t.name.replace(/\.json$/i,""),schema:s.schema});this.forms.unshift({id:n.id,title:n.title,status:n.status,modified:n.modified,fields:n.schema.fields.length,theme:n.schema.settings.theme,entries:0,unread:0,views:0,submissions:0,shortcode:n.shortcode}),this.form=n,this.schema=n.schema,this.selected=null,this.dirty=!1,this.history=[],this.historyAt=-1,this.snapshot(),this.renderBar(),this.renderCanvas(),this.renderInspector(),B("Form imported",n.title)}catch(s){B("Could not import that file",s instanceof Error?s.message:"","error")}}),e.click()}saveButton(){const e=L("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 t=this.editGeneration;try{const s=await I.updateForm(this.form.id,{title:this.form.title,schema:this.schema});if(t===this.editGeneration){this.form=s,this.schema=s.schema,this.dirty=!1,this.rebindCanvas();const i=this.bar.querySelector("[data-atfb-save]");i&&(i.disabled=!0)}Ss(s.id);const n=this.forms.find(i=>i.id===s.id);n&&(n.title=s.title),gn(s.id,s.title,s.previewUrl),e||B("Form saved",s.title)}catch(s){B(Ye("saveFailed","Could not save"),s instanceof Error?s.message:"","error")}finally{this.saveInFlight=!1;const s=this.queuedSave;this.queuedSave=null,s&&this.save(s.silent)}}async openFormById(e){await this.open(e)}async open(e){if(!(this.dirty&&!await fe("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(t){this.fail(t);return}this.renderBar(),this.renderCanvas(),this.renderInspector(),this.announceIdentity()}}announceIdentity(){this.form&&_t(this.root,on(this.form,W?.adminUrl??""))}async showTemplates(){if(!this.config)return;const e=r("div",{class:"atfb-overlay"}),t=i=>{i.key==="Escape"&&s()},s=()=>{e.remove(),document.removeEventListener("keydown",t)},n=r("div",{class:"atfb-templates",children:this.config.templates.map(i=>r("button",{class:"atfb-template",type:"button",on:{click:async()=>{s();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){B("Could not create the form",o instanceof Error?o.message:"","error")}}},children:[U(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"}),n,this.archivedFormsSection(s),r("div",{class:"atfb-modal__actions",children:[L("Cancel",s)]})]})),e.addEventListener("click",i=>{i.target===e&&s()}),document.addEventListener("keydown",t),this.root.append(e),n.querySelector("button")?.focus()}archivedFormsSection(e){const t=r("div",{class:"atfb-archived"});return I.listArchivedForms().then(s=>{s.length&&t.append(r("h3",{class:"atfb-archived__title",text:"Or bring one back from the archive"}),...s.map(n=>r("div",{class:"atfb-archived__row",children:[r("div",{class:"atfb-archived__meta",children:[r("strong",{text:n.title||"(untitled)"}),r("span",{class:"atfb-hint",text:`${n.entries} ${n.entries===1?"entry":"entries"} · ${n.submissions} submissions · ${n.views} views`})]}),L("Restore",async()=>{try{const i=await I.unarchiveForm(n.id);e(),this.forms.unshift(i),B("Form restored",`${i.title||"(untitled)"} is back, with its entries and stats.`),await this.open(i.id)}catch(i){B("Could not restore the form",i instanceof Error?i.message:"","error")}},"secondary","undo")]})))}).catch(()=>{}),t}renderFormsList(){H(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."}),L("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(`${W?.adminUrl??""}admin.php?page=allterrain-forms-entries`)}renderPalette(){if(!this.config)return;H(this.palette);const e=new Map;for(const s of this.config.fieldTypes){const n=e.get(s.group)??[];n.push(s),e.set(s.group,n)}const t=r("input",{class:"atfb-input atfb-palette__search",type:"search",placeholder:"Search fields",attrs:{"aria-label":"Search field types"},on:{input:s=>{const n=s.target.value.toLowerCase().trim();this.palette.querySelectorAll(".atfb-chip").forEach(i=>{const o=(i.textContent??"").toLowerCase();i.hidden=n!==""&&!o.includes(n)}),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(t);for(const[s,n]of Object.entries(this.config.groups)){const i=e.get(s);i?.length&&this.palette.append(r("div",{class:"atfb-group",children:[r("h3",{class:"atfb-group__title",text:n}),r("div",{class:"atfb-group__items",children:i.map(o=>this.paletteChip(o))})]}))}}paletteChip(e){const t=r("button",{class:"atfb-chip",type:"button",title:e.description,attrs:{"data-atf-type":e.type},children:[U(e.icon),r("span",{text:e.label})]});return t.addEventListener("pointerdown",s=>{const n=r("div",{class:"atfb-chip atfb-chip--ghost",children:[U(e.icon),r("span",{text:e.label})]});K().start({payload:Le(se,t,{fieldType:e.type,isNew:!0},s,n),origin:s,onClickOnly:()=>this.addField(e.type)})}),t.addEventListener("click",s=>{K().recentlyEndedDrag()&&s.preventDefault()}),t}renderCanvas(){if(H(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:Ye("emptyCanvas","Drag a field from the left to begin.")})),this.schema.fields.forEach((s,n)=>{e.append(this.renderFieldCard(s,n))});const t=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(t),this.registerCanvasTarget(e),this.paintLogicMap(t),this.paintCanvasTheme()}prefillControl(e,t){const s=e.prefill.startsWith("query:"),n=ze.some(y=>y.value===e.prefill),i=s?"query":n&&e.prefill||(e.prefill?"custom":""),o=r("div",{class:"atfb-prefill__detail"}),l=r("p",{class:"atfb-row__hint atfb-prefill__preview"}),c=y=>{if(o.replaceChildren(),l.replaceChildren(),y==="query"){const u=e.prefill.startsWith("query:")?e.prefill.slice(6):"";o.append(C(u,x=>{const g=x.trim();t("prefill",g?`query:${g}`:""),d(`query:${g}`)},"utm_source"),r("p",{class:"atfb-row__hint",text:"The name of the parameter in the link people arrive on."}))}y==="custom"&&o.append(C(e.prefill,u=>{t("prefill",u),d(u)},"myplugin:something"),r("p",{class:"atfb-row__hint",text:"For a source another plugin has added through atf_resolve_prefill."})),d(e.prefill)},d=y=>{if(l.replaceChildren(),!y)return;if(y.startsWith("query:")){const x=y.slice(6);x&&(l.textContent=`A visit to …/your-page/?${x}=abc opens the form with “abc” in it.`);return}const u=ze.find(x=>x.value===y)?.tag;u&&De(this.form?.id??0).then(x=>{for(const g of x)for(const f of g.items)if(f.tag===u){const E=y.startsWith("user:");if(!f.sample){l.textContent="Empty unless the visitor is signed in.";return}l.textContent=E?`Opens with “${f.sample}” for you — empty for a visitor who is not signed in.`:`Opens with “${f.sample}”.`;return}})};c(i);const h=r("select",{class:"atfb-input atfb-select",on:{change:y=>{const u=y.target.value;t("prefill",u==="query"||u==="custom"?"":u),c(u)}}});h.append(r("option",{value:"",text:"Nothing — leave it empty",attrs:{selected:i===""}}));for(const y of wn){const u=document.createElement("optgroup");u.label=y;for(const x of ze.filter(g=>g.group===y))u.append(r("option",{value:x.value,text:x.label,attrs:{selected:x.value===i}}));h.append(u)}const v=document.createElement("optgroup");return v.label="From the link they arrived on",v.append(r("option",{value:"query",text:"A parameter in the web address",attrs:{selected:i==="query"}})),h.append(v,r("option",{value:"custom",text:"Something else (advanced)",attrs:{selected:i==="custom"}})),b("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,t){const s=t.some(i=>i.kind==="field"&&i.missing),n=r("span",{class:`atfb-cond${s?" is-broken":""}`,attrs:{"aria-label":nt(t)},children:[U("randomize"),...t.map(i=>this.renderConditionToken(e,i))]});return n.addEventListener("pointerdown",i=>i.stopPropagation()),n.addEventListener("click",i=>i.stopPropagation()),n.addEventListener("keydown",i=>i.stopPropagation()),n}editCondition(e,t,s=!0,n=""){const i=this.liveField(e)?.logic;if(i){if(t(i),this.markDirty(),!s){this.logicMap?.setEdges(me(this.schema?.fields??[]));return}this.renderCanvas(),this.renderInspector(),n&&window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-cond="${CSS.escape(n)}"]`)?.focus()})}}condSelect(e,t,s,n,i){if(Y("os-select")&&Y("os-option")){const o=document.createElement("os-select");o.setAttribute("value",e),o.setAttribute("aria-label",n),o.setAttribute("data-cond",s),o.className="atfb-cond__control",o.title=n;for(const l of t){const c=document.createElement("os-option");c.setAttribute("value",l.value),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:n,attrs:{"aria-label":n,"data-cond":s},on:{change:o=>i(o.target.value)},children:t.map(o=>r("option",{value:o.value,text:o.label,attrs:{selected:o.value===e}}))})}renderConditionToken(e,t){if(t.kind==="field"&&!t.missing)return r("button",{class:"atfb-cond__chip atfb-cond__chip--field",type:"button",text:t.text,title:"Go to this question",on:{click:n=>{n.stopPropagation(),this.selectField(t.fieldId),this.canvas.querySelector(`[data-atfb-card="${CSS.escape(t.fieldId)}"]`)?.scrollIntoView({block:"nearest",behavior:"smooth"})}}});if(t.kind==="verb")return r("button",{class:"atfb-cond__verb",type:"button",text:t.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,s=>{s.action=s.action==="hide"?"show":"hide"},!0,`${e.id}:verb`)}});if(t.kind==="join")return r("button",{class:"atfb-cond__join",type:"button",text:t.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,s=>{s.match=s.match==="all"?"any":"all"},!0,`${e.id}:join`)}});if(t.kind==="operator"){const s=`${e.id}:op:${t.ruleIndex}`;return this.condSelect(t.operator,Object.entries(Ae).map(([n,i])=>({value:n,label:i})),s,"How the answer is compared",n=>this.editCondition(e.id,i=>{const o=i.rules[t.ruleIndex];o&&(o.operator=n)},!0,s))}return t.kind==="value"?this.renderConditionValue(e,t):r("span",{class:"atfb-cond__chip atfb-cond__chip--missing",text:t.text})}renderConditionValue(e,t){const s=`${e.id}:value:${t.ruleIndex}`,n=this.schema?.fields.find(c=>c.id===t.sourceId),i=(c,d)=>this.editCondition(e.id,h=>{const v=h.rules[t.ruleIndex];v&&(v.value=c)},d,s);if(n?.choices?.length){const c=n.choices.map(d=>({value:d.value,label:d.label||d.value}));return t.raw!==""&&!n.choices.some(d=>d.value===t.raw)&&c.unshift({value:t.raw,label:t.text}),this.condSelect(t.raw,c,s,"The answer that triggers this",d=>i(d,!0))}const o=["number","range","scale","rating","total"].includes(n?.type??""),l=r("input",{class:"atfb-cond__chip atfb-cond__chip--value atfb-cond__value",value:t.raw,title:"The answer that triggers this. Edit it here.",attrs:{type:"text","aria-label":"The answer that triggers this","data-cond":s,inputmode:o?"decimal":void 0,size:String(Math.max(2,Math.min(24,t.raw.length||2)))}});return l.addEventListener("input",()=>{l.size=Math.max(2,Math.min(24,l.value.length||2)),i(l.value,!1)}),l.addEventListener("change",()=>i(l.value,!0)),l.addEventListener("keydown",c=>{c.key==="Enter"&&(c.preventDefault(),i(l.value,!0))}),l}section(e,t,s,n=!1){const i=r("details",{class:"atfb-section",attrs:{open:this.openSections.get(e)??n},children:[r("summary",{text:t}),...s]});return i.addEventListener("toggle",()=>this.openSections.set(e,i.open)),i}logicMapButton(){const e=me(this.schema?.fields??[]).length>0,t=L(this.logicMapOn?"Hide logic":"Show logic",()=>{this.logicMapOn=!this.logicMapOn,Qt(Ft,this.logicMapOn?"on":"off"),this.renderBar(),this.renderCanvas()},this.logicMapOn?"primary":"secondary","randomize");return t.title="Draw a line from each question to the ones it decides.",t.hidden=!e,t}paintLogicMap(e){this.logicMap?.destroy(),this.logicMap=null;const t=this.schema?.fields??[],s=me(t);if(!s.length||!this.logicMapOn)return;e.classList.add("has-logicmap");const n=new ps(e);n.setEdges(s),n.highlight(this.selected??""),this.logicMap=n,e.addEventListener("pointerover",i=>{const o=i.target.closest("[data-atfb-card]");n.highlight(o?.dataset.atfbCard??this.selected??"")}),e.addEventListener("pointerleave",()=>n.highlight(this.selected??""))}renderFieldCard(e,t){const s=this.config?.fieldTypes.find(d=>d.type===e.type),n=this.selected===e.id,i=this.schema?.fields??[],o=ds(e,i),l=us(i).get(e.id)??0,c=r("div",{class:`atfb-card${n?" is-selected":""}`,attrs:{"data-atfb-card":e.id,"data-index":t,tabindex:"0",role:"button","aria-pressed":n,"aria-label":`${e.label||s?.label||e.type}, ${t+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:[U("menu")]}),r("div",{class:"atfb-card__head",children:[U(s?.icon??"dashicons-forms"),r("span",{class:"atfb-card__type",text:s?.label??e.type}),this.requiredToggle(e),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:[ot(e,s,{edit:d=>{const h=this.liveField(e.id);if(!h)return;d(h),this.markDirty(),this.syncInspector(h);const v=this.selected?this.locateField(this.selected):void 0;v?.parent&&v.parent.id===h.id&&this.syncInspector(v.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}),o.length?this.renderCondition(e,o):null]})]});return c.addEventListener("click",d=>{d.target.closest(".atfb-card__actions")||K().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"?t-1:t+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")||K().start({payload:Le(se,c,{fieldId:e.id,field:e,isNew:!1},d),origin:d})}),c}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:s=>s.stopPropagation(),click:s=>{s.stopPropagation(),e.required=!e.required,this.markDirty(),this.renderCanvas(),this.renderInspector()}}})}cardAction(e,t,s){return r("button",{class:"atfb-card__action",type:"button",title:t,attrs:{"aria-label":t},on:{click:n=>{n.stopPropagation(),s()}},children:[U(e)]})}registerCanvasTarget(e){this.canvasTarget?.(),this.canvasTarget=null;const t=r("div",{class:"atfb-marker",attrs:{"aria-hidden":"true"}}),s=K().registerDropTarget({id:`atfb-canvas-${this.form?.id??0}`,element:e,accept:o=>o.type===se,onEnter:()=>e.classList.add("is-dropping"),onLeave:()=>{e.classList.remove("is-dropping"),t.remove()},onDrop:(o,l)=>{e.classList.remove("is-dropping"),t.remove();const c=o.payload.data,d=c.fieldId?this.canvas.querySelector(`[data-atfb-card="${CSS.escape(c.fieldId)}"]`):null,h=Ee(e,".atfb-card",l.clientY,d??void 0);if(c.isNew&&c.fieldType){this.addField(c.fieldType,h);return}if(c.fieldId&&this.locateField(c.fieldId)){this.relocateField(c.fieldId,null,h);return}c.field&&this.insertField({...c.field,id:""},h)}}),n=this.wireRepeaterZones(e),i=o=>{const l=o.detail;if(l?.payload?.type!==se||!e.classList.contains("is-dropping"))return;const c=l.payload.data?.fieldId?this.canvas.querySelector(`[data-atfb-card="${CSS.escape(l.payload.data.fieldId)}"]`):null,d=l.clientY??0,h=Ee(e,".atfb-card",d,c??void 0),v=Array.from(e.querySelectorAll(".atfb-card")).filter(y=>y!==c);h>=v.length?e.append(t):v[h].before(t)};document.addEventListener("os.drag.move",i),this.canvasTarget=()=>{s(),n.forEach(o=>o()),document.removeEventListener("os.drag.move",i)}}wireRepeaterZones(e){const t=[];return e.querySelectorAll("[data-atfb-repeater-zone]").forEach(s=>{const n=s.dataset.atfbRepeaterZone??"";t.push(K().registerDropTarget({id:`atfb-repzone-${this.form?.id??0}-${n}`,element:s,accept:i=>{if(i.type!==se)return!1;const o=i.data;if(o.fieldId===n)return!1;const l=o.isNew?o.fieldType:this.locateField(o.fieldId??"")?.field.type??o.field?.type;return!!l&&this.allowedInRepeater(l)},onEnter:()=>s.classList.add("is-dropping"),onLeave:()=>s.classList.remove("is-dropping"),onDrop:(i,o)=>{s.classList.remove("is-dropping");const l=i.payload.data,c=l.fieldId?e.querySelector(`[data-atfb-subfield="${CSS.escape(l.fieldId)}"]`):null,d=Ee(s,".atfb-subcard",o.clientY,c??void 0);if(l.isNew&&l.fieldType){this.addFieldToRepeater(l.fieldType,n,d);return}if(l.fieldId&&this.locateField(l.fieldId)){this.relocateField(l.fieldId,n,d);return}l.field&&this.insertFieldIntoRepeater({...l.field,id:""},n,d)}})),s.querySelectorAll(".atfb-subcard").forEach(i=>{const o=i.dataset.atfbSubfield??"";i.addEventListener("click",l=>{l.target.closest(".atfb-preview__remove")||(l.stopPropagation(),!K().recentlyEndedDrag()&&this.selectField(o))}),i.addEventListener("keydown",l=>{if(l.stopPropagation(),l.key==="Enter"||l.key===" "){l.preventDefault(),this.selectField(o);return}if(l.altKey&&(l.key==="ArrowUp"||l.key==="ArrowDown")){l.preventDefault();const c=this.locateField(o);c&&(this.relocateField(o,n,l.key==="ArrowUp"?c.index-1:c.index+1),window.requestAnimationFrame(()=>{this.canvas.querySelector(`[data-atfb-subfield="${CSS.escape(o)}"]`)?.focus()}));return}(l.key==="Delete"||l.key==="Backspace")&&(l.preventDefault(),this.deleteField(o))}),i.addEventListener("pointerdown",l=>{if(l.stopPropagation(),l.target.closest(".atfb-preview__remove"))return;const c=this.locateField(o);c&&K().start({payload:Le(se,i,{fieldId:o,parentId:n,field:c.field,isNew:!1},l),origin:l})})})}),t}addField(e,t){const s=this.buildField(e);s&&this.insertField(s,t)}buildField(e){const t=this.config?.fieldTypes.find(n=>n.type===e);return!t||!this.schema?void 0:{id:this.nextFieldId(),type:e,label:t.input?t.label:"",placeholder:"",hint:"",required:!1,width:"full",cssClass:"",default:"",choices:t.choices?[{label:"First choice",value:"first"},{label:"Second choice",value:"second"}]:[],logic:{enabled:!1,action:"show",match:"all",rules:[]},messages:{},prefill:"",...t.settings}}allowedInRepeater(e){const t=this.config?.fieldTypes.find(s=>s.type===e);return!t||!t.input?!1:!["repeater","page_break","file","signature","total"].includes(e)}addFieldToRepeater(e,t,s){if(!this.allowedInRepeater(e))return;const n=this.buildField(e);n&&this.insertFieldIntoRepeater(n,t,s)}insertFieldIntoRepeater(e,t,s){const n=this.liveField(t);if(!this.schema||!n||n.type!=="repeater")return;e.id||(e.id=this.nextFieldId()),this.snapshot(),Array.isArray(n.fields)||(n.fields=[]);const i=n.fields,o=s===void 0?i.length:Math.max(0,Math.min(s,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,t,s){if(!this.schema)return;const n=this.locateField(e);if(!n)return;if(!n.parent&&!t){this.moveField(e,s);return}const i=t?this.liveField(t):null;if(t&&(!i||i.type!=="repeater"||e===t))return;i&&!Array.isArray(i.fields)&&(i.fields=[]);const o=i?i.fields:this.schema.fields;this.snapshot(),n.list.splice(n.index,1);const l=Math.max(0,Math.min(s,o.length));o.splice(l,0,n.field),this.selected=n.field.id,this.markDirty(),this.renderCanvas(),this.renderInspector()}insertField(e,t){if(!this.schema)return;e.id||(e.id=this.nextFieldId()),this.snapshot();const s=t===void 0?this.schema.fields.length:Math.max(0,Math.min(t,this.schema.fields.length));this.schema.fields.splice(s,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,t){if(!this.schema)return;const s=Ot(this.schema.fields,e,t);if(!s)return;this.snapshot();const[n]=this.schema.fields.splice(s.from,1);this.schema.fields.splice(s.to,0,n),this.markDirty(),this.renderCanvas()}duplicateField(e){if(!this.schema)return;const t=this.locateField(e);if(!t)return;const s=JSON.parse(JSON.stringify(t.field)),n=this.usedFieldIds(),i=()=>{let o=n.size+1;for(;n.has(`f${o}`);)o++;const l=`f${o}`;return n.add(l),l};s.id=i();for(const o of s.fields??[])o.id=i();if(t.parent){this.snapshot(),t.list.splice(t.index+1,0,s),this.selected=s.id,this.markDirty(),this.renderCanvas(),this.renderInspector();return}this.insertField(s,t.index+1)}async deleteField(e){if(!this.schema)return;const t=this.locateField(e);if(!t)return;const s=this.schema.fields.filter(i=>i.logic?.rules?.some(o=>o.field===e)),n=s.length?`Delete this field? ${s.length} other field${s.length===1?"":"s"} use it in a condition, and those conditions will stop working.`:Ye("confirmDelete","Delete this? It cannot be undone.");await fe(n,"Delete field")&&(this.snapshot(),t.list.splice(t.index,1),this.selected===e&&(this.selected=null),this.markDirty(),this.renderCanvas(),this.renderInspector())}selectField(e){this.selected=e;for(const t of this.canvas.querySelectorAll("[data-atfb-card]")){const s=t.dataset.atfbCard===e;t.classList.toggle("is-selected",s),t.setAttribute("aria-pressed",s?"true":"false")}for(const t of this.canvas.querySelectorAll("[data-atfb-subfield]"))t.classList.toggle("is-selected",t.dataset.atfbSubfield===e);this.logicMap?.highlight(e),this.renderInspector()}nextFieldId(){const e=this.usedFieldIds();let t=e.size+1;for(;e.has(`f${t}`);)t++;return`f${t}`}usedFieldIds(){const e=new Set;for(const t of this.schema?.fields??[]){e.add(t.id);for(const s of t.fields??[])e.add(s.id)}return e}nextEntryId(e,t){const s=new Set(t.map(i=>i.id));let n=t.length+1;for(;s.has(`${e}${n}`);)n++;return`${e}${n}`}renderTypeSettings(e,t,s,n){for(const i of s){const o=It[i];o&&(this.inspector.append(Dt(e,o,n)),o.also&&this.inspector.append(Dt(e,{...o,key:o.also.key,label:o.also.label,hint:o.also.hint},n)))}s.includes("rows")&&e.type!=="likert"&&this.inspector.append(b("Lines tall",G(String(e.rows??""),i=>n("rows",i)))),s.includes("rows")&&e.type==="likert"&&this.inspector.append(this.renderStatementList(e,n)),s.includes("parts")&&this.inspector.append(this.renderPartsEditor(e,t,n)),s.includes("default")&&!["files","object"].includes(t?.value??"")&&this.inspector.append(this.renderDefaultControl(e,t,n))}renderStatementList(e,t){const s=Array.isArray(e.rows)?e.rows:[];return b("Statements",ue(s.map(n=>n.label??"").join(` `),n=>t("rows",qt(s,n)),5),"One per line. Each becomes a row of the matrix.")}renderPartsEditor(e,t,s){const n=t?.parts??[],i=Array.isArray(e.parts)?e.parts:n.map(l=>l.key),o=n.map(l=>D(l.label,i.includes(l.key),c=>{const d=n.map(h=>h.key).filter(h=>h===l.key?c:i.includes(h));s("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,t,s){const n="Filled in before they start. They can change it.";return e.type==="switch"||e.type==="consent"?D("On by default",!!e.default,i=>s("default",i)):t?.choices&&(e.choices??[]).length?b("Default answer",O(String(e.default??""),[{value:"",label:"Nothing chosen"},...(e.choices??[]).map(i=>({value:String(i.value),label:i.label||String(i.value)}))],i=>s("default",i)),n):b("Default answer",C(String(e.default??""),i=>s("default",i)),n)}renderChoicesEditor(e,t){const s=e.choices??[],n=o=>this.liveField(e.id)?.choices?.[o],i=r("div",{class:"atfb-choices"});return s.forEach((o,l)=>{const c=r("div",{class:"atfb-choice-row",children:[e.type==="image_choice"?this.choiceImageWell(o,l,e):null,J(C(o.label,d=>{const h=n(l);if(!h)return;const v=!h.value||h.value===h.label;h.label=d,v&&(h.value=d),this.markDirty();const y=this.liveField(e.id);y&&this.syncCanvas(y)}),`choice:${l}:label`),J(C(o.value,d=>{const h=n(l);h&&(h.value=d,this.markDirty())},"value"),`choice:${l}:value`),e.type==="quiz"||o.points!==void 0?G(String(o.points??""),d=>{const h=n(l);h&&(h.points=d===""?void 0:Number(d),this.markDirty())}):G(String(o.price??""),d=>{const h=n(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),t("choices",d.choices),this.renderInspector())}},children:[U("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,L("Add choice",()=>{const o=this.liveField(e.id);if(!o)return;const l=o.choices??[];l.push({label:"",value:""}),t("choices",l),this.renderInspector()},"ghost","plus-alt2"),e.type==="quiz"?b("Correct answer",O(String(e.correct??""),[{value:"",label:"—"},...s.map(o=>({value:o.value,label:o.label}))],o=>t("correct",o))):null]})}choiceImageWell(e,t,s){const n=r("div",{class:`atfb-well${e.image?" has-image":""}`,attrs:{"data-choice":t,"aria-label":`Image for ${e.label||`choice ${t+1}`}`},children:[e.image?r("span",{class:"atfb-well__id",text:`#${e.image}`}):U("format-image")]}),i=K().registerDropTarget({id:`atfb-well-${s.id}-${t}`,element:n,accept:o=>vn.includes(o.type),onEnter:()=>n.classList.add("is-dropping"),onLeave:()=>n.classList.remove("is-dropping"),onDrop:o=>{n.classList.remove("is-dropping");const l=o.payload.data,c=Number(l.attachmentId??l.id??l.file?.id??0);if(!c){B("That is not an image this field can use","","error");return}const d=this.liveField(s.id)?.choices?.[t];d&&(d.image=c,this.markDirty(),this.renderInspector())}});return this.teardowns.push(i),n.addEventListener("click",()=>{const o=this.liveField(s.id)?.choices?.[t];o?.image&&(o.image=void 0,this.markDirty(),this.renderInspector())}),n}renderValidationSection(e,t,s){const n=[],i=[];t.includes("minlength")&&i.push(["minlength","Minimum characters"],["maxlength","Maximum characters"]),t.includes("min")?i.push(["min","Minimum"],["max","Maximum"]):t.includes("max")&&i.push(["max","Highest"]),t.includes("step")&&i.push(["step","Steps of"]),t.includes("mindate")&&i.push(["minDate","Earliest date"],["maxDate","Latest date"]),t.includes("mintime")&&i.push(["minTime","Earliest time"],["maxTime","Latest time"]);for(const[l,c]of i)n.push(b(c,C(String(e[l]??""),d=>s(l,d))));t.includes("pattern")&&n.push(...this.renderAnswerShapeRows(e,s)),t.includes("unique")&&n.push(D("No two people may submit the same value",!!e.unique,l=>s("unique",l)));const o=e.messages??{};return t.includes("required")&&n.push(b("Message when required",C(o.required??"",l=>{o.required=l,s("messages",o)}),"Leave empty for the default wording.")),n.length?this.section(`validation:${e.id}`,"Validation",n):r("div",{class:"atfb-section is-empty"})}buildShapePicker(e,t){const s=[{heading:null,options:[{value:"",label:"Anything at all"}]},...fn.map(i=>({heading:i,options:Ct.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 s){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=>{t(String(o.detail?.value??""))}),i}const n=r("select",{class:"atfb-input atfb-select",attrs:{"aria-label":"What the answer should look like"},on:{change:i=>t(i.target.value)}});for(const i of s){const o=i.heading?(()=>{const l=document.createElement("optgroup");return l.label=i.heading,n.append(l),l})():n;for(const l of i.options)o.append(r("option",{value:l.value,text:l.label,attrs:{selected:l.value===e}}))}return n}renderAnswerShapeRows(e,t){const n=(typeof e.validation=="string"?e.validation:"")||(e.pattern?"custom":""),i=()=>hn({root:this.root,field:this.liveField(e.id)??e,onSave:h=>{t("validation","custom"),t("pattern",h.pattern),t("validationRecipe",JSON.stringify(h.recipe));const v={...this.liveField(e.id)?.messages??{}};v.invalid=h.message,t("messages",v),this.renderInspector()},onCancel:()=>this.renderInspector()}),o=h=>{if(h==="custom"){i();return}t("validation",h),t("pattern",""),t("validationRecipe",""),this.renderInspector()},l=this.buildShapePicker(n,o),c=mn(n),d=[b("The answer should be",l,c?`e.g. ${c.example}`:"Checked as they type, and again on the server.")];if(n==="custom"){const h=St(String(e.validationRecipe??"")),v=Lt(h)||(e.pattern?`Matches the expression ${String(e.pattern)}`:"No rule yet — open the builder.");d.push(b("Your rule",r("div",{class:"atfb-valrule",children:[r("p",{class:"atfb-valrule__words",text:v}),L("Edit the rule…",i,"secondary","edit")]}),xe(h)||e.pattern?"Built in the rule builder, with a playground to test it.":void 0))}return d}renderLogicSection(e){const t=e.logic,s=()=>this.liveField(e.id)?.logic,n=(d,h=!1)=>{const v=s();v&&(d(v),this.markDirty(),this.renderCanvas(),h&&this.renderInspector())},i=(this.schema?.fields??[]).filter(d=>d.id!==e.id&&d.type!=="page_break"),o=()=>r("div",{class:"atfb-rule-join",children:[r("button",{class:"atfb-rule-join__chip",type:"button",text:t.match==="all"?"and":"or",title:"Switch between needing every rule (and) or any one of them (or).",on:{click:()=>n(d=>{d.match=d.match==="all"?"any":"all"},!0)}})]}),l=(d,h)=>{const v=r("button",{class:"atfb-card__action",type:"button",attrs:{"aria-label":"Remove this rule"},title:"Remove this rule",on:{click:()=>n(u=>{u.rules.splice(h,1)},!0)},children:[U("trash")]}),y=[r("div",{class:"atfb-rule__top",children:[O(d.field,i.map(u=>({value:u.id,label:u.label||u.id})),u=>n(x=>{const g=x.rules[h];g&&(g.field=u,g.value="")},!0)),v]}),O(d.operator,Object.entries(this.config?.operators??{}).map(([u,x])=>({value:u,label:x})),u=>n(x=>{const g=x.rules[h];g&&(g.operator=u)},!0))];if(!Te.includes(d.operator)){const u=this.schema?.fields.find(x=>x.id===d.field);if(u?.choices?.length){const x=u.choices.map(g=>({value:g.value,label:g.label||g.value}));d.value!==""&&!u.choices.some(g=>g.value===d.value)&&x.unshift({value:d.value,label:d.value}),y.push(O(d.value,x,g=>n(f=>{const E=f.rules[h];E&&(E.value=g)})))}else y.push(C(d.value,x=>n(g=>{const f=g.rules[h];f&&(f.value=x)}),"The answer to compare against"))}return r("div",{class:"atfb-rule",children:y})},c=r("div",{class:"atfb-rules"});return t.rules.forEach((d,h)=>{h>0&&c.append(o()),c.append(l(d,h))}),this.section(`logic:${e.id}`,"Conditional logic",[D("Only show this field sometimes",t.enabled,d=>{n(h=>{h.enabled=d},!0)}),t.enabled?r("div",{children:[r("div",{class:"atfb-rule-head",children:[O(t.action,[{value:"show",label:"Show"},{value:"hide",label:"Hide"}],d=>n(h=>{h.action=d},!0)),r("span",{text:"this field when"}),O(t.match,[{value:"all",label:"all"},{value:"any",label:"any"}],d=>n(h=>{h.match=d},!0)),r("span",{text:"of these match:"})]}),c,L("Add rule",()=>{n(d=>{d.rules.push({field:i[0]?.id??"",operator:"is",value:""})},!0)},"ghost","plus-alt2")]}):null],t.enabled)}renderTabCanvas(){return this.schema?this.tab==="theme"?ut({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,t)=>{t===""?delete this.schema.settings.themeOverrides[e]:this.schema.settings.themeOverrides[e]=t,this.markDirty()},onOverridesReplaced:e=>{this.schema.settings.themeOverrides={...e},this.markDirty()},previewFor:(e,t)=>this.previewHtml(e,t),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,t=JSON.stringify([e,this.schema.settings.themeOverrides]);if(t!==this.canvasThemeSignature){this.canvasThemeSignature=t;try{const s=await this.previewHtml(e,this.schema.settings.themeOverrides??{});this.root.classList.toggle("atfb--dark-form",/atf-is-dark/.test(s));const n=/