domma-cms 0.55.1 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +130 -2
- package/README.md +4 -4
- package/admin/css/admin.css +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +3 -3
- package/admin/js/lib/page-picker.js +1 -0
- package/admin/js/lib/plugin-accent.js +1 -0
- package/admin/js/lib/plugin-chrome.js +1 -0
- package/admin/js/lib/shortcode-context-menu.js +2 -2
- package/admin/js/lib/sidebar-grouping.js +1 -1
- package/admin/js/lib/sidebar-grouping.test.js +1 -1
- package/admin/js/lib/sidebar-renderer.js +4 -4
- package/admin/js/lib/slideover-resizable.js +1 -0
- package/admin/js/templates/context-menu-editor.html +212 -0
- package/admin/js/templates/context-menus.html +16 -0
- package/admin/js/templates/plugin-code.html +1 -1
- package/{plugins/site-search/admin/templates/site-search.html → admin/js/templates/search.html} +50 -4
- package/admin/js/templates/settings.html +16 -97
- package/admin/js/templates/theme.html +173 -0
- package/admin/js/views/context-menu-editor.js +55 -0
- package/admin/js/views/context-menus.js +5 -0
- package/admin/js/views/form-editor.js +7 -7
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/plugin-marketplace.js +1 -1
- package/admin/js/views/plugins.js +25 -23
- package/admin/js/views/search.js +1 -0
- package/admin/js/views/settings.js +3 -3
- package/admin/js/views/theme.js +1 -0
- package/bin/cli.js +2 -0
- package/bin/update.js +13 -2
- package/config/menus/admin-sidebar.json +129 -23
- package/config/plugins.json +5 -5
- package/config/search.json +13 -0
- package/config/theme.json +18 -0
- package/package.json +12 -4
- package/plugins/_lib/admin/mail/compose-window.js +914 -0
- package/plugins/_lib/admin/mail/contacts.js +301 -0
- package/plugins/_lib/admin/mail/diagnostics-section.js +133 -0
- package/plugins/_lib/admin/mail/folder-tree.js +254 -0
- package/plugins/_lib/admin/mail/identity.js +480 -0
- package/plugins/_lib/admin/mail/image-senders-section.js +131 -0
- package/plugins/_lib/admin/mail/keyboard.js +136 -0
- package/plugins/_lib/admin/mail/mail.css +1 -0
- package/plugins/_lib/admin/mail/mail.html +71 -0
- package/plugins/_lib/admin/mail/panes.js +253 -0
- package/plugins/_lib/admin/mail/reader-view.js +4453 -0
- package/plugins/_lib/admin/mail/resizable.js +26 -0
- package/plugins/_lib/admin/mail/rules.js +343 -0
- package/plugins/_lib/admin/mail/scheduling.js +203 -0
- package/plugins/_lib/admin/mail/section-kit.js +277 -0
- package/plugins/_lib/admin/mail/templates.js +238 -0
- package/plugins/_lib/admin/mail/threads.js +200 -0
- package/plugins/_lib/admin/mail/vacation.js +269 -0
- package/plugins/_lib/admin/ui/help.css +1 -0
- package/plugins/_lib/admin/ui/help.js +174 -0
- package/plugins/_lib/admin/ui/resizable.js +151 -0
- package/plugins/_lib/dataStore.js +117 -0
- package/plugins/_lib/mail/accounts.js +919 -0
- package/plugins/_lib/mail/bodyTokens.js +101 -0
- package/plugins/_lib/mail/compose.js +256 -0
- package/plugins/_lib/mail/defaults.js +57 -0
- package/plugins/_lib/mail/diagnostics.js +154 -0
- package/plugins/_lib/mail/envelope.js +161 -0
- package/plugins/_lib/mail/folders.js +192 -0
- package/plugins/_lib/mail/handoff.js +274 -0
- package/plugins/_lib/mail/imapPool.js +293 -0
- package/plugins/_lib/mail/mbox.js +74 -0
- package/plugins/_lib/mail/pollSchedule.js +79 -0
- package/plugins/_lib/mail/poller.js +135 -0
- package/plugins/_lib/mail/priority.js +138 -0
- package/plugins/_lib/mail/readRoutes.js +680 -0
- package/plugins/_lib/mail/render.js +291 -0
- package/plugins/_lib/mail/ruleRunner.js +152 -0
- package/plugins/_lib/mail/scheduler.js +254 -0
- package/plugins/_lib/mail/secretbox.js +229 -0
- package/plugins/_lib/mail/send.js +396 -0
- package/plugins/_lib/mail/store.js +1002 -0
- package/plugins/_lib/mail/sync.js +292 -0
- package/plugins/_lib/mail/syncPlan.js +126 -0
- package/plugins/_lib/mail/syncSelection.js +82 -0
- package/plugins/_lib/mail/unsubscribe.js +183 -0
- package/plugins/_lib/mail/vacationRunner.js +114 -0
- package/plugins/_lib/mail/write.js +473 -0
- package/plugins/_lib/schemaSync.js +83 -0
- package/plugins/_template/admin/css/index.css +0 -0
- package/plugins/_template/admin/templates/index.html +4 -4
- package/plugins/_template/admin/views/index.js +7 -0
- package/plugins/analytics/admin/css/index.css +1 -0
- package/plugins/analytics/admin/templates/analytics.html +22 -13
- package/plugins/analytics/plugin.json +3 -0
- package/plugins/blog/admin/css/index.css +1 -0
- package/plugins/blog/admin/templates/blog.html +30 -18
- package/plugins/blog/admin/templates/categories.html +2 -2
- package/plugins/blog/admin/templates/comments.html +2 -2
- package/plugins/blog/admin/templates/post-editor.html +34 -34
- package/plugins/blog/admin/templates/settings.html +6 -3
- package/plugins/blog/admin/views/blog.js +8 -5
- package/plugins/blog/admin/views/categories.js +5 -10
- package/plugins/blog/admin/views/comments.js +5 -5
- package/plugins/blog/admin/views/post-editor.js +39 -20
- package/plugins/blog/admin/views/settings.js +52 -50
- package/plugins/blog/collections/categories/schema.json +7 -6
- package/plugins/blog/collections/comments/schema.json +11 -10
- package/plugins/blog/collections/posts/schema.json +14 -13
- package/plugins/blog/plugin.js +36 -13
- package/plugins/blog/plugin.json +13 -5
- package/plugins/blog/plugin.public.js +312 -0
- package/plugins/contacts/admin/css/index.css +1 -0
- package/plugins/contacts/admin/templates/contacts.html +128 -0
- package/plugins/contacts/admin/views/contacts.js +237 -4
- package/plugins/contacts/collections/user-contacts/schema.json +108 -0
- package/plugins/contacts/plugin.js +214 -27
- package/plugins/contacts/plugin.json +4 -1
- package/plugins/invoice/admin/css/index.css +1 -0
- package/plugins/invoice/admin/templates/editor.html +140 -49
- package/plugins/invoice/admin/templates/index.html +153 -23
- package/plugins/invoice/admin/templates/issuers.html +2 -5
- package/plugins/invoice/admin/templates/receivers.html +2 -5
- package/plugins/invoice/admin/views/contacts-source.js +266 -0
- package/plugins/invoice/admin/views/editor.js +366 -199
- package/plugins/invoice/admin/views/export.js +199 -0
- package/plugins/invoice/admin/views/help-content.js +61 -0
- package/plugins/invoice/admin/views/index.js +582 -94
- package/plugins/invoice/admin/views/issuers.js +24 -17
- package/plugins/invoice/admin/views/media.js +172 -0
- package/plugins/invoice/admin/views/party-view.js +305 -67
- package/plugins/invoice/admin/views/payments.js +127 -0
- package/plugins/invoice/admin/views/print.js +130 -0
- package/plugins/invoice/admin/views/receivers.js +49 -16
- package/plugins/invoice/admin/views/send.js +212 -0
- package/plugins/invoice/admin/views/settings.js +594 -0
- package/plugins/invoice/admin/views/view-lifecycle.js +33 -0
- package/plugins/invoice/collections/invoice-issuers/schema.json +77 -11
- package/plugins/invoice/collections/invoice-receivers/schema.json +10 -9
- package/plugins/invoice/collections/invoices/schema.json +19 -13
- package/plugins/invoice/config.js +27 -6
- package/plugins/invoice/pdf.js +164 -0
- package/plugins/invoice/plugin.js +1217 -44
- package/plugins/invoice/plugin.json +10 -9
- package/plugins/invoice/templates/_base.css +1 -0
- package/plugins/invoice/templates/classic-nologo.html +100 -0
- package/plugins/invoice/templates/classic.html +91 -0
- package/plugins/invoice/templates/invoice-print.html +24 -0
- package/plugins/invoice/templates/minimal.html +99 -0
- package/plugins/invoice/templates/modern-nologo.html +114 -0
- package/plugins/invoice/templates/modern.html +113 -0
- package/plugins/invoice/templates/templates.json +11 -0
- package/plugins/mail-reader/admin/views/mail.js +19 -0
- package/plugins/mail-reader/config.js +7 -0
- package/plugins/mail-reader/plugin.js +48 -0
- package/plugins/mail-reader/plugin.json +33 -0
- package/plugins/notes/admin/views/notes.js +1 -1
- package/plugins/notes/plugin.json +2 -2
- package/plugins/surveys/lib/audience.js +37 -0
- package/plugins/surveys/lib/campaigns.js +43 -0
- package/plugins/surveys/lib/ledger.js +110 -0
- package/plugins/surveys/lib/sending.js +106 -0
- package/plugins/surveys/lib/stats.js +62 -0
- package/plugins/surveys/lib/submit.js +95 -0
- package/plugins/surveys/lib/tokens.js +28 -0
- package/plugins/surveys/plugin.public.js +149 -0
- package/plugins/theme-switcher/admin/templates/theme-switcher.html +1 -1
- package/public/css/forms.css +1 -1
- package/public/css/search.css +1 -0
- package/public/css/site.css +1 -1
- package/public/js/collection-context.js +2 -2
- package/public/js/context-menus.js +1 -0
- package/public/js/form-logic-engine.js +1 -1
- package/public/js/forms.js +2 -2
- package/public/js/search.js +1 -0
- package/public/js/site.js +1 -1
- package/scripts/build.js +37 -3
- package/scripts/copy-domma.js +48 -0
- package/scripts/seed.js +1996 -0
- package/server/routes/api/collections.js +34 -0
- package/server/routes/api/context-menus.js +104 -0
- package/server/routes/api/forms.js +42 -3
- package/server/routes/api/notifications.js +69 -19
- package/server/routes/api/plugins.js +50 -6
- package/server/routes/api/search.js +43 -0
- package/server/routes/api/theme.js +69 -0
- package/server/routes/public.js +42 -7
- package/server/server.js +74 -0
- package/server/services/adapters/FileAdapter.js +6 -1
- package/server/services/content.js +26 -0
- package/server/services/contextMenus.js +477 -0
- package/server/services/markdown.js +70 -9
- package/server/services/permissionRegistry.js +24 -0
- package/server/services/pluginFiles.js +52 -11
- package/server/services/plugins.js +229 -6
- package/server/services/renderer.js +144 -22
- package/server/services/roles.js +1 -1
- package/server/services/search-migration.js +82 -0
- package/server/services/search.js +413 -0
- package/server/services/sidebar-migration.js +1 -0
- package/server/services/themeSettings.js +541 -0
- package/server/services/users.js +8 -0
- package/server/templates/page.html +4 -2
- package/plugins/contacts/data/contacts.json +0 -20
- package/plugins/notes/data/notes.json +0 -1
- package/plugins/site-search/admin/views/site-search.js +0 -116
- package/plugins/site-search/config.js +0 -15
- package/plugins/site-search/plugin.js +0 -188
- package/plugins/site-search/plugin.json +0 -40
- package/plugins/site-search/public/inject-body.html +0 -17
- package/plugins/site-search/public/inject-head.html +0 -1
- package/plugins/site-search/public/search.css +0 -1
- package/plugins/site-search/public/search.js +0 -1
- package/plugins/todo/data/todos.json +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{compareValues as
|
|
2
|
-
`),document.head.appendChild(P);function v(t){if(t._dmTable)return{fields:t._dmTable.columns.filter(e=>e.key!=="_cta").map(e=>({name:e.key,label:e.title||e.key})),entries:t._dmTable.rows.map((e,o)=>({id:String(o),data:e}))};if(t._dmCtxModel)return t._dmCtxModel;try{t._dmCtxModel=JSON.parse(atob(t.dataset.ctx))}catch{t._dmCtxModel=null}return t._dmCtxModel}function $(t,e){if(e.field==="*"){const n=String(e.value).toLowerCase();return Object.values(t.data||{}).some(d=>String(d??"").toLowerCase().includes(n))}const o=String(t.data?.[e.field]??"");switch(e.op){case"eq":return o===String(e.value);case"ne":return o!==String(e.value);case"contains":return o.toLowerCase().includes(String(e.value).toLowerCase());case"gt":case"lt":{const n=mt(o,e.value);return e.op==="gt"?n>0:n<0}default:return!0}}function p(t){const e=t._dmCtxFilters||[],o=v(t);if(!o)return;const n=t._dmCtxSort||null,d=D(o.entries.filter(i=>e.every(s=>$(i,s))),n),l=new Set(d.map(i=>i.id));if(t._dmTable)t._dmTable.render(d.map(i=>i.data));else if(t._dmCtx&&t._dmCtx.instance&&t._dmCtx.instance.setItems)t._dmCtx.instance.setItems(t._dmCtx.items.filter(i=>l.has(String(i._entryId))));else if(t._dmCtxSlides)J(t,l);else{const i=Array.from(t.querySelectorAll("[data-entry-id]"));i.forEach(h=>h.classList.toggle("dm-ctx-hidden",!l.has(h.dataset.entryId)));const s=new Map(i.map(h=>[h.dataset.entryId,h])),u=i.length?i[0].parentNode:null;n&&u&&d.forEach(h=>{const x=s.get(h.id);x&&x.parentNode===u&&u.appendChild(x)}),t.querySelectorAll(".dm-ctx-group-heading").forEach(h=>h.remove());const c=t._dmCtxGroup;if(c&&u){let h=null;d.forEach(x=>{const b=String(x.data?.[c]??"")||"-";if(b===h)return;h=b;const a=document.createElement("div");a.className="dm-ctx-group-heading",a.textContent=b;const r=s.get(x.id);r&&u.insertBefore(a,r)})}}Q(t,e),w(t,d.length,e.length),O()}const R="dmf";function A(){return Array.from(document.querySelectorAll("[data-ctx], [data-collection-table]"))}function F(t){return btoa(unescape(encodeURIComponent(JSON.stringify(t)))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function H(t){const e=t.replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(decodeURIComponent(escape(atob(e))))}function O(){const t={};A().forEach((n,d)=>{const l={};n._dmCtxFilters&&n._dmCtxFilters.length&&(l.f=n._dmCtxFilters),n._dmCtxSort&&(l.s=n._dmCtxSort),n._dmCtxGroup&&(l.g=n._dmCtxGroup),Object.keys(l).length&&(t[d]=l)});const e=(location.hash||"").replace(/^#/,"").split("&").filter(n=>n&&!n.startsWith(R+"="));Object.keys(t).length&&e.push(R+"="+F(t));const o=location.pathname+location.search+(e.length?"#"+e.join("&"):"");try{history.replaceState(null,"",o)}catch{}}function V(){const t=(location.hash||"").match(/(?:^#|&)dmf=([A-Za-z0-9_-]+)/);if(!t)return null;try{return H(t[1])}catch{return null}}function N(t=0){const e=V();if(!e)return;const o=A();let n=!1;for(const[d,l]of Object.entries(e)){const i=o[Number(d)];if(!i||!l)continue;if(i.hasAttribute("data-collection-table")?!i._dmTable:i.classList.contains("dm-progression")?!i._dmCtx:i.classList.contains("carousel")?!i._dmCtxSlides:!1){n=!0;continue}const u=Array.isArray(l)?{f:l}:l||{};i._dmCtxFilters=(u.f||[]).filter(c=>c&&c.field&&c.op!=null&&"value"in c),i._dmCtxSort=u.s||null,i._dmCtxGroup=u.g||null,p(i)}n&&t<20&&setTimeout(()=>N(t+1),100)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>setTimeout(N,0)):setTimeout(N,0);function J(t,e){if(t._dmCarousel&&typeof t._dmCarousel.destroy=="function")try{t._dmCarousel.destroy()}catch{}const o=document.createElement("div");o.className="carousel-track",t._dmCtxSlides.forEach(n=>{e.has(n.dataset.entryId)&&o.appendChild(n.cloneNode(!0))}),t.replaceChildren(o),o.children.length&&typeof Domma<"u"&&Domma.elements?.carousel&&(t._dmCarousel=Domma.elements.carousel(t,t._dmCarouselOpts||{}))}function W(t,e,o){const n=URL.createObjectURL(new Blob([t],{type:o})),d=document.createElement("a");d.href=n,d.download=e,document.body.appendChild(d),d.click(),d.remove(),setTimeout(()=>URL.revokeObjectURL(n),0)}function _(t,e){const o=document.createElement("textarea");o.value=t,o.style.cssText="position:fixed;opacity:0;",document.body.appendChild(o),o.select();const n=document.execCommand("copy");o.remove(),typeof E<"u"&&E.toast&&E.toast(n?e:"Copy failed",{type:n?"success":"error"})}function Y(){return new Date().toISOString().slice(0,10)}let k=null;function X(){if(!k){const t=typeof S<"u"&&S.get?S.get("auth_token"):null;k=t?fetch("/api/auth/me",{headers:{Authorization:`Bearer ${t}`}}).then(e=>e.ok?e.json():null).catch(()=>null):Promise.resolve(null)}return k}async function Z(t){if(!t||!t.allowed)return!1;if(t.access==="public")return!0;const e=await X();return e?[e.role,...e.additionalRoles||[]].filter(Boolean).some(n=>(t.roles||[]).includes(n)):!1}const K={eq:"=",ne:"\u2260",contains:"contains",gt:">",lt:"<"};function Q(t,e){let o=t._dmCtxBar;if(!e.length){o&&(o.remove(),t._dmCtxBar=null);return}o||(o=document.createElement("div"),o.className="dm-ctx-chips",t.parentNode.insertBefore(o,t),t._dmCtxBar=o),o.replaceChildren(),e.forEach((d,l)=>{const i=document.createElement("span");i.className="dm-ctx-chip";const s=String(d.value),u=s.length>24?s.slice(0,24)+"\u2026":s;i.appendChild(document.createTextNode(d.field==="*"?`search \u201C${u}\u201D`:`${d.label||d.field} ${K[d.op]||d.op} \u201C${u}\u201D`));const c=document.createElement("button");c.type="button",c.textContent="\xD7",c.title="Remove filter",c.addEventListener("click",()=>{t._dmCtxFilters.splice(l,1),p(t)}),i.appendChild(c),o.appendChild(i)});const n=document.createElement("button");n.type="button",n.className="dm-ctx-chip",n.style.cursor="pointer",n.textContent="Clear all",n.addEventListener("click",()=>{t._dmCtxFilters=[],p(t)}),o.appendChild(n)}function w(t,e,o){if(t._dmCtxEmptyNote&&(t._dmCtxEmptyNote.remove(),t._dmCtxEmptyNote=null),e||!o)return;const n=document.createElement("div");n.className="dm-ctx-empty-note",n.textContent="No entries match the current filters.",t.appendChild(n),t._dmCtxEmptyNote=n}let C=null;function f(){C&&(C.remove(),C=null,document.removeEventListener("mousedown",j,!0),document.removeEventListener("keydown",G,!0),window.removeEventListener("scroll",M,!0))}const j=t=>{C&&!C.contains(t.target)&&f()},G=t=>{t.key==="Escape"&&f()},M=t=>{C&&!C.contains(t.target)&&f()};function m(t,e){const o=document.createElement("button");return o.type="button",o.className="dm-ctx-row",o.textContent=t,o.addEventListener("click",e),o}function y(t){const e=document.createElement("div");return e.className="dm-ctx-heading",e.textContent=t,e}function I(){const t=document.createElement("div");return t.style.cssText="border-top:1px solid var(--dm-border,#2a2a40);margin:.25rem 0;",t}const g=(t,e=24)=>{const o=String(t);return o.length>e?o.slice(0,e)+"\u2026":o};function B(t){const e=t.getBoundingClientRect();t.style.left=Math.min(t._dmX,window.innerWidth-e.width-8)+"px",t.style.top=Math.min(t._dmY,window.innerHeight-e.height-8)+"px"}function U(t,e,o){if(t._dmPanelToken=(t._dmPanelToken||0)+1,t.replaceChildren(),o){const n=document.createElement("div");n.className="dm-ctx-panel-head";const d=document.createElement("button");d.type="button",d.className="dm-ctx-row dm-ctx-back",d.textContent="\u2039 Back",d.addEventListener("click",()=>t._dmPop()),n.appendChild(d),n.appendChild(y(o)),t.appendChild(n)}e(t),B(t)}function tt(t){const e=[];return t._dmPush=(o,n)=>{e.push({build:o,title:n}),U(t,o,n)},t._dmPop=()=>{e.pop();const o=e[e.length-1];o&&U(t,o.build,o.title)},t}function et(t){return!t._dmTable&&!t._dmCtx?.instance?.setItems&&!t._dmCtxSlides}function nt(t,e){const o=t.entries.map(d=>d.data?.[e]).find(d=>d!==""&&d!=null),n=String(o??"");return n!==""&&!Number.isNaN(parseFloat(n))?["low \u2192 high","high \u2192 low"]:Number.isNaN(Date.parse(n))?["A \u2192 Z","Z \u2192 A"]:["oldest \u2192 newest","newest \u2192 oldest"]}function ot(t,e,o){o.fields.forEach(n=>{const[d,l]=nt(o,n.name);t.appendChild(m(`${n.label||n.name} ${d}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"},p(e),f()})),t.appendChild(m(`${n.label||n.name} ${l}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"desc"},p(e),f()}))}),e._dmCtxSort&&t.appendChild(m("Clear sort",()=>{e._dmCtxSort=null,p(e),f()}))}function dt(t,e,o){o.fields.forEach(n=>{t.appendChild(m(n.label||n.name,()=>{e._dmCtxGroup=n.name,(!e._dmCtxSort||e._dmCtxSort.field!==n.name)&&(e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"}),p(e),f()}))}),e._dmCtxGroup&&t.appendChild(m("Clear grouping",()=>{e._dmCtxGroup=null,p(e),f()}))}function z(t,e){const o=t._dmCtxFilters||[];return D(e.entries.filter(n=>o.every(d=>$(n,d))),t._dmCtxSort||null).map(n=>n.data)}function it(t,e,o,n){const d=o.slug||e._dmTable?.slug||"collection";n.formats.forEach(l=>{t.appendChild(m(l.toUpperCase(),()=>{const i=T(z(e,o),o.fields,l);W(i,`${d}-${Y()}.${l}`,l==="csv"?"text/csv;charset=utf-8":"application/json"),f()}))})}function at(t,e,o,n,d){n&&d&&t.appendChild(m("This value",()=>{_(String(n.data?.[d.name]??""),"Value copied"),f()})),n&&t.appendChild(m("This row (JSON)",()=>{_(T([n.data],o.fields,"json"),"Row copied"),f()})),t.appendChild(m("Visible entries as a table",()=>{_(T(z(e,o),o.fields,"markdown"),"Table copied"),f()}))}function lt(t,e,o,n,d){const l=(a,r,L,ct)=>{(e._dmCtxFilters=e._dmCtxFilters||[]).push({field:a,label:r,op:L,value:ct}),p(e),f()};if(n&&o){const a=o.data?.[n.name]??"";t.appendChild(y(n.label||n.name)),t.appendChild(m(`Filter: = \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"eq",a))),t.appendChild(m(`Filter: \u2260 \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"ne",a)));const r=String(a);(r!==""&&!Number.isNaN(parseFloat(r))||!Number.isNaN(Date.parse(r)))&&(t.appendChild(m(`Filter: > \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"gt",a))),t.appendChild(m(`Filter: < \u201C${g(a)}\u201D`,()=>l(n.name,n.label,"lt",a))))}else if(o){t.appendChild(y("Filter by"));for(const a of d.fields){const r=o.data?.[a.name];r==null||String(r)===""||t.appendChild(m(`${a.label||a.name}: \u201C${g(r,20)}\u201D`,()=>l(a.name,a.label,"eq",r)))}}const i=document.createElement("div");i.style.padding=".35rem .6rem";const s=document.createElement("input");s.type="text",s.className="dm-ctx-input",s.placeholder="Search\u2026 or name: value",s.addEventListener("mousedown",a=>a.stopPropagation()),s.addEventListener("keydown",a=>{if(a.key!=="Enter"||!s.value.trim())return;const r=ut(s.value,d.fields);r?l(r.field,r.label,r.op,r.value):l("*","search","contains",s.value.trim())}),i.appendChild(s),t.appendChild(i),t.appendChild(I()),t.appendChild(y("This display")),t.appendChild(m("Sort\u2026",()=>t._dmPush(a=>ot(a,e,d),"Sort"))),et(e)&&t.appendChild(m("Group by\u2026",()=>t._dmPush(a=>dt(a,e,d),"Group by"))),t.appendChild(m("Copy\u2026",()=>t._dmPush(a=>at(a,e,d,o,n),"Copy")));const u=m("Print",()=>{e.setAttribute("data-dm-print",""),document.body.classList.add("dm-ctx-printing"),f();const a=()=>{e.removeAttribute("data-dm-print"),document.body.classList.remove("dm-ctx-printing"),window.removeEventListener("afterprint",a)};window.addEventListener("afterprint",a),window.print()});t.appendChild(u),t.appendChild(m("Copy link to this view",()=>{O(),_(location.href,"Link copied"),f()}));const c=d.export||e._dmTable?.exportCfg,h=t._dmPanelToken;Z(c).then(a=>{!a||C!==t||t._dmPanelToken!==h||(t.insertBefore(m("Export\u2026",()=>t._dmPush(r=>it(r,e,d,c),"Export")),u),B(t))});const x=(e._dmCtxFilters||[]).length;if(x||e._dmCtxSort||e._dmCtxGroup){const a=[];x&&a.push(`${x} filter${x===1?"":"s"}`),e._dmCtxSort&&a.push("sort"),e._dmCtxGroup&&a.push("grouping"),t.appendChild(I()),t.appendChild(m(`Clear all (${a.join(", ")})`,()=>{e._dmCtxFilters=[],e._dmCtxSort=null,e._dmCtxGroup=null,p(e),f()}))}}function st(t,e,o,n,d){f();const l=v(o);if(!l)return;const i=tt(document.createElement("div"));i.className="dm-ctx-menu",i._dmX=t,i._dmY=e,C=i,document.body.appendChild(i),i._dmPush(s=>lt(s,o,n,d,l),null),document.addEventListener("mousedown",j,!0),document.addEventListener("keydown",G,!0),window.addEventListener("scroll",M,!0),setTimeout(()=>{const s=i.querySelector(".dm-ctx-input");s&&s.focus()},0)}function rt(t,e,o){if(t._dmTable){const s=e.closest("tbody tr");if(!s)return{entry:null,field:null};const u=e.closest("td"),c=s.querySelectorAll("td"),h=Array.from(c).map(a=>a.textContent.trim()),x=o.entries.find(a=>o.fields.every((r,L)=>String(a.data?.[r.name]??"").trim()===(h[L]??"").trim()))||null,b=u&&o.fields[u.cellIndex]||null;return{entry:x,field:b}}const n=e.closest("[data-entry-id]");if(!n)return{entry:null,field:null};const d=o.entries.find(s=>s.id===n.dataset.entryId)||null;if(!d)return{entry:null,field:null};const l=(e.textContent||"").trim().slice(0,80);let i=null;if(l){const s=o.fields.filter(u=>{const c=String(d.data?.[u.name]??"");return c&&(c.includes(l)||l.includes(c))});s.length===1&&(i=s[0])}return{entry:d,field:i}}document.addEventListener("contextmenu",t=>{const e=t.target.closest("[data-ctx], [data-collection-table]");if(!e)return;const o=v(e);if(!o||!o.fields?.length)return;t.preventDefault();const{entry:n,field:d}=rt(e,t.target,o);st(t.clientX,t.clientY,e,n,d)})})();
|
|
1
|
+
import{compareValues as ut,sortEntries as F}from"/public/js/collection-sort.mjs";import{serialise as T}from"/public/js/collection-export.mjs";import{parseQuery as ft}from"/public/js/collection-query.mjs";(function(){"use strict";const H='url("data:image/svg+xml,'+encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M5 2v15.5l4.2-4 2.4 5.4 2.8-1.2-2.4-5.3 5.5-.1z' fill='#fff' stroke='#000' stroke-width='1.2' stroke-linejoin='round'/><path d='M13.5 15h9.5l-3.6 4.2v4l-2.3-1.8v-2.2z' fill='#5b8cff' stroke='#fff' stroke-width='1' stroke-linejoin='round'/></svg>")+'") 5 3, context-menu',P=document.createElement("style");P.textContent=["[data-ctx], [data-collection-table] { cursor: "+H+"; }","[data-ctx] a, [data-ctx] button, [data-collection-table] a, [data-collection-table] button,","[data-ctx] input, [data-collection-table] input { cursor: pointer; }",'[data-ctx] input[type="text"], [data-collection-table] input[type="text"] { cursor: text; }',".dm-ctx-hidden { display: none !important; }",".dm-ctx-menu { position: fixed; z-index: 10000; min-width: 200px; max-width: 300px; max-height: 60vh; overflow-y: auto;background: var(--dm-surface, #1c1c30); border: 1px solid var(--dm-border, #2a2a40); border-radius: 6px;box-shadow: var(--dm-shadow-lg, 0 8px 24px rgba(0,0,0,.4)); padding: .3rem; font-size: .83rem;color: var(--dm-text, #e5e5e5); }",".dm-ctx-menu button.dm-ctx-row { display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left;background: none; border: none; color: inherit; font: inherit; padding: .35rem .6rem; border-radius: 4px; cursor: pointer; }",".dm-ctx-menu button.dm-ctx-row:hover { background: var(--dm-hover-bg, rgba(128,128,128,.14)); }",".dm-ctx-heading { padding: .3rem .6rem; font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;color: var(--dm-text-muted, #9a9aac); }",".dm-ctx-input { width: 100%; font-size: .8rem; padding: .3rem .5rem; border-radius: 4px;border: 1px solid var(--dm-border, #2a2a40); background: var(--dm-input-bg, rgba(128,128,128,.08)); color: inherit; cursor: text; }",".dm-ctx-chips { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin: 0 0 .6rem; }",".dm-ctx-chip { display: inline-flex; align-items: center; gap: .35rem; font-size: .76rem; padding: .2rem .6rem;border-radius: 999px; background: var(--dm-hover-bg, rgba(128,128,128,.14)); border: 1px solid var(--dm-border, #2a2a40); }",".dm-ctx-chip button { background: none; border: none; cursor: pointer; color: inherit; font-size: .9rem; line-height: 1; padding: 0; }",".dm-ctx-empty-note { padding: .75rem; font-size: .85rem; color: var(--dm-text-muted, #9a9aac); }",".dm-ctx-panel-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem;border-bottom: 1px solid var(--dm-border, #2a2a40); margin-bottom: .25rem; }",".dm-ctx-menu button.dm-ctx-back { width: auto; padding: .3rem .5rem; color: var(--dm-text-muted, #9a9aac); }",".dm-ctx-group-heading { font-size: .75rem; text-transform: uppercase; letter-spacing: .04em;color: var(--dm-text-muted, #9a9aac); padding: .5rem 0 .25rem; grid-column: 1 / -1; }"].join(`
|
|
2
|
+
`),document.head.appendChild(P);function g(t){if(t._dmTable)return{fields:t._dmTable.columns.filter(e=>e.key!=="_cta").map(e=>({name:e.key,label:e.title||e.key})),entries:t._dmTable.rows.map((e,o)=>({id:String(o),data:e}))};if(t._dmCtxModel)return t._dmCtxModel;try{t._dmCtxModel=JSON.parse(atob(t.dataset.ctx))}catch{t._dmCtxModel=null}return t._dmCtxModel}function $(t,e){if(e.field==="*"){const n=String(e.value).toLowerCase();return Object.values(t.data||{}).some(d=>String(d??"").toLowerCase().includes(n))}const o=String(t.data?.[e.field]??"");switch(e.op){case"eq":return o===String(e.value);case"ne":return o!==String(e.value);case"contains":return o.toLowerCase().includes(String(e.value).toLowerCase());case"gt":case"lt":{const n=ut(o,e.value);return e.op==="gt"?n>0:n<0}default:return!0}}function p(t){const e=t._dmCtxFilters||[],o=g(t);if(!o)return;const n=t._dmCtxSort||null,d=F(o.entries.filter(a=>e.every(s=>$(a,s))),n),l=new Set(d.map(a=>a.id));if(t._dmTable)t._dmTable.render(d.map(a=>a.data));else if(t._dmCtx&&t._dmCtx.instance&&t._dmCtx.instance.setItems)t._dmCtx.instance.setItems(t._dmCtx.items.filter(a=>l.has(String(a._entryId))));else if(t._dmCtxSlides)Y(t,l);else{const a=Array.from(t.querySelectorAll("[data-entry-id]"));a.forEach(h=>h.classList.toggle("dm-ctx-hidden",!l.has(h.dataset.entryId)));const s=new Map(a.map(h=>[h.dataset.entryId,h])),u=a.length?a[0].parentNode:null;n&&u&&d.forEach(h=>{const x=s.get(h.id);x&&x.parentNode===u&&u.appendChild(x)}),t.querySelectorAll(".dm-ctx-group-heading").forEach(h=>h.remove());const c=t._dmCtxGroup;if(c&&u){let h=null;d.forEach(x=>{const b=String(x.data?.[c]??"")||"-";if(b===h)return;h=b;const i=document.createElement("div");i.className="dm-ctx-group-heading",i.textContent=b;const r=s.get(x.id);r&&u.insertBefore(i,r)})}}tt(t,e),et(t,d.length,e.length),M()}const R="dmf";function A(){return Array.from(document.querySelectorAll("[data-ctx], [data-collection-table]"))}function V(t){return btoa(unescape(encodeURIComponent(JSON.stringify(t)))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function J(t){const e=t.replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(decodeURIComponent(escape(atob(e))))}function M(){const t={};A().forEach((n,d)=>{const l={};n._dmCtxFilters&&n._dmCtxFilters.length&&(l.f=n._dmCtxFilters),n._dmCtxSort&&(l.s=n._dmCtxSort),n._dmCtxGroup&&(l.g=n._dmCtxGroup),Object.keys(l).length&&(t[d]=l)});const e=(location.hash||"").replace(/^#/,"").split("&").filter(n=>n&&!n.startsWith(R+"="));Object.keys(t).length&&e.push(R+"="+V(t));const o=location.pathname+location.search+(e.length?"#"+e.join("&"):"");try{history.replaceState(null,"",o)}catch{}}function W(){const t=(location.hash||"").match(/(?:^#|&)dmf=([A-Za-z0-9_-]+)/);if(!t)return null;try{return J(t[1])}catch{return null}}function N(t=0){const e=W();if(!e)return;const o=A();let n=!1;for(const[d,l]of Object.entries(e)){const a=o[Number(d)];if(!a||!l)continue;if(a.hasAttribute("data-collection-table")?!a._dmTable:a.classList.contains("dm-progression")?!a._dmCtx:a.classList.contains("carousel")?!a._dmCtxSlides:!1){n=!0;continue}const u=Array.isArray(l)?{f:l}:l||{};a._dmCtxFilters=(u.f||[]).filter(c=>c&&c.field&&c.op!=null&&"value"in c),a._dmCtxSort=u.s||null,a._dmCtxGroup=u.g||null,p(a)}n&&t<20&&setTimeout(()=>N(t+1),100)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>setTimeout(N,0)):setTimeout(N,0);function Y(t,e){if(t._dmCarousel&&typeof t._dmCarousel.destroy=="function")try{t._dmCarousel.destroy()}catch{}const o=document.createElement("div");o.className="carousel-track",t._dmCtxSlides.forEach(n=>{e.has(n.dataset.entryId)&&o.appendChild(n.cloneNode(!0))}),t.replaceChildren(o),o.children.length&&typeof Domma<"u"&&Domma.elements?.carousel&&(t._dmCarousel=Domma.elements.carousel(t,t._dmCarouselOpts||{}))}function X(t,e,o){const n=URL.createObjectURL(new Blob([t],{type:o})),d=document.createElement("a");d.href=n,d.download=e,document.body.appendChild(d),d.click(),d.remove(),setTimeout(()=>URL.revokeObjectURL(n),0)}function _(t,e){const o=document.createElement("textarea");o.value=t,o.style.cssText="position:fixed;opacity:0;",document.body.appendChild(o),o.select();const n=document.execCommand("copy");o.remove(),typeof E<"u"&&E.toast&&E.toast(n?e:"Copy failed",{type:n?"success":"error"})}function Z(){return new Date().toISOString().slice(0,10)}let L=null;function K(){if(!L){const t=typeof S<"u"&&S.get?S.get("auth_token"):null;L=t?fetch("/api/auth/me",{headers:{Authorization:`Bearer ${t}`}}).then(e=>e.ok?e.json():null).catch(()=>null):Promise.resolve(null)}return L}async function Q(t){if(!t||!t.allowed)return!1;if(t.access==="public")return!0;const e=await K();return e?[e.role,...e.additionalRoles||[]].filter(Boolean).some(n=>(t.roles||[]).includes(n)):!1}const w={eq:"=",ne:"\u2260",contains:"contains",gt:">",lt:"<"};function tt(t,e){let o=t._dmCtxBar;if(!e.length){o&&(o.remove(),t._dmCtxBar=null);return}o||(o=document.createElement("div"),o.className="dm-ctx-chips",t.parentNode.insertBefore(o,t),t._dmCtxBar=o),o.replaceChildren(),e.forEach((d,l)=>{const a=document.createElement("span");a.className="dm-ctx-chip";const s=String(d.value),u=s.length>24?s.slice(0,24)+"\u2026":s;a.appendChild(document.createTextNode(d.field==="*"?`search \u201C${u}\u201D`:`${d.label||d.field} ${w[d.op]||d.op} \u201C${u}\u201D`));const c=document.createElement("button");c.type="button",c.textContent="\xD7",c.title="Remove filter",c.addEventListener("click",()=>{t._dmCtxFilters.splice(l,1),p(t)}),a.appendChild(c),o.appendChild(a)});const n=document.createElement("button");n.type="button",n.className="dm-ctx-chip",n.style.cursor="pointer",n.textContent="Clear all",n.addEventListener("click",()=>{t._dmCtxFilters=[],p(t)}),o.appendChild(n)}function et(t,e,o){if(t._dmCtxEmptyNote&&(t._dmCtxEmptyNote.remove(),t._dmCtxEmptyNote=null),e||!o)return;const n=document.createElement("div");n.className="dm-ctx-empty-note",n.textContent="No entries match the current filters.",t.appendChild(n),t._dmCtxEmptyNote=n}let C=null;function f(){C&&(C.remove(),C=null,document.removeEventListener("mousedown",O,!0),document.removeEventListener("keydown",j,!0),window.removeEventListener("scroll",D,!0))}const O=t=>{C&&!C.contains(t.target)&&f()},j=t=>{t.key==="Escape"&&f()},D=t=>{C&&!C.contains(t.target)&&f()};function m(t,e){const o=document.createElement("button");return o.type="button",o.className="dm-ctx-row",o.textContent=t,o.addEventListener("click",e),o}function v(t){const e=document.createElement("div");return e.className="dm-ctx-heading",e.textContent=t,e}function G(){const t=document.createElement("div");return t.style.cssText="border-top:1px solid var(--dm-border,#2a2a40);margin:.25rem 0;",t}const y=(t,e=24)=>{const o=String(t);return o.length>e?o.slice(0,e)+"\u2026":o};function I(t){const e=t.getBoundingClientRect();t.style.left=Math.min(t._dmX,window.innerWidth-e.width-8)+"px",t.style.top=Math.min(t._dmY,window.innerHeight-e.height-8)+"px"}function B(t,e,o){if(t._dmPanelToken=(t._dmPanelToken||0)+1,t.replaceChildren(),o){const n=document.createElement("div");n.className="dm-ctx-panel-head";const d=document.createElement("button");d.type="button",d.className="dm-ctx-row dm-ctx-back",d.textContent="\u2039 Back",d.addEventListener("click",()=>t._dmPop()),n.appendChild(d),n.appendChild(v(o)),t.appendChild(n)}e(t),I(t)}function nt(t){const e=[];return t._dmPush=(o,n)=>{e.push({build:o,title:n}),B(t,o,n)},t._dmPop=()=>{e.pop();const o=e[e.length-1];o&&B(t,o.build,o.title)},t}function ot(t){return!t._dmTable&&!t._dmCtx?.instance?.setItems&&!t._dmCtxSlides}function dt(t,e){const o=t.entries.map(d=>d.data?.[e]).find(d=>d!==""&&d!=null),n=String(o??"");return n!==""&&!Number.isNaN(parseFloat(n))?["low \u2192 high","high \u2192 low"]:Number.isNaN(Date.parse(n))?["A \u2192 Z","Z \u2192 A"]:["oldest \u2192 newest","newest \u2192 oldest"]}function at(t,e,o){o.fields.forEach(n=>{const[d,l]=dt(o,n.name);t.appendChild(m(`${n.label||n.name} ${d}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"},p(e),f()})),t.appendChild(m(`${n.label||n.name} ${l}`,()=>{e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"desc"},p(e),f()}))}),e._dmCtxSort&&t.appendChild(m("Clear sort",()=>{e._dmCtxSort=null,p(e),f()}))}function it(t,e,o){o.fields.forEach(n=>{t.appendChild(m(n.label||n.name,()=>{e._dmCtxGroup=n.name,(!e._dmCtxSort||e._dmCtxSort.field!==n.name)&&(e._dmCtxSort={field:n.name,label:n.label||n.name,dir:"asc"}),p(e),f()}))}),e._dmCtxGroup&&t.appendChild(m("Clear grouping",()=>{e._dmCtxGroup=null,p(e),f()}))}function U(t,e){const o=t._dmCtxFilters||[];return F(e.entries.filter(n=>o.every(d=>$(n,d))),t._dmCtxSort||null).map(n=>n.data)}function lt(t,e,o,n){const d=o.slug||e._dmTable?.slug||"collection";n.formats.forEach(l=>{t.appendChild(m(l.toUpperCase(),()=>{const a=T(U(e,o),o.fields,l);X(a,`${d}-${Z()}.${l}`,l==="csv"?"text/csv;charset=utf-8":"application/json"),f()}))})}function st(t,e,o,n,d){n&&d&&t.appendChild(m("This value",()=>{_(String(n.data?.[d.name]??""),"Value copied"),f()})),n&&t.appendChild(m("This row (JSON)",()=>{_(T([n.data],o.fields,"json"),"Row copied"),f()})),t.appendChild(m("Visible entries as a table",()=>{_(T(U(e,o),o.fields,"markdown"),"Table copied"),f()}))}function rt(t,e,o,n,d){const l=(i,r,k,mt)=>{(e._dmCtxFilters=e._dmCtxFilters||[]).push({field:i,label:r,op:k,value:mt}),p(e),f()};if(n&&o){const i=o.data?.[n.name]??"";t.appendChild(v(n.label||n.name)),t.appendChild(m(`Filter: = \u201C${y(i)}\u201D`,()=>l(n.name,n.label,"eq",i))),t.appendChild(m(`Filter: \u2260 \u201C${y(i)}\u201D`,()=>l(n.name,n.label,"ne",i)));const r=String(i);(r!==""&&!Number.isNaN(parseFloat(r))||!Number.isNaN(Date.parse(r)))&&(t.appendChild(m(`Filter: > \u201C${y(i)}\u201D`,()=>l(n.name,n.label,"gt",i))),t.appendChild(m(`Filter: < \u201C${y(i)}\u201D`,()=>l(n.name,n.label,"lt",i))))}else if(o){t.appendChild(v("Filter by"));for(const i of d.fields){const r=o.data?.[i.name];r==null||String(r)===""||t.appendChild(m(`${i.label||i.name}: \u201C${y(r,20)}\u201D`,()=>l(i.name,i.label,"eq",r)))}}const a=document.createElement("div");a.style.padding=".35rem .6rem";const s=document.createElement("input");s.type="text",s.className="dm-ctx-input",s.placeholder="Search\u2026 or name: value",s.addEventListener("mousedown",i=>i.stopPropagation()),s.addEventListener("keydown",i=>{if(i.key!=="Enter"||!s.value.trim())return;const r=ft(s.value,d.fields);r?l(r.field,r.label,r.op,r.value):l("*","search","contains",s.value.trim())}),a.appendChild(s),t.appendChild(a),t.appendChild(G()),t.appendChild(v("This display")),t.appendChild(m("Sort\u2026",()=>t._dmPush(i=>at(i,e,d),"Sort"))),ot(e)&&t.appendChild(m("Group by\u2026",()=>t._dmPush(i=>it(i,e,d),"Group by"))),t.appendChild(m("Copy\u2026",()=>t._dmPush(i=>st(i,e,d,o,n),"Copy")));const u=m("Print",()=>{e.setAttribute("data-dm-print",""),document.body.classList.add("dm-ctx-printing"),f();const i=()=>{e.removeAttribute("data-dm-print"),document.body.classList.remove("dm-ctx-printing"),window.removeEventListener("afterprint",i)};window.addEventListener("afterprint",i),window.print()});t.appendChild(u),t.appendChild(m("Copy link to this view",()=>{M(),_(location.href,"Link copied"),f()}));const c=d.export||e._dmTable?.exportCfg,h=t._dmPanelToken;Q(c).then(i=>{!i||C!==t||t._dmPanelToken!==h||(t.insertBefore(m("Export\u2026",()=>t._dmPush(r=>lt(r,e,d,c),"Export")),u),I(t))});const x=(e._dmCtxFilters||[]).length;if(x||e._dmCtxSort||e._dmCtxGroup){const i=[];x&&i.push(`${x} filter${x===1?"":"s"}`),e._dmCtxSort&&i.push("sort"),e._dmCtxGroup&&i.push("grouping"),t.appendChild(G()),t.appendChild(m(`Clear all (${i.join(", ")})`,()=>{e._dmCtxFilters=[],e._dmCtxSort=null,e._dmCtxGroup=null,p(e),f()}))}}function z(t,e,o,n,d){f();const l=g(o);if(!l)return;const a=nt(document.createElement("div"));a.className="dm-ctx-menu",a._dmX=t,a._dmY=e,C=a,document.body.appendChild(a),a._dmPush(s=>rt(s,o,n,d,l),null),document.addEventListener("mousedown",O,!0),document.addEventListener("keydown",j,!0),window.addEventListener("scroll",D,!0),setTimeout(()=>{const s=a.querySelector(".dm-ctx-input");s&&s.focus()},0)}function q(t,e,o){if(t._dmTable){const s=e.closest("tbody tr");if(!s)return{entry:null,field:null};const u=e.closest("td"),c=s.querySelectorAll("td"),h=Array.from(c).map(i=>i.textContent.trim()),x=o.entries.find(i=>o.fields.every((r,k)=>String(i.data?.[r.name]??"").trim()===(h[k]??"").trim()))||null,b=u&&o.fields[u.cellIndex]||null;return{entry:x,field:b}}const n=e.closest("[data-entry-id]");if(!n)return{entry:null,field:null};const d=o.entries.find(s=>s.id===n.dataset.entryId)||null;if(!d)return{entry:null,field:null};const l=(e.textContent||"").trim().slice(0,80);let a=null;if(l){const s=o.fields.filter(u=>{const c=String(d.data?.[u.name]??"");return c&&(c.includes(l)||l.includes(c))});s.length===1&&(a=s[0])}return{entry:d,field:a}}function ct(t){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t,{once:!0}):t()}ct(()=>{if(typeof Domma>"u"||!Domma.elements?.contextMenu){document.addEventListener("contextmenu",t=>{const e=t.target.closest("[data-ctx], [data-collection-table]");if(!e)return;const o=g(e);if(!o||!o.fields?.length)return;t.preventDefault();const{entry:n,field:d}=q(e,t.target,o);z(t.clientX,t.clientY,e,n,d)});return}Domma.elements.contextMenu("[data-ctx], [data-collection-table]",{exclusive:!0,enabled:t=>{const e=g(t);return!!(e&&e.fields?.length)},render:t=>{const e=t.container,o=g(e),{entry:n,field:d}=q(e,t.event.target,o);z(t.x,t.y,e,n,d)}})})})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){"use strict";const d=window.__CMS_CTXMENUS__;if(!Array.isArray(d)||!d.length||typeof Domma>"u"||!Domma.elements||!Domma.elements.contextMenu)return;const s=(e,t)=>{typeof E<"u"&&E.toast&&E.toast(e,{type:t||"info"})},p=".site-search-trigger, .site-search-floating-trigger";function f(e){return e&&e.closest?e.closest("[data-ctx], [data-collection-table]"):null}function i(e){if(!e||!e.closest)return null;const t=e.closest('input, textarea, [contenteditable=""], [contenteditable="true"]');return!t||t.disabled||t.readOnly||t.tagName==="INPUT"&&!/^(text|search|url|tel|email|password|number)$/i.test(t.type)?null:t}function u(e){const t=i(e);if(t&&typeof t.selectionStart=="number")return t.value.slice(t.selectionStart,t.selectionEnd);const n=window.getSelection();return n?n.toString():""}function y(){try{const e=performance.getEntriesByType("navigation")[0];return!!e&&e.type==="back_forward"}catch{return!1}}function m(e,t){const n=e.selectionStart,r=e.selectionEnd;e.value=e.value.slice(0,n)+t+e.value.slice(r);const o=n+t.length;e.setSelectionRange(o,o),e.dispatchEvent(new Event("input",{bubbles:!0}))}const l={reload:{run:()=>window.location.reload()},back:{run:()=>window.history.back(),disabled:()=>window.history.length<=1},forward:{run:()=>window.history.forward(),disabled:()=>!y()},print:{run:()=>window.print()},copy:{run:async e=>{const t=u(e);if(t)try{await navigator.clipboard.writeText(t)}catch{s("Your browser would not let the page copy","error")}},disabled:e=>!u(e)},cut:{run:async e=>{const t=i(e);if(!t)return;const n=u(e);if(n)try{await navigator.clipboard.writeText(n),m(t,"")}catch{s("Your browser would not let the page cut","error")}},disabled:e=>!i(e)||!u(e)},paste:{run:async e=>{const t=i(e);if(t)try{const n=await navigator.clipboard.readText();n&&m(t,n)}catch{s("Your browser blocks paste from a menu - use Ctrl+V","warning")}},disabled:e=>!i(e)},"site-search":{run:()=>{if(window.DommaSiteSearch&&window.DommaSiteSearch.open){window.DommaSiteSearch.open();return}const e=document.querySelector(p);if(e){e.click();return}s("Site search is not available on this site","warning")},disabled:()=>!window.DommaSiteSearch&&!document.querySelector(p)},"select-all":{run:e=>{const t=i(e);if(t){t.select();return}const n=e&&e.closest&&e.closest("[data-ctx], .page-body")||document.body,r=document.createRange();r.selectNodeContents(n);const o=window.getSelection();o.removeAllRanges(),o.addRange(r)}}};function w(e){if(!e||!e.type)return null;if(l[e.type])return l[e.type].run;switch(e.type){case"navigate":return e.url?()=>{window.location.href=e.url}:null;case"copy-link":return async()=>{try{await navigator.clipboard.writeText(window.location.href),s("Link copied","success")}catch{s("Could not copy the link","error")}};case"run-action":return e.slug?async t=>{try{const n=await fetch(`/api/actions/${encodeURIComponent(e.slug)}/run`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({entryId:t&&t.dataset?t.dataset.entryId:void 0,url:window.location.pathname})});if(!n.ok)throw new Error(`HTTP ${n.status}`);s("Done","success")}catch(n){s(`Action failed: ${n.message}`,"error")}}:null;case"mark-as-spam":return async t=>{const n=t&&t.closest?t.closest("[data-entry-id]"):null,r=n&&n.dataset?n.dataset.entryId:"",o=t&&t.closest?t.closest("[data-ctx]"):null;let c="";try{o&&o.dataset.ctx&&(c=(JSON.parse(atob(o.dataset.ctx))||{}).slug||"")}catch{}if(!r||!c){s("Right-click an entry in a collection display to mark it","error");return}try{const a=await fetch(`/api/collections/${encodeURIComponent(c)}/entries/${encodeURIComponent(r)}/spam`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"same-origin",body:JSON.stringify({field:e.field||void 0})});if(a.status===401||a.status===403){s("You do not have permission to do that","error");return}if(!a.ok)throw new Error(`HTTP ${a.status}`);s("Marked as spam","success"),n&&n.setAttribute("data-spam","true")}catch(a){s(`Could not mark as spam: ${a.message}`,"error")}};case"open-modal":return e.block?async()=>{try{const t=await fetch(`/api/blocks/${encodeURIComponent(e.block)}/render`);if(!t.ok)throw new Error(`HTTP ${t.status}`);const{html:n}=await t.json(),r=E.modal({title:e.title||"",closeOnBackdrop:!0}),o=document.createElement("div");o.innerHTML=typeof DOMPurify<"u"?DOMPurify.sanitize(n):n,r.element.appendChild(o),r.open()}catch(t){s(`Could not open: ${t.message}`,"error")}}:null;case"search":return t=>{const n=f(t);n&&n.dispatchEvent(new MouseEvent("contextmenu",{bubbles:!0,cancelable:!0,clientX:0,clientY:0}))};case"filter":case"sort":case"export":return t=>{const n=f(t);n&&n.dispatchEvent(new CustomEvent("dm-ctx-request",{bubbles:!0,detail:{...e}}))};default:return null}}const b=new Set(["search","filter","sort","export"]);function g(e){return l[e]&&l[e].disabled?l[e].disabled:b.has(e)?t=>!f(t):null}function h(e){const t=[];for(const n of e||[]){const r=n.type||"item";if(r==="divider"){t.push({type:"divider"});continue}if(r==="header"){t.push({type:"header",header:n.text||""});continue}if(Array.isArray(n.submenu)&&n.submenu.length){const a=h(n.submenu);a.length&&t.push({label:n.text,icon:n.icon,danger:!!n.danger,submenu:a});continue}const o=w(n.action);if(!o)continue;const c=g(n.action&&n.action.type);t.push({label:n.text,icon:n.icon||void 0,danger:!!n.danger,shortcut:n.shortcut||void 0,...c?{disabled:c}:{},action:o})}return t.some(n=>n.label)?t:[]}for(const e of d){const t=h(e.items);if(!t.length)continue;const n=e.target||{};if(!n.selector)continue;const r=e.theme||{};try{Domma.elements.contextMenu(n.selector,{match:n.match||null,exclude:n.exclude||null,inherit:e.inherit===void 0?"append":e.inherit,priority:e.priority||0,items:t,accent:r.accent,surface:r.surface,radius:r.radius,shadow:r.shadow,opacity:r.opacity,density:r.density,transition:r.transition,ariaLabel:e.name||"Context menu"})}catch(o){console.warn(`[context-menus] Skipped "${e.slug}": ${o.message}`)}}})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(u,f){typeof module<"u"&&module.exports?module.exports=f():u.FormLogicEngine=f()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function u(e){return e===""||e===null||e===void 0?"":String(e)}function f(e){const r=parseFloat(e);return isNaN(r)?null:r}function p(e){return e==null?!0:typeof e=="string"?e.trim()==="":Array.isArray(e)?e.length===0:!1}const F={not_equals:"equals",not_contains:"contains",not_in:"in"};function m(e,r){const n=u(r),t=u(e.value);switch(e.operator){case"equals":return n===t;case"not_equals":return n!==t;case"contains":return n.toLowerCase().includes(t.toLowerCase());case"not_contains":return!n.toLowerCase().includes(t.toLowerCase());case"starts_with":return n.toLowerCase().startsWith(t.toLowerCase());case"ends_with":return n.toLowerCase().endsWith(t.toLowerCase());case"greater_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s>i}case"less_than":{const s=f(r),i=f(e.value);return s!==null&&i!==null&&s<i}case"is_empty":return p(r);case"is_not_empty":return!p(r);case"in":return(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"not_in":return!(Array.isArray(e.value)?e.value.map(u):String(e.value).split(",").map(i=>i.trim())).includes(n);case"matches_regex":try{const s=e.flags||"";return new RegExp(e.value,s).test(n)}catch(s){return typeof console<"u"&&console.warn&&console.warn('[FormLogicEngine] Invalid regex in condition for field "'+e.field+'": '+e.value,s&&s.message),!1}default:return!0}}function y(e,r){if(!e||!e.field||!e.operator)return!0;const n=r[e.field];if(!Array.isArray(n))return m(e,n);if(e.operator==="is_empty")return p(n);if(e.operator==="is_not_empty")return!p(n);const t=F[e.operator];if(t){const s=Object.assign({},e,{operator:t});return!n.some(i=>m(s,i))}return n.some(s=>m(e,s))}function h(e,r){return e?Array.isArray(e.all)?e.all.every(n=>n.all||n.any?h(n,r):y(n,r)):Array.isArray(e.any)?e.any.some(n=>n.all||n.any?h(n,r):y(n,r)):e.field&&e.operator?y(e,r):!0:!0}function g(e,r){const n=e.logic;if(!n||!n.visibility)return"visible";const t=n.visibility,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then==="hidden"?"hidden":"visible";return t.default==="hidden"?"hidden":"visible"}function _(e,r){const n=e.logic;if(!n||!n.requirement)return e.required||!1;const t=n.requirement,s=t.conditions||[];for(const i of s)if(i.when&&h(i.when,r))return i.then===!0;return t.default===!0}function v(e,r,n){const t=e.logic;if(!t||!Array.isArray(t.validation))return[];const s=[];for(const i of t.validation)switch(i.type){case"regex":{if(!p(r))try{new RegExp(i.pattern||"",i.flags||"").test(u(r))||s.push({message:i.message||"Invalid format."})}catch{}break}case"match":{const a=n[i.field];!p(r)&&u(r)!==u(a)&&s.push({message:i.message||"Fields do not match."});break}}return s}function w(e,r){const n=e.logic;if(!n||!n.cascade||!n.cascade.sourceField)return null;const t=n.cascade,s=t.mapping||{},i=r[t.sourceField];if(Array.isArray(i)){const c=new Set,l=[];return i.forEach(function(V){const q=u(V);Object.prototype.hasOwnProperty.call(s,q)&&(s[q]||[]).forEach(function(b){const x=u(b&&b.value);c.has(x)||(c.add(x),l.push(b))})}),l.length?l:t.defaultOptions||null}const a=u(i);return Object.prototype.hasOwnProperty.call(s,a)?s[a]||[]:t.defaultOptions||null}const L={fade:250,slide:300,scale:200};function A(e,r){const n=Number(r);return!isFinite(n)||n<0||n>5e3?L[e]||250:Math.round(n)}function S(e,r,n){const t=A(r,n);if(r==="fade")e.style.transition="opacity "+t+"ms ease",e.style.opacity="1",requestAnimationFrame(function(){e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight="0",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",e.style.transform="scale(1)",e.style.opacity="1",requestAnimationFrame(function(){e.style.transform="scale(0.95)",e.style.opacity="0",setTimeout(function(){e.classList.add("fb-field-hidden"),e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function C(e,r,n){const t=A(r,n);if(e.classList.remove("fb-field-hidden"),r==="fade")e.style.opacity="0",e.style.transition="opacity "+t+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},t+10)});else if(r==="slide"){const s=Math.round(t*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+t+"ms ease, opacity "+s+"ms ease",requestAnimationFrame(function(){e.style.maxHeight=e.scrollHeight+"px",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.maxHeight="",e.style.opacity="",e.style.overflow=""},t+20)})}else r==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+t+"ms ease, transform "+t+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},t+20)}))}function o(e,r,n){this._form=e,this._wrapper=r,this._fields=(e.fields||[]).filter(t=>t.type!=="page-break"),this._listeners=[],this._depMap=new Map,this._initialEval=!1,this._baseValues=n&&n.baseValues||null}function d(e,r,n){const t=n||"",s=r||"";return t+'[name="'+e+'"]'+s+", "+t+'[name="'+e+'[]"]'+s}function k(e){return String(e||"").replace(/\[\]$/,"")}o.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(d(e))},o.prototype._fieldInput=function(e){return this._wrapper.querySelector(d(e))},o.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(r){const n=r.logic;if(!n)return;function t(s){if(!s)return;(s.all||s.any||[]).forEach(function(a){a.field?(e._depMap.has(a.field)||e._depMap.set(a.field,new Set),e._depMap.get(a.field).add(r.name)):t(a)})}if(n.visibility&&(n.visibility.conditions||[]).forEach(function(s){t(s.when)}),n.requirement&&(n.requirement.conditions||[]).forEach(function(s){t(s.when)}),n.cascade&&n.cascade.sourceField){const s=n.cascade.sourceField;e._depMap.has(s)||e._depMap.set(s,new Set),e._depMap.get(s).add(r.name)}})};function E(e,r){const n={};return(r||[]).forEach(function(t){if(!t||!t.name)return;const s=e.querySelectorAll(d(t.name));if(!s.length)return;const i=s[0];if(i.type==="radio"){const a=e.querySelector(d(t.name,":checked"));n[t.name]=a?a.value:""}else if(i.type==="checkbox")if(s.length>1||/\[\]$/.test(i.name||"")){const a=[];s.forEach(function(c){c.checked&&a.push(c.value)}),n[t.name]=a}else n[t.name]=i.checked?i.value||"true":"";else n[t.name]=i.value}),n}function M(e,r){const n=E(e,r),t=[],s=[];return(r||[]).forEach(function(i){if(!i||!i.name||g(i,n)==="hidden")return;const a=n[i.name],c=Array.isArray(a)?a.length===0:!String(a??"").trim();if(_(i,n)&&c){t.push({name:i.name,label:i.label||i.name});return}if(c)return;const l=v(i,a,n);l.length&&s.push(l[0].message)}),{valid:t.length===0&&s.length===0,missing:t,errors:s,values:n}}return o.prototype._getValues=function(){const e=this._baseValues?Object.assign({},this._baseValues):{};return this._fields.forEach(function(r){const n=this._fieldInputs(r.name);if(!n.length)return;const t=n[0];if(t.type==="radio"){const s=this._wrapper.querySelector(d(r.name,":checked"));e[r.name]=s?s.value:""}else if(t.type==="checkbox")if(n.length>1||/\[\]$/.test(t.name||"")){const s=[];n.forEach(function(i){i.checked&&s.push(i.value)}),e[r.name]=s}else e[r.name]=t.checked?t.value||"true":"";else e[r.name]=t.value},this),e},o.prototype._applyVisibility=function(e,r){const t=g(e,r)==="hidden",s=this._findFieldWrapper(e.name);if(!s)return;s.setAttribute("aria-hidden",String(t));const i=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(i==="none"){s.classList.toggle("fb-field-hidden",t);return}const a=e.logic?.visibility?.duration;s.style.transition="",t?S(s,i,a):C(s,i,a)},o.prototype._applyRequirement=function(e,r){const n=_(e,r),t=this._fieldInput(e.name);if(!t)return;if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){const i=this._findFieldWrapper(e.name);t.removeAttribute("required"),i&&(i.setAttribute("aria-required",String(n)),i.classList.toggle("fb-field-required",n));return}n?t.setAttribute("required",""):t.removeAttribute("required");const s=this._findFieldWrapper(e.name);s&&(s.setAttribute("aria-required",String(n)),s.classList.toggle("fb-field-required",n))},o.prototype._applyCascade=function(e,r){const n=w(e,r);if(n===null)return;const t=this._wrapper.querySelector(d(e.name,"","select"));if(!t)return;const s=t.value;t.textContent="",n.forEach(function(i){const a=document.createElement("option");a.value=i.value,a.textContent=i.label||i.value,i.value===s&&(a.selected=!0),t.appendChild(a)})},o.prototype._applyValidation=function(e,r){const n=this._fieldInput(e.name);if(!n)return;const t=v(e,r[e.name],r);let s=n.parentNode.querySelector(".fb-validation-error");t.length?(s||(s=document.createElement("div"),s.className="fb-validation-error",n.parentNode.appendChild(s)),s.textContent=t[0].message):s&&s.remove()},o.prototype._findFieldWrapper=function(e){const r=this._fieldInput(e);if(!r)return null;const n=r.closest("form")||this._wrapper;let t=r;for(;t.parentNode&&t.parentNode!==n;)t=t.parentNode;return t},o.prototype.evaluate=function(e){const r=this._getValues(),n=this;let t;if(e&&this._depMap.has(e)){const s=this._depMap.get(e);t=this._fields.filter(function(i){return s.has(i.name)})}else t=this._fields;t.forEach(function(s){s.logic&&(n._applyVisibility(s,r),n._applyRequirement(s,r),n._applyCascade(s,r))})},o.prototype.init=function(){this._buildDepMap();const e=this;this._wrapper.querySelectorAll("input, select, textarea").forEach(function(t){const s=k(t.getAttribute("name"));if(!s)return;const i=function(){e.evaluate(s)};t.addEventListener("input",i),t.addEventListener("change",i),e._listeners.push({el:t,event:"input",fn:i}),e._listeners.push({el:t,event:"change",fn:i});const a=e._fields.find(function(c){return c.name===s});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const c=function(){const l=e._getValues();e._applyValidation(a,l)};t.addEventListener("blur",c),e._listeners.push({el:t,event:"blur",fn:c})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(t){const s=t.getAttribute("data-chooser-field");if(!s)return;const i=function(){setTimeout(function(){e.evaluate(s)},0)};t.addEventListener("click",i),e._listeners.push({el:t,event:"click",fn:i})}),this._initialEval=!0,this.evaluate(),this._initialEval=!1},o.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn)}),this._listeners=[]},{evaluateCondition:y,evaluateConditionGroup:h,evaluateFieldVisibility:g,evaluateFieldRequirement:_,validateField:v,collectValues:E,validateFields:M,getCascadeOptions:w,FormLogicRuntime:o}});
|
|
1
|
+
(function(l,f){typeof module<"u"&&module.exports?module.exports=f():l.FormLogicEngine=f()})(typeof globalThis<"u"?globalThis:this,function(){"use strict";function l(e){return e===""||e===null||e===void 0?"":String(e)}function f(e){const n=parseFloat(e);return isNaN(n)?null:n}function d(e){return e==null?!0:typeof e=="string"?e.trim()==="":Array.isArray(e)?e.length===0:!1}const M={not_equals:"equals",not_contains:"contains",not_in:"in"};function v(e,n){const t=l(n),r=l(e.value);switch(e.operator){case"equals":return t===r;case"not_equals":return t!==r;case"contains":return t.toLowerCase().includes(r.toLowerCase());case"not_contains":return!t.toLowerCase().includes(r.toLowerCase());case"starts_with":return t.toLowerCase().startsWith(r.toLowerCase());case"ends_with":return t.toLowerCase().endsWith(r.toLowerCase());case"greater_than":{const i=f(n),s=f(e.value);return i!==null&&s!==null&&i>s}case"less_than":{const i=f(n),s=f(e.value);return i!==null&&s!==null&&i<s}case"is_empty":return d(n);case"is_not_empty":return!d(n);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 g(e,n){if(!e||!e.field||!e.operator)return!0;const t=n[e.field];if(!Array.isArray(t))return v(e,t);if(e.operator==="is_empty")return d(t);if(e.operator==="is_not_empty")return!d(t);const r=M[e.operator];if(r){const i=Object.assign({},e,{operator:r});return!t.some(s=>v(i,s))}return t.some(i=>v(e,i))}function p(e,n){return e?Array.isArray(e.all)?e.all.every(t=>t.all||t.any?p(t,n):g(t,n)):Array.isArray(e.any)?e.any.some(t=>t.all||t.any?p(t,n):g(t,n)):e.field&&e.operator?g(e,n):!0:!0}function w(e,n){const t=e.logic;if(!t||!t.visibility)return"visible";const r=t.visibility,i=r.conditions||[];for(const s of i)if(s.when&&p(s.when,n))return s.then==="hidden"?"hidden":"visible";return r.default==="hidden"?"hidden":"visible"}function y(e,n){const t=e.logic;if(!t||!t.requirement)return e.required||!1;const r=t.requirement,i=r.conditions||[];for(const s of i)if(s.when&&p(s.when,n))return s.then===!0;return r.default===!0}function q(e,n,t){const r=e.logic;if(!r||!Array.isArray(r.validation))return[];const i=[];for(const s of r.validation)switch(s.type){case"regex":{if(!d(n))try{new RegExp(s.pattern||"",s.flags||"").test(l(n))||i.push({message:s.message||"Invalid format."})}catch{}break}case"match":{const a=t[s.field];!d(n)&&l(n)!==l(a)&&i.push({message:s.message||"Fields do not match."});break}}return i}function x(e,n){const t=e.logic;if(!t||!t.cascade||!t.cascade.sourceField)return null;const r=t.cascade,i=r.mapping||{},s=n[r.sourceField];if(Array.isArray(s)){const c=new Set,u=[];return s.forEach(function(m){const _=l(m);Object.prototype.hasOwnProperty.call(i,_)&&(i[_]||[]).forEach(function(S){const I=l(S&&S.value);c.has(I)||(c.add(I),u.push(S))})}),u.length?u:r.defaultOptions||null}const a=l(s);return Object.prototype.hasOwnProperty.call(i,a)?i[a]||[]:r.defaultOptions||null}const R={fade:250,slide:300,scale:200};function k(e,n){const t=Number(n);return!isFinite(t)||t<0||t>5e3?R[e]||250:Math.round(t)}function O(e,n,t){const r=k(n,t);if(n==="fade")e.style.transition="opacity "+r+"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=""},r+10)});else if(n==="slide"){const i=Math.round(r*.67);e.style.overflow="hidden",e.style.maxHeight=e.scrollHeight+"px",e.style.transition="max-height "+r+"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=""},r+20)})}else n==="scale"&&(e.style.transition="opacity "+r+"ms ease, transform "+r+"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=""},r+20)}))}function V(e,n,t){const r=k(n,t);if(e.classList.remove("fb-field-hidden"),n==="fade")e.style.opacity="0",e.style.transition="opacity "+r+"ms ease",requestAnimationFrame(function(){e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.opacity=""},r+10)});else if(n==="slide"){const i=Math.round(r*.67);e.style.overflow="hidden",e.style.maxHeight="0",e.style.opacity="0",e.style.transition="max-height "+r+"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=""},r+20)})}else n==="scale"&&(e.style.transform="scale(0.95)",e.style.opacity="0",e.style.transition="opacity "+r+"ms ease, transform "+r+"ms ease",requestAnimationFrame(function(){e.style.transform="scale(1)",e.style.opacity="1",setTimeout(function(){e.style.transition="",e.style.transform="",e.style.opacity=""},r+20)}))}const C={banner:"state","disable-fields":"state","hide-fields":"state","require-fields":"state","block-submit":"state",toast:"event",celebrate:"event","goto-step":"event",redirect:"event","run-action":"event"},B=["block-submit","hide-fields","disable-fields","require-fields","redirect","run-action"];function T(e){return!!e&&!!e.name&&e.type!=="page-break"&&e.type!=="spacer"}function b(e,n,t){const r=(t||[]).filter(T),i=e.target||(e.fields&&e.fields.length?"listed":"rest");if(i==="listed"){const a=new Set(e.fields||[]);return r.filter(c=>a.has(c.name)&&c.name!==n.name).map(c=>c.name)}if(i==="all")return r.filter(a=>a.name!==n.name).map(a=>a.name);const s=r.findIndex(a=>a.name===n.name);return s===-1?[]:r.slice(s+1).map(a=>a.name)}function A(e,n){for(const t of n)e.includes(t)||e.push(t)}function H(e,n,t,r,i){if(!n||!n.type)return;const s=C[n.type];if(s){if(s==="event"){e.events.push({key:i,type:n.type,field:t.name,action:n});return}switch(n.type){case"banner":e.banners.push({key:i,field:t.name,message:n.message||"",level:n.level||"info",position:n.position||"field-below",dismissible:n.dismissible!==!1});break;case"hide-fields":A(e.hidden,b(n,t,r));break;case"disable-fields":A(e.disabled,b(n,t,r));break;case"require-fields":A(e.required,b(n,t,r));break;case"block-submit":e.blocks.push({key:i,message:n.message||"This form cannot be submitted yet."});break;default:break}}}function F(e,n){const t={active:[],banners:[],hidden:[],disabled:[],required:[],blocks:[],events:[]};return(e||[]).forEach(r=>{!T(r)||!Array.isArray(r.triggers)||r.triggers.forEach((i,s)=>{if(!i||i.enabled===!1)return;const a=i.id||`${r.name}::${s}`,c=p(i.when,n),u=`${a}:${c?"then":"else"}`,m=c?i.then:i.otherwise;!Array.isArray(m)||!m.length||(t.active.push(u),m.forEach(_=>H(t,_,r,e,u)))})}),t.required=t.required.filter(r=>!t.hidden.includes(r)),t}function N(e){return(e||[]).some(n=>Array.isArray(n&&n.triggers)&&n.triggers.length>0)}function o(e,n,t){this._form=e,this._wrapper=n,this._fields=(e.fields||[]).filter(r=>r.type!=="page-break"),this._listeners=[],this._depMap=new Map,this._initialEval=!1,this._baseValues=t&&t.baseValues||null,this._hasTriggers=N(this._fields),this._triggerState=null,this._triggerPrev=new Set,this._triggerFired=new Set,this._triggerApplied={hidden:[],disabled:[],required:[]},this._banners=new Map,this._dismissed=new Set}function h(e,n,t){const r=t||"",i=n||"";return r+'[name="'+e+'"]'+i+", "+r+'[name="'+e+'[]"]'+i}function W(e){return String(e||"").replace(/\[\]$/,"")}o.prototype._fieldInputs=function(e){return this._wrapper.querySelectorAll(h(e))},o.prototype._fieldInput=function(e){return this._wrapper.querySelector(h(e))},o.prototype._buildDepMap=function(){this._depMap.clear();const e=this;e._fields.forEach(function(n){const t=n.logic;if(!t)return;function r(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(n.name)):r(a)})}if(t.visibility&&(t.visibility.conditions||[]).forEach(function(i){r(i.when)}),t.requirement&&(t.requirement.conditions||[]).forEach(function(i){r(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(n.name)}})};function L(e,n){const t={};return(n||[]).forEach(function(r){if(!r||!r.name)return;const i=e.querySelectorAll(h(r.name));if(!i.length)return;const s=i[0];if(s.type==="radio"){const a=e.querySelector(h(r.name,":checked"));t[r.name]=a?a.value:""}else if(s.type==="checkbox")if(i.length>1||/\[\]$/.test(s.name||"")){const a=[];i.forEach(function(c){c.checked&&a.push(c.value)}),t[r.name]=a}else t[r.name]=s.checked?s.value||"true":"";else t[r.name]=s.value}),t}function D(e,n){const t=L(e,n),r=[],i=[];return(n||[]).forEach(function(s){if(!s||!s.name||w(s,t)==="hidden")return;const a=t[s.name],c=Array.isArray(a)?a.length===0:!String(a??"").trim();if(y(s,t)&&c){r.push({name:s.name,label:s.label||s.name});return}if(c)return;const u=q(s,a,t);u.length&&i.push(u[0].message)}),{valid:r.length===0&&i.length===0,missing:r,errors:i,values:t}}return o.prototype._getValues=function(){const e=this._baseValues?Object.assign({},this._baseValues):{};return this._fields.forEach(function(n){const t=this._fieldInputs(n.name);if(!t.length)return;const r=t[0];if(r.type==="radio"){const i=this._wrapper.querySelector(h(n.name,":checked"));e[n.name]=i?i.value:""}else if(r.type==="checkbox")if(t.length>1||/\[\]$/.test(r.name||"")){const i=[];t.forEach(function(s){s.checked&&i.push(s.value)}),e[n.name]=i}else e[n.name]=r.checked?r.value||"true":"";else e[n.name]=r.value},this),e},o.prototype._applyVisibility=function(e,n){const r=w(e,n)==="hidden",i=this._findFieldWrapper(e.name);if(!i)return;i.setAttribute("aria-hidden",String(r));const s=this._initialEval?"none":e.logic?.visibility?.transition||"none";if(s==="none"){i.classList.toggle("fb-field-hidden",r);return}const a=e.logic?.visibility?.duration;i.style.transition="",r?O(i,s,a):V(i,s,a)},o.prototype._applyRequirement=function(e,n){const t=y(e,n),r=this._fieldInput(e.name);if(!r)return;if(/\[\]$/.test(r.name||"")||r.closest&&r.closest(".domma-chooser")){const s=this._findFieldWrapper(e.name);r.removeAttribute("required"),s&&(s.setAttribute("aria-required",String(t)),s.classList.toggle("fb-field-required",t));return}t?r.setAttribute("required",""):r.removeAttribute("required");const i=this._findFieldWrapper(e.name);i&&(i.setAttribute("aria-required",String(t)),i.classList.toggle("fb-field-required",t))},o.prototype._applyCascade=function(e,n){const t=x(e,n);if(t===null)return;const r=this._wrapper.querySelector(h(e.name,"","select"));if(!r)return;const i=r.value;r.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),r.appendChild(a)})},o.prototype._applyValidation=function(e,n){const t=this._fieldInput(e.name);if(!t)return;const r=q(e,n[e.name],n);let i=t.parentNode.querySelector(".fb-validation-error");r.length?(i||(i=document.createElement("div"),i.className="fb-validation-error",t.parentNode.appendChild(i)),i.textContent=r[0].message):i&&i.remove()},o.prototype._findFieldWrapper=function(e){const n=this._fieldInput(e);if(!n)return null;const t=n.closest("form")||this._wrapper;let r=n;for(;r.parentNode&&r.parentNode!==t;)r=r.parentNode;return r},o.prototype.evaluate=function(e){const n=this._getValues(),t=this;let r;if(e&&this._depMap.has(e)){const i=this._depMap.get(e);r=this._fields.filter(function(s){return i.has(s.name)})}else r=this._fields;r.forEach(function(i){i.logic&&(t._applyVisibility(i,n),t._applyRequirement(i,n),t._applyCascade(i,n))}),this._applyTriggers(n)},o.prototype.init=function(){this._buildDepMap();const e=this;this._wrapper.querySelectorAll("input, select, textarea").forEach(function(r){const i=W(r.getAttribute("name"));if(!i)return;const s=function(){e.evaluate(i)};r.addEventListener("input",s),r.addEventListener("change",s),e._listeners.push({el:r,event:"input",fn:s}),e._listeners.push({el:r,event:"change",fn:s});const a=e._fields.find(function(c){return c.name===i});if(a&&a.logic&&Array.isArray(a.logic.validation)&&a.logic.validation.length){const c=function(){const u=e._getValues();e._applyValidation(a,u)};r.addEventListener("blur",c),e._listeners.push({el:r,event:"blur",fn:c})}}),this._wrapper.querySelectorAll("[data-chooser-field]").forEach(function(r){const i=r.getAttribute("data-chooser-field");if(!i)return;const s=function(){setTimeout(function(){e.evaluate(i)},0)};r.addEventListener("click",s),e._listeners.push({el:r,event:"click",fn:s})}),this._initialEval=!0,this.evaluate(),this._initialEval=!1},o.prototype.destroy=function(){this._listeners.forEach(function(e){e.el.removeEventListener(e.event,e.fn)}),this._listeners=[],this._banners.forEach(function(e){e&&e.parentNode&&e.parentNode.removeChild(e)}),this._banners.clear()},o.prototype._applyTriggers=function(e){if(!this._hasTriggers)return;const n=F(this._fields,e);this._triggerState=n;const t=this._triggerApplied||{hidden:[],disabled:[],required:[]};t.hidden.forEach(r=>{n.hidden.indexOf(r)===-1&&this._setTriggerHidden(r,!1)}),n.hidden.forEach(r=>this._setTriggerHidden(r,!0)),t.disabled.forEach(r=>{n.disabled.indexOf(r)===-1&&this._setTriggerDisabled(r,!1)}),n.disabled.forEach(r=>this._setTriggerDisabled(r,!0)),t.required.forEach(r=>{n.required.indexOf(r)===-1&&this._restoreRequired(r,e)}),n.required.forEach(r=>this._setTriggerRequired(r,!0)),this._triggerApplied={hidden:n.hidden.slice(),disabled:n.disabled.slice(),required:n.required.slice()},this._syncBanners(n.banners),this._syncSubmitBlock(n.blocks),this._fireTriggerEvents(n)},o.prototype._setTriggerHidden=function(e,n){const t=this._findFieldWrapper(e);t&&(t.classList.toggle("fb-field-trigger-hidden",n),t.setAttribute("aria-hidden",String(n||t.classList.contains("fb-field-hidden"))))},o.prototype._setTriggerDisabled=function(e,n){const t=this._findFieldWrapper(e);t&&t.classList.toggle("fb-field-disabled",n),this._fieldInputs(e).forEach(function(i){i.disabled=n});const r=this._wrapper.querySelector('[data-chooser-field="'+e+'"]');r&&(r.classList.toggle("fb-field-disabled",n),r.querySelectorAll('button, [role="radio"], [role="checkbox"]').forEach(function(i){n?i.setAttribute("aria-disabled","true"):i.removeAttribute("aria-disabled")}))},o.prototype._setTriggerRequired=function(e,n){const t=this._fieldInput(e),r=this._findFieldWrapper(e);if(r&&(r.setAttribute("aria-required",String(n)),r.classList.toggle("fb-field-required",n)),!!t){if(/\[\]$/.test(t.name||"")||t.closest&&t.closest(".domma-chooser")){t.removeAttribute("required");return}n?t.setAttribute("required",""):t.removeAttribute("required")}},o.prototype._restoreRequired=function(e,n){const t=this._fields.find(function(r){return r.name===e});t&&this._setTriggerRequired(e,y(t,n))},o.prototype._syncBanners=function(e){const n=new Map;e.forEach(function(t){n.set(t.key,t)}),this._banners.forEach(function(t,r){n.has(r)||(t.parentNode&&t.parentNode.removeChild(t),this._banners.delete(r))},this),this._dismissed.forEach(function(t){n.has(t)||this._dismissed.delete(t)},this),n.forEach(function(t,r){if(this._banners.has(r)){const a=this._banners.get(r).querySelector(".fb-trigger-banner-text");a&&a.textContent!==t.message&&(a.textContent=t.message);return}if(this._dismissed.has(r))return;const i=this._buildBanner(t,r);i&&this._banners.set(r,i)},this)},o.prototype._buildBanner=function(e,n){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=n;const r=document.createElement("span");if(r.className="fb-trigger-banner-text",r.textContent=e.message,t.appendChild(r),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 c=this;a.addEventListener("click",function(){c._dismissed.add(n),t.parentNode&&t.parentNode.removeChild(t),c._banners.delete(n)}),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},o.prototype._syncSubmitBlock=function(e){const n=this._wrapper.querySelector("form")||this._wrapper,t=n.querySelector('button[type="submit"], input[type="submit"], .fb-form-submit'),r=e.length>0;this._wrapper.dataset.triggerBlocked=r?"true":"false",t&&(t.disabled=r,t.setAttribute("aria-disabled",String(r)));let i=n.querySelector(".fb-trigger-block-note");if(!r){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:n).appendChild(i)),i.textContent=e.map(function(s){return s.message}).join(" ")},o.prototype._fireTriggerEvents=function(e){const n=new Set(e.active),t=this;e.events.forEach(function(r){t._triggerPrev.has(r.key)||r.action.once&&t._triggerFired.has(r.key)||t._initialEval&&r.action.onLoad!==!0||(t._triggerFired.add(r.key),t._runTriggerEvent(r))}),this._triggerPrev=n},o.prototype._runTriggerEvent=function(e){const n=e.action;switch(n.type){case"toast":typeof E<"u"&&E&&typeof E.toast=="function"&&E.toast(n.message||"",{type:n.level||"info",duration:Number(n.duration)||4e3});break;case"celebrate":this._celebrate(n);break;default:break}typeof CustomEvent<"u"&&this._wrapper.dispatchEvent&&this._wrapper.dispatchEvent(new CustomEvent("dm-form-trigger",{bubbles:!0,detail:{type:n.type,field:e.field,action:n}}))},o.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(n){const t=n.CelebrationsEffect;let r=e.theme||"auto";if(r==="auto"&&(r=t.getCurrentTheme(),!r))return;const i=new t({theme:r,intensity:e.intensity||"medium",enabled:!0,zIndex:999});i.init().then(function(){i.start()})}).catch(function(){})},o.prototype.submitBlock=function(){const e=this._triggerState&&this._triggerState.blocks||[];return{blocked:e.length>0,reasons:e.map(function(n){return n.message})}},{evaluateCondition:g,evaluateConditionGroup:p,evaluateFieldVisibility:w,evaluateFieldRequirement:y,validateField:q,collectValues:L,validateFields:D,getCascadeOptions:x,resolveTriggerState:F,resolveTriggerTargets:b,hasTriggers:N,TRIGGER_ACTION_KINDS:C,SERVER_TRIGGER_ACTIONS:B,FormLogicRuntime:o}});
|
package/public/js/forms.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{buildWizardSteps as
|
|
2
|
-
`).replace(/<[^>]+>/g,""))}function F(n){return String(n).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function w(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 N(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 a of i.removedNodes)if(a===n||a.nodeType===1&&a.contains&&a.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function V(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function j(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)),a=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 r={type:a,label:e.label||e.name,required:V(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&&(r.minLength=e.minLength),e.maxLength!==void 0&&(r.maxLength=e.maxLength),e.min!==void 0&&(r.min=e.min),e.max!==void 0&&(r.max=e.max),i&&(e.variant&&(r.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(r.multiple=!0),e.density&&(r.density=e.density),e.columns&&(r.columns=e.columns),e.accent&&(r.accent=e.accent),e.accentStyle&&(r.accentStyle=e.accentStyle),e.glow&&(r.glow=!0),e.glowColour&&(r.glowColour=e.glowColour),e.shadow&&(r.shadow=e.shadow),e.shadowColour&&(r.shadowColour=e.shadowColour)),t[e.name]=r}),t}function W(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 _(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 A="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 O(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 a=document.createElement("button");a.type="button",a.textContent="\xD7",a.setAttribute("aria-label","Close"),a.style.cssText=A+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(a),t.appendChild(e);const d=document.createElement("div");d.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(d),o.appendChild(t);const r=u=>{u.key==="Escape"&&s()};function s(){document.removeEventListener("keydown",r),o.remove()}return a.addEventListener("click",s),o.addEventListener("click",u=>{u.target===o&&s()}),document.addEventListener("keydown",r),document.body.appendChild(o),{body:d,close:s}}function J(n){const{body:o,close:t}=O("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 a=window.I&&typeof I.list=="function"?I.list():[],d=a.map(r=>{const s=document.createElement("button");s.type="button",s.title=r,s.dataset.iconName=r,s.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const u=document.createElement("span");return u.setAttribute("data-icon",r),u.setAttribute("data-icon-size","18"),s.appendChild(u),s.addEventListener("mouseenter",()=>{s.style.borderColor="var(--dm-border)"}),s.addEventListener("mouseleave",()=>{s.style.borderColor="transparent"}),s.addEventListener("click",()=>{t(),n(r)}),i.appendChild(s),s});if(!a.length){const r=document.createElement("p");r.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(r)}window.I?.scan?.(i),e.addEventListener("input",()=>{const r=e.value.trim().toLowerCase();d.forEach(s=>{s.style.display=!r||s.dataset.iconName.includes(r)?"":"none"})}),e.focus()}async function U(){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:a}=await i.json();S.set("auth_token",a),t=await o(a)}}}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 H(n){const{body:o,close:t}=O("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),U().then(({files:i,error:a})=>{if(a){e.textContent=a==="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(r=>{const s=document.createElement("button");s.type="button",s.title=r.name||r.url,s.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const u=document.createElement("img");u.src=r.url,u.alt=r.name||"",u.loading="lazy",u.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const c=document.createElement("span");c.textContent=r.name||r.url,c.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.appendChild(u),s.appendChild(c),s.addEventListener("click",()=>{t(),n(r.url)}),d.appendChild(s)}),o.appendChild(d)})}function R(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function z(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 B(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=A,o}function K(n){if(!window.I||typeof I.list!="function")return;const o=z(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 a=n.value.trim();if(!a)return;const d=document.createElement("span");d.setAttribute("data-icon",a),d.setAttribute("data-icon-size","16"),t.appendChild(d),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=B("Browse");i.addEventListener("click",()=>J(a=>{R(n,a),e()})),o.appendChild(t),o.appendChild(i)}function Y(n){const o=z(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 a=n.value.trim();t.style.display=a?"":"none",a&&(t.src=a)};n.addEventListener("input",e),e();const i=B("Browse");i.addEventListener("click",()=>H(a=>{R(n,a),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"?K(i):Y(i))})}function L(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 P(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(a){if(a.type==="spacer"){const d=document.createElement("div");d.className="fb-spacer";const r=e[i];if(r)t.insertBefore(d,r);else{const s=t.querySelector('[type="submit"]');s?t.insertBefore(d,s):t.appendChild(d)}}else a.type!=="page-break"&&i++})}function k(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 q(n,o,t,e,i,a){const d=i||e,r=d.querySelector(".fb-form-honeypot"),s=r?.querySelector('input[type="text"]')?.value||"",u=r?.querySelector('[name="_t"]')?.value||"",c=Object.assign({},o);delete c._t,r?.dataset.hpName&&delete c[r.dataset.hpName];const m=new Map(a||[]);k(d,m);const l=m.size>0;let b,y;if(l){const p=new FormData;for(const[h,v]of Object.entries(c))v!=null&&(m.has(h)||p.append(h,typeof v=="object"?JSON.stringify(v):String(v)));for(const[h,v]of m)for(const x of v)p.append(h,x,x.name);p.append("_hp",s),p.append("_t",u),b=p,y={}}else{const p=Object.assign({},c,{_hp:s,_t:u});b=JSON.stringify(p),y={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:y,body:b}).then(p=>p.json().then(h=>({ok:p.ok,body:h}))).then(p=>{p.ok&&p.body.ok?(e.textContent="",w(e,p.body.message||t.successMessage||"Thank you.","success")):w(e,p.body.error||"Something went wrong.","error")}).catch(()=>{w(e,"Unable to submit. Please check your connection.","error")})}function $(n,o,t,e,i){const a=document.createElement("form");a.noValidate=!0,o.forEach(function(r){const s=document.createElement("div");s.className="form-group",s.style.marginBottom="1.25rem";const u=document.createElement("label");if(u.className="form-label",u.textContent=r.label||r.name,r.required){const m=document.createElement("span");m.textContent=" *",m.style.color="var(--dm-danger)",u.appendChild(m)}let c;r.type==="textarea"?(c=document.createElement("textarea"),c.rows=r.formConfig?.rows||4,c.className="form-input"):r.type==="select"?(c=document.createElement("select"),c.className="form-input",(r.options||[]).forEach(function(m){const l=document.createElement("option");l.value=typeof m=="string"?m:m.value??"",l.textContent=typeof m=="string"?m:m.label||l.value,c.appendChild(l)})):(c=document.createElement("input"),c.type=r.type==="icon"||r.type==="image"?"text":r.type||"text",c.className="form-input",r.placeholder&&(c.placeholder=r.placeholder),r.type==="file"&&(r.file?.accept&&(c.accept=r.file.accept),r.multiple&&(c.multiple=!0))),c.name=r.name,c.required=r.required||!1,s.appendChild(u),s.appendChild(c),a.appendChild(s)}),t.honeypot&&L(a);const d=document.createElement("button");d.type="submit",d.className="btn btn-primary",d.textContent=t.submitText||"Submit",a.appendChild(d),a.addEventListener("submit",function(r){r.preventDefault();const s={};if(o.forEach(function(u){const c=a.querySelector('[name="'+u.name+'"]');c&&(s[u.name]=c.value)}),window.FormLogicEngine&&i){const u=window.FormLogicEngine,c=[],m=[];if(o.forEach(function(l){if(u.evaluateFieldVisibility(l,s)==="hidden"){delete s[l.name];return}const y=u.evaluateFieldRequirement(l,s),p=s[l.name];y&&(!p||!String(p).trim())&&c.push(l.label||l.name);const h=u.validateField(l,p||"",s);h.length&&m.push(h[0].message)}),c.length||m.length){const l=[];c.length&&l.push("Required: "+c.join(", ")),m.length&&l.push(m.join("; ")),w(n,l.join(". "),"error");return}}n.classList.add("fb-form-loading"),d.disabled=!0,q(e,s,t,n,a).finally(function(){n.classList.remove("fb-form-loading"),d.disabled=!1})}),n.appendChild(a),enhancePickerFields(n,o),window.FormLogicEngine&&i&&o.some(r=>r.logic)&&new window.FormLogicEngine.FormLogicRuntime(i,n).init()}function G(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||{},a=document.createElement("div");a.className="fb-form-wrapper",n.appendChild(a);const d=e.some(r=>r.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const r=Number(i.columns)===3?3:2,s=i.layout||"grid";if(d&&Domma.forms.wizard){const u=D(e,t.title),c=u.map(f=>f.fields),m=u.map(function(f){return{title:f.title,description:f.description,fields:j(f.fields,r)}});let l=0,b=null,y=null;const p=Date.now(),h=new Map,v=function(f){const g=window.FormLogicEngine;if(!g||!g.validateFields)return;const C=g.validateFields(a,c[l]||[]);C.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(a,C.missing),showValidationPopup(C))},x=function(){const f=c[l]||e;if(_(a,f),enhancePickerFields(a,f),f.some(g=>g.type==="spacer")&&P(a,f),i.honeypot){const g=a.querySelector("form");g&&L(g,p)}window.FormLogicEngine&&e.some(g=>g.logic)&&(b&&b.destroy(),b=new window.FormLogicEngine.FormLogicRuntime(t,a,{baseValues:y&&y.getStepData?y.getStepData():{}}),b.init(),N(a,b)),a.querySelectorAll(".wizard-next, .wizard-submit").forEach(g=>g.addEventListener("click",v,!0))};y=Domma.forms.wizard(a,{schema:{steps:m},layout:s,columns:r,finishText:i.submitText||"Finish",onStepChange:function(f){k(a,h),l=f,setTimeout(x,0)},onSubmit:function(f){return k(a,h),q(o,f,i,a,null,h)}}),Promise.resolve(y).then(x)}else if(Domma.forms.render){const u=j(e,r),c=W(e),m=Domma.forms.render(a,u,c,{submitText:i.submitText||"Submit",layout:s,columns:r,onSubmit:function(l){return q(o,l,i,a,null)}});Promise.resolve(m).then(function(){if(_(a,e),enhancePickerFields(a,e),window.FormLogicEngine&&e.some(l=>l.logic)){const l=new window.FormLogicEngine.FormLogicRuntime(t,a);l.init(),N(a,l)}if(e.some(l=>l.type==="spacer")&&P(a,e),s==="grid"&&i.submitSpan==="full"){const l=a.querySelector(".form-buttons");l&&l.classList.add("col-span-full")}if(i.honeypot){const l=a.querySelector("form");l&&L(l)}})}}else $(a,e.filter(r=>r.type!=="page-break"&&r.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{buildWizardSteps as M}from"/public/js/form-steps.mjs";const F=document.querySelectorAll("[data-form]");F.length&&F.forEach(Q);function L(n){return(n||[]).some(o=>o.logic||Array.isArray(o.triggers)&&o.triggers.length)}function V(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let i=t;for(;i.parentNode&&i.parentNode!==e;)i=i.parentNode;return i}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const i=V(n,e.name);i&&(i.classList.add("fb-field-invalid"),t||(t=i))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+N(e.label)+"</strong> is required.").concat((n.errors||[]).map(N)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
|
|
2
|
+
`).replace(/<[^>]+>/g,""))}function N(n){return String(n).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function w(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 _(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 a of i.removedNodes)if(a===n||a.nodeType===1&&a.contains&&a.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function W(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function j(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)),a=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,u={...e.formConfig||{}};u.span==="full"&&o&&(u.span=o);const r={type:a,label:e.label||e.name,required:W(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...u}};e.minLength!==void 0&&(r.minLength=e.minLength),e.maxLength!==void 0&&(r.maxLength=e.maxLength),e.min!==void 0&&(r.min=e.min),e.max!==void 0&&(r.max=e.max),i&&(e.variant&&(r.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(r.multiple=!0),e.density&&(r.density=e.density),e.columns&&(r.columns=e.columns),e.accent&&(r.accent=e.accent),e.accentStyle&&(r.accentStyle=e.accentStyle),e.glow&&(r.glow=!0),e.glowColour&&(r.glowColour=e.glowColour),e.shadow&&(r.shadow=e.shadow),e.shadowColour&&(r.shadowColour=e.shadowColour)),t[e.name]=r}),t}function J(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 A(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 R="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 O(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 a=document.createElement("button");a.type="button",a.textContent="\xD7",a.setAttribute("aria-label","Close"),a.style.cssText=R+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(a),t.appendChild(e);const u=document.createElement("div");u.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(u),o.appendChild(t);const r=l=>{l.key==="Escape"&&s()};function s(){document.removeEventListener("keydown",r),o.remove()}return a.addEventListener("click",s),o.addEventListener("click",l=>{l.target===o&&s()}),document.addEventListener("keydown",r),document.body.appendChild(o),{body:u,close:s}}function U(n){const{body:o,close:t}=O("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 a=window.I&&typeof I.list=="function"?I.list():[],u=a.map(r=>{const s=document.createElement("button");s.type="button",s.title=r,s.dataset.iconName=r,s.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const l=document.createElement("span");return l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","18"),s.appendChild(l),s.addEventListener("mouseenter",()=>{s.style.borderColor="var(--dm-border)"}),s.addEventListener("mouseleave",()=>{s.style.borderColor="transparent"}),s.addEventListener("click",()=>{t(),n(r)}),i.appendChild(s),s});if(!a.length){const r=document.createElement("p");r.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(r)}window.I?.scan?.(i),e.addEventListener("input",()=>{const r=e.value.trim().toLowerCase();u.forEach(s=>{s.style.display=!r||s.dataset.iconName.includes(r)?"":"none"})}),e.focus()}async function H(){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:a}=await i.json();S.set("auth_token",a),t=await o(a)}}}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 K(n){const{body:o,close:t}=O("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),H().then(({files:i,error:a})=>{if(a){e.textContent=a==="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 u=document.createElement("div");u.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(r=>{const s=document.createElement("button");s.type="button",s.title=r.name||r.url,s.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const l=document.createElement("img");l.src=r.url,l.alt=r.name||"",l.loading="lazy",l.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const c=document.createElement("span");c.textContent=r.name||r.url,c.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",s.appendChild(l),s.appendChild(c),s.addEventListener("click",()=>{t(),n(r.url)}),u.appendChild(s)}),o.appendChild(u)})}function B(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function z(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 P(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=R,o}function Y(n){if(!window.I||typeof I.list!="function")return;const o=z(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 a=n.value.trim();if(!a)return;const u=document.createElement("span");u.setAttribute("data-icon",a),u.setAttribute("data-icon-size","16"),t.appendChild(u),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=P("Browse");i.addEventListener("click",()=>U(a=>{B(n,a),e()})),o.appendChild(t),o.appendChild(i)}function $(n){const o=z(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 a=n.value.trim();t.style.display=a?"":"none",a&&(t.src=a)};n.addEventListener("input",e),e();const i=P("Browse");i.addEventListener("click",()=>K(a=>{B(n,a),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"?Y(i):$(i))})}function k(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 D(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(a){if(a.type==="spacer"){const u=document.createElement("div");u.className="fb-spacer";const r=e[i];if(r)t.insertBefore(u,r);else{const s=t.querySelector('[type="submit"]');s?t.insertBefore(u,s):t.appendChild(u)}}else a.type!=="page-break"&&i++})}function T(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 q(n,o,t,e,i,a){const u=i||e,r=u.querySelector(".fb-form-honeypot"),s=r?.querySelector('input[type="text"]')?.value||"",l=r?.querySelector('[name="_t"]')?.value||"",c=Object.assign({},o);delete c._t,r?.dataset.hpName&&delete c[r.dataset.hpName];const m=new Map(a||[]);T(u,m);const d=m.size>0;let b,g;if(d){const p=new FormData;for(const[y,v]of Object.entries(c))v!=null&&(m.has(y)||p.append(y,typeof v=="object"?JSON.stringify(v):String(v)));for(const[y,v]of m)for(const x of v)p.append(y,x,x.name);p.append("_hp",s),p.append("_t",l),b=p,g={}}else{const p=Object.assign({},c,{_hp:s,_t:l});b=JSON.stringify(p),g={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:g,body:b}).then(p=>p.json().then(y=>({ok:p.ok,body:y}))).then(p=>{p.ok&&p.body.ok?(e.textContent="",w(e,p.body.message||t.successMessage||"Thank you.","success")):w(e,p.body.error||"Something went wrong.","error")}).catch(()=>{w(e,"Unable to submit. Please check your connection.","error")})}function G(n,o,t,e,i){const a=document.createElement("form");a.noValidate=!0,o.forEach(function(r){const s=document.createElement("div");s.className="form-group",s.style.marginBottom="1.25rem";const l=document.createElement("label");if(l.className="form-label",l.textContent=r.label||r.name,r.required){const m=document.createElement("span");m.textContent=" *",m.style.color="var(--dm-danger)",l.appendChild(m)}let c;r.type==="textarea"?(c=document.createElement("textarea"),c.rows=r.formConfig?.rows||4,c.className="form-input"):r.type==="select"?(c=document.createElement("select"),c.className="form-input",(r.options||[]).forEach(function(m){const d=document.createElement("option");d.value=typeof m=="string"?m:m.value??"",d.textContent=typeof m=="string"?m:m.label||d.value,c.appendChild(d)})):(c=document.createElement("input"),c.type=r.type==="icon"||r.type==="image"?"text":r.type||"text",c.className="form-input",r.placeholder&&(c.placeholder=r.placeholder),r.type==="file"&&(r.file?.accept&&(c.accept=r.file.accept),r.multiple&&(c.multiple=!0))),c.name=r.name,c.required=r.required||!1,s.appendChild(l),s.appendChild(c),a.appendChild(s)}),t.honeypot&&k(a);const u=document.createElement("button");if(u.type="submit",u.className="btn btn-primary",u.textContent=t.submitText||"Submit",a.appendChild(u),a.addEventListener("submit",function(r){r.preventDefault();const s={};if(o.forEach(function(l){const c=a.querySelector('[name="'+l.name+'"]');c&&(s[l.name]=c.value)}),window.FormLogicEngine&&i){const l=window.FormLogicEngine,c=[],m=[];if(o.forEach(function(d){if(l.evaluateFieldVisibility(d,s)==="hidden"){delete s[d.name];return}const g=l.evaluateFieldRequirement(d,s),p=s[d.name];g&&(!p||!String(p).trim())&&c.push(d.label||d.name);const y=l.validateField(d,p||"",s);y.length&&m.push(y[0].message)}),c.length||m.length){const d=[];c.length&&d.push("Required: "+c.join(", ")),m.length&&d.push(m.join("; ")),w(n,d.join(". "),"error");return}}if(n.dataset.triggerBlocked==="true"){const l=n._formLogicRuntime,c=l&&l.submitBlock?l.submitBlock().reasons:[];w(n,c.join(" ")||"This form cannot be submitted yet.","error");return}n.classList.add("fb-form-loading"),u.disabled=!0,q(e,s,t,n,a).finally(function(){n.classList.remove("fb-form-loading"),u.disabled=!1})}),n.appendChild(a),enhancePickerFields(n,o),window.FormLogicEngine&&i&&L(o)){const r=new window.FormLogicEngine.FormLogicRuntime(i,n);r.init(),n._formLogicRuntime=r}}function Q(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||{},a=document.createElement("div");a.className="fb-form-wrapper",n.appendChild(a);const u=e.some(r=>r.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const r=Number(i.columns)===3?3:2,s=i.layout||"grid";if(u&&Domma.forms.wizard){const l=M(e,t.title),c=l.map(f=>f.fields),m=l.map(function(f){return{title:f.title,description:f.description,fields:j(f.fields,r)}});let d=0,b=null,g=null;const p=Date.now(),y=new Map,v=function(f){const h=window.FormLogicEngine;if(!h||!h.validateFields)return;const C=h.validateFields(a,c[d]||[]);C.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(a,C.missing),showValidationPopup(C))},x=function(){const f=c[d]||e;if(A(a,f),enhancePickerFields(a,f),f.some(h=>h.type==="spacer")&&D(a,f),i.honeypot){const h=a.querySelector("form");h&&k(h,p)}window.FormLogicEngine&&L(e)&&(b&&b.destroy(),b=new window.FormLogicEngine.FormLogicRuntime(t,a,{baseValues:g&&g.getStepData?g.getStepData():{}}),b.init(),_(a,b)),a.querySelectorAll(".wizard-next, .wizard-submit").forEach(h=>h.addEventListener("click",v,!0))};g=Domma.forms.wizard(a,{schema:{steps:m},layout:s,columns:r,finishText:i.submitText||"Finish",onStepChange:function(f){T(a,y),d=f,setTimeout(x,0)},onSubmit:function(f){return T(a,y),q(o,f,i,a,null,y)}}),a.addEventListener("dm-form-trigger",function(f){if(!f.detail||f.detail.type!=="goto-step"||!g||!g.goToStep)return;const h=Number(f.detail.action.step);!isFinite(h)||h<0||h>=m.length||h!==d&&g.goToStep(h)}),Promise.resolve(g).then(x)}else if(Domma.forms.render){const l=j(e,r),c=J(e),m=Domma.forms.render(a,l,c,{submitText:i.submitText||"Submit",layout:s,columns:r,onSubmit:function(d){return q(o,d,i,a,null)}});Promise.resolve(m).then(function(){if(A(a,e),enhancePickerFields(a,e),window.FormLogicEngine&&L(e)){const d=new window.FormLogicEngine.FormLogicRuntime(t,a);d.init(),_(a,d)}if(e.some(d=>d.type==="spacer")&&D(a,e),s==="grid"&&i.submitSpan==="full"){const d=a.querySelector(".form-buttons");d&&d.classList.add("col-span-full")}if(i.honeypot){const d=a.querySelector("form");d&&k(d)}})}}else G(a,e.filter(r=>r.type!=="page-break"&&r.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)})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){"use strict";var l=window.__CMS_SEARCH__||window.__SITE_SEARCH__||{},N=l.placeholder||"Search pages...",y=l.keyboardShortcut!==!1,D=l.debounceMs||300,x=l.displayMode||"navbar",C=l.iconOnly!==!1,L=l.iconRadius!=null?l.iconRadius:26,h=l.iconSize!=null?l.iconSize:52,u=null,c=null,s=null,b=null,p=!1;function g(){var t=document.querySelector("#site-navbar, .navbar");if(t){var e=t.querySelector(".navbar-actions");if(!e){var r=t.querySelector(".navbar-container")||t;e=document.createElement("div"),e.className="navbar-actions",r.appendChild(e)}if(!e.querySelector(".site-search-trigger")){var a=/Mac|iPhone|iPad|iPod/.test(navigator.platform||navigator.userAgent),i=a?"\u2318K":"Ctrl+K",n=document.createElement("button");n.className="navbar-action-link site-search-trigger",n.setAttribute("aria-label","Search"),n.setAttribute("type","button");var o=document.createElement("span");if(o.setAttribute("data-icon","search"),n.appendChild(o),y){var d=document.createElement("span");d.className="site-search-shortcut-hint",d.textContent=i,n.appendChild(d)}e.insertBefore(n,e.firstChild),n.addEventListener("click",m),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(n)}}}function k(){if(document.querySelector("#site-navbar .navbar-actions, .navbar .navbar-actions")){g();return}var t=new MutationObserver(function(){var e=document.querySelector("#site-navbar, .navbar");e&&(t.disconnect(),g())});t.observe(document.body,{childList:!0,subtree:!0}),setTimeout(function(){t.disconnect(),g()},5e3)}function T(){var t=document.createElement("div");t.className="site-search-overlay",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-label","Site search");var e=document.createElement("div");e.className="site-search-panel",e.setAttribute("role","search");var r=document.createElement("div");r.className="site-search-header";var a=document.createElement("span");a.setAttribute("data-icon","search"),r.appendChild(a),c=document.createElement("input"),c.className="site-search-input",c.type="search",c.setAttribute("autocomplete","off"),c.setAttribute("autocorrect","off"),c.setAttribute("spellcheck","false"),c.setAttribute("aria-label","Search"),c.placeholder=N,r.appendChild(c);var i=document.createElement("button");i.className="site-search-close-btn",i.setAttribute("type","button"),i.setAttribute("aria-label","Close search"),i.textContent="Esc",r.appendChild(i),e.appendChild(r),s=document.createElement("div"),s.className="site-search-results",s.setAttribute("role","listbox"),s.setAttribute("aria-live","polite"),e.appendChild(s);var n=document.createElement("div");return n.className="site-search-footer",n.innerHTML="<span><kbd>\u2191</kbd><kbd>\u2193</kbd> navigate</span><span><kbd>\u21B5</kbd> open</span><span><kbd>Esc</kbd> close</span>",e.appendChild(n),t.appendChild(e),t.addEventListener("click",function(o){o.target===t&&v()}),i.addEventListener("click",v),c.addEventListener("input",function(){clearTimeout(b);var o=c.value.trim();if(!o){E();return}b=setTimeout(function(){M(o)},D)}),c.addEventListener("keydown",q),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(r),t}function m(){p||(p=!0,u=T(),document.body.appendChild(u),document.body.style.overflow="hidden",setTimeout(function(){c&&c.focus()},30))}function v(){p&&(p=!1,clearTimeout(b),u&&u.parentNode&&u.parentNode.removeChild(u),u=null,c=null,s=null,document.body.style.overflow="")}function M(t){s&&(R(),fetch("/api/search?q="+encodeURIComponent(t)).then(function(e){return e.json()}).then(function(e){_(e.results||[],t)}).catch(function(){E();var e=document.createElement("div");e.className="site-search-empty",e.textContent="Search unavailable. Please try again.",s.appendChild(e)}))}function R(){s&&(s.innerHTML='<div class="site-search-loading"><div class="site-search-loading-dots"><span></span><span></span><span></span></div></div>')}function E(){s&&(s.innerHTML="")}function _(t,e){if(s){if(s.innerHTML="",!t.length){var r=document.createElement("div");r.className="site-search-empty",r.textContent='No results found for "'+e+'"',s.appendChild(r);return}for(var a=document.createDocumentFragment(),i=0;i<t.length;i++){var n=t[i],o=document.createElement("a");o.className="site-search-result",o.href=n.url||"/",o.setAttribute("role","option"),o.setAttribute("tabindex","-1"),o.setAttribute("data-index",String(i));var d=document.createElement("div");if(d.className="site-search-result-title",S(d,n.title||"Untitled",e),o.appendChild(d),n.snippet){var f=document.createElement("div");f.className="site-search-result-snippet",S(f,n.snippet,e),o.appendChild(f)}o.addEventListener("click",v),a.appendChild(o)}s.appendChild(a)}}function S(t,e,r){if(!r){t.textContent=e;return}var a=r.trim().split(/\s+/).filter(Boolean);if(!a.length){t.textContent=e;return}var i;try{i=new RegExp("("+a.map(function(f){return f.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("|")+")","gi")}catch{t.textContent=e;return}for(var n=e.split(i),o=0;o<n.length;o++){if(i.test(n[o])){var d=document.createElement("mark");d.textContent=n[o],t.appendChild(d)}else t.appendChild(document.createTextNode(n[o]));i.lastIndex=0}}function q(t){if(t.key==="Escape"){t.preventDefault(),v();return}if(s){var e=s.querySelectorAll(".site-search-result");if(e.length){for(var r=s.querySelector(".site-search-result.active"),a=-1,i=0;i<e.length;i++)if(e[i]===r){a=i;break}if(t.key==="ArrowDown")t.preventDefault(),A(e,a<e.length-1?a+1:0);else if(t.key==="ArrowUp")t.preventDefault(),A(e,a>0?a-1:e.length-1);else if(t.key==="Enter"&&r){t.preventDefault();var n=r.getAttribute("href");v(),window.location.href=n}}}}function A(t,e){for(var r=0;r<t.length;r++)t[r].classList.toggle("active",r===e);t[e]&&t[e].scrollIntoView({block:"nearest"})}y&&document.addEventListener("keydown",function(t){if((t.metaKey||t.ctrlKey)&&t.key==="k"){var e=document.activeElement&&document.activeElement.tagName;if((e==="INPUT"||e==="TEXTAREA"||e==="SELECT")&&!p)return;t.preventDefault(),p?v():m()}});function H(t,e,r,a){var i=e==="left-center"||e==="bottom-left"||e==="top-left",n=e==="bottom-left"||e==="bottom-right",o=e==="top-left"||e==="top-right";Object.assign(t.style,{right:i?"auto":r+"px",left:i?r+"px":"auto",top:o?a+"px":n?"auto":"50vh",bottom:n?a+"px":"auto",transform:o||n?"none":"translateY(-50%)"})}function O(){if(!document.querySelector(".site-search-floating-trigger")){var t=l.position||"bottom-right",e=l.offsetX!=null?l.offsetX:32,r=l.offsetY!=null?l.offsetY:32,a=document.createElement("button");a.className="site-search-floating-trigger"+(C?"":" site-search-floating-trigger--pill"),a.setAttribute("type","button"),a.setAttribute("aria-label","Search");var i=document.createElement("span");if(i.setAttribute("data-icon","search"),a.appendChild(i),C)a.style.borderRadius=L+"px",a.style.width=h+"px",a.style.height=h+"px",a.style.setProperty("--ss-icon-glyph",Math.round(h*20/52)+"px");else{var n=document.createElement("span");n.className="site-search-floating-label",n.textContent="Search",a.appendChild(n)}H(a,t,e,r),document.body.appendChild(a),a.addEventListener("click",m),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(a)}}function w(){x==="floating"?O():k()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",w):w(),window.DommaSiteSearch={open:m,close:v,isAvailable:()=>!0}})();
|
package/public/js/site.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{makeBadgeEl as M,applyColour as N,applyPill as B,applyFloat as P,applyHighlight as z,applyItemHighlight as R,itemHighlightAttrs as V,isCurrentItem as O,menuAlign as J}from"/public/js/menu-decor.mjs?v=20260918-item-highlight";import{initFloatingMenus as W}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as j,markInvalidFields as G,showValidationPopup as X}from"/public/js/forms.js?v=20260821-wizard-grid";import{buildWizardSteps as Y}from"/public/js/form-steps.mjs";$(()=>{const b=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let t=function(a){const e=(a||"07:00").split(":");return+e[0]*60+(+e[1]||0)},n=function(){const a=new Date,e=a.getHours()*60+a.getMinutes();return e>=t(o.dayStart)&&e<t(o.nightStart)?o.dayTheme:o.nightTheme};const o=g.autoTheme;Domma.theme.set(n()),setInterval(()=>Domma.theme.set(n()),6e4)}const x=$("#site-navbar");if(x.length&&b.brand){let n=function(i,c=0){return Array.isArray(i)?i.filter(s=>!(s&&s.type==="spacer")).filter(s=>!(s&&s.type==="separator"&&c===0)).map(s=>s&&s.type==="separator"?{divider:!0}:Array.isArray(s?.items)?{...s,items:n(s.items,c+1)}:s):i},a=function(i){return Array.isArray(i)?i.filter(c=>!(c&&(c.type==="separator"||c.type==="spacer"))):[]};const o={...b.brand},t=o.size&&o.size!=="md"?` navbar-brand-${o.size}`:"";if(o.logo||o.icon||o.tagline){let i="";o.logo?i+=`<img src="${o.logo}" class="navbar-brand-logo" alt="${o.text||""}">`:o.icon&&(i+=`<span data-icon="${o.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),o.text&&(i+=`<span class="navbar-brand-text${t}">${o.text}</span>`),o.tagline&&(i+=`<small class="navbar-brand-tagline">${o.tagline}</small>`),o.html=i}else t&&o.text&&(o.html=`<span class="navbar-brand-text${t}">${o.text}</span>`);const e=b.position==="floating",d=b.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:o,items:n(b.items||[]),variant:b.variant||"dark",position:e?"static":b.position||"sticky",collapsible:!0,appearOnHover:!!b.appearOnHover}),Domma.icons.scan("#site-navbar");const h=x.get(0);h.classList.add(`dm-nav-align-${J(b)||"centre"}`),d&&x.get(0).classList.add("dm-nav-vertical",b.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),z(h,b),e&&(P(x.get(0),b),W(x.get(0).parentNode||document));const y=h.querySelector(".navbar-toggle"),f=h.querySelector(".navbar-collapse");if(y&&f){let i=null;const c=()=>{f.classList.contains("show")&&y.click()},s=()=>{i&&(i.remove(),i=null),document.body.classList.remove("dm-drawer-open")},r=()=>{i||(i=document.createElement("div"),i.className="dm-navbar-backdrop",i.addEventListener("click",c),document.body.appendChild(i),document.body.classList.add("dm-drawer-open"))};y.addEventListener("click",()=>{requestAnimationFrame(()=>{f.classList.contains("show")?r():s()})}),f.addEventListener("click",l=>{l.target.closest("a")&&requestAnimationFrame(s)}),document.addEventListener("keydown",l=>{l.key==="Escape"&&f.classList.contains("show")&&c()})}const u=h.querySelector(".navbar-nav");if(u){const i=Array.from(u.children);let c=0;for(const s of b.items||[])if(!(s&&s.type==="separator")){if(s&&s.type==="spacer"){const r=document.createElement("li"),l=["xs","sm","md","lg","xl","flex"].includes(s.size)?s.size:"md";r.className=`dm-menu-spacer dm-menu-spacer--${l}`,r.setAttribute("aria-hidden","true"),u.insertBefore(r,i[c]||null);continue}c++}}const w=a(b.items||[]);h.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(i=>{const c=w[parseInt(i.dataset.index,10)];if(!c)return;const s=i.dataset.subindex!=null,r=s&&Array.isArray(c.items)?c.items[parseInt(i.dataset.subindex,10)]:c;if(!r)return;r.colour&&N(i,r.colour),r.pill&&!s&&B(i,r.pill),R(i,r);const l=M(r.badge);l&&i.appendChild(l),O(r.url,location.pathname)&&(i.classList.add("active"),i.setAttribute("aria-current","page"))})}const C=$("#site-footer");if(C.length){let e=function(r){return String(r??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},d=function(r){return e(r).replace(/'/g,"'")},h=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';if(r&&r.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(r.size)?r.size:"md"}" aria-hidden="true"></li>`;const l=d(r.url||"#"),m=e(r.text||""),v=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(h).join("")}</ul>`:"",A=V(r),D=[A.hover&&` data-menu-item-hover="${d(A.hover)}"`,A.active&&` data-menu-item-active="${d(A.active)}"`].filter(Boolean).join(""),k=A.accent?` style="--dm-menu-highlight:${d(A.accent)}"`:"";return`<li><a href="${l}"${D}${k}>${m}</a>${v}</li>`},y=function(r,l){return(r||[]).forEach(m=>{m&&(m.type==="separator"||m.type==="spacer")||(l.push(m),Array.isArray(m.items)&&m.items.length&&y(m.items,l))}),l};const o=g.social||{},t={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let n='<div class="footer-inner container">';const a=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(a.copyright&&(n+=`<p>${e(a.copyright)}</p>`),a.primary.length&&(n+=`<nav class="footer-nav footer-nav--primary"><ul>${a.primary.map(h).join("")}</ul></nav>`),a.legal.length&&(n+=`<nav class="footer-nav footer-nav--legal"><ul>${a.legal.map(h).join("")}</ul></nav>`),g.footer){const r=Object.keys(t).filter(l=>o[l]);r.length&&(n+='<div class="footer-social">',r.forEach(l=>{const{label:m,svg:v}=t[l];n+=`<a href="${o[l]}" target="_blank" rel="noopener noreferrer" aria-label="${m}" class="footer-social-link">${v}</a>`}),n+="</div>")}n+="</div>",C.html(n);const f=[...y(a.primary,[]),...y(a.legal,[])];C.get(0).querySelectorAll(".footer-nav a").forEach((r,l)=>{const m=f[l];if(!m)return;m.colour&&N(r,m.colour);const v=M(m.badge);v&&r.appendChild(v),O(m.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),z(C.get(0).querySelector(".footer-nav--primary"),{highlight:a.primaryHighlight}),z(C.get(0).querySelector(".footer-nav--legal"),{highlight:a.legalHighlight});const w=g.footer?.showMotionToggle!==!1,i=S.get("reduced_motion"),c=i!==null?!!i:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),s=C.get(0).querySelector(".footer-inner");if(w&&s){const r=document.createElement("input");r.type="checkbox",r.className="form-switch-input",r.id="dm-motion-switch",r.checked=c,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const l=document.createElement("span");l.className="form-switch-label",l.textContent="Reduce motion";const m=document.createElement("label");m.className="form-switch footer-motion-switch",m.title="Reduce motion",m.appendChild(r),m.appendChild(l),s.appendChild(m)}}$("#site-sidebar").length&&Domma.elements.sidebar("#site-sidebar",{autoGenerate:!0,selector:"h2, h3",collapsible:!1,push:!0,contentSelector:".site-content"}),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const p=$(".page-body");if(p.length){p.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),p.find(".tabs").each(function(){Domma.elements.tabs(this)}),p.find(".carousel").each(function(){const o={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const t=parseInt(this.dataset.animationDuration,10);Number.isFinite(t)&&(o.animationDuration=t)}this.dataset.animationEasing&&(o.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(t=>t.cloneNode(!0)),this._dmCarouselOpts=o),this._dmCarousel=Domma.elements.carousel(this,o)}),p.find(".dm-countdown").each(function(){const o={autoStart:!0};this.dataset.to&&(o.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(o.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(o.format=this.dataset.format),Domma.elements.timer(this,o)}),p.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),p.find(".dm-progression").each(function(){const o=Array.from(this.querySelectorAll(".dm-progression-item")).map(a=>{const e={title:a.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:a.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return a.dataset.date&&(e.date=a.dataset.date),a.dataset.status&&(e.status=a.dataset.status),a.dataset.entryId&&(e._entryId=a.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",n=Domma.elements.progression(this,{layout:t,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...o.length?{items:o}:{}});o.length&&(this._dmCtx={instance:n,items:o})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(o=>{const t=o.dataset.revealMode||"stagger",n=o.dataset.revealAnimation||"slide-up",a=parseInt(o.dataset.revealDuration,10)||400,e=parseInt(o.dataset.revealStagger,10)||60,d=parseInt(o.dataset.revealDelay,10)||0,h=o.dataset.revealDirection==="rtl",y=Array.from(o.children),f={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};y.forEach((u,w)=>{u.style.opacity="0",u.style.transform=f[n]||"",u.style.transition=`opacity ${a}ms ease, transform ${a}ms ease`;const i=h?y.length-1-w:w;u.style.transitionDelay=t==="stagger"?`${d+i*e}ms`:`${d}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const u=new IntersectionObserver(w=>{w.forEach(i=>{i.isIntersecting&&(i.target.offsetWidth,i.target.style.opacity="1",i.target.style.transform="none",u.unobserve(i.target))})},{threshold:.1});y.forEach(w=>u.observe(w))}))}),p.find(".card[data-collapsible]").each(function(){const o=this.querySelector(".card-header");o&&o.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),p.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const o=this.dataset.soTarget,t=document.getElementById(o);if(!t)return;const n=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",n.setContent(t),n.open()})})}if(typeof $.setup=="function"){const o=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const n=atob(t.dataset.config),a=JSON.parse(n);Object.assign(o,a)}catch{}}),Object.keys(o).length>0){const t={};for(const[n,a]of Object.entries(o)){const e=a?.events?.click,{confirm:d,toast:h,alert:y,prompt:f,...u}=e||{};d||h||y||f?($(n).on("click",async function(i){if(i.preventDefault(),d&&!await E.confirm(d))return;let c=null;if(!(f&&(c=await E.prompt(f,{inputPlaceholder:u.promptPlaceholder||"",inputValue:u.promptDefault||""}),c===null))){if(u.target){const s=$(u.target);u.toggleClass&&s.toggleClass(u.toggleClass),u.addClass&&s.addClass(u.addClass),u.removeClass&&s.removeClass(u.removeClass),c!==null&&(u.setText&&s.text(c),u.setVal&&s.val(c),u.setAttr&&s.attr(u.setAttr,c))}u.href&&(window.location.href=u.href),h&&E.toast(h,{type:u.toastType||"success"}),y&&E.alert(y)}}),Object.keys(u).length&&(t[n]={...a,events:{...a.events,click:u}})):t[n]=a}$.setup(t)}}p.length&&L(p.get(0))});function L(b){b.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const x=g.dataset.action,C=g.dataset.entry,_=g.dataset.confirm;let p=S.get("auth_token");if(!p){E.toast("Please log in to perform this action.",{type:"warning"});return}if(_&&!await E.confirm(_))return;const o=Array.from(g.childNodes).map(n=>n.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const t=n=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({entryId:C})});try{let n=await t(p);if(n.status===401){const e=S.get("auth_refresh_token");if(e){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(d.ok){const{token:h}=await d.json();S.set("auth_token",h),p=h,n=await t(p)}}}const a=await n.json().catch(()=>({}));if(!n.ok)throw new Error(a.error||a.message||`Error ${n.status}`);E.toast(a.message||"Action completed.",{type:"success"})}catch(n){E.toast(n.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",o.forEach(n=>g.appendChild(n)),Domma.icons.scan(g)}}))})}(function(){const g=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!g.length)return;const x=S.get("auth_token");function C(p,o){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const n=document.createElement("p");if(o){n.appendChild(document.createTextNode("Please "));const a=document.createElement("a");a.href="/login",a.textContent="sign in",n.appendChild(a),n.appendChild(document.createTextNode(" to view your entries."))}else n.textContent=p;return t.appendChild(n),t}function _(p,o){const t=document.createElement("template");t.innerHTML=o||"",p.replaceWith(t.content)}g.forEach(async p=>{const o=p.dataset.collectionAttrs;if(!o)return;if(!x){p.replaceChildren(C("",!0));return}const t=n=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({attrs:o})});try{let n=x,a=await t(n);if(a.status===401){const d=S.get("auth_refresh_token");if(d){const h=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(h.ok){const{token:y}=await h.json();S.set("auth_token",y),n=y,a=await t(n)}}}if(!a.ok){const{error:d}=await a.json().catch(()=>({}));p.replaceChildren(C(d||"Unable to load entries.",!1));return}const{html:e}=await a.json();_(p,e)}catch{p.replaceChildren(C("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),L(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(x=>{let C;try{C=JSON.parse(atob(x.dataset.payload))}catch{return}const{columns:_,rows:p,search:o,sortable:t,exportable:n,pageSize:a,empty:e,ctaConfig:d,slug:h,exportCfg:y}=C;if(!_?.length)return;if(d){const w=_.findIndex(i=>i.key==="_cta");w!==-1&&(_[w]={key:"_cta",title:"",render:(i,c)=>{const s=document.createElement("button");if(s.className=`btn btn-${d.style||"primary"} dm-cta-trigger`,s.dataset.action=d.action||"",s.dataset.entry=c._entryId||"",d.confirm&&(s.dataset.confirm=d.confirm),d.icon){const r=document.createElement("span");r.dataset.icon=d.icon,s.appendChild(r),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(d.label||"Run")),s}})}const f="col-table-"+Math.random().toString(36).slice(2,7),u=document.createElement("div");u.id=f,x.replaceChildren(u),T.create("#"+f,{data:p,columns:_,search:o,sortable:t,exportable:n,pageSize:a,emptyMessage:e}),d&&L(u),x._dmTable={columns:_,rows:p,slug:h,exportCfg:y,render(w){T.create("#"+f,{data:w,columns:_,search:o,sortable:t,exportable:n,pageSize:a,emptyMessage:e}),d&&L(u)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function x(t){const n=t&&t.logic;return!!(n&&(n.visibility||n.requirement))}function C(t,n){const a={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const d=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),h=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":d?"chooser":e.type,y={...e.formConfig||{}};y.span==="full"&&n&&(y.span=n);const f={type:h,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...y}};d&&(e.variant&&(f.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(f.multiple=!0),e.density&&(f.density=e.density),e.columns&&(f.columns=e.columns),e.accent&&(f.accent=e.accent),e.accentStyle&&(f.accentStyle=e.accentStyle),e.glow&&(f.glow=!0),e.glowColour&&(f.glowColour=e.glowColour),e.shadow&&(f.shadow=e.shadow),e.shadowColour&&(f.shadowColour=e.shadowColour)),a[e.name]=f}),a}function _(t){const n={};return(t||[]).forEach(a=>{if(!(!a.name||a.type==="page-break"||a.type==="spacer")&&(a.type==="select"||a.type==="multiselect")&&a.required){const e=(a.options||[])[0];e&&(n[a.name]=typeof e=="object"?e.value:e)}}),n}function p(t,n){(n||[]).forEach(a=>{if(a.type!=="date"||!a.name)return;const e=t.querySelector(`[name="${a.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function o(t,n,a){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=n,e.style.cssText=a?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(t=>{let n;try{n=JSON.parse(atob(t.dataset.formInline))}catch{return}const a=n.fields||[],e=n.settings||{},d=Number(e.columns)===3?3:2,h=e.layout||"grid",y=a.some(c=>c.type==="page-break"),f=async c=>{try{const s=t.querySelector(".fb-form-honeypot"),r=s?.querySelector('input[type="text"]')||null,l=s?.querySelector('[name="_t"]')||null,m=Object.assign({},c);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName],r!==null&&(m._hp=r.value),l!==null&&(m._t=l.value);const v=await H.post(`/api/forms/submit/${n.slug}`,m);if(v&&v.error){o(t,v.error,!0);const A=new Error(v.error);throw A.formSubmitFailed=!0,A}if(v?.redirect){window.location.href=v.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);o(t,v?.message||e.successMessage||"Thank you for your submission.",!1)}catch(s){throw s.formSubmitFailed||o(t,s.message||"Submission failed. Please try again.",!0),s}},u=Date.now();function w(c){const s=c.querySelector("form");if(!s||s.querySelector(".fb-form-honeypot"))return;const r=document.createElement("div");r.className="fb-form-honeypot",r.setAttribute("aria-hidden","true");const l=document.createElement("input");l.name=s.querySelector('[name="website"]')?"_website":"website",r.dataset.hpName=l.name,l.type="text",l.tabIndex=-1,l.autocomplete="url",l.placeholder="https://",r.appendChild(l);const m=document.createElement("input");m.name="_t",m.type="hidden",m.value=u,r.appendChild(m),s.appendChild(r)}function i(c){if(!window.FormLogicEngine||!a.some(r=>r.logic))return null;const s=new window.FormLogicEngine.FormLogicRuntime(n,t,c?{baseValues:c}:void 0);if(s.init(),t._formLogicRuntime=s,t._formLogicObserved)return s;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const r=new MutationObserver(function(l){for(const m of l)for(const v of m.removedNodes)if(v===t||v.nodeType===1&&v.contains&&v.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),r.disconnect();return}});r.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=r}return s}if(y&&F.wizard){const c=Y(a,n.title),s=c.map(k=>({title:k.title,description:k.description,fields:C(k.fields,d)})),r=c.map(k=>k.fields);let l=0,m=null,v=null;const A=k=>{const I=window.FormLogicEngine;if(!I||!I.validateFields)return;const q=I.validateFields(t,r[l]||[]);q.valid||(k.preventDefault(),k.stopImmediatePropagation(),G(t,q.missing),X(q))},D=()=>{const k=r[l]||a;p(t,k),j(t,k),e.honeypot!==!1&&w(t),m&&m.destroy(),m=i(v?.getStepData?v.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(I=>I.addEventListener("click",A,!0))};v=F.wizard(t,{schema:{steps:s},layout:h,columns:d,finishText:e.submitText||"Finish",onSubmit:f,onStepChange:k=>{l=k,setTimeout(D,0)}}),Promise.resolve(v).then(D)}else if(F.render){const c=F.render(t,C(a,d),_(a),{submitText:e.submitText||"Submit",layout:h,columns:d,onSubmit:f});Promise.resolve(c).then(function(){if(h==="grid"&&e.submitSpan==="full"){const s=t.querySelector(".form-buttons");s&&s.classList.add("col-span-full")}p(t,a),j(t,a),e.honeypot!==!1&&w(t),i()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
|
|
1
|
+
import{makeBadgeEl as N,applyColour as M,applyPill as B,applyFloat as R,applyHighlight as z,applyItemHighlight as P,itemHighlightAttrs as V,isCurrentItem as O,menuAlign as J}from"/public/js/menu-decor.mjs?v=20260918-item-highlight";import{initFloatingMenus as W}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as j,markInvalidFields as G,showValidationPopup as X}from"/public/js/forms.js?v=20260821-wizard-grid";import{buildWizardSteps as Y}from"/public/js/form-steps.mjs";$(()=>{const b=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let e=function(a){const t=(a||"07:00").split(":");return+t[0]*60+(+t[1]||0)},n=function(){const a=new Date,t=a.getHours()*60+a.getMinutes();return t>=e(o.dayStart)&&t<e(o.nightStart)?o.dayTheme:o.nightTheme};const o=g.autoTheme;Domma.theme.set(n()),setInterval(()=>Domma.theme.set(n()),6e4)}const k=$("#site-navbar");if(k.length&&b.brand){let n=function(i,l=0){return Array.isArray(i)?i.filter(s=>!(s&&s.type==="spacer")).filter(s=>!(s&&s.type==="separator"&&l===0)).map(s=>s&&s.type==="separator"?{divider:!0}:Array.isArray(s?.items)?{...s,items:n(s.items,l+1)}:s):i},a=function(i){return Array.isArray(i)?i.filter(l=>!(l&&(l.type==="separator"||l.type==="spacer"))):[]};const o={...b.brand},e=o.size&&o.size!=="md"?` navbar-brand-${o.size}`:"";if(o.logo||o.icon||o.tagline){let i="";o.logo?i+=`<img src="${o.logo}" class="navbar-brand-logo" alt="${o.text||""}">`:o.icon&&(i+=`<span data-icon="${o.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),o.text&&(i+=`<span class="navbar-brand-text${e}">${o.text}</span>`),o.tagline&&(i+=`<small class="navbar-brand-tagline">${o.tagline}</small>`),o.html=i}else e&&o.text&&(o.html=`<span class="navbar-brand-text${e}">${o.text}</span>`);const t=b.position==="floating",d=b.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:o,items:n(b.items||[]),variant:b.variant||"dark",position:t?"static":b.position||"sticky",collapsible:!0,appearOnHover:!!b.appearOnHover}),Domma.icons.scan("#site-navbar");const h=k.get(0);h.classList.add(`dm-nav-align-${J(b)||"centre"}`),d&&k.get(0).classList.add("dm-nav-vertical",b.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),z(h,b),t&&(R(k.get(0),b),W(k.get(0).parentNode||document));const y=h.querySelector(".navbar-toggle"),f=h.querySelector(".navbar-collapse");if(y&&f){let i=null;const l=()=>{f.classList.contains("show")&&y.click()},s=()=>{i&&(i.remove(),i=null),document.body.classList.remove("dm-drawer-open")},r=()=>{i||(i=document.createElement("div"),i.className="dm-navbar-backdrop",i.addEventListener("click",l),document.body.appendChild(i),document.body.classList.add("dm-drawer-open"))};y.addEventListener("click",()=>{requestAnimationFrame(()=>{f.classList.contains("show")?r():s()})}),f.addEventListener("click",c=>{c.target.closest("a")&&requestAnimationFrame(s)}),document.addEventListener("keydown",c=>{c.key==="Escape"&&f.classList.contains("show")&&l()})}const u=h.querySelector(".navbar-nav");if(u){const i=Array.from(u.children);let l=0;for(const s of b.items||[])if(!(s&&s.type==="separator")){if(s&&s.type==="spacer"){const r=document.createElement("li"),c=["xs","sm","md","lg","xl","flex"].includes(s.size)?s.size:"md";r.className=`dm-menu-spacer dm-menu-spacer--${c}`,r.setAttribute("aria-hidden","true"),u.insertBefore(r,i[l]||null);continue}l++}}const w=a(b.items||[]);h.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(i=>{const l=w[parseInt(i.dataset.index,10)];if(!l)return;const s=i.dataset.subindex!=null,r=s&&Array.isArray(l.items)?l.items[parseInt(i.dataset.subindex,10)]:l;if(!r)return;r.colour&&M(i,r.colour),r.pill&&!s&&B(i,r.pill),P(i,r);const c=N(r.badge);c&&i.appendChild(c),O(r.url,location.pathname)&&(i.classList.add("active"),i.setAttribute("aria-current","page"))})}const C=$("#site-footer");if(C.length){let t=function(r){return String(r??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},d=function(r){return t(r).replace(/'/g,"'")},h=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';if(r&&r.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(r.size)?r.size:"md"}" aria-hidden="true"></li>`;const c=d(r.url||"#"),m=t(r.text||""),v=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(h).join("")}</ul>`:"",I=V(r),L=[I.hover&&` data-menu-item-hover="${d(I.hover)}"`,I.active&&` data-menu-item-active="${d(I.active)}"`].filter(Boolean).join(""),x=I.accent?` style="--dm-menu-highlight:${d(I.accent)}"`:"";return`<li><a href="${c}"${L}${x}>${m}</a>${v}</li>`},y=function(r,c){return(r||[]).forEach(m=>{m&&(m.type==="separator"||m.type==="spacer")||(c.push(m),Array.isArray(m.items)&&m.items.length&&y(m.items,c))}),c};const o=g.social||{},e={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let n='<div class="footer-inner container">';const a=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(a.copyright&&(n+=`<p>${t(a.copyright)}</p>`),a.primary.length&&(n+=`<nav class="footer-nav footer-nav--primary"><ul>${a.primary.map(h).join("")}</ul></nav>`),a.legal.length&&(n+=`<nav class="footer-nav footer-nav--legal"><ul>${a.legal.map(h).join("")}</ul></nav>`),g.footer){const r=Object.keys(e).filter(c=>o[c]);r.length&&(n+='<div class="footer-social">',r.forEach(c=>{const{label:m,svg:v}=e[c];n+=`<a href="${o[c]}" target="_blank" rel="noopener noreferrer" aria-label="${m}" class="footer-social-link">${v}</a>`}),n+="</div>")}n+="</div>",C.html(n);const f=[...y(a.primary,[]),...y(a.legal,[])];C.get(0).querySelectorAll(".footer-nav a").forEach((r,c)=>{const m=f[c];if(!m)return;m.colour&&M(r,m.colour);const v=N(m.badge);v&&r.appendChild(v),O(m.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),z(C.get(0).querySelector(".footer-nav--primary"),{highlight:a.primaryHighlight}),z(C.get(0).querySelector(".footer-nav--legal"),{highlight:a.legalHighlight});const w=g.footer?.showMotionToggle!==!1,i=S.get("reduced_motion"),l=i!==null?!!i:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),s=C.get(0).querySelector(".footer-inner");if(w&&s){const r=document.createElement("input");r.type="checkbox",r.className="form-switch-input",r.id="dm-motion-switch",r.checked=l,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const c=document.createElement("span");c.className="form-switch-label",c.textContent="Reduce motion";const m=document.createElement("label");m.className="form-switch footer-motion-switch",m.title="Reduce motion",m.appendChild(r),m.appendChild(c),s.appendChild(m)}}$("#site-sidebar").length&&Domma.elements.sidebar("#site-sidebar",{autoGenerate:!0,selector:"h2, h3",collapsible:!1,push:!0,contentSelector:".site-content"}),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const p=$(".page-body");if(p.length){p.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),p.find(".tabs").each(function(){Domma.elements.tabs(this)}),p.find(".carousel").each(function(){const o={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const e=parseInt(this.dataset.animationDuration,10);Number.isFinite(e)&&(o.animationDuration=e)}this.dataset.animationEasing&&(o.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(e=>e.cloneNode(!0)),this._dmCarouselOpts=o),this._dmCarousel=Domma.elements.carousel(this,o)}),p.find(".dm-countdown").each(function(){const o={autoStart:!0};this.dataset.to&&(o.targetDate=new Date(this.dataset.to)),this.dataset.duration&&(o.duration=parseInt(this.dataset.duration,10)),this.dataset.format&&(o.format=this.dataset.format),Domma.elements.timer(this,o)}),p.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),p.find(".dm-progression").each(function(){const o=Array.from(this.querySelectorAll(".dm-progression-item")).map(a=>{const t={title:a.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:a.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return a.dataset.date&&(t.date=a.dataset.date),a.dataset.status&&(t.status=a.dataset.status),a.dataset.entryId&&(t._entryId=a.dataset.entryId),t}),e=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",n=Domma.elements.progression(this,{layout:e,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...o.length?{items:o}:{}});o.length&&(this._dmCtx={instance:n,items:o})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(o=>{const e=o.dataset.revealMode||"stagger",n=o.dataset.revealAnimation||"slide-up",a=parseInt(o.dataset.revealDuration,10)||400,t=parseInt(o.dataset.revealStagger,10)||60,d=parseInt(o.dataset.revealDelay,10)||0,h=o.dataset.revealDirection==="rtl",y=Array.from(o.children),f={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};y.forEach((u,w)=>{u.style.opacity="0",u.style.transform=f[n]||"",u.style.transition=`opacity ${a}ms ease, transform ${a}ms ease`;const i=h?y.length-1-w:w;u.style.transitionDelay=e==="stagger"?`${d+i*t}ms`:`${d}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const u=new IntersectionObserver(w=>{w.forEach(i=>{i.isIntersecting&&(i.target.offsetWidth,i.target.style.opacity="1",i.target.style.transform="none",u.unobserve(i.target))})},{threshold:.1});y.forEach(w=>u.observe(w))}))}),p.find(".card[data-collapsible]").each(function(){const o=this.querySelector(".card-header");o&&o.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),p.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const o=this.dataset.soTarget,e=document.getElementById(o);if(!e)return;const n=E.slideover({title:e.dataset.soTitle||"",size:e.dataset.soSize||"md",position:e.dataset.soPosition||"right"});e.style.display="",n.setContent(e),n.open()})})}if(typeof $.setup=="function"){const o=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(e=>{try{const n=atob(e.dataset.config),a=JSON.parse(n);Object.assign(o,a)}catch{}}),Object.keys(o).length>0){const e={};for(const[n,a]of Object.entries(o)){const t=a?.events?.click,{confirm:d,toast:h,alert:y,prompt:f,...u}=t||{};d||h||y||f?($(n).on("click",async function(i){if(i.preventDefault(),d&&!await E.confirm(d))return;let l=null;if(!(f&&(l=await E.prompt(f,{inputPlaceholder:u.promptPlaceholder||"",inputValue:u.promptDefault||""}),l===null))){if(u.target){const s=$(u.target);u.toggleClass&&s.toggleClass(u.toggleClass),u.addClass&&s.addClass(u.addClass),u.removeClass&&s.removeClass(u.removeClass),l!==null&&(u.setText&&s.text(l),u.setVal&&s.val(l),u.setAttr&&s.attr(u.setAttr,l))}u.href&&(window.location.href=u.href),h&&E.toast(h,{type:u.toastType||"success"}),y&&E.alert(y)}}),Object.keys(u).length&&(e[n]={...a,events:{...a.events,click:u}})):e[n]=a}$.setup(e)}}p.length&&D(p.get(0))});function D(b){b.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const k=g.dataset.action,C=g.dataset.entry,_=g.dataset.confirm;let p=S.get("auth_token");if(!p){E.toast("Please log in to perform this action.",{type:"warning"});return}if(_&&!await E.confirm(_))return;const o=Array.from(g.childNodes).map(n=>n.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const e=n=>fetch(`/api/actions/${k}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({entryId:C})});try{let n=await e(p);if(n.status===401){const t=S.get("auth_refresh_token");if(t){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t})});if(d.ok){const{token:h}=await d.json();S.set("auth_token",h),p=h,n=await e(p)}}}const a=await n.json().catch(()=>({}));if(!n.ok)throw new Error(a.error||a.message||`Error ${n.status}`);E.toast(a.message||"Action completed.",{type:"success"})}catch(n){E.toast(n.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",o.forEach(n=>g.appendChild(n)),Domma.icons.scan(g)}}))})}(function(){const g=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!g.length)return;const k=S.get("auth_token");function C(p,o){const e=document.createElement("div");e.className="dm-collection-display dm-collection-empty";const n=document.createElement("p");if(o){n.appendChild(document.createTextNode("Please "));const a=document.createElement("a");a.href="/login",a.textContent="sign in",n.appendChild(a),n.appendChild(document.createTextNode(" to view your entries."))}else n.textContent=p;return e.appendChild(n),e}function _(p,o){const e=document.createElement("template");e.innerHTML=o||"",p.replaceWith(e.content)}g.forEach(async p=>{const o=p.dataset.collectionAttrs;if(!o)return;if(!k){p.replaceChildren(C("",!0));return}const e=n=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({attrs:o})});try{let n=k,a=await e(n);if(a.status===401){const d=S.get("auth_refresh_token");if(d){const h=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:d})});if(h.ok){const{token:y}=await h.json();S.set("auth_token",y),n=y,a=await e(n)}}}if(!a.ok){const{error:d}=await a.json().catch(()=>({}));p.replaceChildren(C(d||"Unable to load entries.",!1));return}const{html:t}=await a.json();_(p,t)}catch{p.replaceChildren(C("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),D(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(k=>{let C;try{C=JSON.parse(atob(k.dataset.payload))}catch{return}const{columns:_,rows:p,search:o,sortable:e,exportable:n,pageSize:a,empty:t,ctaConfig:d,slug:h,exportCfg:y}=C;if(!_?.length)return;if(d){const w=_.findIndex(i=>i.key==="_cta");w!==-1&&(_[w]={key:"_cta",title:"",render:(i,l)=>{const s=document.createElement("button");if(s.className=`btn btn-${d.style||"primary"} dm-cta-trigger`,s.dataset.action=d.action||"",s.dataset.entry=l._entryId||"",d.confirm&&(s.dataset.confirm=d.confirm),d.icon){const r=document.createElement("span");r.dataset.icon=d.icon,s.appendChild(r),s.appendChild(document.createTextNode(" "))}return s.appendChild(document.createTextNode(d.label||"Run")),s}})}const f="col-table-"+Math.random().toString(36).slice(2,7),u=document.createElement("div");u.id=f,k.replaceChildren(u),T.create("#"+f,{data:p,columns:_,search:o,sortable:e,exportable:n,pageSize:a,emptyMessage:t}),d&&D(u),k._dmTable={columns:_,rows:p,slug:h,exportCfg:y,render(w){T.create("#"+f,{data:w,columns:_,search:o,sortable:e,exportable:n,pageSize:a,emptyMessage:t}),d&&D(u)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function k(e){const n=e&&e.logic;return!!(n&&(n.visibility||n.requirement))}function C(e,n){const a={};return(e||[]).forEach(t=>{if(t.type==="page-break"||t.type==="spacer"||!t.name)return;const d=t.type==="chooser"||!!(t.variant&&["select","radio","checkbox-group"].includes(t.type)),h=t.type==="checkbox"?"boolean":t.type==="date"||t.type==="icon"||t.type==="image"?"string":d?"chooser":t.type,y={...t.formConfig||{}};y.span==="full"&&n&&(y.span=n);const f={type:h,required:k(t)?!1:t.required,label:t.label,options:t.options,formConfig:{...t.placeholder&&{placeholder:t.placeholder},...t.helper&&{hint:t.helper},...y}};d&&(t.variant&&(f.variant=t.variant),(t.multiple||t.type==="checkbox-group")&&(f.multiple=!0),t.density&&(f.density=t.density),t.columns&&(f.columns=t.columns),t.accent&&(f.accent=t.accent),t.accentStyle&&(f.accentStyle=t.accentStyle),t.glow&&(f.glow=!0),t.glowColour&&(f.glowColour=t.glowColour),t.shadow&&(f.shadow=t.shadow),t.shadowColour&&(f.shadowColour=t.shadowColour)),a[t.name]=f}),a}function _(e){const n={};return(e||[]).forEach(a=>{if(!(!a.name||a.type==="page-break"||a.type==="spacer")&&(a.type==="select"||a.type==="multiselect")&&a.required){const t=(a.options||[])[0];t&&(n[a.name]=typeof t=="object"?t.value:t)}}),n}function p(e,n){(n||[]).forEach(a=>{if(a.type!=="date"||!a.name)return;const t=e.querySelector(`[name="${a.name}"]`);t&&t.type!=="date"&&(t.type="date")})}function o(e,n,a){let t=e.querySelector(".cms-form-message");t||(t=document.createElement("p"),t.className="cms-form-message",e.appendChild(t)),t.textContent=n,t.style.cssText=a?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(e=>{let n;try{n=JSON.parse(atob(e.dataset.formInline))}catch{return}const a=n.fields||[],t=n.settings||{},d=Number(t.columns)===3?3:2,h=t.layout||"grid",y=a.some(l=>l.type==="page-break"),f=async l=>{if(e.dataset.triggerBlocked==="true"){const s=e._formLogicRuntime,r=s&&s.submitBlock?s.submitBlock().reasons:[];o(e,r.join(" ")||"This form cannot be submitted yet.",!0);const c=new Error("Blocked by a form trigger");throw c.formSubmitFailed=!0,c}try{const s=e.querySelector(".fb-form-honeypot"),r=s?.querySelector('input[type="text"]')||null,c=s?.querySelector('[name="_t"]')||null,m=Object.assign({},l);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName],r!==null&&(m._hp=r.value),c!==null&&(m._t=c.value);const v=await H.post(`/api/forms/submit/${n.slug}`,m);if(v&&v.error){o(e,v.error,!0);const I=new Error(v.error);throw I.formSubmitFailed=!0,I}if(v?.redirect){window.location.href=v.redirect;return}for(;e.firstChild;)e.removeChild(e.firstChild);o(e,v?.message||t.successMessage||"Thank you for your submission.",!1)}catch(s){throw s.formSubmitFailed||o(e,s.message||"Submission failed. Please try again.",!0),s}},u=Date.now();function w(l){const s=l.querySelector("form");if(!s||s.querySelector(".fb-form-honeypot"))return;const r=document.createElement("div");r.className="fb-form-honeypot",r.setAttribute("aria-hidden","true");const c=document.createElement("input");c.name=s.querySelector('[name="website"]')?"_website":"website",r.dataset.hpName=c.name,c.type="text",c.tabIndex=-1,c.autocomplete="url",c.placeholder="https://",r.appendChild(c);const m=document.createElement("input");m.name="_t",m.type="hidden",m.value=u,r.appendChild(m),s.appendChild(r)}function i(l){if(!window.FormLogicEngine||!a.some(r=>r.logic||Array.isArray(r.triggers)&&r.triggers.length))return null;const s=new window.FormLogicEngine.FormLogicRuntime(n,e,l?{baseValues:l}:void 0);if(s.init(),e._formLogicRuntime=s,e._formLogicObserved)return s;if(e._formLogicObserved=!0,e.parentNode&&typeof MutationObserver<"u"){const r=new MutationObserver(function(c){for(const m of c)for(const v of m.removedNodes)if(v===e||v.nodeType===1&&v.contains&&v.contains(e)){e._formLogicRuntime&&e._formLogicRuntime.destroy(),r.disconnect();return}});r.observe(e.parentNode,{childList:!0,subtree:!1}),e._formLogicObserver=r}return s}if(y&&F.wizard){const l=Y(a,n.title),s=l.map(x=>({title:x.title,description:x.description,fields:C(x.fields,d)})),r=l.map(x=>x.fields);let c=0,m=null,v=null;const I=x=>{const A=window.FormLogicEngine;if(!A||!A.validateFields)return;const q=A.validateFields(e,r[c]||[]);q.valid||(x.preventDefault(),x.stopImmediatePropagation(),G(e,q.missing),X(q))},L=()=>{const x=r[c]||a;p(e,x),j(e,x),t.honeypot!==!1&&w(e),m&&m.destroy(),m=i(v?.getStepData?v.getStepData():void 0),e.querySelectorAll(".wizard-next, .wizard-submit").forEach(A=>A.addEventListener("click",I,!0))};v=F.wizard(e,{schema:{steps:s},layout:h,columns:d,finishText:t.submitText||"Finish",onSubmit:f,onStepChange:x=>{c=x,setTimeout(L,0)}}),e.addEventListener("dm-form-trigger",x=>{if(x.detail?.type!=="goto-step"||!v?.goToStep)return;const A=Number(x.detail.action.step);!Number.isFinite(A)||A<0||A>=s.length||A!==c&&v.goToStep(A)}),Promise.resolve(v).then(L)}else if(F.render){const l=F.render(e,C(a,d),_(a),{submitText:t.submitText||"Submit",layout:h,columns:d,onSubmit:f});Promise.resolve(l).then(function(){if(h==="grid"&&t.submitSpan==="full"){const s=e.querySelector(".form-buttons");s&&s.classList.add("col-span-full")}p(e,a),j(e,a),t.honeypot!==!1&&w(e),i()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
|
package/scripts/build.js
CHANGED
|
@@ -42,15 +42,42 @@ const MINIFY_PATTERNS = [
|
|
|
42
42
|
'plugins/*/public/**/*.js',
|
|
43
43
|
'plugins/*/public/**/*.mjs',
|
|
44
44
|
'plugins/*/public/**/*.css',
|
|
45
|
+
// A plugin's ADMIN stylesheet, declared as `admin.css` in its plugin.json.
|
|
46
|
+
// Absent from this list until 0.60.0, which silently published the invoice
|
|
47
|
+
// plugin with no admin styling at all - the same class of bug as the
|
|
48
|
+
// missing .mjs above, and just as invisible outside a published package.
|
|
49
|
+
'plugins/*/admin/css/**/*.css',
|
|
50
|
+
// The shared mail UI keeps its stylesheet beside its modules rather than in
|
|
51
|
+
// an admin/css directory, so the pattern above does not reach it.
|
|
52
|
+
'plugins/_lib/admin/**/*.css',
|
|
53
|
+
// A PRINT template's stylesheet. The invoice templates share `_base.css`,
|
|
54
|
+
// inlined into each one at render time because a printed page has no
|
|
55
|
+
// stylesheet of its own to fetch - so without this the templates ship and
|
|
56
|
+
// every invoice prints unstyled. Same class of bug as the two above.
|
|
57
|
+
'plugins/*/templates/**/*.css',
|
|
45
58
|
];
|
|
46
59
|
|
|
47
60
|
// Files within plugins that are copied as-is (server-side plugin code)
|
|
48
61
|
const PLUGIN_AS_IS_PATTERNS = [
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
// plugins/_lib is the shared helper library plugins import from. It has no
|
|
63
|
+
// plugin.js, no services/ and no views/, so none of the patterns below
|
|
64
|
+
// reached it and it shipped in no package at all until 0.61.0 - a plugin
|
|
65
|
+
// built against its documented API worked in development and broke on an
|
|
66
|
+
// installed copy.
|
|
67
|
+
'plugins/_lib/**/*.js',
|
|
68
|
+
// A plugin's root-level JS, not just plugin.js and config.js. blog and
|
|
69
|
+
// surveys each keep their PUBLIC SITE routes in plugin.public.js and the
|
|
70
|
+
// invoice plugin its PDF renderer in pdf.js; none of them shipped, so an
|
|
71
|
+
// installed blog had no archive, no post pages and no feed. Exactly the
|
|
72
|
+
// failure the note above records for _lib, one directory over.
|
|
73
|
+
'plugins/*/*.js',
|
|
51
74
|
'plugins/**/routes/**/*.js',
|
|
52
75
|
'plugins/**/services/**/*.js',
|
|
53
76
|
'plugins/**/views/**/*.js',
|
|
77
|
+
// surveys keeps its campaign, audience, ledger, sending and stats modules
|
|
78
|
+
// in lib/ and imports all five from plugin.js - so an installed surveys
|
|
79
|
+
// could not load at all.
|
|
80
|
+
'plugins/**/lib/**/*.js',
|
|
54
81
|
'plugins/**/*.json',
|
|
55
82
|
'plugins/**/*.html',
|
|
56
83
|
];
|
|
@@ -272,7 +299,14 @@ async function build() {
|
|
|
272
299
|
}
|
|
273
300
|
|
|
274
301
|
// Copy plugin server-side code verbatim
|
|
275
|
-
|
|
302
|
+
// `plugins/**/*.json` would otherwise sweep a plugin's runtime data/ directory
|
|
303
|
+
// into the build - analytics counters, and since the mail core moved here,
|
|
304
|
+
// sealed mailbox passwords. The npm `files` list excludes them at publish
|
|
305
|
+
// time, but that is one typo away from shipping someone's credentials, and
|
|
306
|
+
// the build artifact has no business containing them in the first place.
|
|
307
|
+
const PLUGIN_RUNTIME_DATA = /^plugins\/[^/]+\/data\//;
|
|
308
|
+
const pluginAsIs = (await collectFiles('{' + PLUGIN_AS_IS_PATTERNS.join(',') + '}'))
|
|
309
|
+
.filter(rel => !PLUGIN_RUNTIME_DATA.test(rel));
|
|
276
310
|
for (const rel of pluginAsIs) {
|
|
277
311
|
const outPath = join(OUT, rel);
|
|
278
312
|
mkdirSync(dirname(outPath), {recursive: true});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy Domma dist files to admin and public directories.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: This script is now OPTIONAL.
|
|
5
|
+
* The server serves Domma directly from node_modules/domma-js/public/dist at /dist/domma/.
|
|
6
|
+
* Only run this if you need the files as static copies (e.g. for deployment without node_modules).
|
|
7
|
+
*
|
|
8
|
+
* Run: node scripts/copy-domma.js
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { createRequire } from 'module';
|
|
14
|
+
|
|
15
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
// Resolve from npm package
|
|
20
|
+
const dommaPackageDir = path.dirname(require.resolve('domma-js/package.json'));
|
|
21
|
+
const DOMMA_DIST = path.join(dommaPackageDir, 'public', 'dist');
|
|
22
|
+
|
|
23
|
+
const TARGETS = [
|
|
24
|
+
path.join(ROOT, 'admin', 'dist', 'domma'),
|
|
25
|
+
path.join(ROOT, 'public', 'dist', 'domma')
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
async function copyDir(src, dest) {
|
|
29
|
+
await fs.mkdir(dest, { recursive: true });
|
|
30
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const srcPath = path.join(src, entry.name);
|
|
33
|
+
const destPath = path.join(dest, entry.name);
|
|
34
|
+
if (entry.isDirectory()) {
|
|
35
|
+
await copyDir(srcPath, destPath);
|
|
36
|
+
} else {
|
|
37
|
+
await fs.copyFile(srcPath, destPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(`Source: ${DOMMA_DIST}`);
|
|
43
|
+
console.log('Copying Domma dist files...');
|
|
44
|
+
for (const target of TARGETS) {
|
|
45
|
+
await copyDir(DOMMA_DIST, target);
|
|
46
|
+
console.log(` ✓ → ${path.relative(ROOT, target)}`);
|
|
47
|
+
}
|
|
48
|
+
console.log('Done.');
|