@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,15 +1,29 @@
1
+ import type { CmsBlockPath } from '../../shared/block-paths.js';
1
2
  import type { FieldConfig } from '../../shared/index.js';
3
+ import type { CmsInlineOverride } from '../../shared/inline-text.js';
2
4
  import type { CmsPreviewFrameMessage } from '../../shared/preview.js';
3
5
  type __VLS_Props = {
4
6
  field: FieldConfig;
5
- total: number;
6
- selected: number | null;
7
+ fieldKey: string;
8
+ fields: Record<string, FieldConfig> | null;
9
+ blocks: readonly Record<string, unknown>[];
10
+ item: Record<string, unknown> | null;
11
+ locale: string;
12
+ editable: boolean;
13
+ lockedFields: readonly string[];
14
+ selected: CmsBlockPath | null;
15
+ highlighted: CmsBlockPath | null;
7
16
  version: number;
8
17
  };
9
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
18
+ declare function reveal(path: CmsBlockPath): Promise<void>;
19
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
20
+ reveal: typeof reveal;
21
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
22
  message: (message: CmsPreviewFrameMessage) => any;
23
+ inline: (override: CmsInlineOverride | null) => any;
11
24
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
25
  onMessage?: ((message: CmsPreviewFrameMessage) => any) | undefined;
26
+ onInline?: ((override: CmsInlineOverride | null) => any) | undefined;
13
27
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
28
  declare const _default: typeof __VLS_export;
15
29
  export default _default;
@@ -0,0 +1,12 @@
1
+ import type { Directive } from 'vue';
2
+ import type { CmsPreviewTheme } from '../../shared/preview.js';
3
+ export declare const CMS_FIELD_ATTRIBUTE = "data-cms-field";
4
+ export declare const cmsFieldMarking: import("vue").ShallowRef<boolean, boolean>;
5
+ export declare const cmsPreviewEditable: import("vue").ShallowRef<boolean, boolean>;
6
+ export declare const cmsPreviewTheme: import("vue").ShallowRef<CmsPreviewTheme, CmsPreviewTheme>;
7
+ export declare function cmsTokenRoot(theme: CmsPreviewTheme): {
8
+ class: string;
9
+ 'data-preset': string;
10
+ 'data-theme': CmsPreviewTheme;
11
+ };
12
+ export declare const vCmsField: Directive<HTMLElement, string>;
@@ -0,0 +1,20 @@
1
+ import { shallowRef } from "#imports";
2
+ export const CMS_FIELD_ATTRIBUTE = "data-cms-field";
3
+ export const cmsFieldMarking = shallowRef(false);
4
+ export const cmsPreviewEditable = shallowRef(false);
5
+ export const cmsPreviewTheme = shallowRef("system");
6
+ export function cmsTokenRoot(theme) {
7
+ return { class: "k-root", "data-preset": "default", "data-theme": theme };
8
+ }
9
+ function mark(element, name) {
10
+ if (!cmsFieldMarking.value) return;
11
+ if (typeof name === "string" && name) element.setAttribute(CMS_FIELD_ATTRIBUTE, name);
12
+ else element.removeAttribute(CMS_FIELD_ATTRIBUTE);
13
+ }
14
+ export const vCmsField = {
15
+ mounted: (element, binding) => mark(element, binding.value),
16
+ updated: (element, binding) => {
17
+ if (binding.value !== binding.oldValue) mark(element, binding.value);
18
+ },
19
+ getSSRProps: () => ({})
20
+ };
@@ -0,0 +1,15 @@
1
+ export interface CmsInlineTextOptions {
2
+ multiline: boolean;
3
+ maxLength?: number;
4
+ point?: {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ onInput: (value: string, commit: boolean) => void;
9
+ onStop: (value: string) => void;
10
+ }
11
+ export interface CmsInlineTextSession {
12
+ element: HTMLElement;
13
+ stop: (commit: boolean) => void;
14
+ }
15
+ export declare function startInlineText(element: HTMLElement, options: CmsInlineTextOptions): CmsInlineTextSession;
@@ -0,0 +1,158 @@
1
+ import {
2
+ CMS_INLINE_INPUT_DELAY,
3
+ editableText,
4
+ fitInlineInsertion,
5
+ normalizeInlineText
6
+ } from "../../shared/inline-text.js";
7
+ import { onApplePlatform } from "../utils/keyboard.js";
8
+ let plaintextOnly = null;
9
+ function supportsPlaintextOnly() {
10
+ if (plaintextOnly !== null) return plaintextOnly;
11
+ const probe = document.createElement("div");
12
+ try {
13
+ probe.contentEditable = "plaintext-only";
14
+ plaintextOnly = probe.contentEditable === "plaintext-only";
15
+ } catch {
16
+ plaintextOnly = false;
17
+ }
18
+ return plaintextOnly;
19
+ }
20
+ function caretAt(point) {
21
+ const positioned = document;
22
+ const position = positioned.caretPositionFromPoint?.(point.x, point.y);
23
+ if (position) {
24
+ const range = document.createRange();
25
+ range.setStart(position.offsetNode, position.offset);
26
+ return range;
27
+ }
28
+ return document.caretRangeFromPoint?.(point.x, point.y) ?? null;
29
+ }
30
+ function placeCaret(element, point) {
31
+ const selection = window.getSelection();
32
+ if (!selection) return;
33
+ const current = selection.rangeCount ? selection.getRangeAt(0) : null;
34
+ const kept = current && !current.collapsed && element.contains(current.commonAncestorContainer) ? current.cloneRange() : null;
35
+ element.focus({ preventScroll: true });
36
+ const range = kept ?? (point ? caretAt(point) : null);
37
+ if (range && element.contains(range.startContainer)) {
38
+ selection.removeAllRanges();
39
+ selection.addRange(range);
40
+ } else {
41
+ selection.selectAllChildren(element);
42
+ selection.collapseToEnd();
43
+ }
44
+ }
45
+ export function startInlineText(element, options) {
46
+ const nodes = Array.from(element.childNodes);
47
+ const values = nodes.map((node) => node.nodeValue);
48
+ const read = () => normalizeInlineText(editableText(element), options.multiline);
49
+ const initial = read();
50
+ const native = supportsPlaintextOnly();
51
+ let sent = initial;
52
+ let dirty = false;
53
+ let active = true;
54
+ let timer;
55
+ function flush() {
56
+ clearTimeout(timer);
57
+ timer = void 0;
58
+ const value = read();
59
+ if (value === sent) return;
60
+ sent = value;
61
+ dirty = true;
62
+ options.onInput(value, false);
63
+ }
64
+ function onInput() {
65
+ clearTimeout(timer);
66
+ timer = setTimeout(flush, CMS_INLINE_INPUT_DELAY);
67
+ }
68
+ function onKeydown(event) {
69
+ if (event.isComposing) return;
70
+ const mod = onApplePlatform() ? event.metaKey : event.ctrlKey;
71
+ if (event.key === "Escape") {
72
+ event.preventDefault();
73
+ event.stopPropagation();
74
+ stop(false);
75
+ } else if (event.key === "Enter" && (!options.multiline || mod)) {
76
+ event.preventDefault();
77
+ event.stopPropagation();
78
+ stop(true);
79
+ } else if (mod && event.key.toLowerCase() === "s") {
80
+ flush();
81
+ }
82
+ }
83
+ function selectedLength() {
84
+ const selection = window.getSelection();
85
+ if (!selection?.rangeCount || !element.contains(selection.anchorNode)) return 0;
86
+ return selection.toString().length;
87
+ }
88
+ function insertedText(event) {
89
+ if (event.inputType === "insertParagraph" || event.inputType === "insertLineBreak")
90
+ return "\n";
91
+ return event.data ?? event.dataTransfer?.getData("text/plain") ?? "";
92
+ }
93
+ function limitInsertion(event) {
94
+ const max = options.maxLength;
95
+ if (max === void 0 || !event.inputType.startsWith("insert")) return;
96
+ const text = insertedText(event);
97
+ const fitted = fitInlineInsertion(text, max - (read().length - selectedLength()));
98
+ if (fitted === text) return;
99
+ event.preventDefault();
100
+ if (fitted) document.execCommand("insertText", false, fitted);
101
+ }
102
+ function onBeforeInput(event) {
103
+ const type = event.inputType;
104
+ if (type.startsWith("format")) event.preventDefault();
105
+ else if (!options.multiline && (type === "insertParagraph" || type === "insertLineBreak"))
106
+ event.preventDefault();
107
+ else limitInsertion(event);
108
+ }
109
+ function onPaste(event) {
110
+ if (native) return;
111
+ event.preventDefault();
112
+ const text = event.clipboardData?.getData("text/plain") ?? "";
113
+ document.execCommand(
114
+ "insertText",
115
+ false,
116
+ options.multiline ? text : normalizeInlineText(text, false)
117
+ );
118
+ }
119
+ function onDrop(event) {
120
+ event.preventDefault();
121
+ }
122
+ function onBlur() {
123
+ stop(true);
124
+ }
125
+ function stop(commit) {
126
+ if (!active) return;
127
+ active = false;
128
+ clearTimeout(timer);
129
+ const value = commit ? read() : initial;
130
+ element.removeEventListener("input", onInput);
131
+ element.removeEventListener("keydown", onKeydown);
132
+ element.removeEventListener("beforeinput", onBeforeInput);
133
+ element.removeEventListener("paste", onPaste);
134
+ element.removeEventListener("drop", onDrop);
135
+ element.removeEventListener("blur", onBlur);
136
+ element.removeAttribute("contenteditable");
137
+ element.removeAttribute("data-cms-editing");
138
+ if (element.isConnected) {
139
+ nodes.forEach((node, index) => {
140
+ if (node.nodeValue !== values[index]) node.nodeValue = values[index] ?? null;
141
+ });
142
+ element.replaceChildren(...nodes);
143
+ if (document.activeElement === element) element.blur();
144
+ }
145
+ if (dirty || value !== initial) options.onInput(value, true);
146
+ options.onStop(value);
147
+ }
148
+ element.setAttribute("contenteditable", native ? "plaintext-only" : "true");
149
+ element.setAttribute("data-cms-editing", "");
150
+ element.addEventListener("input", onInput);
151
+ element.addEventListener("keydown", onKeydown);
152
+ element.addEventListener("beforeinput", onBeforeInput);
153
+ element.addEventListener("paste", onPaste);
154
+ element.addEventListener("drop", onDrop);
155
+ placeCaret(element, options.point);
156
+ element.addEventListener("blur", onBlur);
157
+ return { element, stop };
158
+ }
@@ -0,0 +1,22 @@
1
+ import type { ComputedRef, InjectionKey, PropType } from 'vue';
2
+ import type { CmsBlockPath } from '../../shared/block-paths.js';
3
+ export interface CmsBlockEditorScope {
4
+ path: ComputedRef<CmsBlockPath>;
5
+ schemaPath: ComputedRef<readonly string[] | null>;
6
+ formPath: ComputedRef<string | null>;
7
+ open: (path: CmsBlockPath) => void;
8
+ }
9
+ export declare const CMS_BLOCK_EDITOR: InjectionKey<CmsBlockEditorScope>;
10
+ export declare const CmsBlockEditorProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
11
+ scope: {
12
+ type: PropType<CmsBlockEditorScope>;
13
+ required: true;
14
+ };
15
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
16
+ [key: string]: any;
17
+ }>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
18
+ scope: {
19
+ type: PropType<CmsBlockEditorScope>;
20
+ required: true;
21
+ };
22
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,12 @@
1
+ import { defineComponent, provide } from "#imports";
2
+ export const CMS_BLOCK_EDITOR = Symbol("cms-block-editor");
3
+ export const CmsBlockEditorProvider = defineComponent({
4
+ name: "CmsBlockEditorProvider",
5
+ props: {
6
+ scope: { type: Object, required: true }
7
+ },
8
+ setup(props, { slots }) {
9
+ provide(CMS_BLOCK_EDITOR, props.scope);
10
+ return () => slots.default?.();
11
+ }
12
+ });
@@ -0,0 +1,6 @@
1
+ import type { CmsClipboardTarget, CmsShortcutTarget } from '../../shared/preview.js';
2
+ export declare function isEditableTarget(target: EventTarget | null): boolean;
3
+ export declare function shortcutTarget(event: KeyboardEvent, selected: boolean): CmsShortcutTarget;
4
+ export declare function clipboardTarget(event: Event, selected: boolean): CmsClipboardTarget;
5
+ export declare function isInForeignOverlay(target: EventTarget | null, root: Element | null): boolean;
6
+ export declare function onApplePlatform(): boolean;
@@ -0,0 +1,52 @@
1
+ import { isApplePlatform } from "../../shared/preview.js";
2
+ const NON_TEXT_INPUTS = /* @__PURE__ */ new Set([
3
+ "checkbox",
4
+ "radio",
5
+ "button",
6
+ "submit",
7
+ "reset",
8
+ "range",
9
+ "color",
10
+ "file",
11
+ "image"
12
+ ]);
13
+ const INTERACTIVE_SELECTOR = 'a[href], button, select, summary, [role="button"], [role="link"], [role="menuitem"], [role="option"], [role="tab"], [role="checkbox"], [role="switch"]';
14
+ const OVERLAY_SELECTOR = 'dialog, [popover], [role="dialog"], [role="alertdialog"], [role="menu"]';
15
+ function elementOf(target) {
16
+ const node = target;
17
+ if (!node || typeof node !== "object" || !("nodeType" in node)) return null;
18
+ const element = node.nodeType === 1 ? node : node.parentElement;
19
+ return element && "isContentEditable" in element ? element : null;
20
+ }
21
+ export function isEditableTarget(target) {
22
+ const element = elementOf(target);
23
+ if (!element) return false;
24
+ if (element.isContentEditable) return true;
25
+ const tag = element.tagName;
26
+ if (tag === "TEXTAREA" || tag === "SELECT") return true;
27
+ return tag === "INPUT" && !NON_TEXT_INPUTS.has(element.type);
28
+ }
29
+ export function shortcutTarget(event, selected) {
30
+ const element = elementOf(event.target);
31
+ return {
32
+ editable: isEditableTarget(event.target),
33
+ interactive: !!element?.closest(INTERACTIVE_SELECTOR),
34
+ selected
35
+ };
36
+ }
37
+ export function clipboardTarget(event, selected) {
38
+ const selection = typeof window === "undefined" ? null : window.getSelection();
39
+ return {
40
+ editable: isEditableTarget(event.target),
41
+ interactive: !!elementOf(event.target)?.closest(INTERACTIVE_SELECTOR),
42
+ textSelected: !!selection && !selection.isCollapsed && selection.toString().trim() !== "",
43
+ selected
44
+ };
45
+ }
46
+ export function isInForeignOverlay(target, root) {
47
+ const overlay = elementOf(target)?.closest(OVERLAY_SELECTOR);
48
+ return !!overlay && !(root && overlay.contains(root));
49
+ }
50
+ export function onApplePlatform() {
51
+ return typeof navigator !== "undefined" && isApplePlatform(navigator.platform || navigator.userAgent);
52
+ }
@@ -0,0 +1,6 @@
1
+ import type { CmsRedirectStatus } from '#nuxt-cms';
2
+ export declare const REDIRECT_STATUS_LABELS: Record<CmsRedirectStatus, string>;
3
+ export declare const REDIRECT_STATUS_OPTIONS: {
4
+ value: number;
5
+ label: string;
6
+ }[];
@@ -0,0 +1,7 @@
1
+ export const REDIRECT_STATUS_LABELS = {
2
+ 301: "Moved permanently",
3
+ 302: "Found (temporary)",
4
+ 307: "Temporary redirect",
5
+ 308: "Permanent redirect"
6
+ };
7
+ export const REDIRECT_STATUS_OPTIONS = Object.entries(REDIRECT_STATUS_LABELS).map(([status, label]) => ({ value: Number(status), label: `${status} ${label}` }));
@@ -1,4 +1,12 @@
1
1
  import type { FieldConfig } from '#nuxt-cms';
