@pie-lib/editable-html-tip-tap 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 (167) hide show
  1. package/CHANGELOG.json +32 -0
  2. package/CHANGELOG.md +2280 -0
  3. package/lib/__tests__/editor.test.js +470 -0
  4. package/lib/__tests__/serialization.test.js +246 -0
  5. package/lib/__tests__/utils.js +106 -0
  6. package/lib/block-tags.js +25 -0
  7. package/lib/constants.js +16 -0
  8. package/lib/editor.js +1356 -0
  9. package/lib/extensions/MediaView.js +112 -0
  10. package/lib/extensions/characters.js +65 -0
  11. package/lib/extensions/component.js +325 -0
  12. package/lib/extensions/css.js +252 -0
  13. package/lib/extensions/custom-toolbar-wrapper.js +124 -0
  14. package/lib/extensions/image.js +106 -0
  15. package/lib/extensions/math.js +330 -0
  16. package/lib/extensions/media.js +276 -0
  17. package/lib/extensions/responseArea.js +278 -0
  18. package/lib/index.js +1213 -0
  19. package/lib/old-index.js +269 -0
  20. package/lib/parse-html.js +16 -0
  21. package/lib/plugins/characters/custom-popper.js +73 -0
  22. package/lib/plugins/characters/index.js +305 -0
  23. package/lib/plugins/characters/utils.js +381 -0
  24. package/lib/plugins/css/icons/index.js +37 -0
  25. package/lib/plugins/css/index.js +390 -0
  26. package/lib/plugins/customPlugin/index.js +114 -0
  27. package/lib/plugins/html/icons/index.js +38 -0
  28. package/lib/plugins/html/index.js +81 -0
  29. package/lib/plugins/image/__tests__/component.test.js +51 -0
  30. package/lib/plugins/image/__tests__/image-toolbar-logic.test.js +56 -0
  31. package/lib/plugins/image/__tests__/image-toolbar.test.js +26 -0
  32. package/lib/plugins/image/__tests__/index.test.js +98 -0
  33. package/lib/plugins/image/__tests__/insert-image-handler.test.js +125 -0
  34. package/lib/plugins/image/__tests__/mock-change.js +25 -0
  35. package/lib/plugins/image/alt-dialog.js +129 -0
  36. package/lib/plugins/image/component.js +419 -0
  37. package/lib/plugins/image/image-toolbar.js +177 -0
  38. package/lib/plugins/image/index.js +263 -0
  39. package/lib/plugins/image/insert-image-handler.js +117 -0
  40. package/lib/plugins/index.js +413 -0
  41. package/lib/plugins/list/__tests__/index.test.js +79 -0
  42. package/lib/plugins/list/index.js +334 -0
  43. package/lib/plugins/math/__tests__/index.test.js +300 -0
  44. package/lib/plugins/math/index.js +454 -0
  45. package/lib/plugins/media/__tests__/index.test.js +71 -0
  46. package/lib/plugins/media/index.js +387 -0
  47. package/lib/plugins/media/media-dialog.js +709 -0
  48. package/lib/plugins/media/media-toolbar.js +101 -0
  49. package/lib/plugins/media/media-wrapper.js +93 -0
  50. package/lib/plugins/rendering/index.js +46 -0
  51. package/lib/plugins/respArea/drag-in-the-blank/choice.js +289 -0
  52. package/lib/plugins/respArea/drag-in-the-blank/index.js +94 -0
  53. package/lib/plugins/respArea/explicit-constructed-response/index.js +120 -0
  54. package/lib/plugins/respArea/icons/index.js +95 -0
  55. package/lib/plugins/respArea/index.js +341 -0
  56. package/lib/plugins/respArea/inline-dropdown/index.js +126 -0
  57. package/lib/plugins/respArea/math-templated/index.js +130 -0
  58. package/lib/plugins/respArea/utils.js +125 -0
  59. package/lib/plugins/table/CustomTablePlugin.js +133 -0
  60. package/lib/plugins/table/__tests__/index.test.js +442 -0
  61. package/lib/plugins/table/__tests__/table-toolbar.test.js +54 -0
  62. package/lib/plugins/table/icons/index.js +69 -0
  63. package/lib/plugins/table/index.js +483 -0
  64. package/lib/plugins/table/table-toolbar.js +187 -0
  65. package/lib/plugins/textAlign/icons/index.js +194 -0
  66. package/lib/plugins/textAlign/index.js +34 -0
  67. package/lib/plugins/toolbar/__tests__/default-toolbar.test.js +128 -0
  68. package/lib/plugins/toolbar/__tests__/editor-and-toolbar.test.js +51 -0
  69. package/lib/plugins/toolbar/__tests__/toolbar-buttons.test.js +54 -0
  70. package/lib/plugins/toolbar/__tests__/toolbar.test.js +120 -0
  71. package/lib/plugins/toolbar/default-toolbar.js +229 -0
  72. package/lib/plugins/toolbar/done-button.js +53 -0
  73. package/lib/plugins/toolbar/editor-and-toolbar.js +286 -0
  74. package/lib/plugins/toolbar/index.js +34 -0
  75. package/lib/plugins/toolbar/toolbar-buttons.js +194 -0
  76. package/lib/plugins/toolbar/toolbar.js +376 -0
  77. package/lib/plugins/utils.js +62 -0
  78. package/lib/serialization.js +677 -0
  79. package/lib/shared/alert-dialog.js +75 -0
  80. package/lib/theme.js +9 -0
  81. package/package.json +69 -0
  82. package/src/__tests__/editor.test.jsx +363 -0
  83. package/src/__tests__/serialization.test.js +291 -0
  84. package/src/__tests__/utils.js +36 -0
  85. package/src/block-tags.js +17 -0
  86. package/src/constants.js +7 -0
  87. package/src/editor.jsx +1197 -0
  88. package/src/extensions/characters.js +46 -0
  89. package/src/extensions/component.jsx +294 -0
  90. package/src/extensions/css.js +217 -0
  91. package/src/extensions/custom-toolbar-wrapper.jsx +100 -0
  92. package/src/extensions/image.js +55 -0
  93. package/src/extensions/math.js +259 -0
  94. package/src/extensions/media.js +182 -0
  95. package/src/extensions/responseArea.js +205 -0
  96. package/src/index.jsx +1462 -0
  97. package/src/old-index.jsx +162 -0
  98. package/src/parse-html.js +8 -0
  99. package/src/plugins/README.md +27 -0
  100. package/src/plugins/characters/custom-popper.js +48 -0
  101. package/src/plugins/characters/index.jsx +284 -0
  102. package/src/plugins/characters/utils.js +447 -0
  103. package/src/plugins/css/icons/index.jsx +17 -0
  104. package/src/plugins/css/index.jsx +340 -0
  105. package/src/plugins/customPlugin/index.jsx +85 -0
  106. package/src/plugins/html/icons/index.jsx +19 -0
  107. package/src/plugins/html/index.jsx +72 -0
  108. package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +51 -0
  109. package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +27 -0
  110. package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +44 -0
  111. package/src/plugins/image/__tests__/component.test.jsx +41 -0
  112. package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +42 -0
  113. package/src/plugins/image/__tests__/image-toolbar.test.jsx +11 -0
  114. package/src/plugins/image/__tests__/index.test.js +95 -0
  115. package/src/plugins/image/__tests__/insert-image-handler.test.js +113 -0
  116. package/src/plugins/image/__tests__/mock-change.js +15 -0
  117. package/src/plugins/image/alt-dialog.jsx +82 -0
  118. package/src/plugins/image/component.jsx +343 -0
  119. package/src/plugins/image/image-toolbar.jsx +100 -0
  120. package/src/plugins/image/index.jsx +227 -0
  121. package/src/plugins/image/insert-image-handler.js +79 -0
  122. package/src/plugins/index.jsx +377 -0
  123. package/src/plugins/list/__tests__/index.test.js +54 -0
  124. package/src/plugins/list/index.jsx +305 -0
  125. package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +48 -0
  126. package/src/plugins/math/__tests__/index.test.jsx +245 -0
  127. package/src/plugins/math/index.jsx +379 -0
  128. package/src/plugins/media/__tests__/index.test.js +75 -0
  129. package/src/plugins/media/index.jsx +325 -0
  130. package/src/plugins/media/media-dialog.js +624 -0
  131. package/src/plugins/media/media-toolbar.jsx +56 -0
  132. package/src/plugins/media/media-wrapper.jsx +43 -0
  133. package/src/plugins/rendering/index.js +31 -0
  134. package/src/plugins/respArea/drag-in-the-blank/choice.jsx +215 -0
  135. package/src/plugins/respArea/drag-in-the-blank/index.jsx +70 -0
  136. package/src/plugins/respArea/explicit-constructed-response/index.jsx +92 -0
  137. package/src/plugins/respArea/icons/index.jsx +71 -0
  138. package/src/plugins/respArea/index.jsx +299 -0
  139. package/src/plugins/respArea/inline-dropdown/index.jsx +108 -0
  140. package/src/plugins/respArea/math-templated/index.jsx +104 -0
  141. package/src/plugins/respArea/utils.jsx +90 -0
  142. package/src/plugins/table/CustomTablePlugin.js +113 -0
  143. package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +44 -0
  144. package/src/plugins/table/__tests__/index.test.jsx +401 -0
  145. package/src/plugins/table/__tests__/table-toolbar.test.jsx +42 -0
  146. package/src/plugins/table/icons/index.jsx +53 -0
  147. package/src/plugins/table/index.jsx +427 -0
  148. package/src/plugins/table/table-toolbar.jsx +136 -0
  149. package/src/plugins/textAlign/icons/index.jsx +114 -0
  150. package/src/plugins/textAlign/index.jsx +23 -0
  151. package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +923 -0
  152. package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +20 -0
  153. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +36 -0
  154. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +46 -0
  155. package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +94 -0
  156. package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +37 -0
  157. package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +51 -0
  158. package/src/plugins/toolbar/__tests__/toolbar.test.jsx +106 -0
  159. package/src/plugins/toolbar/default-toolbar.jsx +206 -0
  160. package/src/plugins/toolbar/done-button.jsx +38 -0
  161. package/src/plugins/toolbar/editor-and-toolbar.jsx +257 -0
  162. package/src/plugins/toolbar/index.jsx +23 -0
  163. package/src/plugins/toolbar/toolbar-buttons.jsx +138 -0
  164. package/src/plugins/toolbar/toolbar.jsx +338 -0
  165. package/src/plugins/utils.js +31 -0
  166. package/src/serialization.jsx +621 -0
  167. package/src/theme.js +1 -0
