@xleddyl/nuxt-cms 0.9.4 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/README.md +1 -1
  2. package/dist/module.d.mts +20 -1
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +1037 -148
  5. package/dist/runtime/app/blocks/CmsBlocks.d.vue.ts +1 -1
  6. package/dist/runtime/app/blocks/CmsBlocks.vue +57 -9
  7. package/dist/runtime/app/blocks/CmsBlocks.vue.d.ts +1 -1
  8. package/dist/runtime/app/blocks/CmsField.d.ts +24 -0
  9. package/dist/runtime/app/blocks/CmsField.js +16 -0
  10. package/dist/runtime/app/blocks/node.d.ts +37 -0
  11. package/dist/runtime/app/blocks/node.js +17 -0
  12. package/dist/runtime/app/blocks/resolve.d.ts +18 -0
  13. package/dist/runtime/app/blocks/resolve.js +34 -0
  14. package/dist/runtime/app/components/cms/BlockPicker.d.vue.ts +22 -0
  15. package/dist/runtime/app/components/cms/BlockPicker.vue +87 -0
  16. package/dist/runtime/app/components/cms/BlockPicker.vue.d.ts +22 -0
  17. package/dist/runtime/app/components/cms/BlockPickerPopover.d.vue.ts +38 -0
  18. package/dist/runtime/app/components/cms/BlockPickerPopover.vue +44 -0
  19. package/dist/runtime/app/components/cms/BlockPickerPopover.vue.d.ts +38 -0
  20. package/dist/runtime/app/components/cms/BlockTree.d.vue.ts +29 -0
  21. package/dist/runtime/app/components/cms/BlockTree.vue +322 -0
  22. package/dist/runtime/app/components/cms/BlockTree.vue.d.ts +29 -0
  23. package/dist/runtime/app/components/cms/BlocksField.vue +569 -219
  24. package/dist/runtime/app/components/cms/BrandMark.vue +7 -13
  25. package/dist/runtime/app/components/cms/ConfirmGroups.vue +15 -13
  26. package/dist/runtime/app/components/cms/{BlockPalette.vue.d.ts → EditorHistory.d.vue.ts} +6 -5
  27. package/dist/runtime/app/components/cms/EditorHistory.vue +34 -0
  28. package/dist/runtime/app/components/cms/{BlockPalette.d.vue.ts → EditorHistory.vue.d.ts} +6 -5
  29. package/dist/runtime/app/components/cms/EntryDrawer.d.vue.ts +11 -5
  30. package/dist/runtime/app/components/cms/EntryDrawer.vue +183 -152
  31. package/dist/runtime/app/components/cms/EntryDrawer.vue.d.ts +11 -5
  32. package/dist/runtime/app/components/cms/EntryForm.d.vue.ts +16 -4
  33. package/dist/runtime/app/components/cms/EntryForm.vue +106 -147
  34. package/dist/runtime/app/components/cms/EntryForm.vue.d.ts +16 -4
  35. package/dist/runtime/app/components/cms/FieldInput.vue +10 -2
  36. package/dist/runtime/app/components/cms/FormSections.d.vue.ts +22 -0
  37. package/dist/runtime/app/components/cms/FormSections.vue +71 -0
  38. package/dist/runtime/app/components/cms/FormSections.vue.d.ts +22 -0
  39. package/dist/runtime/app/components/cms/ImportModal.vue +46 -58
  40. package/dist/runtime/app/components/cms/LinkField.d.vue.ts +16 -0
  41. package/dist/runtime/app/components/cms/LinkField.vue +250 -0
  42. package/dist/runtime/app/components/cms/LinkField.vue.d.ts +16 -0
  43. package/dist/runtime/app/components/cms/ListFilters.vue +10 -12
  44. package/dist/runtime/app/components/cms/LocaleSwitch.d.vue.ts +2 -1
  45. package/dist/runtime/app/components/cms/LocaleSwitch.vue +19 -11
  46. package/dist/runtime/app/components/cms/LocaleSwitch.vue.d.ts +2 -1
  47. package/dist/runtime/app/components/cms/MediaDetail.d.vue.ts +2 -0
  48. package/dist/runtime/app/components/cms/MediaDetail.vue +112 -83
  49. package/dist/runtime/app/components/cms/MediaDetail.vue.d.ts +2 -0
  50. package/dist/runtime/app/components/cms/MediaField.vue +35 -25
  51. package/dist/runtime/app/components/cms/MediaFolderPicker.vue +26 -71
  52. package/dist/runtime/app/components/cms/MediaGallery.d.vue.ts +1 -0
  53. package/dist/runtime/app/components/cms/MediaGallery.vue +442 -419
  54. package/dist/runtime/app/components/cms/MediaGallery.vue.d.ts +1 -0
  55. package/dist/runtime/app/components/cms/MediaThumb.vue +9 -25
  56. package/dist/runtime/app/components/cms/MediaUpload.vue +1 -1
  57. package/dist/runtime/app/components/cms/{BlockOutline.d.vue.ts → NestedBlockList.d.vue.ts} +5 -5
  58. package/dist/runtime/app/components/cms/NestedBlockList.vue +87 -0
  59. package/dist/runtime/app/components/cms/{BlockOutline.vue.d.ts → NestedBlockList.vue.d.ts} +5 -5
  60. package/dist/runtime/app/components/cms/PoweredBy.vue +12 -5
  61. package/dist/runtime/app/components/cms/PresetModal.d.vue.ts +18 -0
  62. package/dist/runtime/app/components/cms/PresetModal.vue +70 -0
  63. package/dist/runtime/app/components/cms/PresetModal.vue.d.ts +18 -0
  64. package/dist/runtime/app/components/cms/RelationField.vue +2 -8
  65. package/dist/runtime/app/components/cms/SettingsAccount.vue +60 -71
  66. package/dist/runtime/app/components/cms/SettingsColumns.vue +47 -69
  67. package/dist/runtime/app/components/cms/SettingsEmptyAdd.d.vue.ts +13 -0
  68. package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue +21 -0
  69. package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue.d.ts +13 -0
  70. package/dist/runtime/app/components/cms/SettingsEntries.d.vue.ts +13 -0
  71. package/dist/runtime/app/components/cms/SettingsEntries.vue +50 -0
  72. package/dist/runtime/app/components/cms/SettingsEntries.vue.d.ts +13 -0
  73. package/dist/runtime/app/components/cms/SettingsEntry.d.vue.ts +1 -10
  74. package/dist/runtime/app/components/cms/SettingsEntry.vue +11 -95
  75. package/dist/runtime/app/components/cms/SettingsEntry.vue.d.ts +1 -10
  76. package/dist/runtime/app/components/cms/SettingsEntryActions.d.vue.ts +7 -0
  77. package/dist/runtime/app/components/cms/SettingsEntryActions.vue +40 -0
  78. package/dist/runtime/app/components/cms/SettingsEntryActions.vue.d.ts +7 -0
  79. package/dist/runtime/app/components/cms/SettingsEntryTabs.d.vue.ts +7 -0
  80. package/dist/runtime/app/components/cms/SettingsEntryTabs.vue +21 -0
  81. package/dist/runtime/app/components/cms/SettingsEntryTabs.vue.d.ts +7 -0
  82. package/dist/runtime/app/components/cms/SettingsFormAction.d.vue.ts +3 -0
  83. package/dist/runtime/app/components/cms/SettingsFormAction.vue +17 -0
  84. package/dist/runtime/app/components/cms/SettingsFormAction.vue.d.ts +3 -0
  85. package/dist/runtime/app/components/cms/SettingsLayout.vue +18 -14
  86. package/dist/runtime/app/components/cms/SettingsPresetForm.d.vue.ts +11 -0
  87. package/dist/runtime/app/components/cms/SettingsPresetForm.vue +60 -0
  88. package/dist/runtime/app/components/cms/SettingsPresetForm.vue.d.ts +11 -0
  89. package/dist/runtime/app/components/cms/SettingsPresets.d.vue.ts +13 -0
  90. package/dist/runtime/app/components/cms/SettingsPresets.vue +65 -0
  91. package/dist/runtime/app/components/cms/SettingsPresets.vue.d.ts +13 -0
  92. package/dist/runtime/app/components/cms/SettingsRecordActions.d.vue.ts +32 -0
  93. package/dist/runtime/app/components/cms/SettingsRecordActions.vue +45 -0
  94. package/dist/runtime/app/components/cms/SettingsRecordActions.vue.d.ts +32 -0
  95. package/dist/runtime/app/components/cms/SettingsRedirectActions.d.vue.ts +3 -0
  96. package/dist/runtime/app/components/cms/SettingsRedirectActions.vue +59 -0
  97. package/dist/runtime/app/components/cms/SettingsRedirectActions.vue.d.ts +3 -0
  98. package/dist/runtime/app/components/cms/SettingsRedirectForm.d.vue.ts +11 -0
  99. package/dist/runtime/app/components/cms/SettingsRedirectForm.vue +77 -0
  100. package/dist/runtime/app/components/cms/SettingsRedirectForm.vue.d.ts +11 -0
  101. package/dist/runtime/app/components/cms/SettingsRedirects.d.vue.ts +13 -0
  102. package/dist/runtime/app/components/cms/SettingsRedirects.vue +117 -0
  103. package/dist/runtime/app/components/cms/SettingsRedirects.vue.d.ts +13 -0
  104. package/dist/runtime/app/components/cms/SettingsSecretCard.d.vue.ts +17 -0
  105. package/dist/runtime/app/components/cms/SettingsSecretCard.vue +43 -0
  106. package/dist/runtime/app/components/cms/SettingsSecretCard.vue.d.ts +17 -0
  107. package/dist/runtime/app/components/cms/SettingsSite.d.vue.ts +3 -0
  108. package/dist/runtime/app/components/cms/SettingsSite.vue +140 -0
  109. package/dist/runtime/app/components/cms/SettingsSite.vue.d.ts +3 -0
  110. package/dist/runtime/app/components/cms/SettingsUserCreate.d.vue.ts +8 -0
  111. package/dist/runtime/app/components/cms/SettingsUserCreate.vue +82 -0
  112. package/dist/runtime/app/components/cms/SettingsUserCreate.vue.d.ts +8 -0
  113. package/dist/runtime/app/components/cms/SettingsUserDetail.d.vue.ts +11 -0
  114. package/dist/runtime/app/components/cms/SettingsUserDetail.vue +179 -0
  115. package/dist/runtime/app/components/cms/SettingsUserDetail.vue.d.ts +11 -0
  116. package/dist/runtime/app/components/cms/SettingsUsers.d.vue.ts +9 -6
  117. package/dist/runtime/app/components/cms/SettingsUsers.vue +88 -234
  118. package/dist/runtime/app/components/cms/SettingsUsers.vue.d.ts +9 -6
  119. package/dist/runtime/app/components/cms/SharePreview.d.vue.ts +18 -0
  120. package/dist/runtime/app/components/cms/SharePreview.vue +219 -0
  121. package/dist/runtime/app/components/cms/SharePreview.vue.d.ts +18 -0
  122. package/dist/runtime/app/components/cms/SlugField.vue +5 -3
  123. package/dist/runtime/app/components/cms/StatusBadge.vue +8 -8
  124. package/dist/runtime/app/components/cms/TranslationBadges.d.vue.ts +7 -0
  125. package/dist/runtime/app/components/cms/TranslationBadges.vue +44 -0
  126. package/dist/runtime/app/components/cms/TranslationBadges.vue.d.ts +7 -0
  127. package/dist/runtime/app/components/cms/TranslationMenu.d.vue.ts +17 -0
  128. package/dist/runtime/app/components/cms/TranslationMenu.vue +28 -0
  129. package/dist/runtime/app/components/cms/TranslationMenu.vue.d.ts +17 -0
  130. package/dist/runtime/app/components/cms/VisualEditor.d.vue.ts +22 -4
  131. package/dist/runtime/app/components/cms/VisualEditor.vue +1153 -338
  132. package/dist/runtime/app/components/cms/VisualEditor.vue.d.ts +22 -4
  133. package/dist/runtime/app/components/cms/WelcomeModal.vue +32 -50
  134. package/dist/runtime/app/composables/cms-clipboard.d.ts +8 -0
  135. package/dist/runtime/app/composables/cms-clipboard.js +38 -0
  136. package/dist/runtime/app/composables/cms-confirm.d.ts +6 -8
  137. package/dist/runtime/app/composables/cms-confirm.js +5 -7
  138. package/dist/runtime/app/composables/cms-entry-disabled.d.ts +5 -1
  139. package/dist/runtime/app/composables/cms-entry-disabled.js +7 -0
  140. package/dist/runtime/app/composables/cms-entry-form.d.ts +15 -0
  141. package/dist/runtime/app/composables/cms-entry-form.js +40 -0
  142. package/dist/runtime/app/composables/cms-entry-settings.d.ts +30 -0
  143. package/dist/runtime/app/composables/cms-entry-settings.js +122 -0
  144. package/dist/runtime/app/composables/cms-entry.d.ts +5 -1
  145. package/dist/runtime/app/composables/cms-entry.js +36 -11
  146. package/dist/runtime/app/composables/cms-history.d.ts +10 -0
  147. package/dist/runtime/app/composables/cms-history.js +24 -0
  148. package/dist/runtime/app/composables/cms-link-targets.d.ts +10 -0
  149. package/dist/runtime/app/composables/cms-link-targets.js +40 -0
  150. package/dist/runtime/app/composables/cms-link-usage.d.ts +1 -0
  151. package/dist/runtime/app/composables/cms-link-usage.js +45 -0
  152. package/dist/runtime/app/composables/cms-media-library.d.ts +19 -9
  153. package/dist/runtime/app/composables/cms-media-library.js +31 -13
  154. package/dist/runtime/app/composables/cms-media-uploader.js +6 -20
  155. package/dist/runtime/app/composables/cms-permissions.d.ts +18 -0
  156. package/dist/runtime/app/composables/cms-permissions.js +54 -0
  157. package/dist/runtime/app/composables/cms-presets.d.ts +11 -0
  158. package/dist/runtime/app/composables/cms-presets.js +40 -0
  159. package/dist/runtime/app/composables/cms-preview-mode.d.ts +4 -0
  160. package/dist/runtime/app/composables/cms-preview-mode.js +8 -0
  161. package/dist/runtime/app/composables/cms-query.d.ts +3 -0
  162. package/dist/runtime/app/composables/cms-query.js +45 -20
  163. package/dist/runtime/app/composables/cms-record-list.d.ts +31 -0
  164. package/dist/runtime/app/composables/cms-record-list.js +75 -0
  165. package/dist/runtime/app/composables/cms-route.d.ts +6 -0
  166. package/dist/runtime/app/composables/cms-route.js +36 -0
  167. package/dist/runtime/app/composables/cms-runtime.d.ts +1 -0
  168. package/dist/runtime/app/composables/cms-save-handoff.d.ts +4 -0
  169. package/dist/runtime/app/composables/cms-save-handoff.js +19 -0
  170. package/dist/runtime/app/composables/cms-seo.d.ts +12 -0
  171. package/dist/runtime/app/composables/cms-seo.js +69 -0
  172. package/dist/runtime/app/composables/cms-settings-form.d.ts +13 -0
  173. package/dist/runtime/app/composables/cms-settings-form.js +29 -0
  174. package/dist/runtime/app/composables/cms-settings-sections.d.ts +26 -0
  175. package/dist/runtime/app/composables/cms-settings-sections.js +181 -0
  176. package/dist/runtime/app/composables/cms-settings-stores.d.ts +52 -0
  177. package/dist/runtime/app/composables/cms-settings-stores.js +156 -0
  178. package/dist/runtime/app/composables/cms-settings.d.ts +3 -3
  179. package/dist/runtime/app/composables/cms-settings.js +14 -8
  180. package/dist/runtime/app/composables/cms-site-disabled.d.ts +7 -0
  181. package/dist/runtime/app/composables/cms-site-disabled.js +8 -0
  182. package/dist/runtime/app/composables/cms-site.d.ts +7 -0
  183. package/dist/runtime/app/composables/cms-site.js +22 -0
  184. package/dist/runtime/app/composables/cms-toast.d.ts +2 -8
  185. package/dist/runtime/app/composables/cms-toast.js +3 -9
  186. package/dist/runtime/app/composables/cms-translation-actions.d.ts +15 -0
  187. package/dist/runtime/app/composables/cms-translation-actions.js +108 -0
  188. package/dist/runtime/app/css-url.d.ts +4 -0
  189. package/dist/runtime/app/image/CmsImage.d.vue.ts +89 -0
  190. package/dist/runtime/app/image/CmsImage.vue +91 -0
  191. package/dist/runtime/app/image/CmsImage.vue.d.ts +89 -0
  192. package/dist/runtime/app/layouts/cms-admin.d.vue.ts +2 -2
  193. package/dist/runtime/app/layouts/cms-admin.vue +98 -76
  194. package/dist/runtime/app/layouts/cms-admin.vue.d.ts +2 -2
  195. package/dist/runtime/app/layouts/cms-editor.vue +7 -2
  196. package/dist/runtime/app/links/CmsLink.d.vue.ts +18 -0
  197. package/dist/runtime/app/links/CmsLink.vue +18 -0
  198. package/dist/runtime/app/links/CmsLink.vue.d.ts +18 -0
  199. package/dist/runtime/app/middleware/cms-auth.js +13 -1
  200. package/dist/runtime/app/pages/admin-collection.vue +473 -297
  201. package/dist/runtime/app/pages/admin-content.vue +191 -54
  202. package/dist/runtime/app/pages/admin-entry.vue +79 -75
  203. package/dist/runtime/app/pages/admin-index.vue +18 -5
  204. package/dist/runtime/app/pages/admin-login.vue +1 -1
  205. package/dist/runtime/app/pages/admin-logout.vue +1 -1
  206. package/dist/runtime/app/pages/admin-media.vue +3 -3
  207. package/dist/runtime/app/pages/admin-preview.vue +112 -24
  208. package/dist/runtime/app/plugins/cms-field.d.ts +2 -0
  209. package/dist/runtime/app/plugins/cms-field.js +8 -0
  210. package/dist/runtime/app/plugins/cms-preview-banner.client.d.ts +2 -0
  211. package/dist/runtime/app/plugins/cms-preview-banner.client.js +19 -0
  212. package/dist/runtime/app/plugins/cms-preview.d.ts +2 -0
  213. package/dist/runtime/app/plugins/cms-preview.js +27 -0
  214. package/dist/runtime/app/preview/CmsPreviewBanner.d.vue.ts +7 -0
  215. package/dist/runtime/app/preview/CmsPreviewBanner.vue +63 -0
  216. package/dist/runtime/app/preview/CmsPreviewBanner.vue.d.ts +7 -0
  217. package/dist/runtime/app/preview/PreviewOverlay.d.vue.ts +17 -3
  218. package/dist/runtime/app/preview/PreviewOverlay.vue +629 -166
  219. package/dist/runtime/app/preview/PreviewOverlay.vue.d.ts +17 -3
  220. package/dist/runtime/app/preview/field-marker.d.ts +12 -0
  221. package/dist/runtime/app/preview/field-marker.js +20 -0
  222. package/dist/runtime/app/preview/inline-text.d.ts +15 -0
  223. package/dist/runtime/app/preview/inline-text.js +158 -0
  224. package/dist/runtime/app/utils/block-editor.d.ts +22 -0
  225. package/dist/runtime/app/utils/block-editor.js +12 -0
  226. package/dist/runtime/app/utils/keyboard.d.ts +6 -0
  227. package/dist/runtime/app/utils/keyboard.js +52 -0
  228. package/dist/runtime/app/utils/redirects.d.ts +6 -0
  229. package/dist/runtime/app/utils/redirects.js +7 -0
  230. package/dist/runtime/app/utils/ui.d.ts +8 -0
  231. package/dist/runtime/app/utils/ui.js +15 -1
  232. package/dist/runtime/app/utils/users.d.ts +15 -0
  233. package/dist/runtime/app/utils/users.js +14 -0
  234. package/dist/runtime/assets/cms.css +1 -1
  235. package/dist/runtime/generate.js +16 -2
  236. package/dist/runtime/server/api/collection-export.get.js +3 -2
  237. package/dist/runtime/server/api/collection-import.post.js +39 -11
  238. package/dist/runtime/server/api/collection.get.js +27 -9
  239. package/dist/runtime/server/api/collection.post.js +28 -11
  240. package/dist/runtime/server/api/collection.put.js +35 -13
  241. package/dist/runtime/server/api/item.delete.js +19 -7
  242. package/dist/runtime/server/api/item.get.js +3 -2
  243. package/dist/runtime/server/api/item.put.js +52 -18
  244. package/dist/runtime/server/api/link-usage.post.d.ts +5 -0
  245. package/dist/runtime/server/api/link-usage.post.js +21 -0
  246. package/dist/runtime/server/api/media-delete.post.js +4 -2
  247. package/dist/runtime/server/api/media-download.get.js +2 -2
  248. package/dist/runtime/server/api/media-folder.delete.js +8 -2
  249. package/dist/runtime/server/api/media-folder.patch.js +10 -2
  250. package/dist/runtime/server/api/media-folder.post.js +4 -2
  251. package/dist/runtime/server/api/media-move.post.js +7 -4
  252. package/dist/runtime/server/api/media-presign.post.js +2 -2
  253. package/dist/runtime/server/api/media-upload.put.js +2 -2
  254. package/dist/runtime/server/api/media-usage.post.d.ts +2 -4
  255. package/dist/runtime/server/api/media-usage.post.js +13 -9
  256. package/dist/runtime/server/api/media.delete.js +4 -2
  257. package/dist/runtime/server/api/media.get.js +22 -7
  258. package/dist/runtime/server/api/media.post.js +4 -2
  259. package/dist/runtime/server/api/media.put.js +33 -16
  260. package/dist/runtime/server/api/preset.delete.d.ts +4 -0
  261. package/dist/runtime/server/api/preset.delete.js +9 -0
  262. package/dist/runtime/server/api/preset.put.d.ts +3 -0
  263. package/dist/runtime/server/api/preset.put.js +23 -0
  264. package/dist/runtime/server/api/presets-field.get.d.ts +3 -0
  265. package/dist/runtime/server/api/presets-field.get.js +13 -0
  266. package/dist/runtime/server/api/presets-field.post.d.ts +3 -0
  267. package/dist/runtime/server/api/presets-field.post.js +36 -0
  268. package/dist/runtime/server/api/presets.get.d.ts +3 -0
  269. package/dist/runtime/server/api/presets.get.js +7 -0
  270. package/dist/runtime/server/api/preview-link.delete.d.ts +4 -0
  271. package/dist/runtime/server/api/preview-link.delete.js +15 -0
  272. package/dist/runtime/server/api/preview-links.get.d.ts +3 -0
  273. package/dist/runtime/server/api/preview-links.get.js +10 -0
  274. package/dist/runtime/server/api/preview-links.post.d.ts +3 -0
  275. package/dist/runtime/server/api/preview-links.post.js +17 -0
  276. package/dist/runtime/server/api/preview.get.d.ts +3 -0
  277. package/dist/runtime/server/api/preview.get.js +7 -0
  278. package/dist/runtime/server/api/redirect.delete.d.ts +4 -0
  279. package/dist/runtime/server/api/redirect.delete.js +10 -0
  280. package/dist/runtime/server/api/redirect.put.d.ts +3 -0
  281. package/dist/runtime/server/api/redirect.put.js +8 -0
  282. package/dist/runtime/server/api/redirects-import.post.d.ts +3 -0
  283. package/dist/runtime/server/api/redirects-import.post.js +13 -0
  284. package/dist/runtime/server/api/redirects.get.d.ts +3 -0
  285. package/dist/runtime/server/api/redirects.get.js +7 -0
  286. package/dist/runtime/server/api/redirects.post.d.ts +3 -0
  287. package/dist/runtime/server/api/redirects.post.js +7 -0
  288. package/dist/runtime/server/api/search.get.js +8 -3
  289. package/dist/runtime/server/api/settings.delete.js +2 -2
  290. package/dist/runtime/server/api/settings.get.js +4 -2
  291. package/dist/runtime/server/api/settings.put.js +2 -2
  292. package/dist/runtime/server/api/site.get.d.ts +3 -0
  293. package/dist/runtime/server/api/site.get.js +7 -0
  294. package/dist/runtime/server/api/site.put.d.ts +3 -0
  295. package/dist/runtime/server/api/site.put.js +16 -0
  296. package/dist/runtime/server/api/tags.get.js +3 -2
  297. package/dist/runtime/server/api/user.delete.js +8 -2
  298. package/dist/runtime/server/api/user.put.js +14 -4
  299. package/dist/runtime/server/api/users.get.js +2 -2
  300. package/dist/runtime/server/api/users.post.js +8 -4
  301. package/dist/runtime/server/middleware/hidden-site.d.ts +2 -0
  302. package/dist/runtime/server/middleware/hidden-site.js +8 -0
  303. package/dist/runtime/server/middleware/preview-links.d.ts +2 -0
  304. package/dist/runtime/server/middleware/preview-links.js +6 -0
  305. package/dist/runtime/server/middleware/redirects.d.ts +2 -0
  306. package/dist/runtime/server/middleware/redirects.js +18 -0
  307. package/dist/runtime/server/plugins/session-validate.js +4 -1
  308. package/dist/runtime/server/plugins/webhooks.d.ts +3 -0
  309. package/dist/runtime/server/plugins/webhooks.js +27 -0
  310. package/dist/runtime/server/routes/graphql.js +5 -3
  311. package/dist/runtime/server/routes/robots.d.ts +2 -0
  312. package/dist/runtime/server/routes/robots.js +16 -0
  313. package/dist/runtime/server/routes/sitemap.d.ts +2 -0
  314. package/dist/runtime/server/routes/sitemap.js +67 -0
  315. package/dist/runtime/server/utils/cached-value.d.ts +5 -0
  316. package/dist/runtime/server/utils/cached-value.js +24 -0
  317. package/dist/runtime/server/utils/content-routes.d.ts +5 -0
  318. package/dist/runtime/server/utils/content-routes.js +29 -0
  319. package/dist/runtime/server/utils/field-rules.d.ts +19 -0
  320. package/dist/runtime/server/utils/field-rules.js +72 -0
  321. package/dist/runtime/server/utils/graphql.d.ts +3 -1
  322. package/dist/runtime/server/utils/graphql.js +143 -28
  323. package/dist/runtime/server/utils/hooks.d.ts +14 -0
  324. package/dist/runtime/server/utils/hooks.js +71 -0
  325. package/dist/runtime/server/utils/import.d.ts +7 -2
  326. package/dist/runtime/server/utils/import.js +108 -14
  327. package/dist/runtime/server/utils/link-usage.d.ts +4 -0
  328. package/dist/runtime/server/utils/link-usage.js +28 -0
  329. package/dist/runtime/server/utils/media-references.d.ts +6 -1
  330. package/dist/runtime/server/utils/media-references.js +49 -20
  331. package/dist/runtime/server/utils/media-usage.d.ts +2 -0
  332. package/dist/runtime/server/utils/media-usage.js +5 -3
  333. package/dist/runtime/server/utils/page-rows.d.ts +2 -0
  334. package/dist/runtime/server/utils/page-rows.js +42 -29
  335. package/dist/runtime/server/utils/permissions.d.ts +14 -0
  336. package/dist/runtime/server/utils/permissions.js +43 -0
  337. package/dist/runtime/server/utils/presets.d.ts +18 -0
  338. package/dist/runtime/server/utils/presets.js +68 -0
  339. package/dist/runtime/server/utils/preview-links.d.ts +207 -0
  340. package/dist/runtime/server/utils/preview-links.js +161 -0
  341. package/dist/runtime/server/utils/redirects.d.ts +31 -0
  342. package/dist/runtime/server/utils/redirects.js +240 -0
  343. package/dist/runtime/server/utils/registry.js +4 -1
  344. package/dist/runtime/server/utils/relations.d.ts +8 -0
  345. package/dist/runtime/server/utils/relations.js +25 -6
  346. package/dist/runtime/server/utils/require-admin.d.ts +0 -1
  347. package/dist/runtime/server/utils/require-admin.js +4 -8
  348. package/dist/runtime/server/utils/search.d.ts +1 -0
  349. package/dist/runtime/server/utils/search.js +44 -19
  350. package/dist/runtime/server/utils/site.d.ts +23 -0
  351. package/dist/runtime/server/utils/site.js +79 -0
  352. package/dist/runtime/server/utils/sitemap.d.ts +12 -0
  353. package/dist/runtime/server/utils/sitemap.js +109 -0
  354. package/dist/runtime/server/utils/user-management.d.ts +4 -0
  355. package/dist/runtime/server/utils/user-management.js +20 -0
  356. package/dist/runtime/server/utils/users.d.ts +1 -1
  357. package/dist/runtime/server/utils/users.js +1 -1
  358. package/dist/runtime/server/utils/visibility.d.ts +1 -0
  359. package/dist/runtime/server/utils/visibility.js +6 -1
  360. package/dist/runtime/server/utils/webhooks.d.ts +24 -0
  361. package/dist/runtime/server/utils/webhooks.js +90 -0
  362. package/dist/runtime/shared/block-paths.d.ts +66 -0
  363. package/dist/runtime/shared/block-paths.js +310 -0
  364. package/dist/runtime/shared/block-picker.d.ts +18 -0
  365. package/dist/runtime/shared/block-picker.js +31 -0
  366. package/dist/runtime/shared/block-signature.d.ts +4 -0
  367. package/dist/runtime/shared/block-signature.js +46 -0
  368. package/dist/runtime/shared/clipboard.d.ts +31 -0
  369. package/dist/runtime/shared/clipboard.js +206 -0
  370. package/dist/runtime/shared/conditions.d.ts +36 -0
  371. package/dist/runtime/shared/conditions.js +100 -0
  372. package/dist/runtime/shared/content-routes.d.ts +42 -0
  373. package/dist/runtime/shared/content-routes.js +237 -0
  374. package/dist/runtime/shared/duplicate.js +2 -1
  375. package/dist/runtime/shared/editor-layout.d.ts +18 -0
  376. package/dist/runtime/shared/editor-layout.js +9 -0
  377. package/dist/runtime/shared/field-options.d.ts +21 -0
  378. package/dist/runtime/shared/field-options.js +90 -0
  379. package/dist/runtime/shared/graphql-sdl.d.ts +1 -0
  380. package/dist/runtime/shared/graphql-sdl.js +50 -26
  381. package/dist/runtime/shared/history.d.ts +27 -0
  382. package/dist/runtime/shared/history.js +123 -0
  383. package/dist/runtime/shared/hooks.d.ts +45 -0
  384. package/dist/runtime/shared/hooks.js +28 -0
  385. package/dist/runtime/shared/index.d.ts +90 -21
  386. package/dist/runtime/shared/index.js +121 -37
  387. package/dist/runtime/shared/inline-text.d.ts +38 -0
  388. package/dist/runtime/shared/inline-text.js +85 -0
  389. package/dist/runtime/shared/layout.d.ts +2 -1
  390. package/dist/runtime/shared/layout.js +3 -0
  391. package/dist/runtime/shared/links.d.ts +48 -0
  392. package/dist/runtime/shared/links.js +155 -0
  393. package/dist/runtime/shared/list-filters.d.ts +2 -0
  394. package/dist/runtime/shared/list-filters.js +2 -0
  395. package/dist/runtime/shared/media-focal.d.ts +30 -0
  396. package/dist/runtime/shared/media-focal.js +52 -0
  397. package/dist/runtime/shared/migrations-dir.d.ts +14 -0
  398. package/dist/runtime/shared/migrations-dir.js +48 -2
  399. package/dist/runtime/shared/presets.d.ts +67 -0
  400. package/dist/runtime/shared/presets.js +127 -0
  401. package/dist/runtime/shared/preview-links.d.ts +64 -0
  402. package/dist/runtime/shared/preview-links.js +54 -0
  403. package/dist/runtime/shared/preview.d.ts +124 -21
  404. package/dist/runtime/shared/preview.js +419 -81
  405. package/dist/runtime/shared/redirects.d.ts +75 -0
  406. package/dist/runtime/shared/redirects.js +230 -0
  407. package/dist/runtime/shared/roles.d.ts +57 -0
  408. package/dist/runtime/shared/roles.js +293 -0
  409. package/dist/runtime/shared/save-state.d.ts +8 -0
  410. package/dist/runtime/shared/save-state.js +15 -0
  411. package/dist/runtime/shared/search.d.ts +16 -1
  412. package/dist/runtime/shared/search.js +41 -7
  413. package/dist/runtime/shared/seo.d.ts +167 -0
  414. package/dist/runtime/shared/seo.js +335 -0
  415. package/dist/runtime/shared/transfer.js +2 -1
  416. package/dist/runtime/shared/translations.d.ts +29 -0
  417. package/dist/runtime/shared/translations.js +123 -0
  418. package/dist/runtime/shared/users.d.ts +1 -1
  419. package/dist/runtime/shared/validation.d.ts +23 -1
  420. package/dist/runtime/shared/validation.js +214 -64
  421. package/dist/runtime/webhooks.d.ts +33 -0
  422. package/dist/runtime/webhooks.js +57 -0
  423. package/dist/types.d.mts +5 -1
  424. package/package.json +6 -2
  425. package/dist/runtime/app/components/cms/BlockOutline.vue +0 -88
  426. package/dist/runtime/app/components/cms/BlockPalette.vue +0 -31
  427. package/dist/runtime/app/components/cms/SettingsModal.d.vue.ts +0 -12
  428. package/dist/runtime/app/components/cms/SettingsModal.vue +0 -126
  429. package/dist/runtime/app/components/cms/SettingsModal.vue.d.ts +0 -12
  430. package/dist/runtime/app/composables/cms-field-focus.d.ts +0 -4
  431. package/dist/runtime/app/composables/cms-field-focus.js +0 -20
