domma-cms 0.36.1 → 0.36.2
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/admin/css/admin.css +1 -1
- package/admin/css/dashboard.css +1 -1
- package/admin/js/lib/card-builder.js +1 -1
- package/admin/js/lib/effects-builder.js +2 -2
- package/admin/js/lib/embed-builder.js +1 -1
- package/admin/js/lib/markdown-toolbar.js +2 -2
- package/admin/js/lib/project-quick-create.js +2 -2
- package/admin/js/lib/scribe-composer.js +3 -3
- package/admin/js/lib/shortcode-context-menu.js +6 -6
- package/admin/js/lib/shortcode-modal.js +1 -1
- package/admin/js/lib/sidebar-renderer.js +2 -2
- package/admin/js/lib/timeline-builder.js +2 -2
- package/admin/js/templates/api-endpoint-editor.html +2 -2
- package/admin/js/templates/block-editor.html +1 -1
- package/admin/js/templates/component-editor.html +4 -4
- package/admin/js/templates/docs/api-actions.html +11 -11
- package/admin/js/templates/docs/api-authentication.html +11 -11
- package/admin/js/templates/docs/api-collections.html +11 -11
- package/admin/js/templates/docs/api-layouts.html +11 -11
- package/admin/js/templates/docs/api-media.html +11 -11
- package/admin/js/templates/docs/api-navigation.html +11 -11
- package/admin/js/templates/docs/api-pages.html +11 -11
- package/admin/js/templates/docs/api-plugins.html +11 -11
- package/admin/js/templates/docs/api-settings.html +11 -11
- package/admin/js/templates/docs/api-users.html +11 -11
- package/admin/js/templates/docs/api-views.html +11 -11
- package/admin/js/templates/form-editor.html +4 -4
- package/admin/js/templates/form-submissions.html +1 -1
- package/admin/js/templates/navigation.html +3 -3
- package/admin/js/templates/notifications.html +1 -1
- package/admin/js/templates/page-editor.html +3 -3
- package/admin/js/templates/project-detail.html +19 -19
- package/admin/js/templates/settings.html +6 -6
- package/admin/js/views/action-editor.js +1 -1
- package/admin/js/views/api-endpoint-editor.js +3 -3
- package/admin/js/views/collection-editor.js +2 -2
- package/admin/js/views/collection-entries.js +1 -1
- package/admin/js/views/component-editor.js +3 -3
- package/admin/js/views/form-editor.js +3 -3
- package/admin/js/views/form-submissions.js +1 -1
- package/admin/js/views/page-editor.js +4 -4
- package/admin/js/views/project-detail.js +1 -1
- package/admin/js/views/settings.js +2 -2
- package/package.json +1 -1
- package/public/css/forms.css +1 -1
- package/public/css/site.css +1 -1
- package/public/js/menu-decor.mjs +1 -1
- package/public/js/site.js +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{api as Y}from"../api.js";import{CardBuilder as Ke}from"../lib/card-builder.js";import{TimelineBuilder as Ze}from"../lib/timeline-builder.js";import{attachEditorKeybindings as Xe,createToolbar as et,insertAtCursor as ye}from"../lib/markdown-toolbar.js";import{EffectsBuilder as tt}from"../lib/effects-builder.js";import{attachContextMenu as nt}from"../lib/shortcode-context-menu.js";import{populateThemeSelect as at}from"../lib/themes.js";import{createFoldingManager as ot}from"../lib/editor-folding.js";import{makeCheckbox as Oe,makeField as G,makeIconInput as He,makeLivePreview as Ue,makeSelect as Le,makeTextInput as re}from"../lib/shortcode-modal.js";import{openScribeComposer as lt}from"../lib/scribe-composer.js";import{openCrudTutorial as it}from"../lib/crud-tutorial.js";function dt(){const d=E.slideover({title:"Editor Reference",size:"md",position:"right"}),ce="background:var(--dm-
|
|
1
|
+
import{api as Y}from"../api.js";import{CardBuilder as Ke}from"../lib/card-builder.js";import{TimelineBuilder as Ze}from"../lib/timeline-builder.js";import{attachEditorKeybindings as Xe,createToolbar as et,insertAtCursor as ye}from"../lib/markdown-toolbar.js";import{EffectsBuilder as tt}from"../lib/effects-builder.js";import{attachContextMenu as nt}from"../lib/shortcode-context-menu.js";import{populateThemeSelect as at}from"../lib/themes.js";import{createFoldingManager as ot}from"../lib/editor-folding.js";import{makeCheckbox as Oe,makeField as G,makeIconInput as He,makeLivePreview as Ue,makeSelect as Le,makeTextInput as re}from"../lib/shortcode-modal.js";import{openScribeComposer as lt}from"../lib/scribe-composer.js";import{openCrudTutorial as it}from"../lib/crud-tutorial.js";function dt(){const d=E.slideover({title:"Editor Reference",size:"md",position:"right"}),ce="background:var(--dm-background-alt,#1a1a2e);padding:.2rem .4rem;border-radius:3px;font-size:.85em;font-family:monospace;",de="margin:1rem 0 .5rem;font-size:1rem;";function U(h){const b=document.createElement("code");return b.style.cssText=ce,b.textContent=h,b}function X(h){const b=document.createElement("h3");return b.style.cssText=de,b.textContent=h,b}const $e=document.createElement("div");$e.style.cssText="padding:1rem;";const Ae=document.createElement("div");Ae.className="tabs";const Me=document.createElement("div");Me.className="tab-list",["Basics","Layout","Components","Data","Advanced"].forEach((h,b)=>{const i=document.createElement("button");i.className="tab-item"+(b===0?" active":""),i.textContent=h,Me.appendChild(i)});const _=document.createElement("div");_.className="tab-content";const Ie="display:flex;flex-direction:column;gap:1rem;",Be=document.createElement("div");Be.className="tab-panel active",Be.style.cssText=Ie;const ve=document.createElement("div");ve.className="tab-panel",ve.style.cssText=Ie;const se=document.createElement("div");se.className="tab-panel",se.style.cssText=Ie;const Ce=document.createElement("div");Ce.className="tab-panel",Ce.style.cssText=Ie;const we=document.createElement("div");we.className="tab-panel",we.style.cssText=Ie,_.appendChild(Be),_.appendChild(ve),_.appendChild(se),_.appendChild(Ce),_.appendChild(we),Ae.appendChild(Me),Ae.appendChild(_),$e.appendChild(Ae);const qe=document.createElement("div");qe.appendChild(X("Markdown Basics"));const pe=document.createElement("table");pe.style.cssText="width:100%;border-collapse:collapse;font-size:.9em;";const ee=document.createElement("thead"),oe=document.createElement("tr");["Syntax","Result"].forEach(h=>{const b=document.createElement("th");b.style.cssText="text-align:left;padding:.4rem .5rem;border-bottom:1px solid var(--dm-border,#333);",b.textContent=h,oe.appendChild(b)}),ee.appendChild(oe),pe.appendChild(ee);const be=document.createElement("tbody");[["**bold**","bold (rendered bold)"],["_italic_","italic (rendered italic)"],["## Heading","Heading (h2)"],["[text](url)","Link"],["","Image"],["- item","Bullet list"],["`code`","Inline code"],["---","Divider"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.35rem .5rem;vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.35rem .5rem;vertical-align:top;color:var(--dm-text-muted,#aaa);font-size:.85em;",s.textContent=b,i.appendChild(o),i.appendChild(s),be.appendChild(i)}),pe.appendChild(be),qe.appendChild(pe),Be.appendChild(qe);const ne=document.createElement("div");ne.appendChild(X("Grid & Columns"));function W(h){const b=document.createElement("p");return b.style.cssText="margin:.3rem 0 .6rem;font-size:.82em;color:var(--dm-text-muted,#aaa);",b.textContent=h,b}function A(h,b,i){const o=document.createElement("p");o.style.cssText="margin:.75rem 0 .25rem;font-size:.85em;font-weight:600;",o.textContent=h;const s=document.createElement("div");s.style.cssText="position:relative;";const j=document.createElement("pre");j.style.cssText=ce+"display:block;padding:.5rem 2rem .5rem .75rem;white-space:pre;overflow-x:auto;margin:0;",j.textContent=b;const Q=document.createElement("button");Q.type="button",Q.title="Copy code",Q.style.cssText="position:absolute;top:.3rem;right:.3rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.15rem;line-height:1;color:inherit;",Q.addEventListener("mouseenter",()=>{Q.style.opacity="1"}),Q.addEventListener("mouseleave",()=>{Q.style.opacity=".45"});const J=document.createElement("span");J.setAttribute("data-icon","copy"),Q.appendChild(J),Q.addEventListener("click",()=>{const P=document.createElement("textarea");P.value=b,P.style.cssText="position:fixed;opacity:0;",document.body.appendChild(P),P.select(),document.execCommand("copy"),P.remove(),E.toast("Copied!",{type:"success",duration:1200})}),s.appendChild(j),s.appendChild(Q);const K=document.createDocumentFragment();return K.appendChild(o),K.appendChild(s),i&&K.appendChild(W(i)),K}const ae=document.createElement("table");ae.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['cols="N"',"[grid] only","Number of columns (1\u201312)"],['gap="N"',"[grid], [row]","Gap between columns/rows (1\u20136)"],['span="N"',"[col] only","How many columns this cell spans"],['fullwidth="true"',"[grid] only","Break out of page container to span full viewport"],['class="x"',"all","Add extra CSS classes"]].forEach(([h,b,i])=>{const o=document.createElement("tr");[h,b,i].forEach((s,j)=>{const Q=document.createElement("td");Q.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",j===0?Q.appendChild(U(h)):(Q.style.color="var(--dm-text-muted,#aaa)",Q.textContent=s),o.appendChild(Q)}),ae.appendChild(o)}),ne.appendChild(ae),ne.appendChild(A("Equal columns",`[grid cols="3" gap="4"]
|
|
2
2
|
[col]One[/col]
|
|
3
3
|
[col]Two[/col]
|
|
4
4
|
[col]Three[/col]
|
|
@@ -84,18 +84,18 @@ In active development.
|
|
|
84
84
|
Markdown content here.
|
|
85
85
|
[/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")),se.appendChild(r);const T=document.createElement("div");T.appendChild(X("DConfig \u2014 Declarative Behaviour")),T.appendChild(W("Define click handlers and class toggles without writing JavaScript. Use the DConfig section above or embed inline with [dconfig]...[/dconfig] in the content body. Inline shortcodes win on selector conflict.")),T.appendChild(A("Toggle a class on click",'{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }','Selector keys use standard CSS selectors. "target" is optional \u2014 defaults to the element itself.')),T.appendChild(A("Inline shortcode syntax",`[dconfig]
|
|
86
86
|
{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }
|
|
87
|
-
[/dconfig]`,null)),we.appendChild(T);const B=document.createElement("div");B.appendChild(X("CSS Editor")),B.appendChild(W("The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page \u2014 one Save, one toast."));const z=document.createElement("table");z.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),z.appendChild(i)}),B.appendChild(z),we.appendChild(B);const w=document.createElement("div");w.appendChild(X("Colour Picker")),w.appendChild(W("Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss.")),we.appendChild(w);const L=document.createElement("div");L.appendChild(X("Keyboard Shortcuts"));const f=document.createElement("table");f.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["Ctrl + B","Bold selected text"],["Ctrl + I","Italic selected text"],["Ctrl + K","Insert link dialog"],["Tab","Indent 2 spaces at cursor"],["Shift + Tab","Dedent 2 spaces on current line"],["Ctrl + X","Cut current line (no selection) or cut selection"],["Ctrl + C","Copy current line (no selection) or copy selection"],["Ctrl + V","Paste from clipboard"],["Ctrl + Z","Undo"],["Ctrl + Y","Redo"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;white-space:nowrap;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),f.appendChild(i)}),L.appendChild(f),Be.appendChild(L);const N=document.createElement("div");N.appendChild(X("Tips"));const M=document.createElement("table");M.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['class="text-center"',"Centre text and inline elements on any shortcode"],['class="mx-auto"',"Centre a block element horizontally"],["[center]...[/center]","Shorthand wrapper for centred content"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),M.appendChild(i)}),N.appendChild(M),N.appendChild(W("Most shortcodes accept a class attribute for custom styling.")),Be.appendChild(N),d.setContent($e),d.open(),E.tabs(Ae),I.scan($e)}function st(d,ce){const de=d.find("#history-tab").get(0),U=d.find("#version-list").get(0),X=d.find("#version-compare").get(0),$e=d.find("#version-compare-old").get(0),Ae=d.find("#version-compare-new").get(0),Me=d.find("#version-compare-label").get(0),_=d.find("#version-compare-back-btn").get(0),Ie=d.find("#version-restore-btn").get(0),Be=d.find("#history-save-named-btn").get(0),ve=d.find("#history-delete-selected-btn").get(0);let se=!1,Ce=null;function we(){U.style.display="",X.style.display="none",Ce=null}function qe(){U.style.display="none",X.style.display=""}async function pe(){U.textContent="";const ee=document.createElement("p");ee.style.color="var(--dm-text-muted)",ee.textContent="Loading\u2026",U.appendChild(ee);let oe;try{oe=(await Y.versions.list(ce)).versions||[]}catch(V){U.textContent="";const q=document.createElement("p");q.style.color="var(--dm-text-danger,#e55)",q.textContent="Failed to load versions: "+V.message,U.appendChild(q);return}if(U.textContent="",ve.style.display="none",!oe.length){const V=document.createElement("p");V.style.color="var(--dm-text-muted)",V.textContent="No versions saved yet. Versions are created automatically on each save.",U.appendChild(V);return}const be=document.createElement("table");be.style.cssText="width:100%;border-collapse:collapse;font-size:.875rem;";const ne=document.createElement("thead"),W=document.createElement("tr"),A=document.createElement("th");A.style.cssText="padding:.5rem .75rem;width:2rem;border-bottom:1px solid var(--dm-border);";const ae=document.createElement("input");ae.type="checkbox",ae.setAttribute("aria-label","Select all versions"),A.appendChild(ae),W.appendChild(A),["Date","Author","Type","Label","Actions"].forEach(V=>{const q=document.createElement("th");q.style.cssText="text-align:left;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border);font-size:.8rem;color:var(--dm-text-muted);",q.textContent=V,W.appendChild(q)}),ne.appendChild(W),be.appendChild(ne);const me=[];function ze(){const V=me.some(ue=>ue.checked),q=me.length>0&&me.every(ue=>ue.checked);ve.style.display=V?"":"none",ae.checked=q,ae.indeterminate=V&&!q}ae.addEventListener("change",()=>{me.forEach(V=>{V.checked=ae.checked}),ze()});const De=document.createElement("tbody");oe.forEach(V=>{const q=document.createElement("tr");q.style.borderBottom="1px solid var(--dm-border)";const ue=document.createElement("td");ue.style.padding=".5rem .75rem";const Ee=document.createElement("input");Ee.type="checkbox",Ee.value=V.filename,Ee.addEventListener("change",ze),ue.appendChild(Ee),me.push(Ee);const ke=document.createElement("td");ke.style.padding=".5rem .75rem",ke.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm");const he=document.createElement("td");he.style.padding=".5rem .75rem",he.textContent=V.author||"\u2014";const Te=document.createElement("td");Te.style.padding=".5rem .75rem";const fe=document.createElement("span");fe.className="badge badge-"+(V.type==="manual"?"primary":"secondary"),fe.style.cssText="font-size:.75rem;padding:.2rem .5rem;border-radius:4px;",fe.textContent=V.type,Te.appendChild(fe);const Ne=document.createElement("td");Ne.style.cssText="padding:.5rem .75rem;color:var(--dm-text-muted);",Ne.textContent=V.label||"\u2014";const ge=document.createElement("td");ge.style.padding=".5rem .75rem";const ie=document.createElement("button");ie.className="btn btn-ghost btn-xs",ie.style.marginRight=".4rem",ie.title="Compare",ie.innerHTML='<span data-icon="columns"></span>',ie.addEventListener("click",async()=>{try{const xe=await Y.versions.get(ce,V.filename);$e.textContent=xe.content,Ae.textContent=d.find("#markdown-editor").get(0).value,Me.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm")+(V.label?` \u2014 ${V.label}`:""),Ce=V.filename,qe()}catch(xe){E.toast("Failed to load version: "+xe.message,{type:"error"})}});const le=document.createElement("button");le.className="btn btn-ghost btn-xs",le.style.color="var(--dm-text-danger,#e55)",le.title="Delete",le.innerHTML='<span data-icon="trash"></span>',le.addEventListener("click",async()=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await Y.versions.delete(ce,V.filename),E.toast("Version deleted.",{type:"success"}),await pe()}catch(xe){E.toast("Failed to delete: "+xe.message,{type:"error"})}}),ge.appendChild(ie),ge.appendChild(le),q.appendChild(ue),q.appendChild(ke),q.appendChild(he),q.appendChild(Te),q.appendChild(Ne),q.appendChild(ge),De.appendChild(q)}),be.appendChild(De),U.appendChild(be),I.scan(U)}de.addEventListener("click",async()=>{se||(se=!0,await pe())}),_.addEventListener("click",()=>{we()}),Ie.addEventListener("click",async()=>{if(!(!Ce||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await Y.versions.restore(ce,Ce),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${ce}`),300)}catch(ee){E.toast("Restore failed: "+ee.message,{type:"error"})}}),ve.addEventListener("click",async()=>{const ee=[...U.querySelectorAll("tbody input[type=checkbox]:checked")].map(oe=>oe.value);if(!(!ee.length||!await E.confirm(`Delete ${ee.length} version${ee.length>1?"s":""}? This cannot be undone.`)))try{await Y.versions.bulkDelete(ce,ee),E.toast(`${ee.length} version${ee.length>1?"s":""} deleted.`,{type:"success"}),await pe()}catch(oe){E.toast("Delete failed: "+oe.message,{type:"error"})}}),Be.addEventListener("click",()=>{const ee=E.modal({title:"Save Named Version"}),oe=document.createElement("div");oe.style.padding="1rem";const be=document.createElement("label");be.className="form-label",be.textContent="Version Label";const ne=document.createElement("input");ne.type="text",ne.className="form-input",ne.placeholder="e.g. Initial design, Before restructure",ne.style.marginBottom=".75rem";const W=document.createElement("button");W.className="btn btn-primary",W.textContent="Save Version",W.addEventListener("click",async()=>{const A=ne.value.trim();try{await Y.versions.create(ce,A||null),E.toast("Named version saved.",{type:"success"}),ee.close(),se=!1,de.classList.contains("active")&&(se=!0,await pe())}catch(ae){E.toast("Failed to save version: "+ae.message,{type:"error"})}}),oe.appendChild(be),oe.appendChild(ne),oe.appendChild(W),ee.element.appendChild(oe),ee.open(),setTimeout(()=>ne.focus(),100)})}let Re=!1,Ge=null,je=!1;function rt(d){return d.split(`
|
|
87
|
+
[/dconfig]`,null)),we.appendChild(T);const B=document.createElement("div");B.appendChild(X("CSS Editor")),B.appendChild(W("The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page \u2014 one Save, one toast."));const z=document.createElement("table");z.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),z.appendChild(i)}),B.appendChild(z),we.appendChild(B);const w=document.createElement("div");w.appendChild(X("Colour Picker")),w.appendChild(W("Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss.")),we.appendChild(w);const L=document.createElement("div");L.appendChild(X("Keyboard Shortcuts"));const f=document.createElement("table");f.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["Ctrl + B","Bold selected text"],["Ctrl + I","Italic selected text"],["Ctrl + K","Insert link dialog"],["Tab","Indent 2 spaces at cursor"],["Shift + Tab","Dedent 2 spaces on current line"],["Ctrl + X","Cut current line (no selection) or cut selection"],["Ctrl + C","Copy current line (no selection) or copy selection"],["Ctrl + V","Paste from clipboard"],["Ctrl + Z","Undo"],["Ctrl + Y","Redo"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;white-space:nowrap;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),f.appendChild(i)}),L.appendChild(f),Be.appendChild(L);const N=document.createElement("div");N.appendChild(X("Tips"));const M=document.createElement("table");M.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['class="text-center"',"Centre text and inline elements on any shortcode"],['class="mx-auto"',"Centre a block element horizontally"],["[center]...[/center]","Shorthand wrapper for centred content"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),M.appendChild(i)}),N.appendChild(M),N.appendChild(W("Most shortcodes accept a class attribute for custom styling.")),Be.appendChild(N),d.setContent($e),d.open(),E.tabs(Ae),I.scan($e)}function st(d,ce){const de=d.find("#history-tab").get(0),U=d.find("#version-list").get(0),X=d.find("#version-compare").get(0),$e=d.find("#version-compare-old").get(0),Ae=d.find("#version-compare-new").get(0),Me=d.find("#version-compare-label").get(0),_=d.find("#version-compare-back-btn").get(0),Ie=d.find("#version-restore-btn").get(0),Be=d.find("#history-save-named-btn").get(0),ve=d.find("#history-delete-selected-btn").get(0);let se=!1,Ce=null;function we(){U.style.display="",X.style.display="none",Ce=null}function qe(){U.style.display="none",X.style.display=""}async function pe(){U.textContent="";const ee=document.createElement("p");ee.style.color="var(--dm-text-muted)",ee.textContent="Loading\u2026",U.appendChild(ee);let oe;try{oe=(await Y.versions.list(ce)).versions||[]}catch(V){U.textContent="";const q=document.createElement("p");q.style.color="var(--dm-danger,#e55)",q.textContent="Failed to load versions: "+V.message,U.appendChild(q);return}if(U.textContent="",ve.style.display="none",!oe.length){const V=document.createElement("p");V.style.color="var(--dm-text-muted)",V.textContent="No versions saved yet. Versions are created automatically on each save.",U.appendChild(V);return}const be=document.createElement("table");be.style.cssText="width:100%;border-collapse:collapse;font-size:.875rem;";const ne=document.createElement("thead"),W=document.createElement("tr"),A=document.createElement("th");A.style.cssText="padding:.5rem .75rem;width:2rem;border-bottom:1px solid var(--dm-border);";const ae=document.createElement("input");ae.type="checkbox",ae.setAttribute("aria-label","Select all versions"),A.appendChild(ae),W.appendChild(A),["Date","Author","Type","Label","Actions"].forEach(V=>{const q=document.createElement("th");q.style.cssText="text-align:left;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border);font-size:.8rem;color:var(--dm-text-muted);",q.textContent=V,W.appendChild(q)}),ne.appendChild(W),be.appendChild(ne);const me=[];function ze(){const V=me.some(ue=>ue.checked),q=me.length>0&&me.every(ue=>ue.checked);ve.style.display=V?"":"none",ae.checked=q,ae.indeterminate=V&&!q}ae.addEventListener("change",()=>{me.forEach(V=>{V.checked=ae.checked}),ze()});const De=document.createElement("tbody");oe.forEach(V=>{const q=document.createElement("tr");q.style.borderBottom="1px solid var(--dm-border)";const ue=document.createElement("td");ue.style.padding=".5rem .75rem";const Ee=document.createElement("input");Ee.type="checkbox",Ee.value=V.filename,Ee.addEventListener("change",ze),ue.appendChild(Ee),me.push(Ee);const ke=document.createElement("td");ke.style.padding=".5rem .75rem",ke.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm");const he=document.createElement("td");he.style.padding=".5rem .75rem",he.textContent=V.author||"\u2014";const Te=document.createElement("td");Te.style.padding=".5rem .75rem";const fe=document.createElement("span");fe.className="badge badge-"+(V.type==="manual"?"primary":"secondary"),fe.style.cssText="font-size:.75rem;padding:.2rem .5rem;border-radius:4px;",fe.textContent=V.type,Te.appendChild(fe);const Ne=document.createElement("td");Ne.style.cssText="padding:.5rem .75rem;color:var(--dm-text-muted);",Ne.textContent=V.label||"\u2014";const ge=document.createElement("td");ge.style.padding=".5rem .75rem";const ie=document.createElement("button");ie.className="btn btn-ghost btn-xs",ie.style.marginRight=".4rem",ie.title="Compare",ie.innerHTML='<span data-icon="columns"></span>',ie.addEventListener("click",async()=>{try{const xe=await Y.versions.get(ce,V.filename);$e.textContent=xe.content,Ae.textContent=d.find("#markdown-editor").get(0).value,Me.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm")+(V.label?` \u2014 ${V.label}`:""),Ce=V.filename,qe()}catch(xe){E.toast("Failed to load version: "+xe.message,{type:"error"})}});const le=document.createElement("button");le.className="btn btn-ghost btn-xs",le.style.color="var(--dm-danger,#e55)",le.title="Delete",le.innerHTML='<span data-icon="trash"></span>',le.addEventListener("click",async()=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await Y.versions.delete(ce,V.filename),E.toast("Version deleted.",{type:"success"}),await pe()}catch(xe){E.toast("Failed to delete: "+xe.message,{type:"error"})}}),ge.appendChild(ie),ge.appendChild(le),q.appendChild(ue),q.appendChild(ke),q.appendChild(he),q.appendChild(Te),q.appendChild(Ne),q.appendChild(ge),De.appendChild(q)}),be.appendChild(De),U.appendChild(be),I.scan(U)}de.addEventListener("click",async()=>{se||(se=!0,await pe())}),_.addEventListener("click",()=>{we()}),Ie.addEventListener("click",async()=>{if(!(!Ce||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await Y.versions.restore(ce,Ce),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${ce}`),300)}catch(ee){E.toast("Restore failed: "+ee.message,{type:"error"})}}),ve.addEventListener("click",async()=>{const ee=[...U.querySelectorAll("tbody input[type=checkbox]:checked")].map(oe=>oe.value);if(!(!ee.length||!await E.confirm(`Delete ${ee.length} version${ee.length>1?"s":""}? This cannot be undone.`)))try{await Y.versions.bulkDelete(ce,ee),E.toast(`${ee.length} version${ee.length>1?"s":""} deleted.`,{type:"success"}),await pe()}catch(oe){E.toast("Delete failed: "+oe.message,{type:"error"})}}),Be.addEventListener("click",()=>{const ee=E.modal({title:"Save Named Version"}),oe=document.createElement("div");oe.style.padding="1rem";const be=document.createElement("label");be.className="form-label",be.textContent="Version Label";const ne=document.createElement("input");ne.type="text",ne.className="form-input",ne.placeholder="e.g. Initial design, Before restructure",ne.style.marginBottom=".75rem";const W=document.createElement("button");W.className="btn btn-primary",W.textContent="Save Version",W.addEventListener("click",async()=>{const A=ne.value.trim();try{await Y.versions.create(ce,A||null),E.toast("Named version saved.",{type:"success"}),ee.close(),se=!1,de.classList.contains("active")&&(se=!0,await pe())}catch(ae){E.toast("Failed to save version: "+ae.message,{type:"error"})}}),oe.appendChild(be),oe.appendChild(ne),oe.appendChild(W),ee.element.appendChild(oe),ee.open(),setTimeout(()=>ne.focus(),100)})}let Re=!1,Ge=null,je=!1;function rt(d){return d.split(`
|
|
88
88
|
`).map(ce=>ce.trimEnd()).join(`
|
|
89
89
|
`).replace(/\n{3,}/g,`
|
|
90
90
|
|
|
91
91
|
`)}const Ye="editor_prefs";function Je(){return S.get(Ye)||{viewMode:"split",fullscreen:!1}}function Qe(d,ce){const de=Je();de[d]=ce,S.set(Ye,de)}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(d){const ce=window.location.hash.match(/#\/pages\/edit(\/.*)/),de=ce?ce[1]:null,U=!!de,X=E.loader(d.get(0),{type:"dots"}),$e=[Y.layouts.get().catch(()=>({})),Y.settings.get().catch(()=>({}))];U&&($e.push(Y.pages.get(de).catch(()=>null)),$e.push(Y.pages.list().catch(()=>[])));const[Ae,Me,_,Ie]=await Promise.all($e);X.destroy(),at(d.find("#field-theme").get(0),{includeDefault:!0});const Be=Me?.layoutOptions?.spacerSize??40;if(U&&!_){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}d.find("#editor-title").text(U?`Edit Page \u2014 ${_.title||de}`:"New Page"),U&&d.find("#page-url-path").val(de),_&&(d.find("#field-title").val(_.title||""),d.find("#field-description").val(_.description||""),d.find("#field-status").val(_.status||"draft"),d.find("#field-sort-order").val(_.sortOrder??99),d.find("#field-show-in-nav").prop("checked",!!_.showInNav),d.find("#field-sidebar").prop("checked",!!_.sidebar),d.find("#field-show-breadcrumbs").prop("checked",_.breadcrumbs!==!1),d.find("#field-bundled").prop("checked",!!_.bundled),d.find("#field-category").val(_.category||""),d.find("#field-visibility").val(_.visibility||"public"),d.find("#field-theme").val(_.theme||""),d.find("#field-seo-title").val(_.seo?.title||""),d.find("#field-seo-desc").val(_.seo?.description||""),_.dconfig&&d.find("#field-dconfig").val(JSON.stringify(_.dconfig,null,2)));{const e=d.find("#field-project").get(0);if(e){const t=await Y.projects.list().catch(()=>[]);t.forEach(l=>{const n=document.createElement("option");n.value=l.slug,n.textContent=l.name||l.slug,e.appendChild(n)});let a="";if(_)if(_.project===null)a="";else if(typeof _.project=="string"&&_.project)a=_.project;else{const l=U?de:"";if(l){let n="",u=-1;for(const v of t)v.rootUrl&&(l===v.rootUrl||l.startsWith(v.rootUrl+"/"))&&v.rootUrl.length>u&&(n=v.slug,u=v.rootUrl.length);a=n}}e.value=a}}const ve=d.find("#quick-switch");U&&Array.isArray(Ie)&&Ie.length&&([...Ie].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath)).forEach(e=>{const t=document.createElement("option");t.value=e.urlPath,t.textContent=`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath===de&&(t.selected=!0),ve.get(0).appendChild(t)}),ve.css("display",""),ve.on("change",function(){const e=this.value;e&&R.navigate("/pages/edit"+e)}));const se=await Y.pages.tags().catch(()=>[]),Ce=d.find("#field-tags").get(0),we=Ce?E.pillbox(Ce,{data:se,value:_?.tags||[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026"}):null,qe=d.find("#field-layout").empty();if(Object.entries(Ae).forEach(([e,t])=>{const a=(_?.layout||"default")===e?"selected":"";qe.append(`<option value="${e}" ${a}>${t.label||e}</option>`)}),U){const e=d.find("#view-page-btn").get(0);e.href=de,e.style.display="";const t=d.find("#live-preview-tab").get(0);t.style.display="";const a=d.find("#history-tab").get(0);a.style.display=""}if(E.tabs(d.find("#editor-meta-tabs").get(0)),U){const e=d.find("#live-preview-tab").get(0),t=d.find("#live-preview-frame").get(0);let a=!1;e.addEventListener("click",function(){a||(t.src=de,a=!0)}),st(d,de)}const pe=d.find("#markdown-editor"),ee=d.find("#markdown-preview");_&&pe.val(_.content||"");let oe=!1,be="";Y.settings.getCustomCss().then(({css:e})=>{if(be=e||"",!be)return;const t=document.createElement("style");t.id="preview-custom-css",t.textContent=be,ee.get(0).parentNode.insertBefore(t,ee.get(0))}).catch(()=>{});let ne=!1;const W=pe.get(0),A=document.createElement("div");A.className="editor-line-numbers editor-line-numbers--foldable",W.parentElement.insertBefore(A,W);const ae=ot(W,A,{onFoldChange:()=>{}});ae.setGuard(e=>{ne=e});function me(){const e=d.find("#css-editor").get(0);if(!e)return;const t=e.value.split(`
|
|
92
|
-
`);for(;A.firstChild;)A.removeChild(A.firstChild);t.forEach((a,l)=>{const n=document.createElement("span");n.className="editor-line-number-row";const u=document.createElement("span");u.className="fold-toggle fold-toggle--empty";const v=document.createElement("span");v.className="editor-line-num",v.textContent=String(l+1),n.appendChild(u),n.appendChild(v),A.appendChild(n)}),A.scrollTop=e.scrollTop}{const e=d.find("#css-editor").get(0);e&&e.addEventListener("scroll",()=>{A.scrollTop=e.scrollTop})}const ze=()=>{ae.refresh(),A.scrollTop=W.scrollTop};W.addEventListener("input",ze),W.addEventListener("scroll",()=>{A.scrollTop=W.scrollTop});let De=null;const V=()=>{clearTimeout(De),De=setTimeout(async()=>{const e=ae.getUnfoldedContent();try{const{html:t}=await Y.pages.preview(e);ee.html(t,{safe:!1}),I.scan(ee.get(0)),ee.get(0).querySelectorAll(".tabs").forEach(a=>Domma.elements.tabs(a))}catch{window.marked&&ee.html(marked.parse(e))}},400)},q=et(pe,d.find("#editor-toolbar"),{spacerDefault:Be});nt(pe.get(0));let ue=!1,Ee="split",ke=null;const he=document.createElement("button");he.className="editor-view-btn",he.type="button";const Te=document.createElement("span");Te.setAttribute("data-icon","css-code"),he.appendChild(Te);const fe=document.createElement("button");fe.className="editor-view-btn",fe.type="button";const Ne=document.createElement("span");Ne.setAttribute("data-icon","code"),fe.appendChild(Ne);let ge=!1;const ie=document.createElement("button");ie.className="editor-view-btn",ie.type="button",ie.textContent="\u25BC\u25BC",ie.style.cssText="font-size:9px;letter-spacing:-1px;";const le=d.find(".editor-toolbar-right").get(0);le.prepend(ie),le.prepend(fe),le.prepend(he),I.scan(he),I.scan(fe),E.tooltip(he,{content:"Edit Custom CSS",position:"top"}),E.tooltip(fe,{content:"Format Markdown",position:"top"}),E.tooltip(ie,{content:"Fold / unfold all shortcodes",position:"top"}),fe.addEventListener("click",()=>{const e=pe.get(0),t=e.selectionStart,a=rt(ae.getUnfoldedContent());ae.unfoldAll(),ne=!0,e.value=a,ne=!1,e.selectionStart=e.selectionEnd=Math.min(t,a.length),e.dispatchEvent(new Event("input")),ae.refresh(),E.toast("Markdown formatted.",{type:"success"})}),ie.addEventListener("click",()=>{ge?(ae.unfoldAll(),ie.textContent="\u25BC\u25BC",ie.classList.remove("active")):(ae.foldAll(),ie.textContent="\u25B6\u25B6",ie.classList.add("active")),ge=!ge});const xe=document.createElement("span");xe.className="editor-toolbar-sep",le.insertBefore(xe,le.children[3]),he.addEventListener("click",()=>{ue=!ue;const e=d.find("#markdown-editor"),t=d.find("#css-editor"),a=d.find("#editor-body");if(ue){const l=d.find(".editor-view-btn[data-mode].active").get(0);Ee=l?l.getAttribute("data-mode"):"split",d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find('.editor-view-btn[data-mode="split"]').addClass("active"),a.removeClass("editor-mode-write editor-mode-preview").addClass("editor-mode-split"),e.hide(),t.show(),oe||(t.val(be),oe=!0,Xe(t.get(0))),me(),he.classList.add("active")}else d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Ee}"]`).addClass("active"),a.removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Ee}`),t.hide(),e.show(),ae.refresh(),he.classList.remove("active")});const Fe=Je();Fe.viewMode&&Fe.viewMode!=="split"&&(d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Fe.viewMode}"]`).addClass("active"),d.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Fe.viewMode}`)),Fe.fullscreen&&d.find(".editor-card").addClass("editor-fullscreen"),d.find("#css-editor").on("input",()=>{me(),clearTimeout(ke),ke=setTimeout(()=>{let e=document.getElementById("preview-custom-css");e||(e=document.createElement("style"),e.id="preview-custom-css",ee.get(0).parentNode.insertBefore(e,ee.get(0))),e.textContent=d.find("#css-editor").val()},400)}),q.onLink(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(r=>({label:r.title||r.urlPath,value:r.urlPath})),a=document.createElement("div");a.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const l=document.createElement("label");l.className="form-label",l.textContent="URL";const n=document.createElement("input");n.type="text",n.className="form-input",n.placeholder="/about or https://example.com";const u=e.value.substring(e.selectionStart,e.selectionEnd);u&&u.startsWith("/")&&(n.value=u),a.appendChild(l),a.appendChild(n);const v=document.createElement("label");v.className="form-label",v.textContent="Link text";const g=document.createElement("input");g.type="text",g.className="form-input",g.placeholder="Display text",u&&!u.startsWith("/")&&(g.value=u),a.appendChild(v),a.appendChild(g);const k=document.createElement("label");k.className="form-label",k.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const c=document.createElement("input");c.type="checkbox",c.style.cssText="width:1rem;height:1rem;cursor:pointer;",k.appendChild(c),k.appendChild(document.createTextNode("Display as button")),a.appendChild(k);const C=document.createElement("label");C.className="form-label",C.textContent="Button colour",C.style.display="none";const y=document.createElement("select");y.className="form-select",y.style.display="none",[["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["outline-success","Outline Success"],["outline-danger","Outline Danger"],["ghost","Ghost"]].forEach(([r,x])=>{const T=document.createElement("option");T.value=r,T.textContent=x,y.appendChild(T)}),a.appendChild(C),a.appendChild(y),c.addEventListener("change",()=>{const r=c.checked;C.style.display=r?"":"none",y.style.display=r?"":"none"});const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Link",a.appendChild(m);const p=E.slideover({title:"Insert Link",size:"md",position:"right",content:a});p.open(),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:r=>{n.value=r.value,g.value||(g.value=r.label)}}),n.focus()}),m.addEventListener("click",()=>{const r=n.value.trim(),x=g.value.trim();if(!r)return;p.close();const T=c.checked?`[button href="${r}" variant="${y.value}"]${x||r}[/button]`:`[${x||r}](${r})`,B=e.selectionStart,z=e.selectionEnd;e.value=e.value.substring(0,B)+T+e.value.substring(z),e.selectionStart=e.selectionEnd=B+T.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onImage(async e=>{const t=(await Y.media.list().catch(()=>[])).filter(n=>/\.(png|jpe?g|gif|webp|svg)$/i.test(n.name)),a=document.createElement("div");if(a.className="media-picker-grid",t.length)t.forEach(n=>{const u=document.createElement("div");u.className="media-picker-item",u.dataset.url=n.url;const v=document.createElement("img");v.src=n.url,v.alt=n.name;const g=document.createElement("span");g.textContent=n.name,u.appendChild(v),u.appendChild(g),a.appendChild(u)});else{const n=document.createElement("p");n.className="text-muted p-3",n.textContent="No images uploaded yet.",a.appendChild(n)}const l=E.slideover({title:"Insert Image",size:"lg",position:"right",content:a});$(l.element).on("click",".media-picker-item",function(){const n=$(this).data("url"),u=$(this).find("span").text();ye(e,``),l.close(),pe.get(0).dispatchEvent(new Event("input",{bubbles:!0}))}),l.open()}),q.onCollection(async e=>{const[t,a]=await Promise.all([Y.collections.list().catch(()=>[]),Y.blocks.list().catch(()=>[])]),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",u="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;",v=document.createElement("div"),g=document.createElement("label");g.style.cssText=n,g.textContent="Collection";const k=document.createElement("select");if(k.style.cssText=u,t.length)t.forEach(H=>{const te=document.createElement("option");te.value=H.slug,te.textContent=H.title||H.slug,k.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No collections found",k.appendChild(H)}v.appendChild(g),v.appendChild(k),l.appendChild(v);const c=document.createElement("div"),C=document.createElement("label");C.style.cssText=n,C.textContent="Display";const y=document.createElement("select");y.style.cssText=u,["table","cards","list","block"].forEach(H=>{const te=document.createElement("option");te.value=H,te.textContent=H.charAt(0).toUpperCase()+H.slice(1),y.appendChild(te)}),c.appendChild(C),c.appendChild(y),l.appendChild(c);const m=document.createElement("div");m.style.display="none";const p=document.createElement("label");p.style.cssText=n,p.textContent="Columns (2\u20134)";const r=document.createElement("input");r.type="number",r.min="2",r.max="4",r.value="3",r.style.cssText=u,m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=document.createElement("div");x.style.display="none";const T=document.createElement("label");T.style.cssText=n,T.textContent="Block template";const B=document.createElement("select");if(B.style.cssText=u,a.length)a.forEach(H=>{const te=document.createElement("option");te.value=H.name??H,te.textContent=H.name??H,B.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No block templates found",B.appendChild(H)}x.appendChild(T),x.appendChild(B),l.appendChild(x);const z=document.createElement("div"),w=document.createElement("label");w.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const L=document.createElement("input");L.type="checkbox",L.checked=!0,w.appendChild(L),w.appendChild(document.createTextNode("Enable search")),z.appendChild(w),l.appendChild(z);const f=document.createElement("div"),N=document.createElement("label");N.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const M=document.createElement("input");M.type="checkbox",M.checked=!0,N.appendChild(M),N.appendChild(document.createTextNode("Sortable columns")),f.appendChild(N),l.appendChild(f);const h=document.createElement("div"),b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const i=document.createElement("input");i.type="checkbox",i.checked=!1,b.appendChild(i),b.appendChild(document.createTextNode("CSV export")),h.appendChild(b),l.appendChild(h);const o=document.createElement("div"),s=document.createElement("label");s.style.cssText=n,s.textContent="Rows per page";const j=document.createElement("input");j.type="number",j.min="5",j.max="100",j.value="25",j.style.cssText=u,o.appendChild(s),o.appendChild(j),l.appendChild(o);const Q=document.createElement("div"),J=document.createElement("label");J.style.cssText=n,J.textContent="Limit (optional)";const K=document.createElement("input");K.type="number",K.placeholder="All",K.style.cssText=u,Q.appendChild(J),Q.appendChild(K),l.appendChild(Q);const P=document.createElement("button");P.type="button",P.className="btn btn-primary",P.textContent="Insert",l.appendChild(P);const F=[z,f,h,o],O=()=>{const H=y.value,te=H==="table";F.forEach(Se=>{Se.style.display=te?"":"none"}),m.style.display=H==="cards"||H==="block"?"":"none",x.style.display=H==="block"?"":"none"};y.addEventListener("change",O),O();const Z=E.slideover({title:"Insert Collection",size:"md",position:"right",content:l});Z.open(),P.addEventListener("click",()=>{const H=k.value;if(!H)return;const te=y.value;let Se=`[collection slug="${H}" display="${te}"`;if(te==="cards"&&(Se+=` columns="${r.value}"`),te==="block"){const _e=B.value;_e&&(Se+=` block="${_e}"`);const Ve=r.value.trim();Ve&&(Se+=` cols="${Ve}"`)}te==="table"&&!L.checked&&(Se+=' search="false"'),te==="table"&&!M.checked&&(Se+=' sortable="false"'),te==="table"&&i.checked&&(Se+=' exportable="true"'),te==="table"&&j.value!=="25"&&(Se+=` page-size="${j.value}"`);const We=K.value.trim();We&&(Se+=` limit="${We}"`),Se+=" /]",Z.close(),ye(e,Se),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBlock(async e=>{let t=[];try{t=await Y.blocks.list()}catch{E.toast("Could not load blocks.",{type:"error"});return}if(!t.length){E.toast("No block templates found. Create one in Blocks first.",{type:"warning"});return}const a=document.createElement("div");a.style.cssText="display:flex;gap:1rem;min-height:320px;";const l=E.slideover({title:"Insert Block",size:"lg",position:"right",content:a}),n=document.createElement("div");n.style.cssText="flex:1;display:flex;flex-direction:column;gap:.75rem;";const u=document.createElement("label");u.className="form-label",u.textContent="Block Template";const v=document.createElement("select");v.className="form-select";const g=document.createElement("option");g.value="",g.textContent="\u2014 select a template \u2014",v.appendChild(g),t.forEach(B=>{const z=document.createElement("option");z.value=B.name,z.textContent=B.name,v.appendChild(z)}),n.appendChild(u),n.appendChild(v);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.5rem;overflow-y:auto;max-height:260px;",n.appendChild(k);const c=document.createElement("button");c.className="btn btn-primary",c.type="button",c.textContent="Insert",c.disabled=!0,n.appendChild(c);const C=document.createElement("div");C.style.cssText="flex:1;border:1px solid var(--dm-border-color);border-radius:var(--dm-radius);padding:.75rem;overflow:auto;background:var(--dm-surface-bg);";const y=document.createElement("p");y.className="text-muted",y.style.cssText="font-size:.8rem;margin:0;",y.textContent="Select a template to see a preview.",C.appendChild(y),a.appendChild(n),a.appendChild(C),l.open();let m=null,p=[];function r(B){return B.replace(/_/g," ").replace(/\b\w/g,z=>z.toUpperCase())}function x(){if(!m)return;const B={};p.forEach(({key:w,input:L})=>{B[w]=L.value});const z=m.replace(/\{\{([\w_]+)\}\}/g,(w,L)=>(B[L]??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"));C.innerHTML=DOMPurify.sanitize(z)}function T(B){k.textContent="",p=[];const z=new Set(["_id","_createdAt","_updatedAt"]),w=new Set;for(const[,L]of B.matchAll(/\{\{([\w_]+)\}\}/g))z.has(L)||w.add(L);if(!w.size){const L=document.createElement("p");L.className="text-muted",L.style.cssText="font-size:.8rem;margin:0;",L.textContent="No editable placeholders in this template.",k.appendChild(L);return}w.forEach(L=>{const f=document.createElement("div"),N=document.createElement("label");N.className="form-label",N.style.cssText="font-size:.8rem;margin-bottom:.2rem;display:block;",N.textContent=r(L);const M=document.createElement("input");M.type="text",M.className="form-input",M.placeholder=r(L),M.addEventListener("input",x),f.appendChild(N),f.appendChild(M),k.appendChild(f),p.push({key:L,input:M})})}v.addEventListener("change",async()=>{const B=v.value;if(!B){m=null,p=[],k.textContent="",C.textContent="",C.appendChild(y),c.disabled=!0;return}m=null,p=[],k.textContent="",c.disabled=!0;try{m=(await Y.blocks.get(B)).content||"",T(m),x(),c.disabled=!1}catch{E.toast("Could not load template.",{type:"error"})}}),c.addEventListener("click",()=>{if(!v.value)return;const B=L=>L.replace(/"/g,""");let z=`template="${B(v.value)}"`;p.forEach(({key:L,input:f})=>{f.value!==""&&(z+=` ${L}="${B(f.value)}"`)});const w=`[block ${z} /]`;ye(e,w),e.dispatchEvent(new Event("input",{bubbles:!0})),l.close(),e.focus()})}),q.onForm(async e=>{const t=await Y.forms.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="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;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="Form";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(C=>{const y=document.createElement("option");y.value=C.slug,y.textContent=C.title||C.slug,g.appendChild(y)});else{const C=document.createElement("option");C.value="",C.textContent="No forms found",g.appendChild(C)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("button");k.className="btn btn-primary btn-sm",k.style.cssText="align-self:flex-end;margin-top:.5rem;",k.textContent="Insert Form",a.appendChild(k);const c=E.slideover({title:"Insert Form",size:"md",position:"right",content:a});c.open(),k.addEventListener("click",()=>{const C=g.value;C&&(ye(e,`[form slug="${C}" /]`),c.close(),pe.get(0).dispatchEvent(new Event("input",{bubbles:!0})))})}),q.onView(async e=>{const t=await Y.views.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="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;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="View";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(p=>{const r=document.createElement("option");r.value=p.slug,r.textContent=p.title||p.slug,g.appendChild(r)});else{const p=document.createElement("option");p.value="",p.textContent="No Views configured yet \u2014 create one under Data \u2192 Views",g.appendChild(p)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("div"),c=document.createElement("label");c.style.cssText=l,c.textContent="Display";const C=document.createElement("select");C.style.cssText=n,["table","cards","list"].forEach(p=>{const r=document.createElement("option");r.value=p,r.textContent=p.charAt(0).toUpperCase()+p.slice(1),C.appendChild(r)}),k.appendChild(c),k.appendChild(C),a.appendChild(k);const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",a.appendChild(y);const m=E.slideover({title:"Insert View",size:"md",position:"right",content:a});m.open(),y.addEventListener("click",()=>{const p=g.value;if(!p)return;const r=`[view slug="${p}" display="${C.value}" /]`;m.close(),ye(e,r),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCta(async e=>{const t=await Y.actions.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l=Le(t.length?t.map(p=>[p.slug,p.title||p.slug]):[["","No Actions configured yet \u2014 create one under Data \u2192 Actions"]]);a.appendChild(G("Action",l));const n=re("Button label","Run");a.appendChild(G("Label",n)),l.addEventListener("change",()=>{const p=t.find(r=>r.slug===l.value);p?.trigger?.label&&(n.value=p.trigger.label)}),t.length&&t[0]?.trigger?.label&&(n.value=t[0].trigger.label);const u=re("Paste entry UUID\u2026","");a.appendChild(G("Entry ID",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["ghost","Ghost"],["danger","Danger"]]);a.appendChild(G("Style",v));const g=He("e.g. check, zap, send (optional)","");a.appendChild(G("Icon",g.el));const k=re("Confirmation message (optional)","");a.appendChild(G("Confirm prompt",k));const c=document.createElement("div");c.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const C=document.createElement("button");C.type="button",C.className="btn btn-ghost",C.textContent="Cancel";const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",c.appendChild(C),c.appendChild(y),a.appendChild(c);const m=E.slideover({title:"Insert CTA Button",size:"md",position:"right",content:a});m.open(),I.scan(a),C.addEventListener("click",()=>m.close()),y.addEventListener("click",()=>{const p=l.value;if(!p)return;const r=u.value.trim().replace(/"/g,""),x=(n.value.trim()||"Run").replace(/\[\/cta\]/gi,""),T=v.value,B=g.input.value.trim().replace(/"/g,""),z=k.value.trim().replace(/"/g,"");let w=`action="${p}" style="${T}"`;r&&(w+=` entry="${r}"`),B&&(w+=` icon="${B}"`),z&&(w+=` confirm="${z}"`),m.close(),ye(e,`[cta ${w}]${x}[/cta]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onButton(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(T=>({label:T.title||T.urlPath,value:T.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Button label",a&&!a.startsWith("/")?a:"");l.appendChild(G("Label",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["ghost","Ghost"],["link","Link"],["outline-success","Outline Success"],["outline-danger","Outline Danger"]]);l.appendChild(G("Variant",v));const g=Le([["","Default"],["sm","Small"],["lg","Large"]]);l.appendChild(G("Size",g));const k=He("e.g. arrow-right, star (optional)","");l.appendChild(G("Icon (before label)",k.el));const c=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (after label)",c.el));const C=Oe("Open in new tab");l.appendChild(C);const y=C.querySelector("input"),m=document.createElement("div");m.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const p=document.createElement("button");p.type="button",p.className="btn btn-ghost",p.textContent="Cancel";const r=document.createElement("button");r.type="button",r.className="btn btn-primary",r.textContent="Insert Button",m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=E.slideover({title:"Insert Button",size:"md",position:"right",content:l});x.open(),I.scan(l),p.addEventListener("click",()=>x.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:T=>{n.value=T.value,u.value||(u.value=T.label)}}),n.focus()}),r.addEventListener("click",()=>{const T=n.value.trim();if(!T)return;x.close();const B=u.value.trim()||T;let z=`href="${T}" variant="${v.value}"`;g.value&&(z+=` size="${g.value}"`);const w=k.input.value.trim().replace(/"/g,"");w&&(z+=` icon="${w}"`);const L=c.input.value.trim().replace(/"/g,"");L&&(z+=` icon-after="${L}"`),y.checked&&(z+=' target="_blank"'),ye(e,`[button ${z}]${B}[/button]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onLinkShortcode(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(x=>({label:x.title||x.urlPath,value:x.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Link text",a&&!a.startsWith("/")?a:"");l.appendChild(G("Link text",u));const v=re("e.g. text-primary, fw-bold (optional)","");l.appendChild(G("CSS class",v));const g=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (before text)",g.el));const k=He("e.g. external-link (optional)","");l.appendChild(G("Icon (after text)",k.el));const c=Oe("Open in new tab");l.appendChild(c);const C=c.querySelector("input"),y=document.createElement("div");y.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const m=document.createElement("button");m.type="button",m.className="btn btn-ghost",m.textContent="Cancel";const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.textContent="Insert Link",y.appendChild(m),y.appendChild(p),l.appendChild(y);const r=E.slideover({title:"Insert Link Shortcode",size:"md",position:"right",content:l});r.open(),I.scan(l),m.addEventListener("click",()=>r.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:x=>{n.value=x.value,u.value||(u.value=x.label)}}),n.focus()}),p.addEventListener("click",()=>{const x=n.value.trim();if(!x)return;r.close();const T=u.value.trim()||x;let B=`href="${x}"`;const z=v.value.trim().replace(/"/g,"");z&&(B+=` class="${z}"`);const w=g.input.value.trim().replace(/"/g,"");w&&(B+=` icon="${w}"`);const L=k.input.value.trim().replace(/"/g,"");L&&(B+=` icon-after="${L}"`),C.checked&&(B+=' target="_blank"'),ye(e,`[link ${B}]${T}[/link]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onTabs(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=Le([["","Default"],["pills","Pills"],["bordered","Bordered"]]);t.appendChild(G("Style",a));const l=Le([["","Left"],["center","Centre"],["right","Right"]]);t.appendChild(G("Alignment",l));const n=Le([["","None"],["fade","Fade"]]);t.appendChild(G("Animation",n));const u=Oe("Allow multiple panels open at once"),v=u.querySelector("input");t.appendChild(u);const g=document.createElement("div");g.style.cssText="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",g.textContent="Tabs",t.appendChild(g);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const c=[];function C(){c.forEach(z=>{z.removeBtn.disabled=c.length<=2,z.removeBtn.style.opacity=c.length<=2?"0.3":"1"})}function y(){const z=a.value,w=l.value,L=n.value,f=v.checked,N=[];z&&N.push(`style="${z}"`),w&&N.push(`align="${w}"`),L&&N.push(L),f&&N.push('multiple="true"');let h=`[tabs${N.length?" "+N.join(" "):""}]
|
|
92
|
+
`);for(;A.firstChild;)A.removeChild(A.firstChild);t.forEach((a,l)=>{const n=document.createElement("span");n.className="editor-line-number-row";const u=document.createElement("span");u.className="fold-toggle fold-toggle--empty";const v=document.createElement("span");v.className="editor-line-num",v.textContent=String(l+1),n.appendChild(u),n.appendChild(v),A.appendChild(n)}),A.scrollTop=e.scrollTop}{const e=d.find("#css-editor").get(0);e&&e.addEventListener("scroll",()=>{A.scrollTop=e.scrollTop})}const ze=()=>{ae.refresh(),A.scrollTop=W.scrollTop};W.addEventListener("input",ze),W.addEventListener("scroll",()=>{A.scrollTop=W.scrollTop});let De=null;const V=()=>{clearTimeout(De),De=setTimeout(async()=>{const e=ae.getUnfoldedContent();try{const{html:t}=await Y.pages.preview(e);ee.html(t,{safe:!1}),I.scan(ee.get(0)),ee.get(0).querySelectorAll(".tabs").forEach(a=>Domma.elements.tabs(a))}catch{window.marked&&ee.html(marked.parse(e))}},400)},q=et(pe,d.find("#editor-toolbar"),{spacerDefault:Be});nt(pe.get(0));let ue=!1,Ee="split",ke=null;const he=document.createElement("button");he.className="editor-view-btn",he.type="button";const Te=document.createElement("span");Te.setAttribute("data-icon","css-code"),he.appendChild(Te);const fe=document.createElement("button");fe.className="editor-view-btn",fe.type="button";const Ne=document.createElement("span");Ne.setAttribute("data-icon","code"),fe.appendChild(Ne);let ge=!1;const ie=document.createElement("button");ie.className="editor-view-btn",ie.type="button",ie.textContent="\u25BC\u25BC",ie.style.cssText="font-size:9px;letter-spacing:-1px;";const le=d.find(".editor-toolbar-right").get(0);le.prepend(ie),le.prepend(fe),le.prepend(he),I.scan(he),I.scan(fe),E.tooltip(he,{content:"Edit Custom CSS",position:"top"}),E.tooltip(fe,{content:"Format Markdown",position:"top"}),E.tooltip(ie,{content:"Fold / unfold all shortcodes",position:"top"}),fe.addEventListener("click",()=>{const e=pe.get(0),t=e.selectionStart,a=rt(ae.getUnfoldedContent());ae.unfoldAll(),ne=!0,e.value=a,ne=!1,e.selectionStart=e.selectionEnd=Math.min(t,a.length),e.dispatchEvent(new Event("input")),ae.refresh(),E.toast("Markdown formatted.",{type:"success"})}),ie.addEventListener("click",()=>{ge?(ae.unfoldAll(),ie.textContent="\u25BC\u25BC",ie.classList.remove("active")):(ae.foldAll(),ie.textContent="\u25B6\u25B6",ie.classList.add("active")),ge=!ge});const xe=document.createElement("span");xe.className="editor-toolbar-sep",le.insertBefore(xe,le.children[3]),he.addEventListener("click",()=>{ue=!ue;const e=d.find("#markdown-editor"),t=d.find("#css-editor"),a=d.find("#editor-body");if(ue){const l=d.find(".editor-view-btn[data-mode].active").get(0);Ee=l?l.getAttribute("data-mode"):"split",d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find('.editor-view-btn[data-mode="split"]').addClass("active"),a.removeClass("editor-mode-write editor-mode-preview").addClass("editor-mode-split"),e.hide(),t.show(),oe||(t.val(be),oe=!0,Xe(t.get(0))),me(),he.classList.add("active")}else d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Ee}"]`).addClass("active"),a.removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Ee}`),t.hide(),e.show(),ae.refresh(),he.classList.remove("active")});const Fe=Je();Fe.viewMode&&Fe.viewMode!=="split"&&(d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Fe.viewMode}"]`).addClass("active"),d.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Fe.viewMode}`)),Fe.fullscreen&&d.find(".editor-card").addClass("editor-fullscreen"),d.find("#css-editor").on("input",()=>{me(),clearTimeout(ke),ke=setTimeout(()=>{let e=document.getElementById("preview-custom-css");e||(e=document.createElement("style"),e.id="preview-custom-css",ee.get(0).parentNode.insertBefore(e,ee.get(0))),e.textContent=d.find("#css-editor").val()},400)}),q.onLink(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(r=>({label:r.title||r.urlPath,value:r.urlPath})),a=document.createElement("div");a.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const l=document.createElement("label");l.className="form-label",l.textContent="URL";const n=document.createElement("input");n.type="text",n.className="form-input",n.placeholder="/about or https://example.com";const u=e.value.substring(e.selectionStart,e.selectionEnd);u&&u.startsWith("/")&&(n.value=u),a.appendChild(l),a.appendChild(n);const v=document.createElement("label");v.className="form-label",v.textContent="Link text";const g=document.createElement("input");g.type="text",g.className="form-input",g.placeholder="Display text",u&&!u.startsWith("/")&&(g.value=u),a.appendChild(v),a.appendChild(g);const k=document.createElement("label");k.className="form-label",k.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const c=document.createElement("input");c.type="checkbox",c.style.cssText="width:1rem;height:1rem;cursor:pointer;",k.appendChild(c),k.appendChild(document.createTextNode("Display as button")),a.appendChild(k);const C=document.createElement("label");C.className="form-label",C.textContent="Button colour",C.style.display="none";const y=document.createElement("select");y.className="form-select",y.style.display="none",[["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["outline-success","Outline Success"],["outline-danger","Outline Danger"],["ghost","Ghost"]].forEach(([r,x])=>{const T=document.createElement("option");T.value=r,T.textContent=x,y.appendChild(T)}),a.appendChild(C),a.appendChild(y),c.addEventListener("change",()=>{const r=c.checked;C.style.display=r?"":"none",y.style.display=r?"":"none"});const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Link",a.appendChild(m);const p=E.slideover({title:"Insert Link",size:"md",position:"right",content:a});p.open(),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:r=>{n.value=r.value,g.value||(g.value=r.label)}}),n.focus()}),m.addEventListener("click",()=>{const r=n.value.trim(),x=g.value.trim();if(!r)return;p.close();const T=c.checked?`[button href="${r}" variant="${y.value}"]${x||r}[/button]`:`[${x||r}](${r})`,B=e.selectionStart,z=e.selectionEnd;e.value=e.value.substring(0,B)+T+e.value.substring(z),e.selectionStart=e.selectionEnd=B+T.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onImage(async e=>{const t=(await Y.media.list().catch(()=>[])).filter(n=>/\.(png|jpe?g|gif|webp|svg)$/i.test(n.name)),a=document.createElement("div");if(a.className="media-picker-grid",t.length)t.forEach(n=>{const u=document.createElement("div");u.className="media-picker-item",u.dataset.url=n.url;const v=document.createElement("img");v.src=n.url,v.alt=n.name;const g=document.createElement("span");g.textContent=n.name,u.appendChild(v),u.appendChild(g),a.appendChild(u)});else{const n=document.createElement("p");n.className="text-muted p-3",n.textContent="No images uploaded yet.",a.appendChild(n)}const l=E.slideover({title:"Insert Image",size:"lg",position:"right",content:a});$(l.element).on("click",".media-picker-item",function(){const n=$(this).data("url"),u=$(this).find("span").text();ye(e,``),l.close(),pe.get(0).dispatchEvent(new Event("input",{bubbles:!0}))}),l.open()}),q.onCollection(async e=>{const[t,a]=await Promise.all([Y.collections.list().catch(()=>[]),Y.blocks.list().catch(()=>[])]),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",u="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;",v=document.createElement("div"),g=document.createElement("label");g.style.cssText=n,g.textContent="Collection";const k=document.createElement("select");if(k.style.cssText=u,t.length)t.forEach(H=>{const te=document.createElement("option");te.value=H.slug,te.textContent=H.title||H.slug,k.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No collections found",k.appendChild(H)}v.appendChild(g),v.appendChild(k),l.appendChild(v);const c=document.createElement("div"),C=document.createElement("label");C.style.cssText=n,C.textContent="Display";const y=document.createElement("select");y.style.cssText=u,["table","cards","list","block"].forEach(H=>{const te=document.createElement("option");te.value=H,te.textContent=H.charAt(0).toUpperCase()+H.slice(1),y.appendChild(te)}),c.appendChild(C),c.appendChild(y),l.appendChild(c);const m=document.createElement("div");m.style.display="none";const p=document.createElement("label");p.style.cssText=n,p.textContent="Columns (2\u20134)";const r=document.createElement("input");r.type="number",r.min="2",r.max="4",r.value="3",r.style.cssText=u,m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=document.createElement("div");x.style.display="none";const T=document.createElement("label");T.style.cssText=n,T.textContent="Block template";const B=document.createElement("select");if(B.style.cssText=u,a.length)a.forEach(H=>{const te=document.createElement("option");te.value=H.name??H,te.textContent=H.name??H,B.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No block templates found",B.appendChild(H)}x.appendChild(T),x.appendChild(B),l.appendChild(x);const z=document.createElement("div"),w=document.createElement("label");w.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const L=document.createElement("input");L.type="checkbox",L.checked=!0,w.appendChild(L),w.appendChild(document.createTextNode("Enable search")),z.appendChild(w),l.appendChild(z);const f=document.createElement("div"),N=document.createElement("label");N.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const M=document.createElement("input");M.type="checkbox",M.checked=!0,N.appendChild(M),N.appendChild(document.createTextNode("Sortable columns")),f.appendChild(N),l.appendChild(f);const h=document.createElement("div"),b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const i=document.createElement("input");i.type="checkbox",i.checked=!1,b.appendChild(i),b.appendChild(document.createTextNode("CSV export")),h.appendChild(b),l.appendChild(h);const o=document.createElement("div"),s=document.createElement("label");s.style.cssText=n,s.textContent="Rows per page";const j=document.createElement("input");j.type="number",j.min="5",j.max="100",j.value="25",j.style.cssText=u,o.appendChild(s),o.appendChild(j),l.appendChild(o);const Q=document.createElement("div"),J=document.createElement("label");J.style.cssText=n,J.textContent="Limit (optional)";const K=document.createElement("input");K.type="number",K.placeholder="All",K.style.cssText=u,Q.appendChild(J),Q.appendChild(K),l.appendChild(Q);const P=document.createElement("button");P.type="button",P.className="btn btn-primary",P.textContent="Insert",l.appendChild(P);const F=[z,f,h,o],O=()=>{const H=y.value,te=H==="table";F.forEach(Se=>{Se.style.display=te?"":"none"}),m.style.display=H==="cards"||H==="block"?"":"none",x.style.display=H==="block"?"":"none"};y.addEventListener("change",O),O();const Z=E.slideover({title:"Insert Collection",size:"md",position:"right",content:l});Z.open(),P.addEventListener("click",()=>{const H=k.value;if(!H)return;const te=y.value;let Se=`[collection slug="${H}" display="${te}"`;if(te==="cards"&&(Se+=` columns="${r.value}"`),te==="block"){const _e=B.value;_e&&(Se+=` block="${_e}"`);const Ve=r.value.trim();Ve&&(Se+=` cols="${Ve}"`)}te==="table"&&!L.checked&&(Se+=' search="false"'),te==="table"&&!M.checked&&(Se+=' sortable="false"'),te==="table"&&i.checked&&(Se+=' exportable="true"'),te==="table"&&j.value!=="25"&&(Se+=` page-size="${j.value}"`);const We=K.value.trim();We&&(Se+=` limit="${We}"`),Se+=" /]",Z.close(),ye(e,Se),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBlock(async e=>{let t=[];try{t=await Y.blocks.list()}catch{E.toast("Could not load blocks.",{type:"error"});return}if(!t.length){E.toast("No block templates found. Create one in Blocks first.",{type:"warning"});return}const a=document.createElement("div");a.style.cssText="display:flex;gap:1rem;min-height:320px;";const l=E.slideover({title:"Insert Block",size:"lg",position:"right",content:a}),n=document.createElement("div");n.style.cssText="flex:1;display:flex;flex-direction:column;gap:.75rem;";const u=document.createElement("label");u.className="form-label",u.textContent="Block Template";const v=document.createElement("select");v.className="form-select";const g=document.createElement("option");g.value="",g.textContent="\u2014 select a template \u2014",v.appendChild(g),t.forEach(B=>{const z=document.createElement("option");z.value=B.name,z.textContent=B.name,v.appendChild(z)}),n.appendChild(u),n.appendChild(v);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.5rem;overflow-y:auto;max-height:260px;",n.appendChild(k);const c=document.createElement("button");c.className="btn btn-primary",c.type="button",c.textContent="Insert",c.disabled=!0,n.appendChild(c);const C=document.createElement("div");C.style.cssText="flex:1;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md);padding:.75rem;overflow:auto;background:var(--dm-surface);";const y=document.createElement("p");y.className="text-muted",y.style.cssText="font-size:.8rem;margin:0;",y.textContent="Select a template to see a preview.",C.appendChild(y),a.appendChild(n),a.appendChild(C),l.open();let m=null,p=[];function r(B){return B.replace(/_/g," ").replace(/\b\w/g,z=>z.toUpperCase())}function x(){if(!m)return;const B={};p.forEach(({key:w,input:L})=>{B[w]=L.value});const z=m.replace(/\{\{([\w_]+)\}\}/g,(w,L)=>(B[L]??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"));C.innerHTML=DOMPurify.sanitize(z)}function T(B){k.textContent="",p=[];const z=new Set(["_id","_createdAt","_updatedAt"]),w=new Set;for(const[,L]of B.matchAll(/\{\{([\w_]+)\}\}/g))z.has(L)||w.add(L);if(!w.size){const L=document.createElement("p");L.className="text-muted",L.style.cssText="font-size:.8rem;margin:0;",L.textContent="No editable placeholders in this template.",k.appendChild(L);return}w.forEach(L=>{const f=document.createElement("div"),N=document.createElement("label");N.className="form-label",N.style.cssText="font-size:.8rem;margin-bottom:.2rem;display:block;",N.textContent=r(L);const M=document.createElement("input");M.type="text",M.className="form-input",M.placeholder=r(L),M.addEventListener("input",x),f.appendChild(N),f.appendChild(M),k.appendChild(f),p.push({key:L,input:M})})}v.addEventListener("change",async()=>{const B=v.value;if(!B){m=null,p=[],k.textContent="",C.textContent="",C.appendChild(y),c.disabled=!0;return}m=null,p=[],k.textContent="",c.disabled=!0;try{m=(await Y.blocks.get(B)).content||"",T(m),x(),c.disabled=!1}catch{E.toast("Could not load template.",{type:"error"})}}),c.addEventListener("click",()=>{if(!v.value)return;const B=L=>L.replace(/"/g,""");let z=`template="${B(v.value)}"`;p.forEach(({key:L,input:f})=>{f.value!==""&&(z+=` ${L}="${B(f.value)}"`)});const w=`[block ${z} /]`;ye(e,w),e.dispatchEvent(new Event("input",{bubbles:!0})),l.close(),e.focus()})}),q.onForm(async e=>{const t=await Y.forms.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="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;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="Form";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(C=>{const y=document.createElement("option");y.value=C.slug,y.textContent=C.title||C.slug,g.appendChild(y)});else{const C=document.createElement("option");C.value="",C.textContent="No forms found",g.appendChild(C)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("button");k.className="btn btn-primary btn-sm",k.style.cssText="align-self:flex-end;margin-top:.5rem;",k.textContent="Insert Form",a.appendChild(k);const c=E.slideover({title:"Insert Form",size:"md",position:"right",content:a});c.open(),k.addEventListener("click",()=>{const C=g.value;C&&(ye(e,`[form slug="${C}" /]`),c.close(),pe.get(0).dispatchEvent(new Event("input",{bubbles:!0})))})}),q.onView(async e=>{const t=await Y.views.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="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;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="View";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(p=>{const r=document.createElement("option");r.value=p.slug,r.textContent=p.title||p.slug,g.appendChild(r)});else{const p=document.createElement("option");p.value="",p.textContent="No Views configured yet \u2014 create one under Data \u2192 Views",g.appendChild(p)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("div"),c=document.createElement("label");c.style.cssText=l,c.textContent="Display";const C=document.createElement("select");C.style.cssText=n,["table","cards","list"].forEach(p=>{const r=document.createElement("option");r.value=p,r.textContent=p.charAt(0).toUpperCase()+p.slice(1),C.appendChild(r)}),k.appendChild(c),k.appendChild(C),a.appendChild(k);const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",a.appendChild(y);const m=E.slideover({title:"Insert View",size:"md",position:"right",content:a});m.open(),y.addEventListener("click",()=>{const p=g.value;if(!p)return;const r=`[view slug="${p}" display="${C.value}" /]`;m.close(),ye(e,r),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCta(async e=>{const t=await Y.actions.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l=Le(t.length?t.map(p=>[p.slug,p.title||p.slug]):[["","No Actions configured yet \u2014 create one under Data \u2192 Actions"]]);a.appendChild(G("Action",l));const n=re("Button label","Run");a.appendChild(G("Label",n)),l.addEventListener("change",()=>{const p=t.find(r=>r.slug===l.value);p?.trigger?.label&&(n.value=p.trigger.label)}),t.length&&t[0]?.trigger?.label&&(n.value=t[0].trigger.label);const u=re("Paste entry UUID\u2026","");a.appendChild(G("Entry ID",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["ghost","Ghost"],["danger","Danger"]]);a.appendChild(G("Style",v));const g=He("e.g. check, zap, send (optional)","");a.appendChild(G("Icon",g.el));const k=re("Confirmation message (optional)","");a.appendChild(G("Confirm prompt",k));const c=document.createElement("div");c.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const C=document.createElement("button");C.type="button",C.className="btn btn-ghost",C.textContent="Cancel";const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",c.appendChild(C),c.appendChild(y),a.appendChild(c);const m=E.slideover({title:"Insert CTA Button",size:"md",position:"right",content:a});m.open(),I.scan(a),C.addEventListener("click",()=>m.close()),y.addEventListener("click",()=>{const p=l.value;if(!p)return;const r=u.value.trim().replace(/"/g,""),x=(n.value.trim()||"Run").replace(/\[\/cta\]/gi,""),T=v.value,B=g.input.value.trim().replace(/"/g,""),z=k.value.trim().replace(/"/g,"");let w=`action="${p}" style="${T}"`;r&&(w+=` entry="${r}"`),B&&(w+=` icon="${B}"`),z&&(w+=` confirm="${z}"`),m.close(),ye(e,`[cta ${w}]${x}[/cta]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onButton(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(T=>({label:T.title||T.urlPath,value:T.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Button label",a&&!a.startsWith("/")?a:"");l.appendChild(G("Label",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["ghost","Ghost"],["link","Link"],["outline-success","Outline Success"],["outline-danger","Outline Danger"]]);l.appendChild(G("Variant",v));const g=Le([["","Default"],["sm","Small"],["lg","Large"]]);l.appendChild(G("Size",g));const k=He("e.g. arrow-right, star (optional)","");l.appendChild(G("Icon (before label)",k.el));const c=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (after label)",c.el));const C=Oe("Open in new tab");l.appendChild(C);const y=C.querySelector("input"),m=document.createElement("div");m.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const p=document.createElement("button");p.type="button",p.className="btn btn-ghost",p.textContent="Cancel";const r=document.createElement("button");r.type="button",r.className="btn btn-primary",r.textContent="Insert Button",m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=E.slideover({title:"Insert Button",size:"md",position:"right",content:l});x.open(),I.scan(l),p.addEventListener("click",()=>x.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:T=>{n.value=T.value,u.value||(u.value=T.label)}}),n.focus()}),r.addEventListener("click",()=>{const T=n.value.trim();if(!T)return;x.close();const B=u.value.trim()||T;let z=`href="${T}" variant="${v.value}"`;g.value&&(z+=` size="${g.value}"`);const w=k.input.value.trim().replace(/"/g,"");w&&(z+=` icon="${w}"`);const L=c.input.value.trim().replace(/"/g,"");L&&(z+=` icon-after="${L}"`),y.checked&&(z+=' target="_blank"'),ye(e,`[button ${z}]${B}[/button]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onLinkShortcode(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(x=>({label:x.title||x.urlPath,value:x.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Link text",a&&!a.startsWith("/")?a:"");l.appendChild(G("Link text",u));const v=re("e.g. text-primary, fw-bold (optional)","");l.appendChild(G("CSS class",v));const g=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (before text)",g.el));const k=He("e.g. external-link (optional)","");l.appendChild(G("Icon (after text)",k.el));const c=Oe("Open in new tab");l.appendChild(c);const C=c.querySelector("input"),y=document.createElement("div");y.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const m=document.createElement("button");m.type="button",m.className="btn btn-ghost",m.textContent="Cancel";const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.textContent="Insert Link",y.appendChild(m),y.appendChild(p),l.appendChild(y);const r=E.slideover({title:"Insert Link Shortcode",size:"md",position:"right",content:l});r.open(),I.scan(l),m.addEventListener("click",()=>r.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:x=>{n.value=x.value,u.value||(u.value=x.label)}}),n.focus()}),p.addEventListener("click",()=>{const x=n.value.trim();if(!x)return;r.close();const T=u.value.trim()||x;let B=`href="${x}"`;const z=v.value.trim().replace(/"/g,"");z&&(B+=` class="${z}"`);const w=g.input.value.trim().replace(/"/g,"");w&&(B+=` icon="${w}"`);const L=k.input.value.trim().replace(/"/g,"");L&&(B+=` icon-after="${L}"`),C.checked&&(B+=' target="_blank"'),ye(e,`[link ${B}]${T}[/link]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onTabs(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=Le([["","Default"],["pills","Pills"],["bordered","Bordered"]]);t.appendChild(G("Style",a));const l=Le([["","Left"],["center","Centre"],["right","Right"]]);t.appendChild(G("Alignment",l));const n=Le([["","None"],["fade","Fade"]]);t.appendChild(G("Animation",n));const u=Oe("Allow multiple panels open at once"),v=u.querySelector("input");t.appendChild(u);const g=document.createElement("div");g.style.cssText="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",g.textContent="Tabs",t.appendChild(g);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const c=[];function C(){c.forEach(z=>{z.removeBtn.disabled=c.length<=2,z.removeBtn.style.opacity=c.length<=2?"0.3":"1"})}function y(){const z=a.value,w=l.value,L=n.value,f=v.checked,N=[];z&&N.push(`style="${z}"`),w&&N.push(`align="${w}"`),L&&N.push(L),f&&N.push('multiple="true"');let h=`[tabs${N.length?" "+N.join(" "):""}]
|
|
93
93
|
`;return c.forEach((b,i)=>{const o=b.titleInput.value.trim()||`Tab ${i+1}`,s=b.iconInput.value.trim(),j=s?` title="${o}" icon="${s}"`:` title="${o}"`;h+=`[tab${j}]Tab content here.[/tab]
|
|
94
94
|
`}),h+="[/tabs]",h}function m(z=""){if(c.length>=10)return;const w=document.createElement("div");w.style.cssText="display:flex;gap:.4rem;align-items:center;";const L=re("Tab title",z);L.style.cssText+="flex:1;";const f=He("icon (optional)");f.el.style.flex=".6";const N=document.createElement("button");N.type="button",N.textContent="\xD7",N.style.cssText="padding:.3rem .5rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;flex-shrink:0;";const M={row:w,titleInput:L,iconInput:f.input,removeBtn:N};c.push(M),w.appendChild(L),w.appendChild(f.el),w.appendChild(N),k.appendChild(w),N.addEventListener("click",()=>{if(c.length<=2)return;const h=c.indexOf(M);c.splice(h,1),k.removeChild(w),C(),r(),x.update(y())}),[L,f.input].forEach(h=>h.addEventListener("input",()=>x.update(y()))),C()}m("Overview"),m("Details"),t.appendChild(k);const p=document.createElement("button");p.type="button",p.textContent="+ Add Tab",p.style.cssText="padding:.35rem .75rem;background:transparent;border:1px dashed var(--dm-border,#555);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;align-self:flex-start;",p.addEventListener("click",()=>{m(""),r(),c[c.length-1].titleInput.focus(),x.update(y())}),t.appendChild(p);function r(){p.disabled=c.length>=10}const x=Ue();x.update(y()),t.appendChild(G("Shortcode preview",x.el)),[a,l,n].forEach(z=>z.addEventListener("change",()=>x.update(y()))),v.addEventListener("change",()=>x.update(y()));const T=document.createElement("button");T.type="button",T.className="btn btn-primary",T.textContent="Insert Tabs",t.appendChild(T);const B=E.slideover({title:"Insert Tabs",size:"md",position:"right",content:t});B.open(),requestAnimationFrame(()=>c[0].titleInput.focus()),T.addEventListener("click",()=>{ye(e,y()),B.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCarousel(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=Le([["slide","Slide (default)"],["fade","Fade"],["crossfade","Crossfade"]]);t.appendChild(G("Animation",a));const l=re("e.g. 500","");t.appendChild(G("Animation duration (ms)",l));const n=Le([["","Default (ease)"],["linear","Linear"],["ease","Ease"],["ease-in","Ease in"],["ease-out","Ease out"],["ease-in-out","Ease in-out"]]);t.appendChild(G("Animation easing",n));const u=Oe("Autoplay"),v=u.querySelector("input");t.appendChild(u);const g=re("e.g. 5000","5000");t.appendChild(G("Autoplay interval (ms)",g));const k=Oe("Loop (wrap from last slide back to first)"),c=k.querySelector("input");c.checked=!0,t.appendChild(k);const C=document.createElement("div");C.style.cssText="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",C.textContent="Slides",t.appendChild(C);const y=document.createElement("div");y.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const m=[];function p(){m.forEach(f=>{f.removeBtn.disabled=m.length<=1,f.removeBtn.style.opacity=m.length<=1?"0.3":"1"})}function r(){const f=a.value,N=l.value.trim(),M=n.value,h=v.checked,b=g.value.trim(),i=c.checked,o=[];h&&o.push('autoplay="true"'),h&&b&&b!=="5000"&&o.push(`interval="${b}"`),i||o.push('loop="false"'),f&&f!=="slide"&&o.push(`animation="${f}"`),N&&o.push(`animation-duration="${N}"`),M&&o.push(`animation-easing="${M}"`);let j=`[carousel${o.length?" "+o.join(" "):""}]
|
|
95
95
|
`;return m.forEach((Q,J)=>{const K=Q.titleInput.value.trim(),P=Q.imageInput.value.trim(),F=[];K&&F.push(`title="${K}"`),P&&F.push(`image="${P}"`);const O=F.length?" "+F.join(" "):"";j+=`[slide${O}]Slide ${J+1} content.[/slide]
|
|
96
96
|
`}),j+="[/carousel]",j}function x(f="",N=""){if(m.length>=10)return;const M=document.createElement("div");M.style.cssText="display:flex;gap:.4rem;align-items:center;";const h=re("Slide title (optional)",f);h.style.cssText+="flex:1;";const b=re("/media/photo.jpg (optional)",N);b.style.cssText+="flex:1.2;";const i=document.createElement("button");i.type="button",i.textContent="\xD7",i.style.cssText="padding:.3rem .5rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;flex-shrink:0;";const o={row:M,titleInput:h,imageInput:b,removeBtn:i};m.push(o),M.appendChild(h),M.appendChild(b),M.appendChild(i),y.appendChild(M),i.addEventListener("click",()=>{if(m.length<=1)return;const s=m.indexOf(o);m.splice(s,1),y.removeChild(M),p(),B(),z.update(r())}),[h,b].forEach(s=>s.addEventListener("input",()=>z.update(r()))),p()}x("Slide 1"),x("Slide 2"),t.appendChild(y);const T=document.createElement("button");T.type="button",T.textContent="+ Add Slide",T.style.cssText="padding:.35rem .75rem;background:transparent;border:1px dashed var(--dm-border,#555);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;align-self:flex-start;",T.addEventListener("click",()=>{x(""),B(),m[m.length-1].titleInput.focus(),z.update(r())}),t.appendChild(T);function B(){T.disabled=m.length>=10}const z=Ue();z.update(r()),t.appendChild(G("Shortcode preview",z.el)),[a,n].forEach(f=>f.addEventListener("change",()=>z.update(r()))),[l,g].forEach(f=>f.addEventListener("input",()=>z.update(r()))),[v,c].forEach(f=>f.addEventListener("change",()=>z.update(r())));const w=document.createElement("button");w.type="button",w.className="btn btn-primary",w.textContent="Insert Carousel",t.appendChild(w);const L=E.slideover({title:"Insert Carousel",size:"md",position:"right",content:t});L.open(),requestAnimationFrame(()=>m[0].titleInput.focus()),w.addEventListener("click",()=>{ye(e,r()),L.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onHero(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=re("Hero title");t.appendChild(G("Title",a));const l=re("Tagline (optional)");t.appendChild(G("Tagline",l));const n=Le([["sm","Small"],["md","Medium (default)"],["lg","Large"],["full","Full"]]);n.value="md",t.appendChild(G("Size",n));const u=Le([["","Left"],["center","Centre"],["right","Right"]]);t.appendChild(G("Alignment",u));const v=document.createElement("div");v.style.cssText="display:flex;gap:.75rem;align-items:center;";const g={};["none","colour","image"].forEach(f=>{const N=document.createElement("label");N.style.cssText="display:flex;align-items:center;gap:.3rem;font-size:.9em;cursor:pointer;";const M=document.createElement("input");M.type="radio",M.name="hero-bg",M.value=f,f==="none"&&(M.checked=!0),g[f]=M,N.appendChild(M),N.appendChild(document.createTextNode(f.charAt(0).toUpperCase()+f.slice(1))),v.appendChild(N)}),t.appendChild(G("Background",v));const k=re("#hex or CSS colour"),c=G("Colour",k);c.style.display="none",t.appendChild(c);const C=re("/media/hero.jpg"),y=Le([["","None"],["dark","Dark"],["light","Light"]]),m=document.createElement("div");m.style.cssText="display:none;flex-direction:column;gap:.5rem;",m.appendChild(G("Image path",C)),m.appendChild(G("Overlay",y)),t.appendChild(m);const p=re("e.g. 400px");t.appendChild(G("Min height",p));const r=Oe("Full-width (break out of page container to span viewport)");t.appendChild(r);const x=r.querySelector("input");function T(){const f=a.value.trim(),N=l.value.trim(),M=n.value,h=u.value,b=Object.keys(g).find(K=>g[K].checked)||"none",i=k.value.trim(),o=C.value.trim(),s=y.value,j=p.value.trim(),Q=x.checked,J=[`title="${f}"`];return N&&J.push(`tagline="${N}"`),M&&M!=="md"&&J.push(`size="${M}"`),h&&J.push(`align="${h}"`),b==="colour"&&i&&J.push(`color="${i}"`),b==="image"&&o&&J.push(`image="${o}"`),b==="image"&&s&&J.push(`overlay="${s}"`),j&&J.push(`min-height="${j}"`),Q&&J.push('fullwidth="true"'),`[hero ${J.join(" ")}]
|
|
97
97
|
Content here.
|
|
98
|
-
[/hero]`}const B=Ue();B.update(T()),t.appendChild(G("Shortcode preview",B.el));function z(){const f=Object.keys(g).find(N=>g[N].checked)||"none";c.style.display=f==="colour"?"":"none",m.style.display=f==="image"?"flex":"none",B.update(T())}Object.values(g).forEach(f=>f.addEventListener("change",z)),[a,l,k,C,p].forEach(f=>f.addEventListener("input",()=>B.update(T()))),[n,u,y].forEach(f=>f.addEventListener("change",()=>B.update(T()))),x.addEventListener("change",()=>B.update(T()));const w=document.createElement("button");w.type="button",w.className="btn btn-primary",w.textContent="Insert Hero",t.appendChild(w);const L=E.slideover({title:"Insert Hero",size:"md",position:"right",content:t});L.open(),requestAnimationFrame(()=>a.focus()),w.addEventListener("click",()=>{ye(e,T()),L.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBanner(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=[{value:"info",label:"Info",color:"
|
|
98
|
+
[/hero]`}const B=Ue();B.update(T()),t.appendChild(G("Shortcode preview",B.el));function z(){const f=Object.keys(g).find(N=>g[N].checked)||"none";c.style.display=f==="colour"?"":"none",m.style.display=f==="image"?"flex":"none",B.update(T())}Object.values(g).forEach(f=>f.addEventListener("change",z)),[a,l,k,C,p].forEach(f=>f.addEventListener("input",()=>B.update(T()))),[n,u,y].forEach(f=>f.addEventListener("change",()=>B.update(T()))),x.addEventListener("change",()=>B.update(T()));const w=document.createElement("button");w.type="button",w.className="btn btn-primary",w.textContent="Insert Hero",t.appendChild(w);const L=E.slideover({title:"Insert Hero",size:"md",position:"right",content:t});L.open(),requestAnimationFrame(()=>a.focus()),w.addEventListener("click",()=>{ye(e,T()),L.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBanner(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=[{value:"info",label:"Info",color:"var(--dm-info)"},{value:"success",label:"Success",color:"var(--dm-success)"},{value:"warning",label:"Warning",color:"var(--dm-warning)"},{value:"danger",label:"Danger",color:"var(--dm-danger)"},{value:"neutral",label:"Neutral",color:"var(--dm-text-muted)"}];let l="info";const n=document.createElement("div");n.style.cssText="display:flex;gap:.35rem;flex-wrap:wrap;";const u={};a.forEach(r=>{const x=document.createElement("button");x.type="button",x.style.cssText="display:flex;align-items:center;gap:.3rem;padding:.3rem .6rem;border:1px solid var(--dm-border,#333);border-radius:4px;background:transparent;color:var(--dm-text,#eee);cursor:pointer;font-size:.85em;";const T=document.createElement("span");T.style.cssText=`display:inline-block;width:.55rem;height:.55rem;border-radius:50%;background:${r.color};flex-shrink:0;`,x.appendChild(T),x.appendChild(document.createTextNode(r.label)),u[r.value]=x,n.appendChild(x),x.addEventListener("click",()=>{l=r.value,Object.entries(u).forEach(([B,z])=>{z.style.borderColor=B===l?r.color:"var(--dm-border,#333)",z.style.background=B===l?`color-mix(in srgb, ${r.color} 13%, transparent)`:"transparent"}),y.update(C())})}),u.info.style.borderColor="var(--dm-info)",u.info.style.background="color-mix(in srgb, var(--dm-info) 13%, transparent)",t.appendChild(G("Type",n));const v=re("Title (optional)");t.appendChild(G("Title",v));const g=He("Icon name (optional)");t.appendChild(G("Icon",g.el));const k=Oe("Dismissible"),c=k.querySelector("input");t.appendChild(k);function C(){const r=[];l!=="info"&&r.push(`type="${l}"`);const x=v.value.trim();x&&r.push(`title="${x}"`);const T=g.input.value.trim();return T&&r.push(`icon="${T}"`),c.checked&&r.push("dismissible"),`[banner${r.length?" "+r.join(" "):""}]
|
|
99
99
|
Banner content here.
|
|
100
100
|
[/banner]`}const y=Ue();y.update(C()),t.appendChild(G("Shortcode preview",y.el)),[v,g.input].forEach(r=>r.addEventListener("input",()=>y.update(C()))),c.addEventListener("change",()=>y.update(C()));const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Banner",t.appendChild(m);const p=E.slideover({title:"Insert Banner",size:"md",position:"right",content:t});p.open(),requestAnimationFrame(()=>v.focus()),m.addEventListener("click",()=>{ye(e,C()),p.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onScribe(e=>lt(e)),q.onGrid(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",l="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;";function n(J,K){const P=document.createElement("div"),F=document.createElement("label");return F.style.cssText=a,F.textContent=J,P.appendChild(F),P.appendChild(K),P}function u(J){const K=document.createElement("select");return K.style.cssText=l,J.forEach(([P,F])=>{const O=document.createElement("option");O.value=P,O.textContent=F,K.appendChild(O)}),K}let v="grid";const g=document.createElement("div");g.style.cssText="display:flex;gap:.5rem;";const k=document.createElement("button");k.type="button",k.className="btn btn-sm btn-primary",k.textContent="Grid";const c=document.createElement("button");c.type="button",c.className="btn btn-sm btn-ghost",c.textContent="Row",g.appendChild(k),g.appendChild(c),t.appendChild(g);const C=document.createElement("input");C.type="number",C.min="1",C.max="12",C.value="2",C.style.cssText=l,t.appendChild(n("Columns",C));const y=u([["0","0"],["1","1"],["2","2"],["3","3"],["4","4 (default)"],["6","6"],["8","8"],["10","10"],["12","12"],["16","16"]]);y.value="4",t.appendChild(n("Gap",y));const m=document.createElement("div");m.style.cssText="display:flex;flex-direction:column;gap:.5rem;";const p=document.createElement("label");p.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const r=document.createElement("input");r.type="checkbox",p.appendChild(r),p.appendChild(document.createTextNode("Full width (breakout)")),m.appendChild(p);const x=document.createElement("div");x.style.cssText=a+"margin-top:.25rem;",x.textContent="Column Spans",m.appendChild(x);const T=document.createElement("div");T.style.cssText="display:flex;flex-direction:column;gap:.3rem;",m.appendChild(T),t.appendChild(m);const B=[];function z(){const J=Math.min(Math.max(parseInt(C.value)||2,1),12),K=B.map(P=>P.value);T.textContent="",B.length=0;for(let P=0;P<J;P++){const F=document.createElement("div");F.style.cssText="display:flex;align-items:center;gap:.5rem;";const O=document.createElement("span");O.style.cssText="font-size:.85em;color:var(--dm-text-muted,#aaa);white-space:nowrap;min-width:3em;",O.textContent=`Col ${P+1}`;const Z=document.createElement("input");Z.type="number",Z.min="1",Z.max="12",Z.placeholder="auto",Z.value=K[P]||"",Z.style.cssText=l+"width:5em;flex:none;",F.appendChild(O),F.appendChild(Z),T.appendChild(F),B.push(Z)}}C.addEventListener("input",z),z();const w=document.createElement("div");w.style.cssText="display:none;flex-direction:column;gap:.5rem;";const L=document.createElement("label");L.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const f=document.createElement("input");f.type="checkbox",L.appendChild(f),L.appendChild(document.createTextNode("Enable staggered reveal")),w.appendChild(L);const N=document.createElement("div");N.style.cssText="display:none;flex-direction:column;gap:.5rem;padding-left:.5rem;border-left:2px solid var(--dm-border,#333);";const M=u([["slide-up","Slide Up"],["slide-down","Slide Down"],["slide-left","Slide Left"],["slide-right","Slide Right"],["fade","Fade"],["zoom","Zoom"],["flip","Flip"]]);N.appendChild(n("Animation",M));const h=u([["stagger","Stagger"],["sequence","Sequence"]]);N.appendChild(n("Mode",h));const b=document.createElement("input");b.type="number",b.value="400",b.style.cssText=l,N.appendChild(n("Duration (ms)",b));const i=document.createElement("input");i.type="number",i.value="60",i.style.cssText=l,N.appendChild(n("Stagger (ms)",i));const o=document.createElement("input");o.type="number",o.value="0",o.style.cssText=l,N.appendChild(n("Delay (ms)",o));const s=u([["ltr","Left to Right"],["rtl","Right to Left"]]);N.appendChild(n("Direction",s)),w.appendChild(N),t.appendChild(w),f.addEventListener("change",()=>{N.style.display=f.checked?"flex":"none"});const j=document.createElement("button");j.type="button",j.className="btn btn-primary",j.textContent="Insert Grid",t.appendChild(j),k.addEventListener("click",()=>{v="grid",k.className="btn btn-sm btn-primary",c.className="btn btn-sm btn-ghost",m.style.display="flex",w.style.display="none",j.textContent="Insert Grid"}),c.addEventListener("click",()=>{v="row",c.className="btn btn-sm btn-primary",k.className="btn btn-sm btn-ghost",w.style.display="flex",m.style.display="none",j.textContent="Insert Row"});const Q=E.slideover({title:"Insert Grid / Row",size:"md",position:"right",content:t});Q.open(),requestAnimationFrame(()=>C.focus()),j.addEventListener("click",()=>{Q.close();const J=Math.min(Math.max(parseInt(C.value)||2,1),12),K=y.value;let P;if(v==="grid"){let F=`cols="${J}"`;K!=="4"&&(F+=` gap="${K}"`),r.checked&&(F+=' fullwidth="true"'),P=`[grid ${F}]
|
|
101
101
|
`;for(let O=0;O<J;O++){const Z=B[O]?.value?.trim(),H=Z?` span="${Z}"`:"";P+=`[col${H}]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{api as
|
|
1
|
+
import{api as k}from"../api.js";import{openQuickCreate as x,INLINE_TYPES as N}from"../lib/project-quick-create.js";function o(n){return String(n??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}const U=[{key:"pages",label:"Pages",singular:"Page",icon:"file-text",color:"var(--dm-primary)",path:"/pages/new"},{key:"collections",label:"Collections",singular:"Collection",icon:"database",color:"var(--dm-secondary)",path:"/collections/new"},{key:"forms",label:"Forms",singular:"Form",icon:"layout",color:"var(--dm-success)",path:"/forms/new"},{key:"actions",label:"Actions",singular:"Action",icon:"zap",color:"var(--dm-warning)",path:"/actions/new"},{key:"menus",label:"Menus",singular:"Menu",icon:"menu",color:"var(--dm-info)",path:"/menus/new"},{key:"blocks",label:"Blocks",singular:"Block",icon:"box",color:"var(--dm-primary-hover)",path:"/blocks/new"},{key:"components",label:"Components",singular:"Component",icon:"component",color:"var(--dm-warning-dark)",path:"/components/new"},{key:"views",label:"Views",singular:"View",icon:"eye",color:"var(--dm-info)",path:"/views/new"},{key:"roles",label:"Roles",singular:"Role",icon:"shield",color:"var(--dm-danger)",path:"/roles"},{key:"users",label:"Users",singular:"User",icon:"users",color:"var(--dm-primary-dark)",path:"/users/new"},{key:"apis",label:"APIs",singular:"API Endpoint",icon:"code",color:"var(--dm-success)",path:"/api-endpoints/new"}];function Y(n){if(!n)return null;const c=new Date(n).getTime();if(Number.isNaN(c))return null;const s=Math.max(0,Math.round((Date.now()-c)/1e3)),t=Math.round(s/60),e=Math.round(t/60),r=Math.round(e/24);if(s<45)return"just now";if(t<60)return`${t} min${t===1?"":"s"} ago`;if(e<24)return`${e} hour${e===1?"":"s"} ago`;if(r<30)return`${r} day${r===1?"":"s"} ago`;const l=Math.round(r/30);if(l<12)return`${l} month${l===1?"":"s"} ago`;const i=Math.round(r/365);return`${i} year${i===1?"":"s"} ago`}function b(n,c){if(!n)return null;const s=new Date(n);if(Number.isNaN(s.getTime()))return null;try{return D(n).format(c)}catch{return s.toLocaleDateString()}}function g({icon:n,color:c,key:s,value:t,title:e}){if(t==null||t==="")return"";const r=`color:${c};background:color-mix(in srgb, ${c} 12%, transparent);border-color:color-mix(in srgb, ${c} 25%, transparent)`,l=e?` title="${o(e)}"`:"";return`<span class="pd-meta-badge" style="${r}"${l}><span data-icon="${o(n)}"></span><span class="pd-meta-k">${o(s)}</span><span class="pd-meta-v">${o(t)}</span></span>`}export const projectDetailView={templateUrl:"/admin/js/templates/project-detail.html",async onMount(n){const s=location.hash.split("?")[0].match(/^#\/projects\/([^/]+)$/),t=s?decodeURIComponent(s[1]):null;if(!t){location.hash="#/projects";return}const e=await k.projects.get(t).catch(()=>null);if(!e){E.toast("Project not found.",{type:"error"}),location.hash="#/projects";return}const r=encodeURIComponent(t);n.find("#pd-name").text(e.name||t),n.find("#pd-icon").attr("data-icon",e.icon||"folder"),n.find("#pd-desc").text(e.description||""),n.find("#pd-settings").attr("href","#/projects/"+r+"/settings");const l=[g({icon:"calendar",color:"var(--dm-primary)",key:"Created",value:b(e.createdAt,"D MMM YYYY")}),g({icon:"user",color:"var(--dm-secondary)",key:"Creator",value:e.createdBy||"Unknown"}),g({icon:"clock",color:"var(--dm-success)",key:"Updated",value:Y(e.updatedAt),title:b(e.updatedAt,"D MMM YYYY, HH:mm")})].join("");n.find("#pd-meta").html(l,{safe:!1}),Domma.icons.scan(n.find(".pd-hero").get(0));const i=n.find("#pd-counts"),w=n.find("#pd-total"),v={slug:t,name:e.name||t,rootUrl:e.rootUrl||""};async function h(){const p=await k.projects.artefacts(t).catch(()=>({}));let d=0;const m=U.map(a=>{const u=Array.isArray(p[a.key])?p[a.key].length:0;d+=u;const j=N.includes(a.key),f=`<span class="pd-tile-chip" style="color:${a.color};background:color-mix(in srgb, ${a.color} 12%, transparent)"><span data-icon="${o(a.icon)}"></span></span>`,y=`<span class="pd-tile-body"><span class="pd-tile-count">${u}</span><span class="pd-tile-label">${o(a.label)}</span></span>`,M=u>0?`<a class="pd-tile-link" href="#/projects/${r}/${o(a.key)}">${f}${y}</a>`:`<div class="pd-tile-link pd-tile-link--empty">${f}${y}</div>`,C=`<button class="pd-tile-add" data-type="${o(a.key)}" data-inline="${j?"1":""}" data-path="${o(a.path)}" title="New ${o(a.singular)}" aria-label="New ${o(a.singular)}"><span data-icon="plus"></span></button>`;return`<div class="pd-tile${u>0?" pd-tile--link":""}" style="--c:${a.color}">${M}${C}</div>`});i.html(`<div class="pd-tiles">${m.join("")}</div>`,{safe:!1}),w.text(d===1?"1 artefact":`${d} artefacts`),Domma.icons.scan(i.get(0))}await h(),i.off("click",".pd-tile-add").on("click",".pd-tile-add",function(){const p=$(this).data("type");if($(this).data("inline")){x({type:p,project:v,onCreated:h});return}const d=$(this).data("path"),m=String(d).includes("?")?"&":"?";location.hash="#"+d+m+"project="+encodeURIComponent(t)}),Domma.icons.scan(n.get(0))}};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{api as C,apiRequest as v}from"../api.js";import{populateThemeSelect as w}from"../lib/themes.js";export const settingsView={templateUrl:"/admin/js/templates/settings.html",async onMount(e){E.tabs(e.find("#settings-tabs").get(0));const k=E.loader(e.get(0),{type:"dots"}),l=await C.settings.get().catch(()=>({}));if(k.destroy(),e.find("#field-site-title").val(l.title||""),e.find("#field-tagline").val(l.tagline||""),e.find("#field-font-family").val(l.fontFamily||"Roboto"),e.find("#field-font-size").val(l.fontSize||16),w(e.find("#field-theme").get(0)),w(e.find("#field-admin-theme").get(0),{includeAdmin:!0}),e.find("#field-theme").val(l.baseTheme||l.theme||"charcoal-dark"),l.baseTheme){e.find("#field-theme").prop("disabled",!0);const t=document.createElement("p");t.className="form-hint",t.style.cssText="margin-top:.4rem;font-size:.8rem;color:var(--dm-info);";const s=document.createElement("a");s.href="#/plugins/theme-roller",s.textContent="Theme Roller",t.appendChild(document.createTextNode(`Custom theme \u201C${l.theme}\u201D is active (based on ${l.baseTheme}). Manage via `)),t.appendChild(s),t.appendChild(document.createTextNode(".")),e.find("#field-theme").get(0).closest(".col-6").appendChild(t)}e.find("#field-admin-theme").val(l.adminTheme||"charcoal-dark");const p=l.autoTheme||{},h=!!p.enabled,b=e.find("#field-auto-theme-enabled"),y=e.find("#auto-theme-fields"),u=e.find("#field-theme"),f=u.get(0).innerHTML;e.find("#field-day-theme").html(f),e.find("#field-night-theme").html(f),l.baseTheme?(b.prop("disabled",!0),e.find("#auto-theme-roller-hint").show()):(b.prop("checked",h),h&&(y.show(),u.prop("disabled",!0)),b.on("change",function(){const t=this.checked;y.toggle(t),u.prop("disabled",t)})),e.find("#field-day-theme").val(p.dayTheme||"charcoal-light"),e.find("#field-night-theme").val(p.nightTheme||"charcoal-dark"),e.find("#field-day-start").val(p.dayStart||"07:00"),e.find("#field-night-start").val(p.nightStart||"19:00"),e.find("#field-spacer-size").val(l.layoutOptions?.spacerSize??40),e.find("#field-seo-title").val(l.seo?.defaultTitle||""),e.find("#field-seo-separator").val(l.seo?.titleSeparator||" | "),e.find("#field-seo-desc").val(l.seo?.defaultDescription||""),e.find("#field-footer-copy").val(l.footer?.copyright||""),e.find("#field-social-twitter").val(l.social?.twitter||""),e.find("#field-social-facebook").val(l.social?.facebook||""),e.find("#field-social-instagram").val(l.social?.instagram||""),e.find("#field-social-linkedin").val(l.social?.linkedin||""),e.find("#field-social-github").val(l.social?.github||""),e.find("#field-social-youtube").val(l.social?.youtube||""),e.find("#field-smtp-host").val(l.smtp?.host||""),e.find("#field-smtp-port").val(l.smtp?.port||587),e.find("#field-smtp-user").val(l.smtp?.user||""),e.find("#field-smtp-pass").val(l.smtp?.pass||""),e.find("#field-smtp-secure").prop("checked",l.smtp?.secure||!1),e.find("#field-smtp-from-address").val(l.smtp?.fromAddress||""),e.find("#field-smtp-from-name").val(l.smtp?.fromName||"");const i=l.backToTop||{};e.find("#field-btt-enabled").prop("checked",i.enabled!==!1),e.find("#field-btt-threshold").val(i.scrollThreshold??300),e.find("#field-btt-position").val(i.position||"bottom-right"),e.find("#field-btt-offset").val(i.offset??32),e.find("#field-btt-bottom-offset").val(i.bottomOffset??i.offset??32),e.find("#field-btt-label").val(i.label||""),e.find("#field-btt-smooth").prop("checked",i.smooth!==!1);const d=l.cookieConsent||{};e.find("#field-cc-enabled").prop("checked",d.enabled!==!1),e.find("#field-cc-message").val(d.message||""),e.find("#field-cc-accept-all").val(d.acceptAllText||"Accept All"),e.find("#field-cc-reject-all").val(d.rejectAllText||"Reject All"),e.find("#field-cc-customize").val(d.customizeText||"Customize"),e.find("#field-cc-save-prefs").val(d.savePreferencesText||"Save Preferences"),e.find("#field-cc-privacy-text").val(d.privacyPolicyText||"Privacy Policy"),e.find("#field-cc-privacy-url").val(d.privacyPolicyUrl||""),e.find("#field-cc-cookie-text").val(d.cookiePolicyText||"Cookie Policy"),e.find("#field-cc-cookie-url").val(d.cookiePolicyUrl||""),e.find("#field-cc-position").val(d.position||"bottom"),e.find("#field-cc-layout").val(d.layout||"bar"),e.find("#field-cc-theme").val(d.theme||"dark"),e.find("#field-cc-show-functional").prop("checked",d.showFunctional!==!1),e.find("#field-cc-show-analytics").prop("checked",d.showAnalytics!==!1),e.find("#field-cc-show-marketing").prop("checked",d.showMarketing!==!1),e.find("#field-cc-version").val(d.consentVersion||"1.0");const
|
|
1
|
+
import{api as C,apiRequest as v}from"../api.js";import{populateThemeSelect as w}from"../lib/themes.js";export const settingsView={templateUrl:"/admin/js/templates/settings.html",async onMount(e){E.tabs(e.find("#settings-tabs").get(0));const k=E.loader(e.get(0),{type:"dots"}),l=await C.settings.get().catch(()=>({}));if(k.destroy(),e.find("#field-site-title").val(l.title||""),e.find("#field-tagline").val(l.tagline||""),e.find("#field-font-family").val(l.fontFamily||"Roboto"),e.find("#field-font-size").val(l.fontSize||16),w(e.find("#field-theme").get(0)),w(e.find("#field-admin-theme").get(0),{includeAdmin:!0}),e.find("#field-theme").val(l.baseTheme||l.theme||"charcoal-dark"),l.baseTheme){e.find("#field-theme").prop("disabled",!0);const t=document.createElement("p");t.className="form-hint",t.style.cssText="margin-top:.4rem;font-size:.8rem;color:var(--dm-info);";const s=document.createElement("a");s.href="#/plugins/theme-roller",s.textContent="Theme Roller",t.appendChild(document.createTextNode(`Custom theme \u201C${l.theme}\u201D is active (based on ${l.baseTheme}). Manage via `)),t.appendChild(s),t.appendChild(document.createTextNode(".")),e.find("#field-theme").get(0).closest(".col-6").appendChild(t)}e.find("#field-admin-theme").val(l.adminTheme||"charcoal-dark");const p=l.autoTheme||{},h=!!p.enabled,b=e.find("#field-auto-theme-enabled"),y=e.find("#auto-theme-fields"),u=e.find("#field-theme"),f=u.get(0).innerHTML;e.find("#field-day-theme").html(f),e.find("#field-night-theme").html(f),l.baseTheme?(b.prop("disabled",!0),e.find("#auto-theme-roller-hint").show()):(b.prop("checked",h),h&&(y.show(),u.prop("disabled",!0)),b.on("change",function(){const t=this.checked;y.toggle(t),u.prop("disabled",t)})),e.find("#field-day-theme").val(p.dayTheme||"charcoal-light"),e.find("#field-night-theme").val(p.nightTheme||"charcoal-dark"),e.find("#field-day-start").val(p.dayStart||"07:00"),e.find("#field-night-start").val(p.nightStart||"19:00"),e.find("#field-spacer-size").val(l.layoutOptions?.spacerSize??40),e.find("#field-seo-title").val(l.seo?.defaultTitle||""),e.find("#field-seo-separator").val(l.seo?.titleSeparator||" | "),e.find("#field-seo-desc").val(l.seo?.defaultDescription||""),e.find("#field-footer-copy").val(l.footer?.copyright||""),e.find("#field-social-twitter").val(l.social?.twitter||""),e.find("#field-social-facebook").val(l.social?.facebook||""),e.find("#field-social-instagram").val(l.social?.instagram||""),e.find("#field-social-linkedin").val(l.social?.linkedin||""),e.find("#field-social-github").val(l.social?.github||""),e.find("#field-social-youtube").val(l.social?.youtube||""),e.find("#field-smtp-host").val(l.smtp?.host||""),e.find("#field-smtp-port").val(l.smtp?.port||587),e.find("#field-smtp-user").val(l.smtp?.user||""),e.find("#field-smtp-pass").val(l.smtp?.pass||""),e.find("#field-smtp-secure").prop("checked",l.smtp?.secure||!1),e.find("#field-smtp-from-address").val(l.smtp?.fromAddress||""),e.find("#field-smtp-from-name").val(l.smtp?.fromName||"");const i=l.backToTop||{};e.find("#field-btt-enabled").prop("checked",i.enabled!==!1),e.find("#field-btt-threshold").val(i.scrollThreshold??300),e.find("#field-btt-position").val(i.position||"bottom-right"),e.find("#field-btt-offset").val(i.offset??32),e.find("#field-btt-bottom-offset").val(i.bottomOffset??i.offset??32),e.find("#field-btt-label").val(i.label||""),e.find("#field-btt-smooth").prop("checked",i.smooth!==!1);const d=l.cookieConsent||{};e.find("#field-cc-enabled").prop("checked",d.enabled!==!1),e.find("#field-cc-message").val(d.message||""),e.find("#field-cc-accept-all").val(d.acceptAllText||"Accept All"),e.find("#field-cc-reject-all").val(d.rejectAllText||"Reject All"),e.find("#field-cc-customize").val(d.customizeText||"Customize"),e.find("#field-cc-save-prefs").val(d.savePreferencesText||"Save Preferences"),e.find("#field-cc-privacy-text").val(d.privacyPolicyText||"Privacy Policy"),e.find("#field-cc-privacy-url").val(d.privacyPolicyUrl||""),e.find("#field-cc-cookie-text").val(d.cookiePolicyText||"Cookie Policy"),e.find("#field-cc-cookie-url").val(d.cookiePolicyUrl||""),e.find("#field-cc-position").val(d.position||"bottom"),e.find("#field-cc-layout").val(d.layout||"bar"),e.find("#field-cc-theme").val(d.theme||"dark"),e.find("#field-cc-show-functional").prop("checked",d.showFunctional!==!1),e.find("#field-cc-show-analytics").prop("checked",d.showAnalytics!==!1),e.find("#field-cc-show-marketing").prop("checked",d.showMarketing!==!1),e.find("#field-cc-version").val(d.consentVersion||"1.0");const n=l.breadcrumbs||{};e.find("#field-breadcrumbs-enabled").prop("checked",n.enabled===!0),e.find("#field-breadcrumbs-home-label").val(n.homeLabel||"Home"),e.find("#field-breadcrumbs-position").val(n.position||"TL"),e.find("#field-bc-offset-x").val(n.offsetX??8),e.find("#field-bc-offset-y").val(n.offsetY??8);function c(t){e.find(".bc-pos-btn").each(function(){const s=this.dataset.pos===t;this.style.background=s?"var(--dm-primary, #5b8cff)":"",this.style.color=s?"var(--dm-primary-text)":""})}c(n.position||"TL"),e.find(".bc-pos-btn").on("click",function(){const t=this.dataset.pos;e.find("#field-breadcrumbs-position").val(t),c(t)});let a=null;try{const{css:t}=await v("/settings/custom-css");e.find("#field-custom-css").val(t||""),E.editor&&(a=E.editor(e.find("#field-custom-css").get(0),{mode:"code",language:"css",lineNumbers:!0,showToolbar:!1,minHeight:420,placeholder:"/* Add your custom CSS here */",characterCount:!0}))}catch{}a&&a._editorEl&&a._editorEl.addEventListener("keydown",t=>{if(!t.ctrlKey&&!t.metaKey)return;if(t.key==="s"){t.preventDefault(),e.find("#save-css-btn").get(0)?.click();return}const s=a._editorEl,m=s.selectionStart!==s.selectionEnd;if((t.key==="c"||t.key==="x")&&!m){t.preventDefault();const o=s.value,g=s.selectionStart,T=o.lastIndexOf(`
|
|
2
2
|
`,g-1)+1,x=o.indexOf(`
|
|
3
|
-
`,g),S=x===-1?o.slice(T):o.slice(T,x+1);if(navigator.clipboard.writeText(S),t.key==="x"){const z=o.slice(0,T),P=x===-1?"":o.slice(x+1);s.value=z+P,s.selectionStart=s.selectionEnd=T,s.dispatchEvent(new Event("input",{bubbles:!0})),E.toast("Line cut",{type:"info",duration:1500})}else E.toast("Line copied",{type:"info",duration:1500})}}),e.find("#save-settings-btn").on("click",async()=>{const t=e.find("#field-admin-theme").val(),s=!l.baseTheme&&e.find("#field-auto-theme-enabled").prop("checked"),
|
|
3
|
+
`,g),S=x===-1?o.slice(T):o.slice(T,x+1);if(navigator.clipboard.writeText(S),t.key==="x"){const z=o.slice(0,T),P=x===-1?"":o.slice(x+1);s.value=z+P,s.selectionStart=s.selectionEnd=T,s.dispatchEvent(new Event("input",{bubbles:!0})),E.toast("Line cut",{type:"info",duration:1500})}else E.toast("Line copied",{type:"info",duration:1500})}}),e.find("#save-settings-btn").on("click",async()=>{const t=e.find("#field-admin-theme").val(),s=!l.baseTheme&&e.find("#field-auto-theme-enabled").prop("checked"),m={enabled:s,dayTheme:e.find("#field-day-theme").val()||"charcoal-light",nightTheme:e.find("#field-night-theme").val()||"charcoal-dark",dayStart:e.find("#field-day-start").val()||"07:00",nightStart:e.find("#field-night-start").val()||"19:00"},o={title:e.find("#field-site-title").val().trim(),tagline:e.find("#field-tagline").val().trim(),fontFamily:e.find("#field-font-family").val()||"Roboto",fontSize:parseInt(e.find("#field-font-size").val(),10)||16,theme:l.baseTheme?l.theme:s?m.dayTheme:e.find("#field-theme").val(),...l.baseTheme?{baseTheme:l.baseTheme}:{},autoTheme:m,adminTheme:t,layoutOptions:{spacerSize:parseInt(e.find("#field-spacer-size").val(),10)||40},seo:{defaultTitle:e.find("#field-seo-title").val().trim(),titleSeparator:e.find("#field-seo-separator").val()||" | ",defaultDescription:e.find("#field-seo-desc").val().trim()},footer:{copyright:e.find("#field-footer-copy").val().trim(),links:l.footer?.links||[]},social:{twitter:e.find("#field-social-twitter").val().trim(),facebook:e.find("#field-social-facebook").val().trim(),instagram:e.find("#field-social-instagram").val().trim(),linkedin:e.find("#field-social-linkedin").val().trim(),github:e.find("#field-social-github").val().trim(),youtube:e.find("#field-social-youtube").val().trim()},smtp:{host:e.find("#field-smtp-host").val().trim(),port:parseInt(e.find("#field-smtp-port").val(),10)||587,user:e.find("#field-smtp-user").val().trim(),pass:e.find("#field-smtp-pass").val(),secure:e.find("#field-smtp-secure").prop("checked"),fromAddress:e.find("#field-smtp-from-address").val().trim(),fromName:e.find("#field-smtp-from-name").val().trim()},backToTop:{enabled:e.find("#field-btt-enabled").prop("checked"),scrollThreshold:parseInt(e.find("#field-btt-threshold").val(),10)||300,position:e.find("#field-btt-position").val()||"bottom-right",offset:parseInt(e.find("#field-btt-offset").val(),10)||32,bottomOffset:parseInt(e.find("#field-btt-bottom-offset").val(),10)||32,label:e.find("#field-btt-label").val().trim(),smooth:e.find("#field-btt-smooth").prop("checked")},cookieConsent:{enabled:e.find("#field-cc-enabled").prop("checked"),message:e.find("#field-cc-message").val().trim(),acceptAllText:e.find("#field-cc-accept-all").val().trim(),rejectAllText:e.find("#field-cc-reject-all").val().trim(),customizeText:e.find("#field-cc-customize").val().trim(),savePreferencesText:e.find("#field-cc-save-prefs").val().trim(),privacyPolicyText:e.find("#field-cc-privacy-text").val().trim(),privacyPolicyUrl:e.find("#field-cc-privacy-url").val().trim(),cookiePolicyText:e.find("#field-cc-cookie-text").val().trim(),cookiePolicyUrl:e.find("#field-cc-cookie-url").val().trim(),position:e.find("#field-cc-position").val(),layout:e.find("#field-cc-layout").val(),theme:e.find("#field-cc-theme").val(),showFunctional:e.find("#field-cc-show-functional").prop("checked"),showAnalytics:e.find("#field-cc-show-analytics").prop("checked"),showMarketing:e.find("#field-cc-show-marketing").prop("checked"),consentVersion:e.find("#field-cc-version").val().trim()||"1.0"}},g=e.find("#save-settings-btn");g.prop("disabled",!0);try{await C.settings.save(o),Domma.theme.set(t),E.toast("Settings saved.",{type:"success"})}catch{E.toast("Failed to save settings.",{type:"error"})}finally{g.prop("disabled",!1)}}),e.find("#send-test-email-btn").on("click",async()=>{const t=e.find("#field-test-email-to").val().trim(),s=e.find("#test-email-result").get(0),m=e.find("#send-test-email-btn");m.prop("disabled",!0),s&&(s.textContent="Sending\u2026",s.style.color="");try{const o=await v("/settings/test-email",{method:"POST",body:JSON.stringify({to:t||void 0})});s&&(s.textContent=o.message||"Test email sent.",s.style.color="var(--dm-success,#4ade80)")}catch(o){s&&(s.textContent=o.message||"Failed to send test email.",s.style.color="var(--dm-danger,#f87171)")}finally{m.prop("disabled",!1)}}),e.find("#save-breadcrumbs-btn").on("click",async()=>{const t=e.find("#save-breadcrumbs-btn");t.prop("disabled",!0);try{const s={enabled:e.find("#field-breadcrumbs-enabled").prop("checked"),homeLabel:e.find("#field-breadcrumbs-home-label").val().trim()||"Home",position:e.find("#field-breadcrumbs-position").val()||"TL",offsetX:parseInt(e.find("#field-bc-offset-x").val(),10)||8,offsetY:parseInt(e.find("#field-bc-offset-y").val(),10)||8};await C.settings.save({...l,breadcrumbs:s}),l.breadcrumbs=s,E.toast("Breadcrumbs settings saved.",{type:"success"})}catch{E.toast("Failed to save breadcrumbs settings.",{type:"error"})}finally{t.prop("disabled",!1)}}),e.find("#save-css-btn").on("click",async()=>{const t=a?a.getValue():e.find("#field-custom-css").val(),s=e.find("#save-css-btn");s.prop("disabled",!0);try{await v("/settings/custom-css",{method:"PUT",body:JSON.stringify({css:t})}),E.toast("Custom CSS saved.",{type:"success"})}catch(m){E.toast(m.message||"Failed to save CSS.",{type:"error"})}finally{s.prop("disabled",!1)}});async function r(){try{const t=await v("/cache/status"),s=t.enabled?`enabled (${t.driver})`:"disabled",m=t.maxItems?` \xB7 ${t.size} / ${t.maxItems} entries`:"";e.find("#cache-status").text(s+m)}catch{e.find("#cache-status").text("unknown")}try{const{entries:t}=await v("/cache/keys");A(e.find("#cache-keys-table"),t),e.find("#cache-key-count").text(`(${t.length})`)}catch(t){e.find("#cache-keys-table").get(0).textContent="Failed to load keys: "+t.message}}await r(),e.find("#btn-clear-cache").on("click",async()=>{if(!await E.confirm("Clear the entire response cache?"))return;const t=e.find("#btn-clear-cache");t.prop("disabled",!0);try{await v("/cache/clear",{method:"POST"}),E.toast("Cache cleared.",{type:"success"}),await r()}catch(s){E.toast(s.message||"Failed to clear cache.",{type:"error"})}finally{t.prop("disabled",!1)}}),e.find("#btn-refresh-cache-keys").on("click",r)}};function A(e,k){const l=e.get(0);if(!l)return;for(;l.firstChild;)l.removeChild(l.firstChild);if(!k.length){const f=document.createElement("p");f.className="text-muted",f.style.fontSize=".875rem",f.textContent="Cache is empty.",l.appendChild(f);return}const p=[...k].reverse(),h=document.createElement("table");h.className="table table-compact";const b=document.createElement("thead"),y=document.createElement("tr");for(const f of["Key","Tags","Expires"]){const i=document.createElement("th");i.textContent=f,y.appendChild(i)}b.appendChild(y),h.appendChild(b);const u=document.createElement("tbody");for(const f of p){const i=document.createElement("tr"),d=document.createElement("td");d.style.fontFamily="monospace",d.style.fontSize="12px",d.textContent=f.key,i.appendChild(d);const n=document.createElement("td");n.style.fontSize="12px";for(const a of f.tags){const r=document.createElement("span");r.className="badge",r.style.marginRight="4px",r.style.fontSize="11px",r.textContent=a,n.appendChild(r)}i.appendChild(n);const c=document.createElement("td");if(c.style.fontSize="12px",c.style.color="var(--dm-text-muted, #6b7280)",f.expiresAt===null)c.textContent="no expiry";else{const a=f.expiresAt-Date.now();a<=0?c.textContent="expired":a<6e4?c.textContent=`${Math.round(a/1e3)}s`:a<36e5?c.textContent=`${Math.round(a/6e4)}m`:c.textContent=`${Math.round(a/36e5)}h`}i.appendChild(c),u.appendChild(i)}h.appendChild(u),l.appendChild(h)}
|
package/package.json
CHANGED
package/public/css/forms.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.fb-form-wrapper{max-width:600px;margin:2rem auto}.fb-form-honeypot{position:absolute;left:-9999px;top:-9999px;width:0;height:0;overflow:hidden;opacity:0;z-index:-1}.fb-form-success{padding:1rem 1.25rem;border-radius:6px;background
|
|
1
|
+
.fb-form-wrapper{max-width:600px;margin:2rem auto}.fb-form-honeypot{position:absolute;left:-9999px;top:-9999px;width:0;height:0;overflow:hidden;opacity:0;z-index:-1}.fb-form-success{padding:1rem 1.25rem;border-radius:6px;background:color-mix(in srgb,var(--dm-success, #34d399) 12%,transparent);border:1px solid color-mix(in srgb,var(--dm-success, #34d399) 30%,transparent);color:var(--dm-success, #34d399);font-size:.95rem;margin-top:.5rem}.fb-form-error{padding:.75rem 1rem;border-radius:6px;background:color-mix(in srgb,var(--dm-danger, #ef4444) 10%,transparent);border:1px solid color-mix(in srgb,var(--dm-danger, #ef4444) 25%,transparent);color:var(--dm-danger, #ef4444);font-size:.875rem;margin-top:.75rem}.fb-form-loading{opacity:.6;pointer-events:none}.wizard-progress{height:4px;background:var(--dm-border, #333);border-radius:2px;margin-bottom:1rem}.wizard-progress-bar{height:100%;background:var(--dm-primary, #5b8cff);border-radius:2px;transition:width .3s ease}.wizard-step-title{font-size:1.1rem;font-weight:600;margin-bottom:.25rem}.wizard-step-description{font-size:.875rem;color:var(--dm-text-muted, #888);margin-bottom:1rem}.wizard-nav{display:flex;justify-content:space-between;gap:.5rem;margin-top:1rem}.fb-field-hidden{display:none!important}.fb-validation-error{color:var(--dm-danger, #ef4444);font-size:.8rem;margin-top:.25rem}.fb-form-wrapper .domma-form-field{margin-bottom:2rem}.fb-form-wrapper .form-group:not(.form-buttons){margin-bottom:2rem}.fb-spacer{height:2rem}
|