@pie-lib/editable-html-tip-tap 1.0.1 → 1.0.3

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 (129) hide show
  1. package/lib/components/CharacterPicker.js +221 -0
  2. package/lib/components/EditableHtml.js +323 -0
  3. package/lib/components/MenuBar.js +693 -0
  4. package/lib/components/TiptapContainer.js +90 -0
  5. package/lib/components/buttons/done-button.js +53 -0
  6. package/lib/components/characters/characterUtils.js +112 -0
  7. package/lib/components/characters/custom-popper.js +73 -0
  8. package/lib/components/common/done-button.js +53 -0
  9. package/lib/components/icons/CssIcon.js +37 -0
  10. package/lib/components/icons/RespArea.js +95 -0
  11. package/lib/components/icons/TableIcons.js +69 -0
  12. package/lib/components/icons/TextAlign.js +194 -0
  13. package/lib/components/icons/index.js +194 -0
  14. package/lib/components/image/ImageToolbar.js +16 -0
  15. package/lib/components/image/InsertImageHandler.js +16 -0
  16. package/lib/components/media/MediaDialog.js +16 -0
  17. package/lib/components/media/MediaToolbar.js +16 -0
  18. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js +94 -0
  19. package/lib/components/respArea/DragInTheBlank/choice.js +289 -0
  20. package/lib/components/respArea/DragInTheBlank.js +94 -0
  21. package/lib/components/respArea/ExplicitConstructedResponse.js +120 -0
  22. package/lib/components/respArea/InlineDropdown.js +126 -0
  23. package/lib/components/respArea/ToolbarIcon.js +105 -0
  24. package/lib/components/respArea/choice.js +2 -0
  25. package/lib/extensions/component.js +5 -5
  26. package/lib/extensions/custom-toolbar-wrapper.js +2 -4
  27. package/lib/extensions/extended-table.js +30 -0
  28. package/lib/extensions/index.js +52 -0
  29. package/lib/extensions/media.js +5 -5
  30. package/lib/extensions/responseArea.js +7 -7
  31. package/lib/index.js +16 -1454
  32. package/lib/plugins/index.js +10 -82
  33. package/lib/styles/editorContainerStyles.js +200 -0
  34. package/lib/utils/size.js +34 -0
  35. package/package.json +1 -1
  36. package/src/components/CharacterPicker.jsx +185 -0
  37. package/src/components/EditableHtml.jsx +306 -0
  38. package/src/components/MenuBar.jsx +630 -0
  39. package/src/components/TiptapContainer.jsx +96 -0
  40. package/src/components/characters/characterUtils.js +127 -0
  41. package/src/components/image/ImageToolbar.jsx +1 -0
  42. package/src/components/image/InsertImageHandler.js +1 -0
  43. package/src/components/media/MediaDialog.js +1 -0
  44. package/src/components/media/MediaToolbar.jsx +1 -0
  45. package/src/{plugins/respArea/drag-in-the-blank → components/respArea/DragInTheBlank}/choice.jsx +1 -1
  46. package/src/{plugins/respArea/inline-dropdown/index.jsx → components/respArea/InlineDropdown.jsx} +1 -1
  47. package/src/components/respArea/ToolbarIcon.jsx +68 -0
  48. package/src/extensions/component.jsx +2 -2
  49. package/src/extensions/custom-toolbar-wrapper.jsx +6 -7
  50. package/src/extensions/extended-table.js +27 -0
  51. package/src/extensions/index.js +76 -0
  52. package/src/extensions/media.js +10 -4
  53. package/src/extensions/responseArea.js +7 -7
  54. package/src/index.jsx +3 -1409
  55. package/src/styles/editorContainerStyles.js +203 -0
  56. package/src/utils/size.js +32 -0
  57. package/src/__tests__/editor.test.jsx +0 -363
  58. package/src/__tests__/serialization.test.js +0 -291
  59. package/src/block-tags.js +0 -17
  60. package/src/editor.jsx +0 -1197
  61. package/src/extensions/characters.js +0 -46
  62. package/src/old-index.jsx +0 -162
  63. package/src/parse-html.js +0 -8
  64. package/src/plugins/README.md +0 -27
  65. package/src/plugins/characters/index.jsx +0 -284
  66. package/src/plugins/characters/utils.js +0 -447
  67. package/src/plugins/css/index.jsx +0 -340
  68. package/src/plugins/customPlugin/index.jsx +0 -85
  69. package/src/plugins/html/icons/index.jsx +0 -19
  70. package/src/plugins/html/index.jsx +0 -72
  71. package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +0 -51
  72. package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +0 -27
  73. package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +0 -44
  74. package/src/plugins/image/__tests__/component.test.jsx +0 -41
  75. package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +0 -42
  76. package/src/plugins/image/__tests__/image-toolbar.test.jsx +0 -11
  77. package/src/plugins/image/__tests__/index.test.js +0 -95
  78. package/src/plugins/image/__tests__/insert-image-handler.test.js +0 -113
  79. package/src/plugins/image/__tests__/mock-change.js +0 -15
  80. package/src/plugins/image/alt-dialog.jsx +0 -82
  81. package/src/plugins/image/component.jsx +0 -343
  82. package/src/plugins/image/image-toolbar.jsx +0 -100
  83. package/src/plugins/image/index.jsx +0 -227
  84. package/src/plugins/image/insert-image-handler.js +0 -79
  85. package/src/plugins/index.jsx +0 -377
  86. package/src/plugins/list/__tests__/index.test.js +0 -54
  87. package/src/plugins/list/index.jsx +0 -305
  88. package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +0 -48
  89. package/src/plugins/math/__tests__/index.test.jsx +0 -245
  90. package/src/plugins/math/index.jsx +0 -379
  91. package/src/plugins/media/__tests__/index.test.js +0 -75
  92. package/src/plugins/media/index.jsx +0 -325
  93. package/src/plugins/media/media-dialog.js +0 -624
  94. package/src/plugins/media/media-toolbar.jsx +0 -56
  95. package/src/plugins/media/media-wrapper.jsx +0 -43
  96. package/src/plugins/rendering/index.js +0 -31
  97. package/src/plugins/respArea/index.jsx +0 -299
  98. package/src/plugins/respArea/math-templated/index.jsx +0 -104
  99. package/src/plugins/respArea/utils.jsx +0 -90
  100. package/src/plugins/table/CustomTablePlugin.js +0 -113
  101. package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +0 -44
  102. package/src/plugins/table/__tests__/index.test.jsx +0 -401
  103. package/src/plugins/table/__tests__/table-toolbar.test.jsx +0 -42
  104. package/src/plugins/table/index.jsx +0 -427
  105. package/src/plugins/table/table-toolbar.jsx +0 -136
  106. package/src/plugins/textAlign/index.jsx +0 -23
  107. package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +0 -923
  108. package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +0 -20
  109. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +0 -36
  110. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +0 -46
  111. package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +0 -94
  112. package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +0 -37
  113. package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +0 -51
  114. package/src/plugins/toolbar/__tests__/toolbar.test.jsx +0 -106
  115. package/src/plugins/toolbar/default-toolbar.jsx +0 -206
  116. package/src/plugins/toolbar/editor-and-toolbar.jsx +0 -257
  117. package/src/plugins/toolbar/index.jsx +0 -23
  118. package/src/plugins/toolbar/toolbar-buttons.jsx +0 -138
  119. package/src/plugins/toolbar/toolbar.jsx +0 -338
  120. package/src/plugins/utils.js +0 -31
  121. package/src/serialization.jsx +0 -621
  122. /package/src/{plugins → components}/characters/custom-popper.js +0 -0
  123. /package/src/{plugins/toolbar → components/common}/done-button.jsx +0 -0
  124. /package/src/{plugins/css/icons/index.jsx → components/icons/CssIcon.jsx} +0 -0
  125. /package/src/{plugins/respArea/icons/index.jsx → components/icons/RespArea.jsx} +0 -0
  126. /package/src/{plugins/table/icons/index.jsx → components/icons/TableIcons.jsx} +0 -0
  127. /package/src/{plugins/textAlign/icons/index.jsx → components/icons/TextAlign.jsx} +0 -0
  128. /package/src/{plugins/respArea/drag-in-the-blank/index.jsx → components/respArea/DragInTheBlank/DragInTheBlank.jsx} +0 -0
  129. /package/src/{plugins/respArea/explicit-constructed-response/index.jsx → components/respArea/ExplicitConstructedResponse.jsx} +0 -0
