domma-cms 0.92.1 → 0.94.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CLAUDE.md +5 -3
  2. package/admin/css/admin.css +1 -1
  3. package/admin/js/app.js +2 -2
  4. package/admin/js/lib/action-editor-arrange.js +1 -1
  5. package/admin/js/lib/api-tokens-arrange.js +2 -2
  6. package/admin/js/lib/block-editor-arrange.js +1 -1
  7. package/admin/js/lib/blocks-arrange.js +1 -1
  8. package/admin/js/lib/collection-entries-arrange.js +1 -1
  9. package/admin/js/lib/components-arrange.js +1 -1
  10. package/admin/js/lib/dashboard-arrange.js +1 -1
  11. package/admin/js/lib/dates.js +1 -0
  12. package/admin/js/lib/forms-arrange.js +1 -1
  13. package/admin/js/lib/media-arrange.js +1 -1
  14. package/admin/js/lib/notifications-arrange.js +1 -1
  15. package/admin/js/lib/pages-arrange.js +1 -1
  16. package/admin/js/lib/related.js +1 -1
  17. package/admin/js/lib/timeline-builder.js +2 -2
  18. package/admin/js/templates/action-editor.html +6 -5
  19. package/admin/js/templates/actions-list.html +1 -1
  20. package/admin/js/templates/contacts.html +1 -1
  21. package/admin/js/templates/docs/api-actions.html +86 -60
  22. package/admin/js/templates/docs/api-authentication.html +159 -123
  23. package/admin/js/templates/docs/api-builder.html +197 -0
  24. package/admin/js/templates/docs/api-collections.html +199 -259
  25. package/admin/js/templates/docs/api-external.html +225 -0
  26. package/admin/js/templates/docs/api-forms.html +268 -0
  27. package/admin/js/templates/docs/api-layouts.html +70 -45
  28. package/admin/js/templates/docs/api-media.html +57 -80
  29. package/admin/js/templates/docs/api-navigation.html +66 -22
  30. package/admin/js/templates/docs/api-pages.html +109 -129
  31. package/admin/js/templates/docs/api-plugins.html +123 -61
  32. package/admin/js/templates/docs/api-scaffold.html +185 -0
  33. package/admin/js/templates/docs/api-settings.html +72 -64
  34. package/admin/js/templates/docs/api-users.html +74 -107
  35. package/admin/js/templates/docs/api-views.html +68 -54
  36. package/admin/js/templates/docs/components-howto.html +20 -17
  37. package/admin/js/templates/docs/components-reference.html +13 -16
  38. package/admin/js/templates/docs/components-rules.html +7 -6
  39. package/admin/js/templates/docs/components-walkthrough.html +19 -19
  40. package/admin/js/templates/docs/tutorial-crud.html +71 -40
  41. package/admin/js/templates/docs/tutorial-forms.html +51 -35
  42. package/admin/js/templates/docs/tutorial-plugin.html +132 -56
  43. package/admin/js/templates/docs/usage-actions.html +61 -15
  44. package/admin/js/templates/docs/usage-collections.html +108 -0
  45. package/admin/js/templates/docs/usage-cta-shortcode.html +14 -3
  46. package/admin/js/templates/docs/usage-dconfig.html +0 -3
  47. package/admin/js/templates/docs/usage-editions.html +213 -0
  48. package/admin/js/templates/docs/usage-media.html +22 -6
  49. package/admin/js/templates/docs/usage-navigation.html +74 -18
  50. package/admin/js/templates/docs/usage-pages.html +60 -20
  51. package/admin/js/templates/docs/usage-plugins.html +89 -17
  52. package/admin/js/templates/docs/usage-shortcodes.html +123 -70
  53. package/admin/js/templates/docs/usage-site-settings.html +50 -18
  54. package/admin/js/templates/docs/usage-tools.html +73 -0
  55. package/admin/js/templates/docs/usage-users-roles.html +99 -20
  56. package/admin/js/templates/docs/usage-views.html +36 -19
  57. package/admin/js/templates/documentation.html +153 -32
  58. package/admin/js/templates/page-editor.html +0 -5
  59. package/admin/js/templates/plugin-guide.html +15 -0
  60. package/admin/js/templates/plugin-guides.html +21 -0
  61. package/admin/js/templates/pro-docs.html +53 -234
  62. package/admin/js/templates/tutorials.html +5 -4
  63. package/admin/js/views/actions-list.js +3 -3
  64. package/admin/js/views/analytics.js +5 -5
  65. package/admin/js/views/api-endpoint-editor.js +2 -2
  66. package/admin/js/views/block-editor.js +4 -4
  67. package/admin/js/views/blocks.js +4 -4
  68. package/admin/js/views/collection-editor.js +4 -4
  69. package/admin/js/views/collection-entries.js +7 -7
  70. package/admin/js/views/component-editor.js +2 -2
  71. package/admin/js/views/contacts.js +22 -20
  72. package/admin/js/views/context-menu-editor.js +5 -5
  73. package/admin/js/views/doc-pages.js +1 -1
  74. package/admin/js/views/form-editor.js +4 -4
  75. package/admin/js/views/form-submissions.js +2 -2
  76. package/admin/js/views/index.js +1 -1
  77. package/admin/js/views/media.js +3 -3
  78. package/admin/js/views/menu-editor.js +13 -13
  79. package/admin/js/views/menu-locations.js +2 -2
  80. package/admin/js/views/my-profile.js +1 -1
  81. package/admin/js/views/page-editor.js +8 -8
  82. package/admin/js/views/plugin-guides.js +5 -0
  83. package/admin/js/views/project-detail.js +2 -2
  84. package/admin/js/views/project-settings.js +1 -1
  85. package/admin/js/views/role-editor.js +4 -4
  86. package/admin/js/views/search.js +2 -2
  87. package/admin/js/views/seo.js +17 -17
  88. package/admin/js/views/settings.js +3 -3
  89. package/admin/js/views/theme.js +3 -3
  90. package/admin/js/views/user-editor.js +1 -1
  91. package/admin/js/views/users.js +2 -2
  92. package/admin/js/views/view-editor.js +1 -1
  93. package/bin/cli.js +13 -13
  94. package/bin/lib/node-version.js +29 -0
  95. package/package.json +1 -1
  96. package/plugins/_lib/admin/mail/compose-window.js +3 -2
  97. package/plugins/_lib/admin/mail/reader-view.js +7 -6
  98. package/plugins/_lib/admin/mail/scheduling.js +4 -2
  99. package/plugins/_lib/admin/mail/templates.js +4 -4
  100. package/plugins/_lib/admin/ui/dates.js +85 -0
  101. package/plugins/blog/CLAUDE.md +31 -22
  102. package/plugins/blog/admin/views/blog.js +3 -2
  103. package/plugins/blog/admin/views/comments.js +2 -1
  104. package/plugins/blog/admin/views/post-editor.js +4 -4
  105. package/plugins/blog/blocks/blog-card-row.html +1 -1
  106. package/plugins/blog/blocks/blog-card.html +2 -2
  107. package/plugins/blog/blocks/blog-post-classic.html +2 -2
  108. package/plugins/blog/blocks/blog-post-essay.html +2 -2
  109. package/plugins/blog/blocks/blog-post-feature.html +2 -2
  110. package/plugins/blog/blocks/blog-post-minimal.html +2 -2
  111. package/plugins/blog/blocks/blog-post-sidebar.html +2 -2
  112. package/plugins/blog/blocks/blog-post-split.html +2 -2
  113. package/plugins/blog/docs/guide.md +205 -0
  114. package/plugins/blog/lib/layouts.js +3 -3
  115. package/plugins/blog/lib/page.js +2 -1
  116. package/plugins/blog/plugin.js +3 -3
  117. package/plugins/blog/plugin.json +4 -4
  118. package/plugins/blog/tests/layouts.test.js +6 -0
  119. package/plugins/feedback/CLAUDE.md +22 -3
  120. package/plugins/feedback/admin/lib/kit.js +6 -7
  121. package/plugins/feedback/admin/views/feedback.js +79 -10
  122. package/plugins/feedback/admin/views/send.js +28 -6
  123. package/plugins/feedback/docs/guide.md +95 -0
  124. package/plugins/feedback/lib/receiver.js +9 -2
  125. package/plugins/feedback/lib/sender.js +3 -2
  126. package/plugins/feedback/plugin.js +54 -6
  127. package/plugins/feedback/plugin.json +4 -4
  128. package/plugins/feedback/tests/api.test.js +74 -2
  129. package/plugins/free-tier.lock.json +49 -44
  130. package/plugins/mail-reader/CLAUDE.md +33 -18
  131. package/plugins/mail-reader/docs/guide.md +147 -0
  132. package/plugins/mail-reader/plugin.json +1 -1
  133. package/plugins/security/CLAUDE.md +4 -1
  134. package/plugins/security/admin/views/security.js +5 -5
  135. package/plugins/security/docs/guide.md +170 -0
  136. package/plugins/security/plugin.js +2 -1
  137. package/plugins/security/plugin.json +2 -1
  138. package/plugins/shopping-cart/CLAUDE.md +7 -1
  139. package/plugins/shopping-cart/admin/lib/kit.js +5 -2
  140. package/plugins/shopping-cart/admin/views/orders.js +4 -4
  141. package/plugins/shopping-cart/admin/views/overview.js +2 -2
  142. package/plugins/shopping-cart/docs/guide.md +191 -0
  143. package/plugins/shopping-cart/lib/render.js +2 -1
  144. package/plugins/shopping-cart/plugin.json +3 -3
  145. package/public/js/collection-browser.js +2 -2
  146. package/public/js/site.js +1 -1
  147. package/scripts/gen-instance-secret.js +3 -1
  148. package/scripts/setup.js +3 -1
  149. package/server/middleware/auth.js +2 -1
  150. package/server/routes/api/actions.js +47 -27
  151. package/server/routes/api/blocks.js +2 -1
  152. package/server/routes/api/collections.js +16 -52
  153. package/server/routes/api/contacts.js +66 -3
  154. package/server/routes/api/documentation.js +42 -0
  155. package/server/routes/api/notifications.js +3 -2
  156. package/server/routes/api/users.js +10 -6
  157. package/server/server.js +16 -1
  158. package/server/services/actions.js +110 -34
  159. package/server/services/adapterRegistry.js +169 -16
  160. package/server/services/adapters/FileAdapter.js +25 -0
  161. package/server/services/adapters/MongoAdapter.js +23 -0
  162. package/server/services/collections.js +104 -1
  163. package/server/services/connectionManager.js +12 -0
  164. package/server/services/dates.js +81 -0
  165. package/server/services/docs.js +13 -2
  166. package/server/services/markdown.js +75 -26
  167. package/server/services/notification-sources.js +6 -5
  168. package/server/services/passwordReset.js +2 -1
  169. package/server/services/permissionRegistry.js +3 -2
  170. package/server/services/pluginGuides.js +255 -0
  171. package/server/services/pluginInstaller.js +54 -13
  172. package/server/services/plugins.js +29 -1
  173. package/server/services/presetCollections.js +31 -5
  174. package/server/services/renderer.js +2 -2
  175. package/server/services/sidebarBadges.js +3 -1
  176. package/server/services/tools.js +4 -2
  177. package/server/templates/page.html +2 -2
