domma-cms 0.16.0 → 0.18.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 +2 -0
- package/admin/css/dashboard.css +1 -0
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +4 -4
- package/admin/index.html +2 -1
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +1 -1
- package/admin/js/lib/card-builder.js +3 -3
- package/admin/js/lib/effects-builder.js +1 -1
- package/admin/js/lib/markdown-toolbar.js +5 -5
- package/admin/js/templates/dashboard/activity-feed.html +3 -0
- package/admin/js/templates/dashboard/cache.html +32 -0
- package/admin/js/templates/dashboard/health-detail.html +2 -0
- package/admin/js/templates/dashboard/journeys.html +17 -0
- package/admin/js/templates/dashboard/kpi-strip.html +34 -0
- package/admin/js/templates/dashboard/spike-feed.html +3 -0
- package/admin/js/templates/dashboard/top-pages.html +3 -0
- package/admin/js/templates/dashboard/traffic-chart.html +3 -0
- package/admin/js/templates/dashboard.html +26 -44
- package/admin/js/templates/settings.html +26 -0
- package/admin/js/views/block-editor-enhance.js +1 -1
- package/admin/js/views/dashboard/lib/escape.js +1 -0
- package/admin/js/views/dashboard/widgets/activity-feed.js +1 -0
- package/admin/js/views/dashboard/widgets/cache.js +1 -0
- package/admin/js/views/dashboard/widgets/health-detail.js +1 -0
- package/admin/js/views/dashboard/widgets/journeys.js +1 -0
- package/admin/js/views/dashboard/widgets/kpi-strip.js +1 -0
- package/admin/js/views/dashboard/widgets/spike-feed.js +6 -0
- package/admin/js/views/dashboard/widgets/top-pages.js +1 -0
- package/admin/js/views/dashboard/widgets/traffic-chart.js +1 -0
- package/admin/js/views/dashboard.js +1 -1
- package/admin/js/views/form-editor.js +7 -7
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/page-editor.js +42 -37
- package/admin/js/views/settings.js +3 -3
- package/config/cache.json +4 -0
- package/config/cache.json.example +12 -0
- package/config/plugins.json +3 -0
- package/package.json +2 -2
- package/plugins/analytics/daily.json +5 -0
- package/plugins/analytics/journeys.json +10 -0
- package/plugins/analytics/lifetime.json +25 -0
- package/plugins/analytics/plugin.js +231 -16
- package/plugins/analytics/public/inject-body.html +26 -2
- package/public/js/forms.js +1 -1
- package/public/js/site.js +1 -1
- package/server/config.js +12 -1
- package/server/routes/api/cache.js +57 -0
- package/server/routes/api/dashboard.js +239 -0
- package/server/routes/api/navigation.js +2 -0
- package/server/routes/api/settings.js +3 -0
- package/server/routes/public.js +11 -3
- package/server/server.js +18 -3
- package/server/services/blocks.js +3 -0
- package/server/services/cache/drivers/MemoryDriver.js +118 -0
- package/server/services/cache/drivers/NoneDriver.js +12 -0
- package/server/services/cache/index.js +229 -0
- package/server/services/cache/lru.js +61 -0
- package/server/services/collections.js +17 -4
- package/server/services/content.js +7 -2
- package/server/services/email.js +60 -20
- package/server/services/forms.js +3 -0
- package/server/services/health.js +282 -0
- package/server/services/markdown.js +25 -15
- package/server/services/plugins.js +37 -5
- package/server/services/views.js +4 -0
- package/server/templates/page.html +130 -130
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function se(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H7V5zM7 11H15a3 3 0 0 1 0 6H7V11z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("italic",{viewBox:"0 0 24 24",path:"M11 5h4M9 19h4M13 5l-2 14",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("strikethrough",{viewBox:"0 0 24 24",path:"M16 4H9a3 3 0 0 0 0 6h6a3 3 0 0 1 0 6H6M3 12h18",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("quote",{viewBox:"0 0 24 24",path:"M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1zM15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("eye",{viewBox:"0 0 24 24",path:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("expand",{viewBox:"0 0 24 24",path:"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("columns",{viewBox:"0 0 24 24",path:"M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM12 4v16",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("card",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M3 9h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("help-circle",{viewBox:"0 0 24 24",path:"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 17h.01M12 13a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("spacer-insert",{viewBox:"0 0 24 24",paths:["M3 8h18","M3 16h18","M12 8v8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("icon-pick",{viewBox:"0 0 24 24",paths:["M4 4h6v6H4z","M14 4h6v6h-6z","M4 14h6v6H4z","M14 14h6v6h-6z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("colour-picker",{viewBox:"0 0 24 24",paths:["M12 2a5 5 0 0 1 5 5c0 3-5 10-5 10S7 10 7 7a5 5 0 0 1 5-5z","M12 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("btn-insert",{viewBox:"0 0 24 24",paths:["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z","M8 12h8M12 9v6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("link-shortcode",{viewBox:"0 0 24 24",paths:["M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71","M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("layout-list",{viewBox:"0 0 24 24",paths:["M3 5h18M3 9h18","M3 14h4v6H3zM9 14h12M9 17h8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("sparkles",{viewBox:"0 0 24 24",paths:["M12 3L13.5 8.5H19L14.5 11.5L16 17L12 14L8 17L9.5 11.5L5 8.5H10.5L12 3Z","M19 3L19.7 5.3H22L20.2 6.6L20.9 9L19 7.7L17.1 9L17.8 6.6L16 5.3H18.3L19 3Z","M5 13L5.5 14.7H7L5.8 15.5L6.3 17.2L5 16.3L3.7 17.2L4.2 15.5L3 14.7H4.5L5 13Z"],stroke:"currentColor",fill:"none",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("accordion-insert",{viewBox:"0 0 24 24",paths:["M3 4h18","M3 8h18","M8 11l4 4 4-4","M3 16h18","M3 20h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("banner-insert",{viewBox:"0 0 24 24",paths:["M3 6h18","M3 10h18","M3 14h12"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("hero",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5z","M7 8h10M7 11h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("text-style",{viewBox:"0 0 24 24",paths:["M4 7V5h16v2","M9 19h6","M12 5v14","M5 12h14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("css-code",{viewBox:"0 0 24 24",paths:["M9 9l-6 3 6 3","M15 9l6 3-6 3","M13 5l-2 14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("scribe-insert",{viewBox:"0 0 24 24",paths:["M4 20h3l10-10-3-3L4 17v3z","M14 7l3 3","M4 4h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"})}export function wrapSelection(t,e,m){const i=t.selectionStart,l=t.selectionEnd,o=t.value,r=o.substring(i,l);r?(t.value=o.substring(0,i)+e+r+m+o.substring(l),t.selectionStart=i+e.length,t.selectionEnd=l+e.length):(t.value=o.substring(0,i)+e+m+o.substring(i),t.selectionStart=t.selectionEnd=i+e.length),t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function insertAtCursor(t,e){const m=t.selectionStart,i=t.value;t.value=i.substring(0,m)+e+i.substring(m),t.selectionStart=t.selectionEnd=m+e.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function attachEditorKeybindings(t){t.addEventListener("keydown",e=>{if(e.key==="Tab"){e.preventDefault();const i=t.selectionStart;if(e.shiftKey){const l=t.value.lastIndexOf(`
|
|
1
|
+
function se(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H7V5zM7 11H15a3 3 0 0 1 0 6H7V11z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("italic",{viewBox:"0 0 24 24",path:"M11 5h4M9 19h4M13 5l-2 14",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("strikethrough",{viewBox:"0 0 24 24",path:"M16 4H9a3 3 0 0 0 0 6h6a3 3 0 0 1 0 6H6M3 12h18",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("quote",{viewBox:"0 0 24 24",path:"M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1zM15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("eye",{viewBox:"0 0 24 24",path:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("expand",{viewBox:"0 0 24 24",path:"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("columns",{viewBox:"0 0 24 24",path:"M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM12 4v16",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("card",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M3 9h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("help-circle",{viewBox:"0 0 24 24",path:"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 17h.01M12 13a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("spacer-insert",{viewBox:"0 0 24 24",paths:["M3 8h18","M3 16h18","M12 8v8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("icon-pick",{viewBox:"0 0 24 24",paths:["M4 4h6v6H4z","M14 4h6v6h-6z","M4 14h6v6H4z","M14 14h6v6h-6z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("colour-picker",{viewBox:"0 0 24 24",paths:["M12 2a5 5 0 0 1 5 5c0 3-5 10-5 10S7 10 7 7a5 5 0 0 1 5-5z","M12 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("btn-insert",{viewBox:"0 0 24 24",paths:["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z","M8 12h8M12 9v6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("link-shortcode",{viewBox:"0 0 24 24",paths:["M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71","M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("layout-list",{viewBox:"0 0 24 24",paths:["M3 5h18M3 9h18","M3 14h4v6H3zM9 14h12M9 17h8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("sparkles",{viewBox:"0 0 24 24",paths:["M12 3L13.5 8.5H19L14.5 11.5L16 17L12 14L8 17L9.5 11.5L5 8.5H10.5L12 3Z","M19 3L19.7 5.3H22L20.2 6.6L20.9 9L19 7.7L17.1 9L17.8 6.6L16 5.3H18.3L19 3Z","M5 13L5.5 14.7H7L5.8 15.5L6.3 17.2L5 16.3L3.7 17.2L4.2 15.5L3 14.7H4.5L5 13Z"],stroke:"currentColor",fill:"none",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("accordion-insert",{viewBox:"0 0 24 24",paths:["M3 4h18","M3 8h18","M8 11l4 4 4-4","M3 16h18","M3 20h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("banner-insert",{viewBox:"0 0 24 24",paths:["M3 6h18","M3 10h18","M3 14h12"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("hero",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5z","M7 8h10M7 11h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("text-style",{viewBox:"0 0 24 24",paths:["M4 7V5h16v2","M9 19h6","M12 5v14","M5 12h14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("css-code",{viewBox:"0 0 24 24",paths:["M9 9l-6 3 6 3","M15 9l6 3-6 3","M13 5l-2 14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("scribe-insert",{viewBox:"0 0 24 24",paths:["M4 20h3l10-10-3-3L4 17v3z","M14 7l3 3","M4 4h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("carousel-insert",{viewBox:"0 0 24 24",paths:["M7 5h10v14H7z","M3 8h2v8H3z","M19 8h2v8h-2z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"})}export function wrapSelection(t,e,m){const i=t.selectionStart,l=t.selectionEnd,o=t.value,r=o.substring(i,l);r?(t.value=o.substring(0,i)+e+r+m+o.substring(l),t.selectionStart=i+e.length,t.selectionEnd=l+e.length):(t.value=o.substring(0,i)+e+m+o.substring(i),t.selectionStart=t.selectionEnd=i+e.length),t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function insertAtCursor(t,e){const m=t.selectionStart,i=t.value;t.value=i.substring(0,m)+e+i.substring(m),t.selectionStart=t.selectionEnd=m+e.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function attachEditorKeybindings(t){t.addEventListener("keydown",e=>{if(e.key==="Tab"){e.preventDefault();const i=t.selectionStart;if(e.shiftKey){const l=t.value.lastIndexOf(`
|
|
2
2
|
`,i-1)+1,o=t.value.substring(l).match(/^ {1,2}/);o&&(t.value=t.value.substring(0,l)+t.value.substring(l+o[0].length),t.selectionStart=t.selectionEnd=Math.max(l,i-o[0].length),t.dispatchEvent(new Event("input",{bubbles:!0})),E.toast("Dedented",{type:"info",duration:800}))}else t.value=t.value.substring(0,i)+" "+t.value.substring(i),t.selectionStart=t.selectionEnd=i+2,t.dispatchEvent(new Event("input",{bubbles:!0})),E.toast("Indented",{type:"info",duration:800});return}if(!(e.ctrlKey||e.metaKey))return;const m=e.key.toLowerCase();if(m==="z")e.preventDefault(),document.execCommand("undo"),E.toast("Undo",{type:"info",duration:1200});else if(m==="y")e.preventDefault(),document.execCommand("redo"),E.toast("Redo",{type:"info",duration:1200});else if(m==="x"&&t.selectionStart===t.selectionEnd){e.preventDefault();const i=t.value.lastIndexOf(`
|
|
3
3
|
`,t.selectionStart-1)+1,l=t.value.indexOf(`
|
|
4
4
|
`,t.selectionStart),o=l===-1?t.value.length:l+1;t.setSelectionRange(i,o),document.execCommand("cut"),t.dispatchEvent(new Event("input",{bubbles:!0})),E.toast("Line cut",{type:"info",duration:1200})}else if(m==="c"&&t.selectionStart===t.selectionEnd){e.preventDefault();const i=t.selectionStart,l=t.value.lastIndexOf(`
|
|
@@ -6,7 +6,7 @@ function se(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6
|
|
|
6
6
|
`,i),r=o===-1?t.value.length:o+1;t.setSelectionRange(l,r),document.execCommand("copy"),t.setSelectionRange(i,i),E.toast("Line copied",{type:"info",duration:1200})}})}export function insertLine(t,e){const m=t.selectionStart,i=t.value,l=i.lastIndexOf(`
|
|
7
7
|
`,m-1)+1,o=i.indexOf(`
|
|
8
8
|
`,l),r=i.substring(l,o===-1?i.length:o);if(r.startsWith(e)){const s=o===-1?"":i.substring(o);t.value=i.substring(0,l)+r.substring(e.length)+s,t.selectionStart=t.selectionEnd=Math.max(l,m-e.length)}else t.value=i.substring(0,l)+e+i.substring(l),t.selectionStart=t.selectionEnd=m+e.length;t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}const J=["activity","airpods","airport","alert-circle","alert-warning","ambulance","angry","annoyed","apartment","arch","archive","arrow-down","arrow-down-left","arrow-down-right","arrow-left","arrow-right","arrow-up","arrow-up-left","arrow-up-right","astonished","at-sign","attachment","award","badge","ban","bandage","bank","banknote","barbell","barcode","barn","baseball","basketball","battery","battery-charging","bauble","bell","bell-off","bells","bicycle","bitcoin","blood-drop","blush","bold","bone","book","book-closed","book-open","bookmark","bookmark-filled","bowling","box","boxing-glove","brain","bridge","briefcase","building","bus","cabin","cake","calculator","calendar","camera","camera-off","candy-cane","capsule","car","cart","cart-add","cash","cast","castle","chart-area","chart-bar","chart-bar-horizontal","chart-candlestick","chart-line","chart-pie","chat","chat-alt","check","check-circle","check-circle-filled","check-square","chevron-down","chevron-left","chevron-right","chevron-up","chevrons-down","chevrons-left","chevrons-right","chevrons-up","church","circle","circle-filled","clear-format","clipboard","clipboard-check","clipboard-list","clock","close","cloud","cloud-download","cloud-drizzle","cloud-lightning","cloud-off","cloud-rain","cloud-sun","cloud-upload","code","code-block","code-inline","cog","coins","columns","comment","compass","component","confused","cool","copy","corner-down-left","corner-down-right","corner-up-left","corner-up-right","court","cpu","credit-card","crown","crutch","cry","currency-dollar","currency-euro","currency-pound","cycling","database","dead","desktop","disappointed","dna","document","document-add","document-check","document-remove","document-text","dollar-sign","dome","dot","dots-horizontal","dots-vertical","download","droplet","droplets","dumbbell","edit","embed","emoji-happy","emoji-sad","euro-sign","exclamation","expand","expressionless","external-link","eye","eye-medical","eye-off","factory","fast-forward","feather","file-code","file-text","file-zip","fill","film","filter","fire","first-aid","fishing","flag","fog","folder","folder-add","folder-minus","folder-open","folder-plus","folder-remove","football","fortress","fuel","gamepad","garage","gauge","gift","git-branch","github","globe","golf","grid","grin","growth","hard-drive","hash","haze","heading-1","heading-2","heading-3","headphones","heart","heart-eyes","heart-filled","heart-pulse","heartbeat","help-circle","holly","home","hospital","hotel","house","image","image-add","images","inbox","indent","info","info-filled","investment","invoice","italic","joy","joystick","key","kettlebell","keyboard","laptop","laugh","layers","layout","library","lighthouse","lightning","link","link-2","link-add","linkedin","list","list-bullet","list-numbered","loader","loading","lock","log-in","log-out","lungs","mail","mail-open","map","map-pin","mask","maximize","medal","medical-cross","menu","menu-alt","message-circle","message-square","mic","mic-off","microscope","minimize","minus","minus-circle","minus-square","monitor","monument","moon","moon-star","more-horizontal","more-vertical","mosque","motorcycle","mountain","mouse","mouse-pointer","move","museum","music","nerd","neutral","notification","obelisk","office","outdent","package","palette","panel-bottom","panel-left","panel-right","panel-top","paperclip","parking","pause","pause-filled","percent","phone","phone-call","phone-incoming","phone-off","phone-outgoing","piggy-bank","pill","pill-bottle","pin","play","play-circle","play-filled","plug","plus","plus-circle","plus-square","podium","pound-sign","printer","pulse","pyramid","qrcode","question","quote","racket","radio","rage","rain","rainbow","receipt","redo","refresh","refresh-cw","reindeer","rewind","road","rotate-ccw","rotate-cw","router","rss","running","sad","safe","save","scale","scale-weight","school","search","send","server","settings","share","share-2","share-alt","shield","shield-alert","shield-check","shield-x","shipping","shocked","shopping-bag","shrink","sick","sidebar-left","sidebar-right","silly","skate","ski","skip-back","skip-forward","skyscraper","sleepy","sleigh","sliders","smartphone","smartwatch","smile","snow","snowflake","snowman","sob","soccer","sort","sparkles","speaker","spinner","square","stadium","star","star-decoration","star-eyes","star-filled","stethoscope","stop","stop-filled","stopwatch","store","strikethrough","sun","sunrise","sunset","surfboard","surprised","swimming","sync","syringe","tablet","tablet-smartphone","tag","tags","target","taxi","temple","tennis","tent","terminal","test-tube","text-center","text-left","text-right","thermometer","thermometer-medical","thermometer-sun","thinking","thumb-down","thumb-up","tongue","tool","tooth","tower","train-station","trash","tree","trending-down","trending-neutral","trending-up","trophy","truck","tv","tv-minimal","twitter","type","umbrella","underline","undo","university","unlink","unlock","upload","usb","user","user-add","user-check","user-group","user-plus","user-remove","users","vaccine","van","vault","video","video-off","volleyball","volume","volume-down","volume-mute","volume-off","volume-up","wallet","warehouse","warning","warning-filled","watch","webcam","wheelchair","whistle","wifi","wifi-off","wind","windmill","wink","wreath","x","x-circle","x-circle-filled","yoga","youtube","zany","zap"];function le(t,e,m){const i=document.querySelector(".editor-spacer-picker");if(i){i.remove();return}const l=document.createElement("div");l.className="editor-spacer-picker";const o=document.createElement("div");o.className="editor-spacer-picker-label",o.textContent="Spacer height",l.appendChild(o);const r=document.createElement("div");r.className="editor-spacer-picker-row";const s=document.createElement("input");s.type="range",s.className="editor-spacer-slider",s.min="4",s.max="200",s.step="4",s.value=m;const p=document.createElement("span");p.className="editor-spacer-slider-value",p.textContent=m+"px",s.addEventListener("input",function(){p.textContent=this.value+"px"}),r.appendChild(s),r.appendChild(p),l.appendChild(r);const d=document.createElement("button");d.type="button",d.className="btn btn-primary btn-sm editor-spacer-insert-btn",d.textContent="Insert",l.appendChild(d);function f(k){!l.contains(k.target)&&k.target!==e&&(l.remove(),document.removeEventListener("click",f,!0))}d.addEventListener("click",function(){l.remove(),document.removeEventListener("click",f,!0),insertAtCursor(t,`[spacer size="${s.value}" /]
|
|
9
|
-
`)});const n=e.getBoundingClientRect(),c=e.closest(".editor-toolbar").getBoundingClientRect();l.style.top=n.bottom-c.top+4+"px";const a=n.left-c.left;l.style.left=Math.min(a,c.width-240-8)+"px",e.closest(".editor-toolbar").appendChild(l),setTimeout(function(){document.addEventListener("click",f,!0)},0)}function ce(t,e){const m=document.querySelector(".editor-icon-picker");if(m){m.remove();return}const i=document.createElement("div");i.className="editor-icon-picker";const l=document.createElement("input");l.type="text",l.className="form-input editor-icon-picker-search",l.placeholder="Search icons\u2026",i.appendChild(l);const o=document.createElement("div");o.className="editor-icon-picker-size-row";const r=document.createElement("label");r.textContent="Size (px)";const s=document.createElement("input");s.type="number",s.className="form-input editor-icon-picker-size",s.placeholder="default",s.min="8",s.max="256",o.appendChild(r),o.appendChild(s),i.appendChild(o);const p=document.createElement("div");p.className="editor-icon-picker-grid",i.appendChild(p);function d(
|
|
9
|
+
`)});const n=e.getBoundingClientRect(),c=e.closest(".editor-toolbar").getBoundingClientRect();l.style.top=n.bottom-c.top+4+"px";const a=n.left-c.left;l.style.left=Math.min(a,c.width-240-8)+"px",e.closest(".editor-toolbar").appendChild(l),setTimeout(function(){document.addEventListener("click",f,!0)},0)}function ce(t,e){const m=document.querySelector(".editor-icon-picker");if(m){m.remove();return}const i=document.createElement("div");i.className="editor-icon-picker";const l=document.createElement("input");l.type="text",l.className="form-input editor-icon-picker-search",l.placeholder="Search icons\u2026",i.appendChild(l);const o=document.createElement("div");o.className="editor-icon-picker-size-row";const r=document.createElement("label");r.textContent="Size (px)";const s=document.createElement("input");s.type="number",s.className="form-input editor-icon-picker-size",s.placeholder="default",s.min="8",s.max="256",o.appendChild(r),o.appendChild(s),i.appendChild(o);const p=document.createElement("div");p.className="editor-icon-picker-grid",i.appendChild(p);function d(w){!i.contains(w.target)&&w.target!==e&&(i.remove(),document.removeEventListener("click",d,!0))}function f(w){p.textContent="";const x=w?J.filter(S=>S.includes(w.toLowerCase())):J;if(x.length===0){const S=document.createElement("div");S.className="editor-icon-picker-empty",S.textContent="No icons found",p.appendChild(S);return}x.forEach(function(S){const M=document.createElement("button");M.type="button",M.className="editor-icon-picker-item";const v=document.createElement("span");v.setAttribute("data-icon",S);const h=document.createElement("span");h.textContent=S,M.appendChild(v),M.appendChild(h),M.addEventListener("click",function(){i.remove(),document.removeEventListener("click",d,!0);const C=s.value.trim(),L=C?`[icon name="${S}" size="${C}" /]`:`[icon name="${S}" /]`;insertAtCursor(t,L)}),p.appendChild(M)}),Domma.icons.scan(p)}f(""),l.addEventListener("input",function(){f(this.value.trim())});const n=e.getBoundingClientRect(),c=e.closest(".editor-toolbar").getBoundingClientRect();i.style.top=n.bottom-c.top+4+"px";const a=n.left-c.left,k=320,y=c.width;i.style.left=Math.min(a,y-k-8)+"px",e.closest(".editor-toolbar").appendChild(i),requestAnimationFrame(function(){l.focus()}),setTimeout(function(){document.addEventListener("click",d,!0)},0)}function ae(t,e,m,i){const l=document.querySelector(".editor-toolbar-dropdown");if(l){l.remove();return}const o=document.createElement("div");o.className="editor-toolbar-dropdown",m.forEach(function(f){const n=document.createElement("button");if(n.type="button",n.className="editor-toolbar-dropdown-item",f.icon){const a=document.createElement("span");a.setAttribute("data-icon",f.icon),n.appendChild(a)}const c=document.createElement("span");c.textContent=f.label,n.appendChild(c),n.addEventListener("click",function(){o.remove(),document.removeEventListener("click",d,!0),U(f.action,t,e,i)}),o.appendChild(n)});const r=e.getBoundingClientRect(),s=e.closest(".editor-toolbar").getBoundingClientRect();o.style.top=r.bottom-s.top+4+"px";const p=r.left-s.left;o.style.left=Math.min(p,s.width-180-8)+"px",e.closest(".editor-toolbar").appendChild(o),Domma.icons.scan(o);function d(f){!o.contains(f.target)&&f.target!==e&&(o.remove(),document.removeEventListener("click",d,!0))}setTimeout(function(){document.addEventListener("click",d,!0)},0)}function U(t,e,m,i){const{spacerDefault:l,handlers:o}=i;if(typeof t=="function")t(e);else if(t==="block")if(o.block)o.block(e);else{const r=e.selectionStart,s='[block template="" /]';e.value=e.value.substring(0,r)+s+e.value.substring(r),e.selectionStart=e.selectionEnd=r+17,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="component")o.component?o.component(e):de(e);else if(t==="button")if(o.button)o.button(e);else{const r=e.selectionStart,s=e.selectionEnd,d=`[button href="" variant="primary"]${e.value.substring(r,s)||"Click me"}[/button]`;e.value=e.value.substring(0,r)+d+e.value.substring(s),e.selectionStart=e.selectionEnd=r+14,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="linksc")if(o.linksc)o.linksc(e);else{const r=e.selectionStart,s=e.selectionEnd,d=`[link href=""]${e.value.substring(r,s)||"Link text"}[/link]`;e.value=e.value.substring(0,r)+d+e.value.substring(s),e.selectionStart=e.selectionEnd=r+12,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="colourpick"){const r=e.selectionStart;document.getElementById("dm-colour-overlay")?.remove();const s=document.createElement("div");s.id="dm-colour-overlay",s.style.cssText="position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.5);";const p=document.createElement("div");p.style.cssText="background:var(--dm-surface,#1e1e2e);border:1px solid var(--dm-border,#3a3a5c);border-radius:12px;padding:1.75rem 2rem;display:flex;flex-direction:column;align-items:center;gap:1.25rem;min-width:260px;box-shadow:0 16px 48px rgba(0,0,0,.55);";const d=document.createElement("p");d.textContent="Colour Picker",d.style.cssText="margin:0;font-weight:700;font-size:1rem;letter-spacing:.02em;";const f=document.createElement("input");f.type="color",f.value="#000000",f.style.cssText="width:160px;height:110px;cursor:pointer;border:none;background:none;padding:0;border-radius:6px;overflow:hidden;";const n=document.createElement("div");n.style.cssText="display:flex;align-items:center;gap:.5rem;";const c=document.createElement("input");c.type="text",c.value="#000000",c.className="form-input",c.style.cssText="font-family:monospace;width:100px;text-transform:uppercase;letter-spacing:.05em;";const a=document.createElement("button");a.type="button",a.className="btn btn-ghost btn-sm",a.textContent="Copy";const k=document.createElement("button");k.type="button",k.className="btn btn-primary btn-sm",k.textContent="Insert";const y=()=>s.remove();f.addEventListener("input",()=>{c.value=f.value}),c.addEventListener("input",()=>{/^#[0-9a-f]{6}$/i.test(c.value)&&(f.value=c.value)}),a.addEventListener("click",()=>{const w=document.createElement("input");w.value=c.value,document.body.appendChild(w),w.select(),document.execCommand("copy"),w.remove(),a.textContent="Copied!",setTimeout(()=>{a.textContent="Copy"},1500)}),k.addEventListener("click",()=>{e.selectionStart=e.selectionEnd=r,insertAtCursor(e,c.value),y()}),s.addEventListener("click",w=>{w.target===s&&y()}),n.appendChild(c),n.appendChild(a),n.appendChild(k),p.appendChild(d),p.appendChild(f),p.appendChild(n),s.appendChild(p),document.body.appendChild(s)}else if(t==="link")o.link&&o.link(e);else if(t==="image")o.image&&o.image(e);else if(t==="card")if(o.card)o.card(e);else{const r=e.selectionStart,s=e.selectionEnd,d=`[card title="Card Title"]
|
|
10
10
|
${e.value.substring(r,s)||"Content here"}
|
|
11
11
|
[/card]`;e.value=e.value.substring(0,r)+d+e.value.substring(s),e.selectionStart=r+13,e.selectionEnd=r+23,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="hero")if(o.hero)o.hero(e);else{const r=e.selectionStart,s=e.selectionEnd,d=`[hero title="Hero Title" tagline="A short tagline" size="lg"]
|
|
12
12
|
${e.value.substring(r,s)||"Optional body content here."}
|
|
@@ -31,7 +31,7 @@ Describe this event.
|
|
|
31
31
|
[item]Item 2[/item]
|
|
32
32
|
[item]Item 3[/item]
|
|
33
33
|
[/listgroup]
|
|
34
|
-
`);else if(t==="collection")o.collection?o.collection(e):insertAtCursor(e,'[collection slug="" display="table" /]');else if(t==="view")o.view&&o.view(e);else if(t==="cta")o.cta&&o.cta(e);else if(t==="form")o.form?o.form(e):insertAtCursor(e,'[form slug="" /]');else if(t==="tabs")o.tabs&&o.tabs(e);else if(t==="banner")o.banner&&o.banner(e);else if(t==="scribe")if(o.scribe)o.scribe(e);else{const r=e.selectionStart,s=`[scribe]
|
|
34
|
+
`);else if(t==="collection")o.collection?o.collection(e):insertAtCursor(e,'[collection slug="" display="table" /]');else if(t==="view")o.view&&o.view(e);else if(t==="cta")o.cta&&o.cta(e);else if(t==="form")o.form?o.form(e):insertAtCursor(e,'[form slug="" /]');else if(t==="tabs")o.tabs&&o.tabs(e);else if(t==="carousel")o.carousel&&o.carousel(e);else if(t==="banner")o.banner&&o.banner(e);else if(t==="scribe")if(o.scribe)o.scribe(e);else{const r=e.selectionStart,s=`[scribe]
|
|
35
35
|
[render]Type text here.[/render]
|
|
36
36
|
[wait]1500[/wait]
|
|
37
37
|
[undo all="true" /]
|
|
@@ -41,6 +41,6 @@ Describe this event.
|
|
|
41
41
|
[item title="Item 1"]Content here.[/item]
|
|
42
42
|
[item title="Item 2"]Content here.[/item]
|
|
43
43
|
[/accordion]
|
|
44
|
-
`;e.value=e.value.substring(0,r)+s+e.value.substring(r),e.selectionStart=e.selectionEnd=r+s.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="text"){let n=function(b,u){const g=document.createElement("div"),z=document.createElement("label");return z.style.cssText=d,z.textContent=b,g.appendChild(z),g.appendChild(u),g},c=function(b){const u=document.createElement("select");return u.style.cssText=f,[["","\u2014 default \u2014"],...b].forEach(([g,z])=>{const O=document.createElement("option");O.value=g,O.textContent=z,u.appendChild(O)}),u},a=function(b,u){const g=document.createElement("input");return g.type="text",g.placeholder=b||"",g.value=u||"",g.style.cssText=f,g},k=function(b){const u=document.createElement("label");u.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const g=document.createElement("input");g.type="checkbox";const z=document.createElement("span");return z.style.cssText="font-size:.85em;color:var(--dm-text,#eee);",z.textContent=b,u.appendChild(g),u.appendChild(z),{wrap:u,cb:g}},y=function(b,u){const g=document.createElement("div");return g.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:.5rem;",g.appendChild(b),g.appendChild(u),g},
|
|
44
|
+
`;e.value=e.value.substring(0,r)+s+e.value.substring(r),e.selectionStart=e.selectionEnd=r+s.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="text"){let n=function(b,u){const g=document.createElement("div"),z=document.createElement("label");return z.style.cssText=d,z.textContent=b,g.appendChild(z),g.appendChild(u),g},c=function(b){const u=document.createElement("select");return u.style.cssText=f,[["","\u2014 default \u2014"],...b].forEach(([g,z])=>{const O=document.createElement("option");O.value=g,O.textContent=z,u.appendChild(O)}),u},a=function(b,u){const g=document.createElement("input");return g.type="text",g.placeholder=b||"",g.value=u||"",g.style.cssText=f,g},k=function(b){const u=document.createElement("label");u.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const g=document.createElement("input");g.type="checkbox";const z=document.createElement("span");return z.style.cssText="font-size:.85em;color:var(--dm-text,#eee);",z.textContent=b,u.appendChild(g),u.appendChild(z),{wrap:u,cb:g}},y=function(b,u){const g=document.createElement("div");return g.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:.5rem;",g.appendChild(b),g.appendChild(u),g},w=function(b){const u=document.createElement("div");return u.style.cssText="border-top:1px solid var(--dm-border,#333);padding-top:.5rem;margin-top:.1rem;font-size:.65rem;font-weight:700;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.08em;",u.textContent=b,u},_=function(){const b=[];M.value&&b.push(`font-size:${ee[M.value]||M.value}`);const u=parseFloat(v.value);!isNaN(u)&&u>0&&b.push(`font-size:${u}pt`),L.checked?b.push("font-weight:700"):h.value&&b.push(`font-weight:${te[h.value]||h.value}`),T.checked&&b.push("font-style:italic");const g=B.value.trim();g&&b.push(`color:${Y[g]||g}`),P.value&&b.push(`font-family:${oe[P.value]}`),W.value&&b.push(`text-transform:${ie[W.value]}`),A.value&&b.push(`text-decoration:${re[A.value]}`),H.value&&b.push(`letter-spacing:${ne[H.value]}`),R.value&&(b.push("display:block"),b.push(`text-align:${R.value}`)),V.value.trim()&&b.push(V.value.trim()),q.style.cssText=b.join(";"),q.textContent=S.value||"Preview text"};const r=e.selectionStart,s=e.selectionEnd,p=e.value.substring(r,s)||"",d="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",f="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",x=document.createElement("div");x.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.6rem;overflow-y:auto;max-height:75vh;";const S=a("Text to style\u2026",p);x.appendChild(n("Content",S)),x.appendChild(w("Typography"));const M=c([["xs","xs \u2014 0.75rem"],["sm","sm \u2014 0.875rem"],["base","base \u2014 1rem"],["lg","lg \u2014 1.125rem"],["xl","xl \u2014 1.25rem"],["2xl","2xl \u2014 1.5rem"],["3xl","3xl \u2014 1.875rem"],["4xl","4xl \u2014 2.25rem"]]),v=a("pt value (overrides Size)");x.appendChild(y(n("Size",M),n("Point Size (pt)",v)));const h=c([["thin","Thin (100)"],["light","Light (300)"],["normal","Normal (400)"],["medium","Medium (500)"],["semibold","Semibold (600)"],["bold","Bold (700)"],["extrabold","Extrabold (800)"],["black","Black (900)"]]),{wrap:C,cb:L}=k("Bold (overrides Weight)"),{wrap:N,cb:T}=k("Italic"),j=document.createElement("div");j.style.cssText="display:flex;flex-direction:column;gap:.4rem;justify-content:flex-end;",j.appendChild(C),j.appendChild(N),x.appendChild(y(n("Weight",h),j)),x.appendChild(w("Appearance"));const B=a("e.g. primary, #ff0000"),P=c([["Georgia","Georgia (serif)"],["Arial","Arial (sans-serif)"],["Verdana","Verdana (sans-serif)"],["Courier New","Courier New (mono)"],["Times New Roman","Times New Roman (serif)"],["Trebuchet MS","Trebuchet MS"]]);x.appendChild(y(n("Colour",B),n("Font",P))),x.appendChild(w("Formatting"));const W=c([["upper","Uppercase"],["lower","Lowercase"],["capitalize","Capitalise"],["none","None"]]),A=c([["underline","Underline"],["line-through","Line-through"],["none","None"]]);x.appendChild(y(n("Transform",W),n("Decoration",A)));const H=c([["tight","Tight"],["normal","Normal"],["wide","Wide"],["wider","Wider"]]),R=c([["left","Left"],["center","Centre"],["right","Right"],["justify","Justify"]]);x.appendChild(y(n("Spacing",H),n("Align",R))),x.appendChild(w("Advanced"));const V=a("e.g. margin-top:1rem;display:block");x.appendChild(n("Style",V));const F=a("CSS class(es)"),G=a("ID");x.appendChild(y(n("Class",F),n("ID",G)));const K=document.createElement("div");K.style.cssText="padding:.75rem;background:var(--dm-surface-subtle,#111);border-radius:4px;min-height:2.5rem;display:flex;align-items:center;";const q=document.createElement("span");q.textContent=p||"Preview text",K.appendChild(q),x.appendChild(n("Preview",K));const Y={primary:"var(--dm-color-primary)",secondary:"var(--dm-color-secondary)",muted:"var(--dm-text-muted)",danger:"var(--dm-color-danger)",success:"var(--dm-color-success)",warning:"var(--dm-color-warning)",info:"var(--dm-color-info)"},ee={xs:".75rem",sm:".875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},te={thin:"100",light:"300",normal:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},ne={tight:"-0.05em",normal:"0em",wide:"0.05em",wider:"0.1em"},oe={Georgia:"Georgia,serif",Arial:"Arial,sans-serif",Verdana:"Verdana,sans-serif","Courier New":"'Courier New',monospace","Times New Roman":"'Times New Roman',serif","Trebuchet MS":"'Trebuchet MS',sans-serif"},ie={upper:"uppercase",lower:"lowercase",capitalize:"capitalize",none:"none"},re={underline:"underline","line-through":"line-through",none:"none"};L.addEventListener("change",()=>{h.disabled=L.checked,L.checked&&(h.value=""),_()}),[M,h,P,W,A,H,R].forEach(b=>{b.addEventListener("change",_)}),[B,S,V,v].forEach(b=>{b.addEventListener("input",_)}),T.addEventListener("change",_);const D=document.createElement("button");D.type="button",D.className="btn btn-primary",D.textContent="Insert",x.appendChild(D);const Z=E.slideover({title:"Style Text",size:"md",position:"right",content:x});Z.open(),D.addEventListener("click",()=>{const b=S.value;if(!b.trim())return;const u=[];M.value&&u.push(`size="${M.value}"`);const g=parseFloat(v.value);!isNaN(g)&&g>0&&u.push(`point-size="${g}"`),L.checked?u.push("bold"):h.value&&u.push(`weight="${h.value}"`),T.checked&&u.push("italic"),B.value.trim()&&u.push(`color="${B.value.trim()}"`),P.value&&u.push(`font="${P.value}"`),W.value&&u.push(`transform="${W.value}"`),A.value&&u.push(`decoration="${A.value}"`),H.value&&u.push(`spacing="${H.value}"`),R.value&&u.push(`align="${R.value}"`),V.value.trim()&&u.push(`style="${V.value.trim().replace(/"/g,""")}"`),F.value.trim()&&u.push(`class="${F.value.trim()}"`),G.value.trim()&&u.push(`id="${G.value.trim()}"`);const O=`[text${u.length?" "+u.join(" "):""}]${b}[/text]`;Z.close(),insertAtCursor(e,O),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}else t==="help"&&o.help&&o.help(e)}const Q=[{icon:"bold",title:"Bold (Ctrl+B)",action:t=>wrapSelection(t,"**","**")},{icon:"italic",title:"Italic (Ctrl+I)",action:t=>wrapSelection(t,"_","_")},{icon:"strikethrough",title:"Strikethrough",action:t=>wrapSelection(t,"~~","~~")},"|",{type:"dropdown",icon:"heading-1",title:"Headings",items:[{label:"Heading 1",icon:"heading-1",action:t=>insertLine(t,"# ")},{label:"Heading 2",icon:"heading-2",action:t=>insertLine(t,"## ")},{label:"Heading 3",icon:"heading-3",action:t=>insertLine(t,"### ")}]},"|",{icon:"list-bullet",title:"Bullet list",action:t=>insertLine(t,"- ")},{icon:"list-numbered",title:"Numbered list",action:t=>insertLine(t,"1. ")},"|",{type:"dropdown",icon:"quote",title:"Paragraph",items:[{label:"Blockquote",icon:"quote",action:t=>insertLine(t,"> ")},{label:"Horizontal rule",icon:"minus-circle",action:t=>insertAtCursor(t,`
|
|
45
45
|
---
|
|
46
|
-
`)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:t=>wrapSelection(t,"`","`")},{label:"Code block",icon:"code-block",action:t=>wrapSelection(t,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",items:[{label:"Accordion",icon:"accordion-insert",action:"accordion"},{label:"Banner",icon:"banner-insert",action:"banner"},{label:"Badge",icon:"badge",action:"badge"},{label:"Block",icon:"layout",action:"block"},{label:"Button",icon:"btn-insert",action:"button"},{label:"Card",icon:"card",action:"card"},{label:"Colour Picker",icon:"colour-picker",action:"colourpick"},{label:"Collection",icon:"database",action:"collection"},{label:"Component",icon:"component",action:"component"},{label:"CTA Button",icon:"mouse-pointer",action:"cta"},{label:"Form",icon:"file-text",action:"form"},{label:"Grid",icon:"columns",action:"grid"},{label:"Hero",icon:"hero",action:"hero"},{label:"Icon",icon:"icon-pick",action:"iconpick"},{label:"Image",icon:"image-add",action:"image"},{label:"Link",icon:"link-shortcode",action:"linksc"},{label:"List Group",icon:"list",action:"listgroup"},{label:"Scribe",icon:"scribe-insert",action:"scribe"},{label:"Spacer",icon:"spacer-insert",action:"spacerpick"},{label:"Tabs",icon:"layout-list",action:"tabs"},{label:"Text",icon:"text-style",action:"text"},{label:"Timeline",icon:"activity",action:"timeline"},{label:"View",icon:"eye",action:"view"}]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(t,e,m={}){se();const i={link:null,image:null,card:null,grid:null,help:null,effects:null,collection:null,view:null,cta:null,form:null,button:null,linksc:null,tabs:null,accordion:null,hero:null,banner:null},l=m.spacerDefault??40,o=t.get(0),r=e.get(0);r.textContent="",Q.forEach((n,c)=>{if(n==="|"){const a=document.createElement("span");a.className="editor-toolbar-sep",r.appendChild(a)}else{const a=document.createElement("button");a.className=n.type==="dropdown"?"editor-toolbar-btn editor-toolbar-dropdown-trigger":"editor-toolbar-btn",a.setAttribute("data-tooltip",n.title),a.setAttribute("data-idx",String(c)),a.type="button";const k=document.createElement("span");if(k.setAttribute("data-icon",n.icon),a.appendChild(k),n.type==="dropdown"){const y=document.createElement("span");y.className="editor-toolbar-caret",y.textContent="\u25BE",a.appendChild(y)}r.appendChild(a)}});const s=document.createElement("div");s.className="editor-toolbar-right",[{mode:"split",icon:"columns",label:"Split view",active:!0},{mode:"write",icon:"file-text",label:"Write only",active:!1},{mode:"preview",icon:"eye",label:"Preview only",active:!1}].forEach(n=>{const c=document.createElement("button");c.className="editor-view-btn"+(n.active?" active":""),c.setAttribute("data-mode",n.mode),c.setAttribute("data-tooltip",n.label),c.type="button";const a=document.createElement("span");a.setAttribute("data-icon",n.icon),c.appendChild(a),s.appendChild(c)});const p=document.createElement("span");p.className="editor-toolbar-sep",s.appendChild(p);const d=document.createElement("button");d.id="fullscreen-btn",d.className="editor-toolbar-btn",d.setAttribute("data-tooltip","Toggle fullscreen"),d.type="button";const f=document.createElement("span");return f.setAttribute("data-icon","expand"),d.appendChild(f),s.appendChild(d),r.appendChild(s),Domma.icons.scan(),r.querySelectorAll("[data-tooltip]").forEach(n=>{E.tooltip(n,{content:n.getAttribute("data-tooltip"),position:"top"})}),e.on("click",".editor-toolbar-btn[data-idx]",function(){const n=parseInt($(this).data("idx"),10),c=Q[n];if(!c||c==="|")return;const a=e.get(0).querySelector(`[data-idx="${n}"]`),k={spacerDefault:l,handlers:i};c.type==="dropdown"?ae(o,a,c.items,k):U(c.action,o,a,k)}),attachEditorKeybindings(o),o.addEventListener("keydown",n=>{const c=n.key.toLowerCase();(n.ctrlKey||n.metaKey)&&(c==="b"?(n.preventDefault(),wrapSelection(o,"**","**")):c==="i"?(n.preventDefault(),wrapSelection(o,"_","_")):c==="k"&&(n.preventDefault(),i.link&&i.link(o)))}),{$toolbar:e,onLink(n){i.link=n},onImage(n){i.image=n},onCard(n){i.card=n},onGrid(n){i.grid=n},onHelp(n){i.help=n},onEffects(n){i.effects=n},onCollection(n){i.collection=n},onBlock(n){i.block=n},onView(n){i.view=n},onCta(n){i.cta=n},onForm(n){i.form=n},onButton(n){i.button=n},onLinkShortcode(n){i.linksc=n},onTabs(n){i.tabs=n},onAccordion(n){i.accordion=n},onHero(n){i.hero=n},onBanner(n){i.banner=n},onListGroup(n){i.listgroup=n},onScribe(n){i.scribe=n},onTimeline(n){i.timeline=n}}}async function de(t){const{api:e}=await import("../api.js");let m;try{m=await e.components.list()}catch(v){E.toast(v.message||"Failed to load components.",{type:"error"});return}if(!m?.length){E.toast("No components yet. Create one in Data \u2192 Components first.",{type:"info"});return}const i=E.slideover({title:"Insert Component",size:"lg",position:"right"}),l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:1rem;padding:.75rem;min-height:100%;";const o=document.createElement("div");o.style.cssText="font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--dm-text-muted,#888);",o.textContent="Gallery";const r=document.createElement("div");r.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:.5rem;";const s=document.createElement("div");s.style.cssText="font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--dm-text-muted,#888);",s.textContent="Props";const p=document.createElement("div");p.style.cssText="padding:.6rem;border:1px solid var(--dm-border,rgba(255,255,255,.08));border-radius:4px;min-height:40px;",p.textContent="Select a component from the gallery above.";const d=document.createElement("div");d.style.cssText="font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--dm-text-muted,#888);",d.textContent="Preview";const f=document.createElement("iframe");f.src="/admin/preview/component-preview.html",f.style.cssText="width:100%;min-height:180px;border:1px solid var(--dm-border,rgba(255,255,255,.08));border-radius:4px;background:#fff;";const n=document.createElement("div");n.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,rgba(255,255,255,.08));";const c=document.createElement("button");c.className="btn btn-ghost",c.textContent="Cancel";const a=document.createElement("button");a.className="btn btn-primary",a.textContent="Insert",a.disabled=!0,n.appendChild(c),n.appendChild(a),l.appendChild(o),l.appendChild(r),l.appendChild(s),l.appendChild(p),l.appendChild(d),l.appendChild(f),l.appendChild(n),i.setContent(l),i.open();let k=null,y={};function C(){r.replaceChildren();for(const v of m){const h=document.createElement("button");h.type="button",h.className="btn btn-ghost",h.style.cssText="display:flex;flex-direction:column;align-items:flex-start;gap:.25rem;padding:.6rem;border:1px solid var(--dm-border,rgba(255,255,255,.08));border-radius:4px;text-align:left;";const w=document.createElement("strong");w.style.cssText="font-size:.9rem;",w.textContent=v.name;const L=document.createElement("span");L.style.cssText="font-size:.72rem;color:var(--dm-text-muted,#888);",L.textContent=`${Object.keys(v.props||{}).length} prop(s)`,h.appendChild(w),h.appendChild(L),h.addEventListener("click",()=>x(v)),r.appendChild(h)}}function x(v){k=v,y={};for(const[h,w]of Object.entries(v.props||{}))y[h]=w.default!==void 0?w.default:"";a.disabled=!1,S(),M()}function S(){p.replaceChildren();const v=Object.entries(k.props||{});if(v.length===0){const h=document.createElement("p");h.className="text-muted",h.style.margin="0",h.textContent="This component takes no props.",p.appendChild(h);return}for(const[h,w]of v){const L=document.createElement("div");L.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem;";const N=document.createElement("label");N.style.cssText="font-size:.8rem;min-width:120px;color:var(--dm-text-muted,#aaa);",N.textContent=w.label||h,L.appendChild(N);const T=ue(w);pe(T,w,y[h]),T.addEventListener("input",()=>{y[h]=X(T,w),f.contentWindow?.postMessage({type:"update",payload:{props:y}},"*")}),T.addEventListener("change",()=>{y[h]=X(T,w),f.contentWindow?.postMessage({type:"update",payload:{props:y}},"*")}),L.appendChild(T),p.appendChild(L)}}async function M(){if(k)try{const v=await fetch(`/api/components/${encodeURIComponent(k.name)}.js`);if(!v.ok)throw new Error(`Failed to load component (${v.status})`);const h=await v.text();f.contentWindow?.postMessage({type:"remount",payload:{compiledJs:h,tagName:`dm-${k.name}`,props:y}},"*")}catch(v){E.toast(v.message||"Failed to load preview.",{type:"error"})}}c.addEventListener("click",()=>i.close()),a.addEventListener("click",()=>{if(!k)return;const v=t.selectionStart,h=t.selectionEnd,w=Object.entries(y).map(([N,T])=>{const j=N.replace(/([A-Z])/g,"-$1").toLowerCase(),B=String(T??"").replace(/"/g,""");return`${j}="${B}"`}).join(" "),L=`[component name="${k.name}"${w?" "+w:""} /]`;t.value=t.value.substring(0,v)+L+t.value.substring(h),t.selectionStart=t.selectionEnd=v+L.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus(),i.close()}),C()}function ue(t){let e;return t.type==="number"?(e=document.createElement("input"),e.type="number",e.className="form-input form-input--sm"):t.type==="boolean"?(e=document.createElement("input"),e.type="checkbox",e.className="form-check"):t.type==="array"||t.type==="object"?(e=document.createElement("textarea"),e.rows=2,e.className="form-input form-input--sm",e.style.fontFamily="var(--dm-font-mono, monospace)"):(e=document.createElement("input"),e.type="text",e.className="form-input form-input--sm"),e.style.flex="1",e}function X(t,e){if(e.type==="number")return t.value===""?null:Number(t.value);if(e.type==="boolean")return!!t.checked;if(e.type==="array"||e.type==="object")try{return JSON.parse(t.value||"null")}catch{return null}return t.value}function pe(t,e,m){e.type==="boolean"?t.checked=!!m:e.type==="array"||e.type==="object"?t.value=JSON.stringify(m??null):t.value=m??""}
|
|
46
|
+
`)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:t=>wrapSelection(t,"`","`")},{label:"Code block",icon:"code-block",action:t=>wrapSelection(t,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",items:[{label:"Accordion",icon:"accordion-insert",action:"accordion"},{label:"Banner",icon:"banner-insert",action:"banner"},{label:"Badge",icon:"badge",action:"badge"},{label:"Block",icon:"layout",action:"block"},{label:"Button",icon:"btn-insert",action:"button"},{label:"Card",icon:"card",action:"card"},{label:"Carousel",icon:"carousel-insert",action:"carousel"},{label:"Colour Picker",icon:"colour-picker",action:"colourpick"},{label:"Collection",icon:"database",action:"collection"},{label:"Component",icon:"component",action:"component"},{label:"CTA Button",icon:"mouse-pointer",action:"cta"},{label:"Form",icon:"file-text",action:"form"},{label:"Grid",icon:"columns",action:"grid"},{label:"Hero",icon:"hero",action:"hero"},{label:"Icon",icon:"icon-pick",action:"iconpick"},{label:"Image",icon:"image-add",action:"image"},{label:"Link",icon:"link-shortcode",action:"linksc"},{label:"List Group",icon:"list",action:"listgroup"},{label:"Scribe",icon:"scribe-insert",action:"scribe"},{label:"Spacer",icon:"spacer-insert",action:"spacerpick"},{label:"Tabs",icon:"layout-list",action:"tabs"},{label:"Text",icon:"text-style",action:"text"},{label:"Timeline",icon:"activity",action:"timeline"},{label:"View",icon:"eye",action:"view"}]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(t,e,m={}){se();const i={link:null,image:null,card:null,grid:null,help:null,effects:null,collection:null,view:null,cta:null,form:null,button:null,linksc:null,tabs:null,accordion:null,carousel:null,hero:null,banner:null},l=m.spacerDefault??40,o=t.get(0),r=e.get(0);r.textContent="",Q.forEach((n,c)=>{if(n==="|"){const a=document.createElement("span");a.className="editor-toolbar-sep",r.appendChild(a)}else{const a=document.createElement("button");a.className=n.type==="dropdown"?"editor-toolbar-btn editor-toolbar-dropdown-trigger":"editor-toolbar-btn",a.setAttribute("data-tooltip",n.title),a.setAttribute("data-idx",String(c)),a.type="button";const k=document.createElement("span");if(k.setAttribute("data-icon",n.icon),a.appendChild(k),n.type==="dropdown"){const y=document.createElement("span");y.className="editor-toolbar-caret",y.textContent="\u25BE",a.appendChild(y)}r.appendChild(a)}});const s=document.createElement("div");s.className="editor-toolbar-right",[{mode:"split",icon:"columns",label:"Split view",active:!0},{mode:"write",icon:"file-text",label:"Write only",active:!1},{mode:"preview",icon:"eye",label:"Preview only",active:!1}].forEach(n=>{const c=document.createElement("button");c.className="editor-view-btn"+(n.active?" active":""),c.setAttribute("data-mode",n.mode),c.setAttribute("data-tooltip",n.label),c.type="button";const a=document.createElement("span");a.setAttribute("data-icon",n.icon),c.appendChild(a),s.appendChild(c)});const p=document.createElement("span");p.className="editor-toolbar-sep",s.appendChild(p);const d=document.createElement("button");d.id="fullscreen-btn",d.className="editor-toolbar-btn",d.setAttribute("data-tooltip","Toggle fullscreen"),d.type="button";const f=document.createElement("span");return f.setAttribute("data-icon","expand"),d.appendChild(f),s.appendChild(d),r.appendChild(s),Domma.icons.scan(),r.querySelectorAll("[data-tooltip]").forEach(n=>{E.tooltip(n,{content:n.getAttribute("data-tooltip"),position:"top"})}),e.on("click",".editor-toolbar-btn[data-idx]",function(){const n=parseInt($(this).data("idx"),10),c=Q[n];if(!c||c==="|")return;const a=e.get(0).querySelector(`[data-idx="${n}"]`),k={spacerDefault:l,handlers:i};c.type==="dropdown"?ae(o,a,c.items,k):U(c.action,o,a,k)}),attachEditorKeybindings(o),o.addEventListener("keydown",n=>{const c=n.key.toLowerCase();(n.ctrlKey||n.metaKey)&&(c==="b"?(n.preventDefault(),wrapSelection(o,"**","**")):c==="i"?(n.preventDefault(),wrapSelection(o,"_","_")):c==="k"&&(n.preventDefault(),i.link&&i.link(o)))}),{$toolbar:e,onLink(n){i.link=n},onImage(n){i.image=n},onCard(n){i.card=n},onGrid(n){i.grid=n},onHelp(n){i.help=n},onEffects(n){i.effects=n},onCollection(n){i.collection=n},onBlock(n){i.block=n},onView(n){i.view=n},onCta(n){i.cta=n},onForm(n){i.form=n},onButton(n){i.button=n},onLinkShortcode(n){i.linksc=n},onTabs(n){i.tabs=n},onCarousel(n){i.carousel=n},onAccordion(n){i.accordion=n},onHero(n){i.hero=n},onBanner(n){i.banner=n},onListGroup(n){i.listgroup=n},onScribe(n){i.scribe=n},onTimeline(n){i.timeline=n}}}async function de(t){const{api:e}=await import("../api.js");let m;try{m=await e.components.list()}catch(v){E.toast(v.message||"Failed to load components.",{type:"error"});return}if(!m?.length){E.toast("No components yet. Create one in Data \u2192 Components first.",{type:"info"});return}const i=E.slideover({title:"Insert Component",size:"lg",position:"right"}),l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:1rem;padding:.75rem;min-height:100%;";const o=document.createElement("div");o.style.cssText="font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--dm-text-muted,#888);",o.textContent="Gallery";const r=document.createElement("div");r.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:.5rem;";const s=document.createElement("div");s.style.cssText="font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--dm-text-muted,#888);",s.textContent="Props";const p=document.createElement("div");p.style.cssText="padding:.6rem;border:1px solid var(--dm-border,rgba(255,255,255,.08));border-radius:4px;min-height:40px;",p.textContent="Select a component from the gallery above.";const d=document.createElement("div");d.style.cssText="font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--dm-text-muted,#888);",d.textContent="Preview";const f=document.createElement("iframe");f.src="/admin/preview/component-preview.html",f.style.cssText="width:100%;min-height:180px;border:1px solid var(--dm-border,rgba(255,255,255,.08));border-radius:4px;background:#fff;";const n=document.createElement("div");n.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,rgba(255,255,255,.08));";const c=document.createElement("button");c.className="btn btn-ghost",c.textContent="Cancel";const a=document.createElement("button");a.className="btn btn-primary",a.textContent="Insert",a.disabled=!0,n.appendChild(c),n.appendChild(a),l.appendChild(o),l.appendChild(r),l.appendChild(s),l.appendChild(p),l.appendChild(d),l.appendChild(f),l.appendChild(n),i.setContent(l),i.open();let k=null,y={};function w(){r.replaceChildren();for(const v of m){const h=document.createElement("button");h.type="button",h.className="btn btn-ghost",h.style.cssText="display:flex;flex-direction:column;align-items:flex-start;gap:.25rem;padding:.6rem;border:1px solid var(--dm-border,rgba(255,255,255,.08));border-radius:4px;text-align:left;";const C=document.createElement("strong");C.style.cssText="font-size:.9rem;",C.textContent=v.name;const L=document.createElement("span");L.style.cssText="font-size:.72rem;color:var(--dm-text-muted,#888);",L.textContent=`${Object.keys(v.props||{}).length} prop(s)`,h.appendChild(C),h.appendChild(L),h.addEventListener("click",()=>x(v)),r.appendChild(h)}}function x(v){k=v,y={};for(const[h,C]of Object.entries(v.props||{}))y[h]=C.default!==void 0?C.default:"";a.disabled=!1,S(),M()}function S(){p.replaceChildren();const v=Object.entries(k.props||{});if(v.length===0){const h=document.createElement("p");h.className="text-muted",h.style.margin="0",h.textContent="This component takes no props.",p.appendChild(h);return}for(const[h,C]of v){const L=document.createElement("div");L.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem;";const N=document.createElement("label");N.style.cssText="font-size:.8rem;min-width:120px;color:var(--dm-text-muted,#aaa);",N.textContent=C.label||h,L.appendChild(N);const T=ue(C);pe(T,C,y[h]),T.addEventListener("input",()=>{y[h]=X(T,C),f.contentWindow?.postMessage({type:"update",payload:{props:y}},"*")}),T.addEventListener("change",()=>{y[h]=X(T,C),f.contentWindow?.postMessage({type:"update",payload:{props:y}},"*")}),L.appendChild(T),p.appendChild(L)}}async function M(){if(k)try{const v=await fetch(`/api/components/${encodeURIComponent(k.name)}.js`);if(!v.ok)throw new Error(`Failed to load component (${v.status})`);const h=await v.text();f.contentWindow?.postMessage({type:"remount",payload:{compiledJs:h,tagName:`dm-${k.name}`,props:y}},"*")}catch(v){E.toast(v.message||"Failed to load preview.",{type:"error"})}}c.addEventListener("click",()=>i.close()),a.addEventListener("click",()=>{if(!k)return;const v=t.selectionStart,h=t.selectionEnd,C=Object.entries(y).map(([N,T])=>{const j=N.replace(/([A-Z])/g,"-$1").toLowerCase(),B=String(T??"").replace(/"/g,""");return`${j}="${B}"`}).join(" "),L=`[component name="${k.name}"${C?" "+C:""} /]`;t.value=t.value.substring(0,v)+L+t.value.substring(h),t.selectionStart=t.selectionEnd=v+L.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus(),i.close()}),w()}function ue(t){let e;return t.type==="number"?(e=document.createElement("input"),e.type="number",e.className="form-input form-input--sm"):t.type==="boolean"?(e=document.createElement("input"),e.type="checkbox",e.className="form-check"):t.type==="array"||t.type==="object"?(e=document.createElement("textarea"),e.rows=2,e.className="form-input form-input--sm",e.style.fontFamily="var(--dm-font-mono, monospace)"):(e=document.createElement("input"),e.type="text",e.className="form-input form-input--sm"),e.style.flex="1",e}function X(t,e){if(e.type==="number")return t.value===""?null:Number(t.value);if(e.type==="boolean")return!!t.checked;if(e.type==="array"||e.type==="object")try{return JSON.parse(t.value||"null")}catch{return null}return t.value}function pe(t,e,m){e.type==="boolean"?t.checked=!!m:e.type==="array"||e.type==="object"?t.value=JSON.stringify(m??null):t.value=m??""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<div class="dash-card-header">
|
|
2
|
+
<h3>Response Cache</h3>
|
|
3
|
+
<label class="dash-cache-toggle" title="Enable / disable cache">
|
|
4
|
+
<input type="checkbox" data-field="toggle">
|
|
5
|
+
<span data-field="toggle-label">…</span>
|
|
6
|
+
</label>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="dash-cache-grid">
|
|
9
|
+
<div class="dash-cache-stat">
|
|
10
|
+
<div class="dash-cache-stat-label">Hit rate</div>
|
|
11
|
+
<div class="dash-cache-stat-value" data-field="hit-rate">—</div>
|
|
12
|
+
<div class="dash-cache-stat-sub" data-field="hits-misses">no traffic yet</div>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="dash-cache-stat">
|
|
15
|
+
<div class="dash-cache-stat-label">Entries</div>
|
|
16
|
+
<div class="dash-cache-stat-value" data-field="size">—</div>
|
|
17
|
+
<div class="dash-cache-stat-sub" data-field="size-bar"><span data-field="size-fill"></span></div>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="dash-cache-stat">
|
|
20
|
+
<div class="dash-cache-stat-label">Writes</div>
|
|
21
|
+
<div class="dash-cache-stat-value" data-field="writes">0</div>
|
|
22
|
+
<div class="dash-cache-stat-sub" data-field="invalidations">0 invalidations</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="dash-cache-stat">
|
|
25
|
+
<div class="dash-cache-stat-label">Last cleared</div>
|
|
26
|
+
<div class="dash-cache-stat-value" data-field="last-cleared">never</div>
|
|
27
|
+
<div class="dash-cache-stat-sub" data-field="driver">driver: —</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="dash-cache-actions">
|
|
31
|
+
<button class="btn btn-sm btn-ghost" data-field="clear-btn"><span data-icon="trash"></span> Clear cache</button>
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<h3>User journeys — last 7 days</h3>
|
|
2
|
+
<div class="dash-journey-grid">
|
|
3
|
+
<div>
|
|
4
|
+
<h4>Top entry pages</h4>
|
|
5
|
+
<div data-field="entry"></div>
|
|
6
|
+
</div>
|
|
7
|
+
<div>
|
|
8
|
+
<h4>Top exit pages</h4>
|
|
9
|
+
<div data-field="exit"></div>
|
|
10
|
+
</div>
|
|
11
|
+
<div>
|
|
12
|
+
<h4>Top paths</h4>
|
|
13
|
+
<div data-field="paths"></div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
<p class="dash-bounce">Bounce rate: <strong data-field="bounce">—</strong></p>
|
|
17
|
+
<p class="dash-empty" hidden>No journey data yet — encourage some traffic and check back.</p>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<div class="dash-card dash-kpi">
|
|
2
|
+
<span class="dash-kpi-icon" data-icon="trending-up"></span>
|
|
3
|
+
<div>
|
|
4
|
+
<div class="dash-kpi-value" data-field="hits-today">—</div>
|
|
5
|
+
<div class="dash-kpi-label">Hits today</div>
|
|
6
|
+
<div class="dash-kpi-delta" data-field="hits-delta"></div>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="dash-card dash-kpi">
|
|
10
|
+
<span class="dash-kpi-icon" data-icon="users"></span>
|
|
11
|
+
<div>
|
|
12
|
+
<div class="dash-kpi-value" data-field="active-sessions">—</div>
|
|
13
|
+
<div class="dash-kpi-label">Active sessions (5m)</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="dash-card dash-kpi">
|
|
17
|
+
<span class="dash-kpi-icon" data-icon="inbox"></span>
|
|
18
|
+
<div>
|
|
19
|
+
<div class="dash-kpi-value" data-field="submissions-week">—</div>
|
|
20
|
+
<div class="dash-kpi-label">Submissions this week</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="dash-card dash-kpi">
|
|
24
|
+
<span class="dash-kpi-icon" data-icon="activity"></span>
|
|
25
|
+
<div>
|
|
26
|
+
<div class="dash-kpi-value">
|
|
27
|
+
<span class="dash-health-pill" data-field="health-pill" data-level="ok">
|
|
28
|
+
<span data-icon="circle"></span>
|
|
29
|
+
<span data-field="health-label">OK</span>
|
|
30
|
+
</span>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="dash-kpi-label">Site health</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
@@ -1,50 +1,32 @@
|
|
|
1
1
|
<div class="view-header">
|
|
2
2
|
<h1><span data-icon="home"></span> Dashboard</h1>
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<div class="row mb-4">
|
|
7
|
-
<div class="col-4">
|
|
8
|
-
<div class="card stat-card">
|
|
9
|
-
<div class="card-body">
|
|
10
|
-
<div class="stat-icon"><span data-icon="file-text"></span></div>
|
|
11
|
-
<div class="stat-body">
|
|
12
|
-
<div class="stat-value" id="stat-total">—</div>
|
|
13
|
-
<div class="stat-label">Total Pages</div>
|
|
14
|
-
</div>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="col-4">
|
|
19
|
-
<div class="card stat-card">
|
|
20
|
-
<div class="card-body">
|
|
21
|
-
<div class="stat-icon stat-icon--success"><span data-icon="check-circle"></span></div>
|
|
22
|
-
<div class="stat-body">
|
|
23
|
-
<div class="stat-value" id="stat-published">—</div>
|
|
24
|
-
<div class="stat-label">Published</div>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
<div class="col-4">
|
|
30
|
-
<div class="card stat-card">
|
|
31
|
-
<div class="card-body">
|
|
32
|
-
<div class="stat-icon stat-icon--warning"><span data-icon="clock"></span></div>
|
|
33
|
-
<div class="stat-body">
|
|
34
|
-
<div class="stat-value" id="stat-drafts">—</div>
|
|
35
|
-
<div class="stat-label">Drafts</div>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
3
|
+
<div class="view-header-actions">
|
|
4
|
+
<span class="dash-updated" id="dash-updated"></span>
|
|
5
|
+
<a href="#/pages/new" class="btn btn-primary"><span data-icon="plus"></span> New Page</a>
|
|
39
6
|
</div>
|
|
40
7
|
</div>
|
|
41
8
|
|
|
42
|
-
<div
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
<
|
|
48
|
-
<div id="
|
|
49
|
-
|
|
9
|
+
<div id="dash-warnings" class="dash-warnings" hidden></div>
|
|
10
|
+
|
|
11
|
+
<div class="dashboard-grid">
|
|
12
|
+
<section id="dash-kpi-strip" class="dash-row dash-row-kpi"></section>
|
|
13
|
+
|
|
14
|
+
<section class="dash-row dash-row-traffic">
|
|
15
|
+
<div id="dash-traffic-chart" class="dash-card dash-card-wide"></div>
|
|
16
|
+
<div id="dash-spike-feed" class="dash-card"></div>
|
|
17
|
+
</section>
|
|
18
|
+
|
|
19
|
+
<section class="dash-row dash-row-content">
|
|
20
|
+
<div id="dash-top-pages" class="dash-card"></div>
|
|
21
|
+
<div id="dash-journeys" class="dash-card"></div>
|
|
22
|
+
</section>
|
|
23
|
+
|
|
24
|
+
<section class="dash-row dash-row-health">
|
|
25
|
+
<div id="dash-health-detail" class="dash-card"></div>
|
|
26
|
+
<div id="dash-activity-feed" class="dash-card"></div>
|
|
27
|
+
</section>
|
|
28
|
+
|
|
29
|
+
<section class="dash-row">
|
|
30
|
+
<div id="dash-cache" class="dash-card dash-card-wide"></div>
|
|
31
|
+
</section>
|
|
50
32
|
</div>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
<button class="tab-item">Cookie Consent</button>
|
|
14
14
|
<button class="tab-item">Breadcrumbs</button>
|
|
15
15
|
<button class="tab-item">Custom CSS</button>
|
|
16
|
+
<button class="tab-item">Cache</button>
|
|
16
17
|
</div>
|
|
17
18
|
<div class="tab-content">
|
|
18
19
|
|
|
@@ -502,5 +503,30 @@
|
|
|
502
503
|
</div>
|
|
503
504
|
</div>
|
|
504
505
|
|
|
506
|
+
<!-- Cache -->
|
|
507
|
+
<div class="tab-panel">
|
|
508
|
+
<div class="row mb-3">
|
|
509
|
+
<div class="col">
|
|
510
|
+
<p class="text-muted" style="font-size:.875rem;margin-bottom:1rem;">
|
|
511
|
+
Status: <strong id="cache-status">checking…</strong>
|
|
512
|
+
</p>
|
|
513
|
+
<p class="text-muted" style="font-size:.875rem;margin-bottom:1rem;">
|
|
514
|
+
Public page renders are cached by URL and role. Writes (page, collection, form, block, view, navigation, site settings) auto-invalidate the relevant tags. Use the button below to flush every cached entry — the next visitor to each page will trigger a fresh render.
|
|
515
|
+
</p>
|
|
516
|
+
<button id="btn-clear-cache" class="btn btn-secondary" type="button"><span data-icon="trash"></span> Clear cache</button>
|
|
517
|
+
<button id="btn-refresh-cache-keys" class="btn btn-ghost" type="button" style="margin-left:8px;"><span data-icon="refresh"></span> Refresh list</button>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
<div class="row">
|
|
521
|
+
<div class="col">
|
|
522
|
+
<h4 style="margin-top:1.5rem;">Cached entries <span id="cache-key-count" class="text-muted" style="font-weight:normal;font-size:.875rem;"></span></h4>
|
|
523
|
+
<p class="text-muted" style="font-size:.85rem;margin-bottom:.5rem;">
|
|
524
|
+
Snapshot of what's currently keyed. Newest entries first. Values are not shown — they can be large HTML blobs.
|
|
525
|
+
</p>
|
|
526
|
+
<div id="cache-keys-table"></div>
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
530
|
+
|
|
505
531
|
</div>
|
|
506
532
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{blockEditorView as r}from"./block-editor.js
|
|
1
|
+
import{blockEditorView as r}from"./block-editor.js";import{createSimpleEditor as u}from"../lib/simple-editor.js";const p=r.onMount;r.onMount=async function(e){await p.call(this,e);const n=e.find(".editor-pane--write").get(0),l=e.find("#block-line-numbers").get(0),t=e.find("#block-content").get(0);if(!n||!t||n.dataset.dmEnhanced==="1")return;n.dataset.dmEnhanced="1",l&&(l.style.display="none"),t.style.display="none",n.style.display="block",n.style.position="relative",n.style.overflow="hidden";const i=document.createElement("div");i.style.cssText="width:100%;height:100%;",n.appendChild(i);const a=u(i,{initialValue:t.value,onChange:o=>{t.value!==o&&(t.value=o,t.dispatchEvent(new Event("input",{bubbles:!0})))}}),d=Object.getPrototypeOf(t),c=Object.getOwnPropertyDescriptor(d,"value");Object.defineProperty(t,"value",{configurable:!0,get(){return c.get.call(this)},set(o){c.set.call(this,o),a.getValue()!==o&&a.setValue(o??"")}});const s=e.find(".card.editor-card").get(0);s&&(s.style.height="min(78vh, 900px)",s.style.minHeight="520px"),g(e)};const f={icon:"box","facebook-icon":"facebook","instagram-icon":"instagram"};function g(e){const n=e.get?e.get(0):e;if(!n)return;const l=n.querySelectorAll("input[data-placeholder]");for(const t of l){const i=(t.dataset.placeholder||"").toLowerCase(),a=f[i];a&&(t.value&&!/^Sample /i.test(t.value)||(t.value=a,t.dispatchEvent(new Event("input",{bubbles:!0}))))}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function escapeHtml(t){return t==null?"":String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}export function safeHref(t){if(t==null)return"#";const r=String(t).trim();if(r==="")return"#";if(r.startsWith("/"))return escapeHtml(r);const e=r.toLowerCase();return e.startsWith("http://")||e.startsWith("https://")||e.startsWith("mailto:")?escapeHtml(r):"#"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{escapeHtml as s}from"../lib/escape.js";const p={edit:"edited",publish:"published",form:"received submission"};function f(e,n){e&&(e.innerHTML=n)}export default function m(e,n){const r=Array.isArray(n?.activity)?n.activity:[];r.length===0?e.find(".dash-empty").removeAttr("hidden"):e.find(".dash-empty").attr("hidden","hidden");const i=r.map(t=>{const o=t.at?D(t.at).fromNow():"",a=t.target||t.form||"",d=t.actor?"<strong>"+s(t.actor)+"</strong> ":"",c=s(p[t.type]||t.type||"");return'<div class="dash-spike-row"><span>'+d+c+" <code>"+s(a)+"</code></span><span>"+s(o)+"</span></div>"});f(e.find('[data-field="rows"]').get(0),i.join(""))}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{apiRequest as r}from"../../../api.js";function h(t){if(!t)return"never";const e=Date.now()-new Date(t).getTime();if(e<0)return"just now";const a=Math.floor(e/1e3);if(a<60)return`${a}s ago`;const i=Math.floor(a/60);if(i<60)return`${i}m ago`;const n=Math.floor(i/60);return n<24?`${n}h ago`:`${Math.floor(n/24)}d ago`}function d(t,e){const a=e.hits+e.misses,i=e.hitRate;t.find('[data-field="hit-rate"]').text(i===null?"\u2014":(i*100).toFixed(1)+"%"),t.find('[data-field="hits-misses"]').text(a===0?"no traffic yet":`${e.hits.toLocaleString()} hits \xB7 ${e.misses.toLocaleString()} misses`);const n=e.size??0,c=e.maxItems??0;t.find('[data-field="size"]').text(c?`${n} / ${c}`:String(n));const l=c?Math.min(100,n/c*100):0,o=t.find('[data-field="size-fill"]').get(0);o&&(o.style.width=l+"%"),t.find('[data-field="writes"]').text(e.writes.toLocaleString()),t.find('[data-field="invalidations"]').text(`${e.invalidations.toLocaleString()} invalidations`),t.find('[data-field="last-cleared"]').text(h(e.lastClearedAt)),t.find('[data-field="driver"]').text("driver: "+e.driver);const f=t.find('[data-field="toggle"]').get(0);f&&(f.checked=!!e.enabled),t.find('[data-field="toggle-label"]').text(e.enabled?"On":"Off")}async function s(t){try{const e=await r("/cache/status");d(t,e),t.data("cache-stats",e)}catch(e){console.warn("[cache widget] failed to refresh:",e)}}export default async function g(t){await s(t);const e=t.find('[data-field="toggle"]');e.on("change",async()=>{const a=e.get(0).checked;try{const i=await r("/cache/toggle",{method:"POST",body:JSON.stringify({enabled:a})});d(t,i),E.toast(`Cache ${i.enabled?"enabled":"disabled"}.`,{type:"success"})}catch(i){e.get(0).checked=!a,E.toast(i.message||"Failed to toggle cache.",{type:"error"})}}),t.find('[data-field="clear-btn"]').on("click",async()=>{if(await E.confirm("Clear the entire response cache?"))try{const a=await r("/cache/clear",{method:"POST"});d(t,a),E.toast("Cache cleared.",{type:"success"})}catch(a){E.toast(a.message||"Failed to clear cache.",{type:"error"})}}),window.Domma&&Domma.icons&&Domma.icons.scan()}export{s as refreshCacheWidget};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const p={ok:"check-circle",warn:"alert-triangle",fail:"x-circle"};export default function h(o,s){const r=s?.health?.checks||[],c=o.find('[data-field="rows"]');c.empty();const a=c.get(0);if(a){for(const e of r){const n=document.createElement("div");n.className="dash-spike-row dash-health-pill",n.setAttribute("data-level",e.level);const l=document.createElement("span"),i=document.createElement("span");i.setAttribute("data-icon",p[e.level]||"circle"),l.appendChild(i),l.appendChild(document.createTextNode(" "+(e.label||e.id)));const d=document.createElement("span");if(d.textContent=String(e.value),n.appendChild(l),n.appendChild(d),a.appendChild(n),Array.isArray(e.detail)&&e.detail.length>0){const t=document.createElement("div");t.className="dash-health-detail",t.style.fontSize="12px",t.style.opacity="0.75",t.style.padding="4px 0 8px",t.textContent=e.detail.slice(0,5).join(", "),a.appendChild(t)}}window.Domma&&Domma.icons&&Domma.icons.scan()}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{escapeHtml as r}from"../lib/escape.js";function s(n,a){return n.map(e=>'<div class="dash-spike-row">'+a(e)+"</div>").join("")}function i(n,a){n&&(n.innerHTML=a)}export default function f(n,a){const e=a?.journeys,d=n.find(".dash-empty"),o=n.find('[data-field="entry"]'),p=n.find('[data-field="exit"]'),u=n.find('[data-field="paths"]'),c=n.find('[data-field="bounce"]');if(!e||!e.totalSessions){d.removeAttr("hidden"),o.empty(),p.empty(),u.empty(),c.text("\u2014");return}d.attr("hidden","hidden"),i(o.get(0),s(e.entry||[],t=>"<span>"+r(t.url)+"</span><span>"+(Number(t.count)|0)+"</span>")),i(p.get(0),s(e.exit||[],t=>"<span>"+r(t.url)+"</span><span>"+(Number(t.count)|0)+"</span>")),i(u.get(0),s(e.paths||[],t=>"<span>"+r(t.from)+" → "+r(t.to)+"</span><span>"+(Number(t.count)|0)+"</span>")),c.text((Number(e.bounceRate)*100).toFixed(1)+"%")}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function n(e,t){const d=t?.traffic?.today??0,a=t?.traffic?.deltaPct;e.find('[data-field="hits-today"]').text(d);const s=e.find('[data-field="hits-delta"]');a==null?s.text("").removeClass("up down"):a>=0?s.text("+"+a+"% vs yesterday").removeClass("down").addClass("up"):s.text(a+"% vs yesterday").removeClass("up").addClass("down"),e.find('[data-field="active-sessions"]').text(t?.realtime?.activeSessions??0),e.find('[data-field="submissions-week"]').text(t?._submissionsWeek??"\u2014");const i=t?.health?.status||"ok",l={ok:"OK",warn:"Attention",fail:"Failing"};e.find('[data-field="health-pill"]').attr("data-level",i),e.find('[data-field="health-label"]').text(l[i])}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{escapeHtml as a,safeHref as d}from"../lib/escape.js";export default function p(i,r){const t=Array.isArray(r?.spikes)?r.spikes:[];t.length===0?i.find(".dash-empty").removeAttr("hidden"):i.find(".dash-empty").attr("hidden","hidden");const s=t.map(e=>`
|
|
2
|
+
<div class="dash-spike-row">
|
|
3
|
+
<span><a href="${d(e.url)}">${a(e.url)}</a></span>
|
|
4
|
+
<span><strong>${Number(e.hits)|0}</strong> \xB7 \xD7${Number(e.ratio)||0}</span>
|
|
5
|
+
</div>
|
|
6
|
+
`).join(""),n=i.find('[data-field="spike-list"]').get(0);n&&(n.innerHTML=s)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{escapeHtml as l,safeHref as i}from"../lib/escape.js";function c(n,s,e){if(s=s||80,e=e||24,!n||n.length===0)return"";const a=n.map(p=>Number(p)||0),o=Math.max.apply(null,a.concat([1])),t=s/Math.max(a.length-1,1),r=a.map((p,d)=>(d*t).toFixed(1)+","+(e-p/o*e).toFixed(1)).join(" ");return'<svg class="dash-spark" viewBox="0 0 '+s+" "+e+'" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"><polyline fill="none" stroke="currentColor" stroke-width="1.5" points="'+r+'"/></svg>'}export default function m(n,s){const e=Array.isArray(s?.topPages)?s.topPages:[];e.length===0?n.find(".dash-empty").removeAttr("hidden"):n.find(".dash-empty").attr("hidden","hidden");const a=e.map(t=>{const r=t.deltaPct==null?"":'<span class="'+(t.deltaPct>=0?"up":"down")+' dash-kpi-delta">'+(t.deltaPct>=0?"+":"")+(Number(t.deltaPct)||0)+"%</span>";return'<div class="dash-spike-row"><span><a href="'+i(t.url)+'">'+l(t.url)+"</a> "+c(t.spark)+"</span><span><strong>"+(Number(t.hits)|0)+"</strong> "+r+"</span></div>"}).join(""),o=n.find('[data-field="rows"]').get(0);o&&(o.innerHTML=a)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const p="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.js";let s=null;function u(){return window.Chart?Promise.resolve(window.Chart):s||(s=new Promise((r,n)=>{const e=document.createElement("script");e.src=p,e.onload=()=>r(window.Chart),e.onerror=n,document.head.appendChild(e)}),s)}let i=null;export default async function m(r,n){const e=await u(),o=30,a=[];for(let t=o-1;t>=0;t-=1)a.push({label:D().subtract(t,"days").format("MM-DD"),hits:0});if(Array.isArray(n?.topPages))for(const t of n.topPages){if(!Array.isArray(t.spark))continue;const l=o-t.spark.length;t.spark.forEach((f,h)=>{a[l+h].hits+=f})}const d=a.every(t=>t.hits===0);d?r.find(".dash-empty").removeAttr("hidden"):r.find(".dash-empty").attr("hidden","hidden");const c=r.find("#dash-traffic-canvas").get(0);c&&(i&&(i.destroy(),i=null),!d&&(i=new e(c,{type:"line",data:{labels:a.map(t=>t.label),datasets:[{data:a.map(t=>t.hits),borderColor:"rgba(37, 99, 235, 1)",backgroundColor:"rgba(37, 99, 235, 0.15)",fill:!0,tension:.3,pointRadius:0}]},options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:!1}},scales:{x:{ticks:{maxTicksLimit:8}},y:{beginAtZero:!0}}}})))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{api as n}from"../api.js";
|
|
1
|
+
import{api as n}from"../api.js";import l from"./dashboard/widgets/kpi-strip.js";import c from"./dashboard/widgets/traffic-chart.js";import m from"./dashboard/widgets/spike-feed.js";import u from"./dashboard/widgets/top-pages.js";import y from"./dashboard/widgets/journeys.js";import b from"./dashboard/widgets/health-detail.js";import g from"./dashboard/widgets/activity-feed.js";import w,{refreshCacheWidget as k}from"./dashboard/widgets/cache.js";const o=[{slot:"#dash-kpi-strip",template:"/admin/js/templates/dashboard/kpi-strip.html",render:l},{slot:"#dash-traffic-chart",template:"/admin/js/templates/dashboard/traffic-chart.html",render:c},{slot:"#dash-spike-feed",template:"/admin/js/templates/dashboard/spike-feed.html",render:m},{slot:"#dash-top-pages",template:"/admin/js/templates/dashboard/top-pages.html",render:u},{slot:"#dash-journeys",template:"/admin/js/templates/dashboard/journeys.html",render:y},{slot:"#dash-health-detail",template:"/admin/js/templates/dashboard/health-detail.html",render:b},{slot:"#dash-activity-feed",template:"/admin/js/templates/dashboard/activity-feed.html",render:g},{slot:"#dash-cache",template:"/admin/js/templates/dashboard/cache.html",render:w}],j=30*1e3;async function v(t){const a=await fetch(t,{credentials:"same-origin"});if(!a.ok)throw new Error(`Failed to load ${t}: ${a.status}`);return a.text()}function S(t,a){t.length&&(t.get(0).innerHTML=a)}function C(t,a){const s=t.find("#dash-warnings");if(!a||a.length===0){s.attr("hidden","hidden");return}s.removeAttr("hidden"),s.get(0).textContent="Some sections could not load: "+a.join(" \xB7 ")}function h(t){t.find("#dash-updated").text("Updated "+D().format("HH:mm:ss"))}function f(t){if(!t||!Array.isArray(t.activity))return t;const a=D().subtract(7,"days").valueOf();return t._submissionsWeek=t.activity.filter(s=>s.type==="form"&&D(s.at).valueOf()>=a).length,t}let i=null;export const dashboardView={templateUrl:"/admin/js/templates/dashboard.html",async onMount(t){const a=E.loader(t.get(0),{type:"dots"}),s=await Promise.all(o.map(e=>v(e.template)));o.forEach((e,d)=>{S(t.find(e.slot),s[d])});let r;try{r=await n.dashboard.summary(),r=f(r)}catch(e){a.destroy();const d=t.find("#dash-warnings");d.removeAttr("hidden"),d.get(0).textContent="Could not load dashboard: "+e.message;return}for(const e of o){const d=t.find(e.slot);try{await e.render(d,r)}catch(p){console.warn("[dashboard]",e.slot,"render failed:",p)}}C(t,r.warnings),h(t),Domma.icons.scan(),a.destroy(),i&&clearInterval(i),i=setInterval(async()=>{if(!document.body.contains(t.get(0))){clearInterval(i),i=null;return}try{const e=await n.dashboard.summaryLite();e.traffic&&(r.traffic={...r.traffic,...e.traffic}),e.realtime&&(r.realtime=e.realtime),e.spikes&&(r.spikes=e.spikes),e.health&&(r.health={...r.health,status:e.health.status}),f(r),await l(t.find("#dash-kpi-strip"),r),await m(t.find("#dash-spike-feed"),r),k(t.find("#dash-cache")).catch(()=>{}),h(t)}catch(e){console.warn("[dashboard] lite refresh failed:",e)}},j)}};
|