@pie-lib/editable-html-tip-tap 2.2.0-beta.9 → 3.0.0-next.20261002094057

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 (235) hide show
  1. package/dist/components/CharacterPicker.d.ts +31 -0
  2. package/dist/components/CharacterPicker.js +141 -0
  3. package/dist/components/EditableHtml.d.ts +11 -0
  4. package/dist/components/EditableHtml.js +331 -0
  5. package/dist/components/MenuBar.d.ts +11 -0
  6. package/dist/components/MenuBar.js +531 -0
  7. package/dist/components/TiptapContainer.d.ts +11 -0
  8. package/dist/components/TiptapContainer.js +167 -0
  9. package/dist/components/characters/characterUtils.d.ts +35 -0
  10. package/dist/components/characters/characterUtils.js +465 -0
  11. package/dist/components/characters/custom-popper.d.ts +14 -0
  12. package/dist/components/characters/custom-popper.js +32 -0
  13. package/dist/components/common/done-button.d.ts +30 -0
  14. package/dist/components/common/done-button.js +26 -0
  15. package/dist/components/common/toolbar-buttons.d.ts +38 -0
  16. package/dist/components/common/toolbar-buttons.js +96 -0
  17. package/dist/components/icons/CssIcon.d.ts +11 -0
  18. package/dist/components/icons/CssIcon.js +14 -0
  19. package/dist/components/icons/RespArea.d.ts +26 -0
  20. package/dist/components/icons/RespArea.js +42 -0
  21. package/dist/components/icons/TableIcons.d.ts +14 -0
  22. package/dist/components/icons/TableIcons.js +34 -0
  23. package/dist/components/icons/TextAlign.d.ts +18 -0
  24. package/dist/components/icons/TextAlign.js +143 -0
  25. package/dist/components/image/AltDialog.d.ts +22 -0
  26. package/dist/components/image/AltDialog.js +61 -0
  27. package/dist/components/image/ImageToolbar.d.ts +24 -0
  28. package/dist/components/image/ImageToolbar.js +80 -0
  29. package/dist/components/image/InsertImageHandler.d.ts +33 -0
  30. package/dist/components/image/InsertImageHandler.js +65 -0
  31. package/dist/components/image/findImageNode.d.ts +3 -0
  32. package/dist/components/image/findImageNode.js +11 -0
  33. package/dist/components/media/MediaDialog.d.ts +43 -0
  34. package/dist/components/media/MediaDialog.js +389 -0
  35. package/dist/components/media/MediaToolbar.d.ts +19 -0
  36. package/dist/components/media/MediaToolbar.js +41 -0
  37. package/dist/components/respArea/DragInTheBlank/DragInTheBlank.d.ts +23 -0
  38. package/dist/components/respArea/DragInTheBlank/DragInTheBlank.js +58 -0
  39. package/dist/components/respArea/DragInTheBlank/choice.d.ts +56 -0
  40. package/dist/components/respArea/DragInTheBlank/choice.js +157 -0
  41. package/dist/components/respArea/ExplicitConstructedResponse.d.ts +20 -0
  42. package/dist/components/respArea/ExplicitConstructedResponse.js +84 -0
  43. package/dist/components/respArea/InlineDropdown.d.ts +18 -0
  44. package/dist/components/respArea/InlineDropdown.js +126 -0
  45. package/dist/components/respArea/MathTemplated.d.ts +19 -0
  46. package/dist/components/respArea/MathTemplated.js +98 -0
  47. package/dist/components/respArea/ToolbarIcon.d.ts +14 -0
  48. package/dist/components/respArea/ToolbarIcon.js +17 -0
  49. package/dist/components/respArea/inlineDropdownUtils.d.ts +15 -0
  50. package/dist/components/respArea/inlineDropdownUtils.js +15 -0
  51. package/dist/constants.d.ts +13 -0
  52. package/dist/constants.js +4 -0
  53. package/dist/extensions/css.d.ts +11 -0
  54. package/dist/extensions/css.js +120 -0
  55. package/dist/extensions/custom-toolbar-wrapper.d.ts +11 -0
  56. package/dist/extensions/custom-toolbar-wrapper.js +61 -0
  57. package/dist/extensions/div-node.d.ts +10 -0
  58. package/dist/extensions/div-node.js +42 -0
  59. package/dist/extensions/ensure-empty-root-div.d.ts +14 -0
  60. package/dist/extensions/ensure-empty-root-div.js +24 -0
  61. package/dist/extensions/ensure-list-item-content-is-div.d.ts +15 -0
  62. package/dist/extensions/ensure-list-item-content-is-div.js +31 -0
  63. package/dist/extensions/extended-list-item.d.ts +13 -0
  64. package/dist/extensions/extended-list-item.js +5 -0
  65. package/dist/extensions/extended-table-cell.d.ts +10 -0
  66. package/dist/extensions/extended-table-cell.js +6 -0
  67. package/dist/extensions/extended-table.d.ts +17 -0
  68. package/dist/extensions/extended-table.js +34 -0
  69. package/dist/extensions/heading-paragraph.d.ts +17 -0
  70. package/dist/extensions/heading-paragraph.js +30 -0
  71. package/dist/extensions/image-component.d.ts +22 -0
  72. package/dist/extensions/image-component.js +223 -0
  73. package/dist/extensions/image.d.ts +10 -0
  74. package/dist/extensions/image.js +77 -0
  75. package/dist/extensions/index.d.ts +16 -0
  76. package/dist/extensions/index.js +64 -0
  77. package/dist/extensions/math.d.ts +15 -0
  78. package/dist/extensions/math.js +214 -0
  79. package/dist/extensions/media.d.ts +19 -0
  80. package/dist/extensions/media.js +149 -0
  81. package/dist/extensions/responseArea.d.ts +27 -0
  82. package/dist/extensions/responseArea.js +255 -0
  83. package/dist/index.d.ts +13 -0
  84. package/dist/index.js +7 -0
  85. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +16 -0
  86. package/dist/utils/helper.d.ts +9 -0
  87. package/dist/utils/helper.js +27 -0
  88. package/dist/utils/size.d.ts +9 -0
  89. package/dist/utils/size.js +14 -0
  90. package/dist/utils/toolbar.d.ts +10 -0
  91. package/dist/utils/toolbar.js +7 -0
  92. package/package.json +59 -43
  93. package/CHANGELOG.json +0 -32
  94. package/CHANGELOG.md +0 -2532
  95. package/lib/components/CharacterPicker.js +0 -226
  96. package/lib/components/CharacterPicker.js.map +0 -1
  97. package/lib/components/EditableHtml.js +0 -388
  98. package/lib/components/EditableHtml.js.map +0 -1
  99. package/lib/components/MenuBar.js +0 -702
  100. package/lib/components/MenuBar.js.map +0 -1
  101. package/lib/components/TiptapContainer.js +0 -242
  102. package/lib/components/TiptapContainer.js.map +0 -1
  103. package/lib/components/characters/characterUtils.js +0 -378
  104. package/lib/components/characters/characterUtils.js.map +0 -1
  105. package/lib/components/characters/custom-popper.js +0 -44
  106. package/lib/components/characters/custom-popper.js.map +0 -1
  107. package/lib/components/common/done-button.js +0 -34
  108. package/lib/components/common/done-button.js.map +0 -1
  109. package/lib/components/common/toolbar-buttons.js +0 -149
  110. package/lib/components/common/toolbar-buttons.js.map +0 -1
  111. package/lib/components/icons/CssIcon.js +0 -25
  112. package/lib/components/icons/CssIcon.js.map +0 -1
  113. package/lib/components/icons/RespArea.js +0 -72
  114. package/lib/components/icons/RespArea.js.map +0 -1
  115. package/lib/components/icons/TableIcons.js +0 -53
  116. package/lib/components/icons/TableIcons.js.map +0 -1
  117. package/lib/components/icons/TextAlign.js +0 -157
  118. package/lib/components/icons/TextAlign.js.map +0 -1
  119. package/lib/components/image/AltDialog.js +0 -98
  120. package/lib/components/image/AltDialog.js.map +0 -1
  121. package/lib/components/image/ImageToolbar.js +0 -137
  122. package/lib/components/image/ImageToolbar.js.map +0 -1
  123. package/lib/components/image/InsertImageHandler.js +0 -135
  124. package/lib/components/image/InsertImageHandler.js.map +0 -1
  125. package/lib/components/media/MediaDialog.js +0 -594
  126. package/lib/components/media/MediaDialog.js.map +0 -1
  127. package/lib/components/media/MediaToolbar.js +0 -74
  128. package/lib/components/media/MediaToolbar.js.map +0 -1
  129. package/lib/components/media/MediaWrapper.js +0 -67
  130. package/lib/components/media/MediaWrapper.js.map +0 -1
  131. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js +0 -84
  132. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js.map +0 -1
  133. package/lib/components/respArea/DragInTheBlank/choice.js +0 -253
  134. package/lib/components/respArea/DragInTheBlank/choice.js.map +0 -1
  135. package/lib/components/respArea/ExplicitConstructedResponse.js +0 -137
  136. package/lib/components/respArea/ExplicitConstructedResponse.js.map +0 -1
  137. package/lib/components/respArea/InlineDropdown.js +0 -223
  138. package/lib/components/respArea/InlineDropdown.js.map +0 -1
  139. package/lib/components/respArea/MathTemplated.js +0 -130
  140. package/lib/components/respArea/MathTemplated.js.map +0 -1
  141. package/lib/components/respArea/ToolbarIcon.js +0 -81
  142. package/lib/components/respArea/ToolbarIcon.js.map +0 -1
  143. package/lib/components/respArea/inlineDropdownUtils.js +0 -67
  144. package/lib/components/respArea/inlineDropdownUtils.js.map +0 -1
  145. package/lib/constants.js +0 -11
  146. package/lib/constants.js.map +0 -1
  147. package/lib/extensions/css.js +0 -227
  148. package/lib/extensions/css.js.map +0 -1
  149. package/lib/extensions/custom-toolbar-wrapper.js +0 -92
  150. package/lib/extensions/custom-toolbar-wrapper.js.map +0 -1
  151. package/lib/extensions/div-node.js +0 -83
  152. package/lib/extensions/div-node.js.map +0 -1
  153. package/lib/extensions/ensure-empty-root-div.js +0 -48
  154. package/lib/extensions/ensure-empty-root-div.js.map +0 -1
  155. package/lib/extensions/ensure-list-item-content-is-div.js +0 -64
  156. package/lib/extensions/ensure-list-item-content-is-div.js.map +0 -1
  157. package/lib/extensions/extended-list-item.js +0 -15
  158. package/lib/extensions/extended-list-item.js.map +0 -1
  159. package/lib/extensions/extended-table-cell.js +0 -22
  160. package/lib/extensions/extended-table-cell.js.map +0 -1
  161. package/lib/extensions/extended-table.js +0 -75
  162. package/lib/extensions/extended-table.js.map +0 -1
  163. package/lib/extensions/heading-paragraph.js +0 -61
  164. package/lib/extensions/heading-paragraph.js.map +0 -1
  165. package/lib/extensions/image-component.js +0 -351
  166. package/lib/extensions/image-component.js.map +0 -1
  167. package/lib/extensions/image.js +0 -134
  168. package/lib/extensions/image.js.map +0 -1
  169. package/lib/extensions/index.js +0 -46
  170. package/lib/extensions/index.js.map +0 -1
  171. package/lib/extensions/math.js +0 -469
  172. package/lib/extensions/math.js.map +0 -1
  173. package/lib/extensions/media.js +0 -243
  174. package/lib/extensions/media.js.map +0 -1
  175. package/lib/extensions/responseArea.js +0 -452
  176. package/lib/extensions/responseArea.js.map +0 -1
  177. package/lib/index.js +0 -37
  178. package/lib/index.js.map +0 -1
  179. package/lib/styles/editorContainerStyles.js +0 -137
  180. package/lib/styles/editorContainerStyles.js.map +0 -1
  181. package/lib/theme.js +0 -8
  182. package/lib/theme.js.map +0 -1
  183. package/lib/utils/helper.js +0 -73
  184. package/lib/utils/helper.js.map +0 -1
  185. package/lib/utils/size.js +0 -26
  186. package/lib/utils/size.js.map +0 -1
  187. package/lib/utils/toolbar.js +0 -19
  188. package/lib/utils/toolbar.js.map +0 -1
  189. package/src/components/CharacterPicker.jsx +0 -237
  190. package/src/components/EditableHtml.jsx +0 -458
  191. package/src/components/MenuBar.jsx +0 -561
  192. package/src/components/TiptapContainer.jsx +0 -235
  193. package/src/components/characters/characterUtils.js +0 -447
  194. package/src/components/characters/custom-popper.js +0 -38
  195. package/src/components/common/done-button.jsx +0 -27
  196. package/src/components/common/toolbar-buttons.jsx +0 -127
  197. package/src/components/icons/CssIcon.jsx +0 -15
  198. package/src/components/icons/RespArea.jsx +0 -71
  199. package/src/components/icons/TableIcons.jsx +0 -52
  200. package/src/components/icons/TextAlign.jsx +0 -114
  201. package/src/components/image/AltDialog.jsx +0 -82
  202. package/src/components/image/ImageToolbar.jsx +0 -99
  203. package/src/components/image/InsertImageHandler.js +0 -107
  204. package/src/components/media/MediaDialog.jsx +0 -596
  205. package/src/components/media/MediaToolbar.jsx +0 -49
  206. package/src/components/media/MediaWrapper.jsx +0 -39
  207. package/src/components/respArea/DragInTheBlank/DragInTheBlank.jsx +0 -76
  208. package/src/components/respArea/DragInTheBlank/choice.jsx +0 -259
  209. package/src/components/respArea/ExplicitConstructedResponse.jsx +0 -136
  210. package/src/components/respArea/InlineDropdown.jsx +0 -240
  211. package/src/components/respArea/MathTemplated.jsx +0 -124
  212. package/src/components/respArea/ToolbarIcon.jsx +0 -66
  213. package/src/components/respArea/inlineDropdownUtils.js +0 -79
  214. package/src/constants.js +0 -5
  215. package/src/extensions/css.js +0 -233
  216. package/src/extensions/custom-toolbar-wrapper.jsx +0 -78
  217. package/src/extensions/div-node.js +0 -86
  218. package/src/extensions/ensure-empty-root-div.js +0 -47
  219. package/src/extensions/ensure-list-item-content-is-div.js +0 -62
  220. package/src/extensions/extended-list-item.js +0 -10
  221. package/src/extensions/extended-table-cell.js +0 -19
  222. package/src/extensions/extended-table.js +0 -60
  223. package/src/extensions/heading-paragraph.js +0 -53
  224. package/src/extensions/image-component.jsx +0 -340
  225. package/src/extensions/image.js +0 -109
  226. package/src/extensions/index.js +0 -81
  227. package/src/extensions/math.js +0 -454
  228. package/src/extensions/media.js +0 -188
  229. package/src/extensions/responseArea.js +0 -407
  230. package/src/index.jsx +0 -5
  231. package/src/styles/editorContainerStyles.js +0 -145
  232. package/src/theme.js +0 -1
  233. package/src/utils/helper.js +0 -69
  234. package/src/utils/size.js +0 -32
  235. package/src/utils/toolbar.js +0 -15
