domma-cms 0.44.0 → 0.45.1

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 (254) hide show
  1. package/CLAUDE.md +53 -53
  2. package/README.md +27 -27
  3. package/admin/css/admin.css +1 -1
  4. package/admin/dist/domma/domma-tools.css +3 -3
  5. package/admin/dist/domma/domma-tools.min.js +3 -3
  6. package/admin/index.html +2 -2
  7. package/admin/js/app.js +1 -1
  8. package/admin/js/lib/card-builder.js +2 -2
  9. package/admin/js/lib/crud-tutorial.js +1 -1
  10. package/admin/js/lib/effect-defs.js +1 -1
  11. package/admin/js/lib/effects-builder.js +1 -1
  12. package/admin/js/lib/image-editor.js +1 -1
  13. package/admin/js/lib/markdown-toolbar.js +2 -2
  14. package/admin/js/lib/project-context.js +1 -1
  15. package/admin/js/lib/project-quick-create.js +1 -1
  16. package/admin/js/lib/scribe-composer.js +1 -1
  17. package/admin/js/lib/server-restart.js +1 -1
  18. package/admin/js/lib/shortcode-context-menu.js +2 -2
  19. package/admin/js/lib/simple-editor.js +1 -1
  20. package/admin/js/lib/themes.js +1 -1
  21. package/admin/js/lib/timeline-builder.js +1 -1
  22. package/admin/js/templates/action-editor.html +8 -8
  23. package/admin/js/templates/api-endpoint-editor.html +7 -7
  24. package/admin/js/templates/api-endpoints.html +1 -1
  25. package/admin/js/templates/api-reference.html +1 -1
  26. package/admin/js/templates/block-editor.html +6 -6
  27. package/admin/js/templates/collection-editor.html +1 -1
  28. package/admin/js/templates/component-editor.html +2 -2
  29. package/admin/js/templates/dashboard/cache.html +3 -3
  30. package/admin/js/templates/dashboard/journeys.html +3 -3
  31. package/admin/js/templates/dashboard/kpi-strip.html +3 -3
  32. package/admin/js/templates/dashboard/top-pages.html +1 -1
  33. package/admin/js/templates/dashboard/traffic-chart.html +1 -1
  34. package/admin/js/templates/docs/api-actions.html +1 -1
  35. package/admin/js/templates/docs/api-collections.html +4 -4
  36. package/admin/js/templates/docs/api-pages.html +2 -2
  37. package/admin/js/templates/docs/api-plugins.html +1 -1
  38. package/admin/js/templates/docs/api-settings.html +2 -2
  39. package/admin/js/templates/docs/api-users.html +1 -1
  40. package/admin/js/templates/docs/components-howto.html +4 -4
  41. package/admin/js/templates/docs/components-reference.html +21 -21
  42. package/admin/js/templates/docs/components-rules.html +14 -14
  43. package/admin/js/templates/docs/components-walkthrough.html +13 -13
  44. package/admin/js/templates/docs/tutorial-crud.html +49 -49
  45. package/admin/js/templates/docs/tutorial-forms.html +4 -4
  46. package/admin/js/templates/docs/tutorial-plugin.html +10 -10
  47. package/admin/js/templates/docs/usage-actions.html +6 -6
  48. package/admin/js/templates/docs/usage-cta-shortcode.html +9 -9
  49. package/admin/js/templates/docs/usage-dconfig.html +4 -4
  50. package/admin/js/templates/docs/usage-navigation.html +1 -1
  51. package/admin/js/templates/docs/usage-pages.html +1 -1
  52. package/admin/js/templates/docs/usage-shortcodes.html +24 -24
  53. package/admin/js/templates/docs/usage-users-roles.html +3 -3
  54. package/admin/js/templates/docs/usage-views.html +4 -4
  55. package/admin/js/templates/documentation.html +1 -1
  56. package/admin/js/templates/effects.html +752 -752
  57. package/admin/js/templates/form-editor.html +5 -5
  58. package/admin/js/templates/forms.html +17 -17
  59. package/admin/js/templates/login.html +5 -5
  60. package/admin/js/templates/menu-editor.html +10 -10
  61. package/admin/js/templates/my-profile.html +17 -17
  62. package/admin/js/templates/navigation.html +11 -11
  63. package/admin/js/templates/notifications.html +1 -1
  64. package/admin/js/templates/page-editor.html +4 -4
  65. package/admin/js/templates/pro-docs.html +14 -14
  66. package/admin/js/templates/role-editor.html +70 -70
  67. package/admin/js/templates/roles.html +10 -10
  68. package/admin/js/templates/settings.html +10 -10
  69. package/admin/js/templates/tutorials.html +3 -3
  70. package/admin/js/templates/view-editor.html +15 -15
  71. package/admin/js/views/action-editor.js +1 -1
  72. package/admin/js/views/actions-list.js +1 -1
  73. package/admin/js/views/api-endpoint-editor.js +2 -2
  74. package/admin/js/views/api-endpoints.js +2 -2
  75. package/admin/js/views/api-tokens.js +3 -3
  76. package/admin/js/views/blocks.js +2 -2
  77. package/admin/js/views/collection-editor.js +1 -1
  78. package/admin/js/views/collection-entries.js +1 -1
  79. package/admin/js/views/collections.js +1 -1
  80. package/admin/js/views/component-editor.js +1 -1
  81. package/admin/js/views/components.js +4 -4
  82. package/admin/js/views/dashboard/widgets/cache.js +1 -1
  83. package/admin/js/views/dashboard/widgets/journeys.js +1 -1
  84. package/admin/js/views/dashboard/widgets/kpi-strip.js +1 -1
  85. package/admin/js/views/form-editor.js +7 -7
  86. package/admin/js/views/form-submissions.js +1 -1
  87. package/admin/js/views/forms.js +1 -1
  88. package/admin/js/views/layouts.js +1 -1
  89. package/admin/js/views/login.js +2 -2
  90. package/admin/js/views/menu-editor.js +3 -3
  91. package/admin/js/views/menu-locations.js +1 -1
  92. package/admin/js/views/menus.js +3 -3
  93. package/admin/js/views/navigation.js +8 -8
  94. package/admin/js/views/page-editor.js +40 -40
  95. package/admin/js/views/pages.js +3 -3
  96. package/admin/js/views/plugin-code.js +2 -2
  97. package/admin/js/views/plugins.js +1 -1
  98. package/admin/js/views/project-settings.js +1 -1
  99. package/admin/js/views/projects.js +1 -1
  100. package/admin/js/views/roles.js +1 -1
  101. package/admin/js/views/user-editor.js +1 -1
  102. package/admin/js/views/users.js +3 -3
  103. package/admin/js/views/view-editor.js +1 -1
  104. package/admin/js/views/view-preview.js +1 -1
  105. package/admin/js/views/views-list.js +1 -1
  106. package/bin/cli.js +8 -8
  107. package/bin/lib/config-merge.js +44 -44
  108. package/bin/update.js +16 -16
  109. package/config/plugins.json +1 -1
  110. package/package.json +2 -2
  111. package/plugins/_template/admin/views/index.js +1 -1
  112. package/plugins/_template/config.js +1 -1
  113. package/plugins/_template/plugin.js +1 -1
  114. package/plugins/analytics/admin/templates/analytics.html +3 -3
  115. package/plugins/analytics/admin/views/analytics.js +1 -1
  116. package/plugins/analytics/config.js +1 -1
  117. package/plugins/analytics/plugin.js +4 -4
  118. package/plugins/analytics/plugin.json +1 -1
  119. package/plugins/analytics/public/inject-body.html +2 -2
  120. package/plugins/analytics/public/inject-head.html +1 -1
  121. package/plugins/blog/admin/templates/blog.html +4 -4
  122. package/plugins/blog/admin/views/blog.js +3 -3
  123. package/plugins/blog/admin/views/categories.js +2 -2
  124. package/plugins/blog/admin/views/comments.js +4 -4
  125. package/plugins/blog/admin/views/post-editor.js +1 -1
  126. package/plugins/blog/plugin.js +2 -2
  127. package/plugins/blog/plugin.json +4 -4
  128. package/plugins/contacts/admin/views/contacts.js +8 -8
  129. package/plugins/contacts/plugin.js +4 -4
  130. package/plugins/contacts/plugin.json +1 -1
  131. package/plugins/invoice/admin/templates/editor.html +6 -6
  132. package/plugins/invoice/admin/templates/index.html +4 -4
  133. package/plugins/invoice/admin/views/editor.js +3 -3
  134. package/plugins/invoice/admin/views/index.js +4 -4
  135. package/plugins/invoice/admin/views/issuers.js +1 -1
  136. package/plugins/invoice/admin/views/party-view.js +3 -3
  137. package/plugins/invoice/admin/views/receivers.js +1 -1
  138. package/plugins/invoice/config.js +1 -1
  139. package/plugins/invoice/plugin.js +1 -1
  140. package/plugins/invoice/plugin.json +4 -4
  141. package/plugins/notes/admin/views/notes.js +4 -4
  142. package/plugins/notes/plugin.js +1 -1
  143. package/plugins/notes/plugin.json +1 -1
  144. package/plugins/site-search/admin/templates/site-search.html +3 -3
  145. package/plugins/site-search/admin/views/site-search.js +1 -1
  146. package/plugins/site-search/config.js +1 -1
  147. package/plugins/site-search/plugin.js +4 -4
  148. package/plugins/site-search/plugin.json +1 -1
  149. package/plugins/surveys/admin/templates/results.html +1 -1
  150. package/plugins/surveys/admin/templates/survey-editor.html +4 -4
  151. package/plugins/surveys/admin/views/audience.js +6 -6
  152. package/plugins/surveys/admin/views/results.js +3 -3
  153. package/plugins/surveys/admin/views/survey-editor.js +1 -1
  154. package/plugins/surveys/admin/views/surveys.js +2 -2
  155. package/plugins/surveys/plugin.js +1 -1
  156. package/plugins/surveys/plugin.json +4 -4
  157. package/plugins/theme-switcher/admin/views/theme-switcher.js +1 -1
  158. package/plugins/theme-switcher/plugin.json +3 -3
  159. package/plugins/theme-switcher/public/inject-body.html +28 -28
  160. package/plugins/theme-switcher/public/inject-head.html +1 -1
  161. package/plugins/todo/plugin.js +1 -1
  162. package/public/css/forms.css +1 -1
  163. package/public/js/collection-browser.js +1 -1
  164. package/public/js/collection-context.js +1 -1
  165. package/public/js/form-logic-engine.js +1 -1
  166. package/public/js/forms.js +2 -1
  167. package/public/js/site.js +1 -1
  168. package/scripts/build.js +14 -14
  169. package/scripts/create-plugin.js +2 -2
  170. package/scripts/fresh.js +2 -2
  171. package/scripts/gen-instance-secret.js +1 -1
  172. package/scripts/pro.js +12 -12
  173. package/scripts/reset.js +2 -2
  174. package/scripts/setup.js +15 -15
  175. package/scripts/users.js +5 -5
  176. package/scripts/verify-assets.mjs +6 -6
  177. package/server/config.js +1 -1
  178. package/server/middleware/auth.js +253 -253
  179. package/server/middleware/managerAuth.js +3 -3
  180. package/server/routes/api/actions.js +4 -4
  181. package/server/routes/api/api-endpoints.js +7 -7
  182. package/server/routes/api/api-tokens.js +5 -5
  183. package/server/routes/api/auth.js +309 -309
  184. package/server/routes/api/blocks.js +3 -3
  185. package/server/routes/api/collections.js +18 -18
  186. package/server/routes/api/dashboard.js +5 -5
  187. package/server/routes/api/effects.js +2 -2
  188. package/server/routes/api/endpoints-public.js +5 -5
  189. package/server/routes/api/forms.js +47 -47
  190. package/server/routes/api/menu-locations.js +3 -3
  191. package/server/routes/api/menus.js +7 -7
  192. package/server/routes/api/navigation.js +42 -42
  193. package/server/routes/api/notifications.js +2 -2
  194. package/server/routes/api/pages.js +14 -2
  195. package/server/routes/api/plugin-marketplace.js +3 -3
  196. package/server/routes/api/plugins.js +6 -6
  197. package/server/routes/api/projects.js +9 -9
  198. package/server/routes/api/scaffold.js +7 -7
  199. package/server/routes/api/settings.js +6 -6
  200. package/server/routes/api/sidebar.js +1 -1
  201. package/server/routes/api/users.js +5 -5
  202. package/server/routes/api/versions.js +1 -1
  203. package/server/routes/api/views.js +1 -1
  204. package/server/routes/docs-public.js +3 -3
  205. package/server/routes/public.js +14 -14
  206. package/server/server.js +34 -16
  207. package/server/services/actions.js +19 -19
  208. package/server/services/adapters/FileAdapter.js +2 -2
  209. package/server/services/adapters/MongoAdapter.js +5 -5
  210. package/server/services/apiEndpoints.js +15 -15
  211. package/server/services/apiTokens.js +7 -7
  212. package/server/services/blocks.js +13 -13
  213. package/server/services/cache/drivers/MemoryDriver.js +3 -3
  214. package/server/services/cache/drivers/NoneDriver.js +1 -1
  215. package/server/services/cache/index.js +5 -5
  216. package/server/services/collections.js +14 -14
  217. package/server/services/components.js +9 -9
  218. package/server/services/connectionManager.js +4 -4
  219. package/server/services/content.js +25 -2
  220. package/server/services/docs.js +14 -14
  221. package/server/services/email.js +167 -167
  222. package/server/services/filterEngine.js +6 -6
  223. package/server/services/forms.js +18 -10
  224. package/server/services/health.js +1 -1
  225. package/server/services/hooks.js +7 -7
  226. package/server/services/images.js +4 -4
  227. package/server/services/managerClient.js +1 -1
  228. package/server/services/markdown.js +79 -79
  229. package/server/services/menuRender.js +5 -5
  230. package/server/services/menus-migration.js +3 -3
  231. package/server/services/menus.js +31 -31
  232. package/server/services/permissionRegistry.js +1 -1
  233. package/server/services/pluginFiles.js +5 -5
  234. package/server/services/pluginInstaller.js +17 -17
  235. package/server/services/pluginScaffold.js +1 -1
  236. package/server/services/plugins.js +17 -17
  237. package/server/services/presetCollections.js +2 -2
  238. package/server/services/projects.js +35 -26
  239. package/server/services/recipes/contact-list.json +1 -1
  240. package/server/services/recipes/onboarding.json +8 -8
  241. package/server/services/references.js +8 -8
  242. package/server/services/renderer.js +9 -9
  243. package/server/services/roles.js +9 -9
  244. package/server/services/rowAccess.js +10 -10
  245. package/server/services/scaffolder.js +30 -30
  246. package/server/services/sidebar-migration.js +10 -10
  247. package/server/services/sitemap.js +1 -1
  248. package/server/services/userProfiles.js +199 -199
  249. package/server/services/userRoles.js +7 -7
  250. package/server/services/users.js +302 -302
  251. package/server/services/versions.js +3 -3
  252. package/server/services/viewPipeline.js +6 -6
  253. package/server/services/views.js +11 -11
  254. package/server/templates/page.html +5 -5