2
+ import type { FormSubmitError } from '@xleddyl/443-components-vue';
3
+ export declare function cmsSettingsLink(section: string, path?: string): string;
2
4
  export declare function errorMessage(error: unknown): string | undefined;
5
+ export interface CmsResponseIssue {
6
+ path: (string | number)[];
7
+ message: string;
8
+ }
9
+ export declare function errorIssues(error: unknown): CmsResponseIssue[];
10
+ export declare function cmsSubmitError(error: unknown): FormSubmitError;
3
11
  export declare function fieldIcon(field: FieldConfig): string;
4
12
  export declare function cmsIcon(name: string): string;
@@ -1,8 +1,21 @@
1
- import { isBuiltinIcon } from "@xleddyl/443-components-vue";
1
+ import { isBuiltinIcon, routeHash } from "@xleddyl/443-components-vue";
2
+ export function cmsSettingsLink(section, path = "/cms") {
3
+ return `${path}${routeHash(void 0, { settings: section })}`;
4
+ }
2
5
  export function errorMessage(error) {
3
6
  const err = error;
4
7
  return err.data?.message ?? err.message;
5
8
  }
9
+ export function errorIssues(error) {
10
+ const issues = error?.data?.data?.issues;
11
+ if (!Array.isArray(issues)) return [];
12
+ return issues.filter(
13
+ (issue) => !!issue && typeof issue === "object" && Array.isArray(issue.path) && typeof issue.message === "string"
14
+ );
15
+ }
16
+ export function cmsSubmitError(error) {
17
+ return { message: errorMessage(error) ?? "Something went wrong.", issues: errorIssues(error) };
18
+ }
6
19
  const FIELD_ICONS = {
7
20
  text: "bars-3-bottom-left",
8
21
  richtext: "document-text",
@@ -17,6 +30,7 @@ const FIELD_ICONS = {
17
30
  json: "code-bracket",
18
31
  media: "photo",
19
32
  relation: "arrows-right-left",
33
+ link: "arrow-top-right-on-square",
20
34
  blocks: "squares-2x2"
21
35
  };
22
36
  export function fieldIcon(field) {
@@ -0,0 +1,15 @@
1
+ import type { CmsAccount } from '#nuxt-cms';
2
+ import type { Tone } from '@xleddyl/443-components-vue';
3
+ interface RoleOption {
4
+ key: string;
5
+ label: string;
6
+ description?: string | null;
7
+ }
8
+ export declare const UNKNOWN_ROLE_HINT = "This role is not in cms.roles anymore, so the account has no access. Pick a new role.";
9
+ export declare function lastSignIn(account: CmsAccount): string;
10
+ export declare function isKnownRole(role: string, options: readonly RoleOption[]): boolean;
11
+ export declare function roleBadge(role: string, options: readonly RoleOption[], label: (key: string) => string): {
12
+ label: string;
13
+ tone: Tone;
14
+ };
15
+ export {};
@@ -0,0 +1,14 @@
1
+ export const UNKNOWN_ROLE_HINT = "This role is not in cms.roles anymore, so the account has no access. Pick a new role.";
2
+ export function lastSignIn(account) {
3
+ if (!account.lastLoginAt) return "Never signed in";
4
+ return `Last sign-in ${new Date(account.lastLoginAt).toLocaleString(void 0, {
5
+ dateStyle: "medium",
6
+ timeStyle: "short"
7
+ })}`;
8
+ }
9
+ export function isKnownRole(role, options) {
10
+ return options.some((option) => option.key === role);
11
+ }
12
+ export function roleBadge(role, options, label) {
13
+ return isKnownRole(role, options) ? { label: label(role), tone: "neutral" } : { label: `Unknown role: ${role}`, tone: "warning" };
14
+ }
@@ -1 +1 @@
1
- html:has(.cms-scope){color-scheme:light dark;overscroll-behavior-y:none}html:has(.cms-scope[data-theme=light]){color-scheme:light}html:has(.cms-scope[data-theme=dark]){color-scheme:dark}body:has(.cms-scope){margin:0;overscroll-behavior-y:none}.cms-canvas{background-color:var(--k-canvas);min-height:100dvh}.cms-form-main{display:flex;flex-direction:column;gap:1.375rem;min-width:0}.cms-form-section.is-titled{background:var(--k-surface);border:1px solid var(--k-line);border-radius:var(--k-radius-lg)}.cms-form-rows{display:flex;flex-direction:column;gap:1.375rem}.cms-form-section.is-titled>.cms-form-rows{border-top:1px solid var(--k-line);padding:1rem 1rem 1.125rem}.cms-block-tile.is-media-only:focus-visible{outline:2px solid var(--k-ring);outline-offset:2px}.cms-media-row.is-dragging,.cms-media-tile.is-dragging{opacity:.45}.cms-media-grid.is-recent .cms-media-tile{border-radius:var(--k-radius-md)}.cms-media-drop-overlay>svg{animation:cms-float 1.6s ease-in-out infinite;color:var(--k-accent-text)}.cms-media-detail-facts dt{color:var(--k-text-muted)}.cms-media-detail-facts dd{color:var(--k-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-media-detail-facts dd.is-mono{font-family:var(--k-font-mono);font-size:.75rem;line-height:1.6}@keyframes cms-float{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}.cms-brand-glyph{height:62%;width:62%}.cms-powered-by-link{color:var(--k-text);font-weight:500;text-decoration:none;transition:color var(--k-duration) var(--k-ease-out)}.cms-powered-by-link:hover{color:var(--k-accent)}.cms-search-option-icon{margin-top:.125rem;--k-icon-size:1rem;color:var(--k-text-dimmed);flex:none}.cms-search-option-text{display:flex;flex:1;flex-direction:column;gap:.125rem;min-width:0}.cms-search-option-head{align-items:center;display:flex;gap:.5rem;min-width:0}.cms-search-option-title{color:var(--k-text);font-weight:500}.cms-search-option-meta,.cms-search-option-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-search-option-meta{color:var(--k-text-dimmed);font-size:.75rem}.cms-search-snippet{display:-webkit-box;-webkit-line-clamp:2;overflow:hidden;-webkit-box-orient:vertical;color:var(--k-text-toned);font-size:.8125rem;line-height:1.45}.cms-search-mark{background:color-mix(in oklab,var(--k-warning) 26%,transparent);border-radius:2px;color:inherit}.cms-code-badge{letter-spacing:.02em}.cms-code-badge,.cms-locale-control{font-family:var(--k-font-mono);text-transform:uppercase}.cms-locale-control{letter-spacing:.04em}.cms-page{animation:k-enter .32s var(--k-ease-out) backwards;display:flex;flex-direction:column;gap:1.5rem;min-width:0}.cms-page.is-fill{flex:1;min-height:0}.cms-count{align-items:center;animation:k-fade .4s var(--k-ease) backwards;background:var(--k-fill);border-radius:var(--k-radius-sm);color:var(--k-text-muted);display:inline-flex;font-family:var(--k-font-mono);font-size:.75rem;font-variant-numeric:tabular-nums;height:1.375rem;padding-inline:.4375rem}.cms-toolbar{align-items:center;display:flex;flex-wrap:wrap;gap:.5rem 1rem}.cms-toolbar-search{flex:1;min-width:12rem}.cms-toolbar-actions{align-items:center;display:flex;flex-shrink:0;gap:.5rem;margin-left:auto}.cms-tree{overflow:hidden}.cms-tree-row{align-items:center;animation:k-row-in .36s var(--k-ease-out) backwards;animation-delay:var(--cms-row-delay,0s);color:inherit;display:flex;gap:.75rem;min-height:3.25rem;padding:.5rem 1rem;text-decoration:none;transition:background-color var(--k-duration) var(--k-ease)}.cms-tree-row+.cms-tree-row{border-top:1px solid var(--k-line)}.cms-tree-row:hover{background-color:var(--k-subtle)}.cms-tree-branch{flex-shrink:0;width:1rem;--k-icon-size:0.875rem;color:var(--k-text-dimmed);flex:none;transform:scaleY(-1) rotate(90deg)}.cms-tree-doc{--k-icon-size:1rem;background:var(--k-subtle);border-radius:var(--k-radius-sm);box-shadow:inset 0 0 0 1px var(--k-line);color:var(--k-text-muted);display:grid;flex:none;height:1.75rem;place-items:center;width:1.75rem}.cms-tree-text{display:flex;flex:1;flex-direction:column;min-width:0}.cms-tree-title{color:var(--k-text);font-size:.875rem;font-weight:500}.cms-tree-path,.cms-tree-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-tree-path{color:var(--k-text-dimmed);font-family:var(--k-font-mono);font-size:.71875rem}.cms-tree-meta{font-size:.75rem}.cms-tree-chevron,.cms-tree-meta{color:var(--k-text-dimmed);flex-shrink:0}.cms-tree-chevron{--k-icon-size:1rem;transition:transform var(--k-duration-lg) var(--k-ease-out),color var(--k-duration) var(--k-ease)}.cms-tree-row:hover .cms-tree-chevron{color:var(--k-text);transform:translateX(2px)}.cms-editor-dirty{color:var(--k-text-muted);font-size:.75rem;white-space:nowrap}.cms-editor-schedule-panel{display:flex;flex-direction:column;gap:.875rem;padding:.875rem;width:18rem}.cms-list-filters{animation:k-fade .3s var(--k-ease) backwards}.cms-list-filter-panel{padding:.75rem;width:18rem}.cms-confirm-groups{display:flex;flex-direction:column;gap:.875rem;max-height:min(50vh,24rem);overflow-y:auto}.cms-confirm-group{display:flex;flex-direction:column;gap:.375rem}.cms-confirm-group-title{color:var(--k-text-toned);font-family:var(--k-font-mono);font-size:.75rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-confirm-list{border:1px solid var(--k-line);border-radius:var(--k-radius-md);display:flex;flex-direction:column;list-style:none;margin:0;overflow:hidden;padding:0}.cms-confirm-list>li+li{border-top:1px solid var(--k-line)}.cms-confirm-link{color:inherit;display:flex;flex-direction:column;gap:.125rem;padding:.5rem .75rem;text-decoration:none;transition:background-color var(--k-duration) var(--k-ease)}.cms-confirm-link:hover{background:var(--k-subtle)}.cms-confirm-link-title{color:var(--k-text);font-size:.8125rem;font-weight:500}.cms-confirm-link-meta{color:var(--k-text-dimmed);font-family:var(--k-font-mono);font-size:.6875rem}.cms-import-file-name{color:var(--k-text-muted);font-size:.8125rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-import-title{display:block;max-width:14rem;overflow:hidden;text-overflow:ellipsis}.cms-import-list{display:flex;flex-direction:column;gap:.125rem;list-style:none;margin:0;padding:0}.cms-import-issues{color:var(--k-danger);font-size:.75rem;white-space:normal}.cms-import-ok{--k-icon-size:0.875rem;align-items:center;color:var(--k-success);display:inline-flex;font-size:.75rem;gap:.25rem}.cms-settings-hint{color:var(--k-text-muted);font-size:.8125rem;overflow:hidden;text-overflow:ellipsis}.cms-settings-status{color:var(--k-text-dimmed);flex:none;font-size:.75rem;padding-top:.25rem;transition:color var(--k-duration) var(--k-ease)}.cms-settings-status.is-saved{color:var(--k-success)}.cms-settings-status.is-error{color:var(--k-danger)}.cms-settings-entry{display:flex;flex:1;flex-direction:column;gap:1rem;min-height:100%}.cms-settings-entry>*{flex-shrink:0}.cms-settings-footer{display:flex;justify-content:flex-end;margin-top:auto;padding-top:.5rem}.cms-settings-subtitle{color:var(--k-text-muted);font-size:.75rem;font-weight:500;margin:.75rem 0 .375rem}.cms-settings-list{border:1px solid var(--k-line);border-radius:var(--k-radius-md);display:flex;flex-direction:column;list-style:none;margin:0;overflow:hidden;padding:0}.cms-settings-columns>.cms-settings-list{margin-top:.75rem}.cms-settings-item{--k-icon-size:1rem;align-items:center;background:var(--k-surface);display:flex;gap:.5rem;min-height:2.5rem;padding:.25rem .75rem;position:relative;transition:background-color var(--k-duration) var(--k-ease),opacity var(--k-duration) var(--k-ease)}.cms-settings-item+.cms-settings-item{border-top:1px solid var(--k-line)}.cms-settings-item.is-draggable{cursor:grab}.cms-settings-item.is-draggable:hover{background:var(--k-subtle)}.cms-settings-item.is-dragging{opacity:.4}.cms-settings-drop-end.is-over:before,.cms-settings-item.is-drop-before:before{background:var(--k-accent);border-radius:var(--k-radius-full);content:"";height:2px;left:.5rem;position:absolute;right:.5rem;top:-1px}.cms-settings-drop-end{height:.75rem;position:relative}.cms-settings-item.is-muted .cms-settings-item-label{color:var(--k-text-muted)}.cms-settings-grip,.cms-settings-item-icon{color:var(--k-text-dimmed);flex:none}.cms-settings-item-label{color:var(--k-text);flex:1;font-size:.8125rem;font-weight:500;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-layout-editor{display:flex;flex-direction:column;gap:.25rem}.cms-layout-areas{display:flex;flex-direction:column;margin-top:.5rem}.cms-layout-area{display:flex;flex-direction:column;gap:.5rem;min-width:0}.cms-layout-section{background:var(--k-subtle);border:1px dashed var(--k-line-strong);border-radius:var(--k-radius-md);display:flex;flex-direction:column;padding:.25rem .5rem}.cms-layout-section.is-titled{background:var(--k-surface);border-color:var(--k-line);border-style:solid}.cms-layout-section-title{align-items:center;color:var(--k-text);display:flex;font-size:.75rem;font-weight:600;gap:.5rem;padding:.375rem .125rem .125rem}.cms-layout-chip,.cms-layout-row{display:flex;gap:.375rem}.cms-layout-chip{--k-icon-size:0.875rem;align-items:center;background:var(--k-field);border:1px solid var(--k-field-line);border-radius:var(--k-radius-sm);box-shadow:var(--k-shadow-xs);cursor:grab;flex:1;height:2.125rem;min-width:0;padding:0 .5rem;position:relative;transition:border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration) var(--k-ease),opacity var(--k-duration) var(--k-ease)}.cms-layout-chip:hover{border-color:var(--k-line-strong)}.cms-layout-chip.is-dragging{opacity:.35}.cms-layout-chip.is-blocked{border-color:var(--k-danger);cursor:not-allowed}.cms-layout-chip.is-drop-after:after,.cms-layout-chip.is-drop-before:before{background:var(--k-accent);border-radius:var(--k-radius-full);bottom:.25rem;content:"";position:absolute;top:.25rem;width:2px}.cms-layout-chip.is-drop-before:before{left:-.25rem}.cms-layout-chip.is-drop-after:after{right:-.25rem}.cms-layout-chip-label{color:var(--k-text);flex:1;font-size:.75rem;font-weight:500;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-layout-chip-tab{background:var(--k-fill);border-radius:var(--k-radius-xs);color:var(--k-text-muted);flex:none;font-size:.625rem;line-height:1rem;padding:0 .3125rem}.cms-layout-gap{height:.375rem;position:relative;transition:height var(--k-duration) var(--k-ease)}.cms-layout-editor.is-dragging .cms-layout-gap{height:.75rem}.cms-layout-gap.is-over:before{background:var(--k-accent);border-radius:var(--k-radius-full);content:"";height:2px;left:0;margin-top:-1px;position:absolute;right:0;top:50%}.cms-layout-editor.is-dragging .cms-layout-gap.is-empty,.cms-layout-gap.is-empty{color:var(--k-text-dimmed);display:grid;font-size:.75rem;height:2.5rem;place-items:center}.cms-layout-empty{border:1px dashed var(--k-line-strong);border-radius:var(--k-radius-md);color:var(--k-text-dimmed);display:grid;font-size:.75rem;min-height:5rem;padding:1rem;place-items:center;text-align:center;transition:border-color var(--k-duration) var(--k-ease),background-color var(--k-duration) var(--k-ease)}.cms-layout-empty.is-over{background:var(--k-accent-soft);border-color:var(--k-accent);color:var(--k-accent-text)}.cms-credentials-alert{animation:k-enter var(--k-duration-lg) var(--k-ease-out) backwards}.cms-credentials-items{margin-top:.625rem}.cms-user-list{border:1px solid var(--k-line);border-radius:var(--k-radius-md);list-style:none;margin:0;overflow:hidden;padding:0}.cms-user-list,.cms-user-row{display:flex;flex-direction:column}.cms-user-row{animation:k-row-in .32s var(--k-ease-out) backwards;background:var(--k-surface)}.cms-user-row+.cms-user-row{border-top:1px solid var(--k-line)}.cms-user-main{align-items:center;display:flex;gap:.75rem;padding:.625rem .75rem}.cms-user-text{display:flex;flex:1;flex-direction:column;line-height:1.3;min-width:0}.cms-user-name{color:var(--k-text);font-size:.8125rem;font-weight:500}.cms-user-meta,.cms-user-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-user-meta{color:var(--k-text-dimmed);font-size:.75rem}.cms-user-reset{padding:0 .75rem .875rem}.cms-user-create{animation:k-enter var(--k-duration-lg) var(--k-ease-out) backwards}.cms-media-gallery{display:flex;flex-direction:column;gap:1.25rem;position:relative}.cms-media-gallery.is-compact{gap:1rem}.cms-media-toolbar{align-items:center;display:flex;flex-wrap:wrap;gap:.5rem}.cms-media-search{flex:1 1 16rem;min-width:0}.cms-media-source{color:var(--k-text-dimmed);font-size:.75rem;margin-top:-.75rem}.cms-media-hint{color:var(--k-text-dimmed);font-size:.8125rem}.cms-media-upload-hint{margin-top:.75rem;text-align:center}.cms-media-loading{align-items:center;animation:k-fade .3s var(--k-ease) .12s backwards;color:var(--k-text-dimmed);display:flex;flex:1;justify-content:center;padding-block:2.5rem}.cms-media-detail .cms-media-loading{justify-content:flex-start;padding-block:.5rem}.cms-media-nav{flex-wrap:wrap;justify-content:space-between;min-height:1.75rem}.cms-media-nav,.cms-media-progress{align-items:center;display:flex;gap:.5rem}.cms-media-progress{animation:k-enter var(--k-duration-lg) var(--k-ease-out) backwards;background:var(--k-accent-soft);border:1px solid var(--k-accent-line);border-radius:var(--k-radius-md);color:var(--k-accent-text);font-size:.8125rem;overflow:hidden;padding:.5rem .75rem;position:relative}.cms-media-selection-bar{top:.75rem}.cms-media-filter-row{align-items:center;display:flex;flex-wrap:wrap;gap:.375rem}.cms-media-section{display:flex;flex-direction:column;gap:.625rem}.cms-media-section-title{--k-icon-size:0.875rem;align-items:center;color:var(--k-text-muted);display:inline-flex;font-size:.75rem;font-weight:500;gap:.375rem}.cms-media-folders{display:grid;gap:.5rem;grid-template-columns:repeat(auto-fill,minmax(13rem,1fr))}.cms-media-gallery.is-compact .cms-media-folders{grid-template-columns:repeat(auto-fill,minmax(10rem,1fr))}.cms-media-folder-tile{align-items:center;background:var(--k-surface);border:1px solid var(--k-line);border-radius:var(--k-radius-lg);cursor:pointer;display:flex;gap:.75rem;min-width:0;padding:.625rem .75rem;text-align:left;transition:background-color var(--k-duration) var(--k-ease),border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration-lg) var(--k-ease),transform var(--k-duration-lg) var(--k-ease-out)}.cms-media-folder-tile:hover{border-color:var(--k-line-strong);box-shadow:var(--k-shadow-sm);transform:translateY(-1px)}.cms-media-folder-tile.is-drop{background:var(--k-accent-soft);border-color:var(--k-accent-line)}.cms-media-folder-tile-icon{box-sizing:content-box;padding:.4375rem;--k-icon-size:1.125rem;background:var(--k-accent-soft);border-radius:var(--k-radius-md);color:var(--k-accent-text);display:grid;flex:none;height:2rem;place-items:center;width:2rem}.cms-media-folder-tile-text{display:flex;flex-direction:column;min-width:0}.cms-media-folder-tile-name{color:var(--k-text);font-size:.8125rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-media-folder-tile-meta{color:var(--k-text-dimmed);font-size:.75rem}.cms-media-grid{display:grid;gap:.875rem;grid-template-columns:repeat(2,minmax(0,1fr))}@media (min-width:640px){.cms-media-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:1024px){.cms-media-grid:not(.is-compact){grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:1280px){.cms-media-grid:not(.is-compact){grid-template-columns:repeat(5,minmax(0,1fr))}}.cms-media-grid.is-recent{gap:.5rem;grid-template-columns:repeat(6,minmax(0,1fr))}.cms-media-tile{overflow:hidden;text-align:left;transition:border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration-lg) var(--k-ease),transform var(--k-duration-lg) var(--k-ease-out)}.cms-media-grid>.cms-media-tile{animation:k-row-in .38s var(--k-ease-out) backwards}.cms-media-grid.is-recent>.cms-media-tile{border-radius:var(--k-radius-md)}.cms-media-tile.is-selectable{cursor:pointer}.cms-media-tile.is-selectable:hover{transform:translateY(-2px)}.cms-media-tile.is-selectable:hover,.cms-media-tile.is-selectable:hover:not([aria-pressed=true]){border-color:var(--k-line-strong);box-shadow:var(--k-shadow-sm)}.cms-media-tile.is-dragging{opacity:.45}.cms-media-preview{--k-icon-size:2rem;align-items:center;aspect-ratio:1;background:var(--k-subtle);color:var(--k-text-dimmed);display:flex;justify-content:center;overflow:hidden;position:relative}.cms-media-grid.is-recent .cms-media-preview{--k-icon-size:1.5rem}.cms-media-preview>img,.cms-media-preview>video{height:100%;inset:0;-o-object-fit:cover;object-fit:cover;position:absolute;transition:transform .5s var(--k-ease-out),border-radius var(--k-duration-lg) var(--k-ease);width:100%}.cms-media-tile.is-selectable:hover:not([aria-pressed=true]) .cms-media-preview>img,.cms-media-tile.is-selectable:hover:not([aria-pressed=true]) .cms-media-preview>video{transform:scale(1.04)}.cms-media-tile[aria-pressed=true] .cms-media-preview>img,.cms-media-tile[aria-pressed=true] .cms-media-preview>video{border-radius:var(--k-radius-md);transform:scale(.94)}.cms-media-check{--k-icon-size:0.875rem;align-items:center;backdrop-filter:blur(4px);background:rgba(0,0,0,.3);border:1.5px solid hsla(0,0%,100%,.9);border-radius:var(--k-radius-full);color:transparent;cursor:pointer;display:flex;height:1.25rem;justify-content:center;left:.5rem;opacity:0;position:absolute;scale:.85;top:.5rem;transition:opacity var(--k-duration) var(--k-ease),scale var(--k-duration-lg) var(--k-ease-out),background-color var(--k-duration) var(--k-ease),border-color var(--k-duration) var(--k-ease),color var(--k-duration) var(--k-ease);width:1.25rem;z-index:1}.cms-media-check.is-on,.cms-media-check.is-visible,.cms-media-tile:focus-visible .cms-media-check,.cms-media-tile:hover .cms-media-check{opacity:1;scale:1}.cms-media-check.is-on{background:var(--k-accent);border-color:var(--k-accent);color:var(--k-accent-contrast)}.cms-media-info{background:linear-gradient(0deg,rgba(0,0,0,.7),transparent);bottom:0;color:#fff;font-family:var(--k-font-mono);font-size:.6875rem;left:0;letter-spacing:.02em;line-height:1.4;opacity:0;padding:1.75rem .625rem .5rem;pointer-events:none;position:absolute;right:0;text-transform:uppercase;transform:translateY(4px);transition:opacity var(--k-duration-lg) var(--k-ease),transform var(--k-duration-lg) var(--k-ease-out)}.cms-media-tile:focus-visible .cms-media-info,.cms-media-tile:hover .cms-media-info{opacity:1;transform:none}.cms-media-meta{border-top:1px solid var(--k-line);display:flex;flex-direction:column;gap:.25rem;padding:.5625rem .75rem}.cms-media-name{color:var(--k-text);font-size:.8125rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-media-folder{color:var(--k-text-dimmed);font-size:.75rem;font-weight:400;overflow:hidden;text-overflow:ellipsis}.cms-media-folder,.cms-media-usage-badge{--k-icon-size:0.75rem;align-items:center;display:inline-flex;gap:.25rem;white-space:nowrap}.cms-media-usage-badge{color:var(--k-accent-text);flex:none;font-size:.6875rem;font-weight:500}.cms-media-usage-badge.is-unused{color:var(--k-text-dimmed);font-weight:400}.cms-media-list{display:flex;flex-direction:column;overflow:hidden}.cms-media-row{align-items:center;animation:k-row-in .32s var(--k-ease-out) backwards;border:1px solid transparent;border-bottom:1px solid var(--k-line);cursor:pointer;display:flex;gap:.875rem;padding:.4375rem .875rem;transition:background-color var(--k-duration) var(--k-ease)}.cms-media-row:last-child{border-bottom-color:transparent}.cms-media-row:hover{background:var(--k-subtle)}.cms-media-row.is-checked{background:var(--k-accent-soft);border-color:var(--k-accent)}.cms-media-row.is-dragging{opacity:.45}.cms-media-row .cms-media-check{backdrop-filter:none;background:var(--k-field);border-color:var(--k-line-strong);border-radius:var(--k-radius-xs);flex:none;height:1rem;position:static;width:1rem}.cms-media-row .cms-media-check.is-on{background:var(--k-accent);border-color:var(--k-accent)}.cms-media-row-name{color:var(--k-text);display:flex;flex:1;flex-direction:column;font-size:.8125rem;font-weight:500;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-media-row-cell{color:var(--k-text-muted);flex:none;font-size:.75rem;font-variant-numeric:tabular-nums;text-align:right;width:5.5rem}.cms-media-row-cell.is-usage{width:7.5rem}.cms-media-row-cell.is-mono{color:var(--k-text-dimmed);font-family:var(--k-font-mono);font-size:.6875rem;text-transform:uppercase;width:3.5rem}@media (max-width:640px){.cms-media-row-cell.is-wide{display:none}.cms-media-grid.is-recent{grid-template-columns:repeat(3,minmax(0,1fr))}}.cms-media-pagination{justify-content:center}.cms-media-drop-overlay{--k-icon-size:2rem;align-items:center;animation:k-fade .16s var(--k-ease);backdrop-filter:blur(4px);background:color-mix(in oklab,var(--k-surface) 84%,transparent);border:1.5px dashed var(--k-accent);border-radius:var(--k-radius-xl);color:var(--k-text);display:flex;flex-direction:column;font-size:.875rem;gap:.5rem;inset:-.5rem;justify-content:center;pointer-events:none;position:absolute;z-index:10}.cms-media-drop-icon,.cms-media-drop-overlay strong{color:var(--k-accent-text)}.cms-media-dropzone-hint{--k-icon-size:0.875rem;align-items:center;color:var(--k-text-dimmed);display:inline-flex;font-size:.75rem;gap:.3rem}.cms-media-folder-picker{display:flex;flex-direction:column;gap:.5rem}.cms-media-folder-picker-list{background:var(--k-field);border:1px solid var(--k-field-line);border-radius:var(--k-radius-md);box-shadow:var(--k-shadow-xs);max-height:16rem;overflow-y:auto;padding:.25rem}.cms-media-detail{display:flex;flex-direction:column;gap:1.5rem}.cms-media-detail-preview{--k-icon-size:3rem;align-items:center;background:repeating-conic-gradient(var(--k-subtle) 0 25%,var(--k-surface) 0 50%) 50% /1.25rem 1.25rem;border:1px solid var(--k-line);border-radius:var(--k-radius-lg);color:var(--k-text-dimmed);display:flex;justify-content:center;max-height:24rem;min-height:12rem;overflow:hidden}.cms-media-detail-preview>img,.cms-media-detail-preview>video{animation:k-fade .3s var(--k-ease);max-height:24rem;max-width:100%;-o-object-fit:contain;object-fit:contain}.cms-media-detail-facts{background:var(--k-subtle);border:1px solid var(--k-line);border-radius:var(--k-radius-lg);display:grid;font-size:.8125rem;gap:.5rem 1.5rem;grid-template-columns:max-content minmax(0,1fr);padding:.125rem 1rem}.cms-media-detail-fact{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-media-detail-fact.k-mono{font-size:.75rem;line-height:1.6}.cms-media-detail-usage{display:flex;flex-direction:column;gap:.625rem}.cms-media-usage-list{border:1px solid var(--k-line);border-radius:var(--k-radius-md);display:flex;flex-direction:column;overflow:hidden}.cms-media-usage-list li+li{border-top:1px solid var(--k-line)}.cms-media-usage-link{display:flex;flex-direction:column;gap:.125rem;padding:.5rem .75rem;transition:background-color var(--k-duration) var(--k-ease)}.cms-media-usage-link:hover{background:var(--k-subtle)}.cms-media-usage-title{color:var(--k-text);font-size:.8125rem;font-weight:500}.cms-media-usage-meta{color:var(--k-text-dimmed);font-family:var(--k-font-mono);font-size:.6875rem}.cms-media-single{max-width:15rem;overflow:hidden;transition:border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration-lg) var(--k-ease);width:100%}.cms-media-single:hover{border-color:var(--k-line-strong);box-shadow:var(--k-shadow-sm)}.cms-media-single.is-missing{border-color:color-mix(in oklab,var(--k-warning) 55%,transparent)}.cms-media-single-preview{--k-icon-size:1.75rem;align-items:center;aspect-ratio:4/3;background:var(--k-subtle);color:var(--k-text-dimmed);cursor:pointer;display:flex;justify-content:center;overflow:hidden;position:relative;width:100%}.cms-media-single-preview>img,.cms-media-single-preview>video{height:100%;inset:0;-o-object-fit:cover;object-fit:cover;position:absolute;transition:transform .5s var(--k-ease-out);width:100%}.cms-media-single:hover .cms-media-single-preview>img,.cms-media-single:hover .cms-media-single-preview>video{transform:scale(1.04)}.cms-media-single-bar{align-items:center;border-top:1px solid var(--k-line);display:flex;gap:.25rem;padding:.3125rem}.cms-media-single-name{color:var(--k-text-toned);flex:1;font-size:.75rem;font-weight:500;overflow:hidden;padding-left:.25rem;text-overflow:ellipsis;white-space:nowrap}.cms-media-single-add{--k-icon-size:1.25rem;align-items:center;background:var(--k-subtle);border:1px dashed var(--k-line-strong);border-radius:var(--k-radius-lg);color:var(--k-text-muted);cursor:pointer;display:flex;flex-direction:column;font-size:.8125rem;font-weight:500;gap:.375rem;justify-content:center;max-width:15rem;min-height:6rem;transition:border-color var(--k-duration) var(--k-ease),background-color var(--k-duration) var(--k-ease),color var(--k-duration) var(--k-ease);width:100%}.cms-media-single-add:hover{background:var(--k-accent-soft);border-color:var(--k-accent-line);color:var(--k-accent-text)}.cms-media-missing{--k-icon-size:1rem;align-items:center;color:var(--k-warning);display:flex;font-size:.75rem;gap:.375rem}.cms-media-thumb{background:var(--k-subtle);border-radius:var(--k-radius-sm);box-shadow:inset 0 0 0 1px var(--k-line);height:2rem;-o-object-fit:cover;object-fit:cover;width:2rem}.cms-media-thumb.is-fallback{--k-icon-size:1rem;align-items:center;color:var(--k-text-dimmed);display:flex;flex:none;justify-content:center}.cms-media-thumb-empty{--k-icon-size:1rem;color:var(--k-text-dimmed);display:inline-flex}.cms-form{container-type:inline-size}.cms-form,.cms-form-main,.cms-form-rows{display:flex;flex-direction:column;gap:1.375rem}.cms-form-main,.cms-form-rows{min-width:0}.cms-form-row{display:grid;gap:1.375rem 1rem;grid-template-columns:minmax(0,1fr)}@container (min-width: 32rem){.cms-form-row{grid-template-columns:repeat(var(--cms-row-cols,1),minmax(0,1fr))}}.cms-form-section-body{border-top:1px solid var(--k-line);padding:1rem 1rem 1.125rem}.cms-field-hint{color:var(--k-text-muted);font-size:.75rem;font-weight:400;line-height:1.45}.cms-search-focus{animation:cms-field-focus 2.4s var(--k-ease);border-radius:var(--k-radius-md)}@keyframes cms-field-focus{0%,60%{background:var(--k-accent-soft);box-shadow:0 0 0 6px var(--k-accent-soft)}to{background:transparent;box-shadow:0 0 0 6px transparent}}.cms-drawer-loading{min-height:12rem}.cms-block-editor-actions,.cms-drawer-actions{flex:1}.cms-blocks-grid{display:grid;gap:.75rem;grid-template-columns:repeat(2,minmax(0,1fr))}@media (min-width:640px){.cms-blocks-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:1024px){.cms-blocks-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}.cms-block-tile{background:var(--k-surface);border:1px solid var(--k-line);border-radius:var(--k-radius-lg);overflow:hidden;transition:opacity var(--k-duration) var(--k-ease),border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration-lg) var(--k-ease),transform var(--k-duration-lg) var(--k-ease-out)}.cms-block-tile:hover{border-color:var(--k-line-strong);box-shadow:var(--k-shadow-sm)}.cms-block-tile.is-muted{opacity:.45}.cms-block-tile.is-missing{border-color:color-mix(in oklab,var(--k-warning) 55%,transparent)}.cms-block-tile.is-dragging{opacity:.4;transform:scale(.98)}.cms-block-tile.is-drop-target{outline:2px solid var(--k-accent);outline-offset:2px}.cms-block-tile.is-media-only{cursor:grab}.cms-block-tile.is-media-only.is-dragging{cursor:grabbing}.cms-block-preview{align-items:center;aspect-ratio:4/3;background:var(--k-subtle);color:var(--k-text-dimmed);display:flex;justify-content:center;overflow:hidden;position:relative;width:100%}.cms-block-tile.is-media-only .cms-block-preview{aspect-ratio:1}.cms-block-preview>img,.cms-block-preview>video{height:100%;inset:0;-o-object-fit:cover;object-fit:cover;position:absolute;transition:transform .5s var(--k-ease-out);width:100%}.cms-block-tile:hover .cms-block-preview>img,.cms-block-tile:hover .cms-block-preview>video{transform:scale(1.03)}.cms-block-icon{--k-icon-size:1.75rem}.cms-block-summary{color:var(--k-text-muted);font-size:.75rem;line-height:1.5;padding:.75rem;text-align:left}.cms-block-hidden{--k-icon-size:1rem;color:#fff;filter:drop-shadow(0 1px 2px rgb(0 0 0/.6));left:.5rem;position:absolute;top:.5rem}.cms-block-missing,.cms-block-remove{--k-icon-size:0.875rem;border-radius:var(--k-radius-full);color:#fff;display:grid;height:1.5rem;place-items:center;position:absolute;width:1.5rem}.cms-block-missing{background:var(--k-warning);bottom:.375rem;left:.375rem}.cms-block-remove{backdrop-filter:blur(6px);background:rgba(0,0,0,.55);opacity:0;right:.375rem;scale:.85;top:.375rem;transition:opacity var(--k-duration) var(--k-ease),scale var(--k-duration-lg) var(--k-ease-out),background-color var(--k-duration) var(--k-ease);z-index:1}.cms-block-tile:focus-within .cms-block-remove,.cms-block-tile:hover .cms-block-remove{opacity:1;scale:1}.cms-block-remove:hover{background:var(--k-danger)}@media (hover:none){.cms-block-remove{opacity:1;scale:1}}.cms-block-bar{--k-icon-size:1rem;border-top:1px solid var(--k-line);gap:.25rem;padding:.3125rem}.cms-block-bar,.cms-block-grip{align-items:center;display:flex}.cms-block-grip{border-radius:var(--k-radius-xs);color:var(--k-text-dimmed);cursor:grab;justify-content:center;padding:.25rem;transition:color var(--k-duration) var(--k-ease),background-color var(--k-duration) var(--k-ease)}.cms-block-grip:hover{background:var(--k-hover);color:var(--k-text-muted)}.cms-block-tile.is-dragging .cms-block-grip{cursor:grabbing}.cms-block-bar-name{color:var(--k-text-toned);flex:1;font-size:.75rem;font-weight:500;overflow:hidden;padding-left:.25rem;text-overflow:ellipsis;white-space:nowrap}.cms-block-missing-icon{color:var(--k-warning);display:flex}.cms-block-add{--k-icon-size:1.25rem;align-items:center;background:var(--k-subtle);border:1px dashed var(--k-line-strong);border-radius:var(--k-radius-lg);color:var(--k-text-muted);display:flex;flex-direction:column;font-size:.8125rem;font-weight:500;gap:.375rem;justify-content:center;min-height:6rem;transition:border-color var(--k-duration) var(--k-ease),background-color var(--k-duration) var(--k-ease),color var(--k-duration) var(--k-ease);width:100%}.cms-block-add:hover:not(:disabled){background:var(--k-accent-soft);border-color:var(--k-accent-line);color:var(--k-accent-text)}.cms-block-add:disabled{cursor:not-allowed;opacity:.55}.cms-editor{background:var(--k-canvas);display:flex;flex-direction:column;height:100dvh}.cms-editor-modal .cms-editor{height:100%}.cms-editor-bar{align-items:center;background:var(--k-surface);border-bottom:1px solid var(--k-line);display:grid;gap:.75rem;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);min-height:3.25rem;padding:.5rem .75rem}.cms-editor-bar-center,.cms-editor-bar-end,.cms-editor-bar-start,.cms-editor-heading{align-items:center;display:flex;min-width:0}.cms-editor-bar-start{gap:.375rem}.cms-editor-heading{gap:.625rem}.cms-editor-bar-center{gap:.5rem;justify-content:center}.cms-editor-bar-end{gap:.375rem;justify-content:flex-end}.cms-editor-title{color:var(--k-text);font-size:.875rem;font-weight:600;letter-spacing:-.005em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-editor-body{display:flex;flex:1;min-height:0}.cms-editor-canvas{display:flex;flex:1;justify-content:center;min-width:0;overflow:auto;padding:1rem}.cms-editor-frame{background:#fff;border-radius:var(--k-radius-lg);box-shadow:var(--k-shadow-raised);height:100%;overflow:hidden;transition:width var(--k-duration-lg) var(--k-ease-out);width:100%}.cms-editor-frame.is-mobile{flex:none;max-width:100%;width:390px}.cms-editor-iframe{border:0;display:block;height:100%;width:100%}.cms-editor-panel{background:var(--k-surface);border-left:1px solid var(--k-line);display:flex;flex-direction:column;flex-shrink:0;min-height:0;width:22rem}.cms-editor-inspector{gap:0}.cms-editor-inspector,.cms-editor-panel-body{display:flex;flex:1;flex-direction:column;min-height:0}.cms-editor-panel-body{container-type:inline-size;gap:1rem;overflow-y:auto;padding:.875rem}.cms-editor-fields{display:flex;flex-direction:column;gap:1.125rem}.cms-editor-section-title{border-top:1px solid var(--k-line);display:flex;flex-direction:column;gap:.25rem;padding-top:.75rem}.cms-editor-section-title:first-child{border-top:0;padding-top:0}.cms-editor-block-head{align-items:center;display:flex;justify-content:space-between;margin:-.25rem -.25rem 0}.cms-editor-block-position{color:var(--k-text-dimmed);font-family:var(--k-font-mono);font-size:.6875rem}.cms-editor-block-title{--k-icon-size:1rem;align-items:center;color:var(--k-text);display:flex;font-size:.9375rem;font-weight:600;gap:.5rem}.cms-editor-block-actions{border-bottom:1px solid var(--k-line);display:flex;flex-wrap:wrap;gap:.375rem;padding-bottom:1rem}.cms-outline-text{display:flex;flex:1;flex-direction:column;gap:.125rem;min-width:0}.cms-outline-text.is-hidden{opacity:.55}.cms-outline-label{color:var(--k-text);font-size:.8125rem;font-weight:500}.cms-outline-label,.cms-outline-summary{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-outline-summary{color:var(--k-text-muted);font-size:.75rem}.cms-outline-hidden{--k-icon-size:1rem;color:var(--k-text-dimmed)}.cms-palette{display:grid;gap:.375rem}.cms-palette-item{align-items:flex-start;background:var(--k-surface);border:1px solid var(--k-line);border-radius:var(--k-radius-lg);display:flex;gap:.625rem;padding:.625rem;text-align:left;transition:background-color var(--k-duration) var(--k-ease),border-color var(--k-duration) var(--k-ease)}.cms-palette-item:hover{background:var(--k-accent-soft);border-color:var(--k-accent-line)}.cms-palette-icon{--k-icon-size:1rem;align-items:center;background:var(--k-fill);border-radius:var(--k-radius-md);color:var(--k-text-toned);display:flex;flex-shrink:0;height:2rem;justify-content:center;width:2rem}.cms-palette-item:hover .cms-palette-icon{color:var(--k-accent-text)}.cms-palette-text{display:flex;flex-direction:column;gap:.1875rem;min-width:0;padding-top:.0625rem}.cms-palette-label{color:var(--k-text);font-size:.8125rem;font-weight:600}.cms-palette-description{color:var(--k-text-muted);font-size:.75rem;line-height:1.4}@media (max-width:767px){.cms-editor-bar{grid-template-columns:minmax(0,1fr) auto}.cms-editor-bar-center{grid-column:1/-1;grid-row:2}.cms-editor-body{flex-direction:column}.cms-editor-canvas{flex:0 0 50%;padding:.5rem}.cms-editor-panel{border-left:0;border-top:1px solid var(--k-line);flex:1;width:auto}}
1
+ .cms-block-tree-add,.cms-block-tree-label,.cms-block-tree-summary,.cms-confirm-group-title,.cms-editor-address-path,.cms-icon-hint,.cms-layout-chip-label,.cms-media-name,.cms-tile-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cms-media-grid.is-recent .cms-media-tile{border-radius:var(--k-radius-md)}.cms-code{font-family:var(--k-font-mono);letter-spacing:.02em;text-transform:uppercase}.cms-list-loading{padding:1rem 1.125rem}.cms-editor-address-path{flex:1;font-size:.8125rem;min-width:0}.cms-editor-address-path.is-empty{color:var(--k-text-muted)}.cms-confirm-group-title{color:var(--k-text-toned);font-weight:500}.cms-import-title{display:block;max-width:14rem;overflow:hidden;text-overflow:ellipsis}.cms-import-issues{white-space:normal}.cms-settings-entry{display:flex;flex:1;flex-direction:column;gap:1rem;min-height:100%}.cms-settings-entry>*{flex-shrink:0}.cms-settings-grip,.cms-settings-item-icon{color:var(--k-text-dimmed);flex:none}.cms-layout-editor{display:flex;flex-direction:column;gap:.25rem}.cms-layout-areas{display:flex;flex-direction:column;margin-top:.5rem}.cms-layout-area{display:flex;flex-direction:column;gap:.5rem;min-width:0}.cms-layout-section{background:var(--k-subtle);border:1px dashed var(--k-line-strong);border-radius:var(--k-radius-md);display:flex;flex-direction:column;padding:.25rem .5rem}.cms-layout-section.is-titled{background:var(--k-surface);border-color:var(--k-line);border-style:solid}.cms-layout-section-title{align-items:center;color:var(--k-text);display:flex;font-size:.75rem;font-weight:600;gap:.5rem;padding:.375rem .125rem .125rem}.cms-layout-chip,.cms-layout-row{display:flex;gap:.375rem}.cms-layout-chip{--k-icon-size:0.875rem;align-items:center;background:var(--k-field);border:1px solid var(--k-field-line);border-radius:var(--k-radius-sm);box-shadow:var(--k-shadow-xs);cursor:grab;flex:1;height:2.125rem;min-width:0;padding:0 .5rem;position:relative;transition:border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration) var(--k-ease),opacity var(--k-duration) var(--k-ease)}.cms-layout-chip:hover{border-color:var(--k-line-strong)}.cms-layout-chip.is-dragging{opacity:.35}.cms-layout-chip.is-blocked{border-color:var(--k-danger);cursor:not-allowed}.cms-layout-chip.is-drop-after:after,.cms-layout-chip.is-drop-before:before{background:var(--k-accent);border-radius:var(--k-radius-full);bottom:.25rem;content:"";position:absolute;top:.25rem;width:2px}.cms-layout-chip.is-drop-before:before{left:-.25rem}.cms-layout-chip.is-drop-after:after{right:-.25rem}.cms-layout-chip-label{color:var(--k-text);flex:1;font-size:.75rem;font-weight:500;min-width:0}.cms-layout-chip-tab{background:var(--k-fill);border-radius:var(--k-radius-xs);color:var(--k-text-muted);flex:none;font-size:.625rem;line-height:1rem;padding:0 .3125rem}.cms-layout-gap{height:.375rem;position:relative;transition:height var(--k-duration) var(--k-ease)}.cms-layout-editor.is-dragging .cms-layout-gap{height:.75rem}.cms-layout-gap.is-over:before{background:var(--k-accent);border-radius:var(--k-radius-full);content:"";height:2px;left:0;margin-top:-1px;position:absolute;right:0;top:50%}.cms-layout-editor.is-dragging .cms-layout-gap.is-empty,.cms-layout-gap.is-empty{color:var(--k-text-dimmed);display:grid;font-size:.75rem;height:2.5rem;place-items:center}.cms-media-gallery{position:relative}.cms-media-files-fill{min-height:20rem}.cms-media-search{flex:1 1 16rem;min-width:0}.cms-media-selection-bar{top:.75rem}.cms-media-tile{overflow:hidden;text-align:left}.cms-media-meta{border-top:1px solid var(--k-line);display:flex;flex-direction:column;gap:.25rem;padding:.5625rem .75rem}.cms-media-name{color:var(--k-text);font-size:.8125rem;font-weight:500}.cms-icon-hint{--k-icon-size:0.75rem;display:inline-flex;font-size:.75rem;gap:.25rem}.cms-icon-hint,.cms-media-detail-preview{align-items:center;color:var(--k-text-dimmed)}.cms-media-detail-preview{--k-icon-size:3rem;background:repeating-conic-gradient(var(--k-subtle) 0 25%,var(--k-surface) 0 50%) 50% /1.25rem 1.25rem;border:1px solid var(--k-line);border-radius:var(--k-radius-lg);display:flex;justify-content:center;max-height:24rem;min-height:12rem;overflow:hidden}.cms-media-detail-preview>video{max-height:24rem;max-width:100%;-o-object-fit:contain;object-fit:contain}.cms-media-single,.cms-media-single-add{max-width:15rem;width:100%}.cms-media-single{overflow:hidden;transition:border-color var(--k-duration) var(--k-ease),box-shadow var(--k-duration-lg) var(--k-ease)}.cms-media-single:hover:not(.is-disabled){border-color:var(--k-line-strong);box-shadow:var(--k-shadow-sm)}.cms-media-thumb-empty{--k-icon-size:1rem;color:var(--k-text-dimmed);display:inline-flex}.cms-form{container-type:inline-size;display:flex;flex-direction:column;gap:1.375rem}.cms-block-editor-actions{flex:1}.cms-block-tile{overflow:hidden}.cms-block-tile.is-muted{opacity:.45}.cms-block-tile.is-missing{border-color:color-mix(in oklab,var(--k-warning) 55%,transparent)}.cms-block-tile.is-invalid{border-color:var(--k-danger)}.cms-block-summary{color:var(--k-text-muted);font-size:.75rem;line-height:1.5;padding:.75rem;text-align:left}.cms-tile-preview{display:block;width:100%}.cms-tile-bar{--k-icon-size:1rem;align-items:center;border-top:1px solid var(--k-line);display:flex;gap:.25rem;padding:.3125rem}.cms-tile-name{color:var(--k-text-toned);flex:1;font-size:.75rem;font-weight:500;padding-left:.25rem}.cms-block-missing-icon{color:var(--k-warning);display:flex}.cms-editor-modal{--k-workspace-height:100%}.cms-editor-tree{display:flex;flex-direction:column;gap:.5rem;padding:.5rem}.cms-editor-canvas-bar{align-items:center;display:grid;flex:1;gap:.5rem;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);justify-items:start}.cms-editor-canvas-toggle.is-end{grid-column:3;justify-self:end}.cms-editor-canvas-tools{align-items:center;display:flex;gap:.5rem;grid-column:2}.cms-editor-width{color:var(--k-text-muted);font-family:var(--k-font-mono);font-size:.6875rem;font-variant-numeric:tabular-nums;min-width:4.5ch;text-align:right;white-space:nowrap}.cms-editor-stage{display:flex;flex:1;justify-content:center;min-height:0;overflow:auto;padding:.75rem 1rem 1rem}.cms-editor-stage.is-compact{padding:.5rem}.cms-editor-frame{background:#fff;border-radius:var(--k-radius-lg);box-shadow:var(--k-shadow-raised);height:100%;overflow:hidden;transition:width var(--k-duration-lg) var(--k-ease-out);width:100%}.cms-editor-frame.is-fixed{flex:none;max-width:100%}.cms-editor-iframe{border:0;display:block;height:100%;width:100%}.cms-editor-inspector,.cms-editor-tabs{display:flex;flex:1;flex-direction:column;min-height:0}.cms-editor-tabs{gap:0}.cms-editor-panel-body{container-type:inline-size;display:flex;flex:1;flex-direction:column;gap:1rem;min-height:0;overflow-y:auto;padding:.875rem}.cms-editor-panel-body.is-empty{justify-content:center}.cms-block-tree,.cms-block-tree-text{display:flex;flex-direction:column}.cms-block-tree-text{gap:.0625rem;min-width:0}.cms-block-tree-label{font-size:.8125rem;font-weight:500}.cms-block-tree-summary{color:var(--k-text-muted);font-size:.75rem}.cms-block-tree-hidden{--k-icon-size:0.875rem;color:var(--k-text-dimmed)}.cms-block-tree-text.is-group .cms-block-tree-label{color:var(--k-text-muted);font-size:.75rem;font-weight:600}.cms-block-tree-add{color:var(--k-text-muted);font-size:.8125rem}.cms-link-input{flex:1 1 16rem;min-width:0}.cms-link-label{flex:1 1 14rem;min-width:0}
@@ -1,7 +1,18 @@
1
1
  import { spawn } from "node:child_process";
2
- import { existsSync } from "node:fs";
2
+ import { existsSync, readFileSync } from "node:fs";
3
3
  import { createRequire } from "node:module";
4
- import { dirname, join } from "node:path";
4
+ import { dirname, isAbsolute, join, resolve } from "node:path";
5
+ import { MIGRATION_FIXES_FILE, fixNewMigrations, migrationSqlFiles } from "./shared/migrations-dir.js";
6
+ function readMigrationFixes(configPath, root) {
7
+ const path = join(dirname(configPath), MIGRATION_FIXES_FILE);
8
+ if (!existsSync(path)) return null;
9
+ try {
10
+ const fixes = JSON.parse(readFileSync(path, "utf8"));
11
+ return { ...fixes, out: isAbsolute(fixes.out) ? fixes.out : resolve(root, fixes.out) };
12
+ } catch {
13
+ return null;
14
+ }
15
+ }
5
16
  export async function generateMigrations(opts = {}) {
6
17
  const root = opts.root ?? process.cwd();
7
18
  const configPath = opts.configPath ?? join(root, ".nuxt/cms/drizzle.config.ts");
@@ -10,6 +21,8 @@ export async function generateMigrations(opts = {}) {
10
21
  `[nuxt-cms] drizzle config not found at ${configPath}. Run \`nuxi prepare\` first.`
11
22
  );
12
23
  }
24
+ const fixes = readMigrationFixes(configPath, root);
25
+ const before = fixes ? migrationSqlFiles(fixes.out) : [];
13
26
  const require = createRequire(import.meta.url);
14
27
  const bin = join(dirname(require.resolve("drizzle-kit")), "bin.cjs");
15
28
  const code = await new Promise((done) => {
@@ -19,4 +32,5 @@ export async function generateMigrations(opts = {}) {
19
32
  }).on("close", (c) => done(c ?? 1)).on("error", () => done(1));
20
33
  });
21
34
  if (code !== 0) throw new Error(`[nuxt-cms] drizzle-kit generate failed (exit ${code})`);
35
+ if (fixes) fixNewMigrations(fixes.out, before, fixes.uniqueTextColumns, fixes.dialect);
22
36
  }
@@ -12,7 +12,7 @@ import {
12
12
  import { listOrderBy, listWhere, readListFilters } from "../utils/list-query.js";
13
13
  import { decodeRows, getContentI18n, getRegistryEntry } from "../utils/registry.js";
14
14
  import { attachManyToMany } from "../utils/relations.js";
15
- import { requireAdmin } from "../utils/require-admin.js";
15
+ import { assertCmsPermission, requireCmsAccess } from "../utils/permissions.js";
16
16
  import { chunks, KEY_CHUNK } from "../utils/write-statements.js";
17
17
  const querySchema = z.object({
18
18
  format: z.enum(TRANSFER_FORMATS).default("json"),
@@ -21,11 +21,12 @@ const querySchema = z.object({
21
21
  order: z.enum(["asc", "desc"]).default("desc")
22
22
  });
23
23
  export default defineEventHandler(async (event) => {
24
- await requireAdmin(event);
24
+ const { access } = await requireCmsAccess(event);
25
25
  const { name, entry, table } = getRegistryEntry(event);
26
26
  if (!isCollectionKind(entry)) {
27
27
  throw createError({ statusCode: 405, statusMessage: "Only collections can be exported" });
28
28
  }
29
+ assertCmsPermission(access, `${name}.export`);
29
30
  const { format, search, sort, order } = await getValidatedQuery(event, querySchema.parse);
30
31
  if (format === "csv" && !canTransferCsv(entry)) {
31
32
  throw createError({