domma-cms 0.6.16 → 0.6.21

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.
Files changed (44) hide show
  1. package/admin/js/api.js +1 -1
  2. package/admin/js/app.js +4 -4
  3. package/admin/js/lib/markdown-toolbar.js +14 -14
  4. package/admin/js/views/collection-editor.js +5 -3
  5. package/admin/js/views/collections.js +1 -1
  6. package/admin/js/views/page-editor.js +27 -27
  7. package/config/plugins.json +16 -0
  8. package/config/site.json +1 -1
  9. package/package.json +2 -2
  10. package/plugins/analytics/stats.json +1 -1
  11. package/plugins/contacts/admin/templates/contacts.html +126 -0
  12. package/plugins/contacts/admin/views/contacts.js +710 -0
  13. package/plugins/contacts/config.js +6 -0
  14. package/plugins/contacts/data/contacts.json +20 -0
  15. package/plugins/contacts/plugin.js +351 -0
  16. package/plugins/contacts/plugin.json +23 -0
  17. package/plugins/docs/admin/templates/docs.html +69 -0
  18. package/plugins/docs/admin/views/docs.js +276 -0
  19. package/plugins/docs/config.js +8 -0
  20. package/plugins/docs/data/documents/452f49b7-9c93-4a67-874d-27f882891ad2.json +11 -0
  21. package/plugins/docs/data/documents/57e003f0-68f2-47dc-9c36-ed4b10ed3deb.json +11 -0
  22. package/plugins/docs/data/folders.json +9 -0
  23. package/plugins/docs/data/templates.json +1 -0
  24. package/plugins/docs/plugin.js +375 -0
  25. package/plugins/docs/plugin.json +23 -0
  26. package/plugins/notes/admin/templates/notes.html +92 -0
  27. package/plugins/notes/admin/views/notes.js +304 -0
  28. package/plugins/notes/config.js +6 -0
  29. package/plugins/notes/data/notes.json +1 -0
  30. package/plugins/notes/plugin.js +177 -0
  31. package/plugins/notes/plugin.json +23 -0
  32. package/plugins/todo/admin/templates/todo.html +164 -0
  33. package/plugins/todo/admin/views/todo.js +328 -0
  34. package/plugins/todo/config.js +7 -0
  35. package/plugins/todo/data/todos.json +1 -0
  36. package/plugins/todo/plugin.js +155 -0
  37. package/plugins/todo/plugin.json +23 -0
  38. package/server/routes/api/auth.js +2 -0
  39. package/server/routes/api/collections.js +55 -0
  40. package/server/routes/api/forms.js +3 -0
  41. package/server/routes/api/settings.js +16 -1
  42. package/server/routes/public.js +2 -0
  43. package/server/services/markdown.js +169 -8
  44. package/server/services/plugins.js +3 -2
