@questpie/admin 3.0.3 → 3.0.5

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 (253) hide show
  1. package/README.md +34 -5
  2. package/dist/client/blocks/block-renderer.d.mts +2 -2
  3. package/dist/client/blocks/block-renderer.mjs +4 -1
  4. package/dist/client/builder/types/action-types.d.mts +31 -3
  5. package/dist/client/builder/types/collection-types.d.mts +140 -0
  6. package/dist/client/builder/types/ui-config.d.mts +16 -2
  7. package/dist/client/builder/types/views.d.mts +57 -0
  8. package/dist/client/builder/types/widget-types.d.mts +5 -0
  9. package/dist/client/components/actions/action-button.mjs +137 -199
  10. package/dist/client/components/actions/action-dialog.mjs +198 -156
  11. package/dist/client/components/actions/confirmation-dialog.mjs +2 -2
  12. package/dist/client/components/actions/header-actions.mjs +52 -53
  13. package/dist/client/components/admin-link.d.mts +2 -2
  14. package/dist/client/components/auth/auth-loading.mjs +41 -18
  15. package/dist/client/components/blocks/block-editor-layout.mjs +2 -2
  16. package/dist/client/components/blocks/block-fields-renderer.mjs +64 -28
  17. package/dist/client/components/blocks/block-insert-button.mjs +4 -4
  18. package/dist/client/components/blocks/block-item.mjs +2 -2
  19. package/dist/client/components/blocks/block-library-sidebar.mjs +91 -63
  20. package/dist/client/components/component-renderer.mjs +1 -1
  21. package/dist/client/components/fields/array-field.mjs +14 -14
  22. package/dist/client/components/fields/asset-preview-field.mjs +1 -1
  23. package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
  24. package/dist/client/components/fields/json-field.mjs +2 -2
  25. package/dist/client/components/fields/object-array-field.mjs +22 -22
  26. package/dist/client/components/fields/object-field.mjs +5 -5
  27. package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
  28. package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
  29. package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
  30. package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
  31. package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
  32. package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
  33. package/dist/client/components/fields/relation-picker.mjs +7 -6
  34. package/dist/client/components/fields/relation-select.mjs +71 -47
  35. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
  36. package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
  37. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
  38. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
  39. package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
  40. package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
  41. package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
  42. package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
  43. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
  44. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
  45. package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
  46. package/dist/client/components/fields/upload-field.mjs +45 -49
  47. package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
  48. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
  49. package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
  50. package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
  51. package/dist/client/components/history-sidebar.mjs +850 -340
  52. package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
  53. package/dist/client/components/locale-switcher.mjs +8 -8
  54. package/dist/client/components/media/media-grid.mjs +106 -86
  55. package/dist/client/components/media/media-picker-dialog.mjs +242 -230
  56. package/dist/client/components/preview/live-preview-mode.mjs +1 -1
  57. package/dist/client/components/primitives/asset-preview.mjs +37 -22
  58. package/dist/client/components/primitives/date-input.mjs +212 -249
  59. package/dist/client/components/primitives/dropzone.mjs +192 -159
  60. package/dist/client/components/primitives/field-select-control.mjs +93 -0
  61. package/dist/client/components/primitives/select-multi.mjs +406 -365
  62. package/dist/client/components/primitives/select-single.mjs +391 -323
  63. package/dist/client/components/primitives/time-input.mjs +2 -2
  64. package/dist/client/components/sheets/resource-sheet.mjs +2 -0
  65. package/dist/client/components/ui/accordion.mjs +4 -4
  66. package/dist/client/components/ui/alert.mjs +3 -3
  67. package/dist/client/components/ui/badge.mjs +4 -4
  68. package/dist/client/components/ui/button.mjs +47 -37
  69. package/dist/client/components/ui/card.mjs +2 -2
  70. package/dist/client/components/ui/checkbox.mjs +1 -1
  71. package/dist/client/components/ui/command.mjs +5 -5
  72. package/dist/client/components/ui/dialog.mjs +3 -3
  73. package/dist/client/components/ui/drawer.mjs +1 -1
  74. package/dist/client/components/ui/dropdown-menu.mjs +157 -15
  75. package/dist/client/components/ui/empty-state.mjs +88 -59
  76. package/dist/client/components/ui/field.mjs +2 -2
  77. package/dist/client/components/ui/input-group.mjs +3 -3
  78. package/dist/client/components/ui/input.mjs +1 -1
  79. package/dist/client/components/ui/kbd.mjs +1 -1
  80. package/dist/client/components/ui/label.mjs +1 -1
  81. package/dist/client/components/ui/popover.mjs +19 -11
  82. package/dist/client/components/ui/scroll-fade.mjs +170 -0
  83. package/dist/client/components/ui/search-input.mjs +1 -1
  84. package/dist/client/components/ui/select.mjs +129 -27
  85. package/dist/client/components/ui/sheet.mjs +54 -34
  86. package/dist/client/components/ui/sidebar.mjs +15 -14
  87. package/dist/client/components/ui/skeleton.mjs +28 -12
  88. package/dist/client/components/ui/switch.mjs +2 -2
  89. package/dist/client/components/ui/table.mjs +82 -74
  90. package/dist/client/components/ui/tabs.mjs +26 -31
  91. package/dist/client/components/ui/textarea.mjs +1 -1
  92. package/dist/client/components/ui/tooltip.mjs +1 -1
  93. package/dist/client/components/widgets/chart-widget.mjs +154 -100
  94. package/dist/client/components/widgets/progress-widget.mjs +63 -36
  95. package/dist/client/components/widgets/quick-actions-widget.mjs +207 -115
  96. package/dist/client/components/widgets/recent-items-widget.mjs +147 -103
  97. package/dist/client/components/widgets/stats-widget.mjs +91 -72
  98. package/dist/client/components/widgets/table-widget.mjs +161 -247
  99. package/dist/client/components/widgets/timeline-widget.mjs +119 -78
  100. package/dist/client/components/widgets/value-widget.mjs +286 -157
  101. package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
  102. package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
  103. package/dist/client/contexts/focus-context.d.mts +2 -2
  104. package/dist/client/hooks/use-action.mjs +63 -55
  105. package/dist/client/hooks/use-audit-history.mjs +1 -65
  106. package/dist/client/hooks/use-collection-validation.mjs +36 -23
  107. package/dist/client/hooks/use-collection.mjs +96 -1
  108. package/dist/client/hooks/use-saved-views.mjs +70 -49
  109. package/dist/client/hooks/use-server-actions.mjs +70 -46
  110. package/dist/client/hooks/use-server-validation.mjs +156 -41
  111. package/dist/client/hooks/use-server-widget-data.mjs +1 -1
  112. package/dist/client/hooks/use-setup-status.d.mts +3 -3
  113. package/dist/client/hooks/use-setup-status.mjs +2 -2
  114. package/dist/client/hooks/use-transition-stage.mjs +2 -10
  115. package/dist/client/hooks/use-validation-error-map.mjs +31 -13
  116. package/dist/client/hooks/use-view-state.mjs +238 -174
  117. package/dist/client/i18n/date-locale.mjs +33 -0
  118. package/dist/client/i18n/hooks.mjs +17 -1
  119. package/dist/client/lib/utils.mjs +3 -2
  120. package/dist/client/preview/block-scope-context.d.mts +2 -2
  121. package/dist/client/preview/preview-banner.d.mts +2 -2
  122. package/dist/client/preview/preview-banner.mjs +75 -46
  123. package/dist/client/preview/preview-field.d.mts +4 -4
  124. package/dist/client/preview/preview-field.mjs +2 -2
  125. package/dist/client/runtime/provider.mjs +8 -1
  126. package/dist/client/runtime/translations-provider.mjs +1 -1
  127. package/dist/client/scope/picker.d.mts +2 -2
  128. package/dist/client/scope/provider.d.mts +2 -2
  129. package/dist/client/styles/base.css +1022 -0
  130. package/dist/client/styles/index.css +3 -589
  131. package/dist/client/utils/auto-expand-fields.mjs +4 -2
  132. package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
  133. package/dist/client/utils/use-lazy-component.mjs +80 -0
  134. package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
  135. package/dist/client/views/auth/auth-layout.d.mts +17 -10
  136. package/dist/client/views/auth/auth-layout.mjs +291 -80
  137. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  138. package/dist/client/views/auth/forgot-password-form.mjs +2 -2
  139. package/dist/client/views/auth/login-form.d.mts +2 -2
  140. package/dist/client/views/auth/login-form.mjs +1 -1
  141. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  142. package/dist/client/views/auth/reset-password-form.mjs +2 -2
  143. package/dist/client/views/auth/setup-form.d.mts +2 -2
  144. package/dist/client/views/collection/auto-form-fields.mjs +11 -9
  145. package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
  146. package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
  147. package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
  148. package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
  149. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
  150. package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
  151. package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
  152. package/dist/client/views/collection/columns/build-columns.mjs +29 -9
  153. package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
  154. package/dist/client/views/collection/field-renderer.mjs +50 -89
  155. package/dist/client/views/collection/form-view.mjs +237 -227
  156. package/dist/client/views/collection/table-view.mjs +1167 -234
  157. package/dist/client/views/collection/view-skeletons.mjs +222 -79
  158. package/dist/client/views/common/global-search.mjs +29 -18
  159. package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
  160. package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
  161. package/dist/client/views/dashboard/widget-card.mjs +23 -14
  162. package/dist/client/views/globals/global-form-view.mjs +634 -589
  163. package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
  164. package/dist/client/views/layout/admin-layout.d.mts +3 -6
  165. package/dist/client/views/layout/admin-layout.mjs +152 -155
  166. package/dist/client/views/layout/admin-router.mjs +936 -616
  167. package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
  168. package/dist/client/views/layout/admin-sidebar.mjs +762 -592
  169. package/dist/client/views/layout/admin-theme.d.mts +10 -0
  170. package/dist/client/views/layout/admin-theme.mjs +84 -0
  171. package/dist/client/views/layout/admin-view-layout.mjs +161 -0
  172. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  173. package/dist/client/views/pages/accept-invite-page.mjs +49 -26
  174. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  175. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  176. package/dist/client/views/pages/forgot-password-page.mjs +2 -19
  177. package/dist/client/views/pages/invite-page.d.mts +2 -2
  178. package/dist/client/views/pages/invite-page.mjs +2 -19
  179. package/dist/client/views/pages/login-page.d.mts +3 -3
  180. package/dist/client/views/pages/login-page.mjs +4 -21
  181. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  182. package/dist/client/views/pages/reset-password-page.mjs +3 -20
  183. package/dist/client/views/pages/setup-page.d.mts +2 -2
  184. package/dist/client/views/pages/setup-page.mjs +70 -71
  185. package/dist/client.d.mts +6 -2
  186. package/dist/client.mjs +2 -1
  187. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  188. package/dist/index.d.mts +6 -2
  189. package/dist/index.mjs +2 -1
  190. package/dist/server/augmentation/dashboard.d.mts +67 -3
  191. package/dist/server/augmentation/form-layout.d.mts +21 -0
  192. package/dist/server/augmentation/index.d.mts +1 -1
  193. package/dist/server/codegen/admin-client-template.mjs +4 -0
  194. package/dist/server/fields/blocks.d.mts +1 -1
  195. package/dist/server/fields/blocks.mjs +12 -0
  196. package/dist/server/fields/rich-text.d.mts +1 -1
  197. package/dist/server/fields/rich-text.mjs +8 -0
  198. package/dist/server/i18n/index.mjs +29 -7
  199. package/dist/server/i18n/messages/cs.mjs +414 -1
  200. package/dist/server/i18n/messages/de.mjs +412 -1
  201. package/dist/server/i18n/messages/en.mjs +166 -1
  202. package/dist/server/i18n/messages/es.mjs +412 -1
  203. package/dist/server/i18n/messages/fr.mjs +412 -1
  204. package/dist/server/i18n/messages/pl.mjs +416 -1
  205. package/dist/server/i18n/messages/pt.mjs +409 -1
  206. package/dist/server/i18n/messages/sk.mjs +216 -2
  207. package/dist/server/modules/admin/block/introspection.mjs +4 -1
  208. package/dist/server/modules/admin/block/prefetch.mjs +12 -2
  209. package/dist/server/modules/admin/collections/account.d.mts +2 -2
  210. package/dist/server/modules/admin/collections/admin-locks.d.mts +2 -2
  211. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  212. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  213. package/dist/server/modules/admin/collections/apikey.d.mts +42 -42
  214. package/dist/server/modules/admin/collections/assets.d.mts +20 -20
  215. package/dist/server/modules/admin/collections/assets.mjs +0 -1
  216. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  217. package/dist/server/modules/admin/collections/user.d.mts +40 -28
  218. package/dist/server/modules/admin/collections/user.mjs +40 -9
  219. package/dist/server/modules/admin/collections/verification.d.mts +36 -36
  220. package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
  221. package/dist/server/modules/admin/factories.mjs +7 -18
  222. package/dist/server/modules/admin/index.d.mts +1 -1
  223. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  224. package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
  225. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  226. package/dist/server/modules/admin/routes/execute-action.mjs +67 -28
  227. package/dist/server/modules/admin/routes/i18n-helpers.mjs +34 -0
  228. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  229. package/dist/server/modules/admin/routes/preview.mjs +25 -17
  230. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  231. package/dist/server/modules/admin/routes/route-helpers.mjs +1 -1
  232. package/dist/server/modules/admin/routes/setup.d.mts +10 -10
  233. package/dist/server/modules/admin/routes/setup.mjs +16 -13
  234. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  235. package/dist/server/modules/admin/routes/translations.mjs +5 -1
  236. package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
  237. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +2 -2
  238. package/dist/server/modules/audit/.generated/module.d.mts +1 -1
  239. package/dist/server/modules/audit/.generated/module.mjs +1 -1
  240. package/dist/server/modules/audit/collections/audit-log.d.mts +2 -2
  241. package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
  242. package/dist/server/modules/audit/config/app.mjs +99 -42
  243. package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
  244. package/dist/server/plugin.mjs +4 -2
  245. package/dist/server/proxy-factories.d.mts +4 -3
  246. package/dist/server/proxy-factories.mjs +34 -8
  247. package/dist/shared/types/saved-views.types.d.mts +2 -0
  248. package/package.json +6 -4
  249. package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
  250. package/dist/client/components/ui/spinner.mjs +0 -52
  251. package/dist/client/components/ui/toolbar.mjs +0 -136
  252. package/dist/client/contexts/breadcrumb-context.mjs +0 -60
  253. package/dist/client/views/layout/admin-topbar.mjs +0 -236
