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

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 (238) 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 +330 -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/media/MediaWrapper.d.ts +19 -0
  38. package/dist/components/respArea/DragInTheBlank/DragInTheBlank.d.ts +23 -0
  39. package/dist/components/respArea/DragInTheBlank/DragInTheBlank.js +58 -0
  40. package/dist/components/respArea/DragInTheBlank/choice.d.ts +56 -0
  41. package/dist/components/respArea/DragInTheBlank/choice.js +157 -0
  42. package/dist/components/respArea/ExplicitConstructedResponse.d.ts +20 -0
  43. package/dist/components/respArea/ExplicitConstructedResponse.js +84 -0
  44. package/dist/components/respArea/InlineDropdown.d.ts +18 -0
  45. package/dist/components/respArea/InlineDropdown.js +126 -0
  46. package/dist/components/respArea/MathTemplated.d.ts +19 -0
  47. package/dist/components/respArea/MathTemplated.js +98 -0
  48. package/dist/components/respArea/ToolbarIcon.d.ts +14 -0
  49. package/dist/components/respArea/ToolbarIcon.js +17 -0
  50. package/dist/components/respArea/inlineDropdownUtils.d.ts +15 -0
  51. package/dist/components/respArea/inlineDropdownUtils.js +15 -0
  52. package/dist/constants.d.ts +13 -0
  53. package/dist/constants.js +4 -0
  54. package/dist/extensions/css.d.ts +11 -0
  55. package/dist/extensions/css.js +120 -0
  56. package/dist/extensions/custom-toolbar-wrapper.d.ts +11 -0
  57. package/dist/extensions/custom-toolbar-wrapper.js +61 -0
  58. package/dist/extensions/div-node.d.ts +10 -0
  59. package/dist/extensions/div-node.js +42 -0
  60. package/dist/extensions/ensure-empty-root-div.d.ts +14 -0
  61. package/dist/extensions/ensure-empty-root-div.js +24 -0
  62. package/dist/extensions/ensure-list-item-content-is-div.d.ts +15 -0
  63. package/dist/extensions/ensure-list-item-content-is-div.js +31 -0
  64. package/dist/extensions/extended-list-item.d.ts +13 -0
  65. package/dist/extensions/extended-list-item.js +5 -0
  66. package/dist/extensions/extended-table-cell.d.ts +10 -0
  67. package/dist/extensions/extended-table-cell.js +6 -0
  68. package/dist/extensions/extended-table.d.ts +17 -0
  69. package/dist/extensions/extended-table.js +34 -0
  70. package/dist/extensions/heading-paragraph.d.ts +17 -0
  71. package/dist/extensions/heading-paragraph.js +30 -0
  72. package/dist/extensions/image-component.d.ts +22 -0
  73. package/dist/extensions/image-component.js +223 -0
  74. package/dist/extensions/image.d.ts +10 -0
  75. package/dist/extensions/image.js +77 -0
  76. package/dist/extensions/index.d.ts +16 -0
  77. package/dist/extensions/index.js +64 -0
  78. package/dist/extensions/math.d.ts +15 -0
  79. package/dist/extensions/math.js +213 -0
  80. package/dist/extensions/media.d.ts +19 -0
  81. package/dist/extensions/media.js +149 -0
  82. package/dist/extensions/responseArea.d.ts +27 -0
  83. package/dist/extensions/responseArea.js +255 -0
  84. package/dist/index.d.ts +13 -0
  85. package/dist/index.js +7 -0
  86. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +16 -0
  87. package/dist/styles/editorContainerStyles.d.ts +134 -0
  88. package/dist/theme.d.ts +9 -0
  89. package/dist/utils/helper.d.ts +9 -0
  90. package/dist/utils/helper.js +27 -0
  91. package/dist/utils/size.d.ts +9 -0
  92. package/dist/utils/size.js +14 -0
  93. package/dist/utils/toolbar.d.ts +10 -0
  94. package/dist/utils/toolbar.js +7 -0
  95. package/package.json +56 -42
  96. package/CHANGELOG.json +0 -32
  97. package/CHANGELOG.md +0 -2532
  98. package/lib/components/CharacterPicker.js +0 -226
  99. package/lib/components/CharacterPicker.js.map +0 -1
  100. package/lib/components/EditableHtml.js +0 -388
  101. package/lib/components/EditableHtml.js.map +0 -1
  102. package/lib/components/MenuBar.js +0 -702
  103. package/lib/components/MenuBar.js.map +0 -1
  104. package/lib/components/TiptapContainer.js +0 -242
  105. package/lib/components/TiptapContainer.js.map +0 -1
  106. package/lib/components/characters/characterUtils.js +0 -378
  107. package/lib/components/characters/characterUtils.js.map +0 -1
  108. package/lib/components/characters/custom-popper.js +0 -44
  109. package/lib/components/characters/custom-popper.js.map +0 -1
  110. package/lib/components/common/done-button.js +0 -34
  111. package/lib/components/common/done-button.js.map +0 -1
  112. package/lib/components/common/toolbar-buttons.js +0 -149
  113. package/lib/components/common/toolbar-buttons.js.map +0 -1
  114. package/lib/components/icons/CssIcon.js +0 -25
  115. package/lib/components/icons/CssIcon.js.map +0 -1
  116. package/lib/components/icons/RespArea.js +0 -72
  117. package/lib/components/icons/RespArea.js.map +0 -1
  118. package/lib/components/icons/TableIcons.js +0 -53
  119. package/lib/components/icons/TableIcons.js.map +0 -1
  120. package/lib/components/icons/TextAlign.js +0 -157
  121. package/lib/components/icons/TextAlign.js.map +0 -1
  122. package/lib/components/image/AltDialog.js +0 -98
  123. package/lib/components/image/AltDialog.js.map +0 -1
  124. package/lib/components/image/ImageToolbar.js +0 -137
  125. package/lib/components/image/ImageToolbar.js.map +0 -1
  126. package/lib/components/image/InsertImageHandler.js +0 -135
  127. package/lib/components/image/InsertImageHandler.js.map +0 -1
  128. package/lib/components/media/MediaDialog.js +0 -594
  129. package/lib/components/media/MediaDialog.js.map +0 -1
  130. package/lib/components/media/MediaToolbar.js +0 -74
  131. package/lib/components/media/MediaToolbar.js.map +0 -1
  132. package/lib/components/media/MediaWrapper.js +0 -67
  133. package/lib/components/media/MediaWrapper.js.map +0 -1
  134. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js +0 -84
  135. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js.map +0 -1
  136. package/lib/components/respArea/DragInTheBlank/choice.js +0 -253
  137. package/lib/components/respArea/DragInTheBlank/choice.js.map +0 -1
  138. package/lib/components/respArea/ExplicitConstructedResponse.js +0 -137
  139. package/lib/components/respArea/ExplicitConstructedResponse.js.map +0 -1
  140. package/lib/components/respArea/InlineDropdown.js +0 -223
  141. package/lib/components/respArea/InlineDropdown.js.map +0 -1
  142. package/lib/components/respArea/MathTemplated.js +0 -130
  143. package/lib/components/respArea/MathTemplated.js.map +0 -1
  144. package/lib/components/respArea/ToolbarIcon.js +0 -81
  145. package/lib/components/respArea/ToolbarIcon.js.map +0 -1
  146. package/lib/components/respArea/inlineDropdownUtils.js +0 -67
  147. package/lib/components/respArea/inlineDropdownUtils.js.map +0 -1
  148. package/lib/constants.js +0 -11
  149. package/lib/constants.js.map +0 -1
  150. package/lib/extensions/css.js +0 -227
  151. package/lib/extensions/css.js.map +0 -1
  152. package/lib/extensions/custom-toolbar-wrapper.js +0 -92
  153. package/lib/extensions/custom-toolbar-wrapper.js.map +0 -1
  154. package/lib/extensions/div-node.js +0 -83
  155. package/lib/extensions/div-node.js.map +0 -1
  156. package/lib/extensions/ensure-empty-root-div.js +0 -48
  157. package/lib/extensions/ensure-empty-root-div.js.map +0 -1
  158. package/lib/extensions/ensure-list-item-content-is-div.js +0 -64
  159. package/lib/extensions/ensure-list-item-content-is-div.js.map +0 -1
  160. package/lib/extensions/extended-list-item.js +0 -15
  161. package/lib/extensions/extended-list-item.js.map +0 -1
  162. package/lib/extensions/extended-table-cell.js +0 -22
  163. package/lib/extensions/extended-table-cell.js.map +0 -1
  164. package/lib/extensions/extended-table.js +0 -75
  165. package/lib/extensions/extended-table.js.map +0 -1
  166. package/lib/extensions/heading-paragraph.js +0 -61
  167. package/lib/extensions/heading-paragraph.js.map +0 -1
  168. package/lib/extensions/image-component.js +0 -351
  169. package/lib/extensions/image-component.js.map +0 -1
  170. package/lib/extensions/image.js +0 -134
  171. package/lib/extensions/image.js.map +0 -1
  172. package/lib/extensions/index.js +0 -46
  173. package/lib/extensions/index.js.map +0 -1
  174. package/lib/extensions/math.js +0 -469
  175. package/lib/extensions/math.js.map +0 -1
  176. package/lib/extensions/media.js +0 -243
  177. package/lib/extensions/media.js.map +0 -1
  178. package/lib/extensions/responseArea.js +0 -452
  179. package/lib/extensions/responseArea.js.map +0 -1
  180. package/lib/index.js +0 -37
  181. package/lib/index.js.map +0 -1
  182. package/lib/styles/editorContainerStyles.js +0 -137
  183. package/lib/styles/editorContainerStyles.js.map +0 -1
  184. package/lib/theme.js +0 -8
  185. package/lib/theme.js.map +0 -1
  186. package/lib/utils/helper.js +0 -73
  187. package/lib/utils/helper.js.map +0 -1
  188. package/lib/utils/size.js +0 -26
  189. package/lib/utils/size.js.map +0 -1
  190. package/lib/utils/toolbar.js +0 -19
  191. package/lib/utils/toolbar.js.map +0 -1
  192. package/src/components/CharacterPicker.jsx +0 -237
  193. package/src/components/EditableHtml.jsx +0 -458
  194. package/src/components/MenuBar.jsx +0 -561
  195. package/src/components/TiptapContainer.jsx +0 -235
  196. package/src/components/characters/characterUtils.js +0 -447
  197. package/src/components/characters/custom-popper.js +0 -38
  198. package/src/components/common/done-button.jsx +0 -27
  199. package/src/components/common/toolbar-buttons.jsx +0 -127
  200. package/src/components/icons/CssIcon.jsx +0 -15
  201. package/src/components/icons/RespArea.jsx +0 -71
  202. package/src/components/icons/TableIcons.jsx +0 -52
  203. package/src/components/icons/TextAlign.jsx +0 -114
  204. package/src/components/image/AltDialog.jsx +0 -82
  205. package/src/components/image/ImageToolbar.jsx +0 -99
  206. package/src/components/image/InsertImageHandler.js +0 -107
  207. package/src/components/media/MediaDialog.jsx +0 -596
  208. package/src/components/media/MediaToolbar.jsx +0 -49
  209. package/src/components/media/MediaWrapper.jsx +0 -39
  210. package/src/components/respArea/DragInTheBlank/DragInTheBlank.jsx +0 -76
  211. package/src/components/respArea/DragInTheBlank/choice.jsx +0 -259
  212. package/src/components/respArea/ExplicitConstructedResponse.jsx +0 -136
  213. package/src/components/respArea/InlineDropdown.jsx +0 -240
  214. package/src/components/respArea/MathTemplated.jsx +0 -124
  215. package/src/components/respArea/ToolbarIcon.jsx +0 -66
  216. package/src/components/respArea/inlineDropdownUtils.js +0 -79
  217. package/src/constants.js +0 -5
  218. package/src/extensions/css.js +0 -233
  219. package/src/extensions/custom-toolbar-wrapper.jsx +0 -78
  220. package/src/extensions/div-node.js +0 -86
  221. package/src/extensions/ensure-empty-root-div.js +0 -47
  222. package/src/extensions/ensure-list-item-content-is-div.js +0 -62
  223. package/src/extensions/extended-list-item.js +0 -10
  224. package/src/extensions/extended-table-cell.js +0 -19
  225. package/src/extensions/extended-table.js +0 -60
  226. package/src/extensions/heading-paragraph.js +0 -53
  227. package/src/extensions/image-component.jsx +0 -340
  228. package/src/extensions/image.js +0 -109
  229. package/src/extensions/index.js +0 -81
  230. package/src/extensions/math.js +0 -454
  231. package/src/extensions/media.js +0 -188
  232. package/src/extensions/responseArea.js +0 -407
  233. package/src/index.jsx +0 -5
  234. package/src/styles/editorContainerStyles.js +0 -145
  235. package/src/theme.js +0 -1
  236. package/src/utils/helper.js +0 -69
  237. package/src/utils/size.js +0 -32
  238. package/src/utils/toolbar.js +0 -15
