domma-cms 0.9.5 → 0.9.10

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.
@@ -1,4 +1,4 @@
1
- import{api as Y}from"../api.js";import{attachEditorKeybindings as He,createToolbar as We,insertAtCursor as ke}from"../lib/markdown-toolbar.js?v=9";import{populateThemeSelect as _e}from"../lib/themes.js";import{createFoldingManager as Ye}from"../lib/editor-folding.js";function Je(){const a=E.slideover({title:"Editor Reference",size:"md",position:"right"}),ie="background:var(--dm-surface-subtle,#1a1a2e);padding:.2rem .4rem;border-radius:3px;font-size:.85em;font-family:monospace;",oe="margin:1rem 0 .5rem;font-size:1rem;";function U(T){const C=document.createElement("code");return C.style.cssText=ie,C.textContent=T,C}function J(T){const C=document.createElement("h3");return C.style.cssText=oe,C.textContent=T,C}const ze=document.createElement("div");ze.style.cssText="padding:1rem;";const $e=document.createElement("div");$e.className="tabs";const Ie=document.createElement("div");Ie.className="tab-list",["Basics","Layout","Components","Data","Advanced"].forEach((T,C)=>{const d=document.createElement("button");d.className="tab-item"+(C===0?" active":""),d.textContent=T,Ie.appendChild(d)});const W=document.createElement("div");W.className="tab-content";const Te="display:flex;flex-direction:column;gap:1rem;",Le=document.createElement("div");Le.className="tab-panel active",Le.style.cssText=Te;const ge=document.createElement("div");ge.className="tab-panel",ge.style.cssText=Te;const le=document.createElement("div");le.className="tab-panel",le.style.cssText=Te;const fe=document.createElement("div");fe.className="tab-panel",fe.style.cssText=Te;const Ce=document.createElement("div");Ce.className="tab-panel",Ce.style.cssText=Te,W.appendChild(Le),W.appendChild(ge),W.appendChild(le),W.appendChild(fe),W.appendChild(Ce),$e.appendChild(Ie),$e.appendChild(W),ze.appendChild($e);const Be=document.createElement("div");Be.appendChild(J("Markdown Basics"));const ce=document.createElement("table");ce.style.cssText="width:100%;border-collapse:collapse;font-size:.9em;";const Q=document.createElement("thead"),ne=document.createElement("tr");["Syntax","Result"].forEach(T=>{const C=document.createElement("th");C.style.cssText="text-align:left;padding:.4rem .5rem;border-bottom:1px solid var(--dm-border,#333);",C.textContent=T,ne.appendChild(C)}),Q.appendChild(ne),ce.appendChild(Q);const be=document.createElement("tbody");[["**bold**","bold (rendered bold)"],["_italic_","italic (rendered italic)"],["## Heading","Heading (h2)"],["[text](url)","Link"],["![alt](url)","Image"],["- item","Bullet list"],["`code`","Inline code"],["---","Divider"]].forEach(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.35rem .5rem;vertical-align:top;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.35rem .5rem;vertical-align:top;color:var(--dm-text-muted,#aaa);font-size:.85em;",o.textContent=C,d.appendChild(s),d.appendChild(o),be.appendChild(d)}),ce.appendChild(be),Be.appendChild(ce),Le.appendChild(Be);const ee=document.createElement("div");ee.appendChild(J("Grid & Columns"));function V(T){const C=document.createElement("p");return C.style.cssText="margin:.3rem 0 .6rem;font-size:.82em;color:var(--dm-text-muted,#aaa);",C.textContent=T,C}function z(T,C,d){const s=document.createElement("p");s.style.cssText="margin:.75rem 0 .25rem;font-size:.85em;font-weight:600;",s.textContent=T;const o=document.createElement("div");o.style.cssText="position:relative;";const he=document.createElement("pre");he.style.cssText=ie+"display:block;padding:.5rem 2rem .5rem .75rem;white-space:pre;overflow-x:auto;margin:0;",he.textContent=C;const H=document.createElement("button");H.type="button",H.title="Copy code",H.style.cssText="position:absolute;top:.3rem;right:.3rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.15rem;line-height:1;color:inherit;",H.addEventListener("mouseenter",()=>{H.style.opacity="1"}),H.addEventListener("mouseleave",()=>{H.style.opacity=".45"});const X=document.createElement("span");X.setAttribute("data-icon","copy"),H.appendChild(X),H.addEventListener("click",()=>{const L=document.createElement("textarea");L.value=C,L.style.cssText="position:fixed;opacity:0;",document.body.appendChild(L),L.select(),document.execCommand("copy"),L.remove(),E.toast("Copied!",{type:"success",duration:1200})}),o.appendChild(he),o.appendChild(H);const P=document.createDocumentFragment();return P.appendChild(s),P.appendChild(o),d&&P.appendChild(V(d)),P}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(([T,C,d])=>{const s=document.createElement("tr");[T,C,d].forEach((o,he)=>{const H=document.createElement("td");H.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",he===0?H.appendChild(U(T)):(H.style.color="var(--dm-text-muted,#aaa)",H.textContent=o),s.appendChild(H)}),ae.appendChild(s)}),ee.appendChild(ae),ee.appendChild(z("Equal columns",`[grid cols="3" gap="4"]
1
+ import{api as Y}from"../api.js";import{CardBuilder as He}from"../lib/card-builder.js?v=4";import{attachEditorKeybindings as We,createToolbar as _e,insertAtCursor as ke}from"../lib/markdown-toolbar.js?v=9";import{populateThemeSelect as Ye}from"../lib/themes.js";import{createFoldingManager as Je}from"../lib/editor-folding.js";function Qe(){const a=E.slideover({title:"Editor Reference",size:"md",position:"right"}),ie="background:var(--dm-surface-subtle,#1a1a2e);padding:.2rem .4rem;border-radius:3px;font-size:.85em;font-family:monospace;",oe="margin:1rem 0 .5rem;font-size:1rem;";function U(T){const C=document.createElement("code");return C.style.cssText=ie,C.textContent=T,C}function J(T){const C=document.createElement("h3");return C.style.cssText=oe,C.textContent=T,C}const ze=document.createElement("div");ze.style.cssText="padding:1rem;";const $e=document.createElement("div");$e.className="tabs";const Ie=document.createElement("div");Ie.className="tab-list",["Basics","Layout","Components","Data","Advanced"].forEach((T,C)=>{const d=document.createElement("button");d.className="tab-item"+(C===0?" active":""),d.textContent=T,Ie.appendChild(d)});const W=document.createElement("div");W.className="tab-content";const Te="display:flex;flex-direction:column;gap:1rem;",Le=document.createElement("div");Le.className="tab-panel active",Le.style.cssText=Te;const ge=document.createElement("div");ge.className="tab-panel",ge.style.cssText=Te;const le=document.createElement("div");le.className="tab-panel",le.style.cssText=Te;const fe=document.createElement("div");fe.className="tab-panel",fe.style.cssText=Te;const Ce=document.createElement("div");Ce.className="tab-panel",Ce.style.cssText=Te,W.appendChild(Le),W.appendChild(ge),W.appendChild(le),W.appendChild(fe),W.appendChild(Ce),$e.appendChild(Ie),$e.appendChild(W),ze.appendChild($e);const Be=document.createElement("div");Be.appendChild(J("Markdown Basics"));const ce=document.createElement("table");ce.style.cssText="width:100%;border-collapse:collapse;font-size:.9em;";const Q=document.createElement("thead"),ne=document.createElement("tr");["Syntax","Result"].forEach(T=>{const C=document.createElement("th");C.style.cssText="text-align:left;padding:.4rem .5rem;border-bottom:1px solid var(--dm-border,#333);",C.textContent=T,ne.appendChild(C)}),Q.appendChild(ne),ce.appendChild(Q);const be=document.createElement("tbody");[["**bold**","bold (rendered bold)"],["_italic_","italic (rendered italic)"],["## Heading","Heading (h2)"],["[text](url)","Link"],["![alt](url)","Image"],["- item","Bullet list"],["`code`","Inline code"],["---","Divider"]].forEach(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.35rem .5rem;vertical-align:top;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.35rem .5rem;vertical-align:top;color:var(--dm-text-muted,#aaa);font-size:.85em;",o.textContent=C,d.appendChild(s),d.appendChild(o),be.appendChild(d)}),ce.appendChild(be),Be.appendChild(ce),Le.appendChild(Be);const ee=document.createElement("div");ee.appendChild(J("Grid & Columns"));function V(T){const C=document.createElement("p");return C.style.cssText="margin:.3rem 0 .6rem;font-size:.82em;color:var(--dm-text-muted,#aaa);",C.textContent=T,C}function z(T,C,d){const s=document.createElement("p");s.style.cssText="margin:.75rem 0 .25rem;font-size:.85em;font-weight:600;",s.textContent=T;const o=document.createElement("div");o.style.cssText="position:relative;";const he=document.createElement("pre");he.style.cssText=ie+"display:block;padding:.5rem 2rem .5rem .75rem;white-space:pre;overflow-x:auto;margin:0;",he.textContent=C;const H=document.createElement("button");H.type="button",H.title="Copy code",H.style.cssText="position:absolute;top:.3rem;right:.3rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.15rem;line-height:1;color:inherit;",H.addEventListener("mouseenter",()=>{H.style.opacity="1"}),H.addEventListener("mouseleave",()=>{H.style.opacity=".45"});const X=document.createElement("span");X.setAttribute("data-icon","copy"),H.appendChild(X),H.addEventListener("click",()=>{const L=document.createElement("textarea");L.value=C,L.style.cssText="position:fixed;opacity:0;",document.body.appendChild(L),L.select(),document.execCommand("copy"),L.remove(),E.toast("Copied!",{type:"success",duration:1200})}),o.appendChild(he),o.appendChild(H);const P=document.createDocumentFragment();return P.appendChild(s),P.appendChild(o),d&&P.appendChild(V(d)),P}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(([T,C,d])=>{const s=document.createElement("tr");[T,C,d].forEach((o,he)=>{const H=document.createElement("td");H.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",he===0?H.appendChild(U(T)):(H.style.color="var(--dm-text-muted,#aaa)",H.textContent=o),s.appendChild(H)}),ae.appendChild(s)}),ee.appendChild(ae),ee.appendChild(z("Equal columns",`[grid cols="3" gap="4"]
2
2
  [col]One[/col]
3
3
  [col]Two[/col]
4
4
  [col]Three[/col]
@@ -81,11 +81,11 @@ In active development.
81
81
  Markdown content here.
82
82
  [/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")),le.appendChild(B);const i=document.createElement("div");i.appendChild(J("DConfig \u2014 Declarative Behaviour")),i.appendChild(V("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.")),i.appendChild(z("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.')),i.appendChild(z("Inline shortcode syntax",`[dconfig]
83
83
  { "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }
84
- [/dconfig]`,null)),Ce.appendChild(i);const g=document.createElement("div");g.appendChild(J("CSS Editor")),g.appendChild(V("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 n=document.createElement("table");n.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(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",o.textContent=C,d.appendChild(s),d.appendChild(o),n.appendChild(d)}),g.appendChild(n),Ce.appendChild(g);const r=document.createElement("div");r.appendChild(J("Colour Picker")),r.appendChild(V("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.")),Ce.appendChild(r);const v=document.createElement("div");v.appendChild(J("Keyboard Shortcuts"));const A=document.createElement("table");A.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(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;white-space:nowrap;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",o.textContent=C,d.appendChild(s),d.appendChild(o),A.appendChild(d)}),v.appendChild(A),Le.appendChild(v);const q=document.createElement("div");q.appendChild(J("Tips"));const j=document.createElement("table");j.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(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",o.textContent=C,d.appendChild(s),d.appendChild(o),j.appendChild(d)}),q.appendChild(j),q.appendChild(V("Most shortcodes accept a class attribute for custom styling.")),Le.appendChild(q),a.setContent(ze),a.open(),E.tabs($e),I.scan(ze)}function Qe(a,ie){const oe=a.find("#history-tab").get(0),U=a.find("#version-list").get(0),J=a.find("#version-compare").get(0),ze=a.find("#version-compare-old").get(0),$e=a.find("#version-compare-new").get(0),Ie=a.find("#version-compare-label").get(0),W=a.find("#version-compare-back-btn").get(0),Te=a.find("#version-restore-btn").get(0),Le=a.find("#history-save-named-btn").get(0),ge=a.find("#history-delete-selected-btn").get(0);let le=!1,fe=null;function Ce(){U.style.display="",J.style.display="none",fe=null}function Be(){U.style.display="none",J.style.display=""}async function ce(){U.textContent="";const Q=document.createElement("p");Q.style.color="var(--dm-text-muted)",Q.textContent="Loading\u2026",U.appendChild(Q);let ne;try{ne=(await Y.versions.list(ie)).versions||[]}catch(M){U.textContent="";const Z=document.createElement("p");Z.style.color="var(--dm-text-danger,#e55)",Z.textContent="Failed to load versions: "+M.message,U.appendChild(Z);return}if(U.textContent="",ge.style.display="none",!ne.length){const M=document.createElement("p");M.style.color="var(--dm-text-muted)",M.textContent="No versions saved yet. Versions are created automatically on each save.",U.appendChild(M);return}const be=document.createElement("table");be.style.cssText="width:100%;border-collapse:collapse;font-size:.875rem;";const ee=document.createElement("thead"),V=document.createElement("tr"),z=document.createElement("th");z.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"),z.appendChild(ae),V.appendChild(z),["Date","Author","Type","Label","Actions"].forEach(M=>{const Z=document.createElement("th");Z.style.cssText="text-align:left;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border);font-size:.8rem;color:var(--dm-text-muted);",Z.textContent=M,V.appendChild(Z)}),ee.appendChild(V),be.appendChild(ee);const pe=[];function ye(){const M=pe.some(se=>se.checked),Z=pe.length>0&&pe.every(se=>se.checked);ge.style.display=M?"":"none",ae.checked=Z,ae.indeterminate=M&&!Z}ae.addEventListener("change",()=>{pe.forEach(M=>{M.checked=ae.checked}),ye()});const De=document.createElement("tbody");ne.forEach(M=>{const Z=document.createElement("tr");Z.style.borderBottom="1px solid var(--dm-border)";const se=document.createElement("td");se.style.padding=".5rem .75rem";const xe=document.createElement("input");xe.type="checkbox",xe.value=M.filename,xe.addEventListener("change",ye),se.appendChild(xe),pe.push(xe);const de=document.createElement("td");de.style.padding=".5rem .75rem",de.textContent=D(M.createdAt).format("D MMM YYYY, HH:mm");const Ne=document.createElement("td");Ne.style.padding=".5rem .75rem",Ne.textContent=M.author||"\u2014";const me=document.createElement("td");me.style.padding=".5rem .75rem";const Se=document.createElement("span");Se.className="badge badge-"+(M.type==="manual"?"primary":"secondary"),Se.style.cssText="font-size:.75rem;padding:.2rem .5rem;border-radius:4px;",Se.textContent=M.type,me.appendChild(Se);const Ee=document.createElement("td");Ee.style.cssText="padding:.5rem .75rem;color:var(--dm-text-muted);",Ee.textContent=M.label||"\u2014";const te=document.createElement("td");te.style.padding=".5rem .75rem";const ve=document.createElement("button");ve.className="btn btn-ghost btn-xs",ve.style.marginRight=".4rem",ve.textContent="Compare",ve.addEventListener("click",async()=>{try{const ue=await Y.versions.get(ie,M.filename);ze.textContent=ue.content,$e.textContent=a.find("#markdown-editor").get(0).value,Ie.textContent=D(M.createdAt).format("D MMM YYYY, HH:mm")+(M.label?` \u2014 ${M.label}`:""),fe=M.filename,Be()}catch(ue){E.toast("Failed to load version: "+ue.message,{type:"error"})}});const re=document.createElement("button");re.className="btn btn-ghost btn-xs",re.style.color="var(--dm-text-danger,#e55)",re.textContent="Delete",re.addEventListener("click",async()=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await Y.versions.delete(ie,M.filename),E.toast("Version deleted.",{type:"success"}),await ce()}catch(ue){E.toast("Failed to delete: "+ue.message,{type:"error"})}}),te.appendChild(ve),te.appendChild(re),Z.appendChild(se),Z.appendChild(de),Z.appendChild(Ne),Z.appendChild(me),Z.appendChild(Ee),Z.appendChild(te),De.appendChild(Z)}),be.appendChild(De),U.appendChild(be)}oe.addEventListener("click",async()=>{le||(le=!0,await ce())}),W.addEventListener("click",()=>{Ce()}),Te.addEventListener("click",async()=>{if(!(!fe||!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(ie,fe),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${ie}`),300)}catch(Q){E.toast("Restore failed: "+Q.message,{type:"error"})}}),ge.addEventListener("click",async()=>{const Q=[...U.querySelectorAll("tbody input[type=checkbox]:checked")].map(ne=>ne.value);if(!(!Q.length||!await E.confirm(`Delete ${Q.length} version${Q.length>1?"s":""}? This cannot be undone.`)))try{await Y.versions.bulkDelete(ie,Q),E.toast(`${Q.length} version${Q.length>1?"s":""} deleted.`,{type:"success"}),await ce()}catch(ne){E.toast("Delete failed: "+ne.message,{type:"error"})}}),Le.addEventListener("click",()=>{const Q=E.modal({title:"Save Named Version"}),ne=document.createElement("div");ne.style.padding="1rem";const be=document.createElement("label");be.className="form-label",be.textContent="Version Label";const ee=document.createElement("input");ee.type="text",ee.className="form-input",ee.placeholder="e.g. Initial design, Before restructure",ee.style.marginBottom=".75rem";const V=document.createElement("button");V.className="btn btn-primary",V.textContent="Save Version",V.addEventListener("click",async()=>{const z=ee.value.trim();try{await Y.versions.create(ie,z||null),E.toast("Named version saved.",{type:"success"}),Q.close(),le=!1,oe.classList.contains("active")&&(le=!0,await ce())}catch(ae){E.toast("Failed to save version: "+ae.message,{type:"error"})}}),ne.appendChild(be),ne.appendChild(ee),ne.appendChild(V),Q.element.appendChild(ne),Q.open(),setTimeout(()=>ee.focus(),100)})}let Ae=!1,Pe=null,Oe=!1;function Ke(a){return a.split(`
84
+ [/dconfig]`,null)),Ce.appendChild(i);const g=document.createElement("div");g.appendChild(J("CSS Editor")),g.appendChild(V("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 n=document.createElement("table");n.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(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",o.textContent=C,d.appendChild(s),d.appendChild(o),n.appendChild(d)}),g.appendChild(n),Ce.appendChild(g);const r=document.createElement("div");r.appendChild(J("Colour Picker")),r.appendChild(V("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.")),Ce.appendChild(r);const v=document.createElement("div");v.appendChild(J("Keyboard Shortcuts"));const A=document.createElement("table");A.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(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;white-space:nowrap;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",o.textContent=C,d.appendChild(s),d.appendChild(o),A.appendChild(d)}),v.appendChild(A),Le.appendChild(v);const q=document.createElement("div");q.appendChild(J("Tips"));const j=document.createElement("table");j.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(([T,C])=>{const d=document.createElement("tr"),s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",s.appendChild(U(T));const o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",o.textContent=C,d.appendChild(s),d.appendChild(o),j.appendChild(d)}),q.appendChild(j),q.appendChild(V("Most shortcodes accept a class attribute for custom styling.")),Le.appendChild(q),a.setContent(ze),a.open(),E.tabs($e),I.scan(ze)}function Ke(a,ie){const oe=a.find("#history-tab").get(0),U=a.find("#version-list").get(0),J=a.find("#version-compare").get(0),ze=a.find("#version-compare-old").get(0),$e=a.find("#version-compare-new").get(0),Ie=a.find("#version-compare-label").get(0),W=a.find("#version-compare-back-btn").get(0),Te=a.find("#version-restore-btn").get(0),Le=a.find("#history-save-named-btn").get(0),ge=a.find("#history-delete-selected-btn").get(0);let le=!1,fe=null;function Ce(){U.style.display="",J.style.display="none",fe=null}function Be(){U.style.display="none",J.style.display=""}async function ce(){U.textContent="";const Q=document.createElement("p");Q.style.color="var(--dm-text-muted)",Q.textContent="Loading\u2026",U.appendChild(Q);let ne;try{ne=(await Y.versions.list(ie)).versions||[]}catch(M){U.textContent="";const Z=document.createElement("p");Z.style.color="var(--dm-text-danger,#e55)",Z.textContent="Failed to load versions: "+M.message,U.appendChild(Z);return}if(U.textContent="",ge.style.display="none",!ne.length){const M=document.createElement("p");M.style.color="var(--dm-text-muted)",M.textContent="No versions saved yet. Versions are created automatically on each save.",U.appendChild(M);return}const be=document.createElement("table");be.style.cssText="width:100%;border-collapse:collapse;font-size:.875rem;";const ee=document.createElement("thead"),V=document.createElement("tr"),z=document.createElement("th");z.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"),z.appendChild(ae),V.appendChild(z),["Date","Author","Type","Label","Actions"].forEach(M=>{const Z=document.createElement("th");Z.style.cssText="text-align:left;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border);font-size:.8rem;color:var(--dm-text-muted);",Z.textContent=M,V.appendChild(Z)}),ee.appendChild(V),be.appendChild(ee);const pe=[];function ye(){const M=pe.some(se=>se.checked),Z=pe.length>0&&pe.every(se=>se.checked);ge.style.display=M?"":"none",ae.checked=Z,ae.indeterminate=M&&!Z}ae.addEventListener("change",()=>{pe.forEach(M=>{M.checked=ae.checked}),ye()});const De=document.createElement("tbody");ne.forEach(M=>{const Z=document.createElement("tr");Z.style.borderBottom="1px solid var(--dm-border)";const se=document.createElement("td");se.style.padding=".5rem .75rem";const xe=document.createElement("input");xe.type="checkbox",xe.value=M.filename,xe.addEventListener("change",ye),se.appendChild(xe),pe.push(xe);const de=document.createElement("td");de.style.padding=".5rem .75rem",de.textContent=D(M.createdAt).format("D MMM YYYY, HH:mm");const Ne=document.createElement("td");Ne.style.padding=".5rem .75rem",Ne.textContent=M.author||"\u2014";const me=document.createElement("td");me.style.padding=".5rem .75rem";const Se=document.createElement("span");Se.className="badge badge-"+(M.type==="manual"?"primary":"secondary"),Se.style.cssText="font-size:.75rem;padding:.2rem .5rem;border-radius:4px;",Se.textContent=M.type,me.appendChild(Se);const Ee=document.createElement("td");Ee.style.cssText="padding:.5rem .75rem;color:var(--dm-text-muted);",Ee.textContent=M.label||"\u2014";const te=document.createElement("td");te.style.padding=".5rem .75rem";const ve=document.createElement("button");ve.className="btn btn-ghost btn-xs",ve.style.marginRight=".4rem",ve.textContent="Compare",ve.addEventListener("click",async()=>{try{const ue=await Y.versions.get(ie,M.filename);ze.textContent=ue.content,$e.textContent=a.find("#markdown-editor").get(0).value,Ie.textContent=D(M.createdAt).format("D MMM YYYY, HH:mm")+(M.label?` \u2014 ${M.label}`:""),fe=M.filename,Be()}catch(ue){E.toast("Failed to load version: "+ue.message,{type:"error"})}});const re=document.createElement("button");re.className="btn btn-ghost btn-xs",re.style.color="var(--dm-text-danger,#e55)",re.textContent="Delete",re.addEventListener("click",async()=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await Y.versions.delete(ie,M.filename),E.toast("Version deleted.",{type:"success"}),await ce()}catch(ue){E.toast("Failed to delete: "+ue.message,{type:"error"})}}),te.appendChild(ve),te.appendChild(re),Z.appendChild(se),Z.appendChild(de),Z.appendChild(Ne),Z.appendChild(me),Z.appendChild(Ee),Z.appendChild(te),De.appendChild(Z)}),be.appendChild(De),U.appendChild(be)}oe.addEventListener("click",async()=>{le||(le=!0,await ce())}),W.addEventListener("click",()=>{Ce()}),Te.addEventListener("click",async()=>{if(!(!fe||!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(ie,fe),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${ie}`),300)}catch(Q){E.toast("Restore failed: "+Q.message,{type:"error"})}}),ge.addEventListener("click",async()=>{const Q=[...U.querySelectorAll("tbody input[type=checkbox]:checked")].map(ne=>ne.value);if(!(!Q.length||!await E.confirm(`Delete ${Q.length} version${Q.length>1?"s":""}? This cannot be undone.`)))try{await Y.versions.bulkDelete(ie,Q),E.toast(`${Q.length} version${Q.length>1?"s":""} deleted.`,{type:"success"}),await ce()}catch(ne){E.toast("Delete failed: "+ne.message,{type:"error"})}}),Le.addEventListener("click",()=>{const Q=E.modal({title:"Save Named Version"}),ne=document.createElement("div");ne.style.padding="1rem";const be=document.createElement("label");be.className="form-label",be.textContent="Version Label";const ee=document.createElement("input");ee.type="text",ee.className="form-input",ee.placeholder="e.g. Initial design, Before restructure",ee.style.marginBottom=".75rem";const V=document.createElement("button");V.className="btn btn-primary",V.textContent="Save Version",V.addEventListener("click",async()=>{const z=ee.value.trim();try{await Y.versions.create(ie,z||null),E.toast("Named version saved.",{type:"success"}),Q.close(),le=!1,oe.classList.contains("active")&&(le=!0,await ce())}catch(ae){E.toast("Failed to save version: "+ae.message,{type:"error"})}}),ne.appendChild(be),ne.appendChild(ee),ne.appendChild(V),Q.element.appendChild(ne),Q.open(),setTimeout(()=>ee.focus(),100)})}let Ae=!1,Pe=null,Oe=!1;function Ze(a){return a.split(`
85
85
  `).map(ie=>ie.trimEnd()).join(`
86
86
  `).replace(/\n{3,}/g,`
87
87
 
88
- `)}const Ge="editor_prefs";function Ue(){return S.get(Ge)||{viewMode:"split",fullscreen:!1}}function Ve(a,ie){const oe=Ue();oe[a]=ie,S.set(Ge,oe)}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(a){const ie=window.location.hash.match(/#\/pages\/edit(\/.*)/),oe=ie?ie[1]:null,U=!!oe,J=E.loader(a.get(0),{type:"dots"}),ze=[Y.layouts.get().catch(()=>({})),Y.settings.get().catch(()=>({}))];U&&(ze.push(Y.pages.get(oe).catch(()=>null)),ze.push(Y.pages.list().catch(()=>[])));const[$e,Ie,W,Te]=await Promise.all(ze);J.destroy(),_e(a.find("#field-theme").get(0),{includeDefault:!0});const Le=Ie?.layoutOptions?.spacerSize??40;if(U&&!W){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}a.find("#editor-title").text(U?`Edit Page \u2014 ${W.title||oe}`:"New Page"),U&&a.find("#page-url-path").val(oe),W&&(a.find("#field-title").val(W.title||""),a.find("#field-description").val(W.description||""),a.find("#field-status").val(W.status||"draft"),a.find("#field-sort-order").val(W.sortOrder??99),a.find("#field-show-in-nav").prop("checked",!!W.showInNav),a.find("#field-sidebar").prop("checked",!!W.sidebar),a.find("#field-show-breadcrumbs").prop("checked",W.breadcrumbs!==!1),a.find("#field-bundled").prop("checked",!!W.bundled),a.find("#field-category").val(W.category||""),a.find("#field-visibility").val(W.visibility||"public"),a.find("#field-theme").val(W.theme||""),a.find("#field-seo-title").val(W.seo?.title||""),a.find("#field-seo-desc").val(W.seo?.description||""),W.dconfig&&a.find("#field-dconfig").val(JSON.stringify(W.dconfig,null,2)));const ge=a.find("#quick-switch");U&&Array.isArray(Te)&&Te.length&&([...Te].sort((e,l)=>(e.title||e.urlPath).localeCompare(l.title||l.urlPath)).forEach(e=>{const l=document.createElement("option");l.value=e.urlPath,l.textContent=`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath===oe&&(l.selected=!0),ge.get(0).appendChild(l)}),ge.css("display",""),ge.on("change",function(){const e=this.value;e&&R.navigate("/pages/edit"+e)}));const le=await Y.pages.tags().catch(()=>[]),fe=a.find("#field-tags").get(0),Ce=fe?E.pillbox(fe,{data:le,value:W?.tags||[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026"}):null,Be=a.find("#field-layout").empty();if(Object.entries($e).forEach(([e,l])=>{const t=(W?.layout||"default")===e?"selected":"";Be.append(`<option value="${e}" ${t}>${l.label||e}</option>`)}),U){const e=a.find("#view-page-btn").get(0);e.href=oe,e.style.display="";const l=a.find("#live-preview-tab").get(0);l.style.display="";const t=a.find("#history-tab").get(0);t.style.display=""}if(E.tabs(a.find("#editor-meta-tabs").get(0)),U){const e=a.find("#live-preview-tab").get(0),l=a.find("#live-preview-frame").get(0);let t=!1;e.addEventListener("click",function(){t||(l.src=oe,t=!0)}),Qe(a,oe)}const ce=a.find("#markdown-editor"),Q=a.find("#markdown-preview");W&&ce.val(W.content||"");let ne=!1,be="";Y.settings.getCustomCss().then(({css:e})=>{if(be=e||"",!be)return;const l=document.createElement("style");l.id="preview-custom-css",l.textContent=be,Q.get(0).parentNode.insertBefore(l,Q.get(0))}).catch(()=>{});let ee=!1;const V=ce.get(0),z=document.createElement("div");z.className="editor-line-numbers editor-line-numbers--foldable",V.parentElement.insertBefore(z,V);const ae=Ye(V,z,{onFoldChange:()=>{}});ae.setGuard(e=>{ee=e});const pe=()=>{ae.refresh(),z.scrollTop=V.scrollTop};V.addEventListener("input",pe),V.addEventListener("scroll",()=>{z.scrollTop=V.scrollTop});let ye=null;const De=()=>{clearTimeout(ye),ye=setTimeout(async()=>{const e=ae.getUnfoldedContent();try{const{html:l}=await Y.pages.preview(e);Q.html(l,{safe:!1}),I.scan(Q.get(0)),Q.get(0).querySelectorAll(".tabs").forEach(t=>Domma.elements.tabs(t))}catch{window.marked&&Q.html(marked.parse(e))}},400)},M=We(ce,a.find("#editor-toolbar"),{spacerDefault:Le});let Z=!1,se="split",xe=null;const de=document.createElement("button");de.className="editor-view-btn",de.type="button";const Ne=document.createElement("span");Ne.setAttribute("data-icon","css-code"),de.appendChild(Ne);const me=document.createElement("button");me.className="editor-view-btn",me.type="button";const Se=document.createElement("span");Se.setAttribute("data-icon","code"),me.appendChild(Se);let Ee=!1;const te=document.createElement("button");te.className="editor-view-btn",te.type="button",te.textContent="\u25BC\u25BC",te.style.cssText="font-size:9px;letter-spacing:-1px;";const ve=a.find(".editor-toolbar-right").get(0);ve.prepend(te),ve.prepend(me),ve.prepend(de),I.scan(de),I.scan(me),E.tooltip(de,{content:"Edit Custom CSS",position:"top"}),E.tooltip(me,{content:"Format Markdown",position:"top"}),E.tooltip(te,{content:"Fold / unfold all shortcodes",position:"top"}),me.addEventListener("click",()=>{const e=ce.get(0),l=e.selectionStart,t=Ke(ae.getUnfoldedContent());ae.unfoldAll(),ee=!0,e.value=t,ee=!1,e.selectionStart=e.selectionEnd=Math.min(l,t.length),e.dispatchEvent(new Event("input")),ae.refresh(),E.toast("Markdown formatted.",{type:"success"})}),te.addEventListener("click",()=>{Ee?(ae.unfoldAll(),te.textContent="\u25BC\u25BC",te.classList.remove("active")):(ae.foldAll(),te.textContent="\u25B6\u25B6",te.classList.add("active")),Ee=!Ee});const re=document.createElement("span");re.className="editor-toolbar-sep",ve.insertBefore(re,ve.children[3]),de.addEventListener("click",()=>{Z=!Z;const e=a.find("#markdown-editor"),l=a.find("#css-editor"),t=a.find("#editor-body");if(Z){const k=a.find(".editor-view-btn[data-mode].active").get(0);se=k?k.getAttribute("data-mode"):"split",a.find(".editor-view-btn[data-mode]").removeClass("active"),a.find('.editor-view-btn[data-mode="split"]').addClass("active"),t.removeClass("editor-mode-write editor-mode-preview").addClass("editor-mode-split"),e.hide(),l.show(),ne||(l.val(be),ne=!0,He(l.get(0))),de.classList.add("active")}else a.find(".editor-view-btn[data-mode]").removeClass("active"),a.find(`.editor-view-btn[data-mode="${se}"]`).addClass("active"),t.removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${se}`),l.hide(),e.show(),de.classList.remove("active")});const ue=Ue();ue.viewMode&&ue.viewMode!=="split"&&(a.find(".editor-view-btn[data-mode]").removeClass("active"),a.find(`.editor-view-btn[data-mode="${ue.viewMode}"]`).addClass("active"),a.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${ue.viewMode}`)),ue.fullscreen&&a.find(".editor-card").addClass("editor-fullscreen"),a.find("#css-editor").on("input",()=>{clearTimeout(xe),xe=setTimeout(()=>{let e=document.getElementById("preview-custom-css");e||(e=document.createElement("style"),e.id="preview-custom-css",Q.get(0).parentNode.insertBefore(e,Q.get(0))),e.textContent=a.find("#css-editor").val()},400)}),M.onLink(async e=>{const l=(await Y.pages.list().catch(()=>[])).map(f=>({label:f.title||f.urlPath,value:f.urlPath})),t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const k=document.createElement("label");k.className="form-label",k.textContent="URL";const m=document.createElement("input");m.type="text",m.className="form-input",m.placeholder="/about or https://example.com";const u=e.value.substring(e.selectionStart,e.selectionEnd);u&&u.startsWith("/")&&(m.value=u),t.appendChild(k),t.appendChild(m);const w=document.createElement("label");w.className="form-label",w.textContent="Link text";const x=document.createElement("input");x.type="text",x.className="form-input",x.placeholder="Display text",u&&!u.startsWith("/")&&(x.value=u),t.appendChild(w),t.appendChild(x);const h=document.createElement("label");h.className="form-label",h.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;",h.appendChild(c),h.appendChild(document.createTextNode("Display as button")),t.appendChild(h);const p=document.createElement("label");p.className="form-label",p.textContent="Button colour",p.style.display="none";const F=document.createElement("select");F.className="form-select",F.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(([f,B])=>{const y=document.createElement("option");y.value=f,y.textContent=B,F.appendChild(y)}),t.appendChild(p),t.appendChild(F),c.addEventListener("change",()=>{const f=c.checked;p.style.display=f?"":"none",F.style.display=f?"":"none"});const N=document.createElement("button");N.type="button",N.className="btn btn-primary",N.textContent="Insert Link",t.appendChild(N);const b=E.modal({title:"Insert Link",size:"sm"});b.element.appendChild(t),b.open(),requestAnimationFrame(()=>{E.autocomplete(m,{data:l,minChars:1,onSelect:f=>{m.value=f.value,x.value||(x.value=f.label)}}),m.focus()}),N.addEventListener("click",()=>{const f=m.value.trim(),B=x.value.trim();if(!f)return;b.close();const y=c.checked?`[button href="${f}" variant="${F.value}"]${B||f}[/button]`:`[${B||f}](${f})`,i=e.selectionStart,g=e.selectionEnd;e.value=e.value.substring(0,i)+y+e.value.substring(g),e.selectionStart=e.selectionEnd=i+y.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onImage(async e=>{const l=(await Y.media.list().catch(()=>[])).filter(m=>/\.(png|jpe?g|gif|webp|svg)$/i.test(m.name)),t=document.createElement("div");if(t.className="media-picker-grid",l.length)l.forEach(m=>{const u=document.createElement("div");u.className="media-picker-item",u.dataset.url=m.url;const w=document.createElement("img");w.src=m.url,w.alt=m.name;const x=document.createElement("span");x.textContent=m.name,u.appendChild(w),u.appendChild(x),t.appendChild(u)});else{const m=document.createElement("p");m.className="text-muted p-3",m.textContent="No images uploaded yet.",t.appendChild(m)}const k=E.modal({title:"Insert Image",size:"lg"});k.element.appendChild(t),$(k.element).on("click",".media-picker-item",function(){const m=$(this).data("url"),u=$(this).find("span").text();ke(e,`![${u}](${m})`),k.close(),ce.get(0).dispatchEvent(new Event("input",{bubbles:!0}))}),k.open()}),M.onCollection(async e=>{const[l,t]=await Promise.all([Y.collections.list().catch(()=>[]),Y.blocks.list().catch(()=>[])]),k=document.createElement("div");k.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const m="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;",w=document.createElement("div"),x=document.createElement("label");x.style.cssText=m,x.textContent="Collection";const h=document.createElement("select");if(h.style.cssText=u,l.length)l.forEach(G=>{const K=document.createElement("option");K.value=G.slug,K.textContent=G.title||G.slug,h.appendChild(K)});else{const G=document.createElement("option");G.value="",G.textContent="No collections found",h.appendChild(G)}w.appendChild(x),w.appendChild(h),k.appendChild(w);const c=document.createElement("div"),p=document.createElement("label");p.style.cssText=m,p.textContent="Display";const F=document.createElement("select");F.style.cssText=u,["table","cards","list","block"].forEach(G=>{const K=document.createElement("option");K.value=G,K.textContent=G.charAt(0).toUpperCase()+G.slice(1),F.appendChild(K)}),c.appendChild(p),c.appendChild(F),k.appendChild(c);const N=document.createElement("div");N.style.display="none";const b=document.createElement("label");b.style.cssText=m,b.textContent="Columns (2\u20134)";const f=document.createElement("input");f.type="number",f.min="2",f.max="4",f.value="3",f.style.cssText=u,N.appendChild(b),N.appendChild(f),k.appendChild(N);const B=document.createElement("div");B.style.display="none";const y=document.createElement("label");y.style.cssText=m,y.textContent="Block template";const i=document.createElement("select");if(i.style.cssText=u,t.length)t.forEach(G=>{const K=document.createElement("option");K.value=G.name??G,K.textContent=G.name??G,i.appendChild(K)});else{const G=document.createElement("option");G.value="",G.textContent="No block templates found",i.appendChild(G)}B.appendChild(y),B.appendChild(i),k.appendChild(B);const g=document.createElement("div"),n=document.createElement("label");n.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const r=document.createElement("input");r.type="checkbox",r.checked=!0,n.appendChild(r),n.appendChild(document.createTextNode("Enable search")),g.appendChild(n),k.appendChild(g);const v=document.createElement("div"),A=document.createElement("label");A.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const q=document.createElement("input");q.type="checkbox",q.checked=!0,A.appendChild(q),A.appendChild(document.createTextNode("Sortable columns")),v.appendChild(A),k.appendChild(v);const j=document.createElement("div"),T=document.createElement("label");T.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const C=document.createElement("input");C.type="checkbox",C.checked=!1,T.appendChild(C),T.appendChild(document.createTextNode("CSV export")),j.appendChild(T),k.appendChild(j);const d=document.createElement("div"),s=document.createElement("label");s.style.cssText=m,s.textContent="Rows per page";const o=document.createElement("input");o.type="number",o.min="5",o.max="100",o.value="25",o.style.cssText=u,d.appendChild(s),d.appendChild(o),k.appendChild(d);const he=document.createElement("div"),H=document.createElement("label");H.style.cssText=m,H.textContent="Limit (optional)";const X=document.createElement("input");X.type="number",X.placeholder="All",X.style.cssText=u,he.appendChild(H),he.appendChild(X),k.appendChild(he);const P=document.createElement("button");P.type="button",P.className="btn btn-primary",P.textContent="Insert",k.appendChild(P);const L=[g,v,j,d],O=()=>{const G=F.value,K=G==="table";L.forEach(we=>{we.style.display=K?"":"none"}),N.style.display=G==="cards"||G==="block"?"":"none",B.style.display=G==="block"?"":"none"};F.addEventListener("change",O),O();const _=E.modal({title:"Insert Collection",size:"sm"});_.element.appendChild(k),_.open(),P.addEventListener("click",()=>{const G=h.value;if(!G)return;const K=F.value;let we=`[collection slug="${G}" display="${K}"`;if(K==="cards"&&(we+=` columns="${f.value}"`),K==="block"){const Me=i.value;Me&&(we+=` block="${Me}"`);const qe=f.value.trim();qe&&(we+=` cols="${qe}"`)}K==="table"&&!r.checked&&(we+=' search="false"'),K==="table"&&!q.checked&&(we+=' sortable="false"'),K==="table"&&C.checked&&(we+=' exportable="true"'),K==="table"&&o.value!=="25"&&(we+=` page-size="${o.value}"`);const Re=X.value.trim();Re&&(we+=` limit="${Re}"`),we+=" /]",_.close(),ke(e,we),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onBlock(async e=>{let l=[];try{l=await Y.blocks.list()}catch{E.toast("Could not load blocks.",{type:"error"});return}if(!l.length){E.toast("No block templates found. Create one in Blocks first.",{type:"warning"});return}const t=E.modal({title:"Insert Block",size:"lg"}),k=document.createElement("div");k.style.cssText="display:flex;gap:1rem;min-height:320px;";const m=document.createElement("div");m.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 w=document.createElement("select");w.className="form-select";const x=document.createElement("option");x.value="",x.textContent="\u2014 select a template \u2014",w.appendChild(x),l.forEach(i=>{const g=document.createElement("option");g.value=i.name,g.textContent=i.name,w.appendChild(g)}),m.appendChild(u),m.appendChild(w);const h=document.createElement("div");h.style.cssText="display:flex;flex-direction:column;gap:.5rem;overflow-y:auto;max-height:260px;",m.appendChild(h);const c=document.createElement("button");c.className="btn btn-primary",c.type="button",c.textContent="Insert",c.disabled=!0,m.appendChild(c);const p=document.createElement("div");p.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 F=document.createElement("p");F.className="text-muted",F.style.cssText="font-size:.8rem;margin:0;",F.textContent="Select a template to see a preview.",p.appendChild(F),k.appendChild(m),k.appendChild(p),t.element.appendChild(k),t.open();let N=null,b=[];function f(i){return i.replace(/_/g," ").replace(/\b\w/g,g=>g.toUpperCase())}function B(){if(!N)return;const i={};b.forEach(({key:n,input:r})=>{i[n]=r.value});const g=N.replace(/\{\{([\w_]+)\}\}/g,(n,r)=>(i[r]??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"));p.innerHTML=DOMPurify.sanitize(g)}function y(i){h.textContent="",b=[];const g=new Set(["_id","_createdAt","_updatedAt"]),n=new Set;for(const[,r]of i.matchAll(/\{\{([\w_]+)\}\}/g))g.has(r)||n.add(r);if(!n.size){const r=document.createElement("p");r.className="text-muted",r.style.cssText="font-size:.8rem;margin:0;",r.textContent="No editable placeholders in this template.",h.appendChild(r);return}n.forEach(r=>{const v=document.createElement("div"),A=document.createElement("label");A.className="form-label",A.style.cssText="font-size:.8rem;margin-bottom:.2rem;display:block;",A.textContent=f(r);const q=document.createElement("input");q.type="text",q.className="form-input",q.placeholder=f(r),q.addEventListener("input",B),v.appendChild(A),v.appendChild(q),h.appendChild(v),b.push({key:r,input:q})})}w.addEventListener("change",async()=>{const i=w.value;if(!i){N=null,b=[],h.textContent="",p.textContent="",p.appendChild(F),c.disabled=!0;return}N=null,b=[],h.textContent="",c.disabled=!0;try{N=(await Y.blocks.get(i)).content||"",y(N),B(),c.disabled=!1}catch{E.toast("Could not load template.",{type:"error"})}}),c.addEventListener("click",()=>{if(!w.value)return;const i=r=>r.replace(/"/g,"&quot;");let g=`template="${i(w.value)}"`;b.forEach(({key:r,input:v})=>{v.value!==""&&(g+=` ${r}="${i(v.value)}"`)});const n=`[block ${g} /]`;ke(e,n),e.dispatchEvent(new Event("input",{bubbles:!0})),t.close(),e.focus()})}),M.onForm(async e=>{const l=await Y.forms.list().catch(()=>[]),t=document.createElement("div");t.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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"),w=document.createElement("label");w.style.cssText=k,w.textContent="Form";const x=document.createElement("select");if(x.style.cssText=m,l.length)l.forEach(p=>{const F=document.createElement("option");F.value=p.slug,F.textContent=p.title||p.slug,x.appendChild(F)});else{const p=document.createElement("option");p.value="",p.textContent="No forms found",x.appendChild(p)}u.appendChild(w),u.appendChild(x),t.appendChild(u);const h=document.createElement("button");h.className="btn btn-primary btn-sm",h.style.cssText="align-self:flex-end;margin-top:.5rem;",h.textContent="Insert Form",t.appendChild(h);const c=E.modal({title:"Insert Form",size:"sm"});c.element.appendChild(t),c.open(),h.addEventListener("click",()=>{const p=x.value;p&&(ke(e,`[form slug="${p}" /]`),c.close(),ce.get(0).dispatchEvent(new Event("input",{bubbles:!0})))})}),M.onView(async e=>{const l=await Y.views.list().catch(()=>[]),t=document.createElement("div");t.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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"),w=document.createElement("label");w.style.cssText=k,w.textContent="View";const x=document.createElement("select");if(x.style.cssText=m,l.length)l.forEach(b=>{const f=document.createElement("option");f.value=b.slug,f.textContent=b.title||b.slug,x.appendChild(f)});else{const b=document.createElement("option");b.value="",b.textContent="No Views configured yet \u2014 create one under Data \u2192 Views",x.appendChild(b)}u.appendChild(w),u.appendChild(x),t.appendChild(u);const h=document.createElement("div"),c=document.createElement("label");c.style.cssText=k,c.textContent="Display";const p=document.createElement("select");p.style.cssText=m,["table","cards","list"].forEach(b=>{const f=document.createElement("option");f.value=b,f.textContent=b.charAt(0).toUpperCase()+b.slice(1),p.appendChild(f)}),h.appendChild(c),h.appendChild(p),t.appendChild(h);const F=document.createElement("button");F.type="button",F.className="btn btn-primary",F.textContent="Insert",t.appendChild(F);const N=E.modal({title:"Insert View",size:"sm"});N.element.appendChild(t),N.open(),F.addEventListener("click",()=>{const b=x.value;if(!b)return;const f=`[view slug="${b}" display="${p.value}" /]`;N.close(),ke(e,f),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onCta(async e=>{const l=await Y.actions.list().catch(()=>[]),t=document.createElement("div");t.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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 u(y,i){const g=document.createElement("div"),n=document.createElement("label");return n.style.cssText=k,n.textContent=y,g.appendChild(n),g.appendChild(i),g}function w(y){const i=document.createElement("select");return i.style.cssText=m,y.forEach(([g,n])=>{const r=document.createElement("option");r.value=g,r.textContent=n,i.appendChild(r)}),i}function x(y,i,g){const n=document.createElement("input");return n.type=y,n.placeholder=i||"",n.value=g||"",n.style.cssText=m,n}const h=w(l.length?l.map(y=>[y.slug,y.title||y.slug]):[["","No Actions configured yet \u2014 create one under Data \u2192 Actions"]]);t.appendChild(u("Action",h));const c=x("text","Button label","Run");if(t.appendChild(u("Label",c)),h.addEventListener("change",()=>{const y=l.find(i=>i.slug===h.value);y?.trigger?.label&&(c.value=y.trigger.label)}),l.length){const y=l[0];y?.trigger?.label&&(c.value=y.trigger.label)}const p=x("text","Paste entry UUID\u2026","");t.appendChild(u("Entry ID",p));const F=w([["primary","Primary"],["secondary","Secondary"],["ghost","Ghost"],["danger","Danger"]]);t.appendChild(u("Style",F));const N=x("text","e.g. check, zap, send (optional)","");t.appendChild(u("Icon",N));const b=x("text","Confirmation message (optional)","");t.appendChild(u("Confirm prompt",b));const f=document.createElement("button");f.type="button",f.className="btn btn-primary",f.textContent="Insert",t.appendChild(f);const B=E.modal({title:"Insert CTA Button",size:"sm"});B.element.appendChild(t),B.open(),f.addEventListener("click",()=>{const y=h.value;if(!y)return;const i=p.value.trim(),g=(c.value.trim()||"Run").replace(/\[\/cta\]/gi,""),n=F.value,r=N.value.trim().replace(/"/g,""),v=b.value.trim().replace(/"/g,""),A=i.replace(/"/g,"");let q=`action="${y}" style="${n}"`;A&&(q+=` entry="${A}"`),r&&(q+=` icon="${r}"`),v&&(q+=` confirm="${v}"`);const j=`[cta ${q}]${g}[/cta]`;B.close(),ke(e,j),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onButton(async e=>{const l=(await Y.pages.list().catch(()=>[])).map(n=>({label:n.title||n.urlPath,value:n.urlPath})),t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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 u(n,r){const v=document.createElement("div"),A=document.createElement("label");return A.style.cssText=k,A.textContent=n,v.appendChild(A),v.appendChild(r),v}function w(n,r){const v=document.createElement("input");return v.type="text",v.placeholder=n,v.value=r||"",v.style.cssText=m,v}function x(n){const r=document.createElement("select");return r.style.cssText=m,n.forEach(([v,A])=>{const q=document.createElement("option");q.value=v,q.textContent=A,r.appendChild(q)}),r}const h=e.value.substring(e.selectionStart,e.selectionEnd),c=w("/about or https://example.com",h.startsWith("/")?h:"");t.appendChild(u("URL",c));const p=w("Button label",h&&!h.startsWith("/")?h:"");t.appendChild(u("Label",p));const F=x([["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"]]);t.appendChild(u("Variant",F));const N=x([["","Default"],["sm","Small"],["lg","Large"]]);t.appendChild(u("Size",N));const b=w("e.g. arrow-right, star (optional)","");t.appendChild(u("Icon (before label)",b));const f=w("e.g. arrow-right (optional)","");t.appendChild(u("Icon (after label)",f));const B=document.createElement("label");B.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.9em;";const y=document.createElement("input");y.type="checkbox",y.style.cssText="width:1rem;height:1rem;",B.appendChild(y),B.appendChild(document.createTextNode("Open in new tab")),t.appendChild(B);const i=document.createElement("button");i.type="button",i.className="btn btn-primary",i.textContent="Insert Button",t.appendChild(i);const g=E.modal({title:"Insert Button",size:"sm"});g.element.appendChild(t),g.open(),requestAnimationFrame(()=>{E.autocomplete(c,{data:l,minChars:1,onSelect:n=>{c.value=n.value,p.value||(p.value=n.label)}}),c.focus()}),i.addEventListener("click",()=>{const n=c.value.trim();if(!n)return;g.close();const r=p.value.trim()||n;let v=`href="${n}" variant="${F.value}"`;N.value&&(v+=` size="${N.value}"`);const A=b.value.trim().replace(/"/g,"");A&&(v+=` icon="${A}"`);const q=f.value.trim().replace(/"/g,"");q&&(v+=` icon-after="${q}"`),y.checked&&(v+=' target="_blank"');const j=`[button ${v}]${r}[/button]`;ke(e,j)})}),M.onLinkShortcode(async e=>{const l=(await Y.pages.list().catch(()=>[])).map(i=>({label:i.title||i.urlPath,value:i.urlPath})),t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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 u(i,g){const n=document.createElement("div"),r=document.createElement("label");return r.style.cssText=k,r.textContent=i,n.appendChild(r),n.appendChild(g),n}function w(i,g){const n=document.createElement("input");return n.type="text",n.placeholder=i,n.value=g||"",n.style.cssText=m,n}const x=e.value.substring(e.selectionStart,e.selectionEnd),h=w("/about or https://example.com",x.startsWith("/")?x:"");t.appendChild(u("URL",h));const c=w("Link text",x&&!x.startsWith("/")?x:"");t.appendChild(u("Link text",c));const p=w("e.g. text-primary, fw-bold (optional)","");t.appendChild(u("CSS class",p));const F=w("e.g. arrow-right (optional)","");t.appendChild(u("Icon (before text)",F));const N=w("e.g. external-link (optional)","");t.appendChild(u("Icon (after text)",N));const b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.9em;";const f=document.createElement("input");f.type="checkbox",f.style.cssText="width:1rem;height:1rem;",b.appendChild(f),b.appendChild(document.createTextNode("Open in new tab")),t.appendChild(b);const B=document.createElement("button");B.type="button",B.className="btn btn-primary",B.textContent="Insert Link",t.appendChild(B);const y=E.modal({title:"Insert Link Shortcode",size:"sm"});y.element.appendChild(t),y.open(),requestAnimationFrame(()=>{E.autocomplete(h,{data:l,minChars:1,onSelect:i=>{h.value=i.value,c.value||(c.value=i.label)}}),h.focus()}),B.addEventListener("click",()=>{const i=h.value.trim();if(!i)return;y.close();const g=c.value.trim()||i;let n=`href="${i}"`;const r=p.value.trim().replace(/"/g,"");r&&(n+=` class="${r}"`);const v=F.value.trim().replace(/"/g,"");v&&(n+=` icon="${v}"`);const A=N.value.trim().replace(/"/g,"");A&&(n+=` icon-after="${A}"`),f.checked&&(n+=' target="_blank"');const q=`[link ${n}]${g}[/link]`;ke(e,q)})}),M.onTabs(e=>{const l=document.createElement("div");l.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const t="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",k="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 m(y,i){const g=document.createElement("div"),n=document.createElement("label");return n.style.cssText=t,n.textContent=y,g.appendChild(n),g.appendChild(i),g}function u(y){const i=document.createElement("select");return i.style.cssText=k,y.forEach(([g,n])=>{const r=document.createElement("option");r.value=g,r.textContent=n,i.appendChild(r)}),i}const w=u([["","Default (underline)"],["pills","Pills"]]);l.appendChild(m("Style",w));const x=u([["","Left"],["center","Centre"]]);l.appendChild(m("Alignment",x));const h=document.createElement("div");h.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const c=[];function p(){c.forEach(y=>{y.removeBtn.disabled=c.length<=2,y.removeBtn.style.opacity=c.length<=2?"0.3":"1"})}function F(y){const i=document.createElement("div");i.style.cssText="display:flex;gap:.4rem;align-items:center;";const g=document.createElement("input");g.type="text",g.placeholder="Tab title",g.value=y||"",g.style.cssText=k+"flex:1;";const n=document.createElement("button");n.type="button",n.textContent="\u2715",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 r={row:i,input:g,removeBtn:n};c.push(r),i.appendChild(g),i.appendChild(n),h.appendChild(i),n.addEventListener("click",()=>{if(c.length<=2)return;const v=c.indexOf(r);c.splice(v,1),h.removeChild(i),p()}),p()}F("Overview"),F("Details");const N=document.createElement("div");N.style.cssText=t,N.textContent="Tabs",l.appendChild(N),l.appendChild(h);const b=document.createElement("button");b.type="button",b.textContent="+ Add Tab",b.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;",b.addEventListener("click",()=>{c.length>=10||(F(""),c[c.length-1].input.focus())}),l.appendChild(b);const f=document.createElement("button");f.type="button",f.className="btn btn-primary",f.textContent="Insert Tabs",l.appendChild(f);const B=E.modal({title:"Insert Tabs",size:"sm"});B.element.appendChild(l),B.open(),requestAnimationFrame(()=>c[0].input.focus()),f.addEventListener("click",()=>{B.close();const y=w.value,i=x.value;let g=y?` style="${y}"`:"";i&&(g+=` align="${i}"`);let n=`[tabs${g}]
88
+ `)}const Ge="editor_prefs";function Ue(){return S.get(Ge)||{viewMode:"split",fullscreen:!1}}function Ve(a,ie){const oe=Ue();oe[a]=ie,S.set(Ge,oe)}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(a){const ie=window.location.hash.match(/#\/pages\/edit(\/.*)/),oe=ie?ie[1]:null,U=!!oe,J=E.loader(a.get(0),{type:"dots"}),ze=[Y.layouts.get().catch(()=>({})),Y.settings.get().catch(()=>({}))];U&&(ze.push(Y.pages.get(oe).catch(()=>null)),ze.push(Y.pages.list().catch(()=>[])));const[$e,Ie,W,Te]=await Promise.all(ze);J.destroy(),Ye(a.find("#field-theme").get(0),{includeDefault:!0});const Le=Ie?.layoutOptions?.spacerSize??40;if(U&&!W){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}a.find("#editor-title").text(U?`Edit Page \u2014 ${W.title||oe}`:"New Page"),U&&a.find("#page-url-path").val(oe),W&&(a.find("#field-title").val(W.title||""),a.find("#field-description").val(W.description||""),a.find("#field-status").val(W.status||"draft"),a.find("#field-sort-order").val(W.sortOrder??99),a.find("#field-show-in-nav").prop("checked",!!W.showInNav),a.find("#field-sidebar").prop("checked",!!W.sidebar),a.find("#field-show-breadcrumbs").prop("checked",W.breadcrumbs!==!1),a.find("#field-bundled").prop("checked",!!W.bundled),a.find("#field-category").val(W.category||""),a.find("#field-visibility").val(W.visibility||"public"),a.find("#field-theme").val(W.theme||""),a.find("#field-seo-title").val(W.seo?.title||""),a.find("#field-seo-desc").val(W.seo?.description||""),W.dconfig&&a.find("#field-dconfig").val(JSON.stringify(W.dconfig,null,2)));const ge=a.find("#quick-switch");U&&Array.isArray(Te)&&Te.length&&([...Te].sort((e,l)=>(e.title||e.urlPath).localeCompare(l.title||l.urlPath)).forEach(e=>{const l=document.createElement("option");l.value=e.urlPath,l.textContent=`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath===oe&&(l.selected=!0),ge.get(0).appendChild(l)}),ge.css("display",""),ge.on("change",function(){const e=this.value;e&&R.navigate("/pages/edit"+e)}));const le=await Y.pages.tags().catch(()=>[]),fe=a.find("#field-tags").get(0),Ce=fe?E.pillbox(fe,{data:le,value:W?.tags||[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026"}):null,Be=a.find("#field-layout").empty();if(Object.entries($e).forEach(([e,l])=>{const t=(W?.layout||"default")===e?"selected":"";Be.append(`<option value="${e}" ${t}>${l.label||e}</option>`)}),U){const e=a.find("#view-page-btn").get(0);e.href=oe,e.style.display="";const l=a.find("#live-preview-tab").get(0);l.style.display="";const t=a.find("#history-tab").get(0);t.style.display=""}if(E.tabs(a.find("#editor-meta-tabs").get(0)),U){const e=a.find("#live-preview-tab").get(0),l=a.find("#live-preview-frame").get(0);let t=!1;e.addEventListener("click",function(){t||(l.src=oe,t=!0)}),Ke(a,oe)}const ce=a.find("#markdown-editor"),Q=a.find("#markdown-preview");W&&ce.val(W.content||"");let ne=!1,be="";Y.settings.getCustomCss().then(({css:e})=>{if(be=e||"",!be)return;const l=document.createElement("style");l.id="preview-custom-css",l.textContent=be,Q.get(0).parentNode.insertBefore(l,Q.get(0))}).catch(()=>{});let ee=!1;const V=ce.get(0),z=document.createElement("div");z.className="editor-line-numbers editor-line-numbers--foldable",V.parentElement.insertBefore(z,V);const ae=Je(V,z,{onFoldChange:()=>{}});ae.setGuard(e=>{ee=e});const pe=()=>{ae.refresh(),z.scrollTop=V.scrollTop};V.addEventListener("input",pe),V.addEventListener("scroll",()=>{z.scrollTop=V.scrollTop});let ye=null;const De=()=>{clearTimeout(ye),ye=setTimeout(async()=>{const e=ae.getUnfoldedContent();try{const{html:l}=await Y.pages.preview(e);Q.html(l,{safe:!1}),I.scan(Q.get(0)),Q.get(0).querySelectorAll(".tabs").forEach(t=>Domma.elements.tabs(t))}catch{window.marked&&Q.html(marked.parse(e))}},400)},M=_e(ce,a.find("#editor-toolbar"),{spacerDefault:Le});let Z=!1,se="split",xe=null;const de=document.createElement("button");de.className="editor-view-btn",de.type="button";const Ne=document.createElement("span");Ne.setAttribute("data-icon","css-code"),de.appendChild(Ne);const me=document.createElement("button");me.className="editor-view-btn",me.type="button";const Se=document.createElement("span");Se.setAttribute("data-icon","code"),me.appendChild(Se);let Ee=!1;const te=document.createElement("button");te.className="editor-view-btn",te.type="button",te.textContent="\u25BC\u25BC",te.style.cssText="font-size:9px;letter-spacing:-1px;";const ve=a.find(".editor-toolbar-right").get(0);ve.prepend(te),ve.prepend(me),ve.prepend(de),I.scan(de),I.scan(me),E.tooltip(de,{content:"Edit Custom CSS",position:"top"}),E.tooltip(me,{content:"Format Markdown",position:"top"}),E.tooltip(te,{content:"Fold / unfold all shortcodes",position:"top"}),me.addEventListener("click",()=>{const e=ce.get(0),l=e.selectionStart,t=Ze(ae.getUnfoldedContent());ae.unfoldAll(),ee=!0,e.value=t,ee=!1,e.selectionStart=e.selectionEnd=Math.min(l,t.length),e.dispatchEvent(new Event("input")),ae.refresh(),E.toast("Markdown formatted.",{type:"success"})}),te.addEventListener("click",()=>{Ee?(ae.unfoldAll(),te.textContent="\u25BC\u25BC",te.classList.remove("active")):(ae.foldAll(),te.textContent="\u25B6\u25B6",te.classList.add("active")),Ee=!Ee});const re=document.createElement("span");re.className="editor-toolbar-sep",ve.insertBefore(re,ve.children[3]),de.addEventListener("click",()=>{Z=!Z;const e=a.find("#markdown-editor"),l=a.find("#css-editor"),t=a.find("#editor-body");if(Z){const k=a.find(".editor-view-btn[data-mode].active").get(0);se=k?k.getAttribute("data-mode"):"split",a.find(".editor-view-btn[data-mode]").removeClass("active"),a.find('.editor-view-btn[data-mode="split"]').addClass("active"),t.removeClass("editor-mode-write editor-mode-preview").addClass("editor-mode-split"),e.hide(),l.show(),ne||(l.val(be),ne=!0,We(l.get(0))),de.classList.add("active")}else a.find(".editor-view-btn[data-mode]").removeClass("active"),a.find(`.editor-view-btn[data-mode="${se}"]`).addClass("active"),t.removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${se}`),l.hide(),e.show(),de.classList.remove("active")});const ue=Ue();ue.viewMode&&ue.viewMode!=="split"&&(a.find(".editor-view-btn[data-mode]").removeClass("active"),a.find(`.editor-view-btn[data-mode="${ue.viewMode}"]`).addClass("active"),a.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${ue.viewMode}`)),ue.fullscreen&&a.find(".editor-card").addClass("editor-fullscreen"),a.find("#css-editor").on("input",()=>{clearTimeout(xe),xe=setTimeout(()=>{let e=document.getElementById("preview-custom-css");e||(e=document.createElement("style"),e.id="preview-custom-css",Q.get(0).parentNode.insertBefore(e,Q.get(0))),e.textContent=a.find("#css-editor").val()},400)}),M.onLink(async e=>{const l=(await Y.pages.list().catch(()=>[])).map(f=>({label:f.title||f.urlPath,value:f.urlPath})),t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const k=document.createElement("label");k.className="form-label",k.textContent="URL";const m=document.createElement("input");m.type="text",m.className="form-input",m.placeholder="/about or https://example.com";const u=e.value.substring(e.selectionStart,e.selectionEnd);u&&u.startsWith("/")&&(m.value=u),t.appendChild(k),t.appendChild(m);const w=document.createElement("label");w.className="form-label",w.textContent="Link text";const x=document.createElement("input");x.type="text",x.className="form-input",x.placeholder="Display text",u&&!u.startsWith("/")&&(x.value=u),t.appendChild(w),t.appendChild(x);const h=document.createElement("label");h.className="form-label",h.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;",h.appendChild(c),h.appendChild(document.createTextNode("Display as button")),t.appendChild(h);const p=document.createElement("label");p.className="form-label",p.textContent="Button colour",p.style.display="none";const F=document.createElement("select");F.className="form-select",F.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(([f,B])=>{const y=document.createElement("option");y.value=f,y.textContent=B,F.appendChild(y)}),t.appendChild(p),t.appendChild(F),c.addEventListener("change",()=>{const f=c.checked;p.style.display=f?"":"none",F.style.display=f?"":"none"});const N=document.createElement("button");N.type="button",N.className="btn btn-primary",N.textContent="Insert Link",t.appendChild(N);const b=E.modal({title:"Insert Link",size:"sm"});b.element.appendChild(t),b.open(),requestAnimationFrame(()=>{E.autocomplete(m,{data:l,minChars:1,onSelect:f=>{m.value=f.value,x.value||(x.value=f.label)}}),m.focus()}),N.addEventListener("click",()=>{const f=m.value.trim(),B=x.value.trim();if(!f)return;b.close();const y=c.checked?`[button href="${f}" variant="${F.value}"]${B||f}[/button]`:`[${B||f}](${f})`,i=e.selectionStart,g=e.selectionEnd;e.value=e.value.substring(0,i)+y+e.value.substring(g),e.selectionStart=e.selectionEnd=i+y.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onImage(async e=>{const l=(await Y.media.list().catch(()=>[])).filter(m=>/\.(png|jpe?g|gif|webp|svg)$/i.test(m.name)),t=document.createElement("div");if(t.className="media-picker-grid",l.length)l.forEach(m=>{const u=document.createElement("div");u.className="media-picker-item",u.dataset.url=m.url;const w=document.createElement("img");w.src=m.url,w.alt=m.name;const x=document.createElement("span");x.textContent=m.name,u.appendChild(w),u.appendChild(x),t.appendChild(u)});else{const m=document.createElement("p");m.className="text-muted p-3",m.textContent="No images uploaded yet.",t.appendChild(m)}const k=E.modal({title:"Insert Image",size:"lg"});k.element.appendChild(t),$(k.element).on("click",".media-picker-item",function(){const m=$(this).data("url"),u=$(this).find("span").text();ke(e,`![${u}](${m})`),k.close(),ce.get(0).dispatchEvent(new Event("input",{bubbles:!0}))}),k.open()}),M.onCollection(async e=>{const[l,t]=await Promise.all([Y.collections.list().catch(()=>[]),Y.blocks.list().catch(()=>[])]),k=document.createElement("div");k.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const m="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;",w=document.createElement("div"),x=document.createElement("label");x.style.cssText=m,x.textContent="Collection";const h=document.createElement("select");if(h.style.cssText=u,l.length)l.forEach(G=>{const K=document.createElement("option");K.value=G.slug,K.textContent=G.title||G.slug,h.appendChild(K)});else{const G=document.createElement("option");G.value="",G.textContent="No collections found",h.appendChild(G)}w.appendChild(x),w.appendChild(h),k.appendChild(w);const c=document.createElement("div"),p=document.createElement("label");p.style.cssText=m,p.textContent="Display";const F=document.createElement("select");F.style.cssText=u,["table","cards","list","block"].forEach(G=>{const K=document.createElement("option");K.value=G,K.textContent=G.charAt(0).toUpperCase()+G.slice(1),F.appendChild(K)}),c.appendChild(p),c.appendChild(F),k.appendChild(c);const N=document.createElement("div");N.style.display="none";const b=document.createElement("label");b.style.cssText=m,b.textContent="Columns (2\u20134)";const f=document.createElement("input");f.type="number",f.min="2",f.max="4",f.value="3",f.style.cssText=u,N.appendChild(b),N.appendChild(f),k.appendChild(N);const B=document.createElement("div");B.style.display="none";const y=document.createElement("label");y.style.cssText=m,y.textContent="Block template";const i=document.createElement("select");if(i.style.cssText=u,t.length)t.forEach(G=>{const K=document.createElement("option");K.value=G.name??G,K.textContent=G.name??G,i.appendChild(K)});else{const G=document.createElement("option");G.value="",G.textContent="No block templates found",i.appendChild(G)}B.appendChild(y),B.appendChild(i),k.appendChild(B);const g=document.createElement("div"),n=document.createElement("label");n.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const r=document.createElement("input");r.type="checkbox",r.checked=!0,n.appendChild(r),n.appendChild(document.createTextNode("Enable search")),g.appendChild(n),k.appendChild(g);const v=document.createElement("div"),A=document.createElement("label");A.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const q=document.createElement("input");q.type="checkbox",q.checked=!0,A.appendChild(q),A.appendChild(document.createTextNode("Sortable columns")),v.appendChild(A),k.appendChild(v);const j=document.createElement("div"),T=document.createElement("label");T.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const C=document.createElement("input");C.type="checkbox",C.checked=!1,T.appendChild(C),T.appendChild(document.createTextNode("CSV export")),j.appendChild(T),k.appendChild(j);const d=document.createElement("div"),s=document.createElement("label");s.style.cssText=m,s.textContent="Rows per page";const o=document.createElement("input");o.type="number",o.min="5",o.max="100",o.value="25",o.style.cssText=u,d.appendChild(s),d.appendChild(o),k.appendChild(d);const he=document.createElement("div"),H=document.createElement("label");H.style.cssText=m,H.textContent="Limit (optional)";const X=document.createElement("input");X.type="number",X.placeholder="All",X.style.cssText=u,he.appendChild(H),he.appendChild(X),k.appendChild(he);const P=document.createElement("button");P.type="button",P.className="btn btn-primary",P.textContent="Insert",k.appendChild(P);const L=[g,v,j,d],O=()=>{const G=F.value,K=G==="table";L.forEach(we=>{we.style.display=K?"":"none"}),N.style.display=G==="cards"||G==="block"?"":"none",B.style.display=G==="block"?"":"none"};F.addEventListener("change",O),O();const _=E.modal({title:"Insert Collection",size:"sm"});_.element.appendChild(k),_.open(),P.addEventListener("click",()=>{const G=h.value;if(!G)return;const K=F.value;let we=`[collection slug="${G}" display="${K}"`;if(K==="cards"&&(we+=` columns="${f.value}"`),K==="block"){const Me=i.value;Me&&(we+=` block="${Me}"`);const qe=f.value.trim();qe&&(we+=` cols="${qe}"`)}K==="table"&&!r.checked&&(we+=' search="false"'),K==="table"&&!q.checked&&(we+=' sortable="false"'),K==="table"&&C.checked&&(we+=' exportable="true"'),K==="table"&&o.value!=="25"&&(we+=` page-size="${o.value}"`);const Re=X.value.trim();Re&&(we+=` limit="${Re}"`),we+=" /]",_.close(),ke(e,we),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onBlock(async e=>{let l=[];try{l=await Y.blocks.list()}catch{E.toast("Could not load blocks.",{type:"error"});return}if(!l.length){E.toast("No block templates found. Create one in Blocks first.",{type:"warning"});return}const t=E.modal({title:"Insert Block",size:"lg"}),k=document.createElement("div");k.style.cssText="display:flex;gap:1rem;min-height:320px;";const m=document.createElement("div");m.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 w=document.createElement("select");w.className="form-select";const x=document.createElement("option");x.value="",x.textContent="\u2014 select a template \u2014",w.appendChild(x),l.forEach(i=>{const g=document.createElement("option");g.value=i.name,g.textContent=i.name,w.appendChild(g)}),m.appendChild(u),m.appendChild(w);const h=document.createElement("div");h.style.cssText="display:flex;flex-direction:column;gap:.5rem;overflow-y:auto;max-height:260px;",m.appendChild(h);const c=document.createElement("button");c.className="btn btn-primary",c.type="button",c.textContent="Insert",c.disabled=!0,m.appendChild(c);const p=document.createElement("div");p.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 F=document.createElement("p");F.className="text-muted",F.style.cssText="font-size:.8rem;margin:0;",F.textContent="Select a template to see a preview.",p.appendChild(F),k.appendChild(m),k.appendChild(p),t.element.appendChild(k),t.open();let N=null,b=[];function f(i){return i.replace(/_/g," ").replace(/\b\w/g,g=>g.toUpperCase())}function B(){if(!N)return;const i={};b.forEach(({key:n,input:r})=>{i[n]=r.value});const g=N.replace(/\{\{([\w_]+)\}\}/g,(n,r)=>(i[r]??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"));p.innerHTML=DOMPurify.sanitize(g)}function y(i){h.textContent="",b=[];const g=new Set(["_id","_createdAt","_updatedAt"]),n=new Set;for(const[,r]of i.matchAll(/\{\{([\w_]+)\}\}/g))g.has(r)||n.add(r);if(!n.size){const r=document.createElement("p");r.className="text-muted",r.style.cssText="font-size:.8rem;margin:0;",r.textContent="No editable placeholders in this template.",h.appendChild(r);return}n.forEach(r=>{const v=document.createElement("div"),A=document.createElement("label");A.className="form-label",A.style.cssText="font-size:.8rem;margin-bottom:.2rem;display:block;",A.textContent=f(r);const q=document.createElement("input");q.type="text",q.className="form-input",q.placeholder=f(r),q.addEventListener("input",B),v.appendChild(A),v.appendChild(q),h.appendChild(v),b.push({key:r,input:q})})}w.addEventListener("change",async()=>{const i=w.value;if(!i){N=null,b=[],h.textContent="",p.textContent="",p.appendChild(F),c.disabled=!0;return}N=null,b=[],h.textContent="",c.disabled=!0;try{N=(await Y.blocks.get(i)).content||"",y(N),B(),c.disabled=!1}catch{E.toast("Could not load template.",{type:"error"})}}),c.addEventListener("click",()=>{if(!w.value)return;const i=r=>r.replace(/"/g,"&quot;");let g=`template="${i(w.value)}"`;b.forEach(({key:r,input:v})=>{v.value!==""&&(g+=` ${r}="${i(v.value)}"`)});const n=`[block ${g} /]`;ke(e,n),e.dispatchEvent(new Event("input",{bubbles:!0})),t.close(),e.focus()})}),M.onForm(async e=>{const l=await Y.forms.list().catch(()=>[]),t=document.createElement("div");t.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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"),w=document.createElement("label");w.style.cssText=k,w.textContent="Form";const x=document.createElement("select");if(x.style.cssText=m,l.length)l.forEach(p=>{const F=document.createElement("option");F.value=p.slug,F.textContent=p.title||p.slug,x.appendChild(F)});else{const p=document.createElement("option");p.value="",p.textContent="No forms found",x.appendChild(p)}u.appendChild(w),u.appendChild(x),t.appendChild(u);const h=document.createElement("button");h.className="btn btn-primary btn-sm",h.style.cssText="align-self:flex-end;margin-top:.5rem;",h.textContent="Insert Form",t.appendChild(h);const c=E.modal({title:"Insert Form",size:"sm"});c.element.appendChild(t),c.open(),h.addEventListener("click",()=>{const p=x.value;p&&(ke(e,`[form slug="${p}" /]`),c.close(),ce.get(0).dispatchEvent(new Event("input",{bubbles:!0})))})}),M.onView(async e=>{const l=await Y.views.list().catch(()=>[]),t=document.createElement("div");t.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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"),w=document.createElement("label");w.style.cssText=k,w.textContent="View";const x=document.createElement("select");if(x.style.cssText=m,l.length)l.forEach(b=>{const f=document.createElement("option");f.value=b.slug,f.textContent=b.title||b.slug,x.appendChild(f)});else{const b=document.createElement("option");b.value="",b.textContent="No Views configured yet \u2014 create one under Data \u2192 Views",x.appendChild(b)}u.appendChild(w),u.appendChild(x),t.appendChild(u);const h=document.createElement("div"),c=document.createElement("label");c.style.cssText=k,c.textContent="Display";const p=document.createElement("select");p.style.cssText=m,["table","cards","list"].forEach(b=>{const f=document.createElement("option");f.value=b,f.textContent=b.charAt(0).toUpperCase()+b.slice(1),p.appendChild(f)}),h.appendChild(c),h.appendChild(p),t.appendChild(h);const F=document.createElement("button");F.type="button",F.className="btn btn-primary",F.textContent="Insert",t.appendChild(F);const N=E.modal({title:"Insert View",size:"sm"});N.element.appendChild(t),N.open(),F.addEventListener("click",()=>{const b=x.value;if(!b)return;const f=`[view slug="${b}" display="${p.value}" /]`;N.close(),ke(e,f),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onCta(async e=>{const l=await Y.actions.list().catch(()=>[]),t=document.createElement("div");t.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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 u(y,i){const g=document.createElement("div"),n=document.createElement("label");return n.style.cssText=k,n.textContent=y,g.appendChild(n),g.appendChild(i),g}function w(y){const i=document.createElement("select");return i.style.cssText=m,y.forEach(([g,n])=>{const r=document.createElement("option");r.value=g,r.textContent=n,i.appendChild(r)}),i}function x(y,i,g){const n=document.createElement("input");return n.type=y,n.placeholder=i||"",n.value=g||"",n.style.cssText=m,n}const h=w(l.length?l.map(y=>[y.slug,y.title||y.slug]):[["","No Actions configured yet \u2014 create one under Data \u2192 Actions"]]);t.appendChild(u("Action",h));const c=x("text","Button label","Run");if(t.appendChild(u("Label",c)),h.addEventListener("change",()=>{const y=l.find(i=>i.slug===h.value);y?.trigger?.label&&(c.value=y.trigger.label)}),l.length){const y=l[0];y?.trigger?.label&&(c.value=y.trigger.label)}const p=x("text","Paste entry UUID\u2026","");t.appendChild(u("Entry ID",p));const F=w([["primary","Primary"],["secondary","Secondary"],["ghost","Ghost"],["danger","Danger"]]);t.appendChild(u("Style",F));const N=x("text","e.g. check, zap, send (optional)","");t.appendChild(u("Icon",N));const b=x("text","Confirmation message (optional)","");t.appendChild(u("Confirm prompt",b));const f=document.createElement("button");f.type="button",f.className="btn btn-primary",f.textContent="Insert",t.appendChild(f);const B=E.modal({title:"Insert CTA Button",size:"sm"});B.element.appendChild(t),B.open(),f.addEventListener("click",()=>{const y=h.value;if(!y)return;const i=p.value.trim(),g=(c.value.trim()||"Run").replace(/\[\/cta\]/gi,""),n=F.value,r=N.value.trim().replace(/"/g,""),v=b.value.trim().replace(/"/g,""),A=i.replace(/"/g,"");let q=`action="${y}" style="${n}"`;A&&(q+=` entry="${A}"`),r&&(q+=` icon="${r}"`),v&&(q+=` confirm="${v}"`);const j=`[cta ${q}]${g}[/cta]`;B.close(),ke(e,j),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onButton(async e=>{const l=(await Y.pages.list().catch(()=>[])).map(n=>({label:n.title||n.urlPath,value:n.urlPath})),t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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 u(n,r){const v=document.createElement("div"),A=document.createElement("label");return A.style.cssText=k,A.textContent=n,v.appendChild(A),v.appendChild(r),v}function w(n,r){const v=document.createElement("input");return v.type="text",v.placeholder=n,v.value=r||"",v.style.cssText=m,v}function x(n){const r=document.createElement("select");return r.style.cssText=m,n.forEach(([v,A])=>{const q=document.createElement("option");q.value=v,q.textContent=A,r.appendChild(q)}),r}const h=e.value.substring(e.selectionStart,e.selectionEnd),c=w("/about or https://example.com",h.startsWith("/")?h:"");t.appendChild(u("URL",c));const p=w("Button label",h&&!h.startsWith("/")?h:"");t.appendChild(u("Label",p));const F=x([["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"]]);t.appendChild(u("Variant",F));const N=x([["","Default"],["sm","Small"],["lg","Large"]]);t.appendChild(u("Size",N));const b=w("e.g. arrow-right, star (optional)","");t.appendChild(u("Icon (before label)",b));const f=w("e.g. arrow-right (optional)","");t.appendChild(u("Icon (after label)",f));const B=document.createElement("label");B.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.9em;";const y=document.createElement("input");y.type="checkbox",y.style.cssText="width:1rem;height:1rem;",B.appendChild(y),B.appendChild(document.createTextNode("Open in new tab")),t.appendChild(B);const i=document.createElement("button");i.type="button",i.className="btn btn-primary",i.textContent="Insert Button",t.appendChild(i);const g=E.modal({title:"Insert Button",size:"sm"});g.element.appendChild(t),g.open(),requestAnimationFrame(()=>{E.autocomplete(c,{data:l,minChars:1,onSelect:n=>{c.value=n.value,p.value||(p.value=n.label)}}),c.focus()}),i.addEventListener("click",()=>{const n=c.value.trim();if(!n)return;g.close();const r=p.value.trim()||n;let v=`href="${n}" variant="${F.value}"`;N.value&&(v+=` size="${N.value}"`);const A=b.value.trim().replace(/"/g,"");A&&(v+=` icon="${A}"`);const q=f.value.trim().replace(/"/g,"");q&&(v+=` icon-after="${q}"`),y.checked&&(v+=' target="_blank"');const j=`[button ${v}]${r}[/button]`;ke(e,j)})}),M.onLinkShortcode(async e=>{const l=(await Y.pages.list().catch(()=>[])).map(i=>({label:i.title||i.urlPath,value:i.urlPath})),t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const k="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",m="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 u(i,g){const n=document.createElement("div"),r=document.createElement("label");return r.style.cssText=k,r.textContent=i,n.appendChild(r),n.appendChild(g),n}function w(i,g){const n=document.createElement("input");return n.type="text",n.placeholder=i,n.value=g||"",n.style.cssText=m,n}const x=e.value.substring(e.selectionStart,e.selectionEnd),h=w("/about or https://example.com",x.startsWith("/")?x:"");t.appendChild(u("URL",h));const c=w("Link text",x&&!x.startsWith("/")?x:"");t.appendChild(u("Link text",c));const p=w("e.g. text-primary, fw-bold (optional)","");t.appendChild(u("CSS class",p));const F=w("e.g. arrow-right (optional)","");t.appendChild(u("Icon (before text)",F));const N=w("e.g. external-link (optional)","");t.appendChild(u("Icon (after text)",N));const b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.9em;";const f=document.createElement("input");f.type="checkbox",f.style.cssText="width:1rem;height:1rem;",b.appendChild(f),b.appendChild(document.createTextNode("Open in new tab")),t.appendChild(b);const B=document.createElement("button");B.type="button",B.className="btn btn-primary",B.textContent="Insert Link",t.appendChild(B);const y=E.modal({title:"Insert Link Shortcode",size:"sm"});y.element.appendChild(t),y.open(),requestAnimationFrame(()=>{E.autocomplete(h,{data:l,minChars:1,onSelect:i=>{h.value=i.value,c.value||(c.value=i.label)}}),h.focus()}),B.addEventListener("click",()=>{const i=h.value.trim();if(!i)return;y.close();const g=c.value.trim()||i;let n=`href="${i}"`;const r=p.value.trim().replace(/"/g,"");r&&(n+=` class="${r}"`);const v=F.value.trim().replace(/"/g,"");v&&(n+=` icon="${v}"`);const A=N.value.trim().replace(/"/g,"");A&&(n+=` icon-after="${A}"`),f.checked&&(n+=' target="_blank"');const q=`[link ${n}]${g}[/link]`;ke(e,q)})}),M.onTabs(e=>{const l=document.createElement("div");l.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const t="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",k="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 m(y,i){const g=document.createElement("div"),n=document.createElement("label");return n.style.cssText=t,n.textContent=y,g.appendChild(n),g.appendChild(i),g}function u(y){const i=document.createElement("select");return i.style.cssText=k,y.forEach(([g,n])=>{const r=document.createElement("option");r.value=g,r.textContent=n,i.appendChild(r)}),i}const w=u([["","Default (underline)"],["pills","Pills"]]);l.appendChild(m("Style",w));const x=u([["","Left"],["center","Centre"]]);l.appendChild(m("Alignment",x));const h=document.createElement("div");h.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const c=[];function p(){c.forEach(y=>{y.removeBtn.disabled=c.length<=2,y.removeBtn.style.opacity=c.length<=2?"0.3":"1"})}function F(y){const i=document.createElement("div");i.style.cssText="display:flex;gap:.4rem;align-items:center;";const g=document.createElement("input");g.type="text",g.placeholder="Tab title",g.value=y||"",g.style.cssText=k+"flex:1;";const n=document.createElement("button");n.type="button",n.textContent="\u2715",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 r={row:i,input:g,removeBtn:n};c.push(r),i.appendChild(g),i.appendChild(n),h.appendChild(i),n.addEventListener("click",()=>{if(c.length<=2)return;const v=c.indexOf(r);c.splice(v,1),h.removeChild(i),p()}),p()}F("Overview"),F("Details");const N=document.createElement("div");N.style.cssText=t,N.textContent="Tabs",l.appendChild(N),l.appendChild(h);const b=document.createElement("button");b.type="button",b.textContent="+ Add Tab",b.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;",b.addEventListener("click",()=>{c.length>=10||(F(""),c[c.length-1].input.focus())}),l.appendChild(b);const f=document.createElement("button");f.type="button",f.className="btn btn-primary",f.textContent="Insert Tabs",l.appendChild(f);const B=E.modal({title:"Insert Tabs",size:"sm"});B.element.appendChild(l),B.open(),requestAnimationFrame(()=>c[0].input.focus()),f.addEventListener("click",()=>{B.close();const y=w.value,i=x.value;let g=y?` style="${y}"`:"";i&&(g+=` align="${i}"`);let n=`[tabs${g}]
89
89
  `;c.forEach((r,v)=>{const A=r.input.value.trim()||`Tab ${v+1}`;n+=`[tab title="${A}"]Tab content here.[/tab]
90
90
  `}),n+="[/tabs]",ke(e,n),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onGrid(e=>{const l=document.createElement("div");l.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const t="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",k="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 m(H,X){const P=document.createElement("div"),L=document.createElement("label");return L.style.cssText=t,L.textContent=H,P.appendChild(L),P.appendChild(X),P}function u(H){const X=document.createElement("select");return X.style.cssText=k,H.forEach(([P,L])=>{const O=document.createElement("option");O.value=P,O.textContent=L,X.appendChild(O)}),X}let w="grid";const x=document.createElement("div");x.style.cssText="display:flex;gap:.5rem;";const h=document.createElement("button");h.type="button",h.className="btn btn-sm btn-primary",h.textContent="Grid";const c=document.createElement("button");c.type="button",c.className="btn btn-sm btn-ghost",c.textContent="Row",x.appendChild(h),x.appendChild(c),l.appendChild(x);const p=document.createElement("input");p.type="number",p.min="1",p.max="12",p.value="2",p.style.cssText=k,l.appendChild(m("Columns",p));const F=u([["0","0"],["1","1"],["2","2"],["3","3"],["4","4 (default)"],["6","6"],["8","8"],["10","10"],["12","12"],["16","16"]]);F.value="4",l.appendChild(m("Gap",F));const N=document.createElement("div");N.style.cssText="display:flex;flex-direction:column;gap:.5rem;";const b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const f=document.createElement("input");f.type="checkbox",b.appendChild(f),b.appendChild(document.createTextNode("Full width (breakout)")),N.appendChild(b);const B=document.createElement("div");B.style.cssText=t+"margin-top:.25rem;",B.textContent="Column Spans",N.appendChild(B);const y=document.createElement("div");y.style.cssText="display:flex;flex-direction:column;gap:.3rem;",N.appendChild(y),l.appendChild(N);const i=[];function g(){const H=Math.min(Math.max(parseInt(p.value)||2,1),12),X=i.map(P=>P.value);y.textContent="",i.length=0;for(let P=0;P<H;P++){const L=document.createElement("div");L.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 _=document.createElement("input");_.type="number",_.min="1",_.max="12",_.placeholder="auto",_.value=X[P]||"",_.style.cssText=k+"width:5em;flex:none;",L.appendChild(O),L.appendChild(_),y.appendChild(L),i.push(_)}}p.addEventListener("input",g),g();const n=document.createElement("div");n.style.cssText="display:none;flex-direction:column;gap:.5rem;";const r=document.createElement("label");r.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const v=document.createElement("input");v.type="checkbox",r.appendChild(v),r.appendChild(document.createTextNode("Enable staggered reveal")),n.appendChild(r);const A=document.createElement("div");A.style.cssText="display:none;flex-direction:column;gap:.5rem;padding-left:.5rem;border-left:2px solid var(--dm-border,#333);";const q=u([["slide-up","Slide Up"],["slide-down","Slide Down"],["slide-left","Slide Left"],["slide-right","Slide Right"],["fade","Fade"],["zoom","Zoom"],["flip","Flip"]]);A.appendChild(m("Animation",q));const j=u([["stagger","Stagger"],["sequence","Sequence"]]);A.appendChild(m("Mode",j));const T=document.createElement("input");T.type="number",T.value="400",T.style.cssText=k,A.appendChild(m("Duration (ms)",T));const C=document.createElement("input");C.type="number",C.value="60",C.style.cssText=k,A.appendChild(m("Stagger (ms)",C));const d=document.createElement("input");d.type="number",d.value="0",d.style.cssText=k,A.appendChild(m("Delay (ms)",d));const s=u([["ltr","Left to Right"],["rtl","Right to Left"]]);A.appendChild(m("Direction",s)),n.appendChild(A),l.appendChild(n),v.addEventListener("change",()=>{A.style.display=v.checked?"flex":"none"});const o=document.createElement("button");o.type="button",o.className="btn btn-primary",o.textContent="Insert Grid",l.appendChild(o),h.addEventListener("click",()=>{w="grid",h.className="btn btn-sm btn-primary",c.className="btn btn-sm btn-ghost",N.style.display="flex",n.style.display="none",o.textContent="Insert Grid"}),c.addEventListener("click",()=>{w="row",c.className="btn btn-sm btn-primary",h.className="btn btn-sm btn-ghost",n.style.display="flex",N.style.display="none",o.textContent="Insert Row"});const he=E.modal({title:"Insert Grid / Row",size:"sm"});he.element.appendChild(l),he.open(),requestAnimationFrame(()=>p.focus()),o.addEventListener("click",()=>{he.close();const H=Math.min(Math.max(parseInt(p.value)||2,1),12),X=F.value;let P;if(w==="grid"){let L=`cols="${H}"`;X!=="4"&&(L+=` gap="${X}"`),f.checked&&(L+=' fullwidth="true"'),P=`[grid ${L}]
91
91
  `;for(let O=0;O<H;O++){const _=i[O]?.value?.trim(),G=_?` span="${_}"`:"";P+=`[col${G}]
@@ -97,4 +97,4 @@ Column ${O+1}
97
97
  `,p.forEach((L,O)=>{const _=L.input.value.trim()||`Item ${O+1}`;P+=`[item title="${_}"]Content here.[/item]
98
98
  `}),P+="[/accordion]";else{const L=g.value;if(!L)return;const O=v.value,_=j.value;let G=`slug="${L}" display="accordion"`;O&&(G+=` title-field="${O}"`),_&&(G+=` body-field="${_}"`);const K=s.value.trim();K&&(G+=` limit="${K}"`),he.checked&&(G+=' multiple="true"'),P=`[collection ${G} /]`}ke(e,P),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onListGroup(e=>{const l=document.createElement("div");l.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const t="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",k="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 m(n,r){const v=document.createElement("div"),A=document.createElement("label");return A.style.cssText=t,A.textContent=n,v.appendChild(A),v.appendChild(r),v}function u(n){const r=document.createElement("select");return r.style.cssText=k,n.forEach(([v,A])=>{const q=document.createElement("option");q.value=v,q.textContent=A,r.appendChild(q)}),r}const w=u([["","Default"],["flush","Flush (no outer border)"],["numbered","Numbered"],["horizontal","Horizontal"]]);l.appendChild(m("Variant",w));const x=u([["","Default"],["sm","Small"],["lg","Large"]]);l.appendChild(m("Size",x));const h=u([["","Default"],["primary","Primary"],["secondary","Secondary"],["success","Success"],["danger","Danger"],["warning","Warning"],["info","Info"]]);l.appendChild(m("Item Colour",h));const c=document.createElement("label");c.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const p=document.createElement("input");p.type="checkbox",c.appendChild(p),c.appendChild(document.createTextNode("Actionable items (hover highlight)")),l.appendChild(c);const F=document.createElement("div");F.style.cssText=t+"margin-bottom:.35rem;",F.textContent="Items",l.appendChild(F);const N=document.createElement("div");N.style.cssText="display:flex;flex-direction:column;gap:.4rem;",l.appendChild(N);const b=[];function f(){b.forEach(n=>{n.removeBtn.disabled=b.length<=1,n.removeBtn.style.opacity=b.length<=1?"0.3":"1"})}function B(n){const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:center;";const v=document.createElement("input");v.type="text",v.placeholder="Item text",v.value=n||"",v.style.cssText=k+"flex:1;";const A=document.createElement("button");A.type="button",A.textContent="\u2715",A.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 q={row:r,input:v,removeBtn:A};b.push(q),r.appendChild(v),r.appendChild(A),N.appendChild(r),A.addEventListener("click",()=>{if(b.length<=1)return;const j=b.indexOf(q);b.splice(j,1),N.removeChild(r),f()}),f()}B("Item 1"),B("Item 2"),B("Item 3");const y=document.createElement("button");y.type="button",y.textContent="+ Add Item",y.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;",y.addEventListener("click",()=>{b.length>=20||(B(""),b[b.length-1].input.focus())}),l.appendChild(y);const i=document.createElement("button");i.type="button",i.className="btn btn-primary",i.textContent="Insert List Group",l.appendChild(i);const g=E.modal({title:"Insert List Group",size:"sm"});g.element.appendChild(l),g.open(),requestAnimationFrame(()=>b[0].input.focus()),i.addEventListener("click",()=>{g.close();let n="";w.value&&(n+=` variant="${w.value}"`),x.value&&(n+=` size="${x.value}"`),h.value&&(n+=` itemvariant="${h.value}"`),p.checked&&(n+=' action="true"');let r=`[listgroup${n}]
99
99
  `;b.forEach(v=>{const A=v.input.value.trim();A&&(r+=`[item]${A}[/item]
100
- `)}),r+="[/listgroup]",ke(e,r),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onHelp(()=>{Je()}),a.find(".editor-view-btn").on("click",function(){const e=$(this).data("mode");e&&(a.find(".editor-view-btn").removeClass("active"),$(this).addClass("active"),a.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${e}`),Ve("viewMode",e))}),a.find("#fullscreen-btn").on("click",function(){a.find(".editor-card").toggleClass("editor-fullscreen"),Ve("fullscreen",a.find(".editor-card").hasClass("editor-fullscreen"))}),Ae=!1,a.find("#quick-switch").prop("disabled",!1),Pe&&window.removeEventListener("beforeunload",Pe),Pe=e=>{Ae&&e.preventDefault()},window.addEventListener("beforeunload",Pe),Oe||(Oe=!0,R.use((e,l,t)=>{const k=window.location.hash.startsWith("#/pages/edit")||window.location.hash==="#/pages/new";if(!Ae||!k)return t();E.confirm("You have unsaved changes. Leave this page?").then(m=>{m&&(Ae=!1,t())})})),ce.on("input",()=>{ee||(Ae=!0,a.find("#quick-switch").prop("disabled",!0),De())});const Fe=a.find("#editor-meta-tabs").get(0);Fe&&(Fe.addEventListener("input",()=>{Ae=!0,a.find("#quick-switch").prop("disabled",!0)}),Fe.addEventListener("change",e=>{e.target.id!=="quick-switch"&&(Ae=!0,a.find("#quick-switch").prop("disabled",!0))})),De(),a.find("#save-btn").on("click",async()=>{const e=a.find("#page-url-path").val().trim();if(!e){E.toast("URL path is required.",{type:"warning"});return}const l=a.find("#field-dconfig").val().trim();let t=null;if(l)try{t=JSON.parse(l)}catch{E.toast("DConfig JSON is invalid. Please check the format before saving.",{type:"warning"});return}const k={title:a.find("#field-title").val().trim()||"Untitled",description:a.find("#field-description").val().trim(),layout:a.find("#field-layout").val(),status:a.find("#field-status").val(),sortOrder:parseInt(a.find("#field-sort-order").val(),10)||99,showInNav:a.find("#field-show-in-nav").is(":checked"),sidebar:a.find("#field-sidebar").is(":checked"),...a.find("#field-show-breadcrumbs").is(":checked")?{}:{breadcrumbs:!1},...a.find("#field-bundled").is(":checked")?{bundled:!0}:{},tags:Ce?Ce.getValue():[],category:a.find("#field-category").val().trim()||null,visibility:a.find("#field-visibility").val()||"public",seo:{title:a.find("#field-seo-title").val().trim(),description:a.find("#field-seo-desc").val().trim()},dconfig:t,...a.find("#field-theme").val()?{theme:a.find("#field-theme").val()}:{}};try{a.find("#save-btn").prop("disabled",!0).text("Saving\u2026");const m=ae.getUnfoldedContent();if(U){const u={frontmatter:k,body:m};e!==oe&&(u.newUrlPath=e),await Y.pages.update(oe,u),ne&&await Y.settings.saveCustomCss(a.find("#css-editor").val()),E.toast(ne?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Ae=!1,a.find("#quick-switch").prop("disabled",!1),e!==oe&&R.navigate(`/pages/edit${e}`)}else await Y.pages.create({urlPath:e,frontmatter:k,body:m}),ne&&await Y.settings.saveCustomCss(a.find("#css-editor").val()),E.toast(ne?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Ae=!1,R.navigate("/pages")}catch(m){E.toast(`Save failed: ${m.message||"Unknown error"}`,{type:"error"})}finally{a.find("#save-btn").prop("disabled",!1).text("Save")}}),a.find("#cancel-btn").on("click",()=>R.navigate("/pages")),Domma.icons.scan()}};
100
+ `)}),r+="[/listgroup]",ke(e,r),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),M.onCard(e=>{He.open(e,{onMediaBrowse:()=>Y.media.list().catch(()=>[])})}),M.onHelp(()=>{Qe()}),a.find(".editor-view-btn").on("click",function(){const e=$(this).data("mode");e&&(a.find(".editor-view-btn").removeClass("active"),$(this).addClass("active"),a.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${e}`),Ve("viewMode",e))}),a.find("#fullscreen-btn").on("click",function(){a.find(".editor-card").toggleClass("editor-fullscreen"),Ve("fullscreen",a.find(".editor-card").hasClass("editor-fullscreen"))}),Ae=!1,a.find("#quick-switch").prop("disabled",!1),Pe&&window.removeEventListener("beforeunload",Pe),Pe=e=>{Ae&&e.preventDefault()},window.addEventListener("beforeunload",Pe),Oe||(Oe=!0,R.use((e,l,t)=>{const k=window.location.hash.startsWith("#/pages/edit")||window.location.hash==="#/pages/new";if(!Ae||!k)return t();E.confirm("You have unsaved changes. Leave this page?").then(m=>{m&&(Ae=!1,t())})})),ce.on("input",()=>{ee||(Ae=!0,a.find("#quick-switch").prop("disabled",!0),De())});const Fe=a.find("#editor-meta-tabs").get(0);Fe&&(Fe.addEventListener("input",()=>{Ae=!0,a.find("#quick-switch").prop("disabled",!0)}),Fe.addEventListener("change",e=>{e.target.id!=="quick-switch"&&(Ae=!0,a.find("#quick-switch").prop("disabled",!0))})),De(),a.find("#save-btn").on("click",async()=>{const e=a.find("#page-url-path").val().trim();if(!e){E.toast("URL path is required.",{type:"warning"});return}const l=a.find("#field-dconfig").val().trim();let t=null;if(l)try{t=JSON.parse(l)}catch{E.toast("DConfig JSON is invalid. Please check the format before saving.",{type:"warning"});return}const k={title:a.find("#field-title").val().trim()||"Untitled",description:a.find("#field-description").val().trim(),layout:a.find("#field-layout").val(),status:a.find("#field-status").val(),sortOrder:parseInt(a.find("#field-sort-order").val(),10)||99,showInNav:a.find("#field-show-in-nav").is(":checked"),sidebar:a.find("#field-sidebar").is(":checked"),...a.find("#field-show-breadcrumbs").is(":checked")?{}:{breadcrumbs:!1},...a.find("#field-bundled").is(":checked")?{bundled:!0}:{},tags:Ce?Ce.getValue():[],category:a.find("#field-category").val().trim()||null,visibility:a.find("#field-visibility").val()||"public",seo:{title:a.find("#field-seo-title").val().trim(),description:a.find("#field-seo-desc").val().trim()},dconfig:t,...a.find("#field-theme").val()?{theme:a.find("#field-theme").val()}:{}};try{a.find("#save-btn").prop("disabled",!0).text("Saving\u2026");const m=ae.getUnfoldedContent();if(U){const u={frontmatter:k,body:m};e!==oe&&(u.newUrlPath=e),await Y.pages.update(oe,u),ne&&await Y.settings.saveCustomCss(a.find("#css-editor").val()),E.toast(ne?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Ae=!1,a.find("#quick-switch").prop("disabled",!1),e!==oe&&R.navigate(`/pages/edit${e}`)}else await Y.pages.create({urlPath:e,frontmatter:k,body:m}),ne&&await Y.settings.saveCustomCss(a.find("#css-editor").val()),E.toast(ne?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Ae=!1,R.navigate("/pages")}catch(m){E.toast(`Save failed: ${m.message||"Unknown error"}`,{type:"error"})}finally{a.find("#save-btn").prop("disabled",!1).text("Save")}}),a.find("#cancel-btn").on("click",()=>R.navigate("/pages")),Domma.icons.scan()}};
@@ -1,44 +1,38 @@
1
- import{api as c}from"../api.js";export const pluginsView={templateUrl:"/admin/js/templates/plugins.html",async onMount(d){const m=E.loader(d.get(0),{type:"dots"});let i=[];try{i=await c.plugins.list()}catch(e){E.toast(`Failed to load plugins: ${e.message}`,{type:"error"})}if(m.destroy(),!i.length){d.find("#plugins-empty").show();return}p(d,i),Domma.icons.scan()}};function p(d,m){const i=d.find("#plugins-grid").empty();m.forEach(e=>{const n=e.enabled?"badge-success":"badge-secondary",l=e.enabled?"Enabled":"Disabled",s=e.enabled?"Disable":"Enable",g=e.enabled?"btn-ghost":"btn-primary",u=e.bundled?'<span class="badge badge-outline" style="font-size:0.65rem;padding:1px 6px;color:var(--dm-info,#2563eb);border-color:var(--dm-info,#2563eb);" title="Included on fresh installs">Bundled</span>':"",r=e.author?`by ${a(e.author)}`:"",t=e.date?a(e.date):"",o=`
1
+ import{api as r}from"../api.js";export const pluginsView={templateUrl:"/admin/js/templates/plugins.html",async onMount(o){const m=E.loader(o.get(0),{type:"dots"});let i=[];try{i=await r.plugins.list()}catch(e){E.toast(`Failed to load plugins: ${e.message}`,{type:"error"})}if(m.destroy(),!i.length){o.find("#plugins-empty").show();return}g(o,i),Domma.icons.scan()}};function g(o,m){const i=o.find("#plugins-grid").empty();m.forEach(e=>{const n=e.enabled?"badge-success":"badge-secondary",l=e.enabled?"Enabled":"Disabled",s=e.enabled?"Disable":"Enable",v=e.enabled?"btn-ghost":"btn-primary",c=e.bundled?"var(--dm-info,#2563eb)":"var(--dm-secondary,#6b7280)",u=e.bundled?"Bundled \u2014 click to unbundle":"Not bundled \u2014 click to bundle",t=`<button class="badge badge-outline btn-bundle-plugin" data-name="${e.name}" data-bundled="${e.bundled?"1":"0"}" title="${u}" style="font-size:0.65rem;padding:1px 6px;cursor:pointer;background:none;border:1px solid;color:${c};border-color:${c};">${e.bundled?"Bundled":"Unbundled"}</button>`,d=e.author?`by ${a(e.author)}`:"",p=e.date?a(e.date):"",b=`
2
2
  <div class="card plugin-card" data-plugin="${e.name}">
3
3
  <div class="card-body">
4
4
  <div class="plugin-header">
5
5
  <div class="plugin-icon"><span data-icon="${e.icon||"package"}"></span></div>
6
6
  <div class="plugin-meta">
7
7
  <div class="plugin-name">${a(e.displayName)}</div>
8
- <div class="plugin-version">v${a(e.version)}${r?` &middot; ${r}`:""}</div>
8
+ <div class="plugin-version">v${a(e.version)}${d?` &middot; ${d}`:""}</div>
9
9
  </div>
10
10
  <div style="display:flex;gap:.35rem;align-items:center;">
11
- ${u}
11
+ ${t}
12
12
  <span class="badge ${n}">${l}</span>
13
13
  </div>
14
14
  </div>
15
15
  <p class="plugin-desc">${a(e.description)}</p>
16
- ${t?`<p class="plugin-date text-muted" style="font-size:.8rem;margin:0">Released ${t}</p>`:""}
16
+ ${p?`<p class="plugin-date text-muted" style="font-size:.8rem;margin:0">Released ${p}</p>`:""}
17
17
  </div>
18
18
  <div class="plugin-footer">
19
19
  <span class="text-muted" style="font-size:.8rem">Restart server after changes</span>
20
20
  <div class="plugin-footer-actions">
21
21
  ${e.settingsSchema?`<button class="btn btn-sm btn-ghost btn-plugin-settings" data-name="${e.name}">Settings</button>`:""}
22
- <button class="btn btn-sm btn-ghost btn-bundle-plugin"
23
- data-name="${e.name}"
24
- data-bundled="${e.bundled?"1":"0"}"
25
- title="${e.bundled?"Remove from fresh install bundle":"Include in fresh install bundle"}">
26
- ${e.bundled?"Unbundle":"Bundle"}
27
- </button>
28
- <button class="btn btn-sm ${g} btn-toggle-plugin"
22
+ <button class="btn btn-sm ${v} btn-toggle-plugin"
29
23
  data-name="${e.name}"
30
24
  data-enabled="${e.enabled?"1":"0"}">
31
25
  ${s}
32
26
  </button>
33
27
  </div>
34
28
  </div>
35
- </div>`;i.append(o)}),Domma.icons.scan(),Domma.effects.reveal(".plugin-card",{animation:"fade",stagger:60,duration:400}),Domma.effects.ripple(".btn-toggle-plugin"),i.on("click",".btn-plugin-settings",async function(){const e=$(this).data("name"),n=m.find(t=>t.name===e);if(!n?.settingsSchema)return;const s=`<form id="plugin-settings-form">${n.settingsSchema.map(t=>{const o=n.settings?.[t.key]??t.default??"";if(t.type==="select"){const v=t.options.map(b=>`<option value="${a(b.value)}"${String(o)===String(b.value)?" selected":""}>${a(b.label)}</option>`).join("");return`<div class="form-group">
29
+ </div>`;i.append(b)}),Domma.icons.scan(),Domma.effects.reveal(".plugin-card",{animation:"fade",stagger:60,duration:400}),Domma.effects.ripple(".btn-toggle-plugin"),i.on("click",".btn-plugin-settings",async function(){const e=$(this).data("name"),n=m.find(t=>t.name===e);if(!n?.settingsSchema)return;const s=`<form id="plugin-settings-form">${n.settingsSchema.map(t=>{const d=n.settings?.[t.key]??t.default??"";if(t.type==="select"){const p=t.options.map(b=>`<option value="${a(b.value)}"${String(d)===String(b.value)?" selected":""}>${a(b.label)}</option>`).join("");return`<div class="form-group">
36
30
  <label class="form-label">${a(t.label)}</label>
37
- <select class="form-control" name="${a(t.key)}">${v}</select>
31
+ <select class="form-control" name="${a(t.key)}">${p}</select>
38
32
  </div>`}return t.type==="number"?`<div class="form-group">
39
33
  <label class="form-label">${a(t.label)}</label>
40
- <input class="form-control" type="number" name="${a(t.key)}" value="${a(String(o))}"${t.min!=null?` min="${t.min}"`:""}${t.max!=null?` max="${t.max}"`:""}>
34
+ <input class="form-control" type="number" name="${a(t.key)}" value="${a(String(d))}"${t.min!=null?` min="${t.min}"`:""}${t.max!=null?` max="${t.max}"`:""}>
41
35
  </div>`:`<div class="form-group">
42
36
  <label class="form-label">${a(t.label)}</label>
43
- <input class="form-control" type="text" name="${a(t.key)}" value="${a(String(o))}">
44
- </div>`}).join("")}</form>`;if(!await E.confirm(s,{title:`${a(n.displayName)} Settings`,confirmText:"Save",cancelText:"Cancel",html:!0}))return;const u=document.getElementById("plugin-settings-form");if(!u)return;const r={};n.settingsSchema.forEach(t=>{const o=u.elements[t.key];o&&(r[t.key]=t.type==="number"?Number(o.value):o.value)});try{await c.plugins.update(e,{settings:r}),n.settings={...n.settings,...r},E.toast("Settings saved.",{type:"success"})}catch(t){E.toast(`Failed to save: ${t.message}`,{type:"error"})}}),i.on("click",".btn-bundle-plugin",async function(){const e=$(this),n=e.data("name"),l=e.data("bundled")!==1&&e.data("bundled")!=="1";e.prop("disabled",!0).text(l?"Bundling\u2026":"Unbundling\u2026");try{await c.plugins.update(n,{bundled:l}),E.toast(`Plugin ${l?"marked as bundled":"unbundled"}.`,{type:"success"});const s=await c.plugins.list();p(d,s)}catch(s){E.toast(`Failed: ${s.message}`,{type:"error"}),e.prop("disabled",!1)}}),i.on("click",".btn-toggle-plugin",async function(){const e=$(this),n=e.data("name"),l=e.data("enabled")!==1&&e.data("enabled")!=="1";e.prop("disabled",!0).text(l?"Enabling\u2026":"Disabling\u2026");try{await c.plugins.update(n,{enabled:l}),E.toast(`Plugin ${l?"enabled":"disabled"}. Restart the server to apply changes.`,{type:"success"});const s=await c.plugins.list();p(d,s)}catch(s){E.toast(`Failed: ${s.message}`,{type:"error"}),e.prop("disabled",!1)}})}function a(d){return String(d).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}
37
+ <input class="form-control" type="text" name="${a(t.key)}" value="${a(String(d))}">
38
+ </div>`}).join("")}</form>`;if(!await E.confirm(s,{title:`${a(n.displayName)} Settings`,confirmText:"Save",cancelText:"Cancel",html:!0}))return;const c=document.getElementById("plugin-settings-form");if(!c)return;const u={};n.settingsSchema.forEach(t=>{const d=c.elements[t.key];d&&(u[t.key]=t.type==="number"?Number(d.value):d.value)});try{await r.plugins.update(e,{settings:u}),n.settings={...n.settings,...u},E.toast("Settings saved.",{type:"success"})}catch(t){E.toast(`Failed to save: ${t.message}`,{type:"error"})}}),i.on("click",".btn-bundle-plugin",async function(){const e=$(this),n=e.data("name"),l=e.data("bundled")!==1&&e.data("bundled")!=="1";e.prop("disabled",!0).text(l?"Bundling\u2026":"Unbundling\u2026");try{await r.plugins.update(n,{bundled:l}),E.toast(`Plugin ${l?"marked as bundled":"unbundled"}.`,{type:"success"});const s=await r.plugins.list();g(o,s)}catch(s){E.toast(`Failed: ${s.message}`,{type:"error"}),e.prop("disabled",!1)}}),i.on("click",".btn-toggle-plugin",async function(){const e=$(this),n=e.data("name"),l=e.data("enabled")!==1&&e.data("enabled")!=="1";e.prop("disabled",!0).text(l?"Enabling\u2026":"Disabling\u2026");try{await r.plugins.update(n,{enabled:l}),E.toast(`Plugin ${l?"enabled":"disabled"}. Restart the server to apply changes.`,{type:"success"});const s=await r.plugins.list();g(o,s)}catch(s){E.toast(`Failed: ${s.message}`,{type:"error"}),e.prop("disabled",!1)}})}function a(o){return String(o).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}
@@ -1 +1 @@
1
- export const tutorialsView={templateUrl:"/admin/js/templates/tutorials.html",async onMount(t){Domma.icons.scan(),Domma.syntax.scan()}};
1
+ export const tutorialsView={templateUrl:"/admin/js/templates/tutorials.html",async onMount(t){E.tabs(t.find("#tutorials-tabs").get(0)),Domma.icons.scan(),Domma.syntax.scan()}};
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "theme-switcher": {
3
3
  "enabled": false,
4
- "settings": {}
4
+ "settings": {},
5
+ "bundled": true
5
6
  },
6
7
  "contacts": {
7
8
  "enabled": true,
@@ -12,19 +13,8 @@
12
13
  "settings": {}
13
14
  },
14
15
  "site-search": {
15
- "enabled": true,
16
- "settings": {
17
- "placeholder": "Search pages...",
18
- "keyboardShortcut": true,
19
- "maxResults": 10,
20
- "minQueryLength": 2,
21
- "debounceMs": 300,
22
- "displayMode": "floating",
23
- "position": "top-right",
24
- "offsetX": 16,
25
- "offsetY": 64,
26
- "iconOnly": true
27
- }
16
+ "enabled": false,
17
+ "settings": {}
28
18
  },
29
19
  "notes": {
30
20
  "enabled": true,
package/config/site.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "tagline": "A nice little bloggy type thingy.",
4
4
  "fontFamily": "Roboto",
5
5
  "fontSize": 16,
6
- "theme": "charcoal-dark",
6
+ "theme": "lemon-light",
7
7
  "autoTheme": {
8
8
  "enabled": false,
9
9
  "dayTheme": "charcoal-light",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.9.5",
3
+ "version": "0.9.10",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -44,7 +44,6 @@ export const notesView = {
44
44
  let activeCategory = '';
45
45
  let searchQuery = '';
46
46
  let editingNoteId = null;
47
- let notesTable = null;
48
47
 
49
48
  // ---- DOM refs ----
50
49
  const editorEl = $container.find('#note-editor').get(0);
@@ -79,14 +78,12 @@ export const notesView = {
79
78
  }
80
79
  }
81
80
 
82
- // ---- Render table (T.create on first call, setData on subsequent) ----
81
+ // ---- Render table ----
83
82
  function renderTable() {
84
- if (notesTable) {
85
- notesTable.setData(notes);
86
- return;
87
- }
83
+ const wrap = $container.find('#notes-table').get(0);
84
+ if (!wrap) return;
88
85
 
89
- notesTable = T.create('#notes-table', {
86
+ T.create(wrap, {
90
87
  data: notes,
91
88
  columns: [
92
89
  {
@@ -132,33 +129,35 @@ export const notesView = {
132
129
  title: 'Actions',
133
130
  sortable: false,
134
131
  render: (id) =>
135
- `<button class="btn btn-sm btn-outline note-edit-btn" data-id="${esc(id)}" style="margin-right:4px;">` +
136
- `<span data-icon="edit" data-icon-size="13"></span> Edit</button>` +
137
- `<button class="btn btn-sm btn-danger note-delete-btn" data-id="${esc(id)}">` +
138
- `<span data-icon="trash" data-icon-size="13"></span></button>`
132
+ `<div style="display:flex;gap:.4rem;">` +
133
+ `<button class="btn btn-sm btn-outline note-edit-btn" data-id="${esc(id)}">Edit</button>` +
134
+ `<button class="btn btn-sm btn-danger note-delete-btn" data-id="${esc(id)}">Delete</button>` +
135
+ `</div>`
139
136
  }
140
137
  ],
141
138
  emptyMessage: 'No notes yet. Click New Note to get started.'
142
139
  });
143
140
 
144
- // Event delegation on the table container
145
- const tableContainer = $container.find('#notes-table').get(0);
146
- tableContainer.addEventListener('click', (e) => {
147
- const editBtn = e.target.closest('.note-edit-btn');
148
- const deleteBtn = e.target.closest('.note-delete-btn');
149
- const catTag = e.target.closest('.notes-cat-tag');
150
-
151
- if (editBtn) {
152
- const note = notes.find((n) => n.id === editBtn.dataset.id);
141
+ wrap.querySelectorAll('.note-edit-btn').forEach((btn) => {
142
+ btn.addEventListener('click', () => {
143
+ const note = notes.find((n) => n.id === btn.dataset.id);
153
144
  if (note) openEditor(note);
154
- } else if (deleteBtn) {
155
- deleteNote(deleteBtn.dataset.id);
156
- } else if (catTag) {
157
- activeCategory = catTag.dataset.cat;
145
+ });
146
+ });
147
+
148
+ wrap.querySelectorAll('.note-delete-btn').forEach((btn) => {
149
+ btn.addEventListener('click', () => deleteNote(btn.dataset.id));
150
+ });
151
+
152
+ wrap.querySelectorAll('.notes-cat-tag').forEach((tag) => {
153
+ tag.addEventListener('click', () => {
154
+ activeCategory = tag.dataset.cat;
158
155
  renderCategoryFilter();
159
156
  loadNotes().then(renderTable);
160
- }
157
+ });
161
158
  });
159
+
160
+ Domma.icons.scan(wrap);
162
161
  }
163
162
 
164
163
  // ---- Render category filter bar (DOM methods — no innerHTML with user data) ----