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.
- package/admin/js/app.js +2 -2
- package/admin/js/lib/card-builder.js +7 -0
- package/admin/js/templates/api-reference.html +943 -1107
- package/admin/js/templates/documentation.html +828 -655
- package/admin/js/templates/tutorials.html +202 -177
- package/admin/js/views/api-reference.js +1 -1
- package/admin/js/views/documentation.js +1 -1
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/page-editor.js +4 -4
- package/admin/js/views/plugins.js +10 -16
- package/admin/js/views/tutorials.js +1 -1
- package/config/plugins.json +4 -14
- package/config/site.json +1 -1
- package/package.json +1 -1
- package/plugins/notes/admin/views/notes.js +24 -25
- package/plugins/todo/admin/views/todo.js +32 -33
- package/public/css/site.css +1 -1
- package/server/services/markdown.js +609 -79
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{api as Y}from"../api.js";import{attachEditorKeybindings as
|
|
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"],["","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
|
|
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,``),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,"&").replace(/</g,"<").replace(/>/g,">"));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,""");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,``),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,"&").replace(/</g,"<").replace(/>/g,">"));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,""");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(()=>{
|
|
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
|
|
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)}${
|
|
8
|
+
<div class="plugin-version">v${a(e.version)}${d?` · ${d}`:""}</div>
|
|
9
9
|
</div>
|
|
10
10
|
<div style="display:flex;gap:.35rem;align-items:center;">
|
|
11
|
-
${
|
|
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
|
-
${
|
|
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
|
|
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(
|
|
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)}">${
|
|
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(
|
|
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(
|
|
44
|
-
</div>`}).join("")}</form>`;if(!await E.confirm(s,{title:`${a(n.displayName)} Settings`,confirmText:"Save",cancelText:"Cancel",html:!0}))return;const
|
|
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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}
|
|
@@ -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()}};
|
package/config/plugins.json
CHANGED
|
@@ -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":
|
|
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
package/package.json
CHANGED
|
@@ -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
|
|
81
|
+
// ---- Render table ----
|
|
83
82
|
function renderTable() {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
83
|
+
const wrap = $container.find('#notes-table').get(0);
|
|
84
|
+
if (!wrap) return;
|
|
88
85
|
|
|
89
|
-
|
|
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
|
-
`<
|
|
136
|
-
`<
|
|
137
|
-
`<button class="btn btn-sm btn-danger note-delete-btn" data-id="${esc(id)}">` +
|
|
138
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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) ----
|