@questpie/admin 0.0.1 → 1.0.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 (250) hide show
  1. package/README.md +439 -424
  2. package/dist/auth-layout-M8K8_q5R.mjs +181 -0
  3. package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
  4. package/dist/bulk-upload-dialog-h7zXD78Y.mjs +274 -0
  5. package/dist/bulk-upload-dialog-h7zXD78Y.mjs.map +1 -0
  6. package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
  7. package/dist/card-BKHjBQfw.mjs.map +1 -0
  8. package/dist/client/styles/index.css +434 -0
  9. package/dist/client-BCGpkAz6.mjs +22635 -0
  10. package/dist/client-BCGpkAz6.mjs.map +1 -0
  11. package/dist/client-CcWZbkBP.d.mts +13585 -0
  12. package/dist/client-CcWZbkBP.d.mts.map +1 -0
  13. package/dist/client.d.mts +3 -0
  14. package/dist/client.mjs +14 -0
  15. package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
  16. package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
  17. package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
  18. package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
  19. package/dist/dashboard-page-CVlyR40m.mjs +6 -0
  20. package/dist/dropzone-Do3awXKd.mjs +634 -0
  21. package/dist/dropzone-Do3awXKd.mjs.map +1 -0
  22. package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
  23. package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
  24. package/dist/forgot-password-page-CIILVhfo.mjs +7 -0
  25. package/dist/index-B9Xwk4hi.d.mts +2753 -0
  26. package/dist/index-B9Xwk4hi.d.mts.map +1 -0
  27. package/dist/index.d.mts +3 -0
  28. package/dist/index.mjs +14 -0
  29. package/dist/login-page-8K7fo0qK.mjs +7 -0
  30. package/dist/login-page-CP4gA-dl.mjs +298 -0
  31. package/dist/login-page-CP4gA-dl.mjs.map +1 -0
  32. package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
  33. package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
  34. package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
  35. package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
  36. package/dist/reset-password-page-DLATv0xQ.mjs +7 -0
  37. package/dist/runtime-6VZM878K.mjs +69 -0
  38. package/dist/runtime-6VZM878K.mjs.map +1 -0
  39. package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
  40. package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
  41. package/dist/server.d.mts +250 -0
  42. package/dist/server.d.mts.map +1 -0
  43. package/dist/server.mjs +832 -0
  44. package/dist/server.mjs.map +1 -0
  45. package/dist/setup-page-CMZ5P_OE.mjs +6 -0
  46. package/dist/setup-page-YAP_fzqh.mjs +264 -0
  47. package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
  48. package/dist/shared.d.mts +57 -0
  49. package/dist/shared.d.mts.map +1 -0
  50. package/dist/shared.mjs +3 -0
  51. package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
  52. package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
  53. package/package.json +48 -197
  54. package/.turbo/turbo-build.log +0 -108
  55. package/CHANGELOG.md +0 -10
  56. package/STATUS.md +0 -917
  57. package/VALIDATION.md +0 -602
  58. package/components.json +0 -24
  59. package/dist/__tests__/setup.mjs +0 -38
  60. package/dist/__tests__/test-utils.mjs +0 -45
  61. package/dist/__tests__/vitest.d.mjs +0 -3
  62. package/dist/components/admin-app.mjs +0 -69
  63. package/dist/components/fields/array-field.mjs +0 -190
  64. package/dist/components/fields/checkbox-field.mjs +0 -34
  65. package/dist/components/fields/custom-field.mjs +0 -32
  66. package/dist/components/fields/date-field.mjs +0 -41
  67. package/dist/components/fields/datetime-field.mjs +0 -42
  68. package/dist/components/fields/email-field.mjs +0 -37
  69. package/dist/components/fields/embedded-collection.mjs +0 -253
  70. package/dist/components/fields/field-types.mjs +0 -1
  71. package/dist/components/fields/field-utils.mjs +0 -10
  72. package/dist/components/fields/field-wrapper.mjs +0 -34
  73. package/dist/components/fields/index.mjs +0 -23
  74. package/dist/components/fields/json-field.mjs +0 -243
  75. package/dist/components/fields/locale-badge.mjs +0 -16
  76. package/dist/components/fields/number-field.mjs +0 -39
  77. package/dist/components/fields/password-field.mjs +0 -37
  78. package/dist/components/fields/relation-field.mjs +0 -104
  79. package/dist/components/fields/relation-picker.mjs +0 -229
  80. package/dist/components/fields/relation-select.mjs +0 -188
  81. package/dist/components/fields/rich-text-editor/index.mjs +0 -897
  82. package/dist/components/fields/select-field.mjs +0 -41
  83. package/dist/components/fields/switch-field.mjs +0 -34
  84. package/dist/components/fields/text-field.mjs +0 -38
  85. package/dist/components/fields/textarea-field.mjs +0 -38
  86. package/dist/components/index.mjs +0 -59
  87. package/dist/components/primitives/checkbox-input.mjs +0 -127
  88. package/dist/components/primitives/date-input.mjs +0 -303
  89. package/dist/components/primitives/index.mjs +0 -12
  90. package/dist/components/primitives/number-input.mjs +0 -104
  91. package/dist/components/primitives/select-input.mjs +0 -177
  92. package/dist/components/primitives/tag-input.mjs +0 -135
  93. package/dist/components/primitives/text-input.mjs +0 -39
  94. package/dist/components/primitives/textarea-input.mjs +0 -37
  95. package/dist/components/primitives/toggle-input.mjs +0 -31
  96. package/dist/components/primitives/types.mjs +0 -12
  97. package/dist/components/ui/accordion.mjs +0 -55
  98. package/dist/components/ui/avatar.mjs +0 -54
  99. package/dist/components/ui/badge.mjs +0 -34
  100. package/dist/components/ui/button.mjs +0 -48
  101. package/dist/components/ui/checkbox.mjs +0 -21
  102. package/dist/components/ui/combobox.mjs +0 -163
  103. package/dist/components/ui/dialog.mjs +0 -95
  104. package/dist/components/ui/dropdown-menu.mjs +0 -138
  105. package/dist/components/ui/field.mjs +0 -113
  106. package/dist/components/ui/input-group.mjs +0 -82
  107. package/dist/components/ui/input.mjs +0 -17
  108. package/dist/components/ui/label.mjs +0 -15
  109. package/dist/components/ui/popover.mjs +0 -56
  110. package/dist/components/ui/scroll-area.mjs +0 -38
  111. package/dist/components/ui/select.mjs +0 -100
  112. package/dist/components/ui/separator.mjs +0 -16
  113. package/dist/components/ui/sheet.mjs +0 -90
  114. package/dist/components/ui/sidebar.mjs +0 -387
  115. package/dist/components/ui/skeleton.mjs +0 -14
  116. package/dist/components/ui/spinner.mjs +0 -16
  117. package/dist/components/ui/switch.mjs +0 -22
  118. package/dist/components/ui/table.mjs +0 -68
  119. package/dist/components/ui/tabs.mjs +0 -48
  120. package/dist/components/ui/textarea.mjs +0 -15
  121. package/dist/components/ui/tooltip.mjs +0 -44
  122. package/dist/config/component-registry.mjs +0 -38
  123. package/dist/config/index.mjs +0 -129
  124. package/dist/hooks/admin-provider.mjs +0 -70
  125. package/dist/hooks/index.mjs +0 -7
  126. package/dist/hooks/store.mjs +0 -178
  127. package/dist/hooks/use-collection-db.mjs +0 -146
  128. package/dist/hooks/use-collection.mjs +0 -112
  129. package/dist/hooks/use-global.mjs +0 -46
  130. package/dist/hooks/use-mobile.mjs +0 -20
  131. package/dist/lib/utils.mjs +0 -10
  132. package/dist/styles/index.css +0 -336
  133. package/dist/styles/index.mjs +0 -1
  134. package/dist/utils/index.mjs +0 -9
  135. package/dist/views/auth/auth-layout.mjs +0 -52
  136. package/dist/views/auth/index.mjs +0 -6
  137. package/dist/views/auth/login-form.mjs +0 -156
  138. package/dist/views/collection/auto-form-fields.mjs +0 -525
  139. package/dist/views/collection/collection-form.mjs +0 -91
  140. package/dist/views/collection/collection-list.mjs +0 -76
  141. package/dist/views/collection/form-field.mjs +0 -42
  142. package/dist/views/collection/index.mjs +0 -6
  143. package/dist/views/common/index.mjs +0 -4
  144. package/dist/views/common/locale-switcher.mjs +0 -39
  145. package/dist/views/common/version-history.mjs +0 -272
  146. package/dist/views/index.mjs +0 -9
  147. package/dist/views/layout/admin-layout.mjs +0 -40
  148. package/dist/views/layout/admin-router.mjs +0 -95
  149. package/dist/views/layout/admin-sidebar.mjs +0 -63
  150. package/dist/views/layout/index.mjs +0 -5
  151. package/src/__tests__/setup.ts +0 -44
  152. package/src/__tests__/test-utils.tsx +0 -49
  153. package/src/__tests__/vitest.d.ts +0 -9
  154. package/src/components/admin-app.tsx +0 -221
  155. package/src/components/fields/array-field.tsx +0 -237
  156. package/src/components/fields/checkbox-field.tsx +0 -47
  157. package/src/components/fields/custom-field.tsx +0 -50
  158. package/src/components/fields/date-field.tsx +0 -65
  159. package/src/components/fields/datetime-field.tsx +0 -67
  160. package/src/components/fields/email-field.tsx +0 -51
  161. package/src/components/fields/embedded-collection.tsx +0 -315
  162. package/src/components/fields/field-types.ts +0 -162
  163. package/src/components/fields/field-utils.ts +0 -6
  164. package/src/components/fields/field-wrapper.tsx +0 -52
  165. package/src/components/fields/index.ts +0 -66
  166. package/src/components/fields/json-field.tsx +0 -440
  167. package/src/components/fields/locale-badge.tsx +0 -15
  168. package/src/components/fields/number-field.tsx +0 -57
  169. package/src/components/fields/password-field.tsx +0 -51
  170. package/src/components/fields/relation-field.tsx +0 -243
  171. package/src/components/fields/relation-picker.tsx +0 -402
  172. package/src/components/fields/relation-select.tsx +0 -327
  173. package/src/components/fields/rich-text-editor/index.tsx +0 -1337
  174. package/src/components/fields/select-field.tsx +0 -61
  175. package/src/components/fields/switch-field.tsx +0 -47
  176. package/src/components/fields/text-field.tsx +0 -55
  177. package/src/components/fields/textarea-field.tsx +0 -55
  178. package/src/components/index.ts +0 -40
  179. package/src/components/primitives/checkbox-input.tsx +0 -193
  180. package/src/components/primitives/date-input.tsx +0 -401
  181. package/src/components/primitives/index.ts +0 -24
  182. package/src/components/primitives/number-input.tsx +0 -132
  183. package/src/components/primitives/select-input.tsx +0 -296
  184. package/src/components/primitives/tag-input.tsx +0 -200
  185. package/src/components/primitives/text-input.tsx +0 -49
  186. package/src/components/primitives/textarea-input.tsx +0 -46
  187. package/src/components/primitives/toggle-input.tsx +0 -36
  188. package/src/components/primitives/types.ts +0 -235
  189. package/src/components/ui/accordion.tsx +0 -72
  190. package/src/components/ui/avatar.tsx +0 -106
  191. package/src/components/ui/badge.tsx +0 -48
  192. package/src/components/ui/button.tsx +0 -53
  193. package/src/components/ui/card.tsx +0 -94
  194. package/src/components/ui/checkbox.tsx +0 -27
  195. package/src/components/ui/combobox.tsx +0 -290
  196. package/src/components/ui/dialog.tsx +0 -151
  197. package/src/components/ui/dropdown-menu.tsx +0 -254
  198. package/src/components/ui/field.tsx +0 -227
  199. package/src/components/ui/input-group.tsx +0 -149
  200. package/src/components/ui/input.tsx +0 -20
  201. package/src/components/ui/label.tsx +0 -18
  202. package/src/components/ui/popover.tsx +0 -88
  203. package/src/components/ui/scroll-area.tsx +0 -53
  204. package/src/components/ui/select.tsx +0 -192
  205. package/src/components/ui/separator.tsx +0 -23
  206. package/src/components/ui/sheet.tsx +0 -127
  207. package/src/components/ui/sidebar.tsx +0 -723
  208. package/src/components/ui/skeleton.tsx +0 -13
  209. package/src/components/ui/spinner.tsx +0 -10
  210. package/src/components/ui/switch.tsx +0 -32
  211. package/src/components/ui/table.tsx +0 -99
  212. package/src/components/ui/tabs.tsx +0 -82
  213. package/src/components/ui/textarea.tsx +0 -18
  214. package/src/components/ui/tooltip.tsx +0 -70
  215. package/src/config/component-registry.ts +0 -190
  216. package/src/config/index.ts +0 -1099
  217. package/src/hooks/README.md +0 -269
  218. package/src/hooks/admin-provider.tsx +0 -110
  219. package/src/hooks/index.ts +0 -41
  220. package/src/hooks/store.ts +0 -248
  221. package/src/hooks/use-auth.ts +0 -168
  222. package/src/hooks/use-collection-db.ts +0 -209
  223. package/src/hooks/use-collection.ts +0 -156
  224. package/src/hooks/use-global.ts +0 -69
  225. package/src/hooks/use-mobile.ts +0 -21
  226. package/src/lib/utils.ts +0 -6
  227. package/src/styles/index.css +0 -340
  228. package/src/utils/index.ts +0 -6
  229. package/src/views/auth/auth-layout.tsx +0 -77
  230. package/src/views/auth/forgot-password-form.tsx +0 -192
  231. package/src/views/auth/index.ts +0 -21
  232. package/src/views/auth/login-form.tsx +0 -229
  233. package/src/views/auth/reset-password-form.tsx +0 -232
  234. package/src/views/collection/auto-form-fields.tsx +0 -982
  235. package/src/views/collection/collection-form.tsx +0 -186
  236. package/src/views/collection/collection-list.tsx +0 -223
  237. package/src/views/collection/form-field.tsx +0 -52
  238. package/src/views/collection/index.ts +0 -15
  239. package/src/views/common/index.ts +0 -8
  240. package/src/views/common/locale-switcher.tsx +0 -45
  241. package/src/views/common/version-history.tsx +0 -406
  242. package/src/views/index.ts +0 -25
  243. package/src/views/layout/admin-layout.tsx +0 -117
  244. package/src/views/layout/admin-router.tsx +0 -206
  245. package/src/views/layout/admin-sidebar.tsx +0 -185
  246. package/src/views/layout/index.ts +0 -12
  247. package/tsconfig.json +0 -13
  248. package/tsconfig.tsbuildinfo +0 -1
  249. package/tsdown.config.ts +0 -13
  250. package/vitest.config.ts +0 -29
