@brightsideoy/kama 1.0.0-alpha.20 → 1.0.0-alpha.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 (65) hide show
  1. package/content/definitions/blocks/image-gallery.yaml +34 -0
  2. package/content/definitions/blocks/youtube.yaml +8 -0
  3. package/content/definitions/field-sets/access.yaml +10 -0
  4. package/content/definitions/field-sets/page-base.yaml +16 -1
  5. package/content/definitions/taxonomies/media-tag.yaml +15 -0
  6. package/definitions/editor/default.ts +15 -1
  7. package/dist/assets/AssetEditor-B4W7tV1a.js +1 -0
  8. package/dist/assets/AssetEditor-D9sz6bfN.css +1 -0
  9. package/dist/assets/CmsFieldTaxonomy-CVlKL-l2.css +1 -0
  10. package/dist/assets/CmsFieldTaxonomy-C_AwHDwY.js +1 -0
  11. package/dist/assets/{CmsHelp-DyPJLGGi.js → CmsHelp-BQkr9KyU.js} +1 -1
  12. package/dist/assets/{CmsPublisher-DNLwjirk.js → CmsPublisher-XSCPrp5L.js} +1 -1
  13. package/dist/assets/NodeEditor-4TsNvk2f.css +1 -0
  14. package/dist/assets/NodeEditor-DA5GRtRP.js +161 -0
  15. package/dist/assets/{TrashWorkspace-DgIg1v6t.js → TrashWorkspace-CATe46WF.js} +1 -1
  16. package/dist/assets/index-CY0VYSyt.css +1 -0
  17. package/dist/assets/index-DdG9Pozx.js +14 -0
  18. package/dist/assets/{plus-FQRsZBoJ.js → plus-CX_GHzXs.js} +1 -1
  19. package/dist/assets/useNodes-CqFlc72m.js +1 -0
  20. package/dist/{dist-D_Q1y4Kh.js → dist-3Xc2TTZw.js} +1117 -456
  21. package/dist/index.html +4 -4
  22. package/dist/index.js +1117 -456
  23. package/dist/schema-compiler.js +1 -1
  24. package/package.json +5 -5
  25. package/schema.sql +10 -0
  26. package/templates/astro-starter/src/components/global/NavigationMenu.astro +11 -3
  27. package/dist/assets/AssetEditor-D5j7pwcK.css +0 -1
  28. package/dist/assets/AssetEditor-Dt1zCR7_.js +0 -1
  29. package/dist/assets/NodeEditor-CiXQKXK1.js +0 -147
  30. package/dist/assets/NodeEditor-pZI3gu4a.css +0 -1
  31. package/dist/assets/index-DQ6_RmCI.js +0 -14
  32. package/dist/assets/index-DcKiaRjI.css +0 -1
  33. package/dist/assets/useNodes-D2-VxsxR.js +0 -1
  34. package/templates/astro-starter/old_src/components/blocks/BlockRenderer.astro +0 -143
  35. package/templates/astro-starter/old_src/components/blocks/ColumnLayout.astro +0 -67
  36. package/templates/astro-starter/old_src/components/blocks/HeaderImage.astro +0 -126
  37. package/templates/astro-starter/old_src/components/blocks/Hero.astro +0 -218
  38. package/templates/astro-starter/old_src/components/blocks/HtmlBlock.astro +0 -25
  39. package/templates/astro-starter/old_src/components/blocks/ImageBlock.astro +0 -91
  40. package/templates/astro-starter/old_src/components/blocks/NodeList.astro +0 -274
  41. package/templates/astro-starter/old_src/components/blocks/TextBlock.astro +0 -15
  42. package/templates/astro-starter/old_src/components/global/Breadcrumb.astro +0 -108
  43. package/templates/astro-starter/old_src/components/global/Footer.astro +0 -50
  44. package/templates/astro-starter/old_src/components/global/Header.astro +0 -171
  45. package/templates/astro-starter/old_src/components/global/MetaHead.astro +0 -266
  46. package/templates/astro-starter/old_src/components/global/NavigationMenu.astro +0 -413
  47. package/templates/astro-starter/old_src/components/ui/KamaImage.astro +0 -180
  48. package/templates/astro-starter/old_src/layouts/SkeletonLayout.astro +0 -56
  49. package/templates/astro-starter/old_src/layouts/StandardLayout.astro +0 -63
  50. package/templates/astro-starter/old_src/lib/cms.ts +0 -219
  51. package/templates/astro-starter/old_src/lib/media/kama-image-service.ts +0 -67
  52. package/templates/astro-starter/old_src/lib/media/media-proxy.ts +0 -148
  53. package/templates/astro-starter/old_src/lib/media/media-url.ts +0 -112
  54. package/templates/astro-starter/old_src/middleware.ts +0 -536
  55. package/templates/astro-starter/old_src/pages/404.astro +0 -46
  56. package/templates/astro-starter/old_src/pages/[...slug].astro +0 -311
  57. package/templates/astro-starter/old_src/pages/api/load-nodes.ts +0 -68
  58. package/templates/astro-starter/old_src/pages/api/partials/node-cards.astro +0 -101
  59. package/templates/astro-starter/old_src/pages/llms-full.txt.ts +0 -171
  60. package/templates/astro-starter/old_src/pages/llms.txt.ts +0 -113
  61. package/templates/astro-starter/old_src/pages/media/[...path].ts +0 -14
  62. package/templates/astro-starter/old_src/pages/partials/footer.astro +0 -69
  63. package/templates/astro-starter/old_src/pages/partials/nav.astro +0 -141
  64. package/templates/astro-starter/old_src/styles/standard-theme.css +0 -157
  65. package/templates/astro-starter/old_src/utils/tiptap.ts +0 -113
