@questpie/admin 3.0.2 → 3.0.4

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 (249) 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-fields-renderer.mjs +64 -28
  16. package/dist/client/components/blocks/block-insert-button.mjs +4 -4
  17. package/dist/client/components/blocks/block-item.mjs +2 -2
  18. package/dist/client/components/blocks/block-library-sidebar.mjs +2 -2
  19. package/dist/client/components/component-renderer.mjs +1 -1
  20. package/dist/client/components/fields/array-field.mjs +14 -14
  21. package/dist/client/components/fields/asset-preview-field.mjs +1 -1
  22. package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
  23. package/dist/client/components/fields/json-field.mjs +2 -2
  24. package/dist/client/components/fields/object-array-field.mjs +22 -22
  25. package/dist/client/components/fields/object-field.mjs +5 -5
  26. package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
  27. package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
  28. package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
  29. package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
  30. package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
  31. package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
  32. package/dist/client/components/fields/relation-picker.mjs +7 -6
  33. package/dist/client/components/fields/relation-select.mjs +71 -47
  34. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
  35. package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
  36. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
  37. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
  38. package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
  39. package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
  40. package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
  41. package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
  42. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
  43. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
  44. package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
  45. package/dist/client/components/fields/upload-field.mjs +45 -49
  46. package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
  47. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
  48. package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
  49. package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
  50. package/dist/client/components/history-sidebar.mjs +850 -340
  51. package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
  52. package/dist/client/components/locale-switcher.mjs +8 -8
  53. package/dist/client/components/media/media-grid.mjs +12 -9
  54. package/dist/client/components/media/media-picker-dialog.mjs +242 -230
  55. package/dist/client/components/preview/live-preview-mode.mjs +1 -1
  56. package/dist/client/components/primitives/asset-preview.mjs +37 -22
  57. package/dist/client/components/primitives/date-input.mjs +212 -249
  58. package/dist/client/components/primitives/dropzone.mjs +192 -159
  59. package/dist/client/components/primitives/field-select-control.mjs +93 -0
  60. package/dist/client/components/primitives/select-multi.mjs +251 -230
  61. package/dist/client/components/primitives/select-single.mjs +345 -290
  62. package/dist/client/components/primitives/time-input.mjs +2 -2
  63. package/dist/client/components/sheets/resource-sheet.mjs +2 -0
  64. package/dist/client/components/ui/accordion.mjs +4 -4
  65. package/dist/client/components/ui/alert.mjs +3 -3
  66. package/dist/client/components/ui/badge.mjs +4 -4
  67. package/dist/client/components/ui/button.mjs +47 -37
  68. package/dist/client/components/ui/card.mjs +2 -2
  69. package/dist/client/components/ui/checkbox.mjs +1 -1
  70. package/dist/client/components/ui/command.mjs +5 -5
  71. package/dist/client/components/ui/dialog.mjs +3 -3
  72. package/dist/client/components/ui/drawer.mjs +1 -1
  73. package/dist/client/components/ui/dropdown-menu.mjs +157 -15
  74. package/dist/client/components/ui/empty-state.mjs +88 -59
  75. package/dist/client/components/ui/field.mjs +2 -2
  76. package/dist/client/components/ui/input-group.mjs +3 -3
  77. package/dist/client/components/ui/input.mjs +1 -1
  78. package/dist/client/components/ui/kbd.mjs +1 -1
  79. package/dist/client/components/ui/label.mjs +1 -1
  80. package/dist/client/components/ui/popover.mjs +19 -11
  81. package/dist/client/components/ui/scroll-fade.mjs +170 -0
  82. package/dist/client/components/ui/search-input.mjs +1 -1
  83. package/dist/client/components/ui/select.mjs +129 -27
  84. package/dist/client/components/ui/sheet.mjs +54 -34
  85. package/dist/client/components/ui/sidebar.mjs +15 -14
  86. package/dist/client/components/ui/skeleton.mjs +28 -12
  87. package/dist/client/components/ui/switch.mjs +2 -2
  88. package/dist/client/components/ui/table.mjs +82 -74
  89. package/dist/client/components/ui/tabs.mjs +26 -31
  90. package/dist/client/components/ui/textarea.mjs +1 -1
  91. package/dist/client/components/ui/tooltip.mjs +1 -1
  92. package/dist/client/components/widgets/chart-widget.mjs +134 -96
  93. package/dist/client/components/widgets/progress-widget.mjs +59 -34
  94. package/dist/client/components/widgets/quick-actions-widget.mjs +184 -113
  95. package/dist/client/components/widgets/recent-items-widget.mjs +144 -102
  96. package/dist/client/components/widgets/stats-widget.mjs +91 -72
  97. package/dist/client/components/widgets/table-widget.mjs +159 -246
  98. package/dist/client/components/widgets/timeline-widget.mjs +66 -43
  99. package/dist/client/components/widgets/value-widget.mjs +261 -152
  100. package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
  101. package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
  102. package/dist/client/contexts/focus-context.d.mts +2 -2
  103. package/dist/client/hooks/use-action.mjs +63 -55
  104. package/dist/client/hooks/use-audit-history.mjs +1 -65
  105. package/dist/client/hooks/use-collection-validation.mjs +36 -23
  106. package/dist/client/hooks/use-collection.mjs +96 -1
  107. package/dist/client/hooks/use-saved-views.mjs +70 -49
  108. package/dist/client/hooks/use-server-actions.mjs +59 -40
  109. package/dist/client/hooks/use-server-validation.mjs +156 -41
  110. package/dist/client/hooks/use-server-widget-data.mjs +1 -1
  111. package/dist/client/hooks/use-setup-status.d.mts +3 -3
  112. package/dist/client/hooks/use-setup-status.mjs +2 -2
  113. package/dist/client/hooks/use-transition-stage.mjs +2 -10
  114. package/dist/client/hooks/use-validation-error-map.mjs +31 -13
  115. package/dist/client/hooks/use-view-state.mjs +238 -174
  116. package/dist/client/i18n/date-locale.mjs +33 -0
  117. package/dist/client/i18n/hooks.mjs +17 -1
  118. package/dist/client/lib/utils.mjs +3 -2
  119. package/dist/client/preview/block-scope-context.d.mts +2 -2
  120. package/dist/client/preview/preview-banner.d.mts +2 -2
  121. package/dist/client/preview/preview-field.d.mts +4 -4
  122. package/dist/client/preview/preview-field.mjs +2 -2
  123. package/dist/client/runtime/provider.mjs +8 -1
  124. package/dist/client/runtime/translations-provider.mjs +1 -1
  125. package/dist/client/scope/picker.d.mts +2 -2
  126. package/dist/client/scope/provider.d.mts +2 -2
  127. package/dist/client/styles/base.css +1022 -0
  128. package/dist/client/styles/index.css +3 -589
  129. package/dist/client/utils/auto-expand-fields.mjs +4 -2
  130. package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
  131. package/dist/client/utils/use-lazy-component.mjs +80 -0
  132. package/dist/client/views/auth/auth-layout.d.mts +18 -11
  133. package/dist/client/views/auth/auth-layout.mjs +291 -80
  134. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  135. package/dist/client/views/auth/forgot-password-form.mjs +2 -2
  136. package/dist/client/views/auth/login-form.d.mts +2 -2
  137. package/dist/client/views/auth/login-form.mjs +1 -1
  138. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  139. package/dist/client/views/auth/reset-password-form.mjs +2 -2
  140. package/dist/client/views/auth/setup-form.d.mts +2 -2
  141. package/dist/client/views/collection/auto-form-fields.mjs +11 -9
  142. package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
  143. package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
  144. package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
  145. package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
  146. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
  147. package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
  148. package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
  149. package/dist/client/views/collection/columns/build-columns.mjs +29 -9
  150. package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
  151. package/dist/client/views/collection/field-renderer.mjs +50 -89
  152. package/dist/client/views/collection/form-view.mjs +237 -227
  153. package/dist/client/views/collection/table-view.mjs +1162 -229
  154. package/dist/client/views/collection/view-skeletons.mjs +222 -79
  155. package/dist/client/views/common/global-search.mjs +29 -18
  156. package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
  157. package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
  158. package/dist/client/views/dashboard/widget-card.mjs +23 -14
  159. package/dist/client/views/globals/global-form-view.mjs +634 -589
  160. package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
  161. package/dist/client/views/layout/admin-layout.d.mts +3 -6
  162. package/dist/client/views/layout/admin-layout.mjs +149 -172
  163. package/dist/client/views/layout/admin-router.mjs +747 -544
  164. package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
  165. package/dist/client/views/layout/admin-sidebar.mjs +751 -591
  166. package/dist/client/views/layout/admin-theme.d.mts +10 -0
  167. package/dist/client/views/layout/admin-theme.mjs +84 -0
  168. package/dist/client/views/layout/admin-view-layout.mjs +161 -0
  169. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  170. package/dist/client/views/pages/accept-invite-page.mjs +49 -26
  171. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  172. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  173. package/dist/client/views/pages/forgot-password-page.mjs +2 -19
  174. package/dist/client/views/pages/invite-page.d.mts +2 -2
  175. package/dist/client/views/pages/invite-page.mjs +2 -19
  176. package/dist/client/views/pages/login-page.d.mts +3 -3
  177. package/dist/client/views/pages/login-page.mjs +4 -21
  178. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  179. package/dist/client/views/pages/reset-password-page.mjs +3 -20
  180. package/dist/client/views/pages/setup-page.d.mts +2 -2
  181. package/dist/client/views/pages/setup-page.mjs +3 -20
  182. package/dist/client.d.mts +6 -2
  183. package/dist/client.mjs +2 -1
  184. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  185. package/dist/index.d.mts +6 -2
  186. package/dist/index.mjs +2 -1
  187. package/dist/server/augmentation/dashboard.d.mts +67 -3
  188. package/dist/server/augmentation/form-layout.d.mts +21 -0
  189. package/dist/server/augmentation/index.d.mts +1 -1
  190. package/dist/server/codegen/admin-client-template.mjs +4 -0
  191. package/dist/server/fields/blocks.d.mts +1 -1
  192. package/dist/server/fields/blocks.mjs +12 -0
  193. package/dist/server/fields/rich-text.d.mts +1 -1
  194. package/dist/server/fields/rich-text.mjs +8 -0
  195. package/dist/server/i18n/index.mjs +17 -1
  196. package/dist/server/i18n/messages/cs.mjs +23 -0
  197. package/dist/server/i18n/messages/de.mjs +23 -0
  198. package/dist/server/i18n/messages/en.mjs +64 -1
  199. package/dist/server/i18n/messages/es.mjs +23 -0
  200. package/dist/server/i18n/messages/fr.mjs +23 -0
  201. package/dist/server/i18n/messages/pl.mjs +23 -0
  202. package/dist/server/i18n/messages/pt.mjs +23 -0
  203. package/dist/server/i18n/messages/sk.mjs +83 -1
  204. package/dist/server/modules/admin/block/introspection.mjs +4 -1
  205. package/dist/server/modules/admin/block/prefetch.mjs +12 -2
  206. package/dist/server/modules/admin/collections/account.d.mts +50 -50
  207. package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
  208. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  209. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  210. package/dist/server/modules/admin/collections/apikey.d.mts +64 -64
  211. package/dist/server/modules/admin/collections/assets.d.mts +20 -20
  212. package/dist/server/modules/admin/collections/assets.mjs +0 -1
  213. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  214. package/dist/server/modules/admin/collections/user.d.mts +40 -28
  215. package/dist/server/modules/admin/collections/user.mjs +40 -9
  216. package/dist/server/modules/admin/collections/verification.d.mts +36 -36
  217. package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
  218. package/dist/server/modules/admin/factories.mjs +7 -18
  219. package/dist/server/modules/admin/index.d.mts +1 -1
  220. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  221. package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
  222. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  223. package/dist/server/modules/admin/routes/execute-action.mjs +33 -0
  224. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  225. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  226. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  227. package/dist/server/modules/admin/routes/setup.d.mts +10 -10
  228. package/dist/server/modules/admin/routes/setup.mjs +7 -7
  229. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  230. package/dist/server/modules/admin/routes/translations.mjs +5 -1
  231. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  232. package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
  233. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +25 -25
  234. package/dist/server/modules/audit/.generated/module.d.mts +7 -7
  235. package/dist/server/modules/audit/.generated/module.mjs +1 -1
  236. package/dist/server/modules/audit/collections/audit-log.d.mts +39 -39
  237. package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
  238. package/dist/server/modules/audit/config/app.mjs +99 -42
  239. package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
  240. package/dist/server/plugin.mjs +4 -2
  241. package/dist/server/proxy-factories.d.mts +4 -3
  242. package/dist/server/proxy-factories.mjs +34 -8
  243. package/dist/shared/types/saved-views.types.d.mts +2 -0
  244. package/package.json +6 -4
  245. package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
  246. package/dist/client/components/ui/spinner.mjs +0 -52
  247. package/dist/client/components/ui/toolbar.mjs +0 -136
  248. package/dist/client/contexts/breadcrumb-context.mjs +0 -60
  249. package/dist/client/views/layout/admin-topbar.mjs +0 -236