@@ -1,897 +0,0 @@
1
- import * as React$1 from "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Button } from "../../ui/button";
4
- import { Input } from "../../ui/input";
5
- import { Label } from "../../ui/label";
6
- import { Popover, PopoverContent, PopoverHeader, PopoverTitle, PopoverTrigger } from "../../ui/popover";
7
- import { LocaleBadge } from "../locale-badge";
8
- import { cn } from "../../../utils";
9
- import { Extension } from "@tiptap/core";
10
- import { BubbleMenu, EditorContent, ReactRenderer, useEditor } from "@tiptap/react";
11
- import StarterKit from "@tiptap/starter-kit";
12
- import Underline from "@tiptap/extension-underline";
13
- import Link from "@tiptap/extension-link";
14
- import Image from "@tiptap/extension-image";
15
- import Placeholder from "@tiptap/extension-placeholder";
16
- import TextAlign from "@tiptap/extension-text-align";
17
- import Table from "@tiptap/extension-table";
18
- import TableRow from "@tiptap/extension-table-row";
19
- import TableHeader from "@tiptap/extension-table-header";
20
- import TableCell from "@tiptap/extension-table-cell";
21
- import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
22
- import CharacterCount from "@tiptap/extension-character-count";
23
- import Suggestion from "@tiptap/suggestion";
24
- import tippy from "tippy.js";
25
- import { common, createLowlight } from "lowlight";
26
-
27
- //#region src/components/fields/rich-text-editor/index.tsx
28
- /**
29
- * RichTextEditor Component
30
- *
31
- * Tiptap-based rich text editor with toolbar controls.
32
- */
33
- const lowlight = createLowlight(common);
34
- const defaultFeatures = {
35
- toolbar: true,
36
- bubbleMenu: true,
37
- slashCommands: true,
38
- history: true,
39
- heading: true,
40
- bold: true,
41
- italic: true,
42
- underline: true,
43
- strike: true,
44
- code: true,
45
- codeBlock: true,
46
- blockquote: true,
47
- bulletList: true,
48
- orderedList: true,
49
- horizontalRule: true,
50
- align: true,
51
- link: true,
52
- image: true,
53
- table: true,
54
- tableControls: true,
55
- characterCount: true
56
- };
57
- function ToolbarButton({ active, disabled, title, onClick, children }) {
58
- return /* @__PURE__ */ jsx(Button, {
59
- type: "button",
60
- variant: "ghost",
61
- size: "xs",
62
- "data-active": active,
63
- title,
64
- disabled,
65
- onClick,
66
- className: "data-[active=true]:bg-muted data-[active=true]:text-foreground",
67
- children
68
- });
69
- }
70
- function ToolbarGroup({ children }) {
71
- return /* @__PURE__ */ jsx("div", {
72
- className: "flex items-center gap-1 border-r border-border pr-2 last:border-r-0 last:pr-0",
73
- children
74
- });
75
- }
76
- const SlashCommandList = React$1.forwardRef(function SlashCommandList$1({ items, command }, ref) {
77
- const [selectedIndex, setSelectedIndex] = React$1.useState(0);
78
- React$1.useEffect(() => {
79
- setSelectedIndex(0);
80
- }, [items]);
81
- const selectItem = React$1.useCallback((index) => {
82
- const item = items[index];
83
- if (item) command(item);
84
- }, [command, items]);
85
- React$1.useImperativeHandle(ref, () => ({ onKeyDown: ({ event }) => {
86
- if (items.length === 0) return false;
87
- if (event.key === "ArrowDown") {
88
- setSelectedIndex((prev) => (prev + 1) % items.length);
89
- return true;
90
- }
91
- if (event.key === "ArrowUp") {
92
- setSelectedIndex((prev) => (prev - 1 + items.length) % items.length);
93
- return true;
94
- }
95
- if (event.key === "Enter") {
96
- selectItem(selectedIndex);
97
- return true;
98
- }
99
- return false;
100
- } }));
101
- return /* @__PURE__ */ jsxs("div", {
102
- className: "qp-rich-text-editor__slash",
103
- children: [items.length === 0 && /* @__PURE__ */ jsx("div", {
104
- className: "qp-rich-text-editor__slash-empty",
105
- children: "No results"
106
- }), items.map((item, index) => /* @__PURE__ */ jsxs("button", {
107
- type: "button",
108
- className: cn("qp-rich-text-editor__slash-item", index === selectedIndex ? "qp-rich-text-editor__slash-item--active" : ""),
109
- onClick: () => selectItem(index),
110
- children: [/* @__PURE__ */ jsx("span", {
111
- className: "qp-rich-text-editor__slash-title",
112
- children: item.title
113
- }), item.description && /* @__PURE__ */ jsx("span", {
114
- className: "qp-rich-text-editor__slash-description",
115
- children: item.description
116
- })]
117
- }, item.title))]
118
- });
119
- });
120
- function getHeadingLevel(editor) {
121
- if (!editor) return "paragraph";
122
- for (let level = 1; level <= 6; level += 1) if (editor.isActive("heading", { level })) return String(level);
123
- return "paragraph";
124
- }
125
- function getOutput(editor, outputFormat) {
126
- if (outputFormat === "html") return editor.getHTML();
127
- if (outputFormat === "markdown") {
128
- const markdown = editor.storage?.markdown?.getMarkdown?.();
129
- if (typeof markdown === "string") return markdown;
130
- return editor.getHTML();
131
- }
132
- return editor.getJSON();
133
- }
134
- function isSameValue(a, b) {
135
- if (a === b) return true;
136
- if (!a || !b) return false;
137
- if (typeof a === "string" && typeof b === "string") return a === b;
138
- try {
139
- return JSON.stringify(a) === JSON.stringify(b);
140
- } catch {
141
- return false;
142
- }
143
- }
144
- function createSlashCommandExtension(getItems) {
145
- return Extension.create({
146
- name: "slashCommand",
147
- addOptions() {
148
- return { suggestion: {
149
- char: "/",
150
- startOfLine: true,
151
- command: ({ editor, range, props }) => {
152
- editor.chain().focus().deleteRange(range).run();
153
- props.command(editor);
154
- },
155
- items: ({ query, editor }) => {
156
- const items = getItems(editor);
157
- if (!query) return items;
158
- const search = query.toLowerCase();
159
- return items.filter((item) => {
160
- return item.title.toLowerCase().includes(search) || item.description?.toLowerCase().includes(search) || item.keywords?.some((keyword) => keyword.toLowerCase().includes(search));
161
- });
162
- },
163
- render: () => {
164
- let component = null;
165
- let popup = null;
166
- return {
167
- onStart: (props) => {
168
- component = new ReactRenderer(SlashCommandList, {
169
- props,
170
- editor: props.editor
171
- });
172
- if (!props.clientRect) return;
173
- popup = tippy("body", {
174
- getReferenceClientRect: props.clientRect,
175
- appendTo: () => document.body,
176
- content: component.element,
177
- showOnCreate: true,
178
- interactive: true,
179
- trigger: "manual",
180
- placement: "bottom-start",
181
- theme: "qp-rich-text-editor"
182
- });
183
- },
184
- onUpdate: (props) => {
185
- component?.updateProps(props);
186
- if (!props.clientRect) return;
187
- popup?.[0].setProps({ getReferenceClientRect: props.clientRect });
188
- },
189
- onKeyDown: (props) => {
190
- if (props.event.key === "Escape") {
191
- popup?.[0].hide();
192
- return true;
193
- }
194
- return component?.ref?.onKeyDown(props) ?? false;
195
- },
196
- onExit: () => {
197
- popup?.[0].destroy();
198
- component?.destroy();
199
- }
200
- };
201
- }
202
- } };
203
- },
204
- addProseMirrorPlugins() {
205
- return [Suggestion(this.options.suggestion)];
206
- }
207
- });
208
- }
209
- function RichTextEditor({ name, value, onChange, disabled, readOnly, label, description, placeholder, required, error, localized, locale, outputFormat = "json", extensions, features, showCharacterCount, maxCharacters, enableImages, onImageUpload }) {
210
- const [linkOpen, setLinkOpen] = React$1.useState(false);
211
- const [linkUrl, setLinkUrl] = React$1.useState("");
212
- const [imageOpen, setImageOpen] = React$1.useState(false);
213
- const [imageUrl, setImageUrl] = React$1.useState("");
214
- const [imageAlt, setImageAlt] = React$1.useState("");
215
- const [uploadingImage, setUploadingImage] = React$1.useState(false);
216
- const fileInputRef = React$1.useRef(null);
217
- const resolvedFeatures = React$1.useMemo(() => ({
218
- ...defaultFeatures,
219
- ...features
220
- }), [features]);
221
- const allowImages = resolvedFeatures.image && (enableImages ?? true);
222
- const allowLinks = resolvedFeatures.link;
223
- const allowTables = resolvedFeatures.table;
224
- const allowTableControls = resolvedFeatures.tableControls && allowTables;
225
- const allowSlashCommands = resolvedFeatures.slashCommands;
226
- const allowBubbleMenu = resolvedFeatures.bubbleMenu;
227
- const allowToolbar = resolvedFeatures.toolbar;
228
- const allowCharacterCount = resolvedFeatures.characterCount && (showCharacterCount || maxCharacters);
229
- const editor = useEditor({
230
- extensions: React$1.useMemo(() => {
231
- const starterKitConfig = { codeBlock: false };
232
- if (!resolvedFeatures.bold) starterKitConfig.bold = false;
233
- if (!resolvedFeatures.italic) starterKitConfig.italic = false;
234
- if (!resolvedFeatures.strike) starterKitConfig.strike = false;
235
- if (!resolvedFeatures.code) starterKitConfig.code = false;
236
- if (!resolvedFeatures.blockquote) starterKitConfig.blockquote = false;
237
- if (!resolvedFeatures.heading) starterKitConfig.heading = false;
238
- if (!resolvedFeatures.bulletList) starterKitConfig.bulletList = false;
239
- if (!resolvedFeatures.orderedList) starterKitConfig.orderedList = false;
240
- if (!resolvedFeatures.bulletList && !resolvedFeatures.orderedList) starterKitConfig.listItem = false;
241
- if (!resolvedFeatures.horizontalRule) starterKitConfig.horizontalRule = false;
242
- if (!resolvedFeatures.history) starterKitConfig.history = false;
243
- const items = [StarterKit.configure(starterKitConfig), Placeholder.configure({ placeholder: placeholder || "Start writing..." })];
244
- if (resolvedFeatures.underline) items.push(Underline);
245
- if (allowLinks) items.push(Link.configure({
246
- openOnClick: false,
247
- autolink: true,
248
- linkOnPaste: true
249
- }));
250
- if (resolvedFeatures.align) items.push(TextAlign.configure({ types: ["heading", "paragraph"] }));
251
- if (allowImages) items.push(Image);
252
- if (allowTables) items.push(Table.configure({ resizable: true }), TableRow, TableHeader, TableCell);
253
- if (resolvedFeatures.codeBlock) items.push(CodeBlockLowlight.configure({ lowlight }));
254
- if (allowCharacterCount) items.push(CharacterCount.configure({ limit: maxCharacters }));
255
- if (allowSlashCommands) items.push(createSlashCommandExtension((editor$1) => {
256
- const commands = [];
257
- if (resolvedFeatures.heading) commands.push({
258
- title: "Heading 1",
259
- description: "Large section heading",
260
- keywords: ["h1"],
261
- command: (cmdEditor) => cmdEditor.chain().focus().toggleHeading({ level: 1 }).run()
262
- }, {
263
- title: "Heading 2",
264
- description: "Medium section heading",
265
- keywords: ["h2"],
266
- command: (cmdEditor) => cmdEditor.chain().focus().toggleHeading({ level: 2 }).run()
267
- }, {
268
- title: "Heading 3",
269
- description: "Small section heading",
270
- keywords: ["h3"],
271
- command: (cmdEditor) => cmdEditor.chain().focus().toggleHeading({ level: 3 }).run()
272
- });
273
- commands.push({
274
- title: "Paragraph",
275
- description: "Start with plain text",
276
- keywords: ["text"],
277
- command: (cmdEditor) => cmdEditor.chain().focus().setParagraph().run()
278
- });
279
- if (resolvedFeatures.bulletList) commands.push({
280
- title: "Bullet list",
281
- description: "Create a bulleted list",
282
- keywords: ["list", "ul"],
283
- command: (cmdEditor) => cmdEditor.chain().focus().toggleBulletList().run()
284
- });
285
- if (resolvedFeatures.orderedList) commands.push({
286
- title: "Numbered list",
287
- description: "Create an ordered list",
288
- keywords: ["list", "ol"],
289
- command: (cmdEditor) => cmdEditor.chain().focus().toggleOrderedList().run()
290
- });
291
- if (resolvedFeatures.blockquote) commands.push({
292
- title: "Quote",
293
- description: "Capture a quote",
294
- keywords: ["blockquote"],
295
- command: (cmdEditor) => cmdEditor.chain().focus().toggleBlockquote().run()
296
- });
297
- if (resolvedFeatures.codeBlock) commands.push({
298
- title: "Code block",
299
- description: "Insert code snippet",
300
- keywords: ["code"],
301
- command: (cmdEditor) => cmdEditor.chain().focus().toggleCodeBlock().run()
302
- });
303
- if (resolvedFeatures.horizontalRule) commands.push({
304
- title: "Divider",
305
- description: "Insert a horizontal rule",
306
- keywords: ["hr"],
307
- command: (cmdEditor) => cmdEditor.chain().focus().setHorizontalRule().run()
308
- });
309
- if (allowTables) commands.push({
310
- title: "Table",
311
- description: "Insert a 3x3 table",
312
- keywords: ["grid"],
313
- command: (cmdEditor) => cmdEditor.chain().focus().insertTable({
314
- rows: 3,
315
- cols: 3,
316
- withHeaderRow: true
317
- }).run()
318
- });
319
- return commands;
320
- }));
321
- if (extensions?.length) items.push(...extensions);
322
- return items;
323
- }, [
324
- allowCharacterCount,
325
- allowImages,
326
- allowLinks,
327
- allowSlashCommands,
328
- allowTables,
329
- extensions,
330
- maxCharacters,
331
- placeholder,
332
- resolvedFeatures
333
- ]),
334
- content: value ?? "",
335
- editorProps: { attributes: { class: "qp-rich-text-editor__content" } },
336
- editable: !disabled && !readOnly,
337
- onUpdate: ({ editor: currentEditor }) => {
338
- if (disabled || readOnly) return;
339
- onChange(getOutput(currentEditor, outputFormat));
340
- }
341
- });
342
- const isEditable = !disabled && !readOnly;
343
- const headingValue = getHeadingLevel(editor);
344
- const inTable = editor?.isActive("table") ?? false;
345
- React$1.useEffect(() => {
346
- if (!editor) return;
347
- editor.setEditable(isEditable);
348
- }, [editor, isEditable]);
349
- React$1.useEffect(() => {
350
- if (!editor) return;
351
- if (value === void 0) return;
352
- if (isSameValue(value, getOutput(editor, outputFormat))) return;
353
- editor.commands.setContent(value ?? "", false);
354
- }, [
355
- editor,
356
- outputFormat,
357
- value
358
- ]);
359
- React$1.useEffect(() => {
360
- if (!linkOpen || !editor) return;
361
- const currentLink = editor.getAttributes("link").href;
362
- setLinkUrl(currentLink || "");
363
- }, [editor, linkOpen]);
364
- const handleApplyLink = React$1.useCallback(() => {
365
- if (!editor) return;
366
- if (!linkUrl) {
367
- editor.chain().focus().unsetLink().run();
368
- setLinkOpen(false);
369
- return;
370
- }
371
- editor.chain().focus().setLink({
372
- href: linkUrl,
373
- target: "_blank",
374
- rel: "noopener noreferrer"
375
- }).run();
376
- setLinkOpen(false);
377
- }, [editor, linkUrl]);
378
- const handleRemoveLink = React$1.useCallback(() => {
379
- if (!editor) return;
380
- editor.chain().focus().unsetLink().run();
381
- setLinkOpen(false);
382
- }, [editor]);
383
- const handleInsertImageUrl = React$1.useCallback(() => {
384
- if (!editor || !imageUrl) return;
385
- editor.chain().focus().setImage({
386
- src: imageUrl,
387
- alt: imageAlt || void 0
388
- }).run();
389
- setImageUrl("");
390
- setImageAlt("");
391
- setImageOpen(false);
392
- }, [
393
- editor,
394
- imageAlt,
395
- imageUrl
396
- ]);
397
- const handleImageUpload = React$1.useCallback(async (event) => {
398
- const file = event.target.files?.[0];
399
- if (!file || !editor || !onImageUpload) return;
400
- try {
401
- setUploadingImage(true);
402
- const url = await onImageUpload(file);
403
- if (url) {
404
- editor.chain().focus().setImage({
405
- src: url,
406
- alt: imageAlt || void 0
407
- }).run();
408
- setImageUrl("");
409
- setImageAlt("");
410
- setImageOpen(false);
411
- }
412
- } finally {
413
- setUploadingImage(false);
414
- event.target.value = "";
415
- }
416
- }, [
417
- editor,
418
- imageAlt,
419
- onImageUpload
420
- ]);
421
- const characterCount = React$1.useMemo(() => {
422
- if (!editor) return {
423
- characters: 0,
424
- words: 0
425
- };
426
- const storage = editor.storage;
427
- if (storage?.characterCount) return {
428
- characters: storage.characterCount.characters(),
429
- words: storage.characterCount.words()
430
- };
431
- const text = editor.getText();
432
- const words = text.trim().length ? text.trim().split(/\s+/).length : 0;
433
- return {
434
- characters: text.length,
435
- words
436
- };
437
- }, [editor, value]);
438
- return /* @__PURE__ */ jsxs("div", {
439
- className: "space-y-2",
440
- "data-disabled": disabled || readOnly,
441
- children: [
442
- label && /* @__PURE__ */ jsxs("div", {
443
- className: "flex items-center gap-2",
444
- children: [/* @__PURE__ */ jsxs(Label, {
445
- htmlFor: name,
446
- children: [label, required && /* @__PURE__ */ jsx("span", {
447
- className: "text-destructive ml-1",
448
- children: "*"
449
- })]
450
- }), localized && /* @__PURE__ */ jsx(LocaleBadge, { locale: locale || "i18n" })]
451
- }),
452
- /* @__PURE__ */ jsxs("div", {
453
- className: cn("qp-rich-text-editor rounded-md border bg-background", disabled || readOnly ? "opacity-60" : "", error ? "border-destructive" : "border-input"),
454
- children: [
455
- editor && allowToolbar && /* @__PURE__ */ jsxs("div", {
456
- className: "flex flex-wrap items-center gap-2 border-b bg-muted/40 p-2",
457
- children: [
458
- resolvedFeatures.history && /* @__PURE__ */ jsxs(ToolbarGroup, { children: [/* @__PURE__ */ jsx(ToolbarButton, {
459
- disabled: !isEditable || !editor.can().undo(),
460
- title: "Undo",
461
- onClick: () => editor.chain().focus().undo().run(),
462
- children: "Undo"
463
- }), /* @__PURE__ */ jsx(ToolbarButton, {
464
- disabled: !isEditable || !editor.can().redo(),
465
- title: "Redo",
466
- onClick: () => editor.chain().focus().redo().run(),
467
- children: "Redo"
468
- })] }),
469
- resolvedFeatures.heading && /* @__PURE__ */ jsx(ToolbarGroup, { children: /* @__PURE__ */ jsxs("select", {
470
- className: "h-6 rounded-sm border bg-background px-2 text-xs",
471
- value: headingValue,
472
- onChange: (event) => {
473
- if (!editor) return;
474
- const nextValue = event.target.value;
475
- if (nextValue === "paragraph") {
476
- editor.chain().focus().setParagraph().run();
477
- return;
478
- }
479
- editor.chain().focus().toggleHeading({ level: Number(nextValue) }).run();
480
- },
481
- disabled: !isEditable,
482
- children: [
483
- /* @__PURE__ */ jsx("option", {
484
- value: "paragraph",
485
- children: "Paragraph"
486
- }),
487
- /* @__PURE__ */ jsx("option", {
488
- value: "1",
489
- children: "Heading 1"
490
- }),
491
- /* @__PURE__ */ jsx("option", {
492
- value: "2",
493
- children: "Heading 2"
494
- }),
495
- /* @__PURE__ */ jsx("option", {
496
- value: "3",
497
- children: "Heading 3"
498
- }),
499
- /* @__PURE__ */ jsx("option", {
500
- value: "4",
501
- children: "Heading 4"
502
- }),
503
- /* @__PURE__ */ jsx("option", {
504
- value: "5",
505
- children: "Heading 5"
506
- }),
507
- /* @__PURE__ */ jsx("option", {
508
- value: "6",
509
- children: "Heading 6"
510
- })
511
- ]
512
- }) }),
513
- /* @__PURE__ */ jsxs(ToolbarGroup, { children: [
514
- resolvedFeatures.bold && /* @__PURE__ */ jsx(ToolbarButton, {
515
- active: editor.isActive("bold"),
516
- disabled: !isEditable,
517
- title: "Bold",
518
- onClick: () => editor.chain().focus().toggleBold().run(),
519
- children: "Bold"
520
- }),
521
- resolvedFeatures.italic && /* @__PURE__ */ jsx(ToolbarButton, {
522
- active: editor.isActive("italic"),
523
- disabled: !isEditable,
524
- title: "Italic",
525
- onClick: () => editor.chain().focus().toggleItalic().run(),
526
- children: "Italic"
527
- }),
528
- resolvedFeatures.underline && /* @__PURE__ */ jsx(ToolbarButton, {
529
- active: editor.isActive("underline"),
530
- disabled: !isEditable,
531
- title: "Underline",
532
- onClick: () => editor.chain().focus().toggleUnderline().run(),
533
- children: "Underline"
534
- }),
535
- resolvedFeatures.strike && /* @__PURE__ */ jsx(ToolbarButton, {
536
- active: editor.isActive("strike"),
537
- disabled: !isEditable,
538
- title: "Strikethrough",
539
- onClick: () => editor.chain().focus().toggleStrike().run(),
540
- children: "Strike"
541
- }),
542
- resolvedFeatures.code && /* @__PURE__ */ jsx(ToolbarButton, {
543
- active: editor.isActive("code"),
544
- disabled: !isEditable,
545
- title: "Inline code",
546
- onClick: () => editor.chain().focus().toggleCode().run(),
547
- children: "Code"
548
- }),
549
- resolvedFeatures.codeBlock && /* @__PURE__ */ jsx(ToolbarButton, {
550
- active: editor.isActive("codeBlock"),
551
- disabled: !isEditable,
552
- title: "Code block",
553
- onClick: () => editor.chain().focus().toggleCodeBlock().run(),
554
- children: "Code Block"
555
- })
556
- ] }),
557
- /* @__PURE__ */ jsxs(ToolbarGroup, { children: [
558
- resolvedFeatures.bulletList && /* @__PURE__ */ jsx(ToolbarButton, {
559
- active: editor.isActive("bulletList"),
560
- disabled: !isEditable,
561
- title: "Bullet list",
562
- onClick: () => editor.chain().focus().toggleBulletList().run(),
563
- children: "Bullet List"
564
- }),
565
- resolvedFeatures.orderedList && /* @__PURE__ */ jsx(ToolbarButton, {
566
- active: editor.isActive("orderedList"),
567
- disabled: !isEditable,
568
- title: "Numbered list",
569
- onClick: () => editor.chain().focus().toggleOrderedList().run(),
570
- children: "Numbered List"
571
- }),
572
- resolvedFeatures.blockquote && /* @__PURE__ */ jsx(ToolbarButton, {
573
- active: editor.isActive("blockquote"),
574
- disabled: !isEditable,
575
- title: "Blockquote",
576
- onClick: () => editor.chain().focus().toggleBlockquote().run(),
577
- children: "Quote"
578
- }),
579
- resolvedFeatures.horizontalRule && /* @__PURE__ */ jsx(ToolbarButton, {
580
- disabled: !isEditable,
581
- title: "Horizontal rule",
582
- onClick: () => editor.chain().focus().setHorizontalRule().run(),
583
- children: "Divider"
584
- })
585
- ] }),
586
- resolvedFeatures.align && /* @__PURE__ */ jsxs(ToolbarGroup, { children: [
587
- /* @__PURE__ */ jsx(ToolbarButton, {
588
- active: editor.isActive({ textAlign: "left" }),
589
- disabled: !isEditable,
590
- title: "Align left",
591
- onClick: () => editor.chain().focus().setTextAlign("left").run(),
592
- children: "Align Left"
593
- }),
594
- /* @__PURE__ */ jsx(ToolbarButton, {
595
- active: editor.isActive({ textAlign: "center" }),
596
- disabled: !isEditable,
597
- title: "Align center",
598
- onClick: () => editor.chain().focus().setTextAlign("center").run(),
599
- children: "Align Center"
600
- }),
601
- /* @__PURE__ */ jsx(ToolbarButton, {
602
- active: editor.isActive({ textAlign: "right" }),
603
- disabled: !isEditable,
604
- title: "Align right",
605
- onClick: () => editor.chain().focus().setTextAlign("right").run(),
606
- children: "Align Right"
607
- }),
608
- /* @__PURE__ */ jsx(ToolbarButton, {
609
- active: editor.isActive({ textAlign: "justify" }),
610
- disabled: !isEditable,
611
- title: "Align justify",
612
- onClick: () => editor.chain().focus().setTextAlign("justify").run(),
613
- children: "Justify"
614
- })
615
- ] }),
616
- /* @__PURE__ */ jsxs(ToolbarGroup, { children: [
617
- allowLinks && /* @__PURE__ */ jsxs(Popover, {
618
- open: linkOpen,
619
- onOpenChange: setLinkOpen,
620
- children: [/* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button, {
621
- type: "button",
622
- variant: "ghost",
623
- size: "xs",
624
- disabled: !isEditable,
625
- "data-active": editor.isActive("link"),
626
- children: "Link"
627
- }) }), /* @__PURE__ */ jsxs(PopoverContent, {
628
- className: "w-72",
629
- children: [/* @__PURE__ */ jsx(PopoverHeader, { children: /* @__PURE__ */ jsx(PopoverTitle, { children: "Insert link" }) }), /* @__PURE__ */ jsxs("div", {
630
- className: "space-y-2",
631
- children: [/* @__PURE__ */ jsx(Input, {
632
- value: linkUrl,
633
- placeholder: "https://example.com",
634
- onChange: (event) => setLinkUrl(event.target.value),
635
- disabled: !isEditable
636
- }), /* @__PURE__ */ jsxs("div", {
637
- className: "flex justify-end gap-2",
638
- children: [/* @__PURE__ */ jsx(Button, {
639
- type: "button",
640
- size: "xs",
641
- variant: "outline",
642
- onClick: handleRemoveLink,
643
- disabled: !isEditable || !editor.isActive("link"),
644
- children: "Remove"
645
- }), /* @__PURE__ */ jsx(Button, {
646
- type: "button",
647
- size: "xs",
648
- onClick: handleApplyLink,
649
- disabled: !isEditable,
650
- children: "Apply"
651
- })]
652
- })]
653
- })]
654
- })]
655
- }),
656
- allowImages && /* @__PURE__ */ jsxs(Popover, {
657
- open: imageOpen,
658
- onOpenChange: setImageOpen,
659
- children: [/* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button, {
660
- type: "button",
661
- variant: "ghost",
662
- size: "xs",
663
- disabled: !isEditable,
664
- children: "Image"
665
- }) }), /* @__PURE__ */ jsxs(PopoverContent, {
666
- className: "w-80",
667
- children: [/* @__PURE__ */ jsx(PopoverHeader, { children: /* @__PURE__ */ jsx(PopoverTitle, { children: "Insert image" }) }), /* @__PURE__ */ jsxs("div", {
668
- className: "space-y-3",
669
- children: [/* @__PURE__ */ jsxs("div", {
670
- className: "space-y-2",
671
- children: [
672
- /* @__PURE__ */ jsx(Input, {
673
- value: imageUrl,
674
- placeholder: "https://example.com/image.jpg",
675
- onChange: (event) => setImageUrl(event.target.value),
676
- disabled: !isEditable
677
- }),
678
- /* @__PURE__ */ jsx(Input, {
679
- value: imageAlt,
680
- placeholder: "Alt text (optional)",
681
- onChange: (event) => setImageAlt(event.target.value),
682
- disabled: !isEditable
683
- }),
684
- /* @__PURE__ */ jsx("div", {
685
- className: "flex justify-end gap-2",
686
- children: /* @__PURE__ */ jsx(Button, {
687
- type: "button",
688
- size: "xs",
689
- onClick: handleInsertImageUrl,
690
- disabled: !isEditable || !imageUrl,
691
- children: "Insert URL"
692
- })
693
- })
694
- ]
695
- }), onImageUpload && /* @__PURE__ */ jsxs("div", {
696
- className: "space-y-2",
697
- children: [
698
- /* @__PURE__ */ jsx("div", {
699
- className: "text-xs font-medium",
700
- children: "Upload file"
701
- }),
702
- /* @__PURE__ */ jsx("input", {
703
- ref: fileInputRef,
704
- type: "file",
705
- accept: "image/*",
706
- onChange: handleImageUpload,
707
- className: "sr-only",
708
- disabled: !isEditable || uploadingImage
709
- }),
710
- /* @__PURE__ */ jsx(Button, {
711
- type: "button",
712
- size: "xs",
713
- variant: "outline",
714
- onClick: () => fileInputRef.current?.click(),
715
- disabled: !isEditable || uploadingImage,
716
- children: uploadingImage ? "Uploading..." : "Choose file"
717
- })
718
- ]
719
- })]
720
- })]
721
- })]
722
- }),
723
- allowTableControls && /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button, {
724
- type: "button",
725
- variant: "ghost",
726
- size: "xs",
727
- disabled: !isEditable,
728
- children: "Table"
729
- }) }), /* @__PURE__ */ jsxs(PopoverContent, {
730
- className: "w-80",
731
- children: [/* @__PURE__ */ jsx(PopoverHeader, { children: /* @__PURE__ */ jsx(PopoverTitle, { children: "Table tools" }) }), /* @__PURE__ */ jsxs("div", {
732
- className: "grid grid-cols-2 gap-2",
733
- children: [
734
- /* @__PURE__ */ jsx(Button, {
735
- type: "button",
736
- size: "xs",
737
- onClick: () => editor.chain().focus().insertTable({
738
- rows: 3,
739
- cols: 3,
740
- withHeaderRow: true
741
- }).run(),
742
- disabled: !isEditable,
743
- children: "Insert table"
744
- }),
745
- /* @__PURE__ */ jsx(Button, {
746
- type: "button",
747
- size: "xs",
748
- variant: "outline",
749
- onClick: () => editor.chain().focus().addRowBefore().run(),
750
- disabled: !isEditable || !inTable,
751
- children: "Add row before"
752
- }),
753
- /* @__PURE__ */ jsx(Button, {
754
- type: "button",
755
- size: "xs",
756
- variant: "outline",
757
- onClick: () => editor.chain().focus().addRowAfter().run(),
758
- disabled: !isEditable || !inTable,
759
- children: "Add row after"
760
- }),
761
- /* @__PURE__ */ jsx(Button, {
762
- type: "button",
763
- size: "xs",
764
- variant: "outline",
765
- onClick: () => editor.chain().focus().addColumnBefore().run(),
766
- disabled: !isEditable || !inTable,
767
- children: "Add column before"
768
- }),
769
- /* @__PURE__ */ jsx(Button, {
770
- type: "button",
771
- size: "xs",
772
- variant: "outline",
773
- onClick: () => editor.chain().focus().addColumnAfter().run(),
774
- disabled: !isEditable || !inTable,
775
- children: "Add column after"
776
- }),
777
- /* @__PURE__ */ jsx(Button, {
778
- type: "button",
779
- size: "xs",
780
- variant: "outline",
781
- onClick: () => editor.chain().focus().deleteRow().run(),
782
- disabled: !isEditable || !inTable,
783
- children: "Delete row"
784
- }),
785
- /* @__PURE__ */ jsx(Button, {
786
- type: "button",
787
- size: "xs",
788
- variant: "outline",
789
- onClick: () => editor.chain().focus().deleteColumn().run(),
790
- disabled: !isEditable || !inTable,
791
- children: "Delete column"
792
- }),
793
- /* @__PURE__ */ jsx(Button, {
794
- type: "button",
795
- size: "xs",
796
- variant: "outline",
797
- onClick: () => editor.chain().focus().toggleHeaderRow().run(),
798
- disabled: !isEditable || !inTable,
799
- children: "Toggle header row"
800
- }),
801
- /* @__PURE__ */ jsx(Button, {
802
- type: "button",
803
- size: "xs",
804
- variant: "outline",
805
- onClick: () => editor.chain().focus().toggleHeaderColumn().run(),
806
- disabled: !isEditable || !inTable,
807
- children: "Toggle header column"
808
- }),
809
- /* @__PURE__ */ jsx(Button, {
810
- type: "button",
811
- size: "xs",
812
- variant: "outline",
813
- onClick: () => editor.chain().focus().mergeCells().run(),
814
- disabled: !isEditable || !inTable,
815
- children: "Merge cells"
816
- }),
817
- /* @__PURE__ */ jsx(Button, {
818
- type: "button",
819
- size: "xs",
820
- variant: "outline",
821
- onClick: () => editor.chain().focus().splitCell().run(),
822
- disabled: !isEditable || !inTable,
823
- children: "Split cell"
824
- }),
825
- /* @__PURE__ */ jsx(Button, {
826
- type: "button",
827
- size: "xs",
828
- variant: "outline",
829
- onClick: () => editor.chain().focus().deleteTable().run(),
830
- disabled: !isEditable || !inTable,
831
- children: "Delete table"
832
- })
833
- ]
834
- })]
835
- })] })
836
- ] })
837
- ]
838
- }),
839
- editor && allowBubbleMenu && /* @__PURE__ */ jsxs(BubbleMenu, {
840
- editor,
841
- className: "flex items-center gap-1 rounded-md border bg-background p-1 shadow",
842
- children: [
843
- resolvedFeatures.bold && /* @__PURE__ */ jsx(ToolbarButton, {
844
- active: editor.isActive("bold"),
845
- disabled: !isEditable,
846
- title: "Bold",
847
- onClick: () => editor.chain().focus().toggleBold().run(),
848
- children: "Bold"
849
- }),
850
- resolvedFeatures.italic && /* @__PURE__ */ jsx(ToolbarButton, {
851
- active: editor.isActive("italic"),
852
- disabled: !isEditable,
853
- title: "Italic",
854
- onClick: () => editor.chain().focus().toggleItalic().run(),
855
- children: "Italic"
856
- }),
857
- resolvedFeatures.underline && /* @__PURE__ */ jsx(ToolbarButton, {
858
- active: editor.isActive("underline"),
859
- disabled: !isEditable,
860
- title: "Underline",
861
- onClick: () => editor.chain().focus().toggleUnderline().run(),
862
- children: "Underline"
863
- })
864
- ]
865
- }),
866
- /* @__PURE__ */ jsx(EditorContent, {
867
- editor,
868
- id: name
869
- }),
870
- allowCharacterCount && showCharacterCount && /* @__PURE__ */ jsxs("div", {
871
- className: "flex items-center justify-between border-t bg-muted/30 px-2 py-1 text-xs text-muted-foreground",
872
- children: [/* @__PURE__ */ jsxs("span", { children: [
873
- characterCount.words,
874
- " word",
875
- characterCount.words === 1 ? "" : "s"
876
- ] }), /* @__PURE__ */ jsxs("span", { children: [
877
- characterCount.characters,
878
- typeof maxCharacters === "number" ? ` / ${maxCharacters}` : "",
879
- "characters"
880
- ] })]
881
- })
882
- ]
883
- }),
884
- description && /* @__PURE__ */ jsx("p", {
885
- className: "text-muted-foreground text-xs",
886
- children: description
887
- }),
888
- error && /* @__PURE__ */ jsx("p", {
889
- className: "text-destructive text-xs",
890
- children: error
891
- })
892
- ]
893
- });
894
- }
895
-
896
- //#endregion
897
- export { RichTextEditor };