@@ -1 +0,0 @@
1
- .global-top-bar[data-v-aa116e0a]{background-color:var(--cms-color-surface);border-bottom:1px solid var(--cms-color-border);z-index:100;flex-shrink:0;justify-content:space-between;align-items:center;height:48px;padding:0 14px;transition:background .3s;display:flex;position:relative}.global-top-bar.has-status-bg[data-v-aa116e0a]{background-color:#fff5f7;background-image:repeating-linear-gradient(-45deg,#f472b614,#f472b614 10px,#0000 10px 20px)}.logo-area[data-v-aa116e0a]{z-index:2;align-items:center;gap:10px;display:flex}@media (width>=769px){.mobile-only-btn[data-v-aa116e0a]{display:none!important}}.sidebar-toggle-chip[data-v-aa116e0a]{color:var(--cms-color-text-muted);cursor:pointer;transition:color var(--cms-transition-fast);background:0 0;border:none;border-radius:50%;outline:none;align-items:center;padding:0;display:inline-flex}.toggle-icon-wrapper[data-v-aa116e0a]{width:28px;height:28px;color:var(--cms-color-text-muted);transition:color var(--cms-transition-fast), border-color var(--cms-transition-fast);border-radius:50%;justify-content:center;align-items:center;margin-left:-4px;display:flex;position:relative}.sidebar-toggle-chip:hover .toggle-icon-wrapper[data-v-aa116e0a],.hamburger-icon.is-open .bar[data-v-aa116e0a]{color:var(--cms-color-primary)}.hamburger-icon[data-v-aa116e0a]{flex-direction:column;justify-content:space-between;width:12px;height:6px;display:flex;position:relative}.hamburger-icon .bar[data-v-aa116e0a]{background-color:currentColor;border-radius:1px;width:100%;height:1.5px;transition:transform .25s cubic-bezier(.4,0,.2,1);display:block}.hamburger-icon .bar-top[data-v-aa116e0a],.hamburger-icon .bar-bottom[data-v-aa116e0a]{transform-origin:50%}.hamburger-icon.is-open .bar-top[data-v-aa116e0a]{transform:translateY(2.25px)rotate(45deg)}.hamburger-icon.is-open .bar-bottom[data-v-aa116e0a]{transform:translateY(-2.25px)rotate(-45deg)}.version-link[data-v-aa116e0a]{color:var(--cms-color-text-faint);transition:color var(--cms-transition-fast);margin-bottom:0;margin-left:2px;font-size:9px;line-height:1;text-decoration:none}.version-link[data-v-aa116e0a]:hover{color:var(--cms-color-text-muted);text-decoration:underline}.logo[data-v-aa116e0a]{-webkit-user-select:none;user-select:none;cursor:pointer;width:60px;height:auto;transition:opacity var(--cms-transition-fast);background:0 0;border:none;outline:none;align-items:center;margin-left:4px;padding:0;display:flex}.logo[data-v-aa116e0a]:hover{opacity:.75}.logo svg[data-v-aa116e0a]{width:100%;height:auto;display:block}.center-status-area[data-v-aa116e0a]{pointer-events:none;z-index:1;justify-content:center;align-items:center;display:flex;position:absolute;left:50%;transform:translate(-50%)}.status-badge[data-v-aa116e0a]{font-family:var(--cms-font-sans);border-radius:9999px;align-items:center;gap:6px;padding:4px 12px;font-size:12px;font-weight:600;display:inline-flex;box-shadow:0 1px 2px #0000000d}.status-badge.status-warning[data-v-aa116e0a]{color:#92400e;background-color:#fef3c7;border:1px solid #fde68a}.status-badge.status-danger[data-v-aa116e0a]{color:#9f1239;background-color:#ffe4e6;border:1px solid #fecdd3}.status-badge.status-info[data-v-aa116e0a]{color:#075985;background-color:#e0f2fe;border:1px solid #bae6fd}.animate-spin[data-v-aa116e0a]{animation:1s linear infinite spin-aa116e0a}@keyframes spin-aa116e0a{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.user-area[data-v-aa116e0a]{z-index:2;align-items:center;gap:10px;display:flex}.topbar-icon-btn[data-v-aa116e0a]{color:var(--cms-color-text-muted);cursor:pointer;transition:color var(--cms-transition-fast);background:0 0;border:none;border-radius:50%;outline:none;align-items:center;padding:0;display:inline-flex}.icon-bubble[data-v-aa116e0a]{width:28px;height:28px;transition:all var(--cms-transition-fast);border-radius:50%;justify-content:center;align-items:center;display:flex;position:relative}.topbar-icon-btn.is-active-view .icon-bubble[data-v-aa116e0a]{color:var(--cms-color-primary)!important}.publish-btn .btn-icon[data-v-aa116e0a]{margin-top:1px;margin-left:-1px}.publish-count-badge[data-v-aa116e0a]{color:var(--cms-color-text-main);border-radius:9999px;justify-content:center;align-items:center;min-width:15px;height:15px;padding:0 3px;font-size:11px;font-weight:700;line-height:1;display:flex;position:absolute;bottom:-2px;right:-5px}.topbar-icon-btn.is-active-view .publish-count-badge[data-v-aa116e0a]{color:var(--cms-color-primary)!important}@media (width<=640px){.center-status-area[data-v-aa116e0a]{display:none}}.channel-selector-row[data-v-1633f33b]{width:100%;margin-bottom:12px}.channel-trigger-btn[data-v-1633f33b]{background:var(--cms-color-surface,#fff);border:1px solid var(--cms-color-border,#e2e8f0);border-radius:var(--cms-radius-md,6px);width:100%;color:var(--cms-color-text-main,#0f172a);font-family:var(--cms-font-sans);cursor:pointer;align-items:center;gap:8px;padding:8px 12px;font-size:13px;font-weight:500;transition:all .15s;display:flex}.channel-trigger-btn[data-v-1633f33b]:hover{border-color:var(--cms-color-border-dark,#cbd5e1);background:var(--cms-color-surface-hover,#f8fafc)}.channel-trigger-btn.is-open[data-v-1633f33b]{border-color:var(--cms-color-primary,#3b82f6)}.trigger-icon[data-v-1633f33b]{color:var(--cms-color-text-faint,#64748b)}.trigger-label[data-v-1633f33b]{text-align:left;white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.trigger-chevron[data-v-1633f33b]{color:var(--cms-color-text-faint,#64748b);transition:transform .2s}.channel-trigger-btn.is-open .trigger-chevron[data-v-1633f33b]{transform:rotate(180deg)}.tree-item-wrapper[data-v-61c96ae9]{flex-direction:column;display:flex}.tree-node[data-v-61c96ae9]{border-radius:var(--cms-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--cms-font-sans);color:var(--cms-color-text-main);transition:all var(--cms-transition-fast);--node-badge-bg:var(--cms-color-bg);border:1px solid #0000;align-items:center;gap:4px;margin:0 -4px;padding:5px 4px;font-size:12.5px;display:flex}.tree-node[data-v-61c96ae9]:hover:not(.is-active){background:var(--cms-color-surface-hover);border-color:var(--cms-color-border);--node-badge-bg:var(--cms-color-surface-hover)}.tree-node.is-active[data-v-61c96ae9]{background:var(--cms-color-primary-light);border-color:var(--cms-color-primary-border);--node-badge-bg:var(--cms-color-primary-light);font-weight:500}@keyframes draft-pulse-61c96ae9{0%{opacity:.5}50%{opacity:.85}to{opacity:.5}}.tree-node.is-draft[data-v-61c96ae9]{border:1px dashed var(--cms-color-border-dark);background:0 0;animation:2s ease-in-out infinite draft-pulse-61c96ae9}.tree-node.is-draft .node-title[data-v-61c96ae9]{color:var(--cms-color-text-muted);font-style:italic}.icon-wrapper[data-v-61c96ae9]{flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;margin-right:2px;display:inline-flex;position:relative}.drag-handle-tree[data-v-61c96ae9]{cursor:grab}.drag-handle-tree[data-v-61c96ae9]:active{cursor:grabbing}.node-icon[data-v-61c96ae9]{color:var(--cms-color-text-faint);transition:color var(--cms-transition-fast)}.toggle-btn[data-v-61c96ae9]{width:16px;height:16px;color:var(--cms-color-text-muted);cursor:pointer;border-radius:var(--cms-radius-xs);transition:background var(--cms-transition-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;padding:2px;display:flex}.toggle-btn[data-v-61c96ae9]:hover{color:var(--cms-color-text-main);background:#0f172a0f}.toggle-placeholder[data-v-61c96ae9]{flex-shrink:0;width:16px;height:16px}.node-title[data-v-61c96ae9]{text-overflow:ellipsis;white-space:nowrap;flex-grow:1;overflow:hidden}.node-actions[data-v-61c96ae9]{opacity:0;transition:opacity var(--cms-transition-fast);align-items:center;display:flex}.tree-node:hover .node-actions[data-v-61c96ae9],.node-actions.menu-open[data-v-61c96ae9]{opacity:1}.action-btn[data-v-61c96ae9]{border-radius:var(--cms-radius-xs);color:var(--cms-color-text-muted);cursor:pointer;transition:all var(--cms-transition-fast);background:0 0;border:none;justify-content:center;align-items:center;padding:3px;display:flex}.action-btn[data-v-61c96ae9]:hover{background:var(--cms-color-border-dark);color:var(--cms-color-text-main)}.nested-tree[data-v-61c96ae9]{padding-left:14px}.tree-drag-area[data-v-61c96ae9]{min-height:3px}.node-tree-container[data-v-18960262]{flex-direction:column;flex:1;display:flex}.tree-header[data-v-18960262]{justify-content:space-between;align-items:center;margin-bottom:8px;padding:0 2px;display:flex}.tree-title[data-v-18960262]{font-family:var(--cms-font-sans);text-transform:uppercase;letter-spacing:.06em;color:var(--cms-color-text-muted);font-size:11px;font-weight:700}.tree-loading[data-v-18960262]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);justify-content:center;align-items:center;gap:6px;padding:12px;font-size:11px;display:flex}.add-root-btn[data-v-18960262]{border-radius:var(--cms-radius-sm);color:var(--cms-color-text-muted);cursor:pointer;font-family:var(--cms-font-sans);transition:all var(--cms-transition-fast);background:0 0;border:none;align-items:center;gap:4px;padding:2px 6px;font-size:11px;font-weight:550;display:flex}.add-root-btn[data-v-18960262]:hover{background:var(--cms-color-surface-hover);color:var(--cms-color-primary)}.add-root-btn[data-v-18960262]:active{transform:scale(.96)}.tree-drag-root[data-v-18960262]{flex-direction:column;gap:3px;min-height:20px;display:flex}.empty-tree-state[data-v-18960262]{background:var(--cms-color-surface-hover);border:1px dashed var(--cms-color-border-dark);border-radius:var(--cms-radius-md);text-align:center;margin-top:4px;padding:16px 12px}.empty-tree-state p[data-v-18960262]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);margin:0 0 10px;font-size:12px}.primary-btn[data-v-18960262]{font-family:var(--cms-font-sans);border-radius:var(--cms-radius-sm);background:var(--cms-color-primary);color:#fff;box-shadow:var(--cms-shadow-xs);cursor:pointer;transition:all var(--cms-transition-fast);border:none;align-items:center;gap:4px;padding:6px 12px;font-size:12px;font-weight:600;display:inline-flex}.primary-btn[data-v-18960262]:hover{background:var(--cms-color-primary-hover);box-shadow:var(--cms-shadow-sm)}.primary-btn[data-v-18960262]:active{transform:scale(.97)}.spin[data-v-18960262]{animation:1s linear infinite spin-18960262}@keyframes spin-18960262{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.tree-pane[data-v-33bb18de]{min-height:0;font-family:var(--cms-font-sans);-ms-overflow-style:none;scrollbar-width:none;flex:1;padding:0 4px 80px;overflow-x:hidden;overflow-y:auto!important}.tree-pane[data-v-33bb18de]::-webkit-scrollbar{display:none}.tree-stack[data-v-33bb18de]{flex-direction:column;gap:12px;display:flex}.tree-block[data-v-33bb18de]{transition:transform var(--cms-transition-fast);flex-direction:column;display:flex}.tree-label-row[data-v-33bb18de]{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;padding:4px 0;display:flex}.tree-block.is-transfer-source .tree-label-row[data-v-33bb18de]{outline:1px dashed var(--cms-color-text-muted);outline-offset:4px;border-radius:2px}.toggle-btn[data-v-33bb18de]{color:var(--cms-color-text-muted);cursor:pointer;border-radius:var(--cms-radius-xs);background:0 0;border:none;justify-content:center;align-items:center;padding:2px;display:flex}.toggle-btn[data-v-33bb18de]:hover{color:var(--cms-color-text-main);background:#0f172a0f}.tree-title[data-v-33bb18de]{text-transform:uppercase;letter-spacing:.05em;color:var(--cms-color-text-muted);white-space:nowrap;text-overflow:ellipsis;padding:2px 0;font-size:11px;font-weight:700;overflow:hidden}.tree-block.is-selected .tree-title[data-v-33bb18de]{color:var(--cms-color-primary)}.tree-title.is-hidden-text[data-v-33bb18de]{opacity:.6}.tree-badges[data-v-33bb18de]{align-items:center;gap:4px;margin-left:auto;display:flex}.status-badge[data-v-33bb18de]{border-radius:var(--cms-radius-full);text-transform:uppercase;letter-spacing:.02em;align-items:center;gap:3px;padding:1px 6px;font-size:9.5px;font-weight:600;display:inline-flex}.status-badge.draft[data-v-33bb18de]{background:var(--cms-color-primary-light);color:var(--cms-color-primary);border:1px solid var(--cms-color-primary-border)}.status-badge.hidden[data-v-33bb18de]{background:var(--cms-color-danger-light);color:var(--cms-color-danger);border:1px solid var(--cms-color-danger-border)}.status-badge.scheduled[data-v-33bb18de]{background:var(--cms-color-warning-light,#fef3c7);color:var(--cms-color-warning,#d97706);border:1px solid var(--cms-color-warning-border,#fcd34d)}.status-badge.expired[data-v-33bb18de]{background:var(--cms-color-muted-light,#f3f4f6);color:var(--cms-color-text-muted);border:1px solid var(--cms-color-border)}.action-buttons[data-v-33bb18de]{opacity:0;transition:opacity var(--cms-transition-fast);align-items:center;gap:2px;display:flex}.tree-label-row:hover .action-buttons[data-v-33bb18de],.action-buttons.menu-open[data-v-33bb18de]{opacity:1}.icon-btn[data-v-33bb18de]{color:var(--cms-color-text-muted);border-radius:var(--cms-radius-xs);cursor:pointer;transition:all var(--cms-transition-fast);background:0 0;border:none;justify-content:center;align-items:center;padding:4px;display:flex}.icon-btn[data-v-33bb18de]:hover{background:var(--cms-color-surface-hover);color:var(--cms-color-text-main)}.cancel-transfer-btn .hover-icon[data-v-33bb18de],.cancel-transfer-btn:hover .default-icon[data-v-33bb18de]{display:none}.cancel-transfer-btn:hover .hover-icon[data-v-33bb18de]{display:block}.cancel-transfer-btn[data-v-33bb18de]:hover{color:var(--cms-color-danger);background:var(--cms-color-danger-light)}.tree-nodes-wrap[data-v-33bb18de]{padding-left:6px}.empty-trees-state[data-v-33bb18de]{background:var(--cms-color-surface-hover);border:1px dashed var(--cms-color-border-dark);border-radius:var(--cms-radius-md);text-align:center;flex-direction:column;justify-content:center;align-items:center;margin-top:4px;padding:24px 12px;display:flex}.empty-trees-state p[data-v-33bb18de]{color:var(--cms-color-text-muted);margin:0 0 10px;font-size:12px}.create-first-btn[data-v-33bb18de]{border-radius:var(--cms-radius-sm);background:var(--cms-color-primary);color:#fff;cursor:pointer;transition:all var(--cms-transition-fast);border:none;align-items:center;gap:4px;padding:5px 10px;font-size:11.5px;font-weight:600;display:inline-flex}.create-first-btn[data-v-33bb18de]:hover{background:var(--cms-color-primary-hover)}.vault-pane[data-v-775ad774]{flex-direction:column;height:100%;min-height:0;display:flex;overflow:hidden!important}.fixed-vault-controls[data-v-775ad774]{background:var(--cms-color-bg);flex-shrink:0;padding-top:2px;padding-bottom:6px}.asset-filter-banner[data-v-775ad774]{background:var(--cms-color-primary-light);color:var(--cms-color-primary);font-size:11px;font-family:var(--cms-font-sans);text-align:center;cursor:pointer;border-bottom:1px solid var(--cms-color-primary-border);flex-shrink:0;padding:6px 12px;font-weight:600}.asset-filter-banner[data-v-775ad774]:hover{background:var(--cms-color-primary);color:#fff}.vault-scroll-area[data-v-775ad774]{-ms-overflow-style:none;scrollbar-width:none;flex:1;min-height:0;padding-top:6px;overflow-x:hidden;overflow-y:auto!important}.vault-scroll-area[data-v-775ad774]::-webkit-scrollbar{display:none}.search-bar[data-v-775ad774]{background:var(--cms-color-surface-hover);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-sm);align-items:center;gap:6px;margin-bottom:8px;padding:5px 8px;display:flex}.search-icon[data-v-775ad774]{color:var(--cms-color-text-muted)}.search-input[data-v-775ad774]{font-family:var(--cms-font-sans);color:var(--cms-color-text-main);background:0 0;border:none;outline:none;width:100%;font-size:13px}.search-input[data-v-775ad774]::placeholder{color:var(--cms-color-text-muted)}.filter-bar[data-v-775ad774]{flex-wrap:wrap;gap:6px 4px;margin-bottom:8px;padding-bottom:8px;display:flex}.filter-pill[data-v-775ad774]{font-family:var(--cms-font-sans);border-radius:var(--cms-radius-full);border:1px solid var(--cms-color-border);background:var(--cms-color-surface);color:var(--cms-color-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--cms-transition-fast);outline:none;padding:3px 9px;font-size:10.5px;font-weight:600}.filter-pill[data-v-775ad774]:hover:not(.active){border-color:var(--cms-color-border-dark);color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.filter-pill.active[data-v-775ad774]{background:var(--cms-color-primary);color:#fff;border-color:var(--cms-color-primary);box-shadow:var(--cms-shadow-xs)}.pane-header[data-v-775ad774]{justify-content:space-between;align-items:center;gap:8px;padding:0 4px;display:flex}.sort-wrapper[data-v-775ad774]{flex:1;align-items:center;gap:4px;min-width:0;display:flex}.sort-dropdown-wrapper[data-v-775ad774]{flex:1;min-width:0;display:flex;position:relative}.sort-trigger-btn[data-v-775ad774]{border-radius:var(--cms-radius-sm);width:100%;font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);cursor:pointer;transition:color var(--cms-transition-fast), background var(--cms-transition-fast);text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:4px;height:24px;padding:2px 6px;font-size:11.5px;font-weight:500;display:flex}.sort-trigger-btn[data-v-775ad774]:hover{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.sort-label[data-v-775ad774]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.sort-chevron[data-v-775ad774]{flex-shrink:0}.pane-icon-btn[data-v-775ad774]{border-radius:var(--cms-radius-sm);cursor:pointer;color:var(--cms-color-text-muted);transition:color var(--cms-transition-fast), background var(--cms-transition-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:flex}.pane-icon-btn[data-v-775ad774]:hover{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.pane-icon-btn.add-content-btn[data-v-775ad774]:hover{color:var(--cms-color-primary)}.vault-list[data-v-775ad774]{flex-direction:column;gap:3px;padding:0 8px 90px;display:flex}.tree-tag-icon[data-v-775ad774],.asset-tag-icon[data-v-775ad774],.count-text[data-v-775ad774]{color:var(--cms-color-text-muted)}.scroll-sentinel[data-v-775ad774]{text-align:center;padding:12px 0 90px}.loading-text[data-v-775ad774],.end-text[data-v-775ad774]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);font-size:11px}.empty-vault-state[data-v-775ad774]{background:var(--cms-color-surface-hover);border:1px dashed var(--cms-color-border-dark);border-radius:var(--cms-radius-md);text-align:center;margin-top:4px;padding:16px 12px}.empty-vault-state p[data-v-775ad774]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);margin:0 0 10px;font-size:12px}.primary-btn[data-v-775ad774]{font-family:var(--cms-font-sans);border-radius:var(--cms-radius-sm);background:var(--cms-color-primary);color:#fff;box-shadow:var(--cms-shadow-xs);cursor:pointer;transition:all var(--cms-transition-fast);border:none;align-items:center;gap:4px;padding:6px 12px;font-size:12px;font-weight:600;display:inline-flex}.primary-btn[data-v-775ad774]:hover{background:var(--cms-color-primary-hover);box-shadow:var(--cms-shadow-sm)}.primary-btn[data-v-775ad774]:active{transform:scale(.97)}.media-pane[data-v-f646bfd3]{flex-direction:column;height:100%;min-height:0;display:flex;position:relative;overflow:hidden!important}.collision-overlay[data-v-f646bfd3]{z-index:100;background:var(--cms-color-overlay,#02061773);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);justify-content:center;align-items:center;padding:24px;display:flex;position:absolute;inset:0}.collision-card[data-v-f646bfd3]{background:var(--cms-color-surface);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-md);width:100%;max-width:400px;font-family:var(--cms-font-sans);flex-direction:column;gap:16px;padding:20px;display:flex}.collision-header[data-v-f646bfd3]{align-items:center;gap:10px;display:flex}.collision-header h3[data-v-f646bfd3]{color:var(--cms-color-text-main);margin:0;font-size:15px}.text-warning[data-v-f646bfd3]{color:var(--cms-color-warning,#f59e0b)}.collision-body p[data-v-f646bfd3]{color:var(--cms-color-text-muted);margin:0 0 8px;font-size:13px}.collision-warning[data-v-f646bfd3]{color:var(--cms-color-warning,#d97706);background:var(--cms-color-warning-light,#fef3c7);border-radius:var(--cms-radius-sm);border:1px solid var(--cms-color-warning-border,#fde68a);padding:8px;font-weight:600}.collision-actions[data-v-f646bfd3]{flex-direction:column;gap:8px;margin-top:8px;display:flex}.hidden-file-input[data-v-f646bfd3]{display:none}.drag-overlay[data-v-f646bfd3]{z-index:50;background:var(--cms-color-primary,#2563ebd9);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);color:#fff;font-family:var(--cms-font-sans);border-radius:var(--cms-radius-md);flex-direction:column;justify-content:center;align-items:center;gap:8px;font-size:13px;font-weight:600;display:flex;position:absolute;inset:0}.fixed-media-controls[data-v-f646bfd3]{background:var(--cms-color-bg);flex-shrink:0;padding-top:2px;padding-bottom:6px}.node-filter-banner[data-v-f646bfd3]{background:var(--cms-color-primary-light);color:var(--cms-color-primary);font-size:11px;font-family:var(--cms-font-sans);text-align:center;cursor:pointer;flex-shrink:0;padding:6px 12px;font-weight:600}.node-filter-banner[data-v-f646bfd3]:hover{background:var(--cms-color-primary);color:#fff}.search-bar[data-v-f646bfd3]{background:var(--cms-color-surface-hover);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-sm);align-items:center;gap:6px;margin-bottom:8px;padding:5px 8px;display:flex}.search-icon[data-v-f646bfd3]{color:var(--cms-color-text-muted)}.search-input[data-v-f646bfd3]{font-family:var(--cms-font-sans);color:var(--cms-color-text-main);background:0 0;border:none;outline:none;width:100%;font-size:13px}.search-input[data-v-f646bfd3]::placeholder{color:var(--cms-color-text-muted)}.filter-bar[data-v-f646bfd3]{flex-wrap:wrap;gap:6px 4px;margin-bottom:8px;padding-bottom:8px;display:flex}.filter-pill[data-v-f646bfd3]{font-family:var(--cms-font-sans);border-radius:var(--cms-radius-full);border:1px solid var(--cms-color-border);background:var(--cms-color-surface);color:var(--cms-color-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--cms-transition-fast);outline:none;padding:3px 9px;font-size:10.5px;font-weight:600}.filter-pill[data-v-f646bfd3]:hover:not(.active){border-color:var(--cms-color-border-dark);color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.filter-pill.active[data-v-f646bfd3]{background:var(--cms-color-primary);color:#fff;border-color:var(--cms-color-primary)}.pane-header[data-v-f646bfd3]{justify-content:space-between;align-items:center;gap:8px;padding:0 4px;display:flex}.sort-wrapper[data-v-f646bfd3]{flex:1;align-items:center;gap:4px;min-width:0;display:flex}.sort-dropdown-wrapper[data-v-f646bfd3]{flex:1;min-width:0;display:flex;position:relative}.sort-trigger-btn[data-v-f646bfd3]{border-radius:var(--cms-radius-sm);width:100%;font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);cursor:pointer;transition:color var(--cms-transition-fast), background var(--cms-transition-fast);text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:4px;height:24px;padding:2px 6px;font-size:11.5px;font-weight:500;display:flex}.sort-trigger-btn[data-v-f646bfd3]:hover{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.sort-label[data-v-f646bfd3]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.sort-chevron[data-v-f646bfd3]{flex-shrink:0}.pane-icon-btn[data-v-f646bfd3]{border-radius:var(--cms-radius-sm);cursor:pointer;color:var(--cms-color-text-muted);transition:color var(--cms-transition-fast), background var(--cms-transition-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:flex}.pane-icon-btn[data-v-f646bfd3]:hover{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.pane-icon-btn.add-content-btn[data-v-f646bfd3]:hover{color:var(--cms-color-primary)}.media-scroll-area[data-v-f646bfd3]{-ms-overflow-style:none;scrollbar-width:none;flex:1;min-height:0;padding:8px 2px 80px;overflow-x:hidden;overflow-y:auto!important}.media-scroll-area[data-v-f646bfd3]::-webkit-scrollbar{display:none}.uploading-banner[data-v-f646bfd3]{background:var(--cms-color-primary-light);border:1px solid var(--cms-color-primary-border);border-radius:var(--cms-radius-sm);color:var(--cms-color-primary);font-family:var(--cms-font-sans);align-items:center;gap:6px;margin-bottom:8px;padding:6px 10px;font-size:11px;font-weight:600;display:flex}.media-list[data-v-f646bfd3]{flex-direction:column;gap:6px;display:flex}.item-details[data-v-f646bfd3]{pointer-events:none;flex-direction:column;flex:1;justify-content:center;min-width:0;display:flex}.meta-row[data-v-f646bfd3]{flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;display:flex}.empty-media-state[data-v-f646bfd3]{color:var(--cms-color-text-muted);border:1px dashed var(--cms-color-border-dark);border-radius:var(--cms-radius-md);cursor:pointer;transition:background var(--cms-transition-fast);flex-direction:column;justify-content:center;align-items:center;margin-top:8px;padding:32px 12px;display:flex}.empty-media-state[data-v-f646bfd3]:hover{background:var(--cms-color-surface-hover)}.empty-icon[data-v-f646bfd3]{color:var(--cms-color-text-faint);margin-bottom:6px}.empty-sub[data-v-f646bfd3]{font-family:var(--cms-font-sans);color:var(--cms-color-text-faint);margin-top:4px;font-size:10px}.scroll-sentinel[data-v-f646bfd3]{text-align:center;padding:12px 0 60px}.loading-text[data-v-f646bfd3],.end-text[data-v-f646bfd3]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);font-size:11px}.spin[data-v-f646bfd3]{animation:1s linear infinite spin-f646bfd3}@keyframes spin-f646bfd3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.node-tag-icon[data-v-f646bfd3],.variant-tag[data-v-f646bfd3]{color:var(--cms-color-text-muted);align-items:center;gap:3px;display:flex}.count-text[data-v-f646bfd3]{color:var(--cms-color-text-muted);font-size:11px;font-weight:500}.vault-pane[data-v-282056a0]{flex-direction:column;height:100%;min-height:0;display:flex;overflow:hidden!important}.fixed-vault-controls[data-v-282056a0]{background:var(--cms-color-bg);flex-shrink:0;padding-top:2px;padding-bottom:6px}.vault-scroll-area[data-v-282056a0]{-ms-overflow-style:none;scrollbar-width:none;flex:1;min-height:0;padding-top:6px;overflow-x:hidden;overflow-y:auto!important}.vault-scroll-area[data-v-282056a0]::-webkit-scrollbar{display:none}.search-bar[data-v-282056a0]{background:var(--cms-color-surface-hover);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-sm);align-items:center;gap:6px;margin-bottom:8px;padding:5px 8px;display:flex}.search-icon[data-v-282056a0]{color:var(--cms-color-text-muted)}.search-input[data-v-282056a0]{font-family:var(--cms-font-sans);color:var(--cms-color-text-main);background:0 0;border:none;outline:none;width:100%;font-size:13px}.search-input[data-v-282056a0]::placeholder{color:var(--cms-color-text-muted)}.filter-bar[data-v-282056a0]{flex-wrap:wrap;gap:6px 4px;margin-bottom:8px;padding-bottom:8px;display:flex}.filter-pill[data-v-282056a0]{font-family:var(--cms-font-sans);border-radius:var(--cms-radius-full);border:1px solid var(--cms-color-border);background:var(--cms-color-surface);color:var(--cms-color-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--cms-transition-fast);outline:none;padding:3px 9px;font-size:10.5px;font-weight:600}.filter-pill[data-v-282056a0]:hover:not(.active){border-color:var(--cms-color-border-dark);color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.filter-pill.active[data-v-282056a0]{background:var(--cms-color-primary);color:#fff;border-color:var(--cms-color-primary);box-shadow:var(--cms-shadow-xs)}.pane-header[data-v-282056a0]{justify-content:space-between;align-items:center;gap:8px;padding:0 4px;display:flex}.sort-wrapper[data-v-282056a0]{flex:1;align-items:center;gap:4px;min-width:0;display:flex}.sort-dropdown-wrapper[data-v-282056a0]{flex:1;min-width:0;display:flex;position:relative}.sort-trigger-btn[data-v-282056a0]{border-radius:var(--cms-radius-sm);width:100%;font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);cursor:pointer;transition:color var(--cms-transition-fast), background var(--cms-transition-fast);text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:4px;height:24px;padding:2px 6px;font-size:11.5px;font-weight:500;display:flex}.sort-trigger-btn[data-v-282056a0]:hover{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.sort-label[data-v-282056a0]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.sort-chevron[data-v-282056a0]{flex-shrink:0}.pane-icon-btn[data-v-282056a0]{border-radius:var(--cms-radius-sm);cursor:pointer;color:var(--cms-color-text-muted);transition:color var(--cms-transition-fast), background var(--cms-transition-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:flex}.pane-icon-btn[data-v-282056a0]:hover{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover)}.pane-icon-btn.add-content-btn[data-v-282056a0]:hover{color:var(--cms-color-primary)}.vault-list[data-v-282056a0]{flex-direction:column;gap:3px;padding:0 8px 90px;display:flex}.scroll-sentinel[data-v-282056a0]{text-align:center;padding:12px 0 90px}.loading-text[data-v-282056a0]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);font-size:11px}.empty-vault-state[data-v-282056a0]{background:var(--cms-color-surface-hover);border:1px dashed var(--cms-color-border-dark);border-radius:var(--cms-radius-md);text-align:center;margin-top:4px;padding:16px 12px}.empty-vault-state p[data-v-282056a0]{font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);margin:0 0 10px;font-size:12px}.primary-btn[data-v-282056a0]{font-family:var(--cms-font-sans);border-radius:var(--cms-radius-sm);background:var(--cms-color-primary);color:#fff;box-shadow:var(--cms-shadow-xs);cursor:pointer;transition:all var(--cms-transition-fast);border:none;align-items:center;gap:4px;padding:6px 12px;font-size:12px;font-weight:600;display:inline-flex}.primary-btn[data-v-282056a0]:hover{background:var(--cms-color-primary-hover);box-shadow:var(--cms-shadow-sm)}.primary-btn[data-v-282056a0]:active{transform:scale(.97)}.panel-tree[data-v-44fc8b2b]{box-sizing:border-box;background:var(--cms-color-bg);border-right:1px solid var(--cms-color-border);-webkit-user-select:none;user-select:none;flex-direction:column;flex-shrink:0;width:260px;height:100%;max-height:100vh;padding:18px 14px 12px;display:flex;overflow:hidden}.segmented-control[data-v-44fc8b2b]{background:var(--cms-color-surface-hover);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-md);flex-shrink:0;gap:2px;margin-bottom:14px;padding:3px;display:flex}.tab-btn[data-v-44fc8b2b]{color:var(--cms-color-text-muted);border-radius:var(--cms-radius-sm);cursor:pointer;transition:all var(--cms-transition-fast);font-family:var(--cms-font-sans);background:0 0;border:none;outline:none;flex:1;justify-content:center;align-items:center;font-weight:550;display:inline-flex;overflow:hidden}.tab-btn span[data-v-44fc8b2b]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.tab-icon[data-v-44fc8b2b]{opacity:.75;transition:opacity var(--cms-transition-fast);flex-shrink:0}.tab-btn[data-v-44fc8b2b]:hover:not(.active){color:var(--cms-color-text-main);background:#0f172a08}.tab-btn:hover:not(.active) .tab-icon[data-v-44fc8b2b]{opacity:1}.tab-btn.active[data-v-44fc8b2b]{background:var(--cms-color-surface);color:var(--cms-color-primary)}.tab-btn.active .tab-icon[data-v-44fc8b2b]{opacity:1;color:var(--cms-color-primary)}.tab-btn[data-v-44fc8b2b]:active{transform:scale(.98)}.pane-wrapper[data-v-44fc8b2b]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.sidebar-footer[data-v-44fc8b2b]{border-top:1px solid var(--cms-color-border);flex-shrink:0;margin-top:0;padding-top:8px}.trash-btn[data-v-44fc8b2b]{width:100%;font-family:var(--cms-font-sans);color:var(--cms-color-text-muted);border-radius:var(--cms-radius-sm);cursor:pointer;transition:all var(--cms-transition-fast);background:0 0;border:1px solid #0000;align-items:center;gap:8px;padding:8px 10px;font-size:13px;font-weight:500;display:flex}.trash-icon[data-v-44fc8b2b]{opacity:.7;transition:opacity .2s}.trash-btn[data-v-44fc8b2b]:hover{color:var(--cms-color-danger,#ef4444);background:#ef44440d}.trash-btn:hover .trash-icon[data-v-44fc8b2b]{opacity:1}.trash-btn.is-active[data-v-44fc8b2b]{color:var(--cms-color-danger,#ef4444);background:#ef44441a;border-color:#ef444433;font-weight:600}.trash-btn.is-active .trash-icon[data-v-44fc8b2b]{opacity:1}.dashboard-canvas[data-v-e6b6e0e0]{padding:var(--cms-page-padding,32px);background:var(--cms-color-bg);font-family:var(--cms-font-sans);flex-grow:1;justify-content:center;align-items:flex-start;display:flex;overflow-y:auto}.dashboard-container[data-v-e6b6e0e0]{width:100%;margin:0 auto}.widgets-grid[data-v-e6b6e0e0]{grid-template-columns:repeat(auto-fit,minmax(min(100%,380px),1fr));gap:20px;margin-bottom:32px;display:grid}.dashboard-widget[data-v-e6b6e0e0]{background:var(--cms-color-surface);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-md);flex-direction:column;padding:24px;display:flex;overflow:hidden}.widget-header[data-v-e6b6e0e0]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.widget-title[data-v-e6b6e0e0]{align-items:center;gap:8px;display:flex}.widget-title h4[data-v-e6b6e0e0]{color:var(--cms-color-text-main);margin:0;font-size:15px;font-weight:600}.widget-icon[data-v-e6b6e0e0]{color:var(--cms-color-text-main)}.count-badge[data-v-e6b6e0e0]{background:var(--cms-color-primary);color:#fff;border-radius:9999px;padding:2px 8px;font-size:11px;font-weight:700;line-height:1.2}.publisher-link-btn[data-v-e6b6e0e0]{background:var(--cms-color-primary-light);color:var(--cms-color-primary);border:1px solid var(--cms-color-primary-border);border-radius:var(--cms-radius-full);cursor:pointer;transition:all var(--cms-transition-fast);align-items:center;gap:6px;padding:4px 10px;font-size:11.5px;font-weight:600;display:inline-flex}.publisher-link-btn[data-v-e6b6e0e0]:hover{background:var(--cms-color-primary);color:#fff}.widget-body[data-v-e6b6e0e0]{flex:1}.caught-up-banner[data-v-e6b6e0e0]{align-items:center;gap:12px;margin-bottom:12px;display:flex}.banner-text[data-v-e6b6e0e0]{flex-direction:column;font-size:12px;line-height:1.5em;display:flex}.history-list[data-v-e6b6e0e0]{flex-direction:column;max-height:320px;margin:0;display:flex;overflow-y:auto}.published-check[data-v-e6b6e0e0]{color:var(--cms-color-success,#10b981);flex-shrink:0}.node-icon[data-v-e6b6e0e0]{color:var(--cms-color-text-faint);flex-shrink:0}.history-title[data-v-e6b6e0e0]{color:var(--cms-color-text-main);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:550;overflow:hidden}.history-time[data-v-e6b6e0e0]{color:var(--cms-color-text-muted);font-size:11.5px;font-family:var(--cms-font-mono);align-items:center;gap:6px;display:flex}.hover-arrow[data-v-e6b6e0e0]{color:var(--cms-color-primary)}.empty-widget-state[data-v-e6b6e0e0]{text-align:center;color:var(--cms-color-text-muted);flex-direction:column;justify-content:center;align-items:center;padding:32px 16px;display:flex}.empty-icon[data-v-e6b6e0e0]{color:var(--cms-color-text-faint);margin-bottom:8px}.empty-widget-state p[data-v-e6b6e0e0]{margin:0;font-size:12.5px}.stats-content[data-v-e6b6e0e0]{align-items:center;gap:32px;display:flex}.stat-total-block[data-v-e6b6e0e0]{flex-direction:column;min-width:100px;display:flex}.stat-big-number[data-v-e6b6e0e0]{color:var(--cms-color-text-main);letter-spacing:-.03em;margin-bottom:6px;font-size:44px;font-weight:800;line-height:1}.stat-subtitle[data-v-e6b6e0e0]{text-transform:uppercase;letter-spacing:.05em;color:var(--cms-color-text-muted);font-size:11px;font-weight:600}.stat-breakdown-list[data-v-e6b6e0e0]{flex-direction:column;flex-grow:1;gap:12px;display:flex}.breakdown-row[data-v-e6b6e0e0]{flex-direction:column;gap:4px;display:flex}.breakdown-meta[data-v-e6b6e0e0]{justify-content:space-between;align-items:center;font-size:12px;font-weight:500;display:flex}.breakdown-label[data-v-e6b6e0e0]{color:var(--cms-color-text-main)}.breakdown-count[data-v-e6b6e0e0]{color:var(--cms-color-text-muted);font-family:var(--cms-font-mono)}.breakdown-track[data-v-e6b6e0e0]{background:var(--cms-color-surface-hover);border-radius:var(--cms-radius-full);width:100%;height:5px;overflow:hidden}.breakdown-fill[data-v-e6b6e0e0]{background:var(--cms-color-primary);border-radius:var(--cms-radius-full);height:100%;transition:width .8s cubic-bezier(.16,1,.3,1)}@media (width<=900px){.stats-content[data-v-e6b6e0e0]{flex-direction:column;align-items:flex-start;gap:16px}.dashboard-widget[data-v-e6b6e0e0]{padding:16px}}.modal-overlay[data-v-8a386e23]{z-index:9999;background:var(--cms-color-overlay,#02061780);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);justify-content:center;align-items:center;padding:16px;display:flex;position:fixed;inset:0}.modal-card[data-v-8a386e23]{background:var(--cms-color-surface);border:1px solid var(--cms-color-border);border-radius:var(--cms-radius-lg);width:100%;max-width:420px;box-shadow:var(--cms-shadow-lg);font-family:var(--cms-font-sans);flex-direction:column;gap:16px;padding:24px;display:flex;position:relative}.close-btn[data-v-8a386e23]{color:var(--cms-color-text-faint);cursor:pointer;border-radius:var(--cms-radius-sm);transition:background-color var(--cms-transition-fast), color var(--cms-transition-fast);background:0 0;border:none;padding:4px;position:absolute;top:16px;right:16px}.close-btn[data-v-8a386e23]:hover{background:var(--cms-color-surface-hover);color:var(--cms-color-text-main)}.modal-header[data-v-8a386e23]{align-items:center;gap:12px;display:flex}.icon-bubble[data-v-8a386e23]{border-radius:var(--cms-radius-full);background:var(--cms-color-warning-light);border:1px solid var(--cms-color-warning-border);flex-shrink:0;justify-content:center;align-items:center;width:40px;height:40px;display:flex}.icon-bubble.is-delete[data-v-8a386e23]{background:var(--cms-color-danger-light);border-color:var(--cms-color-danger-border)}.warning-icon[data-v-8a386e23]{color:var(--cms-color-warning)}.icon-bubble.is-delete .warning-icon[data-v-8a386e23]{color:var(--cms-color-danger)}.modal-header h3[data-v-8a386e23]{color:var(--cms-color-text-main);margin:0;font-size:16px;font-weight:700}.modal-body p[data-v-8a386e23]{color:var(--cms-color-text-muted);margin:0;font-size:13.5px;line-height:1.6}[data-v-8a386e23] .highlight-entity{color:var(--cms-color-text-main);background:var(--cms-color-surface-hover);border-radius:var(--cms-radius-sm);border:1px solid var(--cms-color-border);font-weight:700;font-family:var(--cms-font-mono);padding:2px 6px;font-size:12.5px}.modal-actions[data-v-8a386e23]{justify-content:flex-end;align-items:center;gap:10px;margin-top:8px;display:flex}.btn[data-v-8a386e23]{height:36px;font-family:var(--cms-font-sans);border-radius:var(--cms-radius-md);cursor:pointer;transition:all var(--cms-transition-fast);border:1px solid #0000;outline:none;padding:0 16px;font-size:13px;font-weight:600}.btn-discard[data-v-8a386e23]{background:var(--cms-color-danger);color:var(--cms-color-surface)}.btn-discard[data-v-8a386e23]:hover{background:var(--cms-color-danger-hover);box-shadow:var(--cms-shadow-xs)}.btn-discard[data-v-8a386e23]:active{background:var(--cms-color-danger-active,#991b1b)}.btn-discard[data-v-8a386e23]:focus-visible{box-shadow:0 0 0 2px var(--cms-color-danger-border)}.btn-keep[data-v-8a386e23]{background:var(--cms-color-primary);color:var(--cms-color-surface)}.btn-keep[data-v-8a386e23]:hover{background:var(--cms-color-primary-hover);box-shadow:var(--cms-shadow-xs)}.btn-keep[data-v-8a386e23]:focus-visible{box-shadow:0 0 0 2px var(--cms-color-focus-ring)}.modal-fade-enter-active[data-v-8a386e23],.modal-fade-leave-active[data-v-8a386e23]{transition:opacity var(--cms-transition-normal), transform var(--cms-transition-normal)}.modal-fade-enter-from[data-v-8a386e23],.modal-fade-leave-to[data-v-8a386e23]{opacity:0;transform:scale(.96)}html,body{width:100%;height:100%;margin:0;padding:0}.cms-app-container{background-color:var(--cms-color-surface);flex-direction:column;width:100vw;height:100vh;display:flex;overflow:hidden}.cms-editor{font-family:var(--cms-font-sans);color:var(--cms-color-text-main);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;flex-grow:1;display:flex;position:relative;overflow:hidden}.sidebar-container{width:var(--sidebar-width);background:var(--cms-color-surface);z-index:40;flex-direction:column;flex-shrink:0;height:100%;display:flex}.sidebar-container>*{flex-grow:1;width:100%!important}.main-content-container{z-index:1;flex-direction:column;flex:1;min-width:0;height:100%;display:flex;position:relative}.sidebar-backdrop{z-index:98;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background-color:#0f172a66;position:absolute;inset:0}@media (width<=768px){.main-content-container{z-index:1!important}.sidebar-container{box-shadow:none;transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;position:absolute;top:0;bottom:0;left:0;transform:translate(-320px);z-index:99!important;width:280px!important}.sidebar-container.is-open{transform:translate(0);box-shadow:4px 0 16px #00000026;width:280px!important}}:root{--cms-font-sans:"Chakra Petch", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--cms-font-mono:"Roboto Mono", "Geist Mono", "Fira Code", monospace;--cms-radius-xs:2px;--cms-radius-sm:4px;--cms-radius-md:6px;--cms-radius-lg:8px;--cms-radius-full:9999px;--cms-color-primary:#2563eb;--cms-color-primary-hover:#1d4ed8;--cms-color-primary-light:#eff6ff;--cms-color-primary-border:#93c5fd;--cms-color-danger:#dc2626;--cms-color-danger-hover:#b91c1c;--cms-color-danger-light:transparent;--cms-color-danger-border:#f58989;--cms-color-warning:#ea580c;--cms-color-warning-light:#fff7ed;--cms-color-warning-border:#fdba74;--cms-color-success:#028200;--cms-color-success-light:transparent;--cms-color-success-border:#18b500;--cms-color-info:#2563eb;--cms-color-info-light:transparent;--cms-color-info-border:#509af4;--cms-color-sync:#7c3aed;--cms-color-sync-light:transparent;--cms-color-sync-border:#ddd6fe;--cms-color-offline:#db2777;--cms-color-offline-light:#fdf2f8;--cms-color-offline-border:#fbcfe8;--cms-color-draft:#475569;--cms-color-draft-light:transparent;--cms-color-draft-border:#90949b;--cms-color-bg:#f8fafc;--cms-color-surface:#fff;--cms-color-surface-hover:#f1f5f9;--cms-color-surface-active:#e2e8f0;--cms-color-popover:#fff;--cms-color-border:#d6dce4;--cms-color-border-dark:#b8bfc8;--cms-color-border-input:#64748b;--cms-color-focus-ring:#2563eb40;--cms-color-text-main:#020617;--cms-color-text-subtle:#334155;--cms-color-text-muted:#475569;--cms-color-text-faint:#64748b;--cms-shadow-xs:0 1px 2px 0 #0000000a;--cms-shadow-sm:0 1px 3px 0 #00000014, 0 1px 2px -1px #0000000a;--cms-shadow-md:0 4px 6px -1px #00000014, 0 2px 4px -2px #0000000a, 0 0 0 1px var(--cms-color-border);--cms-shadow-lg:0 10px 15px -3px #00000014, 0 4px 6px -4px #0000000a, 0 0 0 1px var(--cms-color-border);--cms-transition-fast:.1s cubic-bezier(.4, 0, .2, 1);--cms-transition-normal:.2s cubic-bezier(.4, 0, .2, 1);--cms-color-overlay:#02061773;--cms-color-danger-active:#991b1b;--cms-page-padding:32px}@media (width<=768px){:root{--cms-page-padding:16px}}*{box-sizing:border-box}body{font-family:var(--cms-font-sans);color:var(--cms-color-text-main);background-color:var(--cms-color-bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tiptap :last-child{margin-bottom:0}p,ul,ol{margin:0 0 1.25em;line-height:1.6em}li p{margin-bottom:0}
@@ -1 +0,0 @@
1
- import{$ as e,At as t,P as n,W as r,Y as i,j as a,v as o}from"./_plugin-vue_export-helper-CQxWhVtr.js";import{a as s,d as c,l,n as u,o as d,p as f,r as p,s as m,t as h,u as g}from"./schema-helpers-DvficKko.js";var _=t({iban:()=>v}),v=(e,t,n)=>!e||!t||/^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/.test(String(e).toUpperCase())?``:n.rules?.customMessage||`Invalid IBAN format.`,y=t({isMagicWord:()=>b}),b=(e,t,n)=>e&&e.toLowerCase()!==`magic`?n.rules?.customMessage||`You didn't say the magic word!`:``,x=e=>e==null||typeof e==`string`&&e.trim()===``,S={required:(e,t,n)=>(t===!0||String(t).toLowerCase()===`true`)&&x(e)?n.rules?.customMessage||`${n.label||`This field`} is required.`:``,min:(e,t,n)=>x(e)||typeof t!=`number`?``:typeof e==`number`&&e<t?n.rules?.customMessage||`${n.label||`Field`} must be at least ${t}.`:typeof e==`string`&&e.length<t?n.rules?.customMessage||`${n.label||`Field`} must be at least ${t} characters.`:``,max:(e,t,n)=>x(e)||typeof t!=`number`?``:typeof e==`number`&&e>t?n.rules?.customMessage||`${n.label||`Field`} cannot exceed ${t}.`:typeof e==`string`&&e.length>t?n.rules?.customMessage||`${n.label||`Field`} cannot exceed ${t} characters.`:``,email:(e,t,n)=>t!==!0&&String(t).toLowerCase()!==`true`||x(e)||/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(e))?``:n.rules?.customMessage||`Please enter a valid email address.`,pattern:(e,t,n)=>{if(x(e)||!t||typeof t!=`string`)return``;try{if(!new RegExp(t).test(String(e)))return n.rules?.customMessage||`${n.label||`Field`} format is invalid.`}catch{console.warn(`[Validators] Invalid pattern for ${n.label||`field`}:`,t)}return``},unique:async(e,t,n,r)=>(t!==!0&&String(t).toLowerCase()!==`true`||x(e),``),uniqueSibling:async(e,t,n,r)=>(t!==!0&&String(t).toLowerCase()!==`true`||x(e),``)};function C(e,t){S[e]=t}function w(){let e=Object.assign({"../../definitions/validators/iban.ts":_,"../../definitions/validators/magic-word.ts":y});for(let t in e){let n=e[t];if(!n)continue;let r=t.split(`/`).pop()?.replace(/\.ts$/,``)||``;for(let[e,t]of Object.entries(n))typeof t==`function`&&C(e==="default"?r:e,t)}}w();function T(e,t,n){if(!n||typeof n!=`object`)return``;let r=n.rules||{},i={fieldKey:e};if((n.required===!0||String(n.required).toLowerCase()===`true`||r.required===!0||String(r.required).toLowerCase()===`true`)&&x(t))return r.customMessage||`${n.label||e} is required.`;for(let[e,a]of Object.entries(r)){if(e===`customMessage`||e===`uniqueMessage`||e===`unique`||e===`uniqueSibling`||e===`required`)continue;let r=S[e];if(r){let e=r(t,a,n,i);if(typeof e==`string`&&e!==``)return e}}return``}async function E(e,t,n,r){if(!n||typeof n!=`object`)return``;let i=T(e,t,n);if(i)return i;let a={...n.rules};n.unique!==void 0&&a.unique===void 0&&(a.unique=n.unique);let o={fieldKey:e,entityType:r?.entityType,excludeId:r?.excludeId,formData:r?.formData};for(let[e,r]of Object.entries(a)){if(e===`customMessage`||e===`uniqueMessage`)continue;let i=S[e];if(i){let e=await i(t,r,n,o);if(e)return e}}return``}function D(e){for(let t in e){let n=e[t];if(n)for(let[e,t]of Object.entries(n))typeof t==`function`&&C(e,t)}}function ee(){let{validationErrors:e}=m(),t=(e,t)=>{if(e)return t in e?e[t]:t.split(`.`).reduce((e,t)=>e&&e[t]!==void 0?e[t]:void 0,e)};return{validateAgainstSchema:async(n,r,i)=>{let a={};if(!n||!r)return e.value=a,!0;let o={...r.fields||{}};if(r.tabs&&typeof r.tabs==`object`&&Object.values(r.tabs).forEach(e=>{e?.fields&&(Array.isArray(e.fields)?e.fields.forEach(e=>{typeof e==`object`&&e&&Object.entries(e).forEach(([e,t])=>{o[e]={...o[e]||{},...t}})}):typeof e.fields==`object`&&Object.entries(e.fields).forEach(([e,t])=>{o[e]={...o[e]||{},...t}}))}),Object.keys(o).length===0)return e.value=a,!0;let s=n.id,c=typeof s==`number`||s&&!String(s).startsWith(`draft-`)?String(s):``;for(let[e,r]of Object.entries(o)){if(!r||typeof r!=`object`)continue;let o=await E(e,t(n,e),r,{entityType:i,excludeId:c,formData:n});o&&(a[e]=o)}return e.value=a,Object.keys(a).length===0}}}var O=null,k=null;function te(){let{allChannels:e,selectedChannelId:t,availableTrees:n,channelSchemas:r,treeSchemas:i}=m(),a=async()=>{O?.abort(),O=new AbortController;try{let[n,i]=await Promise.all([fetch(`/api/cms/schemas.json`,{signal:O.signal}),fetch(`/api/cms/channels.json`,{signal:O.signal})]);if(n.ok){let e=await n.json();e.channelSchemas&&(r.value=e.channelSchemas)}if(i.ok){let n=await i.json();e.value=n.channels||[],!t.value&&n.channels?.length>0&&(t.value=String(n.channels[0].id))}}catch(e){if(e instanceof DOMException&&e.name===`AbortError`)return;console.error(`[CMS Sync] Failed to fetch channels:`,e)}},o=async()=>{k?.abort(),k=new AbortController;try{let[e,t]=await Promise.all([fetch(`/api/cms/schemas.json`,{signal:k.signal}),fetch(`/api/cms/trees.json`,{signal:k.signal})]);if(e.ok){let t=await e.json();t.treeSchemas&&(i.value=t.treeSchemas)}if(t.ok){let e=await t.json();n.value=Array.isArray(e)?e:[]}}catch(e){if(e instanceof DOMException&&e.name===`AbortError`)return;console.error(`[CMS Sync] Failed to load trees:`,e)}};return{fetchChannels:a,fetchTrees:o,syncSystemMetadata:async()=>{await Promise.all([a(),o()])}}}function A(e){return e===!0||e===1||String(e)===`true`||String(e)===`1`}function ne(e,t=Date.now()){if(!e)return{isDraft:!1,isUnpublishedDraft:!1,isHidden:!1,isScheduled:!1,isUpcoming:!1,isShowing:!1,isPassed:!1,isCurrentlyVisible:!1,hasUnpublishedChanges:!1,statusBadge:`active`,badgeLabel:`Unknown`};let n=!!(e.isNew||!e.id||String(e.id).startsWith(`draft-`)),r=!n&&e.status===`draft`&&!e.publishedAt,i=A(e.isHidden)||A(e.disabled),a=!n&&!r&&A(e.hasUnpublishedChanges),o={};if(e.dataJson)try{o=typeof e.dataJson==`string`?JSON.parse(e.dataJson):e.dataJson}catch{}let s=!r&&o.startShowingAt!==void 0?o.startShowingAt:e.startShowingAt,c=!r&&o.stopShowingAt!==void 0?o.stopShowingAt:e.stopShowingAt,l=s?new Date(s).getTime():null,u=c?new Date(c).getTime():null,d=!!(l||u),f=t,p=!0,m=!1,h=!1,g=!1;d&&(l&&f<l?(p=!1,m=!0):u&&f>u?(p=!1,h=!0):g=!0);let _=!n&&!r&&!i&&p,v=`active`,y=`Visible`;return n?(v=`draft`,y=`Unsaved`):r?(v=`unpublished_draft`,y=`Draft`):a?(v=`unpublished_changes`,y=`Unpublished Changes`):i?(v=`hidden`,y=`Hidden`):m?(v=`scheduled_pending`,y=`Upcoming`):h?(v=`scheduled_expired`,y=`Expired`):g&&d&&(y=`Currently Showing`),{isDraft:n,isUnpublishedDraft:r,isHidden:i,isScheduled:d,isUpcoming:m,isShowing:g,isPassed:h,isCurrentlyVisible:_,hasUnpublishedChanges:a,statusBadge:v,badgeLabel:y}}i();var j=e({}),M=e([]),N=e({}),P=e(!1),F=()=>{let e=[];Object.values(j.value).forEach(t=>{Array.isArray(t)&&e.push(...t)}),M.value=e};function I(){let{taxonomySchemas:e,setNotification:t,setViewMode:n,taxonomySnapshot:r}=m(),i=async e=>{if(e){P.value=!0;try{let t=await fetch(`/api/cms/taxonomies/${e}`);if(t.ok){let n=await t.json(),r=n.items||n.terms||(Array.isArray(n)?n:[]);j.value={...j.value,[e]:r.map(t=>({...t,taxonomy:t.taxonomy||e}))}}else j.value={...j.value,[e]:[]};F()}catch(t){console.error(`[useTaxonomies] Failed to fetch terms:`,t),j.value={...j.value,[e]:[]}}finally{P.value=!1}}};return{terms:M,termsMap:j,activeTerm:N,isLoading:P,fetchTerms:i,fetchAllTaxonomies:async()=>{let t=e.value||{},n=Object.keys(t);n.length>0&&await Promise.all(n.map(e=>i(e)))},loadTerm:async(e,a)=>{if(String(a)===`new`||String(a).startsWith(`draft-`)){N.value={id:`draft-${Date.now()}`,key:``,label:``,taxonomy:e,parentId:null},r&&(r.value=JSON.stringify(N.value));return}let o=M.value.find(e=>String(e.id)===String(a));if(o)N.value={...o,...o.data||{}},r&&(r.value=JSON.stringify(N.value));else{await i(e);let o=M.value.find(e=>String(e.id)===String(a));o?(N.value={...o,...o.data||{}},r&&(r.value=JSON.stringify(N.value))):(t(`Term not found`,`error`),n(`none`))}},saveTerm:async e=>{if(!N.value||!N.value.label)return t(`Label is required`,`error`),!1;let n=String(N.value.id).startsWith(`draft-`),a=n?`POST`:`PUT`,o=n?`/api/cms/taxonomies/${e}`:`/api/cms/taxonomies/${e}/${N.value.id}`,s=[`id`,`taxonomy`,`key`,`label`,`parentId`,`sortOrder`,`createdAt`,`updatedAt`,`data`,`dataJson`],c={};for(let e of Object.keys(N.value))s.includes(e)||(c[e]=N.value[e]);let l={label:N.value.label,key:N.value.key,parentId:N.value.parentId,sortOrder:N.value.sortOrder,data:c};try{let s=await fetch(o,{method:a,headers:{"Content-Type":`application/json`},body:JSON.stringify(l)}),c=await s.json();return s.ok?(t(`Term ${n?`created`:`updated`} successfully`,`success`),await i(e),n&&c.id&&(N.value.id=c.id),r&&(r.value=JSON.stringify(N.value)),!0):(t(c.error||`Failed to save term`,`error`),!1)}catch{return t(`An error occurred while saving`,`error`),!1}},deleteTerm:async(e,n)=>{try{return(await fetch(`/api/cms/taxonomies/${e}/${n}`,{method:`DELETE`})).ok?(t(`Term deleted successfully`,`success`),await i(e),!0):(t(`Failed to delete term`,`error`),!1)}catch{return t(`An error occurred while deleting`,`error`),!1}}}}a();var L=(e,t)=>{if(!e)return{};let n={},r=e.nodeType||e.contentType,i=r?t[r]:null,a=new Set([`id`,`title`,`slug`,`nodeType`,`channelId`,`language`]);i&&(i.fields&&Object.entries(i.fields).forEach(([e,t])=>{t?.liveSync!==!0&&a.add(e)}),i.tabs&&Object.values(i.tabs).forEach(e=>{e.fields&&Object.entries(e.fields).forEach(([e,t])=>{t?.liveSync!==!0&&a.add(e)})}));let o=Object.keys(e).filter(e=>a.has(e)).sort();for(let t of o){let r=e[t];n[t]=r&&typeof r==`object`&&typeof r.id==`string`&&r.id.startsWith(`ast_`)?r.id:r}return n};function R(){let e=m(),{activeTerm:t}=I(),{confirmDiscard:n}=c(),r=o(()=>{if(e.isDocumentLoading.value||e.isSnapshotMode.value||!e.nodeSnapshot.value)return!1;let t=JSON.parse(e.nodeSnapshot.value||`{}`),n=t.node||{};return e.activeNode.value.id===n.id&&JSON.stringify({node:L(e.activeNode.value,e.nodeSchemas.value),blocks:e.blocks.value})!==JSON.stringify({node:L(n,e.nodeSchemas.value),blocks:t.blocks||{}})}),i=o(()=>e.isSnapshotMode.value||!e.treeSnapshot.value||!e.activeTreeSettings.value?!1:JSON.stringify(e.activeTreeSettings.value)!==e.treeSnapshot.value),a=o(()=>e.isSnapshotMode.value||!e.channelSnapshot.value||!e.activeChannelSettings.value?!1:JSON.stringify(e.activeChannelSettings.value)!==e.channelSnapshot.value),s=o(()=>e.isSnapshotMode.value||!e.taxonomySnapshot.value||!t.value?!1:JSON.stringify(t.value)!==e.taxonomySnapshot.value),l=o(()=>e.isSnapshotMode.value?!1:e.activeViewMode.value===`node`?r.value:e.activeViewMode.value===`tree`?i.value:e.activeViewMode.value===`channel`?a.value:e.activeViewMode.value===`taxonomy`&&s.value);return{isNodeDirty:r,isTreeDirty:i,isChannelDirty:a,isTaxonomyDirty:s,isGlobalDirty:l,confirmNavigation:async()=>!l.value||await n(`You have unsaved changes. If you leave, your changes will be lost.`,`Discard unsaved changes?`,`Discard Changes`,`Cancel`)}}a(),i();var re=0,z=0,B=e({});function V(){let{allChannels:t,selectedChannelId:n,selectedLanguage:r,availableTrees:i,activeTreeSettings:a,selectedTreeId:s,nodeTree:c,vaultNodes:l,treeTemplateSchema:d,treeSchemas:h,activeNode:g,blocks:_,regionMeta:v,selectedBlock:y,validationErrors:b,nodeSnapshot:x,treeSnapshot:S,activeTab:C,shouldFocusTitle:w,setViewMode:T,currentVaultType:E,currentVaultSearch:D,currentVaultSort:O,currentVaultOrder:k}=m(),{validateAgainstSchema:ne}=ee(),{fetchTrees:j,fetchChannels:M,syncSystemMetadata:N}=te(),{confirmNavigation:P}=R(),F=e(!1),I=e(!0),L=e(0),V=()=>u(h,f),H=()=>{S.value=JSON.stringify(a.value||{})},U=o(()=>{if(!n.value||n.value===`all`)return i.value.map(e=>({id:e.id,key:e.key,label:e.label||e.key||`Tree ${e.id}`}));let e=t.value.find(e=>String(e.id)===String(n.value));return!e||!Array.isArray(e.trees)?[]:e.trees.map(e=>{let t=typeof e==`object`?e.treeId||e.id:e;if(!t)return null;let n=i.value.find(e=>String(e.id)===String(t)||e.key===t);return n?{id:n.id,key:n.key,label:n.label||n.key||`Tree ${n.id}`}:null}).filter(Boolean)}),W=(e,t,n=null)=>{for(let r of e){if(String(r.id)===String(t))return n;if(r.children&&r.children.length>0){let e=W(r.children,t,r);if(e)return e}}return null},G=(e,t)=>{if(!e||!Array.isArray(e))return!1;for(let n of e){if(String(n.id)===String(t.id))return n.disabledRegions={...t.disabledRegions||{}},t.channels&&(n.channels=t.channels),t.title!==void 0&&(n.title=t.title),t.slug!==void 0&&(n.slug=t.slug),t.isHidden!==void 0&&(n.isHidden=A(t.isHidden)),t.status!==void 0&&(n.status=t.status),t.isDraft!==void 0&&(n.isDraft=A(t.isDraft)),t.draftDataJson!==void 0&&(n.draftDataJson=t.draftDataJson),t.dataJson!==void 0&&(n.dataJson=t.dataJson),!0;if(n.children&&n.children.length>0&&G(n.children,t))return!0}return!1},K=o(()=>g.value?.id?!!W(c.value,g.value.id):!1),ie=e=>B.value[e]||[],ae=async e=>{if(e)try{let t=n.value&&n.value!==`all`?`&channelId=${n.value}`:``,i=await fetch(`/api/cms/tree.json?treeId=${e}&lang=${r.value}&preview=true${t}`);if(i.ok){let t=await i.json(),n=Array.isArray(t)?t:t.tree||[],r=new Set,a=[];for(let e of n){if(e.deletedAt&&String(e.deletedAt).trim()!==``)continue;let t=String(e.id);r.has(t)||(r.add(t),a.push({...e,isHidden:A(e.isHidden),isDraft:e.isDraft===void 0?void 0:A(e.isDraft)}))}B.value[e]=a,String(e)===String(s.value)&&(c.value=a)}}catch(t){console.error(`[CMS] Failed to fetch nodes for tree ${e}:`,t)}},q=async()=>{if(!s.value){c.value=[];return}++re,await ae(s.value)},oe=async(e,t)=>{B.value[e]=t,String(e)===String(s.value)&&(c.value=t);try{let i={treeId:e,language:r.value,tree:t};n.value&&n.value!==`all`&&(i.channelId=n.value);let a=await fetch(`/api/cms/tree.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i)});if(!a.ok){let e=await a.json().catch(()=>({}));throw Error(`[Tree Save] HTTP ${a.status}: ${e.error||`Unknown error`}`)}}catch(t){throw console.error(`[Tree Sync] Failed to save node order for tree ${e}:`,t),t}},se=async()=>{s.value&&await oe(s.value,B.value[s.value]||c.value)},J=async e=>{let t=!1,r=``,i=``;typeof e==`string`?(E.value=e,t=!0):e&&typeof e==`object`&&(t=e.reset??!1,e.type!==void 0&&(E.value=e.type),e.search!==void 0&&(D.value=e.search),e.sort!==void 0&&(O.value=e.sort),e.order!==void 0&&(k.value=e.order),e.ensureItemId&&(r=e.ensureItemId),e.assetId&&(i=e.assetId));let a=Array.isArray(E.value)&&E.value.length>0?E.value.join(`,`):E.value||`all`,o=D.value||``;if(!t&&F.value||!t&&!I.value)return;let s=++z;t&&(L.value=0,I.value=!0,l.value=[]),F.value=!0;try{let e=new URLSearchParams({limit:`50`,offset:String(L.value),sort:O.value,order:k.value});a&&a!==`all`&&e.append(`type`,a),o.trim()&&e.append(`q`,o.trim()),n.value&&n.value!==`all`&&e.append(`channelId`,n.value),r&&e.append(`ensureItemId`,r),i&&e.append(`assetId`,i);let c=await fetch(`/api/cms/nodes.json?${e.toString()}`);if(s!==z)return;if(!c.ok)throw Error(`Failed to fetch vault nodes (${c.status})`);let u=await c.json(),d=(Array.isArray(u)?u:u.items||[]).map(e=>({...e,isHidden:A(e.isHidden)}));I.value=!Array.isArray(u)&&!!u.hasMore,l.value=t?d:[...l.value,...d],L.value+=d.length}catch(e){s===z&&console.error(`[CMS] Failed to fetch vault nodes:`,e)}finally{s===z&&(F.value=!1)}},Y=async e=>{if(!n.value||n.value===`all`)return;let r=t.value.findIndex(e=>String(e.id)===String(n.value));if(r>-1){let n=t.value[r],a=Array.isArray(n.trees)?[...n.trees]:[],o=i.value.find(t=>String(t.id)===String(e)||t.key===e),c=o?o.id:e,l=o?o.key:String(e);a.some(e=>String(typeof e==`object`?e.treeId||e.id:e)===String(c)||(typeof e==`object`?e.treeId||e.id:e)===l)||(a.push({treeId:c,key:l}),(await fetch(`/api/cms/channels.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({...n,trees:a})})).ok&&await M()),s.value=String(c),await q()}},X=async e=>{if(!n.value||n.value===`all`)return;let r=t.value.findIndex(e=>String(e.id)===String(n.value));if(r>-1){let n={...t.value[r]};Array.isArray(n.trees)&&(n.trees=n.trees.filter(t=>String(typeof t==`object`?t.treeId||t.id:t)!==String(e)),await fetch(`/api/cms/channels.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}),await M());let i=U.value;s.value=i.length>0?String(i[0].id):``,await q()}},Z=async(e,r)=>{if(!n.value||n.value===`all`)return;let i=t.value.findIndex(e=>String(e.id)===String(n.value));if(i>-1){let n={...t.value[i]},a=Array.isArray(n.trees)?[...n.trees]:[];if(e<0||e>=a.length||r<0||r>=a.length)return;let[o]=a.splice(e,1);a.splice(r,0,o),n.trees=a,t.value[i]=n;try{await fetch(`/api/cms/channels.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)})}catch(e){console.error(`Failed to reorder channel trees:`,e)}}},Q=async()=>{a.value=null,S.value=``,await T(`none`,!0)};return{currentChannelTrees:U,hasParentNode:K,isLoading:F,hasMore:I,treeNodesMap:B,getNodesForTree:ie,fetchNodeTreeForId:ae,saveTreeOrderForId:oe,reorderChannelTrees:Z,fetchTrees:j,fetchNodeTree:q,fetchVaultNodes:J,linkTreeToChannel:Y,unlinkTreeFromChannel:X,handleAddNewTree:async()=>{if(!await P())return!1;let e={id:`draft-${Date.now()}`,isNew:!0,key:``,label:``,treeType:``,channels:n.value&&n.value!==`all`?[Number(n.value)||n.value]:[]};return a.value=e,H(),b.value={},await T(`tree`,!0),!0},cancelNewTree:Q,saveTreeSettings:async()=>{if(!a.value)return!1;b.value={};let e=V(),t=!a.value.id||String(a.value.id).startsWith(`draft-`),r=a.value.treeType||Object.keys(e)[0]||`navigation`,i=e[r]||{};if(!await ne(a.value,{fields:p(i,d.value)},`tree`))return!1;try{let e=a.value.id,i={...JSON.parse(JSON.stringify(a.value)),id:t?null:typeof e==`number`?e:Number(e)||null,treeType:r};delete i.isNew;let o=await fetch(`/api/cms/trees.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i)});if(o.ok){let e=(await o.json()).id;return a.value.id=e,a.value.treeType=r,delete a.value.isNew,await N(),H(),t&&n.value&&n.value!==`all`?await Y(e):(s.value=String(e),await q()),await T(`tree`,!0),!0}{let e=await o.json().catch(()=>({}));return o.status===409&&e.field&&(b.value={[e.field]:e.error||`This key is already in use.`}),!1}}catch(e){return console.error(`[CMS] Error saving tree settings:`,e),!1}},deleteTree:async e=>{let n=e||a.value?.id;if(n){if(String(n).startsWith(`draft-`)){await Q();return}try{let e=await fetch(`/api/cms/trees.json?id=${n}`,{method:`DELETE`});if(e.ok){a.value=null,t.value.forEach(e=>{Array.isArray(e.trees)&&(e.trees=e.trees.filter(e=>{let t=typeof e==`object`?e.treeId||e.id:e;return String(t)!==String(n)}))}),await N();let e=U.value;if(e.length>0){let t=String(e[0].id);s.value=t,await q()}else s.value=``,c.value=[],await T(`none`,!0)}else{let t=await e.json().catch(()=>({}));alert(`Failed to delete tree. ${t.error||`Check server console.`}`)}}catch{alert(`Network error: Could not reach server to delete the tree.`)}}},saveTreeOrder:se,attachVaultNodeToTree:async(e,t=null)=>{if(!s.value)return alert(`Please select a Navigation Tree before attaching content.`);try{let i={action:`attach`,contentId:e,treeId:s.value,language:r.value,parentId:t?t.id:null};n.value&&n.value!==`all`&&(i.channelId=n.value),(await fetch(`/api/cms/tree.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i)})).ok&&(await q(),await J({reset:!0,ensureItemId:String(e)}))}catch(e){console.error(`[CMS] Failed to attach vault node to tree:`,e)}},detachTreeNode:async e=>{try{(await fetch(`/api/cms/tree.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`detach`,contentId:e,treeId:s.value})})).ok&&await q()}catch(e){console.error(`[CMS] Failed to detach tree node:`,e)}},findParentNodeInTree:W,updateNodeInTree:G,handleTreeChange:async e=>{if(e?.added?.element?._isNew){if(!await T(`node`))return;let t=e.added.element;delete t._isNew,_.value={},v.value={},y.value=null;let r=A(t.isHidden),i={...t,parentId:null,isHidden:r,status:`draft`,blocks:[]};n.value&&n.value!==`all`&&(i.channels=[n.value]);let a=await fetch(`/api/cms/nodes.json`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i)});if(a.ok){let e=await a.json();t.id=e.id,t.treeNodeId=e.id}g.value={...t,isHidden:r,status:`draft`,isNew:!1,disabledRegions:{}},C.value=`content`,w.value=!0,x.value=JSON.stringify({node:g.value,blocks:_.value})}await se()},openTreeSettings:async e=>{if(!await P())return!1;let t=i.value.find(t=>String(t.id)===String(e)||t.key===e),r=t?.treeType||t?.type||Object.keys(h.value||{})[0]||`navigation`;return a.value=t?{...t,treeType:r,channels:Array.isArray(t.channels)?[...t.channels]:[]}:{id:null,key:String(e),label:String(e),treeType:r,channels:n.value&&n.value!==`all`?[Number(n.value)||n.value]:[]},s.value=String(t?t.id:e),H(),b.value={},await T(`tree`,!0),!0},checkUnsavedChanges:P,updateTreeSnapshot:H}}function H(e){if(Array.isArray(e))for(let t=e.length-1;t>=0;t--)e[t].isNew||String(e[t].id).startsWith(`draft-`)?e.splice(t,1):e[t].children&&e[t].children.length>0&&H(e[t].children)}function U(){let e=m(),t=V(),{confirmNavigation:n}=R(),r=()=>null,i=async()=>{if(!await n())return;H(e.nodeTree.value),e.selectedBlock.value=null,e.setViewMode(`node`),e.validationErrors.value={};let t=e.selectedChannelId.value&&e.selectedChannelId.value!==`all`?Number(e.selectedChannelId.value)||e.selectedChannelId.value:``,i={id:`draft-${Date.now()}`,title:``,slug:``,nodeType:``,layoutId:`inherit`,channelId:t,channels:t?[t]:[],language:r(),status:`draft`,children:[],isNew:!0,_draftParentId:null,_isTreeDraft:!0,disabledRegions:{}};e.nodeTree.value.push(i),e.activeNode.value=i,e.blocks.value={},e.regionMeta.value={},e.activeTab.value=`settings`,e.shouldFocusTitle.value=!0,$(e)},a=async t=>{if(!t)return;let n=t.dataJson||t,r=t.id;if(r&&!String(r).startsWith(`draft-`))try{let e=await l.getNode(r);if(e.ok){let t=await e.json();t&&t.node&&(n=t.node)}}catch{console.warn(`Failed to fetch full parent data for draft inheritance`)}if(n&&typeof n==`object`){let t=JSON.parse(JSON.stringify(n));t.subpageLayoutId&&t.subpageLayoutId!==`inherit`&&(e.activeNode.value.resolvedLayoutId=t.subpageLayoutId);let r=new Set([`id`,`treeNodeId`,`contentId`,`parentId`,`_draftParentId`,`title`,`slug`,`children`,`isNew`,`nodeType`,`status`,`disabledRegions`,`layoutId`,`subpageLayoutId`,`createdAt`,`updatedAt`,`publishedAt`,`createdById`,`updatedById`,`trees`,`channels`,`language`]);Object.entries(t).forEach(([t,n])=>{!r.has(t)&&n!=null&&(e.activeNode.value[t]===void 0||e.activeNode.value[t]===``)&&(e.activeNode.value[t]=n)})}try{let{resolveInheritedRegion:r}=le(),i=String(e.selectedChannelId.value||``),a=n.subpageLayoutId;(!a||a===`inherit`)&&(a=n.resolvedLayoutId||n.layoutId);let o=a?e.nodeLayoutSchemas.value[a]:null,s=[];if(o?.regions)for(let[e,t]of Object.entries(o.regions)){let n=t.inherit||t.inherited;(n===`parent`||n===!0||String(n).toLowerCase()===`true`)&&s.push(e)}for(let n of s){let a=await r(t,n,i,``);a&&a.blocks&&a.blocks.length>0&&(e.blocks.value[n]=JSON.parse(JSON.stringify(a.blocks)),e.regionMeta.value[n]={isInherited:!0,inheritedFromId:String(a.inheritedFromId),inheritedFromTitle:a.inheritedFromTitle})}}catch(e){console.warn(`[Draft Hierarchy] Failed to resolve inherited region:`,e)}};return{handleAddRootNode:i,handleAddChild:async t=>{if(String(t.id).startsWith(`draft-`)){typeof window<`u`&&window.dispatchEvent(new CustomEvent(`cms-toast`,{detail:{type:`warning`,message:`Please save this parent page before adding sub-pages to it.`}}));return}if(!await n())return;H(e.nodeTree.value),e.selectedBlock.value=null,e.setViewMode(`node`),e.validationErrors.value={};let i=e.selectedChannelId.value&&e.selectedChannelId.value!==`all`?Number(e.selectedChannelId.value)||e.selectedChannelId.value:``,o=t.id,s={id:`draft-${Date.now()}`,title:``,slug:``,nodeType:``,layoutId:`inherit`,channelId:i,channels:i?[i]:[],language:r(),status:`draft`,children:[],isNew:!0,_draftParentId:o,_isTreeDraft:!0,disabledRegions:{}};t.children||=[],t.children.push(s),e.activeNode.value=s,e.blocks.value={},e.regionMeta.value={},e.activeTab.value=`settings`,e.shouldFocusTitle.value=!0,await a(t),$(e)},handleAddSibling:async i=>{if(String(i.id).startsWith(`draft-`)){typeof window<`u`&&window.dispatchEvent(new CustomEvent(`cms-toast`,{detail:{type:`warning`,message:`Please save this new page before adding sibling pages next to it.`}}));return}if(!await n())return;H(e.nodeTree.value),e.selectedBlock.value=null,e.setViewMode(`node`),e.validationErrors.value={};let o=i.id||``,s=t.findParentNodeInTree(e.nodeTree.value,o),c=s?s.children:e.nodeTree.value,l=c?c.findIndex(e=>e===i||String(e.id)===String(o)):-1,u=e.selectedChannelId.value&&e.selectedChannelId.value!==`all`?Number(e.selectedChannelId.value)||e.selectedChannelId.value:``,d={id:`draft-${Date.now()}`,title:``,slug:``,nodeType:``,layoutId:`inherit`,channelId:u,channels:u?[u]:[],language:r(),status:`draft`,children:[],isNew:!0,_draftParentId:s?s.id:null,_isTreeDraft:!0,disabledRegions:{}};c&&l!==-1?c.splice(l+1,0,d):c&&c.push(d),e.activeNode.value=d,e.blocks.value={},e.regionMeta.value={},e.activeTab.value=`settings`,e.shouldFocusTitle.value=!1,s&&await a(s),$(e)}}}a();var W=null,G=null,K=null;function ie(e){if(!e||typeof e!=`object`)return{};try{return JSON.parse(JSON.stringify(e))}catch{return{}}}function ae(e,t,n,i,a,o){let c=m(),u=V(),d=g(),{confirmNavigation:f,isGlobalDirty:_}=R(),v=(e,t)=>{typeof window<`u`&&(window.dispatchEvent(new CustomEvent(`cms-node-updated`,{detail:{nodeId:e,action:t}})),t.startsWith(`asset-`)&&window.dispatchEvent(new CustomEvent(`cms-assets-updated`)))};r(()=>c.activeNode.value?.nodeType,(e,t)=>{if(c.activeNode.value?.isNew&&e&&e!==t&&!Object.values(c.blocks.value||{}).some(e=>e.length>0)){let t=c.nodeSchemas.value[e];t&&J(c.activeNode.value,t),$(c)}});let y=async e=>{if(!await f())return!1;let t=i.value,n=Object.keys(t),r=e;if(r===void 0){let e=c.currentVaultType.value;if(typeof e==`string`&&e!==`all`&&n.includes(e))r=e;else if(Array.isArray(e)){let t=e.filter(e=>n.includes(e));t.length===1&&(r=t[0])}}let a=r?t[r]||c.nodeSchemas.value[r]:null,s=c.selectedChannelId.value&&c.selectedChannelId.value!==`all`?Number(c.selectedChannelId.value)||c.selectedChannelId.value:``,l={id:`draft-${Date.now()}`,isNew:!0,title:``,slug:``,nodeType:r||``,layoutId:`inherit`,channelId:s,language:c.selectedLanguage.value||null,status:`draft`,channels:s?[s]:[],disabledRegions:{},_isTreeDraft:!1};a&&J(l,a),c.activeNode.value=l,c.blocks.value={},c.regionMeta.value={},c.selectedBlock.value=null,$(c),c.validationErrors.value={};let u=o.value.find(e=>e.key!==`content`&&e.key!==`connections`)?.key||`settings`;return c.activeTab.value=u,c.setViewMode(`node`),c.shouldFocusTitle.value=!0,!0},b=async e=>await y(e),x=async()=>{c.activeNode.value.isNew=!1;let e=t=>{for(let n=t.length-1;n>=0;n--)t[n].isNew||String(t[n].id).startsWith(`draft-`)?t.splice(n,1):t[n].children&&e(t[n].children)};e(c.nodeTree.value),c.selectedBlock.value=null,c.resetActiveNode(),c.nodeTree.value.length>0?await t(c.nodeTree.value[0]):c.setViewMode(`none`,!0)},S=async()=>{if(c.isDocumentUnverified.value||c.isDocumentLoading.value)return;if(c.isOffline.value){d.persistOfflineDraft(c.activeNode.value.id,{node:c.activeNode.value,blocks:c.blocks.value,regionMeta:c.regionMeta.value}),$(c);return}let e=c.nodeSchemas.value[c.activeNode.value.nodeType];if(!s(e).some(({key:e})=>{let t=c.activeNode.value[e];return t!=null&&String(t).trim()!==``}))return;let t=p(e).title?String(c.activeNode.value.title):h(e,c.activeNode.value),n=c.activeNode.value.slug?String(c.activeNode.value.slug).trim():``;n||=(t.trim()||`draft-page`).toLowerCase().replace(/[^a-z0-9\s-]/g,``).replace(/[\s-]+/g,`-`).replace(/^-+|-+$/g,``)||`draft-page-${Date.now()}`;let r=!!c.activeNode.value._isTreeDraft,i=c.activeNode.value.id||c.activeContentId.value,a=typeof i==`number`?i:Number(i)||null,o=c.activeNode.value.isNew||r||String(i||``).startsWith(`draft-`);if(!o&&!_.value&&!c.isPendingOfflineSave.value)return;let f={...c.activeNode.value};f.slug=n,f.title=t;let m=c.activeNode.value.status===`published`||c.activeNode.value.publishedAt?`published`:`draft`;f.status=m,delete f.id,delete f.isNew,delete f._draftParentId,delete f._isTreeDraft,delete f.children,delete f.treeNodeId;let g=A(c.activeNode.value.isHidden);f.isHidden=g;let y=c.selectedChannelId.value&&c.selectedChannelId.value!==`all`?Number(c.selectedChannelId.value)||c.selectedChannelId.value:null,b=Y(c.activeNode.value.channels).map(e=>typeof e==`string`&&!isNaN(Number(e))?Number(e):e);c.activeNode.value.channels===void 0&&y&&(b=[y]),f.channels=b,f.channelId=b.length>0?b[0]:``;let x=[];Object.entries(c.blocks.value||{}).forEach(([e,t])=>{c.regionMeta.value[e]?.isInherited||Array.isArray(t)&&t.forEach((t,n)=>{x.push({instanceId:String(t.instanceId||t.id||`block-${Date.now()}`),componentId:String(t.componentId||t.elementType||`text`),elementType:String(t.componentId||t.elementType||`text`),region:String(e||`content`),sortOrder:n,data:ie(t.data)})})});try{let e=null,i;if(i=o&&r?await l.createInTree({action:`create`,title:f.title,slug:n,nodeType:c.activeNode.value.nodeType,treeId:c.selectedTreeId.value,parentId:c.activeNode.value._draftParentId||null,channels:b,channelId:b.length>0?b[0]:null,isHidden:g,nodeData:{...f,status:m,blocks:x}}):o?await l.saveNode({id:null,...f,status:m,blocks:x}):await l.saveNode({id:a,...f,status:m,blocks:x}),i.ok){let s=await i.json();e=s.id||s.nodeId||a;let l=c.activeNode.value.id;c.activeNode.value.id=String(e),c.activeNode.value.slug=n,c.activeNode.value.title=t,c.activeNode.value.treeNodeId=String(e);let f=s.hasUnpublishedChanges===!0;if(c.activeNode.value.isNew=!1,c.activeNode.value.status=m,c.activeNode.value.hasUnpublishedChanges=f,c.activeNode.value.channels=b,delete c.activeNode.value._isTreeDraft,delete c.activeNode.value._draftParentId,c.nodeTree.value&&e){let i=r=>{for(let a=0;a<r.length;a++){if(r[a]===c.activeNode.value||String(r[a].id)===String(l)||String(r[a].id).startsWith(`draft-`))return r[a].id=String(e),r[a].treeNodeId=String(e),r[a].title=t,r[a].slug=n,r[a].isNew=!1,delete r[a]._isTreeDraft,delete r[a]._draftParentId,!0;if(r[a].children&&i(r[a].children))return!0}return!1};i(c.nodeTree.value),o&&r&&u.saveTreeOrder()}c.updateNodeInState(e,{title:t,slug:n,status:m,hasUnpublishedChanges:f,isHidden:g},String(e)),$(c),d.clearPersistedOfflineDraft(e),d.invalidateAfterSave(e),d.saveToCache(e,{node:c.activeNode.value,blocks:c.blocks.value,regionMeta:c.regionMeta.value}),c.invalidateStats(),v(e,o?`create`:`update`)}else{let e=await i.json().catch(()=>({}));if(i.status===409&&(e.field===`slug`||e.error?.toLowerCase().includes(`slug`)||e.error?.toLowerCase().includes(`exists`))){let e=Math.random().toString(36).substring(2,6),t=`${n}-${e}`;return c.activeNode.value.slug=t,typeof window<`u`&&window.dispatchEvent(new CustomEvent(`cms-toast`,{detail:{type:`warning`,message:`The URL slug "${n}" was already in use. It has been auto-appended to "${t}".`}})),c.validationErrors.value.slug&&delete c.validationErrors.value.slug,await S()}i.status===409&&e.field&&(c.validationErrors.value={...c.validationErrors.value,[e.field]:e.error||`This value is already in use.`})}}catch(e){console.error(`Network error auto-saving node draft:`,e),d.persistOfflineDraft(a||c.activeNode.value.id,{node:c.activeNode.value,blocks:c.blocks.value,regionMeta:c.regionMeta.value}),$(c)}},C=async()=>{c.isSaving.value=!0,c.isAutoSavePending.value=!1,W&&=(clearTimeout(W),null);try{G||=S(),await G}finally{G=null,K||(c.isSaving.value=!1)}};return r([()=>c.activeNode.value,()=>c.blocks.value],()=>{if(!c.activeNode.value?.id||c.isDocumentLoading.value||c.activeNode.value.isNew&&!c.activeNode.value.nodeType)return;let e=h(c.nodeSchemas.value[c.activeNode.value.nodeType],c.activeNode.value);if(c.activeNode.value.isNew&&e.startsWith(`Untitled`)){c.isAutoSavePending.value=!1;return}c.isAutoSavePending.value=!0,W&&clearTimeout(W),W=setTimeout(()=>{C()},1e3)},{deep:!0}),{handleAddNewNode:y,createVaultNode:b,cancelNewNode:x,saveNewNode:async()=>await C(),saveNode:C,publishNode:async()=>c.isDocumentUnverified.value?!1:K||(K=(async()=>{c.isSaving.value=!0;try{if(!await e())return!1;W||c.isAutoSavePending.value||_.value?await C():G&&await G;let t=c.activeNode.value.id||c.activeContentId.value,n=typeof t==`number`?t:Number(t)||null;if(!n)return!1;let r=await l.publishNode(n);if(r.ok){let e=await r.json();return c.activeNode.value.status=`published`,c.activeNode.value.publishedAt=e.publishedAt,c.activeNode.value.hasUnpublishedChanges=!1,c.updateNodeInState(n,{status:`published`,publishedAt:e.publishedAt,hasUnpublishedChanges:!1},String(n)),$(c),d.invalidateAfterSave(n),d.saveToCache(n,{node:c.activeNode.value,blocks:c.blocks.value,regionMeta:c.regionMeta.value}),c.invalidateStats(),await u.fetchNodeTree(),await u.fetchVaultNodes({reset:!0,ensureItemId:String(n)}),v(n,`publish`),!0}}finally{K=null,c.isSaving.value=!1}return!1})(),K),deleteNode:async e=>{let t=e||c.activeNode.value?.id||c.activeContentId.value;if(!t||String(t).startsWith(`draft-`))return x(),!0;try{if((await l.deleteNode(t)).ok)return d.invalidateAfterSave(t),c.invalidateStats(),c.nodeTree.value&&c.nodeTree.value.length>0&&await u.fetchNodeTree(),await u.fetchVaultNodes({reset:!0}),String(c.activeNode.value?.id)===String(t)&&x(),v(t,`delete`),!0}catch(e){console.error(`[CMS] Failed to delete node:`,e)}return!1},restoreNode:async e=>{if(!e)return!1;try{if((await l.restoreNode(e)).ok)return c.invalidateStats(),await u.fetchVaultNodes({reset:!0}),v(e,`restore`),!0}catch(e){console.error(`[CMS] Failed to restore node:`,e)}return!1},purgeNode:async e=>{if(!e)return!1;try{if((await l.purgeNode(e)).ok)return c.invalidateStats(),await u.fetchVaultNodes({reset:!0}),v(e,`purge`),!0}catch(e){console.error(`[CMS] Failed to purge node:`,e)}return!1},toggleNodeVisibility:async e=>{if(!e||!e.id||String(e.id).startsWith(`draft-`))return!1;let t=!A(e.isHidden);try{let n=await l.toggleVisibility(e.id,t);if(n.ok){let r=await n.json().catch(()=>({}));return e.isHidden=t,c.updateNodeInState(e.id,{isHidden:t},e.id),String(c.activeNode.value?.id)===String(e.id)?($(c),d.saveToCache(e.id,{node:JSON.parse(JSON.stringify(c.activeNode.value)),blocks:JSON.parse(JSON.stringify(c.blocks.value)),regionMeta:JSON.parse(JSON.stringify(c.regionMeta.value))})):d.invalidateAfterSave(e.id),r.cacheInvalidated===!1&&typeof window<`u`&&window.dispatchEvent(new CustomEvent(`cms-toast`,{detail:{type:`warning`,message:`Visibility changed, but one or more site caches could not be confirmed purged. Check the Worker logs.`}})),v(e.id,`update`),!0}}catch(e){console.error(`[CMS] Failed to toggle node visibility:`,e)}return!1},restoreSnapshot:async e=>{let n=c.activeNode.value?.id;if(!n||String(n).startsWith(`draft-`))return!1;c.isSaving.value=!0;try{if((await l.restoreSnapshot(n,e)).ok)return c.activeSnapshotVersion.value=null,c.draftBackup.value=null,d.clearCache(n),await t({id:n,nodeType:c.activeNode.value.nodeType,treeNodeId:c.activeNode.value.treeNodeId}),c.activeNode.value.status=`draft`,c.activeNode.value.hasUnpublishedChanges=!0,c.updateNodeInState(n,{...c.activeNode.value,status:`draft`,hasUnpublishedChanges:!0,title:c.activeNode.value.title,isHidden:A(c.activeNode.value.isHidden)},c.activeNode.value.treeNodeId),$(c),c.invalidateStats(),await u.fetchNodeTree(),v(n,`restore-snapshot`),typeof window<`u`&&window.dispatchEvent(new CustomEvent(`cms-toast`,{detail:{type:`success`,message:`Version ${e} restored successfully.`}})),!0}catch(e){console.error(`[CMS] Failed to restore snapshot:`,e)}finally{c.isSaving.value=!1}return!1}}}a();var q=0;function oe(e){return e&&{...e,isHidden:A(e.isHidden)}}function se(e,t=!1){if(!e)return``;let n=new Date,r=String(e).toLowerCase().trim(),i=e=>{let n=e=>e.toString().padStart(2,`0`),r=`${e.getFullYear()}-${n(e.getMonth()+1)}-${n(e.getDate())}`;return t?r:`${r}T${n(e.getHours())}:${n(e.getMinutes())}`};if(r===`now`||r===`today`)return i(n);let a=r.match(/^([+-])\s*(\d+)\s*(minute|hour|day|week|month|year)s?$/);if(a){let e=a[1]===`+`?1:-1,t=parseInt(a[2],10)*e,r=a[3],o=new Date(n);return r===`minute`?o.setMinutes(o.getMinutes()+t):r===`hour`?o.setHours(o.getHours()+t):r===`day`?o.setDate(o.getDate()+t):r===`week`?o.setDate(o.getDate()+t*7):r===`month`?o.setMonth(o.getMonth()+t):r===`year`&&o.setFullYear(o.getFullYear()+t),i(o)}return String(e)}function J(e,t){let n=e=>e==null||e===``,r=t=>{t&&Object.entries(t).forEach(([t,r])=>{r?.default!==void 0&&n(e[t])&&(e[t]=r.type===`datetime`||r.type===`date`?se(r.default,r.type===`date`):r.default)})};r(t?.fields),t?.tabs&&Object.values(t.tabs).forEach(e=>r(e?.fields))}function Y(e){if(!e)return[];if(Array.isArray(e))return e.map(e=>typeof e==`object`&&e?e.id||e.channelId:e).filter(Boolean);if(typeof e==`string`)try{let t=JSON.parse(e);return Array.isArray(t)?Y(t):[e]}catch{return[e]}return[e]}function X(e,t){if(!e)return!1;if(!t||e===t.defaultLayout)return!0;let n=null,r=e=>{e&&(Array.isArray(e)?e.forEach(e=>{e.layoutId&&(n=e.layoutId)}):e.layoutId&&(n=e.layoutId))};if(r(t.fields),!n&&t.tabs&&Object.values(t.tabs).forEach(e=>r(e.fields)),!n)return!1;let i=n.allowedLayouts;return i?typeof i==`string`?i===e:!Array.isArray(i)||i.length===0||i.includes(e):!0}function Z(e,t,n,r){let i=e?.layoutId,a=e?.nodeType?t.nodeSchemas.value[e.nodeType]:null;if((!i||i===`inherit`)&&!e?.resolvedLayoutId&&n&&r){let t=r.findParentNodeInTree(n.nodeTree.value,e?._draftParentId||e?.parentId||``);for(;t;){if(t.subpageLayoutId&&t.subpageLayoutId!==`inherit`){X(t.subpageLayoutId,a)&&(i=t.subpageLayoutId);break}if(t.layoutId&&t.layoutId!==`inherit`){X(t.layoutId,a)&&(i=t.layoutId);break}if(t.resolvedLayoutId){X(t.resolvedLayoutId,a)&&(i=t.resolvedLayoutId);break}t=r.findParentNodeInTree(n.nodeTree.value,t.parentId||``)}}!i||i===`inherit`?(i=e?.resolvedLayoutId,i&&!X(i,a)&&(i=null),i||=a?.defaultLayout):X(i,a)||(i=a?.defaultLayout);let o=i?t.nodeLayoutSchemas.value[i]:null;return o?.regions&&Object.keys(o.regions).length>0?o.regions:{content:{label:`Content`}}}var Q=e=>e===`parent`||e===!0||String(e).toLowerCase()===`true`;function ce(e,t){let n=e.activeNode.value,r=n?.nodeType?e.nodeSchemas.value[n.nodeType]:null,i=n?.layoutId;(!i||i===`inherit`)&&(i=n?.resolvedLayoutId||r?.defaultLayout);let a=i?e.nodeLayoutSchemas.value[i]:null,o=a?.regions&&Object.keys(a.regions).length>0?a.regions:{content:{label:`Content`}},s=new Set(Object.keys(o)),c=t=>{Array.isArray(t)&&t.forEach(t=>{let n=t.componentId||t.elementType,r=e.blockLayoutSchemas.value[n];r?.regions&&Object.keys(r.regions).forEach(n=>{let r=`${t.instanceId||t.id}_${n}`;s.add(r),e.blocks.value[r]&&c(e.blocks.value[r])})})};return t&&Array.isArray(t)&&t.forEach(t=>{let n=t.componentId||t.elementType,r=e.blockLayoutSchemas.value[n];r?.regions&&Object.keys(r.regions).forEach(e=>{let n=`${t.instanceId||t.id}_${e}`;s.add(n)})}),Object.keys(o).forEach(t=>c(e.blocks.value[t]||[])),s}function $(e){if(!e.activeNode.value)return;ce(e).forEach(t=>{e.blocks.value[t]||(e.blocks.value[t]=[])}),e.activeNode.value.disabledRegions||(e.activeNode.value.disabledRegions={}),e.activeNode.value.channels||(e.activeNode.value.channels=[]);let t=d(JSON.parse(JSON.stringify(e.activeNode.value)),e.nodeSchemas.value),n=JSON.parse(JSON.stringify(e.blocks.value));e.nodeSnapshot.value=JSON.stringify({node:t,blocks:n})}function le(){let e=m(),t=V(),i=g(),a=U(),{confirmNavigation:s}=R(),c=()=>$(e),u=o(()=>e.nodeSchemas.value[e.activeNode.value?.nodeType]||null),d=o(()=>Z(e.activeNode.value,{nodeSchemas:e.nodeSchemas,nodeLayoutSchemas:e.nodeLayoutSchemas},e,t)),f=o(()=>{let t=[],n=e.activeNode.value,r=e.nodeSchemas.value[n?.nodeType];if(r){if(r.hasCanvas===!0&&t.push({key:`content`,label:`Content`}),r.tabs&&typeof r.tabs==`object`)for(let[e,n]of Object.entries(r.tabs)){let r=typeof n==`string`?n:n?.label||e;t.push({key:e,label:r})}t.filter(e=>e.key!==`content`).length===0&&t.push({key:`settings`,label:r.label||`Settings`}),t.push({key:`connections`,label:`Connections`})}return t}),p=o(()=>{let t={};for(let[n,r]of Object.entries(e.nodeSchemas.value||{})){let e=r.inTree;(e===!0||String(e)===`true`||e===1)&&(t[n]=r)}return t}),h=o(()=>Object.keys(p.value).map(e=>({value:e,label:p.value[e].label||e}))),_=o(()=>{let t={};for(let[n,r]of Object.entries(e.nodeSchemas.value||{}))r.inVault!==!1&&String(r.inVault)!==`false`&&(t[n]=r);return t}),v=o(()=>Object.keys(_.value).map(e=>({value:e,label:_.value[e].label||e}))),y=o(()=>e.workspaceContext.value===`tree`),b=t=>{if(!e.activeNode.value?.nodeType)return t===`settings`||t===`content`||t===`node`?{nodeType:{label:`Select Node Type`,type:`select`,options:y.value?h.value:v.value,rules:{required:!0}}}:{};let n=u.value;if(!n)return{};let r=t;t===`node`&&!n.tabs?.node&&n.tabs?.settings&&(r=`settings`);let i=n.tabs?.[r]?.fields||n.fields||{},a=JSON.parse(JSON.stringify(i));return a.nodeType&&(a.nodeType.type=`select`,a.nodeType.options=y.value?h.value:v.value),a},x=o(()=>Object.keys(e.validationErrors.value).length===0),S=e=>{},C=async()=>{e.validationErrors.value={};let t=!0,n=``,r=u.value;if(!r)return!1;let i={...r.fields||{}};r.tabs&&Object.values(r.tabs).forEach(e=>{Object.assign(i,e.fields||{})});let a=e.activeNode.value?.id,o=typeof a==`number`||a&&!String(a).startsWith(`draft-`)?String(a):``,s=e.activeNode.value?.treeId||e.selectedTreeId.value||e.activeTreeSettings.value?.id,c=e.activeNode.value?._draftParentId??e.activeNode.value?.parentId??null,l={...e.activeNode.value,treeId:s,parentId:c};for(let[a,s]of Object.entries(i)){let i=e.activeNode.value[a],c=await E(a,i,s,{entityType:`node`,excludeId:e.activeNode.value?.treeNodeId||o,formData:l});if(c&&(e.validationErrors.value[a]=c,t=!1,!n)){for(let[e,t]of Object.entries(r.tabs||{}))if(t.fields?.[a]){n=e;break}}}if(!t){let t=n||f.value.find(e=>e.key!==`content`&&e.key!==`connections`)?.key||`content`;return e.activeTab.value!==t&&(e.activeTab.value=t),e.shouldFocusTitle.value=!0,!1}return!0},w=(e,t)=>{let n={},r=t.filter(e=>typeof e==`object`&&!!e),i=new Set(r.map(e=>String(e.blockId||e.instanceId||e.id))),a=!0;for(;a;){a=!1;for(let[t,r]of Object.entries(e))if(!(n[t]||!r||!Array.isArray(r))){for(let e of i)if(e&&(t.startsWith(`${e}_`)||t.startsWith(`${e}-`))){n[t]=r,r.forEach(e=>{e&&i.add(String(e.blockId||e.instanceId||e.id))}),a=!0;break}}}return n},T=async(n,r,a,o)=>{if(!n||n.isNew||String(n.id||``).startsWith(`draft-`))return{blocks:[]};let s=n;for(;s;){let n=i.getCachedDocument(s.id);if(!n)try{let e=await l.getNode(s.id);if(e.ok){let t=await e.json(),r=t.node||{},a={};Array.isArray(t.blocks)&&t.blocks.forEach(e=>{let t=e.region||`content`;a[t]||(a[t]=[]);let n=typeof e.data==`string`?JSON.parse(e.data):e.data||{};a[t].push({instanceId:String(e.instanceId||e.id),blockId:String(e.blockId||e.instanceId||e.id),componentId:String(e.componentId||e.elementType||`text`),region:t,data:{...n}})}),n={node:r,blocks:a,regionMeta:{}},i.saveToCache(s.id,n)}}catch(e){console.error(`⚠️ Failed to fetch parent node for inheritance:`,e);break}if(n){if(n.node?.disabledRegions?.[r])return{blocks:[]};if(n.blocks?.[r]?.length>0)return{blocks:n.blocks[r],subRegions:w(n.blocks,n.blocks[r]),inheritedFromId:String(n.node.id),inheritedFromTitle:n.node.title||n.node.slug}}let a=t.findParentNodeInTree(e.nodeTree.value,s.id||s.treeNodeId||``);if(!a||String(a.id)===String(s.id))break;s=a}return{blocks:[]}},D=async(r,a)=>{if(String(e.activeNode.value?.id)===String(r.id)&&!e.activeNode.value?.isNew)return a?.workspaceContext&&(e.workspaceContext.value=a.workspaceContext),a?.selectedTreeId&&(e.selectedTreeId.value=a.selectedTreeId),a?.beforeLoad?.(),!0;if(e.activeNode.value?.isNew&&String(e.activeNode.value.id||``).startsWith(`draft-`)||!await s())return!1;a?.workspaceContext&&(e.workspaceContext.value=a.workspaceContext),a?.selectedTreeId&&(e.selectedTreeId.value=a.selectedTreeId),a?.beforeLoad?.(),e.selectedBlock.value=null,e.nodeSnapshot.value=``,e.selectedTreeId.value&&(e.nodeTree.value=t.getNodesForTree(e.selectedTreeId.value)),e.isDocumentLoading.value=!0,i.clearConflict(),i.markUnverified(!1);let o=++q,c=String(r.id),u=i.getCachedDocument(c),d=i.getPersistedOfflineDraft(r.id);H(e.nodeTree.value),e.validationErrors.value={};let p=e.nodeSchemas.value[r.nodeType]||Object.values(e.nodeSchemas.value)[0],m=t.findParentNodeInTree(e.nodeTree.value,r.id||r.treeNodeId||``),h=Y(r.channels||r.channelId).map(e=>typeof e==`string`&&!isNaN(Number(e))?Number(e):e),g=String(h[0]||e.selectedChannelId.value||``),_=r.language||e.activeTreeSettings.value?.defaultLanguage||e.selectedLanguage.value||``;if(d)return e.setViewMode(`node`),e.activeNode.value=JSON.parse(JSON.stringify(d.data.node)),e.blocks.value=JSON.parse(JSON.stringify(d.data.blocks)),e.regionMeta.value=JSON.parse(JSON.stringify(d.data.regionMeta)),$(e),e.isDocumentLoading.value=!1,e.isPendingOfflineSave.value=!0,!0;if(u)return e.setViewMode(`node`),e.activeNode.value=JSON.parse(JSON.stringify(u.node)),e.blocks.value=JSON.parse(JSON.stringify(u.blocks)),e.regionMeta.value=JSON.parse(JSON.stringify(u.regionMeta)),$(e),e.isDocumentLoading.value=!1,!0;try{let a=await l.getNode(r.id);if(o!==q)return!1;if(a.ok){let s=await a.json(),c=s.node||r,l=c.disabledRegions||{},u=c.channels||c.channelId||h,d={...oe(c),id:c.id||r.id,treeNodeId:c.treeNodeId||r.treeNodeId,isNew:!1,disabledRegions:l,channels:Y(u).map(e=>typeof e==`string`&&!isNaN(Number(e))?Number(e):e),trees:c.trees||[]};J(d,p);let v=Z(d,{nodeSchemas:e.nodeSchemas,nodeLayoutSchemas:e.nodeLayoutSchemas},e,t),y={};for(let e of Object.keys(v))Q(v[e].inherit)&&m&&(y[e]=T(m,e,g,_));let b={};for(let[e,t]of Object.entries(y))b[e]=await t;if(o!==q)return!1;let x={},S={},C=new Set(Object.keys(v));if(Array.isArray(s.blocks)&&s.blocks.forEach(e=>C.add(e.region||`content`)),C.forEach(e=>{x[e]=[]}),Array.isArray(s.blocks)){let t=new Set;[...s.blocks].sort((e,t)=>{let n=String(e.region||``).includes(`_`),r=String(t.region||``).includes(`_`);return n&&!r?1:!n&&r?-1:0}).forEach(n=>{let r=n.instanceId||n.id;if(t.has(r))return;t.add(r);let i=n.region||`content`;x[i]||(x[i]=[]);let a=e.blockSchemas.value[n.componentId||n.elementType],o=typeof n.data==`string`?JSON.parse(n.data):n.data||{};a?.fields&&Object.entries(a.fields).forEach(([e,t])=>{(o[e]===void 0||o[e]===null)&&(o[e]=t.default===void 0?``:t.default)}),x[i].push({instanceId:String(r),blockId:String(n.blockId||n.instanceId||n.id),componentId:String(n.componentId||n.elementType||`text`),region:i,data:{...o}})})}for(let e of Object.keys(v)){let t=x[e]&&x[e].length>0,n=l[e];if(Q(v[e].inherit)&&!t&&!n&&m){let t=b[e];if(t&&t.blocks&&t.blocks.length>0){if(x[e]=t.blocks,S[e]={isInherited:!0,inheritedFromId:t.inheritedFromId,inheritedFromTitle:t.inheritedFromTitle},t.subRegions)for(let[n,r]of Object.entries(t.subRegions))n!==e&&Array.isArray(r)&&r.length>0&&(x[n]=r,S[n]={isInherited:!0,inheritedFromId:t.inheritedFromId,inheritedFromTitle:t.inheritedFromTitle})}else S[e]={isInherited:!1}}else S[e]={isInherited:!1}}let w={};Object.keys(x).forEach(e=>{S[e]?.isInherited?w[e]=[]:w[e]=x[e]});let E={node:d,blocks:w,regionMeta:S},{isNodeDirty:D}=R();if(i.evaluateServerResponse(r.id,E,D.value).action===`update_silently`){e.setViewMode(`node`),e.activeNode.value=d,e.blocks.value=x,e.regionMeta.value=S;let a=f.value;if(!a.some(e=>e.key===`content`)&&e.activeTab.value===`content`&&(e.activeTab.value=a.find(e=>e.key!==`content`&&e.key!==`connections`)?.key||`settings`),d.trees&&d.trees.length>0){let n=String(d.trees[0].treeId);e.selectedTreeId.value!==n&&(e.selectedTreeId.value=n,e.nodeTree.value=t.getNodesForTree(n))}await n(),$(e),i.saveToCache(r.id,{node:d,blocks:x,regionMeta:S})}i.markUnverified(!1)}else i.markUnverified(!0)}catch(e){console.error(`⚠️ Network error fetching node content:`,e),i.markUnverified(!0)}finally{e.isDocumentLoading.value=!1}return!0},ee=async t=>{let n=e=>{for(let r of e){if(String(r.id)===String(t))return r;if(r.children){let e=n(r.children);if(e)return e}}return null},r=n(e.nodeTree.value);r?await D(r):await D({id:String(t),title:`Loading...`,slug:``,nodeType:`node`,channelId:``,language:``})};r([()=>e.activeNode.value?.id,()=>e.activeNode.value?.nodeType,()=>e.activeNode.value?.layoutId,()=>e.activeNode.value?.resolvedLayoutId],([n])=>{if(!e.isDocumentLoading.value&&n&&e.activeNode.value?.nodeType){let r=Z(e.activeNode.value,{nodeSchemas:e.nodeSchemas,nodeLayoutSchemas:e.nodeLayoutSchemas},e,t),i=t.findParentNodeInTree(e.nodeTree.value,e.activeNode.value._draftParentId||e.activeNode.value.parentId||``),a=String(e.selectedChannelId.value||``),o=String(e.activeNode.value?.language||e.activeTreeSettings.value?.defaultLanguage||e.selectedLanguage.value||``),s={...e.regionMeta.value},c=!1;for(let t of Object.keys(r)){let l=r[t].inherit,u=e.activeNode.value.disabledRegions?.[t],d=e.blocks.value[t]&&e.blocks.value[t].length>0,f=!s[t],p=!f&&!s[t].isInherited&&Q(l)&&!u&&!d;(f||p)&&(Q(l)&&i&&!u&&!d?(s[t]={isInherited:!0},c=!0,T(i,t,a,o).then(r=>{e.activeNode.value?.id===n&&(r&&r.blocks&&r.blocks.length>0?(e.blocks.value[t]=r.blocks,e.regionMeta.value[t]={isInherited:!0,inheritedFromId:r.inheritedFromId,inheritedFromTitle:r.inheritedFromTitle}):e.regionMeta.value[t]={isInherited:!1})})):f&&(s[t]={isInherited:!1},c=!0))}c&&(e.regionMeta.value=s)}},{immediate:!0,deep:!1});let O=ae(C,D,p,_,y,f);return{applySchemaDefaults:J,currentNodeSchema:u,currentLayoutRegions:d,availableNodeTabs:f,treeEligibleNodeSchemas:p,treeEligibleNodeTypes:h,vaultEligibleNodeSchemas:_,vaultEligibleNodeTypes:v,isTreeContext:y,isFormValid:x,getFieldsForTab:b,setFormValidator:S,validateActiveNode:C,loadNodeContent:D,navigateToNodeById:ee,resolveInheritedRegion:T,handleAddRootNode:a.handleAddRootNode,handleAddChild:a.handleAddChild,handleAddSibling:a.handleAddSibling,handleAddNewNode:O.handleAddNewNode,createVaultNode:O.createVaultNode,cancelNewNode:O.cancelNewNode,saveNewNode:O.saveNewNode,saveNode:O.saveNode,publishNode:O.publishNode,deleteNode:O.deleteNode,restoreNode:O.restoreNode,purgeNode:O.purgeNode,toggleNodeVisibility:O.toggleNodeVisibility,restoreSnapshot:O.restoreSnapshot,updateNodeSnapshot:c}}export{V as a,ne as c,D as d,y as f,le as i,te as l,X as n,R as o,_ as p,$ as r,I as s,J as t,ee as u};
@@ -1,143 +0,0 @@
1
- ---
2
- // src/components/blocks/BlockRenderer.astro
3
-
4
- import ImageBlock from "@/components/blocks/ImageBlock.astro";
5
- import HeaderImage from "@/components/blocks/HeaderImage.astro";
6
- import ColumnLayout from "@/components/blocks/ColumnLayout.astro";
7
- import HtmlBlock from "@/components/blocks/HtmlBlock.astro";
8
- import NodeList from "@/components/blocks/NodeList.astro"; // 🎯 NEW IMPORT
9
- import { extractHtml } from "@/utils/tiptap";
10
-
11
- interface Block {
12
- instanceId: number;
13
- blockId?: string;
14
- componentId: string;
15
- data: Record<string, any>;
16
- }
17
-
18
- interface Props {
19
- blocks?: Block[];
20
- contentMap?: Record<string, any[]>;
21
- region?: string;
22
- }
23
-
24
- const { blocks = [], contentMap = {}, region = "main" } = Astro.props;
25
- const safeBlocks = Array.isArray(blocks) ? blocks : [];
26
-
27
- const visibleBlocks = safeBlocks.filter(b => {
28
- if (!b || (!b.data && !b.componentId?.includes("column"))) return false;
29
-
30
- const blockData = b.data || {};
31
- if (
32
- blockData.hidden === true ||
33
- blockData.hidden === 1 ||
34
- String(blockData.hidden) === "true"
35
- ) {
36
- return false;
37
- }
38
-
39
- const now = new Date();
40
- if (blockData.startShowingAt) {
41
- const start = new Date(blockData.startShowingAt);
42
- if (!isNaN(start.getTime()) && now < start) return false;
43
- }
44
- if (blockData.stopShowingAt) {
45
- const stop = new Date(blockData.stopShowingAt);
46
- if (!isNaN(stop.getTime()) && now > stop) return false;
47
- }
48
-
49
- return true;
50
- });
51
- ---
52
-
53
- {
54
- visibleBlocks.map((block, index) => {
55
- const data = block.data || {};
56
- const blockId = block.blockId || data.blockId || "";
57
- const componentId = (block.componentId || "").toLowerCase();
58
-
59
- // Check for any column layout ending in column or two-column
60
- if (componentId.includes("column")) {
61
- return <ColumnLayout blockId={blockId} contentMap={contentMap} />;
62
- }
63
-
64
- switch (componentId) {
65
- // 🎯 ADDED NODE LIST CASES
66
- case "node-list":
67
- case "nodelist":
68
- case "article-list":
69
- case "content-feed": {
70
- return <NodeList data={data} />;
71
- }
72
-
73
- case "header":
74
- case "headline":
75
- case "header-block":
76
- case "header_block": {
77
- const headline = extractHtml(data.headline || data.title);
78
- const subhead = extractHtml(data.subhead || data.body);
79
- return (
80
- <header class="cms-block cms-block-header">
81
- {headline && <Fragment set:html={headline} />}
82
- {subhead && <Fragment set:html={subhead} />}
83
- </header>
84
- );
85
- }
86
-
87
- case "text":
88
- case "text-block":
89
- case "text_block": {
90
- const bodyText = extractHtml(data.body || data.text || data.content);
91
- return (
92
- <div class="cms-block cms-block-text">
93
- <Fragment set:html={bodyText} />
94
- </div>
95
- );
96
- }
97
-
98
- case "html":
99
- case "html-block":
100
- case "html_block":
101
- case "raw-html": {
102
- return <HtmlBlock data={data} />;
103
- }
104
-
105
- case "header-image":
106
- case "header_image": {
107
- return (
108
- <HeaderImage data={data} region={region} isFirst={index === 0} />
109
- );
110
- }
111
-
112
- case "image":
113
- case "image-block":
114
- case "image_block":
115
- case "single_image":
116
- case "single-image": {
117
- return <ImageBlock data={data} region={region} isFirst={index === 0} />;
118
- }
119
-
120
- default:
121
- return import.meta.env.DEV ? (
122
- <div class="unhandled-block">
123
- <p>Unhandled component: {block.componentId}</p>
124
- </div>
125
- ) : null;
126
- }
127
- })
128
- }
129
-
130
- <style>
131
- .cms-block {
132
- margin-bottom: 1.5rem;
133
- }
134
-
135
- .unhandled-block {
136
- padding: 12px 16px;
137
- border: 1px dashed #cbd5e1;
138
- background: #f8fafc;
139
- color: #64748b;
140
- font-size: 13px;
141
- margin-bottom: 1.5rem;
142
- }
143
- </style>
@@ -1,67 +0,0 @@
1
- ---
2
- // src/components/blocks/ColumnLayout.astro
3
-
4
- import BlockRenderer from "@/components/blocks/BlockRenderer.astro";
5
-
6
- interface Props {
7
- blockId: string;
8
- contentMap: Record<string, any[]>;
9
- }
10
-
11
- const { blockId, contentMap } = Astro.props;
12
-
13
- const order = ["left", "middle", "right", "col1", "col2", "col3", "col4"];
14
-
15
- // 1. Find all sub-regions belonging to this specific layout instance
16
- const regionKeys = Object.keys(contentMap).filter(
17
- key => blockId && key.startsWith(`${blockId}_`),
18
- );
19
-
20
- // 2. Sort keys logically (left -> middle -> right or col1 -> col2 -> col3)
21
- const sortedKeys = regionKeys.sort((a, b) => {
22
- const suffixA = a.replace(`${blockId}_`, "");
23
- const suffixB = b.replace(`${blockId}_`, "");
24
- const idxA = order.indexOf(suffixA);
25
- const idxB = order.indexOf(suffixB);
26
-
27
- if (idxA === -1 && idxB === -1) return a.localeCompare(b);
28
- if (idxA === -1) return 1;
29
- if (idxB === -1) return -1;
30
- return idxA - idxB;
31
- });
32
-
33
- const columnCount = Math.max(sortedKeys.length, 1);
34
- ---
35
-
36
- <div class="cms-column-layout" style={`--col-count: ${columnCount}`}>
37
- {
38
- sortedKeys.map(key => {
39
- const columnBlocks = contentMap[key] || [];
40
- return (
41
- <div class="column">
42
- <!-- 🎯 Passes region={key} down to BlockRenderer -->
43
- <BlockRenderer
44
- blocks={columnBlocks}
45
- contentMap={contentMap}
46
- region={key}
47
- />
48
- </div>
49
- );
50
- })
51
- }
52
- </div>
53
-
54
- <style>
55
- .cms-column-layout {
56
- display: grid;
57
- gap: 2rem;
58
- margin-bottom: 1.5rem;
59
- grid-template-columns: 1fr;
60
- }
61
-
62
- @media (min-width: 768px) {
63
- .cms-column-layout {
64
- grid-template-columns: repeat(var(--col-count, 1), 1fr);
65
- }
66
- }
67
- </style>
@@ -1,126 +0,0 @@
1
- ---
2
- // src/components/blocks/HeaderImage.astro
3
-
4
- import KamaImage from "@/components/ui/KamaImage.astro";
5
-
6
- interface Props {
7
- data: {
8
- image?: any;
9
- image_meta?: any;
10
- width?: number | string;
11
- height?: number | string;
12
- };
13
- region?: string;
14
- isFirst?: boolean;
15
- }
16
-
17
- const { data, region = "main", isFirst = false } = Astro.props;
18
-
19
- const img = data?.image;
20
-
21
- if (!img) {
22
- return null;
23
- }
24
-
25
- /**
26
- * Determine if this image is likely to be the Largest Contentful Paint.
27
- */
28
- const isLcp = region === "header" || (region === "main" && isFirst);
29
-
30
- /**
31
- * Determine grid column count from the region name.
32
- */
33
- let columnCount = 1;
34
-
35
- if (region.includes("_")) {
36
- columnCount = 2;
37
-
38
- if (region.includes("_middle") || region.includes("_col3")) {
39
- columnCount = 3;
40
- }
41
-
42
- if (region.includes("_col4")) {
43
- columnCount = 4;
44
- }
45
- }
46
-
47
- /**
48
- * Default single-column layout (aligned to backend CDN buckets).
49
- */
50
- let maxWidth = "1352";
51
- let targetColumnWidth = 1352;
52
-
53
- // 1-col: 1x/2x desktop and retina buckets
54
- let optimizedWidths = [768, 1352, 1920, 2560];
55
- let sizes = "(max-width: 1399px) calc(100vw - 48px), 1352px";
56
-
57
- /**
58
- * Two-column layout.
59
- */
60
- if (columnCount === 2) {
61
- maxWidth = "660";
62
- targetColumnWidth = 660;
63
-
64
- optimizedWidths = [640, 768, 1024, 1352];
65
- sizes =
66
- "(max-width: 767px) calc(100vw - 48px), " +
67
- "(max-width: 1399px) calc((100vw - 80px) / 2), " +
68
- "660px";
69
- }
70
-
71
- /**
72
- * Three-column layout.
73
- */
74
- else if (columnCount === 3) {
75
- maxWidth = "429";
76
- targetColumnWidth = 429;
77
-
78
- optimizedWidths = [320, 640, 768, 1024];
79
- sizes =
80
- "(max-width: 767px) calc(100vw - 48px), " +
81
- "(max-width: 1399px) calc((100vw - 112px) / 3), " +
82
- "429px";
83
- }
84
-
85
- /**
86
- * Four-column layout.
87
- */
88
- else if (columnCount === 4) {
89
- maxWidth = "314";
90
- targetColumnWidth = 314;
91
-
92
- optimizedWidths = [320, 640, 768];
93
- sizes =
94
- "(max-width: 767px) calc(100vw - 48px), " +
95
- "(max-width: 1399px) calc((100vw - 144px) / 4), " +
96
- "314px";
97
- }
98
- ---
99
-
100
- <div class="cms-block cms-block-header-image" style={`--max-w: ${maxWidth}px;`}>
101
- <KamaImage
102
- image={img}
103
- sizes={sizes}
104
- desktopWidths={optimizedWidths}
105
- idealWidth={targetColumnWidth}
106
- class="responsive-header-image"
107
- loading={isLcp ? "eager" : "lazy"}
108
- fetchpriority={isLcp ? "high" : "auto"}
109
- />
110
- </div>
111
-
112
- <style>
113
- .cms-block-header-image {
114
- width: 100%;
115
- max-width: var(--max-w, 1352px);
116
- margin: 0 auto 1.5rem auto;
117
- }
118
-
119
- :global(.responsive-header-image) {
120
- width: 100%;
121
- height: auto;
122
- display: block;
123
- border-radius: var(--cms-radius-md, 0.5rem);
124
- max-width: 100%;
125
- }
126
- </style>