@@ -2,20 +2,163 @@ import { useResolveText, useTranslation } from "../../../i18n/hooks.mjs";
2
2
  import { cn } from "../../../lib/utils.mjs";
3
3
  import { LocaleBadge } from "../locale-badge.mjs";
4
4
  import { Label } from "../../ui/label.mjs";
5
+ import { Skeleton } from "../../ui/skeleton.mjs";
6
+ import { isModifierShortcut } from "../../../utils/keyboard-shortcuts.mjs";
7
+ import { createLinkAttributes, isLikelyLinkHref } from "./link-utils.mjs";
5
8
  import { RichTextToolbar } from "./toolbar.mjs";
6
9
  import { RichTextBubbleMenu } from "./bubble-menu.mjs";
7
10
  import { buildExtensions } from "./extensions.mjs";
11
+ import { getImageAltFromFile, getImageFilesFromDataTransfer, useRichTextImageUpload } from "./image-upload.mjs";
8
12
  import { ImagePopover } from "./image-popover.mjs";
9
- import { LinkPopover } from "./link-popover.mjs";
10
13
  import { mergePresetFeatures } from "./presets.mjs";
11
14
  import { defaultFeatures } from "./types.mjs";
12
15
  import { getCharacterCount, getHeadingLevel, getOutput, isSameValue } from "./utils.mjs";
13
16
  import { c } from "react/compiler-runtime";
14
17
  import * as React from "react";
15
18
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
19
+ import { toast } from "sonner";
16
20
  import { EditorContent, useEditor } from "@tiptap/react";
17
21
 
18
22
  //#region src/client/components/fields/rich-text-editor/index.tsx