@@ -0,0 +1,325 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { Inline } from 'slate';
4
+ import TheatersIcon from '@material-ui/icons/Theaters';
5
+ import VolumeUpIcon from '@material-ui/icons/VolumeUp';
6
+ import debug from 'debug';
7
+
8
+ import MediaDialog from './media-dialog';
9
+ import MediaToolbar from './media-toolbar';
10
+ import MediaWrapper from './media-wrapper';
11
+
12
+ const log = debug('@pie-lib:editable-html:plugins:image');
13
+
14
+ const removeDialogs = () => {
15
+ const prevDialogs = document.querySelectorAll('.insert-media-dialog');
16
+
17
+ prevDialogs.forEach((s) => s.remove());
18
+ };
19
+
20
+ export const insertDialog = (props) => {
21
+ const newEl = document.createElement('div');
22
+ const { type, callback, opts, ...rest } = props;
23
+ const initialBodyOverflow = document.body.style.overflow;
24
+
25
+ removeDialogs();
26
+
27
+ newEl.className = 'insert-media-dialog';
28
+ document.body.style.overflow = 'hidden';
29
+
30
+ const handleClose = (val, data) => {
31
+ callback(val, data);
32
+ newEl.remove();
33
+ document.body.style.overflow = initialBodyOverflow;
34
+ };
35
+
36
+ const el = (
37
+ <MediaDialog
38
+ {...rest}
39
+ uploadSoundSupport={opts.uploadSoundSupport}
40
+ type={type}
41
+ disablePortal={true}
42
+ open={true}
43
+ handleClose={handleClose}
44
+ />
45
+ );
46
+
47
+ ReactDOM.render(el, newEl);
48
+
49
+ document.body.appendChild(newEl);
50
+ };
51
+
52
+ const types = ['audio', 'video'];
53
+
54
+ export default function MediaPlugin(type, opts) {
55
+ const toolbar = {
56
+ icon: type === 'audio' ? <VolumeUpIcon /> : <TheatersIcon />,
57
+ ariaLabel: type === 'audio' ? 'Insert audio' : 'Insert video',
58
+ onClick: (value, onChange) => {
59
+ log('[toolbar] onClick');
60
+ const inline = Inline.create({
61
+ type: type,
62
+ isVoid: true,
63
+ data: {
64
+ editing: false,
65
+ ends: undefined,
66
+ height: undefined,
67
+ title: undefined,
68
+ starts: undefined,
69
+ src: undefined,
70
+ url: undefined,
71
+ width: undefined,
72
+ },
73
+ });
74
+
75
+ const change = value.change().insertInline(inline);
76
+ onChange(change);
77
+ insertDialog({
78
+ type,
79
+ opts,
80
+ callback: (val, data) => {
81
+ const nodeIsThere = change.value.document.findDescendant((d) => d.key === inline.key);
82
+
83
+ if (nodeIsThere) {
84
+ if (!val) {
85
+ const c = change.removeNodeByKey(inline.key);
86
+ onChange(c, () => opts.focus());
87
+ } else {
88
+ const c = change.setNodeByKey(inline.key, { data });
89
+ onChange(c, () => opts.focus('beginning', nodeIsThere));
90
+ }
91
+ } else {
92
+ opts.focus();
93
+ }
94
+ },
95
+ });
96
+ },
97
+ supports: (node) => node.object === 'inline' && node.type === type,
98
+ };
99
+
100
+ return {
101
+ name: type,
102
+ toolbar,
103
+ deleteNode: (e, node, value, onChange) => {
104
+ e.preventDefault();
105
+ const change = value.change().removeNodeByKey(node.key);
106
+
107
+ onChange(change);
108
+ },
109
+ renderNode(props) {
110
+ if (props.node.type === type) {
111
+ const { node, key } = props;
112
+ const { data } = node;
113
+ const jsonData = data.toJSON();
114
+ const { src, height, width, editing, tag, ...rest } = jsonData;
115
+ const handleEdit = () => {
116
+ const change = opts.createChange();
117
+ const c = change.setNodeByKey(key, {
118
+ data: {
119
+ ...jsonData,
120
+ editing: true,
121
+ },
122
+ });
123
+
124
+ opts.onChange(c, () => {
125
+ insertDialog({
126
+ ...jsonData,
127
+ edit: true,
128
+ type,
129
+ opts,
130
+ callback: (val, data) => {
131
+ const { key } = node;
132
+
133
+ const nodeIsThere = change.value.document.findDescendant(
134
+ (d) => d.type === type && d.data.get('editing'),
135
+ );
136
+
137
+ if (nodeIsThere && val) {
138
+ const c = change.setNodeByKey(key, { data, editing: false });
139
+ opts.onChange(c, () => opts.focus('beginning', nodeIsThere));
140
+ } else {
141
+ opts.focus();
142
+ }
143
+ },
144
+ });
145
+ });
146
+ };
147
+ const handleDelete = () => {
148
+ const change = opts.createChange();
149
+ const c = change.removeNodeByKey(node.key);
150
+
151
+ opts.onChange(c);
152
+ };
153
+ const style = {};
154
+
155
+ if (width) {
156
+ style.width = `${width}px`;
157
+ }
158
+
159
+ if (height) {
160
+ style.height = `${height}px`;
161
+ }
162
+
163
+ if (tag === 'audio') {
164
+ return (
165
+ <MediaWrapper editor data-type={type} width={style.width} {...rest}>
166
+ <audio controls="controls" controlsList="nodownload">
167
+ <source type="audio/mp3" src={src} />
168
+ </audio>
169
+ <MediaToolbar hideEdit onRemove={handleDelete} />
170
+ </MediaWrapper>
171
+ );
172
+ }
173
+
174
+ return (
175
+ <MediaWrapper editor data-type={type} width={style.width} {...rest}>
176
+ <iframe
177
+ frameBorder="0"
178
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
179
+ allowFullScreen
180
+ src={src}
181
+ editing={editing ? 1 : 0}
182
+ {...rest}
183
+ {...style}
184
+ />
185
+ <MediaToolbar onEdit={handleEdit} onRemove={handleDelete} />
186
+ </MediaWrapper>
187
+ );
188
+ }
189
+ },
190
+ normalizeNode: (node) => {
191
+ const textNodeMap = {};
192
+ const updateNodesArray = [];
193
+ let index = 0;
194
+
195
+ if (node.object !== 'document') return;
196
+
197
+ node.findDescendant((d) => {
198
+ if (d.object === 'text') {
199
+ textNodeMap[index] = d;
200
+ }
201
+
202
+ const isMedia = types.indexOf(d.type) >= 0;
203
+
204
+ if (isMedia) {
205
+ if (index > 0 && textNodeMap[index - 1] && textNodeMap[index - 1].text === '') {
206
+ updateNodesArray.push(textNodeMap[index - 1]);
207
+ }
208
+ }
209
+
210
+ index++;
211
+ });
212
+
213
+ if (!updateNodesArray.length) return;
214
+
215
+ return (change) => {
216
+ change.withoutNormalization(() => {
217
+ updateNodesArray.forEach((n) => change.insertTextByKey(n.key, 0, ' '));
218
+ });
219
+ };
220
+ },
221
+ };
222
+ }
223
+
224
+ export const serialization = {
225
+ deserialize(el /*, next*/) {
226
+ let type = el.dataset && el.dataset.type;
227
+ let tag = 'iframe';
228
+ let src;
229
+ const typeIndex = types.indexOf(type);
230
+
231
+ if (typeIndex < 0) {
232
+ if (el instanceof Element && el.tagName.toLowerCase() === 'audio') {
233
+ type = 'audio';
234
+ tag = 'audio';
235
+ src = el.firstChild?.getAttribute('src');
236
+ } else {
237
+ return;
238
+ }
239
+ }
240
+
241
+ const { ends, starts, title, editing, url } = el.dataset || {};
242
+
243
+ log('deserialize: ', name);
244
+ const width = parseInt(el.getAttribute('width'), 10) || null;
245
+ const height = parseInt(el.getAttribute('height'), 10) || null;
246
+
247
+ const out = {
248
+ object: 'inline',
249
+ type: type,
250
+ isVoid: true,
251
+ data: {
252
+ tag,
253
+ src: src || el.getAttribute('src'),
254
+ editing,
255
+ ends,
256
+ height,
257
+ starts,
258
+ title,
259
+ width,
260
+ url,
261
+ },
262
+ };
263
+ log('return object: ', out);
264
+ return out;
265
+ },
266
+ serialize(object /*, children*/) {
267
+ const typeIndex = types.indexOf(object.type);
268
+
269
+ if (typeIndex < 0) return;
270
+
271
+ const type = types[typeIndex];
272
+
273
+ const { data } = object;
274
+ const editing = data.get('editing');
275
+ const tag = data.get('tag');
276
+ const ends = data.get('ends');
277
+ const src = data.get('src');
278
+ const starts = data.get('starts');
279
+ const title = data.get('title');
280
+ const width = data.get('width');
281
+ const height = data.get('height');
282
+ const url = data.get('url');
283
+ const style = {};
284
+
285
+ if (width) {
286
+ style.width = `${width}px`;
287
+ }
288
+
289
+ if (height) {
290
+ style.height = `${height}px`;
291
+ }
292
+
293
+ const divProps = {
294
+ 'data-editing': editing,
295
+ 'data-ends': ends,
296
+ 'data-starts': starts,
297
+ 'data-title': title,
298
+ 'data-url': url,
299
+ };
300
+ const props = {
301
+ ...style,
302
+ src,
303
+ };
304
+
305
+ if (tag === 'audio') {
306
+ return (
307
+ <audio controls="controls" controlsList="nodownload">
308
+ <source type="audio/mp3" src={src} />
309
+ </audio>
310
+ );
311
+ }
312
+
313
+ return (
314
+ <iframe
315
+ data-type={type}
316
+ src={src}
317
+ {...divProps}
318
+ frameBorder="0"
319
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
320
+ allowFullScreen
321
+ {...props}
322
+ />
323
+ );
324
+ },
325
+ };