@velastack/cms 0.1.0

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 (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +644 -0
  3. package/dist/cms.d.ts +6 -0
  4. package/dist/cms.js +30 -0
  5. package/dist/components/admin-bar/admin-bar-internal.svelte +1697 -0
  6. package/dist/components/admin-bar/admin-bar-internal.svelte.d.ts +12 -0
  7. package/dist/components/admin-bar/admin-bar.css +5 -0
  8. package/dist/components/admin-bar/admin-bar.svelte +355 -0
  9. package/dist/components/admin-bar/admin-bar.svelte.d.ts +7 -0
  10. package/dist/components/admin-bar/click-outside.d.ts +8 -0
  11. package/dist/components/admin-bar/click-outside.js +17 -0
  12. package/dist/components/admin-bar/css-root.svelte +23 -0
  13. package/dist/components/admin-bar/css-root.svelte.d.ts +19 -0
  14. package/dist/components/admin-bar/delete-page-dialog.svelte +326 -0
  15. package/dist/components/admin-bar/delete-page-dialog.svelte.d.ts +32 -0
  16. package/dist/components/admin-bar/history-panel.svelte +264 -0
  17. package/dist/components/admin-bar/history-panel.svelte.d.ts +8 -0
  18. package/dist/components/admin-bar/icons/bold.svelte +13 -0
  19. package/dist/components/admin-bar/icons/bold.svelte.d.ts +3 -0
  20. package/dist/components/admin-bar/icons/check.svelte +11 -0
  21. package/dist/components/admin-bar/icons/check.svelte.d.ts +3 -0
  22. package/dist/components/admin-bar/icons/chevron-down.svelte +11 -0
  23. package/dist/components/admin-bar/icons/chevron-down.svelte.d.ts +3 -0
  24. package/dist/components/admin-bar/icons/chevron-right.svelte +11 -0
  25. package/dist/components/admin-bar/icons/chevron-right.svelte.d.ts +3 -0
  26. package/dist/components/admin-bar/icons/chevron-up.svelte +11 -0
  27. package/dist/components/admin-bar/icons/chevron-up.svelte.d.ts +3 -0
  28. package/dist/components/admin-bar/icons/code.svelte +14 -0
  29. package/dist/components/admin-bar/icons/code.svelte.d.ts +3 -0
  30. package/dist/components/admin-bar/icons/external-link.svelte +15 -0
  31. package/dist/components/admin-bar/icons/external-link.svelte.d.ts +3 -0
  32. package/dist/components/admin-bar/icons/file.svelte +19 -0
  33. package/dist/components/admin-bar/icons/file.svelte.d.ts +3 -0
  34. package/dist/components/admin-bar/icons/heading-2.svelte +16 -0
  35. package/dist/components/admin-bar/icons/heading-2.svelte.d.ts +3 -0
  36. package/dist/components/admin-bar/icons/heading-3.svelte +17 -0
  37. package/dist/components/admin-bar/icons/heading-3.svelte.d.ts +3 -0
  38. package/dist/components/admin-bar/icons/icon.svelte +41 -0
  39. package/dist/components/admin-bar/icons/icon.svelte.d.ts +21 -0
  40. package/dist/components/admin-bar/icons/images.svelte +16 -0
  41. package/dist/components/admin-bar/icons/images.svelte.d.ts +3 -0
  42. package/dist/components/admin-bar/icons/italic.svelte +15 -0
  43. package/dist/components/admin-bar/icons/italic.svelte.d.ts +3 -0
  44. package/dist/components/admin-bar/icons/link-2-off.svelte +16 -0
  45. package/dist/components/admin-bar/icons/link-2-off.svelte.d.ts +3 -0
  46. package/dist/components/admin-bar/icons/link.svelte +14 -0
  47. package/dist/components/admin-bar/icons/link.svelte.d.ts +3 -0
  48. package/dist/components/admin-bar/icons/list-ordered.svelte +18 -0
  49. package/dist/components/admin-bar/icons/list-ordered.svelte.d.ts +3 -0
  50. package/dist/components/admin-bar/icons/list.svelte +18 -0
  51. package/dist/components/admin-bar/icons/list.svelte.d.ts +3 -0
  52. package/dist/components/admin-bar/icons/loader-circle.svelte +11 -0
  53. package/dist/components/admin-bar/icons/loader-circle.svelte.d.ts +3 -0
  54. package/dist/components/admin-bar/icons/minus.svelte +11 -0
  55. package/dist/components/admin-bar/icons/minus.svelte.d.ts +3 -0
  56. package/dist/components/admin-bar/icons/quote.svelte +24 -0
  57. package/dist/components/admin-bar/icons/quote.svelte.d.ts +3 -0
  58. package/dist/components/admin-bar/icons/search.svelte +14 -0
  59. package/dist/components/admin-bar/icons/search.svelte.d.ts +3 -0
  60. package/dist/components/admin-bar/icons/trash-2.svelte +17 -0
  61. package/dist/components/admin-bar/icons/trash-2.svelte.d.ts +3 -0
  62. package/dist/components/admin-bar/icons/triangle-alert.svelte +15 -0
  63. package/dist/components/admin-bar/icons/triangle-alert.svelte.d.ts +3 -0
  64. package/dist/components/admin-bar/icons/types.d.ts +7 -0
  65. package/dist/components/admin-bar/icons/types.js +1 -0
  66. package/dist/components/admin-bar/icons/undo-2.svelte +14 -0
  67. package/dist/components/admin-bar/icons/undo-2.svelte.d.ts +3 -0
  68. package/dist/components/admin-bar/icons/upload.svelte +15 -0
  69. package/dist/components/admin-bar/icons/upload.svelte.d.ts +3 -0
  70. package/dist/components/admin-bar/icons/x.svelte +14 -0
  71. package/dist/components/admin-bar/icons/x.svelte.d.ts +3 -0
  72. package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte +96 -0
  73. package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte.d.ts +7 -0
  74. package/dist/components/admin-bar/locales-panel.svelte +137 -0
  75. package/dist/components/admin-bar/locales-panel.svelte.d.ts +9 -0
  76. package/dist/components/admin-bar/media-panel.svelte +282 -0
  77. package/dist/components/admin-bar/media-panel.svelte.d.ts +7 -0
  78. package/dist/components/admin-bar/new-page-chooser-dialog.svelte +56 -0
  79. package/dist/components/admin-bar/new-page-chooser-dialog.svelte.d.ts +10 -0
  80. package/dist/components/admin-bar/new-page-dialog.svelte +126 -0
  81. package/dist/components/admin-bar/new-page-dialog.svelte.d.ts +14 -0
  82. package/dist/components/admin-bar/page-config.d.ts +61 -0
  83. package/dist/components/admin-bar/page-config.js +24 -0
  84. package/dist/components/admin-bar/pages-panel.svelte +639 -0
  85. package/dist/components/admin-bar/pages-panel.svelte.d.ts +13 -0
  86. package/dist/components/admin-bar/panel-footer.svelte +21 -0
  87. package/dist/components/admin-bar/panel-footer.svelte.d.ts +8 -0
  88. package/dist/components/admin-bar/panel-header.svelte +29 -0
  89. package/dist/components/admin-bar/panel-header.svelte.d.ts +10 -0
  90. package/dist/components/admin-bar/panel.svelte +41 -0
  91. package/dist/components/admin-bar/panel.svelte.d.ts +10 -0
  92. package/dist/components/admin-bar/publish-dialog.svelte +387 -0
  93. package/dist/components/admin-bar/publish-dialog.svelte.d.ts +16 -0
  94. package/dist/components/admin-bar/resolve-route.d.ts +20 -0
  95. package/dist/components/admin-bar/resolve-route.js +50 -0
  96. package/dist/components/admin-bar/seo-panel.svelte +387 -0
  97. package/dist/components/admin-bar/seo-panel.svelte.d.ts +7 -0
  98. package/dist/components/admin-bar/share-preview-link-dialog.svelte +97 -0
  99. package/dist/components/admin-bar/share-preview-link-dialog.svelte.d.ts +9 -0
  100. package/dist/components/admin-bar/site-settings-panel.svelte +225 -0
  101. package/dist/components/admin-bar/site-settings-panel.svelte.d.ts +7 -0
  102. package/dist/components/admin-bar/status-pill.svelte +49 -0
  103. package/dist/components/admin-bar/status-pill.svelte.d.ts +11 -0
  104. package/dist/components/admin-bar/theme.svelte.d.ts +16 -0
  105. package/dist/components/admin-bar/theme.svelte.js +39 -0
  106. package/dist/components/admin-bar/ui/badge/badge.svelte +57 -0
  107. package/dist/components/admin-bar/ui/badge/badge.svelte.d.ts +16 -0
  108. package/dist/components/admin-bar/ui/badge/index.d.ts +4 -0
  109. package/dist/components/admin-bar/ui/badge/index.js +4 -0
  110. package/dist/components/admin-bar/ui/button/button.svelte +73 -0
  111. package/dist/components/admin-bar/ui/button/button.svelte.d.ts +16 -0
  112. package/dist/components/admin-bar/ui/button/index.d.ts +4 -0
  113. package/dist/components/admin-bar/ui/button/index.js +4 -0
  114. package/dist/components/admin-bar/ui/collapsible/collapsible-content.svelte +7 -0
  115. package/dist/components/admin-bar/ui/collapsible/collapsible-content.svelte.d.ts +4 -0
  116. package/dist/components/admin-bar/ui/collapsible/collapsible-trigger.svelte +7 -0
  117. package/dist/components/admin-bar/ui/collapsible/collapsible-trigger.svelte.d.ts +4 -0
  118. package/dist/components/admin-bar/ui/collapsible/collapsible.svelte +7 -0
  119. package/dist/components/admin-bar/ui/collapsible/collapsible.svelte.d.ts +4 -0
  120. package/dist/components/admin-bar/ui/collapsible/index.d.ts +4 -0
  121. package/dist/components/admin-bar/ui/collapsible/index.js +6 -0
  122. package/dist/components/admin-bar/ui/dialog/dialog-close.svelte +7 -0
  123. package/dist/components/admin-bar/ui/dialog/dialog-close.svelte.d.ts +4 -0
  124. package/dist/components/admin-bar/ui/dialog/dialog-content.svelte +46 -0
  125. package/dist/components/admin-bar/ui/dialog/dialog-content.svelte.d.ts +11 -0
  126. package/dist/components/admin-bar/ui/dialog/dialog-description.svelte +17 -0
  127. package/dist/components/admin-bar/ui/dialog/dialog-description.svelte.d.ts +4 -0
  128. package/dist/components/admin-bar/ui/dialog/dialog-footer.svelte +23 -0
  129. package/dist/components/admin-bar/ui/dialog/dialog-footer.svelte.d.ts +5 -0
  130. package/dist/components/admin-bar/ui/dialog/dialog-header.svelte +20 -0
  131. package/dist/components/admin-bar/ui/dialog/dialog-header.svelte.d.ts +5 -0
  132. package/dist/components/admin-bar/ui/dialog/dialog-overlay.svelte +20 -0
  133. package/dist/components/admin-bar/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
  134. package/dist/components/admin-bar/ui/dialog/dialog-portal.svelte +7 -0
  135. package/dist/components/admin-bar/ui/dialog/dialog-portal.svelte.d.ts +3 -0
  136. package/dist/components/admin-bar/ui/dialog/dialog-title.svelte +17 -0
  137. package/dist/components/admin-bar/ui/dialog/dialog-title.svelte.d.ts +4 -0
  138. package/dist/components/admin-bar/ui/dialog/dialog-trigger.svelte +7 -0
  139. package/dist/components/admin-bar/ui/dialog/dialog-trigger.svelte.d.ts +4 -0
  140. package/dist/components/admin-bar/ui/dialog/dialog.svelte +7 -0
  141. package/dist/components/admin-bar/ui/dialog/dialog.svelte.d.ts +3 -0
  142. package/dist/components/admin-bar/ui/dialog/index.d.ts +11 -0
  143. package/dist/components/admin-bar/ui/dialog/index.js +13 -0
  144. package/dist/components/admin-bar/ui/input/index.d.ts +3 -0
  145. package/dist/components/admin-bar/ui/input/index.js +3 -0
  146. package/dist/components/admin-bar/ui/input/input.svelte +24 -0
  147. package/dist/components/admin-bar/ui/input/input.svelte.d.ts +5 -0
  148. package/dist/components/admin-bar/ui/kbd/index.d.ts +4 -0
  149. package/dist/components/admin-bar/ui/kbd/index.js +6 -0
  150. package/dist/components/admin-bar/ui/kbd/kbd-group.svelte +20 -0
  151. package/dist/components/admin-bar/ui/kbd/kbd-group.svelte.d.ts +5 -0
  152. package/dist/components/admin-bar/ui/kbd/kbd-shortcut.svelte +52 -0
  153. package/dist/components/admin-bar/ui/kbd/kbd-shortcut.svelte.d.ts +8 -0
  154. package/dist/components/admin-bar/ui/kbd/kbd.svelte +27 -0
  155. package/dist/components/admin-bar/ui/kbd/kbd.svelte.d.ts +5 -0
  156. package/dist/components/admin-bar/ui/label/index.d.ts +3 -0
  157. package/dist/components/admin-bar/ui/label/index.js +3 -0
  158. package/dist/components/admin-bar/ui/label/label.svelte +20 -0
  159. package/dist/components/admin-bar/ui/label/label.svelte.d.ts +4 -0
  160. package/dist/components/admin-bar/ui/menubar/index.d.ts +18 -0
  161. package/dist/components/admin-bar/ui/menubar/index.js +20 -0
  162. package/dist/components/admin-bar/ui/menubar/menubar-checkbox-item.svelte +46 -0
  163. package/dist/components/admin-bar/ui/menubar/menubar-checkbox-item.svelte.d.ts +10 -0
  164. package/dist/components/admin-bar/ui/menubar/menubar-content.svelte +28 -0
  165. package/dist/components/admin-bar/ui/menubar/menubar-content.svelte.d.ts +4 -0
  166. package/dist/components/admin-bar/ui/menubar/menubar-group-heading.svelte +25 -0
  167. package/dist/components/admin-bar/ui/menubar/menubar-group-heading.svelte.d.ts +8 -0
  168. package/dist/components/admin-bar/ui/menubar/menubar-group.svelte +12 -0
  169. package/dist/components/admin-bar/ui/menubar/menubar-group.svelte.d.ts +7 -0
  170. package/dist/components/admin-bar/ui/menubar/menubar-item.svelte +27 -0
  171. package/dist/components/admin-bar/ui/menubar/menubar-item.svelte.d.ts +8 -0
  172. package/dist/components/admin-bar/ui/menubar/menubar-label.svelte +25 -0
  173. package/dist/components/admin-bar/ui/menubar/menubar-label.svelte.d.ts +8 -0
  174. package/dist/components/admin-bar/ui/menubar/menubar-menu.svelte +7 -0
  175. package/dist/components/admin-bar/ui/menubar/menubar-menu.svelte.d.ts +3 -0
  176. package/dist/components/admin-bar/ui/menubar/menubar-portal.svelte +7 -0
  177. package/dist/components/admin-bar/ui/menubar/menubar-portal.svelte.d.ts +3 -0
  178. package/dist/components/admin-bar/ui/menubar/menubar-radio-group.svelte +11 -0
  179. package/dist/components/admin-bar/ui/menubar/menubar-radio-group.svelte.d.ts +4 -0
  180. package/dist/components/admin-bar/ui/menubar/menubar-radio-item.svelte +37 -0
  181. package/dist/components/admin-bar/ui/menubar/menubar-radio-item.svelte.d.ts +8 -0
  182. package/dist/components/admin-bar/ui/menubar/menubar-separator.svelte +17 -0
  183. package/dist/components/admin-bar/ui/menubar/menubar-separator.svelte.d.ts +4 -0
  184. package/dist/components/admin-bar/ui/menubar/menubar-shortcut.svelte +23 -0
  185. package/dist/components/admin-bar/ui/menubar/menubar-shortcut.svelte.d.ts +5 -0
  186. package/dist/components/admin-bar/ui/menubar/menubar-sub-content.svelte +20 -0
  187. package/dist/components/admin-bar/ui/menubar/menubar-sub-content.svelte.d.ts +4 -0
  188. package/dist/components/admin-bar/ui/menubar/menubar-sub-trigger.svelte +29 -0
  189. package/dist/components/admin-bar/ui/menubar/menubar-sub-trigger.svelte.d.ts +8 -0
  190. package/dist/components/admin-bar/ui/menubar/menubar-sub.svelte +7 -0
  191. package/dist/components/admin-bar/ui/menubar/menubar-sub.svelte.d.ts +4 -0
  192. package/dist/components/admin-bar/ui/menubar/menubar-trigger.svelte +20 -0
  193. package/dist/components/admin-bar/ui/menubar/menubar-trigger.svelte.d.ts +4 -0
  194. package/dist/components/admin-bar/ui/menubar/menubar.svelte +20 -0
  195. package/dist/components/admin-bar/ui/menubar/menubar.svelte.d.ts +4 -0
  196. package/dist/components/admin-bar/ui/select/index.d.ts +12 -0
  197. package/dist/components/admin-bar/ui/select/index.js +14 -0
  198. package/dist/components/admin-bar/ui/select/select-content.svelte +45 -0
  199. package/dist/components/admin-bar/ui/select/select-content.svelte.d.ts +11 -0
  200. package/dist/components/admin-bar/ui/select/select-group-heading.svelte +21 -0
  201. package/dist/components/admin-bar/ui/select/select-group-heading.svelte.d.ts +10 -0
  202. package/dist/components/admin-bar/ui/select/select-group.svelte +17 -0
  203. package/dist/components/admin-bar/ui/select/select-group.svelte.d.ts +4 -0
  204. package/dist/components/admin-bar/ui/select/select-item.svelte +40 -0
  205. package/dist/components/admin-bar/ui/select/select-item.svelte.d.ts +5 -0
  206. package/dist/components/admin-bar/ui/select/select-label.svelte +20 -0
  207. package/dist/components/admin-bar/ui/select/select-label.svelte.d.ts +6 -0
  208. package/dist/components/admin-bar/ui/select/select-portal.svelte +7 -0
  209. package/dist/components/admin-bar/ui/select/select-portal.svelte.d.ts +3 -0
  210. package/dist/components/admin-bar/ui/select/select-scroll-down-button.svelte +23 -0
  211. package/dist/components/admin-bar/ui/select/select-scroll-down-button.svelte.d.ts +5 -0
  212. package/dist/components/admin-bar/ui/select/select-scroll-up-button.svelte +23 -0
  213. package/dist/components/admin-bar/ui/select/select-scroll-up-button.svelte.d.ts +5 -0
  214. package/dist/components/admin-bar/ui/select/select-separator.svelte +21 -0
  215. package/dist/components/admin-bar/ui/select/select-separator.svelte.d.ts +4 -0
  216. package/dist/components/admin-bar/ui/select/select-trigger.svelte +31 -0
  217. package/dist/components/admin-bar/ui/select/select-trigger.svelte.d.ts +8 -0
  218. package/dist/components/admin-bar/ui/select/select.svelte +11 -0
  219. package/dist/components/admin-bar/ui/select/select.svelte.d.ts +3 -0
  220. package/dist/components/admin-bar/ui/separator/index.d.ts +2 -0
  221. package/dist/components/admin-bar/ui/separator/index.js +4 -0
  222. package/dist/components/admin-bar/ui/separator/separator.svelte +21 -0
  223. package/dist/components/admin-bar/ui/separator/separator.svelte.d.ts +4 -0
  224. package/dist/components/admin-bar/ui/textarea/index.d.ts +3 -0
  225. package/dist/components/admin-bar/ui/textarea/index.js +3 -0
  226. package/dist/components/admin-bar/ui/textarea/textarea.svelte +21 -0
  227. package/dist/components/admin-bar/ui/textarea/textarea.svelte.d.ts +5 -0
  228. package/dist/components/admin-bar/user-avatar.svelte +29 -0
  229. package/dist/components/admin-bar/user-avatar.svelte.d.ts +7 -0
  230. package/dist/components/admin-bar/utils.d.ts +10 -0
  231. package/dist/components/admin-bar/utils.js +46 -0
  232. package/dist/components/admin-bar/variants.d.ts +20 -0
  233. package/dist/components/admin-bar/variants.js +14 -0
  234. package/dist/components/cms/cms-boolean.svelte +102 -0
  235. package/dist/components/cms/cms-boolean.svelte.d.ts +10 -0
  236. package/dist/components/cms/cms-date-time-editable.svelte +66 -0
  237. package/dist/components/cms/cms-date-time-editable.svelte.d.ts +11 -0
  238. package/dist/components/cms/cms-date-time.svelte +67 -0
  239. package/dist/components/cms/cms-date-time.svelte.d.ts +19 -0
  240. package/dist/components/cms/cms-entries.svelte +24 -0
  241. package/dist/components/cms/cms-entries.svelte.d.ts +31 -0
  242. package/dist/components/cms/cms-image-editable.svelte +439 -0
  243. package/dist/components/cms/cms-image-editable.svelte.d.ts +11 -0
  244. package/dist/components/cms/cms-image.svelte +78 -0
  245. package/dist/components/cms/cms-image.svelte.d.ts +18 -0
  246. package/dist/components/cms/cms-link-editable.svelte +429 -0
  247. package/dist/components/cms/cms-link-editable.svelte.d.ts +13 -0
  248. package/dist/components/cms/cms-link.svelte +92 -0
  249. package/dist/components/cms/cms-link.svelte.d.ts +25 -0
  250. package/dist/components/cms/cms-markdown-editable.svelte +74 -0
  251. package/dist/components/cms/cms-markdown-editable.svelte.d.ts +9 -0
  252. package/dist/components/cms/cms-markdown.svelte +56 -0
  253. package/dist/components/cms/cms-markdown.svelte.d.ts +10 -0
  254. package/dist/components/cms/cms-media-picker.svelte +150 -0
  255. package/dist/components/cms/cms-media-picker.svelte.d.ts +8 -0
  256. package/dist/components/cms/cms-number-editable.svelte +77 -0
  257. package/dist/components/cms/cms-number-editable.svelte.d.ts +13 -0
  258. package/dist/components/cms/cms-number.svelte +63 -0
  259. package/dist/components/cms/cms-number.svelte.d.ts +16 -0
  260. package/dist/components/cms/cms-repeater-editable.svelte +137 -0
  261. package/dist/components/cms/cms-repeater-editable.svelte.d.ts +31 -0
  262. package/dist/components/cms/cms-repeater.svelte +55 -0
  263. package/dist/components/cms/cms-repeater.svelte.d.ts +30 -0
  264. package/dist/components/cms/cms-rich-text-editable.svelte +101 -0
  265. package/dist/components/cms/cms-rich-text-editable.svelte.d.ts +9 -0
  266. package/dist/components/cms/cms-rich-text-toolbar.svelte +246 -0
  267. package/dist/components/cms/cms-rich-text-toolbar.svelte.d.ts +9 -0
  268. package/dist/components/cms/cms-rich-text.svelte +74 -0
  269. package/dist/components/cms/cms-rich-text.svelte.d.ts +10 -0
  270. package/dist/components/cms/cms-store.svelte.d.ts +294 -0
  271. package/dist/components/cms/cms-store.svelte.js +625 -0
  272. package/dist/components/cms/cms-text.svelte +131 -0
  273. package/dist/components/cms/cms-text.svelte.d.ts +11 -0
  274. package/dist/components/cms/index.d.ts +13 -0
  275. package/dist/components/cms/index.js +11 -0
  276. package/dist/components/cms/install-scope.svelte.d.ts +7 -0
  277. package/dist/components/cms/install-scope.svelte.js +33 -0
  278. package/dist/components/cms/locale-merge.d.ts +41 -0
  279. package/dist/components/cms/locale-merge.js +77 -0
  280. package/dist/components/cms/overlay-sync.d.ts +82 -0
  281. package/dist/components/cms/overlay-sync.js +76 -0
  282. package/dist/components/cms/path.d.ts +30 -0
  283. package/dist/components/cms/path.js +156 -0
  284. package/dist/components/cms/scope.d.ts +120 -0
  285. package/dist/components/cms/scope.js +23 -0
  286. package/dist/index.d.ts +27 -0
  287. package/dist/index.js +28 -0
  288. package/dist/srv/README.md +341 -0
  289. package/dist/srv/api-adapter.d.ts +20 -0
  290. package/dist/srv/api-adapter.js +178 -0
  291. package/dist/srv/cms.d.ts +62 -0
  292. package/dist/srv/cms.js +35 -0
  293. package/dist/srv/index.d.ts +5 -0
  294. package/dist/srv/index.js +4 -0
  295. package/dist/srv/load-cms.d.ts +105 -0
  296. package/dist/srv/load-cms.js +227 -0
  297. package/dist/srv/mock-adapter.d.ts +96 -0
  298. package/dist/srv/mock-adapter.js +171 -0
  299. package/dist/srv/types.d.ts +114 -0
  300. package/dist/srv/types.js +1 -0
  301. package/package.json +116 -0
  302. package/plugin/README.md +137 -0
  303. package/plugin/dist/adapter.d.ts +35 -0
  304. package/plugin/dist/adapter.js +346 -0
  305. package/plugin/dist/adapter.js.map +1 -0
  306. package/plugin/dist/build-state.d.ts +10 -0
  307. package/plugin/dist/build-state.js +26 -0
  308. package/plugin/dist/build-state.js.map +1 -0
  309. package/plugin/dist/fallback-shim.js +194 -0
  310. package/plugin/dist/index.d.ts +56 -0
  311. package/plugin/dist/index.js +396 -0
  312. package/plugin/dist/index.js.map +1 -0
  313. package/plugin/dist/manifest.d.ts +76 -0
  314. package/plugin/dist/manifest.js +367 -0
  315. package/plugin/dist/manifest.js.map +1 -0
  316. package/plugin/dist/media.d.ts +36 -0
  317. package/plugin/dist/media.js +153 -0
  318. package/plugin/dist/media.js.map +1 -0
  319. package/plugin/dist/parse-svelte.d.ts +35 -0
  320. package/plugin/dist/parse-svelte.js +120 -0
  321. package/plugin/dist/parse-svelte.js.map +1 -0
  322. package/plugin/dist/route-tree.d.ts +27 -0
  323. package/plugin/dist/route-tree.js +69 -0
  324. package/plugin/dist/route-tree.js.map +1 -0
  325. package/plugin/dist/transforms.d.ts +42 -0
  326. package/plugin/dist/transforms.js +95 -0
  327. package/plugin/dist/transforms.js.map +1 -0
@@ -0,0 +1,131 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { getCmsScope } from './scope.js';
4
+ import { cmsStore, type CmsScopeRef } from './cms-store.svelte.js';
5
+
6
+ type Props = {
7
+ name: string;
8
+ fallback?: string;
9
+ /** Per-item override used by `CmsRepeater`. */
10
+ value?: unknown;
11
+ children?: Snippet;
12
+ };
13
+
14
+ let { name, fallback, value, children }: Props = $props();
15
+
16
+ const scope = getCmsScope();
17
+ const ref = $derived<CmsScopeRef | null>(
18
+ scope ? { scopeId: scope.scopeId, routeId: scope.routeId, params: scope.params } : null
19
+ );
20
+
21
+ const resolved = $derived.by(() => {
22
+ if (value !== undefined) return value;
23
+ return ref ? cmsStore.getValue(ref, name) : undefined;
24
+ });
25
+
26
+ const display = $derived(typeof resolved === 'string' ? resolved : (fallback ?? ''));
27
+ const editable = $derived(cmsStore.isEditing && value === undefined && !!ref);
28
+
29
+ let el = $state<HTMLSpanElement>();
30
+ let childrenEl = $state<HTMLElement>();
31
+ let initialFromChildren = $state<string | undefined>(undefined);
32
+ let composing = false;
33
+
34
+ $effect.pre(() => {
35
+ if (editable && childrenEl && initialFromChildren === undefined) {
36
+ const text = childrenEl.textContent?.trim();
37
+ initialFromChildren = text || undefined;
38
+ }
39
+ });
40
+
41
+ const editValue = $derived.by(() => {
42
+ if (typeof resolved === 'string') return resolved;
43
+ if (fallback !== undefined) return fallback;
44
+ return initialFromChildren ?? '';
45
+ });
46
+
47
+ $effect(() => {
48
+ if (!el) return;
49
+ const target = editValue;
50
+ if (document.activeElement === el) return;
51
+ if (el.textContent === target) return;
52
+ el.textContent = target;
53
+ });
54
+
55
+ const writeValue = (text: string) => {
56
+ if (!ref) return;
57
+ cmsStore.setValue(ref, name, text);
58
+ };
59
+
60
+ const onInput = (e: Event) => {
61
+ if (composing) return;
62
+ writeValue((e.currentTarget as HTMLElement).textContent ?? '');
63
+ };
64
+
65
+ const onKeydown = (e: KeyboardEvent) => {
66
+ if (e.key === 'Enter') e.preventDefault();
67
+ };
68
+
69
+ const onCompositionEnd = (e: CompositionEvent) => {
70
+ composing = false;
71
+ writeValue((e.currentTarget as HTMLElement).textContent ?? '');
72
+ };
73
+ </script>
74
+
75
+ {#if editable && ref}
76
+ <span
77
+ bind:this={el}
78
+ class="cms-text-editable"
79
+ contenteditable="plaintext-only"
80
+ data-placeholder={name}
81
+ data-cms-name={name}
82
+ data-cms-scope={scope?.scopeId ?? '?'}
83
+ role="textbox"
84
+ tabindex="0"
85
+ aria-multiline="false"
86
+ aria-label={name}
87
+ spellcheck="true"
88
+ oninput={onInput}
89
+ onkeydown={onKeydown}
90
+ oncompositionstart={() => (composing = true)}
91
+ oncompositionend={onCompositionEnd}
92
+ ></span>
93
+ {:else if display}
94
+ {display}
95
+ {:else if children}
96
+ <span bind:this={childrenEl} class="cms-text-children">{@render children()}</span>
97
+ {:else}
98
+ <span class="cms-missing" data-cms-name={name} data-cms-scope={scope?.scopeId ?? '?'}>{name}</span
99
+ >
100
+ {/if}
101
+
102
+ <style>
103
+ .cms-text-editable {
104
+ border-radius: 0.125rem;
105
+ outline: 1px dashed rgba(127, 127, 127, 0.6);
106
+ outline-offset: 2px;
107
+ }
108
+ .cms-text-editable:focus {
109
+ outline: 2px solid rgb(99, 102, 241);
110
+ outline-offset: 2px;
111
+ }
112
+ .cms-text-editable:empty::before {
113
+ content: attr(data-placeholder);
114
+ color: rgba(127, 127, 127, 0.6);
115
+ font-style: italic;
116
+ }
117
+
118
+ .cms-text-children {
119
+ display: contents;
120
+ }
121
+
122
+ .cms-missing {
123
+ display: inline-block;
124
+ padding: 0 0.25rem;
125
+ border: 1px dashed rgba(127, 127, 127, 0.6);
126
+ border-radius: 0.25rem;
127
+ font-family: ui-monospace, monospace;
128
+ font-size: 0.85em;
129
+ color: rgba(127, 127, 127, 0.9);
130
+ }
131
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ type Props = {
3
+ name: string;
4
+ fallback?: string;
5
+ /** Per-item override used by `CmsRepeater`. */
6
+ value?: unknown;
7
+ children?: Snippet;
8
+ };
9
+ declare const CmsText: import("svelte").Component<Props, {}, "">;
10
+ type CmsText = ReturnType<typeof CmsText>;
11
+ export default CmsText;
@@ -0,0 +1,13 @@
1
+ export { default as CmsText } from './cms-text.svelte';
2
+ export { default as CmsRichText } from './cms-rich-text.svelte';
3
+ export { default as CmsMarkdown } from './cms-markdown.svelte';
4
+ export { default as CmsImage } from './cms-image.svelte';
5
+ export { default as CmsBoolean } from './cms-boolean.svelte';
6
+ export { default as CmsNumber } from './cms-number.svelte';
7
+ export { default as CmsDateTime } from './cms-date-time.svelte';
8
+ export { default as CmsLink } from './cms-link.svelte';
9
+ export type { CmsLinkValue, CmsLinkRenderProps } from './cms-link.svelte';
10
+ export { default as CmsRepeater } from './cms-repeater.svelte';
11
+ export { default as CmsEntries } from './cms-entries.svelte';
12
+ export { CMS_SCOPE, getCmsScope, getCmsValue } from './scope.js';
13
+ export type { CmsScope, CmsPayload, CmsEntry } from './scope.js';
@@ -0,0 +1,11 @@
1
+ export { default as CmsText } from './cms-text.svelte';
2
+ export { default as CmsRichText } from './cms-rich-text.svelte';
3
+ export { default as CmsMarkdown } from './cms-markdown.svelte';
4
+ export { default as CmsImage } from './cms-image.svelte';
5
+ export { default as CmsBoolean } from './cms-boolean.svelte';
6
+ export { default as CmsNumber } from './cms-number.svelte';
7
+ export { default as CmsDateTime } from './cms-date-time.svelte';
8
+ export { default as CmsLink } from './cms-link.svelte';
9
+ export { default as CmsRepeater } from './cms-repeater.svelte';
10
+ export { default as CmsEntries } from './cms-entries.svelte';
11
+ export { CMS_SCOPE, getCmsScope, getCmsValue } from './scope.js';
@@ -0,0 +1,7 @@
1
+ export type InstallCmsScopeConfig = {
2
+ scopeId: string;
3
+ kind: 'layout' | 'page';
4
+ routeId: string;
5
+ ownedParams: string[];
6
+ };
7
+ export declare const installCmsScope: (config: InstallCmsScopeConfig) => void;
@@ -0,0 +1,33 @@
1
+ import { setContext } from 'svelte';
2
+ import { page } from '$app/state';
3
+ import { CMS_SCOPE } from './scope.js';
4
+ /**
5
+ * Used by the build-time auto-injection in `+layout.svelte` / `+page.svelte`.
6
+ * Sets the `CMS_SCOPE` Svelte context to a runes-backed scope object that
7
+ * tracks `page.params` so navigation between sibling param values updates the
8
+ * scope's `params` (e.g. `{ slug: 'suite-1' }` → `{ slug: 'suite-2' }`).
9
+ */
10
+ const collectOwnedParams = (ownedParams, all) => {
11
+ const out = {};
12
+ for (const p of ownedParams) {
13
+ const v = all[p];
14
+ if (typeof v === 'string')
15
+ out[p] = v;
16
+ }
17
+ return out;
18
+ };
19
+ export const installCmsScope = (config) => {
20
+ // Compute synchronously at init so SSR sees the right params — `$effect`
21
+ // only fires on the client.
22
+ const initialParams = collectOwnedParams(config.ownedParams, page.params);
23
+ const scope = $state({
24
+ scopeId: config.scopeId,
25
+ kind: config.kind,
26
+ routeId: config.routeId,
27
+ params: initialParams
28
+ });
29
+ $effect(() => {
30
+ scope.params = collectOwnedParams(config.ownedParams, page.params);
31
+ });
32
+ setContext(CMS_SCOPE, scope);
33
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Pure locale-fallback merge helpers, shared between the server-load path
3
+ * (`resolveCmsPayload`) and the client-overlay path (`loadAndApplyOverlay`)
4
+ * so both compose the same `requested → default → undefined` chain.
5
+ *
6
+ * The convention (see `mock-adapter.ts`'s contract): adapters return only
7
+ * what's stored for the requested locale. Callers fetch the requested locale
8
+ * AND the default locale separately, then call these helpers to produce the
9
+ * fallback-merged result. Defaults fill gaps; requested values override.
10
+ *
11
+ * Tombstones are not handled here — callers should resolve tombstone
12
+ * precedence (requested wins outright) before passing trees in.
13
+ */
14
+ import type { CmsEntry } from './scope.js';
15
+ import { type Tree } from './path.js';
16
+ /**
17
+ * Merge requested-locale doc trees over default-locale doc trees, per scope.
18
+ *
19
+ * - Both present → `mergeTree(fallback, requested)` (requested overrides on
20
+ * leaves; objects deep-merge; arrays replace).
21
+ * - Requested only → returned as-is (requested locale has its own content;
22
+ * default-locale entry happens to be missing — surface what we have).
23
+ * - Fallback only → returned as-is (requested locale lacks the scope; show
24
+ * the default-locale value).
25
+ * - Neither → scope omitted from output.
26
+ *
27
+ * Pass `fallback = null` for the no-fallback case (locale === defaultLocale,
28
+ * or single-locale fetch); the function then just unwraps `requested`.
29
+ */
30
+ export declare const mergeLocaleDocs: (requested: Record<string, Tree | undefined>, fallback: Record<string, Tree | undefined> | null) => Record<string, Tree>;
31
+ /**
32
+ * Merge requested-locale entry lists over default-locale entry lists, per
33
+ * routeId. Entries are unioned by stringified `params`; requested-locale
34
+ * entries win on metadata when both locales have the same `params`.
35
+ *
36
+ * Pass `fallback = null` for the no-fallback case; the function then returns
37
+ * the requested map verbatim (each list is whatever the caller stored).
38
+ *
39
+ * Tombstone filtering (`redirectTo`, `gone`) happens at the call site.
40
+ */
41
+ export declare const mergeLocaleEntries: (requested: Record<string, CmsEntry[]>, fallback: Record<string, CmsEntry[]> | null) => Record<string, CmsEntry[]>;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Pure locale-fallback merge helpers, shared between the server-load path
3
+ * (`resolveCmsPayload`) and the client-overlay path (`loadAndApplyOverlay`)
4
+ * so both compose the same `requested → default → undefined` chain.
5
+ *
6
+ * The convention (see `mock-adapter.ts`'s contract): adapters return only
7
+ * what's stored for the requested locale. Callers fetch the requested locale
8
+ * AND the default locale separately, then call these helpers to produce the
9
+ * fallback-merged result. Defaults fill gaps; requested values override.
10
+ *
11
+ * Tombstones are not handled here — callers should resolve tombstone
12
+ * precedence (requested wins outright) before passing trees in.
13
+ */
14
+ import { mergeTree } from './path.js';
15
+ /**
16
+ * Merge requested-locale doc trees over default-locale doc trees, per scope.
17
+ *
18
+ * - Both present → `mergeTree(fallback, requested)` (requested overrides on
19
+ * leaves; objects deep-merge; arrays replace).
20
+ * - Requested only → returned as-is (requested locale has its own content;
21
+ * default-locale entry happens to be missing — surface what we have).
22
+ * - Fallback only → returned as-is (requested locale lacks the scope; show
23
+ * the default-locale value).
24
+ * - Neither → scope omitted from output.
25
+ *
26
+ * Pass `fallback = null` for the no-fallback case (locale === defaultLocale,
27
+ * or single-locale fetch); the function then just unwraps `requested`.
28
+ */
29
+ export const mergeLocaleDocs = (requested, fallback) => {
30
+ const out = {};
31
+ const scopeIds = new Set([
32
+ ...Object.keys(requested),
33
+ ...(fallback ? Object.keys(fallback) : [])
34
+ ]);
35
+ for (const scopeId of scopeIds) {
36
+ const r = requested[scopeId];
37
+ const f = fallback?.[scopeId];
38
+ if (f && r)
39
+ out[scopeId] = mergeTree(f, r);
40
+ else if (f)
41
+ out[scopeId] = f;
42
+ else if (r)
43
+ out[scopeId] = r;
44
+ }
45
+ return out;
46
+ };
47
+ /**
48
+ * Merge requested-locale entry lists over default-locale entry lists, per
49
+ * routeId. Entries are unioned by stringified `params`; requested-locale
50
+ * entries win on metadata when both locales have the same `params`.
51
+ *
52
+ * Pass `fallback = null` for the no-fallback case; the function then returns
53
+ * the requested map verbatim (each list is whatever the caller stored).
54
+ *
55
+ * Tombstone filtering (`redirectTo`, `gone`) happens at the call site.
56
+ */
57
+ export const mergeLocaleEntries = (requested, fallback) => {
58
+ if (!fallback) {
59
+ const out = {};
60
+ for (const [rid, list] of Object.entries(requested))
61
+ out[rid] = [...list];
62
+ return out;
63
+ }
64
+ const out = {};
65
+ const routeIds = new Set([...Object.keys(requested), ...Object.keys(fallback)]);
66
+ for (const routeId of routeIds) {
67
+ const r = requested[routeId] ?? [];
68
+ const f = fallback[routeId] ?? [];
69
+ const merged = new Map();
70
+ for (const e of f)
71
+ merged.set(JSON.stringify(e.params), e);
72
+ for (const e of r)
73
+ merged.set(JSON.stringify(e.params), e);
74
+ out[routeId] = [...merged.values()];
75
+ }
76
+ return out;
77
+ };
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Pure decision logic for the editor overlay sync. The admin bar reads URL
3
+ * params + store state, calls `deriveOverlayIntents`, and dispatches the
4
+ * returned intents (URL navigations, async overlay loads, overlay clears).
5
+ *
6
+ * Keeping this pure lets us unit-test every (versionKey, locale, openRelease,
7
+ * previewParam, openReleaseFetched) combination without spinning up Svelte.
8
+ */
9
+ import type { CmsScopeRef } from './cms-store.svelte.js';
10
+ export type OverlayIntent = {
11
+ kind: 'fetch-open-release';
12
+ } | {
13
+ kind: 'fetch-version-release';
14
+ versionKey: string;
15
+ } | {
16
+ kind: 'set-preview-param';
17
+ value: string | null;
18
+ } | {
19
+ kind: 'load-version-overlay';
20
+ versionKey: string;
21
+ locale: string;
22
+ }
23
+ /** `previewKey: null` fetches published-only — used when previewing a
24
+ * non-default locale without an open draft, so the overlay carries the
25
+ * locale's published tree (with default-locale fallback merged by
26
+ * `loadAndApplyOverlay`'s dual-fetch). */
27
+ | {
28
+ kind: 'load-overlay';
29
+ previewKey: string | null;
30
+ locale: string;
31
+ } | {
32
+ kind: 'clear-overlay';
33
+ };
34
+ export interface OverlaySyncInput {
35
+ /** `?version=…` URL param: when set, we're in past-release snapshot mode. */
36
+ versionKey: string | null;
37
+ /** Active editor preview locale (URL `?locale=` overriding `cms.locale`). */
38
+ locale: string;
39
+ /**
40
+ * `page.data.cms.locale` — the locale the server rendered for this request.
41
+ * When `locale === pageLocale`, the page's `cms.docs` already provides the
42
+ * base content (no overlay needed for "show the published tree"). When
43
+ * they differ, we must load the overlay so non-default-locale views see
44
+ * content (with default-locale fallback) rather than empty fields.
45
+ */
46
+ pageLocale: string;
47
+ /** Current open-release preview_key from `cmsStore.openRelease`, or null. */
48
+ openReleaseKey: string | null;
49
+ /** Whether `fetchOpenRelease` has resolved at least once this session. */
50
+ openReleaseFetched: boolean;
51
+ /** `?preview=…` URL param value, or null if absent. */
52
+ previewParam: string | null;
53
+ }
54
+ /**
55
+ * Decide what to do given the current sync state. Rules, in order:
56
+ *
57
+ * 1. If openRelease hasn't been fetched yet, always emit `fetch-open-release`.
58
+ * (Version mode still loads its overlay immediately; non-version decisions
59
+ * defer to the next pass once the fetch resolves.)
60
+ * 2. Version mode wins: load the past-release snapshot for `versionKey` and
61
+ * `locale`. Don't touch `?preview=` (the consumer chose `?version=`).
62
+ * 3. Otherwise, only act on draft-mode rules once `openReleaseFetched` is
63
+ * true — pre-fetch we don't know if there's a draft, so we mustn't strip
64
+ * a preexisting `?preview=` from the URL.
65
+ * 4. With an open release whose key disagrees with `?preview=`, sync the URL
66
+ * first; the param change re-runs the effect into rule 5.
67
+ * 5. With an open release whose key matches: load the draft overlay.
68
+ * 6. With no open release but a stale `?preview=`: strip the param. Then
69
+ * fall through to rule 7's locale logic in the *same* intent batch so the
70
+ * field render isn't briefly empty between strip and the next effect run.
71
+ * 7. With no open release and no draft overlay needed:
72
+ * - `locale === pageLocale`: clear the overlay — the page's `cms.docs` is
73
+ * authoritative and matching, so the field reads from base directly.
74
+ * - `locale !== pageLocale`: load published-only overlay. Without this,
75
+ * `mergedTree(non-pageLocale)` would have empty base AND empty overlay,
76
+ * and fields would fall through to their component fallback even though
77
+ * a default-locale value exists. The dual-fetch in `loadAndApplyOverlay`
78
+ * composes the `requested → default → undefined` chain.
79
+ */
80
+ export declare function deriveOverlayIntents(input: OverlaySyncInput): OverlayIntent[];
81
+ /** Stable cache key for `(scope, locale)` overlay/draft buckets. */
82
+ export declare const composeKey: (scope: CmsScopeRef, locale: string) => string;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Pure decision logic for the editor overlay sync. The admin bar reads URL
3
+ * params + store state, calls `deriveOverlayIntents`, and dispatches the
4
+ * returned intents (URL navigations, async overlay loads, overlay clears).
5
+ *
6
+ * Keeping this pure lets us unit-test every (versionKey, locale, openRelease,
7
+ * previewParam, openReleaseFetched) combination without spinning up Svelte.
8
+ */
9
+ /**
10
+ * Decide what to do given the current sync state. Rules, in order:
11
+ *
12
+ * 1. If openRelease hasn't been fetched yet, always emit `fetch-open-release`.
13
+ * (Version mode still loads its overlay immediately; non-version decisions
14
+ * defer to the next pass once the fetch resolves.)
15
+ * 2. Version mode wins: load the past-release snapshot for `versionKey` and
16
+ * `locale`. Don't touch `?preview=` (the consumer chose `?version=`).
17
+ * 3. Otherwise, only act on draft-mode rules once `openReleaseFetched` is
18
+ * true — pre-fetch we don't know if there's a draft, so we mustn't strip
19
+ * a preexisting `?preview=` from the URL.
20
+ * 4. With an open release whose key disagrees with `?preview=`, sync the URL
21
+ * first; the param change re-runs the effect into rule 5.
22
+ * 5. With an open release whose key matches: load the draft overlay.
23
+ * 6. With no open release but a stale `?preview=`: strip the param. Then
24
+ * fall through to rule 7's locale logic in the *same* intent batch so the
25
+ * field render isn't briefly empty between strip and the next effect run.
26
+ * 7. With no open release and no draft overlay needed:
27
+ * - `locale === pageLocale`: clear the overlay — the page's `cms.docs` is
28
+ * authoritative and matching, so the field reads from base directly.
29
+ * - `locale !== pageLocale`: load published-only overlay. Without this,
30
+ * `mergedTree(non-pageLocale)` would have empty base AND empty overlay,
31
+ * and fields would fall through to their component fallback even though
32
+ * a default-locale value exists. The dual-fetch in `loadAndApplyOverlay`
33
+ * composes the `requested → default → undefined` chain.
34
+ */
35
+ export function deriveOverlayIntents(input) {
36
+ const intents = [];
37
+ if (!input.openReleaseFetched) {
38
+ intents.push({ kind: 'fetch-open-release' });
39
+ }
40
+ if (input.versionKey) {
41
+ intents.push({ kind: 'fetch-version-release', versionKey: input.versionKey }, { kind: 'load-version-overlay', versionKey: input.versionKey, locale: input.locale });
42
+ return intents;
43
+ }
44
+ if (!input.openReleaseFetched)
45
+ return intents;
46
+ if (input.openReleaseKey && input.previewParam !== input.openReleaseKey) {
47
+ intents.push({ kind: 'set-preview-param', value: input.openReleaseKey });
48
+ return intents;
49
+ }
50
+ if (input.openReleaseKey) {
51
+ intents.push({
52
+ kind: 'load-overlay',
53
+ previewKey: input.openReleaseKey,
54
+ locale: input.locale
55
+ });
56
+ return intents;
57
+ }
58
+ if (input.previewParam) {
59
+ intents.push({ kind: 'set-preview-param', value: null });
60
+ }
61
+ if (input.locale !== input.pageLocale) {
62
+ intents.push({ kind: 'load-overlay', previewKey: null, locale: input.locale });
63
+ }
64
+ else {
65
+ intents.push({ kind: 'clear-overlay' });
66
+ }
67
+ return intents;
68
+ }
69
+ /** Stable cache key for `(scope, locale)` overlay/draft buckets. */
70
+ export const composeKey = (scope, locale) => {
71
+ const keys = Object.keys(scope.params).sort();
72
+ const base = keys.length === 0
73
+ ? scope.scopeId
74
+ : `${scope.scopeId}?${keys.map((k) => `${k}=${scope.params[k]}`).join('&')}`;
75
+ return `${base}|locale=${locale}`;
76
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Lodash-style path utilities for tree-shaped CMS state.
3
+ *
4
+ * Paths are dot-separated strings: `welcome.title`, `gallery.0.caption`,
5
+ * `metadata.openGraph.image.url`. Numeric segments index arrays. There are
6
+ * no brackets — `gallery[0].caption` is not supported. When `set` walks into
7
+ * a missing parent, the next segment's shape decides whether to create an
8
+ * array (numeric) or a plain object (anything else).
9
+ *
10
+ * `mergeTree` deep-merges plain objects but **replaces arrays wholesale** —
11
+ * critical so a repeater's reorder/delete doesn't accidentally concat with
12
+ * the previous order.
13
+ */
14
+ export type Tree = Record<string, unknown>;
15
+ export declare const parsePath: (path: string) => string[];
16
+ export declare const get: (tree: unknown, path: string) => unknown;
17
+ export declare const has: (tree: unknown, path: string) => boolean;
18
+ export declare const set: (tree: Tree, path: string, value: unknown) => void;
19
+ export declare const unset: (tree: Tree, path: string) => boolean;
20
+ export declare const mergeTree: (...trees: Array<Tree | undefined>) => Tree;
21
+ /**
22
+ * Sorted leaf paths whose values differ between `before` and `after`. Used by
23
+ * the publish dialog to summarize what changed in a release item.
24
+ *
25
+ * Treats `undefined` as an empty tree at the root, so adding/removing top-level
26
+ * branches still produces leaf paths. Two arrays of equal length recurse per
27
+ * index; arrays of differing length emit the array path itself (aligns with
28
+ * `mergeTree`'s array-replace semantics).
29
+ */
30
+ export declare const diffPaths: (before: unknown, after: unknown) => string[];
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Lodash-style path utilities for tree-shaped CMS state.
3
+ *
4
+ * Paths are dot-separated strings: `welcome.title`, `gallery.0.caption`,
5
+ * `metadata.openGraph.image.url`. Numeric segments index arrays. There are
6
+ * no brackets — `gallery[0].caption` is not supported. When `set` walks into
7
+ * a missing parent, the next segment's shape decides whether to create an
8
+ * array (numeric) or a plain object (anything else).
9
+ *
10
+ * `mergeTree` deep-merges plain objects but **replaces arrays wholesale** —
11
+ * critical so a repeater's reorder/delete doesn't accidentally concat with
12
+ * the previous order.
13
+ */
14
+ const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
15
+ const isIndex = (s) => /^[0-9]+$/.test(s);
16
+ export const parsePath = (path) => (path === '' ? [] : path.split('.'));
17
+ export const get = (tree, path) => {
18
+ const segs = parsePath(path);
19
+ let cur = tree;
20
+ for (const s of segs) {
21
+ if (cur == null || typeof cur !== 'object')
22
+ return undefined;
23
+ cur = cur[s];
24
+ }
25
+ return cur;
26
+ };
27
+ export const has = (tree, path) => {
28
+ const segs = parsePath(path);
29
+ if (segs.length === 0)
30
+ return tree !== undefined;
31
+ let cur = tree;
32
+ for (let i = 0; i < segs.length; i++) {
33
+ if (cur == null || typeof cur !== 'object')
34
+ return false;
35
+ if (!(segs[i] in cur))
36
+ return false;
37
+ cur = cur[segs[i]];
38
+ }
39
+ return true;
40
+ };
41
+ export const set = (tree, path, value) => {
42
+ const segs = parsePath(path);
43
+ if (segs.length === 0)
44
+ throw new Error('set: empty path');
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ let cur = tree;
47
+ for (let i = 0; i < segs.length - 1; i++) {
48
+ const seg = segs[i];
49
+ const next = segs[i + 1];
50
+ const child = cur[seg];
51
+ if (child == null || typeof child !== 'object') {
52
+ cur[seg] = isIndex(next) ? [] : {};
53
+ }
54
+ cur = cur[seg];
55
+ }
56
+ cur[segs[segs.length - 1]] = value;
57
+ };
58
+ export const unset = (tree, path) => {
59
+ const segs = parsePath(path);
60
+ if (segs.length === 0)
61
+ return false;
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ let cur = tree;
64
+ for (let i = 0; i < segs.length - 1; i++) {
65
+ if (cur == null || typeof cur !== 'object')
66
+ return false;
67
+ cur = cur[segs[i]];
68
+ }
69
+ if (cur == null || typeof cur !== 'object')
70
+ return false;
71
+ const last = segs[segs.length - 1];
72
+ if (!(last in cur))
73
+ return false;
74
+ delete cur[last];
75
+ return true;
76
+ };
77
+ export const mergeTree = (...trees) => {
78
+ const out = {};
79
+ for (const tree of trees) {
80
+ if (!tree)
81
+ continue;
82
+ for (const [k, v] of Object.entries(tree)) {
83
+ const prev = out[k];
84
+ if (isPlainObject(v) && isPlainObject(prev)) {
85
+ out[k] = mergeTree(prev, v);
86
+ }
87
+ else {
88
+ out[k] = v;
89
+ }
90
+ }
91
+ }
92
+ return out;
93
+ };
94
+ /**
95
+ * Sorted leaf paths whose values differ between `before` and `after`. Used by
96
+ * the publish dialog to summarize what changed in a release item.
97
+ *
98
+ * Treats `undefined` as an empty tree at the root, so adding/removing top-level
99
+ * branches still produces leaf paths. Two arrays of equal length recurse per
100
+ * index; arrays of differing length emit the array path itself (aligns with
101
+ * `mergeTree`'s array-replace semantics).
102
+ */
103
+ export const diffPaths = (before, after) => {
104
+ const out = [];
105
+ walk(before ?? {}, after ?? {}, '', out);
106
+ out.sort();
107
+ return out;
108
+ };
109
+ const walk = (b, a, prefix, out) => {
110
+ if (b === a)
111
+ return;
112
+ // One side undefined, the other a tree → enumerate the tree's leaves.
113
+ if (b === undefined && (isPlainObject(a) || Array.isArray(a))) {
114
+ walkLeaves(a, prefix, out);
115
+ return;
116
+ }
117
+ if (a === undefined && (isPlainObject(b) || Array.isArray(b))) {
118
+ walkLeaves(b, prefix, out);
119
+ return;
120
+ }
121
+ if (isPlainObject(b) && isPlainObject(a)) {
122
+ const keys = new Set([...Object.keys(b), ...Object.keys(a)]);
123
+ for (const k of keys) {
124
+ const sub = prefix ? `${prefix}.${k}` : k;
125
+ walk(b[k], a[k], sub, out);
126
+ }
127
+ return;
128
+ }
129
+ if (Array.isArray(b) && Array.isArray(a) && b.length === a.length) {
130
+ for (let i = 0; i < b.length; i++) {
131
+ const sub = prefix ? `${prefix}.${i}` : `${i}`;
132
+ walk(b[i], a[i], sub, out);
133
+ }
134
+ return;
135
+ }
136
+ if (prefix)
137
+ out.push(prefix);
138
+ };
139
+ const walkLeaves = (v, prefix, out) => {
140
+ if (isPlainObject(v)) {
141
+ for (const [k, sub] of Object.entries(v)) {
142
+ const p = prefix ? `${prefix}.${k}` : k;
143
+ walkLeaves(sub, p, out);
144
+ }
145
+ return;
146
+ }
147
+ if (Array.isArray(v)) {
148
+ for (let i = 0; i < v.length; i++) {
149
+ const p = prefix ? `${prefix}.${i}` : `${i}`;
150
+ walkLeaves(v[i], p, out);
151
+ }
152
+ return;
153
+ }
154
+ if (prefix)
155
+ out.push(prefix);
156
+ };