23
+ function RichTextToolbarSkeleton() {
24
+ const $ = c(3);
25
+ let t0;
26
+ let t1;
27
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28
+ t0 = /* @__PURE__ */ jsxs("div", {
29
+ className: "flex items-center gap-1",
30
+ role: "presentation",
31
+ children: [/* @__PURE__ */ jsx(Skeleton, { className: "size-8" }), /* @__PURE__ */ jsx(Skeleton, { className: "size-8" })]
32
+ });
33
+ t1 = /* @__PURE__ */ jsx(Skeleton, { className: "h-8 min-w-[136px]" });
34
+ $[0] = t0;
35
+ $[1] = t1;
36
+ } else {
37
+ t0 = $[0];
38
+ t1 = $[1];
39
+ }
40
+ let t2;
41
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
42
+ t2 = /* @__PURE__ */ jsxs("div", {
43
+ className: "qp-rich-text-editor__toolbar border-border-subtle bg-surface-low flex flex-nowrap items-center gap-1.5 overflow-hidden border-b p-1.5",
44
+ "aria-hidden": "true",
45
+ children: [
46
+ t0,
47
+ t1,
48
+ /* @__PURE__ */ jsxs("div", {
49
+ className: "flex items-center gap-1",
50
+ role: "presentation",
51
+ children: [
52
+ /* @__PURE__ */ jsx(Skeleton, { className: "size-8" }),
53
+ /* @__PURE__ */ jsx(Skeleton, { className: "size-8" }),
54
+ /* @__PURE__ */ jsx(Skeleton, { className: "size-8" })
55
+ ]
56
+ }),
57
+ /* @__PURE__ */ jsx(Skeleton, { className: "size-8" }),
58
+ /* @__PURE__ */ jsx(Skeleton, { className: "size-8" })
59
+ ]
60
+ });
61
+ $[2] = t2;
62
+ } else t2 = $[2];
63
+ return t2;
64
+ }
65
+ function RichTextEditorContentSkeleton() {
66
+ const $ = c(4);
67
+ let t0;
68
+ let t1;
69
+ let t2;
70
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
71
+ t0 = /* @__PURE__ */ jsx(Skeleton, {
72
+ variant: "text",
73
+ className: "h-4 w-full max-w-[92%]"
74
+ });
75
+ t1 = /* @__PURE__ */ jsx(Skeleton, {
76
+ variant: "text",
77
+ className: "h-4 w-full max-w-[78%]"
78
+ });
79
+ t2 = /* @__PURE__ */ jsx(Skeleton, {
80
+ variant: "text",
81
+ className: "h-4 w-full max-w-[86%]"
82
+ });
83
+ $[0] = t0;
84
+ $[1] = t1;
85
+ $[2] = t2;
86
+ } else {
87
+ t0 = $[0];
88
+ t1 = $[1];
89
+ t2 = $[2];
90
+ }
91
+ let t3;
92
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
93
+ t3 = /* @__PURE__ */ jsxs("div", {
94
+ className: "qp-rich-text-editor__content space-y-3",
95
+ "aria-hidden": "true",
96
+ children: [
97
+ t0,
98
+ t1,
99
+ t2,
100
+ /* @__PURE__ */ jsx("div", {
101
+ className: "pt-3",
102
+ children: /* @__PURE__ */ jsx(Skeleton, {
103
+ variant: "text",
104
+ className: "h-4 w-full max-w-[58%]"
105
+ })
106
+ })
107
+ ]
108
+ });
109
+ $[3] = t3;
110
+ } else t3 = $[3];
111
+ return t3;
112
+ }
113
+ function RichTextEditorLoadingSkeleton(t0) {
114
+ const $ = c(10);
115
+ const { disabled, readOnly, error, showToolbar } = t0;
116
+ const t1 = disabled || readOnly ? "opacity-60" : "";
117
+ const t2 = error ? "border-destructive" : "border-border";
118
+ let t3;
119
+ if ($[0] !== t1 || $[1] !== t2) {
120
+ t3 = cn("qp-rich-text-editor control-surface h-auto min-h-[160px] overflow-hidden", t1, t2);
121
+ $[0] = t1;
122
+ $[1] = t2;
123
+ $[2] = t3;
124
+ } else t3 = $[2];
125
+ let t4;
126
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
127
+ t4 = /* @__PURE__ */ jsx("span", {
128
+ className: "sr-only",
129
+ children: "Loading editor"
130
+ });
131
+ $[3] = t4;
132
+ } else t4 = $[3];
133
+ let t5;
134
+ if ($[4] !== showToolbar) {
135
+ t5 = showToolbar && /* @__PURE__ */ jsx(RichTextToolbarSkeleton, {});
136
+ $[4] = showToolbar;
137
+ $[5] = t5;
138
+ } else t5 = $[5];
139
+ let t6;
140
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
141
+ t6 = /* @__PURE__ */ jsx(RichTextEditorContentSkeleton, {});
142
+ $[6] = t6;
143
+ } else t6 = $[6];
144
+ let t7;
145
+ if ($[7] !== t3 || $[8] !== t5) {
146
+ t7 = /* @__PURE__ */ jsxs("div", {
147
+ className: t3,
148
+ "data-admin-rich-text-editor": "root",
149
+ "aria-busy": "true",
150
+ children: [
151
+ t4,
152
+ t5,
153
+ t6
154
+ ]
155
+ });
156
+ $[7] = t3;
157
+ $[8] = t5;
158
+ $[9] = t7;
159
+ } else t7 = $[9];
160
+ return t7;
161
+ }
19
162
  /**
20
163
  * Main RichText Editor Component.
21
164
  *
@@ -25,7 +168,7 @@ import { EditorContent, useEditor } from "@tiptap/react";
25
168
  * "Schema is missing its top node type" error.
26
169
  */
