@riducms/admin 0.2.2 → 0.3.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 (352) hide show
  1. package/THIRD_PARTY_NOTICES.md +60 -37
  2. package/package.json +27 -15
  3. package/src/app/admin-core-view-route.svelte +38 -53
  4. package/src/app/admin-extension-route.svelte +19 -0
  5. package/src/app/admin-layout.scss +175 -0
  6. package/src/app/admin-layout.svelte +144 -410
  7. package/src/app/admin-navigation-progress.svelte +11 -77
  8. package/src/app/admin-page-title.svelte +17 -85
  9. package/src/app/admin-page-title.ts +136 -0
  10. package/src/app/admin-route-error.svelte +24 -0
  11. package/src/app/admin-router-provider.svelte +34 -0
  12. package/src/app/admin-router-root.svelte +41 -0
  13. package/src/app/admin-routes.svelte +56 -19
  14. package/src/app/loading-boundary.svelte +3 -1
  15. package/src/app-meta.ts +13 -0
  16. package/src/app.css +138 -496
  17. package/src/app.svelte +60 -26
  18. package/src/components/brand/ridu-logo.svelte +19 -5
  19. package/src/components/data/list-table.scss +63 -0
  20. package/src/components/icons/LICENSE.md +24 -0
  21. package/src/components/icons/chevron.svelte +8 -0
  22. package/src/components/icons/plus.svelte +12 -0
  23. package/src/components/icons/search.svelte +12 -0
  24. package/src/components/icons/x.svelte +8 -0
  25. package/src/components/json-tree/json-tree-node.svelte +61 -67
  26. package/src/components/json-tree/json-viewer.scss +153 -0
  27. package/src/components/json-tree/json-viewer.svelte +57 -96
  28. package/src/components/ui/banner/banner.scss +28 -0
  29. package/src/components/ui/banner/banner.svelte +9 -8
  30. package/src/components/ui/banner/index.ts +1 -5
  31. package/src/components/ui/code-editor/code-editor.scss +20 -0
  32. package/src/components/ui/code-editor/code-editor.svelte +71 -0
  33. package/src/components/ui/code-editor/code-editor.ts +151 -0
  34. package/src/components/ui/code-editor/code-languages.ts +29 -0
  35. package/src/components/ui/collapsible-panel/collapsible-panel.scss +38 -0
  36. package/src/components/ui/collapsible-panel/collapsible-panel.svelte +13 -0
  37. package/src/components/ui/collapsible-panel/index.ts +1 -0
  38. package/src/components/ui/combobox/combobox.scss +163 -0
  39. package/src/components/ui/combobox/index.ts +22 -0
  40. package/src/components/ui/date-value-control/date-value-calendar.svelte +128 -16
  41. package/src/components/ui/date-value-control/date-value-control-loader.scss +26 -0
  42. package/src/components/ui/date-value-control/date-value-control-loader.svelte +35 -13
  43. package/src/components/ui/date-value-control/date-value-control.scss +223 -0
  44. package/src/components/ui/date-value-control/date-value-control.svelte +62 -44
  45. package/src/components/ui/drawer/drawer-depth.ts +8 -0
  46. package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +2 -5
  47. package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +2 -5
  48. package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -2
  49. package/src/components/ui/dropdown-menu/dropdown-menu.scss +62 -0
  50. package/src/components/ui/kbd/kbd.scss +17 -0
  51. package/src/components/ui/kbd/kbd.svelte +3 -10
  52. package/src/components/ui/navigation-drawer/navigation-drawer.scss +40 -0
  53. package/src/components/ui/navigation-drawer/navigation-drawer.svelte +38 -0
  54. package/src/components/ui/popover/popover-content.svelte +3 -5
  55. package/src/components/ui/popover/popover.scss +18 -0
  56. package/src/components/ui/radio-group/index.ts +0 -1
  57. package/src/components/ui/radio-group/radio-card-item.svelte +7 -12
  58. package/src/components/ui/radio-group/radio-group.svelte +2 -2
  59. package/src/components/ui/radio-group/radio.scss +45 -0
  60. package/src/components/ui/select/select-content.svelte +5 -6
  61. package/src/components/ui/select/select-item.svelte +8 -8
  62. package/src/components/ui/select/select-scroll-down-button.svelte +3 -5
  63. package/src/components/ui/select/select-scroll-up-button.svelte +3 -5
  64. package/src/components/ui/select/select-trigger.svelte +6 -7
  65. package/src/components/ui/select/select.scss +126 -0
  66. package/src/components/ui/sheet/sheet-content.svelte +6 -34
  67. package/src/components/ui/sheet/sheet-description.svelte +2 -2
  68. package/src/components/ui/sheet/sheet-overlay.svelte +2 -21
  69. package/src/components/ui/sheet/sheet-title.svelte +2 -2
  70. package/src/components/ui/sheet/sheet.scss +221 -0
  71. package/src/components/ui/skeleton/skeleton.scss +20 -0
  72. package/src/components/ui/skeleton/skeleton.svelte +4 -16
  73. package/src/components/ui/sonner/sonner.scss +121 -0
  74. package/src/components/ui/sonner/sonner.svelte +11 -10
  75. package/src/components/ui/status-indicator/status-indicator.scss +48 -0
  76. package/src/components/ui/status-indicator/status-indicator.svelte +14 -14
  77. package/src/components/ui/tabs/tabs-content.svelte +2 -2
  78. package/src/components/ui/tabs/tabs-list.svelte +7 -7
  79. package/src/components/ui/tabs/tabs-trigger.svelte +2 -8
  80. package/src/components/ui/tabs/tabs.scss +86 -0
  81. package/src/components/ui/tabs/tabs.svelte +2 -2
  82. package/src/components/ui/timezone-picker/timezone-picker.svelte +152 -0
  83. package/src/core/api/admin-client.ts +2 -2
  84. package/src/core/bootstrap/admin-bootstrap.ts +396 -0
  85. package/src/core/bootstrap/admin-prepared-state.ts +213 -0
  86. package/src/core/bootstrap/admin-route-modules.ts +66 -0
  87. package/src/core/clipboard/copy-feedback.svelte.ts +43 -0
  88. package/src/core/forms/embedded-fields.ts +4 -8
  89. package/src/core/forms/field-editor-authoring.ts +8 -0
  90. package/src/core/forms/field-issue-focus.ts +4 -4
  91. package/src/core/forms/field-occurrence.ts +4 -7
  92. package/src/core/forms/form-controller.svelte.ts +14 -21
  93. package/src/core/forms/form-draft-recovery.ts +17 -4
  94. package/src/core/forms/form-issue-correlation.ts +13 -13
  95. package/src/core/forms/form-path.ts +17 -0
  96. package/src/core/forms/form-schema.ts +12 -43
  97. package/src/core/forms/form-validation.ts +7 -46
  98. package/src/core/forms/plugin-field-authoring.ts +6 -2
  99. package/src/core/forms/plugin-field-write.ts +2 -6
  100. package/src/core/i18n/admin-i18n.svelte.ts +18 -0
  101. package/src/core/i18n/format-admin-date-time.ts +19 -0
  102. package/src/core/i18n/humanize-identifier.ts +5 -0
  103. package/src/core/i18n/time-zone-label.ts +20 -0
  104. package/src/core/loaders/admin-view-host.svelte +72 -0
  105. package/src/core/loaders/admin-view-loader.svelte.ts +90 -0
  106. package/src/core/notifications/validation-toast.svelte +2 -2
  107. package/src/core/plugins/field-registry.ts +7 -8
  108. package/src/core/routing/admin-paths.ts +53 -2
  109. package/src/core/routing/admin-scroll.svelte.ts +74 -0
  110. package/src/core/routing/admin-view-selection.ts +78 -0
  111. package/src/core/runtime/admin-runtime.svelte.ts +121 -124
  112. package/src/core/schema/field-default.ts +33 -0
  113. package/src/core/schema/field-localization.ts +15 -0
  114. package/src/core/schema/read-document-path.ts +11 -0
  115. package/src/features/account/account-menu.scss +37 -0
  116. package/src/features/account/account-menu.svelte +115 -0
  117. package/src/features/{auth → account}/account-navigation.svelte +16 -19
  118. package/src/features/{auth → account}/account-route.svelte +206 -49
  119. package/src/features/account/account-security-controller.svelte.ts +157 -0
  120. package/src/features/{auth → account}/account-security-route.svelte +140 -42
  121. package/src/features/api-reference/api-reference-code.svelte +64 -0
  122. package/src/features/api-reference/api-reference-content.svelte +258 -0
  123. package/src/features/api-reference/api-reference-drawer.scss +74 -0
  124. package/src/features/api-reference/api-reference-examples.ts +381 -0
  125. package/src/features/api-reference/api-reference-schema.ts +332 -0
  126. package/src/features/api-reference/api-reference.scss +190 -0
  127. package/src/features/api-reference/api-reference.svelte +74 -0
  128. package/src/features/auth/auth-brand.svelte +5 -3
  129. package/src/features/auth/auth-field.svelte +92 -0
  130. package/src/features/auth/auth-frame.svelte +5 -8
  131. package/src/features/auth/auth.scss +122 -0
  132. package/src/features/auth/create-first-user-controller.svelte.ts +20 -51
  133. package/src/features/auth/create-first-user-route.svelte +83 -122
  134. package/src/features/auth/forgot-password-route.svelte +31 -23
  135. package/src/features/auth/login-route.svelte +68 -116
  136. package/src/features/auth/logout-button.scss +34 -0
  137. package/src/features/auth/logout-button.svelte +52 -0
  138. package/src/features/auth/request-verification-route.svelte +27 -22
  139. package/src/features/auth/reset-password-route.svelte +108 -41
  140. package/src/features/auth/verify-email-route.svelte +49 -15
  141. package/src/features/bulk-edit/bulk-edit-fields.ts +23 -0
  142. package/src/features/bulk-edit/bulk-edit.scss +152 -0
  143. package/src/features/bulk-edit/field-picker.svelte +176 -0
  144. package/src/features/collections/bulk/bulk-actions.svelte +148 -0
  145. package/src/features/collections/bulk/bulk-confirmation.svelte +153 -0
  146. package/src/features/collections/bulk/bulk-editor-loader.svelte +95 -0
  147. package/src/features/collections/bulk/bulk-editor.svelte +186 -0
  148. package/src/features/collections/collection-list-cell-values.ts +144 -0
  149. package/src/features/collections/collection-list-controller.svelte.ts +268 -379
  150. package/src/features/collections/collection-list-preferences-controller.svelte.ts +54 -40
  151. package/src/features/collections/collection-list-query.ts +223 -0
  152. package/src/features/collections/collection-list-results.svelte +205 -329
  153. package/src/features/collections/collection-list-route.svelte +143 -884
  154. package/src/features/collections/collection-list.scss +261 -0
  155. package/src/features/collections/collection-list.svelte.ts +362 -0
  156. package/src/features/collections/controls/column-picker.svelte +110 -0
  157. package/src/features/collections/controls/column-pill.svelte +62 -0
  158. package/src/features/collections/controls/filter-builder.svelte +193 -0
  159. package/src/features/collections/controls/filter-row.svelte +142 -0
  160. package/src/features/collections/controls/list-controls.scss +196 -0
  161. package/src/features/collections/controls/list-options.svelte +203 -0
  162. package/src/features/collections/controls/list-pagination.scss +78 -0
  163. package/src/features/collections/controls/list-pagination.svelte +115 -0
  164. package/src/features/collections/controls/list-toolbar.svelte +132 -0
  165. package/src/features/collections/controls/sort-heading.scss +52 -0
  166. package/src/features/collections/controls/sort-heading.svelte +78 -0
  167. package/src/features/collections/list-columns.ts +43 -0
  168. package/src/features/collections/list-workspace.ts +155 -54
  169. package/src/features/dashboard/dashboard-route.svelte +82 -86
  170. package/src/features/dashboard/dashboard.scss +131 -0
  171. package/src/features/development/development-tools.svelte +20 -36
  172. package/src/features/documents/document-action-bar.svelte +438 -0
  173. package/src/features/documents/document-api-view-loader.svelte +17 -6
  174. package/src/features/documents/document-api-view.scss +120 -0
  175. package/src/features/documents/document-api-view.svelte +169 -454
  176. package/src/features/documents/document-controller.svelte.ts +526 -613
  177. package/src/features/documents/document-credentials.scss +37 -0
  178. package/src/features/documents/document-credentials.svelte +72 -0
  179. package/src/features/documents/{document-route-dirty.ts → document-credentials.ts} +25 -0
  180. package/src/features/documents/document-field-sections.scss +39 -0
  181. package/src/features/documents/document-field-sections.svelte +4 -13
  182. package/src/features/documents/document-loading.scss +24 -0
  183. package/src/features/documents/document-lock-controller.svelte.ts +187 -0
  184. package/src/features/documents/document-operation-dialogs.svelte +110 -0
  185. package/src/features/documents/document-route-loader.svelte +17 -5
  186. package/src/features/documents/document-route.svelte +305 -811
  187. package/src/features/documents/document-schedule.scss +127 -0
  188. package/src/features/documents/document-schedule.svelte +323 -0
  189. package/src/features/documents/document-title.ts +25 -0
  190. package/src/features/documents/document.scss +274 -0
  191. package/src/features/documents/live-preview-panel.scss +117 -0
  192. package/src/features/documents/live-preview-panel.svelte +167 -168
  193. package/src/features/documents/live-preview.ts +2 -10
  194. package/src/features/documents/upload-document-preview-loader.svelte +26 -23
  195. package/src/features/localization/content-locale-switcher.scss +43 -0
  196. package/src/features/localization/content-locale-switcher.svelte +24 -17
  197. package/src/features/navigation/admin-breadcrumbs.scss +56 -0
  198. package/src/features/navigation/admin-breadcrumbs.svelte +102 -37
  199. package/src/features/navigation/admin-command-menu.svelte +38 -15
  200. package/src/features/navigation/admin-navigation.scss +133 -0
  201. package/src/features/navigation/admin-navigation.svelte +169 -0
  202. package/src/features/navigation/breadcrumb-context.svelte.ts +15 -0
  203. package/src/features/navigation/navigation-preference.svelte.ts +70 -0
  204. package/src/features/reference-browser/reference-browser-editor.svelte +180 -0
  205. package/src/features/reference-browser/reference-browser-list.scss +113 -0
  206. package/src/features/reference-browser/reference-browser-list.svelte +370 -0
  207. package/src/features/reference-browser/reference-browser-loader.svelte +26 -8
  208. package/src/features/reference-browser/reference-browser-workflow.svelte.ts +335 -236
  209. package/src/features/reference-browser/reference-browser.scss +217 -0
  210. package/src/features/reference-browser/reference-browser.svelte +154 -797
  211. package/src/features/reference-browser/reference-collection-picker.svelte +116 -0
  212. package/src/features/reference-browser/reference-list-query.ts +35 -0
  213. package/src/features/uploads/bulk-upload-controller.svelte.ts +604 -0
  214. package/src/features/uploads/bulk-upload-edit-all.svelte +92 -0
  215. package/src/features/uploads/bulk-upload-editor.svelte +191 -0
  216. package/src/features/uploads/bulk-upload-file-picker.svelte +70 -0
  217. package/src/features/uploads/bulk-upload-remote.svelte +100 -0
  218. package/src/features/uploads/bulk-upload-route-loader.svelte +54 -0
  219. package/src/features/uploads/bulk-upload-route.svelte +172 -592
  220. package/src/features/uploads/bulk-upload-sidebar.svelte +125 -0
  221. package/src/features/uploads/bulk-upload.scss +526 -0
  222. package/src/features/uploads/bulk-upload.ts +105 -14
  223. package/src/features/uploads/crop-surface.ts +150 -0
  224. package/src/features/uploads/image-editor.svelte +231 -0
  225. package/src/features/uploads/rendition-preview.svelte +64 -0
  226. package/src/features/uploads/upload-control.svelte +340 -0
  227. package/src/features/uploads/upload-document-contracts.ts +30 -0
  228. package/src/features/uploads/upload-draft.svelte.ts +294 -0
  229. package/src/features/uploads/upload-metadata-fields.scss +32 -0
  230. package/src/features/uploads/upload-metadata-fields.svelte +8 -7
  231. package/src/features/uploads/upload-thumbnail.svelte +47 -0
  232. package/src/features/uploads/upload.scss +361 -0
  233. package/src/features/versions/version-comparison.svelte +361 -0
  234. package/src/features/versions/version-diff-fields.svelte +136 -0
  235. package/src/features/versions/version-diff.ts +296 -41
  236. package/src/features/versions/version-history-controller.svelte.ts +311 -0
  237. package/src/features/versions/version-history-route-loader.svelte +32 -0
  238. package/src/features/versions/version-history-route.svelte +157 -522
  239. package/src/features/versions/version-history.scss +444 -0
  240. package/src/features/versions/version-history.ts +45 -0
  241. package/src/features/versions/version-table.svelte +91 -0
  242. package/src/fields/embedded-schema-draft-editor.scss +48 -0
  243. package/src/fields/embedded-schema-draft-editor.svelte +24 -16
  244. package/src/fields/field-collapsible.svelte +14 -8
  245. package/src/fields/field-layout.scss +171 -0
  246. package/src/fields/field-layout.svelte +3 -5
  247. package/src/fields/field-renderer.svelte +17 -29
  248. package/src/fields/field-shell.svelte +1 -1
  249. package/src/fields/field-tab-layout.svelte +25 -19
  250. package/src/fields/join/join-field-controller.svelte.ts +513 -0
  251. package/src/fields/join/join-field-values.ts +111 -0
  252. package/src/fields/join/join-field.scss +189 -0
  253. package/src/fields/join/join-field.svelte +164 -332
  254. package/src/fields/live-validation-feedback.svelte +4 -3
  255. package/src/fields/local-field-editor.svelte +2 -2
  256. package/src/fields/nested/block-name-input.svelte +11 -12
  257. package/src/fields/nested/block-picker.scss +128 -0
  258. package/src/fields/nested/block-picker.svelte +81 -0
  259. package/src/fields/nested/block-placeholder.svg +2 -0
  260. package/src/fields/nested/nested-field.scss +331 -0
  261. package/src/fields/nested/nested-field.svelte +265 -245
  262. package/src/fields/nested/sortable-row.svelte +9 -7
  263. package/src/fields/plugin-field.svelte +4 -6
  264. package/src/fields/point/point-field.svelte +51 -38
  265. package/src/fields/primitive-list/primitive-list-field.svelte +63 -19
  266. package/src/fields/primitive-list/primitive-list.scss +109 -0
  267. package/src/fields/radio/radio-field.svelte +2 -1
  268. package/src/fields/relationship/relationship-field-controller.svelte.ts +81 -41
  269. package/src/fields/relationship/relationship-field.svelte +144 -175
  270. package/src/fields/relationship/relationship-lookup-controller.svelte.ts +58 -30
  271. package/src/fields/relationship/relationship-query.ts +2 -10
  272. package/src/fields/relationship/relationship-quick-picker-controller.svelte.ts +36 -62
  273. package/src/fields/relationship/relationship-quick-picker.svelte +178 -227
  274. package/src/fields/relationship/relationship-selection.svelte +120 -0
  275. package/src/fields/relationship/relationship-value.ts +46 -7
  276. package/src/fields/relationship/relationship.scss +182 -0
  277. package/src/fields/scalar/code-field.svelte +101 -0
  278. package/src/fields/scalar/date-control-value.ts +13 -0
  279. package/src/fields/scalar/scalar-field.svelte +25 -67
  280. package/src/fields/select/select-field.svelte +132 -94
  281. package/src/fields/text/slug-field.scss +28 -0
  282. package/src/fields/text/slug-field.svelte +19 -15
  283. package/src/fields/text/text-field.svelte +1 -2
  284. package/src/fields/ui/ui-field.svelte +7 -4
  285. package/src/fields/virtual/virtual-field.svelte +2 -5
  286. package/src/index.ts +1 -2
  287. package/src/routing.ts +2 -0
  288. package/src/app/deferred-redirect.svelte +0 -23
  289. package/src/components/code-block/code-block.svelte +0 -107
  290. package/src/components/ui/bulk-action-bar/bulk-action-bar.svelte +0 -50
  291. package/src/components/ui/bulk-action-bar/index.ts +0 -1
  292. package/src/components/ui/button/index.ts +0 -8
  293. package/src/components/ui/calendar/calendar-caption.svelte +0 -72
  294. package/src/components/ui/calendar/calendar-cell.svelte +0 -20
  295. package/src/components/ui/calendar/calendar-day.svelte +0 -27
  296. package/src/components/ui/calendar/calendar-grid-row.svelte +0 -13
  297. package/src/components/ui/calendar/calendar-grid.svelte +0 -17
  298. package/src/components/ui/calendar/calendar-head-cell.svelte +0 -20
  299. package/src/components/ui/calendar/calendar-header.svelte +0 -20
  300. package/src/components/ui/calendar/calendar-heading.svelte +0 -17
  301. package/src/components/ui/calendar/calendar-month-select.svelte +0 -45
  302. package/src/components/ui/calendar/calendar-month.svelte +0 -16
  303. package/src/components/ui/calendar/calendar-months.svelte +0 -20
  304. package/src/components/ui/calendar/calendar-nav.svelte +0 -20
  305. package/src/components/ui/calendar/calendar-next-button.svelte +0 -30
  306. package/src/components/ui/calendar/calendar-prev-button.svelte +0 -30
  307. package/src/components/ui/calendar/calendar-year-select.svelte +0 -44
  308. package/src/components/ui/calendar/calendar.svelte +0 -118
  309. package/src/components/ui/calendar/index.ts +0 -1
  310. package/src/components/ui/checkbox/checkbox.svelte +0 -35
  311. package/src/components/ui/checkbox/index.ts +0 -1
  312. package/src/components/ui/dialog/dialog-close.svelte +0 -11
  313. package/src/components/ui/dialog/dialog-content.svelte +0 -52
  314. package/src/components/ui/dialog/dialog-description.svelte +0 -20
  315. package/src/components/ui/dialog/dialog-footer.svelte +0 -20
  316. package/src/components/ui/dialog/dialog-header.svelte +0 -20
  317. package/src/components/ui/dialog/dialog-overlay.svelte +0 -20
  318. package/src/components/ui/dialog/dialog-title.svelte +0 -17
  319. package/src/components/ui/dialog/dialog-trigger.svelte +0 -11
  320. package/src/components/ui/dialog/dialog.svelte +0 -7
  321. package/src/components/ui/dialog/index.ts +0 -8
  322. package/src/components/ui/empty-state/empty-state.svelte +0 -34
  323. package/src/components/ui/empty-state/index.ts +0 -1
  324. package/src/components/ui/input/index.ts +0 -1
  325. package/src/components/ui/pagination/index.ts +0 -1
  326. package/src/components/ui/pagination/pagination.svelte +0 -88
  327. package/src/components/ui/radio-group/radio-group-item.svelte +0 -17
  328. package/src/components/ui/slider/index.ts +0 -3
  329. package/src/components/ui/slider/slider-content.svelte +0 -59
  330. package/src/components/ui/slider/slider.svelte +0 -35
  331. package/src/components/ui/table/index.ts +0 -6
  332. package/src/components/ui/table/table-body.svelte +0 -20
  333. package/src/components/ui/table/table-cell.svelte +0 -23
  334. package/src/components/ui/table/table-head.svelte +0 -23
  335. package/src/components/ui/table/table-header.svelte +0 -20
  336. package/src/components/ui/table/table-row.svelte +0 -23
  337. package/src/components/ui/table/table.svelte +0 -22
  338. package/src/components/ui/textarea/index.ts +0 -1
  339. package/src/components/ui/tooltip/index.ts +0 -4
  340. package/src/components/ui/tooltip/tooltip-content.svelte +0 -50
  341. package/src/components/ui/tooltip/tooltip-provider.svelte +0 -7
  342. package/src/components/ui/tooltip/tooltip-trigger.svelte +0 -7
  343. package/src/components/ui/tooltip/tooltip.svelte +0 -7
  344. package/src/features/auth/account-menu.svelte +0 -159
  345. package/src/features/auth/account-security-controller.svelte.ts +0 -119
  346. package/src/features/collections/collection-list-bulk-actions.svelte +0 -143
  347. package/src/features/collections/collection-list-bulk-editor.svelte +0 -157
  348. package/src/features/collections/collection-list-filter-popover.svelte +0 -238
  349. package/src/features/collections/collection-list-workspace-toolbar.svelte +0 -409
  350. package/src/features/collections/collection-table-skeleton.svelte +0 -44
  351. package/src/features/documents/document-heading.ts +0 -20
  352. package/src/features/documents/upload-document-preview.svelte +0 -525
