domma-cms 1.10.31 → 1.10.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.10.32] - 2026-10-26
4
+
5
+ - Add clickable (?) explanations throughout the Forms editor, including submission actions, triggers, conditions, field options and chooser controls. Newly added controls receive help immediately; help buttons preserve checkbox and panel state.
6
+
3
7
  ## [1.10.31] - 2026-10-26
4
8
 
5
9
  - **Plugins can fetch user-chosen addresses safely.** `hooks.safeFetch(url, opts)` hands plugins the CMS's own outbound guard: public addresses only, the connection pinned to the checked address, redirects re-checked, ports 80 and 443, and the site's `outboundAllowPrivate` rule (ignored on hosted sites). Through the hook a plugin cannot pass in its own policy or resolver, and may raise the size, time and redirect limits only to 25 MB, 60 s and 5. It guards against plugin mistakes; on hosted sites plugin signing is what keeps out hostile code.
@@ -1 +1 @@
1
- export const HELP_GROUP="dm-help";function b(){return typeof E<"u"&&typeof E?.popover=="function"}export function helpPopoverOptions({text:t="",title:n="",position:i="top"}={}){return{content:String(t),title:String(n),html:!1,trigger:"click",placement:i==="bottom"?"bottom":"top",group:HELP_GROUP,ariaLabel:n?null:"Help",className:"dm-help-popover"}}function g(t){const n=document.createElement("button");n.type="button",n.className="dm-help-btn",n.setAttribute("aria-label",t?`Help: ${t}`:"Help");const i=document.createElement("span");return i.setAttribute("data-icon","help-circle"),i.setAttribute("data-icon-size","14"),n.appendChild(i),n.addEventListener("click",r=>{r.preventDefault(),r.stopPropagation()}),n}const u=new Set;let f=!1;function v(){f||(f=!0,window.addEventListener("hashchange",()=>{E.popover.closeAll?.(HELP_GROUP);for(const t of u)t.btn.isConnected||(t.pop.destroy(),u.delete(t))}))}function y(t,n,i,r,s){const o=E.popover(n,helpPopoverOptions({text:i,title:r,position:s})),e={marker:t,btn:n,pop:o};return u.add(e),e}let a=null,h=!1;function l(){a&&(a.btn.setAttribute("aria-expanded","false"),a.el.remove(),a=null)}function A(){h||(h=!0,document.addEventListener("mousedown",t=>{a&&(a.el.contains(t.target)||a.btn.contains(t.target)||l())},!0),document.addEventListener("keydown",t=>{if(t.key==="Escape"&&a){const n=a.btn;l(),n.focus()}}),window.addEventListener("hashchange",l),window.addEventListener("resize",l),document.addEventListener("scroll",t=>{a&&!a.el.contains(t.target)&&l()},!0))}function w(t,n,i){const r=n.getBoundingClientRect(),s=t.offsetWidth,o=t.offsetHeight,e=8,d=i==="bottom"&&r.bottom+o+e<innerHeight||r.top<o+e,p=d?r.bottom+e:r.top-o-e,c=Math.min(Math.max(8,r.left+r.width/2-s/2),innerWidth-s-8);t.style.top=`${Math.round(p)}px`,t.style.left=`${Math.round(c)}px`,t.dataset.side=d?"bottom":"top"}let x=0;function L(t,n,i,r){A();const s=`dm-help-${++x}`;t.setAttribute("aria-expanded","false"),t.setAttribute("aria-controls",s),t.addEventListener("click",()=>{if(a?.btn===t)return l();l();const o=document.createElement("div");if(o.id=s,o.className="dm-help-pop",o.setAttribute("role","dialog"),o.setAttribute("aria-label",i||"Help"),i){const d=document.createElement("strong");d.textContent=i,o.appendChild(d)}const e=document.createElement("p");e.textContent=n,o.appendChild(e),document.body.appendChild(o),w(o,t,r),t.setAttribute("aria-expanded","true"),a={btn:t,el:o}})}export function helpPopovers(t,{position:n="top"}={}){const i=t&&typeof t.get=="function"?t.get(0):t;if(!i)return()=>{};const r=b();r&&v();const s=[],o=[];for(const e of i.querySelectorAll("[data-help]:not([data-help-ready])")){const d=e.getAttribute("data-help")||"",p=e.getAttribute("data-help-title")||"";e.setAttribute("data-help-ready","");let c=[...e.children].find(m=>m.classList?.contains("dm-help-btn"));c||(c=g(p),e.appendChild(c)),o.push(c),r?s.push(y(e,c,d,p,n)):L(c,d,p,n)}return typeof I<"u"&&I.scan&&I.scan(i),()=>{if(!r){a&&o.includes(a.btn)&&l();return}for(const e of s.splice(0))e.pop.destroy(),u.delete(e),e.marker.removeAttribute("data-help-ready")}}
1
+ export const HELP_GROUP="dm-help";function v(){return typeof E<"u"&&typeof E?.popover=="function"}export function helpPopoverOptions({text:t="",title:e="",position:n="top"}={}){return{content:String(t),title:String(e),html:!1,trigger:"click",placement:n==="bottom"?"bottom":"top",group:HELP_GROUP,ariaLabel:e?null:"Help",className:"dm-help-popover"}}function y(t){const e=document.createElement("button");e.type="button",e.className="dm-help-btn",e.setAttribute("aria-label",t?`Help: ${t}`:"Help");const n=document.createElement("span");return n.setAttribute("data-icon","help-circle"),n.setAttribute("data-icon-size","14"),e.appendChild(n),e.addEventListener("click",r=>{r.preventDefault(),r.stopPropagation()}),e}const f=new Set;let m=!1;function A(){m||(m=!0,window.addEventListener("hashchange",()=>{E.popover.closeAll?.(HELP_GROUP);for(const t of f)t.btn.isConnected||(t.pop.destroy(),f.delete(t))}))}function w(t,e,n,r,c){const o=E.popover(e,helpPopoverOptions({text:n,title:r,position:c})),a={marker:t,btn:e,pop:o};return f.add(a),a}let i=null,b=!1;function d(){i&&(i.btn.setAttribute("aria-expanded","false"),i.el.remove(),i=null)}function x(){b||(b=!0,document.addEventListener("mousedown",t=>{i&&(i.el.contains(t.target)||i.btn.contains(t.target)||d())},!0),document.addEventListener("keydown",t=>{if(t.key==="Escape"&&i){const e=i.btn;d(),e.focus()}}),window.addEventListener("hashchange",d),window.addEventListener("resize",d),document.addEventListener("scroll",t=>{i&&!i.el.contains(t.target)&&d()},!0))}function L(t,e,n){const r=e.getBoundingClientRect(),c=t.offsetWidth,o=t.offsetHeight,a=8,l=n==="bottom"&&r.bottom+o+a<innerHeight||r.top<o+a,s=l?r.bottom+a:r.top-o-a,u=Math.min(Math.max(8,r.left+r.width/2-c/2),innerWidth-c-8);t.style.top=`${Math.round(s)}px`,t.style.left=`${Math.round(u)}px`,t.dataset.side=l?"bottom":"top"}let k=0;function C(t,e,n,r){x();const c=`dm-help-${++k}`;t.setAttribute("aria-expanded","false"),t.setAttribute("aria-controls",c),t.addEventListener("click",()=>{if(i?.btn===t)return d();d();const o=document.createElement("div");if(o.id=c,o.className="dm-help-pop",o.setAttribute("role","dialog"),o.setAttribute("aria-label",n||"Help"),n){const l=document.createElement("strong");l.textContent=n,o.appendChild(l)}const a=document.createElement("p");a.textContent=e,o.appendChild(a),document.body.appendChild(o),L(o,t,r),t.setAttribute("aria-expanded","true"),i={btn:t,el:o}})}export function helpPopovers(t,{position:e="top"}={}){const n=t&&typeof t.get=="function"?t.get(0):t;if(!n)return()=>{};const r=v();r&&A();const c=[],o=[],a="[data-help]:not([data-help-ready])",l=[...n.matches?.(a)?[n]:[],...n.querySelectorAll(a)];for(const s of l){const u=s.getAttribute("data-help")||"",h=s.getAttribute("data-help-title")||"";s.setAttribute("data-help-ready","");let p=[...s.children].find(g=>g.classList?.contains("dm-help-btn"));p||(p=y(h),s.appendChild(p)),o.push(p),r?c.push(w(s,p,u,h,e)):C(p,u,h,e)}return typeof I<"u"&&I.scan&&I.scan(n),()=>{if(!r){i&&o.includes(i.btn)&&d();return}for(const s of c.splice(0))s.pop.destroy(),f.delete(s),s.marker.removeAttribute("data-help-ready")}}
@@ -78,7 +78,7 @@
78
78
  <div class="card-body">
79
79
  <div class="row mb-3">
80
80
  <div class="col-7">
81
- <label class="form-label">Title</label>
81
+ <label class="form-label">Title <span data-help-title="Title" data-help="The name used to identify this form in the admin and in submission notifications."></span></label>
82
82
  <input id="field-title" type="text" class="form-input" placeholder="My Form">
83
83
  </div>
84
84
  <div class="col-5">
@@ -90,7 +90,7 @@
90
90
  </div>
91
91
  <div class="row">
92
92
  <div class="col">
93
- <label class="form-label">Description</label>
93
+ <label class="form-label">Description <span data-help-title="Description" data-help="A description to help identify the form and explain its purpose."></span></label>
94
94
  <textarea id="field-description" class="form-input" rows="2"
95
95
  placeholder="Optional form description..."></textarea>
96
96
  </div>
@@ -107,7 +107,7 @@
107
107
  <div class="row mt-3">
108
108
  <div class="col-auto">
109
109
  <label class="form-check-label" title="Included in fresh installs via the seed script">
110
- <input id="field-bundled" type="checkbox" class="form-check"> Bundled
110
+ <input id="field-bundled" type="checkbox" class="form-check"> Bundled <span data-help-title="Bundled" data-help="Include this form in fresh installs created by the seed script."></span>
111
111
  </label>
112
112
  </div>
113
113
  </div>
@@ -121,7 +121,7 @@
121
121
  <div class="card-header"><h2>Settings</h2></div>
122
122
  <div class="card-body">
123
123
  <div class="mb-3">
124
- <label class="form-label">Success Message</label>
124
+ <label class="form-label">Success Message <span data-help-title="Success Message" data-help="The confirmation shown after a successful submission when there is no redirect. An early-finish trigger can supply its own closing message."></span></label>
125
125
  <textarea id="setting-success-message" class="form-input" rows="3"
126
126
  placeholder="Thank you for your submission."></textarea>
127
127
  </div>
@@ -142,7 +142,7 @@
142
142
  </select>
143
143
  </div>
144
144
  <div id="columns-group">
145
- <label class="form-label">Columns</label>
145
+ <label class="form-label">Columns <span data-help-title="Columns" data-help="Choose two or three columns for the grid layout. Each field can span columns or fill a whole row."></span></label>
146
146
  <select id="setting-columns" class="form-select">
147
147
  <option value="2">2 columns</option>
148
148
  <option value="3">3 columns</option>
@@ -166,7 +166,7 @@
166
166
  <div class="card-body">
167
167
  <div class="row">
168
168
  <div class="col-6 mb-3">
169
- <label class="form-label">Text</label>
169
+ <label class="form-label">Text <span data-help-title="Text" data-help="The text on the submit button. On a multi-step form this is used for the final submit button."></span></label>
170
170
  <input id="setting-submit-text" type="text" class="form-input" placeholder="Submit" value="Submit">
171
171
  </div>
172
172
  <div class="col-6 mb-3">
@@ -201,7 +201,7 @@
201
201
  </select>
202
202
  </div>
203
203
  <div class="col-6 mb-3">
204
- <label class="form-label">Size</label>
204
+ <label class="form-label">Size <span data-help-title="Size" data-help="The size of the submit button: Small, Normal or Large."></span></label>
205
205
  <select id="setting-submit-size" class="form-select">
206
206
  <option value="sm">Small</option>
207
207
  <option value="" selected>Normal</option>
@@ -221,7 +221,7 @@
221
221
  <div id="setting-submit-icon-start-slot"></div>
222
222
  </div>
223
223
  <div class="col-6 mb-3">
224
- <label class="form-label">Icon after the text</label>
224
+ <label class="form-label">Icon after the text <span data-help-title="Icon after the text" data-help="An optional icon after the submit button text. Browse for an icon or leave blank for none."></span></label>
225
225
  <div id="setting-submit-icon-end-slot"></div>
226
226
  </div>
227
227
  </div>
@@ -237,7 +237,7 @@
237
237
  <div id="second-button-group" style="display:none;">
238
238
  <div class="row">
239
239
  <div class="col-6 mb-3">
240
- <label class="form-label">Text</label>
240
+ <label class="form-label">Text <span data-help-title="Text" data-help="The text on the second button. Leave blank to use Clear form or Cancel, according to the button type."></span></label>
241
241
  <input id="setting-second-label" type="text" class="form-input" placeholder="Clear form">
242
242
  </div>
243
243
  <div class="col-6 mb-3" id="second-url-group">
@@ -247,7 +247,7 @@
247
247
  </div>
248
248
  <div class="row">
249
249
  <div class="col-6 mb-3">
250
- <label class="form-label">Style</label>
250
+ <label class="form-label">Style <span data-help-title="Style" data-help="The second button colour and appearance from the site theme. Outline draws a border; Ghost shows text until hovered."></span></label>
251
251
  <select id="setting-second-style" class="form-select">
252
252
  <option value="primary">Primary</option>
253
253
  <option value="secondary" selected>Secondary</option>
@@ -279,11 +279,11 @@
279
279
  </div>
280
280
  <div class="row">
281
281
  <div class="col-6 mb-3">
282
- <label class="form-label">Icon before the text</label>
282
+ <label class="form-label">Icon before the text <span data-help-title="Icon before the text" data-help="An optional icon before the second button text. Leave blank for none."></span></label>
283
283
  <div id="setting-second-icon-start-slot"></div>
284
284
  </div>
285
285
  <div class="col-6 mb-3">
286
- <label class="form-label">Icon after the text</label>
286
+ <label class="form-label">Icon after the text <span data-help-title="Icon after the text" data-help="An optional icon after the second button text. Leave blank for none."></span></label>
287
287
  <div id="setting-second-icon-end-slot"></div>
288
288
  </div>
289
289
  </div>
@@ -301,7 +301,7 @@
301
301
  <div class="card-body">
302
302
  <div class="mb-3">
303
303
  <label class="form-label" style="display:flex;align-items:center;gap:.5rem;cursor:pointer;">
304
- <input id="action-email-enabled" type="checkbox"> Send email on submit
304
+ <input id="action-email-enabled" type="checkbox"> Send email on submit <span data-help-title="Send email on submit" data-help="Send an email containing the submitted answers to the recipients below after the submission is saved. Configure SMTP in Site Settings to deliver it."></span>
305
305
  </label>
306
306
  </div>
307
307
  <div class="mb-3">
@@ -311,7 +311,7 @@
311
311
  SMTP settings.</p>
312
312
  </div>
313
313
  <div>
314
- <label class="form-label">Subject Prefix</label>
314
+ <label class="form-label">Subject Prefix <span data-help-title="Subject Prefix" data-help="Text added before New submission in the notification email subject, such as [Contact]. Leave blank to use the form title in brackets."></span></label>
315
315
  <input id="action-email-subject-prefix" type="text" class="form-input" placeholder="[Form]">
316
316
  </div>
317
317
  </div>
@@ -323,7 +323,7 @@
323
323
  <div class="card-body">
324
324
  <div class="mb-3">
325
325
  <label class="form-label" style="display:flex;align-items:center;gap:.5rem;cursor:pointer;">
326
- <input id="action-webhook-enabled" type="checkbox"> POST to webhook on submit
326
+ <input id="action-webhook-enabled" type="checkbox"> POST to webhook on submit <span data-help-title="POST to webhook on submit" data-help="Send each saved submission as JSON to the URL below, using the selected HTTP method."></span>
327
327
  </label>
328
328
  </div>
329
329
  <div class="mb-3">
@@ -332,7 +332,7 @@
332
332
  placeholder="https://hooks.example.com/form">
333
333
  </div>
334
334
  <div>
335
- <label class="form-label">Method</label>
335
+ <label class="form-label">Method <span data-help-title="Method" data-help="The HTTP method used to send the submission as JSON. Choose POST or PUT to match the receiving service."></span></label>
336
336
  <select id="action-webhook-method" class="form-select">
337
337
  <option value="POST">POST</option>
338
338
  <option value="PUT">PUT</option>
@@ -365,7 +365,7 @@
365
365
  <div class="card-body">
366
366
  <div class="mb-3">
367
367
  <label class="form-label" style="display:flex;align-items:center;gap:.5rem;cursor:pointer;">
368
- <input id="setting-honeypot" type="checkbox" checked> Enable honeypot field
368
+ <input id="setting-honeypot" type="checkbox" checked> Enable honeypot field <span data-help-title="Enable honeypot field" data-help="Add a hidden field that visitors should leave empty. Submissions that fill it are treated as spam and silently discarded."></span>
369
369
  </label>
370
370
  <p class="form-hint text-muted" style="margin-top:.3rem;font-size:.8rem;">Silently discards bot submissions
371
371
  that fill a hidden field.</p>
@@ -431,8 +431,8 @@
431
431
  .fb-trig-sec-head .fb-trig-match { width: auto; flex: 0 1 220px; }
432
432
 
433
433
  .fb-trig-cond-list { display: flex; flex-direction: column; gap: .45rem; }
434
- .fb-trig-cond-row { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) auto; gap: .5rem; align-items: center; }
435
- .fb-trig-cond-row .fb-trig-cond-val[hidden] { display: block !important; visibility: hidden; }
434
+ .fb-trig-cond-row { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) auto; gap: .5rem; align-items: end; }
435
+ .fb-trig-cond-row > .fb-trig-f[hidden] { display: flex !important; visibility: hidden; }
436
436
 
437
437
  .fb-trig-action-list { display: flex; flex-direction: column; gap: .55rem; }