@@ -1,458 +0,0 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
- import debounce from 'lodash-es/debounce';
3
- import { EditorContent, useEditor, useEditorState } from '@tiptap/react';
4
- import { styled } from '@mui/material/styles';
5
- import StarterKit from '@tiptap/starter-kit';
6
- import { TextStyleKit } from '@tiptap/extension-text-style';
7
- import { CharacterCount } from '@tiptap/extension-character-count';
8
- import SuperScript from '@tiptap/extension-superscript';
9
- import SubScript from '@tiptap/extension-subscript';
10
- import TextAlign from '@tiptap/extension-text-align';
11
- import Image from '@tiptap/extension-image';
12
- import Placeholder from '@tiptap/extension-placeholder';
13
- import { normalizeInitialMarkup } from '../utils/helper';
14
-
15
- import ExtendedTable from '../extensions/extended-table';
16
- import { ExtendedTableCell, ExtendedTableHeader } from '../extensions/extended-table-cell';
17
- import { DivNode } from '../extensions/div-node';
18
- import { EnsureEmptyRootIsDiv } from '../extensions/ensure-empty-root-div';
19
- import { EnsureListItemContentIsDiv } from '../extensions/ensure-list-item-content-is-div';
20
- import { TableRow } from '@tiptap/extension-table-row';
21
- import {
22
- DragInTheBlankNode,
23
- ExplicitConstructedResponseNode,
24
- InlineDropdownNode,
25
- MathTemplatedNode,
26
- ResponseAreaExtension,
27
- } from '../extensions/responseArea';
28
- import { MathNode } from '../extensions/math';
29
- import { ImageUploadNode } from '../extensions/image';
30
- import { Media } from '../extensions/media';
31
- import { CSSMark } from '../extensions/css';
32
- import { ExtendedListItem } from '../extensions/extended-list-item';
33
- import { HeadingParagraph } from '../extensions/heading-paragraph';
34
-
35
- import EditorContainer from './TiptapContainer';
36
- import { valueToSize } from '../utils/size';
37
- import { buildExtensions, PLUGINS_MAP } from '../extensions';
38
-
39
- const defaultToolbarOpts = {
40
- position: 'bottom',
41
- alignment: 'left',
42
- alwaysVisible: false,
43
- showDone: true,
44
- doneOn: 'blur',
45
- };
46
-
47
- const defaultResponseAreaProps = {
48
- options: {},
49
- respAreaToolbar: () => {},
50
- onHandleAreaChange: () => {},
51
- };
52
-
53
- const DEFAULT_ACTIVE_PLUGINS = [
54
- 'bold',
55
- 'italic',
56
- 'underline',
57
- 'strikethrough',
58
- 'code',
59
- 'bulleted-list',
60
- 'numbered-list',
61
- 'image',
62
- 'math',
63
- 'languageCharacters',
64
- 'text-align',
65
- 'table',
66
- 'video',
67
- 'audio',
68
- 'responseArea',
69
- 'superscript',
70
- 'subscript',
71
- 'css',
72
- 'h3',
73
- 'undo',
74
- 'redo',
75
- ];
76
-
77
- const cssVariables = {
78
- '--white': '#fff',
79
- '--black': '#2e2b29',
80
- '--black-contrast': '#110f0e',
81
- '--gray-1': 'rgba(61, 37, 20, .05)',
82
- '--gray-2': 'rgba(61, 37, 20, .08)',
83
- '--gray-3': 'rgba(61, 37, 20, .12)',
84
- '--gray-4': 'rgba(53, 38, 28, .3)',
85
- '--gray-5': 'rgba(28, 25, 23, .6)',
86
- '--green': '#22c55e',
87
- '--purple': '#6a00f5',
88
- '--purple-contrast': '#5800cc',
89
- '--purple-light': 'rgba(88, 5, 255, .05)',
90
- '--yellow-contrast': '#facc15',
91
- '--yellow': 'rgba(250, 204, 21, .4)',
92
- '--yellow-light': '#fffae5',
93
- '--red': '#ff5c33',
94
- '--red-light': '#ffebe5',
95
- '--shadow': `0px 12px 33px 0px rgba(0, 0, 0, .06),
96
- 0px 3.618px 9.949px 0px rgba(0, 0, 0, .04)`,
97
- };
98
-
99
- export const EditableHtml = (props) => {
100
- const { showParagraphs, separateParagraphs } = props.pluginProps || {};
101
- const [pendingImages, setPendingImages] = useState([]);
102
- const [scheduled, setScheduled] = useState(false);
103
- const { toolbarOpts } = props;
104
-
105
- const removePendingImage = useCallback(
106
- (imagePos) => {
107
- setPendingImages((prev) => {
108
- const next = prev.filter((img) => img.pos !== imagePos);
109
- if (next.length === 0) {
110
- setScheduled(false);
111
- }
112
- return next;
113
- });
114
- },
115
- [setPendingImages],
116
- );
117
-
118
- const toolbarOptsToUse = {
119
- ...defaultToolbarOpts,
120
- ...toolbarOpts,
121
- };
122
-
123
- const commitEditorContent = useCallback(
124
- (editor) => {
125
- const html = editor.getHTML();
126
-
127
- if (props.markup !== html) {
128
- props.onChange?.(html);
129
- }
130
-
131
- if (toolbarOptsToUse.doneOn === 'blur') {
132
- props.onDone?.(html);
133
- }
134
- },
135
- [props.markup, props.onChange, props.onDone, toolbarOptsToUse.doneOn],
136
- );
137
-
138
- const responseAreaPropsToUse = useMemo(
139
- () => ({
140
- ...defaultResponseAreaProps,
141
- ...props.responseAreaProps,
142
- onInlineDropdownToolbarClose: commitEditorContent,
143
- }),
144
- [props.responseAreaProps, commitEditorContent],
145
- );
146
-
147
- const activePluginsToUse = useMemo(() => {
148
- let { customPlugins, ...otherPluginProps } = props.pluginProps || {};
149
-
150
- customPlugins = customPlugins || [];
151
-
152
- const filteredActivePlugins = (props.activePlugins || DEFAULT_ACTIVE_PLUGINS)?.filter((pluginName) => {
153
- const nameToUse = PLUGINS_MAP[pluginName] || pluginName;
154
- const pluginInfo = otherPluginProps[nameToUse] || {};
155
-
156
- return !pluginInfo || !pluginInfo.disabled;
157
- });
158
-
159
- return buildExtensions(filteredActivePlugins, customPlugins, {
160
- math: {},
161
- textAlign: props.textAlign,
162
- html: {},
163
- extraCSSRules: props.extraCSSRules || {},
164
- image: {
165
- ...props.imageSupport,
166
- },
167
- toolbar: {},
168
- table: {},
169
- responseArea: {
170
- type: responseAreaPropsToUse.type,
171
- },
172
- languageCharacters: props.languageCharactersProps,
173
- keyPadCharacterRef: {},
174
- setKeypadInteraction: {},
175
- media: {},
176
- });
177
- }, [props, responseAreaPropsToUse.type]);
178
-
179
- const extensions = [
180
- TextAlign.configure({
181
- types: ['heading', 'paragraph', 'div', 'headingParagraph', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'th'],
182
- alignments: ['left', 'right', 'center', 'justify'],
183
- }),
184
- TextStyleKit,
185
- CharacterCount.configure({
186
- limit: props.charactersLimit || 1000000,
187
- }),
188
- StarterKit.configure({
189
- trailingNode: {
190
- node: 'paragraph',
191
- notAfter: ['paragraph', 'div'],
192
- },
193
- }),
194
- ExtendedListItem,
195
- DivNode,
196
- HeadingParagraph,
197
- EnsureEmptyRootIsDiv,
198
- EnsureListItemContentIsDiv,
199
- Placeholder.configure({
200
- placeholder: props.placeholder,
201
- // show placeholder even when editor is focused
202
- showOnlyWhenEditable: true,
203
- showOnlyCurrent: false, // show on all empty nodes, not only the current one
204
- includeChildren: true,
205
- }),
206
- ExtendedTable,
207
- TableRow,
208
- ExtendedTableHeader,
209
- ExtendedTableCell,
210
- ResponseAreaExtension.configure(responseAreaPropsToUse),
211
- ExplicitConstructedResponseNode.configure(responseAreaPropsToUse),
212
- DragInTheBlankNode.configure(responseAreaPropsToUse),
213
- InlineDropdownNode.configure(responseAreaPropsToUse),
214
- MathTemplatedNode.configure(responseAreaPropsToUse),
215
- MathNode.configure({
216
- toolbarOpts: toolbarOptsToUse,
217
- math: props.pluginProps?.math || {},
218
- }),
219
- SubScript,
220
- SuperScript,
221
- Image,
222
- ImageUploadNode.configure({
223
- toolbarOpts: toolbarOptsToUse,
224
- imageHandling: {
225
- disableImageAlignmentButtons: props.disableImageAlignmentButtons,
226
- onDone: (editor) => props.onDone?.(editor.getHTML()),
227
- onDelete:
228
- props.imageSupport &&
229
- props.imageSupport.delete &&
230
- ((node) => {
231
- const { src } = node.attrs;
232
-
233
- props.imageSupport.delete(src, (e) => {
234
- removePendingImage(node.pos);
235
- });
236
- }),
237
- insertImageRequested:
238
- props.imageSupport &&
239
- ((editor, imageInfo, getHandler) => {
240
- const [addedImage, pos] = imageInfo;
241
-
242
- const onFinish = (result) => {
243
- let cb;
244
-
245
- if (scheduled && result) {
246
- // finish editing only on success
247
- cb = props.onChange;
248
- }
249
-
250
- removePendingImage(pos);
251
- cb?.(editor.getHTML());
252
- };
253
-
254
- const callback = () => {
255
- /**
256
- * The handler is the object through which the outer context
257
- * communicates file upload events like: fileChosen, cancel, progress
258
- */
259
- const handler = getHandler(onFinish);
260
-
261
- // If the user closes the file picker without choosing a file, the window regains
262
- // focus while _insertingImage is still true — drop the stale pending entry.
263
- const focusHandler = debounce(() => {
264
- const detach = () => window.removeEventListener('focus', focusHandler);
265
-
266
- if (!editor._insertingImage) {
267
- detach();
268
- return;
269
- }
270
-
271
- removePendingImage(pos);
272
- editor._insertingImage = false;
273
- detach();
274
- }, 500);
275
-
276
- window.addEventListener('focus', focusHandler);
277
-
278
- props.imageSupport.add(handler);
279
- };
280
-
281
- editor._insertingImage = true;
282
- setPendingImages((prev) => [...prev, addedImage]);
283
- callback();
284
- }),
285
- maxImageWidth: props.maxImageWidth,
286
- maxImageHeight: props.maxImageHeight,
287
- },
288
- limit: 3,
289
- }),
290
- Media.configure({
291
- uploadSoundSupport: props.uploadSoundSupport,
292
- }),
293
- CSSMark.configure({
294
- extraCSSRules: props.extraCSSRules,
295
- }),
296
- ];
297
-
298
- const editor = useEditor(
299
- {
300
- extensions,
301
- immediatelyRender: false,
302
- editorProps: {
303
- handleKeyDown(view, event) {
304
- if (props.onKeyDown) {
305
- return props.onKeyDown(event);
306
- }
307
-
308
- // Return false to let default behavior continue
309
- return false;
310
- },
311
- },
312
- editable: !props.disabled,
313
- content: normalizeInitialMarkup(props.markup),
314
- onUpdate: ({ editor, transaction }) => {
315
- if (transaction.isDone) {
316
- props.onChange?.(editor.getHTML());
317
- }
318
- },
319
- onBlur: ({ editor }) => {
320
- const otherToolbarOpened =
321
- editor._insertingImage ||
322
- editor._toolbarOpened ||
323
- editor.isActive('inline_dropdown') ||
324
- editor.isActive('explicit_constructed_response');
325
-
326
- if (otherToolbarOpened || !editor.schema) {
327
- return;
328
- }
329
-
330
- commitEditorContent(editor);
331
- },
332
- },
333
- [props.charactersLimit],
334
- );
335
-
336
- useEffect(() => {
337
- if (props.editorRef) {
338
- props.editorRef(editor);
339
- }
340
- }, [props.editorRef, editor]);
341
-
342
- useEffect(() => {
343
- editor?.setEditable(!props.disabled);
344
- }, [props.disabled, editor]);
345
-
346
- useEffect(() => {
347
- if (!editor) {
348
- return;
349
- }
350
- const nextMarkup = normalizeInitialMarkup(props.markup);
351
-
352
- if (nextMarkup !== editor.getHTML()) {
353
- editor.commands.setContent(nextMarkup, { emitUpdate: false });
354
- }
355
- }, [props.markup, editor]);
356
-
357
- useEffect(() => {
358
- Object.entries(cssVariables).forEach(([key, value]) => {
359
- document.documentElement.style.setProperty(key, value);
360
- });
361
- }, []);
362
-
363
- const editorState = useEditorState({
364
- editor,
365
- selector: (ctx) => ({
366
- isFocused: ctx.editor?.isFocused,
367
- }),
368
- });
369
-
370
- const sizeStyle = useMemo(() => {
371
- const { minWidth, width, maxWidth, minHeight, height, maxHeight } = props;
372
-
373
- return {
374
- width: valueToSize(width),
375
- minWidth: valueToSize(minWidth),
376
- maxWidth: valueToSize(maxWidth),
377
- height: valueToSize(height),
378
- minHeight: valueToSize(minHeight),
379
- maxHeight: valueToSize(maxHeight),
380
- };
381
- }, [props]);
382
-
383
- return (
384
- <EditorContainer
385
- {...{
386
- ...props,
387
- activePlugins: activePluginsToUse,
388
- toolbarOpts: toolbarOptsToUse,
389
- }}
390
- editorState={editorState}
391
- editor={editor}
392
- >
393
- {editor && (
394
- <StyledEditorContent
395
- style={{
396
- minHeight: sizeStyle.minHeight,
397
- height: sizeStyle.height,
398
- maxHeight: sizeStyle.maxHeight,
399
- }}
400
- showParagraph={showParagraphs && !showParagraphs.disabled}
401
- separateParagraph={separateParagraphs && !separateParagraphs.disabled}
402
- editor={editor}
403
- />
404
- )}
405
- </EditorContainer>
406
- );
407
- };
408
-
409
- const StyledEditorContent = styled(EditorContent, {
410
- shouldForwardProp: (prop) => !['showParagraph', 'separateParagraph'].includes(prop),
411
- })(({ showParagraph, separateParagraph }) => ({
412
- display: 'flex',
413
- outline: 'none !important',
414
- '& .ProseMirror': {
415
- flex: 1,
416
- padding: '5px',
417
- maxHeight: '500px',
418
- outline: 'none !important',
419
- position: 'initial',
420
-
421
- // reset default margins for all block paragraphs/divs in the editor
422
- '& > p, & > div': {
423
- margin: '0',
424
- },
425
-
426
- // Out of flow so the caret stays at the start of the block; in-flow ::before pushes the caret after the hint text.
427
- // :only-child ensures the placeholder is hidden whenever the editor has other content (images, upload nodes, etc.)
428
- // and covers the type+backspace edge case where Tiptap only adds is-empty (not is-editor-empty).
429
- '& p[data-placeholder].is-empty:only-child, & div[data-placeholder].is-empty:only-child': {
430
- position: 'relative',
431
- },
432
- '& p[data-placeholder].is-empty:only-child::before, & div[data-placeholder].is-empty:only-child::before': {
433
- content: 'attr(data-placeholder)',
434
- position: 'absolute',
435
- left: 0,
436
- top: 0,
437
- color: '#9CA3AF',
438
- pointerEvents: 'none',
439
- whiteSpace: 'pre-wrap',
440
- },
441
-
442
- ...(showParagraph && {
443
- '& > p:has(+ p)::after, & > div:has(+ div)::after': {
444
- display: 'block',
445
- content: '"¶"',
446
- fontSize: '1em',
447
- color: '#146EB3',
448
- },
449
- }),
450
- ...(separateParagraph && {
451
- '& > p:has(+ p)': {
452
- marginBottom: '1em',
453
- },
454
- }),
455
- },
456
- }));
457
-
458
- export default EditableHtml;