@@ -1,188 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import ReactDOM from 'react-dom';
3
- import { mergeAttributes, Node } from '@tiptap/core';
4
- import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';
5
- import MediaDialog from '../components/media/MediaDialog';
6
- import MediaToolbar from '../components/media/MediaToolbar';
7
-
8
- export const Media = Node.create({
9
- name: 'media',
10
- group: 'inline',
11
- inline: true,
12
- atom: true,
13
-
14
- addAttributes() {
15
- return {
16
- type: { default: 'video' },
17
- src: { default: null },
18
- width: { default: null },
19
- height: { default: null },
20
- title: { default: null },
21
- starts: { default: null },
22
- ends: { default: null },
23
- editing: { default: false },
24
- tag: { default: 'iframe' }, // 'iframe' or 'audio'
25
- url: { default: null },
26
- };
27
- },
28
-
29
- parseHTML() {
30
- return [
31
- {
32
- tag: 'iframe[data-type="video"]',
33
- getAttrs: (el) => ({
34
- type: 'video',
35
- tag: 'iframe',
36
- src: el.getAttribute('src'),
37
- width: el.getAttribute('width'),
38
- height: el.getAttribute('height'),
39
- title: el.dataset.title,
40
- starts: el.dataset.starts,
41
- ends: el.dataset.ends,
42
- url: el.dataset.url,
43
- }),
44
- },
45
- {
46
- tag: 'audio',
47
- getAttrs: (el) => ({
48
- type: 'audio',
49
- tag: 'audio',
50
- src: el.querySelector('source')?.getAttribute('src'),
51
- }),
52
- },
53
- ];
54
- },
55
-
56
- renderHTML({ HTMLAttributes }) {
57
- const { tag, src, width, height } = HTMLAttributes;
58
-
59
- if (tag === 'audio') {
60
- return ['audio', { controls: 'controls', controlsList: 'nodownload' }, ['source', { src, type: 'audio/mp3' }]];
61
- }
62
-
63
- return [
64
- 'iframe',
65
- mergeAttributes(
66
- {
67
- 'data-type': 'video',
68
- frameborder: '0',
69
- allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',
70
- allowfullscreen: '',
71
- src,
72
- },
73
- width ? { width } : {},
74
- height ? { height } : {},
75
- ),
76
- ];
77
- },
78
-
79
- addCommands() {
80
- return {
81
- insertMedia:
82
- (attrs) =>
83
- ({ commands }) => {
84
- return commands.insertContent({ type: this.name, attrs });
85
- },
86
- updateMedia:
87
- (attrs) =>
88
- ({ commands }) => {
89
- return commands.updateAttributes(this.name, attrs);
90
- },
91
- };
92
- },
93
-
94
- addNodeView() {
95
- return ReactNodeViewRenderer((props) => <MediaNodeView {...{ ...props, options: this.options }} />);
96
- },
97
- });
98
-
99
- const removeDialogs = () => {
100
- const prevDialogs = document.querySelectorAll('.insert-media-dialog');
101
-
102
- prevDialogs.forEach((s) => s.remove());
103
- };
104
-
105
- export const insertDialog = (props) => {
106
- const newEl = document.createElement('div');
107
- const { type, callback, options, ...rest } = props;
108
- const initialBodyOverflow = document.body.style.overflow;
109
-
110
- removeDialogs();
111
-
112
- newEl.className = 'insert-media-dialog';
113
- document.body.style.overflow = 'hidden';
114
-
115
- const handleClose = (val, data) => {
116
- callback(val, data);
117
- newEl.remove();
118
- document.body.style.overflow = initialBodyOverflow;
119
- };
120
-
121
- const el = (
122
- <MediaDialog
123
- {...rest}
124
- uploadSoundSupport={options.uploadSoundSupport}
125
- type={type}
126
- disablePortal={true}
127
- open={true}
128
- handleClose={handleClose}
129
- />
130
- );
131
-
132
- ReactDOM.render(el, newEl);
133
-
134
- document.body.appendChild(newEl);
135
- };
136
-
137
- export default function MediaNodeView({ editor, node, updateAttributes, deleteNode, options }) {
138
- const { type, src, width, height, tag } = node.attrs;
139
-
140
- const handleEdit = () => {
141
- insertDialog({
142
- ...node.attrs,
143
- options: options,
144
- edit: true,
145
- callback: (val, data) => {
146
- if (val) {
147
- updateAttributes(data);
148
- }
149
-
150
- editor.chain().focus().run();
151
- },
152
- });
153
- };
154
-
155
- useEffect(() => {
156
- // Only open dialog for newly inserted media without a src
157
- if (!src) {
158
- insertDialog({
159
- ...node.attrs,
160
- options: options,
161
- edit: true,
162
- callback: (val, data) => {
163
- if (val) {
164
- updateAttributes(data);
165
- } else {
166
- deleteNode();
167
- }
168
-
169
- editor.chain().focus().run();
170
- },
171
- });
172
- }
173
- }, []);
174
-
175
- return (
176
- <NodeViewWrapper data-type={type} style={{ width, height }}>
177
- {tag === 'audio' ? (
178
- <audio controls controlsList="nodownload">
179
- <source type="audio/mp3" src={src} />
180
- </audio>
181
- ) : (
182
- <iframe src={src} allowFullScreen frameBorder="0" width={width} height={height} />
183
- )}
184
-
185
- <MediaToolbar onEdit={handleEdit} onRemove={deleteNode} />
186
- </NodeViewWrapper>
187
- );
188
- }
@@ -1,407 +0,0 @@
1
- import React from 'react';
2
- import { NodeSelection, Plugin, PluginKey, TextSelection } from 'prosemirror-state';
3
- import { Extension } from '@tiptap/core';
4
- import { Node, ReactNodeViewRenderer } from '@tiptap/react';
5
- import ExplicitConstructedResponse from '../components/respArea/ExplicitConstructedResponse';
6
- import DragInTheBlank from '../components/respArea/DragInTheBlank/DragInTheBlank';
7
- import InlineDropdown from '../components/respArea/InlineDropdown';
8
- import MathTemplated from '../components/respArea/MathTemplated';
9
-
10
- const lastIndexMap = {};
11
-
12
- const normalizeType = (type) => String(type || '').replace(/-/g, '_');
13
-
14
- const getAttrIndex = (node) => (node && node.attrs && node.attrs.index != null ? String(node.attrs.index) : null);
15
-
16
- const collectNodesOfType = (doc, typeName) => {
17
- const results = [];
18
-
19
- doc.descendants((node, pos) => {
20
- if (node.type && node.type.name === typeName) {
21
- const index = getAttrIndex(node);
22
- if (index != null) results.push({ index, pos, node });
23
- }
24
- return true;
25
- });
26
-
27
- return results;
28
- };
29
-
30
- const countNodesOfType = (doc, typeName) => {
31
- let count = 0;
32
- doc.descendants((node) => {
33
- if (node.type && node.type.name === typeName) count += 1;
34
- return true;
35
- });
36
- return count;
37
- };
38
-
39
- const getDefaultNode = ({ schema, typeName, index }) => {
40
- const nodeType = schema.nodes[typeName];
41
- if (!nodeType) return null;
42
-
43
- // mirror your Slate "getDefaultElement(opts, newIndex)"
44
- // customize attrs as needed:
45
- return nodeType.create({
46
- index: String(index),
47
- id: String(index),
48
- value: '',
49
- });
50
- };
51
-
52
- // Find a good cursor position *after* an inserted node.
53
- const selectionAfterPos = (doc, pos) => {
54
- const $pos = doc.resolve(Math.min(pos, doc.content.size));
55
- return TextSelection.near($pos, 1);
56
- };
57
-
58
- export const ResponseAreaExtension = Extension.create({
59
- name: 'responseArea',
60
-
61
- addOptions() {
62
- return {
63
- maxResponseAreas: null,
64
- error: null,
65
- options: null,
66
- respAreaToolbar: null,
67
- onHandleAreaChange: null,
68
- };
69
- },
70
-
71
- addProseMirrorPlugins() {
72
- if (!this.options.type) {
73
- return [];
74
- }
75
-
76
- const typeName = normalizeType(this.options.type);
77
- const key = new PluginKey(`response-area-watcher:${typeName}`);
78
-
79
- return [
80
- new Plugin({
81
- key,
82
-
83
- view: (view) => {
84
- // Lazy init lastIndexMap[typeName]
85
- if (lastIndexMap[typeName] === undefined) {
86
- lastIndexMap[typeName] = 0;
87
-
88
- view.state.doc.descendants((node) => {
89
- if (node.type && node.type.name === typeName) {
90
- const idx = getAttrIndex(node);
91
- if (idx != null) {
92
- const n = parseInt(idx, 10);
93
- if (!Number.isNaN(n) && n > lastIndexMap[typeName]) {
94
- lastIndexMap[typeName] = n;
95
- }
96
- }
97
- }
98
- return true;
99
- });
100
- }
101
-
102
- return {
103
- update: (view, prevState) => {
104
- const state = view.state;
105
- if (prevState.doc.eq(state.doc)) return;
106
-
107
- const currentList = collectNodesOfType(state.doc, typeName);
108
- const oldList = collectNodesOfType(prevState.doc, typeName);
109
-
110
- if (this.options.toolbar) {
111
- this.options.toolbar.disabled = currentList.length >= this.options.maxResponseAreas;
112
- }
113
-
114
- // Removed elements (same logic as Slate)
115
- if (oldList.length > currentList.length) {
116
- const currentIndexSet = new Set(currentList.map((x) => x.index));
117
-
118
- const removed = oldList.filter((x) => !currentIndexSet.has(x.index));
119
-
120
- if (removed.length && typeof this.options.onHandleAreaChange === 'function') {
121
- this.options.onHandleAreaChange(removed);
122
- }
123
- }
124
- },
125
- };
126
- },
127
- }),
128
- ];
129
- },
130
-
131
- addCommands() {
132
- return {
133
- insertResponseArea:
134
- (type) =>
135
- ({ tr, state, dispatch, commands }) => {
136
- const typeName = normalizeType(type);
137
-
138
- // --- Slate: currentRespAreaList + max check ---
139
- const currentCount = countNodesOfType(state.doc, typeName);
140
- if (currentCount >= this.options.maxResponseAreas) {
141
- return false;
142
- }
143
-
144
- // --- Slate: indexing logic (kept identical) ---
145
- if (lastIndexMap[typeName] === undefined) {
146
- lastIndexMap[typeName] = 0;
147
- }
148
-
149
- const prevIndex = lastIndexMap[typeName];
150
- const newIndex = prevIndex + 1;
151
-
152
- // Slate increments map even if newIndex === 0
153
- lastIndexMap[typeName] += 1;
154
-
155
- const newInline = getDefaultNode({
156
- schema: state.schema,
157
- typeName,
158
- index: newIndex,
159
- });
160
-
161
- if (!newInline) {
162
- return false;
163
- }
164
-
165
- // --- Insert logic ---
166
- const { selection } = state;
167
- let insertPos = selection.from;
168
-
169
- // If we're in a NodeSelection, insert before/after is ambiguous;
170
- // We'll insert at its "from" (like your current code).
171
- // If insertion fails, we fallback to end of doc.
172
- const tryInsertAt = (pos) => {
173
- try {
174
- tr.insert(pos, newInline);
175
- return pos;
176
- } catch (e) {
177
- return null;
178
- }
179
- };
180
-
181
- let usedPos = tryInsertAt(insertPos);
182
-
183
- // Slate branch: "markup empty and there's no focus"
184
- // ProseMirror doesn't expose "no focus" the same way, so the closest
185
- // equivalent fallback is inserting at end of document.
186
- if (usedPos == null) {
187
- usedPos = tryInsertAt(tr.doc.content.size);
188
- }
189
-
190
- if (usedPos == null) {
191
- return false;
192
- }
193
-
194
- // Optionally select the node you just inserted (like your original command)
195
- // tr.setSelection(NodeSelection.create(tr.doc, usedPos))
196
-
197
- // --- Cursor move behavior for certain types (Slate: moveFocusTo next text) ---
198
- // Only types whose node view opens its own toolbar on selection
199
- // (inline_dropdown, explicit_constructed_response) benefit from a
200
- // NodeSelection here — the toolbar is the visual feedback that it's
201
- // selected. math_templated has no such UI, so a NodeSelection there
202
- // just looks unfocused (a highlighted node, no blinking caret);
203
- // moving the cursor to just after it gives a real, visible caret.
204
- if (['inline_dropdown', 'explicit_constructed_response'].includes(typeName)) {
205
- tr.setSelection(NodeSelection.create(tr.doc, usedPos));
206
- } else {
207
- const after = usedPos + newInline.nodeSize;
208
- tr.setSelection(selectionAfterPos(tr.doc, after));
209
- }
210
-
211
- if (dispatch) {
212
- commands.focus();
213
- dispatch(tr);
214
- }
215
-
216
- return true;
217
- },
218
- refreshResponseArea:
219
- () =>
220
- ({ tr, state, commands, dispatch }) => {
221
- const { selection } = state;
222
- const node = selection.$from.nodeAfter;
223
- const nodePos = selection.from;
224
-
225
- tr.setNodeMarkup(nodePos, undefined, { ...node?.attrs, updated: `${Date.now()}` });
226
- tr.setSelection(NodeSelection.create(tr.doc, nodePos));
227
-
228
- if (dispatch) {
229
- commands.focus();
230
- dispatch(tr);
231
- }
232
-
233
- return true;
234
- },
235
- };
236
- },
237
- });
238
-
239
- /**
240
- * ExplicitConstructedResponse Node
241
- */
242
- export const ExplicitConstructedResponseNode = Node.create({
243
- name: 'explicit_constructed_response',
244
- group: 'inline',
245
- inline: true,
246
- atom: true,
247
- addAttributes() {
248
- return {
249
- index: { default: null },
250
- value: { default: '' },
251
- updated: { default: '' },
252
- };
253
- },
254
- parseHTML() {
255
- return [
256
- {
257
- tag: 'span[data-type="explicit_constructed_response"]',
258
- getAttrs: (el) => ({
259
- index: el.dataset.index,
260
- value: el.dataset.value,
261
- }),
262
- },
263
- ];
264
- },
265
- renderHTML({ HTMLAttributes }) {
266
- return [
267
- 'span',
268
- {
269
- 'data-type': 'explicit_constructed_response',
270
- 'data-index': HTMLAttributes.index,
271
- 'data-value': HTMLAttributes.value,
272
- },
273
- ];
274
- },
275
- addNodeView() {
276
- return ReactNodeViewRenderer((props) => <ExplicitConstructedResponse {...{ ...props, options: this.options }} />);
277
- },
278
- });
279
-
280
- /**
281
- * MathTemplated Node
282
- */
283
- export const MathTemplatedNode = Node.create({
284
- name: 'math_templated',
285
- group: 'inline',
286
- inline: true,
287
- atom: true,
288
- addAttributes() {
289
- return {
290
- index: { default: null },
291
- value: { default: '' },
292
- updated: { default: '' },
293
- };
294
- },
295
- parseHTML() {
296
- return [
297
- {
298
- tag: 'span[data-type="math_templated"]',
299
- getAttrs: (el) => ({
300
- index: el.dataset.index,
301
- value: el.dataset.value,
302
- }),
303
- },
304
- ];
305
- },
306
- renderHTML({ HTMLAttributes }) {
307
- return [
308
- 'span',
309
- {
310
- 'data-type': 'math_templated',
311
- 'data-index': HTMLAttributes.index,
312
- 'data-value': HTMLAttributes.value,
313
- },
314
- ];
315
- },
316
- addNodeView() {
317
- return ReactNodeViewRenderer((props) => <MathTemplated {...{ ...props, options: this.options }} />);
318
- },
319
- });
320
-
321
- /**
322
- * DragInTheBlank Node
323
- */
324
- export const DragInTheBlankNode = Node.create({
325
- name: 'drag_in_the_blank',
326
- group: 'inline',
327
- inline: true,
328
- atom: true,
329
- addAttributes() {
330
- return {
331
- index: { default: null },
332
- id: { default: null },
333
- value: { default: '' },
334
- inTable: { default: null },
335
- updated: { default: '' },
336
- };
337
- },
338
- parseHTML() {
339
- return [
340
- {
341
- tag: 'span[data-type="drag_in_the_blank"]',
342
- getAttrs: (el) => ({
343
- index: el.dataset.index,
344
- id: el.dataset.id,
345
- value: el.dataset.value,
346
- inTable: el.dataset.inTable,
347
- }),
348
- },
349
- ];
350
- },
351
- renderHTML({ HTMLAttributes }) {
352
- return [
353
- 'span',
354
- {
355
- 'data-type': 'drag_in_the_blank',
356
- 'data-index': HTMLAttributes.index,
357
- 'data-id': HTMLAttributes.id,
358
- 'data-value': HTMLAttributes.value,
359
- 'data-in-table': HTMLAttributes.inTable,
360
- },
361
- ];
362
- },
363
- addNodeView() {
364
- return ReactNodeViewRenderer((props) => <DragInTheBlank {...{ ...props, options: this.options }} />);
365
- },
366
- });
367
-
368
- /**
369
- * InlineDropdown Node
370
- */
371
- export const InlineDropdownNode = Node.create({
372
- name: 'inline_dropdown',
373
- group: 'inline',
374
- inline: true,
375
- atom: true,
376
- addAttributes() {
377
- return {
378
- index: { default: null },
379
- value: { default: '' },
380
- updated: { default: '' },
381
- };
382
- },
383
- parseHTML() {
384
- return [
385
- {
386
- tag: 'span[data-type="inline_dropdown"]',
387
- getAttrs: (el) => ({
388
- index: el.dataset.index,
389
- value: el.dataset.value,
390
- }),
391
- },
392
- ];
393
- },
394
- renderHTML({ HTMLAttributes }) {
395
- return [
396
- 'span',
397
- {
398
- 'data-type': 'inline_dropdown',
399
- 'data-index': HTMLAttributes.index,
400
- 'data-value': HTMLAttributes.value,
401
- },
402
- ];
403
- },
404
- addNodeView() {
405
- return ReactNodeViewRenderer((props) => <InlineDropdown {...{ ...props, options: this.options }} />);
406
- },
407
- });
package/src/index.jsx DELETED
@@ -1,5 +0,0 @@
1
- import StyledEditor, { EditableHtml } from './components/EditableHtml';
2
- import { ALL_PLUGINS, DEFAULT_PLUGINS } from './extensions';
3
- import { deleteInlineDropdownByIndex } from './components/respArea/inlineDropdownUtils';
4
- export { EditableHtml, ALL_PLUGINS, DEFAULT_PLUGINS, deleteInlineDropdownByIndex };
5
- export default StyledEditor;