@@ -1,4 +1,4 @@
1
- const __browsers=[];(function(){const t=document.querySelectorAll(".dm-collection-browser");t.length&&(t.forEach((e,i)=>{try{__browsers.push(new CollectionBrowser(e,i))}catch(n){console.error("[collection-browser] hydration failed:",n)}}),installGlobalKeyboardNav())})();function installGlobalKeyboardNav(){__browsers.length&&document.addEventListener("keydown",l=>{const t=l.target&&(l.target.tagName==="INPUT"||l.target.tagName==="TEXTAREA"||l.target.isContentEditable);if(l.key==="/"&&!t){const i=__browsers[0]?.el.querySelector(".dm-cb-search-input");i&&(l.preventDefault(),i.focus(),i.select());return}if((l.key==="ArrowLeft"||l.key==="ArrowRight")&&!t){const e=__browsers.find(s=>s.el.contains(l.target))||__browsers[0];if(!e)return;const i=Math.max(1,Math.ceil(e.currentTotal/e.config.pageSize)),n=l.key==="ArrowRight"?Math.min(i,e.state.page+1):Math.max(1,e.state.page-1);n!==e.state.page&&(l.preventDefault(),e.setState({page:n}))}})}function decodePayload(l){if(!l)return null;try{const t=atob(l),e=decodeURIComponent(escape(t));return JSON.parse(e)}catch{try{return JSON.parse(atob(l))}catch{return null}}}function clear(l){l&&typeof l.replaceChildren=="function"&&l.replaceChildren()}function distinctValues(l,t){const e=new Set;for(const i of l||[]){const n=i?.data?.[t];n!=null&&(Array.isArray(n)?n.forEach(s=>s!=null&&e.add(String(s))):e.add(String(n)))}return[...e].sort()}class CollectionBrowser{constructor(t,e){this.el=t,this.config=decodePayload(t.dataset.cbConfig)||{},this.schema=decodePayload(t.dataset.cbSchema)||{fields:[]};const i=decodePayload(t.dataset.cbData)||{entries:[],total:0,page:1,pageSize:12},n=(this.config.id||`${this.config.slug}-${e}`).replace(/[^a-z0-9]/gi,"_");let s=n,r=1;for(;__browsers.some(a=>a.idScope===s);)r+=1,s=`${n}_${r}`;this.idScope=s,this.urlPrefix=`cb_${s}_`,this._fragReqId=0,this.entries=i.entries||[],this.total=i.total||0,this.state={search:"",filter:{},sort:this.config.initial?.sort||"createdAt",order:this.config.initial?.order||"desc",page:1},this.readUrlState(),this.buildSkeleton(),this.refresh()}buildSkeleton(){clear(this.el);const t=elt("div","dm-cb-header");this.config.filterable?.length&&t.appendChild(this.buildDrawerToggle()),this.config.searchable&&t.appendChild(this.buildSearchInput()),this.config.sortable&&t.appendChild(this.buildSortControl()),this.config.savedSearches!==!1&&t.appendChild(this.buildSavedSearches()),this.config.exportable&&t.appendChild(this.buildExportButton());const e=elt("div","dm-cb-layout");this.filterRail=elt("aside","dm-cb-filter-rail"),this.bodyEl=elt("div","dm-cb-body"),e.appendChild(this.filterRail),e.appendChild(this.bodyEl),this.config.filterable?.length?this.renderFilterRail():this.filterRail.style.display="none",this.pagerEl=elt("div","dm-cb-pagination"),t.childElementCount&&this.el.appendChild(t),this.el.appendChild(e),this.el.appendChild(this.pagerEl),this.el.classList.add("dm-cb-hydrated")}buildSavedSearches(){const t=elt("div","dm-cb-saved"),e=elt("button","dm-cb-saved-toggle btn btn-outline");e.type="button",e.textContent="Saved \u25BE",t.appendChild(e);const i=elt("div","dm-cb-saved-menu");i.hidden=!0,t.appendChild(i);const n=()=>{clear(i);const s=this.loadSavedSearches();if(!s.length){const o=elt("p","dm-cb-saved-empty");o.textContent="No saved views yet.",i.appendChild(o)}for(const o of s){const c=elt("div","dm-cb-saved-item"),d=elt("button","dm-cb-saved-apply");d.type="button",d.textContent=o.name,d.addEventListener("click",()=>{this.state.search=o.search||"",this.state.filter={...o.filter||{}},this.state.sort=o.sort||this.config.initial?.sort||"createdAt",this.state.order=o.order||this.config.initial?.order||"desc",this.state.page=1,this.renderFilterRail();const p=this.el.querySelector(".dm-cb-search-input");p&&(p.value=this.state.search),i.hidden=!0,this.refresh()});const h=elt("button","dm-cb-saved-del");h.type="button",h.textContent="\xD7",h.title="Delete saved view",h.addEventListener("click",p=>{p.stopPropagation(),this.deleteSavedSearch(o.name),n()}),c.appendChild(d),c.appendChild(h),i.appendChild(c)}const r=elt("div","dm-cb-saved-actions"),a=elt("button","dm-cb-saved-create btn btn-primary");a.type="button",a.textContent="Save current view",a.addEventListener("click",async()=>{const o=await this.promptName();o&&(this.addSavedSearch({name:o,search:this.state.search,filter:this.state.filter,sort:this.state.sort,order:this.state.order}),n())}),r.appendChild(a),i.appendChild(r)};return e.addEventListener("click",()=>{i.hidden=!i.hidden,i.hidden||n()}),document.addEventListener("click",s=>{t.contains(s.target)||(i.hidden=!0)}),t}async promptName(){const t=typeof window<"u"&&typeof window.prompt=="function"?window.prompt("Name this saved view:"):null;return t&&t.trim()||null}loadSavedSearches(){try{const t=`cb_saved_${this.idScope}`,e=typeof S<"u"&&S.get?S.get(t):null;return Array.isArray(e)?e:[]}catch{return[]}}addSavedSearch(t){const e=this.loadSavedSearches().filter(i=>i.name!==t.name);e.push(t);try{typeof S<"u"&&S.set&&S.set(`cb_saved_${this.idScope}`,e)}catch{}}deleteSavedSearch(t){const e=this.loadSavedSearches().filter(i=>i.name!==t);try{typeof S<"u"&&S.set&&S.set(`cb_saved_${this.idScope}`,e)}catch{}}buildExportButton(){const t=elt("button","dm-cb-export btn btn-outline");return t.type="button",t.textContent="Export CSV",t.addEventListener("click",()=>this.exportCsv()),t}exportCsv(){if(this.config.mode==="client"){let n=this.entries;if(this.state.search){const o=this.state.search.toLowerCase();n=n.filter(c=>Object.values(c.data||{}).some(d=>String(d).toLowerCase().includes(o)))}const s={...this.state.filter,...this.config.baked||{}};n=applyFilterInMemory(n,s);const r=this.visibleFields(n),a=toCsv(n,r);downloadCsv(`${this.config.slug}-export.csv`,a);return}const t=new URLSearchParams;t.set("format","csv"),this.state.search&&t.set("search",this.state.search);const e={...this.state.filter,...this.config.baked||{}};for(const[n,s]of Object.entries(e))t.set(`filter[${n}]`,s);const i=`/api/collections/${encodeURIComponent(this.config.slug)}/export?${t.toString()}`;window.open(i,"_blank")}buildDrawerToggle(){const t=elt("button","dm-cb-drawer-toggle btn btn-outline");t.type="button",t.setAttribute("aria-label","Toggle filters");const e=elt("span","dm-cb-drawer-label");e.textContent="Filters";const i=elt("span","dm-cb-drawer-count");return t.appendChild(e),t.appendChild(document.createTextNode(" ")),t.appendChild(i),t.addEventListener("click",()=>{this.el.classList.toggle("dm-cb-drawer-open")}),t}buildSearchInput(){const t=elt("div","dm-cb-search"),e=elt("input","dm-cb-search-input");return e.type="search",e.placeholder="Search\u2026",e.value=this.state.search,e.addEventListener("input",debounce(()=>{this.setState({search:e.value,page:1})},200)),t.appendChild(e),t}buildSortControl(){const t=elt("div","dm-cb-sort"),e=elt("label","dm-cb-sort-label");e.textContent="Sort:",t.appendChild(e);const i=elt("select","dm-cb-sort-select"),n=this.sortableFieldList();for(const r of n){const a=elt("option");a.value=r.name,a.textContent=r.label,r.name===this.state.sort&&(a.selected=!0),i.appendChild(a)}i.addEventListener("change",()=>this.setState({sort:i.value,page:1})),t.appendChild(i);const s=elt("button","dm-cb-sort-dir");return s.type="button",s.textContent=this.state.order==="asc"?"\u2191":"\u2193",s.title=this.state.order==="asc"?"Ascending":"Descending",s.addEventListener("click",()=>{this.setState({order:this.state.order==="asc"?"desc":"asc",page:1}),s.textContent=this.state.order==="asc"?"\u2191":"\u2193"}),t.appendChild(s),t}sortableFieldList(){const t=this.config.sortableFields?.length?new Set(this.config.sortableFields):null,e=[{name:"createdAt",label:"Most recent"}];for(const i of this.schema.fields||[])t&&!t.has(i.name)||e.push({name:i.name,label:i.label||i.name});return e}renderFilterRail(){clear(this.filterRail);const t=elt("h4","dm-cb-filter-heading");t.textContent="Filters",this.filterRail.appendChild(t);for(const i of this.config.filterable){const n=(this.schema.fields||[]).find(r=>r.name===i);if(!n)continue;const s=this.buildFilterControl(n);s&&this.filterRail.appendChild(s)}const e=elt("button","dm-cb-filter-reset");e.type="button",e.textContent="Clear filters",e.addEventListener("click",()=>this.setState({filter:{},search:"",page:1})),this.filterRail.appendChild(e)}buildFilterControl(t){const e=elt("div","dm-cb-filter"),i=elt("label","dm-cb-filter-label");switch(i.textContent=t.label||t.name,e.appendChild(i),t.type){case"reference":e.appendChild(this.buildReferenceFilter(t));break;case"select":case"chooser":e.appendChild(this.buildSelectControl(t,!1));break;case"multiselect":case"tags":case"tag":e.appendChild(this.buildSelectControl(t,!0));break;case"number":e.appendChild(this.buildRangeControl(t,"number"));break;case"date":case"datetime":e.appendChild(this.buildRangeControl(t,"date"));break;case"boolean":case"checkbox":e.appendChild(this.buildBooleanControl(t));break;default:e.appendChild(this.buildTextControl(t));break}return e}buildReferenceFilter(t){const e=new Map;for(const r of this.entries){const a=r._refs?.[t.name];if(!a)continue;const o=Array.isArray(a)?a:[a];for(const c of o)!c||c.missing||e.has(c.id)||e.set(c.id,c.display)}const i=`${t.name}_eq`,n=elt("select","dm-cb-select"),s=elt("option");s.value="",s.textContent=this.config.mode==="server"?"Any (loaded)":"Any",n.appendChild(s);for(const[r,a]of e){const o=elt("option");o.value=r,o.textContent=a,String(this.state.filter[i]??"")===String(r)&&(o.selected=!0),n.appendChild(o)}return n.addEventListener("change",()=>this.updateFilter(i,n.value)),n}buildTextControl(t){const e=`${t.name}_contains`,i=elt("input","dm-cb-text");return i.type="text",i.placeholder="Contains\u2026",i.value=this.state.filter[e]||"",i.addEventListener("input",debounce(()=>{this.updateFilter(e,i.value.trim())},200)),i}buildSelectControl(t,e){const i=Array.isArray(t.options)&&t.options.length?t.options.map(o=>typeof o=="object"?o:{value:o,label:o}):distinctValues(this.entries,t.name).map(o=>({value:o,label:o})),n=this.config.mode==="client"?this.facetCounts(t.name,e?"_in":"_eq",i.map(o=>o.value)):null;if(e){const o=`${t.name}_in`,c=elt("div","dm-cb-chips"),d=new Set((this.state.filter[o]||"").split(",").filter(Boolean));for(const h of i){const p=elt("button","dm-cb-chip");p.type="button",d.has(String(h.value))&&p.classList.add("dm-cb-chip-active");const u=elt("span","dm-cb-chip-label");if(u.textContent=h.label??h.value,p.appendChild(u),n){const g=elt("span","dm-cb-chip-count");g.textContent=n[String(h.value)]??0,p.appendChild(g)}p.addEventListener("click",()=>{d.has(String(h.value))?d.delete(String(h.value)):d.add(String(h.value)),this.updateFilter(o,d.size?[...d].join(","):"")}),c.appendChild(p)}return c}const s=`${t.name}_eq`,r=elt("select","dm-cb-select"),a=elt("option");a.value="",a.textContent="Any",r.appendChild(a);for(const o of i){const c=elt("option");c.value=o.value;const d=n?` (${n[String(o.value)]??0})`:"";c.textContent=(o.label??o.value)+d,String(this.state.filter[s]??"")===String(o.value)&&(c.selected=!0),r.appendChild(c)}return r.addEventListener("change",()=>this.updateFilter(s,r.value)),r}facetCounts(t,e,i){const n={};for(const[o,c]of Object.entries(this.state.filter||{})){const{field:d}=parseFilterKey(o);d!==t&&(n[o]=c)}let s=this.entries;if(this.state.search){const o=this.state.search.toLowerCase();s=s.filter(c=>Object.values(c.data||{}).some(d=>String(d).toLowerCase().includes(o)))}const r={...n,...this.config.baked||{}};s=applyFilterInMemory(s,r);const a={};for(const o of i){const c={...r,[`${t}${e}`]:String(o)};a[String(o)]=applyFilterInMemory(s,c).length}return a}buildRangeControl(t,e){const i=`${t.name}_gte`,n=`${t.name}_lte`,s=elt("div","dm-cb-range"),r=elt("div","dm-cb-range-inputs"),a=elt("input","dm-cb-range-min"),o=elt("input","dm-cb-range-max");a.type=e,o.type=e,a.placeholder="Min",o.placeholder="Max",a.value=this.state.filter[i]||"",o.value=this.state.filter[n]||"",r.appendChild(a),r.appendChild(document.createTextNode(" \u2013 ")),r.appendChild(o),s.appendChild(r);let c=null;if(e==="number"&&this.config.mode==="client"&&this.entries.length){const h=this.entries.map(p=>Number(p.data?.[t.name])).filter(p=>Number.isFinite(p));if(h.length){const p=Math.min(...h),u=Math.max(...h);u>p&&(c=this.buildDualSlider(p,u,a,o,i,n),s.appendChild(c))}}const d=debounce(()=>{this.updateFilter(i,a.value,!0),this.updateFilter(n,o.value),c&&syncSliderToInputs(c,a.value,o.value)},250);return a.addEventListener("input",d),o.addEventListener("input",d),s}buildDualSlider(t,e,i,n,s,r){const a=elt("div","dm-cb-slider");a.dataset.lo=String(t),a.dataset.hi=String(e);const o=elt("div","dm-cb-slider-track"),c=elt("div","dm-cb-slider-fill");o.appendChild(c),a.appendChild(o);const d=elt("input","dm-cb-slider-handle dm-cb-slider-handle-min"),h=elt("input","dm-cb-slider-handle dm-cb-slider-handle-max");for(const[f,m]of[[d,t],[h,e]])f.type="range",f.min=String(t),f.max=String(e),f.step="any",f.value=String(m);d.value=String(i.value||t),h.value=String(n.value||e),a.appendChild(d),a.appendChild(h);const p=()=>{const f=Math.min(Number(d.value),Number(h.value)),m=Math.max(Number(d.value),Number(h.value)),b=e-t||1;c.style.left=`${(f-t)/b*100}%`,c.style.right=`${100-(m-t)/b*100}%`};p();const u=()=>{Number(d.value)>Number(h.value)&&(d.value=h.value),p(),i.value=d.value,n.value=h.value};d.addEventListener("input",u),h.addEventListener("input",u);const g=()=>{this.updateFilter(s,Number(d.value)>t?d.value:"",!0),this.updateFilter(r,Number(h.value)<e?h.value:"")};return d.addEventListener("change",g),h.addEventListener("change",g),a}buildBooleanControl(t){const e=`${t.name}_eq`,i=elt("select","dm-cb-select");for(const[n,s]of[["","Any"],["true","Yes"],["false","No"]]){const r=elt("option");r.value=n,r.textContent=s,String(this.state.filter[e]??"")===n&&(r.selected=!0),i.appendChild(r)}return i.addEventListener("change",()=>this.updateFilter(e,i.value)),i}updateFilter(t,e,i=!1){const n={...this.state.filter};e===""||e==null?delete n[t]:n[t]=e,this.state.filter=n,this.state.page=1,i||this.refresh()}setState(t){Object.assign(this.state,t),this.refresh()}async refresh(){this.config.syncUrl&&this.writeUrlState(),this.config.mode==="server"&&await this.fetchPage(),this.renderBody(),this.renderPagination(),this.updateFacetCounts(),this.updateDrawerBadge()}updateFacetCounts(){if(this.config.mode==="client"&&this.filterRail)for(const t of this.config.filterable||[]){const e=(this.schema.fields||[]).find(a=>a.name===t);if(!e)continue;const i=e.type==="multiselect"||e.type==="tags"||e.type==="tag"?"_in":"_eq",n=Array.isArray(e.options)&&e.options.length?e.options.map(a=>typeof a=="object"?a:{value:a,label:a}):distinctValues(this.entries,t).map(a=>({value:a,label:a})),s=this.facetCounts(t,i,n.map(a=>a.value)),r=this.filterRail.querySelectorAll(".dm-cb-filter");for(const a of r){const o=a.querySelector(".dm-cb-filter-label");if(!o||o.textContent!==(e.label||e.name))continue;a.querySelectorAll(".dm-cb-chip").forEach((h,p)=>{const u=h.querySelector(".dm-cb-chip-count");u&&n[p]&&(u.textContent=s[String(n[p].value)]??0)});const d=a.querySelector("select.dm-cb-select");d&&Array.from(d.options).forEach(h=>{if(!h.value)return;const p=n.find(u=>String(u.value)===h.value)?.label??h.value;h.textContent=`${p} (${s[h.value]??0})`})}}}updateDrawerBadge(){const t=this.el.querySelector(".dm-cb-drawer-toggle");if(!t)return;const e=(this.state.search?1:0)+Object.keys(this.state.filter||{}).length,i=t.querySelector(".dm-cb-drawer-count");i&&(i.textContent=e>0?`(${e})`:"")}async fetchPage(){const t={...this.state.filter,...this.config.baked||{}},e=new URLSearchParams;e.set("page",this.state.page),e.set("limit",this.config.pageSize),e.set("sort",this.state.sort),e.set("order",this.state.order),this.state.search&&e.set("search",this.state.search);for(const[n,s]of Object.entries(t))e.set(`filter[${n}]`,s);this._fetchAbort&&this._fetchAbort.abort(),this._fetchAbort=new AbortController;const i=this.config.sourceKind==="view"?`/api/views/${encodeURIComponent(this.config.slug)}/public?${e.toString()}`:`/api/collections/${encodeURIComponent(this.config.slug)}/public?${e.toString()}`;try{const n=await fetch(i,{headers:this.authHeaders(),signal:this._fetchAbort.signal});if(!n.ok){this.entries=[],this.total=0;return}const s=await n.json(),r=s.entries||s.results||[];this.entries=r.map(a=>a.data?a:{id:a.id||"",data:a.data||a}),this.total=s.total||r.length}catch(n){if(n.name==="AbortError")return;this.entries=[],this.total=0}}authHeaders(){try{const t=typeof S<"u"&&S.get?S.get("auth_token"):null;return t?{Authorization:`Bearer ${t}`}:{}}catch{return{}}}pipeline(){if(this.config.mode==="server")return{visible:this.entries,total:this.total};let t=this.entries,e=null;if(this.state.search){const c=this.state.search.toLowerCase();e=new Map,t=t.filter(d=>{let h=0;for(const[p,u]of Object.entries(d.data||{})){if(u==null)continue;const g=String(u).toLowerCase();let f=0,m=0;for(;(f=g.indexOf(c,f))!==-1;)m++,f+=c.length;m>0&&(h+=m*(p===this.config.titleField?3:1))}return h>0&&e.set(d.id||d,h),h>0})}if(Object.keys(this.state.filter).length||Object.keys(this.config.baked||{}).length){const c={...this.state.filter,...this.config.baked||{}};t=applyFilterInMemory(t,c)}const i=this.config.initial?.sort||"createdAt",n=this.config.initial?.order||"desc",s=this.state.sort===i&&this.state.order===n;this.state.search&&e&&s?(t=[...t].sort((c,d)=>{const h=e.get(c.id||c)||0;return(e.get(d.id||d)||0)-h}),this._activeSortMode="relevance"):(t=sortEntries(t,this.state.sort,this.state.order),this._activeSortMode=null);const r=t.length,a=(this.state.page-1)*this.config.pageSize;return{visible:t.slice(a,a+this.config.pageSize),total:r}}renderBody(){const{visible:t,total:e}=this.pipeline();if(this.currentTotal=e,clear(this.bodyEl),!t.length){this.bodyEl.appendChild(this.buildEmptyState());return}const i=this.visibleFields(t);this.bodyEl.appendChild(this.renderForDisplay(t,i)),typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(this.bodyEl),this.config.cta&&typeof wireCTAButtons=="function"&&wireCTAButtons(this.bodyEl)}buildEmptyState(){const t=elt("div","dm-collection-display dm-collection-empty"),e=!!this.state.search||Object.keys(this.state.filter||{}).length>0,i=elt("p");if(e){i.textContent="No results for these filters.",t.appendChild(i);const n=elt("button","btn btn-outline dm-cb-empty-clear");n.type="button",n.textContent="Clear filters",n.addEventListener("click",()=>{this.setState({filter:{},search:"",page:1}),this.renderFilterRail();const s=this.el.querySelector(".dm-cb-search-input");s&&(s.value="")}),t.appendChild(n)}else i.textContent=this.config.emptyMsg,t.appendChild(i);return t}visibleFields(t){let e=this.schema.fields||[];return this.config.fields?.length&&(e=this.config.fields.map(i=>e.find(n=>n.name===i)||{name:i,label:i})),!e.length&&t.length&&(e=Object.keys(t[0].data||{}).map(i=>({name:i,label:i}))),e}renderCards(t,e){const i=elt("div",`dm-collection-cards grid grid-cols-${this.config.columns}`);for(const n of t){const s=elt("div","card dm-collection-card"),r=e.find(c=>c.name===this.config.titleField),a=r?fieldDisplay(n,r):this.config.titleField?formatValue(n.data?.[this.config.titleField]):"";if(a){const c=elt("div","card-header");c.textContent=a,s.appendChild(c)}const o=elt("div","card-body");for(const c of e){if(this.config.titleField===c.name||!fieldDisplay(n,c))continue;const h=elt("div","dm-collection-card-field"),p=elt("strong");p.textContent=(c.label||c.name)+": ",h.appendChild(p),h.appendChild(fieldDisplayNode(n,c)),o.appendChild(h)}this.config.cta&&o.appendChild(this.buildCtaButton(n)),this.config.transitions&&o.appendChild(this.buildTransitionsGroup(n)),s.appendChild(o),i.appendChild(s)}return i}renderList(t,e){const i=elt("ul","dm-collection-list");for(const n of t){const s=elt("li","dm-collection-list-item"),r=e.find(c=>c.name===this.config.titleField),a=r?fieldDisplay(n,r):this.config.titleField?formatValue(n.data?.[this.config.titleField]):"";if(a){const c=elt("div","dm-collection-list-title");c.textContent=a,s.appendChild(c)}const o=e.filter(c=>c.name!==this.config.titleField).map(c=>{const d=fieldDisplay(n,c);return d?`${c.label||c.name}: ${d}`:""}).filter(Boolean).join(" \xB7 ");if(o){const c=elt("div","dm-collection-list-meta");c.textContent=o,s.appendChild(c)}this.config.cta&&s.appendChild(this.buildCtaButton(n)),this.config.transitions&&s.appendChild(this.buildTransitionsGroup(n)),i.appendChild(s)}return i}renderTable(t,e){const i=elt("table","dm-collection-table"),n=elt("thead"),s=elt("tr");for(const a of e){const o=elt("th");o.textContent=a.label||a.name,s.appendChild(o)}this.config.cta&&s.appendChild(elt("th")),this.config.transitions&&s.appendChild(elt("th")),n.appendChild(s),i.appendChild(n);const r=elt("tbody");for(const a of t){const o=elt("tr");for(const c of e){const d=elt("td");d.appendChild(fieldDisplayNode(a,c)),o.appendChild(d)}if(this.config.cta){const c=elt("td");c.appendChild(this.buildCtaButton(a)),o.appendChild(c)}if(this.config.transitions){const c=elt("td");c.appendChild(this.buildTransitionsGroup(a)),o.appendChild(c)}r.appendChild(o)}return i.appendChild(r),i}renderAccordion(t){const e=elt("div","accordion dm-collection-accordion");for(const i of t){const n=elt("div","accordion-item"),s=this.config.titleField&&i.data?.[this.config.titleField]||"Untitled",r=this.config.bodyField&&i.data?.[this.config.bodyField]||"",a=elt("button","accordion-header");a.type="button",a.textContent=String(s);const o=elt("div","accordion-panel");o.textContent=String(r),a.addEventListener("click",()=>n.classList.toggle("open")),n.appendChild(a),n.appendChild(o),e.appendChild(n)}return e}buildCtaButton(t){const e=this.config.cta,i=elt("button",`btn btn-${e.style||"primary"} dm-cta-trigger`);if(i.dataset.action=e.action,i.dataset.entry=t.id||"",e.confirm&&(i.dataset.confirm=e.confirm),e.icon){const n=elt("span");n.dataset.icon=e.icon,i.appendChild(n),i.appendChild(document.createTextNode(" "))}return i.appendChild(document.createTextNode(e.label||"Run")),i}buildTransitionsGroup(t){const e=elt("div","dm-cb-transitions");return e.dataset.entry=t.id||"",e.textContent="Loading actions\u2026",Promise.resolve().then(()=>this.loadTransitions(t,e)),e}async loadTransitions(t,e){try{const i=new URLSearchParams({collection:this.config.slug,entryId:t.id||""}),n=await fetch(`/api/actions/transitions?${i.toString()}`,{headers:this.authHeaders()});if(clear(e),!n.ok)return;const{transitions:s}=await n.json();if(!Array.isArray(s)||!s.length)return;for(const r of s){const a=elt("button",`btn btn-${r.trigger?.style||"outline"} dm-cb-transition-btn dm-cta-trigger`);if(a.dataset.action=r.slug,a.dataset.entry=t.id||"",r.trigger?.confirmMessage&&(a.dataset.confirm=r.trigger.confirmMessage),r.trigger?.icon){const o=elt("span");o.dataset.icon=r.trigger.icon,a.appendChild(o),a.appendChild(document.createTextNode(" "))}a.appendChild(document.createTextNode(r.trigger?.label||r.title)),e.appendChild(a)}typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(e),typeof wireCTAButtons=="function"&&wireCTAButtons(e)}catch{clear(e)}}renderPagination(){if(this.config.pagination==="scroll"){this.renderInfiniteSentinel();return}const t=Math.max(1,Math.ceil(this.currentTotal/this.config.pageSize));if(clear(this.pagerEl),t<=1)return;const e=elt("button","dm-cb-page-prev btn btn-outline");e.type="button",e.textContent="\u2039 Prev",e.disabled=this.state.page<=1,e.addEventListener("click",()=>this.setState({page:Math.max(1,this.state.page-1)}));const i=elt("button","dm-cb-page-next btn btn-outline");i.type="button",i.textContent="Next \u203A",i.disabled=this.state.page>=t,i.addEventListener("click",()=>this.setState({page:Math.min(t,this.state.page+1)}));const n=elt("span","dm-cb-page-info");n.textContent=`Page ${this.state.page} of ${t} (${this.currentTotal} entr${this.currentTotal===1?"y":"ies"})`,this.pagerEl.appendChild(e),this.pagerEl.appendChild(n),this.pagerEl.appendChild(i)}renderInfiniteSentinel(){clear(this.pagerEl);const t=Math.max(1,Math.ceil(this.currentTotal/this.config.pageSize));if(this.state.page>=t){const i=elt("p","dm-cb-scroll-end");i.textContent=`All ${this.currentTotal} entries loaded.`,this.pagerEl.appendChild(i);return}const e=elt("div","dm-cb-scroll-sentinel");e.setAttribute("aria-hidden","true"),e.textContent="Loading more\u2026",this.pagerEl.appendChild(e),this._scrollObserver&&this._scrollObserver.disconnect(),this._scrollObserver=new IntersectionObserver(async i=>{i[0].isIntersecting&&(this._scrollObserver.disconnect(),await this.loadMore())},{rootMargin:"200px 0px"}),this._scrollObserver.observe(e)}async loadMore(){const t=this.state.page+1,e=this.currentTotal,i=this.entries,n=this.state.page;this.state.page=t,this.config.syncUrl&&this.writeUrlState();let s;if(this.config.mode==="server")await this.fetchPage(),s=this.entries;else{const{visible:c}=this.pipeline();s=c}if(!s.length){this.state.page=n,this.entries=i,this.currentTotal=e,this.renderPagination();return}const r=this.visibleFields(s),a=this.renderForDisplay(s,r),o=this.bodyEl.firstElementChild;if(o&&o.tagName===a.tagName)for(;a.firstChild;)o.appendChild(a.firstChild);else this.bodyEl.appendChild(a);typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(this.bodyEl),this.config.cta&&typeof wireCTAButtons=="function"&&wireCTAButtons(this.bodyEl),this.renderPagination()}renderForDisplay(t,e){const i=this.config.display;return i==="list"?this.renderList(t,e):i==="table"?this.renderTable(t,e):i==="accordion"?this.renderAccordion(t):i==="timeline"?this.renderTimeline(t):i==="block"?this.renderBlockPlaceholder(t):this.renderCards(t,e)}renderTimeline(t){const e=["vertical","centred","horizontal"].includes(this.config.layout)?this.config.layout:"vertical",i=["minimal","corporate","modern"].includes(this.config.theme)?this.config.theme:"minimal",n=elt("div",`dm-collection-timeline timeline timeline-${e} timeline-${i}`);for(const s of t){const r=elt("div","timeline-event"),a=this.config.dateField&&s.data?.[this.config.dateField]||"",o=this.config.titleField&&s.data?.[this.config.titleField]||"",c=this.config.bodyField&&s.data?.[this.config.bodyField]||"",d=this.config.statusField&&s.data?.[this.config.statusField]||"",h=this.config.iconField&&s.data?.[this.config.iconField]||"";if(h){const p=elt("span","timeline-icon");p.dataset.icon=String(h),r.appendChild(p)}if(a){const p=elt("div","timeline-date");p.textContent=String(a),r.appendChild(p)}if(o){const p=elt("h4","timeline-title");p.textContent=String(o),r.appendChild(p)}if(d){const p=elt("span",`badge badge-${d}`);p.textContent=String(d),r.appendChild(p)}if(c){const p=elt("div","timeline-body");p.textContent=String(c),r.appendChild(p)}n.appendChild(r)}return n}renderBlockPlaceholder(t){const e=elt("div","dm-collection-display dm-cb-block-loading");return e.textContent="Rendering\u2026",this.fetchBlockFragment(t,e),e}async fetchBlockFragment(t,e){const i=++this._fragReqId,n=t.map(a=>a.id).filter(Boolean),s={slug:this.config.slug,display:"block",block:this.config.block,"title-field":this.config.titleField,"body-field":this.config.bodyField,fields:this.config.fields?this.config.fields.join(","):"",empty:this.config.emptyMsg,limit:String(n.length||1)},r={...this.state.filter,...this.config.baked||{}};for(const[a,o]of Object.entries(r))o!==""&&o!=null&&(s[`where_${a}`]=String(o));s.sort=this.state.sort,s.order=this.state.order,s.limit=String(this.config.pageSize);try{const a=btoa(unescape(encodeURIComponent(JSON.stringify(s)))),o=await fetch("/api/collections/render-fragment",{method:"POST",headers:{"Content-Type":"application/json",...this.authHeaders()},body:JSON.stringify({attrs:a,page:this.state.page})});if(i!==this._fragReqId)return;if(!o.ok){e.textContent=this.config.emptyMsg;return}const{html:c}=await o.json(),d=document.createElement("template");d.innerHTML=c||"",e.replaceWith(d.content)}catch{e.textContent="Unable to load block view."}}readUrlState(){if(!this.config.syncUrl)return;const t=new URLSearchParams(window.location.search),e=this.urlPrefix,i=r=>t.get(e+r);i("search")&&(this.state.search=i("search")),i("sort")&&(this.state.sort=i("sort")),i("order")&&(this.state.order=i("order")),i("page")&&(this.state.page=parseInt(i("page"),10)||1);const n={},s=`${e}filter[`;for(const[r,a]of t.entries())if(r.startsWith(s)&&r.endsWith("]")){const o=r.slice(s.length,-1);o&&(n[o]=a)}Object.keys(n).length&&(this.state.filter=n)}writeUrlState(){const t=new URL(window.location.href),e=this.urlPrefix,i=[];for(const s of t.searchParams.keys())s.startsWith(e)&&i.push(s);i.forEach(s=>t.searchParams.delete(s));const n=(s,r)=>{r!==""&&r!=null&&t.searchParams.set(e+s,r)};n("search",this.state.search),this.state.sort!==(this.config.initial?.sort||"createdAt")&&n("sort",this.state.sort),this.state.order!==(this.config.initial?.order||"desc")&&n("order",this.state.order),this.state.page!==1&&n("page",this.state.page);for(const[s,r]of Object.entries(this.state.filter))r!==""&&r!=null&&t.searchParams.set(`${e}filter[${s}]`,r);try{window.history.replaceState({},"",t.toString())}catch{}}}const OPERATORS=["_eq","_ne","_gte","_lte","_gt","_lt","_in","_nin","_contains","_starts","_ends","_exists"];function parseFilterKey(l){for(const t of OPERATORS)if(l.endsWith(t))return{field:l.slice(0,-t.length),op:t};return{field:l,op:"_eq"}}function resolveField(l,t){if(t==="createdBy")return l.meta?.createdBy;if(t==="id")return l.id;const e=t.split(".");let i=l.data;for(const n of e){if(i==null)return;i=i[n]}return i}function maybeNumber(l){if(typeof l=="number"||typeof l!="string")return l;const t=Number(l);return Number.isFinite(t)&&String(t)===l.trim()?t:l}function applyOp(l,t,e){switch(l){case"_eq":{const i=maybeNumber(t),n=maybeNumber(e);return Array.isArray(t)?t.map(maybeNumber).includes(n):i===n||String(i)===String(n)}case"_ne":{const i=maybeNumber(t),n=maybeNumber(e);return Array.isArray(t)?!t.map(maybeNumber).includes(n):!(i===n||String(i)===String(n))}case"_gt":return maybeNumber(t)>maybeNumber(e);case"_gte":return maybeNumber(t)>=maybeNumber(e);case"_lt":return maybeNumber(t)<maybeNumber(e);case"_lte":return maybeNumber(t)<=maybeNumber(e);case"_in":{const i=String(e).split(",").map(n=>maybeNumber(n.trim()));return Array.isArray(t)?t.map(maybeNumber).some(n=>i.includes(n)):i.includes(maybeNumber(t))}case"_nin":{const i=String(e).split(",").map(n=>maybeNumber(n.trim()));return Array.isArray(t)?!t.map(maybeNumber).some(n=>i.includes(n)):!i.includes(maybeNumber(t))}case"_contains":return String(t??"").toLowerCase().includes(String(e).toLowerCase());case"_starts":return String(t??"").toLowerCase().startsWith(String(e).toLowerCase());case"_ends":return String(t??"").toLowerCase().endsWith(String(e).toLowerCase());case"_exists":{const i=t!=null&&t!=="";return e==="true"||e==="1"||e===!0?i:!i}default:return!1}}function applyFilterInMemory(l,t){return!t||!Object.keys(t).length?l:l.filter(e=>{for(const[i,n]of Object.entries(t)){if(n==null||n==="")continue;const{field:s,op:r}=parseFilterKey(i),a=resolveField(e,s);if(!applyOp(r,a,n))return!1}return!0})}function sortEntries(l,t,e){const i=e==="asc"?1:-1;return[...l].sort((n,s)=>{const r=t==="createdAt"?n.meta?.createdAt||"":n.data?.[t]??"",a=t==="createdAt"?s.meta?.createdAt||"":s.data?.[t]??"";return r<a?-i:r>a?i:0})}function elt(l,t){const e=document.createElement(l);return t&&(e.className=t),e}function isFileRef(l){return l&&typeof l=="object"&&typeof l.url=="string"&&typeof l.name=="string"}function formatValue(l){return l==null?"":isFileRef(l)?l.name:Array.isArray(l)?l.join(", "):typeof l=="boolean"?l?"Yes":"No":String(l)}function fieldDisplay(l,t){if(t?.type==="reference"){const e=l?._refs?.[t.name];if(e!=null)return Array.isArray(e)?e.map(i=>i.missing?`${i.id} (missing)`:i.display).join(", "):e.missing?`${e.id} (missing)`:e.display}return formatValue(l?.data?.[t?.name])}function fieldDisplayNode(l,t){if(t?.type==="reference"){const i=l?._refs?.[t.name];if(i!=null){const n=document.createDocumentFragment();return(Array.isArray(i)?i:[i]).forEach((r,a)=>{if(a>0&&n.appendChild(document.createTextNode(", ")),r.missing)n.appendChild(document.createTextNode(`${r.id} (missing)`));else if(r.link){const o=document.createElement("a");o.href=r.link,o.textContent=r.display,n.appendChild(o)}else n.appendChild(document.createTextNode(r.display))}),n}}const e=l?.data?.[t?.name];if(isFileRef(e)){const i=document.createElement("a");if(i.href=e.url,String(e.mime||"").startsWith("image/")){i.target="_blank",i.rel="noopener";const n=document.createElement("img");n.src=e.url,n.alt=e.name,n.loading="lazy",n.className="dm-file-thumb",i.appendChild(n)}else i.download="",i.textContent=e.name;return i}return document.createTextNode(formatValue(e))}function debounce(l,t){let e;return(...i)=>{clearTimeout(e),e=setTimeout(()=>l(...i),t)}}function toCsv(l,t){const e=s=>{if(s==null)return"";let r=Array.isArray(s)?s.join(", "):String(s);return/[",\n\r]/.test(r)&&(r='"'+r.replace(/"/g,'""')+'"'),r},i=t.map(s=>e(s.label||s.name)).join(","),n=l.map(s=>t.map(r=>e(s.data?.[r.name])).join(",")).join(`
1
+ const __browsers=[];(function(){const t=document.querySelectorAll(".dm-collection-browser");t.length&&(t.forEach((e,i)=>{try{__browsers.push(new CollectionBrowser(e,i))}catch(n){console.error("[collection-browser] hydration failed:",n)}}),installGlobalKeyboardNav())})();function installGlobalKeyboardNav(){__browsers.length&&document.addEventListener("keydown",l=>{const t=l.target&&(l.target.tagName==="INPUT"||l.target.tagName==="TEXTAREA"||l.target.isContentEditable);if(l.key==="/"&&!t){const i=__browsers[0]?.el.querySelector(".dm-cb-search-input");i&&(l.preventDefault(),i.focus(),i.select());return}if((l.key==="ArrowLeft"||l.key==="ArrowRight")&&!t){const e=__browsers.find(s=>s.el.contains(l.target))||__browsers[0];if(!e)return;const i=Math.max(1,Math.ceil(e.currentTotal/e.config.pageSize)),n=l.key==="ArrowRight"?Math.min(i,e.state.page+1):Math.max(1,e.state.page-1);n!==e.state.page&&(l.preventDefault(),e.setState({page:n}))}})}function decodePayload(l){if(!l)return null;try{const t=atob(l),e=decodeURIComponent(escape(t));return JSON.parse(e)}catch{try{return JSON.parse(atob(l))}catch{return null}}}function clear(l){l&&typeof l.replaceChildren=="function"&&l.replaceChildren()}function distinctValues(l,t){const e=new Set;for(const i of l||[]){const n=i?.data?.[t];n!=null&&(Array.isArray(n)?n.forEach(s=>s!=null&&e.add(String(s))):e.add(String(n)))}return[...e].sort()}class CollectionBrowser{constructor(t,e){this.el=t,this.config=decodePayload(t.dataset.cbConfig)||{},this.schema=decodePayload(t.dataset.cbSchema)||{fields:[]};const i=decodePayload(t.dataset.cbData)||{entries:[],total:0,page:1,pageSize:12},n=(this.config.id||`${this.config.slug}-${e}`).replace(/[^a-z0-9]/gi,"_");let s=n,r=1;for(;__browsers.some(a=>a.idScope===s);)r+=1,s=`${n}_${r}`;this.idScope=s,this.urlPrefix=`cb_${s}_`,this._fragReqId=0,this.entries=i.entries||[],this.total=i.total||0,this.state={search:"",filter:{},sort:this.config.initial?.sort||"createdAt",order:this.config.initial?.order||"desc",page:1},this.readUrlState(),this.buildSkeleton(),this.refresh()}buildSkeleton(){clear(this.el);const t=elt("div","dm-cb-header");this.config.filterable?.length&&t.appendChild(this.buildDrawerToggle()),this.config.searchable&&t.appendChild(this.buildSearchInput()),this.config.sortable&&t.appendChild(this.buildSortControl()),this.config.savedSearches!==!1&&t.appendChild(this.buildSavedSearches()),this.config.exportable&&t.appendChild(this.buildExportButton());const e=elt("div","dm-cb-layout");this.filterRail=elt("aside","dm-cb-filter-rail"),this.bodyEl=elt("div","dm-cb-body"),e.appendChild(this.filterRail),e.appendChild(this.bodyEl),this.config.filterable?.length?this.renderFilterRail():this.filterRail.style.display="none",this.pagerEl=elt("div","dm-cb-pagination"),t.childElementCount&&this.el.appendChild(t),this.el.appendChild(e),this.el.appendChild(this.pagerEl),this.el.classList.add("dm-cb-hydrated")}buildSavedSearches(){const t=elt("div","dm-cb-saved"),e=elt("button","dm-cb-saved-toggle btn btn-outline");e.type="button",e.textContent="Saved \u25BE",t.appendChild(e);const i=elt("div","dm-cb-saved-menu");i.hidden=!0,t.appendChild(i);const n=()=>{clear(i);const s=this.loadSavedSearches();if(!s.length){const o=elt("p","dm-cb-saved-empty");o.textContent="No saved views yet.",i.appendChild(o)}for(const o of s){const c=elt("div","dm-cb-saved-item"),d=elt("button","dm-cb-saved-apply");d.type="button",d.textContent=o.name,d.addEventListener("click",()=>{this.state.search=o.search||"",this.state.filter={...o.filter||{}},this.state.sort=o.sort||this.config.initial?.sort||"createdAt",this.state.order=o.order||this.config.initial?.order||"desc",this.state.page=1,this.renderFilterRail();const p=this.el.querySelector(".dm-cb-search-input");p&&(p.value=this.state.search),i.hidden=!0,this.refresh()});const h=elt("button","dm-cb-saved-del");h.type="button",h.textContent="\xD7",h.title="Delete saved view",h.addEventListener("click",p=>{p.stopPropagation(),this.deleteSavedSearch(o.name),n()}),c.appendChild(d),c.appendChild(h),i.appendChild(c)}const r=elt("div","dm-cb-saved-actions"),a=elt("button","dm-cb-saved-create btn btn-primary");a.type="button",a.textContent="Save current view",a.addEventListener("click",async()=>{const o=await this.promptName();o&&(this.addSavedSearch({name:o,search:this.state.search,filter:this.state.filter,sort:this.state.sort,order:this.state.order}),n())}),r.appendChild(a),i.appendChild(r)};return e.addEventListener("click",()=>{i.hidden=!i.hidden,i.hidden||n()}),document.addEventListener("click",s=>{t.contains(s.target)||(i.hidden=!0)}),t}async promptName(){const t=typeof window<"u"&&typeof window.prompt=="function"?window.prompt("Name this saved view:"):null;return t&&t.trim()||null}loadSavedSearches(){try{const t=`cb_saved_${this.idScope}`,e=typeof S<"u"&&S.get?S.get(t):null;return Array.isArray(e)?e:[]}catch{return[]}}addSavedSearch(t){const e=this.loadSavedSearches().filter(i=>i.name!==t.name);e.push(t);try{typeof S<"u"&&S.set&&S.set(`cb_saved_${this.idScope}`,e)}catch{}}deleteSavedSearch(t){const e=this.loadSavedSearches().filter(i=>i.name!==t);try{typeof S<"u"&&S.set&&S.set(`cb_saved_${this.idScope}`,e)}catch{}}buildExportButton(){const t=elt("button","dm-cb-export btn btn-outline");return t.type="button",t.textContent="Export CSV",t.addEventListener("click",()=>this.exportCsv()),t}exportCsv(){if(this.config.mode==="client"){let n=this.entries;if(this.state.search){const o=this.state.search.toLowerCase();n=n.filter(c=>Object.values(c.data||{}).some(d=>String(d).toLowerCase().includes(o)))}const s={...this.state.filter,...this.config.baked||{}};n=applyFilterInMemory(n,s);const r=this.visibleFields(n),a=toCsv(n,r);downloadCsv(`${this.config.slug}-export.csv`,a);return}const t=new URLSearchParams;t.set("format","csv"),this.state.search&&t.set("search",this.state.search);const e={...this.state.filter,...this.config.baked||{}};for(const[n,s]of Object.entries(e))t.set(`filter[${n}]`,s);const i=`/api/collections/${encodeURIComponent(this.config.slug)}/export?${t.toString()}`;window.open(i,"_blank")}buildDrawerToggle(){const t=elt("button","dm-cb-drawer-toggle btn btn-outline");t.type="button",t.setAttribute("aria-label","Toggle filters");const e=elt("span","dm-cb-drawer-label");e.textContent="Filters";const i=elt("span","dm-cb-drawer-count");return t.appendChild(e),t.appendChild(document.createTextNode(" ")),t.appendChild(i),t.addEventListener("click",()=>{this.el.classList.toggle("dm-cb-drawer-open")}),t}buildSearchInput(){const t=elt("div","dm-cb-search"),e=elt("input","dm-cb-search-input");return e.type="search",e.placeholder="Search\u2026",e.value=this.state.search,e.addEventListener("input",debounce(()=>{this.setState({search:e.value,page:1})},200)),t.appendChild(e),t}buildSortControl(){const t=elt("div","dm-cb-sort"),e=elt("label","dm-cb-sort-label");e.textContent="Sort:",t.appendChild(e);const i=elt("select","dm-cb-sort-select"),n=this.sortableFieldList();for(const r of n){const a=elt("option");a.value=r.name,a.textContent=r.label,r.name===this.state.sort&&(a.selected=!0),i.appendChild(a)}i.addEventListener("change",()=>this.setState({sort:i.value,page:1})),t.appendChild(i);const s=elt("button","dm-cb-sort-dir");return s.type="button",s.textContent=this.state.order==="asc"?"\u2191":"\u2193",s.title=this.state.order==="asc"?"Ascending":"Descending",s.addEventListener("click",()=>{this.setState({order:this.state.order==="asc"?"desc":"asc",page:1}),s.textContent=this.state.order==="asc"?"\u2191":"\u2193"}),t.appendChild(s),t}sortableFieldList(){const t=this.config.sortableFields?.length?new Set(this.config.sortableFields):null,e=[{name:"createdAt",label:"Most recent"}];for(const i of this.schema.fields||[])t&&!t.has(i.name)||e.push({name:i.name,label:i.label||i.name});return e}renderFilterRail(){clear(this.filterRail);const t=elt("h4","dm-cb-filter-heading");t.textContent="Filters",this.filterRail.appendChild(t);for(const i of this.config.filterable){const n=(this.schema.fields||[]).find(r=>r.name===i);if(!n)continue;const s=this.buildFilterControl(n);s&&this.filterRail.appendChild(s)}const e=elt("button","dm-cb-filter-reset");e.type="button",e.textContent="Clear filters",e.addEventListener("click",()=>this.setState({filter:{},search:"",page:1})),this.filterRail.appendChild(e)}buildFilterControl(t){const e=elt("div","dm-cb-filter"),i=elt("label","dm-cb-filter-label");switch(i.textContent=t.label||t.name,e.appendChild(i),t.type){case"reference":e.appendChild(this.buildReferenceFilter(t));break;case"select":case"chooser":e.appendChild(this.buildSelectControl(t,!1));break;case"multiselect":case"tags":case"tag":e.appendChild(this.buildSelectControl(t,!0));break;case"number":e.appendChild(this.buildRangeControl(t,"number"));break;case"date":case"datetime":e.appendChild(this.buildRangeControl(t,"date"));break;case"boolean":case"checkbox":e.appendChild(this.buildBooleanControl(t));break;default:e.appendChild(this.buildTextControl(t));break}return e}buildReferenceFilter(t){const e=new Map;for(const r of this.entries){const a=r._refs?.[t.name];if(!a)continue;const o=Array.isArray(a)?a:[a];for(const c of o)!c||c.missing||e.has(c.id)||e.set(c.id,c.display)}const i=`${t.name}_eq`,n=elt("select","dm-cb-select"),s=elt("option");s.value="",s.textContent=this.config.mode==="server"?"Any (loaded)":"Any",n.appendChild(s);for(const[r,a]of e){const o=elt("option");o.value=r,o.textContent=a,String(this.state.filter[i]??"")===String(r)&&(o.selected=!0),n.appendChild(o)}return n.addEventListener("change",()=>this.updateFilter(i,n.value)),n}buildTextControl(t){const e=`${t.name}_contains`,i=elt("input","dm-cb-text");return i.type="text",i.placeholder="Contains\u2026",i.value=this.state.filter[e]||"",i.addEventListener("input",debounce(()=>{this.updateFilter(e,i.value.trim())},200)),i}buildSelectControl(t,e){const i=Array.isArray(t.options)&&t.options.length?t.options.map(o=>typeof o=="object"?o:{value:o,label:o}):distinctValues(this.entries,t.name).map(o=>({value:o,label:o})),n=this.config.mode==="client"?this.facetCounts(t.name,e?"_in":"_eq",i.map(o=>o.value)):null;if(e){const o=`${t.name}_in`,c=elt("div","dm-cb-chips"),d=new Set((this.state.filter[o]||"").split(",").filter(Boolean));for(const h of i){const p=elt("button","dm-cb-chip");p.type="button",d.has(String(h.value))&&p.classList.add("dm-cb-chip-active");const u=elt("span","dm-cb-chip-label");if(u.textContent=h.label??h.value,p.appendChild(u),n){const g=elt("span","dm-cb-chip-count");g.textContent=n[String(h.value)]??0,p.appendChild(g)}p.addEventListener("click",()=>{d.has(String(h.value))?d.delete(String(h.value)):d.add(String(h.value)),this.updateFilter(o,d.size?[...d].join(","):"")}),c.appendChild(p)}return c}const s=`${t.name}_eq`,r=elt("select","dm-cb-select"),a=elt("option");a.value="",a.textContent="Any",r.appendChild(a);for(const o of i){const c=elt("option");c.value=o.value;const d=n?` (${n[String(o.value)]??0})`:"";c.textContent=(o.label??o.value)+d,String(this.state.filter[s]??"")===String(o.value)&&(c.selected=!0),r.appendChild(c)}return r.addEventListener("change",()=>this.updateFilter(s,r.value)),r}facetCounts(t,e,i){const n={};for(const[o,c]of Object.entries(this.state.filter||{})){const{field:d}=parseFilterKey(o);d!==t&&(n[o]=c)}let s=this.entries;if(this.state.search){const o=this.state.search.toLowerCase();s=s.filter(c=>Object.values(c.data||{}).some(d=>String(d).toLowerCase().includes(o)))}const r={...n,...this.config.baked||{}};s=applyFilterInMemory(s,r);const a={};for(const o of i){const c={...r,[`${t}${e}`]:String(o)};a[String(o)]=applyFilterInMemory(s,c).length}return a}buildRangeControl(t,e){const i=`${t.name}_gte`,n=`${t.name}_lte`,s=elt("div","dm-cb-range"),r=elt("div","dm-cb-range-inputs"),a=elt("input","dm-cb-range-min"),o=elt("input","dm-cb-range-max");a.type=e,o.type=e,a.placeholder="Min",o.placeholder="Max",a.value=this.state.filter[i]||"",o.value=this.state.filter[n]||"",r.appendChild(a),r.appendChild(document.createTextNode(" - ")),r.appendChild(o),s.appendChild(r);let c=null;if(e==="number"&&this.config.mode==="client"&&this.entries.length){const h=this.entries.map(p=>Number(p.data?.[t.name])).filter(p=>Number.isFinite(p));if(h.length){const p=Math.min(...h),u=Math.max(...h);u>p&&(c=this.buildDualSlider(p,u,a,o,i,n),s.appendChild(c))}}const d=debounce(()=>{this.updateFilter(i,a.value,!0),this.updateFilter(n,o.value),c&&syncSliderToInputs(c,a.value,o.value)},250);return a.addEventListener("input",d),o.addEventListener("input",d),s}buildDualSlider(t,e,i,n,s,r){const a=elt("div","dm-cb-slider");a.dataset.lo=String(t),a.dataset.hi=String(e);const o=elt("div","dm-cb-slider-track"),c=elt("div","dm-cb-slider-fill");o.appendChild(c),a.appendChild(o);const d=elt("input","dm-cb-slider-handle dm-cb-slider-handle-min"),h=elt("input","dm-cb-slider-handle dm-cb-slider-handle-max");for(const[f,m]of[[d,t],[h,e]])f.type="range",f.min=String(t),f.max=String(e),f.step="any",f.value=String(m);d.value=String(i.value||t),h.value=String(n.value||e),a.appendChild(d),a.appendChild(h);const p=()=>{const f=Math.min(Number(d.value),Number(h.value)),m=Math.max(Number(d.value),Number(h.value)),b=e-t||1;c.style.left=`${(f-t)/b*100}%`,c.style.right=`${100-(m-t)/b*100}%`};p();const u=()=>{Number(d.value)>Number(h.value)&&(d.value=h.value),p(),i.value=d.value,n.value=h.value};d.addEventListener("input",u),h.addEventListener("input",u);const g=()=>{this.updateFilter(s,Number(d.value)>t?d.value:"",!0),this.updateFilter(r,Number(h.value)<e?h.value:"")};return d.addEventListener("change",g),h.addEventListener("change",g),a}buildBooleanControl(t){const e=`${t.name}_eq`,i=elt("select","dm-cb-select");for(const[n,s]of[["","Any"],["true","Yes"],["false","No"]]){const r=elt("option");r.value=n,r.textContent=s,String(this.state.filter[e]??"")===n&&(r.selected=!0),i.appendChild(r)}return i.addEventListener("change",()=>this.updateFilter(e,i.value)),i}updateFilter(t,e,i=!1){const n={...this.state.filter};e===""||e==null?delete n[t]:n[t]=e,this.state.filter=n,this.state.page=1,i||this.refresh()}setState(t){Object.assign(this.state,t),this.refresh()}async refresh(){this.config.syncUrl&&this.writeUrlState(),this.config.mode==="server"&&await this.fetchPage(),this.renderBody(),this.renderPagination(),this.updateFacetCounts(),this.updateDrawerBadge()}updateFacetCounts(){if(this.config.mode==="client"&&this.filterRail)for(const t of this.config.filterable||[]){const e=(this.schema.fields||[]).find(a=>a.name===t);if(!e)continue;const i=e.type==="multiselect"||e.type==="tags"||e.type==="tag"?"_in":"_eq",n=Array.isArray(e.options)&&e.options.length?e.options.map(a=>typeof a=="object"?a:{value:a,label:a}):distinctValues(this.entries,t).map(a=>({value:a,label:a})),s=this.facetCounts(t,i,n.map(a=>a.value)),r=this.filterRail.querySelectorAll(".dm-cb-filter");for(const a of r){const o=a.querySelector(".dm-cb-filter-label");if(!o||o.textContent!==(e.label||e.name))continue;a.querySelectorAll(".dm-cb-chip").forEach((h,p)=>{const u=h.querySelector(".dm-cb-chip-count");u&&n[p]&&(u.textContent=s[String(n[p].value)]??0)});const d=a.querySelector("select.dm-cb-select");d&&Array.from(d.options).forEach(h=>{if(!h.value)return;const p=n.find(u=>String(u.value)===h.value)?.label??h.value;h.textContent=`${p} (${s[h.value]??0})`})}}}updateDrawerBadge(){const t=this.el.querySelector(".dm-cb-drawer-toggle");if(!t)return;const e=(this.state.search?1:0)+Object.keys(this.state.filter||{}).length,i=t.querySelector(".dm-cb-drawer-count");i&&(i.textContent=e>0?`(${e})`:"")}async fetchPage(){const t={...this.state.filter,...this.config.baked||{}},e=new URLSearchParams;e.set("page",this.state.page),e.set("limit",this.config.pageSize),e.set("sort",this.state.sort),e.set("order",this.state.order),this.state.search&&e.set("search",this.state.search);for(const[n,s]of Object.entries(t))e.set(`filter[${n}]`,s);this._fetchAbort&&this._fetchAbort.abort(),this._fetchAbort=new AbortController;const i=this.config.sourceKind==="view"?`/api/views/${encodeURIComponent(this.config.slug)}/public?${e.toString()}`:`/api/collections/${encodeURIComponent(this.config.slug)}/public?${e.toString()}`;try{const n=await fetch(i,{headers:this.authHeaders(),signal:this._fetchAbort.signal});if(!n.ok){this.entries=[],this.total=0;return}const s=await n.json(),r=s.entries||s.results||[];this.entries=r.map(a=>a.data?a:{id:a.id||"",data:a.data||a}),this.total=s.total||r.length}catch(n){if(n.name==="AbortError")return;this.entries=[],this.total=0}}authHeaders(){try{const t=typeof S<"u"&&S.get?S.get("auth_token"):null;return t?{Authorization:`Bearer ${t}`}:{}}catch{return{}}}pipeline(){if(this.config.mode==="server")return{visible:this.entries,total:this.total};let t=this.entries,e=null;if(this.state.search){const c=this.state.search.toLowerCase();e=new Map,t=t.filter(d=>{let h=0;for(const[p,u]of Object.entries(d.data||{})){if(u==null)continue;const g=String(u).toLowerCase();let f=0,m=0;for(;(f=g.indexOf(c,f))!==-1;)m++,f+=c.length;m>0&&(h+=m*(p===this.config.titleField?3:1))}return h>0&&e.set(d.id||d,h),h>0})}if(Object.keys(this.state.filter).length||Object.keys(this.config.baked||{}).length){const c={...this.state.filter,...this.config.baked||{}};t=applyFilterInMemory(t,c)}const i=this.config.initial?.sort||"createdAt",n=this.config.initial?.order||"desc",s=this.state.sort===i&&this.state.order===n;this.state.search&&e&&s?(t=[...t].sort((c,d)=>{const h=e.get(c.id||c)||0;return(e.get(d.id||d)||0)-h}),this._activeSortMode="relevance"):(t=sortEntries(t,this.state.sort,this.state.order),this._activeSortMode=null);const r=t.length,a=(this.state.page-1)*this.config.pageSize;return{visible:t.slice(a,a+this.config.pageSize),total:r}}renderBody(){const{visible:t,total:e}=this.pipeline();if(this.currentTotal=e,clear(this.bodyEl),!t.length){this.bodyEl.appendChild(this.buildEmptyState());return}const i=this.visibleFields(t);this.bodyEl.appendChild(this.renderForDisplay(t,i)),typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(this.bodyEl),this.config.cta&&typeof wireCTAButtons=="function"&&wireCTAButtons(this.bodyEl)}buildEmptyState(){const t=elt("div","dm-collection-display dm-collection-empty"),e=!!this.state.search||Object.keys(this.state.filter||{}).length>0,i=elt("p");if(e){i.textContent="No results for these filters.",t.appendChild(i);const n=elt("button","btn btn-outline dm-cb-empty-clear");n.type="button",n.textContent="Clear filters",n.addEventListener("click",()=>{this.setState({filter:{},search:"",page:1}),this.renderFilterRail();const s=this.el.querySelector(".dm-cb-search-input");s&&(s.value="")}),t.appendChild(n)}else i.textContent=this.config.emptyMsg,t.appendChild(i);return t}visibleFields(t){let e=this.schema.fields||[];return this.config.fields?.length&&(e=this.config.fields.map(i=>e.find(n=>n.name===i)||{name:i,label:i})),!e.length&&t.length&&(e=Object.keys(t[0].data||{}).map(i=>({name:i,label:i}))),e}renderCards(t,e){const i=elt("div",`dm-collection-cards grid grid-cols-${this.config.columns}`);for(const n of t){const s=elt("div","card dm-collection-card"),r=e.find(c=>c.name===this.config.titleField),a=r?fieldDisplay(n,r):this.config.titleField?formatValue(n.data?.[this.config.titleField]):"";if(a){const c=elt("div","card-header");c.textContent=a,s.appendChild(c)}const o=elt("div","card-body");for(const c of e){if(this.config.titleField===c.name||!fieldDisplay(n,c))continue;const h=elt("div","dm-collection-card-field"),p=elt("strong");p.textContent=(c.label||c.name)+": ",h.appendChild(p),h.appendChild(fieldDisplayNode(n,c)),o.appendChild(h)}this.config.cta&&o.appendChild(this.buildCtaButton(n)),this.config.transitions&&o.appendChild(this.buildTransitionsGroup(n)),s.appendChild(o),i.appendChild(s)}return i}renderList(t,e){const i=elt("ul","dm-collection-list");for(const n of t){const s=elt("li","dm-collection-list-item"),r=e.find(c=>c.name===this.config.titleField),a=r?fieldDisplay(n,r):this.config.titleField?formatValue(n.data?.[this.config.titleField]):"";if(a){const c=elt("div","dm-collection-list-title");c.textContent=a,s.appendChild(c)}const o=e.filter(c=>c.name!==this.config.titleField).map(c=>{const d=fieldDisplay(n,c);return d?`${c.label||c.name}: ${d}`:""}).filter(Boolean).join(" \xB7 ");if(o){const c=elt("div","dm-collection-list-meta");c.textContent=o,s.appendChild(c)}this.config.cta&&s.appendChild(this.buildCtaButton(n)),this.config.transitions&&s.appendChild(this.buildTransitionsGroup(n)),i.appendChild(s)}return i}renderTable(t,e){const i=elt("table","dm-collection-table"),n=elt("thead"),s=elt("tr");for(const a of e){const o=elt("th");o.textContent=a.label||a.name,s.appendChild(o)}this.config.cta&&s.appendChild(elt("th")),this.config.transitions&&s.appendChild(elt("th")),n.appendChild(s),i.appendChild(n);const r=elt("tbody");for(const a of t){const o=elt("tr");for(const c of e){const d=elt("td");d.appendChild(fieldDisplayNode(a,c)),o.appendChild(d)}if(this.config.cta){const c=elt("td");c.appendChild(this.buildCtaButton(a)),o.appendChild(c)}if(this.config.transitions){const c=elt("td");c.appendChild(this.buildTransitionsGroup(a)),o.appendChild(c)}r.appendChild(o)}return i.appendChild(r),i}renderAccordion(t){const e=elt("div","accordion dm-collection-accordion");for(const i of t){const n=elt("div","accordion-item"),s=this.config.titleField&&i.data?.[this.config.titleField]||"Untitled",r=this.config.bodyField&&i.data?.[this.config.bodyField]||"",a=elt("button","accordion-header");a.type="button",a.textContent=String(s);const o=elt("div","accordion-panel");o.textContent=String(r),a.addEventListener("click",()=>n.classList.toggle("open")),n.appendChild(a),n.appendChild(o),e.appendChild(n)}return e}buildCtaButton(t){const e=this.config.cta,i=elt("button",`btn btn-${e.style||"primary"} dm-cta-trigger`);if(i.dataset.action=e.action,i.dataset.entry=t.id||"",e.confirm&&(i.dataset.confirm=e.confirm),e.icon){const n=elt("span");n.dataset.icon=e.icon,i.appendChild(n),i.appendChild(document.createTextNode(" "))}return i.appendChild(document.createTextNode(e.label||"Run")),i}buildTransitionsGroup(t){const e=elt("div","dm-cb-transitions");return e.dataset.entry=t.id||"",e.textContent="Loading actions\u2026",Promise.resolve().then(()=>this.loadTransitions(t,e)),e}async loadTransitions(t,e){try{const i=new URLSearchParams({collection:this.config.slug,entryId:t.id||""}),n=await fetch(`/api/actions/transitions?${i.toString()}`,{headers:this.authHeaders()});if(clear(e),!n.ok)return;const{transitions:s}=await n.json();if(!Array.isArray(s)||!s.length)return;for(const r of s){const a=elt("button",`btn btn-${r.trigger?.style||"outline"} dm-cb-transition-btn dm-cta-trigger`);if(a.dataset.action=r.slug,a.dataset.entry=t.id||"",r.trigger?.confirmMessage&&(a.dataset.confirm=r.trigger.confirmMessage),r.trigger?.icon){const o=elt("span");o.dataset.icon=r.trigger.icon,a.appendChild(o),a.appendChild(document.createTextNode(" "))}a.appendChild(document.createTextNode(r.trigger?.label||r.title)),e.appendChild(a)}typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(e),typeof wireCTAButtons=="function"&&wireCTAButtons(e)}catch{clear(e)}}renderPagination(){if(this.config.pagination==="scroll"){this.renderInfiniteSentinel();return}const t=Math.max(1,Math.ceil(this.currentTotal/this.config.pageSize));if(clear(this.pagerEl),t<=1)return;const e=elt("button","dm-cb-page-prev btn btn-outline");e.type="button",e.textContent="\u2039 Prev",e.disabled=this.state.page<=1,e.addEventListener("click",()=>this.setState({page:Math.max(1,this.state.page-1)}));const i=elt("button","dm-cb-page-next btn btn-outline");i.type="button",i.textContent="Next \u203A",i.disabled=this.state.page>=t,i.addEventListener("click",()=>this.setState({page:Math.min(t,this.state.page+1)}));const n=elt("span","dm-cb-page-info");n.textContent=`Page ${this.state.page} of ${t} (${this.currentTotal} entr${this.currentTotal===1?"y":"ies"})`,this.pagerEl.appendChild(e),this.pagerEl.appendChild(n),this.pagerEl.appendChild(i)}renderInfiniteSentinel(){clear(this.pagerEl);const t=Math.max(1,Math.ceil(this.currentTotal/this.config.pageSize));if(this.state.page>=t){const i=elt("p","dm-cb-scroll-end");i.textContent=`All ${this.currentTotal} entries loaded.`,this.pagerEl.appendChild(i);return}const e=elt("div","dm-cb-scroll-sentinel");e.setAttribute("aria-hidden","true"),e.textContent="Loading more\u2026",this.pagerEl.appendChild(e),this._scrollObserver&&this._scrollObserver.disconnect(),this._scrollObserver=new IntersectionObserver(async i=>{i[0].isIntersecting&&(this._scrollObserver.disconnect(),await this.loadMore())},{rootMargin:"200px 0px"}),this._scrollObserver.observe(e)}async loadMore(){const t=this.state.page+1,e=this.currentTotal,i=this.entries,n=this.state.page;this.state.page=t,this.config.syncUrl&&this.writeUrlState();let s;if(this.config.mode==="server")await this.fetchPage(),s=this.entries;else{const{visible:c}=this.pipeline();s=c}if(!s.length){this.state.page=n,this.entries=i,this.currentTotal=e,this.renderPagination();return}const r=this.visibleFields(s),a=this.renderForDisplay(s,r),o=this.bodyEl.firstElementChild;if(o&&o.tagName===a.tagName)for(;a.firstChild;)o.appendChild(a.firstChild);else this.bodyEl.appendChild(a);typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(this.bodyEl),this.config.cta&&typeof wireCTAButtons=="function"&&wireCTAButtons(this.bodyEl),this.renderPagination()}renderForDisplay(t,e){const i=this.config.display;return i==="list"?this.renderList(t,e):i==="table"?this.renderTable(t,e):i==="accordion"?this.renderAccordion(t):i==="timeline"?this.renderTimeline(t):i==="block"?this.renderBlockPlaceholder(t):this.renderCards(t,e)}renderTimeline(t){const e=["vertical","centred","horizontal"].includes(this.config.layout)?this.config.layout:"vertical",i=["minimal","corporate","modern"].includes(this.config.theme)?this.config.theme:"minimal",n=elt("div",`dm-collection-timeline timeline timeline-${e} timeline-${i}`);for(const s of t){const r=elt("div","timeline-event"),a=this.config.dateField&&s.data?.[this.config.dateField]||"",o=this.config.titleField&&s.data?.[this.config.titleField]||"",c=this.config.bodyField&&s.data?.[this.config.bodyField]||"",d=this.config.statusField&&s.data?.[this.config.statusField]||"",h=this.config.iconField&&s.data?.[this.config.iconField]||"";if(h){const p=elt("span","timeline-icon");p.dataset.icon=String(h),r.appendChild(p)}if(a){const p=elt("div","timeline-date");p.textContent=String(a),r.appendChild(p)}if(o){const p=elt("h4","timeline-title");p.textContent=String(o),r.appendChild(p)}if(d){const p=elt("span",`badge badge-${d}`);p.textContent=String(d),r.appendChild(p)}if(c){const p=elt("div","timeline-body");p.textContent=String(c),r.appendChild(p)}n.appendChild(r)}return n}renderBlockPlaceholder(t){const e=elt("div","dm-collection-display dm-cb-block-loading");return e.textContent="Rendering\u2026",this.fetchBlockFragment(t,e),e}async fetchBlockFragment(t,e){const i=++this._fragReqId,n=t.map(a=>a.id).filter(Boolean),s={slug:this.config.slug,display:"block",block:this.config.block,"title-field":this.config.titleField,"body-field":this.config.bodyField,fields:this.config.fields?this.config.fields.join(","):"",empty:this.config.emptyMsg,limit:String(n.length||1)},r={...this.state.filter,...this.config.baked||{}};for(const[a,o]of Object.entries(r))o!==""&&o!=null&&(s[`where_${a}`]=String(o));s.sort=this.state.sort,s.order=this.state.order,s.limit=String(this.config.pageSize);try{const a=btoa(unescape(encodeURIComponent(JSON.stringify(s)))),o=await fetch("/api/collections/render-fragment",{method:"POST",headers:{"Content-Type":"application/json",...this.authHeaders()},body:JSON.stringify({attrs:a,page:this.state.page})});if(i!==this._fragReqId)return;if(!o.ok){e.textContent=this.config.emptyMsg;return}const{html:c}=await o.json(),d=document.createElement("template");d.innerHTML=c||"",e.replaceWith(d.content)}catch{e.textContent="Unable to load block view."}}readUrlState(){if(!this.config.syncUrl)return;const t=new URLSearchParams(window.location.search),e=this.urlPrefix,i=r=>t.get(e+r);i("search")&&(this.state.search=i("search")),i("sort")&&(this.state.sort=i("sort")),i("order")&&(this.state.order=i("order")),i("page")&&(this.state.page=parseInt(i("page"),10)||1);const n={},s=`${e}filter[`;for(const[r,a]of t.entries())if(r.startsWith(s)&&r.endsWith("]")){const o=r.slice(s.length,-1);o&&(n[o]=a)}Object.keys(n).length&&(this.state.filter=n)}writeUrlState(){const t=new URL(window.location.href),e=this.urlPrefix,i=[];for(const s of t.searchParams.keys())s.startsWith(e)&&i.push(s);i.forEach(s=>t.searchParams.delete(s));const n=(s,r)=>{r!==""&&r!=null&&t.searchParams.set(e+s,r)};n("search",this.state.search),this.state.sort!==(this.config.initial?.sort||"createdAt")&&n("sort",this.state.sort),this.state.order!==(this.config.initial?.order||"desc")&&n("order",this.state.order),this.state.page!==1&&n("page",this.state.page);for(const[s,r]of Object.entries(this.state.filter))r!==""&&r!=null&&t.searchParams.set(`${e}filter[${s}]`,r);try{window.history.replaceState({},"",t.toString())}catch{}}}const OPERATORS=["_eq","_ne","_gte","_lte","_gt","_lt","_in","_nin","_contains","_starts","_ends","_exists"];function parseFilterKey(l){for(const t of OPERATORS)if(l.endsWith(t))return{field:l.slice(0,-t.length),op:t};return{field:l,op:"_eq"}}function resolveField(l,t){if(t==="createdBy")return l.meta?.createdBy;if(t==="id")return l.id;const e=t.split(".");let i=l.data;for(const n of e){if(i==null)return;i=i[n]}return i}function maybeNumber(l){if(typeof l=="number"||typeof l!="string")return l;const t=Number(l);return Number.isFinite(t)&&String(t)===l.trim()?t:l}function applyOp(l,t,e){switch(l){case"_eq":{const i=maybeNumber(t),n=maybeNumber(e);return Array.isArray(t)?t.map(maybeNumber).includes(n):i===n||String(i)===String(n)}case"_ne":{const i=maybeNumber(t),n=maybeNumber(e);return Array.isArray(t)?!t.map(maybeNumber).includes(n):!(i===n||String(i)===String(n))}case"_gt":return maybeNumber(t)>maybeNumber(e);case"_gte":return maybeNumber(t)>=maybeNumber(e);case"_lt":return maybeNumber(t)<maybeNumber(e);case"_lte":return maybeNumber(t)<=maybeNumber(e);case"_in":{const i=String(e).split(",").map(n=>maybeNumber(n.trim()));return Array.isArray(t)?t.map(maybeNumber).some(n=>i.includes(n)):i.includes(maybeNumber(t))}case"_nin":{const i=String(e).split(",").map(n=>maybeNumber(n.trim()));return Array.isArray(t)?!t.map(maybeNumber).some(n=>i.includes(n)):!i.includes(maybeNumber(t))}case"_contains":return String(t??"").toLowerCase().includes(String(e).toLowerCase());case"_starts":return String(t??"").toLowerCase().startsWith(String(e).toLowerCase());case"_ends":return String(t??"").toLowerCase().endsWith(String(e).toLowerCase());case"_exists":{const i=t!=null&&t!=="";return e==="true"||e==="1"||e===!0?i:!i}default:return!1}}function applyFilterInMemory(l,t){return!t||!Object.keys(t).length?l:l.filter(e=>{for(const[i,n]of Object.entries(t)){if(n==null||n==="")continue;const{field:s,op:r}=parseFilterKey(i),a=resolveField(e,s);if(!applyOp(r,a,n))return!1}return!0})}function sortEntries(l,t,e){const i=e==="asc"?1:-1;return[...l].sort((n,s)=>{const r=t==="createdAt"?n.meta?.createdAt||"":n.data?.[t]??"",a=t==="createdAt"?s.meta?.createdAt||"":s.data?.[t]??"";return r<a?-i:r>a?i:0})}function elt(l,t){const e=document.createElement(l);return t&&(e.className=t),e}function isFileRef(l){return l&&typeof l=="object"&&typeof l.url=="string"&&typeof l.name=="string"}function formatValue(l){return l==null?"":isFileRef(l)?l.name:Array.isArray(l)?l.join(", "):typeof l=="boolean"?l?"Yes":"No":String(l)}function fieldDisplay(l,t){if(t?.type==="reference"){const e=l?._refs?.[t.name];if(e!=null)return Array.isArray(e)?e.map(i=>i.missing?`${i.id} (missing)`:i.display).join(", "):e.missing?`${e.id} (missing)`:e.display}return formatValue(l?.data?.[t?.name])}function fieldDisplayNode(l,t){if(t?.type==="reference"){const i=l?._refs?.[t.name];if(i!=null){const n=document.createDocumentFragment();return(Array.isArray(i)?i:[i]).forEach((r,a)=>{if(a>0&&n.appendChild(document.createTextNode(", ")),r.missing)n.appendChild(document.createTextNode(`${r.id} (missing)`));else if(r.link){const o=document.createElement("a");o.href=r.link,o.textContent=r.display,n.appendChild(o)}else n.appendChild(document.createTextNode(r.display))}),n}}const e=l?.data?.[t?.name];if(isFileRef(e)){const i=document.createElement("a");if(i.href=e.url,String(e.mime||"").startsWith("image/")){i.target="_blank",i.rel="noopener";const n=document.createElement("img");n.src=e.url,n.alt=e.name,n.loading="lazy",n.className="dm-file-thumb",i.appendChild(n)}else i.download="",i.textContent=e.name;return i}return document.createTextNode(formatValue(e))}function debounce(l,t){let e;return(...i)=>{clearTimeout(e),e=setTimeout(()=>l(...i),t)}}function toCsv(l,t){const e=s=>{if(s==null)return"";let r=Array.isArray(s)?s.join(", "):String(s);return/[",\n\r]/.test(r)&&(r='"'+r.replace(/"/g,'""')+'"'),r},i=t.map(s=>e(s.label||s.name)).join(","),n=l.map(s=>t.map(r=>e(s.data?.[r.name])).join(",")).join(`
2
2
  `);return i+`
3
3
  `+n+`
4
4
  `}function downloadCsv(l,t){const e=new Blob([t],{type:"text/csv;charset=utf-8"}),i=URL.createObjectURL(e),n=document.createElement("a");n.href=i,n.download=l,document.body.appendChild(n),n.click(),n.remove(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}function syncSliderToInputs(l,t,e){if(!l)return;const i=l.querySelector(".dm-cb-slider-handle-min"),n=l.querySelector(".dm-cb-slider-handle-max"),s=l.querySelector(".dm-cb-slider-fill");if(!i||!n||!s)return;const r=Number(l.dataset.lo),a=Number(l.dataset.hi),o=Number(t),c=Number(e);Number.isFinite(o)&&(i.value=String(Math.max(r,Math.min(a,o)))),Number.isFinite(c)&&(n.value=String(Math.max(r,Math.min(a,c))));const d=Math.min(Number(i.value),Number(n.value)),h=Math.max(Number(i.value),Number(n.value)),p=a-r||1;s.style.left=`${(d-r)/p*100}%`,s.style.right=`${100-(h-r)/p*100}%`}
@@ -1,2 +1,2 @@
1
1
  import{compareValues as mt,sortEntries as D}from"/public/js/collection-sort.mjs";import{serialise as T}from"/public/js/collection-export.mjs";import{parseQuery as ut}from"/public/js/collection-query.mjs";(function(){"use strict";const q='url("data:image/svg+xml,'+encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M5 2v15.5l4.2-4 2.4 5.4 2.8-1.2-2.4-5.3 5.5-.1z' fill='#fff' stroke='#000' stroke-width='1.2' stroke-linejoin='round'/><path d='M13.5 15h9.5l-3.6 4.2v4l-2.3-1.8v-2.2z' fill='#5b8cff' stroke='#fff' stroke-width='1' stroke-linejoin='round'/></svg>")+'") 5 3, context-menu',P=document.createElement("style");P.textContent=["[data-ctx], [data-collection-table] { cursor: "+q+"; }","[data-ctx] a, [data-ctx] button, [data-collection-table] a, [data-collection-table] button,","[data-ctx] input, [data-collection-table] input { cursor: pointer; }",'[data-ctx] input[type="text"], [data-collection-table] input[type="text"] { cursor: text; }',".dm-ctx-hidden { display: none !important; }",".dm-ctx-menu { position: fixed; z-index: 10000; min-width: 200px; max-width: 300px; max-height: 60vh; overflow-y: auto;background: var(--dm-surface, #1c1c30); border: 1px solid var(--dm-border, #2a2a40); border-radius: 6px;box-shadow: var(--dm-shadow-lg, 0 8px 24px rgba(0,0,0,.4)); padding: .3rem; font-size: .83rem;color: var(--dm-text, #e5e5e5); }",".dm-ctx-menu button.dm-ctx-row { display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left;background: none; border: none; color: inherit; font: inherit; padding: .35rem .6rem; border-radius: 4px; cursor: pointer; }",".dm-ctx-menu button.dm-ctx-row:hover { background: var(--dm-surface-2, rgba(255,255,255,.06)); }",".dm-ctx-heading { padding: .3rem .6rem; font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;color: var(--dm-text-muted, #9a9aac); }",".dm-ctx-input { width: 100%; font-size: .8rem; padding: .3rem .5rem; border-radius: 4px;border: 1px solid var(--dm-border, #2a2a40); background: var(--dm-surface-2, rgba(255,255,255,.04)); color: inherit; cursor: text; }",".dm-ctx-chips { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin: 0 0 .6rem; }",".dm-ctx-chip { display: inline-flex; align-items: center; gap: .35rem; font-size: .76rem; padding: .2rem .6rem;border-radius: 999px; background: var(--dm-surface-2, rgba(255,255,255,.08)); border: 1px solid var(--dm-border, #2a2a40); }",".dm-ctx-chip button { background: none; border: none; cursor: pointer; color: inherit; font-size: .9rem; line-height: 1; padding: 0; }",".dm-ctx-empty-note { padding: .75rem; font-size: .85rem; color: var(--dm-text-muted, #9a9aac); }",".dm-ctx-panel-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem;border-bottom: 1px solid var(--dm-border, #2a2a40); margin-bottom: .25rem; }",".dm-ctx-menu button.dm-ctx-back { width: auto; padding: .3rem .5rem; color: var(--dm-text-muted, #9a9aac); }",".dm-ctx-group-heading { font-size: .75rem; text-transform: uppercase; letter-spacing: .04em;color: var(--dm-text-muted, #9a9aac); padding: .5rem 0 .25rem; grid-column: 1 / -1; }"].join(`
2
- `),document.head.appendChild(P);function v(t){if(t._dmTable)return{fields:t._dmTable.columns.filter(e=>e.key!=="_cta").map(e=>({name:e.key,label:e.title||e.key})),entries:t._dmTable.rows.map((e,o)=>({id:String(o),data:e}))};if(t._dmCtxModel)return t._dmCtxModel;try{t._dmCtxModel=JSON.parse(atob(t.dataset.ctx))}catch{t._dmCtxModel=null}return t._dmCtxModel}function $(t,e){if(e.field==="*"){const n=String(e.value).toLowerCase();return Object.values(t.data||{}).some(d=>String(d??"").toLowerCase().includes(n))}const o=String(t.data?.[e.field]??"");switch(e.op){case"eq":return o===String(e.value);case"ne":return o!==String(e.value);case"contains":return o.toLowerCase().includes(String(e.value).toLowerCase());case"gt":case"lt":{const n=mt(o,e.value);return e.op==="gt"?n>0:n<0}default:return!0}}function p(t){const e=t._dmCtxFilters||[],o=v(t);if(!o)return;const n=t._dmCtxSort||null,d=D(o.entries.filter(i=>e.every(s=>$(i,s))),n),l=new Set(d.map(i=>i.id));if(t._dmTable)t._dmTable.render(d.map(i=>i.data));else if(t._dmCtx&&t._dmCtx.instance&&t._dmCtx.instance.setItems)t._dmCtx.instance.setItems(t._dmCtx.items.filter(i=>l.has(String(i._entryId))));else if(t._dmCtxSlides)J(t,l);else{const i=Array.from(t.querySelectorAll("[data-entry-id]"));i.forEach(h=>h.classList.toggle("dm-ctx-hidden",!l.has(h.dataset.entryId)));const s=new Map(i.map(h=>[h.dataset.entryId,h])),u=i.length?i[0].parentNode:null;n&&u&&d.forEach(h=>{const x=s.get(h.id);x&&x.parentNode===u&&u.appendChild(x)}),t.querySelectorAll(".dm-ctx-group-heading").forEach(h=>h.remove());const c=t._dmCtxGroup;if(c&&u){let h=null;d.forEach(x=>{const b=String(x.data?.[c]??"")||"\u2014";if(b===h)return;h=b;const a=document.createElement("div");a.className="dm-ctx-group-heading",a.textContent=b;const r=s.get(x.id);r&&u.insertBefore(a,r)})}}Q(t,e),w(t,d.length,e.length),O()}const R="dmf";function A(){return Array.from(document.querySelectorAll("[data-ctx], [data-collection-table]"))}function F(t){return btoa(unescape(encodeURIComponent(JSON.stringify(t)))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function H(t){const e=t.replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(decodeURIComponent(escape(atob(e))))}function O(){const t={};A().forEach((n,d)=>{const l={};n._dmCtxFilters&&n._dmCtxFilters.length&&(l.f=n._dmCtxFilters),n._dmCtxSort&&(l.s=n._dmCtxSort),n._dmCtxGroup&&(l.g=n._dmCtxGroup),Object.keys(l).length&&(t[d]=l)});const e=(location.hash||"").replace(/^#/,"").split("&").filter(n=>n&&!n.startsWith(R+"="));Object.keys(t).length&&e.push(R+"="+F(t));const o=location.pathname+location.search+(e.length?"#"+e.join("&"):"");try{history.replaceState(null,"",o)}catch{}}function V(){const t=(location.hash||"").match(/(?:^#|&)dmf=([A-Za-z0-9_-]+)/);if(!t)return null;try{return H(t[1])}catch{return null}}function N(t=0){const e=V();if(!e)return;const o=A();let n=!1;for(const[d,l]of Object.entries(e)){const i=o[Number(d)];if(!i||!l)continue;if(i.hasAttribute("data-collection-table")?!i._dmTable:i.classList.contains("dm-progression")?!i._dmCtx:i.classList.contains("carousel")?!i._dmCtxSlides:!1){n=!0;continue}const u=Array.isArray(l)?{f:l}:l||{};i._dmCtxFilters=(u.f||[]).filter(c=>c&&c.field&&c.op!=null&&"value"in c),i._dmCtxSort=u.s||null,i._dmCtxGroup=u.g||null,p(i)}n&&t<20&&setTimeout(()=>N(t+1),100)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>setTimeout(N,0)):setTimeout(N,0);function J(t,e){if(t._dmCarousel&&typeof t._dmCarousel.destroy=="function")try{t._dmCarousel.destroy()}catch{}const o=document.createElement("div");o.className="carousel-track",t._dmCtxSlides.forEach(n=>{e.has(n.dataset.entryId)&&o.appendChild(n.cloneNode(!0))}),t.replaceChildren(o),o.children.length&&typeof Domma<"u"&&Domma.elements?.carousel&&(t._dmCarousel=Domma.elements.carousel(t,t._dmCarouselOpts||{}))}function W(t,e,o){const n=URL.createObjectURL(new Blob([t],{type:o})),d=document.createElement("a");d.href=n,d.download=e,document.body.appendChild(d),d.click(),d.remove(),setTimeout(()=>URL.revokeObjectURL(n),0)}function _(t,e){const o=document.createElement("textarea");o.value=t,o.style.cssText="position:fixed;opacity:0;",document.body.appendChild(o),o.select();const n=document.execCommand("copy");o.remove(),typeof E<"u"&&E.toast&&E.toast(n?e:"Copy failed",{type:n?"success":"error"})}function Y(){return new Date().toISOString().slice(0,10)}let k=null;function X(){if(!k){const t=typeof S<"u"&&S.get?S.get("auth_token"):null;k=t?fetch("/api/auth/me",{headers:{Authorization:`Bearer ${t}`}}).then(e=>e.ok?e.json():null).catch(()=>null):Promise.resolve(null)}return k}async function Z(t){if(!t||!t.allowed)return!1;if(t.access==="public")return!0;const e=await X();return e?[e.role,...e.additionalRoles||[]].filter(Boolean).some(n=>(t.roles||[]).includes(n)):!1}const K={eq:"=",ne:"\u2260",contains:"contains",gt:">",lt:"<"};function Q(t,e){let o=t._dmCtxBar;if(!e.length){o&&(o.remove(),t._dmCtxBar=null);return}o||(o=document.createElement("div"),o.className="dm-ctx-chips",t.parentNode.insertBefore(o,t),t._dmCtxBar=o),o.replaceChildren(),e.forEach((d,l)=>{const i=document.createElement("span");i.className="dm-ctx-chip";const s=String(d.value),u=s.length>24?s.slice(0,24)+"\u2026":s;i.appendChild(document.createTextNode(d.field==="*"?`search \u201C${u}\u201D`:`${d.label||d.field} ${K[d.op]||d.op} \u201C${u}\u201D`));const c=document.createElement("button");c.type="button",c.textContent="\xD7",c.title="Remove filter",c.addEventListener("click",()=>{t._dmCtxFilters.splice(l,1),p(t)}),i.appendChild(c),o.appendChild(i)});const n=document.createElement("button");n.type="button",n.className="dm-ctx-chip",n.style.cursor="pointer",n.textContent="Clear all",n.addEventListener("click",()=>{t._dmCtxFilters=[],p(t)}),o.appendChild(n)}function w(t,e,o){if(t._dmCtxEmptyNote&&(t._dmCtxEmptyNote.remove(),t._dmCtxEmptyNote=null),e||!o)return;const n=document.createElement("div");n.className="dm-ctx-empty-note",n.textContent="No entries match the current filters.",t.appendChild(n),t._dmCtxEmptyNote=n}let C=null;function f(){C&&(C.remove(),C=null,document.removeEventListener("mousedown",j,!0),document.removeEventListener("keydown",G,!0),window.removeEventListener("scroll",M,!0))}const j=t=>{C&&!C.contains(t.target)&&f()},G=t=>{t.key==="Escape"&&f()},M=t=>{C&&!C.contains(t.target)&&f()};function m(t,e){const o=document.createElement("button");return o.type="button",o.className="dm-ctx-row",o.textContent=t,o.addEventListener("click",e),o}function y(t){const e=document.createElement("div");return e.className="dm-ctx-heading",e.textContent=t,e}function I(){const t=document.createElement("div");return t.style.cssText="border-top:1px solid var(--dm-border,#2a2a40);margin:.25rem 0;",t}const g=(t,e=24)=>{const o=String(t);return o.length>e?o.slice(0,e)+"\u2026":o};function B(t){const e=t.getBoundingClientRect();t.style.left=Math.min(t._dmX,window.innerWidth-e.width-8)+"px",t.style.top=Math.min(t._dmY,window.innerHeight-e.height-8)+"px"}function U(t,e,o){if(t._dmPanelToken=(t._dmPanelToken||0)+1,t.replaceChildren(),o){const n=document.createElement("div");n.className="dm-ctx-panel-head";const d=document.createElement("button");d.type="button",d.className="dm-ctx-row dm-ctx-back",d.textContent="\u2039 Back",d.addEventListener("click",()=>t._dmPop()),n.appendChild(d),n.appendChild(y(o)),t.appendChild(n)}e(t),B(t)}function tt(t){const e=[];return t._dmPush=(o,n)=>{e.push({build:o,title:n}),U(t,o,n)},t._dmPop=()=>{e.pop();const o=e[e.length-1];o&&U(t,o.build,o.title)},t}function et(t){return!t._dmTable&&!t._dmCtx?.instance?.setItems&&!t._dmCtxSlides}function nt(t,e){const o=t.entries.map(d=>d.data?.[e]).find(d=>d!==""&&d!=null),n=String(o??"");return n!==""&&!Number.isNaN(parseFloat(n))?["low \u2192 high","high \u2192 low"]:Number.isNaN(Date.parse(n))?["A \u2192 Z","Z \u2192 A"]:["oldest \u2192 newest","newest \u2192 oldest"]}function ot(t,e,o){o.fields.forEach(n=>{const[d,l]=nt(o,n.name);t.appendChild(m(`${n.label||n.name} ${d}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"},p(e),f()})),t.appendChild(m(`${n.label||n.name} ${l}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"desc"},p(e),f()}))}),e._dmCtxSort&&t.appendChild(m("Clear sort",()=>{e._dmCtxSort=null,p(e),f()}))}function dt(t,e,o){o.fields.forEach(n=>{t.appendChild(m(n.label||n.name,()=>{e._dmCtxGroup=n.name,(!e._dmCtxSort||e._dmCtxSort.field!==n.name)&&(e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"}),p(e),f()}))}),e._dmCtxGroup&&t.appendChild(m("Clear grouping",()=>{e._dmCtxGroup=null,p(e),f()}))}function z(t,e){const o=t._dmCtxFilters||[];return D(e.entries.filter(n=>o.every(d=>$(n,d))),t._dmCtxSort||null).map(n=>n.data)}function it(t,e,o,n){const d=o.slug||e._dmTable?.slug||"collection";n.formats.forEach(l=>{t.appendChild(m(l.toUpperCase(),()=>{const i=T(z(e,o),o.fields,l);W(i,`${d}-${Y()}.${l}`,l==="csv"?"text/csv;charset=utf-8":"application/json"),f()}))})}function at(t,e,o,n,d){n&&d&&t.appendChild(m("This value",()=>{_(String(n.data?.[d.name]??""),"Value copied"),f()})),n&&t.appendChild(m("This row (JSON)",()=>{_(T([n.data],o.fields,"json"),"Row copied"),f()})),t.appendChild(m("Visible entries as a table",()=>{_(T(z(e,o),o.fields,"markdown"),"Table copied"),f()}))}function lt(t,e,o,n,d){const l=(a,r,L,ct)=>{(e._dmCtxFilters=e._dmCtxFilters||[]).push({field:a,label:r,op:L,value:ct}),p(e),f()};if(n&&o){const a=o.data?.[n.name]??"";t.appendChild(y(n.label||n.name)),t.appendChild(m(`Filter: = \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"eq",a))),t.appendChild(m(`Filter: \u2260 \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"ne",a)));const r=String(a);(r!==""&&!Number.isNaN(parseFloat(r))||!Number.isNaN(Date.parse(r)))&&(t.appendChild(m(`Filter: > \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"gt",a))),t.appendChild(m(`Filter: < \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"lt",a))))}else if(o){t.appendChild(y("Filter by"));for(const a of d.fields){const r=o.data?.[a.name];r==null||String(r)===""||t.appendChild(m(`${a.label||a.name}: \u201C${g(r,20)}\u201D`,()=>l(a.name,a.label,"eq",r)))}}const i=document.createElement("div");i.style.padding=".35rem .6rem";const s=document.createElement("input");s.type="text",s.className="dm-ctx-input",s.placeholder="Search\u2026 or name: value",s.addEventListener("mousedown",a=>a.stopPropagation()),s.addEventListener("keydown",a=>{if(a.key!=="Enter"||!s.value.trim())return;const r=ut(s.value,d.fields);r?l(r.field,r.label,r.op,r.value):l("*","search","contains",s.value.trim())}),i.appendChild(s),t.appendChild(i),t.appendChild(I()),t.appendChild(y("This display")),t.appendChild(m("Sort\u2026",()=>t._dmPush(a=>ot(a,e,d),"Sort"))),et(e)&&t.appendChild(m("Group by\u2026",()=>t._dmPush(a=>dt(a,e,d),"Group by"))),t.appendChild(m("Copy\u2026",()=>t._dmPush(a=>at(a,e,d,o,n),"Copy")));const u=m("Print",()=>{e.setAttribute("data-dm-print",""),document.body.classList.add("dm-ctx-printing"),f();const a=()=>{e.removeAttribute("data-dm-print"),document.body.classList.remove("dm-ctx-printing"),window.removeEventListener("afterprint",a)};window.addEventListener("afterprint",a),window.print()});t.appendChild(u),t.appendChild(m("Copy link to this view",()=>{O(),_(location.href,"Link copied"),f()}));const c=d.export||e._dmTable?.exportCfg,h=t._dmPanelToken;Z(c).then(a=>{!a||C!==t||t._dmPanelToken!==h||(t.insertBefore(m("Export\u2026",()=>t._dmPush(r=>it(r,e,d,c),"Export")),u),B(t))});const x=(e._dmCtxFilters||[]).length;if(x||e._dmCtxSort||e._dmCtxGroup){const a=[];x&&a.push(`${x} filter${x===1?"":"s"}`),e._dmCtxSort&&a.push("sort"),e._dmCtxGroup&&a.push("grouping"),t.appendChild(I()),t.appendChild(m(`Clear all (${a.join(", ")})`,()=>{e._dmCtxFilters=[],e._dmCtxSort=null,e._dmCtxGroup=null,p(e),f()}))}}function st(t,e,o,n,d){f();const l=v(o);if(!l)return;const i=tt(document.createElement("div"));i.className="dm-ctx-menu",i._dmX=t,i._dmY=e,C=i,document.body.appendChild(i),i._dmPush(s=>lt(s,o,n,d,l),null),document.addEventListener("mousedown",j,!0),document.addEventListener("keydown",G,!0),window.addEventListener("scroll",M,!0),setTimeout(()=>{const s=i.querySelector(".dm-ctx-input");s&&s.focus()},0)}function rt(t,e,o){if(t._dmTable){const s=e.closest("tbody tr");if(!s)return{entry:null,field:null};const u=e.closest("td"),c=s.querySelectorAll("td"),h=Array.from(c).map(a=>a.textContent.trim()),x=o.entries.find(a=>o.fields.every((r,L)=>String(a.data?.[r.name]??"").trim()===(h[L]??"").trim()))||null,b=u&&o.fields[u.cellIndex]||null;return{entry:x,field:b}}const n=e.closest("[data-entry-id]");if(!n)return{entry:null,field:null};const d=o.entries.find(s=>s.id===n.dataset.entryId)||null;if(!d)return{entry:null,field:null};const l=(e.textContent||"").trim().slice(0,80);let i=null;if(l){const s=o.fields.filter(u=>{const c=String(d.data?.[u.name]??"");return c&&(c.includes(l)||l.includes(c))});s.length===1&&(i=s[0])}return{entry:d,field:i}}document.addEventListener("contextmenu",t=>{const e=t.target.closest("[data-ctx], [data-collection-table]");if(!e)return;const o=v(e);if(!o||!o.fields?.length)return;t.preventDefault();const{entry:n,field:d}=rt(e,t.target,o);st(t.clientX,t.clientY,e,n,d)})})();
2
+ `),document.head.appendChild(P);function v(t){if(t._dmTable)return{fields:t._dmTable.columns.filter(e=>e.key!=="_cta").map(e=>({name:e.key,label:e.title||e.key})),entries:t._dmTable.rows.map((e,o)=>({id:String(o),data:e}))};if(t._dmCtxModel)return t._dmCtxModel;try{t._dmCtxModel=JSON.parse(atob(t.dataset.ctx))}catch{t._dmCtxModel=null}return t._dmCtxModel}function $(t,e){if(e.field==="*"){const n=String(e.value).toLowerCase();return Object.values(t.data||{}).some(d=>String(d??"").toLowerCase().includes(n))}const o=String(t.data?.[e.field]??"");switch(e.op){case"eq":return o===String(e.value);case"ne":return o!==String(e.value);case"contains":return o.toLowerCase().includes(String(e.value).toLowerCase());case"gt":case"lt":{const n=mt(o,e.value);return e.op==="gt"?n>0:n<0}default:return!0}}function p(t){const e=t._dmCtxFilters||[],o=v(t);if(!o)return;const n=t._dmCtxSort||null,d=D(o.entries.filter(i=>e.every(s=>$(i,s))),n),l=new Set(d.map(i=>i.id));if(t._dmTable)t._dmTable.render(d.map(i=>i.data));else if(t._dmCtx&&t._dmCtx.instance&&t._dmCtx.instance.setItems)t._dmCtx.instance.setItems(t._dmCtx.items.filter(i=>l.has(String(i._entryId))));else if(t._dmCtxSlides)J(t,l);else{const i=Array.from(t.querySelectorAll("[data-entry-id]"));i.forEach(h=>h.classList.toggle("dm-ctx-hidden",!l.has(h.dataset.entryId)));const s=new Map(i.map(h=>[h.dataset.entryId,h])),u=i.length?i[0].parentNode:null;n&&u&&d.forEach(h=>{const x=s.get(h.id);x&&x.parentNode===u&&u.appendChild(x)}),t.querySelectorAll(".dm-ctx-group-heading").forEach(h=>h.remove());const c=t._dmCtxGroup;if(c&&u){let h=null;d.forEach(x=>{const b=String(x.data?.[c]??"")||"-";if(b===h)return;h=b;const a=document.createElement("div");a.className="dm-ctx-group-heading",a.textContent=b;const r=s.get(x.id);r&&u.insertBefore(a,r)})}}Q(t,e),w(t,d.length,e.length),O()}const R="dmf";function A(){return Array.from(document.querySelectorAll("[data-ctx], [data-collection-table]"))}function F(t){return btoa(unescape(encodeURIComponent(JSON.stringify(t)))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function H(t){const e=t.replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(decodeURIComponent(escape(atob(e))))}function O(){const t={};A().forEach((n,d)=>{const l={};n._dmCtxFilters&&n._dmCtxFilters.length&&(l.f=n._dmCtxFilters),n._dmCtxSort&&(l.s=n._dmCtxSort),n._dmCtxGroup&&(l.g=n._dmCtxGroup),Object.keys(l).length&&(t[d]=l)});const e=(location.hash||"").replace(/^#/,"").split("&").filter(n=>n&&!n.startsWith(R+"="));Object.keys(t).length&&e.push(R+"="+F(t));const o=location.pathname+location.search+(e.length?"#"+e.join("&"):"");try{history.replaceState(null,"",o)}catch{}}function V(){const t=(location.hash||"").match(/(?:^#|&)dmf=([A-Za-z0-9_-]+)/);if(!t)return null;try{return H(t[1])}catch{return null}}function N(t=0){const e=V();if(!e)return;const o=A();let n=!1;for(const[d,l]of Object.entries(e)){const i=o[Number(d)];if(!i||!l)continue;if(i.hasAttribute("data-collection-table")?!i._dmTable:i.classList.contains("dm-progression")?!i._dmCtx:i.classList.contains("carousel")?!i._dmCtxSlides:!1){n=!0;continue}const u=Array.isArray(l)?{f:l}:l||{};i._dmCtxFilters=(u.f||[]).filter(c=>c&&c.field&&c.op!=null&&"value"in c),i._dmCtxSort=u.s||null,i._dmCtxGroup=u.g||null,p(i)}n&&t<20&&setTimeout(()=>N(t+1),100)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>setTimeout(N,0)):setTimeout(N,0);function J(t,e){if(t._dmCarousel&&typeof t._dmCarousel.destroy=="function")try{t._dmCarousel.destroy()}catch{}const o=document.createElement("div");o.className="carousel-track",t._dmCtxSlides.forEach(n=>{e.has(n.dataset.entryId)&&o.appendChild(n.cloneNode(!0))}),t.replaceChildren(o),o.children.length&&typeof Domma<"u"&&Domma.elements?.carousel&&(t._dmCarousel=Domma.elements.carousel(t,t._dmCarouselOpts||{}))}function W(t,e,o){const n=URL.createObjectURL(new Blob([t],{type:o})),d=document.createElement("a");d.href=n,d.download=e,document.body.appendChild(d),d.click(),d.remove(),setTimeout(()=>URL.revokeObjectURL(n),0)}function _(t,e){const o=document.createElement("textarea");o.value=t,o.style.cssText="position:fixed;opacity:0;",document.body.appendChild(o),o.select();const n=document.execCommand("copy");o.remove(),typeof E<"u"&&E.toast&&E.toast(n?e:"Copy failed",{type:n?"success":"error"})}function Y(){return new Date().toISOString().slice(0,10)}let k=null;function X(){if(!k){const t=typeof S<"u"&&S.get?S.get("auth_token"):null;k=t?fetch("/api/auth/me",{headers:{Authorization:`Bearer ${t}`}}).then(e=>e.ok?e.json():null).catch(()=>null):Promise.resolve(null)}return k}async function Z(t){if(!t||!t.allowed)return!1;if(t.access==="public")return!0;const e=await X();return e?[e.role,...e.additionalRoles||[]].filter(Boolean).some(n=>(t.roles||[]).includes(n)):!1}const K={eq:"=",ne:"\u2260",contains:"contains",gt:">",lt:"<"};function Q(t,e){let o=t._dmCtxBar;if(!e.length){o&&(o.remove(),t._dmCtxBar=null);return}o||(o=document.createElement("div"),o.className="dm-ctx-chips",t.parentNode.insertBefore(o,t),t._dmCtxBar=o),o.replaceChildren(),e.forEach((d,l)=>{const i=document.createElement("span");i.className="dm-ctx-chip";const s=String(d.value),u=s.length>24?s.slice(0,24)+"\u2026":s;i.appendChild(document.createTextNode(d.field==="*"?`search \u201C${u}\u201D`:`${d.label||d.field} ${K[d.op]||d.op} \u201C${u}\u201D`));const c=document.createElement("button");c.type="button",c.textContent="\xD7",c.title="Remove filter",c.addEventListener("click",()=>{t._dmCtxFilters.splice(l,1),p(t)}),i.appendChild(c),o.appendChild(i)});const n=document.createElement("button");n.type="button",n.className="dm-ctx-chip",n.style.cursor="pointer",n.textContent="Clear all",n.addEventListener("click",()=>{t._dmCtxFilters=[],p(t)}),o.appendChild(n)}function w(t,e,o){if(t._dmCtxEmptyNote&&(t._dmCtxEmptyNote.remove(),t._dmCtxEmptyNote=null),e||!o)return;const n=document.createElement("div");n.className="dm-ctx-empty-note",n.textContent="No entries match the current filters.",t.appendChild(n),t._dmCtxEmptyNote=n}let C=null;function f(){C&&(C.remove(),C=null,document.removeEventListener("mousedown",j,!0),document.removeEventListener("keydown",G,!0),window.removeEventListener("scroll",M,!0))}const j=t=>{C&&!C.contains(t.target)&&f()},G=t=>{t.key==="Escape"&&f()},M=t=>{C&&!C.contains(t.target)&&f()};function m(t,e){const o=document.createElement("button");return o.type="button",o.className="dm-ctx-row",o.textContent=t,o.addEventListener("click",e),o}function y(t){const e=document.createElement("div");return e.className="dm-ctx-heading",e.textContent=t,e}function I(){const t=document.createElement("div");return t.style.cssText="border-top:1px solid var(--dm-border,#2a2a40);margin:.25rem 0;",t}const g=(t,e=24)=>{const o=String(t);return o.length>e?o.slice(0,e)+"\u2026":o};function B(t){const e=t.getBoundingClientRect();t.style.left=Math.min(t._dmX,window.innerWidth-e.width-8)+"px",t.style.top=Math.min(t._dmY,window.innerHeight-e.height-8)+"px"}function U(t,e,o){if(t._dmPanelToken=(t._dmPanelToken||0)+1,t.replaceChildren(),o){const n=document.createElement("div");n.className="dm-ctx-panel-head";const d=document.createElement("button");d.type="button",d.className="dm-ctx-row dm-ctx-back",d.textContent="\u2039 Back",d.addEventListener("click",()=>t._dmPop()),n.appendChild(d),n.appendChild(y(o)),t.appendChild(n)}e(t),B(t)}function tt(t){const e=[];return t._dmPush=(o,n)=>{e.push({build:o,title:n}),U(t,o,n)},t._dmPop=()=>{e.pop();const o=e[e.length-1];o&&U(t,o.build,o.title)},t}function et(t){return!t._dmTable&&!t._dmCtx?.instance?.setItems&&!t._dmCtxSlides}function nt(t,e){const o=t.entries.map(d=>d.data?.[e]).find(d=>d!==""&&d!=null),n=String(o??"");return n!==""&&!Number.isNaN(parseFloat(n))?["low \u2192 high","high \u2192 low"]:Number.isNaN(Date.parse(n))?["A \u2192 Z","Z \u2192 A"]:["oldest \u2192 newest","newest \u2192 oldest"]}function ot(t,e,o){o.fields.forEach(n=>{const[d,l]=nt(o,n.name);t.appendChild(m(`${n.label||n.name} ${d}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"},p(e),f()})),t.appendChild(m(`${n.label||n.name} ${l}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"desc"},p(e),f()}))}),e._dmCtxSort&&t.appendChild(m("Clear sort",()=>{e._dmCtxSort=null,p(e),f()}))}function dt(t,e,o){o.fields.forEach(n=>{t.appendChild(m(n.label||n.name,()=>{e._dmCtxGroup=n.name,(!e._dmCtxSort||e._dmCtxSort.field!==n.name)&&(e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"}),p(e),f()}))}),e._dmCtxGroup&&t.appendChild(m("Clear grouping",()=>{e._dmCtxGroup=null,p(e),f()}))}function z(t,e){const o=t._dmCtxFilters||[];return D(e.entries.filter(n=>o.every(d=>$(n,d))),t._dmCtxSort||null).map(n=>n.data)}function it(t,e,o,n){const d=o.slug||e._dmTable?.slug||"collection";n.formats.forEach(l=>{t.appendChild(m(l.toUpperCase(),()=>{const i=T(z(e,o),o.fields,l);W(i,`${d}-${Y()}.${l}`,l==="csv"?"text/csv;charset=utf-8":"application/json"),f()}))})}function at(t,e,o,n,d){n&&d&&t.appendChild(m("This value",()=>{_(String(n.data?.[d.name]??""),"Value copied"),f()})),n&&t.appendChild(m("This row (JSON)",()=>{_(T([n.data],o.fields,"json"),"Row copied"),f()})),t.appendChild(m("Visible entries as a table",()=>{_(T(z(e,o),o.fields,"markdown"),"Table copied"),f()}))}function lt(t,e,o,n,d){const l=(a,r,L,ct)=>{(e._dmCtxFilters=e._dmCtxFilters||[]).push({field:a,label:r,op:L,value:ct}),p(e),f()};if(n&&o){const a=o.data?.[n.name]??"";t.appendChild(y(n.label||n.name)),t.appendChild(m(`Filter: = \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"eq",a))),t.appendChild(m(`Filter: \u2260 \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"ne",a)));const r=String(a);(r!==""&&!Number.isNaN(parseFloat(r))||!Number.isNaN(Date.parse(r)))&&(t.appendChild(m(`Filter: > \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"gt",a))),t.appendChild(m(`Filter: < \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"lt",a))))}else if(o){t.appendChild(y("Filter by"));for(const a of d.fields){const r=o.data?.[a.name];r==null||String(r)===""||t.appendChild(m(`${a.label||a.name}: \u201C${g(r,20)}\u201D`,()=>l(a.name,a.label,"eq",r)))}}const i=document.createElement("div");i.style.padding=".35rem .6rem";const s=document.createElement("input");s.type="text",s.className="dm-ctx-input",s.placeholder="Search\u2026 or name: value",s.addEventListener("mousedown",a=>a.stopPropagation()),s.addEventListener("keydown",a=>{if(a.key!=="Enter"||!s.value.trim())return;const r=ut(s.value,d.fields);r?l(r.field,r.label,r.op,r.value):l("*","search","contains",s.value.trim())}),i.appendChild(s),t.appendChild(i),t.appendChild(I()),t.appendChild(y("This display")),t.appendChild(m("Sort\u2026",()=>t._dmPush(a=>ot(a,e,d),"Sort"))),et(e)&&t.appendChild(m("Group by\u2026",()=>t._dmPush(a=>dt(a,e,d),"Group by"))),t.appendChild(m("Copy\u2026",()=>t._dmPush(a=>at(a,e,d,o,n),"Copy")));const u=m("Print",()=>{e.setAttribute("data-dm-print",""),document.body.classList.add("dm-ctx-printing"),f();const a=()=>{e.removeAttribute("data-dm-print"),document.body.classList.remove("dm-ctx-printing"),window.removeEventListener("afterprint",a)};window.addEventListener("afterprint",a),window.print()});t.appendChild(u),t.appendChild(m("Copy link to this view",()=>{O(),_(location.href,"Link copied"),f()}));const c=d.export||e._dmTable?.exportCfg,h=t._dmPanelToken;Z(c).then(a=>{!a||C!==t||t._dmPanelToken!==h||(t.insertBefore(m("Export\u2026",()=>t._dmPush(r=>it(r,e,d,c),"Export")),u),B(t))});const x=(e._dmCtxFilters||[]).length;if(x||e._dmCtxSort||e._dmCtxGroup){const a=[];x&&a.push(`${x} filter${x===1?"":"s"}`),e._dmCtxSort&&a.push("sort"),e._dmCtxGroup&&a.push("grouping"),t.appendChild(I()),t.appendChild(m(`Clear all (${a.join(", ")})`,()=>{e._dmCtxFilters=[],e._dmCtxSort=null,e._dmCtxGroup=null,p(e),f()}))}}function st(t,e,o,n,d){f();const l=v(o);if(!l)return;const i=tt(document.createElement("div"));i.className="dm-ctx-menu",i._dmX=t,i._dmY=e,C=i,document.body.appendChild(i),i._dmPush(s=>lt(s,o,n,d,l),null),document.addEventListener("mousedown",j,!0),document.addEventListener("keydown",G,!0),window.addEventListener("scroll",M,!0),setTimeout(()=>{const s=i.querySelector(".dm-ctx-input");s&&s.focus()},0)}function rt(t,e,o){if(t._dmTable){const s=e.closest("tbody tr");if(!s)return{entry:null,field:null};const u=e.closest("td"),c=s.querySelectorAll("td"),h=Array.from(c).map(a=>a.textContent.trim()),x=o.entries.find(a=>o.fields.every((r,L)=>String(a.data?.[r.name]??"").trim()===(h[L]??"").trim()))||null,b=u&&o.fields[u.cellIndex]||null;return{entry:x,field:b}}const n=e.closest("[data-entry-id]");if(!n)return{entry:null,field:null};const d=o.entries.find(s=>s.id===n.dataset.entryId)||null;if(!d)return{entry:null,field:null};const l=(e.textContent||"").trim().slice(0,80);let i=null;if(l){const s=o.fields.filter(u=>{const c=String(d.data?.[u.name]??"");return c&&(c.includes(l)||l.includes(c))});s.length===1&&(i=s[0])}return{entry:d,field:i}}document.addEventListener("contextmenu",t=>{const e=t.target.closest("[data-ctx], [data-collection-table]");if(!e)return;const o=v(e);if(!o||!o.fields?.length)return;t.preventDefault();const{entry:n,field:d}=rt(e,t.target,o);st(t.clientX,t.clientY,e,n,d)})})();
@@ -1 +1 @@
1
- (function(c,l){typeof module<"u"&&module.exports?module.exports=l():c.FormLogicEngine=l()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function c(e){return e===""||e===null||e===void 0?"":String(e)}function l(e){const r=parseFloat(e);return isNaN(r)?null:r}function f(e){return e==null?!0:typeof e=="string"?e.trim()==="":Array.isArray(e)?e.length===0:!1}const x={not_equals:"equals",not_contains:"contains",not_in:"in"};function m(e,r){const s=c(r),t=c(e.value);switch(e.operator){case"equals":return s===t;case"not_equals":return s!==t;case"contains":return s.toLowerCase().includes(t.toLowerCase());case"not_contains":return!s.toLowerCase().includes(t.toLowerCase());case"starts_with":return s.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return s.toLowerCase().endsWith(t.toLowerCase());case"greater_than":{const n=l(r),i=l(e.value);return n!==null&&i!==null&&n>i}case"less_than":{const n=l(r),i=l(e.value);return n!==null&&i!==null&&n<i}case"is_empty":return f(r);case"is_not_empty":return!f(r);case"in":return(Array.isArray(e.value)?e.value.map(c):String(e.value).split(",").map(i=>i.trim())).includes(s);case"not_in":return!(Array.isArray(e.value)?e.value.map(c):String(e.value).split(",").map(i=>i.trim())).includes(s);case"matches_regex":try{const n=e.flags||"";return new RegExp(e.value,n).test(s)}catch(n){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,n&&n.message),!1}default:return!0}}function y(e,r){if(!e||!e.field||!e.operator)return!0;const s=r[e.field];if(!Array.isArray(s))return m(e,s);if(e.operator==="is_empty")return f(s);if(e.operator==="is_not_empty")return!f(s);const t=x[e.operator];if(t){const n=Object.assign({},e,{operator:t});return!s.some(i=>m(n,i))}return s.some(n=>m(e,n))}function p(e,r){return e?Array.isArray(e.all)?e.all.every(s=>s.all||s.any?p(s,r):y(s,r)):Array.isArray(e.any)?e.any.some(s=>s.all||s.any?p(s,r):y(s,r)):e.field&&e.operator?y(e,r):!0:!0}function g(e,r){const s=e.logic;if(!s||!s.visibility)return"visible";const t=s.visibility,n=t.conditions||[];for(const i of n)if(i.when&&p(i.when,r))return i.then==="hidden"?"hidden":"visible";return t.default==="hidden"?"hidden":"visible"}function v(e,r){const s=e.logic;if(!s||!s.requirement)return e.required||!1;const t=s.requirement,n=t.conditions||[];for(const i of n)if(i.when&&p(i.when,r))return i.then===!0;return t.default===!0}function b(e,r,s){const t=e.logic;if(!t||!Array.isArray(t.validation))return[];const n=[];for(const i of t.validation)switch(i.type){case"regex":{if(!f(r))try{new RegExp(i.pattern||"",i.flags||"").test(c(r))||n.push({message:i.message||"Invalid format."})}catch{}break}case"match":{const a=s[i.field];!f(r)&&c(r)!==c(a)&&n.push({message:i.message||"Fields do not match."});break}}return n}function w(e,r){const s=e.logic;if(!s||!s.cascade||!s.cascade.sourceField)return null;const t=s.cascade,n=t.mapping||{},i=r[t.sourceField];if(Array.isArray(i)){const u=new Set,d=[];return i.forEach(function(M){const E=c(M);Object.prototype.hasOwnProperty.call(n,E)&&(n[E]||[]).forEach(function(_){const q=c(_&&_.value);u.has(q)||(u.add(q),d.push(_))})}),d.length?d:t.defaultOptions||null}const a=c(i);return Object.prototype.hasOwnProperty.call(n,a)?n[a]||[]:t.defaultOptions||null}const F={fade:250,slide:300,scale:200};function A(e,r){const s=Number(r);return!isFinite(s)||s<0||s>5e3?F[e]||250:Math.round(s)}function L(e,r,s){const t=A(r,s);if(r==="fade")e.style.transition="opacity "+t+"ms ease",e.style.opacity="1",requestAnimationFrame(function(){e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const n=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+t+"ms ease, opacity "+n+"ms ease",requestAnimationFrame(function(){e.style.maxHeight="0",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",e.style.transform="scale(1)",e.style.opacity="1",requestAnimationFrame(function(){e.style.transform="scale(0.95)",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function C(e,r,s){const t=A(r,s);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+t+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const n=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+t+"ms ease, opacity "+n+"ms ease",requestAnimationFrame(function(){e.style.maxHeight=e.scrollHeight+"px",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function o(e,r){this._form=e,this._wrapper=r,this._fields=(e.fields||[]).filter(s=>s.type!=="page-break"),this._listeners=[],this._depMap=new Map,this._initialEval=!1}function h(e,r,s){const t=s||"",n=r||"";return t+'[name="'+e+'"]'+n+", "+t+'[name="'+e+'[]"]'+n}function S(e){return String(e||"").replace(/\[\]$/,"")}return o.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(h(e))},o.prototype._fieldInput=function(e){return this._wrapper.querySelector(h(e))},o.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const s=r.logic;if(!s)return;function t(n){if(!n)return;(n.all||n.any||[]).forEach(function(a){a.field?(e._depMap.has(a.field)||e._depMap.set(a.field,new Set),e._depMap.get(a.field).add(r.name)):t(a)})}if(s.visibility&&(s.visibility.conditions||[]).forEach(function(n){t(n.when)}),s.requirement&&(s.requirement.conditions||[]).forEach(function(n){t(n.when)}),s.cascade&&s.cascade.sourceField){const n=s.cascade.sourceField;e._depMap.has(n)||e._depMap.set(n,new Set),e._depMap.get(n).add(r.name)}})},o.prototype._getValues=function(){const e={};return this._fields.forEach(function(r){const s=this._fieldInputs(r.name);if(!s.length)return;const t=s[0];if(t.type==="radio"){const n=this._wrapper.querySelector(h(r.name,":checked"));e[r.name]=n?n.value:""}else if(t.type==="checkbox")if(s.length>1||/\[\]$/.test(t.name||"")){const n=[];s.forEach(function(i){i.checked&&n.push(i.value)}),e[r.name]=n}else e[r.name]=t.checked?t.value||"true":"";else e[r.name]=t.value},this),e},o.prototype._applyVisibility=function(e,r){const t=g(e,r)==="hidden",n=this._findFieldWrapper(e.name);if(!n)return;n.setAttribute("aria-hidden",String(t));const i=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(i==="none"){n.classList.toggle("fb-field-hidden",t);return}const a=e.logic?.visibility?.duration;n.style.transition="",t?L(n,i,a):C(n,i,a)},o.prototype._applyRequirement=function(e,r){const s=v(e,r),t=this._fieldInput(e.name);if(t){if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){const n=this._findFieldWrapper(e.name);t.removeAttribute("required"),n&&(n.setAttribute("aria-required",String(s)),n.classList.toggle("fb-field-required",s));return}s?t.setAttribute("required",""):t.removeAttribute("required")}},o.prototype._applyCascade=function(e,r){const s=w(e,r);if(s===null)return;const t=this._wrapper.querySelector(h(e.name,"","select"));if(!t)return;const n=t.value;t.textContent="",s.forEach(function(i){const a=document.createElement("option");a.value=i.value,a.textContent=i.label||i.value,i.value===n&&(a.selected=!0),t.appendChild(a)})},o.prototype._applyValidation=function(e,r){const s=this._fieldInput(e.name);if(!s)return;const t=b(e,r[e.name],r);let n=s.parentNode.querySelector(".fb-validation-error");t.length?(n||(n=document.createElement("div"),n.className="fb-validation-error",s.parentNode.appendChild(n)),n.textContent=t[0].message):n&&n.remove()},o.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const s=r.closest("form")||this._wrapper;let t=r;for(;t.parentNode&&t.parentNode!==s;)t=t.parentNode;return t},o.prototype.evaluate=function(e){const r=this._getValues(),s=this;let t;if(e&&this._depMap.has(e)){const n=this._depMap.get(e);t=this._fields.filter(function(i){return n.has(i.name)})}else t=this._fields;t.forEach(function(n){n.logic&&(s._applyVisibility(n,r),s._applyRequirement(n,r),s._applyCascade(n,r))})},o.prototype.init=function(){this._buildDepMap();const e=this;this._wrapper.querySelectorAll("input, select, textarea").forEach(function(t){const n=S(t.getAttribute("name"));if(!n)return;const i=function(){e.evaluate(n)};t.addEventListener("input",i),t.addEventListener("change",i),e._listeners.push({el:t,event:"input",fn:i}),e._listeners.push({el:t,event:"change",fn:i});const a=e._fields.find(function(u){return u.name===n});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const u=function(){const d=e._getValues();e._applyValidation(a,d)};t.addEventListener("blur",u),e._listeners.push({el:t,event:"blur",fn:u})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(t){const n=t.getAttribute("data-chooser-field");if(!n)return;const i=function(){setTimeout(function(){e.evaluate(n)},0)};t.addEventListener("click",i),e._listeners.push({el:t,event:"click",fn:i})}),this._initialEval=!0,this.evaluate(),this._initialEval=!1},o.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn)}),this._listeners=[]},{evaluateCondition:y,evaluateConditionGroup:p,evaluateFieldVisibility:g,evaluateFieldRequirement:v,validateField:b,getCascadeOptions:w,FormLogicRuntime:o}});
1
+ (function(u,f){typeof module<"u"&&module.exports?module.exports=f():u.FormLogicEngine=f()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function u(e){return e===""||e===null||e===void 0?"":String(e)}function f(e){const r=parseFloat(e);return isNaN(r)?null:r}function p(e){return e==null?!0:typeof e=="string"?e.trim()==="":Array.isArray(e)?e.length===0:!1}const F={not_equals:"equals",not_contains:"contains",not_in:"in"};function m(e,r){const n=u(r),t=u(e.value);switch(e.operator){case"equals":return n===t;case"not_equals":return n!==t;case"contains":return n.toLowerCase().includes(t.toLowerCase());case"not_contains":return!n.toLowerCase().includes(t.toLowerCase());case"starts_with":return n.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return n.toLowerCase().endsWith(t.toLowerCase());case"greater_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s>i}case"less_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s<i}case"is_empty":return p(r);case"is_not_empty":return!p(r);case"in":return(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"not_in":return!(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"matches_regex":try{const s=e.flags||"";return new RegExp(e.value,s).test(n)}catch(s){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,s&&s.message),!1}default:return!0}}function y(e,r){if(!e||!e.field||!e.operator)return!0;const n=r[e.field];if(!Array.isArray(n))return m(e,n);if(e.operator==="is_empty")return p(n);if(e.operator==="is_not_empty")return!p(n);const t=F[e.operator];if(t){const s=Object.assign({},e,{operator:t});return!n.some(i=>m(s,i))}return n.some(s=>m(e,s))}function h(e,r){return e?Array.isArray(e.all)?e.all.every(n=>n.all||n.any?h(n,r):y(n,r)):Array.isArray(e.any)?e.any.some(n=>n.all||n.any?h(n,r):y(n,r)):e.field&&e.operator?y(e,r):!0:!0}function g(e,r){const n=e.logic;if(!n||!n.visibility)return"visible";const t=n.visibility,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then==="hidden"?"hidden":"visible";return t.default==="hidden"?"hidden":"visible"}function _(e,r){const n=e.logic;if(!n||!n.requirement)return e.required||!1;const t=n.requirement,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then===!0;return t.default===!0}function v(e,r,n){const t=e.logic;if(!t||!Array.isArray(t.validation))return[];const s=[];for(const i of t.validation)switch(i.type){case"regex":{if(!p(r))try{new RegExp(i.pattern||"",i.flags||"").test(u(r))||s.push({message:i.message||"Invalid format."})}catch{}break}case"match":{const a=n[i.field];!p(r)&&u(r)!==u(a)&&s.push({message:i.message||"Fields do not match."});break}}return s}function w(e,r){const n=e.logic;if(!n||!n.cascade||!n.cascade.sourceField)return null;const t=n.cascade,s=t.mapping||{},i=r[t.sourceField];if(Array.isArray(i)){const c=new Set,l=[];return i.forEach(function(T){const q=u(T);Object.prototype.hasOwnProperty.call(s,q)&&(s[q]||[]).forEach(function(b){const x=u(b&&b.value);c.has(x)||(c.add(x),l.push(b))})}),l.length?l:t.defaultOptions||null}const a=u(i);return Object.prototype.hasOwnProperty.call(s,a)?s[a]||[]:t.defaultOptions||null}const L={fade:250,slide:300,scale:200};function A(e,r){const n=Number(r);return!isFinite(n)||n<0||n>5e3?L[e]||250:Math.round(n)}function S(e,r,n){const t=A(r,n);if(r==="fade")e.style.transition="opacity "+t+"ms ease",e.style.opacity="1",requestAnimationFrame(function(){e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight="0",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",e.style.transform="scale(1)",e.style.opacity="1",requestAnimationFrame(function(){e.style.transform="scale(0.95)",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function C(e,r,n){const t=A(r,n);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+t+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight=e.scrollHeight+"px",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function o(e,r){this._form=e,this._wrapper=r,this._fields=(e.fields||[]).filter(n=>n.type!=="page-break"),this._listeners=[],this._depMap=new Map,this._initialEval=!1}function d(e,r,n){const t=n||"",s=r||"";return t+'[name="'+e+'"]'+s+", "+t+'[name="'+e+'[]"]'+s}function k(e){return String(e||"").replace(/\[\]$/,"")}o.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(d(e))},o.prototype._fieldInput=function(e){return this._wrapper.querySelector(d(e))},o.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const n=r.logic;if(!n)return;function t(s){if(!s)return;(s.all||s.any||[]).forEach(function(a){a.field?(e._depMap.has(a.field)||e._depMap.set(a.field,new Set),e._depMap.get(a.field).add(r.name)):t(a)})}if(n.visibility&&(n.visibility.conditions||[]).forEach(function(s){t(s.when)}),n.requirement&&(n.requirement.conditions||[]).forEach(function(s){t(s.when)}),n.cascade&&n.cascade.sourceField){const s=n.cascade.sourceField;e._depMap.has(s)||e._depMap.set(s,new Set),e._depMap.get(s).add(r.name)}})};function E(e,r){const n={};return(r||[]).forEach(function(t){if(!t||!t.name)return;const s=e.querySelectorAll(d(t.name));if(!s.length)return;const i=s[0];if(i.type==="radio"){const a=e.querySelector(d(t.name,":checked"));n[t.name]=a?a.value:""}else if(i.type==="checkbox")if(s.length>1||/\[\]$/.test(i.name||"")){const a=[];s.forEach(function(c){c.checked&&a.push(c.value)}),n[t.name]=a}else n[t.name]=i.checked?i.value||"true":"";else n[t.name]=i.value}),n}function M(e,r){const n=E(e,r),t=[],s=[];return(r||[]).forEach(function(i){if(!i||!i.name||g(i,n)==="hidden")return;const a=n[i.name],c=Array.isArray(a)?a.length===0:!String(a??"").trim();if(_(i,n)&&c){t.push({name:i.name,label:i.label||i.name});return}if(c)return;const l=v(i,a,n);l.length&&s.push(l[0].message)}),{valid:t.length===0&&s.length===0,missing:t,errors:s,values:n}}return o.prototype._getValues=function(){const e={};return this._fields.forEach(function(r){const n=this._fieldInputs(r.name);if(!n.length)return;const t=n[0];if(t.type==="radio"){const s=this._wrapper.querySelector(d(r.name,":checked"));e[r.name]=s?s.value:""}else if(t.type==="checkbox")if(n.length>1||/\[\]$/.test(t.name||"")){const s=[];n.forEach(function(i){i.checked&&s.push(i.value)}),e[r.name]=s}else e[r.name]=t.checked?t.value||"true":"";else e[r.name]=t.value},this),e},o.prototype._applyVisibility=function(e,r){const t=g(e,r)==="hidden",s=this._findFieldWrapper(e.name);if(!s)return;s.setAttribute("aria-hidden",String(t));const i=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(i==="none"){s.classList.toggle("fb-field-hidden",t);return}const a=e.logic?.visibility?.duration;s.style.transition="",t?S(s,i,a):C(s,i,a)},o.prototype._applyRequirement=function(e,r){const n=_(e,r),t=this._fieldInput(e.name);if(!t)return;if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){const i=this._findFieldWrapper(e.name);t.removeAttribute("required"),i&&(i.setAttribute("aria-required",String(n)),i.classList.toggle("fb-field-required",n));return}n?t.setAttribute("required",""):t.removeAttribute("required");const s=this._findFieldWrapper(e.name);s&&(s.setAttribute("aria-required",String(n)),s.classList.toggle("fb-field-required",n))},o.prototype._applyCascade=function(e,r){const n=w(e,r);if(n===null)return;const t=this._wrapper.querySelector(d(e.name,"","select"));if(!t)return;const s=t.value;t.textContent="",n.forEach(function(i){const a=document.createElement("option");a.value=i.value,a.textContent=i.label||i.value,i.value===s&&(a.selected=!0),t.appendChild(a)})},o.prototype._applyValidation=function(e,r){const n=this._fieldInput(e.name);if(!n)return;const t=v(e,r[e.name],r);let s=n.parentNode.querySelector(".fb-validation-error");t.length?(s||(s=document.createElement("div"),s.className="fb-validation-error",n.parentNode.appendChild(s)),s.textContent=t[0].message):s&&s.remove()},o.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const n=r.closest("form")||this._wrapper;let t=r;for(;t.parentNode&&t.parentNode!==n;)t=t.parentNode;return t},o.prototype.evaluate=function(e){const r=this._getValues(),n=this;let t;if(e&&this._depMap.has(e)){const s=this._depMap.get(e);t=this._fields.filter(function(i){return s.has(i.name)})}else t=this._fields;t.forEach(function(s){s.logic&&(n._applyVisibility(s,r),n._applyRequirement(s,r),n._applyCascade(s,r))})},o.prototype.init=function(){this._buildDepMap();const e=this;this._wrapper.querySelectorAll("input, select, textarea").forEach(function(t){const s=k(t.getAttribute("name"));if(!s)return;const i=function(){e.evaluate(s)};t.addEventListener("input",i),t.addEventListener("change",i),e._listeners.push({el:t,event:"input",fn:i}),e._listeners.push({el:t,event:"change",fn:i});const a=e._fields.find(function(c){return c.name===s});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const c=function(){const l=e._getValues();e._applyValidation(a,l)};t.addEventListener("blur",c),e._listeners.push({el:t,event:"blur",fn:c})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(t){const s=t.getAttribute("data-chooser-field");if(!s)return;const i=function(){setTimeout(function(){e.evaluate(s)},0)};t.addEventListener("click",i),e._listeners.push({el:t,event:"click",fn:i})}),this._initialEval=!0,this.evaluate(),this._initialEval=!1},o.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn)}),this._listeners=[]},{evaluateCondition:y,evaluateConditionGroup:h,evaluateFieldVisibility:g,evaluateFieldRequirement:_,validateField:v,collectValues:E,validateFields:M,getCascadeOptions:w,FormLogicRuntime:o}});
@@ -1 +1,2 @@
1
- const x=document.querySelectorAll("[data-form]");x.length&&x.forEach(D);function y(a,o,t){const e=a.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=t==="success"?"fb-form-success":"fb-form-error",i.textContent=o,a.appendChild(i)}function E(a,o){if(a._formLogicRuntime=o,!a.parentNode||typeof MutationObserver>"u")return;const t=new MutationObserver(function(e){for(const i of e)for(const r of i.removedNodes)if(r===a||r.nodeType===1&&r.contains&&r.contains(a)){o.destroy(),t.disconnect();return}});t.observe(a.parentNode,{childList:!0,subtree:!1})}function w(a,o){const t={};return a.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const i=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const n={type:r,label:e.label||e.name,required:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(n.minLength=e.minLength),e.maxLength!==void 0&&(n.maxLength=e.maxLength),e.min!==void 0&&(n.min=e.min),e.max!==void 0&&(n.max=e.max),i&&(e.variant&&(n.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(n.multiple=!0),e.density&&(n.density=e.density),e.columns&&(n.columns=e.columns),e.accent&&(n.accent=e.accent),e.accentStyle&&(n.accentStyle=e.accentStyle),e.glow&&(n.glow=!0),e.glowColour&&(n.glowColour=e.glowColour),e.shadow&&(n.shadow=e.shadow),e.shadowColour&&(n.shadowColour=e.shadowColour)),t[e.name]=n}),t}function j(a){const o={};return a.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function C(a,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=a.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}function N(a,o){const t=[];let e=[],i=o||"Step 1",r="";return a.forEach(function(l){l.type==="page-break"?(t.push({title:i,description:r,fieldGroup:e}),e=[],i=l.label||"Step "+(t.length+1),r=l.description||""):l.type!=="spacer"&&e.push(l)}),t.push({title:i,description:r,fieldGroup:e}),t}const k="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function L(a){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const i=document.createElement("strong");i.textContent=a;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=k+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const n=u=>{u.key==="Escape"&&s()};function s(){document.removeEventListener("keydown",n),o.remove()}return r.addEventListener("click",s),o.addEventListener("click",u=>{u.target===o&&s()}),document.addEventListener("keydown",n),document.body.appendChild(o),{body:l,close:s}}function A(a){const{body:o,close:t}=L("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(i);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(n=>{const s=document.createElement("button");s.type="button",s.title=n,s.dataset.iconName=n,s.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const u=document.createElement("span");return u.setAttribute("data-icon",n),u.setAttribute("data-icon-size","18"),s.appendChild(u),s.addEventListener("mouseenter",()=>{s.style.borderColor="var(--dm-border)"}),s.addEventListener("mouseleave",()=>{s.style.borderColor="transparent"}),s.addEventListener("click",()=>{t(),a(n)}),i.appendChild(s),s});if(!r.length){const n=document.createElement("p");n.textContent="Icon engine unavailable \u2014 type an icon name into the field instead.",i.appendChild(n)}window.I?.scan?.(i),e.addEventListener("input",()=>{const n=e.value.trim().toLowerCase();l.forEach(s=>{s.style.display=!n||s.dataset.iconName.includes(n)?"":"none"})}),e.focus()}async function R(){const a=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!a)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(a),t.status===401&&S.get("auth_refresh_token")){const i=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(i.ok){const{token:r}=await i.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function _(a){const{body:o,close:t}=L("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),R().then(({files:i,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library \u2014 or paste an image URL into the field.":"Could not load the media library \u2014 paste an image URL into the field instead.";return}if(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(n=>{const s=document.createElement("button");s.type="button",s.title=n.name||n.url,s.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const u=document.createElement("img");u.src=n.url,u.alt=n.name||"",u.loading="lazy",u.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const d=document.createElement("span");d.textContent=n.name||n.url,d.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.appendChild(u),s.appendChild(d),s.addEventListener("click",()=>{t(),a(n.url)}),l.appendChild(s)}),o.appendChild(l)})}function T(a,o){a.value=o,a.dispatchEvent(new Event("input",{bubbles:!0})),a.dispatchEvent(new Event("change",{bubbles:!0}))}function q(a){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",a.parentNode.insertBefore(o,a),o.appendChild(a),a.style.flex="1",a.style.minWidth="0",o}function F(a){const o=document.createElement("button");return o.type="button",o.textContent=a,o.style.cssText=k,o}function B(a){if(!window.I||typeof I.list!="function")return;const o=q(a),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=a.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};a.addEventListener("input",e),e();const i=F("Browse");i.addEventListener("click",()=>A(r=>{T(a,r),e()})),o.appendChild(t),o.appendChild(i)}function z(a){const o=q(a),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=a.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};a.addEventListener("input",e),e();const i=F("Browse");i.addEventListener("click",()=>_(r=>{T(a,r),e()})),o.appendChild(t),o.appendChild(i)}export function enhancePickerFields(a,o){const t=typeof a=="string"?document.querySelector(a):a;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?B(i):z(i))})}function g(a){const o=document.createElement("div");o.className="fb-form-honeypot",o.setAttribute("aria-hidden","true");const t=document.createElement("input");t.name="website",t.type="text",t.tabIndex=-1,t.autocomplete="url",t.placeholder="https://",o.appendChild(t);const e=document.createElement("input");e.name="_t",e.type="hidden",e.value=Date.now(),o.appendChild(e),a.appendChild(o)}function O(a,o){const t=a.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const n=e[i];if(n)t.insertBefore(l,n);else{const s=t.querySelector('[type="submit"]');s?t.insertBefore(l,s):t.appendChild(l)}}else r.type!=="page-break"&&i++})}function b(a,o,t,e,i){const r=i||e,l=r.querySelector('[name="website"]')?.value||"",n=r.querySelector('[name="_t"]')?.value||"",s=r?Array.from(r.querySelectorAll('input[type="file"]')):[],u=s.some(m=>m.files&&m.files.length>0);let d,c;if(u){const m=new FormData;for(const[h,p]of Object.entries(o||{}))p!=null&&(s.some(f=>f.name===h)||m.append(h,typeof p=="object"?JSON.stringify(p):String(p)));for(const h of s)for(const p of h.files)m.append(h.name,p,p.name);m.append("_hp",l),m.append("_t",n),d=m,c={}}else{const m=Object.assign({},o,{_hp:l,_t:n});d=JSON.stringify(m),c={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+a,{method:"POST",headers:c,body:d}).then(m=>m.json().then(h=>({ok:m.ok,body:h}))).then(m=>{m.ok&&m.body.ok?(e.textContent="",y(e,m.body.message||t.successMessage||"Thank you.","success")):y(e,m.body.error||"Something went wrong.","error")}).catch(()=>{y(e,"Unable to submit. Please check your connection.","error")})}function P(a,o,t,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(n){const s=document.createElement("div");s.className="form-group",s.style.marginBottom="1.25rem";const u=document.createElement("label");if(u.className="form-label",u.textContent=n.label||n.name,n.required){const c=document.createElement("span");c.textContent=" *",c.style.color="var(--dm-danger)",u.appendChild(c)}let d;n.type==="textarea"?(d=document.createElement("textarea"),d.rows=n.formConfig?.rows||4,d.className="form-input"):n.type==="select"?(d=document.createElement("select"),d.className="form-input",(n.options||[]).forEach(function(c){const m=document.createElement("option");m.value=typeof c=="string"?c:c.value??"",m.textContent=typeof c=="string"?c:c.label||m.value,d.appendChild(m)})):(d=document.createElement("input"),d.type=n.type==="icon"||n.type==="image"?"text":n.type||"text",d.className="form-input",n.placeholder&&(d.placeholder=n.placeholder),n.type==="file"&&(n.file?.accept&&(d.accept=n.file.accept),n.multiple&&(d.multiple=!0))),d.name=n.name,d.required=n.required||!1,s.appendChild(u),s.appendChild(d),r.appendChild(s)}),t.honeypot&&g(r);const l=document.createElement("button");l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",r.appendChild(l),r.addEventListener("submit",function(n){n.preventDefault();const s={};if(o.forEach(function(u){const d=r.querySelector('[name="'+u.name+'"]');d&&(s[u.name]=d.value)}),window.FormLogicEngine&&i){const u=window.FormLogicEngine,d=[],c=[];if(o.forEach(function(m){if(u.evaluateFieldVisibility(m,s)==="hidden"){delete s[m.name];return}const p=u.evaluateFieldRequirement(m,s),f=s[m.name];p&&(!f||!String(f).trim())&&d.push(m.label||m.name);const v=u.validateField(m,f||"",s);v.length&&c.push(v[0].message)}),d.length||c.length){const m=[];d.length&&m.push("Required: "+d.join(", ")),c.length&&m.push(c.join("; ")),y(a,m.join(". "),"error");return}}a.classList.add("fb-form-loading"),l.disabled=!0,b(e,s,t,a,r).finally(function(){a.classList.remove("fb-form-loading"),l.disabled=!1})}),a.appendChild(r),enhancePickerFields(a,o),window.FormLogicEngine&&i&&o.some(n=>n.logic)&&new window.FormLogicEngine.FormLogicRuntime(i,a).init()}function D(a){const o=a.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],i=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",a.appendChild(r);const l=e.some(n=>n.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const n=i.columns||1;if(l&&Domma.forms.wizard){const u=N(e,t.title).map(function(c){return{title:c.title,description:c.description,fields:w(c.fieldGroup,n)}}),d=Domma.forms.wizard(r,{schema:{steps:u},onSubmit:function(c){return b(o,c,i,r,null)}});Promise.resolve(d).then(function(){if(C(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&e.some(c=>c.logic)){const c=new window.FormLogicEngine.FormLogicRuntime(t,r);c.init(),E(r,c)}if(i.honeypot){const c=r.querySelector("form");c&&g(c)}})}else if(Domma.forms.render){const s=w(e,n),u=j(e),d=Domma.forms.render(r,s,u,{submitText:i.submitText||"Submit",layout:i.layout||"stacked",columns:n,onSubmit:function(c){return b(o,c,i,r,null)}});Promise.resolve(d).then(function(){if(C(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&e.some(c=>c.logic)){const c=new window.FormLogicEngine.FormLogicRuntime(t,r);c.init(),E(r,c)}if(e.some(c=>c.type==="spacer")&&O(r,e),i.honeypot){const c=r.querySelector("form");c&&g(c)}})}}else P(r,e.filter(n=>n.type!=="page-break"&&n.type!=="spacer"),i,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",a.appendChild(e),console.warn("[forms]",t.message)})}
1
+ const C=document.querySelectorAll("[data-form]");C.length&&C.forEach(U);function A(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let a=t;for(;a.parentNode&&a.parentNode!==e;)a=a.parentNode;return a}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const a=A(n,e.name);a&&(a.classList.add("fb-field-invalid"),t||(t=a))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+k(e.label)+"</strong> is required.").concat((n.errors||[]).map(k)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
2
+ `).replace(/<[^>]+>/g,""))}function k(n){return String(n).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function y(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const a=document.createElement("div");a.className=t==="success"?"fb-form-success":"fb-form-error",a.textContent=o,n.appendChild(a)}function L(n,o){if(n._formLogicRuntime=o,!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const a of e)for(const r of a.removedNodes)if(r===n||r.nodeType===1&&r.contains&&r.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1})}function z(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function T(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const a=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":a?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const i={type:r,label:e.label||e.name,required:z(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(i.minLength=e.minLength),e.maxLength!==void 0&&(i.maxLength=e.maxLength),e.min!==void 0&&(i.min=e.min),e.max!==void 0&&(i.max=e.max),a&&(e.variant&&(i.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(i.multiple=!0),e.density&&(i.density=e.density),e.columns&&(i.columns=e.columns),e.accent&&(i.accent=e.accent),e.accentStyle&&(i.accentStyle=e.accentStyle),e.glow&&(i.glow=!0),e.glowColour&&(i.glowColour=e.glowColour),e.shadow&&(i.shadow=e.shadow),e.shadowColour&&(i.shadowColour=e.shadowColour)),t[e.name]=i}),t}function P(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function q(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}function B(n,o){const t=[];let e=[],a=o||"Step 1",r="";return n.forEach(function(l){l.type==="page-break"?(t.push({title:a,description:r,fieldGroup:e}),e=[],a=l.label||"Step "+(t.length+1),r=l.description||""):l.type!=="spacer"&&e.push(l)}),t.push({title:a,description:r,fieldGroup:e}),t}const F="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function j(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const a=document.createElement("strong");a.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=F+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(a),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const i=m=>{m.key==="Escape"&&s()};function s(){document.removeEventListener("keydown",i),o.remove()}return r.addEventListener("click",s),o.addEventListener("click",m=>{m.target===o&&s()}),document.addEventListener("keydown",i),document.body.appendChild(o),{body:l,close:s}}function O(n){const{body:o,close:t}=j("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const a=document.createElement("div");a.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(a);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(i=>{const s=document.createElement("button");s.type="button",s.title=i,s.dataset.iconName=i,s.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const m=document.createElement("span");return m.setAttribute("data-icon",i),m.setAttribute("data-icon-size","18"),s.appendChild(m),s.addEventListener("mouseenter",()=>{s.style.borderColor="var(--dm-border)"}),s.addEventListener("mouseleave",()=>{s.style.borderColor="transparent"}),s.addEventListener("click",()=>{t(),n(i)}),a.appendChild(s),s});if(!r.length){const i=document.createElement("p");i.textContent="Icon engine unavailable - type an icon name into the field instead.",a.appendChild(i)}window.I?.scan?.(a),e.addEventListener("input",()=>{const i=e.value.trim().toLowerCase();l.forEach(s=>{s.style.display=!i||s.dataset.iconName.includes(i)?"":"none"})}),e.focus()}async function D(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=a=>fetch("/api/media",{headers:{Authorization:"Bearer "+a}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const a=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(a.ok){const{token:r}=await a.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(a=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(a.name||a.url||""))}}function M(n){const{body:o,close:t}=j("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),D().then(({files:a,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!a.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",a.forEach(i=>{const s=document.createElement("button");s.type="button",s.title=i.name||i.url,s.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const m=document.createElement("img");m.src=i.url,m.alt=i.name||"",m.loading="lazy",m.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const d=document.createElement("span");d.textContent=i.name||i.url,d.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.appendChild(m),s.appendChild(d),s.addEventListener("click",()=>{t(),n(i.url)}),l.appendChild(s)}),o.appendChild(l)})}function N(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function _(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function R(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=F,o}function V(n){if(!window.I||typeof I.list!="function")return;const o=_(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=n.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};n.addEventListener("input",e),e();const a=R("Browse");a.addEventListener("click",()=>O(r=>{N(n,r),e()})),o.appendChild(t),o.appendChild(a)}function G(n){const o=_(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=n.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};n.addEventListener("input",e),e();const a=R("Browse");a.addEventListener("click",()=>M(r=>{N(n,r),e()})),o.appendChild(t),o.appendChild(a)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const a=t.querySelector('[name="'+e.name+'"]');!a||a.dataset.pickerEnhanced||(a.dataset.pickerEnhanced="1",e.type==="icon"?V(a):G(a))})}function x(n){const o=document.createElement("div");o.className="fb-form-honeypot",o.setAttribute("aria-hidden","true");const t=document.createElement("input");t.name="website",t.type="text",t.tabIndex=-1,t.autocomplete="url",t.placeholder="https://",o.appendChild(t);const e=document.createElement("input");e.name="_t",e.type="hidden",e.value=Date.now(),o.appendChild(e),n.appendChild(o)}function W(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let a=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const i=e[a];if(i)t.insertBefore(l,i);else{const s=t.querySelector('[type="submit"]');s?t.insertBefore(l,s):t.appendChild(l)}}else r.type!=="page-break"&&a++})}function w(n,o,t,e,a){const r=a||e,l=r.querySelector('[name="website"]')?.value||"",i=r.querySelector('[name="_t"]')?.value||"",s=r?Array.from(r.querySelectorAll('input[type="file"]')):[],m=s.some(c=>c.files&&c.files.length>0);let d,u;if(m){const c=new FormData;for(const[h,f]of Object.entries(o||{}))f!=null&&(s.some(g=>g.name===h)||c.append(h,typeof f=="object"?JSON.stringify(f):String(f)));for(const h of s)for(const f of h.files)c.append(h.name,f,f.name);c.append("_hp",l),c.append("_t",i),d=c,u={}}else{const c=Object.assign({},o,{_hp:l,_t:i});d=JSON.stringify(c),u={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:u,body:d}).then(c=>c.json().then(h=>({ok:c.ok,body:h}))).then(c=>{c.ok&&c.body.ok?(e.textContent="",y(e,c.body.message||t.successMessage||"Thank you.","success")):y(e,c.body.error||"Something went wrong.","error")}).catch(()=>{y(e,"Unable to submit. Please check your connection.","error")})}function J(n,o,t,e,a){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(i){const s=document.createElement("div");s.className="form-group",s.style.marginBottom="1.25rem";const m=document.createElement("label");if(m.className="form-label",m.textContent=i.label||i.name,i.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;i.type==="textarea"?(d=document.createElement("textarea"),d.rows=i.formConfig?.rows||4,d.className="form-input"):i.type==="select"?(d=document.createElement("select"),d.className="form-input",(i.options||[]).forEach(function(u){const c=document.createElement("option");c.value=typeof u=="string"?u:u.value??"",c.textContent=typeof u=="string"?u:u.label||c.value,d.appendChild(c)})):(d=document.createElement("input"),d.type=i.type==="icon"||i.type==="image"?"text":i.type||"text",d.className="form-input",i.placeholder&&(d.placeholder=i.placeholder),i.type==="file"&&(i.file?.accept&&(d.accept=i.file.accept),i.multiple&&(d.multiple=!0))),d.name=i.name,d.required=i.required||!1,s.appendChild(m),s.appendChild(d),r.appendChild(s)}),t.honeypot&&x(r);const l=document.createElement("button");l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",r.appendChild(l),r.addEventListener("submit",function(i){i.preventDefault();const s={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(s[m.name]=d.value)}),window.FormLogicEngine&&a){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(c){if(m.evaluateFieldVisibility(c,s)==="hidden"){delete s[c.name];return}const f=m.evaluateFieldRequirement(c,s),g=s[c.name];f&&(!g||!String(g).trim())&&d.push(c.label||c.name);const p=m.validateField(c,g||"",s);p.length&&u.push(p[0].message)}),d.length||u.length){const c=[];d.length&&c.push("Required: "+d.join(", ")),u.length&&c.push(u.join("; ")),y(n,c.join(". "),"error");return}}n.classList.add("fb-form-loading"),l.disabled=!0,w(e,s,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),enhancePickerFields(n,o),window.FormLogicEngine&&a&&o.some(i=>i.logic)&&new window.FormLogicEngine.FormLogicRuntime(a,n).init()}function U(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],a=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(i=>i.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const i=a.columns||1;if(l&&Domma.forms.wizard){const s=B(e,t.title),m=s.map(p=>p.fieldGroup),d=s.map(function(p){return{title:p.title,description:p.description,fields:T(p.fieldGroup,i)}});let u=0,c=null;const h=function(p){const b=window.FormLogicEngine;if(!b||!b.validateFields)return;const v=b.validateFields(r,m[u]||[]);v.valid||(p.preventDefault(),p.stopImmediatePropagation(),markInvalidFields(r,v.missing),showValidationPopup(v))},f=function(){if(q(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&e.some(p=>p.logic)&&(c&&c.destroy(),c=new window.FormLogicEngine.FormLogicRuntime(t,r),c.init(),L(r,c)),a.honeypot){const p=r.querySelector("form");p&&x(p)}r.querySelectorAll(".wizard-next, .wizard-submit").forEach(p=>p.addEventListener("click",h,!0))},g=Domma.forms.wizard(r,{schema:{steps:d},onSubmit:function(p){return w(o,p,a,r,null)},onStepChange:function(p){u=p,setTimeout(f,0)}});Promise.resolve(g).then(f)}else if(Domma.forms.render){const s=T(e,i),m=P(e),d=Domma.forms.render(r,s,m,{submitText:a.submitText||"Submit",layout:a.layout||"stacked",columns:i,onSubmit:function(u){return w(o,u,a,r,null)}});Promise.resolve(d).then(function(){if(q(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&e.some(u=>u.logic)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),L(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),a.honeypot){const u=r.querySelector("form");u&&x(u)}})}}else J(r,e.filter(i=>i.type!=="page-break"&&i.type!=="spacer"),a,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
package/public/js/site.js CHANGED
@@ -1 +1 @@
1
- import{makeBadgeEl as _,applyColour as A,applyPill as I,applyFloat as M}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as D}from"/public/js/forms.js?v=20260817-multi-chooser";$(()=>{const b=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let n=function(e){const d=(e||"07:00").split(":");return+d[0]*60+(+d[1]||0)},a=function(){const e=new Date,d=e.getHours()*60+e.getMinutes();return d>=n(t.dayStart)&&d<n(t.nightStart)?t.dayTheme:t.nightTheme};const t=g.autoTheme;Domma.theme.set(a()),setInterval(()=>Domma.theme.set(a()),6e4)}const v=$("#site-navbar");if(v.length&&b.brand){let a=function(s,r=0){return Array.isArray(s)?s.filter(c=>!(c&&c.type==="separator"&&r===0)).map(c=>c&&c.type==="separator"?{divider:!0}:Array.isArray(c?.items)?{...c,items:a(c.items,r+1)}:c):s},e=function(s){return Array.isArray(s)?s.filter(r=>!(r&&r.type==="separator")):[]};const t={...b.brand},n=t.size&&t.size!=="md"?` navbar-brand-${t.size}`:"";if(t.logo||t.icon||t.tagline){let s="";t.logo?s+=`<img src="${t.logo}" class="navbar-brand-logo" alt="${t.text||""}">`:t.icon&&(s+=`<span data-icon="${t.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),t.text&&(s+=`<span class="navbar-brand-text${n}">${t.text}</span>`),t.tagline&&(s+=`<small class="navbar-brand-tagline">${t.tagline}</small>`),t.html=s}else n&&t.text&&(t.html=`<span class="navbar-brand-text${n}">${t.text}</span>`);const d=b.position==="floating";b.orientation==="vertical"&&v.get(0).classList.add("dm-nav-vertical",b.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),Domma.elements.navbar("#site-navbar",{brand:t,items:a(b.items||[]),variant:b.variant||"dark",position:d?"static":b.position||"sticky",collapsible:!0}),Domma.icons.scan("#site-navbar"),d&&M(v.get(0),b);const h=v.get(0);if(b.appearOnHover){const s=window.matchMedia("(min-width: 993px)");h.querySelectorAll(".navbar-dropdown").forEach(r=>{r.addEventListener("mouseenter",()=>{s.matches&&r.classList.add("open")}),r.addEventListener("mouseleave",()=>{s.matches&&r.classList.remove("open")})})}const m=h.querySelector(".navbar-toggle"),y=h.querySelector(".navbar-collapse");if(m&&y){let s=null;const r=()=>{y.classList.contains("show")&&m.click()},c=()=>{s&&(s.remove(),s=null),document.body.classList.remove("dm-drawer-open")},o=()=>{s||(s=document.createElement("div"),s.className="dm-navbar-backdrop",s.addEventListener("click",r),document.body.appendChild(s),document.body.classList.add("dm-drawer-open"))};m.addEventListener("click",()=>{requestAnimationFrame(()=>{y.classList.contains("show")?o():c()})}),y.addEventListener("click",i=>{i.target.closest("a")&&requestAnimationFrame(c)}),document.addEventListener("keydown",i=>{i.key==="Escape"&&y.classList.contains("show")&&r()})}const l=e(b.items||[]);h.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(s=>{const r=l[parseInt(s.dataset.index,10)];if(!r)return;const c=s.dataset.subindex!=null,o=c&&Array.isArray(r.items)?r.items[parseInt(s.dataset.subindex,10)]:r;if(!o)return;o.colour&&A(s,o.colour),o.pill&&!c&&I(s,o.pill);const i=_(o.badge);i&&s.appendChild(i)})}const w=$("#site-footer");if(w.length){let d=function(o){return String(o??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},p=function(o){return d(o).replace(/'/g,"&#39;")},h=function(o){if(o&&o.type==="separator")return'<li class="footer-sep"><hr></li>';const i=p(o.url||"#"),f=d(o.text||""),k=Array.isArray(o.items)&&o.items.length?`<ul>${o.items.map(h).join("")}</ul>`:"";return`<li><a href="${i}">${f}</a>${k}</li>`},m=function(o,i){return(o||[]).forEach(f=>{f&&f.type==="separator"||(i.push(f),Array.isArray(f.items)&&f.items.length&&m(f.items,i))}),i};const t=g.social||{},n={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let a='<div class="footer-inner container">';const e=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(e.copyright&&(a+=`<p>${d(e.copyright)}</p>`),e.primary.length&&(a+=`<nav class="footer-nav footer-nav--primary"><ul>${e.primary.map(h).join("")}</ul></nav>`),e.legal.length&&(a+=`<nav class="footer-nav footer-nav--legal"><ul>${e.legal.map(h).join("")}</ul></nav>`),g.footer){const o=Object.keys(n).filter(i=>t[i]);o.length&&(a+='<div class="footer-social">',o.forEach(i=>{const{label:f,svg:k}=n[i];a+=`<a href="${t[i]}" target="_blank" rel="noopener noreferrer" aria-label="${f}" class="footer-social-link">${k}</a>`}),a+="</div>")}a+="</div>",w.html(a);const y=[...m(e.primary,[]),...m(e.legal,[])];w.get(0).querySelectorAll(".footer-nav a").forEach((o,i)=>{const f=y[i];if(!f)return;f.colour&&A(o,f.colour);const k=_(f.badge);k&&o.appendChild(k)});const s=S.get("reduced_motion"),r=s!==null?!!s:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),c=w.get(0).querySelector(".footer-inner");if(c){const o=document.createElement("input");o.type="checkbox",o.className="form-switch-input",o.id="dm-motion-switch",o.checked=r,o.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const i=document.createElement("span");i.className="form-switch-label",i.textContent="Reduce motion";const f=document.createElement("label");f.className="form-switch footer-motion-switch",f.title="Reduce motion",f.appendChild(o),f.appendChild(i),c.appendChild(f)}}$("#site-sidebar").length&&Domma.elements.sidebar("#site-sidebar",{autoGenerate:!0,selector:"h2, h3",collapsible:!1,push:!0,contentSelector:".site-content"}),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const u=$(".page-body");if(u.length){u.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),u.find(".tabs").each(function(){Domma.elements.tabs(this)}),u.find(".carousel").each(function(){const t={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const n=parseInt(this.dataset.animationDuration,10);Number.isFinite(n)&&(t.animationDuration=n)}this.dataset.animationEasing&&(t.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(n=>n.cloneNode(!0)),this._dmCarouselOpts=t),this._dmCarousel=Domma.elements.carousel(this,t)}),u.find(".dm-countdown").each(function(){const t={autoStart:!0};this.dataset.to&&(t.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(t.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(t.format=this.dataset.format),Domma.elements.timer(this,t)}),u.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),u.find(".dm-progression").each(function(){const t=Array.from(this.querySelectorAll(".dm-progression-item")).map(e=>{const d={title:e.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:e.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return e.dataset.date&&(d.date=e.dataset.date),e.dataset.status&&(d.status=e.dataset.status),e.dataset.entryId&&(d._entryId=e.dataset.entryId),d}),n=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",a=Domma.elements.progression(this,{layout:n,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...t.length?{items:t}:{}});t.length&&(this._dmCtx={instance:a,items:t})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(t=>{const n=t.dataset.revealMode||"stagger",a=t.dataset.revealAnimation||"slide-up",e=parseInt(t.dataset.revealDuration,10)||400,d=parseInt(t.dataset.revealStagger,10)||60,p=parseInt(t.dataset.revealDelay,10)||0,h=t.dataset.revealDirection==="rtl",m=Array.from(t.children),y={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};m.forEach((l,s)=>{l.style.opacity="0",l.style.transform=y[a]||"",l.style.transition=`opacity ${e}ms ease, transform ${e}ms ease`;const r=h?m.length-1-s:s;l.style.transitionDelay=n==="stagger"?`${p+r*d}ms`:`${p}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const l=new IntersectionObserver(s=>{s.forEach(r=>{r.isIntersecting&&(r.target.offsetWidth,r.target.style.opacity="1",r.target.style.transform="none",l.unobserve(r.target))})},{threshold:.1});m.forEach(s=>l.observe(s))}))}),u.find(".card[data-collapsible]").each(function(){const t=this.querySelector(".card-header");t&&t.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),u.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const t=this.dataset.soTarget,n=document.getElementById(t);if(!n)return;const a=E.slideover({title:n.dataset.soTitle||"",size:n.dataset.soSize||"md",position:n.dataset.soPosition||"right"});n.style.display="",a.setContent(n),a.open()})})}if(typeof $.setup=="function"){const t=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(n=>{try{const a=atob(n.dataset.config),e=JSON.parse(a);Object.assign(t,e)}catch{}}),Object.keys(t).length>0){const n={};for(const[a,e]of Object.entries(t)){const d=e?.events?.click,{confirm:p,toast:h,alert:m,prompt:y,...l}=d||{};p||h||m||y?($(a).on("click",async function(r){if(r.preventDefault(),p&&!await E.confirm(p))return;let c=null;if(!(y&&(c=await E.prompt(y,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),c===null))){if(l.target){const o=$(l.target);l.toggleClass&&o.toggleClass(l.toggleClass),l.addClass&&o.addClass(l.addClass),l.removeClass&&o.removeClass(l.removeClass),c!==null&&(l.setText&&o.text(c),l.setVal&&o.val(c),l.setAttr&&o.attr(l.setAttr,c))}l.href&&(window.location.href=l.href),h&&E.toast(h,{type:l.toastType||"success"}),m&&E.alert(m)}}),Object.keys(l).length&&(n[a]={...e,events:{...e.events,click:l}})):n[a]=e}$.setup(n)}}u.length&&x(u.get(0))});function x(b){b.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const v=g.dataset.action,w=g.dataset.entry,C=g.dataset.confirm;let u=S.get("auth_token");if(!u){E.toast("Please log in to perform this action.",{type:"warning"});return}if(C&&!await E.confirm(C))return;const t=Array.from(g.childNodes).map(a=>a.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const n=a=>fetch(`/api/actions/${v}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({entryId:w})});try{let a=await n(u);if(a.status===401){const d=S.get("auth_refresh_token");if(d){const p=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(p.ok){const{token:h}=await p.json();S.set("auth_token",h),u=h,a=await n(u)}}}const e=await a.json().catch(()=>({}));if(!a.ok)throw new Error(e.error||e.message||`Error ${a.status}`);E.toast(e.message||"Action completed.",{type:"success"})}catch(a){E.toast(a.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",t.forEach(a=>g.appendChild(a)),Domma.icons.scan(g)}}))})}(function(){const g=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!g.length)return;const v=S.get("auth_token");function w(u,t){const n=document.createElement("div");n.className="dm-collection-display dm-collection-empty";const a=document.createElement("p");if(t){a.appendChild(document.createTextNode("Please "));const e=document.createElement("a");e.href="/login",e.textContent="sign in",a.appendChild(e),a.appendChild(document.createTextNode(" to view your entries."))}else a.textContent=u;return n.appendChild(a),n}function C(u,t){const n=document.createElement("template");n.innerHTML=t||"",u.replaceWith(n.content)}g.forEach(async u=>{const t=u.dataset.collectionAttrs;if(!t)return;if(!v){u.replaceChildren(w("",!0));return}const n=a=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({attrs:t})});try{let a=v,e=await n(a);if(e.status===401){const p=S.get("auth_refresh_token");if(p){const h=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:p})});if(h.ok){const{token:m}=await h.json();S.set("auth_token",m),a=m,e=await n(a)}}}if(!e.ok){const{error:p}=await e.json().catch(()=>({}));u.replaceChildren(w(p||"Unable to load entries.",!1));return}const{html:d}=await e.json();C(u,d)}catch{u.replaceChildren(w("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),x(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(v=>{let w;try{w=JSON.parse(atob(v.dataset.payload))}catch{return}const{columns:C,rows:u,search:t,sortable:n,exportable:a,pageSize:e,empty:d,ctaConfig:p,slug:h,exportCfg:m}=w;if(!C?.length)return;if(p){const s=C.findIndex(r=>r.key==="_cta");s!==-1&&(C[s]={key:"_cta",title:"",render:(r,c)=>{const o=document.createElement("button");if(o.className=`btn btn-${p.style||"primary"} dm-cta-trigger`,o.dataset.action=p.action||"",o.dataset.entry=c._entryId||"",p.confirm&&(o.dataset.confirm=p.confirm),p.icon){const i=document.createElement("span");i.dataset.icon=p.icon,o.appendChild(i),o.appendChild(document.createTextNode(" "))}return o.appendChild(document.createTextNode(p.label||"Run")),o}})}const y="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=y,v.replaceChildren(l),T.create("#"+y,{data:u,columns:C,search:t,sortable:n,exportable:a,pageSize:e,emptyMessage:d}),p&&x(l),v._dmTable={columns:C,rows:u,slug:h,exportCfg:m,render(s){T.create("#"+y,{data:s,columns:C,search:t,sortable:n,exportable:a,pageSize:e,emptyMessage:d}),p&&x(l)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function v(t,n){const a={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const d=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),p=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":d?"chooser":e.type,h={...e.formConfig||{}};h.span==="full"&&n&&(h.span=n);const m={type:p,label:e.label,required:e.required,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...h}};d&&(e.variant&&(m.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(m.multiple=!0),e.density&&(m.density=e.density),e.columns&&(m.columns=e.columns),e.accent&&(m.accent=e.accent),e.accentStyle&&(m.accentStyle=e.accentStyle),e.glow&&(m.glow=!0),e.glowColour&&(m.glowColour=e.glowColour),e.shadow&&(m.shadow=e.shadow),e.shadowColour&&(m.shadowColour=e.shadowColour)),a[e.name]=m}),a}function w(t){const n={};return(t||[]).forEach(a=>{if(!(!a.name||a.type==="page-break"||a.type==="spacer")&&(a.type==="select"||a.type==="multiselect")&&a.required){const e=(a.options||[])[0];e&&(n[a.name]=typeof e=="object"?e.value:e)}}),n}function C(t,n){(n||[]).forEach(a=>{if(a.type!=="date"||!a.name)return;const e=t.querySelector(`[name="${a.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function u(t,n,a){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=n,e.style.cssText=a?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(t=>{let n;try{n=JSON.parse(atob(t.dataset.formInline))}catch{return}const a=n.fields||[],e=n.settings||{},d=e.columns||1,p=e.layout||"stacked",h=a.some(s=>s.type==="page-break"),m=async s=>{try{const r=t.querySelector('[name="website"]'),c=t.querySelector('[name="_t"]'),o=Object.assign({},s);r!==null&&(o._hp=r.value),c!==null&&(o._t=c.value);const i=await H.post(`/api/forms/submit/${n.slug}`,o);if(i&&i.error){u(t,i.error,!0);const f=new Error(i.error);throw f.formSubmitFailed=!0,f}if(i?.redirect){window.location.href=i.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);u(t,i?.message||e.successMessage||"Thank you for your submission.",!1)}catch(r){throw r.formSubmitFailed||u(t,r.message||"Submission failed. Please try again.",!0),r}};function y(s){const r=s.querySelector("form");if(!r)return;const c=document.createElement("div");c.className="fb-form-honeypot",c.setAttribute("aria-hidden","true");const o=document.createElement("input");o.name="website",o.type="text",o.tabIndex=-1,o.autocomplete="url",o.placeholder="https://",c.appendChild(o);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=Date.now(),c.appendChild(i),r.appendChild(c)}function l(){if(!window.FormLogicEngine||!a.some(r=>r.logic))return;const s=new window.FormLogicEngine.FormLogicRuntime(n,t);if(s.init(),t._formLogicRuntime=s,t.parentNode&&typeof MutationObserver<"u"){const r=new MutationObserver(function(c){for(const o of c)for(const i of o.removedNodes)if(i===t||i.nodeType===1&&i.contains&&i.contains(t)){s.destroy(),r.disconnect();return}});r.observe(t.parentNode,{childList:!0,subtree:!1})}}if(h&&F.wizard){const s=[];let r=[],c=n.title||"Step 1",o="";a.forEach(f=>{f.type==="page-break"?(s.push({title:c,description:o,fields:v(r,d)}),r=[],c=f.label||`Step ${s.length+1}`,o=f.description||""):f.type!=="spacer"&&r.push(f)}),s.push({title:c,description:o,fields:v(r,d)});const i=F.wizard(t,{schema:{steps:s},onSubmit:m});Promise.resolve(i).then(function(){C(t,a),D(t,a),e.honeypot!==!1&&y(t),l()})}else if(F.render){const s=F.render(t,v(a,d),w(a),{submitText:e.submitText||"Submit",layout:p,columns:d,onSubmit:m});Promise.resolve(s).then(function(){if(p==="grid"&&e.submitSpan==="full"){const r=t.querySelector(".form-buttons");r&&r.classList.add("col-span-full")}C(t,a),D(t,a),e.honeypot!==!1&&y(t),l()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
1
+ import{makeBadgeEl as M,applyColour as O,applyPill as R,applyFloat as P}from"/public/js/menu-decor.mjs?v=20260817-menu-bindings";import{enhancePickerFields as z,markInvalidFields as B,showValidationPopup as V}from"/public/js/forms.js?v=20260821-wizard-steps";$(()=>{const v=window.__CMS_NAV__||{},h=window.__CMS_SITE__||{};if(h.autoTheme?.enabled){let t=function(a){const e=(a||"07:00").split(":");return+e[0]*60+(+e[1]||0)},o=function(){const a=new Date,e=a.getHours()*60+a.getMinutes();return e>=t(n.dayStart)&&e<t(n.nightStart)?n.dayTheme:n.nightTheme};const n=h.autoTheme;Domma.theme.set(o()),setInterval(()=>Domma.theme.set(o()),6e4)}const w=$("#site-navbar");if(w.length&&v.brand){let o=function(r,i=0){return Array.isArray(r)?r.filter(c=>!(c&&c.type==="separator"&&i===0)).map(c=>c&&c.type==="separator"?{divider:!0}:Array.isArray(c?.items)?{...c,items:o(c.items,i+1)}:c):r},a=function(r){return Array.isArray(r)?r.filter(i=>!(i&&i.type==="separator")):[]};const n={...v.brand},t=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let r="";n.logo?r+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(r+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(r+=`<span class="navbar-brand-text${t}">${n.text}</span>`),n.tagline&&(r+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=r}else t&&n.text&&(n.html=`<span class="navbar-brand-text${t}">${n.text}</span>`);const e=v.position==="floating";v.orientation==="vertical"&&w.get(0).classList.add("dm-nav-vertical",v.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),Domma.elements.navbar("#site-navbar",{brand:n,items:o(v.items||[]),variant:v.variant||"dark",position:e?"static":v.position||"sticky",collapsible:!0}),Domma.icons.scan("#site-navbar"),e&&P(w.get(0),v);const g=w.get(0);if(v.appearOnHover){const r=window.matchMedia("(min-width: 993px)");g.querySelectorAll(".navbar-dropdown").forEach(i=>{i.addEventListener("mouseenter",()=>{r.matches&&i.classList.add("open")}),i.addEventListener("mouseleave",()=>{r.matches&&i.classList.remove("open")})})}const y=g.querySelector(".navbar-toggle"),f=g.querySelector(".navbar-collapse");if(y&&f){let r=null;const i=()=>{f.classList.contains("show")&&y.click()},c=()=>{r&&(r.remove(),r=null),document.body.classList.remove("dm-drawer-open")},s=()=>{r||(r=document.createElement("div"),r.className="dm-navbar-backdrop",r.addEventListener("click",i),document.body.appendChild(r),document.body.classList.add("dm-drawer-open"))};y.addEventListener("click",()=>{requestAnimationFrame(()=>{f.classList.contains("show")?s():c()})}),f.addEventListener("click",l=>{l.target.closest("a")&&requestAnimationFrame(c)}),document.addEventListener("keydown",l=>{l.key==="Escape"&&f.classList.contains("show")&&i()})}const m=a(v.items||[]);g.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(r=>{const i=m[parseInt(r.dataset.index,10)];if(!i)return;const c=r.dataset.subindex!=null,s=c&&Array.isArray(i.items)?i.items[parseInt(r.dataset.subindex,10)]:i;if(!s)return;s.colour&&O(r,s.colour),s.pill&&!c&&R(r,s.pill);const l=M(s.badge);l&&r.appendChild(l)})}const b=$("#site-footer");if(b.length){let e=function(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},u=function(s){return e(s).replace(/'/g,"&#39;")},g=function(s){if(s&&s.type==="separator")return'<li class="footer-sep"><hr></li>';const l=u(s.url||"#"),d=e(s.text||""),k=Array.isArray(s.items)&&s.items.length?`<ul>${s.items.map(g).join("")}</ul>`:"";return`<li><a href="${l}">${d}</a>${k}</li>`},y=function(s,l){return(s||[]).forEach(d=>{d&&d.type==="separator"||(l.push(d),Array.isArray(d.items)&&d.items.length&&y(d.items,l))}),l};const n=h.social||{},t={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let o='<div class="footer-inner container">';const a=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(a.copyright&&(o+=`<p>${e(a.copyright)}</p>`),a.primary.length&&(o+=`<nav class="footer-nav footer-nav--primary"><ul>${a.primary.map(g).join("")}</ul></nav>`),a.legal.length&&(o+=`<nav class="footer-nav footer-nav--legal"><ul>${a.legal.map(g).join("")}</ul></nav>`),h.footer){const s=Object.keys(t).filter(l=>n[l]);s.length&&(o+='<div class="footer-social">',s.forEach(l=>{const{label:d,svg:k}=t[l];o+=`<a href="${n[l]}" target="_blank" rel="noopener noreferrer" aria-label="${d}" class="footer-social-link">${k}</a>`}),o+="</div>")}o+="</div>",b.html(o);const f=[...y(a.primary,[]),...y(a.legal,[])];b.get(0).querySelectorAll(".footer-nav a").forEach((s,l)=>{const d=f[l];if(!d)return;d.colour&&O(s,d.colour);const k=M(d.badge);k&&s.appendChild(k)});const r=S.get("reduced_motion"),i=r!==null?!!r:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),c=b.get(0).querySelector(".footer-inner");if(c){const s=document.createElement("input");s.type="checkbox",s.className="form-switch-input",s.id="dm-motion-switch",s.checked=i,s.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const l=document.createElement("span");l.className="form-switch-label",l.textContent="Reduce motion";const d=document.createElement("label");d.className="form-switch footer-motion-switch",d.title="Reduce motion",d.appendChild(s),d.appendChild(l),c.appendChild(d)}}$("#site-sidebar").length&&Domma.elements.sidebar("#site-sidebar",{autoGenerate:!0,selector:"h2, h3",collapsible:!1,push:!0,contentSelector:".site-content"}),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const p=$(".page-body");if(p.length){p.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),p.find(".tabs").each(function(){Domma.elements.tabs(this)}),p.find(".carousel").each(function(){const n={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const t=parseInt(this.dataset.animationDuration,10);Number.isFinite(t)&&(n.animationDuration=t)}this.dataset.animationEasing&&(n.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(t=>t.cloneNode(!0)),this._dmCarouselOpts=n),this._dmCarousel=Domma.elements.carousel(this,n)}),p.find(".dm-countdown").each(function(){const n={autoStart:!0};this.dataset.to&&(n.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(n.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(n.format=this.dataset.format),Domma.elements.timer(this,n)}),p.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),p.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(a=>{const e={title:a.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:a.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return a.dataset.date&&(e.date=a.dataset.date),a.dataset.status&&(e.status=a.dataset.status),a.dataset.entryId&&(e._entryId=a.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",o=Domma.elements.progression(this,{layout:t,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});n.length&&(this._dmCtx={instance:o,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const t=n.dataset.revealMode||"stagger",o=n.dataset.revealAnimation||"slide-up",a=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,u=parseInt(n.dataset.revealDelay,10)||0,g=n.dataset.revealDirection==="rtl",y=Array.from(n.children),f={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};y.forEach((m,r)=>{m.style.opacity="0",m.style.transform=f[o]||"",m.style.transition=`opacity ${a}ms ease, transform ${a}ms ease`;const i=g?y.length-1-r:r;m.style.transitionDelay=t==="stagger"?`${u+i*e}ms`:`${u}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(r=>{r.forEach(i=>{i.isIntersecting&&(i.target.offsetWidth,i.target.style.opacity="1",i.target.style.transform="none",m.unobserve(i.target))})},{threshold:.1});y.forEach(r=>m.observe(r))}))}),p.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),p.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,t=document.getElementById(n);if(!t)return;const o=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",o.setContent(t),o.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const o=atob(t.dataset.config),a=JSON.parse(o);Object.assign(n,a)}catch{}}),Object.keys(n).length>0){const t={};for(const[o,a]of Object.entries(n)){const e=a?.events?.click,{confirm:u,toast:g,alert:y,prompt:f,...m}=e||{};u||g||y||f?($(o).on("click",async function(i){if(i.preventDefault(),u&&!await E.confirm(u))return;let c=null;if(!(f&&(c=await E.prompt(f,{inputPlaceholder:m.promptPlaceholder||"",inputValue:m.promptDefault||""}),c===null))){if(m.target){const s=$(m.target);m.toggleClass&&s.toggleClass(m.toggleClass),m.addClass&&s.addClass(m.addClass),m.removeClass&&s.removeClass(m.removeClass),c!==null&&(m.setText&&s.text(c),m.setVal&&s.val(c),m.setAttr&&s.attr(m.setAttr,c))}m.href&&(window.location.href=m.href),g&&E.toast(g,{type:m.toastType||"success"}),y&&E.alert(y)}}),Object.keys(m).length&&(t[o]={...a,events:{...a.events,click:m}})):t[o]=a}$.setup(t)}}p.length&&_(p.get(0))});function _(v){v.querySelectorAll(".dm-cta-trigger").forEach(h=>{h.__ctaWired||(h.__ctaWired=!0,h.addEventListener("click",async()=>{const w=h.dataset.action,b=h.dataset.entry,C=h.dataset.confirm;let p=S.get("auth_token");if(!p){E.toast("Please log in to perform this action.",{type:"warning"});return}if(C&&!await E.confirm(C))return;const n=Array.from(h.childNodes).map(o=>o.cloneNode(!0));h.disabled=!0,h.textContent="Running\u2026";const t=o=>fetch(`/api/actions/${w}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({entryId:b})});try{let o=await t(p);if(o.status===401){const e=S.get("auth_refresh_token");if(e){const u=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(u.ok){const{token:g}=await u.json();S.set("auth_token",g),p=g,o=await t(p)}}}const a=await o.json().catch(()=>({}));if(!o.ok)throw new Error(a.error||a.message||`Error ${o.status}`);E.toast(a.message||"Action completed.",{type:"success"})}catch(o){E.toast(o.message||"Action failed.",{type:"error"})}finally{h.disabled=!1,h.textContent="",n.forEach(o=>h.appendChild(o)),Domma.icons.scan(h)}}))})}(function(){const h=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!h.length)return;const w=S.get("auth_token");function b(p,n){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const o=document.createElement("p");if(n){o.appendChild(document.createTextNode("Please "));const a=document.createElement("a");a.href="/login",a.textContent="sign in",o.appendChild(a),o.appendChild(document.createTextNode(" to view your entries."))}else o.textContent=p;return t.appendChild(o),t}function C(p,n){const t=document.createElement("template");t.innerHTML=n||"",p.replaceWith(t.content)}h.forEach(async p=>{const n=p.dataset.collectionAttrs;if(!n)return;if(!w){p.replaceChildren(b("",!0));return}const t=o=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({attrs:n})});try{let o=w,a=await t(o);if(a.status===401){const u=S.get("auth_refresh_token");if(u){const g=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:u})});if(g.ok){const{token:y}=await g.json();S.set("auth_token",y),o=y,a=await t(o)}}}if(!a.ok){const{error:u}=await a.json().catch(()=>({}));p.replaceChildren(b(u||"Unable to load entries.",!1));return}const{html:e}=await a.json();C(p,e)}catch{p.replaceChildren(b("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),_(document.body)},100)})(),(function(){const h=document.querySelectorAll("[data-collection-table]");!h.length||typeof T>"u"||!T.create||h.forEach(w=>{let b;try{b=JSON.parse(atob(w.dataset.payload))}catch{return}const{columns:C,rows:p,search:n,sortable:t,exportable:o,pageSize:a,empty:e,ctaConfig:u,slug:g,exportCfg:y}=b;if(!C?.length)return;if(u){const r=C.findIndex(i=>i.key==="_cta");r!==-1&&(C[r]={key:"_cta",title:"",render:(i,c)=>{const s=document.createElement("button");if(s.className=`btn btn-${u.style||"primary"} dm-cta-trigger`,s.dataset.action=u.action||"",s.dataset.entry=c._entryId||"",u.confirm&&(s.dataset.confirm=u.confirm),u.icon){const l=document.createElement("span");l.dataset.icon=u.icon,s.appendChild(l),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(u.label||"Run")),s}})}const f="col-table-"+Math.random().toString(36).slice(2,7),m=document.createElement("div");m.id=f,w.replaceChildren(m),T.create("#"+f,{data:p,columns:C,search:n,sortable:t,exportable:o,pageSize:a,emptyMessage:e}),u&&_(m),w._dmTable={columns:C,rows:p,slug:g,exportCfg:y,render(r){T.create("#"+f,{data:r,columns:C,search:n,sortable:t,exportable:o,pageSize:a,emptyMessage:e}),u&&_(m)}}})})(),(function(){const h=document.querySelectorAll("[data-form-inline]");if(!h.length||typeof F>"u")return;function w(t){const o=t&&t.logic;return!!(o&&(o.visibility||o.requirement))}function b(t,o){const a={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const u=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),g=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":u?"chooser":e.type,y={...e.formConfig||{}};y.span==="full"&&o&&(y.span=o);const f={type:g,required:w(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...y}};u&&(e.variant&&(f.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(f.multiple=!0),e.density&&(f.density=e.density),e.columns&&(f.columns=e.columns),e.accent&&(f.accent=e.accent),e.accentStyle&&(f.accentStyle=e.accentStyle),e.glow&&(f.glow=!0),e.glowColour&&(f.glowColour=e.glowColour),e.shadow&&(f.shadow=e.shadow),e.shadowColour&&(f.shadowColour=e.shadowColour)),a[e.name]=f}),a}function C(t){const o={};return(t||[]).forEach(a=>{if(!(!a.name||a.type==="page-break"||a.type==="spacer")&&(a.type==="select"||a.type==="multiselect")&&a.required){const e=(a.options||[])[0];e&&(o[a.name]=typeof e=="object"?e.value:e)}}),o}function p(t,o){(o||[]).forEach(a=>{if(a.type!=="date"||!a.name)return;const e=t.querySelector(`[name="${a.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(t,o,a){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=o,e.style.cssText=a?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}h.forEach(t=>{let o;try{o=JSON.parse(atob(t.dataset.formInline))}catch{return}const a=o.fields||[],e=o.settings||{},u=e.columns||1,g=e.layout||"stacked",y=a.some(i=>i.type==="page-break"),f=async i=>{try{const c=t.querySelector('[name="website"]'),s=t.querySelector('[name="_t"]'),l=Object.assign({},i);c!==null&&(l._hp=c.value),s!==null&&(l._t=s.value);const d=await H.post(`/api/forms/submit/${o.slug}`,l);if(d&&d.error){n(t,d.error,!0);const k=new Error(d.error);throw k.formSubmitFailed=!0,k}if(d?.redirect){window.location.href=d.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);n(t,d?.message||e.successMessage||"Thank you for your submission.",!1)}catch(c){throw c.formSubmitFailed||n(t,c.message||"Submission failed. Please try again.",!0),c}};function m(i){const c=i.querySelector("form");if(!c)return;const s=document.createElement("div");s.className="fb-form-honeypot",s.setAttribute("aria-hidden","true");const l=document.createElement("input");l.name="website",l.type="text",l.tabIndex=-1,l.autocomplete="url",l.placeholder="https://",s.appendChild(l);const d=document.createElement("input");d.name="_t",d.type="hidden",d.value=Date.now(),s.appendChild(d),c.appendChild(s)}function r(){if(!window.FormLogicEngine||!a.some(c=>c.logic))return null;const i=new window.FormLogicEngine.FormLogicRuntime(o,t);if(i.init(),t._formLogicRuntime=i,t._formLogicObserved)return i;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const c=new MutationObserver(function(s){for(const l of s)for(const d of l.removedNodes)if(d===t||d.nodeType===1&&d.contains&&d.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),c.disconnect();return}});c.observe(t.parentNode,{childList:!0,subtree:!1})}return i}if(y&&F.wizard){const i=[],c=[];let s=[],l=o.title||"Step 1",d="";const k=()=>{i.push({title:l,description:d,fields:b(s,u)}),c.push(s)};a.forEach(x=>{x.type==="page-break"?(k(),s=[],l=x.label||`Step ${i.length+1}`,d=x.description||""):x.type!=="spacer"&&s.push(x)}),k();let L=0,A=null;const N=x=>{const I=window.FormLogicEngine;if(!I||!I.validateFields)return;const D=I.validateFields(t,c[L]||[]);D.valid||(x.preventDefault(),x.stopImmediatePropagation(),B(t,D.missing),V(D))},q=()=>{p(t,a),z(t,a),e.honeypot!==!1&&m(t),A&&A.destroy(),A=r(),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(x=>x.addEventListener("click",N,!0))},j=F.wizard(t,{schema:{steps:i},onSubmit:f,onStepChange:x=>{L=x,setTimeout(q,0)}});Promise.resolve(j).then(q)}else if(F.render){const i=F.render(t,b(a,u),C(a),{submitText:e.submitText||"Submit",layout:g,columns:u,onSubmit:f});Promise.resolve(i).then(function(){if(g==="grid"&&e.submitSpan==="full"){const c=t.querySelector(".form-buttons");c&&c.classList.add("col-span-full")}p(t,a),z(t,a),e.honeypot!==!1&&m(t),r()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();