package/admin/js/api.js CHANGED
@@ -1 +1 @@
1
- const r="/api";function a(){return S.get("auth_token")}function h(){return S.get("auth_refresh_token")}function m(e){S.set("auth_token",e)}function c(){S.remove("auth_token"),S.remove("auth_refresh_token"),S.remove("auth_user")}async function l(){const e=h();if(!e)throw new Error("No refresh token");const o=await fetch(`${r}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(!o.ok)throw c(),R.navigate("/login"),new Error("Token refresh failed");const{token:s}=await o.json();return m(s),s}async function t(e,o={}){let s=a();const d=i=>({...o.body!==void 0?{"Content-Type":"application/json"}:{},...o.headers,...i?{Authorization:`Bearer ${i}`}:{}});let n=await fetch(`${r}${e}`,{...o,headers:d(s)});if(n.status===401&&h())try{s=await l(),n=await fetch(`${r}${e}`,{...o,headers:d(s)})}catch{return}if(!n.ok){const i=await n.json().catch(()=>({error:"Request failed"}));throw new Error(i.error||i.message||`HTTP ${n.status}`)}return n.status===204?null:n.json()}async function u(e,o){const s=a(),d=s?{Authorization:`Bearer ${s}`}:{},n=await fetch(`${r}${e}`,{method:"POST",headers:d,body:o});if(!n.ok){const i=await n.json().catch(()=>({error:"Upload failed"}));throw new Error(i.error||i.message||`HTTP ${n.status}`)}return n.json()}export const api={auth:{setupStatus:()=>t("/auth/setup-status",{method:"GET"}),setup:e=>t("/auth/setup",{method:"POST",body:JSON.stringify(e)}),login:e=>t("/auth/login",{method:"POST",body:JSON.stringify(e)}),me:()=>t("/auth/me",{method:"GET"}),updateMe:e=>t("/auth/me",{method:"PUT",body:JSON.stringify(e)}),refresh:e=>t("/auth/refresh",{method:"POST",body:JSON.stringify({refreshToken:e})}),forgotPassword:e=>t("/auth/forgot-password",{method:"POST",body:JSON.stringify({email:e})}),resetPassword:(e,o)=>t("/auth/reset-password",{method:"POST",body:JSON.stringify({token:e,password:o})})},pages:{list:()=>t("/pages",{method:"GET"}),get:e=>t(`/pages${e}`,{method:"GET"}),create:e=>t("/pages",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/pages${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/pages${e}`,{method:"DELETE"}),preview:e=>t("/pages/preview",{method:"POST",body:JSON.stringify({markdown:e})}),tags:()=>t("/pages/tags",{method:"GET"}).then(e=>e.tags||[])},settings:{get:()=>t("/settings",{method:"GET"}),save:e=>t("/settings",{method:"PUT",body:JSON.stringify(e)})},navigation:{get:()=>t("/navigation",{method:"GET"}),save:e=>t("/navigation",{method:"PUT",body:JSON.stringify(e)})},layouts:{get:()=>t("/layouts",{method:"GET"}),save:e=>t("/layouts",{method:"PUT",body:JSON.stringify(e)}),getOptions:()=>t("/layouts/options",{method:"GET"}),saveOptions:e=>t("/layouts/options",{method:"PUT",body:JSON.stringify(e)})},media:{list:()=>t("/media",{method:"GET"}),upload:e=>u("/media",e),delete:e=>t(`/media/${encodeURIComponent(e)}`,{method:"DELETE"}),rename:(e,o)=>t(`/media/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({newName:o})}),info:e=>t(`/media/${encodeURIComponent(e)}/info`,{method:"GET"}),transform:(e,o)=>t(`/media/${encodeURIComponent(e)}/transform`,{method:"POST",body:JSON.stringify(o)})},users:{list:()=>t("/users",{method:"GET"}),get:e=>t(`/users/${e}`,{method:"GET"}),create:e=>t("/users",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/users/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/users/${e}`,{method:"DELETE"})},plugins:{list:()=>t("/plugins",{method:"GET"}),update:(e,o)=>t(`/plugins/${e}`,{method:"PUT",body:JSON.stringify(o)}),adminConfig:()=>t("/plugins/admin-config",{method:"GET"})},collections:{list:()=>t("/collections",{method:"GET"}),proStatus:()=>t("/collections/pro-status",{method:"GET"}),get:e=>t(`/collections/${e}`,{method:"GET"}),create:e=>t("/collections",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/collections/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/collections/${e}`,{method:"DELETE"}),listEntries:(e,o={})=>{const s=new URLSearchParams(o).toString();return t(`/collections/${e}/entries${s?"?"+s:""}`,{method:"GET"})},getEntry:(e,o)=>t(`/collections/${e}/entries/${o}`,{method:"GET"}),createEntry:(e,o)=>t(`/collections/${e}/entries`,{method:"POST",body:JSON.stringify({data:o})}),updateEntry:(e,o,s)=>t(`/collections/${e}/entries/${o}`,{method:"PUT",body:JSON.stringify({data:s})}),deleteEntry:(e,o)=>t(`/collections/${e}/entries/${o}`,{method:"DELETE"}),clearEntries:e=>t(`/collections/${e}/entries`,{method:"DELETE"}),import:(e,o)=>t(`/collections/${e}/import`,{method:"POST",body:JSON.stringify({entries:o})}),publicList:(e,o={})=>{const s=new URLSearchParams(o).toString();return t(`/collections/${e}/public${s?"?"+s:""}`,{method:"GET"})},getConnections:()=>t("/collections/connections",{method:"GET"}),saveConnections:e=>t("/collections/connections",{method:"PUT",body:JSON.stringify(e)})},forms:{list:()=>t("/forms",{method:"GET"}),create:e=>t("/forms",{method:"POST",body:JSON.stringify(e)}),get:e=>t(`/forms/${e}`,{method:"GET"}),update:(e,o)=>t(`/forms/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/forms/${e}`,{method:"DELETE"}),listSubmissions:e=>t(`/forms/${e}/submissions`,{method:"GET"}),clearSubmissions:e=>t(`/forms/${e}/submissions`,{method:"DELETE"}),deleteSubmission:(e,o)=>t(`/forms/${e}/submissions/${o}`,{method:"DELETE"}),testEmail:e=>t("/forms/test-email",{method:"POST",body:JSON.stringify({to:e})})},views:{list:()=>t("/views",{method:"GET"}),get:e=>t(`/views/${e}`,{method:"GET"}),create:e=>t("/views",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/views/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/views/${e}`,{method:"DELETE"}),execute:(e,o={})=>{const s=new URLSearchParams(o).toString();return t(`/views/${e}/execute${s?"?"+s:""}`,{method:"GET"})},forCollection:e=>t(`/views/collection/${e}`,{method:"GET"})},actions:{list:()=>t("/actions",{method:"GET"}),get:e=>t(`/actions/${e}`,{method:"GET"}),create:e=>t("/actions",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/actions/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/actions/${e}`,{method:"DELETE"}),execute:(e,o)=>t(`/actions/${e}/execute`,{method:"POST",body:JSON.stringify({entryId:o})}),forCollection:e=>t(`/actions/collection/${e}`,{method:"GET"}),checkAccess:(e,o)=>t(`/actions/${e}/check-access`,{method:"POST",body:JSON.stringify({entryIds:o})})},versions:{list:e=>t(`/versions/list${e}`),get:(e,o)=>t(`/versions/get/${encodeURIComponent(o)}${e}`),create:(e,o)=>t(`/versions/create${e}`,{method:"POST",body:JSON.stringify({label:o})}),restore:(e,o)=>t(`/versions/restore/${encodeURIComponent(o)}${e}`,{method:"POST"}),delete:(e,o)=>t(`/versions/delete/${encodeURIComponent(o)}${e}`,{method:"DELETE"})},blocks:{list:()=>t("/blocks",{method:"GET"}),get:e=>t(`/blocks/${encodeURIComponent(e)}`,{method:"GET"}),put:(e,o)=>t(`/blocks/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/blocks/${encodeURIComponent(e)}`,{method:"DELETE"})},get:e=>t(e,{method:"GET"}),post:(e,o)=>t(e,{method:"POST",body:JSON.stringify(o)}),put:(e,o)=>t(e,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(e,{method:"DELETE"}),themes:{list:()=>t("/plugins/theme-roller/themes",{method:"GET"})},settingsExt:{testEmail:e=>t("/settings/test-email",{method:"POST",body:JSON.stringify({to:e})})}};export function isAuthenticated(){return!!a()}export function getUser(){return S.get("auth_user")}export function setAuthData({token:e,refreshToken:o,user:s}){e&&m(e),o&&S.set("auth_refresh_token",o),s&&S.set("auth_user",s)}export function logout(){const e=h();e&&fetch(`${r}/auth/logout`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})}).catch(()=>{}),c(),R.navigate("/login")}export{t as apiRequest};
1
+ const r="/api";function a(){return S.get("auth_token")}function h(){return S.get("auth_refresh_token")}function m(e){S.set("auth_token",e)}function c(){S.remove("auth_token"),S.remove("auth_refresh_token"),S.remove("auth_user")}async function l(){const e=h();if(!e)throw new Error("No refresh token");const o=await fetch(`${r}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(!o.ok)throw c(),R.navigate("/login"),new Error("Token refresh failed");const{token:s}=await o.json();return m(s),s}async function t(e,o={}){let s=a();const d=i=>({...o.body!==void 0?{"Content-Type":"application/json"}:{},...o.headers,...i?{Authorization:`Bearer ${i}`}:{}});let n=await fetch(`${r}${e}`,{...o,headers:d(s)});if(n.status===401&&h())try{s=await l(),n=await fetch(`${r}${e}`,{...o,headers:d(s)})}catch{return}if(!n.ok){const i=await n.json().catch(()=>({error:"Request failed"}));throw new Error(i.error||i.message||`HTTP ${n.status}`)}return n.status===204?null:n.json()}async function u(e,o){const s=a(),d=s?{Authorization:`Bearer ${s}`}:{},n=await fetch(`${r}${e}`,{method:"POST",headers:d,body:o});if(!n.ok){const i=await n.json().catch(()=>({error:"Upload failed"}));throw new Error(i.error||i.message||`HTTP ${n.status}`)}return n.json()}export const api={auth:{setupStatus:()=>t("/auth/setup-status",{method:"GET"}),setup:e=>t("/auth/setup",{method:"POST",body:JSON.stringify(e)}),login:e=>t("/auth/login",{method:"POST",body:JSON.stringify(e)}),me:()=>t("/auth/me",{method:"GET"}),updateMe:e=>t("/auth/me",{method:"PUT",body:JSON.stringify(e)}),refresh:e=>t("/auth/refresh",{method:"POST",body:JSON.stringify({refreshToken:e})}),forgotPassword:e=>t("/auth/forgot-password",{method:"POST",body:JSON.stringify({email:e})}),resetPassword:(e,o)=>t("/auth/reset-password",{method:"POST",body:JSON.stringify({token:e,password:o})})},pages:{list:()=>t("/pages",{method:"GET"}),get:e=>t(`/pages${e}`,{method:"GET"}),create:e=>t("/pages",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/pages${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/pages${e}`,{method:"DELETE"}),preview:e=>t("/pages/preview",{method:"POST",body:JSON.stringify({markdown:e})}),tags:()=>t("/pages/tags",{method:"GET"}).then(e=>e.tags||[])},settings:{get:()=>t("/settings",{method:"GET"}),save:e=>t("/settings",{method:"PUT",body:JSON.stringify(e)})},navigation:{get:()=>t("/navigation",{method:"GET"}),save:e=>t("/navigation",{method:"PUT",body:JSON.stringify(e)})},layouts:{get:()=>t("/layouts",{method:"GET"}),save:e=>t("/layouts",{method:"PUT",body:JSON.stringify(e)}),getOptions:()=>t("/layouts/options",{method:"GET"}),saveOptions:e=>t("/layouts/options",{method:"PUT",body:JSON.stringify(e)})},media:{list:()=>t("/media",{method:"GET"}),upload:e=>u("/media",e),delete:e=>t(`/media/${encodeURIComponent(e)}`,{method:"DELETE"}),rename:(e,o)=>t(`/media/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({newName:o})}),info:e=>t(`/media/${encodeURIComponent(e)}/info`,{method:"GET"}),transform:(e,o)=>t(`/media/${encodeURIComponent(e)}/transform`,{method:"POST",body:JSON.stringify(o)})},users:{list:()=>t("/users",{method:"GET"}),get:e=>t(`/users/${e}`,{method:"GET"}),create:e=>t("/users",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/users/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/users/${e}`,{method:"DELETE"})},plugins:{list:()=>t("/plugins",{method:"GET"}),update:(e,o)=>t(`/plugins/${e}`,{method:"PUT",body:JSON.stringify(o)}),adminConfig:()=>t("/plugins/admin-config",{method:"GET"})},collections:{list:()=>t("/collections",{method:"GET"}),proStatus:()=>t("/collections/pro-status",{method:"GET"}),get:e=>t(`/collections/${e}`,{method:"GET"}),create:e=>t("/collections",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/collections/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/collections/${e}`,{method:"DELETE"}),listEntries:(e,o={})=>{const s=new URLSearchParams(o).toString();return t(`/collections/${e}/entries${s?"?"+s:""}`,{method:"GET"})},getEntry:(e,o)=>t(`/collections/${e}/entries/${o}`,{method:"GET"}),createEntry:(e,o)=>t(`/collections/${e}/entries`,{method:"POST",body:JSON.stringify({data:o})}),updateEntry:(e,o,s)=>t(`/collections/${e}/entries/${o}`,{method:"PUT",body:JSON.stringify({data:s})}),deleteEntry:(e,o)=>t(`/collections/${e}/entries/${o}`,{method:"DELETE"}),clearEntries:e=>t(`/collections/${e}/entries`,{method:"DELETE"}),import:(e,o)=>t(`/collections/${e}/import`,{method:"POST",body:JSON.stringify({entries:o})}),publicList:(e,o={})=>{const s=new URLSearchParams(o).toString();return t(`/collections/${e}/public${s?"?"+s:""}`,{method:"GET"})},getConnections:()=>t("/collections/connections",{method:"GET"}),saveConnections:e=>t("/collections/connections",{method:"PUT",body:JSON.stringify(e)}),migrateStorage:(e,o)=>t(`/collections/${e}/migrate-storage`,{method:"POST",body:JSON.stringify({storage:o})})},forms:{list:()=>t("/forms",{method:"GET"}),create:e=>t("/forms",{method:"POST",body:JSON.stringify(e)}),get:e=>t(`/forms/${e}`,{method:"GET"}),update:(e,o)=>t(`/forms/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/forms/${e}`,{method:"DELETE"}),listSubmissions:e=>t(`/forms/${e}/submissions`,{method:"GET"}),clearSubmissions:e=>t(`/forms/${e}/submissions`,{method:"DELETE"}),deleteSubmission:(e,o)=>t(`/forms/${e}/submissions/${o}`,{method:"DELETE"}),testEmail:e=>t("/forms/test-email",{method:"POST",body:JSON.stringify({to:e})})},views:{list:()=>t("/views",{method:"GET"}),get:e=>t(`/views/${e}`,{method:"GET"}),create:e=>t("/views",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/views/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/views/${e}`,{method:"DELETE"}),execute:(e,o={})=>{const s=new URLSearchParams(o).toString();return t(`/views/${e}/execute${s?"?"+s:""}`,{method:"GET"})},forCollection:e=>t(`/views/collection/${e}`,{method:"GET"})},actions:{list:()=>t("/actions",{method:"GET"}),get:e=>t(`/actions/${e}`,{method:"GET"}),create:e=>t("/actions",{method:"POST",body:JSON.stringify(e)}),update:(e,o)=>t(`/actions/${e}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/actions/${e}`,{method:"DELETE"}),execute:(e,o)=>t(`/actions/${e}/execute`,{method:"POST",body:JSON.stringify({entryId:o})}),forCollection:e=>t(`/actions/collection/${e}`,{method:"GET"}),checkAccess:(e,o)=>t(`/actions/${e}/check-access`,{method:"POST",body:JSON.stringify({entryIds:o})})},versions:{list:e=>t(`/versions/list${e}`),get:(e,o)=>t(`/versions/get/${encodeURIComponent(o)}${e}`),create:(e,o)=>t(`/versions/create${e}`,{method:"POST",body:JSON.stringify({label:o})}),restore:(e,o)=>t(`/versions/restore/${encodeURIComponent(o)}${e}`,{method:"POST"}),delete:(e,o)=>t(`/versions/delete/${encodeURIComponent(o)}${e}`,{method:"DELETE"})},blocks:{list:()=>t("/blocks",{method:"GET"}),get:e=>t(`/blocks/${encodeURIComponent(e)}`,{method:"GET"}),put:(e,o)=>t(`/blocks/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(`/blocks/${encodeURIComponent(e)}`,{method:"DELETE"})},get:e=>t(e,{method:"GET"}),post:(e,o)=>t(e,{method:"POST",body:JSON.stringify(o)}),put:(e,o)=>t(e,{method:"PUT",body:JSON.stringify(o)}),delete:e=>t(e,{method:"DELETE"}),themes:{list:()=>t("/plugins/theme-roller/themes",{method:"GET"})},settingsExt:{testEmail:e=>t("/settings/test-email",{method:"POST",body:JSON.stringify({to:e})})}};export function isAuthenticated(){return!!a()}export function getUser(){return S.get("auth_user")}export function setAuthData({token:e,refreshToken:o,user:s}){e&&m(e),o&&S.set("auth_refresh_token",o),s&&S.set("auth_user",s)}export function logout(){const e=h();e&&fetch(`${r}/auth/logout`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})}).catch(()=>{}),c(),R.navigate("/login")}export{t as apiRequest};
package/admin/js/app.js CHANGED
@@ -1,6 +1,6 @@
1
- import{getSidebarConfig as F}from"./config/sidebar-config.js";import{views as J}from"./views/index.js";import{api as o,getUser as r,isAuthenticated as l,logout as K}from"./api.js";$(()=>{(async()=>{try{const t=l()?await o.settings.get():null;Domma.theme.init({theme:t?.adminTheme||"charcoal-dark",persist:!0})}catch{Domma.theme.init({theme:"charcoal-dark",persist:!0})}})();const k=["jb-company","jb-agent","jb-candidate"],P=["/job-board","/my-profile"];function m(t){return t&&k.includes(t.role)}function d(t){return P.some(e=>t===e||t.startsWith(e+"/"))}R.use(async(t,e,i)=>{if(t.path==="/login"||t.path==="/reset-password")return i();if(!l()){R.navigate("/login");return}if(m(r())&&!d(t.path)){R.navigate("/job-board");return}i()});let c=null;async function j(){if(!l())return{};try{const[t,e,i,a,s,n,W,x,T,V,B,I,U]=await Promise.all([o.pages.list().catch(()=>[]),o.media.list().catch(()=>[]),o.users.list().catch(()=>[]),o.plugins.list().catch(()=>[]),o.collections.list().catch(()=>[]),o.forms.list().catch(()=>[]),o.themes.list().catch(()=>[]),o.views.list().catch(()=>[]),o.actions.list().catch(()=>[]),o.blocks.list().catch(()=>[]),o.navigation.get().catch(()=>({})),o.layouts.get().catch(()=>({})),o.get("/collections/roles/entries?limit=100").catch(()=>({entries:[]}))]),S=B.items||[],_=S.filter(h=>!h.hidden).length,D=S.length,O=a.filter(h=>h.enabled).length,y=a.length;return{pages:t.length,media:e.length,users:i.length,plugins:y>0?`${O}/${y}`:null,collections:s.length,forms:n.length,themes:W.length,views:x.length,actions:T.length,blocks:V.length,navigation:D>0?`${_}/${D}`:null,layouts:Object.keys(I).length,roles:(U.entries||[]).length}}catch{return{}}}async function u(){try{return(await o.get("/auth/permissions")).permissions||[]}catch{return[]}}async function g(t){c&&$("#admin-sidebar").empty();const e=await j(),i=b.map(a=>{if(!a.countKey)return a;const s=e[a.countKey];return{...a,badge:s!=null&&s>0?String(s):null}});c=Domma.elements.sidebar("#admin-sidebar",{header:{title:"CMS Admin",icon:"layout"},items:F(t,e,i),collapsible:!0,collapseAt:992,push:!0,contentSelector:".dashboard-main",top:"60px"}),A(),L()}function A(){$("#admin-sidebar .sidebar-link").each(function(){const t=$(this).find(".sidebar-text").text().trim();t&&$(this).attr("data-tooltip",t)}),E.tooltip("#admin-sidebar [data-tooltip]",{placement:"right"})}function L(){$("#admin-sidebar .sidebar-heading").each(function(){const t=$(this);t.addClass("sidebar-heading--collapsible"),t.append('<span class="sidebar-heading-toggle"><span data-icon="chevron-down"></span></span>'),t.on("click",function(){const e=!t.hasClass("is-collapsed");t.toggleClass("is-collapsed",e);let i=t.next();for(;i.length&&!i.hasClass("sidebar-heading")&&!i.hasClass("sidebar-divider");)i.toggle(!e),i=i.next()})}),Domma.icons.scan("#admin-sidebar")}M.subscribe("router:afterChange",({to:t})=>{c&&t.path!=="/login"&&t.path!=="/reset-password"&&c.setActive("#"+t.path)});const N=[{path:"/",view:"dashboard",title:"Dashboard - Domma CMS"},{path:"/pages",view:"pages",title:"Pages - Domma CMS"},{path:"/pages/new",view:"pageEditor",title:"New Page - Domma CMS"},{path:"/pages/edit/*",view:"pageEditor",title:"Edit Page - Domma CMS"},{path:"/media",view:"media",title:"Media - Domma CMS"},{path:"/navigation",view:"navigation",title:"Navigation - Domma CMS"},{path:"/layouts",view:"layouts",title:"Layouts - Domma CMS"},{path:"/settings",view:"settings",title:"Settings - Domma CMS"},{path:"/users",view:"users",title:"Users - Domma CMS"},{path:"/users/new",view:"userEditor",title:"New User - Domma CMS"},{path:"/users/edit/:id",view:"userEditor",title:"Edit User - Domma CMS"},{path:"/plugins",view:"plugins",title:"Plugins - Domma CMS"},{path:"/documentation",view:"documentation",title:"Usage - Domma CMS"},{path:"/tutorials",view:"tutorials",title:"Tutorials - Domma CMS"},{path:"/api-reference",view:"apiReference",title:"API Reference - Domma CMS"},{path:"/collections",view:"collections",title:"Collections - Domma CMS"},{path:"/collections/new",view:"collectionEditor",title:"New Collection - Domma CMS"},{path:"/collections/edit/:slug",view:"collectionEditor",title:"Edit Collection - Domma CMS"},{path:"/collections/:slug/entries",view:"collectionEntries",title:"Entries - Domma CMS"},{path:"/forms",view:"forms",title:"Forms - Domma CMS"},{path:"/forms/new",view:"formEditor",title:"New Form - Domma CMS"},{path:"/forms/edit/:slug",view:"formEditor",title:"Edit Form - Domma CMS"},{path:"/forms/:slug/submissions",view:"formSubmissions",title:"Submissions - Domma CMS"},{path:"/views",view:"viewsList",title:"Views - Domma CMS"},{path:"/views/new",view:"viewEditor",title:"New View - Domma CMS"},{path:"/views/edit/:slug",view:"viewEditor",title:"Edit View - Domma CMS"},{path:"/views/:slug/preview",view:"viewPreview",title:"View Preview - Domma CMS"},{path:"/actions",view:"actionsList",title:"Actions - Domma CMS"},{path:"/actions/new",view:"actionEditor",title:"New Action - Domma CMS"},{path:"/actions/edit/:slug",view:"actionEditor",title:"Edit Action - Domma CMS"},{path:"/pro/docs",view:"proDocs",title:"Pro Documentation - Domma CMS"},{path:"/blocks",view:"blocks",title:"Blocks - Domma CMS"},{path:"/blocks/new",view:"blockEditor",title:"New Block - Domma CMS"},{path:"/blocks/edit/:name",view:"blockEditor",title:"Edit Block - Domma CMS"},{path:"/my-profile",view:"myProfile",title:"My Profile - Domma CMS"},{path:"/roles",view:"roles",title:"Roles & Permissions - Domma CMS"},{path:"/roles/edit/:id",view:"roleEditor",title:"Edit Role - Domma CMS"},{path:"/login",view:"login",title:"Sign in - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}},{path:"/reset-password",view:"login",title:"Reset Password - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}}];M.subscribe("router:afterChange",async({to:t,from:e})=>{if(!(t.path==="/login"||t.path==="/reset-password")){if(m(r())&&!d(t.path)){R.navigate("/job-board");return}if($("#admin-sidebar").show(),$("#admin-topbar").show(),e?.path==="/login"||e?.path==="/reset-password"){$("#topbar-user-name").remove(),await f();const i=await u();g(i)}v()}}),M.subscribe("router:afterChange",()=>{setTimeout(()=>{$(".btn-primary, .btn-danger").length&&Domma.effects.reveal(".btn-primary, .btn-danger",{animation:"fade",stagger:40,duration:300})},50)}),$("#view-container").on("click",".card-collapsible .card-header",function(t){$(t.target).closest("button, a").length||$(this).closest(".card").toggleClass("card-collapsed")}),document.addEventListener("keydown",t=>{if(!(t.ctrlKey||t.metaKey)||t.key!=="s"||window.location.hash==="#/login"||window.location.hash.startsWith("#/reset-password"))return;const e=document.querySelector("#view-container .view-header button.btn-primary");e&&(t.preventDefault(),e.click())});const w={...J},p=[...N];let b=[];async function f(){if(l())try{const t=await o.plugins.adminConfig();b=t.sidebar||[],t.routes?.length&&p.push(...t.routes);for(const[e,i]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${i.entry}`);w[e]=a[i.exportName]}catch{}}catch{}}function v(){const t=r();if(!t||$("#topbar-user-name").length)return;const i={admin:"Admin",manager:"Manager",editor:"Editor",subscriber:"Subscriber","jb-company":"Company","jb-agent":"Agent","jb-candidate":"Candidate"}[t.role]||t.role;$("#topbar-user").html(`
2
- <span id="topbar-user-name" class="topbar-user-name">${C(t.name)}</span>
3
- <span class="topbar-role-badge topbar-role-badge--${C(t.role)}">${i}</span>
1
+ import{getSidebarConfig as J}from"./config/sidebar-config.js";import{views as K}from"./views/index.js";import{api as o,getUser as r,isAuthenticated as l,logout as H}from"./api.js";$(()=>{(async()=>{try{const t=l()?await o.settings.get():null;Domma.theme.init({theme:t?.adminTheme||"charcoal-dark",persist:!0})}catch{Domma.theme.init({theme:"charcoal-dark",persist:!0})}})();const k=["jb-company","jb-agent","jb-candidate"],P=["/job-board","/my-profile"];function d(t){return t&&k.includes(t.role)}function m(t){return P.some(e=>t===e||t.startsWith(e+"/"))}R.use(async(t,e,i)=>{if(t.path==="/login"||t.path==="/reset-password")return i();if(!l()){R.navigate("/login");return}if(d(r())&&!m(t.path)){R.navigate("/job-board");return}i()});let c=null;async function x(){if(!l())return{};try{const[t,e,i,a,s,n,W,B,T,V,I,U,_]=await Promise.all([o.pages.list().catch(()=>[]),o.media.list().catch(()=>[]),o.users.list().catch(()=>[]),o.plugins.list().catch(()=>[]),o.collections.list().catch(()=>[]),o.forms.list().catch(()=>[]),o.themes.list().catch(()=>[]),o.views.list().catch(()=>[]),o.actions.list().catch(()=>[]),o.blocks.list().catch(()=>[]),o.navigation.get().catch(()=>({})),o.layouts.get().catch(()=>({})),o.get("/collections/roles/entries?limit=100").catch(()=>({entries:[]}))]),C=I.items||[],O=C.filter(h=>!h.hidden).length,D=C.length,F=a.filter(h=>h.enabled).length,y=a.length;return{pages:t.length,media:e.length,users:i.length,plugins:y>0?`${F}/${y}`:null,collections:s.length,forms:n.length,themes:W.length,views:B.length,actions:T.length,blocks:V.length,navigation:D>0?`${O}/${D}`:null,layouts:Object.keys(U).length,roles:(_.entries||[]).length}}catch{return{}}}async function u(){try{return(await o.get("/auth/permissions")).permissions||[]}catch{return[]}}async function j(){try{return await o.get("/settings/db-status")}catch{return{configured:!1}}}async function g(t){c&&$("#admin-sidebar").empty();const[e,i]=await Promise.all([x(),j()]),a=w.map(s=>{if(!s.countKey)return s;const n=e[s.countKey];return{...s,badge:n!=null&&n>0?String(n):null}});if(c=Domma.elements.sidebar("#admin-sidebar",{header:{title:"CMS Admin",icon:"layout"},items:J(t,e,a),collapsible:!0,collapseAt:992,push:!0,contentSelector:".dashboard-main",top:"60px"}),A(),L(),i?.configured){const s=$("#admin-sidebar").find(".sidebar-header-title").first();s.length&&!s.find(".db-badge").length&&s.append('<span class="db-badge" title="MongoDB connected" style="display:inline-flex;align-items:center;background:#16a34a;color:#fff;font-size:10px;font-weight:700;padding:2px 6px;border-radius:9999px;letter-spacing:.5px;margin-left:6px;vertical-align:middle;line-height:1;">DB</span>')}}function A(){$("#admin-sidebar .sidebar-link").each(function(){const t=$(this).find(".sidebar-text").text().trim();t&&$(this).attr("data-tooltip",t)}),E.tooltip("#admin-sidebar [data-tooltip]",{placement:"right"})}function L(){$("#admin-sidebar .sidebar-heading").each(function(){const t=$(this);t.addClass("sidebar-heading--collapsible"),t.append('<span class="sidebar-heading-toggle"><span data-icon="chevron-down"></span></span>'),t.on("click",function(){const e=!t.hasClass("is-collapsed");t.toggleClass("is-collapsed",e);let i=t.next();for(;i.length&&!i.hasClass("sidebar-heading")&&!i.hasClass("sidebar-divider");)i.toggle(!e),i=i.next()})}),Domma.icons.scan("#admin-sidebar")}M.subscribe("router:afterChange",({to:t})=>{c&&t.path!=="/login"&&t.path!=="/reset-password"&&c.setActive("#"+t.path)});const N=[{path:"/",view:"dashboard",title:"Dashboard - Domma CMS"},{path:"/pages",view:"pages",title:"Pages - Domma CMS"},{path:"/pages/new",view:"pageEditor",title:"New Page - Domma CMS"},{path:"/pages/edit/*",view:"pageEditor",title:"Edit Page - Domma CMS"},{path:"/media",view:"media",title:"Media - Domma CMS"},{path:"/navigation",view:"navigation",title:"Navigation - Domma CMS"},{path:"/layouts",view:"layouts",title:"Layouts - Domma CMS"},{path:"/settings",view:"settings",title:"Settings - Domma CMS"},{path:"/users",view:"users",title:"Users - Domma CMS"},{path:"/users/new",view:"userEditor",title:"New User - Domma CMS"},{path:"/users/edit/:id",view:"userEditor",title:"Edit User - Domma CMS"},{path:"/plugins",view:"plugins",title:"Plugins - Domma CMS"},{path:"/documentation",view:"documentation",title:"Usage - Domma CMS"},{path:"/tutorials",view:"tutorials",title:"Tutorials - Domma CMS"},{path:"/api-reference",view:"apiReference",title:"API Reference - Domma CMS"},{path:"/collections",view:"collections",title:"Collections - Domma CMS"},{path:"/collections/new",view:"collectionEditor",title:"New Collection - Domma CMS"},{path:"/collections/edit/:slug",view:"collectionEditor",title:"Edit Collection - Domma CMS"},{path:"/collections/:slug/entries",view:"collectionEntries",title:"Entries - Domma CMS"},{path:"/forms",view:"forms",title:"Forms - Domma CMS"},{path:"/forms/new",view:"formEditor",title:"New Form - Domma CMS"},{path:"/forms/edit/:slug",view:"formEditor",title:"Edit Form - Domma CMS"},{path:"/forms/:slug/submissions",view:"formSubmissions",title:"Submissions - Domma CMS"},{path:"/views",view:"viewsList",title:"Views - Domma CMS"},{path:"/views/new",view:"viewEditor",title:"New View - Domma CMS"},{path:"/views/edit/:slug",view:"viewEditor",title:"Edit View - Domma CMS"},{path:"/views/:slug/preview",view:"viewPreview",title:"View Preview - Domma CMS"},{path:"/actions",view:"actionsList",title:"Actions - Domma CMS"},{path:"/actions/new",view:"actionEditor",title:"New Action - Domma CMS"},{path:"/actions/edit/:slug",view:"actionEditor",title:"Edit Action - Domma CMS"},{path:"/pro/docs",view:"proDocs",title:"Pro Documentation - Domma CMS"},{path:"/blocks",view:"blocks",title:"Blocks - Domma CMS"},{path:"/blocks/new",view:"blockEditor",title:"New Block - Domma CMS"},{path:"/blocks/edit/:name",view:"blockEditor",title:"Edit Block - Domma CMS"},{path:"/my-profile",view:"myProfile",title:"My Profile - Domma CMS"},{path:"/roles",view:"roles",title:"Roles & Permissions - Domma CMS"},{path:"/roles/edit/:id",view:"roleEditor",title:"Edit Role - Domma CMS"},{path:"/login",view:"login",title:"Sign in - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}},{path:"/reset-password",view:"login",title:"Reset Password - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}}];M.subscribe("router:afterChange",async({to:t,from:e})=>{if(!(t.path==="/login"||t.path==="/reset-password")){if(d(r())&&!m(t.path)){R.navigate("/job-board");return}if($("#admin-sidebar").show(),$("#admin-topbar").show(),e?.path==="/login"||e?.path==="/reset-password"){$("#topbar-user-name").remove(),await f();const i=await u();g(i)}v()}}),M.subscribe("router:afterChange",()=>{setTimeout(()=>{$(".btn-primary, .btn-danger").length&&Domma.effects.reveal(".btn-primary, .btn-danger",{animation:"fade",stagger:40,duration:300})},50)}),$("#view-container").on("click",".card-collapsible .card-header",function(t){$(t.target).closest("button, a").length||$(this).closest(".card").toggleClass("card-collapsed")}),document.addEventListener("keydown",t=>{if(!(t.ctrlKey||t.metaKey)||t.key!=="s"||window.location.hash==="#/login"||window.location.hash.startsWith("#/reset-password"))return;const e=document.querySelector("#view-container .view-header button.btn-primary");e&&(t.preventDefault(),e.click())});const b={...K},p=[...N];let w=[];async function f(){if(l())try{const t=await o.plugins.adminConfig();w=t.sidebar||[],t.routes?.length&&p.push(...t.routes);for(const[e,i]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${i.entry}`);b[e]=a[i.exportName]}catch{}}catch{}}function v(){const t=r();if(!t||$("#topbar-user-name").length)return;const i={admin:"Admin",manager:"Manager",editor:"Editor",subscriber:"Subscriber","jb-company":"Company","jb-agent":"Agent","jb-candidate":"Candidate"}[t.role]||t.role;$("#topbar-user").html(`
2
+ <span id="topbar-user-name" class="topbar-user-name">${S(t.name)}</span>
3
+ <span class="topbar-role-badge topbar-role-badge--${S(t.role)}">${i}</span>
4
4
  `),$("#topbar-actions").html(`
5
5
  <a href="#/my-profile" class="topbar-action-link" data-tooltip="My Profile" data-tooltip-placement="bottom">
6
6
  <span data-icon="user"></span>
@@ -14,4 +14,4 @@ import{getSidebarConfig as F}from"./config/sidebar-config.js";import{views as J}
14
14
  <span data-icon="log-out"></span>
15
15
  <span>Sign out</span>
16
16
  </a>
17
- `),$("#topbar-logout-btn").on("click",a=>{a.preventDefault(),K()}),Domma.icons.scan("#admin-topbar"),E.tooltip("#topbar-actions [data-tooltip]",{placement:"bottom"})}function C(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}(async()=>{if(!l()&&!window.location.hash.startsWith("#/reset-password"))window.location.hash="#/login";else{const a=(window.location.hash||"#/").slice(1)||"/";if(m(r())&&!d(a)&&(window.location.hash="#/job-board"),await f(),r()){const n=await u();await g(n),v()}}R.init({container:"#view-container",routes:p,views:w,default:"/",transitions:{enter:"fadeIn",leave:"fadeOut",duration:150}});const t=R._extractParams.bind(R);R._extractParams=function(a,s){if(a.endsWith("/*")){const n=a.slice(0,-2);return s.startsWith(n+"/")?{}:null}return t(a,s)};const e=(window.location.hash||"#/").slice(1)||"/";p.filter(a=>a.path.endsWith("/*")).some(a=>e.startsWith(a.path.slice(0,-2)+"/"))&&R._handleRouteChange()})()});
17
+ `),$("#topbar-logout-btn").on("click",a=>{a.preventDefault(),H()}),Domma.icons.scan("#admin-topbar"),E.tooltip("#topbar-actions [data-tooltip]",{placement:"bottom"})}function S(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}(async()=>{if(!l()&&!window.location.hash.startsWith("#/reset-password"))window.location.hash="#/login";else{const a=(window.location.hash||"#/").slice(1)||"/";if(d(r())&&!m(a)&&(window.location.hash="#/job-board"),await f(),r()){const n=await u();await g(n),v()}}R.init({container:"#view-container",routes:p,views:b,default:"/",transitions:{enter:"fadeIn",leave:"fadeOut",duration:150}});const t=R._extractParams.bind(R);R._extractParams=function(a,s){if(a.endsWith("/*")){const n=a.slice(0,-2);return s.startsWith(n+"/")?{}:null}return t(a,s)};const e=(window.location.hash||"#/").slice(1)||"/";p.filter(a=>a.path.endsWith("/*")).some(a=>e.startsWith(a.path.slice(0,-2)+"/"))&&R._handleRouteChange()})()});
@@ -1,6 +1,6 @@
1
- function z(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H7V5zM7 11H15a3 3 0 0 1 0 6H7V11z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("italic",{viewBox:"0 0 24 24",path:"M11 5h4M9 19h4M13 5l-2 14",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("strikethrough",{viewBox:"0 0 24 24",path:"M16 4H9a3 3 0 0 0 0 6h6a3 3 0 0 1 0 6H6M3 12h18",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("quote",{viewBox:"0 0 24 24",path:"M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1zM15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("eye",{viewBox:"0 0 24 24",path:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("expand",{viewBox:"0 0 24 24",path:"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("columns",{viewBox:"0 0 24 24",path:"M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM12 4v16",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("card",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M3 9h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("help-circle",{viewBox:"0 0 24 24",path:"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 17h.01M12 13a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("spacer-insert",{viewBox:"0 0 24 24",paths:["M3 8h18","M3 16h18","M12 8v8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("icon-pick",{viewBox:"0 0 24 24",paths:["M4 4h6v6H4z","M14 4h6v6h-6z","M4 14h6v6H4z","M14 14h6v6h-6z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("btn-insert",{viewBox:"0 0 24 24",paths:["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z","M8 12h8M12 9v6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("link-shortcode",{viewBox:"0 0 24 24",paths:["M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71","M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("layout-list",{viewBox:"0 0 24 24",paths:["M3 5h18M3 9h18","M3 14h4v6H3zM9 14h12M9 17h8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("sparkles",{viewBox:"0 0 24 24",paths:["M12 3L13.5 8.5H19L14.5 11.5L16 17L12 14L8 17L9.5 11.5L5 8.5H10.5L12 3Z","M19 3L19.7 5.3H22L20.2 6.6L20.9 9L19 7.7L17.1 9L17.8 6.6L16 5.3H18.3L19 3Z","M5 13L5.5 14.7H7L5.8 15.5L6.3 17.2L5 16.3L3.7 17.2L4.2 15.5L3 14.7H4.5L5 13Z"],stroke:"currentColor",fill:"none",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("accordion-insert",{viewBox:"0 0 24 24",paths:["M3 4h18","M3 8h18","M8 11l4 4 4-4","M3 16h18","M3 20h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("hero",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5z","M7 8h10M7 11h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"})}export function wrapSelection(t,e,p){const i=t.selectionStart,s=t.selectionEnd,n=t.value,l=n.substring(i,s);l?(t.value=n.substring(0,i)+e+l+p+n.substring(s),t.selectionStart=i+e.length,t.selectionEnd=s+e.length):(t.value=n.substring(0,i)+e+p+n.substring(i),t.selectionStart=t.selectionEnd=i+e.length),t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function insertAtCursor(t,e){const p=t.selectionStart,i=t.value;t.value=i.substring(0,p)+e+i.substring(p),t.selectionStart=t.selectionEnd=p+e.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function insertLine(t,e){const p=t.selectionStart,i=t.value,s=i.lastIndexOf(`
2
- `,p-1)+1,n=i.indexOf(`
3
- `,s),l=i.substring(s,n===-1?i.length:n);if(l.startsWith(e)){const r=n===-1?"":i.substring(n);t.value=i.substring(0,s)+l.substring(e.length)+r,t.selectionStart=t.selectionEnd=Math.max(s,p-e.length)}else t.value=i.substring(0,s)+e+i.substring(s),t.selectionStart=t.selectionEnd=p+e.length;t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}const B=[{category:"Entrance"},{label:"Reveal (fade)",snippet:t=>`[reveal animation="fade"]
1
+ function ne(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H7V5zM7 11H15a3 3 0 0 1 0 6H7V11z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("italic",{viewBox:"0 0 24 24",path:"M11 5h4M9 19h4M13 5l-2 14",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("strikethrough",{viewBox:"0 0 24 24",path:"M16 4H9a3 3 0 0 0 0 6h6a3 3 0 0 1 0 6H6M3 12h18",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("quote",{viewBox:"0 0 24 24",path:"M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1zM15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("eye",{viewBox:"0 0 24 24",path:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("expand",{viewBox:"0 0 24 24",path:"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("columns",{viewBox:"0 0 24 24",path:"M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM12 4v16",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("card",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M3 9h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("help-circle",{viewBox:"0 0 24 24",path:"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 17h.01M12 13a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("spacer-insert",{viewBox:"0 0 24 24",paths:["M3 8h18","M3 16h18","M12 8v8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("icon-pick",{viewBox:"0 0 24 24",paths:["M4 4h6v6H4z","M14 4h6v6h-6z","M4 14h6v6H4z","M14 14h6v6h-6z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("btn-insert",{viewBox:"0 0 24 24",paths:["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z","M8 12h8M12 9v6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("link-shortcode",{viewBox:"0 0 24 24",paths:["M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71","M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("layout-list",{viewBox:"0 0 24 24",paths:["M3 5h18M3 9h18","M3 14h4v6H3zM9 14h12M9 17h8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("sparkles",{viewBox:"0 0 24 24",paths:["M12 3L13.5 8.5H19L14.5 11.5L16 17L12 14L8 17L9.5 11.5L5 8.5H10.5L12 3Z","M19 3L19.7 5.3H22L20.2 6.6L20.9 9L19 7.7L17.1 9L17.8 6.6L16 5.3H18.3L19 3Z","M5 13L5.5 14.7H7L5.8 15.5L6.3 17.2L5 16.3L3.7 17.2L4.2 15.5L3 14.7H4.5L5 13Z"],stroke:"currentColor",fill:"none",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("accordion-insert",{viewBox:"0 0 24 24",paths:["M3 4h18","M3 8h18","M8 11l4 4 4-4","M3 16h18","M3 20h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("hero",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5z","M7 8h10M7 11h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("text-style",{viewBox:"0 0 24 24",paths:["M4 7V5h16v2","M9 19h6","M12 5v14","M5 12h14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"})}export function wrapSelection(t,e,b){const l=t.selectionStart,c=t.selectionEnd,o=t.value,r=o.substring(l,c);r?(t.value=o.substring(0,l)+e+r+b+o.substring(c),t.selectionStart=l+e.length,t.selectionEnd=c+e.length):(t.value=o.substring(0,l)+e+b+o.substring(l),t.selectionStart=t.selectionEnd=l+e.length),t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function insertAtCursor(t,e){const b=t.selectionStart,l=t.value;t.value=l.substring(0,b)+e+l.substring(b),t.selectionStart=t.selectionEnd=b+e.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}export function insertLine(t,e){const b=t.selectionStart,l=t.value,c=l.lastIndexOf(`
2
+ `,b-1)+1,o=l.indexOf(`
3
+ `,c),r=l.substring(c,o===-1?l.length:o);if(r.startsWith(e)){const i=o===-1?"":l.substring(o);t.value=l.substring(0,c)+r.substring(e.length)+i,t.selectionStart=t.selectionEnd=Math.max(c,b-e.length)}else t.value=l.substring(0,c)+e+l.substring(c),t.selectionStart=t.selectionEnd=b+e.length;t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}const oe=[{category:"Entrance"},{label:"Reveal (fade)",snippet:t=>`[reveal animation="fade"]
4
4
  ${t||"Content"}
5
5
  [/reveal]`},{label:"Reveal (slide up)",snippet:t=>`[reveal animation="slide-up"]
6
6
  ${t||"Content"}
@@ -29,12 +29,12 @@ ${t||"Content"}
29
29
  [/firework]`},{label:"Fireworks show",snippet:()=>`[fireworks]
30
30
  [firework type="burst" colour="rainbow" /]
31
31
  [firework type="sparkle" colour="primary" /]
32
- [/fireworks]`,insert:!0},{label:"Celebrate",snippet:()=>'[celebrate theme="auto" intensity="medium" /]',insert:!0}];function N(t,e){const p=document.querySelector(".editor-effects-dropdown-menu");if(p){p.remove();return}const i=document.createElement("div");i.className="editor-effects-dropdown-menu",B.forEach(function(r){if(r.category){const d=document.createElement("div");d.className="editor-effects-category",d.textContent=r.category,i.appendChild(d)}else{const d=document.createElement("button");d.type="button",d.className="editor-effects-item",d.textContent=r.label,d.addEventListener("click",function(){if(i.remove(),r.insert)insertAtCursor(t,r.snippet(""));else{const c=t.selectionStart,h=t.selectionEnd,o=t.value.substring(c,h),a=r.snippet(o);t.value=t.value.substring(0,c)+a+t.value.substring(h),t.selectionStart=c,t.selectionEnd=c+a.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}}),i.appendChild(d)}});const s=e.getBoundingClientRect(),n=e.closest(".editor-toolbar").getBoundingClientRect();i.style.top=s.bottom-n.top+4+"px",i.style.left=s.left-n.left+"px",e.closest(".editor-toolbar").appendChild(i);function l(r){!i.contains(r.target)&&r.target!==e&&(i.remove(),document.removeEventListener("click",l,!0))}setTimeout(function(){document.addEventListener("click",l,!0)},0)}const L=["activity","airpods","airport","alert-circle","alert-warning","ambulance","angry","annoyed","apartment","arch","archive","arrow-down","arrow-down-left","arrow-down-right","arrow-left","arrow-right","arrow-up","arrow-up-left","arrow-up-right","astonished","at-sign","attachment","award","badge","ban","bandage","bank","banknote","barbell","barcode","barn","baseball","basketball","battery","battery-charging","bauble","bell","bell-off","bells","bicycle","bitcoin","blood-drop","blush","bold","bone","book","book-closed","book-open","bookmark","bookmark-filled","bowling","box","boxing-glove","brain","bridge","briefcase","building","bus","cabin","cake","calculator","calendar","camera","camera-off","candy-cane","capsule","car","cart","cart-add","cash","cast","castle","chart-area","chart-bar","chart-bar-horizontal","chart-candlestick","chart-line","chart-pie","chat","chat-alt","check","check-circle","check-circle-filled","check-square","chevron-down","chevron-left","chevron-right","chevron-up","chevrons-down","chevrons-left","chevrons-right","chevrons-up","church","circle","circle-filled","clear-format","clipboard","clipboard-check","clipboard-list","clock","close","cloud","cloud-download","cloud-drizzle","cloud-lightning","cloud-off","cloud-rain","cloud-sun","cloud-upload","code","code-block","code-inline","cog","coins","columns","comment","compass","component","confused","cool","copy","corner-down-left","corner-down-right","corner-up-left","corner-up-right","court","cpu","credit-card","crown","crutch","cry","currency-dollar","currency-euro","currency-pound","cycling","database","dead","desktop","disappointed","dna","document","document-add","document-check","document-remove","document-text","dollar-sign","dome","dot","dots-horizontal","dots-vertical","download","droplet","droplets","dumbbell","edit","embed","emoji-happy","emoji-sad","euro-sign","exclamation","expand","expressionless","external-link","eye","eye-medical","eye-off","factory","fast-forward","feather","file-code","file-text","file-zip","fill","film","filter","fire","first-aid","fishing","flag","fog","folder","folder-add","folder-minus","folder-open","folder-plus","folder-remove","football","fortress","fuel","gamepad","garage","gauge","gift","git-branch","github","globe","golf","grid","grin","growth","hard-drive","hash","haze","heading-1","heading-2","heading-3","headphones","heart","heart-eyes","heart-filled","heart-pulse","heartbeat","help-circle","holly","home","hospital","hotel","house","image","image-add","images","inbox","indent","info","info-filled","investment","invoice","italic","joy","joystick","key","kettlebell","keyboard","laptop","laugh","layers","layout","library","lighthouse","lightning","link","link-2","link-add","linkedin","list","list-bullet","list-numbered","loader","loading","lock","log-in","log-out","lungs","mail","mail-open","map","map-pin","mask","maximize","medal","medical-cross","menu","menu-alt","message-circle","message-square","mic","mic-off","microscope","minimize","minus","minus-circle","minus-square","monitor","monument","moon","moon-star","more-horizontal","more-vertical","mosque","motorcycle","mountain","mouse","mouse-pointer","move","museum","music","nerd","neutral","notification","obelisk","office","outdent","package","palette","panel-bottom","panel-left","panel-right","panel-top","paperclip","parking","pause","pause-filled","percent","phone","phone-call","phone-incoming","phone-off","phone-outgoing","piggy-bank","pill","pill-bottle","pin","play","play-circle","play-filled","plug","plus","plus-circle","plus-square","podium","pound-sign","printer","pulse","pyramid","qrcode","question","quote","racket","radio","rage","rain","rainbow","receipt","redo","refresh","refresh-cw","reindeer","rewind","road","rotate-ccw","rotate-cw","router","rss","running","sad","safe","save","scale","scale-weight","school","search","send","server","settings","share","share-2","share-alt","shield","shield-alert","shield-check","shield-x","shipping","shocked","shopping-bag","shrink","sick","sidebar-left","sidebar-right","silly","skate","ski","skip-back","skip-forward","skyscraper","sleepy","sleigh","sliders","smartphone","smartwatch","smile","snow","snowflake","snowman","sob","soccer","sort","sparkles","speaker","spinner","square","stadium","star","star-decoration","star-eyes","star-filled","stethoscope","stop","stop-filled","stopwatch","store","strikethrough","sun","sunrise","sunset","surfboard","surprised","swimming","sync","syringe","tablet","tablet-smartphone","tag","tags","target","taxi","temple","tennis","tent","terminal","test-tube","text-center","text-left","text-right","thermometer","thermometer-medical","thermometer-sun","thinking","thumb-down","thumb-up","tongue","tool","tooth","tower","train-station","trash","tree","trending-down","trending-neutral","trending-up","trophy","truck","tv","tv-minimal","twitter","type","umbrella","underline","undo","university","unlink","unlock","upload","usb","user","user-add","user-check","user-group","user-plus","user-remove","users","vaccine","van","vault","video","video-off","volleyball","volume","volume-down","volume-mute","volume-off","volume-up","wallet","warehouse","warning","warning-filled","watch","webcam","wheelchair","whistle","wifi","wifi-off","wind","windmill","wink","wreath","x","x-circle","x-circle-filled","yoga","youtube","zany","zap"];function H(t,e,p){const i=document.querySelector(".editor-spacer-picker");if(i){i.remove();return}const s=document.createElement("div");s.className="editor-spacer-picker";const n=document.createElement("div");n.className="editor-spacer-picker-label",n.textContent="Spacer height",s.appendChild(n);const l=document.createElement("div");l.className="editor-spacer-picker-row";const r=document.createElement("input");r.type="range",r.className="editor-spacer-slider",r.min="4",r.max="200",r.step="4",r.value=p;const d=document.createElement("span");d.className="editor-spacer-slider-value",d.textContent=p+"px",r.addEventListener("input",function(){d.textContent=this.value+"px"}),l.appendChild(r),l.appendChild(d),s.appendChild(l);const c=document.createElement("button");c.type="button",c.className="btn btn-primary btn-sm editor-spacer-insert-btn",c.textContent="Insert",s.appendChild(c);function h(b){!s.contains(b.target)&&b.target!==e&&(s.remove(),document.removeEventListener("click",h,!0))}c.addEventListener("click",function(){s.remove(),document.removeEventListener("click",h,!0),insertAtCursor(t,`[spacer size="${r.value}" /]
33
- `)});const o=e.getBoundingClientRect(),a=e.closest(".editor-toolbar").getBoundingClientRect();s.style.top=o.bottom-a.top+4+"px";const u=o.left-a.left;s.style.left=Math.min(u,a.width-240-8)+"px",e.closest(".editor-toolbar").appendChild(s),setTimeout(function(){document.addEventListener("click",h,!0)},0)}function A(t,e){const p=document.querySelector(".editor-icon-picker");if(p){p.remove();return}const i=document.createElement("div");i.className="editor-icon-picker";const s=document.createElement("input");s.type="text",s.className="form-input editor-icon-picker-search",s.placeholder="Search icons\u2026",i.appendChild(s);const n=document.createElement("div");n.className="editor-icon-picker-size-row";const l=document.createElement("label");l.textContent="Size (px)";const r=document.createElement("input");r.type="number",r.className="form-input editor-icon-picker-size",r.placeholder="default",r.min="8",r.max="256",n.appendChild(l),n.appendChild(r),i.appendChild(n);const d=document.createElement("div");d.className="editor-icon-picker-grid",i.appendChild(d);function c(g){!i.contains(g.target)&&g.target!==e&&(i.remove(),document.removeEventListener("click",c,!0))}function h(g){d.textContent="";const k=g?L.filter(f=>f.includes(g.toLowerCase())):L;if(k.length===0){const f=document.createElement("div");f.className="editor-icon-picker-empty",f.textContent="No icons found",d.appendChild(f);return}k.forEach(function(f){const v=document.createElement("button");v.type="button",v.className="editor-icon-picker-item";const w=document.createElement("span");w.setAttribute("data-icon",f);const y=document.createElement("span");y.textContent=f,v.appendChild(w),v.appendChild(y),v.addEventListener("click",function(){i.remove(),document.removeEventListener("click",c,!0);const C=r.value.trim(),M=C?`[icon name="${f}" size="${C}" /]`:`[icon name="${f}" /]`;insertAtCursor(t,M)}),d.appendChild(v)}),Domma.icons.scan(d)}h(""),s.addEventListener("input",function(){h(this.value.trim())});const o=e.getBoundingClientRect(),a=e.closest(".editor-toolbar").getBoundingClientRect();i.style.top=o.bottom-a.top+4+"px";const u=o.left-a.left,b=320,m=a.width;i.style.left=Math.min(u,m-b-8)+"px",e.closest(".editor-toolbar").appendChild(i),requestAnimationFrame(function(){s.focus()}),setTimeout(function(){document.addEventListener("click",c,!0)},0)}function j(t,e,p,i){const s=document.querySelector(".editor-toolbar-dropdown");if(s){s.remove();return}const n=document.createElement("div");n.className="editor-toolbar-dropdown",p.forEach(function(h){const o=document.createElement("button");if(o.type="button",o.className="editor-toolbar-dropdown-item",h.icon){const u=document.createElement("span");u.setAttribute("data-icon",h.icon),o.appendChild(u)}const a=document.createElement("span");a.textContent=h.label,o.appendChild(a),o.addEventListener("click",function(){n.remove(),document.removeEventListener("click",c,!0),x(h.action,t,e,i)}),n.appendChild(o)});const l=e.getBoundingClientRect(),r=e.closest(".editor-toolbar").getBoundingClientRect();n.style.top=l.bottom-r.top+4+"px";const d=l.left-r.left;n.style.left=Math.min(d,r.width-180-8)+"px",e.closest(".editor-toolbar").appendChild(n),Domma.icons.scan(n);function c(h){!n.contains(h.target)&&h.target!==e&&(n.remove(),document.removeEventListener("click",c,!0))}setTimeout(function(){document.addEventListener("click",c,!0)},0)}function x(t,e,p,i){const{spacerDefault:s,handlers:n}=i;if(typeof t=="function")t(e);else if(t==="button")if(n.button)n.button(e);else{const l=e.selectionStart,r=e.selectionEnd,c=`[button href="" variant="primary"]${e.value.substring(l,r)||"Click me"}[/button]`;e.value=e.value.substring(0,l)+c+e.value.substring(r),e.selectionStart=e.selectionEnd=l+14,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="linksc")if(n.linksc)n.linksc(e);else{const l=e.selectionStart,r=e.selectionEnd,c=`[link href=""]${e.value.substring(l,r)||"Link text"}[/link]`;e.value=e.value.substring(0,l)+c+e.value.substring(r),e.selectionStart=e.selectionEnd=l+12,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="link")n.link&&n.link(e);else if(t==="image")n.image&&n.image(e);else if(t==="card")if(n.card)n.card(e);else{const l=e.selectionStart,r=e.selectionEnd,c=`[card title="Card Title"]
34
- ${e.value.substring(l,r)||"Content here"}
35
- [/card]`;e.value=e.value.substring(0,l)+c+e.value.substring(r),e.selectionStart=l+13,e.selectionEnd=l+23,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="hero"){const l=e.selectionStart,r=e.selectionEnd,c=`[hero title="Hero Title" tagline="A short tagline" size="lg" variant="gradient-blue"]
36
- ${e.value.substring(l,r)||"Optional body content here."}
37
- [/hero]`;e.value=e.value.substring(0,l)+c+e.value.substring(r),e.selectionStart=e.selectionEnd=l+c.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="grid")if(n.grid)n.grid(e);else{const l=e.selectionStart,r=`[grid cols="2" gap="4"]
32
+ [/fireworks]`,insert:!0},{label:"Celebrate",snippet:()=>'[celebrate theme="auto" intensity="medium" /]',insert:!0}];function ie(t,e){const b=document.querySelector(".editor-effects-dropdown-menu");if(b){b.remove();return}const l=document.createElement("div");l.className="editor-effects-dropdown-menu",oe.forEach(function(i){if(i.category){const u=document.createElement("div");u.className="editor-effects-category",u.textContent=i.category,l.appendChild(u)}else{const u=document.createElement("button");u.type="button",u.className="editor-effects-item",u.textContent=i.label,u.addEventListener("click",function(){if(l.remove(),i.insert)insertAtCursor(t,i.snippet(""));else{const a=t.selectionStart,f=t.selectionEnd,n=t.value.substring(a,f),s=i.snippet(n);t.value=t.value.substring(0,a)+s+t.value.substring(f),t.selectionStart=a,t.selectionEnd=a+s.length,t.dispatchEvent(new Event("input",{bubbles:!0})),t.focus()}}),l.appendChild(u)}});const c=e.getBoundingClientRect(),o=e.closest(".editor-toolbar").getBoundingClientRect();l.style.top=c.bottom-o.top+4+"px",l.style.left=c.left-o.left+"px",e.closest(".editor-toolbar").appendChild(l);function r(i){!l.contains(i.target)&&i.target!==e&&(l.remove(),document.removeEventListener("click",r,!0))}setTimeout(function(){document.addEventListener("click",r,!0)},0)}const G=["activity","airpods","airport","alert-circle","alert-warning","ambulance","angry","annoyed","apartment","arch","archive","arrow-down","arrow-down-left","arrow-down-right","arrow-left","arrow-right","arrow-up","arrow-up-left","arrow-up-right","astonished","at-sign","attachment","award","badge","ban","bandage","bank","banknote","barbell","barcode","barn","baseball","basketball","battery","battery-charging","bauble","bell","bell-off","bells","bicycle","bitcoin","blood-drop","blush","bold","bone","book","book-closed","book-open","bookmark","bookmark-filled","bowling","box","boxing-glove","brain","bridge","briefcase","building","bus","cabin","cake","calculator","calendar","camera","camera-off","candy-cane","capsule","car","cart","cart-add","cash","cast","castle","chart-area","chart-bar","chart-bar-horizontal","chart-candlestick","chart-line","chart-pie","chat","chat-alt","check","check-circle","check-circle-filled","check-square","chevron-down","chevron-left","chevron-right","chevron-up","chevrons-down","chevrons-left","chevrons-right","chevrons-up","church","circle","circle-filled","clear-format","clipboard","clipboard-check","clipboard-list","clock","close","cloud","cloud-download","cloud-drizzle","cloud-lightning","cloud-off","cloud-rain","cloud-sun","cloud-upload","code","code-block","code-inline","cog","coins","columns","comment","compass","component","confused","cool","copy","corner-down-left","corner-down-right","corner-up-left","corner-up-right","court","cpu","credit-card","crown","crutch","cry","currency-dollar","currency-euro","currency-pound","cycling","database","dead","desktop","disappointed","dna","document","document-add","document-check","document-remove","document-text","dollar-sign","dome","dot","dots-horizontal","dots-vertical","download","droplet","droplets","dumbbell","edit","embed","emoji-happy","emoji-sad","euro-sign","exclamation","expand","expressionless","external-link","eye","eye-medical","eye-off","factory","fast-forward","feather","file-code","file-text","file-zip","fill","film","filter","fire","first-aid","fishing","flag","fog","folder","folder-add","folder-minus","folder-open","folder-plus","folder-remove","football","fortress","fuel","gamepad","garage","gauge","gift","git-branch","github","globe","golf","grid","grin","growth","hard-drive","hash","haze","heading-1","heading-2","heading-3","headphones","heart","heart-eyes","heart-filled","heart-pulse","heartbeat","help-circle","holly","home","hospital","hotel","house","image","image-add","images","inbox","indent","info","info-filled","investment","invoice","italic","joy","joystick","key","kettlebell","keyboard","laptop","laugh","layers","layout","library","lighthouse","lightning","link","link-2","link-add","linkedin","list","list-bullet","list-numbered","loader","loading","lock","log-in","log-out","lungs","mail","mail-open","map","map-pin","mask","maximize","medal","medical-cross","menu","menu-alt","message-circle","message-square","mic","mic-off","microscope","minimize","minus","minus-circle","minus-square","monitor","monument","moon","moon-star","more-horizontal","more-vertical","mosque","motorcycle","mountain","mouse","mouse-pointer","move","museum","music","nerd","neutral","notification","obelisk","office","outdent","package","palette","panel-bottom","panel-left","panel-right","panel-top","paperclip","parking","pause","pause-filled","percent","phone","phone-call","phone-incoming","phone-off","phone-outgoing","piggy-bank","pill","pill-bottle","pin","play","play-circle","play-filled","plug","plus","plus-circle","plus-square","podium","pound-sign","printer","pulse","pyramid","qrcode","question","quote","racket","radio","rage","rain","rainbow","receipt","redo","refresh","refresh-cw","reindeer","rewind","road","rotate-ccw","rotate-cw","router","rss","running","sad","safe","save","scale","scale-weight","school","search","send","server","settings","share","share-2","share-alt","shield","shield-alert","shield-check","shield-x","shipping","shocked","shopping-bag","shrink","sick","sidebar-left","sidebar-right","silly","skate","ski","skip-back","skip-forward","skyscraper","sleepy","sleigh","sliders","smartphone","smartwatch","smile","snow","snowflake","snowman","sob","soccer","sort","sparkles","speaker","spinner","square","stadium","star","star-decoration","star-eyes","star-filled","stethoscope","stop","stop-filled","stopwatch","store","strikethrough","sun","sunrise","sunset","surfboard","surprised","swimming","sync","syringe","tablet","tablet-smartphone","tag","tags","target","taxi","temple","tennis","tent","terminal","test-tube","text-center","text-left","text-right","thermometer","thermometer-medical","thermometer-sun","thinking","thumb-down","thumb-up","tongue","tool","tooth","tower","train-station","trash","tree","trending-down","trending-neutral","trending-up","trophy","truck","tv","tv-minimal","twitter","type","umbrella","underline","undo","university","unlink","unlock","upload","usb","user","user-add","user-check","user-group","user-plus","user-remove","users","vaccine","van","vault","video","video-off","volleyball","volume","volume-down","volume-mute","volume-off","volume-up","wallet","warehouse","warning","warning-filled","watch","webcam","wheelchair","whistle","wifi","wifi-off","wind","windmill","wink","wreath","x","x-circle","x-circle-filled","yoga","youtube","zany","zap"];function le(t,e,b){const l=document.querySelector(".editor-spacer-picker");if(l){l.remove();return}const c=document.createElement("div");c.className="editor-spacer-picker";const o=document.createElement("div");o.className="editor-spacer-picker-label",o.textContent="Spacer height",c.appendChild(o);const r=document.createElement("div");r.className="editor-spacer-picker-row";const i=document.createElement("input");i.type="range",i.className="editor-spacer-slider",i.min="4",i.max="200",i.step="4",i.value=b;const u=document.createElement("span");u.className="editor-spacer-slider-value",u.textContent=b+"px",i.addEventListener("input",function(){u.textContent=this.value+"px"}),r.appendChild(i),r.appendChild(u),c.appendChild(r);const a=document.createElement("button");a.type="button",a.className="btn btn-primary btn-sm editor-spacer-insert-btn",a.textContent="Insert",c.appendChild(a);function f(g){!c.contains(g.target)&&g.target!==e&&(c.remove(),document.removeEventListener("click",f,!0))}a.addEventListener("click",function(){c.remove(),document.removeEventListener("click",f,!0),insertAtCursor(t,`[spacer size="${i.value}" /]
33
+ `)});const n=e.getBoundingClientRect(),s=e.closest(".editor-toolbar").getBoundingClientRect();c.style.top=n.bottom-s.top+4+"px";const d=n.left-s.left;c.style.left=Math.min(d,s.width-240-8)+"px",e.closest(".editor-toolbar").appendChild(c),setTimeout(function(){document.addEventListener("click",f,!0)},0)}function re(t,e){const b=document.querySelector(".editor-icon-picker");if(b){b.remove();return}const l=document.createElement("div");l.className="editor-icon-picker";const c=document.createElement("input");c.type="text",c.className="form-input editor-icon-picker-search",c.placeholder="Search icons\u2026",l.appendChild(c);const o=document.createElement("div");o.className="editor-icon-picker-size-row";const r=document.createElement("label");r.textContent="Size (px)";const i=document.createElement("input");i.type="number",i.className="form-input editor-icon-picker-size",i.placeholder="default",i.min="8",i.max="256",o.appendChild(r),o.appendChild(i),l.appendChild(o);const u=document.createElement("div");u.className="editor-icon-picker-grid",l.appendChild(u);function a(y){!l.contains(y.target)&&y.target!==e&&(l.remove(),document.removeEventListener("click",a,!0))}function f(y){u.textContent="";const C=y?G.filter(w=>w.includes(y.toLowerCase())):G;if(C.length===0){const w=document.createElement("div");w.className="editor-icon-picker-empty",w.textContent="No icons found",u.appendChild(w);return}C.forEach(function(w){const k=document.createElement("button");k.type="button",k.className="editor-icon-picker-item";const P=document.createElement("span");P.setAttribute("data-icon",w);const L=document.createElement("span");L.textContent=w,k.appendChild(P),k.appendChild(L),k.addEventListener("click",function(){l.remove(),document.removeEventListener("click",a,!0);const V=i.value.trim(),A=V?`[icon name="${w}" size="${V}" /]`:`[icon name="${w}" /]`;insertAtCursor(t,A)}),u.appendChild(k)}),Domma.icons.scan(u)}f(""),c.addEventListener("input",function(){f(this.value.trim())});const n=e.getBoundingClientRect(),s=e.closest(".editor-toolbar").getBoundingClientRect();l.style.top=n.bottom-s.top+4+"px";const d=n.left-s.left,g=320,m=s.width;l.style.left=Math.min(d,m-g-8)+"px",e.closest(".editor-toolbar").appendChild(l),requestAnimationFrame(function(){c.focus()}),setTimeout(function(){document.addEventListener("click",a,!0)},0)}function se(t,e,b,l){const c=document.querySelector(".editor-toolbar-dropdown");if(c){c.remove();return}const o=document.createElement("div");o.className="editor-toolbar-dropdown",b.forEach(function(f){const n=document.createElement("button");if(n.type="button",n.className="editor-toolbar-dropdown-item",f.icon){const d=document.createElement("span");d.setAttribute("data-icon",f.icon),n.appendChild(d)}const s=document.createElement("span");s.textContent=f.label,n.appendChild(s),n.addEventListener("click",function(){o.remove(),document.removeEventListener("click",a,!0),K(f.action,t,e,l)}),o.appendChild(n)});const r=e.getBoundingClientRect(),i=e.closest(".editor-toolbar").getBoundingClientRect();o.style.top=r.bottom-i.top+4+"px";const u=r.left-i.left;o.style.left=Math.min(u,i.width-180-8)+"px",e.closest(".editor-toolbar").appendChild(o),Domma.icons.scan(o);function a(f){!o.contains(f.target)&&f.target!==e&&(o.remove(),document.removeEventListener("click",a,!0))}setTimeout(function(){document.addEventListener("click",a,!0)},0)}function K(t,e,b,l){const{spacerDefault:c,handlers:o}=l;if(typeof t=="function")t(e);else if(t==="block")if(o.block)o.block(e);else{const r=e.selectionStart,i='[block template="" /]';e.value=e.value.substring(0,r)+i+e.value.substring(r),e.selectionStart=e.selectionEnd=r+17,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="button")if(o.button)o.button(e);else{const r=e.selectionStart,i=e.selectionEnd,a=`[button href="" variant="primary"]${e.value.substring(r,i)||"Click me"}[/button]`;e.value=e.value.substring(0,r)+a+e.value.substring(i),e.selectionStart=e.selectionEnd=r+14,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="linksc")if(o.linksc)o.linksc(e);else{const r=e.selectionStart,i=e.selectionEnd,a=`[link href=""]${e.value.substring(r,i)||"Link text"}[/link]`;e.value=e.value.substring(0,r)+a+e.value.substring(i),e.selectionStart=e.selectionEnd=r+12,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="link")o.link&&o.link(e);else if(t==="image")o.image&&o.image(e);else if(t==="card")if(o.card)o.card(e);else{const r=e.selectionStart,i=e.selectionEnd,a=`[card title="Card Title"]
34
+ ${e.value.substring(r,i)||"Content here"}
35
+ [/card]`;e.value=e.value.substring(0,r)+a+e.value.substring(i),e.selectionStart=r+13,e.selectionEnd=r+23,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="hero"){const r=e.selectionStart,i=e.selectionEnd,a=`[hero title="Hero Title" tagline="A short tagline" size="lg" variant="gradient-blue"]
36
+ ${e.value.substring(r,i)||"Optional body content here."}
37
+ [/hero]`;e.value=e.value.substring(0,r)+a+e.value.substring(i),e.selectionStart=e.selectionEnd=r+a.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="grid")if(o.grid)o.grid(e);else{const r=e.selectionStart,i=`[grid cols="2" gap="4"]
38
38
  [col]
39
39
  Column 1
40
40
  [/col]
@@ -42,7 +42,7 @@ Column 1
42
42
  Column 2
43
43
  [/col]
44
44
  [/grid]
45
- `;e.value=e.value.substring(0,l)+r+e.value.substring(l),e.selectionStart=e.selectionEnd=l+r.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="badge"){const l=e.selectionStart,r=e.selectionEnd,c=`[badge variant="primary"]${e.value.substring(l,r)||"New"}[/badge]`;e.value=e.value.substring(0,l)+c+e.value.substring(r),e.selectionStart=l+16,e.selectionEnd=l+23,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="timeline"){const l=e.selectionStart,r=`[timeline layout="vertical"]
45
+ `;e.value=e.value.substring(0,r)+i+e.value.substring(r),e.selectionStart=e.selectionEnd=r+i.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="badge"){const r=e.selectionStart,i=e.selectionEnd,a=`[badge variant="primary"]${e.value.substring(r,i)||"New"}[/badge]`;e.value=e.value.substring(0,r)+a+e.value.substring(i),e.selectionStart=r+16,e.selectionEnd=r+23,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="timeline"){const r=e.selectionStart,i=`[timeline layout="vertical"]
46
46
  [event title="First Event" date="${new Date().toISOString().slice(0,10)}" status="completed"]
47
47
  Describe this event.
48
48
  [/event]
@@ -50,11 +50,11 @@ Describe this event.
50
50
  Describe this event.
51
51
  [/event]
52
52
  [/timeline]
53
- `;e.value=e.value.substring(0,l)+r+e.value.substring(l),e.selectionStart=e.selectionEnd=l+r.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="effects")n.effects?n.effects(e):N(e,p);else if(t==="spacerpick")H(e,p,s);else if(t==="iconpick")A(e,p);else if(t==="collection")n.collection?n.collection(e):insertAtCursor(e,'[collection slug="" display="table" /]');else if(t==="view")n.view&&n.view(e);else if(t==="cta")n.cta&&n.cta(e);else if(t==="form")n.form?n.form(e):insertAtCursor(e,'[form slug="" /]');else if(t==="tabs")n.tabs&&n.tabs(e);else if(t==="accordion")if(n.accordion)n.accordion(e);else{const l=e.selectionStart,r=`[accordion]
53
+ `;e.value=e.value.substring(0,r)+i+e.value.substring(r),e.selectionStart=e.selectionEnd=r+i.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="effects")o.effects?o.effects(e):ie(e,b);else if(t==="spacerpick")le(e,b,c);else if(t==="iconpick")re(e,b);else if(t==="collection")o.collection?o.collection(e):insertAtCursor(e,'[collection slug="" display="table" /]');else if(t==="view")o.view&&o.view(e);else if(t==="cta")o.cta&&o.cta(e);else if(t==="form")o.form?o.form(e):insertAtCursor(e,'[form slug="" /]');else if(t==="tabs")o.tabs&&o.tabs(e);else if(t==="accordion")if(o.accordion)o.accordion(e);else{const r=e.selectionStart,i=`[accordion]
54
54
  [item title="Item 1"]Content here.[/item]
55
55
  [item title="Item 2"]Content here.[/item]
56
56
  [/accordion]
57
- `;e.value=e.value.substring(0,l)+r+e.value.substring(l),e.selectionStart=e.selectionEnd=l+r.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else t==="help"&&n.help&&n.help(e)}const S=[{icon:"bold",title:"Bold (Ctrl+B)",action:t=>wrapSelection(t,"**","**")},{icon:"italic",title:"Italic (Ctrl+I)",action:t=>wrapSelection(t,"_","_")},{icon:"strikethrough",title:"Strikethrough",action:t=>wrapSelection(t,"~~","~~")},"|",{type:"dropdown",icon:"heading-1",title:"Headings",items:[{label:"Heading 1",icon:"heading-1",action:t=>insertLine(t,"# ")},{label:"Heading 2",icon:"heading-2",action:t=>insertLine(t,"## ")},{label:"Heading 3",icon:"heading-3",action:t=>insertLine(t,"### ")}]},"|",{icon:"list-bullet",title:"Bullet list",action:t=>insertLine(t,"- ")},{icon:"list-numbered",title:"Numbered list",action:t=>insertLine(t,"1. ")},"|",{type:"dropdown",icon:"quote",title:"Paragraph",items:[{label:"Blockquote",icon:"quote",action:t=>insertLine(t,"> ")},{label:"Horizontal rule",icon:"minus-circle",action:t=>insertAtCursor(t,`
57
+ `;e.value=e.value.substring(0,r)+i+e.value.substring(r),e.selectionStart=e.selectionEnd=r+i.length,e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}else if(t==="text"){let n=function(h,p){const v=document.createElement("div"),x=document.createElement("label");return x.style.cssText=a,x.textContent=h,v.appendChild(x),v.appendChild(p),v},s=function(h){const p=document.createElement("select");return p.style.cssText=f,[["","\u2014 default \u2014"],...h].forEach(([v,x])=>{const W=document.createElement("option");W.value=v,W.textContent=x,p.appendChild(W)}),p},d=function(h,p){const v=document.createElement("input");return v.type="text",v.placeholder=h||"",v.value=p||"",v.style.cssText=f,v},g=function(h){const p=document.createElement("label");p.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const v=document.createElement("input");v.type="checkbox";const x=document.createElement("span");return x.style.cssText="font-size:.85em;color:var(--dm-text,#eee);",x.textContent=h,p.appendChild(v),p.appendChild(x),{wrap:p,cb:v}},q=function(){const h=[];C.value&&h.push(`font-size:${J[C.value]||C.value}`);const p=parseFloat(w.value);!isNaN(p)&&p>0&&h.push(`font-size:${p}pt`),L.checked?h.push("font-weight:700"):k.value&&h.push(`font-weight:${Q[k.value]||k.value}`),A.checked&&h.push("font-style:italic");const v=R.value.trim();v&&h.push(`color:${U[v]||v}`),S.value&&h.push(`font-family:${Y[S.value]}`),M.value&&h.push(`text-transform:${ee[M.value]}`),z.value&&h.push(`text-decoration:${te[z.value]}`),N.value&&h.push(`letter-spacing:${X[N.value]}`),T.value&&(h.push("display:block"),h.push(`text-align:${T.value}`)),B.value.trim()&&h.push(B.value.trim()),j.style.cssText=h.join(";"),j.textContent=y.value||"Preview text"};const r=e.selectionStart,i=e.selectionEnd,u=e.value.substring(r,i)||"",a="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",f="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;",m=document.createElement("div");m.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;";const y=d("Text to style\u2026",u);m.appendChild(n("Content",y));const C=s([["xs","xs \u2014 0.75rem"],["sm","sm \u2014 0.875rem"],["base","base \u2014 1rem"],["lg","lg \u2014 1.125rem"],["xl","xl \u2014 1.25rem"],["2xl","2xl \u2014 1.5rem"],["3xl","3xl \u2014 1.875rem"],["4xl","4xl \u2014 2.25rem"]]);m.appendChild(n("Size",C));const w=d("e.g. 14 (overrides Size above)");m.appendChild(n("Point Size (pt)",w));const k=s([["thin","Thin (100)"],["light","Light (300)"],["normal","Normal (400)"],["medium","Medium (500)"],["semibold","Semibold (600)"],["bold","Bold (700)"],["extrabold","Extrabold (800)"],["black","Black (900)"]]);m.appendChild(n("Weight",k));const{wrap:P,cb:L}=g("Bold (shorthand \u2014 overrides Weight)");m.appendChild(P);const{wrap:V,cb:A}=g("Italic");m.appendChild(V);const R=d("e.g. primary, #ff0000, rgb(255,0,0)");m.appendChild(n("Colour",R));const S=s([["Georgia","Georgia (serif)"],["Arial","Arial (sans-serif)"],["Verdana","Verdana (sans-serif)"],["Courier New","Courier New (monospace)"],["Times New Roman","Times New Roman (serif)"],["Trebuchet MS","Trebuchet MS (sans-serif)"]]);m.appendChild(n("Font",S));const M=s([["upper","Uppercase"],["lower","Lowercase"],["capitalize","Capitalise"],["none","None"]]);m.appendChild(n("Transform",M));const z=s([["underline","Underline"],["line-through","Line-through"],["none","None"]]);m.appendChild(n("Decoration",z));const N=s([["tight","Tight"],["normal","Normal"],["wide","Wide"],["wider","Wider"]]);m.appendChild(n("Spacing",N));const T=s([["left","Left"],["center","Centre"],["right","Right"],["justify","Justify"]]);m.appendChild(n("Align",T));const B=d("e.g. margin-top:1rem;display:block");m.appendChild(n("Style",B));const D=d("Optional CSS class");m.appendChild(n("CSS Class",D));const O=d("Optional ID");m.appendChild(n("ID",O));const _=document.createElement("div");_.style.cssText="padding:.75rem;background:var(--dm-surface-subtle,#111);border-radius:4px;min-height:2.5rem;display:flex;align-items:center;";const j=document.createElement("span");j.textContent=u||"Preview text",_.appendChild(j),m.appendChild(n("Preview",_));const U={primary:"var(--dm-color-primary)",secondary:"var(--dm-color-secondary)",muted:"var(--dm-text-muted)",danger:"var(--dm-color-danger)",success:"var(--dm-color-success)",warning:"var(--dm-color-warning)",info:"var(--dm-color-info)"},J={xs:".75rem",sm:".875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},Q={thin:"100",light:"300",normal:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},X={tight:"-0.05em",normal:"0em",wide:"0.05em",wider:"0.1em"},Y={Georgia:"Georgia,serif",Arial:"Arial,sans-serif",Verdana:"Verdana,sans-serif","Courier New":"'Courier New',monospace","Times New Roman":"'Times New Roman',serif","Trebuchet MS":"'Trebuchet MS',sans-serif"},ee={upper:"uppercase",lower:"lowercase",capitalize:"capitalize",none:"none"},te={underline:"underline","line-through":"line-through",none:"none"};L.addEventListener("change",()=>{k.disabled=L.checked,L.checked&&(k.value=""),q()}),[C,k,S,M,z,N,T].forEach(h=>{h.addEventListener("change",q)}),[R,y,B,w].forEach(h=>{h.addEventListener("input",q)}),A.addEventListener("change",q);const H=document.createElement("button");H.type="button",H.className="btn btn-primary",H.textContent="Insert",m.appendChild(H);const F=E.modal({title:"Style Text",size:"sm"});F.element.appendChild(m),F.open(),H.addEventListener("click",()=>{const h=y.value;if(!h.trim())return;const p=[];C.value&&p.push(`size="${C.value}"`);const v=parseFloat(w.value);!isNaN(v)&&v>0&&p.push(`point-size="${v}"`),L.checked?p.push("bold"):k.value&&p.push(`weight="${k.value}"`),A.checked&&p.push("italic"),R.value.trim()&&p.push(`color="${R.value.trim()}"`),S.value&&p.push(`font="${S.value}"`),M.value&&p.push(`transform="${M.value}"`),z.value&&p.push(`decoration="${z.value}"`),N.value&&p.push(`spacing="${N.value}"`),T.value&&p.push(`align="${T.value}"`),B.value.trim()&&p.push(`style="${B.value.trim().replace(/"/g,"&quot;")}"`),D.value.trim()&&p.push(`class="${D.value.trim()}"`),O.value.trim()&&p.push(`id="${O.value.trim()}"`);const W=`[text${p.length?" "+p.join(" "):""}]${h}[/text]`;F.close(),insertAtCursor(e,W),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()})}else t==="help"&&o.help&&o.help(e)}const Z=[{icon:"bold",title:"Bold (Ctrl+B)",action:t=>wrapSelection(t,"**","**")},{icon:"italic",title:"Italic (Ctrl+I)",action:t=>wrapSelection(t,"_","_")},{icon:"strikethrough",title:"Strikethrough",action:t=>wrapSelection(t,"~~","~~")},"|",{type:"dropdown",icon:"heading-1",title:"Headings",items:[{label:"Heading 1",icon:"heading-1",action:t=>insertLine(t,"# ")},{label:"Heading 2",icon:"heading-2",action:t=>insertLine(t,"## ")},{label:"Heading 3",icon:"heading-3",action:t=>insertLine(t,"### ")}]},"|",{icon:"list-bullet",title:"Bullet list",action:t=>insertLine(t,"- ")},{icon:"list-numbered",title:"Numbered list",action:t=>insertLine(t,"1. ")},"|",{type:"dropdown",icon:"quote",title:"Paragraph",items:[{label:"Blockquote",icon:"quote",action:t=>insertLine(t,"> ")},{label:"Horizontal rule",icon:"minus-circle",action:t=>insertAtCursor(t,`
58
58
  ---
59
- `)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:t=>wrapSelection(t,"`","`")},{label:"Code block",icon:"code-block",action:t=>wrapSelection(t,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",items:[{label:"Accordion",icon:"accordion-insert",action:"accordion"},{label:"Badge",icon:"badge",action:"badge"},{label:"Button",icon:"btn-insert",action:"button"},{label:"Card",icon:"card",action:"card"},{label:"Collection",icon:"database",action:"collection"},{label:"CTA Button",icon:"mouse-pointer",action:"cta"},{label:"Form",icon:"file-text",action:"form"},{label:"Grid",icon:"columns",action:"grid"},{label:"Hero",icon:"hero",action:"hero"},{label:"Icon",icon:"icon-pick",action:"iconpick"},{label:"Image",icon:"image-add",action:"image"},{label:"Link",icon:"link-shortcode",action:"linksc"},{label:"Spacer",icon:"spacer-insert",action:"spacerpick"},{label:"Tabs",icon:"layout-list",action:"tabs"},{label:"Timeline",icon:"activity",action:"timeline"},{label:"View",icon:"eye",action:"view"}]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(t,e,p={}){z();const i={link:null,image:null,card:null,grid:null,help:null,effects:null,collection:null,view:null,cta:null,form:null,button:null,linksc:null,tabs:null,accordion:null},s=p.spacerDefault??40,n=t.get(0),l=e.get(0);l.textContent="",S.forEach((o,a)=>{if(o==="|"){const u=document.createElement("span");u.className="editor-toolbar-sep",l.appendChild(u)}else{const u=document.createElement("button");u.className=o.type==="dropdown"?"editor-toolbar-btn editor-toolbar-dropdown-trigger":"editor-toolbar-btn",u.setAttribute("data-tooltip",o.title),u.setAttribute("data-idx",String(a)),u.type="button";const b=document.createElement("span");if(b.setAttribute("data-icon",o.icon),u.appendChild(b),o.type==="dropdown"){const m=document.createElement("span");m.className="editor-toolbar-caret",m.textContent="\u25BE",u.appendChild(m)}l.appendChild(u)}});const r=document.createElement("div");r.className="editor-toolbar-right",[{mode:"split",icon:"columns",label:"Split view",active:!0},{mode:"write",icon:"file-text",label:"Write only",active:!1},{mode:"preview",icon:"eye",label:"Preview only",active:!1}].forEach(o=>{const a=document.createElement("button");a.className="editor-view-btn"+(o.active?" active":""),a.setAttribute("data-mode",o.mode),a.setAttribute("data-tooltip",o.label),a.type="button";const u=document.createElement("span");u.setAttribute("data-icon",o.icon),a.appendChild(u),r.appendChild(a)});const d=document.createElement("span");d.className="editor-toolbar-sep",r.appendChild(d);const c=document.createElement("button");c.id="fullscreen-btn",c.className="editor-toolbar-btn",c.setAttribute("data-tooltip","Toggle fullscreen"),c.type="button";const h=document.createElement("span");return h.setAttribute("data-icon","expand"),c.appendChild(h),r.appendChild(c),l.appendChild(r),Domma.icons.scan(),l.querySelectorAll("[data-tooltip]").forEach(o=>{E.tooltip(o,{content:o.getAttribute("data-tooltip"),position:"top"})}),e.on("click",".editor-toolbar-btn[data-idx]",function(){const o=parseInt($(this).data("idx"),10),a=S[o];if(!a||a==="|")return;const u=e.get(0).querySelector(`[data-idx="${o}"]`),b={spacerDefault:s,handlers:i};a.type==="dropdown"?j(n,u,a.items,b):x(a.action,n,u,b)}),t.on("keydown",function(o){const a=o.key.toLowerCase();if(o.ctrlKey||o.metaKey)a==="b"?(o.preventDefault(),wrapSelection(n,"**","**")):a==="i"?(o.preventDefault(),wrapSelection(n,"_","_")):a==="k"&&(o.preventDefault(),i.link&&i.link(n));else if(o.key==="Tab")if(o.preventDefault(),o.shiftKey){const u=n.value.lastIndexOf(`
60
- `,n.selectionStart-1)+1,b=n.value.substring(u),m=b.match(/^ {1,4}/);if(m){const g=n.value.substring(0,u),k=n.value.substring(u+m[0].length);n.value=g+b.substring(m[0].length),n.selectionStart=n.selectionEnd=Math.max(u,n.selectionStart-m[0].length),n.dispatchEvent(new Event("input",{bubbles:!0}))}}else insertAtCursor(n," ")}),{$toolbar:e,onLink(o){i.link=o},onImage(o){i.image=o},onCard(o){i.card=o},onGrid(o){i.grid=o},onHelp(o){i.help=o},onEffects(o){i.effects=o},onCollection(o){i.collection=o},onView(o){i.view=o},onCta(o){i.cta=o},onForm(o){i.form=o},onButton(o){i.button=o},onLinkShortcode(o){i.linksc=o},onTabs(o){i.tabs=o},onAccordion(o){i.accordion=o}}}
59
+ `)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:t=>wrapSelection(t,"`","`")},{label:"Code block",icon:"code-block",action:t=>wrapSelection(t,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",items:[{label:"Accordion",icon:"accordion-insert",action:"accordion"},{label:"Badge",icon:"badge",action:"badge"},{label:"Block",icon:"layout",action:"block"},{label:"Button",icon:"btn-insert",action:"button"},{label:"Card",icon:"card",action:"card"},{label:"Collection",icon:"database",action:"collection"},{label:"CTA Button",icon:"mouse-pointer",action:"cta"},{label:"Form",icon:"file-text",action:"form"},{label:"Grid",icon:"columns",action:"grid"},{label:"Hero",icon:"hero",action:"hero"},{label:"Icon",icon:"icon-pick",action:"iconpick"},{label:"Image",icon:"image-add",action:"image"},{label:"Link",icon:"link-shortcode",action:"linksc"},{label:"Spacer",icon:"spacer-insert",action:"spacerpick"},{label:"Tabs",icon:"layout-list",action:"tabs"},{label:"Text",icon:"text-style",action:"text"},{label:"Timeline",icon:"activity",action:"timeline"},{label:"View",icon:"eye",action:"view"}]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(t,e,b={}){ne();const l={link:null,image:null,card:null,grid:null,help:null,effects:null,collection:null,view:null,cta:null,form:null,button:null,linksc:null,tabs:null,accordion:null},c=b.spacerDefault??40,o=t.get(0),r=e.get(0);r.textContent="",Z.forEach((n,s)=>{if(n==="|"){const d=document.createElement("span");d.className="editor-toolbar-sep",r.appendChild(d)}else{const d=document.createElement("button");d.className=n.type==="dropdown"?"editor-toolbar-btn editor-toolbar-dropdown-trigger":"editor-toolbar-btn",d.setAttribute("data-tooltip",n.title),d.setAttribute("data-idx",String(s)),d.type="button";const g=document.createElement("span");if(g.setAttribute("data-icon",n.icon),d.appendChild(g),n.type==="dropdown"){const m=document.createElement("span");m.className="editor-toolbar-caret",m.textContent="\u25BE",d.appendChild(m)}r.appendChild(d)}});const i=document.createElement("div");i.className="editor-toolbar-right",[{mode:"split",icon:"columns",label:"Split view",active:!0},{mode:"write",icon:"file-text",label:"Write only",active:!1},{mode:"preview",icon:"eye",label:"Preview only",active:!1}].forEach(n=>{const s=document.createElement("button");s.className="editor-view-btn"+(n.active?" active":""),s.setAttribute("data-mode",n.mode),s.setAttribute("data-tooltip",n.label),s.type="button";const d=document.createElement("span");d.setAttribute("data-icon",n.icon),s.appendChild(d),i.appendChild(s)});const u=document.createElement("span");u.className="editor-toolbar-sep",i.appendChild(u);const a=document.createElement("button");a.id="fullscreen-btn",a.className="editor-toolbar-btn",a.setAttribute("data-tooltip","Toggle fullscreen"),a.type="button";const f=document.createElement("span");return f.setAttribute("data-icon","expand"),a.appendChild(f),i.appendChild(a),r.appendChild(i),Domma.icons.scan(),r.querySelectorAll("[data-tooltip]").forEach(n=>{E.tooltip(n,{content:n.getAttribute("data-tooltip"),position:"top"})}),e.on("click",".editor-toolbar-btn[data-idx]",function(){const n=parseInt($(this).data("idx"),10),s=Z[n];if(!s||s==="|")return;const d=e.get(0).querySelector(`[data-idx="${n}"]`),g={spacerDefault:c,handlers:l};s.type==="dropdown"?se(o,d,s.items,g):K(s.action,o,d,g)}),t.on("keydown",function(n){const s=n.key.toLowerCase();if(n.ctrlKey||n.metaKey)s==="b"?(n.preventDefault(),wrapSelection(o,"**","**")):s==="i"?(n.preventDefault(),wrapSelection(o,"_","_")):s==="k"&&(n.preventDefault(),l.link&&l.link(o));else if(n.key==="Tab")if(n.preventDefault(),n.shiftKey){const d=o.value.lastIndexOf(`
60
+ `,o.selectionStart-1)+1,g=o.value.substring(d),m=g.match(/^ {1,4}/);if(m){const y=o.value.substring(0,d),C=o.value.substring(d+m[0].length);o.value=y+g.substring(m[0].length),o.selectionStart=o.selectionEnd=Math.max(d,o.selectionStart-m[0].length),o.dispatchEvent(new Event("input",{bubbles:!0}))}}else insertAtCursor(o," ")}),{$toolbar:e,onLink(n){l.link=n},onImage(n){l.image=n},onCard(n){l.card=n},onGrid(n){l.grid=n},onHelp(n){l.help=n},onEffects(n){l.effects=n},onCollection(n){l.collection=n},onBlock(n){l.block=n},onView(n){l.view=n},onCta(n){l.cta=n},onForm(n){l.form=n},onButton(n){l.button=n},onLinkShortcode(n){l.linksc=n},onTabs(n){l.tabs=n},onAccordion(n){l.accordion=n}}}
@@ -1,3 +1,5 @@
1
- import{api as z}from"../api.js";const Z=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"hidden",label:"Hidden field"}],Q=new Set(["select","radio","checkbox-group"]),ne=["public","subscriber","editor","manager","admin"],$=["create","read","update","delete"];let u=[],w=null,T=!0,q=null;function ee(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}function te(e){return Z.find(t=>t.value===e)?.label||e}function ae(e){const t={...u[e]},n=document.getElementById(`fb-label-${e}`),a=document.getElementById(`fb-name-${e}`),i=document.getElementById(`fb-type-${e}`),p=document.getElementById(`fb-required-${e}`),r=document.getElementById(`fb-placeholder-${e}`),l=document.getElementById(`fb-helper-${e}`);if(n&&(t.label=n.value.trim()||t.label),a&&(t.name=a.value.trim()||t.name),i&&(t.type=i.value||t.type),p&&(t.required=p.checked),r&&(t.placeholder=r.value.trim()),l&&(t.helper=l.value.trim()),Q.has(t.type)){const c=document.getElementById(`fb-options-${e}`);c&&(t.options=c.value.split(`
2
- `).filter(f=>f.trim()).map(f=>{const[g,...m]=f.split(":");return{value:g.trim(),label:m.join(":").trim()||g.trim()}}))}const o=document.getElementById(`fb-span-${e}`);if(document.getElementById(`fb-fullwidth-${e}`)?.checked)t.fullWidth=!0,delete t.span;else{delete t.fullWidth;const c=parseInt(o?.value,10);c>1?t.span=c:delete t.span}return t}function X(){return u.map((e,t)=>ae(t))}function oe(e,t){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px solid var(--border-color,#333);border-radius:8px;margin-bottom:.75rem;overflow:hidden;";const a=document.createElement("div");a.className="fb-field-header",a.style.cssText="display:flex;align-items:center;gap:.5rem;padding:.6rem .75rem;background:var(--card-header-bg,rgba(255,255,255,.03));cursor:pointer;user-select:none;";const i=document.createElement("span");i.textContent="\u283F",i.style.cssText="cursor:grab;opacity:.4;font-size:1.1rem;flex-shrink:0;",n.draggable=!0,i.addEventListener("mousedown",()=>{n.draggable=!0}),n.addEventListener("dragstart",s=>{q=t,s.dataTransfer.effectAllowed="move",n.style.opacity="0.4"}),n.addEventListener("dragend",()=>{n.style.opacity="",document.querySelectorAll(".fb-field-card").forEach(s=>s.classList.remove("fb-drag-over"))}),n.addEventListener("dragover",s=>{s.preventDefault(),s.dataTransfer.dropEffect="move",document.querySelectorAll(".fb-field-card").forEach(y=>y.classList.remove("fb-drag-over")),n.classList.add("fb-drag-over")}),n.addEventListener("dragleave",()=>{n.classList.remove("fb-drag-over")}),n.addEventListener("drop",s=>{if(s.preventDefault(),n.classList.remove("fb-drag-over"),q===null||q===t)return;u=X();const[y]=u.splice(q,1);u.splice(t,0,y),q=null,P(document.getElementById("fields-list"))});const p=document.createElement("span");p.className="fb-field-summary",p.style.cssText="flex:1;font-weight:500;font-size:.9rem;",p.textContent=e.label||"(Untitled field)";const r=document.createElement("span");r.style.cssText="font-size:.75rem;opacity:.5;",r.textContent=te(e.type);const l=document.createElement("span");l.className="fb-field-chevron",l.textContent="\u25BE",l.style.cssText="opacity:.5;transition:transform .2s;";const o=document.createElement("button");o.type="button",o.textContent="\xD7",o.className="btn btn-sm",o.style.cssText="padding:.15rem .45rem;line-height:1;font-size:1rem;opacity:.6;",o.title="Remove field",o.addEventListener("click",s=>{s.stopPropagation(),u.splice(t,1),P(document.getElementById("fields-list"))}),a.appendChild(i),a.appendChild(p),a.appendChild(r),a.appendChild(l),a.appendChild(o);const d=document.createElement("div");d.className="fb-field-body",d.style.cssText="padding:.75rem;display:none;";const c=document.createElement("div");c.style.cssText="display:grid;grid-template-columns:1fr 1fr 1fr;gap:.6rem;margin-bottom:.6rem;";const f=document.createElement("div"),g=document.createElement("label");g.className="form-label",g.textContent="Label";const m=document.createElement("input");m.id=`fb-label-${t}`,m.type="text",m.className="form-input",m.value=e.label||"",m.addEventListener("input",()=>{p.textContent=m.value.trim()||"(Untitled field)";const s=document.getElementById(`fb-name-${t}`);s&&!s.dataset.manual&&(s.value=ee(m.value).replace(/-/g,"_"))}),f.appendChild(g),f.appendChild(m);const L=document.createElement("div"),h=document.createElement("label");h.className="form-label",h.textContent="Name (key)";const v=document.createElement("input");v.id=`fb-name-${t}`,v.type="text",v.className="form-input",v.value=e.name||"",v.addEventListener("input",()=>{v.dataset.manual="1"}),L.appendChild(h),L.appendChild(v);const O=document.createElement("div"),U=document.createElement("label");U.className="form-label",U.textContent="Type";const C=document.createElement("select");C.id=`fb-type-${t}`,C.className="form-input",Z.forEach(s=>{const y=document.createElement("option");y.value=s.value,y.textContent=s.label,s.value===e.type&&(y.selected=!0),C.appendChild(y)}),C.addEventListener("change",()=>{r.textContent=te(C.value);const s=d.querySelector(".fb-options-wrap");s&&(s.style.display=Q.has(C.value)?"":"none")}),O.appendChild(U),O.appendChild(C),c.appendChild(f),c.appendChild(L),c.appendChild(O);const N=document.createElement("div");N.style.cssText="display:grid;grid-template-columns:1fr 1fr auto;gap:.6rem;align-items:end;margin-bottom:.6rem;";const _=document.createElement("div"),M=document.createElement("label");M.className="form-label",M.textContent="Placeholder";const I=document.createElement("input");I.id=`fb-placeholder-${t}`,I.type="text",I.className="form-input",I.value=e.placeholder||"",_.appendChild(M),_.appendChild(I);const j=document.createElement("div"),V=document.createElement("label");V.className="form-label",V.textContent="Helper text";const S=document.createElement("input");S.id=`fb-helper-${t}`,S.type="text",S.className="form-input",S.value=e.helper||"",j.appendChild(V),j.appendChild(S);const H=document.createElement("div");H.style.cssText="padding-bottom:.35rem;";const A=document.createElement("label");A.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;white-space:nowrap;";const W=document.createElement("input");W.id=`fb-required-${t}`,W.type="checkbox",W.checked=!!e.required,A.appendChild(W),A.appendChild(document.createTextNode("Required")),H.appendChild(A),N.appendChild(_),N.appendChild(j),N.appendChild(H);const k=document.createElement("div");k.className="fb-options-wrap",k.style.display=Q.has(e.type)?"":"none";const Y=document.createElement("label");Y.className="form-label",Y.textContent="Options (one per line: value: Label)";const B=document.createElement("textarea");B.id=`fb-options-${t}`,B.className="form-input",B.rows=4,B.value=(e.options||[]).map(s=>typeof s=="string"?`${s}: ${s}`:`${s.value??""}: ${s.label??s.value??""}`).join(`
3
- `),k.appendChild(Y),k.appendChild(B);const b=document.createElement("div");b.className="fb-grid-row",b.style.gridTemplateColumns="1fr auto",b.style.gap=".6rem",b.style.alignItems="end",b.style.marginBottom=".6rem",b.style.display=document.getElementById("collection-layout")?.value==="grid"?"grid":"none";const G=document.createElement("div"),J=document.createElement("label");J.className="form-label",J.textContent="Column Span";const x=document.createElement("input");x.id=`fb-span-${t}`,x.type="number",x.className="form-input",x.min="1",x.max="6",x.value=e.span>1?String(e.span):"1",G.appendChild(J),G.appendChild(x);const K=document.createElement("div");K.style.cssText="padding-bottom:.35rem;";const F=document.createElement("label");F.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;white-space:nowrap;";const D=document.createElement("input");return D.id=`fb-fullwidth-${t}`,D.type="checkbox",D.checked=!!e.fullWidth,F.appendChild(D),F.appendChild(document.createTextNode("Full Width")),K.appendChild(F),b.appendChild(G),b.appendChild(K),d.appendChild(c),d.appendChild(N),d.appendChild(k),d.appendChild(b),a.addEventListener("click",()=>{const s=d.style.display!=="none";d.style.display=s?"none":"",l.style.transform=s?"":"rotate(180deg)"}),n.appendChild(a),n.appendChild(d),n}function P(e){if(e){if(e.textContent="",u.length===0){const t=document.createElement("p");t.className="text-muted",t.id="fields-empty-msg",t.style.cssText="text-align:center;padding:2rem 0;",t.textContent='No fields yet. Click "Add Field" to get started.',e.appendChild(t);return}u.forEach((t,n)=>{e.appendChild(oe(t,n))})}}function se(e,t){t.textContent="",$.forEach(n=>{const a=e?.[n]||{enabled:!1,access:"admin"},i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:140px 1fr 160px;gap:.75rem;align-items:center;padding:.6rem 0;border-bottom:1px solid var(--border-color,#333);";const p=document.createElement("strong");p.textContent=n.charAt(0).toUpperCase()+n.slice(1),p.style.cssText="font-size:.9rem;";const r=document.createElement("label");r.style.cssText="display:flex;align-items:center;gap:.45rem;cursor:pointer;font-size:.875rem;";const l=document.createElement("input");l.type="checkbox",l.id=`api-${n}-enabled`,l.checked=!!a.enabled,r.appendChild(l),r.appendChild(document.createTextNode("Enable public access"));const o=document.createElement("select");o.id=`api-${n}-access`,o.className="form-input",ne.forEach(d=>{const c=document.createElement("option");c.value=d,c.textContent=d.charAt(0).toUpperCase()+d.slice(1),d===a.access&&(c.selected=!0),o.appendChild(c)}),i.appendChild(p),i.appendChild(r),i.appendChild(o),t.appendChild(i)})}function de(e,t){E.dropdown("#storage-adapter-trigger",{items:[{label:"File (default)",value:"file"},{label:"MongoDB",value:"mongodb"}],onSelect:({item:a})=>{e.find("#storage-adapter").val(a.value),e.find("#storage-adapter-label").text(a.label);const i=a.value==="mongodb";e.find("#storage-connection-group").toggle(i),e.find("#storage-migration-warning").toggle(i&&!T)}});const n=t.map(a=>({label:a,value:a}));E.dropdown("#storage-connection-trigger",{items:n.length?n:[{label:"default",value:"default"}],onSelect:({item:a})=>{e.find("#storage-connection").val(a.value),e.find("#storage-connection-label").text(a.label)}})}function le(){return(document.getElementById("storage-adapter")?.value||"file")==="mongodb"?{adapter:"mongodb",connection:document.getElementById("storage-connection")?.value||"default"}:{adapter:"file"}}function ce(){const e={};return $.forEach(t=>{const n=document.getElementById(`api-${t}-enabled`)?.checked??!1,a=document.getElementById(`api-${t}-access`)?.value||"admin";e[t]={enabled:n,access:a}}),e}export const collectionEditorView={templateUrl:"/admin/js/templates/collection-editor.html",async onMount(e){u=[],w=null,T=!0;const n=window.location.hash.match(/\/collections\/edit\/([^/?#]+)/);n&&(w=n[1],T=!1),E.tabs(e.find("#collection-tabs").get(0)),e.find("#collection-layout").get(0)?.addEventListener("change",function(){const l=this.value==="grid";e.find("#collection-columns-group").get(0).style.display=l?"":"none",document.querySelectorAll(".fb-grid-row").forEach(o=>{o.style.display=l?"grid":"none"})});const a=e.find("#fields-list").get(0),i=e.find("#api-access-rows").get(0),p=await z.collections.proStatus();p?.pro&&w!=="roles"&&(e.find("#storage-tab-btn").show(),de(e,p.connections));let r={create:{enabled:!1,access:"admin"},read:{enabled:!0,access:"public"},update:{enabled:!1,access:"admin"},delete:{enabled:!1,access:"admin"}};if(T){const l=e.find("#field-title").get(0),o=e.find("#field-slug").get(0);l&&o&&(l.addEventListener("input",()=>{o.dataset.manual||(o.value=ee(l.value))}),o.addEventListener("input",()=>{o.dataset.manual="1"}))}else try{const l=await z.collections.get(w);if(!l){E.toast("Collection not found.",{type:"error"}),R.navigate("/collections");return}const o=e.find("#editor-title-text").get(0);o&&(o.textContent=l.title),e.find("#field-title").val(l.title||""),e.find("#field-slug").val(l.slug||""),e.find("#field-slug").prop("readonly",!0),e.find("#slug-hint").get(0).textContent="Slug cannot be changed after creation.",e.find("#field-description").val(l.description||""),e.find("#collection-layout").val(l.layout||"stacked"),e.find("#collection-columns").val(l.columns||2),e.find("#collection-columns-group").get(0).style.display=l.layout==="grid"?"":"none",u=l.fields||[],r=l.api||r,l.storage&&(e.find("#storage-adapter").val(l.storage.adapter||"file"),e.find("#storage-adapter-label").text(l.storage.adapter==="mongodb"?"MongoDB":"File (default)"),l.storage.adapter==="mongodb"&&(e.find("#storage-connection-group").show(),e.find("#storage-connection").val(l.storage.connection||"default"),e.find("#storage-connection-label").text(l.storage.connection||"default"))),w==="roles"&&e.find("#storage-tab-btn").hide()}catch{E.toast("Failed to load collection.",{type:"error"}),R.navigate("/collections");return}P(a),se(r,i),e.find("#add-field-btn").off("click").on("click",()=>{u=X(),u.push({id:`field-${Date.now()}`,name:"",label:"",type:"string",required:!1,placeholder:"",helper:"",options:[],validation:[],logic:null}),P(a);const l=a.querySelectorAll(".fb-field-card");if(l.length){const o=l[l.length-1],d=o.querySelector(".fb-field-body"),c=o.querySelector(".fb-field-chevron");d&&(d.style.display=""),c&&(c.style.transform="rotate(180deg)"),o.querySelector(`#fb-label-${u.length-1}`)?.focus()}}),e.find("#save-collection-btn").off("click").on("click",async()=>{const l=e.find("#field-title").val().trim(),o=e.find("#field-slug").val().trim(),d=e.find("#field-description").val().trim();if(!l){E.toast("Title is required.",{type:"warning"});return}const c=X(),f=ce(),g=e.find("#collection-layout").val()||"stacked",m=parseInt(e.find("#collection-columns").val(),10)||2,L=e.find("#save-collection-btn");L.prop("disabled",!0);try{if(T){const h=await z.collections.create({title:l,slug:o,description:d,layout:g,columns:m,fields:c,api:f,storage:le()});w=h.slug,T=!1,E.toast("Collection created.",{type:"success"}),R.navigate(`/collections/edit/${h.slug}`)}else await z.collections.update(w,{title:l,description:d,layout:g,columns:m,fields:c,api:f,storage:le()}),E.toast("Collection saved.",{type:"success"})}catch(h){E.toast(h.message||"Failed to save.",{type:"error"})}finally{L.prop("disabled",!1)}}),Domma.icons.scan()}};
1
+ import{api as N}from"../api.js";const Z=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"hidden",label:"Hidden field"}],Q=new Set(["select","radio","checkbox-group"]),ae=["public","subscriber","editor","manager","admin"],ee=["create","read","update","delete"];let g=[],y=null,k=!0,D=null,S="file";function te(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}function le(e){return Z.find(t=>t.value===e)?.label||e}function ne(e){const t={...g[e]},a=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),i=document.getElementById(`fb-type-${e}`),p=document.getElementById(`fb-required-${e}`),r=document.getElementById(`fb-placeholder-${e}`),l=document.getElementById(`fb-helper-${e}`);if(a&&(t.label=a.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),i&&(t.type=i.value||t.type),p&&(t.required=p.checked),r&&(t.placeholder=r.value.trim()),l&&(t.helper=l.value.trim()),Q.has(t.type)){const c=document.getElementById(`fb-options-${e}`);c&&(t.options=c.value.split(`
2
+ `).filter(b=>b.trim()).map(b=>{const[h,...m]=b.split(":");return{value:h.trim(),label:m.join(":").trim()||h.trim()}}))}const o=document.getElementById(`fb-span-${e}`);if(document.getElementById(`fb-fullwidth-${e}`)?.checked)t.fullWidth=!0,delete t.span;else{delete t.fullWidth;const c=parseInt(o?.value,10);c>1?t.span=c:delete t.span}return t}function X(){return g.map((e,t)=>ne(t))}function oe(e,t){const a=document.createElement("div");a.className="fb-field-card",a.dataset.index=t,a.style.cssText="border:1px solid var(--border-color,#333);border-radius:8px;margin-bottom:.75rem;overflow:hidden;";const n=document.createElement("div");n.className="fb-field-header",n.style.cssText="display:flex;align-items:center;gap:.5rem;padding:.6rem .75rem;background:var(--card-header-bg,rgba(255,255,255,.03));cursor:pointer;user-select:none;";const i=document.createElement("span");i.textContent="\u283F",i.style.cssText="cursor:grab;opacity:.4;font-size:1.1rem;flex-shrink:0;",a.draggable=!0,i.addEventListener("mousedown",()=>{a.draggable=!0}),a.addEventListener("dragstart",s=>{D=t,s.dataTransfer.effectAllowed="move",a.style.opacity="0.4"}),a.addEventListener("dragend",()=>{a.style.opacity="",document.querySelectorAll(".fb-field-card").forEach(s=>s.classList.remove("fb-drag-over"))}),a.addEventListener("dragover",s=>{s.preventDefault(),s.dataTransfer.dropEffect="move",document.querySelectorAll(".fb-field-card").forEach(L=>L.classList.remove("fb-drag-over")),a.classList.add("fb-drag-over")}),a.addEventListener("dragleave",()=>{a.classList.remove("fb-drag-over")}),a.addEventListener("drop",s=>{if(s.preventDefault(),a.classList.remove("fb-drag-over"),D===null||D===t)return;g=X();const[L]=g.splice(D,1);g.splice(t,0,L),D=null,U(document.getElementById("fields-list"))});const p=document.createElement("span");p.className="fb-field-summary",p.style.cssText="flex:1;font-weight:500;font-size:.9rem;",p.textContent=e.label||"(Untitled field)";const r=document.createElement("span");r.style.cssText="font-size:.75rem;opacity:.5;",r.textContent=le(e.type);const l=document.createElement("span");l.className="fb-field-chevron",l.textContent="\u25BE",l.style.cssText="opacity:.5;transition:transform .2s;";const o=document.createElement("button");o.type="button",o.textContent="\xD7",o.className="btn btn-sm",o.style.cssText="padding:.15rem .45rem;line-height:1;font-size:1rem;opacity:.6;",o.title="Remove field",o.addEventListener("click",s=>{s.stopPropagation(),g.splice(t,1),U(document.getElementById("fields-list"))}),n.appendChild(i),n.appendChild(p),n.appendChild(r),n.appendChild(l),n.appendChild(o);const d=document.createElement("div");d.className="fb-field-body",d.style.cssText="padding:.75rem;display:none;";const c=document.createElement("div");c.style.cssText="display:grid;grid-template-columns:1fr 1fr 1fr;gap:.6rem;margin-bottom:.6rem;";const b=document.createElement("div"),h=document.createElement("label");h.className="form-label",h.textContent="Label";const m=document.createElement("input");m.id=`fb-label-${t}`,m.type="text",m.className="form-input",m.value=e.label||"",m.addEventListener("input",()=>{p.textContent=m.value.trim()||"(Untitled field)";const s=document.getElementById(`fb-name-${t}`);s&&!s.dataset.manual&&(s.value=te(m.value).replace(/-/g,"_"))}),b.appendChild(h),b.appendChild(m);const u=document.createElement("div"),I=document.createElement("label");I.className="form-label",I.textContent="Name (key)";const f=document.createElement("input");f.id=`fb-name-${t}`,f.type="text",f.className="form-input",f.value=e.name||"",f.addEventListener("input",()=>{f.dataset.manual="1"}),u.appendChild(I),u.appendChild(f);const x=document.createElement("div"),B=document.createElement("label");B.className="form-label",B.textContent="Type";const w=document.createElement("select");w.id=`fb-type-${t}`,w.className="form-input",Z.forEach(s=>{const L=document.createElement("option");L.value=s.value,L.textContent=s.label,s.value===e.type&&(L.selected=!0),w.appendChild(L)}),w.addEventListener("change",()=>{r.textContent=le(w.value);const s=d.querySelector(".fb-options-wrap");s&&(s.style.display=Q.has(w.value)?"":"none")}),x.appendChild(B),x.appendChild(w),c.appendChild(b),c.appendChild(u),c.appendChild(x);const v=document.createElement("div");v.style.cssText="display:grid;grid-template-columns:1fr 1fr auto;gap:.6rem;align-items:end;margin-bottom:.6rem;";const _=document.createElement("div"),$=document.createElement("label");$.className="form-label",$.textContent="Placeholder";const q=document.createElement("input");q.id=`fb-placeholder-${t}`,q.type="text",q.className="form-input",q.value=e.placeholder||"",_.appendChild($),_.appendChild(q);const j=document.createElement("div"),V=document.createElement("label");V.className="form-label",V.textContent="Helper text";const A=document.createElement("input");A.id=`fb-helper-${t}`,A.type="text",A.className="form-input",A.value=e.helper||"",j.appendChild(V),j.appendChild(A);const Y=document.createElement("div");Y.style.cssText="padding-bottom:.35rem;";const M=document.createElement("label");M.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;white-space:nowrap;";const z=document.createElement("input");z.id=`fb-required-${t}`,z.type="checkbox",z.checked=!!e.required,M.appendChild(z),M.appendChild(document.createTextNode("Required")),Y.appendChild(M),v.appendChild(_),v.appendChild(j),v.appendChild(Y);const W=document.createElement("div");W.className="fb-options-wrap",W.style.display=Q.has(e.type)?"":"none";const H=document.createElement("label");H.className="form-label",H.textContent="Options (one per line: value: Label)";const F=document.createElement("textarea");F.id=`fb-options-${t}`,F.className="form-input",F.rows=4,F.value=(e.options||[]).map(s=>typeof s=="string"?`${s}: ${s}`:`${s.value??""}: ${s.label??s.value??""}`).join(`
3
+ `),W.appendChild(H),W.appendChild(F);const C=document.createElement("div");C.className="fb-grid-row",C.style.gridTemplateColumns="1fr auto",C.style.gap=".6rem",C.style.alignItems="end",C.style.marginBottom=".6rem",C.style.display=document.getElementById("collection-layout")?.value==="grid"?"grid":"none";const G=document.createElement("div"),J=document.createElement("label");J.className="form-label",J.textContent="Column Span";const T=document.createElement("input");T.id=`fb-span-${t}`,T.type="number",T.className="form-input",T.min="1",T.max="6",T.value=e.span>1?String(e.span):"1",G.appendChild(J),G.appendChild(T);const K=document.createElement("div");K.style.cssText="padding-bottom:.35rem;";const P=document.createElement("label");P.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;white-space:nowrap;";const O=document.createElement("input");return O.id=`fb-fullwidth-${t}`,O.type="checkbox",O.checked=!!e.fullWidth,P.appendChild(O),P.appendChild(document.createTextNode("Full Width")),K.appendChild(P),C.appendChild(G),C.appendChild(K),d.appendChild(c),d.appendChild(v),d.appendChild(W),d.appendChild(C),n.addEventListener("click",()=>{const s=d.style.display!=="none";d.style.display=s?"none":"",l.style.transform=s?"":"rotate(180deg)"}),a.appendChild(n),a.appendChild(d),a}function U(e){if(e){if(e.textContent="",g.length===0){const t=document.createElement("p");t.className="text-muted",t.id="fields-empty-msg",t.style.cssText="text-align:center;padding:2rem 0;",t.textContent='No fields yet. Click "Add Field" to get started.',e.appendChild(t);return}g.forEach((t,a)=>{e.appendChild(oe(t,a))})}}function se(e,t){t.textContent="",ee.forEach(a=>{const n=e?.[a]||{enabled:!1,access:"admin"},i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:140px 1fr 160px;gap:.75rem;align-items:center;padding:.6rem 0;border-bottom:1px solid var(--border-color,#333);";const p=document.createElement("strong");p.textContent=a.charAt(0).toUpperCase()+a.slice(1),p.style.cssText="font-size:.9rem;";const r=document.createElement("label");r.style.cssText="display:flex;align-items:center;gap:.45rem;cursor:pointer;font-size:.875rem;";const l=document.createElement("input");l.type="checkbox",l.id=`api-${a}-enabled`,l.checked=!!n.enabled,r.appendChild(l),r.appendChild(document.createTextNode("Enable public access"));const o=document.createElement("select");o.id=`api-${a}-access`,o.className="form-input",ae.forEach(d=>{const c=document.createElement("option");c.value=d,c.textContent=d.charAt(0).toUpperCase()+d.slice(1),d===n.access&&(c.selected=!0),o.appendChild(c)}),i.appendChild(p),i.appendChild(r),i.appendChild(o),t.appendChild(i)})}function de(e,t){E.dropdown("#storage-adapter-trigger",{items:[{label:"File (default)",value:"file"},{label:"MongoDB",value:"mongodb"}],onSelect:({item:n})=>{e.find("#storage-adapter").val(n.value),e.find("#storage-adapter-label").text(n.label);const i=n.value==="mongodb";e.find("#storage-connection-group").toggle(i),e.find("#storage-migration-warning").toggle(i&&!k)}});const a=t.map(n=>({label:n,value:n}));E.dropdown("#storage-connection-trigger",{items:a.length?a:[{label:"default",value:"default"}],onSelect:({item:n})=>{e.find("#storage-connection").val(n.value),e.find("#storage-connection-label").text(n.label)}})}function ce(){return(document.getElementById("storage-adapter")?.value||"file")==="mongodb"?{adapter:"mongodb",connection:document.getElementById("storage-connection")?.value||"default"}:{adapter:"file"}}function ie(){const e={};return ee.forEach(t=>{const a=document.getElementById(`api-${t}-enabled`)?.checked??!1,n=document.getElementById(`api-${t}-access`)?.value||"admin";e[t]={enabled:a,access:n}}),e}export const collectionEditorView={templateUrl:"/admin/js/templates/collection-editor.html",async onMount(e){g=[],y=null,k=!0;const a=window.location.hash.match(/\/collections\/edit\/([^/?#]+)/);a&&(y=a[1],k=!1),E.tabs(e.find("#collection-tabs").get(0)),e.find("#collection-layout").get(0)?.addEventListener("change",function(){const l=this.value==="grid";e.find("#collection-columns-group").get(0).style.display=l?"":"none",document.querySelectorAll(".fb-grid-row").forEach(o=>{o.style.display=l?"grid":"none"})});const n=e.find("#fields-list").get(0),i=e.find("#api-access-rows").get(0),p=await N.collections.proStatus();p?.pro&&y!=="roles"&&(e.find("#storage-tab-btn").show(),de(e,p.connections));let r={create:{enabled:!1,access:"admin"},read:{enabled:!0,access:"public"},update:{enabled:!1,access:"admin"},delete:{enabled:!1,access:"admin"}};if(k){const l=e.find("#field-title").get(0),o=e.find("#field-slug").get(0);l&&o&&(l.addEventListener("input",()=>{o.dataset.manual||(o.value=te(l.value))}),o.addEventListener("input",()=>{o.dataset.manual="1"}))}else try{const l=await N.collections.get(y);if(!l){E.toast("Collection not found.",{type:"error"}),R.navigate("/collections");return}const o=e.find("#editor-title-text").get(0);o&&(o.textContent=l.title),e.find("#field-title").val(l.title||""),e.find("#field-slug").val(l.slug||""),e.find("#field-slug").prop("readonly",!0),e.find("#slug-hint").get(0).textContent="Slug cannot be changed after creation.",e.find("#field-description").val(l.description||""),e.find("#collection-layout").val(l.layout||"stacked"),e.find("#collection-columns").val(l.columns||2),e.find("#collection-columns-group").get(0).style.display=l.layout==="grid"?"":"none",g=l.fields||[],r=l.api||r,S=l.storage?.adapter||"file",l.storage&&(e.find("#storage-adapter").val(l.storage.adapter||"file"),e.find("#storage-adapter-label").text(l.storage.adapter==="mongodb"?"MongoDB":"File (default)"),l.storage.adapter==="mongodb"&&(e.find("#storage-connection-group").show(),e.find("#storage-connection").val(l.storage.connection||"default"),e.find("#storage-connection-label").text(l.storage.connection||"default"))),y==="roles"&&e.find("#storage-tab-btn").hide()}catch{E.toast("Failed to load collection.",{type:"error"}),R.navigate("/collections");return}U(n),se(r,i),e.find("#add-field-btn").off("click").on("click",()=>{g=X(),g.push({id:`field-${Date.now()}`,name:"",label:"",type:"string",required:!1,placeholder:"",helper:"",options:[],validation:[],logic:null}),U(n);const l=n.querySelectorAll(".fb-field-card");if(l.length){const o=l[l.length-1],d=o.querySelector(".fb-field-body"),c=o.querySelector(".fb-field-chevron");d&&(d.style.display=""),c&&(c.style.transform="rotate(180deg)"),o.querySelector(`#fb-label-${g.length-1}`)?.focus()}}),e.find("#save-collection-btn").off("click").on("click",async()=>{const l=e.find("#field-title").val().trim(),o=e.find("#field-slug").val().trim(),d=e.find("#field-description").val().trim();if(!l){E.toast("Title is required.",{type:"warning"});return}const c=X(),b=ie(),h=e.find("#collection-layout").val()||"stacked",m=parseInt(e.find("#collection-columns").val(),10)||2,u=ce(),I=e.find("#save-collection-btn");I.prop("disabled",!0);try{if(k){const f=await N.collections.create({title:l,slug:o,description:d,layout:h,columns:m,fields:c,api:b,storage:u});y=f.slug,S=u.adapter||"file",k=!1,E.toast("Collection created.",{type:"success"}),R.navigate(`/collections/edit/${f.slug}`)}else if((u.adapter||"file")!==S){let x=0;try{x=(await N.collections.listEntries(y,{limit:1}))?.total??0}catch{}const B=S==="file"?`file \u2192 ${u.adapter}`:`${S} \u2192 ${u.adapter||"file"}`;if(x>0&&await E.confirm(`You changed the storage adapter (${B}).
4
+
5
+ Migrate ${x} existing ${x===1?"entry":"entries"} to the new storage?`)){const v=await N.collections.migrateStorage(y,u);S=u.adapter||"file",E.toast(`Migrated ${v.migrated} of ${v.total} entries.`,{type:"success"})}else await N.collections.update(y,{title:l,description:d,layout:h,columns:m,fields:c,api:b,storage:u}),S=u.adapter||"file",E.toast("Collection saved.",{type:"success"})}else await N.collections.update(y,{title:l,description:d,layout:h,columns:m,fields:c,api:b,storage:u}),E.toast("Collection saved.",{type:"success"})}catch(f){E.toast(f.message||"Failed to save.",{type:"error"})}finally{I.prop("disabled",!1)}}),Domma.icons.scan()}};
@@ -1 +1 @@
1
- import{api as h}from"../api.js";function b(e){return String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}let i={};export const collectionsView={templateUrl:"/admin/js/templates/collections.html",async onMount(e){const a=E.loader(e.get(0),{type:"dots"});E.tabs(e.find("#collections-tabs").get(0));const o=e.find("#collections-tabs").get(0)?.querySelector(".tab-list");if(o){const t=e.find("#collections-header-actions").get(0);Array.from(o.querySelectorAll(".tab-item")).forEach((n,c)=>{n.addEventListener("click",()=>{t&&(t.style.display=c===0?"":"none")})})}await Promise.all([j(e),q(e)]),a.destroy(),e.find("#create-collection-btn").off("click").on("click",()=>{const t=E.modal({title:"New Collection",size:"sm"}),n=document.createElement("div");n.style.cssText="padding:.25rem 0 .5rem;";const c=document.createElement("div");F.create({title:{type:"string",label:"Collection Title",placeholder:"e.g. Products, Blog Posts\u2026",required:!0}},{},{showSubmitButton:!1}).renderTo(c),n.appendChild(c);const d=document.createElement("div");d.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem;";const s=document.createElement("button");s.className="btn btn-ghost",s.textContent="Cancel";const l=document.createElement("button");l.className="btn btn-primary",l.textContent="Create",d.appendChild(s),d.appendChild(l),n.appendChild(d),t.element.appendChild(n),t.open();const r=c.querySelector('input[name="title"]');setTimeout(()=>r?.focus(),50);async function m(){const p=r?.value.trim();if(p)try{const u=await h.collections.create({title:p});t.close(),R.navigate(`/collections/edit/${u.slug}`)}catch(u){E.toast(u.message||"Failed to create collection.",{type:"error"})}}s.addEventListener("click",()=>t.close()),l.addEventListener("click",m),r?.addEventListener("keydown",p=>{p.key==="Enter"&&m()})}),e.find("#connections-raw-toggle").on("change",function(){if(this.checked)i=w(e),v(e),e.find("#connections-form-view").hide(),e.find("#connections-raw-view").show();else{const t=e.find("#connections-raw-json").get(0)?.value||"{}";try{i=JSON.parse(t),C(e),e.find("#connections-form-view").show(),e.find("#connections-raw-view").hide()}catch{E.toast("Invalid JSON \u2014 fix before switching to form view.",{type:"warning"}),this.checked=!0}}}),e.find("#add-connection-btn").on("click",()=>{i=w(e);let t=Object.keys(i).length+1,n=`connection${t}`;for(;i[n];)t++,n=`connection${t}`;i[n]={type:"mongodb",uri:"",database:"",options:{}},C(e),v(e)}),e.find("#save-connections-btn").on("click",async()=>{const t=e.find("#connections-raw-toggle").get(0)?.checked;let n;if(t)try{n=JSON.parse(e.find("#connections-raw-json").get(0)?.value||"{}")}catch{E.toast("Invalid JSON \u2014 fix before saving.",{type:"warning"});return}else n=w(e);try{await h.collections.saveConnections(n),i=n,E.toast("Connections saved.",{type:"success"})}catch(c){E.toast(c.message||"Failed to save connections.",{type:"error"})}}),Domma.icons.scan()}};async function j(e){let a=[];try{a=await h.collections.list()}catch{E.toast("Could not load collections.",{type:"error"})}T.create("#collections-table",{data:a,columns:[{key:"title",title:"Title",render:(o,t)=>{const n=document.createElement("a");return n.href=`#/collections/${b(t.slug)}/entries`,n.textContent=o,n.style.fontWeight="600",n.outerHTML}},{key:"slug",title:"Slug",render:o=>{const t=document.createElement("code");return t.textContent=o,t.outerHTML}},{key:"fields",title:"Field Count",render:o=>String(o?.length??0)},{key:"entryCount",title:"Entry Count",render:o=>String(o??0)},{key:"slug",title:"Actions",render:o=>{const t=document.createElement("div");t.style.cssText="display:flex;gap:.4rem;justify-content:flex-end;flex-wrap:wrap;";const n=document.createElement("a");n.href=`#/collections/edit/${b(o)}`,n.className="btn btn-sm btn-ghost",n.textContent="Edit Schema";const c=document.createElement("a");if(c.href=`#/collections/${b(o)}/entries`,c.className="btn btn-sm btn-ghost",c.textContent="Entries",t.appendChild(n),t.appendChild(c),!new Set(["roles","user-profiles"]).has(o)){const l=document.createElement("a");l.href=`#/forms/edit/${b(o)}`,l.className="btn btn-sm btn-ghost",l.textContent="Form",t.appendChild(l)}const s=document.createElement("button");return s.className="btn btn-sm btn-danger js-delete-collection",s.dataset.slug=o,s.textContent="Delete",t.appendChild(s),t.outerHTML}}],emptyMessage:'No collections yet. Click "New Collection" to get started.'}),document.querySelectorAll(".js-delete-collection").forEach(o=>{o.addEventListener("click",async()=>{const t=o.dataset.slug;if(await E.confirm(`Delete collection "${t}" and all its data? This cannot be undone.`))try{await h.collections.delete(t),E.toast("Collection deleted.",{type:"success"}),await j(e)}catch{E.toast("Failed to delete collection.",{type:"error"})}})}),Domma.icons.scan()}async function q(e){try{i=await h.collections.getConnections()}catch{i={}}C(e),v(e)}function C(e){const a=e.find("#connections-list").get(0),o=e.find("#connections-empty").get(0);if(!a)return;a.textContent="";const t=Object.keys(i);o&&(o.style.display=t.length?"none":""),t.forEach(n=>{const c=i[n],d=document.createElement("div");d.className="conn-card card mb-3",d.dataset.connKey=n;const s=document.createElement("div");s.className="card-header",s.style.cssText="display:flex;align-items:center;gap:.5rem;";const l=document.createElement("input");l.type="text",l.className="form-input conn-name",l.value=n,l.placeholder="Connection name",l.style.cssText="flex:1;";const r=document.createElement("button");r.type="button",r.className="btn btn-sm btn-danger",r.textContent="Delete",r.addEventListener("click",()=>{i=w(e);const L=l.value.trim();L&&delete i[L],C(e),v(e)}),s.appendChild(l),s.appendChild(r);const m=document.createElement("div");m.className="card-body",m.style.cssText="display:grid;grid-template-columns:1fr 2fr 1fr;gap:.6rem;";const p=document.createElement("div"),u=document.createElement("label");u.className="form-label",u.textContent="Type";const f=document.createElement("input");f.type="text",f.className="form-input conn-type",f.value=c.type||"mongodb",f.disabled=!0,p.appendChild(u),p.appendChild(f);const x=document.createElement("div"),S=document.createElement("label");S.className="form-label",S.textContent="URI";const y=document.createElement("input");y.type="text",y.className="form-input conn-uri",y.value=c.uri||"",y.placeholder="mongodb://localhost:27017",x.appendChild(S),x.appendChild(y);const N=document.createElement("div"),k=document.createElement("label");k.className="form-label",k.textContent="Database";const g=document.createElement("input");g.type="text",g.className="form-input conn-database",g.value=c.database||"",g.placeholder="mydb",N.appendChild(k),N.appendChild(g),m.appendChild(p),m.appendChild(x),m.appendChild(N),d.appendChild(s),d.appendChild(m),a.appendChild(d)})}function w(e){const a={},o=e.find("#connections-list").get(0)?.querySelectorAll(".conn-card")||[];for(const t of o){const n=t.querySelector(".conn-name")?.value.trim(),c=t.querySelector(".conn-uri")?.value.trim()||"",d=t.querySelector(".conn-database")?.value.trim()||"";n&&(a[n]={type:"mongodb",uri:c,database:d,options:{}})}return a}function v(e){const a=e.find("#connections-raw-json").get(0);a&&(a.value=JSON.stringify(i,null,2))}
1
+ import{api as b}from"../api.js";function h(e){return String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}let d={};export const collectionsView={templateUrl:"/admin/js/templates/collections.html",async onMount(e){const i=E.loader(e.get(0),{type:"dots"});E.tabs(e.find("#collections-tabs").get(0));const o=e.find("#collections-tabs").get(0)?.querySelector(".tab-list");if(o){const t=e.find("#collections-header-actions").get(0);Array.from(o.querySelectorAll(".tab-item")).forEach((n,c)=>{n.addEventListener("click",()=>{t&&(t.style.display=c===0?"":"none")})})}await Promise.all([B(e),j(e)]),i.destroy(),e.find("#create-collection-btn").off("click").on("click",()=>{const t=E.modal({title:"New Collection",size:"sm"}),n=document.createElement("div");n.style.cssText="padding:.25rem 0 .5rem;";const c=document.createElement("div");F.create({title:{type:"string",label:"Collection Title",placeholder:"e.g. Products, Blog Posts\u2026",required:!0}},{},{showSubmitButton:!1}).renderTo(c),n.appendChild(c);const l=document.createElement("div");l.style.cssText="display:flex;justify-content:flex-end;gap:.5rem;margin-top:.75rem;";const a=document.createElement("button");a.className="btn btn-ghost",a.textContent="Cancel";const s=document.createElement("button");s.className="btn btn-primary",s.textContent="Create",l.appendChild(a),l.appendChild(s),n.appendChild(l),t.element.appendChild(n),t.open();const r=c.querySelector('input[name="title"]');setTimeout(()=>r?.focus(),50);async function m(){const p=r?.value.trim();if(p)try{const u=await b.collections.create({title:p});t.close(),R.navigate(`/collections/edit/${u.slug}`)}catch(u){E.toast(u.message||"Failed to create collection.",{type:"error"})}}a.addEventListener("click",()=>t.close()),s.addEventListener("click",m),r?.addEventListener("keydown",p=>{p.key==="Enter"&&m()})}),e.find("#connections-raw-toggle").on("change",function(){if(this.checked)d=x(e),v(e),e.find("#connections-form-view").hide(),e.find("#connections-raw-view").show();else{const t=e.find("#connections-raw-json").get(0)?.value||"{}";try{d=JSON.parse(t),C(e),e.find("#connections-form-view").show(),e.find("#connections-raw-view").hide()}catch{E.toast("Invalid JSON \u2014 fix before switching to form view.",{type:"warning"}),this.checked=!0}}}),e.find("#add-connection-btn").on("click",()=>{d=x(e);let t=Object.keys(d).length+1,n=`connection${t}`;for(;d[n];)t++,n=`connection${t}`;d[n]={type:"mongodb",uri:"",database:"",options:{}},C(e),v(e)}),e.find("#save-connections-btn").on("click",async()=>{const t=e.find("#connections-raw-toggle").get(0)?.checked;let n;if(t)try{n=JSON.parse(e.find("#connections-raw-json").get(0)?.value||"{}")}catch{E.toast("Invalid JSON \u2014 fix before saving.",{type:"warning"});return}else n=x(e);try{await b.collections.saveConnections(n),d=n,E.toast("Connections saved.",{type:"success"})}catch(c){E.toast(c.message||"Failed to save connections.",{type:"error"})}}),Domma.icons.scan()}};async function B(e){let i=[];try{i=await b.collections.list()}catch{E.toast("Could not load collections.",{type:"error"})}T.create("#collections-table",{data:i,columns:[{key:"title",title:"Title",render:(o,t)=>{const n=document.createElement("span");n.style.cssText="display:flex;align-items:center;gap:.4rem;";const c=document.createElement("a");if(c.href=`#/collections/${h(t.slug)}/entries`,c.textContent=o,c.style.fontWeight="600",n.appendChild(c),t.storage?.adapter==="mongodb"){const l=document.createElement("span");l.className="badge badge-outline",l.textContent="MongoDB",l.title=`Connection: ${t.storage.connection||"default"}`,l.style.cssText="font-size:0.65rem;padding:1px 6px;color:var(--dm-success,#16a34a);border-color:var(--dm-success,#16a34a);flex-shrink:0;",n.appendChild(l)}return n.outerHTML}},{key:"slug",title:"Slug",render:o=>{const t=document.createElement("code");return t.textContent=o,t.outerHTML}},{key:"fields",title:"Field Count",render:o=>String(o?.length??0)},{key:"entryCount",title:"Entry Count",render:o=>String(o??0)},{key:"slug",title:"Actions",render:o=>{const t=document.createElement("div");t.style.cssText="display:flex;gap:.4rem;justify-content:flex-end;flex-wrap:wrap;";const n=document.createElement("a");n.href=`#/collections/edit/${h(o)}`,n.className="btn btn-sm btn-ghost",n.textContent="Edit Schema";const c=document.createElement("a");if(c.href=`#/collections/${h(o)}/entries`,c.className="btn btn-sm btn-ghost",c.textContent="Entries",t.appendChild(n),t.appendChild(c),!new Set(["roles","user-profiles"]).has(o)){const s=document.createElement("a");s.href=`#/forms/edit/${h(o)}`,s.className="btn btn-sm btn-ghost",s.textContent="Form",t.appendChild(s)}const a=document.createElement("button");return a.className="btn btn-sm btn-danger js-delete-collection",a.dataset.slug=o,a.textContent="Delete",t.appendChild(a),t.outerHTML}}],emptyMessage:'No collections yet. Click "New Collection" to get started.'}),document.querySelectorAll(".js-delete-collection").forEach(o=>{o.addEventListener("click",async()=>{const t=o.dataset.slug;if(await E.confirm(`Delete collection "${t}" and all its data? This cannot be undone.`))try{await b.collections.delete(t),E.toast("Collection deleted.",{type:"success"}),await B(e)}catch{E.toast("Failed to delete collection.",{type:"error"})}})}),Domma.icons.scan()}async function j(e){try{d=await b.collections.getConnections()}catch{d={}}C(e),v(e)}function C(e){const i=e.find("#connections-list").get(0),o=e.find("#connections-empty").get(0);if(!i)return;i.textContent="";const t=Object.keys(d);o&&(o.style.display=t.length?"none":""),t.forEach(n=>{const c=d[n],l=document.createElement("div");l.className="conn-card card mb-3",l.dataset.connKey=n;const a=document.createElement("div");a.className="card-header",a.style.cssText="display:flex;align-items:center;gap:.5rem;";const s=document.createElement("input");s.type="text",s.className="form-input conn-name",s.value=n,s.placeholder="Connection name",s.style.cssText="flex:1;";const r=document.createElement("button");r.type="button",r.className="btn btn-sm btn-danger",r.textContent="Delete",r.addEventListener("click",()=>{d=x(e);const L=s.value.trim();L&&delete d[L],C(e),v(e)}),a.appendChild(s),a.appendChild(r);const m=document.createElement("div");m.className="card-body",m.style.cssText="display:grid;grid-template-columns:1fr 2fr 1fr;gap:.6rem;";const p=document.createElement("div"),u=document.createElement("label");u.className="form-label",u.textContent="Type";const f=document.createElement("input");f.type="text",f.className="form-input conn-type",f.value=c.type||"mongodb",f.disabled=!0,p.appendChild(u),p.appendChild(f);const w=document.createElement("div"),S=document.createElement("label");S.className="form-label",S.textContent="URI";const y=document.createElement("input");y.type="text",y.className="form-input conn-uri",y.value=c.uri||"",y.placeholder="mongodb://localhost:27017",w.appendChild(S),w.appendChild(y);const N=document.createElement("div"),k=document.createElement("label");k.className="form-label",k.textContent="Database";const g=document.createElement("input");g.type="text",g.className="form-input conn-database",g.value=c.database||"",g.placeholder="mydb",N.appendChild(k),N.appendChild(g),m.appendChild(p),m.appendChild(w),m.appendChild(N),l.appendChild(a),l.appendChild(m),i.appendChild(l)})}function x(e){const i={},o=e.find("#connections-list").get(0)?.querySelectorAll(".conn-card")||[];for(const t of o){const n=t.querySelector(".conn-name")?.value.trim(),c=t.querySelector(".conn-uri")?.value.trim()||"",l=t.querySelector(".conn-database")?.value.trim()||"";n&&(i[n]={type:"mongodb",uri:c,database:l,options:{}})}return i}function v(e){const i=e.find("#connections-raw-json").get(0);i&&(i.value=JSON.stringify(d,null,2))}