@@ -1,365 +1,197 @@
1
- <script module lang="ts">
2
- import type { AdminI18n } from "@riducms/plugin";
3
- interface JoinColumn {
4
- path: string;
5
- label: string;
6
- }
7
-
8
- function joinDocuments(value: unknown) {
9
- return Array.isArray(value)
10
- ? value.filter(
11
- (document): document is AdminDocument =>
12
- typeof document === "object" && document !== null && typeof document.id === "string"
13
- )
14
- : [];
15
- }
16
-
17
- function joinColumns(
18
- field: SchemaField,
19
- collection: SchemaCollection | undefined,
20
- i18n: AdminI18n
21
- ): JoinColumn[] {
22
- if (collection === undefined) return [{ path: "id", label: i18n.t("fields:id") }];
23
- const configured = field.join?.defaultColumns ?? collection.admin.defaultColumns ?? [];
24
- const fallback =
25
- collection.admin.useAsTitle ??
26
- collection.fields.find((candidate) => candidate.type === "text")?.path ??
27
- "id";
28
- const paths = configured.length > 0 ? configured : [fallback, "updatedAt"];
29
- return paths.map((path) => ({
30
- path,
31
- label:
32
- collection.fields.find((candidate) => candidate.path === path)?.admin.label ??
33
- systemColumnLabel(path, i18n) ??
34
- humanize(path, i18n.language),
35
- }));
36
- }
37
-
38
- function joinDefaultValues(path: string, id: string) {
39
- const values: Record<string, unknown> = {};
40
- writePath(values, path, id);
41
- return values;
42
- }
43
-
44
- function writePath(values: Record<string, unknown>, path: string, value: unknown) {
45
- const segments = path.split(".").filter(Boolean);
46
- let current = values;
47
- for (const segment of segments.slice(0, -1)) {
48
- const existing = current[segment];
49
- if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
50
- current = existing as Record<string, unknown>;
51
- } else {
52
- const nested: Record<string, unknown> = {};
53
- current[segment] = nested;
54
- current = nested;
55
- }
56
- }
57
- const last = segments.at(-1);
58
- if (last !== undefined) current[last] = value;
59
- }
60
-
61
- function readPath(value: unknown, path: string): unknown {
62
- let current = value;
63
- for (const segment of path.split(".")) {
64
- if (typeof current !== "object" || current === null || Array.isArray(current))
65
- return undefined;
66
- current = (current as Record<string, unknown>)[segment];
67
- }
68
- return current;
69
- }
70
-
71
- function displayValue(value: unknown, i18n: AdminI18n): string {
72
- if (value === null || value === undefined || value === "") return "—";
73
- if (typeof value === "boolean") return i18n.t(value ? "general:yes" : "general:no");
74
- if (typeof value === "number") return i18n.formatNumber(value);
75
- if (typeof value === "object") {
76
- if (Array.isArray(value)) return i18n.t("fields:itemCount", { count: value.length });
77
- const record = value as Record<string, unknown>;
78
- return String(
79
- record.title ?? record.name ?? record.email ?? record.id ?? i18n.t("fields:relatedDocument")
80
- );
81
- }
82
- if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
83
- const date = new Date(value);
84
- if (!Number.isNaN(date.valueOf())) return i18n.formatDate(date, { dateStyle: "medium" });
85
- }
86
- return String(value);
87
- }
88
-
89
- function documentLabel(document: AdminDocument) {
90
- return String(document.title ?? document.name ?? document.email ?? document.id);
91
- }
92
-
93
- function sortDocuments(documents: readonly AdminDocument[], sort: string, i18n: AdminI18n) {
94
- if (sort === "") return [...documents];
95
- const descending = sort.startsWith("-");
96
- const path = descending ? sort.slice(1) : sort;
97
- return [...documents].sort((left, right) => {
98
- const leftValue = displayValue(readPath(left, path), i18n);
99
- const rightValue = displayValue(readPath(right, path), i18n);
100
- const comparison = leftValue.localeCompare(rightValue, i18n.language, { numeric: true });
101
- return descending ? -comparison : comparison;
102
- });
103
- }
104
-
105
- function humanize(value: string, language: string) {
106
- return value
107
- .split(".")
108
- .at(-1)!
109
- .replace(/([a-z\d])([A-Z])/g, "$1 $2")
110
- .replaceAll(/[_-]+/g, " ")
111
- .replace(/\b\w/g, (letter) => letter.toLocaleUpperCase(language));
112
- }
113
-
114
- function systemColumnLabel(path: string, i18n: AdminI18n) {
115
- if (path === "id") return i18n.t("fields:id");
116
- if (path === "_status") return i18n.t("fields:status");
117
- if (path === "createdAt") return i18n.t("fields:createdAt");
118
- if (path === "updatedAt") return i18n.t("fields:updatedAt");
119
- return undefined;
120
- }
121
- </script>
122
-
123
1
  <script lang="ts">