@@ -1,3 +1,4 @@
1
+ import { MAX_BLOCKS_DEPTH, blockFieldsDeep, mapBlocks } from "./block-paths.js";
1
2
  export const MEDIA_TYPES = ["image", "video", "file"];
2
3
  const MEDIA_EXTENSIONS = {
3
4
  image: [
@@ -120,8 +121,15 @@ export function groupMediaUsage(usage) {
120
121
  }
121
122
  return [...entries.values()];
122
123
  }
123
- export function mediaUsageGroups(usage, keys) {
124
- return [...new Set(keys)].map((key) => ({ key, entries: groupMediaUsage(usage[key] ?? []) })).filter((group) => group.entries.length > 0);
124
+ export function mediaUsageGroups(usage, keys, hidden = {}) {
125
+ return [...new Set(keys)].map((key) => ({
126
+ key,
127
+ entries: groupMediaUsage(usage[key] ?? []),
128
+ hidden: hidden[key] ?? 0
129
+ })).filter((group) => group.entries.length > 0 || group.hidden > 0);
130
+ }
131
+ export function otherEntriesLabel(count) {
132
+ return `${count} other entr${count === 1 ? "y" : "ies"}`;
125
133
  }
126
134
  export function selectOptions(field) {
127
135
  return (field.options ?? []).map(
@@ -148,28 +156,21 @@ export function selectDisplayValue(field, value) {
148
156
  if (Array.isArray(value)) return value.map((item) => selectOptionLabel(field, item)).join(", ");
149
157
  return selectOptionLabel(field, value);
150
158
  }
159
+ export function relationTarget(field) {
160
+ return typeof field.to === "string" ? field.to : "";
161
+ }
151
162
  export function isPrivateField(field) {
152
163
  return !!field.private;
153
164
  }
154
165
  export function isRequiredField(field) {
155
166
  return !!field.required && !field.showIf;
156
167
  }
157
- export function fieldConditions(field) {
158
- if (!field.showIf) return [];
159
- return Array.isArray(field.showIf) ? field.showIf : [field.showIf];
160
- }
161
- function matchesCondition(condition, value) {
162
- if (condition.in) return condition.in.some((option) => option === value);
163
- return condition.eq === value;
164
- }
165
- export function isFieldVisible(field, values) {
166
- const conditions = fieldConditions(field);
167
- if (!conditions.length) return true;
168
- return conditions.every((condition) => matchesCondition(condition, values?.[condition.field]));
169
- }
170
168
  export function isTranslatableField(field) {
171
169
  return !!field.translatable && (field.type === "text" || field.type === "richtext" || field.type === "media");
172
170
  }
171
+ export function isLocalizedLinkField(field) {
172
+ return field.type === "link" && !!field.translatable && !!field.withLabel;
173
+ }
173
174
  export function isTranslatableMediaField(field) {
174
175
  return !!field.translatable && field.type === "media";
175
176
  }
@@ -285,8 +286,8 @@ export function translatableBlockFieldKeys(block) {
285
286
  }
286
287
  export function hasTranslatableBlockFields(field) {
287
288
  if (field.type !== "blocks") return false;
288
- return Object.values(field.blocks ?? {}).some(
289
- (block) => Object.values(block.fields).some(isTranslatableField)
289
+ return blockFieldsDeep(field).some(
290
+ (blockField) => isTranslatableField(blockField) || isLocalizedLinkField(blockField)
290
291
  );
291
292
  }
292
293
  export function canAddBlock(field, count) {
@@ -300,11 +301,11 @@ export function isHiddenBlock(item) {
300
301
  return !!item && typeof item === "object" && item.hidden === true;
301
302
  }
302
303
  export function publicBlocks(field, value) {
303
- if (!Array.isArray(value)) return value;
304
- return value.filter((item) => {
305
- if (!isHiddenBlock(item)) return true;
306
- return declaresHiddenField(field.blocks?.[String(item.type)]);
307
- });
304
+ return mapBlocks(
305
+ field,
306
+ value,
307
+ (item, block) => isHiddenBlock(item) && !declaresHiddenField(block) ? null : item
308
+ );
308
309
  }
309
310
  export function localizeBlock(field, item, locale, defaultLocale) {
310
311
  if (!item || typeof item !== "object") return item;
@@ -320,8 +321,11 @@ export function localizeBlock(field, item, locale, defaultLocale) {
320
321
  return localized;
321
322
  }
322
323
  export function localizeBlocks(field, value, locale, defaultLocale) {
323
- if (!Array.isArray(value)) return value;
324
- return value.map((item) => localizeBlock(field, item, locale, defaultLocale));
324
+ return mapBlocks(
325
+ field,
326
+ value,
327
+ (item, _block, owner) => localizeBlock(owner, item, locale, defaultLocale)
328
+ );
325
329
  }
326
330
  export const CMS_GRAPHQL_BATCH_LIMIT = 20;
327
331
  export const MOBILE_MEDIA_SUFFIX = "Mobile";
@@ -389,8 +393,10 @@ export const CONTENT_SYSTEM_FIELDS = [
389
393
  "body",
390
394
  "seoTitle",
391
395
  "seoDescription",
392
- "seoImage"
396
+ "seoImage",
397
+ "seoNoindex"
393
398
  ];
399
+ export const CONTENT_NOINDEX_FIELD = "seoNoindex";
394
400
  export const CONTENT_LIST_COLUMNS = ["title", "status", "publishedAt"];
395
401
  export function isContentEntry(entry) {
396
402
  return entry.kind === "content";
@@ -430,7 +436,12 @@ function contentSystemFields(blocks, labels, translatable) {
430
436
  textarea: true,
431
437
  ...localized
432
438
  },
433
- seoImage: { label: label("seoImage", "SEO image"), type: "media", mediaType: "image" }
439
+ seoImage: { label: label("seoImage", "SEO image"), type: "media", mediaType: "image" },
440
+ seoNoindex: {
441
+ label: label("seoNoindex", "Hide from search engines"),
442
+ type: "boolean",
443
+ description: "Adds noindex to the page and leaves it out of the sitemap."
444
+ }
434
445
  };
435
446
  }
436
447
  function normalizeContentEntry(entry, translatable) {
@@ -440,7 +451,7 @@ function normalizeContentEntry(entry, translatable) {
440
451
  const extra = Object.fromEntries(
441
452
  Object.entries(declared).filter(([key]) => !Object.hasOwn(system, key))
442
453
  );
443
- const { body, seoTitle, seoDescription, seoImage, ...head } = system;
454
+ const { body, seoTitle, seoDescription, seoImage, seoNoindex, ...head } = system;
444
455
  return Object.assign(entry, {
445
456
  declared: {
446
457
  fields: Object.keys(declared),
@@ -449,7 +460,7 @@ function normalizeContentEntry(entry, translatable) {
449
460
  },
450
461
  titleField: CONTENT_TITLE_FIELD,
451
462
  drafts: true,
452
- fields: { ...head, ...extra, body, seoTitle, seoDescription, seoImage },
463
+ fields: { ...head, ...extra, body, seoTitle, seoDescription, seoImage, seoNoindex },
453
464
  list: entry.list ?? { columns: [...CONTENT_LIST_COLUMNS] }
454
465
  });
455
466
  }
@@ -460,8 +471,72 @@ export function normalizeContentEntries(config, i18n) {
460
471
  }
461
472
  return config;
462
473
  }
474
+ function boundBlocksField(field, depth, trail) {
475
+ const blocks = field.blocks;
476
+ if (!blocks || typeof blocks !== "object") return field;
477
+ const inner = new Set(trail).add(blocks);
478
+ let changed = false;
479
+ const bounded = {};
480
+ for (const [name, block] of Object.entries(blocks)) {
481
+ if (!block?.fields || typeof block.fields !== "object") {
482
+ bounded[name] = block;
483
+ continue;
484
+ }
485
+ let fields = null;
486
+ let dropped = false;
487
+ for (const [key, subfield] of Object.entries(block.fields)) {
488
+ if (subfield?.type !== "blocks" || !subfield.blocks) continue;
489
+ const cyclic = inner.has(subfield.blocks);
490
+ if (depth >= MAX_BLOCKS_DEPTH) {
491
+ if (cyclic) dropped = true;
492
+ continue;
493
+ }
494
+ const next = boundBlocksField(subfield, depth + 1, inner);
495
+ if (next === subfield) continue;
496
+ fields ??= { ...block.fields };
497
+ fields[key] = next;
498
+ }
499
+ if (dropped) {
500
+ changed = true;
501
+ continue;
502
+ }
503
+ if (fields) {
504
+ changed = true;
505
+ bounded[name] = { ...block, fields };
506
+ } else {
507
+ bounded[name] = block;
508
+ }
509
+ }
510
+ return changed ? { ...field, blocks: bounded } : field;
511
+ }
512
+ function boundFields(fields) {
513
+ let next = null;
514
+ for (const [key, field] of Object.entries(fields)) {
515
+ if (field?.type !== "blocks") continue;
516
+ const bounded = boundBlocksField(field, 1, /* @__PURE__ */ new Set());
517
+ if (bounded === field) continue;
518
+ next ??= { ...fields };
519
+ next[key] = bounded;
520
+ }
521
+ return next ?? fields;
522
+ }
523
+ export function boundBlockNesting(config) {
524
+ for (const entry of Object.values(config)) {
525
+ if (!entry?.fields || typeof entry.fields !== "object") continue;
526
+ entry.fields = boundFields(entry.fields);
527
+ if (entry.overrides && typeof entry.overrides === "object") {
528
+ entry.overrides = Object.fromEntries(
529
+ Object.entries(entry.overrides).map(([path, override]) => [
530
+ path,
531
+ override && typeof override === "object" ? boundFields(override) : override
532
+ ])
533
+ );
534
+ }
535
+ }
536
+ return config;
537
+ }
463
538
  export function normalizeCmsConfig(config, i18n) {
464
- return expandMobileMedia(normalizeContentEntries(config, i18n));
539
+ return boundBlockNesting(expandMobileMedia(normalizeContentEntries(config, i18n)));
465
540
  }
466
541
  export function slugSourceValue(source, value, defaultLocale) {
467
542
  if (value == null) return null;
@@ -478,10 +553,7 @@ export function isScheduledContent(row, now = /* @__PURE__ */ new Date()) {
478
553
  return !Number.isNaN(time) && time > now.getTime();
479
554
  }
480
555
  export function resolveBlocksMedia(field, value, resolve) {
481
- if (!Array.isArray(value)) return value;
482
- return value.map((item) => {
483
- if (!item || typeof item !== "object") return item;
484
- const block = field.blocks?.[String(item.type)];
556
+ return mapBlocks(field, value, (item, block) => {
485
557
  if (!block) return item;
486
558
  const resolved = { ...item };
487
559
  for (const [key, blockField] of Object.entries(block.fields)) {
@@ -586,11 +658,15 @@ export function entryFieldsFor(entry, path) {
586
658
  export function typeName(name) {
587
659
  return name.replace(/(?:^|_)([a-z0-9])/gi, (_, c) => c.toUpperCase());
588
660
  }
589
- export function blocksFieldTypeName(entryName, fieldKey) {
590
- return `${typeName(entryName)}${typeName(fieldKey)}Block`;
661
+ export function blocksTypePrefix(entryName, schemaPath) {
662
+ const segments = typeof schemaPath === "string" ? schemaPath.split(".") : schemaPath;
663
+ return `${typeName(entryName)}${segments.map(typeName).join("")}`;
664
+ }
665
+ export function blocksFieldTypeName(entryName, schemaPath) {
666
+ return `${blocksTypePrefix(entryName, schemaPath)}Block`;
591
667
  }
592
- export function blockTypeName(entryName, fieldKey, blockName) {
593
- return `${typeName(entryName)}${typeName(fieldKey)}${typeName(blockName)}`;
668
+ export function blockTypeName(entryName, schemaPath, blockName) {
669
+ return `${blocksTypePrefix(entryName, schemaPath)}${typeName(blockName)}`;
594
670
  }
595
671
  export function defineCmsConfig(config) {
596
672
  return config;
@@ -598,5 +674,13 @@ export function defineCmsConfig(config) {
598
674
  export function defineCmsBlocks(blocks) {
599
675
  return blocks;
600
676
  }
677
+ export * from "./block-paths.js";
678
+ export * from "./conditions.js";
679
+ export * from "./content-routes.js";
680
+ export * from "./seo.js";
681
+ export * from "./redirects.js";
601
682
  export * from "./layout.js";
683
+ export * from "./media-focal.js";
602
684
  export * from "./users.js";
685
+ export * from "./preview-links.js";
686
+ export * from "./links.js";
@@ -0,0 +1,38 @@
1
+ import type { CmsBlockPath } from './block-paths.js';
2
+ import type { FieldConfig } from './index.js';
3
+ export declare const CMS_INLINE_TEXT_MAX_LENGTH = 100000;
4
+ export declare const CMS_INLINE_INPUT_DELAY = 250;
5
+ export interface CmsInlineNode {
6
+ nodeType: number;
7
+ nodeName: string;
8
+ nodeValue: string | null;
9
+ childNodes: ArrayLike<CmsInlineNode>;
10
+ }
11
+ export interface CmsInlineOverride {
12
+ path: CmsBlockPath | null;
13
+ key: string;
14
+ value: unknown;
15
+ settled: boolean;
16
+ }
17
+ export declare function isInlineTextField(field: FieldConfig | undefined): field is FieldConfig;
18
+ export declare function isPlainTextContent(node: CmsInlineNode): boolean;
19
+ export declare function editableText(node: CmsInlineNode): string;
20
+ export declare function normalizeInlineText(text: string, multiline: boolean): string;
21
+ export declare function inlineTextLimit(field: FieldConfig | undefined): number | undefined;
22
+ export declare function clampInlineText(text: string, max: number | undefined): string;
23
+ export declare function fitInlineInsertion(text: string, room: number): string;
24
+ export declare function inlineFieldPath(path: CmsBlockPath | null, key: string): string;
25
+ export interface CmsInlineLockOptions {
26
+ fields: Record<string, FieldConfig> | null;
27
+ values: Record<string, unknown>;
28
+ blocksFields: Record<string, FieldConfig>;
29
+ blocksValues: Record<string, unknown>;
30
+ locked?: readonly string[];
31
+ }
32
+ export declare function lockedInlineFields(options: CmsInlineLockOptions): string[];
33
+ export declare function matchesInlineValue(text: string, value: unknown): boolean;
34
+ export declare function inlineFieldValue(field: FieldConfig, current: unknown, locale: string, defaultLocale: string, text: string): unknown;
35
+ export declare function applyInlineOverride<T extends Record<string, unknown>>(blocks: readonly T[], item: Record<string, unknown> | null, override: CmsInlineOverride | null): {
36
+ blocks: T[];
37
+ item: Record<string, unknown> | null;
38
+ };
@@ -0,0 +1,85 @@
1
+ import { formatBlockPath, updateBlockAt, walkBlocks } from "./block-paths.js";
2
+ import { decodeTranslatableValue, isFieldVisible, isTranslatableField } from "./index.js";
3
+ export const CMS_INLINE_TEXT_MAX_LENGTH = 1e5;
4
+ export const CMS_INLINE_INPUT_DELAY = 250;
5
+ const TEXT_NODE = 3;
6
+ const ELEMENT_NODE = 1;
7
+ const LINE_TAGS = /* @__PURE__ */ new Set(["DIV", "P", "LI"]);
8
+ export function isInlineTextField(field) {
9
+ return field?.type === "text";
10
+ }
11
+ export function isPlainTextContent(node) {
12
+ return Array.from(node.childNodes).every((child) => child.nodeType !== ELEMENT_NODE);
13
+ }
14
+ export function editableText(node) {
15
+ let text = "";
16
+ const walk = (parent) => {
17
+ for (const child of Array.from(parent.childNodes)) {
18
+ if (child.nodeType === TEXT_NODE) text += child.nodeValue ?? "";
19
+ else if (child.nodeType !== ELEMENT_NODE) continue;
20
+ else if (child.nodeName === "BR") text += "\n";
21
+ else {
22
+ if (LINE_TAGS.has(child.nodeName) && text && !text.endsWith("\n")) text += "\n";
23
+ walk(child);
24
+ }
25
+ }
26
+ };
27
+ walk(node);
28
+ return text;
29
+ }
30
+ export function normalizeInlineText(text, multiline) {
31
+ const value = text.replace(/ /g, " ").replace(/\r\n?/g, "\n").replace(/\n$/, "");
32
+ return multiline ? value : value.replace(/[^\S\n]*\n\s*/g, " ");
33
+ }
34
+ export function inlineTextLimit(field) {
35
+ return isInlineTextField(field) && typeof field.max === "number" ? field.max : void 0;
36
+ }
37
+ export function clampInlineText(text, max) {
38
+ return max === void 0 || text.length <= max ? text : text.slice(0, max);
39
+ }
40
+ export function fitInlineInsertion(text, room) {
41
+ return text.slice(0, Math.max(room, 0));
42
+ }
43
+ export function inlineFieldPath(path, key) {
44
+ return path ? `${formatBlockPath(path)}.${key}` : key;
45
+ }
46
+ export function lockedInlineFields(options) {
47
+ const paths = [];
48
+ for (const [key, field] of Object.entries(options.fields ?? {})) {
49
+ if (!isInlineTextField(field)) continue;
50
+ if (options.locked?.includes(key) || !isFieldVisible(field, options.values, options.fields))
51
+ paths.push(key);
52
+ }
53
+ walkBlocks(options.blocksFields, options.blocksValues, ({ item, block, path }) => {
54
+ for (const [key, field] of Object.entries(block.fields)) {
55
+ if (isInlineTextField(field) && !isFieldVisible(field, item, block.fields))
56
+ paths.push(inlineFieldPath(path, key));
57
+ }
58
+ });
59
+ return paths;
60
+ }
61
+ export function matchesInlineValue(text, value) {
62
+ if (value != null && typeof value !== "string") return false;
63
+ return text.trim() === (value ?? "").trim();
64
+ }
65
+ export function inlineFieldValue(field, current, locale, defaultLocale, text) {
66
+ if (!isTranslatableField(field)) return text === "" ? null : text;
67
+ const translations = decodeTranslatableValue(current, defaultLocale) ?? {};
68
+ const next = Object.fromEntries(Object.entries(translations).filter(([code]) => code !== locale));
69
+ if (text !== "") next[locale] = text;
70
+ return Object.keys(next).length ? next : null;
71
+ }
72
+ export function applyInlineOverride(blocks, item, override) {
73
+ if (!override) return { blocks: [...blocks], item };
74
+ if (!override.path)
75
+ return {
76
+ blocks: [...blocks],
77
+ item: item ? { ...item, [override.key]: override.value } : item
78
+ };
79
+ const root = String(override.path[0]);
80
+ const updated = updateBlockAt({ [root]: blocks }, override.path, (block) => ({
81
+ ...block,
82
+ [override.key]: override.value
83
+ }));
84
+ return { blocks: [...updated[root] ?? []], item };
85
+ }
@@ -1,4 +1,4 @@
1
- import type { FieldConfig } from './index.js';
1
+ import type { BlockConfig, FieldConfig } from './index.js';
2
2
  export declare const MAX_LAYOUT_ROW_FIELDS = 4;
3
3
  export type CmsLayoutRow = string | string[];
4
4
  export interface CmsLayoutSectionInput {
@@ -28,6 +28,7 @@ export interface CmsEntrySettings {
28
28
  export type CmsSettingsMap = Record<string, CmsEntrySettings>;
29
29
  export declare function layoutFromConfig(input: CmsLayoutBlock[] | undefined): CmsFormLayout;
30
30
  export declare function resolveFormLayout(fields: Record<string, FieldConfig>, layout: CmsFormLayout | undefined): CmsFormLayout;
31
+ export declare function blockFormLayout(block: Pick<BlockConfig, 'fields' | 'layout'>): CmsFormLayout;
31
32
  export declare function defaultListColumns(fields: Record<string, FieldConfig>, list: CmsListInput | undefined, extra?: string[]): string[];
32
33
  export declare function resolveListColumns(fields: Record<string, FieldConfig>, saved: string[] | undefined, list: CmsListInput | undefined, extra?: string[]): string[];
33
34
  export declare function layoutErrors(at: string, fields: Record<string, FieldConfig>, input: CmsLayoutBlock[] | undefined): string[];
@@ -78,6 +78,9 @@ export function resolveFormLayout(fields, layout) {
78
78
  }
79
79
  return { main };
80
80
  }
81
+ export function blockFormLayout(block) {
82
+ return resolveFormLayout(block.fields, layoutFromConfig(block.layout));
83
+ }
81
84
  export function defaultListColumns(fields, list, extra = []) {
82
85
  const available = [...Object.keys(fields), ...extra];
83
86
  const configured = list?.columns?.filter((key) => available.includes(key));
@@ -0,0 +1,48 @@
1
+ import type { CmsConfig, CmsEntry, FieldConfig } from './index.js';
2
+ export declare const LINK_URL_MAX_LENGTH = 2048;
3
+ export declare const LINK_URL_SCHEMES: readonly string[];
4
+ export declare const LINK_TARGET_SEPARATOR = ":";
5
+ export interface CmsLinkValue {
6
+ url?: string;
7
+ entry?: string;
8
+ id?: string;
9
+ label?: string | Record<string, string>;
10
+ newTab?: boolean;
11
+ }
12
+ export interface CmsLink {
13
+ href: string | null;
14
+ label: string | null;
15
+ newTab: boolean;
16
+ external: boolean;
17
+ entry: string | null;
18
+ id: string | null;
19
+ }
20
+ export interface CmsLinkTarget {
21
+ entry: string;
22
+ id: string;
23
+ }
24
+ export interface CmsLinkReference extends CmsLinkTarget {
25
+ field: string;
26
+ }
27
+ export type CmsLinkUrlKind = 'absolute' | 'path' | 'anchor';
28
+ export declare function linkUrlKind(url: string): CmsLinkUrlKind | null;
29
+ export declare function linkUrlError(url: unknown): string | null;
30
+ export declare function isExternalLinkUrl(url: string | null | undefined): boolean;
31
+ export declare function isLinkTargetEntry(entry: CmsEntry | null | undefined): boolean;
32
+ export declare function declaredLinkTargets(field: FieldConfig): string[] | null;
33
+ export declare function linkTargetNames(config: CmsConfig, field: FieldConfig): string[];
34
+ export declare function allowsExternalLinks(field: FieldConfig): boolean;
35
+ export declare function linkTargetKey(entry: string, id: string): string;
36
+ export declare function parseLinkTargetKey(key: string): CmsLinkTarget | null;
37
+ export declare function readLinkValue(value: unknown): CmsLinkValue | null;
38
+ export declare function linkTargetOf(value: unknown): CmsLinkTarget | null;
39
+ export declare function linkLabelText(label: unknown, locale: string, defaultLocale: string): string | null;
40
+ export declare function linkLabelTexts(label: unknown): {
41
+ locale: string | null;
42
+ text: string;
43
+ }[];
44
+ export declare function pageLinkPath(entry: CmsEntry | undefined, id: string): string | null;
45
+ export declare function linkHref(config: CmsConfig, link: CmsLinkValue | null, locale: string, target?: Record<string, unknown> | null): string | null;
46
+ export declare function resolveCmsLink(config: CmsConfig, value: unknown, locale: string, defaultLocale: string, target?: Record<string, unknown> | null): CmsLink | null;
47
+ export declare function linkReferences(fields: Record<string, FieldConfig>, values: Record<string, unknown>): CmsLinkReference[];
48
+ export declare function linkDisplayText(value: unknown, locale: string, defaultLocale: string, targetTitle?: string | null): string;
@@ -0,0 +1,155 @@
1
+ import { blockReferenceLabel, walkBlocks } from "./block-paths.js";
2
+ import { contentItemPath, isRoutedContent } from "./content-routes.js";
3
+ export const LINK_URL_MAX_LENGTH = 2048;
4
+ export const LINK_URL_SCHEMES = ["http", "https", "mailto", "tel"];
5
+ export const LINK_TARGET_SEPARATOR = ":";
6
+ const SCHEME = /^([a-z][a-z\d+.-]*):/i;
7
+ const UNSAFE_CHARACTERS = /[\s\u0000-\u001F\u007F]/;
8
+ const TEL_NUMBER = /^\+?[\d().\-/]+$/;
9
+ export function linkUrlKind(url) {
10
+ if (url.startsWith("#")) return "anchor";
11
+ if (url.startsWith("/") && !url.startsWith("//") && !url.startsWith("/\\")) return "path";
12
+ const scheme = SCHEME.exec(url)?.[1]?.toLowerCase();
13
+ return scheme && LINK_URL_SCHEMES.includes(scheme) ? "absolute" : null;
14
+ }
15
+ export function linkUrlError(url) {
16
+ if (typeof url !== "string" || !url) return "Enter a URL";
17
+ if (url.length > LINK_URL_MAX_LENGTH) return "The URL is too long";
18
+ if (UNSAFE_CHARACTERS.test(url)) return "A URL cannot contain spaces";
19
+ if (url.startsWith("//") || url.startsWith("/\\") || url.startsWith("\\"))
20
+ return "Use https:// for links to other sites";
21
+ if (url.startsWith("/")) return null;
22
+ if (url.startsWith("#")) return url.length > 1 ? null : "Add an anchor name after #";
23
+ const scheme = SCHEME.exec(url)?.[1]?.toLowerCase();
24
+ if (!scheme) return "Use a full URL (https://...), a path starting with / or an #anchor";
25
+ if (!LINK_URL_SCHEMES.includes(scheme))
26
+ return `${scheme}: links are not allowed (use http, https, mailto or tel)`;
27
+ const rest = url.slice(scheme.length + 1);
28
+ if (scheme === "mailto") return rest ? null : "Add an email address after mailto:";
29
+ if (scheme === "tel") return TEL_NUMBER.test(rest) ? null : "Add a phone number after tel:";
30
+ if (!rest.startsWith("//")) return "Invalid URL";
31
+ try {
32
+ return new URL(url).hostname ? null : "Invalid URL";
33
+ } catch {
34
+ return "Invalid URL";
35
+ }
36
+ }
37
+ export function isExternalLinkUrl(url) {
38
+ return !!url && linkUrlKind(url) === "absolute";
39
+ }
40
+ export function isLinkTargetEntry(entry) {
41
+ return !!entry && (entry.kind === "page" || isRoutedContent(entry));
42
+ }
43
+ export function declaredLinkTargets(field) {
44
+ const to = field.to;
45
+ if (!Array.isArray(to)) return null;
46
+ return to.filter((name) => typeof name === "string");
47
+ }
48
+ export function linkTargetNames(config, field) {
49
+ const declared = declaredLinkTargets(field);
50
+ if (declared) return declared.filter((name) => isLinkTargetEntry(config[name]));
51
+ return Object.entries(config).filter(([, entry]) => isLinkTargetEntry(entry)).map(([name]) => name);
52
+ }
53
+ export function allowsExternalLinks(field) {
54
+ return field.external !== false;
55
+ }
56
+ export function linkTargetKey(entry, id) {
57
+ return `${entry}${LINK_TARGET_SEPARATOR}${id}`;
58
+ }
59
+ export function parseLinkTargetKey(key) {
60
+ const index = key.indexOf(LINK_TARGET_SEPARATOR);
61
+ if (index <= 0 || index === key.length - 1) return null;
62
+ return { entry: key.slice(0, index), id: key.slice(index + 1) };
63
+ }
64
+ function isRecord(value) {
65
+ return !!value && typeof value === "object" && !Array.isArray(value);
66
+ }
67
+ export function readLinkValue(value) {
68
+ let parsed = value;
69
+ if (typeof parsed === "string") {
70
+ const text = parsed.trim();
71
+ if (!text.startsWith("{")) return text ? { url: text } : null;
72
+ try {
73
+ parsed = JSON.parse(text);
74
+ } catch {
75
+ return null;
76
+ }
77
+ }
78
+ if (!isRecord(parsed)) return null;
79
+ const link = {};
80
+ if (typeof parsed.url === "string" && parsed.url) link.url = parsed.url;
81
+ if (typeof parsed.entry === "string" && parsed.entry) link.entry = parsed.entry;
82
+ if (typeof parsed.id === "string" && parsed.id) link.id = parsed.id;
83
+ if (typeof parsed.label === "string" || isRecord(parsed.label))
84
+ link.label = parsed.label;
85
+ if (parsed.newTab === true) link.newTab = true;
86
+ return link;
87
+ }
88
+ export function linkTargetOf(value) {
89
+ const link = readLinkValue(value);
90
+ if (!link?.entry || !link.id || link.url) return null;
91
+ return { entry: link.entry, id: link.id };
92
+ }
93
+ export function linkLabelText(label, locale, defaultLocale) {
94
+ if (typeof label === "string") return label || null;
95
+ if (!isRecord(label)) return null;
96
+ const pick = (key) => {
97
+ const text = label[key];
98
+ return typeof text === "string" && text ? text : null;
99
+ };
100
+ return pick(locale) ?? pick(defaultLocale) ?? Object.keys(label).map(pick).find((text) => text !== null) ?? null;
101
+ }
102
+ export function linkLabelTexts(label) {
103
+ if (typeof label === "string") return label ? [{ locale: null, text: label }] : [];
104
+ if (!isRecord(label)) return [];
105
+ return Object.entries(label).filter((pair) => typeof pair[1] === "string" && !!pair[1]).map(([locale, text]) => ({ locale, text }));
106
+ }
107
+ export function pageLinkPath(entry, id) {
108
+ if (entry?.kind !== "page") return null;
109
+ return entry.pages?.find((route) => route.key === id)?.path ?? null;
110
+ }
111
+ export function linkHref(config, link, locale, target) {
112
+ if (!link) return null;
113
+ if (link.url) return linkUrlError(link.url) ? null : link.url;
114
+ if (!link.entry || !link.id) return null;
115
+ const entry = config[link.entry];
116
+ if (entry?.kind === "page") return pageLinkPath(entry, link.id);
117
+ if (!target || !isRoutedContent(entry)) return null;
118
+ return contentItemPath(entry, target, locale);
119
+ }
120
+ export function resolveCmsLink(config, value, locale, defaultLocale, target) {
121
+ const link = readLinkValue(value);
122
+ if (!link || !link.url && !(link.entry && link.id)) return null;
123
+ return {
124
+ href: linkHref(config, link, locale, target),
125
+ label: linkLabelText(link.label, locale, defaultLocale),
126
+ newTab: !!link.newTab,
127
+ external: isExternalLinkUrl(link.url),
128
+ entry: link.url ? null : link.entry ?? null,
129
+ id: link.url ? null : link.id ?? null
130
+ };
131
+ }
132
+ export function linkReferences(fields, values) {
133
+ const references = [];
134
+ for (const [key, field] of Object.entries(fields)) {
135
+ if (field.type !== "link") continue;
136
+ const target = linkTargetOf(values[key]);
137
+ if (target) references.push({ field: key, ...target });
138
+ }
139
+ walkBlocks(fields, values, ({ item, block, path }) => {
140
+ for (const [blockFieldKey, blockField] of Object.entries(block.fields)) {
141
+ if (blockField.type !== "link") continue;
142
+ const target = linkTargetOf(item[blockFieldKey]);
143
+ if (target) references.push({ field: blockReferenceLabel(path, blockFieldKey), ...target });
144
+ }
145
+ });
146
+ return references;
147
+ }
148
+ export function linkDisplayText(value, locale, defaultLocale, targetTitle) {
149
+ const link = readLinkValue(value);
150
+ if (!link) return "";
151
+ const label = linkLabelText(link.label, locale, defaultLocale);
152
+ const target = link.url ?? targetTitle ?? null;
153
+ if (label && target) return `${label} (${target})`;
154
+ return label ?? target ?? (link.entry && link.id ? `${link.entry} #${link.id}` : "");
155
+ }
@@ -1,7 +1,9 @@
1
1
  import type { CmsEntry, SelectOption } from './index.js';
2
2
  export declare const LIST_FILTER_PREFIX = "filter.";
3
+ export declare const LIST_SEARCH_PARAM = "q";
3
4
  export declare const LIST_FILTER_STATUS = "status";
4
5
  export declare const LIST_FILTER_ID_MAX = 256;
6
+ export declare const LIST_IDS_MAX = 1000;
5
7
  export type CmsListFilters = Record<string, string>;
6
8
  type FilterEntry = Pick<CmsEntry, 'kind' | 'fields' | 'drafts' | 'list'>;
7
9
  export declare function listFilterExtras(entry: FilterEntry): string[];
@@ -1,7 +1,9 @@
1
1
  import { isCollectionKind, listFilterKeys, selectOptions } from "./index.js";
2
2
  export const LIST_FILTER_PREFIX = "filter.";
3
+ export const LIST_SEARCH_PARAM = "q";
3
4
  export const LIST_FILTER_STATUS = "status";
4
5
  export const LIST_FILTER_ID_MAX = 256;
6
+ export const LIST_IDS_MAX = 1e3;
5
7
  const STATUS_OPTIONS = [
6
8
  { value: "draft", label: "Draft" },
7
9
  { value: "published", label: "Published" }
@@ -0,0 +1,30 @@
1
+ export interface CmsFocalPoint {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export interface CmsFocalMedia {
6
+ focalX?: number | null;
7
+ focalY?: number | null;
8
+ }
9
+ export declare function isFocalCoordinate(value: unknown): value is number;
10
+ export declare function roundFocalCoordinate(value: number): number;
11
+ export declare function focalPointOf(media: CmsFocalMedia | null | undefined): CmsFocalPoint | null;
12
+ export declare function focalPointIssue(focalX: unknown, focalY: unknown): string | null;
13
+ export declare function focalObjectPosition(media: CmsFocalMedia | null | undefined): string | undefined;
14
+ export declare function imgixFocalModifiers(media: CmsFocalMedia | null | undefined): Record<string, string | number>;
15
+ export interface CmsImageMedia extends CmsFocalMedia {
16
+ url: string | null;
17
+ type?: string | null;
18
+ alt?: string | null;
19
+ width?: number | null;
20
+ height?: number | null;
21
+ }
22
+ export interface CmsImageSizeInput {
23
+ width?: number | string | null;
24
+ height?: number | string | null;
25
+ }
26
+ export declare function cmsImageSize(media: Pick<CmsImageMedia, 'width' | 'height'> | null | undefined, input?: CmsImageSizeInput): {
27
+ width: number | undefined;
28
+ height: number | undefined;
29
+ };
30
+ export declare function isRenderableImage(media: CmsImageMedia | null | undefined): media is CmsImageMedia;