domma-cms 0.35.0 → 0.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{api as Y}from"../api.js";import{CardBuilder as Ke}from"../lib/card-builder.js";import{TimelineBuilder as Ze}from"../lib/timeline-builder.js";import{attachEditorKeybindings as Xe,createToolbar as et,insertAtCursor as ye}from"../lib/markdown-toolbar.js";import{EffectsBuilder as tt}from"../lib/effects-builder.js";import{populateThemeSelect as nt}from"../lib/themes.js";import{createFoldingManager as at}from"../lib/editor-folding.js";import{makeCheckbox as Oe,makeField as G,makeIconInput as He,makeLivePreview as Ue,makeSelect as Le,makeTextInput as re}from"../lib/shortcode-modal.js";import{openScribeComposer as ot}from"../lib/scribe-composer.js";import{openCrudTutorial as lt}from"../lib/crud-tutorial.js";function it(){const d=E.slideover({title:"Editor Reference",size:"md",position:"right"}),ce="background:var(--dm-surface-subtle,#1a1a2e);padding:.2rem .4rem;border-radius:3px;font-size:.85em;font-family:monospace;",de="margin:1rem 0 .5rem;font-size:1rem;";function U(h){const b=document.createElement("code");return b.style.cssText=ce,b.textContent=h,b}function X(h){const b=document.createElement("h3");return b.style.cssText=de,b.textContent=h,b}const $e=document.createElement("div");$e.style.cssText="padding:1rem;";const Ae=document.createElement("div");Ae.className="tabs";const Me=document.createElement("div");Me.className="tab-list",["Basics","Layout","Components","Data","Advanced"].forEach((h,b)=>{const i=document.createElement("button");i.className="tab-item"+(b===0?" active":""),i.textContent=h,Me.appendChild(i)});const _=document.createElement("div");_.className="tab-content";const Ie="display:flex;flex-direction:column;gap:1rem;",Be=document.createElement("div");Be.className="tab-panel active",Be.style.cssText=Ie;const ve=document.createElement("div");ve.className="tab-panel",ve.style.cssText=Ie;const se=document.createElement("div");se.className="tab-panel",se.style.cssText=Ie;const Ce=document.createElement("div");Ce.className="tab-panel",Ce.style.cssText=Ie;const we=document.createElement("div");we.className="tab-panel",we.style.cssText=Ie,_.appendChild(Be),_.appendChild(ve),_.appendChild(se),_.appendChild(Ce),_.appendChild(we),Ae.appendChild(Me),Ae.appendChild(_),$e.appendChild(Ae);const qe=document.createElement("div");qe.appendChild(X("Markdown Basics"));const ue=document.createElement("table");ue.style.cssText="width:100%;border-collapse:collapse;font-size:.9em;";const ee=document.createElement("thead"),oe=document.createElement("tr");["Syntax","Result"].forEach(h=>{const b=document.createElement("th");b.style.cssText="text-align:left;padding:.4rem .5rem;border-bottom:1px solid var(--dm-border,#333);",b.textContent=h,oe.appendChild(b)}),ee.appendChild(oe),ue.appendChild(ee);const be=document.createElement("tbody");[["**bold**","bold (rendered bold)"],["_italic_","italic (rendered italic)"],["## Heading","Heading (h2)"],["[text](url)","Link"],["![alt](url)","Image"],["- item","Bullet list"],["`code`","Inline code"],["---","Divider"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.35rem .5rem;vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.35rem .5rem;vertical-align:top;color:var(--dm-text-muted,#aaa);font-size:.85em;",s.textContent=b,i.appendChild(o),i.appendChild(s),be.appendChild(i)}),ue.appendChild(be),qe.appendChild(ue),Be.appendChild(qe);const ne=document.createElement("div");ne.appendChild(X("Grid & Columns"));function W(h){const b=document.createElement("p");return b.style.cssText="margin:.3rem 0 .6rem;font-size:.82em;color:var(--dm-text-muted,#aaa);",b.textContent=h,b}function A(h,b,i){const o=document.createElement("p");o.style.cssText="margin:.75rem 0 .25rem;font-size:.85em;font-weight:600;",o.textContent=h;const s=document.createElement("div");s.style.cssText="position:relative;";const j=document.createElement("pre");j.style.cssText=ce+"display:block;padding:.5rem 2rem .5rem .75rem;white-space:pre;overflow-x:auto;margin:0;",j.textContent=b;const Q=document.createElement("button");Q.type="button",Q.title="Copy code",Q.style.cssText="position:absolute;top:.3rem;right:.3rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.15rem;line-height:1;color:inherit;",Q.addEventListener("mouseenter",()=>{Q.style.opacity="1"}),Q.addEventListener("mouseleave",()=>{Q.style.opacity=".45"});const J=document.createElement("span");J.setAttribute("data-icon","copy"),Q.appendChild(J),Q.addEventListener("click",()=>{const P=document.createElement("textarea");P.value=b,P.style.cssText="position:fixed;opacity:0;",document.body.appendChild(P),P.select(),document.execCommand("copy"),P.remove(),E.toast("Copied!",{type:"success",duration:1200})}),s.appendChild(j),s.appendChild(Q);const K=document.createDocumentFragment();return K.appendChild(o),K.appendChild(s),i&&K.appendChild(W(i)),K}const ae=document.createElement("table");ae.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['cols="N"',"[grid] only","Number of columns (1\u201312)"],['gap="N"',"[grid], [row]","Gap between columns/rows (1\u20136)"],['span="N"',"[col] only","How many columns this cell spans"],['fullwidth="true"',"[grid] only","Break out of page container to span full viewport"],['class="x"',"all","Add extra CSS classes"]].forEach(([h,b,i])=>{const o=document.createElement("tr");[h,b,i].forEach((s,j)=>{const Q=document.createElement("td");Q.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",j===0?Q.appendChild(U(h)):(Q.style.color="var(--dm-text-muted,#aaa)",Q.textContent=s),o.appendChild(Q)}),ae.appendChild(o)}),ne.appendChild(ae),ne.appendChild(A("Equal columns",`[grid cols="3" gap="4"]
1
+ import{api as Y}from"../api.js";import{CardBuilder as Ke}from"../lib/card-builder.js";import{TimelineBuilder as Ze}from"../lib/timeline-builder.js";import{attachEditorKeybindings as Xe,createToolbar as et,insertAtCursor as ye}from"../lib/markdown-toolbar.js";import{EffectsBuilder as tt}from"../lib/effects-builder.js";import{attachContextMenu as nt}from"../lib/shortcode-context-menu.js";import{populateThemeSelect as at}from"../lib/themes.js";import{createFoldingManager as ot}from"../lib/editor-folding.js";import{makeCheckbox as Oe,makeField as G,makeIconInput as He,makeLivePreview as Ue,makeSelect as Le,makeTextInput as re}from"../lib/shortcode-modal.js";import{openScribeComposer as lt}from"../lib/scribe-composer.js";import{openCrudTutorial as it}from"../lib/crud-tutorial.js";function dt(){const d=E.slideover({title:"Editor Reference",size:"md",position:"right"}),ce="background:var(--dm-surface-subtle,#1a1a2e);padding:.2rem .4rem;border-radius:3px;font-size:.85em;font-family:monospace;",de="margin:1rem 0 .5rem;font-size:1rem;";function U(h){const b=document.createElement("code");return b.style.cssText=ce,b.textContent=h,b}function X(h){const b=document.createElement("h3");return b.style.cssText=de,b.textContent=h,b}const $e=document.createElement("div");$e.style.cssText="padding:1rem;";const Ae=document.createElement("div");Ae.className="tabs";const Me=document.createElement("div");Me.className="tab-list",["Basics","Layout","Components","Data","Advanced"].forEach((h,b)=>{const i=document.createElement("button");i.className="tab-item"+(b===0?" active":""),i.textContent=h,Me.appendChild(i)});const _=document.createElement("div");_.className="tab-content";const Ie="display:flex;flex-direction:column;gap:1rem;",Be=document.createElement("div");Be.className="tab-panel active",Be.style.cssText=Ie;const ve=document.createElement("div");ve.className="tab-panel",ve.style.cssText=Ie;const se=document.createElement("div");se.className="tab-panel",se.style.cssText=Ie;const Ce=document.createElement("div");Ce.className="tab-panel",Ce.style.cssText=Ie;const we=document.createElement("div");we.className="tab-panel",we.style.cssText=Ie,_.appendChild(Be),_.appendChild(ve),_.appendChild(se),_.appendChild(Ce),_.appendChild(we),Ae.appendChild(Me),Ae.appendChild(_),$e.appendChild(Ae);const qe=document.createElement("div");qe.appendChild(X("Markdown Basics"));const pe=document.createElement("table");pe.style.cssText="width:100%;border-collapse:collapse;font-size:.9em;";const ee=document.createElement("thead"),oe=document.createElement("tr");["Syntax","Result"].forEach(h=>{const b=document.createElement("th");b.style.cssText="text-align:left;padding:.4rem .5rem;border-bottom:1px solid var(--dm-border,#333);",b.textContent=h,oe.appendChild(b)}),ee.appendChild(oe),pe.appendChild(ee);const be=document.createElement("tbody");[["**bold**","bold (rendered bold)"],["_italic_","italic (rendered italic)"],["## Heading","Heading (h2)"],["[text](url)","Link"],["![alt](url)","Image"],["- item","Bullet list"],["`code`","Inline code"],["---","Divider"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.35rem .5rem;vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.35rem .5rem;vertical-align:top;color:var(--dm-text-muted,#aaa);font-size:.85em;",s.textContent=b,i.appendChild(o),i.appendChild(s),be.appendChild(i)}),pe.appendChild(be),qe.appendChild(pe),Be.appendChild(qe);const ne=document.createElement("div");ne.appendChild(X("Grid & Columns"));function W(h){const b=document.createElement("p");return b.style.cssText="margin:.3rem 0 .6rem;font-size:.82em;color:var(--dm-text-muted,#aaa);",b.textContent=h,b}function A(h,b,i){const o=document.createElement("p");o.style.cssText="margin:.75rem 0 .25rem;font-size:.85em;font-weight:600;",o.textContent=h;const s=document.createElement("div");s.style.cssText="position:relative;";const j=document.createElement("pre");j.style.cssText=ce+"display:block;padding:.5rem 2rem .5rem .75rem;white-space:pre;overflow-x:auto;margin:0;",j.textContent=b;const Q=document.createElement("button");Q.type="button",Q.title="Copy code",Q.style.cssText="position:absolute;top:.3rem;right:.3rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.15rem;line-height:1;color:inherit;",Q.addEventListener("mouseenter",()=>{Q.style.opacity="1"}),Q.addEventListener("mouseleave",()=>{Q.style.opacity=".45"});const J=document.createElement("span");J.setAttribute("data-icon","copy"),Q.appendChild(J),Q.addEventListener("click",()=>{const P=document.createElement("textarea");P.value=b,P.style.cssText="position:fixed;opacity:0;",document.body.appendChild(P),P.select(),document.execCommand("copy"),P.remove(),E.toast("Copied!",{type:"success",duration:1200})}),s.appendChild(j),s.appendChild(Q);const K=document.createDocumentFragment();return K.appendChild(o),K.appendChild(s),i&&K.appendChild(W(i)),K}const ae=document.createElement("table");ae.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['cols="N"',"[grid] only","Number of columns (1\u201312)"],['gap="N"',"[grid], [row]","Gap between columns/rows (1\u20136)"],['span="N"',"[col] only","How many columns this cell spans"],['fullwidth="true"',"[grid] only","Break out of page container to span full viewport"],['class="x"',"all","Add extra CSS classes"]].forEach(([h,b,i])=>{const o=document.createElement("tr");[h,b,i].forEach((s,j)=>{const Q=document.createElement("td");Q.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",j===0?Q.appendChild(U(h)):(Q.style.color="var(--dm-text-muted,#aaa)",Q.textContent=s),o.appendChild(Q)}),ae.appendChild(o)}),ne.appendChild(ae),ne.appendChild(A("Equal columns",`[grid cols="3" gap="4"]
2
2
  [col]One[/col]
3
3
  [col]Two[/col]
4
4
  [col]Three[/col]
@@ -22,21 +22,21 @@ import{api as Y}from"../api.js";import{CardBuilder as Ke}from"../lib/card-builde
22
22
  [col]
23
23
  [card title="Three"]Content[/card]
24
24
  [/col]
25
- [/grid]`,null)),ve.appendChild(ne);const pe=document.createElement("div");pe.appendChild(X("Cards")),pe.appendChild(A("Basic card",`[card title="Optional Title"]
25
+ [/grid]`,null)),ve.appendChild(ne);const me=document.createElement("div");me.appendChild(X("Cards")),me.appendChild(A("Basic card",`[card title="Optional Title"]
26
26
  Markdown **works** here.
27
- [/card]`,"Omit title for a card with no header.")),pe.appendChild(A("Icon \u2014 inline (default)",`[card title="Feature" icon="star"]
27
+ [/card]`,"Omit title for a card with no header.")),me.appendChild(A("Icon \u2014 inline (default)",`[card title="Feature" icon="star"]
28
28
  Icon sits left of the title in a flex row.
29
- [/card]`,"icon accepts any Domma icon name. Default layout when icon is set.")),pe.appendChild(A("Icon \u2014 stacked (centred)",`[card title="Feature" icon="star" icon-layout="stacked" hover]
29
+ [/card]`,"icon accepts any Domma icon name. Default layout when icon is set.")),me.appendChild(A("Icon \u2014 stacked (centred)",`[card title="Feature" icon="star" icon-layout="stacked" hover]
30
30
  Icon is centred above the title. Great for feature tiles.
31
- [/card]`,'icon-layout="stacked" centres the icon above the title. Combine with hover for a lift effect.')),pe.appendChild(A("Icon with subtitle",`[card title="Feature" subtitle="Tagline here" icon="star" icon-layout="stacked"]
31
+ [/card]`,'icon-layout="stacked" centres the icon above the title. Combine with hover for a lift effect.')),me.appendChild(A("Icon with subtitle",`[card title="Feature" subtitle="Tagline here" icon="star" icon-layout="stacked"]
32
32
  Body content.
33
- [/card]`,"subtitle adds a secondary line beneath the title in both layouts.")),pe.appendChild(A("Collapsible card",`[card title="Click to expand" collapsible="true"]
33
+ [/card]`,"subtitle adds a secondary line beneath the title in both layouts.")),me.appendChild(A("Collapsible card",`[card title="Click to expand" collapsible="true"]
34
34
  Hidden by default.
35
- [/card]`,null)),pe.appendChild(A("Full attribute reference",`[card title="Title" subtitle="Sub" icon="star" icon-layout="stacked"
35
+ [/card]`,null)),me.appendChild(A("Full attribute reference",`[card title="Title" subtitle="Sub" icon="star" icon-layout="stacked"
36
36
  variant="primary" hover footer="Footer text"
37
37
  collapsible="true" class="extra" id="my-card"]
38
38
  Body content.
39
- [/card]`,'All attributes are optional. variant accepts "primary". icon-layout accepts "inline" (default) or "stacked".')),pe.appendChild(A("Rich header / footer sub-tags",`[card]
39
+ [/card]`,'All attributes are optional. variant accepts "primary". icon-layout accepts "inline" (default) or "stacked".')),me.appendChild(A("Rich header / footer sub-tags",`[card]
40
40
  [header]
41
41
  ### Custom Title with **bold** and [a link](/about)
42
42
  [/header]
@@ -46,7 +46,7 @@ Body content here.
46
46
  [footer]
47
47
  [Read more](/about) | [icon name="arrow-right" /]
48
48
  [/footer]
49
- [/card]`,"Use [header] and [footer] sub-tags for Markdown-rendered header/footer regions. Sub-tags override the title/subtitle/icon and footer attributes when both are present.")),se.appendChild(pe);const ze=document.createElement("div");ze.appendChild(X("Badge")),ze.appendChild(W("Inline badge/label elements. Self-closing renders an empty coloured dot."));const De=document.createElement("table");De.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['variant="..."',"primary (default), secondary, success, danger, warning, info, light, dark"],["pill","Flag: rounded pill shape (.badge-pill)"],["outline","Flag: outlined style (.badge-outline)"],['size="small|large"',"Reduced or enlarged badge"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),De.appendChild(i)}),ze.appendChild(De),ze.appendChild(A("Basic badge",'[badge variant="success"]New[/badge]',null)),ze.appendChild(A("Pill outline badge",'[badge variant="danger" outline pill]Deprecated[/badge]',null)),se.appendChild(ze);const V=document.createElement("div");V.appendChild(X("Button")),V.appendChild(W("Renders a styled anchor as a Domma button. Use the Insert \u2192 Button toolbar item for a guided dialog."));const q=document.createElement("table");q.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['href="..."',"Link destination (required)"],['label="..."',"Button text (self-closing form)"],['variant="..."',"primary (default), secondary, success, danger, warning, info, outline, ghost, link, outline-*"],['size="sm|lg"',"Button size modifier"],['icon="..."',"Domma icon name before the label"],['icon-after="..."',"Domma icon name after the label"],['target="..."','Link target, e.g. "_blank"'],['class="..."',"Extra CSS classes"],['id="..."',"Element id"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),q.appendChild(i)}),V.appendChild(q),V.appendChild(A("Primary button",'[button href="/contact" variant="primary"]Get in touch[/button]',null)),V.appendChild(A("Self-closing with icon",'[button href="/download" variant="success" icon="download" size="sm" label="Download" /]',null)),V.appendChild(A("Opens in new tab",'[button href="https://example.com" variant="outline" target="_blank"]Visit site[/button]',null)),se.appendChild(V);const me=document.createElement("div");me.appendChild(X("Link (shortcode)")),me.appendChild(W("Renders a plain anchor with optional icon, target, and class. Use Insert \u2192 Link for a guided dialog. For simple inline links, standard Markdown [text](url) is fine."));const Ee=document.createElement("table");Ee.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['href="..."',"Link destination (required)"],['label="..."',"Link text (self-closing form)"],['target="..."','Link target, e.g. "_blank"'],['class="..."',"CSS classes on the <a>"],['icon="..."',"Domma icon name before the text"],['icon-after="..."',"Domma icon name after the text"],['id="..."',"Element id"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),Ee.appendChild(i)}),me.appendChild(Ee),me.appendChild(A("External link in new tab",'[link href="https://example.com" target="_blank" icon-after="external-link"]Visit site[/link]',null)),me.appendChild(A("Self-closing with icon",'[link href="/about" icon="arrow-right" label="About us" /]',null)),se.appendChild(me);const ke=document.createElement("div");ke.appendChild(X("Spacer")),ke.appendChild(W("Self-closing shortcode that inserts a fixed-height blank gap."));const he=document.createElement("table");he.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['size="N"',"Height in px (default: 8)"],['class="..."',"Extra CSS class on the spacer div"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),he.appendChild(i)}),ke.appendChild(he),ke.appendChild(A("32px gap",'[spacer size="32" /]',null)),ve.appendChild(ke);const Te=document.createElement("div");Te.appendChild(X("Icon")),Te.appendChild(W("Self-closing shortcode that renders any Domma icon inline."));const fe=document.createElement("table");fe.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['name="..."',"Domma icon name (required). Also accepted as src=."],['size="N"',"Width and height in px"],['color="..."',"CSS colour applied via style"],['class="..."',"Extra CSS classes"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),fe.appendChild(i)}),Te.appendChild(fe),Te.appendChild(A("Coloured icon",'[icon name="star" size="24" color="#f5a623" /]',null)),se.appendChild(Te);const Ne=document.createElement("div");Ne.appendChild(X("Center")),Ne.appendChild(W("Wraps content in a centred div. Works with any content including cards, grids, and text.")),Ne.appendChild(A("Example","[center]Centred content here[/center]",'Accepts an optional class="..." attribute for extra styling.')),ve.appendChild(Ne);const ge=document.createElement("div");ge.appendChild(X("Hero")),ge.appendChild(W("Full-width hero sections \u2014 no plugin required. Uses Domma's built-in Hero CSS component."));const ie=document.createElement("table");ie.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['title="..."',"Heading text"],['tagline="..."',"Subtitle text"],['size="sm|lg|full"',"Height variant (default: normal)"],['variant="dark|primary|gradient-blue|gradient-purple|gradient-sunset|gradient-ocean"',"Colour / gradient preset"],['image="url"',"Background image URL (adds cover mode)"],['overlay="light|dark|darker|gradient|gradient-reverse"',"Image overlay style"],['align="center|left"',"Content alignment (default: center)"],['fullwidth="true"',"Break out of the page container to span full viewport width"],['bg="..."',"Background colour CSS value"],["twinkle","Flag: adds particle overlay (requires Effects plugin)"],['twinkle-count="N"',"Number of particles"],['twinkle-colour="..."',"Particle colour CSS value"],["blobs","Flag: adds ambient blob background"],['blobs-type="..."',"Blob animation type (default: float-blobs)"],['class="..."',"Extra CSS classes"],['id="..."',"Element id"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),ie.appendChild(i)}),ge.appendChild(ie),ge.appendChild(A("Basic hero",'[hero title="Welcome" tagline="Build something great"][/hero]',null)),ge.appendChild(A("Gradient with body content",`[hero title="Get Started" tagline="Everything you need." size="lg" variant="gradient-blue" align="center"]
49
+ [/card]`,"Use [header] and [footer] sub-tags for Markdown-rendered header/footer regions. Sub-tags override the title/subtitle/icon and footer attributes when both are present.")),se.appendChild(me);const ze=document.createElement("div");ze.appendChild(X("Badge")),ze.appendChild(W("Inline badge/label elements. Self-closing renders an empty coloured dot."));const De=document.createElement("table");De.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['variant="..."',"primary (default), secondary, success, danger, warning, info, light, dark"],["pill","Flag: rounded pill shape (.badge-pill)"],["outline","Flag: outlined style (.badge-outline)"],['size="small|large"',"Reduced or enlarged badge"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),De.appendChild(i)}),ze.appendChild(De),ze.appendChild(A("Basic badge",'[badge variant="success"]New[/badge]',null)),ze.appendChild(A("Pill outline badge",'[badge variant="danger" outline pill]Deprecated[/badge]',null)),se.appendChild(ze);const V=document.createElement("div");V.appendChild(X("Button")),V.appendChild(W("Renders a styled anchor as a Domma button. Use the Insert \u2192 Button toolbar item for a guided dialog."));const q=document.createElement("table");q.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['href="..."',"Link destination (required)"],['label="..."',"Button text (self-closing form)"],['variant="..."',"primary (default), secondary, success, danger, warning, info, outline, ghost, link, outline-*"],['size="sm|lg"',"Button size modifier"],['icon="..."',"Domma icon name before the label"],['icon-after="..."',"Domma icon name after the label"],['target="..."','Link target, e.g. "_blank"'],['class="..."',"Extra CSS classes"],['id="..."',"Element id"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),q.appendChild(i)}),V.appendChild(q),V.appendChild(A("Primary button",'[button href="/contact" variant="primary"]Get in touch[/button]',null)),V.appendChild(A("Self-closing with icon",'[button href="/download" variant="success" icon="download" size="sm" label="Download" /]',null)),V.appendChild(A("Opens in new tab",'[button href="https://example.com" variant="outline" target="_blank"]Visit site[/button]',null)),se.appendChild(V);const ue=document.createElement("div");ue.appendChild(X("Link (shortcode)")),ue.appendChild(W("Renders a plain anchor with optional icon, target, and class. Use Insert \u2192 Link for a guided dialog. For simple inline links, standard Markdown [text](url) is fine."));const Ee=document.createElement("table");Ee.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['href="..."',"Link destination (required)"],['label="..."',"Link text (self-closing form)"],['target="..."','Link target, e.g. "_blank"'],['class="..."',"CSS classes on the <a>"],['icon="..."',"Domma icon name before the text"],['icon-after="..."',"Domma icon name after the text"],['id="..."',"Element id"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),Ee.appendChild(i)}),ue.appendChild(Ee),ue.appendChild(A("External link in new tab",'[link href="https://example.com" target="_blank" icon-after="external-link"]Visit site[/link]',null)),ue.appendChild(A("Self-closing with icon",'[link href="/about" icon="arrow-right" label="About us" /]',null)),se.appendChild(ue);const ke=document.createElement("div");ke.appendChild(X("Spacer")),ke.appendChild(W("Self-closing shortcode that inserts a fixed-height blank gap."));const he=document.createElement("table");he.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['size="N"',"Height in px (default: 8)"],['class="..."',"Extra CSS class on the spacer div"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),he.appendChild(i)}),ke.appendChild(he),ke.appendChild(A("32px gap",'[spacer size="32" /]',null)),ve.appendChild(ke);const Te=document.createElement("div");Te.appendChild(X("Icon")),Te.appendChild(W("Self-closing shortcode that renders any Domma icon inline."));const fe=document.createElement("table");fe.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['name="..."',"Domma icon name (required). Also accepted as src=."],['size="N"',"Width and height in px"],['color="..."',"CSS colour applied via style"],['class="..."',"Extra CSS classes"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),fe.appendChild(i)}),Te.appendChild(fe),Te.appendChild(A("Coloured icon",'[icon name="star" size="24" color="#f5a623" /]',null)),se.appendChild(Te);const Ne=document.createElement("div");Ne.appendChild(X("Center")),Ne.appendChild(W("Wraps content in a centred div. Works with any content including cards, grids, and text.")),Ne.appendChild(A("Example","[center]Centred content here[/center]",'Accepts an optional class="..." attribute for extra styling.')),ve.appendChild(Ne);const ge=document.createElement("div");ge.appendChild(X("Hero")),ge.appendChild(W("Full-width hero sections \u2014 no plugin required. Uses Domma's built-in Hero CSS component."));const ie=document.createElement("table");ie.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['title="..."',"Heading text"],['tagline="..."',"Subtitle text"],['size="sm|lg|full"',"Height variant (default: normal)"],['variant="dark|primary|gradient-blue|gradient-purple|gradient-sunset|gradient-ocean"',"Colour / gradient preset"],['image="url"',"Background image URL (adds cover mode)"],['overlay="light|dark|darker|gradient|gradient-reverse"',"Image overlay style"],['align="center|left"',"Content alignment (default: center)"],['fullwidth="true"',"Break out of the page container to span full viewport width"],['bg="..."',"Background colour CSS value"],["twinkle","Flag: adds particle overlay (requires Effects plugin)"],['twinkle-count="N"',"Number of particles"],['twinkle-colour="..."',"Particle colour CSS value"],["blobs","Flag: adds ambient blob background"],['blobs-type="..."',"Blob animation type (default: float-blobs)"],['class="..."',"Extra CSS classes"],['id="..."',"Element id"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),ie.appendChild(i)}),ge.appendChild(ie),ge.appendChild(A("Basic hero",'[hero title="Welcome" tagline="Build something great"][/hero]',null)),ge.appendChild(A("Gradient with body content",`[hero title="Get Started" tagline="Everything you need." size="lg" variant="gradient-blue" align="center"]
50
50
  Some introductory **Markdown** content here.
51
51
  [/hero]`,null)),ge.appendChild(A("Background image with overlay",'[hero title="Our Story" image="/media/hero.jpg" overlay="dark" size="full"][/hero]',"Combine image + overlay for text legibility over photos.")),ve.appendChild(ge);const le=document.createElement("div");le.appendChild(X("Interactive Components")),le.appendChild(W("Tabs, accordion, carousel, and countdown \u2014 no plugin required.")),le.appendChild(A("Tabs",`[tabs]
52
52
  [tab title="First"]Content **A**[/tab]
@@ -84,12 +84,12 @@ In active development.
84
84
  Markdown content here.
85
85
  [/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")),se.appendChild(r);const T=document.createElement("div");T.appendChild(X("DConfig \u2014 Declarative Behaviour")),T.appendChild(W("Define click handlers and class toggles without writing JavaScript. Use the DConfig section above or embed inline with [dconfig]...[/dconfig] in the content body. Inline shortcodes win on selector conflict.")),T.appendChild(A("Toggle a class on click",'{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }','Selector keys use standard CSS selectors. "target" is optional \u2014 defaults to the element itself.')),T.appendChild(A("Inline shortcode syntax",`[dconfig]
86
86
  { "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }
87
- [/dconfig]`,null)),we.appendChild(T);const B=document.createElement("div");B.appendChild(X("CSS Editor")),B.appendChild(W("The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page \u2014 one Save, one toast."));const z=document.createElement("table");z.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),z.appendChild(i)}),B.appendChild(z),we.appendChild(B);const w=document.createElement("div");w.appendChild(X("Colour Picker")),w.appendChild(W("Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss.")),we.appendChild(w);const L=document.createElement("div");L.appendChild(X("Keyboard Shortcuts"));const f=document.createElement("table");f.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["Ctrl + B","Bold selected text"],["Ctrl + I","Italic selected text"],["Ctrl + K","Insert link dialog"],["Tab","Indent 2 spaces at cursor"],["Shift + Tab","Dedent 2 spaces on current line"],["Ctrl + X","Cut current line (no selection) or cut selection"],["Ctrl + C","Copy current line (no selection) or copy selection"],["Ctrl + V","Paste from clipboard"],["Ctrl + Z","Undo"],["Ctrl + Y","Redo"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;white-space:nowrap;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),f.appendChild(i)}),L.appendChild(f),Be.appendChild(L);const N=document.createElement("div");N.appendChild(X("Tips"));const M=document.createElement("table");M.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['class="text-center"',"Centre text and inline elements on any shortcode"],['class="mx-auto"',"Centre a block element horizontally"],["[center]...[/center]","Shorthand wrapper for centred content"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),M.appendChild(i)}),N.appendChild(M),N.appendChild(W("Most shortcodes accept a class attribute for custom styling.")),Be.appendChild(N),d.setContent($e),d.open(),E.tabs(Ae),I.scan($e)}function dt(d,ce){const de=d.find("#history-tab").get(0),U=d.find("#version-list").get(0),X=d.find("#version-compare").get(0),$e=d.find("#version-compare-old").get(0),Ae=d.find("#version-compare-new").get(0),Me=d.find("#version-compare-label").get(0),_=d.find("#version-compare-back-btn").get(0),Ie=d.find("#version-restore-btn").get(0),Be=d.find("#history-save-named-btn").get(0),ve=d.find("#history-delete-selected-btn").get(0);let se=!1,Ce=null;function we(){U.style.display="",X.style.display="none",Ce=null}function qe(){U.style.display="none",X.style.display=""}async function ue(){U.textContent="";const ee=document.createElement("p");ee.style.color="var(--dm-text-muted)",ee.textContent="Loading\u2026",U.appendChild(ee);let oe;try{oe=(await Y.versions.list(ce)).versions||[]}catch(V){U.textContent="";const q=document.createElement("p");q.style.color="var(--dm-text-danger,#e55)",q.textContent="Failed to load versions: "+V.message,U.appendChild(q);return}if(U.textContent="",ve.style.display="none",!oe.length){const V=document.createElement("p");V.style.color="var(--dm-text-muted)",V.textContent="No versions saved yet. Versions are created automatically on each save.",U.appendChild(V);return}const be=document.createElement("table");be.style.cssText="width:100%;border-collapse:collapse;font-size:.875rem;";const ne=document.createElement("thead"),W=document.createElement("tr"),A=document.createElement("th");A.style.cssText="padding:.5rem .75rem;width:2rem;border-bottom:1px solid var(--dm-border);";const ae=document.createElement("input");ae.type="checkbox",ae.setAttribute("aria-label","Select all versions"),A.appendChild(ae),W.appendChild(A),["Date","Author","Type","Label","Actions"].forEach(V=>{const q=document.createElement("th");q.style.cssText="text-align:left;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border);font-size:.8rem;color:var(--dm-text-muted);",q.textContent=V,W.appendChild(q)}),ne.appendChild(W),be.appendChild(ne);const pe=[];function ze(){const V=pe.some(me=>me.checked),q=pe.length>0&&pe.every(me=>me.checked);ve.style.display=V?"":"none",ae.checked=q,ae.indeterminate=V&&!q}ae.addEventListener("change",()=>{pe.forEach(V=>{V.checked=ae.checked}),ze()});const De=document.createElement("tbody");oe.forEach(V=>{const q=document.createElement("tr");q.style.borderBottom="1px solid var(--dm-border)";const me=document.createElement("td");me.style.padding=".5rem .75rem";const Ee=document.createElement("input");Ee.type="checkbox",Ee.value=V.filename,Ee.addEventListener("change",ze),me.appendChild(Ee),pe.push(Ee);const ke=document.createElement("td");ke.style.padding=".5rem .75rem",ke.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm");const he=document.createElement("td");he.style.padding=".5rem .75rem",he.textContent=V.author||"\u2014";const Te=document.createElement("td");Te.style.padding=".5rem .75rem";const fe=document.createElement("span");fe.className="badge badge-"+(V.type==="manual"?"primary":"secondary"),fe.style.cssText="font-size:.75rem;padding:.2rem .5rem;border-radius:4px;",fe.textContent=V.type,Te.appendChild(fe);const Ne=document.createElement("td");Ne.style.cssText="padding:.5rem .75rem;color:var(--dm-text-muted);",Ne.textContent=V.label||"\u2014";const ge=document.createElement("td");ge.style.padding=".5rem .75rem";const ie=document.createElement("button");ie.className="btn btn-ghost btn-xs",ie.style.marginRight=".4rem",ie.title="Compare",ie.innerHTML='<span data-icon="columns"></span>',ie.addEventListener("click",async()=>{try{const xe=await Y.versions.get(ce,V.filename);$e.textContent=xe.content,Ae.textContent=d.find("#markdown-editor").get(0).value,Me.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm")+(V.label?` \u2014 ${V.label}`:""),Ce=V.filename,qe()}catch(xe){E.toast("Failed to load version: "+xe.message,{type:"error"})}});const le=document.createElement("button");le.className="btn btn-ghost btn-xs",le.style.color="var(--dm-text-danger,#e55)",le.title="Delete",le.innerHTML='<span data-icon="trash"></span>',le.addEventListener("click",async()=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await Y.versions.delete(ce,V.filename),E.toast("Version deleted.",{type:"success"}),await ue()}catch(xe){E.toast("Failed to delete: "+xe.message,{type:"error"})}}),ge.appendChild(ie),ge.appendChild(le),q.appendChild(me),q.appendChild(ke),q.appendChild(he),q.appendChild(Te),q.appendChild(Ne),q.appendChild(ge),De.appendChild(q)}),be.appendChild(De),U.appendChild(be),I.scan(U)}de.addEventListener("click",async()=>{se||(se=!0,await ue())}),_.addEventListener("click",()=>{we()}),Ie.addEventListener("click",async()=>{if(!(!Ce||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await Y.versions.restore(ce,Ce),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${ce}`),300)}catch(ee){E.toast("Restore failed: "+ee.message,{type:"error"})}}),ve.addEventListener("click",async()=>{const ee=[...U.querySelectorAll("tbody input[type=checkbox]:checked")].map(oe=>oe.value);if(!(!ee.length||!await E.confirm(`Delete ${ee.length} version${ee.length>1?"s":""}? This cannot be undone.`)))try{await Y.versions.bulkDelete(ce,ee),E.toast(`${ee.length} version${ee.length>1?"s":""} deleted.`,{type:"success"}),await ue()}catch(oe){E.toast("Delete failed: "+oe.message,{type:"error"})}}),Be.addEventListener("click",()=>{const ee=E.modal({title:"Save Named Version"}),oe=document.createElement("div");oe.style.padding="1rem";const be=document.createElement("label");be.className="form-label",be.textContent="Version Label";const ne=document.createElement("input");ne.type="text",ne.className="form-input",ne.placeholder="e.g. Initial design, Before restructure",ne.style.marginBottom=".75rem";const W=document.createElement("button");W.className="btn btn-primary",W.textContent="Save Version",W.addEventListener("click",async()=>{const A=ne.value.trim();try{await Y.versions.create(ce,A||null),E.toast("Named version saved.",{type:"success"}),ee.close(),se=!1,de.classList.contains("active")&&(se=!0,await ue())}catch(ae){E.toast("Failed to save version: "+ae.message,{type:"error"})}}),oe.appendChild(be),oe.appendChild(ne),oe.appendChild(W),ee.element.appendChild(oe),ee.open(),setTimeout(()=>ne.focus(),100)})}let Re=!1,Ge=null,je=!1;function st(d){return d.split(`
87
+ [/dconfig]`,null)),we.appendChild(T);const B=document.createElement("div");B.appendChild(X("CSS Editor")),B.appendChild(W("The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page \u2014 one Save, one toast."));const z=document.createElement("table");z.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),z.appendChild(i)}),B.appendChild(z),we.appendChild(B);const w=document.createElement("div");w.appendChild(X("Colour Picker")),w.appendChild(W("Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss.")),we.appendChild(w);const L=document.createElement("div");L.appendChild(X("Keyboard Shortcuts"));const f=document.createElement("table");f.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[["Ctrl + B","Bold selected text"],["Ctrl + I","Italic selected text"],["Ctrl + K","Insert link dialog"],["Tab","Indent 2 spaces at cursor"],["Shift + Tab","Dedent 2 spaces on current line"],["Ctrl + X","Cut current line (no selection) or cut selection"],["Ctrl + C","Copy current line (no selection) or copy selection"],["Ctrl + V","Paste from clipboard"],["Ctrl + Z","Undo"],["Ctrl + Y","Redo"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;white-space:nowrap;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),f.appendChild(i)}),L.appendChild(f),Be.appendChild(L);const N=document.createElement("div");N.appendChild(X("Tips"));const M=document.createElement("table");M.style.cssText="width:100%;border-collapse:collapse;font-size:.85em;margin-bottom:.5rem;",[['class="text-center"',"Centre text and inline elements on any shortcode"],['class="mx-auto"',"Centre a block element horizontally"],["[center]...[/center]","Shorthand wrapper for centred content"]].forEach(([h,b])=>{const i=document.createElement("tr"),o=document.createElement("td");o.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;",o.appendChild(U(h));const s=document.createElement("td");s.style.cssText="padding:.3rem .4rem;border-bottom:1px solid var(--dm-border,#333);vertical-align:top;color:var(--dm-text-muted,#aaa);",s.textContent=b,i.appendChild(o),i.appendChild(s),M.appendChild(i)}),N.appendChild(M),N.appendChild(W("Most shortcodes accept a class attribute for custom styling.")),Be.appendChild(N),d.setContent($e),d.open(),E.tabs(Ae),I.scan($e)}function st(d,ce){const de=d.find("#history-tab").get(0),U=d.find("#version-list").get(0),X=d.find("#version-compare").get(0),$e=d.find("#version-compare-old").get(0),Ae=d.find("#version-compare-new").get(0),Me=d.find("#version-compare-label").get(0),_=d.find("#version-compare-back-btn").get(0),Ie=d.find("#version-restore-btn").get(0),Be=d.find("#history-save-named-btn").get(0),ve=d.find("#history-delete-selected-btn").get(0);let se=!1,Ce=null;function we(){U.style.display="",X.style.display="none",Ce=null}function qe(){U.style.display="none",X.style.display=""}async function pe(){U.textContent="";const ee=document.createElement("p");ee.style.color="var(--dm-text-muted)",ee.textContent="Loading\u2026",U.appendChild(ee);let oe;try{oe=(await Y.versions.list(ce)).versions||[]}catch(V){U.textContent="";const q=document.createElement("p");q.style.color="var(--dm-text-danger,#e55)",q.textContent="Failed to load versions: "+V.message,U.appendChild(q);return}if(U.textContent="",ve.style.display="none",!oe.length){const V=document.createElement("p");V.style.color="var(--dm-text-muted)",V.textContent="No versions saved yet. Versions are created automatically on each save.",U.appendChild(V);return}const be=document.createElement("table");be.style.cssText="width:100%;border-collapse:collapse;font-size:.875rem;";const ne=document.createElement("thead"),W=document.createElement("tr"),A=document.createElement("th");A.style.cssText="padding:.5rem .75rem;width:2rem;border-bottom:1px solid var(--dm-border);";const ae=document.createElement("input");ae.type="checkbox",ae.setAttribute("aria-label","Select all versions"),A.appendChild(ae),W.appendChild(A),["Date","Author","Type","Label","Actions"].forEach(V=>{const q=document.createElement("th");q.style.cssText="text-align:left;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border);font-size:.8rem;color:var(--dm-text-muted);",q.textContent=V,W.appendChild(q)}),ne.appendChild(W),be.appendChild(ne);const me=[];function ze(){const V=me.some(ue=>ue.checked),q=me.length>0&&me.every(ue=>ue.checked);ve.style.display=V?"":"none",ae.checked=q,ae.indeterminate=V&&!q}ae.addEventListener("change",()=>{me.forEach(V=>{V.checked=ae.checked}),ze()});const De=document.createElement("tbody");oe.forEach(V=>{const q=document.createElement("tr");q.style.borderBottom="1px solid var(--dm-border)";const ue=document.createElement("td");ue.style.padding=".5rem .75rem";const Ee=document.createElement("input");Ee.type="checkbox",Ee.value=V.filename,Ee.addEventListener("change",ze),ue.appendChild(Ee),me.push(Ee);const ke=document.createElement("td");ke.style.padding=".5rem .75rem",ke.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm");const he=document.createElement("td");he.style.padding=".5rem .75rem",he.textContent=V.author||"\u2014";const Te=document.createElement("td");Te.style.padding=".5rem .75rem";const fe=document.createElement("span");fe.className="badge badge-"+(V.type==="manual"?"primary":"secondary"),fe.style.cssText="font-size:.75rem;padding:.2rem .5rem;border-radius:4px;",fe.textContent=V.type,Te.appendChild(fe);const Ne=document.createElement("td");Ne.style.cssText="padding:.5rem .75rem;color:var(--dm-text-muted);",Ne.textContent=V.label||"\u2014";const ge=document.createElement("td");ge.style.padding=".5rem .75rem";const ie=document.createElement("button");ie.className="btn btn-ghost btn-xs",ie.style.marginRight=".4rem",ie.title="Compare",ie.innerHTML='<span data-icon="columns"></span>',ie.addEventListener("click",async()=>{try{const xe=await Y.versions.get(ce,V.filename);$e.textContent=xe.content,Ae.textContent=d.find("#markdown-editor").get(0).value,Me.textContent=D(V.createdAt).format("D MMM YYYY, HH:mm")+(V.label?` \u2014 ${V.label}`:""),Ce=V.filename,qe()}catch(xe){E.toast("Failed to load version: "+xe.message,{type:"error"})}});const le=document.createElement("button");le.className="btn btn-ghost btn-xs",le.style.color="var(--dm-text-danger,#e55)",le.title="Delete",le.innerHTML='<span data-icon="trash"></span>',le.addEventListener("click",async()=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await Y.versions.delete(ce,V.filename),E.toast("Version deleted.",{type:"success"}),await pe()}catch(xe){E.toast("Failed to delete: "+xe.message,{type:"error"})}}),ge.appendChild(ie),ge.appendChild(le),q.appendChild(ue),q.appendChild(ke),q.appendChild(he),q.appendChild(Te),q.appendChild(Ne),q.appendChild(ge),De.appendChild(q)}),be.appendChild(De),U.appendChild(be),I.scan(U)}de.addEventListener("click",async()=>{se||(se=!0,await pe())}),_.addEventListener("click",()=>{we()}),Ie.addEventListener("click",async()=>{if(!(!Ce||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await Y.versions.restore(ce,Ce),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${ce}`),300)}catch(ee){E.toast("Restore failed: "+ee.message,{type:"error"})}}),ve.addEventListener("click",async()=>{const ee=[...U.querySelectorAll("tbody input[type=checkbox]:checked")].map(oe=>oe.value);if(!(!ee.length||!await E.confirm(`Delete ${ee.length} version${ee.length>1?"s":""}? This cannot be undone.`)))try{await Y.versions.bulkDelete(ce,ee),E.toast(`${ee.length} version${ee.length>1?"s":""} deleted.`,{type:"success"}),await pe()}catch(oe){E.toast("Delete failed: "+oe.message,{type:"error"})}}),Be.addEventListener("click",()=>{const ee=E.modal({title:"Save Named Version"}),oe=document.createElement("div");oe.style.padding="1rem";const be=document.createElement("label");be.className="form-label",be.textContent="Version Label";const ne=document.createElement("input");ne.type="text",ne.className="form-input",ne.placeholder="e.g. Initial design, Before restructure",ne.style.marginBottom=".75rem";const W=document.createElement("button");W.className="btn btn-primary",W.textContent="Save Version",W.addEventListener("click",async()=>{const A=ne.value.trim();try{await Y.versions.create(ce,A||null),E.toast("Named version saved.",{type:"success"}),ee.close(),se=!1,de.classList.contains("active")&&(se=!0,await pe())}catch(ae){E.toast("Failed to save version: "+ae.message,{type:"error"})}}),oe.appendChild(be),oe.appendChild(ne),oe.appendChild(W),ee.element.appendChild(oe),ee.open(),setTimeout(()=>ne.focus(),100)})}let Re=!1,Ge=null,je=!1;function rt(d){return d.split(`
88
88
  `).map(ce=>ce.trimEnd()).join(`
89
89
  `).replace(/\n{3,}/g,`
90
90
 
91
- `)}const Ye="editor_prefs";function Je(){return S.get(Ye)||{viewMode:"split",fullscreen:!1}}function Qe(d,ce){const de=Je();de[d]=ce,S.set(Ye,de)}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(d){const ce=window.location.hash.match(/#\/pages\/edit(\/.*)/),de=ce?ce[1]:null,U=!!de,X=E.loader(d.get(0),{type:"dots"}),$e=[Y.layouts.get().catch(()=>({})),Y.settings.get().catch(()=>({}))];U&&($e.push(Y.pages.get(de).catch(()=>null)),$e.push(Y.pages.list().catch(()=>[])));const[Ae,Me,_,Ie]=await Promise.all($e);X.destroy(),nt(d.find("#field-theme").get(0),{includeDefault:!0});const Be=Me?.layoutOptions?.spacerSize??40;if(U&&!_){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}d.find("#editor-title").text(U?`Edit Page \u2014 ${_.title||de}`:"New Page"),U&&d.find("#page-url-path").val(de),_&&(d.find("#field-title").val(_.title||""),d.find("#field-description").val(_.description||""),d.find("#field-status").val(_.status||"draft"),d.find("#field-sort-order").val(_.sortOrder??99),d.find("#field-show-in-nav").prop("checked",!!_.showInNav),d.find("#field-sidebar").prop("checked",!!_.sidebar),d.find("#field-show-breadcrumbs").prop("checked",_.breadcrumbs!==!1),d.find("#field-bundled").prop("checked",!!_.bundled),d.find("#field-category").val(_.category||""),d.find("#field-visibility").val(_.visibility||"public"),d.find("#field-theme").val(_.theme||""),d.find("#field-seo-title").val(_.seo?.title||""),d.find("#field-seo-desc").val(_.seo?.description||""),_.dconfig&&d.find("#field-dconfig").val(JSON.stringify(_.dconfig,null,2)));{const e=d.find("#field-project").get(0);if(e){const t=await Y.projects.list().catch(()=>[]);t.forEach(l=>{const n=document.createElement("option");n.value=l.slug,n.textContent=l.name||l.slug,e.appendChild(n)});let a="";if(_)if(_.project===null)a="";else if(typeof _.project=="string"&&_.project)a=_.project;else{const l=U?de:"";if(l){let n="",u=-1;for(const v of t)v.rootUrl&&(l===v.rootUrl||l.startsWith(v.rootUrl+"/"))&&v.rootUrl.length>u&&(n=v.slug,u=v.rootUrl.length);a=n}}e.value=a}}const ve=d.find("#quick-switch");U&&Array.isArray(Ie)&&Ie.length&&([...Ie].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath)).forEach(e=>{const t=document.createElement("option");t.value=e.urlPath,t.textContent=`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath===de&&(t.selected=!0),ve.get(0).appendChild(t)}),ve.css("display",""),ve.on("change",function(){const e=this.value;e&&R.navigate("/pages/edit"+e)}));const se=await Y.pages.tags().catch(()=>[]),Ce=d.find("#field-tags").get(0),we=Ce?E.pillbox(Ce,{data:se,value:_?.tags||[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026"}):null,qe=d.find("#field-layout").empty();if(Object.entries(Ae).forEach(([e,t])=>{const a=(_?.layout||"default")===e?"selected":"";qe.append(`<option value="${e}" ${a}>${t.label||e}</option>`)}),U){const e=d.find("#view-page-btn").get(0);e.href=de,e.style.display="";const t=d.find("#live-preview-tab").get(0);t.style.display="";const a=d.find("#history-tab").get(0);a.style.display=""}if(E.tabs(d.find("#editor-meta-tabs").get(0)),U){const e=d.find("#live-preview-tab").get(0),t=d.find("#live-preview-frame").get(0);let a=!1;e.addEventListener("click",function(){a||(t.src=de,a=!0)}),dt(d,de)}const ue=d.find("#markdown-editor"),ee=d.find("#markdown-preview");_&&ue.val(_.content||"");let oe=!1,be="";Y.settings.getCustomCss().then(({css:e})=>{if(be=e||"",!be)return;const t=document.createElement("style");t.id="preview-custom-css",t.textContent=be,ee.get(0).parentNode.insertBefore(t,ee.get(0))}).catch(()=>{});let ne=!1;const W=ue.get(0),A=document.createElement("div");A.className="editor-line-numbers editor-line-numbers--foldable",W.parentElement.insertBefore(A,W);const ae=at(W,A,{onFoldChange:()=>{}});ae.setGuard(e=>{ne=e});function pe(){const e=d.find("#css-editor").get(0);if(!e)return;const t=e.value.split(`
92
- `);for(;A.firstChild;)A.removeChild(A.firstChild);t.forEach((a,l)=>{const n=document.createElement("span");n.className="editor-line-number-row";const u=document.createElement("span");u.className="fold-toggle fold-toggle--empty";const v=document.createElement("span");v.className="editor-line-num",v.textContent=String(l+1),n.appendChild(u),n.appendChild(v),A.appendChild(n)}),A.scrollTop=e.scrollTop}{const e=d.find("#css-editor").get(0);e&&e.addEventListener("scroll",()=>{A.scrollTop=e.scrollTop})}const ze=()=>{ae.refresh(),A.scrollTop=W.scrollTop};W.addEventListener("input",ze),W.addEventListener("scroll",()=>{A.scrollTop=W.scrollTop});let De=null;const V=()=>{clearTimeout(De),De=setTimeout(async()=>{const e=ae.getUnfoldedContent();try{const{html:t}=await Y.pages.preview(e);ee.html(t,{safe:!1}),I.scan(ee.get(0)),ee.get(0).querySelectorAll(".tabs").forEach(a=>Domma.elements.tabs(a))}catch{window.marked&&ee.html(marked.parse(e))}},400)},q=et(ue,d.find("#editor-toolbar"),{spacerDefault:Be});let me=!1,Ee="split",ke=null;const he=document.createElement("button");he.className="editor-view-btn",he.type="button";const Te=document.createElement("span");Te.setAttribute("data-icon","css-code"),he.appendChild(Te);const fe=document.createElement("button");fe.className="editor-view-btn",fe.type="button";const Ne=document.createElement("span");Ne.setAttribute("data-icon","code"),fe.appendChild(Ne);let ge=!1;const ie=document.createElement("button");ie.className="editor-view-btn",ie.type="button",ie.textContent="\u25BC\u25BC",ie.style.cssText="font-size:9px;letter-spacing:-1px;";const le=d.find(".editor-toolbar-right").get(0);le.prepend(ie),le.prepend(fe),le.prepend(he),I.scan(he),I.scan(fe),E.tooltip(he,{content:"Edit Custom CSS",position:"top"}),E.tooltip(fe,{content:"Format Markdown",position:"top"}),E.tooltip(ie,{content:"Fold / unfold all shortcodes",position:"top"}),fe.addEventListener("click",()=>{const e=ue.get(0),t=e.selectionStart,a=st(ae.getUnfoldedContent());ae.unfoldAll(),ne=!0,e.value=a,ne=!1,e.selectionStart=e.selectionEnd=Math.min(t,a.length),e.dispatchEvent(new Event("input")),ae.refresh(),E.toast("Markdown formatted.",{type:"success"})}),ie.addEventListener("click",()=>{ge?(ae.unfoldAll(),ie.textContent="\u25BC\u25BC",ie.classList.remove("active")):(ae.foldAll(),ie.textContent="\u25B6\u25B6",ie.classList.add("active")),ge=!ge});const xe=document.createElement("span");xe.className="editor-toolbar-sep",le.insertBefore(xe,le.children[3]),he.addEventListener("click",()=>{me=!me;const e=d.find("#markdown-editor"),t=d.find("#css-editor"),a=d.find("#editor-body");if(me){const l=d.find(".editor-view-btn[data-mode].active").get(0);Ee=l?l.getAttribute("data-mode"):"split",d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find('.editor-view-btn[data-mode="split"]').addClass("active"),a.removeClass("editor-mode-write editor-mode-preview").addClass("editor-mode-split"),e.hide(),t.show(),oe||(t.val(be),oe=!0,Xe(t.get(0))),pe(),he.classList.add("active")}else d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Ee}"]`).addClass("active"),a.removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Ee}`),t.hide(),e.show(),ae.refresh(),he.classList.remove("active")});const Fe=Je();Fe.viewMode&&Fe.viewMode!=="split"&&(d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Fe.viewMode}"]`).addClass("active"),d.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Fe.viewMode}`)),Fe.fullscreen&&d.find(".editor-card").addClass("editor-fullscreen"),d.find("#css-editor").on("input",()=>{pe(),clearTimeout(ke),ke=setTimeout(()=>{let e=document.getElementById("preview-custom-css");e||(e=document.createElement("style"),e.id="preview-custom-css",ee.get(0).parentNode.insertBefore(e,ee.get(0))),e.textContent=d.find("#css-editor").val()},400)}),q.onLink(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(r=>({label:r.title||r.urlPath,value:r.urlPath})),a=document.createElement("div");a.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const l=document.createElement("label");l.className="form-label",l.textContent="URL";const n=document.createElement("input");n.type="text",n.className="form-input",n.placeholder="/about or https://example.com";const u=e.value.substring(e.selectionStart,e.selectionEnd);u&&u.startsWith("/")&&(n.value=u),a.appendChild(l),a.appendChild(n);const v=document.createElement("label");v.className="form-label",v.textContent="Link text";const g=document.createElement("input");g.type="text",g.className="form-input",g.placeholder="Display text",u&&!u.startsWith("/")&&(g.value=u),a.appendChild(v),a.appendChild(g);const k=document.createElement("label");k.className="form-label",k.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const c=document.createElement("input");c.type="checkbox",c.style.cssText="width:1rem;height:1rem;cursor:pointer;",k.appendChild(c),k.appendChild(document.createTextNode("Display as button")),a.appendChild(k);const C=document.createElement("label");C.className="form-label",C.textContent="Button colour",C.style.display="none";const y=document.createElement("select");y.className="form-select",y.style.display="none",[["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["outline-success","Outline Success"],["outline-danger","Outline Danger"],["ghost","Ghost"]].forEach(([r,x])=>{const T=document.createElement("option");T.value=r,T.textContent=x,y.appendChild(T)}),a.appendChild(C),a.appendChild(y),c.addEventListener("change",()=>{const r=c.checked;C.style.display=r?"":"none",y.style.display=r?"":"none"});const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Link",a.appendChild(m);const p=E.slideover({title:"Insert Link",size:"md",position:"right",content:a});p.open(),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:r=>{n.value=r.value,g.value||(g.value=r.label)}}),n.focus()}),m.addEventListener("click",()=>{const r=n.value.trim(),x=g.value.trim();if(!r)return;p.close();const T=c.checked?`[button href="${r}" variant="${y.value}"]${x||r}[/button]`:`[${x||r}](${r})`,B=e.selectionStart,z=e.selectionEnd;e.value=e.value.substring(0,B)+T+e.value.substring(z),e.selectionStart=e.selectionEnd=B+T.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onImage(async e=>{const t=(await Y.media.list().catch(()=>[])).filter(n=>/\.(png|jpe?g|gif|webp|svg)$/i.test(n.name)),a=document.createElement("div");if(a.className="media-picker-grid",t.length)t.forEach(n=>{const u=document.createElement("div");u.className="media-picker-item",u.dataset.url=n.url;const v=document.createElement("img");v.src=n.url,v.alt=n.name;const g=document.createElement("span");g.textContent=n.name,u.appendChild(v),u.appendChild(g),a.appendChild(u)});else{const n=document.createElement("p");n.className="text-muted p-3",n.textContent="No images uploaded yet.",a.appendChild(n)}const l=E.slideover({title:"Insert Image",size:"lg",position:"right",content:a});$(l.element).on("click",".media-picker-item",function(){const n=$(this).data("url"),u=$(this).find("span").text();ye(e,`![${u}](${n})`),l.close(),ue.get(0).dispatchEvent(new Event("input",{bubbles:!0}))}),l.open()}),q.onCollection(async e=>{const[t,a]=await Promise.all([Y.collections.list().catch(()=>[]),Y.blocks.list().catch(()=>[])]),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",u="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",v=document.createElement("div"),g=document.createElement("label");g.style.cssText=n,g.textContent="Collection";const k=document.createElement("select");if(k.style.cssText=u,t.length)t.forEach(H=>{const te=document.createElement("option");te.value=H.slug,te.textContent=H.title||H.slug,k.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No collections found",k.appendChild(H)}v.appendChild(g),v.appendChild(k),l.appendChild(v);const c=document.createElement("div"),C=document.createElement("label");C.style.cssText=n,C.textContent="Display";const y=document.createElement("select");y.style.cssText=u,["table","cards","list","block"].forEach(H=>{const te=document.createElement("option");te.value=H,te.textContent=H.charAt(0).toUpperCase()+H.slice(1),y.appendChild(te)}),c.appendChild(C),c.appendChild(y),l.appendChild(c);const m=document.createElement("div");m.style.display="none";const p=document.createElement("label");p.style.cssText=n,p.textContent="Columns (2\u20134)";const r=document.createElement("input");r.type="number",r.min="2",r.max="4",r.value="3",r.style.cssText=u,m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=document.createElement("div");x.style.display="none";const T=document.createElement("label");T.style.cssText=n,T.textContent="Block template";const B=document.createElement("select");if(B.style.cssText=u,a.length)a.forEach(H=>{const te=document.createElement("option");te.value=H.name??H,te.textContent=H.name??H,B.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No block templates found",B.appendChild(H)}x.appendChild(T),x.appendChild(B),l.appendChild(x);const z=document.createElement("div"),w=document.createElement("label");w.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const L=document.createElement("input");L.type="checkbox",L.checked=!0,w.appendChild(L),w.appendChild(document.createTextNode("Enable search")),z.appendChild(w),l.appendChild(z);const f=document.createElement("div"),N=document.createElement("label");N.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const M=document.createElement("input");M.type="checkbox",M.checked=!0,N.appendChild(M),N.appendChild(document.createTextNode("Sortable columns")),f.appendChild(N),l.appendChild(f);const h=document.createElement("div"),b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const i=document.createElement("input");i.type="checkbox",i.checked=!1,b.appendChild(i),b.appendChild(document.createTextNode("CSV export")),h.appendChild(b),l.appendChild(h);const o=document.createElement("div"),s=document.createElement("label");s.style.cssText=n,s.textContent="Rows per page";const j=document.createElement("input");j.type="number",j.min="5",j.max="100",j.value="25",j.style.cssText=u,o.appendChild(s),o.appendChild(j),l.appendChild(o);const Q=document.createElement("div"),J=document.createElement("label");J.style.cssText=n,J.textContent="Limit (optional)";const K=document.createElement("input");K.type="number",K.placeholder="All",K.style.cssText=u,Q.appendChild(J),Q.appendChild(K),l.appendChild(Q);const P=document.createElement("button");P.type="button",P.className="btn btn-primary",P.textContent="Insert",l.appendChild(P);const F=[z,f,h,o],O=()=>{const H=y.value,te=H==="table";F.forEach(Se=>{Se.style.display=te?"":"none"}),m.style.display=H==="cards"||H==="block"?"":"none",x.style.display=H==="block"?"":"none"};y.addEventListener("change",O),O();const Z=E.slideover({title:"Insert Collection",size:"md",position:"right",content:l});Z.open(),P.addEventListener("click",()=>{const H=k.value;if(!H)return;const te=y.value;let Se=`[collection slug="${H}" display="${te}"`;if(te==="cards"&&(Se+=` columns="${r.value}"`),te==="block"){const _e=B.value;_e&&(Se+=` block="${_e}"`);const Ve=r.value.trim();Ve&&(Se+=` cols="${Ve}"`)}te==="table"&&!L.checked&&(Se+=' search="false"'),te==="table"&&!M.checked&&(Se+=' sortable="false"'),te==="table"&&i.checked&&(Se+=' exportable="true"'),te==="table"&&j.value!=="25"&&(Se+=` page-size="${j.value}"`);const We=K.value.trim();We&&(Se+=` limit="${We}"`),Se+=" /]",Z.close(),ye(e,Se),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBlock(async e=>{let t=[];try{t=await Y.blocks.list()}catch{E.toast("Could not load blocks.",{type:"error"});return}if(!t.length){E.toast("No block templates found. Create one in Blocks first.",{type:"warning"});return}const a=document.createElement("div");a.style.cssText="display:flex;gap:1rem;min-height:320px;";const l=E.slideover({title:"Insert Block",size:"lg",position:"right",content:a}),n=document.createElement("div");n.style.cssText="flex:1;display:flex;flex-direction:column;gap:.75rem;";const u=document.createElement("label");u.className="form-label",u.textContent="Block Template";const v=document.createElement("select");v.className="form-select";const g=document.createElement("option");g.value="",g.textContent="\u2014 select a template \u2014",v.appendChild(g),t.forEach(B=>{const z=document.createElement("option");z.value=B.name,z.textContent=B.name,v.appendChild(z)}),n.appendChild(u),n.appendChild(v);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.5rem;overflow-y:auto;max-height:260px;",n.appendChild(k);const c=document.createElement("button");c.className="btn btn-primary",c.type="button",c.textContent="Insert",c.disabled=!0,n.appendChild(c);const C=document.createElement("div");C.style.cssText="flex:1;border:1px solid var(--dm-border-color);border-radius:var(--dm-radius);padding:.75rem;overflow:auto;background:var(--dm-surface-bg);";const y=document.createElement("p");y.className="text-muted",y.style.cssText="font-size:.8rem;margin:0;",y.textContent="Select a template to see a preview.",C.appendChild(y),a.appendChild(n),a.appendChild(C),l.open();let m=null,p=[];function r(B){return B.replace(/_/g," ").replace(/\b\w/g,z=>z.toUpperCase())}function x(){if(!m)return;const B={};p.forEach(({key:w,input:L})=>{B[w]=L.value});const z=m.replace(/\{\{([\w_]+)\}\}/g,(w,L)=>(B[L]??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"));C.innerHTML=DOMPurify.sanitize(z)}function T(B){k.textContent="",p=[];const z=new Set(["_id","_createdAt","_updatedAt"]),w=new Set;for(const[,L]of B.matchAll(/\{\{([\w_]+)\}\}/g))z.has(L)||w.add(L);if(!w.size){const L=document.createElement("p");L.className="text-muted",L.style.cssText="font-size:.8rem;margin:0;",L.textContent="No editable placeholders in this template.",k.appendChild(L);return}w.forEach(L=>{const f=document.createElement("div"),N=document.createElement("label");N.className="form-label",N.style.cssText="font-size:.8rem;margin-bottom:.2rem;display:block;",N.textContent=r(L);const M=document.createElement("input");M.type="text",M.className="form-input",M.placeholder=r(L),M.addEventListener("input",x),f.appendChild(N),f.appendChild(M),k.appendChild(f),p.push({key:L,input:M})})}v.addEventListener("change",async()=>{const B=v.value;if(!B){m=null,p=[],k.textContent="",C.textContent="",C.appendChild(y),c.disabled=!0;return}m=null,p=[],k.textContent="",c.disabled=!0;try{m=(await Y.blocks.get(B)).content||"",T(m),x(),c.disabled=!1}catch{E.toast("Could not load template.",{type:"error"})}}),c.addEventListener("click",()=>{if(!v.value)return;const B=L=>L.replace(/"/g,"&quot;");let z=`template="${B(v.value)}"`;p.forEach(({key:L,input:f})=>{f.value!==""&&(z+=` ${L}="${B(f.value)}"`)});const w=`[block ${z} /]`;ye(e,w),e.dispatchEvent(new Event("input",{bubbles:!0})),l.close(),e.focus()})}),q.onForm(async e=>{const t=await Y.forms.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="Form";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(C=>{const y=document.createElement("option");y.value=C.slug,y.textContent=C.title||C.slug,g.appendChild(y)});else{const C=document.createElement("option");C.value="",C.textContent="No forms found",g.appendChild(C)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("button");k.className="btn btn-primary btn-sm",k.style.cssText="align-self:flex-end;margin-top:.5rem;",k.textContent="Insert Form",a.appendChild(k);const c=E.slideover({title:"Insert Form",size:"md",position:"right",content:a});c.open(),k.addEventListener("click",()=>{const C=g.value;C&&(ye(e,`[form slug="${C}" /]`),c.close(),ue.get(0).dispatchEvent(new Event("input",{bubbles:!0})))})}),q.onView(async e=>{const t=await Y.views.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="View";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(p=>{const r=document.createElement("option");r.value=p.slug,r.textContent=p.title||p.slug,g.appendChild(r)});else{const p=document.createElement("option");p.value="",p.textContent="No Views configured yet \u2014 create one under Data \u2192 Views",g.appendChild(p)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("div"),c=document.createElement("label");c.style.cssText=l,c.textContent="Display";const C=document.createElement("select");C.style.cssText=n,["table","cards","list"].forEach(p=>{const r=document.createElement("option");r.value=p,r.textContent=p.charAt(0).toUpperCase()+p.slice(1),C.appendChild(r)}),k.appendChild(c),k.appendChild(C),a.appendChild(k);const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",a.appendChild(y);const m=E.slideover({title:"Insert View",size:"md",position:"right",content:a});m.open(),y.addEventListener("click",()=>{const p=g.value;if(!p)return;const r=`[view slug="${p}" display="${C.value}" /]`;m.close(),ye(e,r),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCta(async e=>{const t=await Y.actions.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l=Le(t.length?t.map(p=>[p.slug,p.title||p.slug]):[["","No Actions configured yet \u2014 create one under Data \u2192 Actions"]]);a.appendChild(G("Action",l));const n=re("Button label","Run");a.appendChild(G("Label",n)),l.addEventListener("change",()=>{const p=t.find(r=>r.slug===l.value);p?.trigger?.label&&(n.value=p.trigger.label)}),t.length&&t[0]?.trigger?.label&&(n.value=t[0].trigger.label);const u=re("Paste entry UUID\u2026","");a.appendChild(G("Entry ID",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["ghost","Ghost"],["danger","Danger"]]);a.appendChild(G("Style",v));const g=He("e.g. check, zap, send (optional)","");a.appendChild(G("Icon",g.el));const k=re("Confirmation message (optional)","");a.appendChild(G("Confirm prompt",k));const c=document.createElement("div");c.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const C=document.createElement("button");C.type="button",C.className="btn btn-ghost",C.textContent="Cancel";const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",c.appendChild(C),c.appendChild(y),a.appendChild(c);const m=E.slideover({title:"Insert CTA Button",size:"md",position:"right",content:a});m.open(),I.scan(a),C.addEventListener("click",()=>m.close()),y.addEventListener("click",()=>{const p=l.value;if(!p)return;const r=u.value.trim().replace(/"/g,""),x=(n.value.trim()||"Run").replace(/\[\/cta\]/gi,""),T=v.value,B=g.input.value.trim().replace(/"/g,""),z=k.value.trim().replace(/"/g,"");let w=`action="${p}" style="${T}"`;r&&(w+=` entry="${r}"`),B&&(w+=` icon="${B}"`),z&&(w+=` confirm="${z}"`),m.close(),ye(e,`[cta ${w}]${x}[/cta]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onButton(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(T=>({label:T.title||T.urlPath,value:T.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Button label",a&&!a.startsWith("/")?a:"");l.appendChild(G("Label",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["ghost","Ghost"],["link","Link"],["outline-success","Outline Success"],["outline-danger","Outline Danger"]]);l.appendChild(G("Variant",v));const g=Le([["","Default"],["sm","Small"],["lg","Large"]]);l.appendChild(G("Size",g));const k=He("e.g. arrow-right, star (optional)","");l.appendChild(G("Icon (before label)",k.el));const c=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (after label)",c.el));const C=Oe("Open in new tab");l.appendChild(C);const y=C.querySelector("input"),m=document.createElement("div");m.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const p=document.createElement("button");p.type="button",p.className="btn btn-ghost",p.textContent="Cancel";const r=document.createElement("button");r.type="button",r.className="btn btn-primary",r.textContent="Insert Button",m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=E.slideover({title:"Insert Button",size:"md",position:"right",content:l});x.open(),I.scan(l),p.addEventListener("click",()=>x.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:T=>{n.value=T.value,u.value||(u.value=T.label)}}),n.focus()}),r.addEventListener("click",()=>{const T=n.value.trim();if(!T)return;x.close();const B=u.value.trim()||T;let z=`href="${T}" variant="${v.value}"`;g.value&&(z+=` size="${g.value}"`);const w=k.input.value.trim().replace(/"/g,"");w&&(z+=` icon="${w}"`);const L=c.input.value.trim().replace(/"/g,"");L&&(z+=` icon-after="${L}"`),y.checked&&(z+=' target="_blank"'),ye(e,`[button ${z}]${B}[/button]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onLinkShortcode(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(x=>({label:x.title||x.urlPath,value:x.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Link text",a&&!a.startsWith("/")?a:"");l.appendChild(G("Link text",u));const v=re("e.g. text-primary, fw-bold (optional)","");l.appendChild(G("CSS class",v));const g=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (before text)",g.el));const k=He("e.g. external-link (optional)","");l.appendChild(G("Icon (after text)",k.el));const c=Oe("Open in new tab");l.appendChild(c);const C=c.querySelector("input"),y=document.createElement("div");y.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const m=document.createElement("button");m.type="button",m.className="btn btn-ghost",m.textContent="Cancel";const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.textContent="Insert Link",y.appendChild(m),y.appendChild(p),l.appendChild(y);const r=E.slideover({title:"Insert Link Shortcode",size:"md",position:"right",content:l});r.open(),I.scan(l),m.addEventListener("click",()=>r.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:x=>{n.value=x.value,u.value||(u.value=x.label)}}),n.focus()}),p.addEventListener("click",()=>{const x=n.value.trim();if(!x)return;r.close();const T=u.value.trim()||x;let B=`href="${x}"`;const z=v.value.trim().replace(/"/g,"");z&&(B+=` class="${z}"`);const w=g.input.value.trim().replace(/"/g,"");w&&(B+=` icon="${w}"`);const L=k.input.value.trim().replace(/"/g,"");L&&(B+=` icon-after="${L}"`),C.checked&&(B+=' target="_blank"'),ye(e,`[link ${B}]${T}[/link]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onTabs(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=Le([["","Default"],["pills","Pills"],["bordered","Bordered"]]);t.appendChild(G("Style",a));const l=Le([["","Left"],["center","Centre"],["right","Right"]]);t.appendChild(G("Alignment",l));const n=Le([["","None"],["fade","Fade"]]);t.appendChild(G("Animation",n));const u=Oe("Allow multiple panels open at once"),v=u.querySelector("input");t.appendChild(u);const g=document.createElement("div");g.style.cssText="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",g.textContent="Tabs",t.appendChild(g);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const c=[];function C(){c.forEach(z=>{z.removeBtn.disabled=c.length<=2,z.removeBtn.style.opacity=c.length<=2?"0.3":"1"})}function y(){const z=a.value,w=l.value,L=n.value,f=v.checked,N=[];z&&N.push(`style="${z}"`),w&&N.push(`align="${w}"`),L&&N.push(L),f&&N.push('multiple="true"');let h=`[tabs${N.length?" "+N.join(" "):""}]
91
+ `)}const Ye="editor_prefs";function Je(){return S.get(Ye)||{viewMode:"split",fullscreen:!1}}function Qe(d,ce){const de=Je();de[d]=ce,S.set(Ye,de)}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(d){const ce=window.location.hash.match(/#\/pages\/edit(\/.*)/),de=ce?ce[1]:null,U=!!de,X=E.loader(d.get(0),{type:"dots"}),$e=[Y.layouts.get().catch(()=>({})),Y.settings.get().catch(()=>({}))];U&&($e.push(Y.pages.get(de).catch(()=>null)),$e.push(Y.pages.list().catch(()=>[])));const[Ae,Me,_,Ie]=await Promise.all($e);X.destroy(),at(d.find("#field-theme").get(0),{includeDefault:!0});const Be=Me?.layoutOptions?.spacerSize??40;if(U&&!_){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}d.find("#editor-title").text(U?`Edit Page \u2014 ${_.title||de}`:"New Page"),U&&d.find("#page-url-path").val(de),_&&(d.find("#field-title").val(_.title||""),d.find("#field-description").val(_.description||""),d.find("#field-status").val(_.status||"draft"),d.find("#field-sort-order").val(_.sortOrder??99),d.find("#field-show-in-nav").prop("checked",!!_.showInNav),d.find("#field-sidebar").prop("checked",!!_.sidebar),d.find("#field-show-breadcrumbs").prop("checked",_.breadcrumbs!==!1),d.find("#field-bundled").prop("checked",!!_.bundled),d.find("#field-category").val(_.category||""),d.find("#field-visibility").val(_.visibility||"public"),d.find("#field-theme").val(_.theme||""),d.find("#field-seo-title").val(_.seo?.title||""),d.find("#field-seo-desc").val(_.seo?.description||""),_.dconfig&&d.find("#field-dconfig").val(JSON.stringify(_.dconfig,null,2)));{const e=d.find("#field-project").get(0);if(e){const t=await Y.projects.list().catch(()=>[]);t.forEach(l=>{const n=document.createElement("option");n.value=l.slug,n.textContent=l.name||l.slug,e.appendChild(n)});let a="";if(_)if(_.project===null)a="";else if(typeof _.project=="string"&&_.project)a=_.project;else{const l=U?de:"";if(l){let n="",u=-1;for(const v of t)v.rootUrl&&(l===v.rootUrl||l.startsWith(v.rootUrl+"/"))&&v.rootUrl.length>u&&(n=v.slug,u=v.rootUrl.length);a=n}}e.value=a}}const ve=d.find("#quick-switch");U&&Array.isArray(Ie)&&Ie.length&&([...Ie].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath)).forEach(e=>{const t=document.createElement("option");t.value=e.urlPath,t.textContent=`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath===de&&(t.selected=!0),ve.get(0).appendChild(t)}),ve.css("display",""),ve.on("change",function(){const e=this.value;e&&R.navigate("/pages/edit"+e)}));const se=await Y.pages.tags().catch(()=>[]),Ce=d.find("#field-tags").get(0),we=Ce?E.pillbox(Ce,{data:se,value:_?.tags||[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026"}):null,qe=d.find("#field-layout").empty();if(Object.entries(Ae).forEach(([e,t])=>{const a=(_?.layout||"default")===e?"selected":"";qe.append(`<option value="${e}" ${a}>${t.label||e}</option>`)}),U){const e=d.find("#view-page-btn").get(0);e.href=de,e.style.display="";const t=d.find("#live-preview-tab").get(0);t.style.display="";const a=d.find("#history-tab").get(0);a.style.display=""}if(E.tabs(d.find("#editor-meta-tabs").get(0)),U){const e=d.find("#live-preview-tab").get(0),t=d.find("#live-preview-frame").get(0);let a=!1;e.addEventListener("click",function(){a||(t.src=de,a=!0)}),st(d,de)}const pe=d.find("#markdown-editor"),ee=d.find("#markdown-preview");_&&pe.val(_.content||"");let oe=!1,be="";Y.settings.getCustomCss().then(({css:e})=>{if(be=e||"",!be)return;const t=document.createElement("style");t.id="preview-custom-css",t.textContent=be,ee.get(0).parentNode.insertBefore(t,ee.get(0))}).catch(()=>{});let ne=!1;const W=pe.get(0),A=document.createElement("div");A.className="editor-line-numbers editor-line-numbers--foldable",W.parentElement.insertBefore(A,W);const ae=ot(W,A,{onFoldChange:()=>{}});ae.setGuard(e=>{ne=e});function me(){const e=d.find("#css-editor").get(0);if(!e)return;const t=e.value.split(`
92
+ `);for(;A.firstChild;)A.removeChild(A.firstChild);t.forEach((a,l)=>{const n=document.createElement("span");n.className="editor-line-number-row";const u=document.createElement("span");u.className="fold-toggle fold-toggle--empty";const v=document.createElement("span");v.className="editor-line-num",v.textContent=String(l+1),n.appendChild(u),n.appendChild(v),A.appendChild(n)}),A.scrollTop=e.scrollTop}{const e=d.find("#css-editor").get(0);e&&e.addEventListener("scroll",()=>{A.scrollTop=e.scrollTop})}const ze=()=>{ae.refresh(),A.scrollTop=W.scrollTop};W.addEventListener("input",ze),W.addEventListener("scroll",()=>{A.scrollTop=W.scrollTop});let De=null;const V=()=>{clearTimeout(De),De=setTimeout(async()=>{const e=ae.getUnfoldedContent();try{const{html:t}=await Y.pages.preview(e);ee.html(t,{safe:!1}),I.scan(ee.get(0)),ee.get(0).querySelectorAll(".tabs").forEach(a=>Domma.elements.tabs(a))}catch{window.marked&&ee.html(marked.parse(e))}},400)},q=et(pe,d.find("#editor-toolbar"),{spacerDefault:Be});nt(pe.get(0));let ue=!1,Ee="split",ke=null;const he=document.createElement("button");he.className="editor-view-btn",he.type="button";const Te=document.createElement("span");Te.setAttribute("data-icon","css-code"),he.appendChild(Te);const fe=document.createElement("button");fe.className="editor-view-btn",fe.type="button";const Ne=document.createElement("span");Ne.setAttribute("data-icon","code"),fe.appendChild(Ne);let ge=!1;const ie=document.createElement("button");ie.className="editor-view-btn",ie.type="button",ie.textContent="\u25BC\u25BC",ie.style.cssText="font-size:9px;letter-spacing:-1px;";const le=d.find(".editor-toolbar-right").get(0);le.prepend(ie),le.prepend(fe),le.prepend(he),I.scan(he),I.scan(fe),E.tooltip(he,{content:"Edit Custom CSS",position:"top"}),E.tooltip(fe,{content:"Format Markdown",position:"top"}),E.tooltip(ie,{content:"Fold / unfold all shortcodes",position:"top"}),fe.addEventListener("click",()=>{const e=pe.get(0),t=e.selectionStart,a=rt(ae.getUnfoldedContent());ae.unfoldAll(),ne=!0,e.value=a,ne=!1,e.selectionStart=e.selectionEnd=Math.min(t,a.length),e.dispatchEvent(new Event("input")),ae.refresh(),E.toast("Markdown formatted.",{type:"success"})}),ie.addEventListener("click",()=>{ge?(ae.unfoldAll(),ie.textContent="\u25BC\u25BC",ie.classList.remove("active")):(ae.foldAll(),ie.textContent="\u25B6\u25B6",ie.classList.add("active")),ge=!ge});const xe=document.createElement("span");xe.className="editor-toolbar-sep",le.insertBefore(xe,le.children[3]),he.addEventListener("click",()=>{ue=!ue;const e=d.find("#markdown-editor"),t=d.find("#css-editor"),a=d.find("#editor-body");if(ue){const l=d.find(".editor-view-btn[data-mode].active").get(0);Ee=l?l.getAttribute("data-mode"):"split",d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find('.editor-view-btn[data-mode="split"]').addClass("active"),a.removeClass("editor-mode-write editor-mode-preview").addClass("editor-mode-split"),e.hide(),t.show(),oe||(t.val(be),oe=!0,Xe(t.get(0))),me(),he.classList.add("active")}else d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Ee}"]`).addClass("active"),a.removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Ee}`),t.hide(),e.show(),ae.refresh(),he.classList.remove("active")});const Fe=Je();Fe.viewMode&&Fe.viewMode!=="split"&&(d.find(".editor-view-btn[data-mode]").removeClass("active"),d.find(`.editor-view-btn[data-mode="${Fe.viewMode}"]`).addClass("active"),d.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${Fe.viewMode}`)),Fe.fullscreen&&d.find(".editor-card").addClass("editor-fullscreen"),d.find("#css-editor").on("input",()=>{me(),clearTimeout(ke),ke=setTimeout(()=>{let e=document.getElementById("preview-custom-css");e||(e=document.createElement("style"),e.id="preview-custom-css",ee.get(0).parentNode.insertBefore(e,ee.get(0))),e.textContent=d.find("#css-editor").val()},400)}),q.onLink(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(r=>({label:r.title||r.urlPath,value:r.urlPath})),a=document.createElement("div");a.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const l=document.createElement("label");l.className="form-label",l.textContent="URL";const n=document.createElement("input");n.type="text",n.className="form-input",n.placeholder="/about or https://example.com";const u=e.value.substring(e.selectionStart,e.selectionEnd);u&&u.startsWith("/")&&(n.value=u),a.appendChild(l),a.appendChild(n);const v=document.createElement("label");v.className="form-label",v.textContent="Link text";const g=document.createElement("input");g.type="text",g.className="form-input",g.placeholder="Display text",u&&!u.startsWith("/")&&(g.value=u),a.appendChild(v),a.appendChild(g);const k=document.createElement("label");k.className="form-label",k.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const c=document.createElement("input");c.type="checkbox",c.style.cssText="width:1rem;height:1rem;cursor:pointer;",k.appendChild(c),k.appendChild(document.createTextNode("Display as button")),a.appendChild(k);const C=document.createElement("label");C.className="form-label",C.textContent="Button colour",C.style.display="none";const y=document.createElement("select");y.className="form-select",y.style.display="none",[["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["outline-success","Outline Success"],["outline-danger","Outline Danger"],["ghost","Ghost"]].forEach(([r,x])=>{const T=document.createElement("option");T.value=r,T.textContent=x,y.appendChild(T)}),a.appendChild(C),a.appendChild(y),c.addEventListener("change",()=>{const r=c.checked;C.style.display=r?"":"none",y.style.display=r?"":"none"});const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Link",a.appendChild(m);const p=E.slideover({title:"Insert Link",size:"md",position:"right",content:a});p.open(),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:r=>{n.value=r.value,g.value||(g.value=r.label)}}),n.focus()}),m.addEventListener("click",()=>{const r=n.value.trim(),x=g.value.trim();if(!r)return;p.close();const T=c.checked?`[button href="${r}" variant="${y.value}"]${x||r}[/button]`:`[${x||r}](${r})`,B=e.selectionStart,z=e.selectionEnd;e.value=e.value.substring(0,B)+T+e.value.substring(z),e.selectionStart=e.selectionEnd=B+T.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onImage(async e=>{const t=(await Y.media.list().catch(()=>[])).filter(n=>/\.(png|jpe?g|gif|webp|svg)$/i.test(n.name)),a=document.createElement("div");if(a.className="media-picker-grid",t.length)t.forEach(n=>{const u=document.createElement("div");u.className="media-picker-item",u.dataset.url=n.url;const v=document.createElement("img");v.src=n.url,v.alt=n.name;const g=document.createElement("span");g.textContent=n.name,u.appendChild(v),u.appendChild(g),a.appendChild(u)});else{const n=document.createElement("p");n.className="text-muted p-3",n.textContent="No images uploaded yet.",a.appendChild(n)}const l=E.slideover({title:"Insert Image",size:"lg",position:"right",content:a});$(l.element).on("click",".media-picker-item",function(){const n=$(this).data("url"),u=$(this).find("span").text();ye(e,`![${u}](${n})`),l.close(),pe.get(0).dispatchEvent(new Event("input",{bubbles:!0}))}),l.open()}),q.onCollection(async e=>{const[t,a]=await Promise.all([Y.collections.list().catch(()=>[]),Y.blocks.list().catch(()=>[])]),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",u="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",v=document.createElement("div"),g=document.createElement("label");g.style.cssText=n,g.textContent="Collection";const k=document.createElement("select");if(k.style.cssText=u,t.length)t.forEach(H=>{const te=document.createElement("option");te.value=H.slug,te.textContent=H.title||H.slug,k.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No collections found",k.appendChild(H)}v.appendChild(g),v.appendChild(k),l.appendChild(v);const c=document.createElement("div"),C=document.createElement("label");C.style.cssText=n,C.textContent="Display";const y=document.createElement("select");y.style.cssText=u,["table","cards","list","block"].forEach(H=>{const te=document.createElement("option");te.value=H,te.textContent=H.charAt(0).toUpperCase()+H.slice(1),y.appendChild(te)}),c.appendChild(C),c.appendChild(y),l.appendChild(c);const m=document.createElement("div");m.style.display="none";const p=document.createElement("label");p.style.cssText=n,p.textContent="Columns (2\u20134)";const r=document.createElement("input");r.type="number",r.min="2",r.max="4",r.value="3",r.style.cssText=u,m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=document.createElement("div");x.style.display="none";const T=document.createElement("label");T.style.cssText=n,T.textContent="Block template";const B=document.createElement("select");if(B.style.cssText=u,a.length)a.forEach(H=>{const te=document.createElement("option");te.value=H.name??H,te.textContent=H.name??H,B.appendChild(te)});else{const H=document.createElement("option");H.value="",H.textContent="No block templates found",B.appendChild(H)}x.appendChild(T),x.appendChild(B),l.appendChild(x);const z=document.createElement("div"),w=document.createElement("label");w.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const L=document.createElement("input");L.type="checkbox",L.checked=!0,w.appendChild(L),w.appendChild(document.createTextNode("Enable search")),z.appendChild(w),l.appendChild(z);const f=document.createElement("div"),N=document.createElement("label");N.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const M=document.createElement("input");M.type="checkbox",M.checked=!0,N.appendChild(M),N.appendChild(document.createTextNode("Sortable columns")),f.appendChild(N),l.appendChild(f);const h=document.createElement("div"),b=document.createElement("label");b.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const i=document.createElement("input");i.type="checkbox",i.checked=!1,b.appendChild(i),b.appendChild(document.createTextNode("CSV export")),h.appendChild(b),l.appendChild(h);const o=document.createElement("div"),s=document.createElement("label");s.style.cssText=n,s.textContent="Rows per page";const j=document.createElement("input");j.type="number",j.min="5",j.max="100",j.value="25",j.style.cssText=u,o.appendChild(s),o.appendChild(j),l.appendChild(o);const Q=document.createElement("div"),J=document.createElement("label");J.style.cssText=n,J.textContent="Limit (optional)";const K=document.createElement("input");K.type="number",K.placeholder="All",K.style.cssText=u,Q.appendChild(J),Q.appendChild(K),l.appendChild(Q);const P=document.createElement("button");P.type="button",P.className="btn btn-primary",P.textContent="Insert",l.appendChild(P);const F=[z,f,h,o],O=()=>{const H=y.value,te=H==="table";F.forEach(Se=>{Se.style.display=te?"":"none"}),m.style.display=H==="cards"||H==="block"?"":"none",x.style.display=H==="block"?"":"none"};y.addEventListener("change",O),O();const Z=E.slideover({title:"Insert Collection",size:"md",position:"right",content:l});Z.open(),P.addEventListener("click",()=>{const H=k.value;if(!H)return;const te=y.value;let Se=`[collection slug="${H}" display="${te}"`;if(te==="cards"&&(Se+=` columns="${r.value}"`),te==="block"){const _e=B.value;_e&&(Se+=` block="${_e}"`);const Ve=r.value.trim();Ve&&(Se+=` cols="${Ve}"`)}te==="table"&&!L.checked&&(Se+=' search="false"'),te==="table"&&!M.checked&&(Se+=' sortable="false"'),te==="table"&&i.checked&&(Se+=' exportable="true"'),te==="table"&&j.value!=="25"&&(Se+=` page-size="${j.value}"`);const We=K.value.trim();We&&(Se+=` limit="${We}"`),Se+=" /]",Z.close(),ye(e,Se),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBlock(async e=>{let t=[];try{t=await Y.blocks.list()}catch{E.toast("Could not load blocks.",{type:"error"});return}if(!t.length){E.toast("No block templates found. Create one in Blocks first.",{type:"warning"});return}const a=document.createElement("div");a.style.cssText="display:flex;gap:1rem;min-height:320px;";const l=E.slideover({title:"Insert Block",size:"lg",position:"right",content:a}),n=document.createElement("div");n.style.cssText="flex:1;display:flex;flex-direction:column;gap:.75rem;";const u=document.createElement("label");u.className="form-label",u.textContent="Block Template";const v=document.createElement("select");v.className="form-select";const g=document.createElement("option");g.value="",g.textContent="\u2014 select a template \u2014",v.appendChild(g),t.forEach(B=>{const z=document.createElement("option");z.value=B.name,z.textContent=B.name,v.appendChild(z)}),n.appendChild(u),n.appendChild(v);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.5rem;overflow-y:auto;max-height:260px;",n.appendChild(k);const c=document.createElement("button");c.className="btn btn-primary",c.type="button",c.textContent="Insert",c.disabled=!0,n.appendChild(c);const C=document.createElement("div");C.style.cssText="flex:1;border:1px solid var(--dm-border-color);border-radius:var(--dm-radius);padding:.75rem;overflow:auto;background:var(--dm-surface-bg);";const y=document.createElement("p");y.className="text-muted",y.style.cssText="font-size:.8rem;margin:0;",y.textContent="Select a template to see a preview.",C.appendChild(y),a.appendChild(n),a.appendChild(C),l.open();let m=null,p=[];function r(B){return B.replace(/_/g," ").replace(/\b\w/g,z=>z.toUpperCase())}function x(){if(!m)return;const B={};p.forEach(({key:w,input:L})=>{B[w]=L.value});const z=m.replace(/\{\{([\w_]+)\}\}/g,(w,L)=>(B[L]??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"));C.innerHTML=DOMPurify.sanitize(z)}function T(B){k.textContent="",p=[];const z=new Set(["_id","_createdAt","_updatedAt"]),w=new Set;for(const[,L]of B.matchAll(/\{\{([\w_]+)\}\}/g))z.has(L)||w.add(L);if(!w.size){const L=document.createElement("p");L.className="text-muted",L.style.cssText="font-size:.8rem;margin:0;",L.textContent="No editable placeholders in this template.",k.appendChild(L);return}w.forEach(L=>{const f=document.createElement("div"),N=document.createElement("label");N.className="form-label",N.style.cssText="font-size:.8rem;margin-bottom:.2rem;display:block;",N.textContent=r(L);const M=document.createElement("input");M.type="text",M.className="form-input",M.placeholder=r(L),M.addEventListener("input",x),f.appendChild(N),f.appendChild(M),k.appendChild(f),p.push({key:L,input:M})})}v.addEventListener("change",async()=>{const B=v.value;if(!B){m=null,p=[],k.textContent="",C.textContent="",C.appendChild(y),c.disabled=!0;return}m=null,p=[],k.textContent="",c.disabled=!0;try{m=(await Y.blocks.get(B)).content||"",T(m),x(),c.disabled=!1}catch{E.toast("Could not load template.",{type:"error"})}}),c.addEventListener("click",()=>{if(!v.value)return;const B=L=>L.replace(/"/g,"&quot;");let z=`template="${B(v.value)}"`;p.forEach(({key:L,input:f})=>{f.value!==""&&(z+=` ${L}="${B(f.value)}"`)});const w=`[block ${z} /]`;ye(e,w),e.dispatchEvent(new Event("input",{bubbles:!0})),l.close(),e.focus()})}),q.onForm(async e=>{const t=await Y.forms.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="Form";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(C=>{const y=document.createElement("option");y.value=C.slug,y.textContent=C.title||C.slug,g.appendChild(y)});else{const C=document.createElement("option");C.value="",C.textContent="No forms found",g.appendChild(C)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("button");k.className="btn btn-primary btn-sm",k.style.cssText="align-self:flex-end;margin-top:.5rem;",k.textContent="Insert Form",a.appendChild(k);const c=E.slideover({title:"Insert Form",size:"md",position:"right",content:a});c.open(),k.addEventListener("click",()=>{const C=g.value;C&&(ye(e,`[form slug="${C}" /]`),c.close(),pe.get(0).dispatchEvent(new Event("input",{bubbles:!0})))})}),q.onView(async e=>{const t=await Y.views.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",n="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",u=document.createElement("div"),v=document.createElement("label");v.style.cssText=l,v.textContent="View";const g=document.createElement("select");if(g.style.cssText=n,t.length)t.forEach(p=>{const r=document.createElement("option");r.value=p.slug,r.textContent=p.title||p.slug,g.appendChild(r)});else{const p=document.createElement("option");p.value="",p.textContent="No Views configured yet \u2014 create one under Data \u2192 Views",g.appendChild(p)}u.appendChild(v),u.appendChild(g),a.appendChild(u);const k=document.createElement("div"),c=document.createElement("label");c.style.cssText=l,c.textContent="Display";const C=document.createElement("select");C.style.cssText=n,["table","cards","list"].forEach(p=>{const r=document.createElement("option");r.value=p,r.textContent=p.charAt(0).toUpperCase()+p.slice(1),C.appendChild(r)}),k.appendChild(c),k.appendChild(C),a.appendChild(k);const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",a.appendChild(y);const m=E.slideover({title:"Insert View",size:"md",position:"right",content:a});m.open(),y.addEventListener("click",()=>{const p=g.value;if(!p)return;const r=`[view slug="${p}" display="${C.value}" /]`;m.close(),ye(e,r),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCta(async e=>{const t=await Y.actions.list().catch(()=>[]),a=document.createElement("div");a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const l=Le(t.length?t.map(p=>[p.slug,p.title||p.slug]):[["","No Actions configured yet \u2014 create one under Data \u2192 Actions"]]);a.appendChild(G("Action",l));const n=re("Button label","Run");a.appendChild(G("Label",n)),l.addEventListener("change",()=>{const p=t.find(r=>r.slug===l.value);p?.trigger?.label&&(n.value=p.trigger.label)}),t.length&&t[0]?.trigger?.label&&(n.value=t[0].trigger.label);const u=re("Paste entry UUID\u2026","");a.appendChild(G("Entry ID",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["ghost","Ghost"],["danger","Danger"]]);a.appendChild(G("Style",v));const g=He("e.g. check, zap, send (optional)","");a.appendChild(G("Icon",g.el));const k=re("Confirmation message (optional)","");a.appendChild(G("Confirm prompt",k));const c=document.createElement("div");c.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const C=document.createElement("button");C.type="button",C.className="btn btn-ghost",C.textContent="Cancel";const y=document.createElement("button");y.type="button",y.className="btn btn-primary",y.textContent="Insert",c.appendChild(C),c.appendChild(y),a.appendChild(c);const m=E.slideover({title:"Insert CTA Button",size:"md",position:"right",content:a});m.open(),I.scan(a),C.addEventListener("click",()=>m.close()),y.addEventListener("click",()=>{const p=l.value;if(!p)return;const r=u.value.trim().replace(/"/g,""),x=(n.value.trim()||"Run").replace(/\[\/cta\]/gi,""),T=v.value,B=g.input.value.trim().replace(/"/g,""),z=k.value.trim().replace(/"/g,"");let w=`action="${p}" style="${T}"`;r&&(w+=` entry="${r}"`),B&&(w+=` icon="${B}"`),z&&(w+=` confirm="${z}"`),m.close(),ye(e,`[cta ${w}]${x}[/cta]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onButton(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(T=>({label:T.title||T.urlPath,value:T.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Button label",a&&!a.startsWith("/")?a:"");l.appendChild(G("Label",u));const v=Le([["primary","Primary"],["secondary","Secondary"],["success","Success (Green)"],["danger","Danger (Red)"],["warning","Warning (Orange)"],["info","Info (Blue)"],["outline","Outline"],["ghost","Ghost"],["link","Link"],["outline-success","Outline Success"],["outline-danger","Outline Danger"]]);l.appendChild(G("Variant",v));const g=Le([["","Default"],["sm","Small"],["lg","Large"]]);l.appendChild(G("Size",g));const k=He("e.g. arrow-right, star (optional)","");l.appendChild(G("Icon (before label)",k.el));const c=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (after label)",c.el));const C=Oe("Open in new tab");l.appendChild(C);const y=C.querySelector("input"),m=document.createElement("div");m.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const p=document.createElement("button");p.type="button",p.className="btn btn-ghost",p.textContent="Cancel";const r=document.createElement("button");r.type="button",r.className="btn btn-primary",r.textContent="Insert Button",m.appendChild(p),m.appendChild(r),l.appendChild(m);const x=E.slideover({title:"Insert Button",size:"md",position:"right",content:l});x.open(),I.scan(l),p.addEventListener("click",()=>x.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:T=>{n.value=T.value,u.value||(u.value=T.label)}}),n.focus()}),r.addEventListener("click",()=>{const T=n.value.trim();if(!T)return;x.close();const B=u.value.trim()||T;let z=`href="${T}" variant="${v.value}"`;g.value&&(z+=` size="${g.value}"`);const w=k.input.value.trim().replace(/"/g,"");w&&(z+=` icon="${w}"`);const L=c.input.value.trim().replace(/"/g,"");L&&(z+=` icon-after="${L}"`),y.checked&&(z+=' target="_blank"'),ye(e,`[button ${z}]${B}[/button]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onLinkShortcode(async e=>{const t=(await Y.pages.list().catch(()=>[])).map(x=>({label:x.title||x.urlPath,value:x.urlPath})),a=e.value.substring(e.selectionStart,e.selectionEnd),l=document.createElement("div");l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const n=re("/about or https://example.com",a.startsWith("/")?a:"");l.appendChild(G("URL",n));const u=re("Link text",a&&!a.startsWith("/")?a:"");l.appendChild(G("Link text",u));const v=re("e.g. text-primary, fw-bold (optional)","");l.appendChild(G("CSS class",v));const g=He("e.g. arrow-right (optional)","");l.appendChild(G("Icon (before text)",g.el));const k=He("e.g. external-link (optional)","");l.appendChild(G("Icon (after text)",k.el));const c=Oe("Open in new tab");l.appendChild(c);const C=c.querySelector("input"),y=document.createElement("div");y.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const m=document.createElement("button");m.type="button",m.className="btn btn-ghost",m.textContent="Cancel";const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.textContent="Insert Link",y.appendChild(m),y.appendChild(p),l.appendChild(y);const r=E.slideover({title:"Insert Link Shortcode",size:"md",position:"right",content:l});r.open(),I.scan(l),m.addEventListener("click",()=>r.close()),requestAnimationFrame(()=>{E.autocomplete(n,{data:t,minChars:1,onSelect:x=>{n.value=x.value,u.value||(u.value=x.label)}}),n.focus()}),p.addEventListener("click",()=>{const x=n.value.trim();if(!x)return;r.close();const T=u.value.trim()||x;let B=`href="${x}"`;const z=v.value.trim().replace(/"/g,"");z&&(B+=` class="${z}"`);const w=g.input.value.trim().replace(/"/g,"");w&&(B+=` icon="${w}"`);const L=k.input.value.trim().replace(/"/g,"");L&&(B+=` icon-after="${L}"`),C.checked&&(B+=' target="_blank"'),ye(e,`[link ${B}]${T}[/link]`),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onTabs(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=Le([["","Default"],["pills","Pills"],["bordered","Bordered"]]);t.appendChild(G("Style",a));const l=Le([["","Left"],["center","Centre"],["right","Right"]]);t.appendChild(G("Alignment",l));const n=Le([["","None"],["fade","Fade"]]);t.appendChild(G("Animation",n));const u=Oe("Allow multiple panels open at once"),v=u.querySelector("input");t.appendChild(u);const g=document.createElement("div");g.style.cssText="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",g.textContent="Tabs",t.appendChild(g);const k=document.createElement("div");k.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const c=[];function C(){c.forEach(z=>{z.removeBtn.disabled=c.length<=2,z.removeBtn.style.opacity=c.length<=2?"0.3":"1"})}function y(){const z=a.value,w=l.value,L=n.value,f=v.checked,N=[];z&&N.push(`style="${z}"`),w&&N.push(`align="${w}"`),L&&N.push(L),f&&N.push('multiple="true"');let h=`[tabs${N.length?" "+N.join(" "):""}]
93
93
  `;return c.forEach((b,i)=>{const o=b.titleInput.value.trim()||`Tab ${i+1}`,s=b.iconInput.value.trim(),j=s?` title="${o}" icon="${s}"`:` title="${o}"`;h+=`[tab${j}]Tab content here.[/tab]
94
94
  `}),h+="[/tabs]",h}function m(z=""){if(c.length>=10)return;const w=document.createElement("div");w.style.cssText="display:flex;gap:.4rem;align-items:center;";const L=re("Tab title",z);L.style.cssText+="flex:1;";const f=He("icon (optional)");f.el.style.flex=".6";const N=document.createElement("button");N.type="button",N.textContent="\xD7",N.style.cssText="padding:.3rem .5rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;flex-shrink:0;";const M={row:w,titleInput:L,iconInput:f.input,removeBtn:N};c.push(M),w.appendChild(L),w.appendChild(f.el),w.appendChild(N),k.appendChild(w),N.addEventListener("click",()=>{if(c.length<=2)return;const h=c.indexOf(M);c.splice(h,1),k.removeChild(w),C(),r(),x.update(y())}),[L,f.input].forEach(h=>h.addEventListener("input",()=>x.update(y()))),C()}m("Overview"),m("Details"),t.appendChild(k);const p=document.createElement("button");p.type="button",p.textContent="+ Add Tab",p.style.cssText="padding:.35rem .75rem;background:transparent;border:1px dashed var(--dm-border,#555);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;align-self:flex-start;",p.addEventListener("click",()=>{m(""),r(),c[c.length-1].titleInput.focus(),x.update(y())}),t.appendChild(p);function r(){p.disabled=c.length>=10}const x=Ue();x.update(y()),t.appendChild(G("Shortcode preview",x.el)),[a,l,n].forEach(z=>z.addEventListener("change",()=>x.update(y()))),v.addEventListener("change",()=>x.update(y()));const T=document.createElement("button");T.type="button",T.className="btn btn-primary",T.textContent="Insert Tabs",t.appendChild(T);const B=E.slideover({title:"Insert Tabs",size:"md",position:"right",content:t});B.open(),requestAnimationFrame(()=>c[0].titleInput.focus()),T.addEventListener("click",()=>{ye(e,y()),B.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCarousel(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=Le([["slide","Slide (default)"],["fade","Fade"],["crossfade","Crossfade"]]);t.appendChild(G("Animation",a));const l=re("e.g. 500","");t.appendChild(G("Animation duration (ms)",l));const n=Le([["","Default (ease)"],["linear","Linear"],["ease","Ease"],["ease-in","Ease in"],["ease-out","Ease out"],["ease-in-out","Ease in-out"]]);t.appendChild(G("Animation easing",n));const u=Oe("Autoplay"),v=u.querySelector("input");t.appendChild(u);const g=re("e.g. 5000","5000");t.appendChild(G("Autoplay interval (ms)",g));const k=Oe("Loop (wrap from last slide back to first)"),c=k.querySelector("input");c.checked=!0,t.appendChild(k);const C=document.createElement("div");C.style.cssText="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",C.textContent="Slides",t.appendChild(C);const y=document.createElement("div");y.style.cssText="display:flex;flex-direction:column;gap:.4rem;";const m=[];function p(){m.forEach(f=>{f.removeBtn.disabled=m.length<=1,f.removeBtn.style.opacity=m.length<=1?"0.3":"1"})}function r(){const f=a.value,N=l.value.trim(),M=n.value,h=v.checked,b=g.value.trim(),i=c.checked,o=[];h&&o.push('autoplay="true"'),h&&b&&b!=="5000"&&o.push(`interval="${b}"`),i||o.push('loop="false"'),f&&f!=="slide"&&o.push(`animation="${f}"`),N&&o.push(`animation-duration="${N}"`),M&&o.push(`animation-easing="${M}"`);let j=`[carousel${o.length?" "+o.join(" "):""}]
95
95
  `;return m.forEach((Q,J)=>{const K=Q.titleInput.value.trim(),P=Q.imageInput.value.trim(),F=[];K&&F.push(`title="${K}"`),P&&F.push(`image="${P}"`);const O=F.length?" "+F.join(" "):"";j+=`[slide${O}]Slide ${J+1} content.[/slide]
@@ -97,7 +97,7 @@ Markdown content here.
97
97
  Content here.
98
98
  [/hero]`}const B=Ue();B.update(T()),t.appendChild(G("Shortcode preview",B.el));function z(){const f=Object.keys(g).find(N=>g[N].checked)||"none";c.style.display=f==="colour"?"":"none",m.style.display=f==="image"?"flex":"none",B.update(T())}Object.values(g).forEach(f=>f.addEventListener("change",z)),[a,l,k,C,p].forEach(f=>f.addEventListener("input",()=>B.update(T()))),[n,u,y].forEach(f=>f.addEventListener("change",()=>B.update(T()))),x.addEventListener("change",()=>B.update(T()));const w=document.createElement("button");w.type="button",w.className="btn btn-primary",w.textContent="Insert Hero",t.appendChild(w);const L=E.slideover({title:"Insert Hero",size:"md",position:"right",content:t});L.open(),requestAnimationFrame(()=>a.focus()),w.addEventListener("click",()=>{ye(e,T()),L.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onBanner(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a=[{value:"info",label:"Info",color:"#3b82f6"},{value:"success",label:"Success",color:"#22c55e"},{value:"warning",label:"Warning",color:"#f59e0b"},{value:"danger",label:"Danger",color:"#ef4444"},{value:"neutral",label:"Neutral",color:"#888"}];let l="info";const n=document.createElement("div");n.style.cssText="display:flex;gap:.35rem;flex-wrap:wrap;";const u={};a.forEach(r=>{const x=document.createElement("button");x.type="button",x.style.cssText="display:flex;align-items:center;gap:.3rem;padding:.3rem .6rem;border:1px solid var(--dm-border,#333);border-radius:4px;background:transparent;color:var(--dm-text,#eee);cursor:pointer;font-size:.85em;";const T=document.createElement("span");T.style.cssText=`display:inline-block;width:.55rem;height:.55rem;border-radius:50%;background:${r.color};flex-shrink:0;`,x.appendChild(T),x.appendChild(document.createTextNode(r.label)),u[r.value]=x,n.appendChild(x),x.addEventListener("click",()=>{l=r.value,Object.entries(u).forEach(([B,z])=>{z.style.borderColor=B===l?r.color:"var(--dm-border,#333)",z.style.background=B===l?`${r.color}22`:"transparent"}),y.update(C())})}),u.info.style.borderColor="#3b82f6",u.info.style.background="#3b82f622",t.appendChild(G("Type",n));const v=re("Title (optional)");t.appendChild(G("Title",v));const g=He("Icon name (optional)");t.appendChild(G("Icon",g.el));const k=Oe("Dismissible"),c=k.querySelector("input");t.appendChild(k);function C(){const r=[];l!=="info"&&r.push(`type="${l}"`);const x=v.value.trim();x&&r.push(`title="${x}"`);const T=g.input.value.trim();return T&&r.push(`icon="${T}"`),c.checked&&r.push("dismissible"),`[banner${r.length?" "+r.join(" "):""}]
99
99
  Banner content here.
100
- [/banner]`}const y=Ue();y.update(C()),t.appendChild(G("Shortcode preview",y.el)),[v,g.input].forEach(r=>r.addEventListener("input",()=>y.update(C()))),c.addEventListener("change",()=>y.update(C()));const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Banner",t.appendChild(m);const p=E.slideover({title:"Insert Banner",size:"md",position:"right",content:t});p.open(),requestAnimationFrame(()=>v.focus()),m.addEventListener("click",()=>{ye(e,C()),p.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onScribe(e=>ot(e)),q.onGrid(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",l="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;";function n(J,K){const P=document.createElement("div"),F=document.createElement("label");return F.style.cssText=a,F.textContent=J,P.appendChild(F),P.appendChild(K),P}function u(J){const K=document.createElement("select");return K.style.cssText=l,J.forEach(([P,F])=>{const O=document.createElement("option");O.value=P,O.textContent=F,K.appendChild(O)}),K}let v="grid";const g=document.createElement("div");g.style.cssText="display:flex;gap:.5rem;";const k=document.createElement("button");k.type="button",k.className="btn btn-sm btn-primary",k.textContent="Grid";const c=document.createElement("button");c.type="button",c.className="btn btn-sm btn-ghost",c.textContent="Row",g.appendChild(k),g.appendChild(c),t.appendChild(g);const C=document.createElement("input");C.type="number",C.min="1",C.max="12",C.value="2",C.style.cssText=l,t.appendChild(n("Columns",C));const y=u([["0","0"],["1","1"],["2","2"],["3","3"],["4","4 (default)"],["6","6"],["8","8"],["10","10"],["12","12"],["16","16"]]);y.value="4",t.appendChild(n("Gap",y));const m=document.createElement("div");m.style.cssText="display:flex;flex-direction:column;gap:.5rem;";const p=document.createElement("label");p.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const r=document.createElement("input");r.type="checkbox",p.appendChild(r),p.appendChild(document.createTextNode("Full width (breakout)")),m.appendChild(p);const x=document.createElement("div");x.style.cssText=a+"margin-top:.25rem;",x.textContent="Column Spans",m.appendChild(x);const T=document.createElement("div");T.style.cssText="display:flex;flex-direction:column;gap:.3rem;",m.appendChild(T),t.appendChild(m);const B=[];function z(){const J=Math.min(Math.max(parseInt(C.value)||2,1),12),K=B.map(P=>P.value);T.textContent="",B.length=0;for(let P=0;P<J;P++){const F=document.createElement("div");F.style.cssText="display:flex;align-items:center;gap:.5rem;";const O=document.createElement("span");O.style.cssText="font-size:.85em;color:var(--dm-text-muted,#aaa);white-space:nowrap;min-width:3em;",O.textContent=`Col ${P+1}`;const Z=document.createElement("input");Z.type="number",Z.min="1",Z.max="12",Z.placeholder="auto",Z.value=K[P]||"",Z.style.cssText=l+"width:5em;flex:none;",F.appendChild(O),F.appendChild(Z),T.appendChild(F),B.push(Z)}}C.addEventListener("input",z),z();const w=document.createElement("div");w.style.cssText="display:none;flex-direction:column;gap:.5rem;";const L=document.createElement("label");L.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const f=document.createElement("input");f.type="checkbox",L.appendChild(f),L.appendChild(document.createTextNode("Enable staggered reveal")),w.appendChild(L);const N=document.createElement("div");N.style.cssText="display:none;flex-direction:column;gap:.5rem;padding-left:.5rem;border-left:2px solid var(--dm-border,#333);";const M=u([["slide-up","Slide Up"],["slide-down","Slide Down"],["slide-left","Slide Left"],["slide-right","Slide Right"],["fade","Fade"],["zoom","Zoom"],["flip","Flip"]]);N.appendChild(n("Animation",M));const h=u([["stagger","Stagger"],["sequence","Sequence"]]);N.appendChild(n("Mode",h));const b=document.createElement("input");b.type="number",b.value="400",b.style.cssText=l,N.appendChild(n("Duration (ms)",b));const i=document.createElement("input");i.type="number",i.value="60",i.style.cssText=l,N.appendChild(n("Stagger (ms)",i));const o=document.createElement("input");o.type="number",o.value="0",o.style.cssText=l,N.appendChild(n("Delay (ms)",o));const s=u([["ltr","Left to Right"],["rtl","Right to Left"]]);N.appendChild(n("Direction",s)),w.appendChild(N),t.appendChild(w),f.addEventListener("change",()=>{N.style.display=f.checked?"flex":"none"});const j=document.createElement("button");j.type="button",j.className="btn btn-primary",j.textContent="Insert Grid",t.appendChild(j),k.addEventListener("click",()=>{v="grid",k.className="btn btn-sm btn-primary",c.className="btn btn-sm btn-ghost",m.style.display="flex",w.style.display="none",j.textContent="Insert Grid"}),c.addEventListener("click",()=>{v="row",c.className="btn btn-sm btn-primary",k.className="btn btn-sm btn-ghost",w.style.display="flex",m.style.display="none",j.textContent="Insert Row"});const Q=E.slideover({title:"Insert Grid / Row",size:"md",position:"right",content:t});Q.open(),requestAnimationFrame(()=>C.focus()),j.addEventListener("click",()=>{Q.close();const J=Math.min(Math.max(parseInt(C.value)||2,1),12),K=y.value;let P;if(v==="grid"){let F=`cols="${J}"`;K!=="4"&&(F+=` gap="${K}"`),r.checked&&(F+=' fullwidth="true"'),P=`[grid ${F}]
100
+ [/banner]`}const y=Ue();y.update(C()),t.appendChild(G("Shortcode preview",y.el)),[v,g.input].forEach(r=>r.addEventListener("input",()=>y.update(C()))),c.addEventListener("change",()=>y.update(C()));const m=document.createElement("button");m.type="button",m.className="btn btn-primary",m.textContent="Insert Banner",t.appendChild(m);const p=E.slideover({title:"Insert Banner",size:"md",position:"right",content:t});p.open(),requestAnimationFrame(()=>v.focus()),m.addEventListener("click",()=>{ye(e,C()),p.close(),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onScribe(e=>lt(e)),q.onGrid(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",l="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;";function n(J,K){const P=document.createElement("div"),F=document.createElement("label");return F.style.cssText=a,F.textContent=J,P.appendChild(F),P.appendChild(K),P}function u(J){const K=document.createElement("select");return K.style.cssText=l,J.forEach(([P,F])=>{const O=document.createElement("option");O.value=P,O.textContent=F,K.appendChild(O)}),K}let v="grid";const g=document.createElement("div");g.style.cssText="display:flex;gap:.5rem;";const k=document.createElement("button");k.type="button",k.className="btn btn-sm btn-primary",k.textContent="Grid";const c=document.createElement("button");c.type="button",c.className="btn btn-sm btn-ghost",c.textContent="Row",g.appendChild(k),g.appendChild(c),t.appendChild(g);const C=document.createElement("input");C.type="number",C.min="1",C.max="12",C.value="2",C.style.cssText=l,t.appendChild(n("Columns",C));const y=u([["0","0"],["1","1"],["2","2"],["3","3"],["4","4 (default)"],["6","6"],["8","8"],["10","10"],["12","12"],["16","16"]]);y.value="4",t.appendChild(n("Gap",y));const m=document.createElement("div");m.style.cssText="display:flex;flex-direction:column;gap:.5rem;";const p=document.createElement("label");p.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const r=document.createElement("input");r.type="checkbox",p.appendChild(r),p.appendChild(document.createTextNode("Full width (breakout)")),m.appendChild(p);const x=document.createElement("div");x.style.cssText=a+"margin-top:.25rem;",x.textContent="Column Spans",m.appendChild(x);const T=document.createElement("div");T.style.cssText="display:flex;flex-direction:column;gap:.3rem;",m.appendChild(T),t.appendChild(m);const B=[];function z(){const J=Math.min(Math.max(parseInt(C.value)||2,1),12),K=B.map(P=>P.value);T.textContent="",B.length=0;for(let P=0;P<J;P++){const F=document.createElement("div");F.style.cssText="display:flex;align-items:center;gap:.5rem;";const O=document.createElement("span");O.style.cssText="font-size:.85em;color:var(--dm-text-muted,#aaa);white-space:nowrap;min-width:3em;",O.textContent=`Col ${P+1}`;const Z=document.createElement("input");Z.type="number",Z.min="1",Z.max="12",Z.placeholder="auto",Z.value=K[P]||"",Z.style.cssText=l+"width:5em;flex:none;",F.appendChild(O),F.appendChild(Z),T.appendChild(F),B.push(Z)}}C.addEventListener("input",z),z();const w=document.createElement("div");w.style.cssText="display:none;flex-direction:column;gap:.5rem;";const L=document.createElement("label");L.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const f=document.createElement("input");f.type="checkbox",L.appendChild(f),L.appendChild(document.createTextNode("Enable staggered reveal")),w.appendChild(L);const N=document.createElement("div");N.style.cssText="display:none;flex-direction:column;gap:.5rem;padding-left:.5rem;border-left:2px solid var(--dm-border,#333);";const M=u([["slide-up","Slide Up"],["slide-down","Slide Down"],["slide-left","Slide Left"],["slide-right","Slide Right"],["fade","Fade"],["zoom","Zoom"],["flip","Flip"]]);N.appendChild(n("Animation",M));const h=u([["stagger","Stagger"],["sequence","Sequence"]]);N.appendChild(n("Mode",h));const b=document.createElement("input");b.type="number",b.value="400",b.style.cssText=l,N.appendChild(n("Duration (ms)",b));const i=document.createElement("input");i.type="number",i.value="60",i.style.cssText=l,N.appendChild(n("Stagger (ms)",i));const o=document.createElement("input");o.type="number",o.value="0",o.style.cssText=l,N.appendChild(n("Delay (ms)",o));const s=u([["ltr","Left to Right"],["rtl","Right to Left"]]);N.appendChild(n("Direction",s)),w.appendChild(N),t.appendChild(w),f.addEventListener("change",()=>{N.style.display=f.checked?"flex":"none"});const j=document.createElement("button");j.type="button",j.className="btn btn-primary",j.textContent="Insert Grid",t.appendChild(j),k.addEventListener("click",()=>{v="grid",k.className="btn btn-sm btn-primary",c.className="btn btn-sm btn-ghost",m.style.display="flex",w.style.display="none",j.textContent="Insert Grid"}),c.addEventListener("click",()=>{v="row",c.className="btn btn-sm btn-primary",k.className="btn btn-sm btn-ghost",w.style.display="flex",m.style.display="none",j.textContent="Insert Row"});const Q=E.slideover({title:"Insert Grid / Row",size:"md",position:"right",content:t});Q.open(),requestAnimationFrame(()=>C.focus()),j.addEventListener("click",()=>{Q.close();const J=Math.min(Math.max(parseInt(C.value)||2,1),12),K=y.value;let P;if(v==="grid"){let F=`cols="${J}"`;K!=="4"&&(F+=` gap="${K}"`),r.checked&&(F+=' fullwidth="true"'),P=`[grid ${F}]
101
101
  `;for(let O=0;O<J;O++){const Z=B[O]?.value?.trim(),H=Z?` span="${Z}"`:"";P+=`[col${H}]
102
102
  Column ${O+1}
103
103
  [/col]
@@ -107,4 +107,4 @@ Column ${O+1}
107
107
  `,C.forEach((F,O)=>{const Z=F.input.value.trim()||`Item ${O+1}`;P+=`[item title="${Z}"]Content here.[/item]
108
108
  `}),P+="[/accordion]";else{const F=z.value;if(!F)return;const O=f.value,Z=h.value;let H=`slug="${F}" display="accordion"`;O&&(H+=` title-field="${O}"`),Z&&(H+=` body-field="${Z}"`);const te=s.value.trim();te&&(H+=` limit="${te}"`),Q.checked&&(H+=' multiple="true"'),P=`[collection ${H} /]`}ye(e,P),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onListGroup(e=>{const t=document.createElement("div");t.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const a="display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",l="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;";function n(w,L){const f=document.createElement("div"),N=document.createElement("label");return N.style.cssText=a,N.textContent=w,f.appendChild(N),f.appendChild(L),f}function u(w){const L=document.createElement("select");return L.style.cssText=l,w.forEach(([f,N])=>{const M=document.createElement("option");M.value=f,M.textContent=N,L.appendChild(M)}),L}const v=u([["","Default"],["flush","Flush (no outer border)"],["numbered","Numbered"],["horizontal","Horizontal"]]);t.appendChild(n("Variant",v));const g=u([["","Default"],["sm","Small"],["lg","Large"]]);t.appendChild(n("Size",g));const k=u([["","Default"],["primary","Primary"],["secondary","Secondary"],["success","Success"],["danger","Danger"],["warning","Warning"],["info","Info"]]);t.appendChild(n("Item Colour",k));const c=document.createElement("label");c.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.9em;cursor:pointer;";const C=document.createElement("input");C.type="checkbox",c.appendChild(C),c.appendChild(document.createTextNode("Actionable items (hover highlight)")),t.appendChild(c);const y=document.createElement("div");y.style.cssText=a+"margin-bottom:.35rem;",y.textContent="Items",t.appendChild(y);const m=document.createElement("div");m.style.cssText="display:flex;flex-direction:column;gap:.4rem;",t.appendChild(m);const p=[];function r(){p.forEach(w=>{w.removeBtn.disabled=p.length<=1,w.removeBtn.style.opacity=p.length<=1?"0.3":"1"})}function x(w){const L=document.createElement("div");L.style.cssText="display:flex;gap:.4rem;align-items:center;";const f=document.createElement("input");f.type="text",f.placeholder="Item text",f.value=w||"",f.style.cssText=l+"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 M={row:L,input:f,removeBtn:N};p.push(M),L.appendChild(f),L.appendChild(N),m.appendChild(L),N.addEventListener("click",()=>{if(p.length<=1)return;const h=p.indexOf(M);p.splice(h,1),m.removeChild(L),r()}),r()}x("Item 1"),x("Item 2"),x("Item 3");const T=document.createElement("button");T.type="button",T.textContent="+ Add Item",T.style.cssText="padding:.35rem .75rem;background:transparent;border:1px dashed var(--dm-border,#555);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;align-self:flex-start;",T.addEventListener("click",()=>{p.length>=20||(x(""),p[p.length-1].input.focus())}),t.appendChild(T);const B=document.createElement("button");B.type="button",B.className="btn btn-primary",B.textContent="Insert List Group",t.appendChild(B);const z=E.slideover({title:"Insert List Group",size:"md",position:"right",content:t});z.open(),requestAnimationFrame(()=>p[0].input.focus()),B.addEventListener("click",()=>{z.close();let w="";v.value&&(w+=` variant="${v.value}"`),g.value&&(w+=` size="${g.value}"`),k.value&&(w+=` itemvariant="${k.value}"`),C.checked&&(w+=' action="true"');let L=`[listgroup${w}]
109
109
  `;p.forEach(f=>{const N=f.input.value.trim();N&&(L+=`[item]${N}[/item]
110
- `)}),L+="[/listgroup]",ye(e,L),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCard(e=>{Ke.open(e,{onMediaBrowse:()=>Y.media.list().catch(()=>[])})}),q.onTimeline(e=>{Ze.open(e,{onPreview:async t=>{try{return await Y.pages.preview(t)}catch{return null}},onListCollections:()=>Y.collections.list().catch(()=>[]),onGetCollection:t=>Y.collections.get(t).catch(()=>null)})}),q.onEffects(e=>tt.open(e)),q.onHelp(()=>{it()}),q.onTutorial(e=>{lt(e)}),d.find(".editor-view-btn").on("click",function(){const e=$(this).data("mode");e&&(d.find(".editor-view-btn").removeClass("active"),$(this).addClass("active"),d.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${e}`),Qe("viewMode",e))}),d.find("#fullscreen-btn").on("click",function(){d.find(".editor-card").toggleClass("editor-fullscreen"),Qe("fullscreen",d.find(".editor-card").hasClass("editor-fullscreen"))}),Re=!1,d.find("#quick-switch").prop("disabled",!1),Ge&&window.removeEventListener("beforeunload",Ge),Ge=e=>{Re&&e.preventDefault()},window.addEventListener("beforeunload",Ge),je||(je=!0,R.use((e,t,a)=>{const l=window.location.hash.startsWith("#/pages/edit")||window.location.hash==="#/pages/new";if(!Re||!l)return a();E.confirm("You have unsaved changes. Leave this page?").then(n=>{n&&(Re=!1,a())})})),ue.on("input",()=>{ne||(Re=!0,d.find("#quick-switch").prop("disabled",!0),V())});const Pe=d.find("#editor-meta-tabs").get(0);Pe&&(Pe.addEventListener("input",()=>{Re=!0,d.find("#quick-switch").prop("disabled",!0)}),Pe.addEventListener("change",e=>{e.target.id!=="quick-switch"&&(Re=!0,d.find("#quick-switch").prop("disabled",!0))})),V(),d.find("#save-btn").on("click",async()=>{const e=d.find("#page-url-path").val().trim();if(!e){E.toast("URL path is required.",{type:"warning"});return}const t=d.find("#field-dconfig").val().trim();let a=null;if(t)try{a=JSON.parse(t)}catch{E.toast("DConfig JSON is invalid. Please check the format before saving.",{type:"warning"});return}const l={title:d.find("#field-title").val().trim()||"Untitled",description:d.find("#field-description").val().trim(),layout:d.find("#field-layout").val(),status:d.find("#field-status").val(),sortOrder:parseInt(d.find("#field-sort-order").val(),10)||99,showInNav:d.find("#field-show-in-nav").is(":checked"),sidebar:d.find("#field-sidebar").is(":checked"),...d.find("#field-show-breadcrumbs").is(":checked")?{}:{breadcrumbs:!1},...d.find("#field-bundled").is(":checked")?{bundled:!0}:{},tags:we?we.getValue():[],category:d.find("#field-category").val().trim()||null,visibility:d.find("#field-visibility").val()||"public",project:d.find("#field-project").val()||""||null,seo:{title:d.find("#field-seo-title").val().trim(),description:d.find("#field-seo-desc").val().trim()},dconfig:a,...d.find("#field-theme").val()?{theme:d.find("#field-theme").val()}:{}};try{d.find("#save-btn").prop("disabled",!0).text("Saving\u2026");const n=ae.getUnfoldedContent();if(U){const u={frontmatter:l,body:n};e!==de&&(u.newUrlPath=e),await Y.pages.update(de,u),oe&&await Y.settings.saveCustomCss(d.find("#css-editor").val()),E.toast(oe?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Re=!1,d.find("#quick-switch").prop("disabled",!1),e!==de&&R.navigate(`/pages/edit${e}`)}else await Y.pages.create({urlPath:e,frontmatter:l,body:n}),oe&&await Y.settings.saveCustomCss(d.find("#css-editor").val()),E.toast(oe?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Re=!1,R.navigate("/pages")}catch(n){E.toast(`Save failed: ${n.message||"Unknown error"}`,{type:"error"})}finally{d.find("#save-btn").prop("disabled",!1).text("Save")}}),d.find("#cancel-btn").on("click",()=>R.navigate("/pages")),Domma.icons.scan()}};
110
+ `)}),L+="[/listgroup]",ye(e,L),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}),q.onCard(e=>{Ke.open(e,{onMediaBrowse:()=>Y.media.list().catch(()=>[])})}),q.onTimeline(e=>{Ze.open(e,{onPreview:async t=>{try{return await Y.pages.preview(t)}catch{return null}},onListCollections:()=>Y.collections.list().catch(()=>[]),onGetCollection:t=>Y.collections.get(t).catch(()=>null)})}),q.onEffects(e=>tt.open(e)),q.onHelp(()=>{dt()}),q.onTutorial(e=>{it(e)}),d.find(".editor-view-btn").on("click",function(){const e=$(this).data("mode");e&&(d.find(".editor-view-btn").removeClass("active"),$(this).addClass("active"),d.find("#editor-body").removeClass("editor-mode-split editor-mode-write editor-mode-preview").addClass(`editor-mode-${e}`),Qe("viewMode",e))}),d.find("#fullscreen-btn").on("click",function(){d.find(".editor-card").toggleClass("editor-fullscreen"),Qe("fullscreen",d.find(".editor-card").hasClass("editor-fullscreen"))}),Re=!1,d.find("#quick-switch").prop("disabled",!1),Ge&&window.removeEventListener("beforeunload",Ge),Ge=e=>{Re&&e.preventDefault()},window.addEventListener("beforeunload",Ge),je||(je=!0,R.use((e,t,a)=>{const l=window.location.hash.startsWith("#/pages/edit")||window.location.hash==="#/pages/new";return!Re||!l?a():E.confirm("You have unsaved changes. Leave this page?").then(n=>{n&&(Re=!1,a())})})),pe.on("input",()=>{ne||(Re=!0,d.find("#quick-switch").prop("disabled",!0),V())});const Pe=d.find("#editor-meta-tabs").get(0);Pe&&(Pe.addEventListener("input",()=>{Re=!0,d.find("#quick-switch").prop("disabled",!0)}),Pe.addEventListener("change",e=>{e.target.id!=="quick-switch"&&(Re=!0,d.find("#quick-switch").prop("disabled",!0))})),V(),d.find("#save-btn").on("click",async()=>{const e=d.find("#page-url-path").val().trim();if(!e){E.toast("URL path is required.",{type:"warning"});return}const t=d.find("#field-dconfig").val().trim();let a=null;if(t)try{a=JSON.parse(t)}catch{E.toast("DConfig JSON is invalid. Please check the format before saving.",{type:"warning"});return}const l={title:d.find("#field-title").val().trim()||"Untitled",description:d.find("#field-description").val().trim(),layout:d.find("#field-layout").val(),status:d.find("#field-status").val(),sortOrder:parseInt(d.find("#field-sort-order").val(),10)||99,showInNav:d.find("#field-show-in-nav").is(":checked"),sidebar:d.find("#field-sidebar").is(":checked"),...d.find("#field-show-breadcrumbs").is(":checked")?{}:{breadcrumbs:!1},...d.find("#field-bundled").is(":checked")?{bundled:!0}:{},tags:we?we.getValue():[],category:d.find("#field-category").val().trim()||null,visibility:d.find("#field-visibility").val()||"public",project:d.find("#field-project").val()||""||null,seo:{title:d.find("#field-seo-title").val().trim(),description:d.find("#field-seo-desc").val().trim()},dconfig:a,...d.find("#field-theme").val()?{theme:d.find("#field-theme").val()}:{}};try{d.find("#save-btn").prop("disabled",!0).text("Saving\u2026");const n=ae.getUnfoldedContent();if(U){const u={frontmatter:l,body:n};e!==de&&(u.newUrlPath=e),await Y.pages.update(de,u),oe&&await Y.settings.saveCustomCss(d.find("#css-editor").val()),E.toast(oe?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Re=!1,d.find("#quick-switch").prop("disabled",!1),e!==de&&R.navigate(`/pages/edit${e}`)}else await Y.pages.create({urlPath:e,frontmatter:l,body:n}),oe&&await Y.settings.saveCustomCss(d.find("#css-editor").val()),E.toast(oe?"Page and CSS saved.":"Page saved successfully.",{type:"success"}),Re=!1,R.navigate("/pages")}catch(n){E.toast(`Save failed: ${n.message||"Unknown error"}`,{type:"error"})}finally{d.find("#save-btn").prop("disabled",!1).text("Save")}}),d.find("#cancel-btn").on("click",()=>R.navigate("/pages")),Domma.icons.scan()}};
@@ -0,0 +1,9 @@
1
+ {
2
+ "allowedHosts": [
3
+ "www.google.com",
4
+ "www.openstreetmap.org",
5
+ "codepen.io",
6
+ "codesandbox.io",
7
+ "open.spotify.com"
8
+ ]
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.35.0",
3
+ "version": "0.36.1",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",