@@ -27,6 +27,26 @@ function getCodeBlockExtension() {
27
27
  });
28
28
  return codeBlockLoadPromise;
29
29
  }
30
+ const defaultLabels = {
31
+ bulletList: "Bullet list",
32
+ bulletListDescription: "Create a bulleted list",
33
+ codeBlock: "Code block",
34
+ codeBlockDescription: "Insert code snippet",
35
+ divider: "Divider",
36
+ dividerDescription: "Insert a horizontal rule",
37
+ heading: (level) => `Heading ${level}`,
38
+ heading1Description: "Large section heading",
39
+ heading2Description: "Medium section heading",
40
+ heading3Description: "Small section heading",
41
+ orderedList: "Numbered list",
42
+ orderedListDescription: "Create an ordered list",
43
+ paragraph: "Paragraph",
44
+ paragraphDescription: "Start with plain text",
45
+ quote: "Quote",
46
+ quoteDescription: "Capture a quote",
47
+ table: "Table",
48
+ tableDescription: "Insert a 3x3 table"
49
+ };
30
50
  /**
31
51
  * Build Tiptap extensions based on feature configuration.
32
52
  *
@@ -34,9 +54,10 @@ function getCodeBlockExtension() {
34
54
  * (i.e. codeBlock disabled, or lowlight already cached). Only returns a
35
55
  * `Promise` on the first build that includes codeBlock.
36
56
  */