124
- import { Link } from "@hvniel/svelte-router";
125
2
  import type { FieldAuthoringHost } from "@riducms/plugin";
126
- import type { SchemaCollection, SchemaField } from "@riducms/protocol";
127
- import { onDestroy } from "svelte";
128
- import ArrowDownIcon from "~icons/lucide/arrow-down";
129
- import ArrowUpIcon from "~icons/lucide/arrow-up";
130
- import ArrowUpRightIcon from "~icons/lucide/arrow-up-right";
3
+ import type { SchemaField } from "@riducms/protocol";
4
+ import ChevronDownIcon from "~icons/lucide/chevron-down";
131
5
  import ListPlusIcon from "~icons/lucide/list-plus";
132
-
133
- import { Button } from "@admin/components/ui/button";
134
- import type { AdminDocument } from "@admin/core/api/admin-client";
6
+ import PencilIcon from "~icons/lucide/pencil";
7
+ import { FieldFeedback } from "@riducms/ui";
8
+ import { CollapsiblePanel } from "@admin/components/ui/collapsible-panel";
135
9
  import type { FormController } from "@admin/core/forms/form-controller.svelte";
136
10
  import { getNotificationCenter } from "@admin/core/notifications/notification-center.svelte";
137
- import { documentPath } from "@admin/core/routing/admin-paths";
138
11
  import { getAdminRuntime } from "@admin/core/runtime/admin-runtime.svelte";