@@ -1,8 +1,8 @@
1
- import{apiRequest as se}from"/admin/js/api.js";import{makeIconInput as zt}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as nt}from"/public/js/forms.js";import{buildWizardSteps as Pt}from"/public/js/form-steps.mjs";import{addBannerAction as Ae}from"../lib/plugin-chrome.js";import{helpPopovers as _t}from"../lib/help-popover.js";import{openMenuAt as lt,sidebarCount as jt}from"../lib/tool-kit.js";import{draftKey as re,draftOf as Vt,duplicateField as Gt,fieldTitle as Fe,fingerprint as at,leavingEditor as ot,moveField as it,restoreDraft as Ht,snapshotOf as Ie}from"../lib/form-editor-arrange.js";const st=[{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"}],Be=new Set(["select","radio","checkbox-group","chooser"]);let C=[],be=[],N=null,ge=null,le=null,ye={};function q(e,t,o=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(o)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function ce(e,t,o,n=14){return q(e,t,n),e.appendChild(document.createTextNode(" "+o)),e}function Oe(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 ve=null,rt=null,Me=null,de=null;function Re(){Me?.(),clearTimeout(rt),rt=setTimeout(()=>{ve&&ve()},350)}function ct(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function dt(e){return st.find(t=>t.value===e)?.label||e}function pt(e){return(e||[]).some(t=>t.logic||Array.isArray(t.triggers)&&t.triggers.length)}function ut(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function Wt(e){const t={...C[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const f=document.getElementById(`fb-pb-label-${e}`),x=document.getElementById(`fb-pb-desc-${e}`);return f&&(t.label=f.value.trim()||t.label),x&&(t.description=x.value.trim()),t}const o=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),a=document.getElementById(`fb-required-${e}`),i=document.getElementById(`fb-placeholder-${e}`),r=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(o&&(t.label=o.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),l&&(t.type=l.value||t.type),a&&(t.required=a.checked),i&&(t.placeholder=i.value.trim()),r&&(t.helper=r.value.trim()),c&&(t.tooltip=c.value.trim()),t.type==="chooser"){const f=document.getElementById(`fb-chooser-variant-${e}`)?.value;f&&(t.variant=f);const x=document.getElementById(`fb-chooser-multiple-${e}`);x&&(t.multiple=x.checked);const $=document.getElementById(`fb-chooser-density-${e}`)?.value;$&&(t.density=$);const A=document.getElementById(`fb-chooser-columns-${e}`)?.value;A!==""&&A!==void 0&&(t.columns=parseInt(A,10)||3);const H=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();H?t.accent=H:delete t.accent;const _=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;_?t.accentStyle=_:delete t.accentStyle;const j=document.getElementById(`fb-chooser-glow-${e}`);j&&(t.glow=j.checked);const I=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();I?t.glowColour=I:delete t.glowColour;const X=document.getElementById(`fb-chooser-shadow-${e}`)?.value;X&&X!=="none"?t.shadow=X:delete t.shadow;const U=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();U?t.shadowColour=U:delete t.shadowColour,Se(e),C[e]&&Array.isArray(C[e].options)&&(t.options=C[e].options)}else if(Be.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(x=>delete t[x]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const f=document.getElementById(`fb-options-${e}`);f&&(t.options=f.value.split(`
1
+ import{apiRequest as ie}from"/admin/js/api.js";import{makeIconInput as Mt}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as tt}from"/public/js/forms.js";import{buildWizardSteps as zt}from"/public/js/form-steps.mjs";import{addBannerAction as $e}from"../lib/plugin-chrome.js";import{helpPopovers as Pt}from"../lib/help-popover.js";import{openMenuAt as nt,sidebarCount as _t}from"../lib/tool-kit.js";import{draftKey as se,draftOf as jt,duplicateField as Vt,fieldTitle as Ae,fingerprint as lt,leavingEditor as at,moveField as ot,restoreDraft as Gt,snapshotOf as Fe}from"../lib/form-editor-arrange.js";import{fmtDateTime as Wt}from"../lib/dates.js";const it=[{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"}],Ie=new Set(["select","radio","checkbox-group","chooser"]);let C=[],he=[],N=null,be=null,ne=null,ge={};function q(e,t,o=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(o)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function re(e,t,o,n=14){return q(e,t,n),e.appendChild(document.createTextNode(" "+o)),e}function Be(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 ye=null,st=null,Oe=null,ce=null;function Re(){Oe?.(),clearTimeout(st),st=setTimeout(()=>{ye&&ye()},350)}function rt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function ct(e){return it.find(t=>t.value===e)?.label||e}function dt(e){return(e||[]).some(t=>t.logic||Array.isArray(t.triggers)&&t.triggers.length)}function pt(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function Ht(e){const t={...C[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const f=document.getElementById(`fb-pb-label-${e}`),x=document.getElementById(`fb-pb-desc-${e}`);return f&&(t.label=f.value.trim()||t.label),x&&(t.description=x.value.trim()),t}const o=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),a=document.getElementById(`fb-required-${e}`),i=document.getElementById(`fb-placeholder-${e}`),r=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(o&&(t.label=o.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),l&&(t.type=l.value||t.type),a&&(t.required=a.checked),i&&(t.placeholder=i.value.trim()),r&&(t.helper=r.value.trim()),c&&(t.tooltip=c.value.trim()),t.type==="chooser"){const f=document.getElementById(`fb-chooser-variant-${e}`)?.value;f&&(t.variant=f);const x=document.getElementById(`fb-chooser-multiple-${e}`);x&&(t.multiple=x.checked);const $=document.getElementById(`fb-chooser-density-${e}`)?.value;$&&(t.density=$);const A=document.getElementById(`fb-chooser-columns-${e}`)?.value;A!==""&&A!==void 0&&(t.columns=parseInt(A,10)||3);const G=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();G?t.accent=G:delete t.accent;const P=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;P?t.accentStyle=P:delete t.accentStyle;const _=document.getElementById(`fb-chooser-glow-${e}`);_&&(t.glow=_.checked);const I=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();I?t.glowColour=I:delete t.glowColour;const Q=document.getElementById(`fb-chooser-shadow-${e}`)?.value;Q&&Q!=="none"?t.shadow=Q:delete t.shadow;const H=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();H?t.shadowColour=H:delete t.shadowColour,ke(e),C[e]&&Array.isArray(C[e].options)&&(t.options=C[e].options)}else if(Ie.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(x=>delete t[x]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const f=document.getElementById(`fb-options-${e}`);f&&(t.options=f.value.split(`
2
2
  `).filter(x=>x.trim()).map(x=>{const[$,...A]=x.split(":");return{value:$.trim(),label:A.join(":").trim()||$.trim()}}))}if(t.type==="textarea"){const f=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);f>0&&(t.formConfig={...t.formConfig||{},rows:f})}const s=document.getElementById(`fb-span-${e}`),d=document.getElementById(`fb-fullwidth-${e}`);if(s||d){const f={...t.formConfig||{}};if(d?.checked)f.span="full";else{const x=parseInt(s?.value,10);x>1?f.span=x:delete f.span}t.formConfig=Object.keys(f).length?f:void 0}const u=document.getElementById(`fb-minlength-${e}`)?.value;u&&(t.minLength=parseInt(u,10));const b=document.getElementById(`fb-maxlength-${e}`)?.value;b&&(t.maxLength=parseInt(b,10));const g=document.getElementById(`fb-min-${e}`)?.value;g!==""&&g!==void 0&&(t.min=parseFloat(g));const m=document.getElementById(`fb-max-${e}`)?.value;m!==""&&m!==void 0&&(t.max=parseFloat(m));const h=Ut(e);h?t.logic=h:delete t.logic;const w=dn(e);return w?t.triggers=w:delete t.triggers,t}function Ut(e){const t=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!t)return;const o=t.querySelector(".fb-field-logic");if(!o)return;const n={};let l=!1;const a=o.querySelector('[data-logic-section="visibility"]');if(a){const s=a.querySelector(".fb-logic-vis-default"),d=a.querySelector(".fb-logic-vis-transition"),u=Array.from(a.querySelectorAll(".fb-logic-cond-row")).map(h=>{const w=h.querySelector(".fb-logic-cond-field"),f=h.querySelector(".fb-logic-cond-op"),x=h.querySelector(".fb-logic-cond-val"),$=h.querySelector(".fb-logic-vis-then");return w?.value?{when:{all:[{field:w.value,operator:f.value,value:x.value}]},then:$.value}:null}).filter(Boolean),b=s?.value||"visible",g=d?.value||"none",m=parseInt(a.querySelector(".fb-logic-vis-duration")?.value||"",10);(b!=="visible"||u.length>0||g!=="none")&&(n.visibility={default:b,conditions:u},g!=="none"&&(n.visibility.transition=g),g!=="none"&&Number.isFinite(m)&&(n.visibility.duration=m),l=!0)}const i=o.querySelector('[data-logic-section="requirement"]');if(i){const s=i.querySelector(".fb-logic-req-default"),d=Array.from(i.querySelectorAll(".fb-logic-cond-row")).map(u=>{const b=u.querySelector(".fb-logic-cond-field"),g=u.querySelector(".fb-logic-cond-op"),m=u.querySelector(".fb-logic-cond-val"),h=u.querySelector(".fb-logic-req-then");return b?.value?{when:{all:[{field:b.value,operator:g.value,value:m.value}]},then:h.value==="true"}:null}).filter(Boolean);d.length>0&&(n.requirement={default:s?.checked===!0,conditions:d},l=!0)}const r=o.querySelector('[data-logic-section="validation"]');if(r){const s=Array.from(r.querySelectorAll(".fb-logic-val-rule")).map(d=>{const u=d.querySelector(".fb-logic-val-type"),b=d.querySelector(".fb-logic-val-pattern"),g=d.querySelector(".fb-logic-val-flags"),m=d.querySelector(".fb-logic-val-message");if(!b?.value.trim())return null;const h=u?.value||"regex",w={type:h,message:m?.value.trim()||"Invalid value."};return h==="regex"?(w.pattern=b.value.trim(),g?.value.trim()&&(w.flags=g.value.trim())):w.field=b.value.trim(),w}).filter(Boolean);s.length>0&&(n.validation=s,l=!0)}const c=o.querySelector('[data-logic-section="cascade"]');if(c){const s=c.querySelector(".fb-logic-cascade-source"),d=c.querySelector(".fb-logic-cascade-mapping"),u=c.querySelector(".fb-logic-cascade-defaults"),b=s?.value?.trim();if(b){let g={};try{g=JSON.parse(d?.value||"{}")}catch{}const m=(u?.value||"").split(`
3
- `).filter(h=>h.trim()).map(h=>{const[w,...f]=h.split(":");return{value:w.trim(),label:f.join(":").trim()||w.trim()}});n.cascade={sourceField:b,mapping:g,defaultOptions:m},l=!0}}return l?n:void 0}function O(){C=C.map((e,t)=>Wt(t))}let ae=null;function Jt(e,t,o){const n=e.firstElementChild;if(!n)return;const l=document.createElement("span");l.setAttribute("data-icon","menu"),l.setAttribute("data-icon-size","13"),l.title="Drag to reorder",l.style.cssText="cursor:grab;opacity:.35;flex-shrink:0;display:inline-flex;align-items:center;",n.insertBefore(l,n.firstChild),window.I?.scan?.(n),n.draggable=!0,n.addEventListener("dragstart",a=>{ae=t,a.dataTransfer.effectAllowed="move",e.style.opacity="0.4"}),n.addEventListener("dragend",()=>{e.style.opacity="",document.querySelectorAll("#fields-list .fb-field-card").forEach(a=>a.classList.remove("fb-drag-over"))}),e.addEventListener("dragover",a=>{ae!=null&&(a.preventDefault(),a.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(i=>i.classList.remove("fb-drag-over")),e.classList.add("fb-drag-over"))}),e.addEventListener("dragleave",()=>e.classList.remove("fb-drag-over")),e.addEventListener("drop",a=>{if(a.preventDefault(),e.classList.remove("fb-drag-over"),ae==null||ae===t){ae=null;return}O();const[i]=C.splice(ae,1);C.splice(t,0,i),ae=null,Y(o)})}function Y(e){const t=e.find("#fields-list").get(0),o=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),C.length===0){o&&(o.style.display=""),de?.(t),Re();return}o&&(o.style.display="none"),C.forEach((n,l)=>{const a=n.type==="page-break"?Yt(n,l,e):n.type==="spacer"?Kt(n,l,e):Qt(n,l,e);Jt(a,l,e),t.appendChild(a)}),de?.(t),Re()}}function Yt(e,t,o){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 i=document.createElement("span");i.textContent=e.label||"Untitled Step",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted);";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit step",q(c,"more-horizontal"),c.addEventListener("click",g=>{g.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove page break",q(s,"x"),s.addEventListener("click",async g=>{g.stopPropagation(),await E.confirm("Remove this page break?")&&(O(),C.splice(t,1),Y(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=document.createElement("div");d.className="fb-field-body",d.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const u=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")]),b=u.querySelector(`#fb-pb-label-${t}`);return b&&b.addEventListener("input",()=>{i.textContent=b.value||"Untitled Step"}),d.appendChild(u),n.appendChild(l),n.appendChild(d),n}function Kt(e,t,o){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 i=document.createElement("span");i.textContent="Spacer",i.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const r=document.createElement("div");r.style.cssText="flex:1;height:1px;background:var(--dm-border);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const s=document.createElement("button");return s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove spacer",q(s,"x"),s.addEventListener("click",async d=>{d.stopPropagation(),O(),C.splice(t,1),Y(o)}),c.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.appendChild(c),n.appendChild(l),n}function Qt(e,t,o){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=dt(e.type),a.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary);white-space:nowrap;flex-shrink:0;";const i=document.createElement("span");i.textContent=e.label||"(unlabelled)",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit field",q(c,"more-horizontal"),c.addEventListener("click",u=>{u.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");if(s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove field",q(s,"x"),s.addEventListener("click",async u=>{u.stopPropagation(),await E.confirm("Remove this field?")&&(O(),C.splice(t,1),Y(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),e.required){const u=document.createElement("span");u.textContent="required",u.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",l.appendChild(u)}if(ut(e.logic)){const u=document.createElement("span");q(u,"zap"),u.title="Has conditional logic",u.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",l.appendChild(u)}l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=Xt(e,t,i);return d.style.display="none",n.appendChild(l),n.appendChild(d),n}function Xt(e,t,o){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=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")]),a=z([gn("Type",`fb-type-${t}`,st,e.type||"string"),qt("Required",`fb-required-${t}`,e.required||!1)]),i=z([P("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),r=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")]),c=e.formConfig?.span,s=z([P("Column Span",`fb-span-${t}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),qt("Full Width",`fb-fullwidth-${t}`,c==="full")]);s.classList.add("fb-grid-row"),s.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(l),n.appendChild(a),n.appendChild(i),n.appendChild(r),n.appendChild(s);const d=n.querySelector(`#fb-label-${t}`),u=n.querySelector(`#fb-name-${t}`);d&&d.addEventListener("input",()=>{o&&(o.textContent=d.value||"(unlabelled)"),u&&!u.dataset.manuallyEdited&&(u.value=ct(d.value))}),u&&u.addEventListener("input",()=>{u.dataset.manuallyEdited="1"});const b=n.querySelector(`#fb-type-${t}`);b&&b.addEventListener("change",()=>{const m=n.closest(".fb-field-card");if(m){const f=m.querySelector("span");f&&(f.textContent=dt(b.value))}const h=n.querySelector(".fb-field-extras");h&&h.remove();const w=St(b.value,e,t);w&&n.appendChild(w)});const g=St(e.type,e,t);return g&&n.appendChild(g),n.appendChild(ln(e,t)),n.appendChild(rn(e,t)),n}const xe=[{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"}],De=new Set(["is_empty","is_not_empty"]),mt={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 ze(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function Ce(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 Ee(e,t,o,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 i=document.createElement("span");i.textContent="When",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-cond-field",r.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,e&&m.value===e.field&&(h.selected=!0),r.appendChild(h)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",xe.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,e&&m.value===e.operator&&(h.selected=!0),c.appendChild(h)});const s=()=>{const m=t.find(h=>h.value===r.value);Array.from(c.options).forEach(h=>{const w=xe.find(f=>f.value===h.value);h.textContent=m?.multi&&mt[h.value]||w?.label||h.value})};s(),r.addEventListener("change",s);const d=document.createElement("input");d.type="text",d.className="form-input fb-logic-cond-val",d.placeholder="value",d.style.cssText="flex:1 1 120px;min-width:100px;",d.value=e?.value||"",e&&De.has(e.operator)&&(d.style.display="none"),c.addEventListener("change",()=>{d.style.display=De.has(c.value)?"none":""});const u=document.createElement("span");q(u,"arrow-right"),u.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const b=document.createElement("select");b.className=`form-select ${n}`,b.style.cssText="flex:1 1 140px;min-width:120px;",o.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,m.value===l&&(h.selected=!0),b.appendChild(h)});const g=document.createElement("button");return g.type="button",g.className="btn btn-xs btn-ghost",g.style.cssText="line-height:1;opacity:.6;",q(g,"x"),g.style.flexShrink="0",g.addEventListener("click",()=>a.remove()),a.appendChild(i),a.appendChild(r),a.appendChild(c),a.appendChild(d),a.appendChild(u),a.appendChild(b),a.appendChild(g),a}function Zt(e,t,o){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(Ce("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const a=document.createElement("span");a.textContent="Default:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-vis-default",i.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===(e.default||"visible")&&(x.selected=!0),i.appendChild(x)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const c=document.createElement("span");c.textContent="Transition:",c.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-vis-transition",s.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===(e.transition||"none")&&(x.selected=!0),s.appendChild(x)}),r.appendChild(c),r.appendChild(s),n.appendChild(r);const d=document.createElement("div");d.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const u=document.createElement("span");u.textContent="Speed:",u.style.cssText="font-size:.8rem;flex-shrink:0;";const b=document.createElement("select");b.className="form-select fb-logic-vis-duration",b.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(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===String(e.duration??"")&&(x.selected=!0),b.appendChild(x)}),d.appendChild(u),d.appendChild(b),n.appendChild(d);const g=()=>{d.style.display=s.value==="none"?"none":""};g(),s.addEventListener("change",g);const m=document.createElement("div");m.className="fb-logic-vis-rules";const h=o.map(f=>({value:f.name,label:f.label||f.name,multi:ze(f)})),w=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(f=>{const x=(f.when?.all||f.when?.any||[])[0],$=f.then==="hidden"?"hidden":"visible";h.length>0&&m.appendChild(Ee(x,h,w,"fb-logic-vis-then",$))}),n.appendChild(m),h.length>0){const f=document.createElement("button");f.type="button",f.className="btn btn-xs btn-ghost",f.style.cssText="font-size:.73rem;margin-top:.35rem;",ce(f,"plus","Add visibility rule"),f.addEventListener("click",()=>m.appendChild(Ee(null,h,w,"fb-logic-vis-then","visible"))),n.appendChild(f)}return n}function en(e,t,o){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(Ce("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 i=document.createElement("div");i.className="fb-logic-req-rules";const r=o.map(s=>({value:s.name,label:s.label||s.name,multi:ze(s)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(s=>{const d=(s.when?.all||s.when?.any||[])[0],u=s.then===!0?"true":"false";r.length>0&&i.appendChild(Ee(d,r,c,"fb-logic-req-then",u))}),n.appendChild(i),r.length>0){const s=document.createElement("button");s.type="button",s.className="btn btn-xs btn-ghost",s.style.cssText="font-size:.73rem;margin-top:.35rem;",ce(s,"plus","Add requirement rule"),s.addEventListener("click",()=>i.appendChild(Ee(null,r,c,"fb-logic-req-then","true"))),n.appendChild(s)}return n}function ft(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 o=document.createElement("select");o.className="form-select fb-logic-val-type",o.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===(e?.type||"regex")&&(c.selected=!0),o.appendChild(c)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),o.addEventListener("change",()=>{l.style.display=o.value==="match"?"none":"",n.placeholder=o.value==="match"?"field name":"pattern"});const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-message",a.placeholder="Error message",a.value=e?.message||"",a.style.cssText="flex:4;";const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="line-height:1;opacity:.6;",q(i,"x"),i.style.flexShrink="0",i.addEventListener("click",()=>t.remove()),t.appendChild(o),t.appendChild(n),t.appendChild(l),t.appendChild(a),t.appendChild(i),t}function tn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(Ce("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(i=>l.appendChild(ft(i))),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;",ce(a,"plus","Add validation rule"),a.addEventListener("click",()=>l.appendChild(ft(null))),n.appendChild(a),n}function nn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(Ce("Cascade Options")),n.lastChild.appendChild(Oe("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const a=document.createElement("span");a.textContent="Source field:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-cascade-source",i.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",i.appendChild(r),o.forEach(b=>{const g=document.createElement("option");g.value=b.name,g.textContent=b.label||b.name,b.name===e.sourceField&&(g.selected=!0),i.appendChild(g)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Oe(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),c.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const s=document.createElement("textarea");s.className="form-input fb-logic-cascade-mapping",s.rows=4,s.style.cssText="font-family:monospace;",s.placeholder='{"uk": [{"value": "london", "label": "London"}]}',s.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(c),n.appendChild(s);const d=document.createElement("p");d.textContent="Default options (one per line: value:Label)",d.appendChild(Oe("Shown before the source field has a value, or when its value has no mapping entry.")),d.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const u=document.createElement("textarea");return u.className="form-input fb-logic-cascade-defaults",u.rows=3,u.style.cssText="font-family:monospace;",u.placeholder=`option1:Option 1
3
+ `).filter(h=>h.trim()).map(h=>{const[w,...f]=h.split(":");return{value:w.trim(),label:f.join(":").trim()||w.trim()}});n.cascade={sourceField:b,mapping:g,defaultOptions:m},l=!0}}return l?n:void 0}function O(){C=C.map((e,t)=>Ht(t))}let le=null;function Jt(e,t,o){const n=e.firstElementChild;if(!n)return;const l=document.createElement("span");l.setAttribute("data-icon","menu"),l.setAttribute("data-icon-size","13"),l.title="Drag to reorder",l.style.cssText="cursor:grab;opacity:.35;flex-shrink:0;display:inline-flex;align-items:center;",n.insertBefore(l,n.firstChild),window.I?.scan?.(n),n.draggable=!0,n.addEventListener("dragstart",a=>{le=t,a.dataTransfer.effectAllowed="move",e.style.opacity="0.4"}),n.addEventListener("dragend",()=>{e.style.opacity="",document.querySelectorAll("#fields-list .fb-field-card").forEach(a=>a.classList.remove("fb-drag-over"))}),e.addEventListener("dragover",a=>{le!=null&&(a.preventDefault(),a.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(i=>i.classList.remove("fb-drag-over")),e.classList.add("fb-drag-over"))}),e.addEventListener("dragleave",()=>e.classList.remove("fb-drag-over")),e.addEventListener("drop",a=>{if(a.preventDefault(),e.classList.remove("fb-drag-over"),le==null||le===t){le=null;return}O();const[i]=C.splice(le,1);C.splice(t,0,i),le=null,J(o)})}function J(e){const t=e.find("#fields-list").get(0),o=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),C.length===0){o&&(o.style.display=""),ce?.(t),Re();return}o&&(o.style.display="none"),C.forEach((n,l)=>{const a=n.type==="page-break"?Yt(n,l,e):n.type==="spacer"?Kt(n,l,e):Qt(n,l,e);Jt(a,l,e),t.appendChild(a)}),ce?.(t),Re()}}function Yt(e,t,o){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 i=document.createElement("span");i.textContent=e.label||"Untitled Step",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted);";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit step",q(c,"more-horizontal"),c.addEventListener("click",g=>{g.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove page break",q(s,"x"),s.addEventListener("click",async g=>{g.stopPropagation(),await E.confirm("Remove this page break?")&&(O(),C.splice(t,1),J(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=document.createElement("div");d.className="fb-field-body",d.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const u=D([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")]),b=u.querySelector(`#fb-pb-label-${t}`);return b&&b.addEventListener("input",()=>{i.textContent=b.value||"Untitled Step"}),d.appendChild(u),n.appendChild(l),n.appendChild(d),n}function Kt(e,t,o){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 i=document.createElement("span");i.textContent="Spacer",i.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const r=document.createElement("div");r.style.cssText="flex:1;height:1px;background:var(--dm-border);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const s=document.createElement("button");return s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove spacer",q(s,"x"),s.addEventListener("click",async d=>{d.stopPropagation(),O(),C.splice(t,1),J(o)}),c.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.appendChild(c),n.appendChild(l),n}function Qt(e,t,o){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=ct(e.type),a.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary);white-space:nowrap;flex-shrink:0;";const i=document.createElement("span");i.textContent=e.label||"(unlabelled)",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit field",q(c,"more-horizontal"),c.addEventListener("click",u=>{u.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");if(s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove field",q(s,"x"),s.addEventListener("click",async u=>{u.stopPropagation(),await E.confirm("Remove this field?")&&(O(),C.splice(t,1),J(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),e.required){const u=document.createElement("span");u.textContent="required",u.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",l.appendChild(u)}if(pt(e.logic)){const u=document.createElement("span");q(u,"zap"),u.title="Has conditional logic",u.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",l.appendChild(u)}l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=Xt(e,t,i);return d.style.display="none",n.appendChild(l),n.appendChild(d),n}function Xt(e,t,o){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=D([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=D([gn("Type",`fb-type-${t}`,it,e.type||"string"),Lt("Required",`fb-required-${t}`,e.required||!1)]),i=D([z("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),r=D([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")]),c=e.formConfig?.span,s=D([z("Column Span",`fb-span-${t}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),Lt("Full Width",`fb-fullwidth-${t}`,c==="full")]);s.classList.add("fb-grid-row"),s.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(l),n.appendChild(a),n.appendChild(i),n.appendChild(r),n.appendChild(s);const d=n.querySelector(`#fb-label-${t}`),u=n.querySelector(`#fb-name-${t}`);d&&d.addEventListener("input",()=>{o&&(o.textContent=d.value||"(unlabelled)"),u&&!u.dataset.manuallyEdited&&(u.value=rt(d.value))}),u&&u.addEventListener("input",()=>{u.dataset.manuallyEdited="1"});const b=n.querySelector(`#fb-type-${t}`);b&&b.addEventListener("change",()=>{const m=n.closest(".fb-field-card");if(m){const f=m.querySelector("span");f&&(f.textContent=ct(b.value))}const h=n.querySelector(".fb-field-extras");h&&h.remove();const w=kt(b.value,e,t);w&&n.appendChild(w)});const g=kt(e.type,e,t);return g&&n.appendChild(g),n.appendChild(ln(e,t)),n.appendChild(rn(e,t)),n}const ve=[{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"}],De=new Set(["is_empty","is_not_empty"]),ut={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 Me(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function xe(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 Ce(e,t,o,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 i=document.createElement("span");i.textContent="When",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-cond-field",r.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,e&&m.value===e.field&&(h.selected=!0),r.appendChild(h)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",ve.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,e&&m.value===e.operator&&(h.selected=!0),c.appendChild(h)});const s=()=>{const m=t.find(h=>h.value===r.value);Array.from(c.options).forEach(h=>{const w=ve.find(f=>f.value===h.value);h.textContent=m?.multi&&ut[h.value]||w?.label||h.value})};s(),r.addEventListener("change",s);const d=document.createElement("input");d.type="text",d.className="form-input fb-logic-cond-val",d.placeholder="value",d.style.cssText="flex:1 1 120px;min-width:100px;",d.value=e?.value||"",e&&De.has(e.operator)&&(d.style.display="none"),c.addEventListener("change",()=>{d.style.display=De.has(c.value)?"none":""});const u=document.createElement("span");q(u,"arrow-right"),u.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const b=document.createElement("select");b.className=`form-select ${n}`,b.style.cssText="flex:1 1 140px;min-width:120px;",o.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,m.value===l&&(h.selected=!0),b.appendChild(h)});const g=document.createElement("button");return g.type="button",g.className="btn btn-xs btn-ghost",g.style.cssText="line-height:1;opacity:.6;",q(g,"x"),g.style.flexShrink="0",g.addEventListener("click",()=>a.remove()),a.appendChild(i),a.appendChild(r),a.appendChild(c),a.appendChild(d),a.appendChild(u),a.appendChild(b),a.appendChild(g),a}function Zt(e,t,o){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(xe("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const a=document.createElement("span");a.textContent="Default:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-vis-default",i.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===(e.default||"visible")&&(x.selected=!0),i.appendChild(x)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const c=document.createElement("span");c.textContent="Transition:",c.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-vis-transition",s.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===(e.transition||"none")&&(x.selected=!0),s.appendChild(x)}),r.appendChild(c),r.appendChild(s),n.appendChild(r);const d=document.createElement("div");d.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const u=document.createElement("span");u.textContent="Speed:",u.style.cssText="font-size:.8rem;flex-shrink:0;";const b=document.createElement("select");b.className="form-select fb-logic-vis-duration",b.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(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===String(e.duration??"")&&(x.selected=!0),b.appendChild(x)}),d.appendChild(u),d.appendChild(b),n.appendChild(d);const g=()=>{d.style.display=s.value==="none"?"none":""};g(),s.addEventListener("change",g);const m=document.createElement("div");m.className="fb-logic-vis-rules";const h=o.map(f=>({value:f.name,label:f.label||f.name,multi:Me(f)})),w=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(f=>{const x=(f.when?.all||f.when?.any||[])[0],$=f.then==="hidden"?"hidden":"visible";h.length>0&&m.appendChild(Ce(x,h,w,"fb-logic-vis-then",$))}),n.appendChild(m),h.length>0){const f=document.createElement("button");f.type="button",f.className="btn btn-xs btn-ghost",f.style.cssText="font-size:.73rem;margin-top:.35rem;",re(f,"plus","Add visibility rule"),f.addEventListener("click",()=>m.appendChild(Ce(null,h,w,"fb-logic-vis-then","visible"))),n.appendChild(f)}return n}function en(e,t,o){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(xe("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 i=document.createElement("div");i.className="fb-logic-req-rules";const r=o.map(s=>({value:s.name,label:s.label||s.name,multi:Me(s)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(s=>{const d=(s.when?.all||s.when?.any||[])[0],u=s.then===!0?"true":"false";r.length>0&&i.appendChild(Ce(d,r,c,"fb-logic-req-then",u))}),n.appendChild(i),r.length>0){const s=document.createElement("button");s.type="button",s.className="btn btn-xs btn-ghost",s.style.cssText="font-size:.73rem;margin-top:.35rem;",re(s,"plus","Add requirement rule"),s.addEventListener("click",()=>i.appendChild(Ce(null,r,c,"fb-logic-req-then","true"))),n.appendChild(s)}return n}function mt(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 o=document.createElement("select");o.className="form-select fb-logic-val-type",o.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===(e?.type||"regex")&&(c.selected=!0),o.appendChild(c)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),o.addEventListener("change",()=>{l.style.display=o.value==="match"?"none":"",n.placeholder=o.value==="match"?"field name":"pattern"});const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-message",a.placeholder="Error message",a.value=e?.message||"",a.style.cssText="flex:4;";const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="line-height:1;opacity:.6;",q(i,"x"),i.style.flexShrink="0",i.addEventListener("click",()=>t.remove()),t.appendChild(o),t.appendChild(n),t.appendChild(l),t.appendChild(a),t.appendChild(i),t}function tn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(xe("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(i=>l.appendChild(mt(i))),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;",re(a,"plus","Add validation rule"),a.addEventListener("click",()=>l.appendChild(mt(null))),n.appendChild(a),n}function nn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(xe("Cascade Options")),n.lastChild.appendChild(Be("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const a=document.createElement("span");a.textContent="Source field:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-cascade-source",i.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",i.appendChild(r),o.forEach(b=>{const g=document.createElement("option");g.value=b.name,g.textContent=b.label||b.name,b.name===e.sourceField&&(g.selected=!0),i.appendChild(g)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Be(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),c.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const s=document.createElement("textarea");s.className="form-input fb-logic-cascade-mapping",s.rows=4,s.style.cssText="font-family:monospace;",s.placeholder='{"uk": [{"value": "london", "label": "London"}]}',s.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(c),n.appendChild(s);const d=document.createElement("p");d.textContent="Default options (one per line: value:Label)",d.appendChild(Be("Shown before the source field has a value, or when its value has no mapping entry.")),d.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const u=document.createElement("textarea");return u.className="form-input fb-logic-cascade-defaults",u.rows=3,u.style.cssText="font-family:monospace;",u.placeholder=`option1:Option 1
4
4
  option2:Option 2`,u.value=(e.defaultOptions||[]).map(b=>{const g=typeof b=="string"?b:b.value??"",m=typeof b=="string"?b:b.label??g;return g===m?g:`${g}:${m}`}).join(`
5
- `),n.appendChild(d),n.appendChild(u),n}function ln(e,t){const o=e.logic||{},n=C.filter((u,b)=>b!==t&&u.type!=="page-break"&&u.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const i=document.createElement("span");i.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",i.textContent="\u26A1 Conditional Logic";const r=ut(o),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",q(c,r?"chevron-down":"chevron-right",12);const s=document.createElement("div");s.className="fb-logic-body",s.style.cssText="padding:.25rem 0 .25rem;"+(r?"":"display:none;"),a.addEventListener("click",()=>{const u=s.style.display==="none";s.style.display=u?"":"none",q(c,u?"chevron-down":"chevron-right",12)}),a.appendChild(i),a.appendChild(c),l.appendChild(a),s.appendChild(Zt(o.visibility||{},t,n)),s.appendChild(en(o.requirement||{},t,n)),s.appendChild(tn(o.validation||[],t,n));const d=document.getElementById(`fb-type-${t}`)?.value||e.type;return Be.has(d)&&s.appendChild(nn(o.cascade||{},t,n)),l.appendChild(s),l}const pe=[{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"}],we=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],ht=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],bt=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],gt=[{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 yt(e,t=!1){const o=(i,r)=>({value:i.name,label:`${i.label||i.name}${r?" (this field)":""}`,multi:ze(i)}),n=i=>i&&i.type!=="page-break"&&i.type!=="spacer"&&i.name,l=C.filter((i,r)=>r!==e&&n(i)).map(i=>o(i,!1)),a=C[e];return t&&n(a)?[o(a,!0),...l]:l}function K(e,t,o){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===o&&(a.selected=!0),n.appendChild(a)}),n}function oe(e,t,o){const n=document.createElement("input");return n.type="text",n.className=`form-input ${e}`,n.value=t==null?"":String(t),o&&(n.placeholder=o),n}function Pe(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-remove",t&&(o.title=t,o.setAttribute("aria-label",t)),q(o,"x"),o.addEventListener("click",n=>{n.stopPropagation(),e()}),o}function G(e,t,{full:o=!1,hint:n=""}={}){const l=document.createElement("label");l.className=`fb-trig-f${o?" 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 i=document.createElement("span");i.className="fb-trig-f-hint",i.textContent=n,l.appendChild(i)}return l}function ue(e,t,o,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(o)),l}function vt(e,t){const o=document.createElement("div");o.className="fb-trig-cond-row";const n=K("fb-trig-cond-field",t,e?.field),l=K("fb-trig-cond-op",xe,e?.operator),a=oe("fb-trig-cond-val",e?.value,"value"),i=()=>{const c=t.find(s=>s.value===n.value);Array.from(l.options).forEach(s=>{const d=xe.find(u=>u.value===s.value);s.textContent=c?.multi&&mt[s.value]||d?.label||s.value})},r=()=>{a.hidden=De.has(l.value)};return i(),r(),n.addEventListener("change",i),l.addEventListener("change",r),o.appendChild(n),o.appendChild(l),o.appendChild(a),o.appendChild(Pe(()=>o.remove(),"Remove condition")),o}function xt(e,t){const o=document.createElement("div");o.className="fb-trig-params";const n=pe.find(c=>c.value===(e.type||"banner"));if(!n)return o;const l=document.createElement("div");l.className="fb-trig-grid";const a=document.createElement("div");a.className="fb-trig-opts";const i=[];for(const c of n.params)switch(c){case"message":l.appendChild(G(n.messageLabel||"Message",oe("fb-trig-p-message",e.message,n.placeholder||""),{full:!0}));break;case"finish":a.appendChild(ue("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 s=G("Button text",oe("fb-trig-p-finish",e.finishLabel,"Finish"));i.push(s),l.appendChild(s);break}case"doneMessage":{const s=G("Closing message",oe("fb-trig-p-done",e.doneMessage,"Blank: the form's own success message"));i.push(s),l.appendChild(s);break}case"record":{const s=ue("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.`);i.push(s),a.appendChild(s);break}case"level":l.appendChild(G(n.value==="notify"?"Severity":"Level",K("fb-trig-p-level",we,e.level||"info")));break;case"position":l.appendChild(G("Where",K("fb-trig-p-position",ht,e.position||"field-below")));break;case"dismissible":a.appendChild(ue("fb-trig-p-dismissible",e.dismissible!==!1,"The visitor can dismiss it"));break;case"target":{const s=K("fb-trig-p-target",bt,e.target||(e.fields?.length?"listed":"rest")),d=document.createElement("select");d.className="form-select fb-trig-p-fields",d.multiple=!0,d.size=4;const u=new Set(e.fields||[]);yt(t).forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,u.has(m.value)&&(h.selected=!0),d.appendChild(h)});const b=G("Fields",d,{hint:"Ctrl/Cmd-click to pick several"}),g=()=>{b.hidden=s.value!=="listed"};g(),s.addEventListener("change",g),l.appendChild(G("Which fields",s)),l.appendChild(b);break}case"step":{const s=oe("fb-trig-p-step",e.step,"0");s.type="number",s.min="0",l.appendChild(G("Step",s,{hint:"Counting from 0"}));break}case"url":l.appendChild(G("Send them to",oe("fb-trig-p-url",e.url,"/thank-you"),{full:!0}));break;case"theme":l.appendChild(G("Theme",K("fb-trig-p-theme",gt,e.theme||"auto")));break;case"intensity":l.appendChild(G("Intensity",K("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium")));break;case"slug":{const s=[{value:"",label:be.length?"Choose an action":"No actions available"}].concat(be.map(d=>({value:d.slug,label:d.title||d.slug})));l.appendChild(G("Action",K("fb-trig-p-slug",s,e.slug||""),{full:!0}));break}default:break}n.kind==="event"&&!n.noOnce&&a.appendChild(ue("fb-trig-p-once",!!e.once,"Only once","Fire the first time only, rather than every time the answer swings back."));const r=a.querySelector(".fb-trig-p-finish-on");if(r){const c=()=>i.forEach(s=>{s.hidden=!r.checked});c(),r.addEventListener("change",c)}return l.children.length&&o.appendChild(l),a.children.length&&o.appendChild(a),o}function an(e){return e?.kindText?e.kindText:e?.kind==="event"?"once, when it becomes true":"while it is true"}const on=(e,t=48)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,ie=(e,t)=>e.find(o=>o.value===t)?.label||t;function sn(e){if(!e)return"";const t=[],o=l=>l?`"${on(l)}"`:"",n=()=>e.target==="listed"?e.fields?.length?e.fields.join(", "):"no fields chosen":ie(bt,e.target||"rest").toLowerCase();switch(e.type){case"banner":t.push(o(e.message)||"No message yet",ie(we,e.level||"info"),ie(ht,e.position||"field-below").toLowerCase());break;case"toast":t.push(o(e.message)||"No message yet",ie(we,e.level||"info"));break;case"hide-fields":case"disable-fields":case"require-fields":t.push(n());break;case"block-submit":t.push(o(e.message)||"the standard reason");break;case"end-form":t.push(o(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(ie(gt,e.theme||"auto"),`${e.intensity||"medium"} intensity`);break;case"run-action":t.push(e.slug?be.find(l=>l.slug===e.slug)?.title||e.slug:"no action chosen");break;case"notify":t.push(o(e.message)||"titled after the form",ie(we,e.level||"info"));break;default:break}return e.once&&t.push("only once"),t.filter(Boolean).join(" \xB7 ")}function _e(e,t,{open:o=!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 i=document.createElement("span");i.className="fb-trig-action-main";const r=document.createElement("strong"),c=document.createElement("small");c.className="fb-trig-action-summary",i.append(r,c);const s=document.createElement("span");s.className="fb-trig-kind",l.append(a,i,s,Pe(()=>n.remove(),"Remove action"));const d=document.createElement("div");d.className="fb-trig-action-body";const u=K("fb-trig-action-type",pe,e.type||"banner");d.appendChild(G("Action",u,{full:!0})),d.appendChild(xt(e,t));const b=()=>{const m=pe.find(h=>h.value===u.value);r.textContent=m?.label||u.value,s.textContent=an(m),s.classList.toggle("fb-trig-kind--event",m?.kind==="event"),c.textContent=sn(kt(n))},g=m=>{d.hidden=!m,n.classList.toggle("is-open",m),l.setAttribute("aria-expanded",String(m)),q(a,m?"chevron-down":"chevron-right",12)};return l.addEventListener("click",()=>g(d.hidden)),l.addEventListener("keydown",m=>{m.target!==l||m.key!=="Enter"&&m.key!==" "||(m.preventDefault(),g(d.hidden))}),u.addEventListener("change",()=>{const m=xt({type:u.value},t);d.replaceChild(m,d.querySelector(".fb-trig-params")),b(),window.I?.scan?.()}),d.addEventListener("input",b),d.addEventListener("change",b),n.append(l,d),g(o),b(),n}function Ct(e,t,o){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),o){const i=document.createElement("span");i.className="fb-trig-sec-hint",i.textContent=o,l.appendChild(i)}return n.appendChild(l),n}function je(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-add",ce(o,"plus",e,12),o.addEventListener("click",t),o}function Et(e,t,o,n){const a=Ct(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 i=document.createElement("div");return i.className="fb-trig-action-list",(o||[]).forEach(r=>i.appendChild(_e(r,n))),a.appendChild(i),a.appendChild(je("Add action",()=>{i.appendChild(_e({type:"banner"},n,{open:!0})),window.I?.scan?.()})),a}function wt(e,t,o){const n=yt(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 i=document.createElement("span");i.className="fb-trig-card-title",i.textContent=`Trigger ${o+1}`,a.appendChild(i);const r=ue("fb-trig-enabled",e.enabled!==!1,"Enabled","Untick to keep the trigger but switch it off.");if(a.appendChild(r),a.appendChild(Pe(()=>l.remove(),"Remove trigger")),l.appendChild(a),!n.length){const u=document.createElement("p");return u.className="fb-trig-empty",u.textContent="Give this field a name first - a trigger tests an answer, and it needs something to test.",l.appendChild(u),l}const c=Ct("when","When");c.querySelector(".fb-trig-sec-head").appendChild(K("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all"));const s=document.createElement("div");s.className="fb-trig-cond-list";const d=e.when?.all||e.when?.any||[];return(d.length?d:[{}]).forEach(u=>s.appendChild(vt(u,n))),c.appendChild(s),c.appendChild(je("Add condition",()=>{s.appendChild(vt({},n)),window.I?.scan?.()})),l.appendChild(c),l.appendChild(Et("then","Then",e.then,t)),l.appendChild(Et("otherwise","Otherwise",e.otherwise,t)),l}function rn(e,t){const o=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${o.length?` (${o.length})`:""}`;const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",q(i,o.length?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-triggers-body",r.hidden=!o.length,l.addEventListener("click",()=>{r.hidden=!r.hidden,q(i,r.hidden?"chevron-right":"chevron-down",12)});const c=document.createElement("p");c.className="fb-trig-blurb",c.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, end the form early, notify the admins, jump to a step, or celebrate.",r.appendChild(c);const s=document.createElement("div");return s.className="fb-trig-list",o.forEach((d,u)=>s.appendChild(wt(d,t,u))),r.appendChild(s),r.appendChild(je("Add trigger",()=>{const d=wt({enabled:!0,then:[]},t,s.children.length);s.appendChild(d),d.querySelector('.fb-trig-branch[data-branch="then"] .fb-trig-action-list')?.appendChild(_e({type:"banner"},t,{open:!0})),window.I?.scan?.()})),l.appendChild(a),l.appendChild(i),n.appendChild(l),n.appendChild(r),n}function kt(e){const t=e.querySelector(".fb-trig-action-type")?.value,o=pe.find(a=>a.value===t);if(!o)return null;const n={type:t},l=a=>e.querySelector(a)?.value?.trim()||"";for(const a of o.params)switch(a){case"message":n.message=l(".fb-trig-p-message");break;case"finishLabel":{const i=l(".fb-trig-p-finish");i&&(n.finishLabel=i);break}case"doneMessage":{const i=l(".fb-trig-p-done");i&&(n.doneMessage=i);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 i=l(".fb-trig-p-target")||"rest";n.target=i,i==="listed"&&(n.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(r=>r.selected).map(r=>r.value));break}case"step":{const i=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(i)&&(n.step=i);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 o.kind==="event"&&!o.noOnce&&e.querySelector(".fb-trig-p-once")?.checked&&(n.once=!0),n}function cn(e){const t=kt(e);if(!t)return null;const o=pe.find(a=>a.value===t.type),n=t.type,l=["block-submit","end-form","notify"].includes(o.value);return o.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 dn(e){const o=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!o)return;const n=[];return o.querySelectorAll(".fb-trig-card").forEach(l=>{const a=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(u=>{const b=u.querySelector(".fb-trig-cond-field")?.value,g=u.querySelector(".fb-trig-cond-op")?.value;if(!b||!g)return null;const m=u.querySelector(".fb-trig-cond-val")?.value??"";return{field:b,operator:g,value:m}}).filter(Boolean);if(!a.length)return;const i=u=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${u}"] .fb-trig-action-row`)).map(cn).filter(Boolean),r=i("then"),c=i("otherwise");if(!r.length&&!c.length)return;const s=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",d={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[s]:a}};r.length&&(d.then=r),c.length&&(d.otherwise=c),n.push(d)}),n.length?n:void 0}function St(e,t,o){const n=document.createElement("div");return n.className="fb-field-extras",e==="chooser"?(n.appendChild(pn(t,o)),n.appendChild(mn(t.options||[],o))):(Be.has(e)&&n.appendChild(yn(t.options||[],o)),e==="textarea"&&n.appendChild(z([P("Rows",`fb-rows-${o}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(z([P("Min Length",`fb-minlength-${o}`,"number",t.minLength||"",""),P("Max Length",`fb-maxlength-${o}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(z([P("Min",`fb-min-${o}`,"number",t.min??"",""),P("Max",`fb-max-${o}`,"number",t.max??"","")]))),n.children.length?n:null}function Tt(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 o=document.createElement("div");o.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",o.textContent=e,t.appendChild(o);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 ke(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",n.forEach(([c,s])=>{const d=document.createElement("option");d.value=c,d.textContent=s,String(c)===String(o)&&(d.selected=!0),r.appendChild(d)}),a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(c)}return a}function Nt(e,t,o,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 i=document.createElement("input");if(i.id=e,i.type="checkbox",i.checked=!!o,a.appendChild(i),a.appendChild(document.createTextNode(" "+t)),l.appendChild(a),n){const r=document.createElement("p");r.className="form-hint text-muted",r.textContent=n,r.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(r)}return l}function Ve(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem",a.appendChild(i);const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const c=document.createElement("input");c.id=e,c.type="text",c.className="form-input",c.value=o||"",n&&(c.placeholder=n),c.style.flex="1";const s=document.createElement("input");s.type="color",s.title="Pick a colour",s.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const d=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(s.value=d?c.value:"#000000",s.addEventListener("input",()=>{c.value=s.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),r.appendChild(c),r.appendChild(s),a.appendChild(r),l){const u=document.createElement("p");u.className="form-hint text-muted",u.textContent=l,u.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(u)}return a}function pn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=Tt("Layout");n.body.appendChild(z([ke(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),Nt(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(z([ke(`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.")])),o.appendChild(n.wrap);const l=Tt("Visual");return l.body.appendChild(z([Ve(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),ke(`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(z([Nt(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),Ve(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(z([ke(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),Ve(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),o.appendChild(l.wrap),o}function un(e,t,o,n){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(o),l.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const a=document.createElement("div");a.style.cssText="display:flex; gap:.4rem; align-items:center;";const i=document.createElement("div");i.style.cssText="display:flex; flex-direction:column; gap:1px;";const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.title="Move up",q(r,"arrow-up"),r.addEventListener("click",I=>{I.preventDefault(),Lt(t,o,-1,n)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",q(c,"arrow-down"),c.addEventListener("click",I=>{I.preventDefault(),Lt(t,o,1,n)}),i.appendChild(r),i.appendChild(c),a.appendChild(i);const s=document.createElement("input");s.type="text",s.className="form-input fb-chooser-opt-value",s.placeholder="value",s.value=e.value||"",s.style.flex="1",a.appendChild(s);const d=document.createElement("input");d.type="text",d.className="form-input fb-chooser-opt-label",d.placeholder="label (visible to users)",d.value=e.label||"",d.style.flex="2",a.appendChild(d);const u=document.createElement("button");u.type="button",u.className="btn btn-xs btn-ghost",u.style.cssText="line-height:1;opacity:.6;",u.title="Remove option",q(u,"x"),u.addEventListener("click",I=>{I.preventDefault(),bn(t,o,n)}),a.appendChild(u),l.appendChild(a);const b=document.createElement("div");b.style.cssText="display:flex; gap:.4rem;";const g=zt("icon name (optional)",e.icon||"");g.input.classList.add("fb-chooser-opt-icon"),g.el.style.flex="1",b.appendChild(g.el);const m=document.createElement("input");m.type="text",m.className="form-input fb-chooser-opt-description",m.placeholder="description (card + comfortable only)",m.value=e.description||"",m.style.flex="2",b.appendChild(m),l.appendChild(b);const h=document.createElement("div");h.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",h.appendChild(w);const f=document.createElement("input");f.type="text",f.className="form-input fb-chooser-opt-badge-text",f.placeholder="badge text",f.value=e.badge?.text||"",f.style.flex="1",h.appendChild(f);const x=document.createElement("select");x.className="form-input fb-chooser-opt-badge-type",x.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([I,X])=>{const U=document.createElement("option");U.value=I,U.textContent=X,(e.badge?.type||"")===I&&(U.selected=!0),x.appendChild(U)}),h.appendChild(x),l.appendChild(h);const $=document.createElement("div");$.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const A=document.createElement("label");A.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const H=document.createElement("input");H.type="checkbox",H.className="fb-chooser-opt-recommended",H.checked=!!e.recommended,A.appendChild(H),A.appendChild(document.createTextNode(" Recommended")),$.appendChild(A);const _=document.createElement("label");_.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const j=document.createElement("input");return j.type="checkbox",j.className="fb-chooser-opt-disabled",j.checked=!!e.disabled,_.appendChild(j),_.appendChild(document.createTextNode(" Disabled")),$.appendChild(_),l.appendChild($),l}function mn(e,t){const o=document.createElement("div");o.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",ce(a,"plus","Add option"),n.appendChild(a),o.appendChild(n);const i=document.createElement("div");i.className="fb-chooser-options-list",i.id=`fb-chooser-options-${t}`,i.style.cssText="display:flex; flex-direction:column; gap:.4rem;",o.appendChild(i);const r=()=>{i.replaceChildren();const c=fn(t);(c.length?c:e||[]).forEach((d,u)=>{i.appendChild(un(d,t,u,r))})};return a.addEventListener("click",c=>{c.preventDefault(),hn(t,r)}),r(),o}function fn(e){const t=C[e];return!t||!Array.isArray(t.options)?[]:t.options}function Ge(e){return C[e]?(Array.isArray(C[e].options)||(C[e].options=[]),C[e].options):[]}function hn(e,t){Se(e),Ge(e).push({value:"new",label:"New option"}),t()}function bn(e,t,o){Se(e),Ge(e).splice(t,1),o()}function Lt(e,t,o,n){Se(e);const l=Ge(e),a=t+o;if(a<0||a>=l.length)return;const[i]=l.splice(t,1);l.splice(a,0,i),n()}function Se(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const o=t.querySelectorAll(".fb-chooser-option-row"),n=[];o.forEach(l=>{const a={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},i=l.querySelector(".fb-chooser-opt-icon")?.value.trim();i&&(a.icon=i);const r=l.querySelector(".fb-chooser-opt-description")?.value.trim();r&&(a.description=r);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(a.tooltip=c);const s=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),d=l.querySelector(".fb-chooser-opt-badge-type")?.value;(s||d)&&(a.badge={},s&&(a.badge.text=s),d&&(a.badge.type=d)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(a.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(a.disabled=!0),n.push(a)}),C[e]&&(C[e].options=n)}function z(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(o=>{o&&t.appendChild(o)}),t}function P(e,t,o,n,l){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";const r=document.createElement("input");if(r.id=t,r.type=o||"text",r.className="form-input",r.value=n??"",a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",a.appendChild(c)}return a}function gn(e,t,o,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 i=document.createElement("select");return i.id=t,i.className="form-select",o.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===n&&(c.selected=!0),i.appendChild(c)}),l.appendChild(a),l.appendChild(i),l}function qt(e,t,o){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=o,l.appendChild(a),l.appendChild(document.createTextNode(e)),n.appendChild(l),n}function yn(e,t){const o=document.createElement("div");o.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(d),n.appendChild(u),n}function ln(e,t){const o=e.logic||{},n=C.filter((u,b)=>b!==t&&u.type!=="page-break"&&u.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const i=document.createElement("span");i.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",i.textContent="\u26A1 Conditional Logic";const r=pt(o),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",q(c,r?"chevron-down":"chevron-right",12);const s=document.createElement("div");s.className="fb-logic-body",s.style.cssText="padding:.25rem 0 .25rem;"+(r?"":"display:none;"),a.addEventListener("click",()=>{const u=s.style.display==="none";s.style.display=u?"":"none",q(c,u?"chevron-down":"chevron-right",12)}),a.appendChild(i),a.appendChild(c),l.appendChild(a),s.appendChild(Zt(o.visibility||{},t,n)),s.appendChild(en(o.requirement||{},t,n)),s.appendChild(tn(o.validation||[],t,n));const d=document.getElementById(`fb-type-${t}`)?.value||e.type;return Ie.has(d)&&s.appendChild(nn(o.cascade||{},t,n)),l.appendChild(s),l}const de=[{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"}],Ee=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],ft=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],ht=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],bt=[{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 gt(e,t=!1){const o=(i,r)=>({value:i.name,label:`${i.label||i.name}${r?" (this field)":""}`,multi:Me(i)}),n=i=>i&&i.type!=="page-break"&&i.type!=="spacer"&&i.name,l=C.filter((i,r)=>r!==e&&n(i)).map(i=>o(i,!1)),a=C[e];return t&&n(a)?[o(a,!0),...l]:l}function Y(e,t,o){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===o&&(a.selected=!0),n.appendChild(a)}),n}function ae(e,t,o){const n=document.createElement("input");return n.type="text",n.className=`form-input ${e}`,n.value=t==null?"":String(t),o&&(n.placeholder=o),n}function ze(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-remove",t&&(o.title=t,o.setAttribute("aria-label",t)),q(o,"x"),o.addEventListener("click",n=>{n.stopPropagation(),e()}),o}function V(e,t,{full:o=!1,hint:n=""}={}){const l=document.createElement("label");l.className=`fb-trig-f${o?" 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 i=document.createElement("span");i.className="fb-trig-f-hint",i.textContent=n,l.appendChild(i)}return l}function pe(e,t,o,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(o)),l}function yt(e,t){const o=document.createElement("div");o.className="fb-trig-cond-row";const n=Y("fb-trig-cond-field",t,e?.field),l=Y("fb-trig-cond-op",ve,e?.operator),a=ae("fb-trig-cond-val",e?.value,"value"),i=()=>{const c=t.find(s=>s.value===n.value);Array.from(l.options).forEach(s=>{const d=ve.find(u=>u.value===s.value);s.textContent=c?.multi&&ut[s.value]||d?.label||s.value})},r=()=>{a.hidden=De.has(l.value)};return i(),r(),n.addEventListener("change",i),l.addEventListener("change",r),o.appendChild(n),o.appendChild(l),o.appendChild(a),o.appendChild(ze(()=>o.remove(),"Remove condition")),o}function vt(e,t){const o=document.createElement("div");o.className="fb-trig-params";const n=de.find(c=>c.value===(e.type||"banner"));if(!n)return o;const l=document.createElement("div");l.className="fb-trig-grid";const a=document.createElement("div");a.className="fb-trig-opts";const i=[];for(const c of n.params)switch(c){case"message":l.appendChild(V(n.messageLabel||"Message",ae("fb-trig-p-message",e.message,n.placeholder||""),{full:!0}));break;case"finish":a.appendChild(pe("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 s=V("Button text",ae("fb-trig-p-finish",e.finishLabel,"Finish"));i.push(s),l.appendChild(s);break}case"doneMessage":{const s=V("Closing message",ae("fb-trig-p-done",e.doneMessage,"Blank: the form's own success message"));i.push(s),l.appendChild(s);break}case"record":{const s=pe("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.`);i.push(s),a.appendChild(s);break}case"level":l.appendChild(V(n.value==="notify"?"Severity":"Level",Y("fb-trig-p-level",Ee,e.level||"info")));break;case"position":l.appendChild(V("Where",Y("fb-trig-p-position",ft,e.position||"field-below")));break;case"dismissible":a.appendChild(pe("fb-trig-p-dismissible",e.dismissible!==!1,"The visitor can dismiss it"));break;case"target":{const s=Y("fb-trig-p-target",ht,e.target||(e.fields?.length?"listed":"rest")),d=document.createElement("select");d.className="form-select fb-trig-p-fields",d.multiple=!0,d.size=4;const u=new Set(e.fields||[]);gt(t).forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,u.has(m.value)&&(h.selected=!0),d.appendChild(h)});const b=V("Fields",d,{hint:"Ctrl/Cmd-click to pick several"}),g=()=>{b.hidden=s.value!=="listed"};g(),s.addEventListener("change",g),l.appendChild(V("Which fields",s)),l.appendChild(b);break}case"step":{const s=ae("fb-trig-p-step",e.step,"0");s.type="number",s.min="0",l.appendChild(V("Step",s,{hint:"Counting from 0"}));break}case"url":l.appendChild(V("Send them to",ae("fb-trig-p-url",e.url,"/thank-you"),{full:!0}));break;case"theme":l.appendChild(V("Theme",Y("fb-trig-p-theme",bt,e.theme||"auto")));break;case"intensity":l.appendChild(V("Intensity",Y("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium")));break;case"slug":{const s=[{value:"",label:he.length?"Choose an action":"No actions available"}].concat(he.map(d=>({value:d.slug,label:d.title||d.slug})));l.appendChild(V("Action",Y("fb-trig-p-slug",s,e.slug||""),{full:!0}));break}default:break}n.kind==="event"&&!n.noOnce&&a.appendChild(pe("fb-trig-p-once",!!e.once,"Only once","Fire the first time only, rather than every time the answer swings back."));const r=a.querySelector(".fb-trig-p-finish-on");if(r){const c=()=>i.forEach(s=>{s.hidden=!r.checked});c(),r.addEventListener("change",c)}return l.children.length&&o.appendChild(l),a.children.length&&o.appendChild(a),o}function an(e){return e?.kindText?e.kindText:e?.kind==="event"?"once, when it becomes true":"while it is true"}const on=(e,t=48)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,oe=(e,t)=>e.find(o=>o.value===t)?.label||t;function sn(e){if(!e)return"";const t=[],o=l=>l?`"${on(l)}"`:"",n=()=>e.target==="listed"?e.fields?.length?e.fields.join(", "):"no fields chosen":oe(ht,e.target||"rest").toLowerCase();switch(e.type){case"banner":t.push(o(e.message)||"No message yet",oe(Ee,e.level||"info"),oe(ft,e.position||"field-below").toLowerCase());break;case"toast":t.push(o(e.message)||"No message yet",oe(Ee,e.level||"info"));break;case"hide-fields":case"disable-fields":case"require-fields":t.push(n());break;case"block-submit":t.push(o(e.message)||"the standard reason");break;case"end-form":t.push(o(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(oe(bt,e.theme||"auto"),`${e.intensity||"medium"} intensity`);break;case"run-action":t.push(e.slug?he.find(l=>l.slug===e.slug)?.title||e.slug:"no action chosen");break;case"notify":t.push(o(e.message)||"titled after the form",oe(Ee,e.level||"info"));break;default:break}return e.once&&t.push("only once"),t.filter(Boolean).join(" \xB7 ")}function Pe(e,t,{open:o=!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 i=document.createElement("span");i.className="fb-trig-action-main";const r=document.createElement("strong"),c=document.createElement("small");c.className="fb-trig-action-summary",i.append(r,c);const s=document.createElement("span");s.className="fb-trig-kind",l.append(a,i,s,ze(()=>n.remove(),"Remove action"));const d=document.createElement("div");d.className="fb-trig-action-body";const u=Y("fb-trig-action-type",de,e.type||"banner");d.appendChild(V("Action",u,{full:!0})),d.appendChild(vt(e,t));const b=()=>{const m=de.find(h=>h.value===u.value);r.textContent=m?.label||u.value,s.textContent=an(m),s.classList.toggle("fb-trig-kind--event",m?.kind==="event"),c.textContent=sn(wt(n))},g=m=>{d.hidden=!m,n.classList.toggle("is-open",m),l.setAttribute("aria-expanded",String(m)),q(a,m?"chevron-down":"chevron-right",12)};return l.addEventListener("click",()=>g(d.hidden)),l.addEventListener("keydown",m=>{m.target!==l||m.key!=="Enter"&&m.key!==" "||(m.preventDefault(),g(d.hidden))}),u.addEventListener("change",()=>{const m=vt({type:u.value},t);d.replaceChild(m,d.querySelector(".fb-trig-params")),b(),window.I?.scan?.()}),d.addEventListener("input",b),d.addEventListener("change",b),n.append(l,d),g(o),b(),n}function xt(e,t,o){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),o){const i=document.createElement("span");i.className="fb-trig-sec-hint",i.textContent=o,l.appendChild(i)}return n.appendChild(l),n}function _e(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-add",re(o,"plus",e,12),o.addEventListener("click",t),o}function Ct(e,t,o,n){const a=xt(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 i=document.createElement("div");return i.className="fb-trig-action-list",(o||[]).forEach(r=>i.appendChild(Pe(r,n))),a.appendChild(i),a.appendChild(_e("Add action",()=>{i.appendChild(Pe({type:"banner"},n,{open:!0})),window.I?.scan?.()})),a}function Et(e,t,o){const n=gt(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 i=document.createElement("span");i.className="fb-trig-card-title",i.textContent=`Trigger ${o+1}`,a.appendChild(i);const r=pe("fb-trig-enabled",e.enabled!==!1,"Enabled","Untick to keep the trigger but switch it off.");if(a.appendChild(r),a.appendChild(ze(()=>l.remove(),"Remove trigger")),l.appendChild(a),!n.length){const u=document.createElement("p");return u.className="fb-trig-empty",u.textContent="Give this field a name first - a trigger tests an answer, and it needs something to test.",l.appendChild(u),l}const c=xt("when","When");c.querySelector(".fb-trig-sec-head").appendChild(Y("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 s=document.createElement("div");s.className="fb-trig-cond-list";const d=e.when?.all||e.when?.any||[];return(d.length?d:[{}]).forEach(u=>s.appendChild(yt(u,n))),c.appendChild(s),c.appendChild(_e("Add condition",()=>{s.appendChild(yt({},n)),window.I?.scan?.()})),l.appendChild(c),l.appendChild(Ct("then","Then",e.then,t)),l.appendChild(Ct("otherwise","Otherwise",e.otherwise,t)),l}function rn(e,t){const o=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${o.length?` (${o.length})`:""}`;const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",q(i,o.length?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-triggers-body",r.hidden=!o.length,l.addEventListener("click",()=>{r.hidden=!r.hidden,q(i,r.hidden?"chevron-right":"chevron-down",12)});const c=document.createElement("p");c.className="fb-trig-blurb",c.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, end the form early, notify the admins, jump to a step, or celebrate.",r.appendChild(c);const s=document.createElement("div");return s.className="fb-trig-list",o.forEach((d,u)=>s.appendChild(Et(d,t,u))),r.appendChild(s),r.appendChild(_e("Add trigger",()=>{const d=Et({enabled:!0,then:[]},t,s.children.length);s.appendChild(d),d.querySelector('.fb-trig-branch[data-branch="then"] .fb-trig-action-list')?.appendChild(Pe({type:"banner"},t,{open:!0})),window.I?.scan?.()})),l.appendChild(a),l.appendChild(i),n.appendChild(l),n.appendChild(r),n}function wt(e){const t=e.querySelector(".fb-trig-action-type")?.value,o=de.find(a=>a.value===t);if(!o)return null;const n={type:t},l=a=>e.querySelector(a)?.value?.trim()||"";for(const a of o.params)switch(a){case"message":n.message=l(".fb-trig-p-message");break;case"finishLabel":{const i=l(".fb-trig-p-finish");i&&(n.finishLabel=i);break}case"doneMessage":{const i=l(".fb-trig-p-done");i&&(n.doneMessage=i);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 i=l(".fb-trig-p-target")||"rest";n.target=i,i==="listed"&&(n.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(r=>r.selected).map(r=>r.value));break}case"step":{const i=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(i)&&(n.step=i);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 o.kind==="event"&&!o.noOnce&&e.querySelector(".fb-trig-p-once")?.checked&&(n.once=!0),n}function cn(e){const t=wt(e);if(!t)return null;const o=de.find(a=>a.value===t.type),n=t.type,l=["block-submit","end-form","notify"].includes(o.value);return o.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 dn(e){const o=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!o)return;const n=[];return o.querySelectorAll(".fb-trig-card").forEach(l=>{const a=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(u=>{const b=u.querySelector(".fb-trig-cond-field")?.value,g=u.querySelector(".fb-trig-cond-op")?.value;if(!b||!g)return null;const m=u.querySelector(".fb-trig-cond-val")?.value??"";return{field:b,operator:g,value:m}}).filter(Boolean);if(!a.length)return;const i=u=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${u}"] .fb-trig-action-row`)).map(cn).filter(Boolean),r=i("then"),c=i("otherwise");if(!r.length&&!c.length)return;const s=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",d={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[s]:a}};r.length&&(d.then=r),c.length&&(d.otherwise=c),n.push(d)}),n.length?n:void 0}function kt(e,t,o){const n=document.createElement("div");return n.className="fb-field-extras",e==="chooser"?(n.appendChild(pn(t,o)),n.appendChild(mn(t.options||[],o))):(Ie.has(e)&&n.appendChild(yn(t.options||[],o)),e==="textarea"&&n.appendChild(D([z("Rows",`fb-rows-${o}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(D([z("Min Length",`fb-minlength-${o}`,"number",t.minLength||"",""),z("Max Length",`fb-maxlength-${o}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(D([z("Min",`fb-min-${o}`,"number",t.min??"",""),z("Max",`fb-max-${o}`,"number",t.max??"","")]))),n.children.length?n:null}function St(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 o=document.createElement("div");o.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",o.textContent=e,t.appendChild(o);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 we(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",n.forEach(([c,s])=>{const d=document.createElement("option");d.value=c,d.textContent=s,String(c)===String(o)&&(d.selected=!0),r.appendChild(d)}),a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(c)}return a}function Tt(e,t,o,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 i=document.createElement("input");if(i.id=e,i.type="checkbox",i.checked=!!o,a.appendChild(i),a.appendChild(document.createTextNode(" "+t)),l.appendChild(a),n){const r=document.createElement("p");r.className="form-hint text-muted",r.textContent=n,r.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(r)}return l}function je(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem",a.appendChild(i);const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const c=document.createElement("input");c.id=e,c.type="text",c.className="form-input",c.value=o||"",n&&(c.placeholder=n),c.style.flex="1";const s=document.createElement("input");s.type="color",s.title="Pick a colour",s.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const d=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(s.value=d?c.value:"#000000",s.addEventListener("input",()=>{c.value=s.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),r.appendChild(c),r.appendChild(s),a.appendChild(r),l){const u=document.createElement("p");u.className="form-hint text-muted",u.textContent=l,u.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(u)}return a}function pn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=St("Layout");n.body.appendChild(D([we(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),Tt(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(D([we(`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.")])),o.appendChild(n.wrap);const l=St("Visual");return l.body.appendChild(D([je(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),we(`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(D([Tt(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),je(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(D([we(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),je(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),o.appendChild(l.wrap),o}function un(e,t,o,n){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(o),l.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const a=document.createElement("div");a.style.cssText="display:flex; gap:.4rem; align-items:center;";const i=document.createElement("div");i.style.cssText="display:flex; flex-direction:column; gap:1px;";const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.title="Move up",q(r,"arrow-up"),r.addEventListener("click",I=>{I.preventDefault(),Nt(t,o,-1,n)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",q(c,"arrow-down"),c.addEventListener("click",I=>{I.preventDefault(),Nt(t,o,1,n)}),i.appendChild(r),i.appendChild(c),a.appendChild(i);const s=document.createElement("input");s.type="text",s.className="form-input fb-chooser-opt-value",s.placeholder="value",s.value=e.value||"",s.style.flex="1",a.appendChild(s);const d=document.createElement("input");d.type="text",d.className="form-input fb-chooser-opt-label",d.placeholder="label (visible to users)",d.value=e.label||"",d.style.flex="2",a.appendChild(d);const u=document.createElement("button");u.type="button",u.className="btn btn-xs btn-ghost",u.style.cssText="line-height:1;opacity:.6;",u.title="Remove option",q(u,"x"),u.addEventListener("click",I=>{I.preventDefault(),bn(t,o,n)}),a.appendChild(u),l.appendChild(a);const b=document.createElement("div");b.style.cssText="display:flex; gap:.4rem;";const g=Mt("icon name (optional)",e.icon||"");g.input.classList.add("fb-chooser-opt-icon"),g.el.style.flex="1",b.appendChild(g.el);const m=document.createElement("input");m.type="text",m.className="form-input fb-chooser-opt-description",m.placeholder="description (card + comfortable only)",m.value=e.description||"",m.style.flex="2",b.appendChild(m),l.appendChild(b);const h=document.createElement("div");h.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",h.appendChild(w);const f=document.createElement("input");f.type="text",f.className="form-input fb-chooser-opt-badge-text",f.placeholder="badge text",f.value=e.badge?.text||"",f.style.flex="1",h.appendChild(f);const x=document.createElement("select");x.className="form-input fb-chooser-opt-badge-type",x.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([I,Q])=>{const H=document.createElement("option");H.value=I,H.textContent=Q,(e.badge?.type||"")===I&&(H.selected=!0),x.appendChild(H)}),h.appendChild(x),l.appendChild(h);const $=document.createElement("div");$.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const A=document.createElement("label");A.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const G=document.createElement("input");G.type="checkbox",G.className="fb-chooser-opt-recommended",G.checked=!!e.recommended,A.appendChild(G),A.appendChild(document.createTextNode(" Recommended")),$.appendChild(A);const P=document.createElement("label");P.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const _=document.createElement("input");return _.type="checkbox",_.className="fb-chooser-opt-disabled",_.checked=!!e.disabled,P.appendChild(_),P.appendChild(document.createTextNode(" Disabled")),$.appendChild(P),l.appendChild($),l}function mn(e,t){const o=document.createElement("div");o.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",re(a,"plus","Add option"),n.appendChild(a),o.appendChild(n);const i=document.createElement("div");i.className="fb-chooser-options-list",i.id=`fb-chooser-options-${t}`,i.style.cssText="display:flex; flex-direction:column; gap:.4rem;",o.appendChild(i);const r=()=>{i.replaceChildren();const c=fn(t);(c.length?c:e||[]).forEach((d,u)=>{i.appendChild(un(d,t,u,r))})};return a.addEventListener("click",c=>{c.preventDefault(),hn(t,r)}),r(),o}function fn(e){const t=C[e];return!t||!Array.isArray(t.options)?[]:t.options}function Ve(e){return C[e]?(Array.isArray(C[e].options)||(C[e].options=[]),C[e].options):[]}function hn(e,t){ke(e),Ve(e).push({value:"new",label:"New option"}),t()}function bn(e,t,o){ke(e),Ve(e).splice(t,1),o()}function Nt(e,t,o,n){ke(e);const l=Ve(e),a=t+o;if(a<0||a>=l.length)return;const[i]=l.splice(t,1);l.splice(a,0,i),n()}function ke(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const o=t.querySelectorAll(".fb-chooser-option-row"),n=[];o.forEach(l=>{const a={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},i=l.querySelector(".fb-chooser-opt-icon")?.value.trim();i&&(a.icon=i);const r=l.querySelector(".fb-chooser-opt-description")?.value.trim();r&&(a.description=r);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(a.tooltip=c);const s=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),d=l.querySelector(".fb-chooser-opt-badge-type")?.value;(s||d)&&(a.badge={},s&&(a.badge.text=s),d&&(a.badge.type=d)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(a.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(a.disabled=!0),n.push(a)}),C[e]&&(C[e].options=n)}function D(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(o=>{o&&t.appendChild(o)}),t}function z(e,t,o,n,l){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";const r=document.createElement("input");if(r.id=t,r.type=o||"text",r.className="form-input",r.value=n??"",a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",a.appendChild(c)}return a}function gn(e,t,o,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 i=document.createElement("select");return i.id=t,i.className="form-select",o.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===n&&(c.selected=!0),i.appendChild(c)}),l.appendChild(a),l.appendChild(i),l}function Lt(e,t,o){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=o,l.appendChild(a),l.appendChild(document.createTextNode(e)),n.appendChild(l),n}function yn(e,t){const o=document.createElement("div");o.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
6
6
  no:No
7
7
  maybe:Maybe`,l.value=(e||[]).map(a=>{const i=typeof a=="string"?a:a.value??"",r=typeof a=="string"?a:a.label??i;return i===r?i:`${i}:${r}`}).join(`
8
- `),l.style.fontFamily="monospace",o.appendChild(n),o.appendChild(l),o}function Te(e){return parseInt(e,10)===3?3:2}function Ne(e){const t=e.find("#field-project").val()||"";return O(),{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:{...ye||{},project:t||null},fields:C,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:Te(e.find("#setting-columns").val()),submitSpan:e.find("#setting-submit-span").val()||"",honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...ge!==null&&{collection:ge}}}}function $t(e,t){const o={};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)),r={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&&(r.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(r.multiple=!0),n.density&&(r.density=n.density),n.columns&&(r.columns=n.columns),n.accent&&(r.accent=n.accent),n.accentStyle&&(r.accentStyle=n.accentStyle),n.glow&&(r.glow=!0),n.glowColour&&(r.glowColour=n.glowColour),n.shadow&&(r.shadow=n.shadow),n.shadowColour&&(r.shadowColour=n.shadowColour)),o[n.name]=r}),o}function At(e,t){const o=typeof e=="string"?document.querySelector(e):e;o&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const l=o.querySelector(`[name="${n.name}"]`);l&&l.type!=="date"&&(l.type="date")})}function Ft(e,t){const o=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(o){for(;o.nextSibling;)o.nextSibling.remove();o.after(document.createTextNode(String(t||"")))}}const vn=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");let W=null,It=0,Bt=!1;const Le=e=>String(e||"").split("?")[0].replace(/\/$/,"");function xn(){Bt||!window.R?.use||(Bt=!0,R.use((e,t,o)=>!W||!ot(t?.path,e?.path)||W.path!==Le(t?.path)||(W.flush(),!W.dirty())?o():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(n=>{n?o():history.replaceState(null,"",`#${t.path}`)})),M.subscribe("router:afterChange",({to:e,from:t}={})=>{if(W&&W.path===Le(t?.path)&&ot(t?.path,e?.path)){const o=W;W=null,o.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(xn(),W){const p=W;W=null,p.dispose()}const t=Le(location.hash.replace(/^#/,"")),o=++It,n=()=>o!==It||!e.get(0)?.isConnected||Le(location.hash.replace(/^#/,""))!==t;C=[],N=null,ge=null;const l=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);N=l?l[1]:null;let a=null;const i=E.loader(e.get(0),{type:"dots"});if(N)try{if(a=await se(`/forms/${N}`),n()){i.destroy();return}C=a.fields||[],ge=a.actions?.collection??null}catch{if(n()){i.destroy();return}E.toast("Could not load form.",{type:"error"})}ye={};try{const p=await se("/projects").catch(()=>[]);if(n()){i.destroy();return}const v=e.find("#field-project").get(0);v&&(Array.isArray(p)?p:[]).forEach(y=>{const k=document.createElement("option");k.value=y.slug,k.textContent=y.name||y.slug,v.appendChild(k)})}catch{}if(i.destroy(),Ft(e.get(0),a?a.title||a.slug:"New form"),N||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(ct(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),ye=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const p=a.settings||{};e.find("#setting-submit-text").val(p.submitText||"Submit"),e.find("#setting-success-message").val(p.successMessage||""),e.find("#setting-layout").val(p.layout||"grid"),e.find("#setting-columns").val(Te(p.columns)),e.find("#setting-submit-span").val(p.submitSpan||""),e.find("#columns-group").get(0).style.display=(p.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",p.honeypot!==!1),e.find("#setting-rate-limit").val(p.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(p.successRedirect||"");const v=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",v.enabled||!1),e.find("#action-email-recipients").val(v.recipients||""),e.find("#action-email-subject-prefix").val(v.subjectPrefix||"");const y=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",y.enabled||!1),e.find("#action-webhook-url").val(y.url||""),e.find("#action-webhook-method").val(y.method||"POST")}const r=a?.settings?.actionSlug||"";try{const p=await se("/actions").catch(()=>[]);if(n())return;const v=e.find("#action-cms-slug").get(0);if(be=Array.isArray(p)?p:[],(Array.isArray(p)?p:[]).forEach(y=>{const k=document.createElement("option");k.value=y.slug,k.textContent=y.title||y.slug,y.slug===r&&(k.selected=!0),v.appendChild(k)}),!p.length){const y=document.createElement("option");y.value="",y.textContent="No actions available",y.disabled=!0,v.appendChild(y)}}catch{}const c=p=>{e.find("#columns-group").get(0).style.display=p?"":"none",document.querySelectorAll(".fb-grid-row").forEach(v=>{v.style.display=p?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){c(this.value==="grid")}),c(e.find("#setting-layout").val()==="grid"),Y(e);const s=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",p=>{p.stopPropagation(),s.style.display=s.style.display==="none"?"":"none"}),le&&document.removeEventListener("click",le),le=()=>{s&&(s.style.display="none")},document.addEventListener("click",le),e.find("#add-field-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O();const p=C.length;C.push({name:`field_${p+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),Y(e);const v=e.find("#fields-list").get(0)?.lastElementChild;if(v){const y=v.querySelector(".fb-field-body");y&&(y.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O(),C.push({type:"spacer"}),Y(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O();const p=C.filter(v=>v.type==="page-break").length+2;C.push({type:"page-break",label:`Step ${p}`,description:""}),Y(e)}),ve=()=>{const p=Ne(e),v=e.find("#preview-container").get(0);if(!v)return;const y=e.find("#preview-test-result").get(0),k=e.find("#preview-test-badge").get(0);y&&(y.style.display="none",y.textContent=""),k&&(k.style.display=N?"":"none"),e.find("#preview-card").get(0).style.display="",v.textContent="";const V=document.createElement("div");V.id="fb-preview-form",v.appendChild(V);const J=N?async L=>{y&&(y.style.display="none",y.textContent="");try{const T=await fetch(`/api/forms/submit/${N}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(L)}),Q=await T.json();if(!T.ok)throw new Error(Q.error||"Submission failed.");y&&(y.textContent=Q.message||p.settings?.successMessage||"Submitted successfully.",y.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(T){y&&(y.textContent=T.message,y.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(T.message,{type:"error"})}return!1}:()=>!1,fe=p.fields.some(L=>L.type==="page-break");if(V.addEventListener("dm-form-end",L=>{const T=L.detail?.validation;if(T&&!T.valid){E.toast(`Still to answer: ${T.missing.map(Q=>Q.label).concat(T.errors).join(", ")}`,{type:"warning"});return}J(L.detail?.values||{})}),typeof F<"u"){const L=Te(p.settings?.columns),T=p.settings?.layout||"grid";if(fe&&F.wizard){const Q=Pt(p.fields,p.title),he=Q.map(ne=>({title:ne.title,description:ne.description,fields:$t(ne.fields,L)}));let B=0,Z=null,$e=null;const et=ne=>{const tt=(Q[B]||{}).fields||[];At("#fb-preview-form",tt),nt(V,tt),ne&&window.FormLogicEngine&&pt(p.fields)&&(Z?.destroy?.(),Z=new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},V,{baseValues:$e?.getStepData?$e.getStepData():{}}),Z.init())};$e=F.wizard("#fb-preview-form",{schema:{steps:he},layout:T,columns:L,finishText:p.settings?.submitText||"Finish",onStepChange:ne=>{B=ne,queueMicrotask(()=>et(!0))},onSubmit:J}),et(!1)}else if(F.render){const Q=$t(p.fields,L),he={};if(p.fields.forEach(B=>{if(!(!B.name||B.type==="page-break"||B.type==="spacer")&&(B.type==="select"||B.type==="multiselect")&&B.required){const Z=(B.options||[])[0];Z&&(he[B.name]=typeof Z=="object"?Z.value:Z)}}),F.render("#fb-preview-form",Q,he,{submitText:p.settings?.submitText||"Submit",layout:T,columns:L,onSubmit:J}),T==="grid"&&p.settings?.submitSpan==="full"){const B=document.querySelector("#fb-preview-form .form-buttons");B&&B.classList.add("col-span-full")}At("#fb-preview-form",p.fields),nt(V,p.fields)}window.FormLogicEngine&&pt(p.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},V).init()})}else{const L=document.createElement("p");L.textContent=`${p.fields.filter(T=>T.type!=="page-break").length} field(s): ${p.fields.filter(T=>T.type!=="page-break").map(T=>T.label).join(", ")}`,L.style.cssText="color:var(--dm-text-muted);font-style:italic;",V.appendChild(L)}},ve();const d=e.find("#editor-tabs").get(0),u=e.find("#preview-card").get(0),b=p=>{u&&u.contains(p.target)||Re()};d&&(d.addEventListener("input",b),d.addEventListener("change",b));const g=e.get(0),m=[],h=p=>(m.push(p),p);let w=!1;const f=M.observable(!1),x=M.observable(!1);let $=N,A=Ne(e),H=Ie(A),_=A;const j=()=>{w||!g.isConnected||(_=Ne(e),f.value=Ie(_)!==H)};let I=null;Me=()=>{clearTimeout(I),I=setTimeout(j,150)},h(()=>{clearTimeout(I),Me=null,de=null});const X=p=>{const v=p.settings||{};e.find("#field-title").val(p.title||""),e.find("#field-slug").val(p.slug||""),e.find("#field-description").val(p.description||""),e.find("#field-bundled").prop("checked",!!p.bundled),ye={...p.meta||{}},e.find("#field-project").val(p.meta?.project||""),e.find("#setting-submit-text").val(v.submitText||"Submit"),e.find("#setting-success-message").val(v.successMessage||""),e.find("#setting-layout").val(v.layout||"grid"),e.find("#setting-columns").val(Te(v.columns)),e.find("#setting-submit-span").val(v.submitSpan||""),e.find("#setting-honeypot").prop("checked",v.honeypot!==!1),e.find("#setting-rate-limit").val(v.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(v.successRedirect||""),e.find("#action-cms-slug").val(v.actionSlug||"");const y=p.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!y.enabled),e.find("#action-email-recipients").val(y.recipients||""),e.find("#action-email-subject-prefix").val(y.subjectPrefix||"");const k=p.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!k.enabled),e.find("#action-webhook-url").val(k.url||""),e.find("#action-webhook-method").val(k.method||"POST"),C=JSON.parse(JSON.stringify(p.fields||[])),c((v.layout||"grid")==="grid"),Y(e)};async function U(){if(x.peek()||w)return;const p=Ne(e);if(!p.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}x.value=!0;const v=N;try{N?(await se(`/forms/${N}`,{method:"PUT",body:JSON.stringify(p)}),E.toast("Form saved.",{type:"success"})):(N=(await se("/forms",{method:"POST",body:JSON.stringify(p)})).slug,E.toast("Form created.",{type:"success"})),$=N,A=p,H=Ie(p),_=p,f.value=!1;for(const y of new Set([re(v),re(N)]))try{S.remove?S.remove(y):S.set(y,null)}catch{}Ft(g,p.title),jt("#/forms"),v||R.navigate(`/forms/edit/${N}`)}catch(y){v||(N=null),E.toast(y.message||"Failed to save form.",{type:"error"})}finally{x.value=!1}}async function Ot(){f.peek()&&(!await E.confirm("Discard the changes you have not saved?")||w||(X(A),j(),Qe()))}const He=g.querySelector(".fex-bar");if(He){const p=M.applyBindings({dirty:f,saving:x},He,{methods:{save:U,discard:Ot}});h(()=>p.dispose())}h(_t(g,{position:"bottom"})),Ae(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>U()}),Ae(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),N&&Ae(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(N)}/submissions`}});const We=p=>{n()||!(p.ctrlKey||p.metaKey)||String(p.key).toLowerCase()!=="s"||(p.preventDefault(),p.stopImmediatePropagation(),U())};document.addEventListener("keydown",We,!0),h(()=>document.removeEventListener("keydown",We,!0));const ee=e.find("#fields-list").get(0),Mt=p=>p?.closest?.(".fb-field-card"),Ue=p=>Number(p?.dataset.index),Je=p=>p?.querySelector(":scope > .fb-field-body"),Ye=p=>{const v=Je(p);v&&(v.style.display=v.style.display==="none"?"":"none")},me=(p,v)=>{C=p,Y(e),v!=null&&ee?.querySelectorAll(".fb-field-card")[v]?.focus()},Rt=async p=>{try{await navigator.clipboard.writeText(p),E.toast(`Copied "${p}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${p}.`,{type:"info"})}},Dt=p=>{const v=Mt(p),y=Ue(v);O();const k=C[y];if(!k)return[];const V=k.type!=="spacer"&&k.type!=="page-break",J=Je(v),fe=J&&J.style.display!=="none";return[{header:Fe(k)},...J?[{label:fe?"Close":"Edit",icon:fe?"chevron-up":"edit",action:()=>Ye(v)}]:[],...V?[{label:"Logic & triggers",icon:"zap",action:()=>{J&&(J.style.display=""),(J?.querySelector(".fb-field-logic")||J)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{O(),me(Gt(C,y),y+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",disabled:y===0,action:()=>{O(),me(it(C,y,-1),y-1)}},{label:"Move down",icon:"arrow-down",disabled:y>=C.length-1,action:()=>{O(),me(it(C,y,1),y+1)}},...V&&k.name?[{label:"Copy field name",icon:"clipboard",action:()=>Rt(k.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(k.type!=="spacer"&&!await E.confirm(`Remove "${vn(Fe(k))}"?`))return;O();const L=[...C];L.splice(y,1),me(L,Math.min(y,L.length-1))}}]};let Ke=null;if(ee&&E.contextMenu&&(Ke=E.contextMenu(ee,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:p=>Dt(p)}),h(()=>Ke?.destroy?.())),de=p=>{for(const v of p.querySelectorAll(".fb-field-card")){v.tabIndex=0;const y=v.firstElementChild;if(!y||y.querySelector(".fex-kebab"))continue;const k=document.createElement("button");k.type="button",k.className="fex-kebab",k.textContent="\u22EE",k.title="Actions",O(),k.setAttribute("aria-label",`Actions for ${Fe(C[Ue(v)])}`),k.addEventListener("click",V=>{V.stopPropagation(),lt(k)}),y.appendChild(k)}},ee){de(ee);const p=v=>{const y=v.target?.classList?.contains("fb-field-card")?v.target:null;y&&(v.key==="F10"&&v.shiftKey?(v.preventDefault(),lt(y.firstElementChild)):v.key==="Enter"&&(v.preventDefault(),Ye(y)))};ee.addEventListener("keydown",p),h(()=>ee.removeEventListener("keydown",p))}const Qe=()=>{try{const p=re($);S.remove?S.remove(p):S.set(p,null)}catch{}},Xe=p=>{if(!f.peek()||!p){Qe();return}try{S.set(re($),{data:Vt(p),base:at(H),at:new Date().toISOString()})}catch{}},Ze=p=>{j(),f.peek()&&(Xe(_),p.preventDefault(),p.returnValue="")};window.addEventListener("beforeunload",Ze),h(()=>window.removeEventListener("beforeunload",Ze)),h(()=>{le&&(document.removeEventListener("click",le),le=null)}),W={path:t,dirty:()=>f.peek(),flush:()=>{clearTimeout(I),j()},dispose(){w||(Xe(_),w=!0,m.splice(0).reverse().forEach(p=>{try{p?.()}catch{}}))}};const qe=re(N);let te=null;try{te=S.get(qe)}catch{}if(te?.data){try{S.remove?S.remove(qe):S.set(qe,null)}catch{}const p=te.base&&te.base!==at(H),v=te.at?` (${D(te.at).format("D MMM HH:mm")})`:"";await E.confirm(`You left unsaved changes to this form${v}.${p?" The saved form has changed since then.":""} Pick up where you left off?`)&&!w&&(X(Ht(te.data,A)),j())}}};
8
+ `),l.style.fontFamily="monospace",o.appendChild(n),o.appendChild(l),o}function Se(e){return parseInt(e,10)===3?3:2}function Te(e){const t=e.find("#field-project").val()||"";return O(),{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:{...ge||{},project:t||null},fields:C,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:Se(e.find("#setting-columns").val()),submitSpan:e.find("#setting-submit-span").val()||"",honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...be!==null&&{collection:be}}}}function qt(e,t){const o={};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)),r={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&&(r.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(r.multiple=!0),n.density&&(r.density=n.density),n.columns&&(r.columns=n.columns),n.accent&&(r.accent=n.accent),n.accentStyle&&(r.accentStyle=n.accentStyle),n.glow&&(r.glow=!0),n.glowColour&&(r.glowColour=n.glowColour),n.shadow&&(r.shadow=n.shadow),n.shadowColour&&(r.shadowColour=n.shadowColour)),o[n.name]=r}),o}function $t(e,t){const o=typeof e=="string"?document.querySelector(e):e;o&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const l=o.querySelector(`[name="${n.name}"]`);l&&l.type!=="date"&&(l.type="date")})}function At(e,t){const o=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(o){for(;o.nextSibling;)o.nextSibling.remove();o.after(document.createTextNode(String(t||"")))}}const vn=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");let W=null,Ft=0,It=!1;const Ne=e=>String(e||"").split("?")[0].replace(/\/$/,"");function xn(){It||!window.R?.use||(It=!0,R.use((e,t,o)=>!W||!at(t?.path,e?.path)||W.path!==Ne(t?.path)||(W.flush(),!W.dirty())?o():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(n=>{n?o():history.replaceState(null,"",`#${t.path}`)})),M.subscribe("router:afterChange",({to:e,from:t}={})=>{if(W&&W.path===Ne(t?.path)&&at(t?.path,e?.path)){const o=W;W=null,o.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(xn(),W){const p=W;W=null,p.dispose()}const t=Ne(location.hash.replace(/^#/,"")),o=++Ft,n=()=>o!==Ft||!e.get(0)?.isConnected||Ne(location.hash.replace(/^#/,""))!==t;C=[],N=null,be=null;const l=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);N=l?l[1]:null;let a=null;const i=E.loader(e.get(0),{type:"dots"});if(N)try{if(a=await ie(`/forms/${N}`),n()){i.destroy();return}C=a.fields||[],be=a.actions?.collection??null}catch{if(n()){i.destroy();return}E.toast("Could not load form.",{type:"error"})}ge={};try{const p=await ie("/projects").catch(()=>[]);if(n()){i.destroy();return}const v=e.find("#field-project").get(0);v&&(Array.isArray(p)?p:[]).forEach(y=>{const k=document.createElement("option");k.value=y.slug,k.textContent=y.name||y.slug,v.appendChild(k)})}catch{}if(i.destroy(),At(e.get(0),a?a.title||a.slug:"New form"),N||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(rt(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),ge=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const p=a.settings||{};e.find("#setting-submit-text").val(p.submitText||"Submit"),e.find("#setting-success-message").val(p.successMessage||""),e.find("#setting-layout").val(p.layout||"grid"),e.find("#setting-columns").val(Se(p.columns)),e.find("#setting-submit-span").val(p.submitSpan||""),e.find("#columns-group").get(0).style.display=(p.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",p.honeypot!==!1),e.find("#setting-rate-limit").val(p.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(p.successRedirect||"");const v=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",v.enabled||!1),e.find("#action-email-recipients").val(v.recipients||""),e.find("#action-email-subject-prefix").val(v.subjectPrefix||"");const y=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",y.enabled||!1),e.find("#action-webhook-url").val(y.url||""),e.find("#action-webhook-method").val(y.method||"POST")}const r=a?.settings?.actionSlug||"";try{const p=await ie("/actions").catch(()=>[]);if(n())return;const v=e.find("#action-cms-slug").get(0);if(he=Array.isArray(p)?p:[],(Array.isArray(p)?p:[]).forEach(y=>{const k=document.createElement("option");k.value=y.slug,k.textContent=y.title||y.slug,y.slug===r&&(k.selected=!0),v.appendChild(k)}),!p.length){const y=document.createElement("option");y.value="",y.textContent="No actions available",y.disabled=!0,v.appendChild(y)}}catch{}const c=p=>{e.find("#columns-group").get(0).style.display=p?"":"none",document.querySelectorAll(".fb-grid-row").forEach(v=>{v.style.display=p?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){c(this.value==="grid")}),c(e.find("#setting-layout").val()==="grid"),J(e);const s=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",p=>{p.stopPropagation(),s.style.display=s.style.display==="none"?"":"none"}),ne&&document.removeEventListener("click",ne),ne=()=>{s&&(s.style.display="none")},document.addEventListener("click",ne),e.find("#add-field-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O();const p=C.length;C.push({name:`field_${p+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),J(e);const v=e.find("#fields-list").get(0)?.lastElementChild;if(v){const y=v.querySelector(".fb-field-body");y&&(y.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O(),C.push({type:"spacer"}),J(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O();const p=C.filter(v=>v.type==="page-break").length+2;C.push({type:"page-break",label:`Step ${p}`,description:""}),J(e)}),ye=()=>{const p=Te(e),v=e.find("#preview-container").get(0);if(!v)return;const y=e.find("#preview-test-result").get(0),k=e.find("#preview-test-badge").get(0);y&&(y.style.display="none",y.textContent=""),k&&(k.style.display=N?"":"none"),e.find("#preview-card").get(0).style.display="",v.textContent="";const j=document.createElement("div");j.id="fb-preview-form",v.appendChild(j);const U=N?async L=>{y&&(y.style.display="none",y.textContent="");try{const T=await fetch(`/api/forms/submit/${N}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(L)}),K=await T.json();if(!T.ok)throw new Error(K.error||"Submission failed.");y&&(y.textContent=K.message||p.settings?.successMessage||"Submitted successfully.",y.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(T){y&&(y.textContent=T.message,y.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(T.message,{type:"error"})}return!1}:()=>!1,me=p.fields.some(L=>L.type==="page-break");if(j.addEventListener("dm-form-end",L=>{const T=L.detail?.validation;if(T&&!T.valid){E.toast(`Still to answer: ${T.missing.map(K=>K.label).concat(T.errors).join(", ")}`,{type:"warning"});return}U(L.detail?.values||{})}),typeof F<"u"){const L=Se(p.settings?.columns),T=p.settings?.layout||"grid";if(me&&F.wizard){const K=zt(p.fields,p.title),fe=K.map(te=>({title:te.title,description:te.description,fields:qt(te.fields,L)}));let B=0,X=null,qe=null;const Ze=te=>{const et=(K[B]||{}).fields||[];$t("#fb-preview-form",et),tt(j,et),te&&window.FormLogicEngine&&dt(p.fields)&&(X?.destroy?.(),X=new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},j,{baseValues:qe?.getStepData?qe.getStepData():{}}),X.init())};qe=F.wizard("#fb-preview-form",{schema:{steps:fe},layout:T,columns:L,finishText:p.settings?.submitText||"Finish",onStepChange:te=>{B=te,queueMicrotask(()=>Ze(!0))},onSubmit:U}),Ze(!1)}else if(F.render){const K=qt(p.fields,L),fe={};if(p.fields.forEach(B=>{if(!(!B.name||B.type==="page-break"||B.type==="spacer")&&(B.type==="select"||B.type==="multiselect")&&B.required){const X=(B.options||[])[0];X&&(fe[B.name]=typeof X=="object"?X.value:X)}}),F.render("#fb-preview-form",K,fe,{submitText:p.settings?.submitText||"Submit",layout:T,columns:L,onSubmit:U}),T==="grid"&&p.settings?.submitSpan==="full"){const B=document.querySelector("#fb-preview-form .form-buttons");B&&B.classList.add("col-span-full")}$t("#fb-preview-form",p.fields),tt(j,p.fields)}window.FormLogicEngine&&dt(p.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},j).init()})}else{const L=document.createElement("p");L.textContent=`${p.fields.filter(T=>T.type!=="page-break").length} field(s): ${p.fields.filter(T=>T.type!=="page-break").map(T=>T.label).join(", ")}`,L.style.cssText="color:var(--dm-text-muted);font-style:italic;",j.appendChild(L)}},ye();const d=e.find("#editor-tabs").get(0),u=e.find("#preview-card").get(0),b=p=>{u&&u.contains(p.target)||Re()};d&&(d.addEventListener("input",b),d.addEventListener("change",b));const g=e.get(0),m=[],h=p=>(m.push(p),p);let w=!1;const f=M.observable(!1),x=M.observable(!1);let $=N,A=Te(e),G=Fe(A),P=A;const _=()=>{w||!g.isConnected||(P=Te(e),f.value=Fe(P)!==G)};let I=null;Oe=()=>{clearTimeout(I),I=setTimeout(_,150)},h(()=>{clearTimeout(I),Oe=null,ce=null});const Q=p=>{const v=p.settings||{};e.find("#field-title").val(p.title||""),e.find("#field-slug").val(p.slug||""),e.find("#field-description").val(p.description||""),e.find("#field-bundled").prop("checked",!!p.bundled),ge={...p.meta||{}},e.find("#field-project").val(p.meta?.project||""),e.find("#setting-submit-text").val(v.submitText||"Submit"),e.find("#setting-success-message").val(v.successMessage||""),e.find("#setting-layout").val(v.layout||"grid"),e.find("#setting-columns").val(Se(v.columns)),e.find("#setting-submit-span").val(v.submitSpan||""),e.find("#setting-honeypot").prop("checked",v.honeypot!==!1),e.find("#setting-rate-limit").val(v.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(v.successRedirect||""),e.find("#action-cms-slug").val(v.actionSlug||"");const y=p.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!y.enabled),e.find("#action-email-recipients").val(y.recipients||""),e.find("#action-email-subject-prefix").val(y.subjectPrefix||"");const k=p.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!k.enabled),e.find("#action-webhook-url").val(k.url||""),e.find("#action-webhook-method").val(k.method||"POST"),C=JSON.parse(JSON.stringify(p.fields||[])),c((v.layout||"grid")==="grid"),J(e)};async function H(){if(x.peek()||w)return;const p=Te(e);if(!p.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}x.value=!0;const v=N;try{N?(await ie(`/forms/${N}`,{method:"PUT",body:JSON.stringify(p)}),E.toast("Form saved.",{type:"success"})):(N=(await ie("/forms",{method:"POST",body:JSON.stringify(p)})).slug,E.toast("Form created.",{type:"success"})),$=N,A=p,G=Fe(p),P=p,f.value=!1;for(const y of new Set([se(v),se(N)]))try{S.remove?S.remove(y):S.set(y,null)}catch{}At(g,p.title),_t("#/forms"),v||R.navigate(`/forms/edit/${N}`)}catch(y){v||(N=null),E.toast(y.message||"Failed to save form.",{type:"error"})}finally{x.value=!1}}async function Bt(){f.peek()&&(!await E.confirm("Discard the changes you have not saved?")||w||(Q(A),_(),Ke()))}const Ge=g.querySelector(".fex-bar");if(Ge){const p=M.applyBindings({dirty:f,saving:x},Ge,{methods:{save:H,discard:Bt}});h(()=>p.dispose())}h(Pt(g,{position:"bottom"})),$e(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>H()}),$e(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),N&&$e(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(N)}/submissions`}});const We=p=>{n()||!(p.ctrlKey||p.metaKey)||String(p.key).toLowerCase()!=="s"||(p.preventDefault(),p.stopImmediatePropagation(),H())};document.addEventListener("keydown",We,!0),h(()=>document.removeEventListener("keydown",We,!0));const Z=e.find("#fields-list").get(0),Ot=p=>p?.closest?.(".fb-field-card"),He=p=>Number(p?.dataset.index),Ue=p=>p?.querySelector(":scope > .fb-field-body"),Je=p=>{const v=Ue(p);v&&(v.style.display=v.style.display==="none"?"":"none")},ue=(p,v)=>{C=p,J(e),v!=null&&Z?.querySelectorAll(".fb-field-card")[v]?.focus()},Rt=async p=>{try{await navigator.clipboard.writeText(p),E.toast(`Copied "${p}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${p}.`,{type:"info"})}},Dt=p=>{const v=Ot(p),y=He(v);O();const k=C[y];if(!k)return[];const j=k.type!=="spacer"&&k.type!=="page-break",U=Ue(v),me=U&&U.style.display!=="none";return[{header:Ae(k)},...U?[{label:me?"Close":"Edit",icon:me?"chevron-up":"edit",action:()=>Je(v)}]:[],...j?[{label:"Logic & triggers",icon:"zap",action:()=>{U&&(U.style.display=""),(U?.querySelector(".fb-field-logic")||U)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{O(),ue(Vt(C,y),y+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",disabled:y===0,action:()=>{O(),ue(ot(C,y,-1),y-1)}},{label:"Move down",icon:"arrow-down",disabled:y>=C.length-1,action:()=>{O(),ue(ot(C,y,1),y+1)}},...j&&k.name?[{label:"Copy field name",icon:"clipboard",action:()=>Rt(k.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(k.type!=="spacer"&&!await E.confirm(`Remove "${vn(Ae(k))}"?`))return;O();const L=[...C];L.splice(y,1),ue(L,Math.min(y,L.length-1))}}]};let Ye=null;if(Z&&E.contextMenu&&(Ye=E.contextMenu(Z,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:p=>Dt(p)}),h(()=>Ye?.destroy?.())),ce=p=>{for(const v of p.querySelectorAll(".fb-field-card")){v.tabIndex=0;const y=v.firstElementChild;if(!y||y.querySelector(".fex-kebab"))continue;const k=document.createElement("button");k.type="button",k.className="fex-kebab",k.textContent="\u22EE",k.title="Actions",O(),k.setAttribute("aria-label",`Actions for ${Ae(C[He(v)])}`),k.addEventListener("click",j=>{j.stopPropagation(),nt(k)}),y.appendChild(k)}},Z){ce(Z);const p=v=>{const y=v.target?.classList?.contains("fb-field-card")?v.target:null;y&&(v.key==="F10"&&v.shiftKey?(v.preventDefault(),nt(y.firstElementChild)):v.key==="Enter"&&(v.preventDefault(),Je(y)))};Z.addEventListener("keydown",p),h(()=>Z.removeEventListener("keydown",p))}const Ke=()=>{try{const p=se($);S.remove?S.remove(p):S.set(p,null)}catch{}},Qe=p=>{if(!f.peek()||!p){Ke();return}try{S.set(se($),{data:jt(p),base:lt(G),at:new Date().toISOString()})}catch{}},Xe=p=>{_(),f.peek()&&(Qe(P),p.preventDefault(),p.returnValue="")};window.addEventListener("beforeunload",Xe),h(()=>window.removeEventListener("beforeunload",Xe)),h(()=>{ne&&(document.removeEventListener("click",ne),ne=null)}),W={path:t,dirty:()=>f.peek(),flush:()=>{clearTimeout(I),_()},dispose(){w||(Qe(P),w=!0,m.splice(0).reverse().forEach(p=>{try{p?.()}catch{}}))}};const Le=se(N);let ee=null;try{ee=S.get(Le)}catch{}if(ee?.data){try{S.remove?S.remove(Le):S.set(Le,null)}catch{}const p=ee.base&&ee.base!==lt(G),v=ee.at?` (${Wt(ee.at)})`:"";await E.confirm(`You left unsaved changes to this form${v}.${p?" The saved form has changed since then.":""} Pick up where you left off?`)&&!w&&(Q(Gt(ee.data,A)),_())}}};
@@ -1,4 +1,4 @@
1
- import{apiRequest as A}from"/admin/js/api.js";import{addBannerAction as V}from"/admin/js/lib/plugin-chrome.js";import{helpPopovers as re}from"/admin/js/lib/help-popover.js";import{onceClosed as ke,openMenuAt as ce,sidebarCount as z,viewLifetime as $e}from"/admin/js/lib/tool-kit.js";import{FILTERS as Se,answerFields as Ne,answerText as O,arrangeSubmissions as Me,submissionCounts as Te,submissionRow as L,submissionText as Ae}from"/admin/js/lib/form-submissions-arrange.js";const le=/^#\/forms\/[^/?#]+\/submissions\/?(\?.*)?$/,G="form-submissions.filter",De=`
1
+ import{apiRequest as A}from"/admin/js/api.js";import{addBannerAction as H}from"/admin/js/lib/plugin-chrome.js";import{helpPopovers as re}from"/admin/js/lib/help-popover.js";import{onceClosed as ke,openMenuAt as ce,sidebarCount as G,viewLifetime as $e}from"/admin/js/lib/tool-kit.js";import{FILTERS as Se,answerFields as Ne,answerText as O,arrangeSubmissions as Te,submissionCounts as Me,submissionRow as L,submissionText as Ae}from"/admin/js/lib/form-submissions-arrange.js";import{fmtDateTime as De}from"../lib/dates.js";const le=/^#\/forms\/[^/?#]+\/submissions\/?(\?.*)?$/,X="form-submissions.filter",Le=`
2
2
  <div class="fsx-row" data-id="{{id}}" tabindex="0" data-bind-class="rowCls">
3
3
  <span class="fsx-dot" aria-hidden="true"></span>
4
4
  <span class="fsx-main"><strong>{{title}}</strong><small>{{meta}}</small></span>
@@ -8,4 +8,4 @@ import{apiRequest as A}from"/admin/js/api.js";import{addBannerAction as V}from"/
8
8
  </span>
9
9
  <span class="fsx-when" title="{{whenFull}}">{{when}}</span>
10
10
  <button type="button" class="fsx-kebab" aria-label="Actions for this submission" title="Actions">\u22EE</button>
11
- </div>`,X=i=>String(i??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;"),U=(i,r,b=`${r}s`)=>`${i} ${i===1?r:b}`,Q=i=>i?D(i).format("DD MMM YYYY HH:mm"):"";async function me(i){try{return await navigator.clipboard.writeText(i),!0}catch{}try{const r=document.createElement("textarea");r.value=i,r.style.cssText="position:fixed;opacity:0;",document.body.appendChild(r),r.select();const b=document.execCommand("copy");return r.remove(),b}catch{return!1}}const h=$e(le);export const formSubmissionsView={templateUrl:"/admin/js/templates/form-submissions.html",async onMount(i){h.reset();const r=i.get(0).querySelector(".fsx")||i.get(0),b=()=>le.test(location.hash)&&r.isConnected,p=decodeURIComponent((location.hash.match(/^#\/forms\/([^/?#]+)\/submissions/)||[])[1]||"");if(!p){E.toast("No form selected.",{type:"error"});return}const C=encodeURIComponent(p),y=M.observable(null),c=M.observable([]),Z=M.observable(!0),q=M.observable("");let ee="inbox";try{ee=Se.includes(S.get(G))?S.get(G):"inbox"}catch{}const w=M.observable(ee),te=M.observable(""),j=M.observable(""),F=M.observable("");h.add(M.effect(()=>{const e=w.value;try{S.set(G,e)}catch{}}));const k=M.computed(()=>Ne(y.value||{})),P=M.observable([]);h.add(M.effect(()=>{const e=Date.now(),t=Me(c.value,{filter:w.value,query:te.value,from:j.value,to:F.value,now:e}),s=k.value;P.value=t.map(n=>{const a=L(n,s,e);return{...a,when:a.at?D(a.at).fromNow():"",whenFull:Q(a.at)}})}));const de=M.computed(()=>Te(c.value)),pe=M.computed(()=>{const e=P.value.length,t=c.value.length;return t?e===t?U(t,"submission"):`${e} of ${U(t,"submission")}`:""}),ue=M.computed(()=>c.value.length?w.value==="spam"?"Nothing marked as spam.":"No submissions match.":"No submissions yet - they appear here as people send the form."),fe=M.computed(()=>y.value?`What people sent through "${y.value.title||p}".`:"What people sent through this form."),R=e=>c.peek().find(t=>String(t.id)===String(e));async function he(){try{const[e,t]=await Promise.all([A(`/forms/${C}`),A(`/forms/${C}/submissions`)]);if(!b())return;y.value=e||null,c.value=Array.isArray(t)?t:[],q.value="",be(e?.title||p)}catch(e){if(!b())return;q.value=`Could not load the submissions: ${e.message||e}`}finally{Z.value=!1}}function be(e){const t=i.get(0).querySelector(".dm-plugin-banner-name"),s=t?.lastChild;s&&s.nodeType===Node.TEXT_NODE&&t.querySelector(".dm-plugin-banner-sep")&&(s.textContent=`${e} submissions`),document.title=`${e} - Submissions - Domma CMS`}async function B(e,t){try{const s=await A(`/forms/${C}/submissions/${encodeURIComponent(e.id)}/spam`,{method:"POST",body:JSON.stringify({spam:t})});return c.value=c.peek().map(n=>String(n.id)===String(e.id)?{...n,data:s?.entry?.data||{...n.data,spam:t}}:n),E.toast(t?"Marked as spam - it is under Spam now.":"Back in the inbox.",{type:"success"}),z("#/forms"),!0}catch(s){return E.toast(`Not changed: ${s.message||s}`,{type:"error"}),!1}}async function Y(e){const t=L(e,k.peek()).title;if(!await E.confirm(`Delete the submission from "${X(t)}"? This cannot be undone.`))return!1;try{return await A(`/forms/${C}/submissions/${encodeURIComponent(e.id)}`,{method:"DELETE"}),c.value=c.peek().filter(s=>String(s.id)!==String(e.id)),E.toast("Submission deleted.",{type:"success"}),z("#/forms"),!0}catch(s){return E.toast(`Not deleted: ${s.message||s}`,{type:"error"}),!1}}async function ye(){const e=c.peek().length;if(!e){E.toast("There are no submissions to clear.",{type:"info"});return}const t=y.peek()?.title||p;if(await E.confirm(`Delete all ${U(e,"submission")} to "${X(t)}", spam included? This cannot be undone - Export them first if you may need them.`))try{await A(`/forms/${C}/submissions`,{method:"DELETE"}),c.value=[],E.toast("All submissions cleared.",{type:"success"}),z("#/forms")}catch(s){E.toast(`Not cleared: ${s.message||s}`,{type:"error"})}}const se=async e=>{const t=Ae(e,k.peek(),{formTitle:y.peek()?.title||p,when:Q(e.meta?.createdAt)});E.toast(await me(t)?"Copied.":"Copy failed.",{type:"info"})},we=async e=>{E.toast(await me(e)?`Copied ${e}.`:"Copy failed.",{type:"info"})},ne=e=>{const t=L(e,k.peek()).email;if(!t)return;const s=`Re: ${y.peek()?.title||p}`;window.location.href=`mailto:${encodeURIComponent(t)}?subject=${encodeURIComponent(s)}`};async function Ee(e,t){try{const s=await fetch(`/api/forms/${C}/submissions/${e}`,{headers:{Authorization:`Bearer ${S.get("auth_token")||""}`}});if(!s.ok)throw new Error(`${s.status} ${s.statusText}`);const n=await s.blob(),a=document.createElement("a");return a.href=URL.createObjectURL(n),a.download=t,document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(a.href),1e3),!0}catch(s){return E.toast(`Export failed: ${s.message||s}`,{type:"error"}),!1}}const H=new Set;function oe(e,t,s="md"){const n=E.slideover({title:X(e),size:s,position:"right"});n.element.appendChild(t);const a=re(t);return H.add(n),ke(n,()=>{H.delete(n),a()}),I.scan(t),n.open(),n}function ve(){const e=c.peek().length,t=document.createElement("div");t.className="fsx-export";const s=document.createElement("p");s.className="fsx-note",s.textContent=e?`All ${U(e,"submission")}, spam included.`:"There are no submissions yet - the file will be empty.",t.appendChild(s);let n;const a=(N,v,_,J,$)=>{const l=document.createElement("button");l.type="button",l.className="btn btn-ghost";const x=document.createElement("span");x.setAttribute("data-icon",v),l.append(x,document.createTextNode(` ${N}`));const T=document.createElement("span");T.setAttribute("data-help",$),l.addEventListener("click",async()=>{await Ee(_,`${p}-submissions.${J}`)&&n?.close()});const o=document.createElement("div");o.append(l,T),t.appendChild(o)};a("Export as CSV","file-text","export","csv","One row per submission, one column per question - opens in Excel, Numbers or Google Sheets."),a("Export as JSON","code","export/json","json","Every submission exactly as stored, with its id and dates - for importing elsewhere or keeping a full copy."),n=oe("Export submissions",t,"sm")}function W(e){if(!e)return;const t=k.peek(),s=L(e,t),n=document.createElement("div");n.className="fsx-detail";const a=document.createElement("div");a.className="fsx-facts";const N=o=>{const m=document.createElement("span");m.textContent=o,a.appendChild(m)};e.meta?.createdAt&&N(`Sent ${Q(e.meta.createdAt)} (${D(e.meta.createdAt).fromNow()})`),e.meta?.ip&&N(`IP ${e.meta.ip}`),s.spam&&N("Marked as spam"),n.appendChild(a);const v=document.createElement("dl");v.className="fsx-answers";const _=t.filter(o=>O(e.data?.[o.name])!=="");for(const o of _){const m=document.createElement("div");m.className="fsx-answer";const f=document.createElement("dt");f.textContent=o.label;const g=document.createElement("dd");g.textContent=O(e.data[o.name]),m.append(f,g),v.appendChild(m)}const J=new Set(t.map(o=>o.name));for(const[o,m]of Object.entries(e.data||{})){if(J.has(o)||o==="spam"||O(m)==="")continue;const f=document.createElement("div");f.className="fsx-answer";const g=document.createElement("dt");g.textContent=`${o} (no longer on the form)`;const d=document.createElement("dd");d.textContent=O(m),f.append(g,d),v.appendChild(f)}if(v.children.length)n.appendChild(v);else{const o=document.createElement("p");o.className="fsx-note",o.textContent="Nothing was filled in.",n.appendChild(o)}const $=document.createElement("div");$.className="fsx-actions";const l=(o,m,f,g)=>{const d=document.createElement("button");d.type="button",d.className=`btn btn-sm ${f}`;const K=document.createElement("span");return K.setAttribute("data-icon",m),K.setAttribute("data-icon-size","13"),d.append(K,document.createTextNode(` ${o}`)),d.addEventListener("click",g),$.appendChild(d),d};let x;l("Copy","copy","btn-ghost",()=>se(e)),s.email&&l("Email them","mail","btn-ghost",()=>ne(e)),l(s.spam?"Not spam":"Mark as spam",s.spam?"inbox":"alert-triangle","btn-ghost",async()=>{await B(e,!s.spam)&&x.close()});const T=document.createElement("span");T.className="fsx-spacer",$.appendChild(T),l("Delete","trash","btn-ghost text-danger",async()=>{await Y(e)&&x.close()}),l("Close","x","btn-ghost",()=>x.close()),n.appendChild($),x=oe(s.title,n)}function xe(e){const t=R(e);if(!t)return[];const s=L(t,k.peek());return[{header:s.title},{label:"Open\u2026",icon:"eye",action:()=>W(t)},{label:"Copy submission",icon:"copy",action:()=>se(t)},{type:"divider"},{label:s.email?`Copy ${s.email}`:"Copy email",icon:"at-sign",disabled:!s.email,action:()=>we(s.email)},{label:"Email them\u2026",icon:"mail",disabled:!s.email,action:()=>ne(t)},{type:"divider"},s.spam?{label:"Not spam - back to the inbox",icon:"inbox",action:()=>B(t,!1)}:{label:"Mark as spam",icon:"alert-triangle",action:()=>B(t,!0)},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>Y(t)}]}const u=r.querySelector(".fsx-list");u.innerHTML=De;const ge=M.applyBindings({loading:Z,loadError:q,filter:w,query:te,from:j,to:F,rows:P,counts:de,summary:pe,emptyText:ue,intro:fe},r,{methods:{showInbox:()=>{w.value="inbox"},showNew:()=>{w.value="new"},showSpam:()=>{w.value="spam"},clearDates:()=>{j.value="",F.value=""}}});h.add(()=>ge.dispose()),h.add(re(r,{position:"bottom"}));const Ce=E.contextMenu(u,{cursor:"glyph",match:".fsx-row",inherit:!1,density:"compact",items:e=>xe(e.dataset.id)});h.add(()=>Ce?.destroy?.());const ae=e=>{const t=e.target.closest(".fsx-row");if(!t)return;const s=e.target.closest(".fsx-kebab");if(s){ce(s);return}W(R(t.dataset.id))},ie=e=>{const t=e.target.closest(".fsx-row");if(!(!t||e.target!==t)){if(e.key==="F10"&&e.shiftKey)e.preventDefault(),ce(t);else if(e.key==="Enter")W(R(t.dataset.id));else if(e.key==="Delete"){e.preventDefault();const s=R(t.dataset.id);s&&Y(s)}}};u.addEventListener("click",ae),u.addEventListener("keydown",ie),h.add(()=>{u.removeEventListener("click",ae),u.removeEventListener("keydown",ie)}),V(i,{id:"form-submissions-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),V(i,{id:"form-submissions-export",icon:"download",title:"Export (CSV or JSON)",onClick:ve}),V(i,{id:"form-submissions-clear",icon:"trash",title:"Clear all submissions",onClick:ye}),h.add(()=>{[...H].forEach(e=>{try{e.close()}catch{}})}),I.scan(r),await he(),b()&&requestAnimationFrame(()=>{u.isConnected&&I.scan(u)})}};
11
+ </div>`,Y=i=>String(i??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;"),U=(i,r,b=`${r}s`)=>`${i} ${i===1?r:b}`,Q=i=>i?De(i):"";async function me(i){try{return await navigator.clipboard.writeText(i),!0}catch{}try{const r=document.createElement("textarea");r.value=i,r.style.cssText="position:fixed;opacity:0;",document.body.appendChild(r),r.select();const b=document.execCommand("copy");return r.remove(),b}catch{return!1}}const h=$e(le);export const formSubmissionsView={templateUrl:"/admin/js/templates/form-submissions.html",async onMount(i){h.reset();const r=i.get(0).querySelector(".fsx")||i.get(0),b=()=>le.test(location.hash)&&r.isConnected,p=decodeURIComponent((location.hash.match(/^#\/forms\/([^/?#]+)\/submissions/)||[])[1]||"");if(!p){E.toast("No form selected.",{type:"error"});return}const C=encodeURIComponent(p),y=M.observable(null),c=M.observable([]),Z=M.observable(!0),q=M.observable("");let ee="inbox";try{ee=Se.includes(S.get(X))?S.get(X):"inbox"}catch{}const w=M.observable(ee),te=M.observable(""),j=M.observable(""),F=M.observable("");h.add(M.effect(()=>{const e=w.value;try{S.set(X,e)}catch{}}));const k=M.computed(()=>Ne(y.value||{})),P=M.observable([]);h.add(M.effect(()=>{const e=Date.now(),t=Te(c.value,{filter:w.value,query:te.value,from:j.value,to:F.value,now:e}),s=k.value;P.value=t.map(n=>{const a=L(n,s,e);return{...a,when:a.at?D(a.at).fromNow():"",whenFull:Q(a.at)}})}));const de=M.computed(()=>Me(c.value)),pe=M.computed(()=>{const e=P.value.length,t=c.value.length;return t?e===t?U(t,"submission"):`${e} of ${U(t,"submission")}`:""}),ue=M.computed(()=>c.value.length?w.value==="spam"?"Nothing marked as spam.":"No submissions match.":"No submissions yet - they appear here as people send the form."),fe=M.computed(()=>y.value?`What people sent through "${y.value.title||p}".`:"What people sent through this form."),R=e=>c.peek().find(t=>String(t.id)===String(e));async function he(){try{const[e,t]=await Promise.all([A(`/forms/${C}`),A(`/forms/${C}/submissions`)]);if(!b())return;y.value=e||null,c.value=Array.isArray(t)?t:[],q.value="",be(e?.title||p)}catch(e){if(!b())return;q.value=`Could not load the submissions: ${e.message||e}`}finally{Z.value=!1}}function be(e){const t=i.get(0).querySelector(".dm-plugin-banner-name"),s=t?.lastChild;s&&s.nodeType===Node.TEXT_NODE&&t.querySelector(".dm-plugin-banner-sep")&&(s.textContent=`${e} submissions`),document.title=`${e} - Submissions - Domma CMS`}async function B(e,t){try{const s=await A(`/forms/${C}/submissions/${encodeURIComponent(e.id)}/spam`,{method:"POST",body:JSON.stringify({spam:t})});return c.value=c.peek().map(n=>String(n.id)===String(e.id)?{...n,data:s?.entry?.data||{...n.data,spam:t}}:n),E.toast(t?"Marked as spam - it is under Spam now.":"Back in the inbox.",{type:"success"}),G("#/forms"),!0}catch(s){return E.toast(`Not changed: ${s.message||s}`,{type:"error"}),!1}}async function W(e){const t=L(e,k.peek()).title;if(!await E.confirm(`Delete the submission from "${Y(t)}"? This cannot be undone.`))return!1;try{return await A(`/forms/${C}/submissions/${encodeURIComponent(e.id)}`,{method:"DELETE"}),c.value=c.peek().filter(s=>String(s.id)!==String(e.id)),E.toast("Submission deleted.",{type:"success"}),G("#/forms"),!0}catch(s){return E.toast(`Not deleted: ${s.message||s}`,{type:"error"}),!1}}async function ye(){const e=c.peek().length;if(!e){E.toast("There are no submissions to clear.",{type:"info"});return}const t=y.peek()?.title||p;if(await E.confirm(`Delete all ${U(e,"submission")} to "${Y(t)}", spam included? This cannot be undone - Export them first if you may need them.`))try{await A(`/forms/${C}/submissions`,{method:"DELETE"}),c.value=[],E.toast("All submissions cleared.",{type:"success"}),G("#/forms")}catch(s){E.toast(`Not cleared: ${s.message||s}`,{type:"error"})}}const se=async e=>{const t=Ae(e,k.peek(),{formTitle:y.peek()?.title||p,when:Q(e.meta?.createdAt)});E.toast(await me(t)?"Copied.":"Copy failed.",{type:"info"})},we=async e=>{E.toast(await me(e)?`Copied ${e}.`:"Copy failed.",{type:"info"})},ne=e=>{const t=L(e,k.peek()).email;if(!t)return;const s=`Re: ${y.peek()?.title||p}`;window.location.href=`mailto:${encodeURIComponent(t)}?subject=${encodeURIComponent(s)}`};async function Ee(e,t){try{const s=await fetch(`/api/forms/${C}/submissions/${e}`,{headers:{Authorization:`Bearer ${S.get("auth_token")||""}`}});if(!s.ok)throw new Error(`${s.status} ${s.statusText}`);const n=await s.blob(),a=document.createElement("a");return a.href=URL.createObjectURL(n),a.download=t,document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(a.href),1e3),!0}catch(s){return E.toast(`Export failed: ${s.message||s}`,{type:"error"}),!1}}const _=new Set;function oe(e,t,s="md"){const n=E.slideover({title:Y(e),size:s,position:"right"});n.element.appendChild(t);const a=re(t);return _.add(n),ke(n,()=>{_.delete(n),a()}),I.scan(t),n.open(),n}function ve(){const e=c.peek().length,t=document.createElement("div");t.className="fsx-export";const s=document.createElement("p");s.className="fsx-note",s.textContent=e?`All ${U(e,"submission")}, spam included.`:"There are no submissions yet - the file will be empty.",t.appendChild(s);let n;const a=(N,v,K,V,$)=>{const l=document.createElement("button");l.type="button",l.className="btn btn-ghost";const x=document.createElement("span");x.setAttribute("data-icon",v),l.append(x,document.createTextNode(` ${N}`));const T=document.createElement("span");T.setAttribute("data-help",$),l.addEventListener("click",async()=>{await Ee(K,`${p}-submissions.${V}`)&&n?.close()});const o=document.createElement("div");o.append(l,T),t.appendChild(o)};a("Export as CSV","file-text","export","csv","One row per submission, one column per question - opens in Excel, Numbers or Google Sheets."),a("Export as JSON","code","export/json","json","Every submission exactly as stored, with its id and dates - for importing elsewhere or keeping a full copy."),n=oe("Export submissions",t,"sm")}function J(e){if(!e)return;const t=k.peek(),s=L(e,t),n=document.createElement("div");n.className="fsx-detail";const a=document.createElement("div");a.className="fsx-facts";const N=o=>{const m=document.createElement("span");m.textContent=o,a.appendChild(m)};e.meta?.createdAt&&N(`Sent ${Q(e.meta.createdAt)} (${D(e.meta.createdAt).fromNow()})`),e.meta?.ip&&N(`IP ${e.meta.ip}`),s.spam&&N("Marked as spam"),n.appendChild(a);const v=document.createElement("dl");v.className="fsx-answers";const K=t.filter(o=>O(e.data?.[o.name])!=="");for(const o of K){const m=document.createElement("div");m.className="fsx-answer";const f=document.createElement("dt");f.textContent=o.label;const g=document.createElement("dd");g.textContent=O(e.data[o.name]),m.append(f,g),v.appendChild(m)}const V=new Set(t.map(o=>o.name));for(const[o,m]of Object.entries(e.data||{})){if(V.has(o)||o==="spam"||O(m)==="")continue;const f=document.createElement("div");f.className="fsx-answer";const g=document.createElement("dt");g.textContent=`${o} (no longer on the form)`;const d=document.createElement("dd");d.textContent=O(m),f.append(g,d),v.appendChild(f)}if(v.children.length)n.appendChild(v);else{const o=document.createElement("p");o.className="fsx-note",o.textContent="Nothing was filled in.",n.appendChild(o)}const $=document.createElement("div");$.className="fsx-actions";const l=(o,m,f,g)=>{const d=document.createElement("button");d.type="button",d.className=`btn btn-sm ${f}`;const z=document.createElement("span");return z.setAttribute("data-icon",m),z.setAttribute("data-icon-size","13"),d.append(z,document.createTextNode(` ${o}`)),d.addEventListener("click",g),$.appendChild(d),d};let x;l("Copy","copy","btn-ghost",()=>se(e)),s.email&&l("Email them","mail","btn-ghost",()=>ne(e)),l(s.spam?"Not spam":"Mark as spam",s.spam?"inbox":"alert-triangle","btn-ghost",async()=>{await B(e,!s.spam)&&x.close()});const T=document.createElement("span");T.className="fsx-spacer",$.appendChild(T),l("Delete","trash","btn-ghost text-danger",async()=>{await W(e)&&x.close()}),l("Close","x","btn-ghost",()=>x.close()),n.appendChild($),x=oe(s.title,n)}function xe(e){const t=R(e);if(!t)return[];const s=L(t,k.peek());return[{header:s.title},{label:"Open\u2026",icon:"eye",action:()=>J(t)},{label:"Copy submission",icon:"copy",action:()=>se(t)},{type:"divider"},{label:s.email?`Copy ${s.email}`:"Copy email",icon:"at-sign",disabled:!s.email,action:()=>we(s.email)},{label:"Email them\u2026",icon:"mail",disabled:!s.email,action:()=>ne(t)},{type:"divider"},s.spam?{label:"Not spam - back to the inbox",icon:"inbox",action:()=>B(t,!1)}:{label:"Mark as spam",icon:"alert-triangle",action:()=>B(t,!0)},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>W(t)}]}const u=r.querySelector(".fsx-list");u.innerHTML=Le;const ge=M.applyBindings({loading:Z,loadError:q,filter:w,query:te,from:j,to:F,rows:P,counts:de,summary:pe,emptyText:ue,intro:fe},r,{methods:{showInbox:()=>{w.value="inbox"},showNew:()=>{w.value="new"},showSpam:()=>{w.value="spam"},clearDates:()=>{j.value="",F.value=""}}});h.add(()=>ge.dispose()),h.add(re(r,{position:"bottom"}));const Ce=E.contextMenu(u,{cursor:"glyph",match:".fsx-row",inherit:!1,density:"compact",items:e=>xe(e.dataset.id)});h.add(()=>Ce?.destroy?.());const ae=e=>{const t=e.target.closest(".fsx-row");if(!t)return;const s=e.target.closest(".fsx-kebab");if(s){ce(s);return}J(R(t.dataset.id))},ie=e=>{const t=e.target.closest(".fsx-row");if(!(!t||e.target!==t)){if(e.key==="F10"&&e.shiftKey)e.preventDefault(),ce(t);else if(e.key==="Enter")J(R(t.dataset.id));else if(e.key==="Delete"){e.preventDefault();const s=R(t.dataset.id);s&&W(s)}}};u.addEventListener("click",ae),u.addEventListener("keydown",ie),h.add(()=>{u.removeEventListener("click",ae),u.removeEventListener("keydown",ie)}),H(i,{id:"form-submissions-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),H(i,{id:"form-submissions-export",icon:"download",title:"Export (CSV or JSON)",onClick:ve}),H(i,{id:"form-submissions-clear",icon:"trash",title:"Clear all submissions",onClick:ye}),h.add(()=>{[..._].forEach(e=>{try{e.close()}catch{}})}),I.scan(r),await he(),b()&&requestAnimationFrame(()=>{u.isConnected&&I.scan(u)})}};
@@ -1 +1 @@
1
- import{dashboardView as o}from"./dashboard.js";import{pagesView as i}from"./pages.js";import{pageEditorView as r}from"./page-editor.js";import{settingsView as t}from"./settings.js";import{themeView as e}from"./theme.js";import{notificationsView as m}from"./notifications.js";import{layoutsView as p}from"./layouts.js";import{mediaView as s}from"./media.js";import{loginView as n}from"./login.js";import{usersView as f}from"./users.js";import{userEditorView as w}from"./user-editor.js";import{pluginsView as c}from"./plugins.js";import{pluginCodeView as V}from"./plugin-code.js";import{documentationView as a}from"./documentation.js";import{tutorialsView as d}from"./tutorials.js";import{docViews as l}from"./doc-pages.js";import{apiReferenceView as u}from"./api-reference.js";import{collectionsView as E}from"./collections.js";import{collectionEditorView as g}from"./collection-editor.js";import{collectionEntriesView as v}from"./collection-entries.js";import{formsView as b}from"./forms.js";import{formEditorView as h}from"./form-editor.js";import{formSubmissionsView as y}from"./form-submissions.js";import{viewsListView as j}from"./views-list.js";import{viewEditorView as k}from"./view-editor.js";import{viewPreviewView as L}from"./view-preview.js";import{actionsListView as x}from"./actions-list.js";import{actionEditorView as M}from"./action-editor.js";import{proDocsView as D}from"./pro-docs.js";import{blocksView as P}from"./blocks.js";import{blockEditorView as R}from"./block-editor.js";import{componentsView as S}from"./components.js";import{componentEditorView as C}from"./component-editor.js";import{myProfileView as T}from"./my-profile.js";import{rolesView as U}from"./roles.js";import{roleEditorView as q}from"./role-editor.js";import{effectsView as z}from"./effects.js";import{searchView as A}from"./search.js";import{notesView as B}from"./notes.js";import{todoView as F}from"./todo.js";import{analyticsView as G}from"./analytics.js";import{seoView as H}from"./seo.js";import{contactsView as I}from"./contacts.js";import{menusView as J}from"./menus.js";import{contextMenusView as K}from"./context-menus.js";import{contextMenuEditorView as N}from"./context-menu-editor.js";import{menuEditorView as O}from"./menu-editor.js";import{menuLocationsView as Q}from"./menu-locations.js";import{projectsView as W}from"./projects.js";import{projectDetailView as X}from"./project-detail.js";import{projectSettingsView as Y}from"./project-settings.js";import{apiTokensView as Z}from"./api-tokens.js";import{apiEndpointsView as _}from"./api-endpoints.js";import{apiEndpointEditorView as $}from"./api-endpoint-editor.js";const oo={templateUrl:"",async onMount(){location.hash="#/menus"}};export const views={projects:W,projectDetail:X,projectSettings:Y,apiTokens:Z,apiEndpoints:_,apiEndpointEditor:$,dashboard:o,pages:i,pageEditor:r,settings:t,theme:e,layouts:p,media:s,login:n,users:f,userEditor:w,plugins:c,pluginCode:V,documentation:a,tutorials:d,apiReference:u,collections:E,collectionEditor:g,collectionEntries:v,forms:b,formEditor:h,formSubmissions:y,viewsList:j,viewEditor:k,viewPreview:L,actionsList:x,actionEditor:M,proDocs:D,blocks:P,blockEditor:R,components:S,componentEditor:C,myProfile:T,roles:U,roleEditor:q,effects:z,search:A,notes:B,todo:F,analytics:G,seo:H,contacts:I,notifications:m,menus:J,contextMenus:K,contextMenuEditor:N,menuEditor:O,menuLocations:Q,menusRedirect:oo,...l};
1
+ import{dashboardView as o}from"./dashboard.js";import{pagesView as i}from"./pages.js";import{pageEditorView as r}from"./page-editor.js";import{settingsView as t}from"./settings.js";import{themeView as e}from"./theme.js";import{notificationsView as m}from"./notifications.js";import{layoutsView as p}from"./layouts.js";import{mediaView as n}from"./media.js";import{loginView as s}from"./login.js";import{usersView as f}from"./users.js";import{userEditorView as w}from"./user-editor.js";import{pluginsView as c}from"./plugins.js";import{pluginCodeView as V}from"./plugin-code.js";import{documentationView as d}from"./documentation.js";import{tutorialsView as a}from"./tutorials.js";import{docViews as l}from"./doc-pages.js";import{pluginGuidesView as u,pluginGuideView as E}from"./plugin-guides.js";import{apiReferenceView as g}from"./api-reference.js";import{collectionsView as v}from"./collections.js";import{collectionEditorView as b}from"./collection-editor.js";import{collectionEntriesView as h}from"./collection-entries.js";import{formsView as y}from"./forms.js";import{formEditorView as j}from"./form-editor.js";import{formSubmissionsView as k}from"./form-submissions.js";import{viewsListView as L}from"./views-list.js";import{viewEditorView as x}from"./view-editor.js";import{viewPreviewView as M}from"./view-preview.js";import{actionsListView as D}from"./actions-list.js";import{actionEditorView as G}from"./action-editor.js";import{proDocsView as P}from"./pro-docs.js";import{blocksView as R}from"./blocks.js";import{blockEditorView as S}from"./block-editor.js";import{componentsView as C}from"./components.js";import{componentEditorView as T}from"./component-editor.js";import{myProfileView as U}from"./my-profile.js";import{rolesView as q}from"./roles.js";import{roleEditorView as z}from"./role-editor.js";import{effectsView as A}from"./effects.js";import{searchView as B}from"./search.js";import{notesView as F}from"./notes.js";import{todoView as H}from"./todo.js";import{analyticsView as I}from"./analytics.js";import{seoView as J}from"./seo.js";import{contactsView as K}from"./contacts.js";import{menusView as N}from"./menus.js";import{contextMenusView as O}from"./context-menus.js";import{contextMenuEditorView as Q}from"./context-menu-editor.js";import{menuEditorView as W}from"./menu-editor.js";import{menuLocationsView as X}from"./menu-locations.js";import{projectsView as Y}from"./projects.js";import{projectDetailView as Z}from"./project-detail.js";import{projectSettingsView as _}from"./project-settings.js";import{apiTokensView as $}from"./api-tokens.js";import{apiEndpointsView as oo}from"./api-endpoints.js";import{apiEndpointEditorView as io}from"./api-endpoint-editor.js";const ro={templateUrl:"",async onMount(){location.hash="#/menus"}};export const views={projects:Y,projectDetail:Z,projectSettings:_,apiTokens:$,apiEndpoints:oo,apiEndpointEditor:io,dashboard:o,pages:i,pageEditor:r,settings:t,theme:e,layouts:p,media:n,login:s,users:f,userEditor:w,plugins:c,pluginCode:V,documentation:d,tutorials:a,apiReference:g,collections:v,collectionEditor:b,collectionEntries:h,forms:y,formEditor:j,formSubmissions:k,viewsList:L,viewEditor:x,viewPreview:M,actionsList:D,actionEditor:G,proDocs:P,blocks:R,blockEditor:S,components:C,componentEditor:T,myProfile:U,roles:q,roleEditor:z,effects:A,search:B,notes:F,todo:H,analytics:I,seo:J,contacts:K,notifications:m,menus:N,contextMenus:O,contextMenuEditor:Q,menuEditor:W,menuLocations:X,menusRedirect:ro,pluginGuides:u,pluginGuide:E,...l};