37
- function buildExtensions({ features, placeholder, maxCharacters, customExtensions }) {
57
+ function buildExtensions({ features, labels, placeholder, maxCharacters, customExtensions }) {
38
58
  const base = buildBaseExtensions({
39
59
  features,
60
+ labels,
40
61
  placeholder,
41
62
  maxCharacters,
42
63
  customExtensions
@@ -46,7 +67,7 @@ function buildExtensions({ features, placeholder, maxCharacters, customExtension
46
67
  if (!(codeBlock instanceof Promise)) return [...base, codeBlock];
47
68
  return codeBlock.then((ext) => [...base, ext]);
48
69
  }
49
- function buildBaseExtensions({ features, placeholder, maxCharacters, customExtensions }) {
70
+ function buildBaseExtensions({ features, labels = defaultLabels, placeholder, maxCharacters, customExtensions }) {
50
71
  const starterKitConfig = { codeBlock: false };
51
72
  if (!features.bold) starterKitConfig.bold = false;
52
73
  if (!features.italic) starterKitConfig.italic = false;
@@ -70,63 +91,73 @@ function buildBaseExtensions({ features, placeholder, maxCharacters, customExten
70
91
  if (features.image) extensions.push(Image);
71
92
  if (features.table) extensions.push(Table.configure({ resizable: true }), TableRow, TableHeader, TableCell);
72
93
  if (features.characterCount && maxCharacters) extensions.push(CharacterCount.configure({ limit: maxCharacters }));
73
- if (features.slashCommands) extensions.push(createSlashCommandExtension((editor) => {
94
+ if (features.slashCommands) extensions.push(createSlashCommandExtension((_editor) => {
74
95
  const commands = [];
75
96
  if (features.heading) commands.push({
76
- title: "Heading 1",
77
- description: "Large section heading",
97
+ title: labels.heading(1),
98
+ description: labels.heading1Description,
99
+ icon: "ph:text-h-one",
78
100
  keywords: ["h1"],
79
101
  command: (cmdEditor) => cmdEditor.chain().focus().toggleHeading({ level: 1 }).run()
80
102
  }, {
81
- title: "Heading 2",
82
- description: "Medium section heading",
103
+ title: labels.heading(2),
104
+ description: labels.heading2Description,
105
+ icon: "ph:text-h-two",
83
106
  keywords: ["h2"],
84
107
  command: (cmdEditor) => cmdEditor.chain().focus().toggleHeading({ level: 2 }).run()
85
108
  }, {
86
- title: "Heading 3",
87
- description: "Small section heading",
109
+ title: labels.heading(3),
110
+ description: labels.heading3Description,
111
+ icon: "ph:text-h-three",
88
112
  keywords: ["h3"],
89
113
  command: (cmdEditor) => cmdEditor.chain().focus().toggleHeading({ level: 3 }).run()
90
114
  });
91
115
  commands.push({
92
- title: "Paragraph",
93
- description: "Start with plain text",
116
+ title: labels.paragraph,
117
+ description: labels.paragraphDescription,
118
+ icon: "ph:text-align-left",
94
119
  keywords: ["text"],
95
120
  command: (cmdEditor) => cmdEditor.chain().focus().setParagraph().run()
96
121
  });
97
122
  if (features.bulletList) commands.push({
98
- title: "Bullet list",
99
- description: "Create a bulleted list",
123
+ title: labels.bulletList,
124
+ description: labels.bulletListDescription,
125
+ icon: "ph:list-bullets",
100
126
  keywords: ["list", "ul"],
101
127
  command: (cmdEditor) => cmdEditor.chain().focus().toggleBulletList().run()
102
128
  });
103
129
  if (features.orderedList) commands.push({
104
- title: "Numbered list",
105
- description: "Create an ordered list",
130
+ title: labels.orderedList,
131
+ description: labels.orderedListDescription,
132
+ icon: "ph:list-numbers",
106
133
  keywords: ["list", "ol"],
107
134
  command: (cmdEditor) => cmdEditor.chain().focus().toggleOrderedList().run()
108
135
  });
109
136
  if (features.blockquote) commands.push({
110
- title: "Quote",
111
- description: "Capture a quote",
137
+ title: labels.quote,
138
+ description: labels.quoteDescription,
139
+ icon: "ph:quotes",
112
140
  keywords: ["blockquote"],
113
141
  command: (cmdEditor) => cmdEditor.chain().focus().toggleBlockquote().run()
114
142
  });
115
143
  if (features.codeBlock) commands.push({
116
- title: "Code block",
117
- description: "Insert code snippet",
144
+ title: labels.codeBlock,
145
+ description: labels.codeBlockDescription,
146
+ icon: "ph:code-block",
118
147
  keywords: ["code"],
119
148
  command: (cmdEditor) => cmdEditor.chain().focus().toggleCodeBlock().run()
120
149
  });
121
150
  if (features.horizontalRule) commands.push({
122
- title: "Divider",
123
- description: "Insert a horizontal rule",
151
+ title: labels.divider,
152
+ description: labels.dividerDescription,
153
+ icon: "ph:minus",
124
154
  keywords: ["hr"],
125
155
  command: (cmdEditor) => cmdEditor.chain().focus().setHorizontalRule().run()
126
156
  });
127
157
  if (features.table) commands.push({
128
- title: "Table",
129
- description: "Insert a 3x3 table",
158
+ title: labels.table,
159
+ description: labels.tableDescription,
160
+ icon: "ph:table",
130
161
  keywords: ["grid"],
131
162
  command: (cmdEditor) => cmdEditor.chain().focus().insertTable({
132
163
  rows: 3,
@@ -1,12 +1,10 @@
1
1
  import { useTranslation } from "../../../i18n/hooks.mjs";
2
2
  import { Button } from "../../ui/button.mjs";
3
3
  import { Input } from "../../ui/input.mjs";
4
- import { sanitizeFilename } from "../field-utils.mjs";
5
4
  import { Popover, PopoverContent, PopoverHeader, PopoverTitle, PopoverTrigger } from "../../ui/popover.mjs";
6
5
  import { useCollectionItem } from "../../../hooks/use-collection.mjs";
7
- import { useUploadCollection } from "../../../hooks/use-upload-collection.mjs";
8
- import { useUpload } from "../../../hooks/use-upload.mjs";
9
6
  import { MediaPickerDialog } from "../../media/media-picker-dialog.mjs";
7
+ import { useRichTextImageUpload } from "./image-upload.mjs";
10
8
  import * as React from "react";
11
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
10
  import { toast } from "sonner";
@@ -24,8 +22,10 @@ function ImagePopover({ editor, open, onOpenChange, disabled, onImageUpload, ima
24
22
  const fileInputRef = React.useRef(null);
25
23
  const [isPickerOpen, setIsPickerOpen] = React.useState(false);
26
24
  const [selectedAssetId, setSelectedAssetId] = React.useState(null);
27
- const { upload } = useUpload();
28
- const { collection, collections: availableUploadCollections } = useUploadCollection(imageCollection);
25
+ const { collection, uploadImageFile } = useRichTextImageUpload({
26
+ imageCollection,
27
+ onImageUpload
28
+ });
29
29
  const showMediaLibrary = enableMediaLibrary ?? true;
30
30
  const { data: selectedAsset } = useCollectionItem(collection || "", selectedAssetId || "", void 0, { enabled: !!collection && !!selectedAssetId });
31
31
  const handleInsertImageUrl = React.useCallback(() => {
@@ -48,45 +48,14 @@ function ImagePopover({ editor, open, onOpenChange, disabled, onImageUpload, ima
48
48
  if (!file || !editor) return;
49
49
  try {
50
50
  setUploadingImage(true);
51
- let url;
52
- if (onImageUpload) url = await onImageUpload(file);
53
- else {
54
- if (!collection) {
55
- let errorMessage;
56
- if (availableUploadCollections.length > 1) errorMessage = `Multiple upload collections are available (${availableUploadCollections.join(", ")}). Configure rich-text imageCollection to choose one.`;
57
- else errorMessage = "No upload collection is configured for rich-text image uploads.";
58
- toast.error(errorMessage);
59
- setUploadingImage(false);
60
- event.target.value = "";
61
- return;
62
- }
63
- const sanitizedName = sanitizeFilename(file.name);
64
- let uploadFile;
65
- if (sanitizedName === file.name) uploadFile = file;
66
- else uploadFile = new File([file], sanitizedName, { type: file.type });
67
- const uploadedAsset = await upload(uploadFile, { to: collection });
68
- if (uploadedAsset) {
69
- if (uploadedAsset.url) url = uploadedAsset.url;
70
- }
71
- if (!url) {
72
- toast.error(t("upload.error"));
73
- setUploadingImage(false);
74
- event.target.value = "";
75
- return;
76
- }
77
- }
78
- if (url) {
79
- let altValue;
80
- if (imageAlt) altValue = imageAlt;
81
- else altValue = void 0;
82
- editor.chain().focus().setImage({
83
- src: url,
84
- alt: altValue
85
- }).run();
86
- setImageUrl("");
87
- setImageAlt("");
88
- onOpenChange(false);
89
- }
51
+ const url = await uploadImageFile(file);
52
+ editor.chain().focus().setImage({
53
+ src: url,
54
+ alt: imageAlt || void 0
55
+ }).run();
56
+ setImageUrl("");
57
+ setImageAlt("");
58
+ onOpenChange(false);
90
59
  setUploadingImage(false);
91
60
  event.target.value = "";
92
61
  } catch (err) {
@@ -98,14 +67,11 @@ function ImagePopover({ editor, open, onOpenChange, disabled, onImageUpload, ima
98
67
  event.target.value = "";
99
68
  }
100
69
  }, [
101
- collection,
102
- availableUploadCollections,
103
70
  editor,
104
71
  imageAlt,
105
- onImageUpload,
106
72
  onOpenChange,
107
73
  t,
108
- upload
74
+ uploadImageFile
109
75
  ]);
110
76
  React.useEffect(() => {
111
77
  if (!selectedAssetId || !selectedAsset || !editor) return;
@@ -148,14 +114,22 @@ function ImagePopover({ editor, open, onOpenChange, disabled, onImageUpload, ima
148
114
  className: "space-y-2",
149
115
  children: [
150
116
  /* @__PURE__ */ jsx(Input, {
117
+ "aria-label": t("editor.image"),
118
+ autoComplete: "off",
119
+ inputMode: "url",
120
+ name: "rich-text-image-url",
121
+ type: "url",
151
122
  value: imageUrl,
152
- placeholder: "https://example.com/image.jpg",
123
+ placeholder: "https://example.com/image.jpg",
153
124
  onChange: (event_0) => setImageUrl(event_0.target.value),
154
125
  disabled
155
126
  }),
156
127
  /* @__PURE__ */ jsx(Input, {
128
+ "aria-label": t("editor.altText"),
129
+ autoComplete: "off",
130
+ name: "rich-text-image-alt",
157
131
  value: imageAlt,
158
- placeholder: t("editor.altText"),
132
+ placeholder: `${t("editor.altText")}…`,
159
133
  onChange: (event_1) => setImageAlt(event_1.target.value),
160
134
  disabled
161
135
  }),
@@ -0,0 +1,66 @@
1
+ import { useTranslation } from "../../../i18n/hooks.mjs";
2
+ import { sanitizeFilename } from "../field-utils.mjs";
3
+ import { useUploadCollection } from "../../../hooks/use-upload-collection.mjs";
4
+ import { useUpload } from "../../../hooks/use-upload.mjs";
5
+ import { c } from "react/compiler-runtime";
6
+
7
+ //#region src/client/components/fields/rich-text-editor/image-upload.ts
8
+ function getImageFilesFromDataTransfer(dataTransfer) {
9
+ return Array.from(dataTransfer?.files ?? []).filter((file) => file.type.startsWith("image/"));
10
+ }
11
+ function getImageAltFromFile(file) {
12
+ const cleanName = file.name.trim();
13
+ if (!cleanName) return void 0;
14
+ return cleanName.replace(/\.[^.]+$/, "") || cleanName;
15
+ }
16
+ function useRichTextImageUpload(t0) {
17
+ const $ = c(11);
18
+ const { imageCollection, onImageUpload } = t0;
19
+ const { t } = useTranslation();
20
+ const { upload, isUploading } = useUpload();
21
+ const { collection, collections } = useUploadCollection(imageCollection);
22
+ let t1;
23
+ if ($[0] !== collection || $[1] !== collections || $[2] !== onImageUpload || $[3] !== t || $[4] !== upload) {
24
+ t1 = async (file) => {
25
+ if (!file.type.startsWith("image/")) throw new Error(`"${file.name}" is not an image file.`);
26
+ if (onImageUpload) {
27
+ const url = await onImageUpload(file);
28
+ if (!url) throw new Error(t("upload.error"));
29
+ return url;
30
+ }
31
+ if (!collection) {
32
+ if (collections.length > 1) throw new Error(`Multiple upload collections are available (${collections.join(", ")}). Configure rich-text imageCollection to choose one.`);
33
+ throw new Error("No upload collection is configured for rich-text image uploads.");
34
+ }
35
+ const sanitizedName = sanitizeFilename(file.name);
36
+ const uploadedAsset = await upload(sanitizedName === file.name ? file : new File([file], sanitizedName, { type: file.type }), { to: collection });
37
+ if (!uploadedAsset?.url) throw new Error(t("upload.error"));
38
+ return uploadedAsset.url;
39
+ };
40
+ $[0] = collection;
41
+ $[1] = collections;
42
+ $[2] = onImageUpload;
43
+ $[3] = t;
44
+ $[4] = upload;
45
+ $[5] = t1;
46
+ } else t1 = $[5];
47
+ const uploadImageFile = t1;
48
+ let t2;
49
+ if ($[6] !== collection || $[7] !== collections || $[8] !== isUploading || $[9] !== uploadImageFile) {
50
+ t2 = {
51
+ collection,
52
+ collections,
53
+ isUploading,
54
+ uploadImageFile
55
+ };
56
+ $[6] = collection;
57
+ $[7] = collections;
58
+ $[8] = isUploading;
59
+ $[9] = uploadImageFile;
60
+ $[10] = t2;
61
+ } else t2 = $[10];
62
+ return t2;
63
+ }
64
+
65
+ //#endregion
66
+ export { getImageAltFromFile, getImageFilesFromDataTransfer, useRichTextImageUpload };
@@ -0,0 +1,38 @@
1
+ import { RichTextEditorProps } from "./types.mjs";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
+
4
+ //#region src/client/components/fields/rich-text-editor/index.d.ts
5
+
6
+ /**
7
+ * Main RichText Editor Component.
8
+ *
9
+ * Loads Tiptap extensions asynchronously (lowlight etc.) and delegates to
10
+ * `RichTextEditorCore` once they are ready. This avoids initializing
11
+ * `useEditor` with an empty extension list which causes the ProseMirror
12
+ * "Schema is missing its top node type" error.
13
+ */
14
+ declare function RichTextEditor({
15
+ name,
16
+ value,
17
+ onChange,
18
+ disabled,
19
+ readOnly,
20
+ label,
21
+ description,
22
+ placeholder,
23
+ required,
24
+ error,
25
+ localized,
26
+ locale,
27
+ extensions,
28
+ preset,
29
+ features,
30
+ showCharacterCount,
31
+ maxCharacters,
32
+ enableImages,
33
+ onImageUpload,
34
+ imageCollection,
35
+ enableMediaLibrary
36
+ }: RichTextEditorProps): react_jsx_runtime0.JSX.Element;
37
+ //#endregion
38
+ export { RichTextEditor };