438
438
  .fb-trig-action-row { border: 1px solid var(--dm-border); border-radius: var(--dm-radius-md);
@@ -470,9 +470,9 @@
470
470
  narrow on a wide screen (a resized slideover, a two-column editor). */
471
471
  @container (max-width: 460px) {
472
472
  .fb-trig-cond-row { grid-template-columns: minmax(0, 1fr) auto; }
473
- .fb-trig-cond-row > .form-select, .fb-trig-cond-row > .form-input { grid-column: 1; }
473
+ .fb-trig-cond-row > .fb-trig-f { grid-column: 1; }
474
474
  .fb-trig-cond-row > .fb-trig-remove { grid-column: 2; grid-row: 1; }
475
- .fb-trig-cond-row .fb-trig-cond-val[hidden] { display: none !important; }
475
+ .fb-trig-cond-row > .fb-trig-f[hidden] { display: none !important; }
476
476
  .fb-trig-kind { display: none; }
477
477
  }
478
478
  </style>
@@ -1,8 +1,8 @@
1
- import{apiRequest as pe}from"/admin/js/api.js";import{makeIconInput as Re}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as dt}from"/public/js/forms.js";import{buildWizardSteps as an}from"/public/js/form-steps.mjs";import{DEFAULT_MAX_FILES as ut,MAX_FILES_LIMIT as De,captureFileFields as pt,destroyDropzones as mt,fileBlueprint as on,restoreFileFields as sn,splitFiles as rn,submitBody as cn,wireFileFields as dn}from"/public/js/form-files.mjs";import{applyFormClasses as ft,applySubmitButtons as un,applyWizardButtons as pn,buttonSettingsProblems as mn,formClassProblems as fn,resolveSubmitAlign as ht}from"/public/js/form-submit.mjs";import{addBannerAction as _e}from"../lib/plugin-chrome.js";import{helpPopovers as hn}from"../lib/help-popover.js";import{openMenuAt as bt,sidebarCount as bn}from"../lib/tool-kit.js";import{draftBaseOf as gn,draftChoice as yn,draftKey as me,draftOf as vn,duplicateField as xn,editorDraftQuestion as Cn,fieldTitle as Pe,fingerprint as gt,leavingEditor as yt,moveField as vt,restoreDraft as En,snapshotOf as ve}from"../lib/form-editor-arrange.js";import{fmtDateTime as wn}from"../lib/dates.js";const xt=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"chooser",label:"Chooser (visual options)"},{value:"icon",label:"Icon (icon picker)"},{value:"image",label:"Image (media library)"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"password",label:"Password"},{value:"file",label:"File upload"},{value:"hidden",label:"Hidden field"}],je=new Set(["select","radio","checkbox-group","chooser"]);let T=[],xe=[],A=null,Ce=null,ie=null,Ee={};function B(e,t,i=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(i)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function fe(e,t,i,n=14){return B(e,t,n),e.appendChild(document.createTextNode(" "+i)),e}function Ve(e){const t=document.createElement("span");return t.setAttribute("data-icon","help-circle"),t.setAttribute("data-icon-size","12"),t.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;margin-left:.3rem;opacity:.55;cursor:help;",t.title=e,window.I?.scan?.(t),requestAnimationFrame(()=>{try{t.parentNode&&typeof E<"u"&&E.tooltip&&(t.removeAttribute("title"),E.tooltip(t,{content:e,position:"top"}))}catch{}}),t}let we=null,Ct=null,Ge=null,he=null;function We(){Ge?.(),clearTimeout(Ct),Ct=setTimeout(()=>{we&&we()},350)}function Et(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function wt(e){return xt.find(t=>t.value===e)?.label||e}function kt(e){return(e||[]).some(t=>t.logic||Array.isArray(t.triggers)&&t.triggers.length)}function St(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function kn(e){const t={...T[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const b=document.getElementById(`fb-pb-label-${e}`),C=document.getElementById(`fb-pb-desc-${e}`);return b&&(t.label=b.value.trim()||t.label),C&&(t.description=C.value.trim()),t}const i=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),a=document.getElementById(`fb-required-${e}`),o=document.getElementById(`fb-placeholder-${e}`),s=document.getElementById(`fb-helper-${e}`),d=document.getElementById(`fb-tooltip-${e}`);i&&(t.label=i.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),l&&(t.type=l.value||t.type),a&&(t.required=a.checked),o&&(t.placeholder=o.value.trim()),s&&(t.helper=s.value.trim()),d&&(t.tooltip=d.value.trim());const r=document.getElementById(`fb-class-${e}`);if(r){const b=r.value.trim();b?t.class=b:delete t.class}if(t.type==="chooser"){const b=document.getElementById(`fb-chooser-variant-${e}`)?.value;b&&(t.variant=b);const C=document.getElementById(`fb-chooser-multiple-${e}`);C&&(t.multiple=C.checked);const L=document.getElementById(`fb-chooser-density-${e}`)?.value;L&&(t.density=L);const q=document.getElementById(`fb-chooser-columns-${e}`)?.value;q!==""&&q!==void 0&&(t.columns=parseInt(q,10)||3);const D=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();D?t.accent=D:delete t.accent;const V=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;V?t.accentStyle=V:delete t.accentStyle;const _=document.getElementById(`fb-chooser-glow-${e}`);_&&(t.glow=_.checked);const K=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();K?t.glowColour=K:delete t.glowColour;const G=document.getElementById(`fb-chooser-shadow-${e}`)?.value;G&&G!=="none"?t.shadow=G:delete t.shadow;const ne=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();ne?t.shadowColour=ne:delete t.shadowColour,$e(e),T[e]&&Array.isArray(T[e].options)&&(t.options=T[e].options)}else if(je.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(C=>delete t[C]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const b=document.getElementById(`fb-options-${e}`);b&&(t.options=b.value.split(`
2
- `).filter(C=>C.trim()).map(C=>{const[L,...q]=C.split(":");return{value:L.trim(),label:q.join(":").trim()||L.trim()}}))}for(const b of["prefix","suffix"]){const C=document.getElementById(`fb-${b}-icon-${e}`),L=document.getElementById(`fb-${b}-text-${e}`),q={...t.formConfig||{}};if(C||L){const D=C?.value.trim()||"",V=L?.value.trim()||"";D&&/^[a-z0-9-]+$/i.test(D)?q[b]={icon:D}:V?q[b]={text:V.slice(0,24)}:delete q[b]}else jt.includes(t.type)||delete q[b];t.formConfig=Object.keys(q).length?q:void 0}{const b={...t.formConfig||{}};for(const C of Vt){const L=document.getElementById(`fb-extra-${C.key}-${e}`);L&&C.types.includes(t.type)?L.checked?b[C.key]=!0:delete b[C.key]:C.types.includes(t.type)||delete b[C.key]}t.formConfig=Object.keys(b).length?b:void 0}if(t.type==="file"){const b=document.getElementById(`fb-file-multiple-${e}`);if(b){const C={...t.file||{}};if(b.checked){t.multiple=!0;const L=parseInt(document.getElementById(`fb-file-max-${e}`)?.value,10);L>=1?C.maxFiles=Math.min(L,De):delete C.maxFiles}else delete t.multiple,delete C.maxFiles;t.file=Object.keys(C).length?C:void 0}}if(t.type==="textarea"){const b=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);b>0&&(t.formConfig={...t.formConfig||{},rows:b})}const u=document.getElementById(`fb-span-${e}`),p=document.getElementById(`fb-fullwidth-${e}`);if(u||p){const b={...t.formConfig||{}};if(p?.checked)b.span="full";else{const C=parseInt(u?.value,10);C>1?b.span=C:delete b.span}t.formConfig=Object.keys(b).length?b:void 0}const m=document.getElementById(`fb-minlength-${e}`)?.value;m&&(t.minLength=parseInt(m,10));const v=document.getElementById(`fb-maxlength-${e}`)?.value;v&&(t.maxLength=parseInt(v,10));const f=document.getElementById(`fb-min-${e}`)?.value;f!==""&&f!==void 0&&(t.min=parseFloat(f));const y=document.getElementById(`fb-max-${e}`)?.value;y!==""&&y!==void 0&&(t.max=parseFloat(y));const w=Sn(e);w?t.logic=w:delete t.logic;const x=Gn(e);return x?t.triggers=x:delete t.triggers,t}function Sn(e){const t=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!t)return;const i=t.querySelector(".fb-field-logic");if(!i)return;const n={};let l=!1;const a=i.querySelector('[data-logic-section="visibility"]');if(a){const r=a.querySelector(".fb-logic-vis-default"),u=a.querySelector(".fb-logic-vis-transition"),p=Array.from(a.querySelectorAll(".fb-logic-cond-row")).map(y=>{const w=y.querySelector(".fb-logic-cond-field"),x=y.querySelector(".fb-logic-cond-op"),b=y.querySelector(".fb-logic-cond-val"),C=y.querySelector(".fb-logic-vis-then");return w?.value?{when:{all:[{field:w.value,operator:x.value,value:b.value}]},then:C.value}:null}).filter(Boolean),m=r?.value||"visible",v=u?.value||"none",f=parseInt(a.querySelector(".fb-logic-vis-duration")?.value||"",10);(m!=="visible"||p.length>0||v!=="none")&&(n.visibility={default:m,conditions:p},v!=="none"&&(n.visibility.transition=v),v!=="none"&&Number.isFinite(f)&&(n.visibility.duration=f),l=!0)}const o=i.querySelector('[data-logic-section="requirement"]');if(o){const r=o.querySelector(".fb-logic-req-default"),u=Array.from(o.querySelectorAll(".fb-logic-cond-row")).map(p=>{const m=p.querySelector(".fb-logic-cond-field"),v=p.querySelector(".fb-logic-cond-op"),f=p.querySelector(".fb-logic-cond-val"),y=p.querySelector(".fb-logic-req-then");return m?.value?{when:{all:[{field:m.value,operator:v.value,value:f.value}]},then:y.value==="true"}:null}).filter(Boolean);u.length>0&&(n.requirement={default:r?.checked===!0,conditions:u},l=!0)}const s=i.querySelector('[data-logic-section="validation"]');if(s){const r=Array.from(s.querySelectorAll(".fb-logic-val-rule")).map(u=>{const p=u.querySelector(".fb-logic-val-type"),m=u.querySelector(".fb-logic-val-pattern"),v=u.querySelector(".fb-logic-val-flags"),f=u.querySelector(".fb-logic-val-message");if(!m?.value.trim())return null;const y=p?.value||"regex",w={type:y,message:f?.value.trim()||"Invalid value."};return y==="regex"?(w.pattern=m.value.trim(),v?.value.trim()&&(w.flags=v.value.trim())):w.field=m.value.trim(),w}).filter(Boolean);r.length>0&&(n.validation=r,l=!0)}const d=i.querySelector('[data-logic-section="cascade"]');if(d){const r=d.querySelector(".fb-logic-cascade-source"),u=d.querySelector(".fb-logic-cascade-mapping"),p=d.querySelector(".fb-logic-cascade-defaults"),m=r?.value?.trim();if(m){let v={};try{v=JSON.parse(u?.value||"{}")}catch{}const f=(p?.value||"").split(`
3
- `).filter(y=>y.trim()).map(y=>{const[w,...x]=y.split(":");return{value:w.trim(),label:x.join(":").trim()||w.trim()}});n.cascade={sourceField:m,mapping:v,defaultOptions:f},l=!0}}return l?n:void 0}function j(){T=T.map((e,t)=>kn(t))}function Tn(e){const t=e.firstElementChild;if(!t||t.querySelector(".fb-drag-grip"))return;const i=document.createElement("span");i.className="fb-drag-grip",i.setAttribute("data-icon","grip-vertical"),i.setAttribute("data-icon-size","16"),i.title="Drag to reorder",t.insertBefore(i,t.firstChild),window.I?.scan?.(t)}function te(e){const t=e.find("#fields-list").get(0),i=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),T.length===0){i&&(i.style.display=""),he?.(t),We();return}i&&(i.style.display="none"),T.forEach((n,l)=>{const a=n.type==="page-break"?Nn(n,l,e):n.type==="spacer"?Ln(n,l,e):$n(n,l,e);Tn(a),t.appendChild(a)}),he?.(t),We()}}function Nn(e,t,i){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:2px dashed var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent="- Page Break -",a.style.cssText="font-size:.7rem;padding:.15rem .5rem;border-radius:999px;background:color-mix(in srgb, var(--dm-text-muted) 20%, transparent);color:var(--dm-text-muted);white-space:nowrap;flex-shrink:0;font-style:italic;";const o=document.createElement("span");o.textContent=e.label||"Untitled Step",o.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted);";const s=document.createElement("div");s.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const d=document.createElement("button");d.className="btn btn-xs btn-ghost",d.title="Edit step",B(d,"more-horizontal"),d.addEventListener("click",v=>{v.stopPropagation(),u.style.display=u.style.display==="none"?"":"none"}),s.appendChild(d);const r=document.createElement("button");r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove page break",B(r,"x"),r.addEventListener("click",async v=>{v.stopPropagation(),await E.confirm("Remove this page break?")&&(j(),T.splice(t,1),te(i))}),s.appendChild(r),l.appendChild(a),l.appendChild(o),l.appendChild(s),l.addEventListener("click",()=>{u.style.display=u.style.display==="none"?"":"none"});const u=document.createElement("div");u.className="fb-field-body",u.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const p=O([z("Step Title",`fb-pb-label-${t}`,"text",e.label||"","Shown as the wizard step heading"),z("Step Description",`fb-pb-desc-${t}`,"text",e.description||"","Optional sub-heading")]),m=p.querySelector(`#fb-pb-label-${t}`);return m&&m.addEventListener("input",()=>{o.textContent=m.value||"Untitled Step"}),u.appendChild(p),n.appendChild(l),n.appendChild(u),n}function Ln(e,t,i){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px dashed var(--dm-border);border-radius:6px;margin-bottom:.5rem;background:transparent;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.4rem .8rem;";const a=document.createElement("div");a.style.cssText="flex:1;height:1px;background:var(--dm-border);";const o=document.createElement("span");o.textContent="Spacer",o.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const s=document.createElement("div");s.style.cssText="flex:1;height:1px;background:var(--dm-border);";const d=document.createElement("div");d.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const r=document.createElement("button");return r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove spacer",B(r,"x"),r.addEventListener("click",async u=>{u.stopPropagation(),j(),T.splice(t,1),te(i)}),d.appendChild(r),l.appendChild(a),l.appendChild(o),l.appendChild(s),l.appendChild(d),n.appendChild(l),n}function $n(e,t,i){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px solid var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);box-shadow:var(--dm-shadow-sm);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;background:var(--dm-card-header-bg);cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent=wt(e.type),a.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary);white-space:nowrap;flex-shrink:0;";const o=document.createElement("span");o.textContent=e.label||"(unlabelled)",o.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const s=document.createElement("div");s.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const d=document.createElement("button");d.className="btn btn-xs btn-ghost",d.title="Edit field",B(d,"more-horizontal"),d.addEventListener("click",p=>{p.stopPropagation(),u.style.display=u.style.display==="none"?"":"none"}),s.appendChild(d);const r=document.createElement("button");if(r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove field",B(r,"x"),r.addEventListener("click",async p=>{p.stopPropagation(),await E.confirm("Remove this field?")&&(j(),T.splice(t,1),te(i))}),s.appendChild(r),l.appendChild(a),l.appendChild(o),e.required){const p=document.createElement("span");p.textContent="required",p.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",l.appendChild(p)}if(St(e.logic)){const p=document.createElement("span");B(p,"zap"),p.title="Has conditional logic",p.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",l.appendChild(p)}l.appendChild(s),l.addEventListener("click",()=>{u.style.display=u.style.display==="none"?"":"none"});const u=qn(e,t,o);return u.style.display="none",n.appendChild(l),n.appendChild(u),n}function qn(e,t,i){const n=document.createElement("div");n.className="fb-field-body",n.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border);";const l=O([z("Label",`fb-label-${t}`,"text",e.label||"","Shown above the field"),z("Field Name",`fb-name-${t}`,"text",e.name||"","Used as data key")]),a=O([Zn("Type",`fb-type-${t}`,xt,e.type||"string"),qe("Required",`fb-required-${t}`,e.required||!1)]),o=O([z("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),s=O([z("Helper Text",`fb-helper-${t}`,"text",e.helper||"","Shown below the field"),z("Tooltip",`fb-tooltip-${t}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),d=O([z("CSS classes",`fb-class-${t}`,"text",e.class||"","Your own class names, separated by spaces, on the field's wrapper - style them in Custom CSS")]),r=e.formConfig?.span,u=O([z("Column Span",`fb-span-${t}`,"number",r&&r!=="full"?String(r):"1","Columns to span (grid only)"),qe("Full Width",`fb-fullwidth-${t}`,r==="full")]);u.classList.add("fb-grid-row"),u.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(l),n.appendChild(a),n.appendChild(o),n.appendChild(s),n.appendChild(d),n.appendChild(u);const p=n.querySelector(`#fb-label-${t}`),m=n.querySelector(`#fb-name-${t}`);p&&p.addEventListener("input",()=>{i&&(i.textContent=p.value||"(unlabelled)"),m&&!m.dataset.manuallyEdited&&(m.value=Et(p.value))}),m&&m.addEventListener("input",()=>{m.dataset.manuallyEdited="1"});const v=n.querySelector(`#fb-type-${t}`);v&&v.addEventListener("change",()=>{const y=n.closest(".fb-field-card");if(y){const b=y.querySelector("span");b&&(b.textContent=wt(v.value))}const w=n.querySelector(".fb-field-extras");w&&w.remove();const x=Pt(v.value,e,t);x&&n.appendChild(x)});const f=Pt(e.type,e,t);return f&&n.appendChild(f),n.appendChild(On(e,t)),n.appendChild(jn(e,t)),n}const ke=[{value:"equals",label:"equals"},{value:"not_equals",label:"does not equal"},{value:"contains",label:"contains"},{value:"not_contains",label:"does not contain"},{value:"starts_with",label:"starts with"},{value:"ends_with",label:"ends with"},{value:"greater_than",label:"is greater than"},{value:"less_than",label:"is less than"},{value:"is_empty",label:"is empty"},{value:"is_not_empty",label:"is not empty"},{value:"in",label:"is one of (comma sep)"},{value:"not_in",label:"is not one of (comma sep)"},{value:"matches_regex",label:"matches regex"}],He=new Set(["is_empty","is_not_empty"]),Tt={equals:"includes",not_equals:"does not include",contains:"any value contains",not_contains:"no value contains",starts_with:"any value starts with",ends_with:"any value ends with",greater_than:"any value is greater than",less_than:"any value is less than",is_empty:"nothing selected",is_not_empty:"something selected",in:"includes one of (comma sep)",not_in:"includes none of (comma sep)",matches_regex:"any value matches regex"};function Ue(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function Se(e){const t=document.createElement("p");return t.textContent=e,t.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",t}function Te(e,t,i,n,l){const a=document.createElement("div");a.className="fb-logic-cond-row",a.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const o=document.createElement("span");o.textContent="When",o.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-cond-field",s.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,e&&f.value===e.field&&(y.selected=!0),s.appendChild(y)});const d=document.createElement("select");d.className="form-select fb-logic-cond-op",d.style.cssText="flex:1 1 160px;min-width:140px;",ke.forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,e&&f.value===e.operator&&(y.selected=!0),d.appendChild(y)});const r=()=>{const f=t.find(y=>y.value===s.value);Array.from(d.options).forEach(y=>{const w=ke.find(x=>x.value===y.value);y.textContent=f?.multi&&Tt[y.value]||w?.label||y.value})};r(),s.addEventListener("change",r);const u=document.createElement("input");u.type="text",u.className="form-input fb-logic-cond-val",u.placeholder="value",u.style.cssText="flex:1 1 120px;min-width:100px;",u.value=e?.value||"",e&&He.has(e.operator)&&(u.style.display="none"),d.addEventListener("change",()=>{u.style.display=He.has(d.value)?"none":""});const p=document.createElement("span");B(p,"arrow-right"),p.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const m=document.createElement("select");m.className=`form-select ${n}`,m.style.cssText="flex:1 1 140px;min-width:120px;",i.forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,f.value===l&&(y.selected=!0),m.appendChild(y)});const v=document.createElement("button");return v.type="button",v.className="btn btn-xs btn-ghost",v.style.cssText="line-height:1;opacity:.6;",B(v,"x"),v.style.flexShrink="0",v.addEventListener("click",()=>a.remove()),a.appendChild(o),a.appendChild(s),a.appendChild(d),a.appendChild(u),a.appendChild(p),a.appendChild(m),a.appendChild(v),a}function An(e,t,i){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(Se("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const a=document.createElement("span");a.textContent="Default:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const o=document.createElement("select");o.className="form-select fb-logic-vis-default",o.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(x=>{const b=document.createElement("option");b.value=x.value,b.textContent=x.label,x.value===(e.default||"visible")&&(b.selected=!0),o.appendChild(b)}),l.appendChild(a),l.appendChild(o),n.appendChild(l);const s=document.createElement("div");s.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const d=document.createElement("span");d.textContent="Transition:",d.style.cssText="font-size:.8rem;flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-vis-transition",r.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(x=>{const b=document.createElement("option");b.value=x.value,b.textContent=x.label,x.value===(e.transition||"none")&&(b.selected=!0),r.appendChild(b)}),s.appendChild(d),s.appendChild(r),n.appendChild(s);const u=document.createElement("div");u.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const p=document.createElement("span");p.textContent="Speed:",p.style.cssText="font-size:.8rem;flex-shrink:0;";const m=document.createElement("select");m.className="form-select fb-logic-vis-duration",m.style.cssText="max-width:240px;",[{value:"",label:"Default"},{value:"120",label:"Very fast (120ms)"},{value:"200",label:"Fast (200ms)"},{value:"350",label:"Medium (350ms)"},{value:"600",label:"Slow (600ms)"},{value:"1000",label:"Very slow (1s)"}].forEach(x=>{const b=document.createElement("option");b.value=x.value,b.textContent=x.label,x.value===String(e.duration??"")&&(b.selected=!0),m.appendChild(b)}),u.appendChild(p),u.appendChild(m),n.appendChild(u);const v=()=>{u.style.display=r.value==="none"?"none":""};v(),r.addEventListener("change",v);const f=document.createElement("div");f.className="fb-logic-vis-rules";const y=i.map(x=>({value:x.name,label:x.label||x.name,multi:Ue(x)})),w=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(x=>{const b=(x.when?.all||x.when?.any||[])[0],C=x.then==="hidden"?"hidden":"visible";y.length>0&&f.appendChild(Te(b,y,w,"fb-logic-vis-then",C))}),n.appendChild(f),y.length>0){const x=document.createElement("button");x.type="button",x.className="btn btn-xs btn-ghost",x.style.cssText="font-size:.73rem;margin-top:.35rem;",fe(x,"plus","Add visibility rule"),x.addEventListener("click",()=>f.appendChild(Te(null,y,w,"fb-logic-vis-then","visible"))),n.appendChild(x)}return n}function Fn(e,t,i){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(Se("Conditional Requirement"));const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8rem;cursor:pointer;margin-bottom:.65rem;";const a=document.createElement("input");a.type="checkbox",a.className="fb-logic-req-default",a.checked=e.default===!0,l.appendChild(a),l.appendChild(document.createTextNode("Required by default")),n.appendChild(l);const o=document.createElement("div");o.className="fb-logic-req-rules";const s=i.map(r=>({value:r.name,label:r.label||r.name,multi:Ue(r)})),d=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(r=>{const u=(r.when?.all||r.when?.any||[])[0],p=r.then===!0?"true":"false";s.length>0&&o.appendChild(Te(u,s,d,"fb-logic-req-then",p))}),n.appendChild(o),s.length>0){const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.style.cssText="font-size:.73rem;margin-top:.35rem;",fe(r,"plus","Add requirement rule"),r.addEventListener("click",()=>o.appendChild(Te(null,s,d,"fb-logic-req-then","true"))),n.appendChild(r)}return n}function Nt(e){const t=document.createElement("div");t.className="fb-logic-val-rule",t.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const i=document.createElement("select");i.className="form-select fb-logic-val-type",i.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(s=>{const d=document.createElement("option");d.value=s.value,d.textContent=s.label,s.value===(e?.type||"regex")&&(d.selected=!0),i.appendChild(d)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),i.addEventListener("change",()=>{l.style.display=i.value==="match"?"none":"",n.placeholder=i.value==="match"?"field name":"pattern"});const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-message",a.placeholder="Error message",a.value=e?.message||"",a.style.cssText="flex:4;";const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost",o.style.cssText="line-height:1;opacity:.6;",B(o,"x"),o.style.flexShrink="0",o.addEventListener("click",()=>t.remove()),t.appendChild(i),t.appendChild(n),t.appendChild(l),t.appendChild(a),t.appendChild(o),t}function Bn(e,t,i){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(Se("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(o=>l.appendChild(Nt(o))),n.appendChild(l);const a=document.createElement("button");return a.type="button",a.className="btn btn-xs btn-ghost",a.style.cssText="font-size:.73rem;margin-top:.35rem;",fe(a,"plus","Add validation rule"),a.addEventListener("click",()=>l.appendChild(Nt(null))),n.appendChild(a),n}function In(e,t,i){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(Se("Cascade Options")),n.lastChild.appendChild(Ve("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const a=document.createElement("span");a.textContent="Source field:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const o=document.createElement("select");o.className="form-select fb-logic-cascade-source",o.style.cssText="flex:1;";const s=document.createElement("option");s.value="",s.textContent="- none -",o.appendChild(s),i.forEach(m=>{const v=document.createElement("option");v.value=m.name,v.textContent=m.label||m.name,m.name===e.sourceField&&(v.selected=!0),o.appendChild(v)}),l.appendChild(a),l.appendChild(o),n.appendChild(l);const d=document.createElement("p");d.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',d.appendChild(Ve(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),d.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const r=document.createElement("textarea");r.className="form-input fb-logic-cascade-mapping",r.rows=4,r.style.cssText="font-family:monospace;",r.placeholder='{"uk": [{"value": "london", "label": "London"}]}',r.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(d),n.appendChild(r);const u=document.createElement("p");u.textContent="Default options (one per line: value:Label)",u.appendChild(Ve("Shown before the source field has a value, or when its value has no mapping entry.")),u.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const p=document.createElement("textarea");return p.className="form-input fb-logic-cascade-defaults",p.rows=3,p.style.cssText="font-family:monospace;",p.placeholder=`option1:Option 1
1
+ import{apiRequest as fe}from"/admin/js/api.js";import{makeIconInput as je}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as bt}from"/public/js/forms.js";import{buildWizardSteps as dn}from"/public/js/form-steps.mjs";import{DEFAULT_MAX_FILES as gt,MAX_FILES_LIMIT as He,captureFileFields as yt,destroyDropzones as vt,fileBlueprint as un,restoreFileFields as pn,splitFiles as mn,submitBody as fn,wireFileFields as hn}from"/public/js/form-files.mjs";import{applyFormClasses as xt,applySubmitButtons as bn,applyWizardButtons as gn,buttonSettingsProblems as yn,formClassProblems as vn,resolveSubmitAlign as wt}from"/public/js/form-submit.mjs";import{addBannerAction as Ve}from"../lib/plugin-chrome.js";import{helpPopovers as xn}from"../lib/help-popover.js";import{openMenuAt as Ct,sidebarCount as wn}from"../lib/tool-kit.js";import{draftBaseOf as Cn,draftChoice as En,draftKey as he,draftOf as kn,duplicateField as Sn,editorDraftQuestion as Tn,fieldTitle as We,fingerprint as Et,leavingEditor as kt,moveField as St,restoreDraft as Ln,snapshotOf as Ee}from"../lib/form-editor-arrange.js";import{fmtDateTime as Nn}from"../lib/dates.js";const Tt=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"chooser",label:"Chooser (visual options)"},{value:"icon",label:"Icon (icon picker)"},{value:"image",label:"Image (media library)"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"password",label:"Password"},{value:"file",label:"File upload"},{value:"hidden",label:"Hidden field"}],Ue=new Set(["select","radio","checkbox-group","chooser"]);let T=[],ke=[],I=null,Se=null,oe=null,Te={};function O(e,t,s=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(s)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function be(e,t,s,n=14){return O(e,t,n),e.appendChild(document.createTextNode(" "+s)),e}function A(e,t=""){const s=document.createElement("span");return s.setAttribute("data-help",e),t&&s.setAttribute("data-help-title",t),s}const ge={Label:"The name visitors see above this field.","Field Name":"The key stored with this answer. Use a unique name without spaces, such as email_address. Conditions, message tokens and integrations refer to this name.",Type:"The kind of answer this field accepts. Dropdowns, radio buttons and checkbox groups use the Options list below.",Required:"The visitor must answer this field before submitting. Conditional logic can change whether an answer is required.",Placeholder:"An example or short hint inside an empty input. It disappears when the visitor types.","Helper Text":"Instructions shown below the field, even after the visitor enters an answer.",Tooltip:"Help for visitors, shown beside the field label. Enter the explanation you want visitors to read.","Column Span":"How many columns this field occupies in a grid layout. Full Width spans the entire row.","Full Width":"Make this field span every column in the grid layout.","Min Length":"The fewest characters an answer may contain. Leave blank for no minimum; use Required to prevent an empty answer.","Max Length":"The most characters an answer may contain. Leave blank for no maximum.",Min:"The lowest number allowed. Leave blank for no lower limit.",Max:"The highest number allowed. Leave blank for no upper limit."},ye={Action:"Choose what happens when this branch is active. Banners, field changes and submission blocks apply while the condition holds. Toasts, step jumps and celebrations fire when the branch becomes active. Redirects, CMS actions and admin notifications are handled on submission.",Message:"The text visitors see. Use {{field_name}} to insert an answer; password and upload answers are never included.","Reason, shown under the button":"Explain why submission is blocked. Leave blank to use the default refusal message.","Message shown in place of the rest":"Explain why the form ends here. The remaining fields are hidden while this condition holds. You can insert answers with {{field_name}}.","Notification title":"The title of the admin notification created when the submitted answers meet this condition. Leave blank to use the form title. Field tokens are not expanded here.","Button text":"The button used to send the answers given so far when the form ends early. Leave blank for Finish.","Closing message":"Shown after the visitor finishes early. Leave blank for the form success message. You can insert answers with {{field_name}}.",Level:"The visual style of the message: Info, Success, Warning or Error.",Severity:"The level attached to the admin notification: Info, Success, Warning or Error.",Where:"Place the banner above or below the field that owns this trigger, or at the top of the form.","Which fields":"The rest of the form means fields after this trigger's field. Every other field excludes this field. Chosen fields lets you select specific targets.",Fields:"Select the fields this action changes. Use Ctrl-click on Windows or Linux, or Cmd-click on macOS, to select several.",Step:"The wizard step to open when this branch becomes active. Steps count from zero: 0 is the first step, 1 is the second. Add Page Breaks to create steps.","Send them to":"The destination after a successful submission when this condition matches. Use a site path such as /thank-you or a full URL. Field tokens are not expanded.",Theme:"The celebration to play when this branch becomes active. Whatever is in season chooses the seasonal theme automatically.",Intensity:"How much animation the celebration produces. Low is subtle; High adds more activity."};let Le=null,Lt=null,Ge=null,ve=null;function Ke(){Ge?.(),clearTimeout(Lt),Lt=setTimeout(()=>{Le&&Le()},350)}function Nt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function qt(e){return Tt.find(t=>t.value===e)?.label||e}function $t(e){return(e||[]).some(t=>t.logic||Array.isArray(t.triggers)&&t.triggers.length)}function At(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function qn(e){const t={...T[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const b=document.getElementById(`fb-pb-label-${e}`),w=document.getElementById(`fb-pb-desc-${e}`);return b&&(t.label=b.value.trim()||t.label),w&&(t.description=w.value.trim()),t}const s=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),a=document.getElementById(`fb-type-${e}`),i=document.getElementById(`fb-required-${e}`),o=document.getElementById(`fb-placeholder-${e}`),l=document.getElementById(`fb-helper-${e}`),d=document.getElementById(`fb-tooltip-${e}`);s&&(t.label=s.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),a&&(t.type=a.value||t.type),i&&(t.required=i.checked),o&&(t.placeholder=o.value.trim()),l&&(t.helper=l.value.trim()),d&&(t.tooltip=d.value.trim());const r=document.getElementById(`fb-class-${e}`);if(r){const b=r.value.trim();b?t.class=b:delete t.class}if(t.type==="chooser"){const b=document.getElementById(`fb-chooser-variant-${e}`)?.value;b&&(t.variant=b);const w=document.getElementById(`fb-chooser-multiple-${e}`);w&&(t.multiple=w.checked);const q=document.getElementById(`fb-chooser-density-${e}`)?.value;q&&(t.density=q);const B=document.getElementById(`fb-chooser-columns-${e}`)?.value;B!==""&&B!==void 0&&(t.columns=parseInt(B,10)||3);const _=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();_?t.accent=_:delete t.accent;const W=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;W?t.accentStyle=W:delete t.accentStyle;const j=document.getElementById(`fb-chooser-glow-${e}`);j&&(t.glow=j.checked);const Y=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();Y?t.glowColour=Y:delete t.glowColour;const U=document.getElementById(`fb-chooser-shadow-${e}`)?.value;U&&U!=="none"?t.shadow=U:delete t.shadow;const ae=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();ae?t.shadowColour=ae:delete t.shadowColour,Be(e),T[e]&&Array.isArray(T[e].options)&&(t.options=T[e].options)}else if(Ue.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(w=>delete t[w]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const b=document.getElementById(`fb-options-${e}`);b&&(t.options=b.value.split(`
2
+ `).filter(w=>w.trim()).map(w=>{const[q,...B]=w.split(":");return{value:q.trim(),label:B.join(":").trim()||q.trim()}}))}for(const b of["prefix","suffix"]){const w=document.getElementById(`fb-${b}-icon-${e}`),q=document.getElementById(`fb-${b}-text-${e}`),B={...t.formConfig||{}};if(w||q){const _=w?.value.trim()||"",W=q?.value.trim()||"";_&&/^[a-z0-9-]+$/i.test(_)?B[b]={icon:_}:W?B[b]={text:W.slice(0,24)}:delete B[b]}else Kt.includes(t.type)||delete B[b];t.formConfig=Object.keys(B).length?B:void 0}{const b={...t.formConfig||{}};for(const w of et){const q=document.getElementById(`fb-extra-${w.key}-${e}`);q&&w.types.includes(t.type)?q.checked?b[w.key]=!0:delete b[w.key]:w.types.includes(t.type)||delete b[w.key]}t.formConfig=Object.keys(b).length?b:void 0}if(t.type==="file"){const b=document.getElementById(`fb-file-multiple-${e}`);if(b){const w={...t.file||{}};if(b.checked){t.multiple=!0;const q=parseInt(document.getElementById(`fb-file-max-${e}`)?.value,10);q>=1?w.maxFiles=Math.min(q,He):delete w.maxFiles}else delete t.multiple,delete w.maxFiles;t.file=Object.keys(w).length?w:void 0}}if(t.type==="textarea"){const b=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);b>0&&(t.formConfig={...t.formConfig||{},rows:b})}const u=document.getElementById(`fb-span-${e}`),p=document.getElementById(`fb-fullwidth-${e}`);if(u||p){const b={...t.formConfig||{}};if(p?.checked)b.span="full";else{const w=parseInt(u?.value,10);w>1?b.span=w:delete b.span}t.formConfig=Object.keys(b).length?b:void 0}const m=document.getElementById(`fb-minlength-${e}`)?.value;m&&(t.minLength=parseInt(m,10));const v=document.getElementById(`fb-maxlength-${e}`)?.value;v&&(t.maxLength=parseInt(v,10));const f=document.getElementById(`fb-min-${e}`)?.value;f!==""&&f!==void 0&&(t.min=parseFloat(f));const y=document.getElementById(`fb-max-${e}`)?.value;y!==""&&y!==void 0&&(t.max=parseFloat(y));const C=$n(e);C?t.logic=C:delete t.logic;const x=Yn(e);return x?t.triggers=x:delete t.triggers,t}function $n(e){const t=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!t)return;const s=t.querySelector(".fb-field-logic");if(!s)return;const n={};let a=!1;const i=s.querySelector('[data-logic-section="visibility"]');if(i){const r=i.querySelector(".fb-logic-vis-default"),u=i.querySelector(".fb-logic-vis-transition"),p=Array.from(i.querySelectorAll(".fb-logic-cond-row")).map(y=>{const C=y.querySelector(".fb-logic-cond-field"),x=y.querySelector(".fb-logic-cond-op"),b=y.querySelector(".fb-logic-cond-val"),w=y.querySelector(".fb-logic-vis-then");return C?.value?{when:{all:[{field:C.value,operator:x.value,value:b.value}]},then:w.value}:null}).filter(Boolean),m=r?.value||"visible",v=u?.value||"none",f=parseInt(i.querySelector(".fb-logic-vis-duration")?.value||"",10);(m!=="visible"||p.length>0||v!=="none")&&(n.visibility={default:m,conditions:p},v!=="none"&&(n.visibility.transition=v),v!=="none"&&Number.isFinite(f)&&(n.visibility.duration=f),a=!0)}const o=s.querySelector('[data-logic-section="requirement"]');if(o){const r=o.querySelector(".fb-logic-req-default"),u=Array.from(o.querySelectorAll(".fb-logic-cond-row")).map(p=>{const m=p.querySelector(".fb-logic-cond-field"),v=p.querySelector(".fb-logic-cond-op"),f=p.querySelector(".fb-logic-cond-val"),y=p.querySelector(".fb-logic-req-then");return m?.value?{when:{all:[{field:m.value,operator:v.value,value:f.value}]},then:y.value==="true"}:null}).filter(Boolean);u.length>0&&(n.requirement={default:r?.checked===!0,conditions:u},a=!0)}const l=s.querySelector('[data-logic-section="validation"]');if(l){const r=Array.from(l.querySelectorAll(".fb-logic-val-rule")).map(u=>{const p=u.querySelector(".fb-logic-val-type"),m=u.querySelector(".fb-logic-val-pattern"),v=u.querySelector(".fb-logic-val-flags"),f=u.querySelector(".fb-logic-val-message");if(!m?.value.trim())return null;const y=p?.value||"regex",C={type:y,message:f?.value.trim()||"Invalid value."};return y==="regex"?(C.pattern=m.value.trim(),v?.value.trim()&&(C.flags=v.value.trim())):C.field=m.value.trim(),C}).filter(Boolean);r.length>0&&(n.validation=r,a=!0)}const d=s.querySelector('[data-logic-section="cascade"]');if(d){const r=d.querySelector(".fb-logic-cascade-source"),u=d.querySelector(".fb-logic-cascade-mapping"),p=d.querySelector(".fb-logic-cascade-defaults"),m=r?.value?.trim();if(m){let v={};try{v=JSON.parse(u?.value||"{}")}catch{}const f=(p?.value||"").split(`
3
+ `).filter(y=>y.trim()).map(y=>{const[C,...x]=y.split(":");return{value:C.trim(),label:x.join(":").trim()||C.trim()}});n.cascade={sourceField:m,mapping:v,defaultOptions:f},a=!0}}return a?n:void 0}function V(){T=T.map((e,t)=>qn(t))}function An(e){const t=e.firstElementChild;if(!t||t.querySelector(".fb-drag-grip"))return;const s=document.createElement("span");s.className="fb-drag-grip",s.setAttribute("data-icon","grip-vertical"),s.setAttribute("data-icon-size","16"),s.title="Drag to reorder",t.insertBefore(s,t.firstChild),window.I?.scan?.(t)}function ne(e){const t=e.find("#fields-list").get(0),s=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),T.length===0){s&&(s.style.display=""),ve?.(t),Ke();return}s&&(s.style.display="none"),T.forEach((n,a)=>{const i=n.type==="page-break"?Fn(n,a,e):n.type==="spacer"?Bn(n,a,e):In(n,a,e);An(i),t.appendChild(i)}),ve?.(t),Ke()}}function Fn(e,t,s){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:2px dashed var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const i=document.createElement("span");i.textContent="- Page Break -",i.style.cssText="font-size:.7rem;padding:.15rem .5rem;border-radius:999px;background:color-mix(in srgb, var(--dm-text-muted) 20%, transparent);color:var(--dm-text-muted);white-space:nowrap;flex-shrink:0;font-style:italic;";const o=document.createElement("span");o.textContent=e.label||"Untitled Step",o.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted);";const l=document.createElement("div");l.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const d=document.createElement("button");d.className="btn btn-xs btn-ghost",d.title="Edit step",O(d,"more-horizontal"),d.addEventListener("click",v=>{v.stopPropagation(),u.style.display=u.style.display==="none"?"":"none"}),l.appendChild(d);const r=document.createElement("button");r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove page break",O(r,"x"),r.addEventListener("click",async v=>{v.stopPropagation(),await E.confirm("Remove this page break?")&&(V(),T.splice(t,1),ne(s))}),l.appendChild(r),a.appendChild(i),a.appendChild(o),a.appendChild(l),a.addEventListener("click",()=>{u.style.display=u.style.display==="none"?"":"none"});const u=document.createElement("div");u.className="fb-field-body",u.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const p=z([P("Step Title",`fb-pb-label-${t}`,"text",e.label||"","Shown as the wizard step heading"),P("Step Description",`fb-pb-desc-${t}`,"text",e.description||"","Optional sub-heading")]),m=p.querySelector(`#fb-pb-label-${t}`);return m&&m.addEventListener("input",()=>{o.textContent=m.value||"Untitled Step"}),u.appendChild(p),n.appendChild(a),n.appendChild(u),n}function Bn(e,t,s){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px dashed var(--dm-border);border-radius:6px;margin-bottom:.5rem;background:transparent;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.4rem .8rem;";const i=document.createElement("div");i.style.cssText="flex:1;height:1px;background:var(--dm-border);";const o=document.createElement("span");o.textContent="Spacer",o.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const l=document.createElement("div");l.style.cssText="flex:1;height:1px;background:var(--dm-border);";const d=document.createElement("div");d.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const r=document.createElement("button");return r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove spacer",O(r,"x"),r.addEventListener("click",async u=>{u.stopPropagation(),V(),T.splice(t,1),ne(s)}),d.appendChild(r),a.appendChild(i),a.appendChild(o),a.appendChild(l),a.appendChild(d),n.appendChild(a),n}function In(e,t,s){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px solid var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);box-shadow:var(--dm-shadow-sm);";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;background:var(--dm-card-header-bg);cursor:pointer;user-select:none;";const i=document.createElement("span");i.textContent=qt(e.type),i.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary);white-space:nowrap;flex-shrink:0;";const o=document.createElement("span");o.textContent=e.label||"(unlabelled)",o.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const l=document.createElement("div");l.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const d=document.createElement("button");d.className="btn btn-xs btn-ghost",d.title="Edit field",O(d,"more-horizontal"),d.addEventListener("click",p=>{p.stopPropagation(),u.style.display=u.style.display==="none"?"":"none"}),l.appendChild(d);const r=document.createElement("button");if(r.className="btn btn-xs btn-ghost",r.style.cssText="line-height:1;opacity:.6;",r.title="Remove field",O(r,"x"),r.addEventListener("click",async p=>{p.stopPropagation(),await E.confirm("Remove this field?")&&(V(),T.splice(t,1),ne(s))}),l.appendChild(r),a.appendChild(i),a.appendChild(o),e.required){const p=document.createElement("span");p.textContent="required",p.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",a.appendChild(p)}if(At(e.logic)){const p=document.createElement("span");O(p,"zap"),p.title="Has conditional logic",p.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",a.appendChild(p)}a.appendChild(l),a.addEventListener("click",()=>{u.style.display=u.style.display==="none"?"":"none"});const u=Mn(e,t,o);return u.style.display="none",n.appendChild(a),n.appendChild(u),n}function Mn(e,t,s){const n=document.createElement("div");n.className="fb-field-body",n.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border);";const a=z([P("Label",`fb-label-${t}`,"text",e.label||"","Shown above the field"),P("Field Name",`fb-name-${t}`,"text",e.name||"","Used as data key")]),i=z([ia("Type",`fb-type-${t}`,Tt,e.type||"string"),Ie("Required",`fb-required-${t}`,e.required||!1)]),o=z([P("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),l=z([P("Helper Text",`fb-helper-${t}`,"text",e.helper||"","Shown below the field"),P("Tooltip",`fb-tooltip-${t}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),d=z([P("CSS classes",`fb-class-${t}`,"text",e.class||"","Your own class names, separated by spaces, on the field's wrapper - style them in Custom CSS")]),r=e.formConfig?.span,u=z([P("Column Span",`fb-span-${t}`,"number",r&&r!=="full"?String(r):"1","Columns to span (grid only)"),Ie("Full Width",`fb-fullwidth-${t}`,r==="full")]);u.classList.add("fb-grid-row"),u.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(a),n.appendChild(i),n.appendChild(o),n.appendChild(l),n.appendChild(d),n.appendChild(u);const p=n.querySelector(`#fb-label-${t}`),m=n.querySelector(`#fb-name-${t}`);p&&p.addEventListener("input",()=>{s&&(s.textContent=p.value||"(unlabelled)"),m&&!m.dataset.manuallyEdited&&(m.value=Nt(p.value))}),m&&m.addEventListener("input",()=>{m.dataset.manuallyEdited="1"});const v=n.querySelector(`#fb-type-${t}`);v&&v.addEventListener("change",()=>{const y=n.closest(".fb-field-card");if(y){const b=y.querySelector("span");b&&(b.textContent=qt(v.value))}const C=n.querySelector(".fb-field-extras");C&&C.remove();const x=Gt(v.value,e,t);x&&n.appendChild(x)});const f=Gt(e.type,e,t);return f&&n.appendChild(f),n.appendChild(_n(e,t)),n.appendChild(Gn(e,t)),n}const Ne=[{value:"equals",label:"equals"},{value:"not_equals",label:"does not equal"},{value:"contains",label:"contains"},{value:"not_contains",label:"does not contain"},{value:"starts_with",label:"starts with"},{value:"ends_with",label:"ends with"},{value:"greater_than",label:"is greater than"},{value:"less_than",label:"is less than"},{value:"is_empty",label:"is empty"},{value:"is_not_empty",label:"is not empty"},{value:"in",label:"is one of (comma sep)"},{value:"not_in",label:"is not one of (comma sep)"},{value:"matches_regex",label:"matches regex"}],Ye=new Set(["is_empty","is_not_empty"]),Ft={equals:"includes",not_equals:"does not include",contains:"any value contains",not_contains:"no value contains",starts_with:"any value starts with",ends_with:"any value ends with",greater_than:"any value is greater than",less_than:"any value is less than",is_empty:"nothing selected",is_not_empty:"something selected",in:"includes one of (comma sep)",not_in:"includes none of (comma sep)",matches_regex:"any value matches regex"};function Je(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function qe(e){const t=document.createElement("p");return t.textContent=e,t.appendChild(A({Visibility:"Choose whether this field starts visible or hidden, then add rules to show or hide it based on answers. The transition and speed control how it appears.","Conditional Requirement":"Make this field required or optional according to another answer. Hidden fields are not required.","Custom Validation":"Regex tests the answer against a regular expression; flags such as i make it case insensitive. Match field compares with another field name, such as password confirmation. Set the error message visitors see if the check fails.","Cascade Options":"Replace this field's choices according to another field's answer. Map source values to option lists and provide default options for unmatched or empty answers."}[e],e)),t.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",t}function $e(e,t,s,n,a){const i=document.createElement("div");i.className="fb-logic-cond-row",i.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const o=document.createElement("span");o.textContent="When",o.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const l=document.createElement("select");l.className="form-select fb-logic-cond-field",l.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,e&&f.value===e.field&&(y.selected=!0),l.appendChild(y)});const d=document.createElement("select");d.className="form-select fb-logic-cond-op",d.style.cssText="flex:1 1 160px;min-width:140px;",Ne.forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,e&&f.value===e.operator&&(y.selected=!0),d.appendChild(y)});const r=()=>{const f=t.find(y=>y.value===l.value);Array.from(d.options).forEach(y=>{const C=Ne.find(x=>x.value===y.value);y.textContent=f?.multi&&Ft[y.value]||C?.label||y.value})};r(),l.addEventListener("change",r);const u=document.createElement("input");u.type="text",u.className="form-input fb-logic-cond-val",u.placeholder="value",u.style.cssText="flex:1 1 120px;min-width:100px;",u.value=e?.value||"",e&&Ye.has(e.operator)&&(u.style.display="none"),d.addEventListener("change",()=>{u.style.display=Ye.has(d.value)?"none":""});const p=document.createElement("span");O(p,"arrow-right"),p.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const m=document.createElement("select");m.className=`form-select ${n}`,m.style.cssText="flex:1 1 140px;min-width:120px;",s.forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,f.value===a&&(y.selected=!0),m.appendChild(y)});const v=document.createElement("button");return v.type="button",v.className="btn btn-xs btn-ghost",v.style.cssText="line-height:1;opacity:.6;",O(v,"x"),v.style.flexShrink="0",v.addEventListener("click",()=>i.remove()),i.appendChild(o),i.appendChild(L("Field",l,{help:"The answer this rule tests. Select another named field from the form."})),i.appendChild(L("Comparison",d,{help:"How to compare the answer. Multi-choice fields test their selected values. Empty and not empty do not need a value."})),i.appendChild(L("Value",u,{help:"The stored value to compare against. For one of, enter comma-separated values. For regex, enter a regular expression."})),i.appendChild(p),i.appendChild(L("Result",m,{help:"What happens to this field when the condition matches: change its visibility or whether an answer is required."})),i.appendChild(v),i}function On(e,t,s){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(qe("Visibility"));const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const i=document.createElement("span");i.textContent="Default:",i.style.cssText="font-size:.8rem;flex-shrink:0;";const o=document.createElement("select");o.className="form-select fb-logic-vis-default",o.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(x=>{const b=document.createElement("option");b.value=x.value,b.textContent=x.label,x.value===(e.default||"visible")&&(b.selected=!0),o.appendChild(b)}),i.appendChild(A("Whether the field is visible before any rule matches.","Default visibility")),a.appendChild(i),a.appendChild(o),n.appendChild(a);const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const d=document.createElement("span");d.textContent="Transition:",d.style.cssText="font-size:.8rem;flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-vis-transition",r.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(x=>{const b=document.createElement("option");b.value=x.value,b.textContent=x.label,x.value===(e.transition||"none")&&(b.selected=!0),r.appendChild(b)}),d.appendChild(A("The animation used when this field appears or disappears. None switches instantly.","Transition")),l.appendChild(d),l.appendChild(r),n.appendChild(l);const u=document.createElement("div");u.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const p=document.createElement("span");p.textContent="Speed:",p.style.cssText="font-size:.8rem;flex-shrink:0;";const m=document.createElement("select");m.className="form-select fb-logic-vis-duration",m.style.cssText="max-width:240px;",[{value:"",label:"Default"},{value:"120",label:"Very fast (120ms)"},{value:"200",label:"Fast (200ms)"},{value:"350",label:"Medium (350ms)"},{value:"600",label:"Slow (600ms)"},{value:"1000",label:"Very slow (1s)"}].forEach(x=>{const b=document.createElement("option");b.value=x.value,b.textContent=x.label,x.value===String(e.duration??"")&&(b.selected=!0),m.appendChild(b)}),p.appendChild(A("How long the visibility animation lasts. Default uses the effect timing; shorter times are faster.","Speed")),u.appendChild(p),u.appendChild(m),n.appendChild(u);const v=()=>{u.style.display=r.value==="none"?"none":""};v(),r.addEventListener("change",v);const f=document.createElement("div");f.className="fb-logic-vis-rules";const y=s.map(x=>({value:x.name,label:x.label||x.name,multi:Je(x)})),C=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(x=>{const b=(x.when?.all||x.when?.any||[])[0],w=x.then==="hidden"?"hidden":"visible";y.length>0&&f.appendChild($e(b,y,C,"fb-logic-vis-then",w))}),n.appendChild(f),y.length>0){const x=document.createElement("button");x.type="button",x.className="btn btn-xs btn-ghost",x.style.cssText="font-size:.73rem;margin-top:.35rem;",be(x,"plus","Add visibility rule"),x.addEventListener("click",()=>f.appendChild($e(null,y,C,"fb-logic-vis-then","visible"))),n.appendChild(x)}return n}function Rn(e,t,s){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(qe("Conditional Requirement"));const a=document.createElement("label");a.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8rem;cursor:pointer;margin-bottom:.65rem;";const i=document.createElement("input");i.type="checkbox",i.className="fb-logic-req-default",i.checked=e.default===!0,a.appendChild(i),a.appendChild(document.createTextNode("Required by default")),a.appendChild(A("Whether this field requires an answer before a conditional requirement rule matches.","Required by default")),n.appendChild(a);const o=document.createElement("div");o.className="fb-logic-req-rules";const l=s.map(r=>({value:r.name,label:r.label||r.name,multi:Je(r)})),d=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(r=>{const u=(r.when?.all||r.when?.any||[])[0],p=r.then===!0?"true":"false";l.length>0&&o.appendChild($e(u,l,d,"fb-logic-req-then",p))}),n.appendChild(o),l.length>0){const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.style.cssText="font-size:.73rem;margin-top:.35rem;",be(r,"plus","Add requirement rule"),r.addEventListener("click",()=>o.appendChild($e(null,l,d,"fb-logic-req-then","true"))),n.appendChild(r)}return n}function Bt(e){const t=document.createElement("div");t.className="fb-logic-val-rule",t.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const s=document.createElement("select");s.className="form-select fb-logic-val-type",s.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(l=>{const d=document.createElement("option");d.value=l.value,d.textContent=l.label,l.value===(e?.type||"regex")&&(d.selected=!0),s.appendChild(d)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-flags",a.placeholder="flags",a.value=e?.flags||"",a.style.cssText="flex:0 0 55px;",e?.type==="match"&&(a.style.display="none"),s.addEventListener("change",()=>{a.style.display=s.value==="match"?"none":"",n.placeholder=s.value==="match"?"field name":"pattern"});const i=document.createElement("input");i.type="text",i.className="form-input fb-logic-val-message",i.placeholder="Error message",i.value=e?.message||"",i.style.cssText="flex:4;";const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost",o.style.cssText="line-height:1;opacity:.6;",O(o,"x"),o.style.flexShrink="0",o.addEventListener("click",()=>t.remove()),t.appendChild(L("Validation",s,{help:"Regex checks a pattern. Match field requires the same answer as another named field."})),t.appendChild(L("Pattern or field name",n,{help:"For Regex, enter a regular expression without enclosing slashes. For Match field, enter the other field name, such as password."})),t.appendChild(L("Flags",a,{help:"Optional regular expression flags, such as i for case insensitive matching. Applies only to Regex."})),t.appendChild(L("Error message",i,{help:"The explanation visitors see when the answer fails this validation rule."})),t.appendChild(o),t}function Dn(e,t,s){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(qe("Custom Validation"));const a=document.createElement("div");a.className="fb-logic-val-rules",(e||[]).forEach(o=>a.appendChild(Bt(o))),n.appendChild(a);const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="font-size:.73rem;margin-top:.35rem;",be(i,"plus","Add validation rule"),i.addEventListener("click",()=>a.appendChild(Bt(null))),n.appendChild(i),n}function zn(e,t,s){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(qe("Cascade Options")),n.lastChild.appendChild(A("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const i=document.createElement("span");i.textContent="Source field:",i.style.cssText="font-size:.8rem;flex-shrink:0;";const o=document.createElement("select");o.className="form-select fb-logic-cascade-source",o.style.cssText="flex:1;";const l=document.createElement("option");l.value="",l.textContent="- none -",o.appendChild(l),s.forEach(m=>{const v=document.createElement("option");v.value=m.name,v.textContent=m.label||m.name,m.name===e.sourceField&&(v.selected=!0),o.appendChild(v)}),a.appendChild(i),a.appendChild(o),n.appendChild(a);const d=document.createElement("p");d.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',d.appendChild(A(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),d.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const r=document.createElement("textarea");r.className="form-input fb-logic-cascade-mapping",r.rows=4,r.style.cssText="font-family:monospace;",r.placeholder='{"uk": [{"value": "london", "label": "London"}]}',r.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(d),n.appendChild(r);const u=document.createElement("p");u.textContent="Default options (one per line: value:Label)",u.appendChild(A("Shown before the source field has a value, or when its value has no mapping entry.")),u.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const p=document.createElement("textarea");return p.className="form-input fb-logic-cascade-defaults",p.rows=3,p.style.cssText="font-family:monospace;",p.placeholder=`option1:Option 1
4
4
  option2:Option 2`,p.value=(e.defaultOptions||[]).map(m=>{const v=typeof m=="string"?m:m.value??"",f=typeof m=="string"?m:m.label??v;return v===f?v:`${v}:${f}`}).join(`
5
- `),n.appendChild(u),n.appendChild(p),n}function On(e,t){const i=e.logic||{},n=T.filter((p,m)=>m!==t&&p.type!=="page-break"&&p.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const o=document.createElement("span");o.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",o.textContent="\u26A1 Conditional Logic";const s=St(i),d=document.createElement("button");d.type="button",d.className="btn btn-xs btn-ghost",B(d,s?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-logic-body",r.style.cssText="padding:.25rem 0 .25rem;"+(s?"":"display:none;"),a.addEventListener("click",()=>{const p=r.style.display==="none";r.style.display=p?"":"none",B(d,p?"chevron-down":"chevron-right",12)}),a.appendChild(o),a.appendChild(d),l.appendChild(a),r.appendChild(An(i.visibility||{},t,n)),r.appendChild(Fn(i.requirement||{},t,n)),r.appendChild(Bn(i.validation||[],t,n));const u=document.getElementById(`fb-type-${t}`)?.value||e.type;return je.has(u)&&r.appendChild(In(i.cascade||{},t,n)),l.appendChild(r),l}const be=[{value:"banner",label:"Show a banner",kind:"state",params:["message","level","position","dismissible"],placeholder:"e.g. You must be 18 or over to continue."},{value:"toast",label:"Show a toast",kind:"event",params:["message","level"],placeholder:"e.g. Thanks - carry on."},{value:"hide-fields",label:"Hide fields",kind:"state",params:["target"]},{value:"disable-fields",label:"Disable fields",kind:"state",params:["target"]},{value:"require-fields",label:"Make fields required",kind:"state",params:["target"]},{value:"block-submit",label:"Block submission",kind:"state",params:["message"],messageLabel:"Reason, shown under the button",placeholder:'Blank: "This form cannot be submitted yet."'},{value:"end-form",label:"End the form here",kind:"state",params:["message","finish","finishLabel","doneMessage","record"],messageLabel:"Message shown in place of the rest",placeholder:"e.g. Sorry - you must be 18 or over to apply."},{value:"goto-step",label:"Jump to a wizard step",kind:"event",params:["step"]},{value:"redirect",label:"Redirect after submit",kind:"event",params:["url"]},{value:"celebrate",label:"Celebrate",kind:"event",params:["theme","intensity"]},{value:"run-action",label:"Run a CMS action",kind:"event",params:["slug"]},{value:"notify",label:"Notify the admins",kind:"event",params:["message","level"],messageLabel:"Notification title",placeholder:"Blank: titled after the form",noOnce:!0,kindText:"when the form is submitted"}],Ne=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],Lt=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],$t=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],qt=[{value:"auto",label:"Whatever is in season"},{value:"christmas",label:"Christmas"},{value:"halloween",label:"Halloween"},{value:"valentines",label:"Valentine's Day"},{value:"guy-fawkes",label:"Guy Fawkes Night"},{value:"st-patricks",label:"St Patrick's Day"},{value:"st-andrews",label:"St Andrew's Day"},{value:"st-davids",label:"St David's Day"},{value:"st-georges",label:"St George's Day"}];function At(e,t=!1){const i=(o,s)=>({value:o.name,label:`${o.label||o.name}${s?" (this field)":""}`,multi:Ue(o)}),n=o=>o&&o.type!=="page-break"&&o.type!=="spacer"&&o.name,l=T.filter((o,s)=>s!==e&&n(o)).map(o=>i(o,!1)),a=T[e];return t&&n(a)?[i(a,!0),...l]:l}function X(e,t,i){const n=document.createElement("select");return n.className=`form-select ${e}`,t.forEach(l=>{const a=document.createElement("option");a.value=l.value,a.textContent=l.label,l.value===i&&(a.selected=!0),n.appendChild(a)}),n}function se(e,t,i){const n=document.createElement("input");return n.type="text",n.className=`form-input ${e}`,n.value=t==null?"":String(t),i&&(n.placeholder=i),n}function Ke(e,t){const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost fb-trig-remove",t&&(i.title=t,i.setAttribute("aria-label",t)),B(i,"x"),i.addEventListener("click",n=>{n.stopPropagation(),e()}),i}function H(e,t,{full:i=!1,hint:n=""}={}){const l=document.createElement("label");l.className=`fb-trig-f${i?" fb-trig-f--full":""}`;const a=document.createElement("span");if(a.className="fb-trig-f-label",a.textContent=e,l.appendChild(a),l.appendChild(t),n){const o=document.createElement("span");o.className="fb-trig-f-hint",o.textContent=n,l.appendChild(o)}return l}function ge(e,t,i,n){const l=document.createElement("label");l.className="fb-trig-check",n&&(l.title=n);const a=document.createElement("input");return a.type="checkbox",a.className=`form-check ${e}`,a.checked=!!t,l.appendChild(a),l.appendChild(document.createTextNode(i)),l}function Ft(e,t){const i=document.createElement("div");i.className="fb-trig-cond-row";const n=X("fb-trig-cond-field",t,e?.field),l=X("fb-trig-cond-op",ke,e?.operator),a=se("fb-trig-cond-val",e?.value,"value"),o=()=>{const d=t.find(r=>r.value===n.value);Array.from(l.options).forEach(r=>{const u=ke.find(p=>p.value===r.value);r.textContent=d?.multi&&Tt[r.value]||u?.label||r.value})},s=()=>{a.hidden=He.has(l.value)};return o(),s(),n.addEventListener("change",o),l.addEventListener("change",s),i.appendChild(n),i.appendChild(l),i.appendChild(a),i.appendChild(Ke(()=>i.remove(),"Remove condition")),i}const Bt=["banner","toast","block-submit","end-form"],It=["password","file","image","signature"],Mn="Put an answer in with {{field_name}} - e.g. Hello {{name}}. Pick one from Insert field.";function zn(){try{j()}catch{}return T.filter(e=>e&&e.name&&e.type!=="page-break"&&e.type!=="spacer"&&!It.includes(e.type))}function Ot(e,t,i){const n=se(e,t,i),l=document.createElement("span");l.className="fb-token-row";const a=document.createElement("select");a.className="form-input fb-token-pick",a.title="Insert an answer into the message",a.setAttribute("aria-label","Insert a field's answer into the message");const o=()=>{a.replaceChildren(new Option("Insert field",""));for(const s of zn())a.appendChild(new Option(`${s.label||s.name} ({{${s.name}}})`,s.name))};return o(),a.addEventListener("focus",o),a.addEventListener("mousedown",o),a.addEventListener("change",()=>{const s=a.value;if(a.value="",!s)return;const d=`{{${s}}}`,r=n.selectionStart??n.value.length,u=n.selectionEnd??r;n.value=n.value.slice(0,r)+d+n.value.slice(u),n.focus(),n.setSelectionRange(r+d.length,r+d.length),n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}),l.append(n,a),l}function Rn(e){const t=window.FormLogicEngine;if(!t?.triggerTokens)return[];const i=new Map((e||[]).filter(l=>l&&l.name).map(l=>[l.name,l])),n=new Set;for(const l of e||[])for(const a of l?.triggers||[])for(const o of[...a.then||[],...a.otherwise||[]])if(Bt.includes(o?.type))for(const s of[...t.triggerTokens(o.message),...t.triggerTokens(o.doneMessage)]){const d=i.get(s);(!d||It.includes(d.type))&&n.add(s)}return[...n]}function Mt(e,t){const i=document.createElement("div");i.className="fb-trig-params";const n=be.find(d=>d.value===(e.type||"banner"));if(!n)return i;const l=document.createElement("div");l.className="fb-trig-grid";const a=document.createElement("div");a.className="fb-trig-opts";const o=[];for(const d of n.params)switch(d){case"message":l.appendChild(Bt.includes(n.value)?H(n.messageLabel||"Message",Ot("fb-trig-p-message",e.message,n.placeholder||""),{full:!0,hint:Mn}):H(n.messageLabel||"Message",se("fb-trig-p-message",e.message,n.placeholder||""),{full:!0}));break;case"finish":a.appendChild(ge("fb-trig-p-finish-on",e.finish!==!1,"Let the visitor finish (send the answers given so far)",'Untick to stop the form dead: the submit button is disabled and nothing is sent, so nothing is saved and "Notify the admins" cannot fire.'));break;case"finishLabel":{const r=H("Button text",se("fb-trig-p-finish",e.finishLabel,"Finish"));o.push(r),l.appendChild(r);break}case"doneMessage":{const r=H("Closing message",Ot("fb-trig-p-done",e.doneMessage,"Blank: the form's own success message"));o.push(r),l.appendChild(r);break}case"record":{const r=ge("fb-trig-p-record",e.record!==!1,"Save the answers given so far",`Untick to keep nothing: no submission is stored and the form's email, webhook and actions do not run. A "Notify the admins" action still fires.`);o.push(r),a.appendChild(r);break}case"level":l.appendChild(H(n.value==="notify"?"Severity":"Level",X("fb-trig-p-level",Ne,e.level||"info")));break;case"position":l.appendChild(H("Where",X("fb-trig-p-position",Lt,e.position||"field-below")));break;case"dismissible":a.appendChild(ge("fb-trig-p-dismissible",e.dismissible!==!1,"The visitor can dismiss it"));break;case"target":{const r=X("fb-trig-p-target",$t,e.target||(e.fields?.length?"listed":"rest")),u=document.createElement("select");u.className="form-select fb-trig-p-fields",u.multiple=!0,u.size=4;const p=new Set(e.fields||[]);At(t).forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,p.has(f.value)&&(y.selected=!0),u.appendChild(y)});const m=H("Fields",u,{hint:"Ctrl/Cmd-click to pick several"}),v=()=>{m.hidden=r.value!=="listed"};v(),r.addEventListener("change",v),l.appendChild(H("Which fields",r)),l.appendChild(m);break}case"step":{const r=se("fb-trig-p-step",e.step,"0");r.type="number",r.min="0",l.appendChild(H("Step",r,{hint:"Counting from 0"}));break}case"url":l.appendChild(H("Send them to",se("fb-trig-p-url",e.url,"/thank-you"),{full:!0}));break;case"theme":l.appendChild(H("Theme",X("fb-trig-p-theme",qt,e.theme||"auto")));break;case"intensity":l.appendChild(H("Intensity",X("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium")));break;case"slug":{const r=[{value:"",label:xe.length?"Choose an action":"No actions available"}].concat(xe.map(u=>({value:u.slug,label:u.title||u.slug})));l.appendChild(H("Action",X("fb-trig-p-slug",r,e.slug||""),{full:!0}));break}default:break}n.kind==="event"&&!n.noOnce&&a.appendChild(ge("fb-trig-p-once",!!e.once,"Only once","Fire the first time only, rather than every time the answer swings back."));const s=a.querySelector(".fb-trig-p-finish-on");if(s){const d=()=>o.forEach(r=>{r.hidden=!s.checked});d(),s.addEventListener("change",d)}return l.children.length&&i.appendChild(l),a.children.length&&i.appendChild(a),i}function Dn(e){return e?.kindText?e.kindText:e?.kind==="event"?"once, when it becomes true":"while it is true"}const _n=(e,t=48)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,re=(e,t)=>e.find(i=>i.value===t)?.label||t;function Pn(e){if(!e)return"";const t=[],i=l=>l?`"${_n(l)}"`:"",n=()=>e.target==="listed"?e.fields?.length?e.fields.join(", "):"no fields chosen":re($t,e.target||"rest").toLowerCase();switch(e.type){case"banner":t.push(i(e.message)||"No message yet",re(Ne,e.level||"info"),re(Lt,e.position||"field-below").toLowerCase());break;case"toast":t.push(i(e.message)||"No message yet",re(Ne,e.level||"info"));break;case"hide-fields":case"disable-fields":case"require-fields":t.push(n());break;case"block-submit":t.push(i(e.message)||"the standard reason");break;case"end-form":t.push(i(e.message)||"no message"),e.finish===!1?t.push("submit disabled"):t.push(`button "${e.finishLabel||"Finish"}"`,e.record===!1?"saves nothing":"saves the answers");break;case"goto-step":t.push(Number.isFinite(e.step)?`step ${e.step}`:"no step yet");break;case"redirect":t.push(e.url||"no address yet");break;case"celebrate":t.push(re(qt,e.theme||"auto"),`${e.intensity||"medium"} intensity`);break;case"run-action":t.push(e.slug?xe.find(l=>l.slug===e.slug)?.title||e.slug:"no action chosen");break;case"notify":t.push(i(e.message)||"titled after the form",re(Ne,e.level||"info"));break;default:break}return e.once&&t.push("only once"),t.filter(Boolean).join(" \xB7 ")}function Je(e,t,{open:i=!1}={}){const n=document.createElement("div");n.className="fb-trig-action-row";const l=document.createElement("div");l.className="fb-trig-action-head",l.tabIndex=0,l.setAttribute("role","button");const a=document.createElement("span");a.className="fb-trig-chevron";const o=document.createElement("span");o.className="fb-trig-action-main";const s=document.createElement("strong"),d=document.createElement("small");d.className="fb-trig-action-summary",o.append(s,d);const r=document.createElement("span");r.className="fb-trig-kind",l.append(a,o,r,Ke(()=>n.remove(),"Remove action"));const u=document.createElement("div");u.className="fb-trig-action-body";const p=X("fb-trig-action-type",be,e.type||"banner");u.appendChild(H("Action",p,{full:!0})),u.appendChild(Mt(e,t));const m=()=>{const f=be.find(y=>y.value===p.value);s.textContent=f?.label||p.value,r.textContent=Dn(f),r.classList.toggle("fb-trig-kind--event",f?.kind==="event"),d.textContent=Pn(_t(n))},v=f=>{u.hidden=!f,n.classList.toggle("is-open",f),l.setAttribute("aria-expanded",String(f)),B(a,f?"chevron-down":"chevron-right",12)};return l.addEventListener("click",()=>v(u.hidden)),l.addEventListener("keydown",f=>{f.target!==l||f.key!=="Enter"&&f.key!==" "||(f.preventDefault(),v(u.hidden))}),p.addEventListener("change",()=>{const f=Mt({type:p.value},t);u.replaceChild(f,u.querySelector(".fb-trig-params")),m(),window.I?.scan?.()}),u.addEventListener("input",m),u.addEventListener("change",m),n.append(l,u),v(i),m(),n}function zt(e,t,i){const n=document.createElement("section");n.className=`fb-trig-sec fb-trig-sec--${e}`;const l=document.createElement("div");l.className="fb-trig-sec-head";const a=document.createElement("span");if(a.className="fb-trig-sec-title",a.textContent=t,l.appendChild(a),i){const o=document.createElement("span");o.className="fb-trig-sec-hint",o.textContent=i,l.appendChild(o)}return n.appendChild(l),n}function Ye(e,t){const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost fb-trig-add",fe(i,"plus",e,12),i.addEventListener("click",t),i}function Rt(e,t,i,n){const a=zt(e,t,e==="then"?"What happens while the answers match.":"What happens while they do not. Leave empty for nothing.");a.classList.add("fb-trig-branch"),a.dataset.branch=e;const o=document.createElement("div");return o.className="fb-trig-action-list",(i||[]).forEach(s=>o.appendChild(Je(s,n))),a.appendChild(o),a.appendChild(Ye("Add action",()=>{o.appendChild(Je({type:"banner"},n,{open:!0})),window.I?.scan?.()})),a}function Dt(e,t,i){const n=At(t,!0),l=document.createElement("div");l.className="fb-trig-card",l.dataset.triggerId=e.id||`trg-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;const a=document.createElement("div");a.className="fb-trig-card-head";const o=document.createElement("span");o.className="fb-trig-card-title",o.textContent=`Trigger ${i+1}`,a.appendChild(o);const s=ge("fb-trig-enabled",e.enabled!==!1,"Enabled","Untick to keep the trigger but switch it off.");if(a.appendChild(s),a.appendChild(Ke(()=>l.remove(),"Remove trigger")),l.appendChild(a),!n.length){const p=document.createElement("p");return p.className="fb-trig-empty",p.textContent="Give this field a name first - a trigger tests an answer, and it needs something to test.",l.appendChild(p),l}const d=zt("when","When");d.querySelector(".fb-trig-sec-head").appendChild(X("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all"));const r=document.createElement("div");r.className="fb-trig-cond-list";const u=e.when?.all||e.when?.any||[];return(u.length?u:[{}]).forEach(p=>r.appendChild(Ft(p,n))),d.appendChild(r),d.appendChild(Ye("Add condition",()=>{r.appendChild(Ft({},n)),window.I?.scan?.()})),l.appendChild(d),l.appendChild(Rt("then","Then",e.then,t)),l.appendChild(Rt("otherwise","Otherwise",e.otherwise,t)),l}function jn(e,t){const i=Array.isArray(e.triggers)?e.triggers:[],n=document.createElement("div");n.className="fb-field-triggers";const l=document.createElement("div");l.className="fb-trig-panel-head";const a=document.createElement("span");a.className="fb-trig-panel-title",a.textContent=`\u{1F3AF} Triggers${i.length?` (${i.length})`:""}`;const o=document.createElement("button");o.type="button",o.className="btn btn-xs btn-ghost",B(o,i.length?"chevron-down":"chevron-right",12);const s=document.createElement("div");s.className="fb-triggers-body",s.hidden=!i.length,l.addEventListener("click",()=>{s.hidden=!s.hidden,B(o,s.hidden?"chevron-right":"chevron-down",12)});const d=document.createElement("p");d.className="fb-trig-blurb",d.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, end the form early, notify the admins, jump to a step, or celebrate.",s.appendChild(d);const r=document.createElement("div");return r.className="fb-trig-list",i.forEach((u,p)=>r.appendChild(Dt(u,t,p))),s.appendChild(r),s.appendChild(Ye("Add trigger",()=>{const u=Dt({enabled:!0,then:[]},t,r.children.length);r.appendChild(u),u.querySelector('.fb-trig-branch[data-branch="then"] .fb-trig-action-list')?.appendChild(Je({type:"banner"},t,{open:!0})),window.I?.scan?.()})),l.appendChild(a),l.appendChild(o),n.appendChild(l),n.appendChild(s),n}function _t(e){const t=e.querySelector(".fb-trig-action-type")?.value,i=be.find(a=>a.value===t);if(!i)return null;const n={type:t},l=a=>e.querySelector(a)?.value?.trim()||"";for(const a of i.params)switch(a){case"message":n.message=l(".fb-trig-p-message");break;case"finishLabel":{const o=l(".fb-trig-p-finish");o&&(n.finishLabel=o);break}case"doneMessage":{const o=l(".fb-trig-p-done");o&&(n.doneMessage=o);break}case"finish":e.querySelector(".fb-trig-p-finish-on")?.checked||(n.finish=!1);break;case"record":e.querySelector(".fb-trig-p-record")?.checked||(n.record=!1);break;case"level":n.level=l(".fb-trig-p-level")||"info";break;case"position":n.position=l(".fb-trig-p-position")||"field-below";break;case"dismissible":n.dismissible=!!e.querySelector(".fb-trig-p-dismissible")?.checked;break;case"target":{const o=l(".fb-trig-p-target")||"rest";n.target=o,o==="listed"&&(n.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(s=>s.selected).map(s=>s.value));break}case"step":{const o=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(o)&&(n.step=o);break}case"url":n.url=l(".fb-trig-p-url");break;case"theme":n.theme=l(".fb-trig-p-theme")||"auto";break;case"intensity":n.intensity=l(".fb-trig-p-intensity")||"medium";break;case"slug":n.slug=l(".fb-trig-p-slug");break;default:break}return i.kind==="event"&&!i.noOnce&&e.querySelector(".fb-trig-p-once")?.checked&&(n.once=!0),n}function Vn(e){const t=_t(e);if(!t)return null;const i=be.find(a=>a.value===t.type),n=t.type,l=["block-submit","end-form","notify"].includes(i.value);return i.params.includes("message")&&!t.message&&!l?(delete t.message,null):(l&&!t.message&&delete t.message,n==="redirect"&&!t.url||n==="run-action"&&!t.slug?null:t)}function Gn(e){const i=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!i)return;const n=[];return i.querySelectorAll(".fb-trig-card").forEach(l=>{const a=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(p=>{const m=p.querySelector(".fb-trig-cond-field")?.value,v=p.querySelector(".fb-trig-cond-op")?.value;if(!m||!v)return null;const f=p.querySelector(".fb-trig-cond-val")?.value??"";return{field:m,operator:v,value:f}}).filter(Boolean);if(!a.length)return;const o=p=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${p}"] .fb-trig-action-row`)).map(Vn).filter(Boolean),s=o("then"),d=o("otherwise");if(!s.length&&!d.length)return;const r=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",u={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[r]:a}};s.length&&(u.then=s),d.length&&(u.otherwise=d),n.push(u)}),n.length?n:void 0}function Pt(e,t,i){const n=document.createElement("div");if(n.className="fb-field-extras",e==="chooser")n.appendChild(Un(t,i)),n.appendChild(Jn(t.options||[],i));else if(je.has(e)&&n.appendChild(el(t.options||[],i)),e==="textarea"&&n.appendChild(O([z("Rows",`fb-rows-${i}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(O([z("Min Length",`fb-minlength-${i}`,"number",t.minLength||"",""),z("Max Length",`fb-maxlength-${i}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(O([z("Min",`fb-min-${i}`,"number",t.min??"",""),z("Max",`fb-max-${i}`,"number",t.max??"","")])),e==="file"){const l=z("Most files",`fb-file-max-${i}`,"number",t.file?.maxFiles||"",`${ut} when left empty, ${De} at most`),a=l.querySelector("input");a.min="1",a.max=String(De),a.placeholder=String(ut);const o=qe("Several files",`fb-file-multiple-${i}`,!!t.multiple),s=()=>{l.hidden=!o.querySelector("input").checked};o.querySelector("input").addEventListener("change",s),s(),n.appendChild(O([l,o]))}return jt.includes(e)&&n.appendChild(Hn(t,i)),n.children.length?n:null}const jt=["string","email","tel","number","url","date","time","password","select","textarea"],Vt=[{key:"reveal",label:"Show / hide button",types:["password"],hint:"Show / hide lets the visitor see what they typed."},{key:"clear",label:"Clear button",types:["string","email","tel","url","textarea"],hint:"Clear adds an x that empties the field."},{key:"stepper",label:"- / + buttons",types:["number"],hint:"The - and + buttons step the number within its min, max and step."},{key:"counter",label:"Character counter",types:["string","textarea"],hint:"The counter shows how many characters are used, against Max Length if one is set."}];function Wn(e){return e?typeof e=="string"?{icon:"",text:e}:{icon:e.icon||"",text:e.icon?"":e.text??""}:{icon:"",text:""}}function Hn(e,t){const i=document.createElement("div");i.className="fb-addons";const n=(o,s)=>{const d=Wn(e.formConfig?.[o]),r=document.createElement("div");r.style.flex="1";const u=document.createElement("span");u.className="form-label",u.style.fontSize=".8rem",u.textContent=s;const p=Re("Icon, e.g. search",d.icon);p.input.id=`fb-${o}-icon-${t}`,p.input.setAttribute("aria-label",`${s}: icon`);const m=document.createElement("input");return m.type="text",m.className="form-input",m.id=`fb-${o}-text-${t}`,m.value=d.text,m.placeholder="or text, e.g. \xA3 or kg",m.maxLength=24,m.setAttribute("aria-label",`${s}: text`),m.style.marginTop=".35rem",p.input.addEventListener("input",()=>{p.input.value.trim()&&(m.value="")}),m.addEventListener("input",()=>{m.value.trim()&&(p.input.value="")}),r.append(u,p.el,m),r};i.appendChild(O([n("prefix","Before the field"),n("suffix","After the field")]));const l=document.createElement("p");l.className="form-hint text-muted",l.style.cssText="font-size:.73rem;margin:-.4rem 0 .75rem;",l.textContent="An icon or a short text joined to the start or end of the input, like \xA3 before a price or kg after a weight. Leave both empty for none.",i.appendChild(l);const a=Vt.filter(o=>o.types.includes(e.type));if(a.length){i.appendChild(O(a.map(s=>qe(s.label,`fb-extra-${s.key}-${t}`,!!e.formConfig?.[s.key]))));const o=document.createElement("p");o.className="form-hint text-muted",o.style.cssText="font-size:.73rem;margin:-.4rem 0 .75rem;",o.textContent=a.map(s=>s.hint).join(" "),i.appendChild(o)}return i}function Gt(e){const t=document.createElement("div");t.className="fb-chooser-section",t.style.cssText="border:1px solid var(--dm-border); border-radius:6px; margin-top:.5rem; overflow:hidden;";const i=document.createElement("div");i.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",i.textContent=e,t.appendChild(i);const n=document.createElement("div");return n.className="fb-chooser-section-body",n.style.cssText="padding:.55rem .6rem; display:flex; flex-direction:column; gap:.45rem;",t.appendChild(n),{wrap:t,body:n}}function Le(e,t,i,n,l){const a=document.createElement("div");a.style.flex="1";const o=document.createElement("label");o.htmlFor=e,o.className="form-label",o.textContent=t,o.style.fontSize=".8rem";const s=document.createElement("select");if(s.id=e,s.className="form-input",n.forEach(([d,r])=>{const u=document.createElement("option");u.value=d,u.textContent=r,String(d)===String(i)&&(u.selected=!0),s.appendChild(u)}),a.appendChild(o),a.appendChild(s),l){const d=document.createElement("p");d.className="form-hint text-muted",d.textContent=l,d.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(d)}return a}function Wt(e,t,i,n){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const o=document.createElement("input");if(o.id=e,o.type="checkbox",o.checked=!!i,a.appendChild(o),a.appendChild(document.createTextNode(" "+t)),l.appendChild(a),n){const s=document.createElement("p");s.className="form-hint text-muted",s.textContent=n,s.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(s)}return l}function Xe(e,t,i,n,l){const a=document.createElement("div");a.style.flex="1";const o=document.createElement("label");o.htmlFor=e,o.className="form-label",o.textContent=t,o.style.fontSize=".8rem",a.appendChild(o);const s=document.createElement("div");s.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const d=document.createElement("input");d.id=e,d.type="text",d.className="form-input",d.value=i||"",n&&(d.placeholder=n),d.style.flex="1";const r=document.createElement("input");r.type="color",r.title="Pick a colour",r.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const u=String(d.value).match(/^#[0-9a-fA-F]{3,8}$/);if(r.value=u?d.value:"#000000",r.addEventListener("input",()=>{d.value=r.value,d.dispatchEvent(new Event("input",{bubbles:!0}))}),s.appendChild(d),s.appendChild(r),a.appendChild(s),l){const p=document.createElement("p");p.className="form-hint text-muted",p.textContent=l,p.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(p)}return a}function Un(e,t){const i=document.createElement("div");i.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=Gt("Layout");n.body.appendChild(O([Le(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),Wt(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(O([Le(`fb-chooser-density-${t}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),z("Columns",`fb-chooser-columns-${t}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),i.appendChild(n.wrap);const l=Gt("Visual");return l.body.appendChild(O([Xe(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),Le(`fb-chooser-accent-style-${t}`,"Accent style",e.accentStyle||"border",[["border","Border (default)"],["solid","Solid"],["glow","Glow"],["overlay","Overlay"],["underline","Underline"]],"Visual treatment of the selected state.")])),l.body.appendChild(O([Wt(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),Xe(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(O([Le(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),Xe(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),i.appendChild(l.wrap),i}function Kn(e,t,i,n){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(i),l.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const a=document.createElement("div");a.style.cssText="display:flex; gap:.4rem; align-items:center;";const o=document.createElement("div");o.style.cssText="display:flex; flex-direction:column; gap:1px;";const s=document.createElement("button");s.type="button",s.className="btn btn-xs btn-ghost",s.title="Move up",B(s,"arrow-up"),s.addEventListener("click",_=>{_.preventDefault(),Ht(t,i,-1,n)});const d=document.createElement("button");d.type="button",d.className="btn btn-xs btn-ghost",d.title="Move down",B(d,"arrow-down"),d.addEventListener("click",_=>{_.preventDefault(),Ht(t,i,1,n)}),o.appendChild(s),o.appendChild(d),a.appendChild(o);const r=document.createElement("input");r.type="text",r.className="form-input fb-chooser-opt-value",r.placeholder="value",r.value=e.value||"",r.style.flex="1",a.appendChild(r);const u=document.createElement("input");u.type="text",u.className="form-input fb-chooser-opt-label",u.placeholder="label (visible to users)",u.value=e.label||"",u.style.flex="2",a.appendChild(u);const p=document.createElement("button");p.type="button",p.className="btn btn-xs btn-ghost",p.style.cssText="line-height:1;opacity:.6;",p.title="Remove option",B(p,"x"),p.addEventListener("click",_=>{_.preventDefault(),Qn(t,i,n)}),a.appendChild(p),l.appendChild(a);const m=document.createElement("div");m.style.cssText="display:flex; gap:.4rem;";const v=Re("icon name (optional)",e.icon||"");v.input.classList.add("fb-chooser-opt-icon"),v.el.style.flex="1",m.appendChild(v.el);const f=document.createElement("input");f.type="text",f.className="form-input fb-chooser-opt-description",f.placeholder="description (card + comfortable only)",f.value=e.description||"",f.style.flex="2",m.appendChild(f),l.appendChild(m);const y=document.createElement("div");y.style.cssText="display:flex; gap:.4rem;";const w=document.createElement("input");w.type="text",w.className="form-input fb-chooser-opt-tooltip",w.placeholder="tooltip (hover hint)",w.value=e.tooltip||"",w.style.flex="2",y.appendChild(w);const x=document.createElement("input");x.type="text",x.className="form-input fb-chooser-opt-badge-text",x.placeholder="badge text",x.value=e.badge?.text||"",x.style.flex="1",y.appendChild(x);const b=document.createElement("select");b.className="form-input fb-chooser-opt-badge-type",b.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([_,K])=>{const G=document.createElement("option");G.value=_,G.textContent=K,(e.badge?.type||"")===_&&(G.selected=!0),b.appendChild(G)}),y.appendChild(b),l.appendChild(y);const C=document.createElement("div");C.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const L=document.createElement("label");L.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const q=document.createElement("input");q.type="checkbox",q.className="fb-chooser-opt-recommended",q.checked=!!e.recommended,L.appendChild(q),L.appendChild(document.createTextNode(" Recommended")),C.appendChild(L);const D=document.createElement("label");D.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const V=document.createElement("input");return V.type="checkbox",V.className="fb-chooser-opt-disabled",V.checked=!!e.disabled,D.appendChild(V),D.appendChild(document.createTextNode(" Disabled")),C.appendChild(D),l.appendChild(C),l}function Jn(e,t){const i=document.createElement("div");i.style.cssText="margin-top:.5rem;";const n=document.createElement("div");n.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:.4rem;";const l=document.createElement("p");l.textContent="Options",l.style.cssText="font-size:.85rem;font-weight:600;margin:0;",n.appendChild(l);const a=document.createElement("button");a.type="button",a.className="btn btn-xs btn-ghost",fe(a,"plus","Add option"),n.appendChild(a),i.appendChild(n);const o=document.createElement("div");o.className="fb-chooser-options-list",o.id=`fb-chooser-options-${t}`,o.style.cssText="display:flex; flex-direction:column; gap:.4rem;",i.appendChild(o);const s=()=>{o.replaceChildren();const d=Yn(t);(d.length?d:e||[]).forEach((u,p)=>{o.appendChild(Kn(u,t,p,s))})};return a.addEventListener("click",d=>{d.preventDefault(),Xn(t,s)}),s(),i}function Yn(e){const t=T[e];return!t||!Array.isArray(t.options)?[]:t.options}function Qe(e){return T[e]?(Array.isArray(T[e].options)||(T[e].options=[]),T[e].options):[]}function Xn(e,t){$e(e),Qe(e).push({value:"new",label:"New option"}),t()}function Qn(e,t,i){$e(e),Qe(e).splice(t,1),i()}function Ht(e,t,i,n){$e(e);const l=Qe(e),a=t+i;if(a<0||a>=l.length)return;const[o]=l.splice(t,1);l.splice(a,0,o),n()}function $e(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const i=t.querySelectorAll(".fb-chooser-option-row"),n=[];i.forEach(l=>{const a={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},o=l.querySelector(".fb-chooser-opt-icon")?.value.trim();o&&(a.icon=o);const s=l.querySelector(".fb-chooser-opt-description")?.value.trim();s&&(a.description=s);const d=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();d&&(a.tooltip=d);const r=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),u=l.querySelector(".fb-chooser-opt-badge-type")?.value;(r||u)&&(a.badge={},r&&(a.badge.text=r),u&&(a.badge.type=u)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(a.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(a.disabled=!0),n.push(a)}),T[e]&&(T[e].options=n)}function O(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(i=>{i&&t.appendChild(i)}),t}function z(e,t,i,n,l){const a=document.createElement("div");a.style.flex="1";const o=document.createElement("label");o.htmlFor=t,o.className="form-label",o.textContent=e,o.style.fontSize=".8rem";const s=document.createElement("input");if(s.id=t,s.type=i||"text",s.className="form-input",s.value=n??"",a.appendChild(o),a.appendChild(s),l){const d=document.createElement("p");d.className="form-hint text-muted",d.textContent=l,d.style.cssText="font-size:.73rem;margin-top:.35rem;",a.appendChild(d)}return a}function Zn(e,t,i,n){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.htmlFor=t,a.className="form-label",a.textContent=e,a.style.fontSize=".8rem";const o=document.createElement("select");return o.id=t,o.className="form-select",i.forEach(s=>{const d=document.createElement("option");d.value=s.value,d.textContent=s.label,s.value===n&&(d.selected=!0),o.appendChild(d)}),l.appendChild(a),l.appendChild(o),l}function qe(e,t,i){const n=document.createElement("div");n.style.cssText="flex:0;min-width:80px;display:flex;flex-direction:column;justify-content:flex-end;";const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;font-size:.8rem;white-space:nowrap;";const a=document.createElement("input");return a.id=t,a.type="checkbox",a.checked=i,l.appendChild(a),l.appendChild(document.createTextNode(e)),n.appendChild(l),n}function el(e,t){const i=document.createElement("div");i.style.cssText="margin-top:.4rem;";const n=document.createElement("p");n.textContent="Options (one per line: value or value:Label)",n.style.cssText="font-size:.8rem;font-weight:600;margin-bottom:.3rem;";const l=document.createElement("textarea");return l.id=`fb-options-${t}`,l.className="form-input",l.rows=4,l.placeholder=`yes:Yes
5
+ `),n.appendChild(u),n.appendChild(p),n}function _n(e,t){const s=e.logic||{},n=T.filter((p,m)=>m!==t&&p.type!=="page-break"&&p.type!=="spacer"),a=document.createElement("div");a.className="fb-field-logic",a.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const i=document.createElement("div");i.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const o=document.createElement("span");o.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",o.textContent="\u26A1 Conditional Logic";const l=At(s),d=document.createElement("button");d.type="button",d.className="btn btn-xs btn-ghost",O(d,l?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-logic-body",r.style.cssText="padding:.25rem 0 .25rem;"+(l?"":"display:none;"),i.addEventListener("click",()=>{const p=r.style.display==="none";r.style.display=p?"":"none",O(d,p?"chevron-down":"chevron-right",12)}),i.appendChild(o),i.appendChild(d),a.appendChild(i),r.appendChild(On(s.visibility||{},t,n)),r.appendChild(Rn(s.requirement||{},t,n)),r.appendChild(Dn(s.validation||[],t,n));const u=document.getElementById(`fb-type-${t}`)?.value||e.type;return Ue.has(u)&&r.appendChild(zn(s.cascade||{},t,n)),a.appendChild(r),a}const xe=[{value:"banner",label:"Show a banner",kind:"state",params:["message","level","position","dismissible"],placeholder:"e.g. You must be 18 or over to continue."},{value:"toast",label:"Show a toast",kind:"event",params:["message","level"],placeholder:"e.g. Thanks - carry on."},{value:"hide-fields",label:"Hide fields",kind:"state",params:["target"]},{value:"disable-fields",label:"Disable fields",kind:"state",params:["target"]},{value:"require-fields",label:"Make fields required",kind:"state",params:["target"]},{value:"block-submit",label:"Block submission",kind:"state",params:["message"],messageLabel:"Reason, shown under the button",placeholder:'Blank: "This form cannot be submitted yet."'},{value:"end-form",label:"End the form here",kind:"state",params:["message","finish","finishLabel","doneMessage","record"],messageLabel:"Message shown in place of the rest",placeholder:"e.g. Sorry - you must be 18 or over to apply."},{value:"goto-step",label:"Jump to a wizard step",kind:"event",params:["step"]},{value:"redirect",label:"Redirect after submit",kind:"event",params:["url"]},{value:"celebrate",label:"Celebrate",kind:"event",params:["theme","intensity"]},{value:"run-action",label:"Run a CMS action",kind:"event",params:["slug"]},{value:"notify",label:"Notify the admins",kind:"event",params:["message","level"],messageLabel:"Notification title",placeholder:"Blank: titled after the form",noOnce:!0,kindText:"when the form is submitted"}],Ae=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],It=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],Mt=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],Ot=[{value:"auto",label:"Whatever is in season"},{value:"christmas",label:"Christmas"},{value:"halloween",label:"Halloween"},{value:"valentines",label:"Valentine's Day"},{value:"guy-fawkes",label:"Guy Fawkes Night"},{value:"st-patricks",label:"St Patrick's Day"},{value:"st-andrews",label:"St Andrew's Day"},{value:"st-davids",label:"St David's Day"},{value:"st-georges",label:"St George's Day"}];function Rt(e,t=!1){const s=(o,l)=>({value:o.name,label:`${o.label||o.name}${l?" (this field)":""}`,multi:Je(o)}),n=o=>o&&o.type!=="page-break"&&o.type!=="spacer"&&o.name,a=T.filter((o,l)=>l!==e&&n(o)).map(o=>s(o,!1)),i=T[e];return t&&n(i)?[s(i,!0),...a]:a}function Q(e,t,s){const n=document.createElement("select");return n.className=`form-select ${e}`,t.forEach(a=>{const i=document.createElement("option");i.value=a.value,i.textContent=a.label,a.value===s&&(i.selected=!0),n.appendChild(i)}),n}function re(e,t,s){const n=document.createElement("input");return n.type="text",n.className=`form-input ${e}`,n.value=t==null?"":String(t),s&&(n.placeholder=s),n}function Xe(e,t){const s=document.createElement("button");return s.type="button",s.className="btn btn-xs btn-ghost fb-trig-remove",t&&(s.title=t,s.setAttribute("aria-label",t)),O(s,"x"),s.addEventListener("click",n=>{n.stopPropagation(),e()}),s}function L(e,t,{full:s=!1,hint:n="",help:a=""}={}){const i=document.createElement("label");i.className=`fb-trig-f${s?" fb-trig-f--full":""}`,i.style.flex="1";const o=document.createElement("span");if(o.className="fb-trig-f-label",o.textContent=e,(a||n||ye[e])&&o.appendChild(A(a||n||ye[e],e)),i.appendChild(o),i.appendChild(t),n){const l=document.createElement("span");l.className="fb-trig-f-hint",l.textContent=n,i.appendChild(l)}return i}function we(e,t,s,n){const a=document.createElement("label");a.className="fb-trig-check";const i=document.createElement("input");return i.type="checkbox",i.className=`form-check ${e}`,i.checked=!!t,a.appendChild(i),a.appendChild(document.createTextNode(s)),a.appendChild(A(n||"Allow the visitor to close this banner while the condition holds. It can appear again when the condition becomes true again.",s)),a}function Dt(e,t){const s=document.createElement("div");s.className="fb-trig-cond-row";const n=Q("fb-trig-cond-field",t,e?.field),a=Q("fb-trig-cond-op",Ne,e?.operator),i=re("fb-trig-cond-val",e?.value,"value"),o=L("Value",i,{help:"Compare with the stored value. For one of, separate values with commas; for regex, enter a regular expression."}),l=()=>{const r=t.find(u=>u.value===n.value);Array.from(a.options).forEach(u=>{const p=Ne.find(m=>m.value===u.value);u.textContent=r?.multi&&Ft[u.value]||p?.label||u.value})},d=()=>{o.hidden=Ye.has(a.value)};return l(),d(),n.addEventListener("change",l),a.addEventListener("change",d),s.appendChild(L("Field",n,{help:"The answer to test, including this field or another named field."})),s.appendChild(L("Comparison",a,{help:"How to compare the answer. Multi-choice fields test their selected values. Empty and not empty need no comparison value."})),s.appendChild(o),s.appendChild(Xe(()=>s.remove(),"Remove condition")),s}const zt=["banner","toast","block-submit","end-form"],_t=["password","file","image","signature"],Pn="Put an answer in with {{field_name}} - e.g. Hello {{name}}. Pick one from Insert field.";function jn(){try{V()}catch{}return T.filter(e=>e&&e.name&&e.type!=="page-break"&&e.type!=="spacer"&&!_t.includes(e.type))}function Pt(e,t,s){const n=re(e,t,s),a=document.createElement("span");a.className="fb-token-row";const i=document.createElement("select");i.className="form-input fb-token-pick",i.title="Insert an answer into the message",i.setAttribute("aria-label","Insert a field's answer into the message");const o=()=>{i.replaceChildren(new Option("Insert field",""));for(const l of jn())i.appendChild(new Option(`${l.label||l.name} ({{${l.name}}})`,l.name))};return o(),i.addEventListener("focus",o),i.addEventListener("mousedown",o),i.addEventListener("change",()=>{const l=i.value;if(i.value="",!l)return;const d=`{{${l}}}`,r=n.selectionStart??n.value.length,u=n.selectionEnd??r;n.value=n.value.slice(0,r)+d+n.value.slice(u),n.focus(),n.setSelectionRange(r+d.length,r+d.length),n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}),a.append(n,i),a}function Hn(e){const t=window.FormLogicEngine;if(!t?.triggerTokens)return[];const s=new Map((e||[]).filter(a=>a&&a.name).map(a=>[a.name,a])),n=new Set;for(const a of e||[])for(const i of a?.triggers||[])for(const o of[...i.then||[],...i.otherwise||[]])if(zt.includes(o?.type))for(const l of[...t.triggerTokens(o.message),...t.triggerTokens(o.doneMessage)]){const d=s.get(l);(!d||_t.includes(d.type))&&n.add(l)}return[...n]}function jt(e,t){const s=document.createElement("div");s.className="fb-trig-params";const n=xe.find(d=>d.value===(e.type||"banner"));if(!n)return s;const a=document.createElement("div");a.className="fb-trig-grid";const i=document.createElement("div");i.className="fb-trig-opts";const o=[];for(const d of n.params)switch(d){case"message":a.appendChild(zt.includes(n.value)?L(n.messageLabel||"Message",Pt("fb-trig-p-message",e.message,n.placeholder||""),{full:!0,hint:Pn,help:ye[n.messageLabel||"Message"]}):L(n.messageLabel||"Message",re("fb-trig-p-message",e.message,n.placeholder||""),{full:!0}));break;case"finish":i.appendChild(we("fb-trig-p-finish-on",e.finish!==!1,"Let the visitor finish (send the answers given so far)",'Untick to stop the form dead: the submit button is disabled and nothing is sent, so nothing is saved and "Notify the admins" cannot fire.'));break;case"finishLabel":{const r=L("Button text",re("fb-trig-p-finish",e.finishLabel,"Finish"));o.push(r),a.appendChild(r);break}case"doneMessage":{const r=L("Closing message",Pt("fb-trig-p-done",e.doneMessage,"Blank: the form's own success message"));o.push(r),a.appendChild(r);break}case"record":{const r=we("fb-trig-p-record",e.record!==!1,"Save the answers given so far",`Untick to keep nothing: no submission is stored and the form's email, webhook and actions do not run. A "Notify the admins" action still fires.`);o.push(r),i.appendChild(r);break}case"level":a.appendChild(L(n.value==="notify"?"Severity":"Level",Q("fb-trig-p-level",Ae,e.level||"info")));break;case"position":a.appendChild(L("Where",Q("fb-trig-p-position",It,e.position||"field-below")));break;case"dismissible":i.appendChild(we("fb-trig-p-dismissible",e.dismissible!==!1,"The visitor can dismiss it"));break;case"target":{const r=Q("fb-trig-p-target",Mt,e.target||(e.fields?.length?"listed":"rest")),u=document.createElement("select");u.className="form-select fb-trig-p-fields",u.multiple=!0,u.size=4;const p=new Set(e.fields||[]);Rt(t).forEach(f=>{const y=document.createElement("option");y.value=f.value,y.textContent=f.label,p.has(f.value)&&(y.selected=!0),u.appendChild(y)});const m=L("Fields",u,{hint:"Ctrl/Cmd-click to pick several",help:ye.Fields}),v=()=>{m.hidden=r.value!=="listed"};v(),r.addEventListener("change",v),a.appendChild(L("Which fields",r)),a.appendChild(m);break}case"step":{const r=re("fb-trig-p-step",e.step,"0");r.type="number",r.min="0",a.appendChild(L("Step",r,{hint:"Counting from 0",help:ye.Step}));break}case"url":a.appendChild(L("Send them to",re("fb-trig-p-url",e.url,"/thank-you"),{full:!0}));break;case"theme":a.appendChild(L("Theme",Q("fb-trig-p-theme",Ot,e.theme||"auto")));break;case"intensity":a.appendChild(L("Intensity",Q("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium")));break;case"slug":{const r=[{value:"",label:ke.length?"Choose an action":"No actions available"}].concat(ke.map(u=>({value:u.slug,label:u.title||u.slug})));a.appendChild(L("Action",Q("fb-trig-p-slug",r,e.slug||""),{full:!0,help:"The CMS action to run after a matching submission is saved. Choose an action defined under Data > Actions. Requires Pro with MongoDB."}));break}default:break}n.kind==="event"&&!n.noOnce&&i.appendChild(we("fb-trig-p-once",!!e.once,"Only once","Fire the first time only, rather than every time the answer swings back."));const l=i.querySelector(".fb-trig-p-finish-on");if(l){const d=()=>o.forEach(r=>{r.hidden=!l.checked});d(),l.addEventListener("change",d)}return a.children.length&&s.appendChild(a),i.children.length&&s.appendChild(i),s}function Vn(e){return e?.kindText?e.kindText:e?.kind==="event"?"once, when it becomes true":"while it is true"}const Wn=(e,t=48)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,ce=(e,t)=>e.find(s=>s.value===t)?.label||t;function Un(e){if(!e)return"";const t=[],s=a=>a?`"${Wn(a)}"`:"",n=()=>e.target==="listed"?e.fields?.length?e.fields.join(", "):"no fields chosen":ce(Mt,e.target||"rest").toLowerCase();switch(e.type){case"banner":t.push(s(e.message)||"No message yet",ce(Ae,e.level||"info"),ce(It,e.position||"field-below").toLowerCase());break;case"toast":t.push(s(e.message)||"No message yet",ce(Ae,e.level||"info"));break;case"hide-fields":case"disable-fields":case"require-fields":t.push(n());break;case"block-submit":t.push(s(e.message)||"the standard reason");break;case"end-form":t.push(s(e.message)||"no message"),e.finish===!1?t.push("submit disabled"):t.push(`button "${e.finishLabel||"Finish"}"`,e.record===!1?"saves nothing":"saves the answers");break;case"goto-step":t.push(Number.isFinite(e.step)?`step ${e.step}`:"no step yet");break;case"redirect":t.push(e.url||"no address yet");break;case"celebrate":t.push(ce(Ot,e.theme||"auto"),`${e.intensity||"medium"} intensity`);break;case"run-action":t.push(e.slug?ke.find(a=>a.slug===e.slug)?.title||e.slug:"no action chosen");break;case"notify":t.push(s(e.message)||"titled after the form",ce(Ae,e.level||"info"));break;default:break}return e.once&&t.push("only once"),t.filter(Boolean).join(" \xB7 ")}function Qe(e,t,{open:s=!1}={}){const n=document.createElement("div");n.className="fb-trig-action-row";const a=document.createElement("div");a.className="fb-trig-action-head",a.tabIndex=0,a.setAttribute("role","button");const i=document.createElement("span");i.className="fb-trig-chevron";const o=document.createElement("span");o.className="fb-trig-action-main";const l=document.createElement("strong"),d=document.createElement("small");d.className="fb-trig-action-summary",o.append(l,d);const r=document.createElement("span");r.className="fb-trig-kind",a.append(i,o,r,Xe(()=>n.remove(),"Remove action"));const u=document.createElement("div");u.className="fb-trig-action-body";const p=Q("fb-trig-action-type",xe,e.type||"banner");u.appendChild(L("Action",p,{full:!0})),u.appendChild(jt(e,t));const m=()=>{const f=xe.find(y=>y.value===p.value);l.textContent=f?.label||p.value,r.textContent=Vn(f),r.classList.toggle("fb-trig-kind--event",f?.kind==="event"),d.textContent=Un(Ut(n))},v=f=>{u.hidden=!f,n.classList.toggle("is-open",f),a.setAttribute("aria-expanded",String(f)),O(i,f?"chevron-down":"chevron-right",12)};return a.addEventListener("click",()=>v(u.hidden)),a.addEventListener("keydown",f=>{f.target!==a||f.key!=="Enter"&&f.key!==" "||(f.preventDefault(),v(u.hidden))}),p.addEventListener("change",()=>{const f=jt({type:p.value},t);u.replaceChild(f,u.querySelector(".fb-trig-params")),m(),window.I?.scan?.()}),u.addEventListener("input",m),u.addEventListener("change",m),n.append(a,u),v(s),m(),n}function Ht(e,t,s){const n=document.createElement("section");n.className=`fb-trig-sec fb-trig-sec--${e}`;const a=document.createElement("div");a.className="fb-trig-sec-head";const i=document.createElement("span");if(i.className="fb-trig-sec-title",i.textContent=t,i.appendChild(A({When:"Choose the answers to test. All requires every condition to match; Any requires at least one. Compare stored option values, not their display labels.",Then:"Actions applied when the conditions match.",Otherwise:"Optional actions applied when the conditions do not match. Leave empty to do nothing in this branch."}[t],t)),a.appendChild(i),s){const o=document.createElement("span");o.className="fb-trig-sec-hint",o.textContent=s,a.appendChild(o)}return n.appendChild(a),n}function Ze(e,t){const s=document.createElement("button");return s.type="button",s.className="btn btn-xs btn-ghost fb-trig-add",be(s,"plus",e,12),s.addEventListener("click",t),s}function Vt(e,t,s,n){const i=Ht(e,t,e==="then"?"What happens while the answers match.":"What happens while they do not. Leave empty for nothing.");i.classList.add("fb-trig-branch"),i.dataset.branch=e;const o=document.createElement("div");return o.className="fb-trig-action-list",(s||[]).forEach(l=>o.appendChild(Qe(l,n))),i.appendChild(o),i.appendChild(Ze("Add action",()=>{o.appendChild(Qe({type:"banner"},n,{open:!0})),window.I?.scan?.()})),i}function Wt(e,t,s){const n=Rt(t,!0),a=document.createElement("div");a.className="fb-trig-card",a.dataset.triggerId=e.id||`trg-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;const i=document.createElement("div");i.className="fb-trig-card-head";const o=document.createElement("span");o.className="fb-trig-card-title",o.textContent=`Trigger ${s+1}`,i.appendChild(o);const l=we("fb-trig-enabled",e.enabled!==!1,"Enabled","Untick to keep the trigger but switch it off.");if(i.appendChild(l),i.appendChild(Xe(()=>a.remove(),"Remove trigger")),a.appendChild(i),!n.length){const p=document.createElement("p");return p.className="fb-trig-empty",p.textContent="Give this field a name first - a trigger tests an answer, and it needs something to test.",a.appendChild(p),a}const d=Ht("when","When");d.querySelector(".fb-trig-sec-head").appendChild(Q("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all"));const r=document.createElement("div");r.className="fb-trig-cond-list";const u=e.when?.all||e.when?.any||[];return(u.length?u:[{}]).forEach(p=>r.appendChild(Dt(p,n))),d.appendChild(r),d.appendChild(Ze("Add condition",()=>{r.appendChild(Dt({},n)),window.I?.scan?.()})),a.appendChild(d),a.appendChild(Vt("then","Then",e.then,t)),a.appendChild(Vt("otherwise","Otherwise",e.otherwise,t)),a}function Gn(e,t){const s=Array.isArray(e.triggers)?e.triggers:[],n=document.createElement("div");n.className="fb-field-triggers";const a=document.createElement("div");a.className="fb-trig-panel-head";const i=document.createElement("span");i.className="fb-trig-panel-title",i.textContent=`\u{1F3AF} Triggers${s.length?` (${s.length})`:""}`,i.appendChild(A("Triggers test answers and choose a Then or Otherwise branch. Add conditions and actions below. Enabled switches a trigger on without deleting its settings.","Triggers"));const o=document.createElement("button");o.type="button",o.className="btn btn-xs btn-ghost",O(o,s.length?"chevron-down":"chevron-right",12);const l=document.createElement("div");l.className="fb-triggers-body",l.hidden=!s.length,a.addEventListener("click",()=>{l.hidden=!l.hidden,O(o,l.hidden?"chevron-right":"chevron-down",12)});const d=document.createElement("p");d.className="fb-trig-blurb",d.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, end the form early, notify the admins, jump to a step, or celebrate.",l.appendChild(d);const r=document.createElement("div");return r.className="fb-trig-list",s.forEach((u,p)=>r.appendChild(Wt(u,t,p))),l.appendChild(r),l.appendChild(Ze("Add trigger",()=>{const u=Wt({enabled:!0,then:[]},t,r.children.length);r.appendChild(u),u.querySelector('.fb-trig-branch[data-branch="then"] .fb-trig-action-list')?.appendChild(Qe({type:"banner"},t,{open:!0})),window.I?.scan?.()})),a.appendChild(i),a.appendChild(o),n.appendChild(a),n.appendChild(l),n}function Ut(e){const t=e.querySelector(".fb-trig-action-type")?.value,s=xe.find(i=>i.value===t);if(!s)return null;const n={type:t},a=i=>e.querySelector(i)?.value?.trim()||"";for(const i of s.params)switch(i){case"message":n.message=a(".fb-trig-p-message");break;case"finishLabel":{const o=a(".fb-trig-p-finish");o&&(n.finishLabel=o);break}case"doneMessage":{const o=a(".fb-trig-p-done");o&&(n.doneMessage=o);break}case"finish":e.querySelector(".fb-trig-p-finish-on")?.checked||(n.finish=!1);break;case"record":e.querySelector(".fb-trig-p-record")?.checked||(n.record=!1);break;case"level":n.level=a(".fb-trig-p-level")||"info";break;case"position":n.position=a(".fb-trig-p-position")||"field-below";break;case"dismissible":n.dismissible=!!e.querySelector(".fb-trig-p-dismissible")?.checked;break;case"target":{const o=a(".fb-trig-p-target")||"rest";n.target=o,o==="listed"&&(n.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(l=>l.selected).map(l=>l.value));break}case"step":{const o=parseInt(a(".fb-trig-p-step"),10);Number.isFinite(o)&&(n.step=o);break}case"url":n.url=a(".fb-trig-p-url");break;case"theme":n.theme=a(".fb-trig-p-theme")||"auto";break;case"intensity":n.intensity=a(".fb-trig-p-intensity")||"medium";break;case"slug":n.slug=a(".fb-trig-p-slug");break;default:break}return s.kind==="event"&&!s.noOnce&&e.querySelector(".fb-trig-p-once")?.checked&&(n.once=!0),n}function Kn(e){const t=Ut(e);if(!t)return null;const s=xe.find(i=>i.value===t.type),n=t.type,a=["block-submit","end-form","notify"].includes(s.value);return s.params.includes("message")&&!t.message&&!a?(delete t.message,null):(a&&!t.message&&delete t.message,n==="redirect"&&!t.url||n==="run-action"&&!t.slug?null:t)}function Yn(e){const s=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!s)return;const n=[];return s.querySelectorAll(".fb-trig-card").forEach(a=>{const i=Array.from(a.querySelectorAll(".fb-trig-cond-row")).map(p=>{const m=p.querySelector(".fb-trig-cond-field")?.value,v=p.querySelector(".fb-trig-cond-op")?.value;if(!m||!v)return null;const f=p.querySelector(".fb-trig-cond-val")?.value??"";return{field:m,operator:v,value:f}}).filter(Boolean);if(!i.length)return;const o=p=>Array.from(a.querySelectorAll(`.fb-trig-branch[data-branch="${p}"] .fb-trig-action-row`)).map(Kn).filter(Boolean),l=o("then"),d=o("otherwise");if(!l.length&&!d.length)return;const r=a.querySelector(".fb-trig-match")?.value==="any"?"any":"all",u={id:a.dataset.triggerId,enabled:!!a.querySelector(".fb-trig-enabled")?.checked,when:{[r]:i}};l.length&&(u.then=l),d.length&&(u.otherwise=d),n.push(u)}),n.length?n:void 0}function Gt(e,t,s){const n=document.createElement("div");if(n.className="fb-field-extras",e==="chooser")n.appendChild(Qn(t,s)),n.appendChild(ea(t.options||[],s));else if(Ue.has(e)&&n.appendChild(sa(t.options||[],s)),e==="textarea"&&n.appendChild(z([P("Rows",`fb-rows-${s}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(z([P("Min Length",`fb-minlength-${s}`,"number",t.minLength||"",""),P("Max Length",`fb-maxlength-${s}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(z([P("Min",`fb-min-${s}`,"number",t.min??"",""),P("Max",`fb-max-${s}`,"number",t.max??"","")])),e==="file"){const a=P("Most files",`fb-file-max-${s}`,"number",t.file?.maxFiles||"",`${gt} when left empty, ${He} at most`),i=a.querySelector("input");i.min="1",i.max=String(He),i.placeholder=String(gt);const o=Ie("Several files",`fb-file-multiple-${s}`,!!t.multiple),l=()=>{a.hidden=!o.querySelector("input").checked};o.querySelector("input").addEventListener("change",l),l(),n.appendChild(z([a,o]))}return Kt.includes(e)&&n.appendChild(Xn(t,s)),n.children.length?n:null}const Kt=["string","email","tel","number","url","date","time","password","select","textarea"],et=[{key:"reveal",label:"Show / hide button",types:["password"],hint:"Show / hide lets the visitor see what they typed."},{key:"clear",label:"Clear button",types:["string","email","tel","url","textarea"],hint:"Clear adds an x that empties the field."},{key:"stepper",label:"- / + buttons",types:["number"],hint:"The - and + buttons step the number within its min, max and step."},{key:"counter",label:"Character counter",types:["string","textarea"],hint:"The counter shows how many characters are used, against Max Length if one is set."}];function Jn(e){return e?typeof e=="string"?{icon:"",text:e}:{icon:e.icon||"",text:e.icon?"":e.text??""}:{icon:"",text:""}}function Xn(e,t){const s=document.createElement("div");s.className="fb-addons";const n=(o,l)=>{const d=Jn(e.formConfig?.[o]),r=document.createElement("div");r.style.flex="1";const u=document.createElement("span");u.className="form-label",u.style.fontSize=".8rem",u.textContent=l,u.appendChild(A("An icon or short text joined to this side of the input, such as a currency symbol or unit. Choose an icon or enter text; leave both blank for none.",l));const p=je("Icon, e.g. search",d.icon);p.input.id=`fb-${o}-icon-${t}`,p.input.setAttribute("aria-label",`${l}: icon`);const m=document.createElement("input");return m.type="text",m.className="form-input",m.id=`fb-${o}-text-${t}`,m.value=d.text,m.placeholder="or text, e.g. \xA3 or kg",m.maxLength=24,m.setAttribute("aria-label",`${l}: text`),m.style.marginTop=".35rem",p.input.addEventListener("input",()=>{p.input.value.trim()&&(m.value="")}),m.addEventListener("input",()=>{m.value.trim()&&(p.input.value="")}),r.append(u,p.el,m),r};s.appendChild(z([n("prefix","Before the field"),n("suffix","After the field")]));const a=document.createElement("p");a.className="form-hint text-muted",a.style.cssText="font-size:.73rem;margin:-.4rem 0 .75rem;",a.textContent="An icon or a short text joined to the start or end of the input, like \xA3 before a price or kg after a weight. Leave both empty for none.",s.appendChild(a);const i=et.filter(o=>o.types.includes(e.type));if(i.length){s.appendChild(z(i.map(l=>Ie(l.label,`fb-extra-${l.key}-${t}`,!!e.formConfig?.[l.key]))));const o=document.createElement("p");o.className="form-hint text-muted",o.style.cssText="font-size:.73rem;margin:-.4rem 0 .75rem;",o.textContent=i.map(l=>l.hint).join(" "),s.appendChild(o)}return s}function Yt(e){const t=document.createElement("div");t.className="fb-chooser-section",t.style.cssText="border:1px solid var(--dm-border); border-radius:6px; margin-top:.5rem; overflow:hidden;";const s=document.createElement("div");s.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",s.textContent=e,t.appendChild(s);const n=document.createElement("div");return n.className="fb-chooser-section-body",n.style.cssText="padding:.55rem .6rem; display:flex; flex-direction:column; gap:.45rem;",t.appendChild(n),{wrap:t,body:n}}function Fe(e,t,s,n,a){const i=document.createElement("div");i.style.flex="1";const o=document.createElement("label");o.htmlFor=e,o.className="form-label",o.textContent=t,a&&o.appendChild(A(a,t)),o.style.fontSize=".8rem";const l=document.createElement("select");if(l.id=e,l.className="form-input",n.forEach(([d,r])=>{const u=document.createElement("option");u.value=d,u.textContent=r,String(d)===String(s)&&(u.selected=!0),l.appendChild(u)}),i.appendChild(o),i.appendChild(l),a){const d=document.createElement("p");d.className="form-hint text-muted",d.textContent=a,d.style.cssText="font-size:.72rem;margin-top:.2rem;",i.appendChild(d)}return i}function Jt(e,t,s,n){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const o=document.createElement("input");if(o.id=e,o.type="checkbox",o.checked=!!s,i.appendChild(o),i.appendChild(document.createTextNode(" "+t)),n&&i.appendChild(A(n,t)),a.appendChild(i),n){const l=document.createElement("p");l.className="form-hint text-muted",l.textContent=n,l.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(l)}return a}function tt(e,t,s,n,a){const i=document.createElement("div");i.style.flex="1";const o=document.createElement("label");o.htmlFor=e,o.className="form-label",o.textContent=t,a&&o.appendChild(A(a,t)),o.style.fontSize=".8rem",i.appendChild(o);const l=document.createElement("div");l.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const d=document.createElement("input");d.id=e,d.type="text",d.className="form-input",d.value=s||"",n&&(d.placeholder=n),d.style.flex="1";const r=document.createElement("input");r.type="color",r.title="Pick a colour",r.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const u=String(d.value).match(/^#[0-9a-fA-F]{3,8}$/);if(r.value=u?d.value:"#000000",r.addEventListener("input",()=>{d.value=r.value,d.dispatchEvent(new Event("input",{bubbles:!0}))}),l.appendChild(d),l.appendChild(r),i.appendChild(l),a){const p=document.createElement("p");p.className="form-hint text-muted",p.textContent=a,p.style.cssText="font-size:.72rem;margin-top:.2rem;",i.appendChild(p)}return i}function Qn(e,t){const s=document.createElement("div");s.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=Yt("Layout");n.body.appendChild(z([Fe(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),Jt(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(z([Fe(`fb-chooser-density-${t}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),P("Columns",`fb-chooser-columns-${t}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),s.appendChild(n.wrap);const a=Yt("Visual");return a.body.appendChild(z([tt(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),Fe(`fb-chooser-accent-style-${t}`,"Accent style",e.accentStyle||"border",[["border","Border (default)"],["solid","Solid"],["glow","Glow"],["overlay","Overlay"],["underline","Underline"]],"Visual treatment of the selected state.")])),a.body.appendChild(z([Jt(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),tt(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),a.body.appendChild(z([Fe(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),tt(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),s.appendChild(a.wrap),s}function Zn(e,t,s,n){const a=document.createElement("div");a.className="fb-chooser-option-row",a.dataset.optIdx=String(s),a.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const i=document.createElement("div");i.style.cssText="display:flex; gap:.4rem; align-items:center;";const o=document.createElement("div");o.style.cssText="display:flex; flex-direction:column; gap:1px;";const l=document.createElement("button");l.type="button",l.className="btn btn-xs btn-ghost",l.title="Move up",O(l,"arrow-up"),l.addEventListener("click",j=>{j.preventDefault(),Xt(t,s,-1,n)});const d=document.createElement("button");d.type="button",d.className="btn btn-xs btn-ghost",d.title="Move down",O(d,"arrow-down"),d.addEventListener("click",j=>{j.preventDefault(),Xt(t,s,1,n)}),o.appendChild(l),o.appendChild(d),i.appendChild(o);const r=document.createElement("input");r.type="text",r.className="form-input fb-chooser-opt-value",r.placeholder="value",r.value=e.value||"",r.style.flex="1",i.appendChild(L("Value",r,{help:"The value stored with the submission and compared by trigger conditions. Keep it unique within this field."}));const u=document.createElement("input");u.type="text",u.className="form-input fb-chooser-opt-label",u.placeholder="label (visible to users)",u.value=e.label||"",u.style.flex="2",i.appendChild(L("Label",u,{help:"The choice text visitors see. The stored value can be different."}));const p=document.createElement("button");p.type="button",p.className="btn btn-xs btn-ghost",p.style.cssText="line-height:1;opacity:.6;",p.title="Remove option",O(p,"x"),p.addEventListener("click",j=>{j.preventDefault(),aa(t,s,n)}),i.appendChild(p),a.appendChild(i);const m=document.createElement("div");m.style.cssText="display:flex; gap:.4rem;";const v=je("icon name (optional)",e.icon||"");v.input.classList.add("fb-chooser-opt-icon"),v.el.style.flex="1",m.appendChild(L("Icon",v.el,{help:"An optional icon for this choice. Browse for an icon or leave blank for none."}));const f=document.createElement("input");f.type="text",f.className="form-input fb-chooser-opt-description",f.placeholder="description (card + comfortable only)",f.value=e.description||"",f.style.flex="2",m.appendChild(L("Description",f,{help:"Extra explanation shown by the card variant at comfortable density."})),a.appendChild(m);const y=document.createElement("div");y.style.cssText="display:flex; gap:.4rem;";const C=document.createElement("input");C.type="text",C.className="form-input fb-chooser-opt-tooltip",C.placeholder="tooltip (hover hint)",C.value=e.tooltip||"",C.style.flex="2",y.appendChild(L("Tooltip",C,{help:"An optional hover hint for this choice."}));const x=document.createElement("input");x.type="text",x.className="form-input fb-chooser-opt-badge-text",x.placeholder="badge text",x.value=e.badge?.text||"",x.style.flex="1",y.appendChild(L("Badge text",x,{help:"A short badge label attached to this choice. Leave blank for no badge."}));const b=document.createElement("select");b.className="form-input fb-chooser-opt-badge-type",b.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([j,Y])=>{const U=document.createElement("option");U.value=j,U.textContent=Y,(e.badge?.type||"")===j&&(U.selected=!0),b.appendChild(U)}),y.appendChild(L("Badge style",b,{help:"The theme colour used for the badge."})),a.appendChild(y);const w=document.createElement("div");w.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const q=document.createElement("label");q.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const B=document.createElement("input");B.type="checkbox",B.className="fb-chooser-opt-recommended",B.checked=!!e.recommended,q.appendChild(B),q.appendChild(document.createTextNode(" Recommended")),q.appendChild(A("Highlight this choice as recommended. This does not select it automatically.","Recommended")),w.appendChild(q);const _=document.createElement("label");_.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const W=document.createElement("input");return W.type="checkbox",W.className="fb-chooser-opt-disabled",W.checked=!!e.disabled,_.appendChild(W),_.appendChild(document.createTextNode(" Disabled")),_.appendChild(A("Show this choice but prevent the visitor from selecting it.","Disabled")),w.appendChild(_),a.appendChild(w),a}function ea(e,t){const s=document.createElement("div");s.style.cssText="margin-top:.5rem;";const n=document.createElement("div");n.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:.4rem;";const a=document.createElement("p");a.textContent="Options",a.appendChild(A("Each option has a stored value and a label shown to visitors. Keep values unique and use them in trigger conditions. Add an icon, description, tooltip or badge to explain a choice. Recommended highlights an option; Disabled prevents selection.","Chooser options")),a.style.cssText="font-size:.85rem;font-weight:600;margin:0;",n.appendChild(a);const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",be(i,"plus","Add option"),n.appendChild(i),s.appendChild(n);const o=document.createElement("div");o.className="fb-chooser-options-list",o.id=`fb-chooser-options-${t}`,o.style.cssText="display:flex; flex-direction:column; gap:.4rem;",s.appendChild(o);const l=()=>{o.replaceChildren();const d=ta(t);(d.length?d:e||[]).forEach((u,p)=>{o.appendChild(Zn(u,t,p,l))})};return i.addEventListener("click",d=>{d.preventDefault(),na(t,l)}),l(),s}function ta(e){const t=T[e];return!t||!Array.isArray(t.options)?[]:t.options}function nt(e){return T[e]?(Array.isArray(T[e].options)||(T[e].options=[]),T[e].options):[]}function na(e,t){Be(e),nt(e).push({value:"new",label:"New option"}),t()}function aa(e,t,s){Be(e),nt(e).splice(t,1),s()}function Xt(e,t,s,n){Be(e);const a=nt(e),i=t+s;if(i<0||i>=a.length)return;const[o]=a.splice(t,1);a.splice(i,0,o),n()}function Be(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const s=t.querySelectorAll(".fb-chooser-option-row"),n=[];s.forEach(a=>{const i={value:a.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:a.querySelector(".fb-chooser-opt-label")?.value.trim()||""},o=a.querySelector(".fb-chooser-opt-icon")?.value.trim();o&&(i.icon=o);const l=a.querySelector(".fb-chooser-opt-description")?.value.trim();l&&(i.description=l);const d=a.querySelector(".fb-chooser-opt-tooltip")?.value.trim();d&&(i.tooltip=d);const r=a.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),u=a.querySelector(".fb-chooser-opt-badge-type")?.value;(r||u)&&(i.badge={},r&&(i.badge.text=r),u&&(i.badge.type=u)),a.querySelector(".fb-chooser-opt-recommended")?.checked&&(i.recommended=!0),a.querySelector(".fb-chooser-opt-disabled")?.checked&&(i.disabled=!0),n.push(i)}),T[e]&&(T[e].options=n)}function z(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(s=>{s&&t.appendChild(s)}),t}function P(e,t,s,n,a){const i=document.createElement("div");i.style.flex="1";const o=document.createElement("label");o.htmlFor=t,o.className="form-label",o.textContent=e,o.style.fontSize=".8rem",(ge[e]||a)&&o.appendChild(A(ge[e]||a,e));const l=document.createElement("input");if(l.id=t,l.type=s||"text",l.className="form-input",l.value=n??"",i.appendChild(o),i.appendChild(l),a){const d=document.createElement("p");d.className="form-hint text-muted",d.textContent=a,d.style.cssText="font-size:.73rem;margin-top:.35rem;",i.appendChild(d)}return i}function ia(e,t,s,n){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=t,i.className="form-label",i.textContent=e,i.style.fontSize=".8rem",ge[e]&&i.appendChild(A(ge[e],e));const o=document.createElement("select");return o.id=t,o.className="form-select",s.forEach(l=>{const d=document.createElement("option");d.value=l.value,d.textContent=l.label,l.value===n&&(d.selected=!0),o.appendChild(d)}),a.appendChild(i),a.appendChild(o),a}function Ie(e,t,s){const n=document.createElement("div");n.style.cssText="flex:0;min-width:80px;display:flex;flex-direction:column;justify-content:flex-end;";const a=document.createElement("label");a.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;font-size:.8rem;white-space:nowrap;";const i=document.createElement("input");return i.id=t,i.type="checkbox",i.checked=s,a.appendChild(i),a.appendChild(document.createTextNode(e)),a.appendChild(A(ge[e]||et.find(o=>o.label===e)?.hint||e,e)),n.appendChild(a),n}function sa(e,t){const s=document.createElement("div");s.style.cssText="margin-top:.4rem;";const n=document.createElement("p");n.textContent="Options (one per line: value or value:Label)",n.style.cssText="font-size:.8rem;font-weight:600;margin-bottom:.3rem;";const a=document.createElement("textarea");return a.id=`fb-options-${t}`,a.className="form-input",a.rows=4,a.placeholder=`yes:Yes
6
6
  no:No
7
- maybe:Maybe`,l.value=(e||[]).map(a=>{const o=typeof a=="string"?a:a.value??"",s=typeof a=="string"?a:a.label??o;return o===s?o:`${o}:${s}`}).join(`
8
- `),l.style.fontFamily="monospace",i.appendChild(n),i.appendChild(l),i}function Ae(e){return parseInt(e,10)===3?3:2}const tl=[["#setting-submit-icon-start-slot","setting-submit-icon-start"],["#setting-submit-icon-end-slot","setting-submit-icon-end"],["#setting-second-icon-start-slot","setting-second-icon-start"],["#setting-second-icon-end-slot","setting-second-icon-end"]];function nl(e){tl.forEach(([t,i])=>{const n=e.find(t).get(0);if(!n||n.querySelector(`#${i}`))return;const l=Re("none","");l.input.id=i,l.input.classList.add("form-input"),n.appendChild(l.el)})}function Ut(e){const t=e.find("#setting-second-kind").val()||"",i=e.find("#second-button-group").get(0);i&&(i.style.display=t?"":"none");const n=e.find("#second-url-group").get(0);n&&(n.style.display=t==="link"?"":"none");const l=e.find("#setting-second-label").get(0);l&&(l.placeholder=t==="link"?"Cancel":"Clear form")}function ll(e){const t=a=>String(e.find(a).val()||"").trim(),i={},n={style:t("#setting-submit-style")||"primary",size:t("#setting-submit-size"),iconStart:t("#setting-submit-icon-start"),iconEnd:t("#setting-submit-icon-end")};(n.style!=="primary"||n.size||n.iconStart||n.iconEnd)&&(i.submitButton=n);const l=t("#setting-second-kind");return(l==="reset"||l==="link")&&(i.secondaryButton={kind:l,label:t("#setting-second-label"),...l==="link"?{url:t("#setting-second-url")}:{},style:t("#setting-second-style")||"secondary",iconStart:t("#setting-second-icon-start"),iconEnd:t("#setting-second-icon-end"),first:t("#setting-second-order")==="first",stack:t("#setting-second-arrange")==="stack"}),i}function Kt(e,t){const i=t&&t.submitButton||{},n=t&&t.secondaryButton||{};e.find("#setting-submit-style").val(i.style||"primary"),e.find("#setting-submit-size").val(i.size||""),e.find("#setting-submit-icon-start").val(i.iconStart||""),e.find("#setting-submit-icon-end").val(i.iconEnd||""),e.find("#setting-second-kind").val(n.kind==="reset"||n.kind==="link"?n.kind:""),e.find("#setting-second-label").val(n.label||""),e.find("#setting-second-url").val(n.url||""),e.find("#setting-second-style").val(n.style||"secondary"),e.find("#setting-second-icon-start").val(n.iconStart||""),e.find("#setting-second-icon-end").val(n.iconEnd||""),e.find("#setting-second-order").val(n.first?"first":"after"),e.find("#setting-second-arrange").val(n.stack?"stack":"row"),Ut(e)}function ye(e){const t=e.find("#field-project").val()||"";return j(),{title:e.find("#field-title").val().trim(),slug:e.find("#field-slug").val().trim(),description:e.find("#field-description").val().trim(),...e.find("#field-bundled").is(":checked")?{bundled:!0}:{},meta:{...Ee||{},project:t||null},fields:T,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:Ae(e.find("#setting-columns").val()),submitAlign:e.find("#setting-submit-align").val()||"",...ll(e),...e.find("#setting-form-class").val().trim()&&{class:e.find("#setting-form-class").val().trim()},...e.find("#setting-submit-class").val().trim()&&{submitClass:e.find("#setting-submit-class").val().trim()},honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...Ce!==null&&{collection:Ce}}}}function Jt(e,t){const i={};return e.forEach(n=>{if(n.type==="page-break"||n.type==="spacer")return;const l={...n.formConfig||{}};l.span==="full"&&t&&(l.span=t);const a=n.type==="chooser"||!!(n.variant&&["select","radio","checkbox-group"].includes(n.type)),s={type:n.type==="checkbox"?"boolean":n.type==="date"||n.type==="icon"||n.type==="image"?"string":a?"chooser":n.type,label:n.label,required:n.required,options:n.options,formConfig:{...n.placeholder&&{placeholder:n.placeholder},...n.helper&&{helperText:n.helper},...n.tooltip&&{tooltip:n.tooltip},...l}};a&&(n.variant&&(s.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(s.multiple=!0),n.density&&(s.density=n.density),n.columns&&(s.columns=n.columns),n.accent&&(s.accent=n.accent),n.accentStyle&&(s.accentStyle=n.accentStyle),n.glow&&(s.glow=!0),n.glowColour&&(s.glowColour=n.glowColour),n.shadow&&(s.shadow=n.shadow),n.shadowColour&&(s.shadowColour=n.shadowColour)),i[n.name]=n.type==="file"?on(n,s):s}),i}function Yt(e,t){const i=typeof e=="string"?document.querySelector(e):e;i&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const l=i.querySelector(`[name="${n.name}"]`);l&&l.type!=="date"&&(l.type="date")})}function Ze(e,t){const i=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(i){for(;i.nextSibling;)i.nextSibling.remove();i.after(document.createTextNode(String(t||"")))}}const Xt=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");let J=null,Qt=0,Zt=!1;const Fe=e=>String(e||"").split("?")[0].replace(/\/$/,"");function al(){Zt||!window.R?.use||(Zt=!0,R.use((e,t,i)=>!J||!yt(t?.path,e?.path)||J.path!==Fe(t?.path)||(J.flush(),!J.dirty())?i():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(n=>{n?i():history.replaceState(null,"",`#${t.path}`)})),M.subscribe("router:afterChange",({to:e,from:t}={})=>{if(J&&J.path===Fe(t?.path)&&yt(t?.path,e?.path)){const i=J;J=null,i.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(al(),J){const c=J;J=null,c.dispose()}const t=Fe(location.hash.replace(/^#/,"")),i=++Qt,n=()=>i!==Qt||!e.get(0)?.isConnected||Fe(location.hash.replace(/^#/,""))!==t;T=[],A=null,Ce=null,nl(e),e.find("#setting-second-kind").get(0)?.addEventListener("change",()=>Ut(e));const l=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);A=l?l[1]:null;let a=null,o=null;const s=E.loader(e.get(0),{type:"dots"});if(A)try{if(a=await pe(`/forms/${A}`),n()){s.destroy();return}T=a.fields||[],Ce=a.actions?.collection??null}catch(c){if(n()){s.destroy();return}o={missing:c?.status===404,message:c?.message||String(c)},E.toast(o.missing?"This form no longer exists.":`Could not load the form: ${o.message}`,{type:"error"})}Ee={};try{const c=await pe("/projects").catch(()=>[]);if(n()){s.destroy();return}const h=e.find("#field-project").get(0);h&&(Array.isArray(c)?c:[]).forEach(g=>{const k=document.createElement("option");k.value=g.slug,k.textContent=g.name||g.slug,h.appendChild(k)})}catch{}if(s.destroy(),Ze(e.get(0),a?a.title||a.slug:"New form"),A||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(Et(this.value))}),E.tabs(e.find("#editor-tabs").get(0)),a){e.find("#field-title").val(a.title),e.find("#field-slug").val(a.slug),e.find("#field-description").val(a.description||""),e.find("#field-bundled").prop("checked",!!a.bundled),Ee=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const c=a.settings||{};e.find("#setting-submit-text").val(c.submitText||"Submit"),e.find("#setting-success-message").val(c.successMessage||""),e.find("#setting-layout").val(c.layout||"grid"),e.find("#setting-columns").val(Ae(c.columns)),e.find("#setting-submit-align").val(ht(c,c.layout||"grid")),Kt(e,c),e.find("#setting-form-class").val(c.class||""),e.find("#setting-submit-class").val(c.submitClass||""),e.find("#columns-group").get(0).style.display=(c.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",c.honeypot!==!1),e.find("#setting-rate-limit").val(c.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(c.successRedirect||"");const h=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",h.enabled||!1),e.find("#action-email-recipients").val(h.recipients||""),e.find("#action-email-subject-prefix").val(h.subjectPrefix||"");const g=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",g.enabled||!1),e.find("#action-webhook-url").val(g.url||""),e.find("#action-webhook-method").val(g.method||"POST")}const d=a?.settings?.actionSlug||"";try{const c=await pe("/actions").catch(()=>[]);if(n())return;const h=e.find("#action-cms-slug").get(0);if(xe=Array.isArray(c)?c:[],(Array.isArray(c)?c:[]).forEach(g=>{const k=document.createElement("option");k.value=g.slug,k.textContent=g.title||g.slug,g.slug===d&&(k.selected=!0),h.appendChild(k)}),!c.length){const g=document.createElement("option");g.value="",g.textContent="No actions available",g.disabled=!0,h.appendChild(g)}}catch{}const r=c=>{e.find("#columns-group").get(0).style.display=c?"":"none",document.querySelectorAll(".fb-grid-row").forEach(h=>{h.style.display=c?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){r(this.value==="grid")}),r(e.find("#setting-layout").val()==="grid"),te(e);const u=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",c=>{c.stopPropagation(),u.style.display=u.style.display==="none"?"":"none"}),ie&&document.removeEventListener("click",ie),ie=()=>{u&&(u.style.display="none")},document.addEventListener("click",ie),e.find("#add-field-btn").get(0).addEventListener("click",()=>{u&&(u.style.display="none"),j();const c=T.length;T.push({name:`field_${c+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),te(e);const h=e.find("#fields-list").get(0)?.lastElementChild;if(h){const g=h.querySelector(".fb-field-body");g&&(g.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{u&&(u.style.display="none"),j(),T.push({type:"spacer"}),te(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{u&&(u.style.display="none"),j();const c=T.filter(h=>h.type==="page-break").length+2;T.push({type:"page-break",label:`Step ${c}`,description:""}),te(e)}),we=()=>{const c=ye(e),h=e.find("#preview-container").get(0);if(!h)return;const g=e.find("#preview-test-result").get(0),k=e.find("#preview-test-badge").get(0);g&&(g.style.display="none",g.textContent=""),k&&(k.style.display=A?"":"none"),e.find("#preview-card").get(0).style.display="",mt(h),h.textContent="";const N=document.createElement("div");N.id="fb-preview-form",h.appendChild(N);const P=new Map;dn(N,c.fields);const U=A?async I=>{g&&(g.style.display="none",g.textContent="");try{const $=new Map(P);pt(N,$);const ee=rn(I,c.fields,$),le=cn(ee.values,ee.files),W=await fetch(`/api/forms/submit/${A}`,{method:"POST",headers:le.headers,body:le.body}),Y=await W.json();if(!W.ok)throw new Error(Y.error||"Submission failed.");g&&(g.textContent=Y.message||c.settings?.successMessage||"Submitted successfully.",g.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-success) 12%, transparent);color:var(--dm-success);"),E.toast("Test submission stored.",{type:"success"})}catch($){g&&(g.textContent=$.message,g.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-danger) 12%, transparent);color:var(--dm-danger);"),E.toast($.message,{type:"error"})}return!1}:()=>!1,ue=c.fields.some(I=>I.type==="page-break");if(N.addEventListener("click",I=>{const $=I.target.closest?.("a.fb-secondary-btn");$&&(I.preventDefault(),E.toast(`Cancel takes the visitor to ${$.getAttribute("href")}`,{type:"info"}))}),N.addEventListener("dm-form-end",I=>{const $=I.detail?.validation;if($&&!$.valid){E.toast(`Still to answer: ${$.missing.map(ee=>ee.label).concat($.errors).join(", ")}`,{type:"warning"});return}U(I.detail?.values||{})}),typeof F<"u"){const I=Ae(c.settings?.columns),$=c.settings?.layout||"grid";if(ue&&F.wizard){const ee=an(c.fields,c.title),le=ee.map(ae=>({title:ae.title,description:ae.description,fields:Jt(ae.fields,I)}));let W=0,Y=null,Me=null;const ct=ae=>{const ze=(ee[W]||{}).fields||[];pn(N,c.settings),ft(N,c.settings,ze),Yt("#fb-preview-form",ze),dt(N,ze),sn(N,P),ae&&window.FormLogicEngine&&kt(c.fields)&&(Y?.destroy?.(),Y=new window.FormLogicEngine.FormLogicRuntime({fields:c.fields},N,{baseValues:Me?.getStepData?Me.getStepData():{}}),Y.init())};Me=F.wizard("#fb-preview-form",{schema:{steps:le},layout:$,columns:I,finishText:c.settings?.submitText||"Finish",onStepChange:ae=>{pt(N,P),W=ae,queueMicrotask(()=>ct(!0))},onSubmit:U}),ct(!1)}else if(F.render){const ee=Jt(c.fields,I),le={};c.fields.forEach(W=>{if(!(!W.name||W.type==="page-break"||W.type==="spacer")&&(W.type==="select"||W.type==="multiselect")&&W.required){const Y=(W.options||[])[0];Y&&(le[W.name]=typeof Y=="object"?Y.value:Y)}}),F.render("#fb-preview-form",ee,le,{submitText:c.settings?.submitText||"Submit",layout:$,columns:I,onSubmit:U}),un(N,c.settings,$),ft(N,c.settings,c.fields),Yt("#fb-preview-form",c.fields),dt(N,c.fields)}window.FormLogicEngine&&kt(c.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:c.fields},N).init()})}else{const I=document.createElement("p");I.textContent=`${c.fields.filter($=>$.type!=="page-break").length} field(s): ${c.fields.filter($=>$.type!=="page-break").map($=>$.label).join(", ")}`,I.style.cssText="color:var(--dm-text-muted);font-style:italic;",N.appendChild(I)}},we();const p=e.find("#editor-tabs").get(0),m=e.find("#preview-card").get(0),v=c=>{m&&m.contains(c.target)||We()};p&&(p.addEventListener("input",v),p.addEventListener("change",v));const f=e.get(0),y=[],w=c=>(y.push(c),c);let x=!1;const b=M.observable(!1),C=M.observable(!1);let L=A,q=null,D=!1,V=!1,_=!1,K=ye(e),G=ve(K),ne=K;const oe=()=>{x||!f.isConnected||(ne=ye(e),b.value=ve(ne)!==G)};let ce=null;Ge=()=>{clearTimeout(ce),ce=setTimeout(oe,150)},w(()=>{clearTimeout(ce),Ge=null,he=null}),w(()=>mt(f.querySelector("#preview-container")));const Be=c=>{const h=c.settings||{};e.find("#field-title").val(c.title||""),e.find("#field-slug").val(c.slug||""),e.find("#field-description").val(c.description||""),e.find("#field-bundled").prop("checked",!!c.bundled),Ee={...c.meta||{}},e.find("#field-project").val(c.meta?.project||""),e.find("#setting-submit-text").val(h.submitText||"Submit"),e.find("#setting-success-message").val(h.successMessage||""),e.find("#setting-layout").val(h.layout||"grid"),e.find("#setting-columns").val(Ae(h.columns)),e.find("#setting-submit-align").val(ht(h,h.layout||"grid")),Kt(e,h),e.find("#setting-form-class").val(h.class||""),e.find("#setting-submit-class").val(h.submitClass||""),e.find("#setting-honeypot").prop("checked",h.honeypot!==!1),e.find("#setting-rate-limit").val(h.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(h.successRedirect||""),e.find("#action-cms-slug").val(h.actionSlug||"");const g=c.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!g.enabled),e.find("#action-email-recipients").val(g.recipients||""),e.find("#action-email-subject-prefix").val(g.subjectPrefix||"");const k=c.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!k.enabled),e.find("#action-webhook-url").val(k.url||""),e.find("#action-webhook-method").val(k.method||"POST"),T=JSON.parse(JSON.stringify(c.fields||[])),r((h.layout||"grid")==="grid"),te(e)};async function Ie(){if(C.peek()||x)return;if(o){E.toast("This form did not load, so saving would replace it with an empty one. Reload the page to try again.",{type:"error"});return}const c=ye(e);if(!c.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}const h=mn(c.settings);if(h.length){E.toast(`${h[0]} (Settings > Submit Button)`,{type:"error"});return}const g=fn(c.settings,c.fields);if(g.length){E.toast(g[0],{type:"error"});return}const k=Rn(c.fields);k.length&&E.toast(`Some trigger messages use ${k.map(U=>`{{${U}}}`).join(", ")}, which will show as blank: no field has that name, or it is a password, file or image.`,{type:"warning",duration:9e3}),C.value=!0;const N=A,P=me(L);N||(f.inert=!0);try{if(A?(await pe(`/forms/${A}`,{method:"PUT",body:JSON.stringify(c)}),E.toast("Form saved.",{type:"success"})):(A=(await pe("/forms",{method:"POST",body:JSON.stringify(c)})).slug,E.toast("Form created.",{type:"success"})),x){if(!N)try{S.remove?S.remove(P):S.set(P,null)}catch{}return}L=A,K=c,G=ve(c),q=null,V=!1,_=!1,clearTimeout(ce),oe();for(const U of new Set([P,me(A)]))try{S.remove?S.remove(U):S.set(U,null)}catch{}Ze(f,c.title),bn("#/forms"),N||R.navigate(`/forms/edit/${A}`)}catch(U){N||(A=null),E.toast(U.message||"Failed to save form.",{type:"error"})}finally{C.value=!1,f.inert=!1}}async function en(){b.peek()&&(!await E.confirm("Throw away the changes you have not saved?",{confirmText:"Throw away",cancelText:"Keep editing"})||x||(Be(K),oe(),ot()))}const et=f.querySelector(".fex-bar");if(et){const c=M.applyBindings({dirty:b,saving:C},et,{methods:{save:Ie,discard:en}});w(()=>c.dispose())}w(hn(f,{position:"bottom"})),_e(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>Ie()}),_e(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),A&&_e(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(A)}/submissions`}});const tt=c=>{n()||!(c.ctrlKey||c.metaKey)||String(c.key).toLowerCase()!=="s"||(c.preventDefault(),c.stopImmediatePropagation(),Ie())};document.addEventListener("keydown",tt,!0),w(()=>document.removeEventListener("keydown",tt,!0));const Q=e.find("#fields-list").get(0),tn=c=>c?.closest?.(".fb-field-card"),nt=c=>Number(c?.dataset.index),lt=c=>c?.querySelector(":scope > .fb-field-body"),at=c=>{const h=lt(c);h&&(h.style.display=h.style.display==="none"?"":"none")},de=(c,h)=>{T=c,te(e),h!=null&&Q?.querySelectorAll(".fb-field-card")[h]?.focus()},nn=async c=>{try{await navigator.clipboard.writeText(c),E.toast(`Copied "${c}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${c}.`,{type:"info"})}},ln=c=>{const h=tn(c),g=nt(h);j();const k=T[g];if(!k)return[];const N=k.type!=="spacer"&&k.type!=="page-break",P=lt(h),U=P&&P.style.display!=="none";return[{header:Pe(k)},...P?[{label:U?"Close":"Edit",icon:U?"chevron-up":"edit",action:()=>at(h)}]:[],...N?[{label:"Logic & triggers",icon:"zap",action:()=>{P&&(P.style.display=""),(P?.querySelector(".fb-field-logic")||P)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{j(),de(xn(T,g),g+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",shortcut:"Alt+\u2191",disabled:g===0,action:()=>{j(),de(vt(T,g,-1),g-1)}},{label:"Move down",icon:"arrow-down",shortcut:"Alt+\u2193",disabled:g>=T.length-1,action:()=>{j(),de(vt(T,g,1),g+1)}},...N&&k.name?[{label:"Copy field name",icon:"clipboard",action:()=>nn(k.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(k.type!=="spacer"&&!await E.confirm(`Remove "${Xt(Pe(k))}"?`))return;j();const ue=[...T];ue.splice(g,1),de(ue,Math.min(g,ue.length-1))}}]};if(Q&&typeof E.sortable=="function"){const c=E.sortable(Q,{items:".fb-field-card",handle:".fb-drag-grip",key:null,onSort:({from:h,to:g})=>{j();const k=[...T],[N]=k.splice(h,1);k.splice(g,0,N),de(k,g)}});w(()=>c.destroy())}let it=null;if(Q&&E.contextMenu&&(it=E.contextMenu(Q,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:c=>ln(c)}),w(()=>it?.destroy?.())),he=c=>{for(const h of c.querySelectorAll(".fb-field-card")){h.tabIndex=0;const g=h.firstElementChild;if(!g||g.querySelector(".fex-kebab"))continue;const k=document.createElement("button");k.type="button",k.className="fex-kebab",k.textContent="\u22EE",k.title="Actions",j(),k.setAttribute("aria-label",`Actions for ${Pe(T[nt(h)])}`),k.addEventListener("click",N=>{N.stopPropagation(),bt(k)}),g.appendChild(k)}},Q){he(Q);const c=h=>{const g=h.target?.classList?.contains("fb-field-card")?h.target:null;g&&(h.key==="F10"&&h.shiftKey?(h.preventDefault(),bt(g.firstElementChild)):h.key==="Enter"&&(h.preventDefault(),at(g)))};Q.addEventListener("keydown",c),w(()=>Q.removeEventListener("keydown",c))}const ot=()=>{try{const c=me(L);S.remove?S.remove(c):S.set(c,null)}catch{}},st=c=>{if(!o){if(!b.peek()||!c){!D&&!_&&ot();return}try{S.set(me(L),{data:vn(c),base:gn(q,gt(G)),...V?{newFrom:!0}:{},at:new Date().toISOString()})}catch{}}},rt=c=>{oe(),b.peek()&&(st(ne),c.preventDefault(),c.returnValue="")};if(window.addEventListener("beforeunload",rt),w(()=>window.removeEventListener("beforeunload",rt)),w(()=>{ie&&(document.removeEventListener("click",ie),ie=null)}),J={path:t,dirty:()=>b.peek(),flush:()=>{clearTimeout(ce),oe()},dispose(){x||(st(ne),x=!0,y.splice(0).reverse().forEach(c=>{try{c?.()}catch{}}))}},o){const c=document.createElement("p");c.className="fex-load-error",c.setAttribute("role","alert"),c.textContent=o.missing?"This form no longer exists - it may have been deleted. Nothing here can be saved over it.":`This form could not be loaded (${o.message}). Saving is off so an empty editor cannot replace it - reload the page to try again.`;const h=f.querySelector(".fex-bar");h?h.before(c):f.prepend(c),w(()=>c.remove())}const Oe=me(A);let Z=null;try{Z=S.get(Oe)}catch{}if(Z?.data&&(!o||o.missing)){const c=!!o?.missing,h=yn(Z,{missing:c});D=!0;const g=await E.confirm(Xt(Cn(Z,{current:gt(G),missing:c,when:Z.at?wn(Z.at):""})),{title:"Unsaved changes",confirmText:"Throw away",cancelText:h==="new"?"Start a new form":h==="refuse"?"Not now":"Keep them"});if(D=!1,g)try{S.remove?S.remove(Oe):S.set(Oe,null)}catch{}else h==="refuse"?_=!0:x||(c?(A=null,o=null,q="",V=!0,K=ye(e),G=ve(K),Ze(f,"New form"),f.querySelector(".fex-load-error")?.remove(),Be(Z.data)):(q=Z.base??"",Be(En(Z.data,K))),oe())}}};
7
+ maybe:Maybe`,a.value=(e||[]).map(i=>{const o=typeof i=="string"?i:i.value??"",l=typeof i=="string"?i:i.label??o;return o===l?o:`${o}:${l}`}).join(`
8
+ `),a.style.fontFamily="monospace",n.appendChild(A("Enter one choice per line. Use value:Label, for example yes:Yes please. The value is stored and tested by conditions; the label is shown to visitors. A line without a colon uses the same text for both.","Options")),s.appendChild(n),s.appendChild(a),s}function Me(e){return parseInt(e,10)===3?3:2}const oa=[["#setting-submit-icon-start-slot","setting-submit-icon-start"],["#setting-submit-icon-end-slot","setting-submit-icon-end"],["#setting-second-icon-start-slot","setting-second-icon-start"],["#setting-second-icon-end-slot","setting-second-icon-end"]];function la(e){oa.forEach(([t,s])=>{const n=e.find(t).get(0);if(!n||n.querySelector(`#${s}`))return;const a=je("none","");a.input.id=s,a.input.classList.add("form-input"),n.appendChild(a.el)})}function Qt(e){const t=e.find("#setting-second-kind").val()||"",s=e.find("#second-button-group").get(0);s&&(s.style.display=t?"":"none");const n=e.find("#second-url-group").get(0);n&&(n.style.display=t==="link"?"":"none");const a=e.find("#setting-second-label").get(0);a&&(a.placeholder=t==="link"?"Cancel":"Clear form")}function ra(e){const t=i=>String(e.find(i).val()||"").trim(),s={},n={style:t("#setting-submit-style")||"primary",size:t("#setting-submit-size"),iconStart:t("#setting-submit-icon-start"),iconEnd:t("#setting-submit-icon-end")};(n.style!=="primary"||n.size||n.iconStart||n.iconEnd)&&(s.submitButton=n);const a=t("#setting-second-kind");return(a==="reset"||a==="link")&&(s.secondaryButton={kind:a,label:t("#setting-second-label"),...a==="link"?{url:t("#setting-second-url")}:{},style:t("#setting-second-style")||"secondary",iconStart:t("#setting-second-icon-start"),iconEnd:t("#setting-second-icon-end"),first:t("#setting-second-order")==="first",stack:t("#setting-second-arrange")==="stack"}),s}function Zt(e,t){const s=t&&t.submitButton||{},n=t&&t.secondaryButton||{};e.find("#setting-submit-style").val(s.style||"primary"),e.find("#setting-submit-size").val(s.size||""),e.find("#setting-submit-icon-start").val(s.iconStart||""),e.find("#setting-submit-icon-end").val(s.iconEnd||""),e.find("#setting-second-kind").val(n.kind==="reset"||n.kind==="link"?n.kind:""),e.find("#setting-second-label").val(n.label||""),e.find("#setting-second-url").val(n.url||""),e.find("#setting-second-style").val(n.style||"secondary"),e.find("#setting-second-icon-start").val(n.iconStart||""),e.find("#setting-second-icon-end").val(n.iconEnd||""),e.find("#setting-second-order").val(n.first?"first":"after"),e.find("#setting-second-arrange").val(n.stack?"stack":"row"),Qt(e)}function Ce(e){const t=e.find("#field-project").val()||"";return V(),{title:e.find("#field-title").val().trim(),slug:e.find("#field-slug").val().trim(),description:e.find("#field-description").val().trim(),...e.find("#field-bundled").is(":checked")?{bundled:!0}:{},meta:{...Te||{},project:t||null},fields:T,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:Me(e.find("#setting-columns").val()),submitAlign:e.find("#setting-submit-align").val()||"",...ra(e),...e.find("#setting-form-class").val().trim()&&{class:e.find("#setting-form-class").val().trim()},...e.find("#setting-submit-class").val().trim()&&{submitClass:e.find("#setting-submit-class").val().trim()},honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...Se!==null&&{collection:Se}}}}function en(e,t){const s={};return e.forEach(n=>{if(n.type==="page-break"||n.type==="spacer")return;const a={...n.formConfig||{}};a.span==="full"&&t&&(a.span=t);const i=n.type==="chooser"||!!(n.variant&&["select","radio","checkbox-group"].includes(n.type)),l={type:n.type==="checkbox"?"boolean":n.type==="date"||n.type==="icon"||n.type==="image"?"string":i?"chooser":n.type,label:n.label,required:n.required,options:n.options,formConfig:{...n.placeholder&&{placeholder:n.placeholder},...n.helper&&{helperText:n.helper},...n.tooltip&&{tooltip:n.tooltip},...a}};i&&(n.variant&&(l.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(l.multiple=!0),n.density&&(l.density=n.density),n.columns&&(l.columns=n.columns),n.accent&&(l.accent=n.accent),n.accentStyle&&(l.accentStyle=n.accentStyle),n.glow&&(l.glow=!0),n.glowColour&&(l.glowColour=n.glowColour),n.shadow&&(l.shadow=n.shadow),n.shadowColour&&(l.shadowColour=n.shadowColour)),s[n.name]=n.type==="file"?un(n,l):l}),s}function tn(e,t){const s=typeof e=="string"?document.querySelector(e):e;s&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const a=s.querySelector(`[name="${n.name}"]`);a&&a.type!=="date"&&(a.type="date")})}function at(e,t){const s=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(s){for(;s.nextSibling;)s.nextSibling.remove();s.after(document.createTextNode(String(t||"")))}}const nn=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");let J=null,an=0,sn=!1;const Oe=e=>String(e||"").split("?")[0].replace(/\/$/,"");function ca(){sn||!window.R?.use||(sn=!0,R.use((e,t,s)=>!J||!kt(t?.path,e?.path)||J.path!==Oe(t?.path)||(J.flush(),!J.dirty())?s():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(n=>{n?s():history.replaceState(null,"",`#${t.path}`)})),M.subscribe("router:afterChange",({to:e,from:t}={})=>{if(J&&J.path===Oe(t?.path)&&kt(t?.path,e?.path)){const s=J;J=null,s.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(ca(),J){const c=J;J=null,c.dispose()}const t=Oe(location.hash.replace(/^#/,"")),s=++an,n=()=>s!==an||!e.get(0)?.isConnected||Oe(location.hash.replace(/^#/,""))!==t;T=[],I=null,Se=null,la(e),e.find("#setting-second-kind").get(0)?.addEventListener("change",()=>Qt(e));const a=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);I=a?a[1]:null;let i=null,o=null;const l=E.loader(e.get(0),{type:"dots"});if(I)try{if(i=await fe(`/forms/${I}`),n()){l.destroy();return}T=i.fields||[],Se=i.actions?.collection??null}catch(c){if(n()){l.destroy();return}o={missing:c?.status===404,message:c?.message||String(c)},E.toast(o.missing?"This form no longer exists.":`Could not load the form: ${o.message}`,{type:"error"})}Te={};try{const c=await fe("/projects").catch(()=>[]);if(n()){l.destroy();return}const h=e.find("#field-project").get(0);h&&(Array.isArray(c)?c:[]).forEach(g=>{const k=document.createElement("option");k.value=g.slug,k.textContent=g.name||g.slug,h.appendChild(k)})}catch{}if(l.destroy(),at(e.get(0),i?i.title||i.slug:"New form"),I||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(Nt(this.value))}),E.tabs(e.find("#editor-tabs").get(0)),i){e.find("#field-title").val(i.title),e.find("#field-slug").val(i.slug),e.find("#field-description").val(i.description||""),e.find("#field-bundled").prop("checked",!!i.bundled),Te=i.meta||{},e.find("#field-project").val(i.meta?.project||"");const c=i.settings||{};e.find("#setting-submit-text").val(c.submitText||"Submit"),e.find("#setting-success-message").val(c.successMessage||""),e.find("#setting-layout").val(c.layout||"grid"),e.find("#setting-columns").val(Me(c.columns)),e.find("#setting-submit-align").val(wt(c,c.layout||"grid")),Zt(e,c),e.find("#setting-form-class").val(c.class||""),e.find("#setting-submit-class").val(c.submitClass||""),e.find("#columns-group").get(0).style.display=(c.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",c.honeypot!==!1),e.find("#setting-rate-limit").val(c.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(c.successRedirect||"");const h=i.actions?.email||{};e.find("#action-email-enabled").prop("checked",h.enabled||!1),e.find("#action-email-recipients").val(h.recipients||""),e.find("#action-email-subject-prefix").val(h.subjectPrefix||"");const g=i.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",g.enabled||!1),e.find("#action-webhook-url").val(g.url||""),e.find("#action-webhook-method").val(g.method||"POST")}const d=i?.settings?.actionSlug||"";try{const c=await fe("/actions").catch(()=>[]);if(n())return;const h=e.find("#action-cms-slug").get(0);if(ke=Array.isArray(c)?c:[],(Array.isArray(c)?c:[]).forEach(g=>{const k=document.createElement("option");k.value=g.slug,k.textContent=g.title||g.slug,g.slug===d&&(k.selected=!0),h.appendChild(k)}),!c.length){const g=document.createElement("option");g.value="",g.textContent="No actions available",g.disabled=!0,h.appendChild(g)}}catch{}const r=c=>{e.find("#columns-group").get(0).style.display=c?"":"none",document.querySelectorAll(".fb-grid-row").forEach(h=>{h.style.display=c?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){r(this.value==="grid")}),r(e.find("#setting-layout").val()==="grid"),ne(e);const u=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",c=>{c.stopPropagation(),u.style.display=u.style.display==="none"?"":"none"}),oe&&document.removeEventListener("click",oe),oe=()=>{u&&(u.style.display="none")},document.addEventListener("click",oe),e.find("#add-field-btn").get(0).addEventListener("click",()=>{u&&(u.style.display="none"),V();const c=T.length;T.push({name:`field_${c+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),ne(e);const h=e.find("#fields-list").get(0)?.lastElementChild;if(h){const g=h.querySelector(".fb-field-body");g&&(g.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{u&&(u.style.display="none"),V(),T.push({type:"spacer"}),ne(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{u&&(u.style.display="none"),V();const c=T.filter(h=>h.type==="page-break").length+2;T.push({type:"page-break",label:`Step ${c}`,description:""}),ne(e)}),Le=()=>{const c=Ce(e),h=e.find("#preview-container").get(0);if(!h)return;const g=e.find("#preview-test-result").get(0),k=e.find("#preview-test-badge").get(0);g&&(g.style.display="none",g.textContent=""),k&&(k.style.display=I?"":"none"),e.find("#preview-card").get(0).style.display="",vt(h),h.textContent="";const N=document.createElement("div");N.id="fb-preview-form",h.appendChild(N);const H=new Map;hn(N,c.fields);const K=I?async D=>{g&&(g.style.display="none",g.textContent="");try{const $=new Map(H);yt(N,$);const te=mn(D,c.fields,$),ie=fn(te.values,te.files),G=await fetch(`/api/forms/submit/${I}`,{method:"POST",headers:ie.headers,body:ie.body}),X=await G.json();if(!G.ok)throw new Error(X.error||"Submission failed.");g&&(g.textContent=X.message||c.settings?.successMessage||"Submitted successfully.",g.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-success) 12%, transparent);color:var(--dm-success);"),E.toast("Test submission stored.",{type:"success"})}catch($){g&&(g.textContent=$.message,g.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-danger) 12%, transparent);color:var(--dm-danger);"),E.toast($.message,{type:"error"})}return!1}:()=>!1,me=c.fields.some(D=>D.type==="page-break");if(N.addEventListener("click",D=>{const $=D.target.closest?.("a.fb-secondary-btn");$&&(D.preventDefault(),E.toast(`Cancel takes the visitor to ${$.getAttribute("href")}`,{type:"info"}))}),N.addEventListener("dm-form-end",D=>{const $=D.detail?.validation;if($&&!$.valid){E.toast(`Still to answer: ${$.missing.map(te=>te.label).concat($.errors).join(", ")}`,{type:"warning"});return}K(D.detail?.values||{})}),typeof F<"u"){const D=Me(c.settings?.columns),$=c.settings?.layout||"grid";if(me&&F.wizard){const te=dn(c.fields,c.title),ie=te.map(se=>({title:se.title,description:se.description,fields:en(se.fields,D)}));let G=0,X=null,_e=null;const ht=se=>{const Pe=(te[G]||{}).fields||[];gn(N,c.settings),xt(N,c.settings,Pe),tn("#fb-preview-form",Pe),bt(N,Pe),pn(N,H),se&&window.FormLogicEngine&&$t(c.fields)&&(X?.destroy?.(),X=new window.FormLogicEngine.FormLogicRuntime({fields:c.fields},N,{baseValues:_e?.getStepData?_e.getStepData():{}}),X.init())};_e=F.wizard("#fb-preview-form",{schema:{steps:ie},layout:$,columns:D,finishText:c.settings?.submitText||"Finish",onStepChange:se=>{yt(N,H),G=se,queueMicrotask(()=>ht(!0))},onSubmit:K}),ht(!1)}else if(F.render){const te=en(c.fields,D),ie={};c.fields.forEach(G=>{if(!(!G.name||G.type==="page-break"||G.type==="spacer")&&(G.type==="select"||G.type==="multiselect")&&G.required){const X=(G.options||[])[0];X&&(ie[G.name]=typeof X=="object"?X.value:X)}}),F.render("#fb-preview-form",te,ie,{submitText:c.settings?.submitText||"Submit",layout:$,columns:D,onSubmit:K}),bn(N,c.settings,$),xt(N,c.settings,c.fields),tn("#fb-preview-form",c.fields),bt(N,c.fields)}window.FormLogicEngine&&$t(c.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:c.fields},N).init()})}else{const D=document.createElement("p");D.textContent=`${c.fields.filter($=>$.type!=="page-break").length} field(s): ${c.fields.filter($=>$.type!=="page-break").map($=>$.label).join(", ")}`,D.style.cssText="color:var(--dm-text-muted);font-style:italic;",N.appendChild(D)}},Le();const p=e.find("#editor-tabs").get(0),m=e.find("#preview-card").get(0),v=c=>{m&&m.contains(c.target)||Ke()};p&&(p.addEventListener("input",v),p.addEventListener("change",v));const f=e.get(0),y=[],C=c=>(y.push(c),c);let x=!1;const b=M.observable(!1),w=M.observable(!1);let q=I,B=null,_=!1,W=!1,j=!1,Y=Ce(e),U=Ee(Y),ae=Y;const le=()=>{x||!f.isConnected||(ae=Ce(e),b.value=Ee(ae)!==U)};let de=null;Ge=()=>{clearTimeout(de),de=setTimeout(le,150)},C(()=>{clearTimeout(de),Ge=null,ve=null}),C(()=>vt(f.querySelector("#preview-container")));const Re=c=>{const h=c.settings||{};e.find("#field-title").val(c.title||""),e.find("#field-slug").val(c.slug||""),e.find("#field-description").val(c.description||""),e.find("#field-bundled").prop("checked",!!c.bundled),Te={...c.meta||{}},e.find("#field-project").val(c.meta?.project||""),e.find("#setting-submit-text").val(h.submitText||"Submit"),e.find("#setting-success-message").val(h.successMessage||""),e.find("#setting-layout").val(h.layout||"grid"),e.find("#setting-columns").val(Me(h.columns)),e.find("#setting-submit-align").val(wt(h,h.layout||"grid")),Zt(e,h),e.find("#setting-form-class").val(h.class||""),e.find("#setting-submit-class").val(h.submitClass||""),e.find("#setting-honeypot").prop("checked",h.honeypot!==!1),e.find("#setting-rate-limit").val(h.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(h.successRedirect||""),e.find("#action-cms-slug").val(h.actionSlug||"");const g=c.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!g.enabled),e.find("#action-email-recipients").val(g.recipients||""),e.find("#action-email-subject-prefix").val(g.subjectPrefix||"");const k=c.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!k.enabled),e.find("#action-webhook-url").val(k.url||""),e.find("#action-webhook-method").val(k.method||"POST"),T=JSON.parse(JSON.stringify(c.fields||[])),r((h.layout||"grid")==="grid"),ne(e)};async function De(){if(w.peek()||x)return;if(o){E.toast("This form did not load, so saving would replace it with an empty one. Reload the page to try again.",{type:"error"});return}const c=Ce(e);if(!c.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}const h=yn(c.settings);if(h.length){E.toast(`${h[0]} (Settings > Submit Button)`,{type:"error"});return}const g=vn(c.settings,c.fields);if(g.length){E.toast(g[0],{type:"error"});return}const k=Hn(c.fields);k.length&&E.toast(`Some trigger messages use ${k.map(K=>`{{${K}}}`).join(", ")}, which will show as blank: no field has that name, or it is a password, file or image.`,{type:"warning",duration:9e3}),w.value=!0;const N=I,H=he(q);N||(f.inert=!0);try{if(I?(await fe(`/forms/${I}`,{method:"PUT",body:JSON.stringify(c)}),E.toast("Form saved.",{type:"success"})):(I=(await fe("/forms",{method:"POST",body:JSON.stringify(c)})).slug,E.toast("Form created.",{type:"success"})),x){if(!N)try{S.remove?S.remove(H):S.set(H,null)}catch{}return}q=I,Y=c,U=Ee(c),B=null,W=!1,j=!1,clearTimeout(de),le();for(const K of new Set([H,he(I)]))try{S.remove?S.remove(K):S.set(K,null)}catch{}at(f,c.title),wn("#/forms"),N||R.navigate(`/forms/edit/${I}`)}catch(K){N||(I=null),E.toast(K.message||"Failed to save form.",{type:"error"})}finally{w.value=!1,f.inert=!1}}async function on(){b.peek()&&(!await E.confirm("Throw away the changes you have not saved?",{confirmText:"Throw away",cancelText:"Keep editing"})||x||(Re(Y),le(),pt()))}const it=f.querySelector(".fex-bar");if(it){const c=M.applyBindings({dirty:b,saving:w},it,{methods:{save:De,discard:on}});C(()=>c.dispose())}const ue=new Map,st=()=>{for(const[c,h]of ue)f.contains(c)||(h(),ue.delete(c));for(const c of f.querySelectorAll("[data-help]:not([data-help-ready])"))ue.set(c,xn(c,{position:"bottom"}))};st();const ot=new MutationObserver(st);ot.observe(f,{childList:!0,subtree:!0}),C(()=>{ot.disconnect();for(const c of ue.values())c();ue.clear()}),Ve(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>De()}),Ve(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),I&&Ve(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(I)}/submissions`}});const lt=c=>{n()||!(c.ctrlKey||c.metaKey)||String(c.key).toLowerCase()!=="s"||(c.preventDefault(),c.stopImmediatePropagation(),De())};document.addEventListener("keydown",lt,!0),C(()=>document.removeEventListener("keydown",lt,!0));const Z=e.find("#fields-list").get(0),ln=c=>c?.closest?.(".fb-field-card"),rt=c=>Number(c?.dataset.index),ct=c=>c?.querySelector(":scope > .fb-field-body"),dt=c=>{const h=ct(c);h&&(h.style.display=h.style.display==="none"?"":"none")},pe=(c,h)=>{T=c,ne(e),h!=null&&Z?.querySelectorAll(".fb-field-card")[h]?.focus()},rn=async c=>{try{await navigator.clipboard.writeText(c),E.toast(`Copied "${c}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${c}.`,{type:"info"})}},cn=c=>{const h=ln(c),g=rt(h);V();const k=T[g];if(!k)return[];const N=k.type!=="spacer"&&k.type!=="page-break",H=ct(h),K=H&&H.style.display!=="none";return[{header:We(k)},...H?[{label:K?"Close":"Edit",icon:K?"chevron-up":"edit",action:()=>dt(h)}]:[],...N?[{label:"Logic & triggers",icon:"zap",action:()=>{H&&(H.style.display=""),(H?.querySelector(".fb-field-logic")||H)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{V(),pe(Sn(T,g),g+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",shortcut:"Alt+\u2191",disabled:g===0,action:()=>{V(),pe(St(T,g,-1),g-1)}},{label:"Move down",icon:"arrow-down",shortcut:"Alt+\u2193",disabled:g>=T.length-1,action:()=>{V(),pe(St(T,g,1),g+1)}},...N&&k.name?[{label:"Copy field name",icon:"clipboard",action:()=>rn(k.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(k.type!=="spacer"&&!await E.confirm(`Remove "${nn(We(k))}"?`))return;V();const me=[...T];me.splice(g,1),pe(me,Math.min(g,me.length-1))}}]};if(Z&&typeof E.sortable=="function"){const c=E.sortable(Z,{items:".fb-field-card",handle:".fb-drag-grip",key:null,onSort:({from:h,to:g})=>{V();const k=[...T],[N]=k.splice(h,1);k.splice(g,0,N),pe(k,g)}});C(()=>c.destroy())}let ut=null;if(Z&&E.contextMenu&&(ut=E.contextMenu(Z,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:c=>cn(c)}),C(()=>ut?.destroy?.())),ve=c=>{for(const h of c.querySelectorAll(".fb-field-card")){h.tabIndex=0;const g=h.firstElementChild;if(!g||g.querySelector(".fex-kebab"))continue;const k=document.createElement("button");k.type="button",k.className="fex-kebab",k.textContent="\u22EE",k.title="Actions",V(),k.setAttribute("aria-label",`Actions for ${We(T[rt(h)])}`),k.addEventListener("click",N=>{N.stopPropagation(),Ct(k)}),g.appendChild(k)}},Z){ve(Z);const c=h=>{const g=h.target?.classList?.contains("fb-field-card")?h.target:null;g&&(h.key==="F10"&&h.shiftKey?(h.preventDefault(),Ct(g.firstElementChild)):h.key==="Enter"&&(h.preventDefault(),dt(g)))};Z.addEventListener("keydown",c),C(()=>Z.removeEventListener("keydown",c))}const pt=()=>{try{const c=he(q);S.remove?S.remove(c):S.set(c,null)}catch{}},mt=c=>{if(!o){if(!b.peek()||!c){!_&&!j&&pt();return}try{S.set(he(q),{data:kn(c),base:Cn(B,Et(U)),...W?{newFrom:!0}:{},at:new Date().toISOString()})}catch{}}},ft=c=>{le(),b.peek()&&(mt(ae),c.preventDefault(),c.returnValue="")};if(window.addEventListener("beforeunload",ft),C(()=>window.removeEventListener("beforeunload",ft)),C(()=>{oe&&(document.removeEventListener("click",oe),oe=null)}),J={path:t,dirty:()=>b.peek(),flush:()=>{clearTimeout(de),le()},dispose(){x||(mt(ae),x=!0,y.splice(0).reverse().forEach(c=>{try{c?.()}catch{}}))}},o){const c=document.createElement("p");c.className="fex-load-error",c.setAttribute("role","alert"),c.textContent=o.missing?"This form no longer exists - it may have been deleted. Nothing here can be saved over it.":`This form could not be loaded (${o.message}). Saving is off so an empty editor cannot replace it - reload the page to try again.`;const h=f.querySelector(".fex-bar");h?h.before(c):f.prepend(c),C(()=>c.remove())}const ze=he(I);let ee=null;try{ee=S.get(ze)}catch{}if(ee?.data&&(!o||o.missing)){const c=!!o?.missing,h=En(ee,{missing:c});_=!0;const g=await E.confirm(nn(Tn(ee,{current:Et(U),missing:c,when:ee.at?Nn(ee.at):""})),{title:"Unsaved changes",confirmText:"Throw away",cancelText:h==="new"?"Start a new form":h==="refuse"?"Not now":"Keep them"});if(_=!1,g)try{S.remove?S.remove(ze):S.set(ze,null)}catch{}else h==="refuse"?j=!0:x||(c?(I=null,o=null,B="",W=!0,Y=Ce(e),U=Ee(Y),at(f,"New form"),f.querySelector(".fex-load-error")?.remove(),Re(ee.data)):(B=ee.base??"",Re(Ln(ee.data,Y))),le())}}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.10.31",
3
+ "version": "1.10.32",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",