@xleddyl/nuxt-cms 0.9.4 → 0.10.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 (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 -218
  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 -146
  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 +29 -5
  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 +42 -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 +9 -8
  124. package/dist/runtime/app/components/cms/TranslationBadges.d.vue.ts +7 -0
  125. package/dist/runtime/app/components/cms/TranslationBadges.vue +45 -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 +1152 -335
  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 +190 -53
  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
@@ -7,11 +7,45 @@ import {
7
7
  isTranslatableField,
8
8
  isTranslatableMediaField,
9
9
  localizeBlocks,
10
+ blockAt,
11
+ blockListAt,
12
+ blockListPath,
13
+ blockPathIndex,
14
+ blockPathStartsWith,
15
+ blocksFieldAt,
16
+ canAddBlock,
17
+ formatBlockPath,
18
+ insertBlocks,
19
+ isBlockListPath,
20
+ mapBlocks,
21
+ parentBlockPath,
22
+ parseBlockPath,
23
+ sameBlockPath,
24
+ updateBlockAt,
25
+ walkBlocks,
26
+ mediaFilename,
10
27
  mediaPublicUrl,
11
28
  mediaTypeForKey,
12
29
  pickTranslatedMedia,
13
- resolveBlocksMedia
30
+ resolveBlocksMedia,
31
+ linkDisplayText,
32
+ resolveCmsLink
14
33
  } from "./index.js";
34
+ import { CMS_INLINE_TEXT_MAX_LENGTH } from "./inline-text.js";
35
+ import { MAX_BLOCKS_DEPTH, isBlockItemPath, resolveBlockPath } from "./block-paths.js";
36
+ import { blockSignature } from "./block-signature.js";
37
+ function externalLinks(locale, defaultLocale) {
38
+ return (value) => resolveCmsLink({}, value, locale, defaultLocale);
39
+ }
40
+ function previewBlockLinks(field, items, resolveLink) {
41
+ return mapBlocks(field, items, (item, block) => {
42
+ const keys = Object.entries(block?.fields ?? {}).filter(([, blockField]) => blockField.type === "link").map(([key]) => key);
43
+ if (!keys.length) return item;
44
+ const resolved = { ...item };
45
+ for (const key of keys) resolved[key] = resolveLink(item[key]);
46
+ return resolved;
47
+ });
48
+ }
15
49
  export const CMS_PREVIEW_CHANNEL = "nuxt-cms:preview";
16
50
  export const DEFAULT_CMS_PREVIEW_PATH = "/cms/preview";
17
51
  const RESERVED_ADMIN_SEGMENTS = /* @__PURE__ */ new Set(["login", "logout", "media"]);
@@ -26,48 +60,118 @@ export function previewPathErrors(path, entryNames) {
26
60
  return [`preview.path '${path}' clashes with an admin route, pick another segment`];
27
61
  return [];
28
62
  }
63
+ const PREVIEW_THEMES = ["system", "light", "dark"];
64
+ export function readPreviewTheme(value) {
65
+ return PREVIEW_THEMES.find((theme) => theme === value) ?? "system";
66
+ }
67
+ export const CMS_CLIPBOARD_MAX_LENGTH = 2e6;
29
68
  export function previewEnvelope(message) {
30
69
  return { ...message, channel: CMS_PREVIEW_CHANNEL };
31
70
  }
32
71
  function isRecord(value) {
33
72
  return !!value && typeof value === "object" && !Array.isArray(value);
34
73
  }
35
- function isIndex(value) {
36
- return typeof value === "number" && Number.isInteger(value) && value >= 0;
74
+ const FIELD_KEY = /^[a-z_]\w{0,99}$/i;
75
+ export function isFieldKey(value) {
76
+ return typeof value === "string" && FIELD_KEY.test(value);
77
+ }
78
+ export function readMessagePath(value) {
79
+ if (!Array.isArray(value) || value.length > MAX_BLOCKS_DEPTH * 2) return null;
80
+ const valid = value.every(
81
+ (segment, position) => position % 2 === 0 ? isFieldKey(segment) : typeof segment === "number" && Number.isSafeInteger(segment) && segment >= 0
82
+ );
83
+ return valid && isBlockItemPath(value) ? [...value] : null;
84
+ }
85
+ function readOptionalPath(value) {
86
+ return value === null ? null : readMessagePath(value) ?? void 0;
37
87
  }
38
88
  function envelope(data) {
39
89
  if (!isRecord(data) || data.channel !== CMS_PREVIEW_CHANNEL) return null;
40
90
  return typeof data.type === "string" ? data : null;
41
91
  }
92
+ const LOCALE_CODE = /^[a-z0-9_-]{1,35}$/i;
93
+ function parseFieldInput(message) {
94
+ const path = readOptionalPath(message.path);
95
+ if (path === void 0 || !isFieldKey(message.key)) return null;
96
+ if (typeof message.locale !== "string" || !LOCALE_CODE.test(message.locale)) return null;
97
+ if (typeof message.value !== "string" || message.value.length > CMS_INLINE_TEXT_MAX_LENGTH)
98
+ return null;
99
+ return {
100
+ type: "field-input",
101
+ path,
102
+ key: message.key,
103
+ locale: message.locale,
104
+ value: message.value,
105
+ ...message.commit === true ? { commit: true } : {}
106
+ };
107
+ }
108
+ function parsePaste(message) {
109
+ const path = readMessagePath(message.path);
110
+ if (!path) return null;
111
+ if (message.text === void 0) return { type: "paste", path };
112
+ return typeof message.text === "string" && message.text.length <= CMS_CLIPBOARD_MAX_LENGTH ? { type: "paste", path, text: message.text } : null;
113
+ }
42
114
  export function parseFrameMessage(data) {
43
115
  const message = envelope(data);
44
116
  if (!message) return null;
45
117
  const focus = message.focus === true ? { focus: true } : {};
46
118
  switch (message.type) {
47
119
  case "ready":
48
- return { type: "ready" };
120
+ case "undo":
121
+ case "redo":
122
+ case "save":
123
+ return { type: message.type };
49
124
  case "select":
50
- return message.index === null || isIndex(message.index) ? { type: "select", index: message.index, ...focus } : null;
51
- case "move":
52
- return isIndex(message.from) && isIndex(message.to) ? { type: "move", from: message.from, to: message.to, ...focus } : null;
125
+ case "hover": {
126
+ const path = readOptionalPath(message.path);
127
+ if (path === void 0) return null;
128
+ return message.type === "select" ? { type: "select", path, ...focus } : { type: "hover", path };
129
+ }
130
+ case "move": {
131
+ const from = readMessagePath(message.from);
132
+ const to = readMessagePath(message.to);
133
+ return from && to ? { type: "move", from, to, ...focus } : null;
134
+ }
53
135
  case "insert":
54
136
  case "duplicate":
55
137
  case "toggle-hidden":
56
138
  case "remove":
57
- return isIndex(message.index) ? { type: message.type, index: message.index } : null;
139
+ case "copy":
140
+ case "cut": {
141
+ const path = readMessagePath(message.path);
142
+ return path ? { type: message.type, path } : null;
143
+ }
144
+ case "focus-field": {
145
+ const path = readOptionalPath(message.path);
146
+ return path !== void 0 && isFieldKey(message.key) ? { type: "focus-field", path, key: message.key } : null;
147
+ }
148
+ case "field-input":
149
+ return parseFieldInput(message);
150
+ case "paste":
151
+ return parsePaste(message);
58
152
  default:
59
153
  return null;
60
154
  }
61
155
  }
62
156
  export function parseHostMessage(data) {
63
157
  const message = envelope(data);
64
- if (!message || message.type !== "render" || !isRecord(message.state)) return null;
158
+ if (!message) return null;
159
+ if (message.type === "highlight") {
160
+ const path = readOptionalPath(message.path);
161
+ return path === void 0 ? null : { type: "highlight", path };
162
+ }
163
+ if (message.type === "reveal") {
164
+ const path = readMessagePath(message.path);
165
+ return path ? { type: "reveal", path } : null;
166
+ }
167
+ if (message.type !== "render" || !isRecord(message.state)) return null;
65
168
  const state = message.state;
66
169
  if (typeof state.entry !== "string" || typeof state.field !== "string") return null;
67
170
  if (typeof state.locale !== "string" || !Array.isArray(state.blocks)) return null;
68
171
  if (state.item !== null && !isRecord(state.item)) return null;
69
172
  if (!isRecord(state.media)) return null;
70
- if (state.selected !== null && !isIndex(state.selected)) return null;
173
+ const selected = readOptionalPath(state.selected);
174
+ if (selected === void 0) return null;
71
175
  return {
72
176
  type: "render",
73
177
  state: {
@@ -77,69 +181,118 @@ export function parseHostMessage(data) {
77
181
  blocks: state.blocks.filter(isRecord),
78
182
  item: state.item,
79
183
  media: state.media,
80
- selected: state.selected
184
+ selected,
185
+ editable: state.editable !== false,
186
+ lockedFields: Array.isArray(state.lockedFields) ? state.lockedFields.filter((path) => typeof path === "string") : [],
187
+ theme: readPreviewTheme(state.theme)
81
188
  }
82
189
  };
83
190
  }
84
- export function isTrustedPreviewEvent(event, origin, source) {
85
- return !!source && event.origin === origin && event.source === source;
191
+ export function previewFieldConfig(target, blocksFields, blocksValues, entryFields, blocksKey) {
192
+ if (!isFieldKey(target.key)) return void 0;
193
+ if (target.path) {
194
+ const block = resolveBlockPath(blocksFields, blocksValues, target.path)?.block;
195
+ return block && Object.hasOwn(block.fields, target.key) ? block.fields[target.key] : void 0;
196
+ }
197
+ if (!entryFields || target.key === blocksKey || !Object.hasOwn(entryFields, target.key))
198
+ return void 0;
199
+ const field = entryFields[target.key];
200
+ return isPrivateField(field) ? void 0 : field;
86
201
  }
87
- function clamp(index, length) {
88
- return Math.min(Math.max(index, 0), length);
202
+ export function isApplePlatform(platform) {
203
+ return /mac|iphone|ipad|ipod/i.test(platform);
89
204
  }
90
- export function emptyBlock(type, block) {
91
- return { type, ...Object.fromEntries(Object.keys(block.fields).map((key) => [key, null])) };
205
+ export function editorShortcut(event, apple) {
206
+ if (event.altKey) return null;
207
+ const key = event.key.toLowerCase();
208
+ const mod = apple ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey;
209
+ if (mod) {
210
+ if (key === "z") return event.shiftKey ? "redo" : "undo";
211
+ if (event.shiftKey) return null;
212
+ if (key === "y") return "redo";
213
+ if (key === "s") return "save";
214
+ if (key === "d") return "duplicate";
215
+ if (key === "arrowup") return "move-up";
216
+ if (key === "arrowdown") return "move-down";
217
+ return null;
218
+ }
219
+ if (event.metaKey || event.ctrlKey) return null;
220
+ if (key === "enter") return event.shiftKey ? "insert-before" : "insert-after";
221
+ if (event.shiftKey) return null;
222
+ if (key === "delete" || key === "backspace") return "remove";
223
+ if (key === "escape") return "deselect";
224
+ return null;
92
225
  }
93
- export function insertBlock(list, index, item) {
94
- const next = [...list];
95
- next.splice(clamp(index, list.length), 0, item);
96
- return next;
226
+ export function shortcutApplies(action, target) {
227
+ if (action === "save") return true;
228
+ if (target.editable) return false;
229
+ if (action === "undo" || action === "redo") return true;
230
+ if (!target.selected) return false;
231
+ if (action === "deselect") return true;
232
+ return !target.interactive;
97
233
  }
98
- export function moveBlock(list, from, to) {
99
- if (from === to || from < 0 || from >= list.length || to < 0 || to >= list.length)
100
- return [...list];
101
- const next = [...list];
102
- const [item] = next.splice(from, 1);
103
- next.splice(to, 0, item);
104
- return next;
234
+ export function clipboardActionApplies(action, target) {
235
+ if (target.editable) return false;
236
+ if (action === "paste") return true;
237
+ if (action === "cut" && target.interactive) return false;
238
+ return target.selected && !target.textSelected;
239
+ }
240
+ export function isTrustedPreviewEvent(event, origin, source) {
241
+ return !!source && event.origin === origin && event.source === source;
242
+ }
243
+ export function emptyBlock(type, block) {
244
+ const item = { type };
245
+ for (const [key, field] of Object.entries(block.fields))
246
+ item[key] = field.type === "blocks" ? starterBlocks(field) : null;
247
+ return item;
105
248
  }
106
- export function duplicateBlock(list, index) {
107
- const item = list[index];
108
- if (!item) return [...list];
109
- return insertBlock(list, index + 1, JSON.parse(JSON.stringify(item)));
249
+ function starterBlocks(field) {
250
+ const types = Object.entries(field.blocks ?? {});
251
+ const count = Math.min(field.min ?? 0, field.max ?? Number.POSITIVE_INFINITY);
252
+ if (types.length !== 1 || count < 1) return null;
253
+ const [type, block] = types[0];
254
+ return Array.from({ length: count }, () => emptyBlock(type, block));
110
255
  }
111
- export function removeBlock(list, index) {
112
- return list.filter((_, i) => i !== index);
256
+ export function duplicateBlockAt(values, path) {
257
+ const item = blockAt(values, path);
258
+ if (!item) return values;
259
+ const copy = JSON.parse(JSON.stringify(item));
260
+ return insertBlocks(values, blockListPath(path), blockPathIndex(path) + 1, [copy]);
113
261
  }
114
262
  export function canHideBlock(block) {
115
263
  return !!block && !declaresHiddenField(block);
116
264
  }
117
- export function toggleBlockHidden(list, index, block) {
118
- const item = list[index];
119
- if (!item || !canHideBlock(block)) return [...list];
120
- const { [BLOCK_HIDDEN_KEY]: _hidden, ...rest } = item;
121
- const updated = isHiddenBlock(item) ? rest : { ...rest, [BLOCK_HIDDEN_KEY]: true };
122
- return list.map((current, i) => i === index ? updated : current);
265
+ export function toggleBlockHiddenAt(values, path, block) {
266
+ if (!canHideBlock(block)) return values;
267
+ return updateBlockAt(values, path, (item) => {
268
+ const { [BLOCK_HIDDEN_KEY]: _hidden, ...rest } = item;
269
+ return isHiddenBlock(item) ? rest : { ...rest, [BLOCK_HIDDEN_KEY]: true };
270
+ });
123
271
  }
124
- export function selectionAfterMove(selected, from, to) {
125
- if (selected === null) return null;
126
- if (selected === from) return to;
127
- if (from < selected && to >= selected) return selected - 1;
128
- if (from > selected && to <= selected) return selected + 1;
129
- return selected;
272
+ export function canMoveBlock(fields, values, from, toList) {
273
+ const source = resolveBlockPath(fields, values, from);
274
+ if (!source?.block || !isBlockListPath(toList) || blockPathStartsWith(toList, from)) return false;
275
+ const target = blocksFieldAt(fields, values, toList);
276
+ const type = String(source.item.type);
277
+ const blocks = target?.blocks ?? {};
278
+ if (!target || !Object.hasOwn(blocks, type)) return false;
279
+ if (sameBlockPath(blockListPath(from), toList)) return true;
280
+ if (blockSignature(blocks[type]) !== blockSignature(source.block)) return false;
281
+ return canAddBlock(target, blockListAt(values, toList)?.length ?? 0);
130
282
  }
131
- export function selectionAfterRemove(selected, index) {
132
- if (selected === null || selected === index) return null;
133
- return selected > index ? selected - 1 : selected;
283
+ export function isHorizontalList(boxes) {
284
+ return boxes.some((box, position) => {
285
+ const next = boxes[position + 1];
286
+ return !!next && next.left >= box.right - 1 && next.top < box.bottom - 1;
287
+ });
134
288
  }
135
- export function moveTargetForInsertion(from, insertAt) {
136
- return insertAt > from ? insertAt - 1 : insertAt;
137
- }
138
- export function insertionIndex(blocks, y, total) {
139
- for (const block of blocks) {
140
- if (y < (block.top + block.bottom) / 2) return block.index;
289
+ export function insertionIndex(boxes, point, total) {
290
+ const horizontal = isHorizontalList(boxes);
291
+ for (const box of boxes) {
292
+ const before = horizontal ? point.x < (box.left + box.right) / 2 : point.y < (box.top + box.bottom) / 2;
293
+ if (before) return box.index;
141
294
  }
142
- const last = blocks[blocks.length - 1];
295
+ const last = boxes[boxes.length - 1];
143
296
  return last ? last.index + 1 : total;
144
297
  }
145
298
  function pushMediaKeys(keys, field, value) {
@@ -149,20 +302,11 @@ function pushMediaKeys(keys, field, value) {
149
302
  }
150
303
  export function collectMediaKeys(fields, values) {
151
304
  const keys = /* @__PURE__ */ new Set();
152
- for (const [key, field] of Object.entries(fields)) {
153
- const value = values?.[key];
154
- if (field.type === "media") {
155
- pushMediaKeys(keys, field, value);
156
- continue;
157
- }
158
- if (field.type !== "blocks" || !Array.isArray(value)) continue;
159
- for (const item of value) {
160
- if (!isRecord(item)) continue;
161
- const block = field.blocks?.[String(item.type)];
162
- for (const [blockKey, blockField] of Object.entries(block?.fields ?? {}))
163
- pushMediaKeys(keys, blockField, item[blockKey]);
164
- }
165
- }
305
+ for (const [key, field] of Object.entries(fields)) pushMediaKeys(keys, field, values?.[key]);
306
+ walkBlocks(fields, values, ({ item, block }) => {
307
+ for (const [blockKey, blockField] of Object.entries(block.fields))
308
+ pushMediaKeys(keys, blockField, item[blockKey]);
309
+ });
166
310
  return [...keys];
167
311
  }
168
312
  export function previewMedia(key, item, baseUrl) {
@@ -175,21 +319,37 @@ export function previewMedia(key, item, baseUrl) {
175
319
  mime: item?.mime ?? null,
176
320
  size: item?.size ?? null,
177
321
  width: item?.width ?? null,
178
- height: item?.height ?? null
322
+ height: item?.height ?? null,
323
+ focalX: item?.focalX ?? null,
324
+ focalY: item?.focalY ?? null
179
325
  };
180
326
  }
181
- export function previewBlocks(field, value, locale, defaultLocale, media) {
327
+ export function previewBlocks(field, value, locale, defaultLocale, media, resolveLink = externalLinks(locale, defaultLocale)) {
182
328
  if (!Array.isArray(value)) return [];
183
329
  const localized = localizeBlocks(field, value, locale, defaultLocale);
184
- return resolveBlocksMedia(field, localized, (key) => media[key] ?? null);
330
+ const resolved = resolveBlocksMedia(field, localized, (key) => media[key] ?? null);
331
+ return previewNestedLists(
332
+ field,
333
+ previewBlockLinks(field, resolved, resolveLink)
334
+ );
335
+ }
336
+ function previewNestedLists(field, items) {
337
+ return mapBlocks(field, items, (item, block) => {
338
+ const empty = Object.entries(block?.fields ?? {}).filter(
339
+ ([key, nested]) => nested.type === "blocks" && !Array.isArray(item[key])
340
+ );
341
+ return empty.length ? { ...item, ...Object.fromEntries(empty.map(([key]) => [key, []])) } : item;
342
+ });
185
343
  }
186
- export function previewItem(fields, values, locale, defaultLocale, media) {
344
+ export function previewItem(fields, values, locale, defaultLocale, media, resolveLink = externalLinks(locale, defaultLocale)) {
187
345
  const item = {};
188
346
  for (const [key, field] of Object.entries(fields)) {
189
347
  if (isPrivateField(field)) continue;
190
348
  const value = values[key] ?? null;
191
349
  if (field.type === "blocks") {
192
- item[key] = previewBlocks(field, value, locale, defaultLocale, media);
350
+ item[key] = previewBlocks(field, value, locale, defaultLocale, media, resolveLink);
351
+ } else if (field.type === "link") {
352
+ item[key] = resolveLink(value);
193
353
  } else if (field.type === "media") {
194
354
  const mediaKey = isTranslatableMediaField(field) ? pickTranslatedMedia(
195
355
  decodeTranslatableValue(value, defaultLocale),
@@ -206,14 +366,192 @@ export function previewItem(fields, values, locale, defaultLocale, media) {
206
366
  }
207
367
  return item;
208
368
  }
209
- export function blockSummary(block, item, locale, defaultLocale, max = 80) {
369
+ const SUMMARY_FIELD_TYPES = /* @__PURE__ */ new Set(["text", "richtext", "email"]);
370
+ const HTML_ENTITIES = {
371
+ amp: "&",
372
+ lt: "<",
373
+ gt: ">",
374
+ quot: '"',
375
+ apos: "'",
376
+ nbsp: " ",
377
+ "#39": "'"
378
+ };
379
+ function plainText(value) {
380
+ return value.replace(/<[^>]*>/g, " ").replace(/&(amp|lt|gt|quot|apos|nbsp|#39);/g, (_, name) => HTML_ENTITIES[name]).replace(/\s+/g, " ").trim();
381
+ }
382
+ function localizedText(raw, locale, defaultLocale) {
383
+ if (typeof raw === "string") return raw;
384
+ if (!isRecord(raw)) return "";
385
+ const value = raw[locale] || raw[defaultLocale];
386
+ return typeof value === "string" ? value : "";
387
+ }
388
+ function blockMediaName(block, item, locale, defaultLocale) {
210
389
  for (const [key, field] of Object.entries(block?.fields ?? {})) {
211
- if (field.type !== "text" && field.type !== "richtext") continue;
390
+ if (field.type !== "media") continue;
212
391
  const raw = item[key];
213
- const translations = isRecord(raw) ? raw : null;
214
- const value = typeof raw === "string" ? raw : translations?.[locale] || translations?.[defaultLocale] || "";
215
- const text = value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
216
- if (text) return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
392
+ const value = isTranslatableMediaField(field) ? pickTranslatedMedia(decodeTranslatableValue(raw, defaultLocale), locale, defaultLocale) : raw;
393
+ if (typeof value === "string" && value) return mediaFilename(value);
217
394
  }
218
395
  return "";
219
396
  }
397
+ export function blockSummary(block, item, locale, defaultLocale, max = 80) {
398
+ let text = "";
399
+ for (const [key, field] of Object.entries(block?.fields ?? {})) {
400
+ if (field.type === "link") {
401
+ text = linkDisplayText(item[key], locale, defaultLocale).trim();
402
+ if (text) break;
403
+ continue;
404
+ }
405
+ if (!SUMMARY_FIELD_TYPES.has(field.type)) continue;
406
+ text = plainText(localizedText(item[key], locale, defaultLocale));
407
+ if (text) break;
408
+ }
409
+ if (!text) text = blockMediaName(block, item, locale, defaultLocale);
410
+ if (!text) text = nestedBlockSummary(block, item, locale, defaultLocale, max);
411
+ return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
412
+ }
413
+ function nestedBlockSummary(block, item, locale, defaultLocale, max) {
414
+ let count = 0;
415
+ for (const [key, field] of Object.entries(block?.fields ?? {})) {
416
+ const list = item[key];
417
+ if (field.type !== "blocks" || !Array.isArray(list)) continue;
418
+ for (const child of list) {
419
+ if (!isRecord(child)) continue;
420
+ count++;
421
+ const text = blockSummary(
422
+ field.blocks?.[String(child.type)],
423
+ child,
424
+ locale,
425
+ defaultLocale,
426
+ max
427
+ );
428
+ if (text) return text;
429
+ }
430
+ }
431
+ return count ? `${count} ${count === 1 ? "block" : "blocks"}` : "";
432
+ }
433
+ function itemPrefixes(segments) {
434
+ const prefixes = [];
435
+ for (let end = 2; end <= segments.length; end += 2) {
436
+ if (!/^\d+$/.test(segments[end - 1])) break;
437
+ prefixes.push(segments.slice(0, end).join("."));
438
+ }
439
+ return prefixes;
440
+ }
441
+ export function blockErrorPaths(errors, fieldKey) {
442
+ const paths = /* @__PURE__ */ new Set();
443
+ for (const [key, message] of Object.entries(errors)) {
444
+ if (!message || !key.startsWith(`${fieldKey}.`)) continue;
445
+ for (const prefix of itemPrefixes(key.split("."))) paths.add(prefix);
446
+ }
447
+ return paths;
448
+ }
449
+ function compareErrorKeys(a, b) {
450
+ const left = a.split(".");
451
+ const right = b.split(".");
452
+ for (let position = 0; position < Math.min(left.length, right.length); position++) {
453
+ const x = left[position];
454
+ const y = right[position];
455
+ if (x === y) continue;
456
+ if (/^\d+$/.test(x) && /^\d+$/.test(y)) return Number(x) - Number(y);
457
+ return 0;
458
+ }
459
+ return left.length - right.length;
460
+ }
461
+ export function firstBlockError(errors, fieldKey) {
462
+ const keys = Object.keys(errors).filter((key) => errors[key] && key.startsWith(`${fieldKey}.`)).sort(compareErrorKeys);
463
+ for (const key of keys) {
464
+ const segments = key.split(".");
465
+ const deepest = itemPrefixes(segments).at(-1);
466
+ const path = deepest ? parseBlockPath(deepest) : null;
467
+ if (!path) continue;
468
+ const next = segments[path.length];
469
+ return next ? { path, key: next } : { path };
470
+ }
471
+ return null;
472
+ }
473
+ export function editorIssueKeys(fields, values, path, fieldKey) {
474
+ const [head] = path;
475
+ if (typeof head !== "string" && typeof head !== "number") return [];
476
+ const keys = [String(head)];
477
+ if (String(head) !== fieldKey || typeof path[1] !== "number") return keys;
478
+ let end = 2;
479
+ while (end <= MAX_BLOCKS_DEPTH * 2) {
480
+ const item = path.slice(0, end);
481
+ const next = path[end];
482
+ if (typeof next !== "string" && typeof next !== "number") {
483
+ keys.push(formatBlockPath(item));
484
+ break;
485
+ }
486
+ const block = resolveBlockPath(fields, values, item)?.block;
487
+ const field = block && Object.hasOwn(block.fields, next) ? block.fields[next] : void 0;
488
+ if (field?.type === "blocks" && typeof path[end + 1] === "number") {
489
+ end += 2;
490
+ continue;
491
+ }
492
+ keys.push(`${formatBlockPath(item)}.${String(next)}`);
493
+ break;
494
+ }
495
+ return keys;
496
+ }
497
+ export function blockTreeVisits(fields, values, prefix = []) {
498
+ const visits = [];
499
+ for (const [key, field] of Object.entries(fields)) {
500
+ const list = values?.[key];
501
+ if (field?.type !== "blocks" || !Array.isArray(list)) continue;
502
+ list.forEach((item, index) => {
503
+ if (!isRecord(item)) return;
504
+ const block = field.blocks?.[String(item.type)];
505
+ const path = [...prefix, key, index];
506
+ visits.push({ path, item, block, field });
507
+ if (block) visits.push(...blockTreeVisits(block.fields, item, path));
508
+ });
509
+ }
510
+ return visits;
511
+ }
512
+ function listKeyOf(path, ids) {
513
+ const parent = parentBlockPath(path);
514
+ const owner = parent ? ids.get(formatBlockPath(parent)) : "root";
515
+ return `${String(owner)}:${String(path.at(-2))}`;
516
+ }
517
+ function replacedId(before, item, index, present, used) {
518
+ let best;
519
+ before?.items.forEach((candidate, position) => {
520
+ const id = before.ids[position];
521
+ if (id === void 0 || used.has(id) || present.has(candidate)) return;
522
+ if (candidate.type !== item.type) return;
523
+ const distance = Math.abs(position - index);
524
+ if (!best || distance < best.distance) best = { id, distance };
525
+ });
526
+ return best?.id;
527
+ }
528
+ export function stableBlockTreeIds(visits, previous, createId) {
529
+ const present = new Set(visits.map((visit) => visit.item));
530
+ const used = /* @__PURE__ */ new Set();
531
+ const assigned = /* @__PURE__ */ new Map();
532
+ visits.forEach((visit, position) => {
533
+ const id = previous?.items.get(visit.item);
534
+ if (id === void 0 || used.has(id)) return;
535
+ used.add(id);
536
+ assigned.set(position, id);
537
+ });
538
+ const ids = /* @__PURE__ */ new Map();
539
+ const snapshot = { items: /* @__PURE__ */ new Map(), lists: /* @__PURE__ */ new Map() };
540
+ visits.forEach((visit, position) => {
541
+ const listKey = listKeyOf(visit.path, ids);
542
+ const index = blockPathIndex(visit.path);
543
+ let id = assigned.get(position);
544
+ if (id === void 0) {
545
+ id = replacedId(previous?.lists.get(listKey), visit.item, index, present, used);
546
+ id ??= createId();
547
+ used.add(id);
548
+ }
549
+ ids.set(formatBlockPath(visit.path), id);
550
+ if (!snapshot.items.has(visit.item)) snapshot.items.set(visit.item, id);
551
+ const list = snapshot.lists.get(listKey) ?? { items: [], ids: [] };
552
+ list.items[index] = visit.item;
553
+ list.ids[index] = id;
554
+ snapshot.lists.set(listKey, list);
555
+ });
556
+ return { ids, snapshot };
557
+ }