27
170
  function RichTextEditor(t0) {
28
- const $ = c(56);
171
+ const $ = c(119);
29
172
  const { name, value, onChange, disabled, readOnly, label, description, placeholder, required, error, localized, locale, extensions, preset, features, showCharacterCount, maxCharacters, enableImages, onImageUpload, imageCollection, enableMediaLibrary } = t0;
30
173
  const { t } = useTranslation();
31
174
  const resolveText = useResolveText();
@@ -45,57 +188,221 @@ function RichTextEditor(t0) {
45
188
  $[5] = t2;
46
189
  } else t2 = $[5];
47
190
  const resolvedDescription = t2;
191
+ const descriptionId = resolvedDescription ? `${name}-description` : void 0;
192
+ const errorId = error ? `${name}-error` : void 0;
48
193
  let t3;
194
+ if ($[6] !== descriptionId || $[7] !== errorId) {
195
+ t3 = [descriptionId, errorId].filter(Boolean);
196
+ $[6] = descriptionId;
197
+ $[7] = errorId;
198
+ $[8] = t3;
199
+ } else t3 = $[8];
200
+ const describedBy = t3.join(" ");
201
+ let t4;
49
202
  bb0: {
50
203
  if (preset) {
51
- let t4$2;
52
- if ($[6] !== features || $[7] !== preset) {
53
- t4$2 = mergePresetFeatures(preset, features);
54
- $[6] = features;
55
- $[7] = preset;
56
- $[8] = t4$2;
57
- } else t4$2 = $[8];
58
- t3 = t4$2;
204
+ let t5$2;
205
+ if ($[9] !== features || $[10] !== preset) {
206
+ t5$2 = mergePresetFeatures(preset, features);
207
+ $[9] = features;
208
+ $[10] = preset;
209
+ $[11] = t5$2;
210
+ } else t5$2 = $[11];
211
+ t4 = t5$2;
59
212
  break bb0;
60
213
  }
61
- let t4$1;
62
- if ($[9] !== features) {
63
- t4$1 = {
214
+ let t5$1;
215
+ if ($[12] !== features) {
216
+ t5$1 = {
64
217
  ...defaultFeatures,
65
218
  ...features
66
219
  };
67
- $[9] = features;
68
- $[10] = t4$1;
69
- } else t4$1 = $[10];
70
- t3 = t4$1;
220
+ $[12] = features;
221
+ $[13] = t5$1;
222
+ } else t5$1 = $[13];
223
+ t4 = t5$1;
71
224
  }
72
- const resolvedFeatures = t3;
73
- let t4;
74
- if ($[11] !== extensions || $[12] !== maxCharacters || $[13] !== placeholder || $[14] !== resolvedFeatures || $[15] !== t) {
75
- t4 = () => {
225
+ const resolvedFeatures = t4;
226
+ let t5;
227
+ if ($[14] !== t) {
228
+ t5 = t("editor.unorderedList");
229
+ $[14] = t;
230
+ $[15] = t5;
231
+ } else t5 = $[15];
232
+ let t6;
233
+ if ($[16] !== t) {
234
+ t6 = t("editor.bulletListDescription");
235
+ $[16] = t;
236
+ $[17] = t6;
237
+ } else t6 = $[17];
238
+ let t7;
239
+ if ($[18] !== t) {
240
+ t7 = t("editor.codeBlock");
241
+ $[18] = t;
242
+ $[19] = t7;
243
+ } else t7 = $[19];
244
+ let t8;
245
+ if ($[20] !== t) {
246
+ t8 = t("editor.codeBlockDescription");
247
+ $[20] = t;
248
+ $[21] = t8;
249
+ } else t8 = $[21];
250
+ let t9;
251
+ if ($[22] !== t) {
252
+ t9 = t("editor.horizontalRule");
253
+ $[22] = t;
254
+ $[23] = t9;
255
+ } else t9 = $[23];
256
+ let t10;
257
+ if ($[24] !== t) {
258
+ t10 = t("editor.dividerDescription");
259
+ $[24] = t;
260
+ $[25] = t10;
261
+ } else t10 = $[25];
262
+ let t11;
263
+ let t12;
264
+ if ($[26] !== t) {
265
+ t11 = (level) => t("editor.heading", { level });
266
+ t12 = t("editor.heading1Description");
267
+ $[26] = t;
268
+ $[27] = t11;
269
+ $[28] = t12;
270
+ } else {
271
+ t11 = $[27];
272
+ t12 = $[28];
273
+ }
274
+ let t13;
275
+ if ($[29] !== t) {
276
+ t13 = t("editor.heading2Description");
277
+ $[29] = t;
278
+ $[30] = t13;
279
+ } else t13 = $[30];
280
+ let t14;
281
+ if ($[31] !== t) {
282
+ t14 = t("editor.heading3Description");
283
+ $[31] = t;
284
+ $[32] = t14;
285
+ } else t14 = $[32];
286
+ let t15;
287
+ if ($[33] !== t) {
288
+ t15 = t("editor.orderedList");
289
+ $[33] = t;
290
+ $[34] = t15;
291
+ } else t15 = $[34];
292
+ let t16;
293
+ if ($[35] !== t) {
294
+ t16 = t("editor.orderedListDescription");
295
+ $[35] = t;
296
+ $[36] = t16;
297
+ } else t16 = $[36];
298
+ let t17;
299
+ if ($[37] !== t) {
300
+ t17 = t("editor.paragraph");
301
+ $[37] = t;
302
+ $[38] = t17;
303
+ } else t17 = $[38];
304
+ let t18;
305
+ if ($[39] !== t) {
306
+ t18 = t("editor.paragraphDescription");
307
+ $[39] = t;
308
+ $[40] = t18;
309
+ } else t18 = $[40];
310
+ let t19;
311
+ if ($[41] !== t) {
312
+ t19 = t("editor.quote");
313
+ $[41] = t;
314
+ $[42] = t19;
315
+ } else t19 = $[42];
316
+ let t20;
317
+ if ($[43] !== t) {
318
+ t20 = t("editor.quoteDescription");
319
+ $[43] = t;
320
+ $[44] = t20;
321
+ } else t20 = $[44];
322
+ let t21;
323
+ if ($[45] !== t) {
324
+ t21 = t("editor.table");
325
+ $[45] = t;
326
+ $[46] = t21;
327
+ } else t21 = $[46];
328
+ let t22;
329
+ if ($[47] !== t) {
330
+ t22 = t("editor.tableDescription");
331
+ $[47] = t;
332
+ $[48] = t22;
333
+ } else t22 = $[48];
334
+ let t23;
335
+ if ($[49] !== t10 || $[50] !== t11 || $[51] !== t12 || $[52] !== t13 || $[53] !== t14 || $[54] !== t15 || $[55] !== t16 || $[56] !== t17 || $[57] !== t18 || $[58] !== t19 || $[59] !== t20 || $[60] !== t21 || $[61] !== t22 || $[62] !== t5 || $[63] !== t6 || $[64] !== t7 || $[65] !== t8 || $[66] !== t9) {
336
+ t23 = {
337
+ bulletList: t5,
338
+ bulletListDescription: t6,
339
+ codeBlock: t7,
340
+ codeBlockDescription: t8,
341
+ divider: t9,
342
+ dividerDescription: t10,
343
+ heading: t11,
344
+ heading1Description: t12,
345
+ heading2Description: t13,
346
+ heading3Description: t14,
347
+ orderedList: t15,
348
+ orderedListDescription: t16,
349
+ paragraph: t17,
350
+ paragraphDescription: t18,
351
+ quote: t19,
352
+ quoteDescription: t20,
353
+ table: t21,
354
+ tableDescription: t22
355
+ };
356
+ $[49] = t10;
357
+ $[50] = t11;
358
+ $[51] = t12;
359
+ $[52] = t13;
360
+ $[53] = t14;
361
+ $[54] = t15;
362
+ $[55] = t16;
363
+ $[56] = t17;
364
+ $[57] = t18;
365
+ $[58] = t19;
366
+ $[59] = t20;
367
+ $[60] = t21;
368
+ $[61] = t22;
369
+ $[62] = t5;
370
+ $[63] = t6;
371
+ $[64] = t7;
372
+ $[65] = t8;
373
+ $[66] = t9;
374
+ $[67] = t23;
375
+ } else t23 = $[67];
376
+ const extensionLabels = t23;
377
+ let t24;
378
+ if ($[68] !== extensionLabels || $[69] !== extensions || $[70] !== maxCharacters || $[71] !== placeholder || $[72] !== resolvedFeatures || $[73] !== t) {
379
+ t24 = () => {
76
380
  const result = buildExtensions({
77
381
  features: resolvedFeatures,
382
+ labels: extensionLabels,
78
383
  placeholder: placeholder || t("editor.startWriting"),
79
384
  maxCharacters,
80
385
  customExtensions: extensions
81
386
  });
82
387
  return result instanceof Promise ? void 0 : result;
83
388
  };
84
- $[11] = extensions;
85
- $[12] = maxCharacters;
86
- $[13] = placeholder;
87
- $[14] = resolvedFeatures;
88
- $[15] = t;
89
- $[16] = t4;
90
- } else t4 = $[16];
91
- const [resolvedExtensions, setResolvedExtensions] = React.useState(t4);
92
- let t5;
93
- let t6;
94
- if ($[17] !== extensions || $[18] !== maxCharacters || $[19] !== placeholder || $[20] !== resolvedFeatures || $[21] !== t) {
95
- t5 = () => {
389
+ $[68] = extensionLabels;
390
+ $[69] = extensions;
391
+ $[70] = maxCharacters;
392
+ $[71] = placeholder;
393
+ $[72] = resolvedFeatures;
394
+ $[73] = t;
395
+ $[74] = t24;
396
+ } else t24 = $[74];
397
+ const [resolvedExtensions, setResolvedExtensions] = React.useState(t24);
398
+ let t25;
399
+ let t26;
400
+ if ($[75] !== extensionLabels || $[76] !== extensions || $[77] !== maxCharacters || $[78] !== placeholder || $[79] !== resolvedFeatures || $[80] !== t) {
401
+ t25 = () => {
96
402
  let mounted = true;
97
403
  const result_0 = buildExtensions({
98
404
  features: resolvedFeatures,
405
+ labels: extensionLabels,
99
406
  placeholder: placeholder || t("editor.startWriting"),
100
407
  maxCharacters,
101
408
  customExtensions: extensions
@@ -108,29 +415,31 @@ function RichTextEditor(t0) {
108
415
  mounted = false;
109
416
  };
110
417
  };
111
- t6 = [
418
+ t26 = [
112
419
  resolvedFeatures,
420
+ extensionLabels,
113
421
  placeholder,
114
422
  maxCharacters,
115
423
  extensions,
116
424
  t
117
425
  ];
118
- $[17] = extensions;
119
- $[18] = maxCharacters;
120
- $[19] = placeholder;
121
- $[20] = resolvedFeatures;
122
- $[21] = t;
123
- $[22] = t5;
124
- $[23] = t6;
426
+ $[75] = extensionLabels;
427
+ $[76] = extensions;
428
+ $[77] = maxCharacters;
429
+ $[78] = placeholder;
430
+ $[79] = resolvedFeatures;
431
+ $[80] = t;
432
+ $[81] = t25;
433
+ $[82] = t26;
125
434
  } else {
126
- t5 = $[22];
127
- t6 = $[23];
435
+ t25 = $[81];
436
+ t26 = $[82];
128
437
  }
129
- React.useEffect(t5, t6);
130
- const t7 = disabled || readOnly;
131
- let t8;
132
- if ($[24] !== locale || $[25] !== localized || $[26] !== name || $[27] !== required || $[28] !== resolvedLabel) {
133
- t8 = resolvedLabel && /* @__PURE__ */ jsxs("div", {
438
+ React.useEffect(t25, t26);
439
+ const t27 = disabled || readOnly;
440
+ let t28;
441
+ if ($[83] !== locale || $[84] !== localized || $[85] !== name || $[86] !== required || $[87] !== resolvedLabel) {
442
+ t28 = resolvedLabel && /* @__PURE__ */ jsxs("div", {
134
443
  className: "flex items-center gap-2",
135
444
  children: [/* @__PURE__ */ jsxs(Label, {
136
445
  htmlFor: name,
@@ -140,17 +449,19 @@ function RichTextEditor(t0) {
140
449
  })]
141
450
  }), localized && /* @__PURE__ */ jsx(LocaleBadge, { locale: locale || "i18n" })]
142
451
  });
143
- $[24] = locale;
144
- $[25] = localized;
145
- $[26] = name;
146
- $[27] = required;
147
- $[28] = resolvedLabel;
148
- $[29] = t8;
149
- } else t8 = $[29];
150
- let t9;
151
- if ($[30] !== disabled || $[31] !== enableImages || $[32] !== enableMediaLibrary || $[33] !== error || $[34] !== imageCollection || $[35] !== locale || $[36] !== maxCharacters || $[37] !== name || $[38] !== onChange || $[39] !== onImageUpload || $[40] !== readOnly || $[41] !== resolvedExtensions || $[42] !== resolvedFeatures || $[43] !== showCharacterCount || $[44] !== value) {
152
- t9 = resolvedExtensions ? /* @__PURE__ */ jsx(RichTextEditorCore, {
452
+ $[83] = locale;
453
+ $[84] = localized;
454
+ $[85] = name;
455
+ $[86] = required;
456
+ $[87] = resolvedLabel;
457
+ $[88] = t28;
458
+ } else t28 = $[88];
459
+ let t29;
460
+ if ($[89] !== describedBy || $[90] !== disabled || $[91] !== enableImages || $[92] !== enableMediaLibrary || $[93] !== error || $[94] !== imageCollection || $[95] !== locale || $[96] !== maxCharacters || $[97] !== name || $[98] !== onChange || $[99] !== onImageUpload || $[100] !== readOnly || $[101] !== resolvedExtensions || $[102] !== resolvedFeatures || $[103] !== resolvedLabel || $[104] !== showCharacterCount || $[105] !== value) {
461
+ t29 = resolvedExtensions ? /* @__PURE__ */ jsx(RichTextEditorCore, {
153
462
  name,
463
+ ariaLabel: resolvedLabel ?? name,
464
+ ariaDescribedBy: describedBy || void 0,
154
465
  value,
155
466
  onChange,
156
467
  disabled,
@@ -165,355 +476,305 @@ function RichTextEditor(t0) {
165
476
  onImageUpload,
166
477
  imageCollection,
167
478
  enableMediaLibrary
168
- }) : /* @__PURE__ */ jsx("div", {
169
- className: cn("qp-rich-text-editor bg-transparent border border-input", disabled || readOnly ? "opacity-60" : "", error ? "border-destructive" : "border-border"),
170
- children: /* @__PURE__ */ jsx("div", {
171
- className: "text-muted-foreground flex min-h-[120px] items-center justify-center text-sm",
172
- children: "Loading editor..."
173
- })
479
+ }) : /* @__PURE__ */ jsx(RichTextEditorLoadingSkeleton, {
480
+ disabled,
481
+ readOnly,
482
+ error,
483
+ showToolbar: resolvedFeatures.toolbar
174
484
  });
175
- $[30] = disabled;
176
- $[31] = enableImages;
177
- $[32] = enableMediaLibrary;
178
- $[33] = error;
179
- $[34] = imageCollection;
180
- $[35] = locale;
181
- $[36] = maxCharacters;
182
- $[37] = name;
183
- $[38] = onChange;
184
- $[39] = onImageUpload;
185
- $[40] = readOnly;
186
- $[41] = resolvedExtensions;
187
- $[42] = resolvedFeatures;
188
- $[43] = showCharacterCount;
189
- $[44] = value;
190
- $[45] = t9;
191
- } else t9 = $[45];
192
- let t10;
193
- if ($[46] !== resolvedDescription) {
194
- t10 = resolvedDescription && /* @__PURE__ */ jsx("p", {
485
+ $[89] = describedBy;
486
+ $[90] = disabled;
487
+ $[91] = enableImages;
488
+ $[92] = enableMediaLibrary;
489
+ $[93] = error;
490
+ $[94] = imageCollection;
491
+ $[95] = locale;
492
+ $[96] = maxCharacters;
493
+ $[97] = name;
494
+ $[98] = onChange;
495
+ $[99] = onImageUpload;
496
+ $[100] = readOnly;
497
+ $[101] = resolvedExtensions;
498
+ $[102] = resolvedFeatures;
499
+ $[103] = resolvedLabel;
500
+ $[104] = showCharacterCount;
501
+ $[105] = value;
502
+ $[106] = t29;
503
+ } else t29 = $[106];
504
+ let t30;
505
+ if ($[107] !== descriptionId || $[108] !== resolvedDescription) {
506
+ t30 = resolvedDescription && /* @__PURE__ */ jsx("p", {
507
+ id: descriptionId,
195
508
  className: "text-muted-foreground text-xs",
196
509
  children: resolvedDescription
197
510
  });
198
- $[46] = resolvedDescription;
199
- $[47] = t10;
200
- } else t10 = $[47];
201
- let t11;
202
- if ($[48] !== error) {
203
- t11 = error && /* @__PURE__ */ jsx("p", {
511
+ $[107] = descriptionId;
512
+ $[108] = resolvedDescription;
513
+ $[109] = t30;
514
+ } else t30 = $[109];
515
+ let t31;
516
+ if ($[110] !== error || $[111] !== errorId) {
517
+ t31 = error && /* @__PURE__ */ jsx("p", {
518
+ id: errorId,
204
519
  className: "text-destructive text-xs",
205
520
  children: error
206
521
  });
207
- $[48] = error;
208
- $[49] = t11;
209
- } else t11 = $[49];
210
- let t12;
211
- if ($[50] !== t10 || $[51] !== t11 || $[52] !== t7 || $[53] !== t8 || $[54] !== t9) {
212
- t12 = /* @__PURE__ */ jsxs("div", {
522
+ $[110] = error;
523
+ $[111] = errorId;
524
+ $[112] = t31;
525
+ } else t31 = $[112];
526
+ let t32;
527
+ if ($[113] !== t27 || $[114] !== t28 || $[115] !== t29 || $[116] !== t30 || $[117] !== t31) {
528
+ t32 = /* @__PURE__ */ jsxs("div", {
213
529
  className: "space-y-2",
214
- "data-disabled": t7,
530
+ "data-disabled": t27,
215
531
  children: [
216
- t8,
217
- t9,
218
- t10,
219
- t11
532
+ t28,
533
+ t29,
534
+ t30,
535
+ t31
220
536
  ]
221
537
  });
222
- $[50] = t10;
223
- $[51] = t11;
224
- $[52] = t7;
225
- $[53] = t8;
226
- $[54] = t9;
227
- $[55] = t12;
228
- } else t12 = $[55];
229
- return t12;
538
+ $[113] = t27;
539
+ $[114] = t28;
540
+ $[115] = t29;
541
+ $[116] = t30;
542
+ $[117] = t31;
543
+ $[118] = t32;
544
+ } else t32 = $[118];
545
+ return t32;
230
546
  }
231
547
  /**
232
548
  * Core editor — only mounts when extensions are ready.
233
549
  * `useEditor` always receives a complete extension list, so the ProseMirror
234
550
  * schema always has its `doc` node.
235
551
  */
236
- function RichTextEditorCore(t0) {
237
- const $ = c(73);
238
- const { name, value, onChange, disabled, readOnly, error, locale, features, resolvedExtensions, showCharacterCount, maxCharacters, enableImages, onImageUpload, imageCollection, enableMediaLibrary } = t0;
552
+ function RichTextEditorCore({ name, ariaLabel, ariaDescribedBy, value, onChange, disabled, readOnly, error, locale, features, resolvedExtensions, showCharacterCount, maxCharacters, enableImages, onImageUpload, imageCollection, enableMediaLibrary }) {
553
+ const { t } = useTranslation();
239
554
  const [linkOpen, setLinkOpen] = React.useState(false);
240
555
  const [imageOpen, setImageOpen] = React.useState(false);
556
+ const [uploadingInlineImage, setUploadingInlineImage] = React.useState(false);
241
557
  const lastEmittedValueRef = React.useRef(void 0);
558
+ const editorRef = React.useRef(null);
242
559
  const allowImages = features.image && (enableImages ?? true);
243
560
  const allowLinks = features.link;
244
561
  const allowBubbleMenu = features.bubbleMenu;
245
562
  const allowToolbar = features.toolbar;
246
563
  const allowCharacterCount = features.characterCount && (showCharacterCount || maxCharacters);
247
564
  const isEditable = !disabled && !readOnly;
248
- const t1 = value ?? "";
249
- let t2;
250
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
251
- t2 = { attributes: { class: "qp-rich-text-editor__content" } };
252
- $[0] = t2;
253
- } else t2 = $[0];
254
- let t3;
255
- if ($[1] !== disabled || $[2] !== onChange || $[3] !== readOnly) {
256
- t3 = (t4$1) => {
257
- const { editor: currentEditor } = t4$1;
565
+ const editorStateRef = React.useRef({
566
+ allowImages,
567
+ allowLinks,
568
+ isEditable
569
+ });
570
+ editorStateRef.current = {
571
+ allowImages,
572
+ allowLinks,
573
+ isEditable
574
+ };
575
+ const { uploadImageFile } = useRichTextImageUpload({
576
+ imageCollection,
577
+ onImageUpload
578
+ });
579
+ const insertUploadedImages = React.useCallback(async (files, options) => {
580
+ const currentEditor = editorRef.current;
581
+ if (!currentEditor || files.length === 0) return;
582
+ try {
583
+ setUploadingInlineImage(true);
584
+ const imageNodes = [];
585
+ for (const file of files) {
586
+ const url = await uploadImageFile(file);
587
+ imageNodes.push({
588
+ type: "image",
589
+ attrs: {
590
+ src: url,
591
+ alt: getImageAltFromFile(file)
592
+ }
593
+ });
594
+ }
595
+ if (imageNodes.length === 0) return;
596
+ const chain = currentEditor.chain().focus();
597
+ if (typeof options?.position === "number") chain.insertContentAt(options.position, imageNodes).run();
598
+ else chain.insertContent(imageNodes).run();
599
+ } catch (err) {
600
+ const error_0 = err instanceof Error ? err : new Error(t("upload.error"));
601
+ toast.error(error_0.message);
602
+ } finally {
603
+ setUploadingInlineImage(false);
604
+ }
605
+ }, [t, uploadImageFile]);
606
+ const handleEditorPaste = React.useCallback((event) => {
607
+ const currentEditor_0 = editorRef.current;
608
+ const state = editorStateRef.current;
609
+ if (!currentEditor_0 || !state.isEditable) return false;
610
+ const imageFiles = getImageFilesFromDataTransfer(event.clipboardData);
611
+ if (state.allowImages && imageFiles.length > 0) {
612
+ event.preventDefault();
613
+ insertUploadedImages(imageFiles);
614
+ return true;
615
+ }
616
+ const pastedText = event.clipboardData?.getData("text/plain") ?? "";
617
+ if (state.allowLinks && isLikelyLinkHref(pastedText) && !currentEditor_0.state.selection.empty) {
618
+ event.preventDefault();
619
+ currentEditor_0.chain().focus().extendMarkRange("link").setLink(createLinkAttributes(pastedText)).run();
620
+ return true;
621
+ }
622
+ return false;
623
+ }, [insertUploadedImages]);
624
+ const handleEditorDrop = React.useCallback((view, event_0, moved) => {
625
+ const state_0 = editorStateRef.current;
626
+ if (moved || !state_0.isEditable || !state_0.allowImages) return false;
627
+ const imageFiles_0 = getImageFilesFromDataTransfer(event_0.dataTransfer);
628
+ if (imageFiles_0.length === 0) return false;
629
+ event_0.preventDefault();
630
+ const position = view.posAtCoords({
631
+ left: event_0.clientX,
632
+ top: event_0.clientY
633
+ })?.pos;
634
+ insertUploadedImages(imageFiles_0, { position });
635
+ return true;
636
+ }, [insertUploadedImages]);
637
+ const handleEditorKeyDown = React.useCallback((event_1) => {
638
+ if (!isModifierShortcut(event_1)) return false;
639
+ const key = event_1.key.toLowerCase();
640
+ if (key === "k" && allowLinks && isEditable) {
641
+ event_1.preventDefault();
642
+ event_1.stopPropagation();
643
+ setLinkOpen(true);
644
+ return true;
645
+ }
646
+ if ([
647
+ "b",
648
+ "e",
649
+ "i",
650
+ "u",
651
+ "y",
652
+ "z"
653
+ ].includes(key)) event_1.stopPropagation();
654
+ return false;
655
+ }, [allowLinks, isEditable]);
656
+ const editor = useEditor({
657
+ extensions: resolvedExtensions,
658
+ content: value ?? "",
659
+ editorProps: {
660
+ attributes: {
661
+ class: "qp-rich-text-editor__content",
662
+ "aria-label": ariaLabel ?? name,
663
+ "aria-multiline": "true",
664
+ "data-admin-rich-text-editor": "content",
665
+ role: "textbox",
666
+ ...ariaDescribedBy ? { "aria-describedby": ariaDescribedBy } : {},
667
+ ...error ? { "aria-invalid": "true" } : {}
668
+ },
669
+ handleKeyDown: (_view, event_2) => handleEditorKeyDown(event_2),
670
+ handlePaste: (_view_0, event_3) => handleEditorPaste(event_3),
671
+ handleDrop: (view_0, event_4, _slice, moved_0) => handleEditorDrop(view_0, event_4, moved_0)
672
+ },
673
+ editable: isEditable,
674
+ onUpdate: ({ editor: currentEditor_1 }) => {
258
675
  if (disabled || readOnly) return;
259
- const nextValue = getOutput(currentEditor);
676
+ const nextValue = getOutput(currentEditor_1);
260
677
  lastEmittedValueRef.current = nextValue;
261
678
  onChange?.(nextValue);
679
+ }
680
+ });
681
+ React.useEffect(() => {
682
+ editorRef.current = editor;
683
+ return () => {
684
+ if (editorRef.current === editor) editorRef.current = null;
262
685
  };
263
- $[1] = disabled;
264
- $[2] = onChange;
265
- $[3] = readOnly;
266
- $[4] = t3;
267
- } else t3 = $[4];
268
- let t4;
269
- if ($[5] !== isEditable || $[6] !== resolvedExtensions || $[7] !== t1 || $[8] !== t3) {
270
- t4 = {
271
- extensions: resolvedExtensions,
272
- content: t1,
273
- editorProps: t2,
274
- editable: isEditable,
275
- onUpdate: t3
276
- };
277
- $[5] = isEditable;
278
- $[6] = resolvedExtensions;
279
- $[7] = t1;
280
- $[8] = t3;
281
- $[9] = t4;
282
- } else t4 = $[9];
283
- const editor = useEditor(t4);
284
- let t5;
285
- if ($[10] !== editor) {
286
- t5 = getHeadingLevel(editor);
287
- $[10] = editor;
288
- $[11] = t5;
289
- } else t5 = $[11];
290
- const headingValue = t5;
291
- let t6;
292
- if ($[12] !== editor) {
293
- t6 = editor?.isActive("table") ?? false;
294
- $[12] = editor;
295
- $[13] = t6;
296
- } else t6 = $[13];
297
- const inTable = t6;
298
- let t7;
299
- let t8;
300
- if ($[14] !== editor || $[15] !== isEditable) {
301
- t7 = () => {
302
- if (!editor) return;
303
- editor.setEditable(isEditable);
304
- };
305
- t8 = [editor, isEditable];
306
- $[14] = editor;
307
- $[15] = isEditable;
308
- $[16] = t7;
309
- $[17] = t8;
310
- } else {
311
- t7 = $[16];
312
- t8 = $[17];
313
- }
314
- React.useEffect(t7, t8);
686
+ }, [editor]);
687
+ const headingValue = getHeadingLevel(editor);
688
+ const inTable = editor?.isActive("table") ?? false;
689
+ React.useEffect(() => {
690
+ if (!editor) return;
691
+ editor.setEditable(isEditable);
692
+ }, [editor, isEditable]);
315
693
  const prevLocaleRef = React.useRef(locale);
316
- let t10;
317
- let t9;
318
- if ($[18] !== locale) {
319
- t9 = () => {
320
- if (prevLocaleRef.current !== locale) {
321
- prevLocaleRef.current = locale;
322
- lastEmittedValueRef.current = void 0;
323
- }
324
- };
325
- t10 = [locale];
326
- $[18] = locale;
327
- $[19] = t10;
328
- $[20] = t9;
329
- } else {
330
- t10 = $[19];
331
- t9 = $[20];
332
- }
333
- React.useEffect(t9, t10);
334
- let t11;
335
- let t12;
336
- if ($[21] !== editor || $[22] !== value) {
337
- t11 = () => {
338
- if (!editor) return;
339
- if (value === void 0) return;
340
- if (isSameValue(value, lastEmittedValueRef.current)) return;
341
- lastEmittedValueRef.current = value;
342
- editor.commands.setContent(value ?? "", false);
343
- };
344
- t12 = [editor, value];
345
- $[21] = editor;
346
- $[22] = value;
347
- $[23] = t11;
348
- $[24] = t12;
349
- } else {
350
- t11 = $[23];
351
- t12 = $[24];
352
- }
353
- React.useEffect(t11, t12);
354
- let t13;
355
- if ($[25] !== editor) {
356
- t13 = getCharacterCount(editor);
357
- $[25] = editor;
358
- $[26] = t13;
359
- } else t13 = $[26];
360
- const characterCount = t13;
361
- const t14 = disabled || readOnly ? "opacity-60" : "";
362
- const t15 = error ? "border-destructive" : "border-border";
363
- let t16;
364
- if ($[27] !== t14 || $[28] !== t15) {
365
- t16 = cn("qp-rich-text-editor bg-transparent border border-input", t14, t15);
366
- $[27] = t14;
367
- $[28] = t15;
368
- $[29] = t16;
369
- } else t16 = $[29];
370
- let t17;
371
- if ($[30] !== allowToolbar || $[31] !== editor || $[32] !== features || $[33] !== headingValue || $[34] !== inTable || $[35] !== isEditable) {
372
- t17 = editor && allowToolbar && /* @__PURE__ */ jsx(RichTextToolbar, {
373
- editor,
374
- features,
375
- disabled: !isEditable,
376
- headingValue,
377
- onHeadingChange: (value_0) => {
378
- if (!editor) return;
379
- if (value_0 === "paragraph") {
380
- editor.chain().focus().setParagraph().run();
381
- return;
382
- }
383
- editor.chain().focus().toggleHeading({ level: Number(value_0) }).run();
384
- },
385
- onLinkClick: () => setLinkOpen(true),
386
- onImageClick: () => setImageOpen(true),
387
- onTableClick: () => {
388
- if (!inTable) editor.chain().focus().insertTable({
389
- rows: 3,
390
- cols: 3,
391
- withHeaderRow: true
392
- }).run();
393
- },
394
- inTable
395
- });
396
- $[30] = allowToolbar;
397
- $[31] = editor;
398
- $[32] = features;
399
- $[33] = headingValue;
400
- $[34] = inTable;
401
- $[35] = isEditable;
402
- $[36] = t17;
403
- } else t17 = $[36];
404
- let t18;
405
- if ($[37] !== allowBubbleMenu || $[38] !== editor || $[39] !== features || $[40] !== isEditable) {
406
- t18 = editor && allowBubbleMenu && /* @__PURE__ */ jsx(RichTextBubbleMenu, {
407
- editor,
408
- features,
409
- disabled: !isEditable,
410
- onLinkClick: () => setLinkOpen(true)
411
- });
412
- $[37] = allowBubbleMenu;
413
- $[38] = editor;
414
- $[39] = features;
415
- $[40] = isEditable;
416
- $[41] = t18;
417
- } else t18 = $[41];
418
- let t19;
419
- if ($[42] !== editor || $[43] !== name) {
420
- t19 = editor ? /* @__PURE__ */ jsx(EditorContent, {
421
- editor,
422
- id: name
423
- }) : /* @__PURE__ */ jsx("div", {
424
- className: "text-muted-foreground flex min-h-[120px] items-center justify-center text-sm",
425
- children: "Loading editor..."
426
- });
427
- $[42] = editor;
428
- $[43] = name;
429
- $[44] = t19;
430
- } else t19 = $[44];
431
- let t20;
432
- if ($[45] !== allowCharacterCount || $[46] !== characterCount || $[47] !== maxCharacters || $[48] !== showCharacterCount) {
433
- t20 = allowCharacterCount && showCharacterCount && /* @__PURE__ */ jsxs("div", {
434
- className: "bg-muted text-muted-foreground flex items-center justify-between border-t px-2 py-1 text-xs",
435
- children: [/* @__PURE__ */ jsxs("span", { children: [
436
- characterCount.words,
437
- " word",
438
- characterCount.words === 1 ? "" : "s"
439
- ] }), /* @__PURE__ */ jsxs("span", { children: [
440
- characterCount.characters,
441
- typeof maxCharacters === "number" ? ` / ${maxCharacters}` : "",
442
- " ",
443
- "characters"
444
- ] })]
445
- });
446
- $[45] = allowCharacterCount;
447
- $[46] = characterCount;
448
- $[47] = maxCharacters;
449
- $[48] = showCharacterCount;
450
- $[49] = t20;
451
- } else t20 = $[49];
452
- let t21;
453
- if ($[50] !== t16 || $[51] !== t17 || $[52] !== t18 || $[53] !== t19 || $[54] !== t20) {
454
- t21 = /* @__PURE__ */ jsxs("div", {
455
- className: t16,
456
- children: [
457
- t17,
458
- t18,
459
- t19,
460
- t20
461
- ]
462
- });
463
- $[50] = t16;
464
- $[51] = t17;
465
- $[52] = t18;
466
- $[53] = t19;
467
- $[54] = t20;
468
- $[55] = t21;
469
- } else t21 = $[55];
470
- let t22;
471
- if ($[56] !== allowLinks || $[57] !== editor || $[58] !== isEditable || $[59] !== linkOpen) {
472
- t22 = allowLinks && /* @__PURE__ */ jsx(LinkPopover, {
473
- editor,
474
- open: linkOpen,
475
- onOpenChange: setLinkOpen,
476
- disabled: !isEditable
477
- });
478
- $[56] = allowLinks;
479
- $[57] = editor;
480
- $[58] = isEditable;
481
- $[59] = linkOpen;
482
- $[60] = t22;
483
- } else t22 = $[60];
484
- let t23;
485
- if ($[61] !== allowImages || $[62] !== editor || $[63] !== enableMediaLibrary || $[64] !== imageCollection || $[65] !== imageOpen || $[66] !== isEditable || $[67] !== onImageUpload) {
486
- t23 = allowImages && /* @__PURE__ */ jsx(ImagePopover, {
487
- editor,
488
- open: imageOpen,
489
- onOpenChange: setImageOpen,
490
- disabled: !isEditable,
491
- onImageUpload,
492
- imageCollection,
493
- enableMediaLibrary
494
- });
495
- $[61] = allowImages;
496
- $[62] = editor;
497
- $[63] = enableMediaLibrary;
498
- $[64] = imageCollection;
499
- $[65] = imageOpen;
500
- $[66] = isEditable;
501
- $[67] = onImageUpload;
502
- $[68] = t23;
503
- } else t23 = $[68];
504
- let t24;
505
- if ($[69] !== t21 || $[70] !== t22 || $[71] !== t23) {
506
- t24 = /* @__PURE__ */ jsxs(Fragment, { children: [
507
- t21,
508
- t22,
509
- t23
510
- ] });
511
- $[69] = t21;
512
- $[70] = t22;
513
- $[71] = t23;
514
- $[72] = t24;
515
- } else t24 = $[72];
516
- return t24;
694
+ React.useEffect(() => {
695
+ if (prevLocaleRef.current !== locale) {
696
+ prevLocaleRef.current = locale;
697
+ lastEmittedValueRef.current = void 0;
698
+ }
699
+ }, [locale]);
700
+ React.useEffect(() => {
701
+ if (!editor) return;
702
+ if (value === void 0) return;
703
+ if (isSameValue(value, lastEmittedValueRef.current)) return;
704
+ lastEmittedValueRef.current = value;
705
+ editor.commands.setContent(value ?? "", false);
706
+ }, [editor, value]);
707
+ const characterCount = getCharacterCount(editor);
708
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
709
+ className: cn("qp-rich-text-editor control-surface h-auto min-h-[160px] overflow-hidden", disabled || readOnly ? "opacity-60" : "", error ? "border-destructive" : "border-border"),
710
+ "data-admin-rich-text-editor": "root",
711
+ children: [
712
+ editor && allowToolbar && /* @__PURE__ */ jsx(RichTextToolbar, {
713
+ editor,
714
+ features,
715
+ disabled: !isEditable,
716
+ headingValue,
717
+ onHeadingChange: (value_0) => {
718
+ if (!editor) return;
719
+ if (value_0 === "paragraph") {
720
+ editor.chain().focus().setParagraph().run();
721
+ return;
722
+ }
723
+ editor.chain().focus().toggleHeading({ level: Number(value_0) }).run();
724
+ },
725
+ onLinkClick: () => setLinkOpen(true),
726
+ onImageClick: () => setImageOpen(true),
727
+ onTableClick: () => {
728
+ if (!inTable) editor.chain().focus().insertTable({
729
+ rows: 3,
730
+ cols: 3,
731
+ withHeaderRow: true
732
+ }).run();
733
+ },
734
+ inTable
735
+ }),
736
+ editor && (allowBubbleMenu || linkOpen) && /* @__PURE__ */ jsx(RichTextBubbleMenu, {
737
+ editor,
738
+ features,
739
+ disabled: !isEditable,
740
+ linkOpen,
741
+ onImageClick: allowImages ? () => setImageOpen(true) : void 0,
742
+ onLinkOpenChange: setLinkOpen,
743
+ showFormatting: allowBubbleMenu
744
+ }),
745
+ editor ? /* @__PURE__ */ jsx(EditorContent, {
746
+ editor,
747
+ id: name
748
+ }) : /* @__PURE__ */ jsx(RichTextEditorContentSkeleton, {}),
749
+ uploadingInlineImage && /* @__PURE__ */ jsx("div", {
750
+ className: "qp-rich-text-editor__upload-status",
751
+ role: "status",
752
+ "aria-live": "polite",
753
+ children: t("editor.uploading")
754
+ }),
755
+ allowCharacterCount && showCharacterCount && /* @__PURE__ */ jsxs("div", {
756
+ className: "bg-surface-low text-muted-foreground border-border-subtle flex items-center justify-between border-t px-2 py-1 text-xs",
757
+ children: [/* @__PURE__ */ jsxs("span", { children: [
758
+ characterCount.words,
759
+ " word",
760
+ characterCount.words === 1 ? "" : "s"
761
+ ] }), /* @__PURE__ */ jsxs("span", { children: [
762
+ characterCount.characters,
763
+ typeof maxCharacters === "number" ? ` / ${maxCharacters}` : "",
764
+ " ",
765
+ "characters"
766
+ ] })]
767
+ })
768
+ ]
769
+ }), allowImages && /* @__PURE__ */ jsx(ImagePopover, {
770
+ editor,
771
+ open: imageOpen,
772
+ onOpenChange: setImageOpen,
773
+ disabled: !isEditable,
774
+ onImageUpload,
775
+ imageCollection,
776
+ enableMediaLibrary
777
+ })] });
517
778
  }
518
779
 
519
780
  //#endregion