139
- import FieldShell from "@admin/fields/field-shell.svelte";
12
+ import ColumnPicker from "@admin/features/collections/controls/column-picker.svelte";
13
+ import SortHeading from "@admin/features/collections/controls/sort-heading.svelte";
14
+ import { documentLabel } from "@admin/features/documents/document-title";
15
+ import { JoinFieldController } from "@admin/fields/join/join-field-controller.svelte";
16
+ import "@admin/fields/join/join-field.scss";
140
17
 
141
18
  let {
142
19
  field,
143
20
  form,
144
21
  authoring,
145
- }: { field: SchemaField; form: FormController; authoring?: FieldAuthoringHost } = $props();
146
- const runtime = getAdminRuntime();
147
- const notifications = getNotificationCenter();
148
- const ReferenceBrowser = $derived(authoring?.referenceBrowser);
149
- const targetCollection = $derived(
150
- authoring?.collections.find((collection) => collection.id === field.join?.collectionId)
151
- );
152
- const sourceID = $derived(form.resource?.global ? undefined : form.resource?.id);
153
- const targetOperations = $derived(
154
- targetCollection === undefined ? undefined : runtime.collectionOperations[targetCollection.slug]
155
- );
156
- const canAttach = $derived(sourceID !== undefined && targetOperations?.update === true);
157
- const canCreate = $derived(
158
- sourceID !== undefined && field.join?.allowCreate !== false && targetOperations?.create === true
159
- );
160
- const canManage = $derived(!field.admin.readOnly && (canAttach || canCreate));
161
- const editingBlocked = $derived(form.editingBlocked);
162
- let browserOpen = $state(false);
163
- let pending = $state(false);
164
- let mutationError = $state<string>();
165
- let mutationController: AbortController | undefined;
166
- let documents = $state.raw<AdminDocument[]>([]);
167
- let sortOverride = $state<string>();
168
- const sort = $derived(sortOverride ?? field.join?.defaultSort ?? "");
169
- const columns = $derived(joinColumns(field, targetCollection, runtime.i18n));
170
- const sortedDocuments = $derived(sortDocuments(documents, sort, runtime.i18n));
171
- onDestroy(() => mutationController?.abort());
22
+ }: {
23
+ field: SchemaField;
24
+ form: FormController;
25
+ authoring?: FieldAuthoringHost;
26
+ } = $props();
172
27
 
