domma-cms 1.10.14 → 1.10.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/admin/css/admin.css +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +4 -4
- package/admin/index.html +2 -2
- package/admin/js/api.js +1 -1
- package/admin/js/lib/hotkeys-ui.js +7 -16
- package/admin/js/lib/hotkeys.js +1 -1
- package/admin/js/lib/media-arrange.js +1 -1
- package/admin/js/lib/palette-commands.js +1 -0
- package/admin/js/templates/media.html +19 -10
- package/admin/js/views/form-editor.js +6 -6
- package/admin/js/views/media.js +3 -3
- package/docs/configuration.md +7 -3
- package/docs/markdown-shortcodes.md +3 -2
- package/package.json +2 -2
- package/public/css/forms.css +1 -1
- package/public/css/site.css +1 -1
- package/public/js/collection-browser.js +2 -2
- package/public/js/collection-range.mjs +1 -0
- package/public/js/form-files.mjs +1 -0
- package/public/js/form-logic-engine.js +1 -1
- package/public/js/forms.js +2 -2
- package/public/js/site.js +1 -1
- package/server/routes/api/forms.js +63 -38
- package/server/routes/api/media.js +25 -2
- package/server/server.js +8 -2
- package/server/services/mediaTypes.js +22 -0
- package/server/templates/page.html +8 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __browsers=[];let __keyboardNavInstalled=!1;function bootstrapCollectionBrowsers(l=document){const t=[...l.querySelectorAll(".dm-collection-browser")].filter(e=>!e.__dmCollectionBrowser);t.length&&(t.forEach(e=>{e.__dmCollectionBrowser=!0;try{__browsers.push(new CollectionBrowser(e,__browsers.length))}catch(i){console.error("[collection-browser] hydration failed:",i)}}),!__keyboardNavInstalled&&__browsers.length&&(__keyboardNavInstalled=!0,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.config.scope==="mine"&&e.set("scope","mine"),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||"",this.config.scope&&(i.dataset.scope=this.config.scope),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||""});this.config.scope==="mine"&&i.set("scope","mine");const 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||"",this.config.scope&&(a.dataset.scope=this.config.scope),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=this.config.scope==="mine"?"/api/collections/render-scope":"/api/collections/render-fragment",c=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",...this.authHeaders()},body:JSON.stringify({attrs:a,page:this.state.page})});if(i!==this._fragReqId)return;if(!c.ok){e.textContent=this.config.emptyMsg;return}const{html:d}=await c.json(),h=document.createElement("template");h.innerHTML=d||"",e.replaceWith(h.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=[];let __keyboardNavInstalled=!1;function bootstrapCollectionBrowsers(l=document){const t=[...l.querySelectorAll(".dm-collection-browser")].filter(e=>!e.__dmCollectionBrowser);t.length&&(t.forEach(e=>{e.__dmCollectionBrowser=!0;try{__browsers.push(new CollectionBrowser(e,__browsers.length))}catch(i){console.error("[collection-browser] hydration failed:",i)}}),!__keyboardNavInstalled&&__browsers.length&&(__keyboardNavInstalled=!0,installGlobalKeyboardNav()))}function installGlobalKeyboardNav(){__browsers.length&&document.addEventListener("keydown",l=>{const t=l.target&&(l.target.tagName==="INPUT"||l.target.tagName==="TEXTAREA"||l.target.isContentEditable||!!l.target.closest?.('[role="slider"]'));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,a=1;for(;__browsers.some(r=>r.idScope===s);)a+=1,s=`${n}_${a}`;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 a=elt("div","dm-cb-saved-actions"),r=elt("button","dm-cb-saved-create btn btn-primary");r.type="button",r.textContent="Save current view",r.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())}),a.appendChild(r),i.appendChild(a)};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 a=this.visibleFields(n),r=toCsv(n,a);downloadCsv(`${this.config.slug}-export.csv`,r);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 a of n){const r=elt("option");r.value=a.name,r.textContent=a.label,a.name===this.state.sort&&(r.selected=!0),i.appendChild(r)}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(){for(const i of this._sliders||[])i.destroy();this._sliders=[],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(a=>a.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.renderFilterRail();const i=this.el.querySelector(".dm-cb-search-input");i&&(i.value=""),this.filterRail.querySelector(".dm-cb-filter-reset")?.focus()}),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 a of this.entries){const r=a._refs?.[t.name];if(!r)continue;const o=Array.isArray(r)?r:[r];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[a,r]of e){const o=elt("option");o.value=a,o.textContent=r,String(this.state.filter[i]??"")===String(a)&&(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 f=elt("span","dm-cb-chip-label");if(f.textContent=h.label??h.value,p.appendChild(f),n){const u=elt("span","dm-cb-chip-count");u.textContent=n[String(h.value)]??0,p.appendChild(u)}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`,a=elt("select","dm-cb-select"),r=elt("option");r.value="",r.textContent="Any",a.appendChild(r);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),a.appendChild(c)}return a.addEventListener("change",()=>this.updateFilter(s,a.value)),a}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 a={...n,...this.config.baked||{}};s=applyFilterInMemory(s,a);const r={};for(const o of i){const c={...a,[`${t}${e}`]:String(o)};r[String(o)]=applyFilterInMemory(s,c).length}return r}buildRangeControl(t,e){const i=`${t.name}_gte`,n=`${t.name}_lte`,s=elt("div","dm-cb-range"),a=elt("div","dm-cb-range-inputs"),r=elt("input","dm-cb-range-min"),o=elt("input","dm-cb-range-max");r.type=e,o.type=e,r.placeholder="Min",o.placeholder="Max",r.value=this.state.filter[i]||"",o.value=this.state.filter[n]||"",a.appendChild(r),a.appendChild(document.createTextNode(" - ")),a.appendChild(o),s.appendChild(a);let c=null,d=null,h=null;const p=window.DommaCollectionRange;if(e==="number"&&this.config.mode==="client"&&this.entries.length&&p&&typeof E<"u"&&E.rangeSlider&&(d=p.rangeBounds(this.entries.map(u=>u.data?.[t.name]))),d){const u=elt("div","dm-cb-slider");s.appendChild(u);const g=t.label||t.name,m=b=>{const C=p.rangeFilter(d,b);(!h||b[0]!==h[0])&&(r.value=C.gte),(!h||b[1]!==h[1])&&(o.value=C.lte)};c=E.rangeSlider(u,{range:!0,min:d.min,max:d.max,step:d.step,value:p.sliderValue(d,r.value,o.value),labels:p.rangeLabel(t,d.step),ariaLabels:[`${g} from`,`${g} to`],onInput:m,onChange:b=>{m(b),h=b.slice(),this.updateFilter(i,r.value,!0),this.updateFilter(n,o.value)}}),h=c.getValue().slice(),this._sliders.push(c)}const f=debounce(()=>{this.updateFilter(i,r.value,!0),this.updateFilter(n,o.value),c&&(c.setValue(p.sliderValue(d,r.value,o.value),{silent:!0}),h=c.getValue().slice())},250);return r.addEventListener("input",f),o.addEventListener("input",f),s}buildBooleanControl(t){const e=`${t.name}_eq`,i=elt("select","dm-cb-select");for(const[n,s]of[["","Any"],["true","Yes"],["false","No"]]){const a=elt("option");a.value=n,a.textContent=s,String(this.state.filter[e]??"")===n&&(a.selected=!0),i.appendChild(a)}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(r=>r.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(r=>typeof r=="object"?r:{value:r,label:r}):distinctValues(this.entries,t).map(r=>({value:r,label:r})),s=this.facetCounts(t,i,n.map(r=>r.value)),a=this.filterRail.querySelectorAll(".dm-cb-filter");for(const r of a){const o=r.querySelector(".dm-cb-filter-label");if(!o||o.textContent!==(e.label||e.name))continue;r.querySelectorAll(".dm-cb-chip").forEach((h,p)=>{const f=h.querySelector(".dm-cb-chip-count");f&&n[p]&&(f.textContent=s[String(n[p].value)]??0)});const d=r.querySelector("select.dm-cb-select");d&&Array.from(d.options).forEach(h=>{if(!h.value)return;const p=n.find(f=>String(f.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.config.scope==="mine"&&e.set("scope","mine"),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(),a=s.entries||s.results||[];this.entries=a.map(r=>r.data?r:{id:r.id||"",data:r.data||r}),this.total=s.total||a.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,f]of Object.entries(d.data||{})){if(f==null)continue;const u=String(f).toLowerCase();let g=0,m=0;for(;(g=u.indexOf(c,g))!==-1;)m++,g+=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 a=t.length,r=(this.state.page-1)*this.config.pageSize;return{visible:t.slice(r,r+this.config.pageSize),total:a}}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"),a=e.find(c=>c.name===this.config.titleField),r=a?fieldDisplay(n,a):this.config.titleField?formatValue(n.data?.[this.config.titleField]):"";if(r){const c=elt("div","card-header");c.textContent=r,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"),a=e.find(c=>c.name===this.config.titleField),r=a?fieldDisplay(n,a):this.config.titleField?formatValue(n.data?.[this.config.titleField]):"";if(r){const c=elt("div","dm-collection-list-title");c.textContent=r,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 r of e){const o=elt("th");o.textContent=r.label||r.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 a=elt("tbody");for(const r of t){const o=elt("tr");for(const c of e){const d=elt("td");d.appendChild(fieldDisplayNode(r,c)),o.appendChild(d)}if(this.config.cta){const c=elt("td");c.appendChild(this.buildCtaButton(r)),o.appendChild(c)}if(this.config.transitions){const c=elt("td");c.appendChild(this.buildTransitionsGroup(r)),o.appendChild(c)}a.appendChild(o)}return i.appendChild(a),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",a=this.config.bodyField&&i.data?.[this.config.bodyField]||"",r=elt("button","accordion-header");r.type="button",r.textContent=String(s);const o=elt("div","accordion-panel");o.textContent=String(a),r.addEventListener("click",()=>n.classList.toggle("open")),n.appendChild(r),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||"",this.config.scope&&(i.dataset.scope=this.config.scope),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||""});this.config.scope==="mine"&&i.set("scope","mine");const 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 a of s){const r=elt("button",`btn btn-${a.trigger?.style||"outline"} dm-cb-transition-btn dm-cta-trigger`);if(r.dataset.action=a.slug,r.dataset.entry=t.id||"",this.config.scope&&(r.dataset.scope=this.config.scope),a.trigger?.confirmMessage&&(r.dataset.confirm=a.trigger.confirmMessage),a.trigger?.icon){const o=elt("span");o.dataset.icon=a.trigger.icon,r.appendChild(o),r.appendChild(document.createTextNode(" "))}r.appendChild(document.createTextNode(a.trigger?.label||a.title)),e.appendChild(r)}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 a=this.visibleFields(s),r=this.renderForDisplay(s,a),o=this.bodyEl.firstElementChild;if(o&&o.tagName===r.tagName)for(;r.firstChild;)o.appendChild(r.firstChild);else this.bodyEl.appendChild(r);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 a=elt("div","timeline-event"),r=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),a.appendChild(p)}if(r){const p=elt("div","timeline-date");p.textContent=String(r),a.appendChild(p)}if(o){const p=elt("h4","timeline-title");p.textContent=String(o),a.appendChild(p)}if(d){const p=elt("span",`badge badge-${d}`);p.textContent=String(d),a.appendChild(p)}if(c){const p=elt("div","timeline-body");p.textContent=String(c),a.appendChild(p)}n.appendChild(a)}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(r=>r.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)},a={...this.state.filter,...this.config.baked||{}};for(const[r,o]of Object.entries(a))o!==""&&o!=null&&(s[`where_${r}`]=String(o));s.sort=this.state.sort,s.order=this.state.order,s.limit=String(this.config.pageSize);try{const r=btoa(unescape(encodeURIComponent(JSON.stringify(s)))),o=this.config.scope==="mine"?"/api/collections/render-scope":"/api/collections/render-fragment",c=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",...this.authHeaders()},body:JSON.stringify({attrs:r,page:this.state.page})});if(i!==this._fragReqId)return;if(!c.ok){e.textContent=this.config.emptyMsg;return}const{html:d}=await c.json(),h=document.createElement("template");h.innerHTML=d||"",e.replaceWith(h.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=a=>t.get(e+a);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[a,r]of t.entries())if(a.startsWith(s)&&a.endsWith("]")){const o=a.slice(s.length,-1);o&&(n[o]=r)}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,a)=>{a!==""&&a!=null&&t.searchParams.set(e+s,a)};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,a]of Object.entries(this.state.filter))a!==""&&a!=null&&t.searchParams.set(`${e}filter[${s}]`,a);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:a}=parseFilterKey(i),r=resolveField(e,s);if(!applyOp(a,r,n))return!1}return!0})}function sortEntries(l,t,e){const i=e==="asc"?1:-1;return[...l].sort((n,s)=>{const a=t==="createdAt"?n.meta?.createdAt||"":n.data?.[t]??"",r=t==="createdAt"?s.meta?.createdAt||"":s.data?.[t]??"";return a<r?-i:a>r?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((a,r)=>{if(r>0&&n.appendChild(document.createTextNode(", ")),a.missing)n.appendChild(document.createTextNode(`${a.id} (missing)`));else if(a.link){const o=document.createElement("a");o.href=a.link,o.textContent=a.display,n.appendChild(o)}else n.appendChild(document.createTextNode(a.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 a=Array.isArray(s)?s.join(", "):String(s);return/[",\n\r]/.test(a)&&(a='"'+a.replace(/"/g,'""')+'"'),a},i=t.map(s=>e(s.label||s.name)).join(","),n=l.map(s=>t.map(a=>e(s.data?.[a.name])).join(",")).join(`
|
|
2
2
|
`);return i+`
|
|
3
3
|
`+n+`
|
|
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)}
|
|
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)}window.DommaCollectionBrowser={hydrate:bootstrapCollectionBrowsers},bootstrapCollectionBrowsers();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function x(t){const n=String(t);if(n.includes("e-"))return Number(n.split("e-")[1])||0;const e=n.indexOf(".");return e===-1?0:n.length-e-1}const m=(t,n)=>Number(t.toFixed(Math.min(n,10)));export function rangeBounds(t){const n=(t||[]).filter(s=>s!=null&&s!==""&&typeof s!="boolean").map(Number).filter(Number.isFinite);if(!n.length)return null;const e=Math.min(...n),o=Math.max(...n);if(!(o>e))return null;const a=Math.min(6,Math.max(...n.map(x))),u=10**-a,c=10**Math.floor(Math.log10((o-e)/100)),r=m(Math.max(c,u),a),i=Math.max(a,x(r));let f=m(Math.floor(m(e/r,6))*r,i),l=m(Math.ceil(m(o/r,6))*r,i);return f>e&&(f=m(f-r,i)),l<o&&(l=m(l+r,i)),{min:f,max:l,step:r,lo:e,hi:o}}export function sliderValue(t,n,e){const o=(c,r)=>{if(c===""||c===null||c===void 0)return r;const i=Number(c);return Number.isFinite(i)?Math.min(Math.max(i,t.min),t.max):r},a=o(n,t.min),u=o(e,t.max);return a<=u?[a,u]:[u,a]}export function rangeFilter(t,[n,e]){return{gte:n>t.lo?String(n):"",lte:e<t.hi?String(e):""}}function h(t){return t?typeof t=="string"?t:t.icon?"":String(t.text??""):""}export function rangeLabel(t,n,e){const o=h(t?.prefix),a=h(t?.suffix),u=x(n);let c;try{c=new Intl.NumberFormat(e,{maximumFractionDigits:u})}catch{c={format:i=>String(i)}}const r=(i,f)=>/^[A-Za-z]/.test(i)&&f==="after"||/[A-Za-z]$/.test(i)&&f==="before"?" ":"";return i=>{const f=c.format(Number(i));return`${o}${o?r(o,"before"):""}${f}${a?r(a,"after"):""}${a}`}}typeof window<"u"&&(window.DommaCollectionRange={rangeBounds,sliderValue,rangeFilter,rangeLabel});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_MAX_SIZE=5242880;export function fileRules(t){const e=t&&t.file||{};return{accept:String(e.accept||"").split(",").map(i=>i.trim()).filter(Boolean),maxSize:Number(e.maxSize)||5242880,multiple:!!(t&&t.multiple)}}export function mimeAccepted(t,e){if(!t||!t.length)return!0;const i=String(e||"");return t.some(o=>o.endsWith("/*")?i.startsWith(o.slice(0,-1)):o===i)}export function cleanUploadName(t){const e=i=>i.replace(/^[-.]+|[-.]+$/g,"");return e(e(String(t||"upload").toLowerCase().replace(/[^\w.-]+/g,"-").replace(/-+/g,"-")).slice(0,200))||"upload"}const u=/^(text\/html|text\/xml|text\/xsl|text\/javascript|text\/ecmascript|application\/(x-)?javascript|application\/ecmascript|application\/xml|application\/[\w.-]+\+xml|image\/svg\+xml)\b/i,d=/\.(html?|xht(ml)?|shtml?|svgz?|xml|xsd|xslt?|xul|rdf|owl|atom|rss|wsdl|smil?|kml|opf|xlf|gpx|ttml|mathml|mml|xop|m?js|mht(ml)?)$/i;function p(t){const e=/\.[^.]+$/.exec(cleanUploadName(t&&(t.filename??t.name)||""));return e?e[0]:""}export function isActiveFile(t){const e=String(t&&(t.mimetype??t.type)||""),i=t&&(t.filename??t.name)||"";return u.test(e)||d.test(cleanUploadName(i))}export function fileRefusal(t,e){const i=fileRules(t),o=t&&(t.label||t.name)||"File";if(Number(e&&e.size)>i.maxSize)return`"${o}" file is too large (max ${Math.round(i.maxSize/1024)} KB).`;const n=e&&(e.mimetype??e.type)||"";return isActiveFile(e)?`"${o}" file type "${n||p(e)}" not allowed (it could run as a page on this site).`:i.accept.length&&!mimeAccepted(i.accept,n)?`"${o}" file type "${n}" not allowed (expected: ${String(t.file.accept).trim()}).`:null}const m=[[/wordprocessingml|^msword$/,"Word"],[/spreadsheetml|ms-excel/,"Excel"],[/presentationml|ms-powerpoint/,"PowerPoint"],[/^plain$/,"text"]];export function describeAccept(t){const e=[];return(t||[]).forEach(i=>{const[o,n]=String(i).split("/");let r;n==="*"?r={image:"images",audio:"audio",video:"video",text:"text files"}[o]||`${o} files`:n?r=m.find(([s])=>s.test(n))?.[1]||n.replace(/^(x-|vnd\.)/,"").split(/[.+]/)[0].toUpperCase():r=String(i),r&&!e.includes(r)&&e.push(r)}),e.length<2?e[0]||"":`${e.slice(0,-1).join(", ")} or ${e[e.length-1]}`}export function formatSize(t){const e=Number(t)||0;if(e<1024)return`${e} B`;const i=["KB","MB","GB"];let o=e,n=-1;do o/=1024,n++;while(o>=1024&&n<i.length-1);return`${o>=10?Math.round(o):Math.round(o*10)/10} ${i[n]}`}export function fileHint(t){const e=fileRules(t),i=describeAccept(e.accept),o=`up to ${formatSize(e.maxSize)}`;return i?`${i[0].toUpperCase()}${i.slice(1)} - ${o}`:`Any file - ${o}`}export function dropzoneOptions(t){const e=fileRules(t);return{accept:e.accept.length?e.accept.join(","):null,maxSize:e.maxSize,multiple:e.multiple,labels:{prompt:e.multiple?"Drop files here, paste, or click to browse":"Drop a file here, paste, or click to browse",hint:fileHint(t),required:"Please add a file",type:refusalMessage(t,{name:"{name}"},"type"),size:refusalMessage(t,{name:"{name}"},"size"),count:refusalMessage(t,{name:"{name}"},"count")}}}export function fileBlueprint(t,e){return{...e,type:"dropzone",formConfig:{...e.formConfig||{},...dropzoneOptions(t)}}}export function refusalMessage(t,e,i){const o=fileRules(t),n=e&&e.name||"That file";if(i==="size")return`${n} was not added: it is larger than ${formatSize(o.maxSize)}.`;if(i==="type"){const r=describeAccept(o.accept);return`${n} was not added: ${r?`only ${r} can be uploaded here`:"that type of file is not accepted"}.`}return i==="active"?`${n} was not added: web pages, SVG images and scripts cannot be uploaded.`:`${n} was not added: only one file can be added here.`}function h(t){return Array.isArray(t)&&t.length>0&&typeof File<"u"&&t.every(e=>e instanceof File)}export function splitFiles(t,e,i){const o={...t||{}},n=new Map,r=new Set((e||[]).filter(s=>s&&s.type==="file"&&s.name).map(s=>s.name));for(const[s,l]of Object.entries(o))h(l)?(n.set(s,l),delete o[s]):r.has(s)&&(Array.isArray(l)||l==null)&&(o[s]="");for(const[s,l]of i||[])n.set(s,l||[]);for(const[s,l]of n)l.length?delete o[s]:(n.delete(s),(r.has(s)||s in o)&&(o[s]=""));return{values:o,files:n}}export function submitBody(t,e){if(![...(e||new Map).values()].some(n=>n&&n.length))return{body:JSON.stringify(t),headers:{"Content-Type":"application/json"},multipart:!1};const o=new FormData;for(const[n,r]of Object.entries(t))r==null||e.has(n)||o.append(n,typeof r=="object"?JSON.stringify(r):String(r));for(const[n,r]of e)for(const s of r||[])o.append(n,s,s.name);return{body:o,headers:{},multipart:!0}}export function captureFileFields(t,e){!t||!e||t.querySelectorAll('input[type="file"]').forEach(i=>{i.name&&e.set(i.name,Array.from(i.files||[]))})}export function restoreFileFields(t,e){!t||!e||!e.size||t.querySelectorAll('input[type="file"]').forEach(i=>{const o=e.get(i.name);if(!o||!o.length||i.files&&i.files.length)return;const n=f(i);if(n){n.addFiles(o);return}try{const r=new DataTransfer;o.forEach(s=>r.items.add(s)),i.files=r.files}catch{}})}function f(t){const e=globalThis.E;if(!e||typeof e.get!="function")return null;const i=t.closest("[data-dropzone-field]"),o=i&&e.get(i,"dropzone")||e.get(t,"dropzone");return o&&typeof o.addFiles=="function"?o:null}function c(t,e){const i=String(e&&e.name||"").replace(/\[\]$/,"");return(t||[]).find(o=>o&&o.name===i)||{name:i}}function x(t){let e=t.nextElementSibling;return(!e||!e.classList.contains("fb-file-refusal"))&&(e=document.createElement("p"),e.className="fb-file-refusal",e.hidden=!0,t.after(e)),e}export function wireFileFields(t,e){if(!t||t._fbFilesWired)return;t._fbFilesWired=!0;const i=new WeakMap,o=(n,r,s)=>{const l=x(n.zone),a=i.get(n.zone)||[];a.push(refusalMessage(c(e,n.input),r,s)),i.set(n.zone,a),l.textContent=a.join(" "),l.hidden=!1,n.zone.classList.add("is-invalid"),queueMicrotask(()=>i.delete(n.zone))};t.addEventListener("dm:dropzone:reject",n=>{const r=n.detail&&n.detail.instance,[s,l]=n.detail&&n.detail.args||[];r&&r.zone&&o(r,s,l)}),t.addEventListener("dm:dropzone:beforeadd",n=>{const r=n.detail&&n.detail.instance,[s]=n.detail&&n.detail.args||[];!r||!r.zone||!s||!isActiveFile(s.file||s)||(n.preventDefault(),o(r,s,"active"))}),t.addEventListener("dm:dropzone:add",n=>{const r=n.detail&&n.detail.instance;if(!r||!r.zone||i.get(r.zone))return;const s=r.zone.nextElementSibling;s&&s.classList.contains("fb-file-refusal")&&(s.hidden=!0,s.textContent="")}),t.addEventListener("dm:dropzone:change",n=>{const r=n.detail&&n.detail.instance;if(!r||!r.input)return;r.input.dispatchEvent(new Event("input",{bubbles:!0}));const s=r.input.closest(".fb-field-invalid");s&&r.getFiles().length&&s.classList.remove("fb-field-invalid")})}export function enhanceFileInputs(t,e){const i=globalThis.E;!t||!i||typeof i.dropzone!="function"||(t.querySelectorAll('input[type="file"]').forEach(o=>{f(o)||i.dropzone(o,dropzoneOptions(c(e,o)))}),wireFileFields(t,e))}export function checkFileInputs(t,e){const i=[];return t&&t.querySelectorAll('input[type="file"]').forEach(o=>{const n=c(e,o),r=Array.from(o.files||[]);!fileRules(n).multiple&&r.length>1&&i.push(`"${n.label||n.name}" takes one file.`),r.forEach(s=>{const l=fileRefusal(n,s);l&&i.push(l)})}),i}export function destroyDropzones(t){const e=globalThis.E;!t||!e||typeof e.get!="function"||t.querySelectorAll('.dm-dropzone, input[type="file"]').forEach(i=>{const o=e.get(i,"dropzone");o&&typeof o.destroy=="function"&&o.destroy()})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(l,d){typeof module<"u"&&module.exports?module.exports=d():l.FormLogicEngine=d()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function l(e){return e===""||e===null||e===void 0?"":String(e)}function d(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 z={not_equals:"equals",not_contains:"contains",not_in:"in"};function q(e,r){const t=l(r),n=l(e.value);switch(e.operator){case"equals":return t===n;case"not_equals":return t!==n;case"contains":return t.toLowerCase().includes(n.toLowerCase());case"not_contains":return!t.toLowerCase().includes(n.toLowerCase());case"starts_with":return t.toLowerCase().startsWith(n.toLowerCase());case"ends_with":return t.toLowerCase().endsWith(n.toLowerCase());case"greater_than":{const i=d(r),s=d(e.value);return i!==null&&s!==null&&i>s}case"less_than":{const i=d(r),s=d(e.value);return i!==null&&s!==null&&i<s}case"is_empty":return p(r);case"is_not_empty":return!p(r);case"in":return(Array.isArray(e.value)?e.value.map(l):String(e.value).split(",").map(s=>s.trim())).includes(t);case"not_in":return!(Array.isArray(e.value)?e.value.map(l):String(e.value).split(",").map(s=>s.trim())).includes(t);case"matches_regex":try{const i=e.flags||"";return new RegExp(e.value,i).test(t)}catch(i){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,i&&i.message),!1}default:return!0}}function _(e,r){if(!e||!e.field||!e.operator)return!0;const t=r[e.field];if(!Array.isArray(t))return q(e,t);if(e.operator==="is_empty")return p(t);if(e.operator==="is_not_empty")return!p(t);const n=z[e.operator];if(n){const i=Object.assign({},e,{operator:n});return!t.some(s=>q(i,s))}return t.some(i=>q(e,i))}function h(e,r){return e?Array.isArray(e.all)?e.all.every(t=>t.all||t.any?h(t,r):_(t,r)):Array.isArray(e.any)?e.any.some(t=>t.all||t.any?h(t,r):_(t,r)):e.field&&e.operator?_(e,r):!0:!0}function v(e,r){const t=e.logic;if(!t||!t.visibility)return"visible";const n=t.visibility,i=n.conditions||[];for(const s of i)if(s.when&&h(s.when,r))return s.then==="hidden"?"hidden":"visible";return n.default==="hidden"?"hidden":"visible"}function w(e,r){const t=e.logic;if(!t||!t.requirement)return e.required||!1;const n=t.requirement,i=n.conditions||[];for(const s of i)if(s.when&&h(s.when,r))return s.then===!0;return n.default===!0}function A(e){if(e==null||e==="")return null;const r=Number(e);return Number.isFinite(r)?r:null}function j(e,r){if(p(r)||Array.isArray(r)||typeof r=="object")return[];const t=e.label||e.name;if(e.type==="number"){const a=Number(r);if(!Number.isFinite(a)||String(r).trim()==="")return[{message:`${t} must be a number.`}];const o=A(e.min),c=A(e.max);return o!==null&&a<o?[{message:`${t} must be at least ${o}.`}]:c!==null&&a>c?[{message:`${t} must be no more than ${c}.`}]:[]}const n=String(r).length,i=A(e.minLength),s=A(e.maxLength);return i!==null&&n<i?[{message:`${t} must be at least ${i} characters.`}]:s!==null&&n>s?[{message:`${t} must be no more than ${s} characters.`}]:[]}function k(e,r,t){const n=j(e,r),i=e.logic;if(!i||!Array.isArray(i.validation))return n;for(const s of i.validation)switch(s.type){case"regex":{if(!p(r))try{new RegExp(s.pattern||"",s.flags||"").test(l(r))||n.push({message:s.message||"Invalid format."})}catch{}break}case"match":{const a=t[s.field];!p(r)&&l(r)!==l(a)&&n.push({message:s.message||"Fields do not match."});break}}return n}function T(e,r){const t=e.logic;if(!t||!t.cascade||!t.cascade.sourceField)return null;const n=t.cascade,i=n.mapping||{},s=r[n.sourceField];if(Array.isArray(s)){const o=new Set,c=[];return s.forEach(function(g){const f=l(g);Object.prototype.hasOwnProperty.call(i,f)&&(i[f]||[]).forEach(function(x){const P=l(x&&x.value);o.has(P)||(o.add(P),c.push(x))})}),c.length?c:n.defaultOptions||null}const a=l(s);return Object.prototype.hasOwnProperty.call(i,a)?i[a]||[]:n.defaultOptions||null}const G={fade:250,slide:300,scale:200};function N(e,r){const t=Number(r);return!isFinite(t)||t<0||t>5e3?G[e]||250:Math.round(t)}function K(e,r,t){const n=N(r,t);if(r==="fade")e.style.transition="opacity "+n+"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=""},n+10)});else if(r==="slide"){const i=Math.round(n*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+n+"ms ease, opacity "+i+"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=""},n+20)})}else r==="scale"&&(e.style.transition="opacity "+n+"ms ease, transform "+n+"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=""},n+20)}))}function U(e,r,t){const n=N(r,t);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+n+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},n+10)});else if(r==="slide"){const i=Math.round(n*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+n+"ms ease, opacity "+i+"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=""},n+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+n+"ms ease, transform "+n+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},n+20)}))}const C={banner:"state","disable-fields":"state","hide-fields":"state","require-fields":"state","block-submit":"state","end-form":"state",toast:"event",celebrate:"event","goto-step":"event",redirect:"event","run-action":"event",notify:"event"},Y=["block-submit","hide-fields","disable-fields","require-fields","end-form","redirect","run-action","notify"];function y(e){return!!e&&!!e.name&&e.type!=="page-break"&&e.type!=="spacer"}function b(e,r,t){const n=(t||[]).filter(y),i=e.target||(e.fields&&e.fields.length?"listed":"rest");if(i==="listed"){const a=new Set(e.fields||[]);return n.filter(o=>a.has(o.name)&&o.name!==r.name).map(o=>o.name)}if(i==="all")return n.filter(a=>a.name!==r.name).map(a=>a.name);const s=n.findIndex(a=>a.name===r.name);return s===-1?[]:n.slice(s+1).map(a=>a.name)}function S(e,r){for(const t of r)e.includes(t)||e.push(t)}function X(e,r,t,n,i){if(!r||!r.type)return;const s=C[r.type];if(s){if(s==="event"){e.events.push({key:i,type:r.type,field:t.name,action:r});return}switch(r.type){case"banner":e.banners.push({key:i,field:t.name,message:r.message||"",level:r.level||"info",position:r.position||"field-below",dismissible:r.dismissible!==!1});break;case"hide-fields":S(e.hidden,b(r,t,n));break;case"disable-fields":S(e.disabled,b(r,t,n));break;case"require-fields":S(e.required,b(r,t,n));break;case"block-submit":e.blocks.push({key:i,message:r.message||"This form cannot be submitted yet."});break;case"end-form":S(e.masked,b({target:"rest"},t,n)),e.ends.push({key:i,field:t.name,message:r.message||"",finishLabel:r.finishLabel||"Finish",doneMessage:r.doneMessage||"",record:r.record!==!1,finish:r.finish!==!1}),r.finish===!1&&e.blocks.push({key:i,quiet:!0,message:r.message||"This form cannot be submitted."});break;default:break}}}const L=/\{\{\s*([A-Za-z_][A-Za-z0-9_-]*)\s*\}\}/g,Z=["password","file","image","signature"],F=200,J={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:" ",pound:"\xA3",euro:"\u20AC",copy:"\xA9",reg:"\xAE"};function I(e){return String(e).replace(/<[^>]*>/g,"").replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(r,t)=>{if(t[0]==="#"){const n=t[1]==="x"||t[1]==="X"?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return Number.isFinite(n)&&n>31?String.fromCodePoint(n):" "}return J[t.toLowerCase()]??r})}function M(e,r){const t=Array.isArray(e.options)?e.options:[];for(const n of t)if(n&&typeof n=="object"){if(String(n.value)===String(r))return I(n.label!=null?n.label:n.value)}else if(String(n)===String(r))return I(n);return String(r)}function Q(e,r){if(!e||Z.includes(e.type)||r==null||r===!1)return"";let t;return Array.isArray(r)?t=r.filter(n=>n!==""&&n!=null).map(n=>M(e,n)).join(", "):e.type==="checkbox"?t=r&&r!=="false"?"Yes":"":Array.isArray(e.options)&&e.options.length?t=r===""?"":M(e,r):t=String(r),t=t.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim(),t.length>F?t.slice(0,F-1).trimEnd()+"\u2026":t}function O(e,r,t,n){if(!e||typeof e!="string"||e.indexOf("{{")===-1)return e||"";const i=n instanceof Set?n:new Set(n||[]),s=new Map((r||[]).filter(y).map(a=>[a.name,a]));return e.replace(L,(a,o)=>{const c=s.get(o);return!c||i.has(o)?"":Q(c,(t||{})[o])})}function ee(e){const r=[];return String(e||"").replace(L,(t,n)=>(r.includes(n)||r.push(n),t)),r}function te(e,r,t){const n=new Set([...e.hidden,...e.disabled,...e.masked]);(r||[]).forEach(s=>{y(s)&&v(s,t)==="hidden"&&n.add(s.name)});const i=s=>O(s,r,t,n);e.banners.forEach(s=>{s.message=i(s.message)}),e.blocks.forEach(s=>{s.message=i(s.message)}),e.ends.forEach(s=>{s.message=i(s.message),s.doneMessage=i(s.doneMessage)}),e.events.forEach(s=>{s.type==="toast"&&s.action&&s.action.message&&(s.action=Object.assign({},s.action,{message:i(s.action.message)}))})}function B(e,r){const t={active:[],banners:[],hidden:[],disabled:[],required:[],blocks:[],events:[],masked:[],ends:[]};return(e||[]).forEach(n=>{!y(n)||!Array.isArray(n.triggers)||n.triggers.forEach((i,s)=>{if(!i||i.enabled===!1)return;const a=i.id||`${n.name}::${s}`,o=h(i.when,r),c=`${a}:${o?"then":"else"}`,g=o?i.then:i.otherwise;!Array.isArray(g)||!g.length||(t.active.push(c),g.forEach(f=>X(t,f,n,e,c)))})}),t.required=t.required.filter(n=>!t.hidden.includes(n)&&!t.masked.includes(n)),te(t,e,r||{}),t}function R(e){return(e||[]).some(r=>Array.isArray(r&&r.triggers)&&r.triggers.length>0)}function u(e,r,t){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,this._baseValues=t&&t.baseValues||null,this._hasTriggers=R(this._fields),this._triggerState=null,this._triggerPrev=new Set,this._triggerFired=new Set,this._triggerApplied={hidden:[],disabled:[],required:[],masked:[]},this._banners=new Map,this._dismissed=new Set,this._end=null}function m(e,r,t){const n=t||"",i=r||"";return n+'[name="'+e+'"]'+i+", "+n+'[name="'+e+'[]"]'+i}function ne(e){return String(e||"").replace(/\[\]$/,"")}u.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(m(e))},u.prototype._fieldInput=function(e){return this._wrapper.querySelector(m(e))},u.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const t=r.logic;if(!t)return;function n(i){if(!i)return;(i.all||i.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)):n(a)})}if(t.visibility&&(t.visibility.conditions||[]).forEach(function(i){n(i.when)}),t.requirement&&(t.requirement.conditions||[]).forEach(function(i){n(i.when)}),t.cascade&&t.cascade.sourceField){const i=t.cascade.sourceField;e._depMap.has(i)||e._depMap.set(i,new Set),e._depMap.get(i).add(r.name)}})};function $(e,r){const t={};return(r||[]).forEach(function(n){if(!n||!n.name)return;const i=e.querySelectorAll(m(n.name));if(!i.length)return;const s=i[0];if(s.type==="radio"){const a=e.querySelector(m(n.name,":checked"));t[n.name]=a?a.value:""}else if(s.type==="checkbox")if(i.length>1||/\[\]$/.test(s.name||"")){const a=[];i.forEach(function(o){o.checked&&a.push(o.value)}),t[n.name]=a}else t[n.name]=s.checked?s.value||"true":"";else t[n.name]=s.value}),t}function V(e,r){const t=$(e,r),n=[],i=[];return(r||[]).forEach(function(s){if(!s||!s.name||v(s,t)==="hidden")return;const a=t[s.name],o=Array.isArray(a)?a.length===0:!String(a??"").trim();if(w(s,t)&&o){n.push({name:s.name,label:s.label||s.name});return}if(o)return;const c=k(s,a,t);c.length&&i.push(c[0].message)}),{valid:n.length===0&&i.length===0,missing:n,errors:i,values:t}}u.prototype._getValues=function(){const e=this._baseValues?Object.assign({},this._baseValues):{};return this._fields.forEach(function(r){const t=this._fieldInputs(r.name);if(!t.length)return;const n=t[0];if(n.type==="radio"){const i=this._wrapper.querySelector(m(r.name,":checked"));e[r.name]=i?i.value:""}else if(n.type==="checkbox")if(t.length>1||/\[\]$/.test(n.name||"")){const i=[];t.forEach(function(s){s.checked&&i.push(s.value)}),e[r.name]=i}else e[r.name]=n.checked?n.value||"true":"";else e[r.name]=n.value},this),e},u.prototype._applyVisibility=function(e,r){const n=v(e,r)==="hidden",i=this._findFieldWrapper(e.name);if(!i)return;i.setAttribute("aria-hidden",String(n));const s=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(s==="none"){i.classList.toggle("fb-field-hidden",n);return}const a=e.logic?.visibility?.duration;i.style.transition="",n?K(i,s,a):U(i,s,a)},u.prototype._applyRequirement=function(e,r){const t=w(e,r),n=this._fieldInput(e.name);if(!n)return;if(/\[\]$/.test(n.name||"")||n.closest&&n.closest(".domma-chooser")){const s=this._findFieldWrapper(e.name);n.removeAttribute("required"),s&&(s.setAttribute("aria-required",String(t)),s.classList.toggle("fb-field-required",t));return}t?n.setAttribute("required",""):n.removeAttribute("required");const i=this._findFieldWrapper(e.name);i&&(i.setAttribute("aria-required",String(t)),i.classList.toggle("fb-field-required",t))},u.prototype._applyCascade=function(e,r){const t=T(e,r);if(t===null)return;const n=this._wrapper.querySelector(m(e.name,"","select"));if(!n)return;const i=n.value;n.textContent="",t.forEach(function(s){const a=document.createElement("option");a.value=s.value,a.textContent=s.label||s.value,s.value===i&&(a.selected=!0),n.appendChild(a)})},u.prototype._applyValidation=function(e,r){const t=this._fieldInput(e.name);if(!t)return;const n=k(e,r[e.name],r);let i=t.parentNode.querySelector(".fb-validation-error");n.length?(i||(i=document.createElement("div"),i.className="fb-validation-error",t.parentNode.appendChild(i)),i.textContent=n[0].message):i&&i.remove()},u.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const t=r.closest("form")||this._wrapper;let n=r;for(;n.parentNode&&n.parentNode!==t;)n=n.parentNode;return n},u.prototype.evaluate=function(e){const r=this._getValues(),t=this;let n;if(e&&this._depMap.has(e)){const i=this._depMap.get(e);n=this._fields.filter(function(s){return i.has(s.name)})}else n=this._fields;n.forEach(function(i){i.logic&&(t._applyVisibility(i,r),t._applyRequirement(i,r),t._applyCascade(i,r))}),this._applyTriggers(r)},u.prototype.init=function(){this._buildDepMap();const e=this;if(this._wrapper.querySelectorAll("input, select, textarea").forEach(function(n){const i=ne(n.getAttribute("name"));if(!i)return;const s=function(){e.evaluate(i)};n.addEventListener("input",s),n.addEventListener("change",s),e._listeners.push({el:n,event:"input",fn:s}),e._listeners.push({el:n,event:"change",fn:s});const a=e._fields.find(function(o){return o.name===i});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const o=function(){const c=e._getValues();e._applyValidation(a,c)};n.addEventListener("blur",o),e._listeners.push({el:n,event:"blur",fn:o})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(n){const i=n.getAttribute("data-chooser-field");if(!i)return;const s=function(){setTimeout(function(){e.evaluate(i)},0)};n.addEventListener("click",s),e._listeners.push({el:n,event:"click",fn:s})}),this._hasTriggers){const n=function(i){if(e._end&&!(i.type==="click"&&!(i.target&&i.target.closest&&i.target.closest(re)))){if(!e._end.spec.finish){i.preventDefault(),i.stopImmediatePropagation();return}e._wrapper.dataset.triggerBlocked!=="true"&&(i.preventDefault(),i.stopImmediatePropagation(),e._finishEnded())}};this._wrapper.addEventListener("click",n,!0),this._wrapper.addEventListener("submit",n,!0),this._listeners.push({el:this._wrapper,event:"click",fn:n,capture:!0}),this._listeners.push({el:this._wrapper,event:"submit",fn:n,capture:!0})}this._initialEval=!0,this.evaluate(),this._initialEval=!1},u.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn,!!e.capture)}),this._listeners=[],this._banners.forEach(function(e){e&&e.parentNode&&e.parentNode.removeChild(e)}),this._banners.clear(),this._syncEnd([])},u.prototype._applyTriggers=function(e){if(!this._hasTriggers)return;const r=B(this._fields,e);this._triggerState=r;const t=this._triggerApplied||{hidden:[],disabled:[],required:[]};t.hidden.forEach(n=>{r.hidden.indexOf(n)===-1&&this._setTriggerHidden(n,!1)}),r.hidden.forEach(n=>this._setTriggerHidden(n,!0)),t.disabled.forEach(n=>{r.disabled.indexOf(n)===-1&&this._setTriggerDisabled(n,!1)}),r.disabled.forEach(n=>this._setTriggerDisabled(n,!0)),t.required.forEach(n=>{r.required.indexOf(n)===-1&&this._restoreRequired(n,e)}),r.required.forEach(n=>this._setTriggerRequired(n,!0)),(t.masked||[]).forEach(n=>{r.masked.indexOf(n)===-1&&this._setTriggerMasked(n,!1)}),r.masked.forEach(n=>this._setTriggerMasked(n,!0)),this._triggerApplied={hidden:r.hidden.slice(),disabled:r.disabled.slice(),required:r.required.slice(),masked:r.masked.slice()},this._syncBanners(r.banners),this._syncSubmitBlock(r.blocks),this._syncEnd(r.ends),this._fireTriggerEvents(r)},u.prototype._setTriggerHidden=function(e,r){const t=this._findFieldWrapper(e);t&&(t.classList.toggle("fb-field-trigger-hidden",r),t.setAttribute("aria-hidden",String(r||t.classList.contains("fb-field-hidden"))))},u.prototype._setTriggerMasked=function(e,r){const t=this._findFieldWrapper(e);t&&(t.classList.toggle("fb-field-trigger-masked",r),t.setAttribute("aria-hidden",String(r||t.classList.contains("fb-field-hidden")||t.classList.contains("fb-field-trigger-hidden"))))},u.prototype._setTriggerDisabled=function(e,r){const t=this._findFieldWrapper(e);t&&t.classList.toggle("fb-field-disabled",r),this._fieldInputs(e).forEach(function(i){i.disabled=r});const n=this._wrapper.querySelector('[data-chooser-field="'+e+'"]');n&&(n.classList.toggle("fb-field-disabled",r),n.querySelectorAll('button, [role="radio"], [role="checkbox"]').forEach(function(i){r?i.setAttribute("aria-disabled","true"):i.removeAttribute("aria-disabled")}))},u.prototype._setTriggerRequired=function(e,r){const t=this._fieldInput(e),n=this._findFieldWrapper(e);if(n&&(n.setAttribute("aria-required",String(r)),n.classList.toggle("fb-field-required",r)),!!t){if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){t.removeAttribute("required");return}r?t.setAttribute("required",""):t.removeAttribute("required")}},u.prototype._restoreRequired=function(e,r){const t=this._fields.find(function(n){return n.name===e});t&&this._setTriggerRequired(e,w(t,r))},u.prototype._syncBanners=function(e){const r=new Map;e.forEach(function(t){r.set(t.key,t)}),this._banners.forEach(function(t,n){r.has(n)||(t.parentNode&&t.parentNode.removeChild(t),this._banners.delete(n))},this),this._dismissed.forEach(function(t){r.has(t)||this._dismissed.delete(t)},this),r.forEach(function(t,n){if(this._banners.has(n)){const a=this._banners.get(n).querySelector(".fb-trigger-banner-text");a&&a.textContent!==t.message&&(a.textContent=t.message);return}if(this._dismissed.has(n))return;const i=this._buildBanner(t,n);i&&this._banners.set(n,i)},this)},u.prototype._buildBanner=function(e,r){if(typeof document>"u"||!e.message)return null;const t=document.createElement("div");t.className="fb-trigger-banner fb-trigger-banner--"+(e.level||"info"),t.setAttribute("role",e.level==="error"?"alert":"status"),t.dataset.triggerKey=r;const n=document.createElement("span");if(n.className="fb-trigger-banner-text",n.textContent=e.message,t.appendChild(n),e.dismissible){const a=document.createElement("button");a.type="button",a.className="fb-trigger-banner-close",a.setAttribute("aria-label","Dismiss"),a.textContent="\xD7";const o=this;a.addEventListener("click",function(){o._dismissed.add(r),t.parentNode&&t.parentNode.removeChild(t),o._banners.delete(r)}),t.appendChild(a)}const i=this._findFieldWrapper(e.field),s=this._wrapper.querySelector("form")||this._wrapper;return e.position==="form-top"?s.insertBefore(t,s.firstChild):i&&i.parentNode?e.position==="field-above"?i.parentNode.insertBefore(t,i):i.parentNode.insertBefore(t,i.nextSibling):s.appendChild(t),t},u.prototype._syncSubmitBlock=function(e){const r=this._wrapper.querySelector("form")||this._wrapper,t=r.querySelector('button[type="submit"], input[type="submit"], .fb-form-submit'),n=e.length>0;this._wrapper.dataset.triggerBlocked=n?"true":"false",t&&(t.disabled=n,t.setAttribute("aria-disabled",String(n)));let i=r.querySelector(".fb-trigger-block-note");const s=e.filter(function(a){return!a.quiet}).map(function(a){return a.message});if(!s.length){i&&i.parentNode&&i.parentNode.removeChild(i);return}i||(i=document.createElement("p"),i.className="fb-trigger-block-note",i.setAttribute("role","status"),(t&&t.parentNode?t.parentNode:r).appendChild(i)),i.textContent=s.join(" ")};const re='button[type="submit"], input[type="submit"], .fb-form-submit, .wizard-next, .wizard-submit';u.prototype._primaryButton=function(){return this._wrapper.querySelector(".wizard-next, .wizard-submit")||this._wrapper.querySelector('button[type="submit"], input[type="submit"], .fb-form-submit')};function W(e){return!!(e.matches&&e.matches(".wizard-next, .wizard-submit"))}function D(e){return e.querySelector?e.querySelector(".fb-btn-label"):null}function ie(e){return e.tagName==="INPUT"?e.value:(D(e)||e).textContent}function H(e,r){if(e.tagName==="INPUT"){e.value=r;return}const t=D(e);(t||e).textContent=r}return u.prototype._syncEnd=function(e){const r=e&&e.length?e[0]:null,t=this._end;if(t&&(!r||t.spec.key!==r.key)&&(t.panel&&t.panel.parentNode&&t.panel.parentNode.removeChild(t.panel),t.button&&t.button.isConnected&&(t.spec.finish?H(t.button,t.label):W(t.button)&&(t.button.disabled=!1)),this._end=null),this._wrapper.dataset.triggerEnded=r?"true":"false",!r||typeof document>"u")return;if(this._end){const a=this._end.panel&&this._end.panel.querySelector(".fb-trigger-end-text");a&&a.textContent!==r.message&&(a.textContent=r.message),this._end.spec=r;return}let n=null;if(r.message){n=document.createElement("div"),n.className="fb-trigger-end",n.setAttribute("role","status"),n.dataset.triggerKey=r.key;const a=document.createElement("div");a.className="fb-trigger-end-text",a.textContent=r.message,n.appendChild(a);const o=this._findFieldWrapper(r.field);o&&o.parentNode?o.parentNode.insertBefore(n,o.nextSibling):(this._wrapper.querySelector("form")||this._wrapper).appendChild(n)}const i=this._primaryButton();let s="";i&&r.finish?(s=ie(i),H(i,r.finishLabel)):i&&W(i)&&(i.disabled=!0),this._end={spec:r,panel:n,button:i,label:s}},u.prototype._finishEnded=function(){const e=this._triggerState||{},r=new Set([].concat(e.masked||[],e.hidden||[],e.disabled||[])),t=this,n=this._fields.filter(function(a){return y(a)&&!r.has(a.name)&&t._fieldInput(a.name)}),i=this._getValues();(e.masked||[]).forEach(function(a){delete i[a]});const s=V(this._wrapper,n);(e.required||[]).forEach(function(a){const o=n.find(function(f){return f.name===a});if(!o)return;const c=i[a];(Array.isArray(c)?c.length===0:!String(c??"").trim())&&!s.missing.some(function(f){return f.name===a})&&(s.missing.push({name:a,label:o.label||a}),s.valid=!1)}),this._wrapper.dispatchEvent(new CustomEvent("dm-form-end",{bubbles:!0,detail:{values:i,validation:s,end:this._end?this._end.spec:null}}))},u.prototype._fireTriggerEvents=function(e){const r=new Set(e.active),t=this;e.events.forEach(function(n){t._triggerPrev.has(n.key)||n.action.once&&t._triggerFired.has(n.key)||t._initialEval&&n.action.onLoad!==!0||(t._triggerFired.add(n.key),t._runTriggerEvent(n))}),this._triggerPrev=r},u.prototype._runTriggerEvent=function(e){const r=e.action;switch(r.type){case"toast":typeof E<"u"&&E&&typeof E.toast=="function"&&E.toast(r.message||"",{type:r.level||"info",duration:Number(r.duration)||4e3});break;case"celebrate":this._celebrate(r);break;default:break}typeof CustomEvent<"u"&&this._wrapper.dispatchEvent&&this._wrapper.dispatchEvent(new CustomEvent("dm-form-trigger",{bubbles:!0,detail:{type:r.type,field:e.field,action:r}}))},u.prototype._celebrate=function(e){typeof window>"u"||typeof document>"u"||window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches||import("/public/js/celebrations/index.js").then(function(r){const t=r.CelebrationsEffect;let n=e.theme||"auto";if(n==="auto"&&(n=t.getCurrentTheme(),!n))return;const i=new t({theme:n,intensity:e.intensity||"medium",enabled:!0,zIndex:999});i.init().then(function(){i.start()})}).catch(function(){})},u.prototype.submitBlock=function(){const e=this._triggerState&&this._triggerState.blocks||[];return{blocked:e.length>0,reasons:e.map(function(r){return r.message})}},{evaluateCondition:_,evaluateConditionGroup:h,evaluateFieldVisibility:v,evaluateFieldRequirement:w,validateField:k,collectValues:$,validateFields:V,getCascadeOptions:T,resolveTriggerState:B,resolveTriggerTargets:b,fillTriggerText:O,triggerTokens:ee,hasTriggers:R,TRIGGER_ACTION_KINDS:C,SERVER_TRIGGER_ACTIONS:Y,FormLogicRuntime:u}});
|
|
1
|
+
(function(l,d){typeof module<"u"&&module.exports?module.exports=d():l.FormLogicEngine=d()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function l(e){return e===""||e===null||e===void 0?"":String(e)}function d(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 P={not_equals:"equals",not_contains:"contains",not_in:"in"};function q(e,r){const t=l(r),n=l(e.value);switch(e.operator){case"equals":return t===n;case"not_equals":return t!==n;case"contains":return t.toLowerCase().includes(n.toLowerCase());case"not_contains":return!t.toLowerCase().includes(n.toLowerCase());case"starts_with":return t.toLowerCase().startsWith(n.toLowerCase());case"ends_with":return t.toLowerCase().endsWith(n.toLowerCase());case"greater_than":{const i=d(r),s=d(e.value);return i!==null&&s!==null&&i>s}case"less_than":{const i=d(r),s=d(e.value);return i!==null&&s!==null&&i<s}case"is_empty":return p(r);case"is_not_empty":return!p(r);case"in":return(Array.isArray(e.value)?e.value.map(l):String(e.value).split(",").map(s=>s.trim())).includes(t);case"not_in":return!(Array.isArray(e.value)?e.value.map(l):String(e.value).split(",").map(s=>s.trim())).includes(t);case"matches_regex":try{const i=e.flags||"";return new RegExp(e.value,i).test(t)}catch(i){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,i&&i.message),!1}default:return!0}}function _(e,r){if(!e||!e.field||!e.operator)return!0;const t=r[e.field];if(!Array.isArray(t))return q(e,t);if(e.operator==="is_empty")return p(t);if(e.operator==="is_not_empty")return!p(t);const n=P[e.operator];if(n){const i=Object.assign({},e,{operator:n});return!t.some(s=>q(i,s))}return t.some(i=>q(e,i))}function h(e,r){return e?Array.isArray(e.all)?e.all.every(t=>t.all||t.any?h(t,r):_(t,r)):Array.isArray(e.any)?e.any.some(t=>t.all||t.any?h(t,r):_(t,r)):e.field&&e.operator?_(e,r):!0:!0}function v(e,r){const t=e.logic;if(!t||!t.visibility)return"visible";const n=t.visibility,i=n.conditions||[];for(const s of i)if(s.when&&h(s.when,r))return s.then==="hidden"?"hidden":"visible";return n.default==="hidden"?"hidden":"visible"}function w(e,r){const t=e.logic;if(!t||!t.requirement)return e.required||!1;const n=t.requirement,i=n.conditions||[];for(const s of i)if(s.when&&h(s.when,r))return s.then===!0;return n.default===!0}function A(e){if(e==null||e==="")return null;const r=Number(e);return Number.isFinite(r)?r:null}function j(e,r){if(p(r)||Array.isArray(r)||typeof r=="object")return[];const t=e.label||e.name;if(e.type==="number"){const a=Number(r);if(!Number.isFinite(a)||String(r).trim()==="")return[{message:`${t} must be a number.`}];const o=A(e.min),u=A(e.max);return o!==null&&a<o?[{message:`${t} must be at least ${o}.`}]:u!==null&&a>u?[{message:`${t} must be no more than ${u}.`}]:[]}const n=String(r).length,i=A(e.minLength),s=A(e.maxLength);return i!==null&&n<i?[{message:`${t} must be at least ${i} characters.`}]:s!==null&&n>s?[{message:`${t} must be no more than ${s} characters.`}]:[]}function k(e,r,t){const n=j(e,r),i=e.logic;if(!i||!Array.isArray(i.validation))return n;for(const s of i.validation)switch(s.type){case"regex":{if(!p(r))try{new RegExp(s.pattern||"",s.flags||"").test(l(r))||n.push({message:s.message||"Invalid format."})}catch{}break}case"match":{const a=t[s.field];!p(r)&&l(r)!==l(a)&&n.push({message:s.message||"Fields do not match."});break}}return n}function T(e,r){const t=e.logic;if(!t||!t.cascade||!t.cascade.sourceField)return null;const n=t.cascade,i=n.mapping||{},s=r[n.sourceField];if(Array.isArray(s)){const o=new Set,u=[];return s.forEach(function(g){const f=l(g);Object.prototype.hasOwnProperty.call(i,f)&&(i[f]||[]).forEach(function(x){const H=l(x&&x.value);o.has(H)||(o.add(H),u.push(x))})}),u.length?u:n.defaultOptions||null}const a=l(s);return Object.prototype.hasOwnProperty.call(i,a)?i[a]||[]:n.defaultOptions||null}const G={fade:250,slide:300,scale:200};function N(e,r){const t=Number(r);return!isFinite(t)||t<0||t>5e3?G[e]||250:Math.round(t)}function K(e,r,t){const n=N(r,t);if(r==="fade")e.style.transition="opacity "+n+"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=""},n+10)});else if(r==="slide"){const i=Math.round(n*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+n+"ms ease, opacity "+i+"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=""},n+20)})}else r==="scale"&&(e.style.transition="opacity "+n+"ms ease, transform "+n+"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=""},n+20)}))}function U(e,r,t){const n=N(r,t);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+n+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},n+10)});else if(r==="slide"){const i=Math.round(n*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+n+"ms ease, opacity "+i+"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=""},n+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+n+"ms ease, transform "+n+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},n+20)}))}const C={banner:"state","disable-fields":"state","hide-fields":"state","require-fields":"state","block-submit":"state","end-form":"state",toast:"event",celebrate:"event","goto-step":"event",redirect:"event","run-action":"event",notify:"event"},Y=["block-submit","hide-fields","disable-fields","require-fields","end-form","redirect","run-action","notify"];function y(e){return!!e&&!!e.name&&e.type!=="page-break"&&e.type!=="spacer"}function b(e,r,t){const n=(t||[]).filter(y),i=e.target||(e.fields&&e.fields.length?"listed":"rest");if(i==="listed"){const a=new Set(e.fields||[]);return n.filter(o=>a.has(o.name)&&o.name!==r.name).map(o=>o.name)}if(i==="all")return n.filter(a=>a.name!==r.name).map(a=>a.name);const s=n.findIndex(a=>a.name===r.name);return s===-1?[]:n.slice(s+1).map(a=>a.name)}function S(e,r){for(const t of r)e.includes(t)||e.push(t)}function X(e,r,t,n,i){if(!r||!r.type)return;const s=C[r.type];if(s){if(s==="event"){e.events.push({key:i,type:r.type,field:t.name,action:r});return}switch(r.type){case"banner":e.banners.push({key:i,field:t.name,message:r.message||"",level:r.level||"info",position:r.position||"field-below",dismissible:r.dismissible!==!1});break;case"hide-fields":S(e.hidden,b(r,t,n));break;case"disable-fields":S(e.disabled,b(r,t,n));break;case"require-fields":S(e.required,b(r,t,n));break;case"block-submit":e.blocks.push({key:i,message:r.message||"This form cannot be submitted yet."});break;case"end-form":S(e.masked,b({target:"rest"},t,n)),e.ends.push({key:i,field:t.name,message:r.message||"",finishLabel:r.finishLabel||"Finish",doneMessage:r.doneMessage||"",record:r.record!==!1,finish:r.finish!==!1}),r.finish===!1&&e.blocks.push({key:i,quiet:!0,message:r.message||"This form cannot be submitted."});break;default:break}}}const L=/\{\{\s*([A-Za-z_][A-Za-z0-9_-]*)\s*\}\}/g,Z=["password","file","image","signature"],F=200,J={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:" ",pound:"\xA3",euro:"\u20AC",copy:"\xA9",reg:"\xAE"};function I(e){return String(e).replace(/<[^>]*>/g,"").replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(r,t)=>{if(t[0]==="#"){const n=t[1]==="x"||t[1]==="X"?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return Number.isFinite(n)&&n>31?String.fromCodePoint(n):" "}return J[t.toLowerCase()]??r})}function M(e,r){const t=Array.isArray(e.options)?e.options:[];for(const n of t)if(n&&typeof n=="object"){if(String(n.value)===String(r))return I(n.label!=null?n.label:n.value)}else if(String(n)===String(r))return I(n);return String(r)}function Q(e,r){if(!e||Z.includes(e.type)||r==null||r===!1)return"";let t;return Array.isArray(r)?t=r.filter(n=>n!==""&&n!=null).map(n=>M(e,n)).join(", "):e.type==="checkbox"?t=r&&r!=="false"?"Yes":"":Array.isArray(e.options)&&e.options.length?t=r===""?"":M(e,r):t=String(r),t=t.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim(),t.length>F?t.slice(0,F-1).trimEnd()+"\u2026":t}function O(e,r,t,n){if(!e||typeof e!="string"||e.indexOf("{{")===-1)return e||"";const i=n instanceof Set?n:new Set(n||[]),s=new Map((r||[]).filter(y).map(a=>[a.name,a]));return e.replace(L,(a,o)=>{const u=s.get(o);return!u||i.has(o)?"":Q(u,(t||{})[o])})}function ee(e){const r=[];return String(e||"").replace(L,(t,n)=>(r.includes(n)||r.push(n),t)),r}function te(e,r,t){const n=new Set([...e.hidden,...e.disabled,...e.masked]);(r||[]).forEach(s=>{y(s)&&v(s,t)==="hidden"&&n.add(s.name)});const i=s=>O(s,r,t,n);e.banners.forEach(s=>{s.message=i(s.message)}),e.blocks.forEach(s=>{s.message=i(s.message)}),e.ends.forEach(s=>{s.message=i(s.message),s.doneMessage=i(s.doneMessage)}),e.events.forEach(s=>{s.type==="toast"&&s.action&&s.action.message&&(s.action=Object.assign({},s.action,{message:i(s.action.message)}))})}function B(e,r){const t={active:[],banners:[],hidden:[],disabled:[],required:[],blocks:[],events:[],masked:[],ends:[]};return(e||[]).forEach(n=>{!y(n)||!Array.isArray(n.triggers)||n.triggers.forEach((i,s)=>{if(!i||i.enabled===!1)return;const a=i.id||`${n.name}::${s}`,o=h(i.when,r),u=`${a}:${o?"then":"else"}`,g=o?i.then:i.otherwise;!Array.isArray(g)||!g.length||(t.active.push(u),g.forEach(f=>X(t,f,n,e,u)))})}),t.required=t.required.filter(n=>!t.hidden.includes(n)&&!t.masked.includes(n)),te(t,e,r||{}),t}function R(e){return(e||[]).some(r=>Array.isArray(r&&r.triggers)&&r.triggers.length>0)}function c(e,r,t){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,this._baseValues=t&&t.baseValues||null,this._hasTriggers=R(this._fields),this._triggerState=null,this._triggerPrev=new Set,this._triggerFired=new Set,this._triggerApplied={hidden:[],disabled:[],required:[],masked:[]},this._banners=new Map,this._dismissed=new Set,this._end=null}function m(e,r,t){const n=t||"",i=r||"";return n+'[name="'+e+'"]'+i+", "+n+'[name="'+e+'[]"]'+i}function ne(e){return String(e||"").replace(/\[\]$/,"")}c.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(m(e))},c.prototype._fieldInput=function(e){return this._wrapper.querySelector(m(e))},c.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const t=r.logic;if(!t)return;function n(i){if(!i)return;(i.all||i.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)):n(a)})}if(t.visibility&&(t.visibility.conditions||[]).forEach(function(i){n(i.when)}),t.requirement&&(t.requirement.conditions||[]).forEach(function(i){n(i.when)}),t.cascade&&t.cascade.sourceField){const i=t.cascade.sourceField;e._depMap.has(i)||e._depMap.set(i,new Set),e._depMap.get(i).add(r.name)}})};function $(e,r){const t={};return(r||[]).forEach(function(n){if(!n||!n.name)return;const i=e.querySelectorAll(m(n.name));if(!i.length)return;const s=i[0];if(s.type==="radio"){const a=e.querySelector(m(n.name,":checked"));t[n.name]=a?a.value:""}else if(s.type==="checkbox")if(i.length>1||/\[\]$/.test(s.name||"")){const a=[];i.forEach(function(o){o.checked&&a.push(o.value)}),t[n.name]=a}else t[n.name]=s.checked?s.value||"true":"";else t[n.name]=s.value}),t}function V(e,r){const t=$(e,r),n=[],i=[];return(r||[]).forEach(function(s){if(!s||!s.name||v(s,t)==="hidden")return;const a=t[s.name],o=Array.isArray(a)?a.length===0:!String(a??"").trim();if(w(s,t)&&o){n.push({name:s.name,label:s.label||s.name});return}if(o)return;const u=k(s,a,t);u.length&&i.push(u[0].message)}),{valid:n.length===0&&i.length===0,missing:n,errors:i,values:t}}c.prototype._getValues=function(){const e=this._baseValues?Object.assign({},this._baseValues):{};return this._fields.forEach(function(r){const t=this._fieldInputs(r.name);if(!t.length)return;const n=t[0];if(n.type==="radio"){const i=this._wrapper.querySelector(m(r.name,":checked"));e[r.name]=i?i.value:""}else if(n.type==="checkbox")if(t.length>1||/\[\]$/.test(n.name||"")){const i=[];t.forEach(function(s){s.checked&&i.push(s.value)}),e[r.name]=i}else e[r.name]=n.checked?n.value||"true":"";else e[r.name]=n.value},this),e},c.prototype._applyVisibility=function(e,r){const n=v(e,r)==="hidden",i=this._findFieldWrapper(e.name);if(!i)return;i.setAttribute("aria-hidden",String(n));const s=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(s==="none"){i.classList.toggle("fb-field-hidden",n);return}const a=e.logic?.visibility?.duration;i.style.transition="",n?K(i,s,a):U(i,s,a)},c.prototype._applyRequirement=function(e,r){const t=w(e,r),n=this._fieldInput(e.name);if(!n)return;if(/\[\]$/.test(n.name||"")||n.closest&&n.closest(".domma-chooser")){const s=this._findFieldWrapper(e.name);n.removeAttribute("required"),s&&(s.setAttribute("aria-required",String(t)),s.classList.toggle("fb-field-required",t));return}t?n.setAttribute("required",""):n.removeAttribute("required");const i=this._findFieldWrapper(e.name);i&&(i.setAttribute("aria-required",String(t)),i.classList.toggle("fb-field-required",t))},c.prototype._applyCascade=function(e,r){const t=T(e,r);if(t===null)return;const n=this._wrapper.querySelector(m(e.name,"","select"));if(!n)return;const i=n.value;n.textContent="",t.forEach(function(s){const a=document.createElement("option");a.value=s.value,a.textContent=s.label||s.value,s.value===i&&(a.selected=!0),n.appendChild(a)})},c.prototype._applyValidation=function(e,r){const t=this._fieldInput(e.name);if(!t)return;const n=k(e,r[e.name],r);let i=t.parentNode.querySelector(".fb-validation-error");n.length?(i||(i=document.createElement("div"),i.className="fb-validation-error",t.parentNode.appendChild(i)),i.textContent=n[0].message):i&&i.remove()},c.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const t=r.closest("form")||this._wrapper;let n=r;for(;n.parentNode&&n.parentNode!==t;)n=n.parentNode;return n},c.prototype.evaluate=function(e){const r=this._getValues(),t=this;let n;if(e&&this._depMap.has(e)){const i=this._depMap.get(e);n=this._fields.filter(function(s){return i.has(s.name)})}else n=this._fields;n.forEach(function(i){i.logic&&(t._applyVisibility(i,r),t._applyRequirement(i,r),t._applyCascade(i,r))}),this._applyTriggers(r)},c.prototype.init=function(){this._buildDepMap();const e=this;if(this._wrapper.querySelectorAll("input, select, textarea").forEach(function(n){const i=ne(n.getAttribute("name"));if(!i)return;const s=function(){e.evaluate(i)};n.addEventListener("input",s),n.addEventListener("change",s),e._listeners.push({el:n,event:"input",fn:s}),e._listeners.push({el:n,event:"change",fn:s});const a=e._fields.find(function(o){return o.name===i});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const o=function(){const u=e._getValues();e._applyValidation(a,u)};n.addEventListener("blur",o),e._listeners.push({el:n,event:"blur",fn:o})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(n){const i=n.getAttribute("data-chooser-field");if(!i)return;const s=function(){setTimeout(function(){e.evaluate(i)},0)};n.addEventListener("click",s),e._listeners.push({el:n,event:"click",fn:s})}),this._hasTriggers){const n=function(i){if(e._end&&!(i.type==="click"&&!(i.target&&i.target.closest&&i.target.closest(re)))){if(!e._end.spec.finish){i.preventDefault(),i.stopImmediatePropagation();return}e._wrapper.dataset.triggerBlocked!=="true"&&(i.preventDefault(),i.stopImmediatePropagation(),e._finishEnded())}};this._wrapper.addEventListener("click",n,!0),this._wrapper.addEventListener("submit",n,!0),this._listeners.push({el:this._wrapper,event:"click",fn:n,capture:!0}),this._listeners.push({el:this._wrapper,event:"submit",fn:n,capture:!0})}this._initialEval=!0,this.evaluate(),this._initialEval=!1},c.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn,!!e.capture)}),this._listeners=[],this._banners.forEach(function(e){e&&e.parentNode&&e.parentNode.removeChild(e)}),this._banners.clear(),this._syncEnd([])},c.prototype._applyTriggers=function(e){if(!this._hasTriggers)return;const r=B(this._fields,e);this._triggerState=r;const t=this._triggerApplied||{hidden:[],disabled:[],required:[]};t.hidden.forEach(n=>{r.hidden.indexOf(n)===-1&&this._setTriggerHidden(n,!1)}),r.hidden.forEach(n=>this._setTriggerHidden(n,!0)),t.disabled.forEach(n=>{r.disabled.indexOf(n)===-1&&this._setTriggerDisabled(n,!1)}),r.disabled.forEach(n=>this._setTriggerDisabled(n,!0)),t.required.forEach(n=>{r.required.indexOf(n)===-1&&this._restoreRequired(n,e)}),r.required.forEach(n=>this._setTriggerRequired(n,!0)),(t.masked||[]).forEach(n=>{r.masked.indexOf(n)===-1&&this._setTriggerMasked(n,!1)}),r.masked.forEach(n=>this._setTriggerMasked(n,!0)),this._triggerApplied={hidden:r.hidden.slice(),disabled:r.disabled.slice(),required:r.required.slice(),masked:r.masked.slice()},this._syncBanners(r.banners),this._syncSubmitBlock(r.blocks),this._syncEnd(r.ends),this._fireTriggerEvents(r)},c.prototype._setTriggerHidden=function(e,r){const t=this._findFieldWrapper(e);t&&(t.classList.toggle("fb-field-trigger-hidden",r),t.setAttribute("aria-hidden",String(r||t.classList.contains("fb-field-hidden"))))},c.prototype._setTriggerMasked=function(e,r){const t=this._findFieldWrapper(e);t&&(t.classList.toggle("fb-field-trigger-masked",r),t.setAttribute("aria-hidden",String(r||t.classList.contains("fb-field-hidden")||t.classList.contains("fb-field-trigger-hidden"))))},c.prototype._setTriggerDisabled=function(e,r){const t=this._findFieldWrapper(e);t&&t.classList.toggle("fb-field-disabled",r),this._fieldInputs(e).forEach(function(s){s.disabled=r});const n=this._wrapper.querySelector('[data-chooser-field="'+e+'"]');n&&(n.classList.toggle("fb-field-disabled",r),n.querySelectorAll('button, [role="radio"], [role="checkbox"]').forEach(function(s){r?s.setAttribute("aria-disabled","true"):s.removeAttribute("aria-disabled")}));const i=typeof window<"u"?window.E:null;if(i&&typeof i.get=="function"){const s=Array.prototype.slice.call(this._fieldInputs(e)),a=this._wrapper.querySelector('[data-dropzone-field="'+e+'"]');a&&s.push(a),s.forEach(function(o){const u=i.get(o,"dropzone");u&&typeof u.disable=="function"&&(r?u.disable():u.enable())})}},c.prototype._setTriggerRequired=function(e,r){const t=this._fieldInput(e),n=this._findFieldWrapper(e);if(n&&(n.setAttribute("aria-required",String(r)),n.classList.toggle("fb-field-required",r)),!!t){if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){t.removeAttribute("required");return}r?t.setAttribute("required",""):t.removeAttribute("required")}},c.prototype._restoreRequired=function(e,r){const t=this._fields.find(function(n){return n.name===e});t&&this._setTriggerRequired(e,w(t,r))},c.prototype._syncBanners=function(e){const r=new Map;e.forEach(function(t){r.set(t.key,t)}),this._banners.forEach(function(t,n){r.has(n)||(t.parentNode&&t.parentNode.removeChild(t),this._banners.delete(n))},this),this._dismissed.forEach(function(t){r.has(t)||this._dismissed.delete(t)},this),r.forEach(function(t,n){if(this._banners.has(n)){const a=this._banners.get(n).querySelector(".fb-trigger-banner-text");a&&a.textContent!==t.message&&(a.textContent=t.message);return}if(this._dismissed.has(n))return;const i=this._buildBanner(t,n);i&&this._banners.set(n,i)},this)},c.prototype._buildBanner=function(e,r){if(typeof document>"u"||!e.message)return null;const t=document.createElement("div");t.className="fb-trigger-banner fb-trigger-banner--"+(e.level||"info"),t.setAttribute("role",e.level==="error"?"alert":"status"),t.dataset.triggerKey=r;const n=document.createElement("span");if(n.className="fb-trigger-banner-text",n.textContent=e.message,t.appendChild(n),e.dismissible){const a=document.createElement("button");a.type="button",a.className="fb-trigger-banner-close",a.setAttribute("aria-label","Dismiss"),a.textContent="\xD7";const o=this;a.addEventListener("click",function(){o._dismissed.add(r),t.parentNode&&t.parentNode.removeChild(t),o._banners.delete(r)}),t.appendChild(a)}const i=this._findFieldWrapper(e.field),s=this._wrapper.querySelector("form")||this._wrapper;return e.position==="form-top"?s.insertBefore(t,s.firstChild):i&&i.parentNode?e.position==="field-above"?i.parentNode.insertBefore(t,i):i.parentNode.insertBefore(t,i.nextSibling):s.appendChild(t),t},c.prototype._syncSubmitBlock=function(e){const r=this._wrapper.querySelector("form")||this._wrapper,t=r.querySelector('button[type="submit"], input[type="submit"], .fb-form-submit'),n=e.length>0;this._wrapper.dataset.triggerBlocked=n?"true":"false",t&&(t.disabled=n,t.setAttribute("aria-disabled",String(n)));let i=r.querySelector(".fb-trigger-block-note");const s=e.filter(function(a){return!a.quiet}).map(function(a){return a.message});if(!s.length){i&&i.parentNode&&i.parentNode.removeChild(i);return}i||(i=document.createElement("p"),i.className="fb-trigger-block-note",i.setAttribute("role","status"),(t&&t.parentNode?t.parentNode:r).appendChild(i)),i.textContent=s.join(" ")};const re='button[type="submit"], input[type="submit"], .fb-form-submit, .wizard-next, .wizard-submit';c.prototype._primaryButton=function(){return this._wrapper.querySelector(".wizard-next, .wizard-submit")||this._wrapper.querySelector('button[type="submit"], input[type="submit"], .fb-form-submit')};function z(e){return!!(e.matches&&e.matches(".wizard-next, .wizard-submit"))}function W(e){return e.querySelector?e.querySelector(".fb-btn-label"):null}function ie(e){return e.tagName==="INPUT"?e.value:(W(e)||e).textContent}function D(e,r){if(e.tagName==="INPUT"){e.value=r;return}const t=W(e);(t||e).textContent=r}return c.prototype._syncEnd=function(e){const r=e&&e.length?e[0]:null,t=this._end;if(t&&(!r||t.spec.key!==r.key)&&(t.panel&&t.panel.parentNode&&t.panel.parentNode.removeChild(t.panel),t.button&&t.button.isConnected&&(t.spec.finish?D(t.button,t.label):z(t.button)&&(t.button.disabled=!1)),this._end=null),this._wrapper.dataset.triggerEnded=r?"true":"false",!r||typeof document>"u")return;if(this._end){const a=this._end.panel&&this._end.panel.querySelector(".fb-trigger-end-text");a&&a.textContent!==r.message&&(a.textContent=r.message),this._end.spec=r;return}let n=null;if(r.message){n=document.createElement("div"),n.className="fb-trigger-end",n.setAttribute("role","status"),n.dataset.triggerKey=r.key;const a=document.createElement("div");a.className="fb-trigger-end-text",a.textContent=r.message,n.appendChild(a);const o=this._findFieldWrapper(r.field);o&&o.parentNode?o.parentNode.insertBefore(n,o.nextSibling):(this._wrapper.querySelector("form")||this._wrapper).appendChild(n)}const i=this._primaryButton();let s="";i&&r.finish?(s=ie(i),D(i,r.finishLabel)):i&&z(i)&&(i.disabled=!0),this._end={spec:r,panel:n,button:i,label:s}},c.prototype._finishEnded=function(){const e=this._triggerState||{},r=new Set([].concat(e.masked||[],e.hidden||[],e.disabled||[])),t=this,n=this._fields.filter(function(a){return y(a)&&!r.has(a.name)&&t._fieldInput(a.name)}),i=this._getValues();(e.masked||[]).forEach(function(a){delete i[a]});const s=V(this._wrapper,n);(e.required||[]).forEach(function(a){const o=n.find(function(f){return f.name===a});if(!o)return;const u=i[a];(Array.isArray(u)?u.length===0:!String(u??"").trim())&&!s.missing.some(function(f){return f.name===a})&&(s.missing.push({name:a,label:o.label||a}),s.valid=!1)}),this._wrapper.dispatchEvent(new CustomEvent("dm-form-end",{bubbles:!0,detail:{values:i,validation:s,end:this._end?this._end.spec:null}}))},c.prototype._fireTriggerEvents=function(e){const r=new Set(e.active),t=this;e.events.forEach(function(n){t._triggerPrev.has(n.key)||n.action.once&&t._triggerFired.has(n.key)||t._initialEval&&n.action.onLoad!==!0||(t._triggerFired.add(n.key),t._runTriggerEvent(n))}),this._triggerPrev=r},c.prototype._runTriggerEvent=function(e){const r=e.action;switch(r.type){case"toast":typeof E<"u"&&E&&typeof E.toast=="function"&&E.toast(r.message||"",{type:r.level||"info",duration:Number(r.duration)||4e3});break;case"celebrate":this._celebrate(r);break;default:break}typeof CustomEvent<"u"&&this._wrapper.dispatchEvent&&this._wrapper.dispatchEvent(new CustomEvent("dm-form-trigger",{bubbles:!0,detail:{type:r.type,field:e.field,action:r}}))},c.prototype._celebrate=function(e){typeof window>"u"||typeof document>"u"||window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches||import("/public/js/celebrations/index.js").then(function(r){const t=r.CelebrationsEffect;let n=e.theme||"auto";if(n==="auto"&&(n=t.getCurrentTheme(),!n))return;const i=new t({theme:n,intensity:e.intensity||"medium",enabled:!0,zIndex:999});i.init().then(function(){i.start()})}).catch(function(){})},c.prototype.submitBlock=function(){const e=this._triggerState&&this._triggerState.blocks||[];return{blocked:e.length>0,reasons:e.map(function(r){return r.message})}},{evaluateCondition:_,evaluateConditionGroup:h,evaluateFieldVisibility:v,evaluateFieldRequirement:w,validateField:k,collectValues:$,validateFields:V,getCascadeOptions:T,resolveTriggerState:B,resolveTriggerTargets:b,fillTriggerText:O,triggerTokens:ee,hasTriggers:R,TRIGGER_ACTION_KINDS:C,SERVER_TRIGGER_ACTIONS:Y,FormLogicRuntime:c}});
|
package/public/js/forms.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{installSmoothCarets as
|
|
2
|
-
`).replace(/<[^>]+>/g,""))}function A(n){return String(n).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function q(n,o){let t=!1;n.addEventListener("dm-form-end",function(e){const i=e.detail&&e.detail.validation;if(i&&!i.valid){markInvalidFields(n,i.missing),showValidationPopup(i);return}t||(t=!0,n.classList.add("fb-form-loading"),Promise.resolve(o(e.detail&&e.detail.values||{})).catch(function(){}).finally(function(){t=!1,n.classList.remove("fb-form-loading")}))})}function C(n,o,t){const e=n.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,n.appendChild(i)}function B(n,o){if(n._formLogicRuntime=o,n._formLogicObserver&&(n._formLogicObserver.disconnect(),n._formLogicObserver=null),!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const i of e)for(const r of i.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}),n._formLogicObserver=t}function G(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function R(n,o){const t={};return n.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 s={type:r,label:e.label||e.name,required:G(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&&(s.minLength=e.minLength),e.maxLength!==void 0&&(s.maxLength=e.maxLength),e.min!==void 0&&(s.min=e.min),e.max!==void 0&&(s.max=e.max),i&&(e.variant&&(s.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(s.multiple=!0),e.density&&(s.density=e.density),e.columns&&(s.columns=e.columns),e.accent&&(s.accent=e.accent),e.accentStyle&&(s.accentStyle=e.accentStyle),e.glow&&(s.glow=!0),e.glowColour&&(s.glowColour=e.glowColour),e.shadow&&(s.shadow=e.shadow),e.shadowColour&&(s.shadowColour=e.shadowColour)),t[e.name]=s}),t}function Q(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 O(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")})}const z="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 P(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 i=document.createElement("strong");i.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=z+"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 s=c=>{c.key==="Escape"&&a()};function a(){document.removeEventListener("keydown",s),o.remove()}return r.addEventListener("click",a),o.addEventListener("click",c=>{c.target===o&&a()}),document.addEventListener("keydown",s),document.body.appendChild(o),{body:l,close:a}}function X(n){const{body:o,close:t}=P("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(s=>{const a=document.createElement("button");a.type="button",a.title=s,a.dataset.iconName=s,a.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 c=document.createElement("span");return c.setAttribute("data-icon",s),c.setAttribute("data-icon-size","18"),a.appendChild(c),a.addEventListener("mouseenter",()=>{a.style.borderColor="var(--dm-border)"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="transparent"}),a.addEventListener("click",()=>{t(),n(s)}),i.appendChild(a),a});if(!r.length){const s=document.createElement("p");s.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(s)}window.I?.scan?.(i),e.addEventListener("input",()=>{const s=e.value.trim().toLowerCase();l.forEach(a=>{a.style.display=!s||a.dataset.iconName.includes(s)?"":"none"})}),e.focus()}async function Z(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(n),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 ee(n){const{body:o,close:t}=P("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),Z().then(({files:i,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(!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(s=>{const a=document.createElement("button");a.type="button",a.title=s.name||s.url,a.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 c=document.createElement("img");c.src=s.url,c.alt=s.name||"",c.loading="lazy",c.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const m=document.createElement("span");m.textContent=s.name||s.url,m.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",a.appendChild(c),a.appendChild(m),a.addEventListener("click",()=>{t(),n(s.url)}),l.appendChild(a)}),o.appendChild(l)})}function D(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function M(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 V(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=z,o}function te(n){if(!window.I||typeof I.list!="function")return;const o=M(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 i=V("Browse");i.addEventListener("click",()=>X(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}function ne(n){const o=M(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 i=V("Browse");i.addEventListener("click",()=>ee(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}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 i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?te(i):ne(i))})}function N(n,o){const t=document.createElement("div");t.className="fb-form-honeypot",t.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=n.querySelector('[name="website"]')?"_website":"website",t.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",t.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),t.appendChild(i),n.appendChild(t)}function W(n,o){const t=n.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 s=e[i];if(s)t.insertBefore(l,s);else{const a=t.querySelector('[type="submit"]');a?t.insertBefore(l,a):t.appendChild(l)}}else r.type!=="page-break"&&i++})}function L(n,o){!n||!o||n.querySelectorAll('input[type="file"]').forEach(function(t){t.name&&t.files&&t.files.length&&o.set(t.name,Array.from(t.files))})}function x(n,o,t,e,i,r){const l=i||e,s=l.querySelector(".fb-form-honeypot"),a=s?.querySelector('input[type="text"]')?.value||"",c=s?.querySelector('[name="_t"]')?.value||"",m=Object.assign({},o);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName];const d=new Map(r||[]);L(l,d);const u=d.size>0;let p,b;if(u){const h=new FormData;for(const[g,v]of Object.entries(m))v!=null&&(d.has(g)||h.append(g,typeof v=="object"?JSON.stringify(v):String(v)));for(const[g,v]of d)for(const w of v)h.append(g,w,w.name);h.append("_hp",a),h.append("_t",c),p=h,b={}}else{const h=Object.assign({},m,{_hp:a,_t:c});p=JSON.stringify(h),b={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:b,body:p}).then(h=>h.json().then(g=>({ok:h.ok,body:g}))).then(h=>{h.ok&&h.body.ok?(e.textContent="",C(e,h.body.message||t.successMessage||"Thank you.","success")):C(e,h.body.error||"Something went wrong.","error")}).catch(()=>{C(e,"Unable to submit. Please check your connection.","error")})}function oe(n,o,t,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(a){const c=document.createElement("div");c.className="form-group",c.style.marginBottom="1.25rem",a.name&&(c.dataset.field=a.name);const m=document.createElement("label");if(m.className="form-label",m.textContent=a.label||a.name,a.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;a.type==="textarea"?(d=document.createElement("textarea"),d.rows=a.formConfig?.rows||4,d.className="form-input"):a.type==="select"?(d=document.createElement("select"),d.className="form-input",(a.options||[]).forEach(function(u){const p=document.createElement("option");p.value=typeof u=="string"?u:u.value??"",p.textContent=typeof u=="string"?u:u.label||p.value,d.appendChild(p)})):(d=document.createElement("input"),d.type=a.type==="icon"||a.type==="image"?"text":a.type||"text",d.className="form-input",a.placeholder&&(d.placeholder=a.placeholder),a.type==="file"&&(a.file?.accept&&(d.accept=a.file.accept),a.multiple&&(d.multiple=!0))),d.name=a.name,d.required=a.required||!1,c.appendChild(m),c.appendChild(d),r.appendChild(c)}),t.honeypot&&N(r);const l=document.createElement("button");if(l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",Y(t,"stacked").length||K(t)){const a=document.createElement("div");a.className="form-group form-buttons",a.appendChild(l),r.appendChild(a)}else r.appendChild(l);if(r.addEventListener("submit",function(a){a.preventDefault();const c={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(c[m.name]=d.value)}),window.FormLogicEngine&&i){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(p){if(m.evaluateFieldVisibility(p,c)==="hidden"){delete c[p.name];return}const h=m.evaluateFieldRequirement(p,c),g=c[p.name];h&&(!g||!String(g).trim())&&d.push(p.label||p.name);const v=m.validateField(p,g||"",c);v.length&&u.push(v[0].message)}),d.length||u.length){const p=[];d.length&&p.push("Required: "+d.join(", ")),u.length&&p.push(u.join("; ")),C(n,p.join(". "),"error");return}}if(n.dataset.triggerBlocked==="true"){const m=n._formLogicRuntime,d=m&&m.submitBlock?m.submitBlock().reasons:[];C(n,d.join(" ")||"This form cannot be submitted yet.","error");return}n.classList.add("fb-form-loading"),l.disabled=!0,x(e,c,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),_(r,t,"stacked"),T(r,t,o),enhancePickerFields(n,o),q(n,function(a){return x(e,a,t,n,r)}),window.FormLogicEngine&&i&&F(o)){const a=new window.FormLogicEngine.FormLogicRuntime(i,n);a.init(),n._formLogicRuntime=a}}function re(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||[],i=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(s=>s.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const s=Number(i.columns)===3?3:2,a=i.layout||"grid";if(l&&Domma.forms.wizard){const c=U(e,t.title),m=c.map(f=>f.fields),d=c.map(function(f){return{title:f.title,description:f.description,fields:R(f.fields,s)}});let u=0,p=null,b=null;const h=Date.now(),g=new Map,v=function(f){const y=window.FormLogicEngine;if(!y||!y.validateFields)return;const k=y.validateFields(r,m[u]||[]);k.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(r,k.missing),showValidationPopup(k))},w=function(){const f=m[u]||e;if(H(r,i),T(r,i,f),O(r,f),enhancePickerFields(r,f),f.some(y=>y.type==="spacer")&&W(r,f),i.honeypot){const y=r.querySelector("form");y&&N(y,h)}window.FormLogicEngine&&F(e)&&(p&&p.destroy(),p=new window.FormLogicEngine.FormLogicRuntime(t,r,{baseValues:b&&b.getStepData?b.getStepData():{}}),p.init(),B(r,p)),r.querySelectorAll(".wizard-next, .wizard-submit").forEach(y=>y.addEventListener("click",v,!0))};b=Domma.forms.wizard(r,{schema:{steps:d},layout:a,columns:s,finishText:i.submitText||"Finish",onStepChange:function(f){L(r,g),u=f,setTimeout(w,0)},onSubmit:function(f){return L(r,g),x(o,f,i,r,null,g)}}),q(r,function(f){return L(r,g),x(o,f,i,r,null,g)}),r.addEventListener("dm-form-trigger",function(f){if(!f.detail||f.detail.type!=="goto-step"||!b||!b.goToStep)return;const y=Number(f.detail.action.step);!isFinite(y)||y<0||y>=d.length||y!==u&&b.goToStep(y)}),Promise.resolve(b).then(w)}else if(Domma.forms.render){const c=R(e,s),m=Q(e);q(r,function(u){return x(o,u,i,r,null)});const d=Domma.forms.render(r,c,m,{submitText:i.submitText||"Submit",layout:a,columns:s,onSubmit:function(u){return x(o,u,i,r,null)}});Promise.resolve(d).then(function(){if(_(r,i,a),T(r,i,e),O(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&F(e)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),B(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),i.honeypot){const u=r.querySelector("form");u&&N(u)}})}}else oe(r,e.filter(s=>s.type!=="page-break"&&s.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;",n.appendChild(e),console.warn("[forms]",t.message)})}
|
|
1
|
+
import{installSmoothCarets as H}from"/public/js/smooth-caret.js";import{buildWizardSteps as K}from"/public/js/form-steps.mjs";import{applyFormClasses as F,applySubmitButtons as _,applyWizardButtons as J,resolveSecondaryButton as Y,submitWrapperClasses as $}from"/public/js/form-submit.mjs";import{captureFileFields as L,checkFileInputs as G,destroyDropzones as Q,enhanceFileInputs as X,fileBlueprint as Z,restoreFileFields as ee,splitFiles as te,submitBody as ne,wireFileFields as j}from"/public/js/form-files.mjs";H(document);const B=document.querySelectorAll("[data-form]");B.length&&B.forEach(me);function T(t){return(t||[]).some(o=>o.logic||Array.isArray(o.triggers)&&o.triggers.length)}function oe(t,o){const n=t.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||t.querySelector('[data-chooser-field="'+o+'"]');if(!n)return null;const e=n.closest("form")||t;let i=n;for(;i.parentNode&&i.parentNode!==e;)i=i.parentNode;return i}export function markInvalidFields(t,o){t.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let n=null;(o||[]).forEach(function(e){const i=oe(t,e.name);i&&(i.classList.add("fb-field-invalid"),n||(n=i))}),n&&n.scrollIntoView&&n.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(t){const o=(t.missing||[]).map(e=>"<strong>"+R(e.label)+"</strong> is required.").concat((t.errors||[]).map(R)),n=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(n,{title:"Please complete this step"});return}window.alert(o.join(`
|
|
2
|
+
`).replace(/<[^>]+>/g,""))}function R(t){return String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function q(t,o){let n=!1;t.addEventListener("dm-form-end",function(e){const i=e.detail&&e.detail.validation;if(i&&!i.valid){markInvalidFields(t,i.missing),showValidationPopup(i);return}n||(n=!0,t.classList.add("fb-form-loading"),Promise.resolve(o(e.detail&&e.detail.values||{})).catch(function(){}).finally(function(){n=!1,t.classList.remove("fb-form-loading")}))})}function v(t,o,n){const e=t.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=n==="success"?"fb-form-success":"fb-form-error",i.textContent=o,t.appendChild(i)}function A(t,o){if(t._formLogicRuntime=o,t._formLogicObserver&&(t._formLogicObserver.disconnect(),t._formLogicObserver=null),!t.parentNode||typeof MutationObserver>"u"||t._formLogicObserved)return;t._formLogicObserved=!0;const n=new MutationObserver(function(e){for(const i of e)for(const r of i.removedNodes)if(r===t||r.nodeType===1&&r.contains&&r.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),n.disconnect();return}});n.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=n}function re(t){const o=t&&t.logic;return!!(o&&(o.visibility||o.requirement))}function z(t,o){const n={};return t.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,d={...e.formConfig||{}};d.span==="full"&&o&&(d.span=o);const s={type:r,label:e.label||e.name,required:re(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...d}};e.minLength!==void 0&&(s.minLength=e.minLength),e.maxLength!==void 0&&(s.maxLength=e.maxLength),e.min!==void 0&&(s.min=e.min),e.max!==void 0&&(s.max=e.max),i&&(e.variant&&(s.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(s.multiple=!0),e.density&&(s.density=e.density),e.columns&&(s.columns=e.columns),e.accent&&(s.accent=e.accent),e.accentStyle&&(s.accentStyle=e.accentStyle),e.glow&&(s.glow=!0),e.glowColour&&(s.glowColour=e.glowColour),e.shadow&&(s.shadow=e.shadow),e.shadowColour&&(s.shadowColour=e.shadowColour)),n[e.name]=e.type==="file"?Z(e,s):s}),n}function ie(t){const o={};return t.forEach(function(n){if(!(!n.name||n.type==="page-break"||n.type==="spacer")&&(n.type==="select"||n.type==="multiselect")&&n.required){const e=(n.options||[])[0];e&&(o[n.name]=typeof e=="object"?e.value:e)}}),o}function P(t,o){(o||[]).forEach(function(n){if(n.type!=="date"||!n.name)return;const e=t.querySelector('[name="'+n.name+'"]');e&&e.type!=="date"&&(e.type="date")})}const O="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 D(t){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 n=document.createElement("div");n.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=t;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=O+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(r),n.appendChild(e);const d=document.createElement("div");d.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",n.appendChild(d),o.appendChild(n);const s=l=>{l.key==="Escape"&&a()};function a(){document.removeEventListener("keydown",s),o.remove()}return r.addEventListener("click",a),o.addEventListener("click",l=>{l.target===o&&a()}),document.addEventListener("keydown",s),document.body.appendChild(o),{body:d,close:a}}function ae(t){const{body:o,close:n}=D("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():[],d=r.map(s=>{const a=document.createElement("button");a.type="button",a.title=s,a.dataset.iconName=s,a.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 l=document.createElement("span");return l.setAttribute("data-icon",s),l.setAttribute("data-icon-size","18"),a.appendChild(l),a.addEventListener("mouseenter",()=>{a.style.borderColor="var(--dm-border)"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="transparent"}),a.addEventListener("click",()=>{n(),t(s)}),i.appendChild(a),a});if(!r.length){const s=document.createElement("p");s.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(s)}window.I?.scan?.(i),e.addEventListener("input",()=>{const s=e.value.trim().toLowerCase();d.forEach(a=>{a.style.display=!s||a.dataset.iconName.includes(s)?"":"none"})}),e.focus()}async function se(){const t=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!t)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let n;try{if(n=await o(t),n.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),n=await o(r)}}}catch{return{error:"load"}}if(!n.ok)return{error:n.status===401||n.status===403?"auth":"load"};const e=await n.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function ce(t){const{body:o,close:n}=D("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),se().then(({files:i,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(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const d=document.createElement("div");d.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(s=>{const a=document.createElement("button");a.type="button",a.title=s.name||s.url,a.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 l=document.createElement("img");l.src=s.url,l.alt=s.name||"",l.loading="lazy",l.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const f=document.createElement("span");f.textContent=s.name||s.url,f.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",a.appendChild(l),a.appendChild(f),a.addEventListener("click",()=>{n(),t(s.url)}),d.appendChild(a)}),o.appendChild(d)})}function M(t,o){t.value=o,t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0}))}function V(t){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",t.parentNode.insertBefore(o,t),o.appendChild(t),t.style.flex="1",t.style.minWidth="0",o}function W(t){const o=document.createElement("button");return o.type="button",o.textContent=t,o.style.cssText=O,o}function le(t){if(!window.I||typeof I.list!="function")return;const o=V(t),n=document.createElement("span");n.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=()=>{n.textContent="";const r=t.value.trim();if(!r)return;const d=document.createElement("span");d.setAttribute("data-icon",r),d.setAttribute("data-icon-size","16"),n.appendChild(d),window.I?.scan?.(n)};t.addEventListener("input",e),e();const i=W("Browse");i.addEventListener("click",()=>ae(r=>{M(t,r),e()})),o.appendChild(n),o.appendChild(i)}function ue(t){const o=V(t),n=document.createElement("img");n.alt="",n.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=t.value.trim();n.style.display=r?"":"none",r&&(n.src=r)};t.addEventListener("input",e),e();const i=W("Browse");i.addEventListener("click",()=>ce(r=>{M(t,r),e()})),o.appendChild(n),o.appendChild(i)}export function enhancePickerFields(t,o){const n=typeof t=="string"?document.querySelector(t):t;n&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=n.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?le(i):ue(i))})}function N(t,o){const n=document.createElement("div");n.className="fb-form-honeypot",n.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=t.querySelector('[name="website"]')?"_website":"website",n.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",n.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),n.appendChild(i),t.appendChild(n)}function U(t,o){const n=t.querySelector("form");if(!n)return;const e=Array.from(n.querySelectorAll(".form-group"));let i=0;o.forEach(function(r){if(r.type==="spacer"){const d=document.createElement("div");d.className="fb-spacer";const s=e[i];if(s)n.insertBefore(d,s);else{const a=n.querySelector('[type="submit"]');a?n.insertBefore(d,a):n.appendChild(d)}}else r.type!=="page-break"&&i++})}function x(t,o,n,e,i,r,d){const s=i||e,a=s.querySelector(".fb-form-honeypot"),l=a?.querySelector('input[type="text"]')?.value||"",f=a?.querySelector('[name="_t"]')?.value||"",u=Object.assign({},o);delete u._t,a?.dataset.hpName&&delete u[a.dataset.hpName];const c=new Map(r||[]);L(s,c);const h=te(u,d,c),{body:p,headers:w}=ne(Object.assign(h.values,{_hp:l,_t:f}),h.files);return fetch("/api/forms/submit/"+t,{method:"POST",headers:w,body:p}).then(g=>g.json().then(b=>({ok:g.ok,body:b}))).then(g=>{g.ok&&g.body.ok?(Q(e),e.textContent="",v(e,g.body.message||n.successMessage||"Thank you.","success")):v(e,g.body.error||"Something went wrong.","error")}).catch(()=>{v(e,"Unable to submit. Please check your connection.","error")})}function de(t,o,n,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(a){const l=document.createElement("div");l.className="form-group",l.style.marginBottom="1.25rem",a.name&&(l.dataset.field=a.name);const f=document.createElement("label");if(f.className="form-label",f.textContent=a.label||a.name,a.required){const c=document.createElement("span");c.textContent=" *",c.style.color="var(--dm-danger)",f.appendChild(c)}let u;a.type==="textarea"?(u=document.createElement("textarea"),u.rows=a.formConfig?.rows||4,u.className="form-input"):a.type==="select"?(u=document.createElement("select"),u.className="form-input",(a.options||[]).forEach(function(c){const h=document.createElement("option");h.value=typeof c=="string"?c:c.value??"",h.textContent=typeof c=="string"?c:c.label||h.value,u.appendChild(h)})):(u=document.createElement("input"),u.type=a.type==="icon"||a.type==="image"?"text":a.type||"text",u.className="form-input",a.placeholder&&(u.placeholder=a.placeholder),a.type==="file"&&(a.file?.accept&&(u.accept=a.file.accept),a.multiple&&(u.multiple=!0))),u.name=a.name,u.required=a.required||!1,l.appendChild(f),l.appendChild(u),r.appendChild(l)}),n.honeypot&&N(r);const d=document.createElement("button");if(d.type="submit",d.className="btn btn-primary",d.textContent=n.submitText||"Submit",$(n,"stacked").length||Y(n)){const a=document.createElement("div");a.className="form-group form-buttons",a.appendChild(d),r.appendChild(a)}else r.appendChild(d);if(r.addEventListener("submit",function(a){a.preventDefault();const l={};if(o.forEach(function(u){const c=r.querySelector('[name="'+u.name+'"]');c&&(l[u.name]=c.value)}),window.FormLogicEngine&&i){const u=window.FormLogicEngine,c=[],h=[];if(o.forEach(function(p){if(u.evaluateFieldVisibility(p,l)==="hidden"){delete l[p.name];return}const g=u.evaluateFieldRequirement(p,l),b=l[p.name];g&&(!b||!String(b).trim())&&c.push(p.label||p.name);const C=u.validateField(p,b||"",l);C.length&&h.push(C[0].message)}),c.length||h.length){const p=[];c.length&&p.push("Required: "+c.join(", ")),h.length&&p.push(h.join("; ")),v(t,p.join(". "),"error");return}}const f=G(r,o);if(f.length){v(t,f.join(" "),"error");return}if(t.dataset.triggerBlocked==="true"){const u=t._formLogicRuntime,c=u&&u.submitBlock?u.submitBlock().reasons:[];v(t,c.join(" ")||"This form cannot be submitted yet.","error");return}t.classList.add("fb-form-loading"),d.disabled=!0,x(e,l,n,t,r,null,o).finally(function(){t.classList.remove("fb-form-loading"),d.disabled=!1})}),t.appendChild(r),_(r,n,"stacked"),F(r,n,o),enhancePickerFields(t,o),X(t,o),q(t,function(a){return x(e,a,n,t,r,null,o)}),window.FormLogicEngine&&i&&T(o)){const a=new window.FormLogicEngine.FormLogicRuntime(i,t);a.init(),t._formLogicRuntime=a}}function me(t){const o=t.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(n=>{if(!n.ok)throw new Error("Form not found: "+o);return n.json()}).then(n=>{const e=n.fields||[],i=n.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",t.appendChild(r);const d=e.some(s=>s.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const s=Number(i.columns)===3?3:2,a=i.layout||"grid";if(d&&Domma.forms.wizard){const l=K(e,n.title),f=l.map(m=>m.fields),u=l.map(function(m){return{title:m.title,description:m.description,fields:z(m.fields,s)}});let c=0,h=null,p=null;const w=Date.now(),g=new Map;j(r,e);const b=function(m){const y=window.FormLogicEngine;if(!y||!y.validateFields)return;const k=y.validateFields(r,f[c]||[]);k.valid||(m.preventDefault(),m.stopImmediatePropagation(),markInvalidFields(r,k.missing),showValidationPopup(k))},C=function(){const m=f[c]||e;if(J(r,i),F(r,i,m),P(r,m),enhancePickerFields(r,m),ee(r,g),m.some(y=>y.type==="spacer")&&U(r,m),i.honeypot){const y=r.querySelector("form");y&&N(y,w)}window.FormLogicEngine&&T(e)&&(h&&h.destroy(),h=new window.FormLogicEngine.FormLogicRuntime(n,r,{baseValues:p&&p.getStepData?p.getStepData():{}}),h.init(),A(r,h)),r.querySelectorAll(".wizard-next, .wizard-submit").forEach(y=>y.addEventListener("click",b,!0))};p=Domma.forms.wizard(r,{schema:{steps:u},layout:a,columns:s,finishText:i.submitText||"Finish",onStepChange:function(m){L(r,g),c=m,setTimeout(C,0)},onSubmit:function(m){return L(r,g),x(o,m,i,r,null,g,e)}}),q(r,function(m){return L(r,g),x(o,m,i,r,null,g,e)}),r.addEventListener("dm-form-trigger",function(m){if(!m.detail||m.detail.type!=="goto-step"||!p||!p.goToStep)return;const y=Number(m.detail.action.step);!isFinite(y)||y<0||y>=u.length||y!==c&&p.goToStep(y)}),Promise.resolve(p).then(C)}else if(Domma.forms.render){const l=z(e,s),f=ie(e);j(r,e),q(r,function(c){return x(o,c,i,r,null,null,e)});const u=Domma.forms.render(r,l,f,{submitText:i.submitText||"Submit",layout:a,columns:s,onSubmit:function(c){return x(o,c,i,r,null,null,e)}});Promise.resolve(u).then(function(){if(_(r,i,a),F(r,i,e),P(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&T(e)){const c=new window.FormLogicEngine.FormLogicRuntime(n,r);c.init(),A(r,c)}if(e.some(c=>c.type==="spacer")&&U(r,e),i.honeypot){const c=r.querySelector("form");c&&N(c)}})}}else de(r,e.filter(s=>s.type!=="page-break"&&s.type!=="spacer"),i,o,n)}).catch(n=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",t.appendChild(e),console.warn("[forms]",n.message)})}
|