@@ -1,340 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom';
3
- import List from '@material-ui/core/List';
4
- import { Leaf, Mark } from 'slate';
5
- import Immutable from 'immutable';
6
- import ListItem from '@material-ui/core/ListItem';
7
- import isEmpty from 'lodash/isEmpty';
8
- import debug from 'debug';
9
- import CssIcon from './icons';
10
-
11
- const log = debug('@pie-lib:editable-html:plugins:characters');
12
-
13
- export const removeDialogs = () => {
14
- const prevDialogs = document.querySelectorAll('.insert-css-dialog');
15
-
16
- log('[characters:removeDialogs]');
17
- prevDialogs.forEach((s) => s.remove());
18
- };
19
-
20
- const insertDialog = ({ editorDOM, value, callback, opts, textNode, parentNode }) => {
21
- const newEl = document.createElement('div');
22
-
23
- log('[characters:insertDialog]');
24
-
25
- removeDialogs();
26
-
27
- newEl.className = 'insert-css-dialog';
28
-
29
- let popoverEl;
30
-
31
- const closePopOver = () => {
32
- if (popoverEl) {
33
- popoverEl.remove();
34
- }
35
- };
36
-
37
- let firstCallMade = false;
38
-
39
- const listener = (e) => {
40
- // this will be triggered right after setting it because
41
- // this toolbar is added on the mousedown event
42
- // so right after mouseup, the click will be triggered
43
- if (firstCallMade) {
44
- const focusIsInModals = newEl.contains(e.target) || (popoverEl && popoverEl.contains(e.target));
45
- const focusIsInEditor = editorDOM.contains(e.target);
46
-
47
- if (!(focusIsInModals || focusIsInEditor)) {
48
- handleClose();
49
- }
50
- } else {
51
- firstCallMade = true;
52
- }
53
- };
54
-
55
- const handleClose = () => {
56
- callback(undefined, true);
57
- newEl.remove();
58
- closePopOver();
59
- document.body.removeEventListener('click', listener);
60
- };
61
-
62
- const handleChange = (name) => {
63
- callback(name, true);
64
- newEl.remove();
65
- closePopOver();
66
- document.body.removeEventListener('click', listener);
67
- };
68
-
69
- const selectedText = textNode.text.slice(value.selection.anchorOffset, value.selection.focusOffset);
70
- const parentNodeClass = parentNode?.data?.get('attributes')?.class;
71
- const createHTML = (name) => {
72
- let html = `<span class="${name}">${selectedText}</span>`;
73
-
74
- if (parentNode) {
75
- let tag;
76
-
77
- if (parentNode?.object === 'inline') {
78
- tag = 'span';
79
- }
80
-
81
- if (parentNode?.object === 'block') {
82
- tag = 'div';
83
- }
84
-
85
- html = `<${tag} class="${parentNodeClass}">${parentNode.text.slice(
86
- 0,
87
- value.selection.anchorOffset,
88
- )}${html}${parentNode.text.slice(value.selection.focusOffset)}</${tag}>`;
89
- }
90
-
91
- return html;
92
- };
93
-
94
- const el = (
95
- <div
96
- style={{ background: 'white', height: 500, padding: 20, overflow: 'hidden', display: 'flex', flexFlow: 'column' }}
97
- >
98
- <h2>Please choose a css class</h2>
99
- {parentNodeClass && <div>The current parent has this class {parentNodeClass}</div>}
100
- <List component="nav" style={{ overflow: 'scroll' }}>
101
- {opts.names.map((name, i) => (
102
- <ListItem key={`rule-${i}`} button onClick={() => handleChange(name)}>
103
- <div style={{ marginRight: 20 }}>{name}</div>
104
- <div
105
- dangerouslySetInnerHTML={{
106
- __html: createHTML(name),
107
- }}
108
- />
109
- </ListItem>
110
- ))}
111
- </List>
112
- </div>
113
- );
114
-
115
- ReactDOM.render(el, newEl, () => {
116
- const cursorItem = document.querySelector(`[data-key="${value.anchorKey}"]`);
117
-
118
- if (cursorItem) {
119
- const bodyRect = editorDOM.parentElement.parentElement.parentElement.getBoundingClientRect();
120
- const boundRect = cursorItem.getBoundingClientRect();
121
-
122
- editorDOM.parentElement.parentElement.parentElement.appendChild(newEl);
123
-
124
- newEl.style.maxWidth = '500px';
125
- newEl.style.position = 'absolute';
126
- newEl.style.top = 0;
127
- newEl.style.zIndex = 99999;
128
-
129
- const leftValue = `${boundRect.left + Math.abs(bodyRect.left) + cursorItem.offsetWidth + 10}px`;
130
-
131
- const rightValue = `${boundRect.x}px`;
132
-
133
- newEl.style.left = leftValue;
134
-
135
- const leftAlignedWidth = newEl.offsetWidth;
136
-
137
- newEl.style.left = 'unset';
138
- newEl.style.right = rightValue;
139
-
140
- const rightAlignedWidth = newEl.offsetWidth;
141
-
142
- newEl.style.left = 'unset';
143
- newEl.style.right = 'unset';
144
-
145
- if (leftAlignedWidth >= rightAlignedWidth) {
146
- newEl.style.left = leftValue;
147
- } else {
148
- newEl.style.right = rightValue;
149
- }
150
-
151
- document.body.addEventListener('click', listener);
152
- }
153
- });
154
- };
155
-
156
- const findParentNodeInfo = (value, textNode) => {
157
- const closestInline = value.document.getClosestInline(value.selection.endKey);
158
- const closestBlock = value.document.getClosestBlock(value.selection.endKey);
159
- let nodeToUse = null;
160
-
161
- if (closestInline?.nodes?.find((n) => n.key === textNode.key)) {
162
- nodeToUse = closestInline;
163
- }
164
-
165
- if (closestBlock?.nodes?.find((n) => n.key === textNode.key)) {
166
- nodeToUse = closestBlock;
167
- }
168
-
169
- return nodeToUse;
170
- };
171
-
172
- /**
173
- * Find the node that has a class attribute and return it.
174
- * Keeping this in case the implementation of classes needs to be changed
175
- * @param value
176
- * @param opts
177
- * @returns {*}
178
- */
179
- const getNodeWithClass = (value, opts) => {
180
- const blocksAtRange = value.document.getBlocksAtRangeAsArray(value.selection);
181
- const inlinesAtRange = value.document.getInlinesAtRangeAsArray(value.selection);
182
- const blockData = blocksAtRange[0]?.data.toJSON() || {};
183
- const inlineData = inlinesAtRange[0]?.data.toJSON() || {};
184
-
185
- if (!blockData.attributes?.class && !inlineData.attributes?.class) {
186
- return null;
187
- }
188
-
189
- const { class: blockClass } = blockData.attributes || {};
190
- const { class: inlineClass } = inlineData.attributes || {};
191
- const inlineHasClass = opts.names.find((name) => inlineClass.includes(name));
192
-
193
- if (inlineHasClass) {
194
- return inlinesAtRange[0];
195
- }
196
-
197
- const blockHasClass = opts.names.find((name) => blockClass.includes(name));
198
-
199
- if (blockHasClass) {
200
- return blocksAtRange[0];
201
- }
202
-
203
- return null;
204
- };
205
-
206
- /**
207
- * Plugin in order to be able to add a css clas that is provided through the model
208
- * on a text element. Works like a mark (bold, italic etc.).
209
- * @param opts
210
- * @constructor
211
- */
212
- export default function CSSPlugin(opts) {
213
- const plugin = {
214
- name: 'extraCSSRules',
215
- toolbar: {
216
- isMark: true,
217
- icon: <CssIcon />,
218
- ariaLabel: 'CSS editor',
219
- type: 'css',
220
- onToggle: (change) => {
221
- const type = 'css';
222
- const hasMark = change.value.activeMarks.find((entry) => {
223
- return entry.type === type;
224
- });
225
-
226
- if (hasMark) {
227
- change.removeMark(hasMark);
228
- } else {
229
- const newMark = Mark.create(type);
230
-
231
- change.addMark(newMark);
232
- }
233
-
234
- return change;
235
- },
236
- onClick: (value, onChange, getFocusedValue) => {
237
- const type = 'css';
238
- const hasMark = value.activeMarks.find((entry) => {
239
- return entry.type === type;
240
- });
241
-
242
- let change = value.change();
243
-
244
- if (hasMark) {
245
- change.removeMark(hasMark);
246
- onChange(change);
247
- return;
248
- }
249
-
250
- // keeping this if implementation needs to be changed to regular blocks instead of marks
251
- // let nodeWithClass = getNodeWithClass(value, opts);
252
- //
253
- // if (nodeWithClass) {
254
- // const nodeAttributes = nodeWithClass.data.get('attributes');
255
- //
256
- // opts.names.forEach((name) => {
257
- // if (nodeAttributes.class.includes(name)) {
258
- // nodeAttributes.class = nodeAttributes.class.replace(name, '');
259
- // }
260
- // });
261
- //
262
- // // keeping only one space between classes
263
- // nodeAttributes.class = nodeAttributes.class.replace(/ +/g, ' ');
264
- //
265
- // nodeWithClass.data.set('attributes', nodeAttributes);
266
- //
267
- // let change = value.change();
268
- // change.replaceNodeByKey(nodeWithClass.key, nodeWithClass);
269
- //
270
- // onChange(change);
271
- // return;
272
- // }
273
-
274
- const editorDOM = document.querySelector(`[data-key="${value.document.key}"]`);
275
- let valueToUse = value;
276
-
277
- const callback = (className, focus) => {
278
- if (getFocusedValue) {
279
- valueToUse = getFocusedValue() || valueToUse;
280
- }
281
-
282
- if (className) {
283
- let change = valueToUse.change();
284
-
285
- const newMark = Mark.create({
286
- object: 'mark',
287
- type: 'css',
288
- data: {
289
- attributes: {
290
- class: className,
291
- },
292
- },
293
- });
294
-
295
- change.addMark(newMark);
296
- // keeping this if implementation needs to be changed to regular blocks instead of marks
297
- // change = change.wrapInline({ type: 'span', data: { attributes: { class: className } } });
298
- //
299
- // // change = change.splitBlockAtRange(adaptedRange);
300
- // //
301
- // // const newBlock = change.value.document.getFurthestBlock(change.value.selection.endKey);
302
- // //
303
- // // change = change.setNodeByKey(newBlock.key, { data: { attributes: { class: className } } });
304
- //
305
- // valueToUse = change.value;
306
- // log('[characters:insert]: ', value);
307
- onChange(change);
308
- }
309
-
310
- log('[characters:click]');
311
-
312
- if (focus) {
313
- setTimeout(() => {
314
- if (editorDOM) {
315
- editorDOM.focus();
316
- }
317
- }, 0);
318
- }
319
- };
320
- const textNode = value.document.getTextsAtRangeAsArray(value.selection)[0];
321
-
322
- if (textNode) {
323
- const parentNode = findParentNodeInfo(value, textNode, opts);
324
-
325
- insertDialog({ editorDOM, value: valueToUse, callback, opts, textNode, parentNode });
326
- }
327
- },
328
- },
329
- renderMark(props) {
330
- if (props.mark.type === 'css') {
331
- const { data } = props.mark || {};
332
- const jsonData = data?.toJSON() || {};
333
-
334
- return <span {...jsonData.attributes}>{props.children}</span>;
335
- }
336
- },
337
- };
338
-
339
- return plugin;
340
- }
@@ -1,85 +0,0 @@
1
- import React from 'react';
2
- import { htmlToValue } from '../../serialization';
3
-
4
- // We're possibly going to have to support content types, so starting it as an enum
5
- export const CONTENT_TYPE = {
6
- FRAGMENT: 'FRAGMENT',
7
- };
8
-
9
- // We're possibly going to have to support multiple icon types, so starting it as an enum
10
- export const ICON_TYPE = {
11
- SVG: 'SVG',
12
- };
13
-
14
- const getIcon = (customPluginProps) => {
15
- const svg = customPluginProps.icon;
16
-
17
- switch (customPluginProps.iconType) {
18
- case ICON_TYPE.SVG:
19
- return <span style={{ width: 28, height: 28 }} dangerouslySetInnerHTML={{ __html: svg }} />;
20
- default:
21
- return <span>{customPluginProps.iconAlt}</span>;
22
- }
23
- };
24
-
25
- export default function CustomPlugin(type, customPluginProps) {
26
- const toolbar = {
27
- icon: getIcon(customPluginProps),
28
- onClick: (value, onChange, getFocusedValue) => {
29
- const editorDOM = document.querySelector(`[data-key="${value.document.key}"]`);
30
- let valueToUse = value;
31
- const callback = ({ customContent, contentType }, focus) => {
32
- valueToUse = getFocusedValue();
33
-
34
- switch (contentType) {
35
- case CONTENT_TYPE.FRAGMENT:
36
- default: {
37
- const contentValue = htmlToValue(customContent);
38
- const change = valueToUse.change().insertFragment(contentValue.document);
39
-
40
- valueToUse = change.value;
41
- onChange(change);
42
-
43
- break;
44
- }
45
- }
46
-
47
- if (focus) {
48
- if (editorDOM) {
49
- editorDOM.focus();
50
- }
51
- }
52
- };
53
-
54
- // NOTE: the emitted event (custom event named by client) will be suffixed with "PIE-"
55
- window.dispatchEvent(
56
- new CustomEvent(`PIE-${customPluginProps.event}`, {
57
- detail: {
58
- ...customPluginProps,
59
- callback,
60
- },
61
- }),
62
- );
63
- },
64
- supports: (node) => node.object === 'inline' && node.type === type,
65
- };
66
-
67
- return {
68
- name: type,
69
- toolbar,
70
- renderNode(props) {
71
- if (props.node.type === type) {
72
- const { node } = props;
73
- const { data } = node;
74
- const jsonData = data.toJSON();
75
- const { customContent, contentType } = jsonData;
76
-
77
- switch (contentType) {
78
- case CONTENT_TYPE.FRAGMENT:
79
- default:
80
- return customContent;
81
- }
82
- }
83
- },
84
- };
85
- }
@@ -1,19 +0,0 @@
1
- import React from 'react';
2
- import { withStyles } from '@material-ui/core/styles';
3
-
4
- const styles = (theme) => ({
5
- icon: {
6
- fontFamily: 'Cerebri Sans, Arial, sans-serif',
7
- fontSize: theme.typography.fontSize,
8
- fontWeight: 'bold',
9
- lineHeight: '14px',
10
- position: 'relative',
11
- whiteSpace: 'nowrap',
12
- },
13
- });
14
-
15
- const HtmlModeIcon = ({ classes, isHtmlMode }) => (
16
- <div className={classes.icon}>{isHtmlMode ? 'Exit <HTML> mode' : '<HTML>'}</div>
17
- );
18
-
19
- export default withStyles(styles)(HtmlModeIcon);
@@ -1,72 +0,0 @@
1
- import React from 'react';
2
- import HtmlModeIcon from './icons';
3
- import { htmlToValue, valueToHtml } from './../../serialization';
4
-
5
- const toggleToRichText = (value, onChange, dismiss) => {
6
- const plainText = value.document.text;
7
- const slateValue = dismiss ? value : htmlToValue(plainText);
8
-
9
- const change = value
10
- .change()
11
- .selectAll()
12
- .delete()
13
- .insertFragment(slateValue.document);
14
- onChange(change);
15
- };
16
-
17
- export default function HtmlPlugin(opts) {
18
- const { isHtmlMode, isEditedInHtmlMode, toggleHtmlMode, handleAlertDialog, currentValue } = opts || {};
19
-
20
- const handleHtmlModeOn = (value, onChange) => {
21
- const dialogProps = {
22
- title: 'Warning',
23
- text: 'Returning to rich text mode without saving will cause edits to be lost.',
24
- onConfirmText: 'Dismiss changes',
25
- onCloseText: 'Continue Editing',
26
- onConfirm: () => {
27
- handleAlertDialog(false);
28
- toggleToRichText(currentValue, onChange, true);
29
- toggleHtmlMode();
30
- },
31
- onClose: () => {
32
- handleAlertDialog(false);
33
- },
34
- };
35
-
36
- handleAlertDialog(true, dialogProps);
37
- };
38
-
39
- const handleHtmlModeOff = (value, onChange) => {
40
- const change = value
41
- .change()
42
- .selectAll()
43
- .delete()
44
- .insertText(valueToHtml(value));
45
- onChange(change);
46
- };
47
-
48
- return {
49
- name: 'html',
50
- toolbar: {
51
- icon: <HtmlModeIcon isHtmlMode={isHtmlMode} />,
52
- ariaLabel: 'Html editor',
53
- buttonStyles: {
54
- margin: '0 20px 0 auto',
55
- },
56
- type: 'html',
57
- onClick: (value, onChange) => {
58
- if (isHtmlMode) {
59
- if (isEditedInHtmlMode) {
60
- handleHtmlModeOn(value, onChange);
61
- } else {
62
- toggleToRichText(value, onChange);
63
- toggleHtmlMode();
64
- }
65
- } else {
66
- handleHtmlModeOff(value, onChange);
67
- toggleHtmlMode();
68
- }
69
- },
70
- },
71
- };
72
- }
@@ -1,51 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`renders correctly 1`] = `
4
- Array [
5
- <span>
6
-  
7
- </span>,
8
- <div
9
- className=""
10
- style={
11
- Object {
12
- "justifyContent": "flex-start",
13
- }
14
- }
15
- >
16
- <div
17
- className="MuiLinearProgress-root-1 MuiLinearProgress-colorPrimary-2 MuiLinearProgress-indeterminate-5"
18
- mode="determinate"
19
- role="progressbar"
20
- >
21
- <div
22
- className="MuiLinearProgress-bar-11 MuiLinearProgress-barColorPrimary-12 MuiLinearProgress-bar1Indeterminate-14"
23
- style={Object {}}
24
- />
25
- <div
26
- className="MuiLinearProgress-bar-11 MuiLinearProgress-barColorPrimary-12 MuiLinearProgress-bar2Indeterminate-17"
27
- style={Object {}}
28
- />
29
- </div>
30
- <div>
31
- <img
32
- className=""
33
- onLoad={[Function]}
34
- style={
35
- Object {
36
- "height": "50px",
37
- "objectFit": "contain",
38
- "width": "50px",
39
- }
40
- }
41
- />
42
- <div
43
- className="resize"
44
- />
45
- </div>
46
- </div>,
47
- <span>
48
-  
49
- </span>,
50
- ]
51
- `;
@@ -1,27 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`ImageToolbar onChange renders 1`] = `
4
- <div>
5
- <AlignmentButton
6
- active={false}
7
- alignment="left"
8
- onClick={[Function]}
9
- />
10
- <AlignmentButton
11
- active={false}
12
- alignment="center"
13
- onClick={[Function]}
14
- />
15
- <AlignmentButton
16
- active={false}
17
- alignment="right"
18
- onClick={[Function]}
19
- />
20
- <span
21
- className="undefined"
22
- onMouseDown={[Function]}
23
- >
24
- Alt text
25
- </span>
26
- </div>
27
- `;
@@ -1,44 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`renders correctly 1`] = `
4
- <div
5
- className="ImageToolbar-holder-1 holder"
6
- >
7
- <button
8
- aria-label="left"
9
- aria-pressed={false}
10
- className="RawMarkButton-button-4"
11
- onKeyDown={[Function]}
12
- onMouseDown={[Function]}
13
- tabIndex={0}
14
- >
15
- left
16
- </button>
17
- <button
18
- aria-label="center"
19
- aria-pressed={false}
20
- className="RawMarkButton-button-4"
21
- onKeyDown={[Function]}
22
- onMouseDown={[Function]}
23
- tabIndex={0}
24
- >
25
- center
26
- </button>
27
- <button
28
- aria-label="right"
29
- aria-pressed={false}
30
- className="RawMarkButton-button-4"
31
- onKeyDown={[Function]}
32
- onMouseDown={[Function]}
33
- tabIndex={0}
34
- >
35
- right
36
- </button>
37
- <span
38
- className="ImageToolbar-disabled-2 ImageToolbar-altButton-3"
39
- onMouseDown={[Function]}
40
- >
41
- Alt text
42
- </span>
43
- </div>
44
- `;
@@ -1,41 +0,0 @@
1
- import { Data, Block } from 'slate';
2
- import { Component } from '../component';
3
- import React from 'react';
4
- import renderer from 'react-test-renderer';
5
-
6
- it('renders correctly', () => {
7
- const node = Block.fromJSON({
8
- type: 'image',
9
- data: Data.create({
10
- width: 50,
11
- height: 50,
12
- }),
13
- });
14
-
15
- const editor = {
16
- value: {},
17
- change: jest.fn(),
18
- };
19
-
20
- const onDelete = jest.fn();
21
-
22
- const classes = {
23
- active: 'active',
24
- loading: 'loading',
25
- pendingDelete: 'pendingDelete',
26
- };
27
-
28
- const tree = renderer
29
- .create(<Component node={node} editor={editor} classes={classes} onDelete={onDelete} />, {
30
- createNodeMock: (el) => {
31
- if (el.type === 'img') {
32
- return {
33
- naturalWidth: 100,
34
- naturalHeight: 100,
35
- };
36
- }
37
- },
38
- })
39
- .toJSON();
40
- expect(tree).toMatchSnapshot();
41
- });