173
- $effect(() => {
174
- form.revision;
175
- documents = joinDocuments(form.get(field.path));
28
+ const runtime = getAdminRuntime();
29
+ const controller = new JoinFieldController({
30
+ runtime,
31
+ notifications: getNotificationCenter(),
32
+ get field() {
33
+ return field;
34
+ },
35
+ get form() {
36
+ return form;
37
+ },
38
+ get authoring() {
39
+ return authoring;
40
+ },
176
41
  });
177
-
178
- function toggleSort(path: string) {
179
- sortOverride = sort === path ? `-${path}` : sort === `-${path}` ? "" : path;
180
- }
181
-
182
- async function commit(ids: string[]) {
183
- if (editingBlocked) return false;
184
- const source = form.resource;
185
- if (
186
- source?.id === undefined ||
187
- source.global ||
188
- sourceID === undefined ||
189
- targetCollection === undefined ||
190
- field.join === undefined
191
- )
192
- return false;
193
- pending = true;
194
- mutationError = undefined;
195
- const current = new Set(documents.map((document) => document.id));
196
- const requested = new Set(ids);
197
- const additions = ids.filter((id) => !current.has(id));
198
- const removals = documents
199
- .filter((document) => !requested.has(document.id))
200
- .map((document) => document.id);
201
- if (additions.length === 0 && removals.length === 0) {
202
- pending = false;
203
- return true;
204
- }
205
- mutationController = new AbortController();
206
- try {
207
- const result = await runtime.client.mutateJoin(
208
- source.collection,
209
- source.id,
210
- field.path,
211
- { additions, removals },
212
- { signal: mutationController.signal, locale: form.contentLocale }
213
- );
214
- if (mutationController.signal.aborted) return false;
215
- documents = joinDocuments(readPath(result.doc, field.path));
216
- runtime.documentsChanged();
217
- notifications.success({
218
- title: runtime.i18n.t("fields:updated", { label: field.admin.label }),
219
- message: runtime.i18n.t("fields:joinChanges", {
220
- added: result.added,
221
- removed: result.removed,
222
- }),
223
- });
224
- return true;
225
- } catch (cause) {
226
- if (mutationController.signal.aborted) return false;
227
- mutationError =
228
- cause instanceof Error ? cause.message : runtime.i18n.t("errors:relatedDocumentsUpdate");
229
- await refresh().catch(() => {});
230
- notifications.error({
231
- title: runtime.i18n.t("errors:updateUnconfirmed", { label: field.admin.label }),
232
- message: mutationError,
233
- });
234
- return false;
235
- } finally {
236
- pending = false;
237
- mutationController = undefined;
238
- }
239
- }
240
-
241
- async function refresh() {
242
- const source = form.resource;
243
- if (source?.id === undefined) return;
244
- const document = await runtime.client.find(source.collection, source.id, {
245
- locale: form.contentLocale,
246
- });
247
- documents = joinDocuments(document[field.name]);
248
- }
249
-
250
- function setBrowserOpen(open: boolean) {
251
- browserOpen = open;
252
- }
42
+ const ReferenceBrowser = $derived(authoring?.referenceBrowser);
43
+ const {
44
+ targetCollection,
45
+ sourceID,
46
+ canCreate,
47
+ canManage,
48
+ canOpenDocument,
49
+ editingBlocked,
50
+ pending,
51
+ mutationError,
52
+ documents,
53
+ sortedDocuments,
54
+ availableColumns,
55
+ columnSelection,
56
+ visibleColumns,
57
+ sort,
58
+ browserOpen,
59
+ browserMode,
60
+ browserDocumentID,
61
+ } = $derived(controller);
62
+
63
+ let columnsOpen = $state(false);
253
64
  </script>
254
65
 
255
- <FieldShell
256
- {field}
257
- issues={mutationError === undefined
258
- ? []
259
- : [{ code: "join_update_failed", path: field.path, message: mutationError }]}
260
- >
261
- <div
262
- class="overflow-hidden rounded-[4px] border border-control-border"
263
- data-join-field={field.name}
264
- >
265
- <div
266
- class="flex items-center justify-between gap-3 border-b border-control-border bg-control px-3 py-2"
267
- >
268
- <p class="font-mono text-[9.5px] tracking-[0.09em] text-foreground-faint uppercase">
269
- {runtime.i18n.t("fields:showingRelated", {
270
- count: documents.length,
271
- label: targetCollection?.labels.plural ?? field.admin.label,
272
- })}
273
- </p>
66
+ <div class="ridu-field ridu-join" data-field-path={field.path} data-join-field={field.name}>
67
+ <div class="ridu-field-heading ridu-join__heading">
68
+ <label id={`${field.id}-label`} class="ridu-field-label" for={field.id}>
69
+ {field.admin.label}
70
+ </label>
71
+ {#if field.required}
72
+ <span class="ridu-field-required" aria-hidden="true"></span>
73
+ {/if}
74
+ {#if field.admin.readOnly}
75
+ <span class="ridu-field-status">Read only</span>
76
+ {/if}
77
+ <div class="ridu-join__actions">
78
+ {#if canCreate}
79
+ <button
80
+ class="ridu-join__add"
81
+ type="button"
82
+ disabled={pending || editingBlocked}
83
+ onclick={() => controller.openBrowser("create")}
84
+ >
85
+ {runtime.i18n.t("fields:addNew")}
86
+ </button>
87
+ {/if}
274
88
  {#if canManage}
275
- <Button
276
- variant="outline"
277
- size="sm"
89
+ <button
90
+ class="ridu-join__pill ridu-join__manage"
91
+ type="button"
278
92
  disabled={pending || editingBlocked}
279
- onclick={() => (browserOpen = true)}
93
+ onclick={() => controller.openBrowser("manage")}
94
+ aria-label={runtime.i18n.t(pending ? "fields:updating" : "fields:manageRelationships")}
95
+ title={runtime.i18n.t("fields:manageRelationships")}
280
96
  >
281
- <ListPlusIcon class="size-3" />
282
- {runtime.i18n.t(pending ? "fields:updating" : "fields:manageRelationships")}
283
- </Button>
97
+ <ListPlusIcon aria-hidden="true" />
98
+ </button>
284
99
  {/if}
100
+ <button
101
+ class="ridu-join__pill"
102
+ type="button"
103
+ aria-expanded={columnsOpen}
104
+ aria-controls={`${field.id}-columns`}
105
+ onclick={() => (columnsOpen = !columnsOpen)}
106
+ >
107
+ {runtime.i18n.t("collections:columns")}
108
+ <ChevronDownIcon
109
+ class={["ridu-join__chevron", columnsOpen && "ridu-join__chevron--open"]}
110
+ aria-hidden="true"
111
+ />
112
+ </button>
285
113
  </div>
286
- {#if sortedDocuments.length > 0}
287
- <div class="overflow-x-auto">
288
- <table class="w-full min-w-[520px] border-collapse text-start text-[12px]">
289
- <thead>
290
- <tr class="border-b border-control-border bg-control">
291
- {#each columns as column (column.path)}
292
- <th class="px-3 py-2 font-medium text-foreground-faint">
293
- <button
294
- type="button"
295
- class="inline-flex items-center gap-1.5 outline-none hover:text-foreground focus-visible:text-primary"
296
- onclick={() => toggleSort(column.path)}
297
- aria-label={runtime.i18n.t("fields:sortBy", { label: column.label })}
298
- >
299
- {column.label}
300
- {#if sort === column.path}<ArrowUpIcon
301
- class="size-3"
302
- />{:else if sort === `-${column.path}`}<ArrowDownIcon class="size-3" />{/if}
303
- </button>
304
- </th>
305
- {/each}
306
- <th class="w-10 px-3 py-2">
307
- <span class="sr-only">
308
- {runtime.i18n.t("general:open")}
309
- </span>
310
- </th>
311
- </tr>
312
- </thead>
313
- <tbody>
314
- {#each sortedDocuments as document (document.id)}
315
- <tr class="border-b border-control-border last:border-b-0 hover:bg-control">
316
- {#each columns as column (column.path)}
317
- <td class="max-w-64 px-3 py-2.5 text-foreground-muted">
318
- <span class="block truncate">
319
- {displayValue(readPath(document, column.path), runtime.i18n)}
320
- </span>
321
- </td>
114
+ </div>
115
+ <FieldFeedback
116
+ controlID={field.id}
117
+ description={field.admin.description}
118
+ errors={mutationError === undefined ? [] : [mutationError]}
119
+ >
120
+ <CollapsiblePanel id={`${field.id}-columns`} open={columnsOpen}>
121
+ <ColumnPicker
122
+ columns={columnSelection}
123
+ {availableColumns}
124
+ canReadField={() => true}
125
+ onChange={controller.setColumns}
126
+ />
127
+ </CollapsiblePanel>
128
+ <div class="ridu-join__table-wrap" aria-busy={pending}>
129
+ {#if sortedDocuments.length > 0 && visibleColumns.length > 0}
130
+ <div class="ridu-join__scroll">
131
+ <table class="ridu-join__table" aria-labelledby={`${field.id}-label`}>
132
+ <thead>
133
+ <tr>
134
+ {#each visibleColumns as column (column.path)}
135
+ <SortHeading {column} {sort} onSort={controller.setSort} compact />
322
136
  {/each}
323
- <td class="px-3 py-2.5">
324
- <Link
325
- class="inline-flex text-foreground-faint hover:text-primary"
326
- to={documentPath(field.join?.collectionSlug ?? "", document.id)}
327
- aria-label={runtime.i18n.t("fields:open", {
328
- label: documentLabel(document),
329
- })}
330
- >
331
- <ArrowUpRightIcon class="size-3.5 rtl:-rotate-90" />
332
- </Link>
333
- </td>
334
137
  </tr>
335
- {/each}
336
- </tbody>
337
- </table>
338
- </div>
339
- {:else}
340
- <p class="px-3 py-4 text-[12px] text-foreground-faint">
341
- {runtime.i18n.t("fields:noRelated", {
342
- label: (targetCollection?.labels.plural ?? field.admin.label).toLocaleLowerCase(
343
- runtime.i18n.language
344
- ),
345
- })}
346
- </p>
347
- {/if}
348
- </div>
349
- </FieldShell>
138
+ </thead>
139
+ <tbody>
140
+ {#each sortedDocuments as document (document.id)}
141
+ <tr>
142
+ {#each visibleColumns as column, index (column.path)}
143
+ <td>
144
+ {#if index === 0 && canOpenDocument}
145
+ <button
146
+ class="ridu-join__document"
147
+ type="button"
148
+ onclick={() => controller.openBrowser("edit", document.id)}
149
+ aria-label={runtime.i18n.t("fields:open", {
150
+ label: documentLabel(targetCollection, document),
151
+ })}
152
+ >
153
+ <span>{controller.cellText(document, column)}</span>
154
+ <PencilIcon aria-hidden="true" />
155
+ </button>
156
+ {:else}
157
+ <span class="ridu-join__cell">{controller.cellText(document, column)}</span>
158
+ {/if}
159
+ </td>
160
+ {/each}
161
+ </tr>
162
+ {/each}
163
+ </tbody>
164
+ </table>
165
+ </div>
166
+ {:else if sortedDocuments.length === 0}
167
+ <p class="ridu-join__empty">
168
+ {runtime.i18n.t("fields:noRelated", {
169
+ label: (targetCollection?.labels.plural ?? field.admin.label).toLocaleLowerCase(
170
+ runtime.i18n.language
171
+ ),
172
+ })}
173
+ </p>
174
+ {:else}
175
+ <p class="ridu-join__empty">{runtime.i18n.t("collections:columns")}</p>
176
+ {/if}
177
+ </div>
178
+ </FieldFeedback>
179
+ </div>
350
180
 
351
181
  {#if browserOpen && targetCollection !== undefined && ReferenceBrowser !== undefined && sourceID !== undefined}
352
182
  <ReferenceBrowser
353
- bind:open={() => browserOpen, setBrowserOpen}
183
+ bind:open={() => browserOpen, controller.setBrowserOpen}
354
184
  {field}
355
185
  collection={targetCollection}
356
186
  hasMany={true}
357
187
  selectedIDs={documents.map((document) => document.id)}
358
- readOnly={!canAttach && !canCreate}
359
- defaultValues={joinDefaultValues(field.join?.on ?? "", sourceID)}
188
+ readOnly={controller.browserReadOnly}
189
+ defaultValues={controller.defaultValues}
360
190
  allowCreate={canCreate}
191
+ initialCreate={browserMode === "create"}
192
+ initialDocumentID={browserMode === "edit" ? browserDocumentID : undefined}
361
193
  locale={form.contentLocale}
362
- onCommit={commit}
363
- onClose={() => setBrowserOpen(false)}
194
+ onCommit={controller.commit}
195
+ onClose={controller.browserClosed}
364
196
  />
365
197
  {/if}
@@ -1,21 +1,22 @@
1
1
  <script lang="ts">
2
2
  import type { AdminI18n, FieldLiveValidation } from "@riducms/plugin";
3
3
  import { Button } from "@riducms/ui";
4
+ import "@admin/fields/field-layout.scss";
4
5
  let { feedback, i18n, path }: { feedback: FieldLiveValidation; i18n: AdminI18n; path: string } =
5
6
  $props();
6
7
  </script>
7
8
 
8
9
  <div data-live-validation={feedback.status} data-live-validation-path={path} aria-live="polite">
9
10
  {#if feedback.status === "pending"}
10
- <p class="mt-1 text-xs text-muted-foreground">{i18n.t("fields:liveValidationPending")}</p>
11
+ <p class="ridu-field-live-validation">{i18n.t("fields:liveValidationPending")}</p>
11
12
  {:else if feedback.status === "failed"}
12
- <div class="mt-1 flex items-center gap-2 text-xs text-muted-foreground">
13
+ <div class="ridu-field-live-validation ridu-field-live-validation--failed">
13
14
  <p>{i18n.t("fields:liveValidationFailed")}</p>
14
15
  <Button variant="ghost" size="sm" onclick={feedback.retry}>
15
16
  {i18n.t("fields:liveValidationRetry")}
16
17
  </Button>
17
18
  </div>
18
19
  {:else if feedback.status === "skipped"}
19
- <p class="mt-1 text-xs text-muted-foreground">{i18n.t("fields:liveValidationSkipped")}</p>
20
+ <p class="ridu-field-live-validation">{i18n.t("fields:liveValidationSkipped")}</p>
20
21
  {/if}
21
22
  </div>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { onDestroy, type Component } from "svelte";
2
+ import type { Component } from "svelte";
3
3
  import type { SchemaField } from "@riducms/protocol";
4
4
  import type { FieldAuthoringHost, AdminI18n } from "@riducms/plugin";
5
5
  import type { FieldEditorProps, RegisteredFieldEditor } from "@riducms/plugin/editor";
@@ -40,7 +40,7 @@
40
40
  () => runtime.manifestRevision
41
41
  );
42
42
  const guardedAuthoring = guardEditorAuthoring(() => authoring, field.assertActive);
43
- onDestroy(field.destroy);
43
+ $effect(() => field.destroy);
44
44
  </script>
45
45
 
46
46
  <Editor
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
- import { onDestroy } from "svelte";
3
2
  import type { SchemaBlockType, SchemaField } from "@riducms/protocol";
4
- import { Input } from "@admin/components/ui/input";
3
+ import { Input } from "@riducms/ui";
5
4
  import FieldMessages from "@admin/fields/field-messages.svelte";
6
5
  import LiveValidationFeedback from "@admin/fields/live-validation-feedback.svelte";
7
6
  import type { FormController } from "@admin/core/forms/form-controller.svelte";
@@ -13,6 +12,7 @@
13
12
  contentLocaleLabel,
14
13
  withContentLocaleLabel,
15
14
  } from "@admin/fields/localized-field-presentation";
15
+ import "@admin/fields/nested/nested-field.scss";
16
16
 
17
17
  let {
18
18
  schema,
@@ -55,7 +55,7 @@
55
55
  else form.set(binding.schema.path, value);
56
56
  }
57
57
  );
58
- onDestroy(binding.destroy);
58
+ $effect(() => binding.destroy);
59
59
  const current = $derived(binding.schema);
60
60
  const placeholder = $derived(
61
61
  blockHeaderValue(
@@ -82,13 +82,13 @@
82
82
  </script>
83
83
 
84
84
  {#if binding.visible}
85
- <div class="min-w-0 flex-1" data-field-path={current.path} onfocusout={focusout}>
85
+ <div class="ridu-block-name" data-field-path={current.path} onfocusout={focusout}>
86
86
  <FieldMessages
87
87
  controlID={current.id}
88
88
  description={current.admin.description}
89
89
  issues={binding.issues}
90
90
  >
91
- <label class="sr-only" for={current.id}>{current.admin.label}</label>
91
+ <label class="ridu-block-name__label" for={current.id}>{current.admin.label}</label>
92
92
  <Input
93
93
  {...binding.inputProps}
94
94
  value={binding.value ?? ""}
@@ -97,7 +97,7 @@
97
97
  {disabled}
98
98
  minlength={current.text?.minLength}
99
99
  maxlength={current.text?.maxLength}
100
- class="h-8 min-w-0"
100
+ class="ridu-block-name__input"
101
101
  oninput={(event) => binding.set(event.currentTarget.value)}
102
102
  onkeydown={keydown}
103
103
  />
@@ -107,15 +107,14 @@
107
107
  i18n={runtime.i18n}
108
108
  path={current.path}
109
109
  />
110
- {#if inherited !== undefined}<p
111
- class="mt-1 text-xs text-foreground-faint"
112
- data-localization-source={inherited}
113
- >
110
+ {#if inherited !== undefined}
111
+ <p class="ridu-block-name__localization" data-localization-source={inherited}>
114
112
  {runtime.i18n.t("documents:inheritedFrom", {
115
113
  locale: contentLocaleLabel(runtime.contentLocales, inherited) ?? inherited,
116
114
  })}
117
- </p>{:else if current.localized && form.contentLocale !== undefined && binding.value === undefined}
118
- <p class="mt-1 text-xs text-foreground-faint" data-localization-missing={form.contentLocale}>
115
+ </p>
116
+ {:else if current.localized && form.contentLocale !== undefined && binding.value === undefined}
117
+ <p class="ridu-block-name__localization" data-localization-missing={form.contentLocale}>
119
118
  {runtime.i18n.t("documents:missingTranslation", {
120
119
  locale:
121
120
  contentLocaleLabel(runtime.contentLocales, form.contentLocale) ?? form.contentLocale,