@pie-lib/editable-html-tip-tap 1.0.2 → 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 -1481
  32. package/lib/plugins/index.js +8 -80
  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 -1440
  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,43 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import classNames from 'classnames';
4
- import { withStyles } from '@material-ui/core/styles';
5
-
6
- const useStyles = withStyles(() => ({
7
- root: {
8
- position: 'relative',
9
- },
10
- editor: {
11
- display: 'inline-block',
12
- overflow: 'hidden',
13
- },
14
- }));
15
-
16
- class MediaWrapper extends React.Component {
17
- static propTypes = {
18
- classes: PropTypes.object,
19
- children: PropTypes.array,
20
- editor: PropTypes.bool,
21
- width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
22
- };
23
-
24
- render() {
25
- const { editor, classes, children, width, ...rest } = this.props;
26
-
27
- return (
28
- <span
29
- className={classNames(classes.root, {
30
- [classes.editor]: editor,
31
- })}
32
- {...rest}
33
- style={{
34
- width: width || 300,
35
- }}
36
- >
37
- {children}
38
- </span>
39
- );
40
- }
41
- }
42
-
43
- export default useStyles(MediaWrapper);
@@ -1,31 +0,0 @@
1
- import React from 'react';
2
-
3
- /**
4
- * Plugin to render the normal divs and spans with attributes (if they are provided)
5
- */
6
- export default () => {
7
- return {
8
- name: 'renderingPlugin',
9
- renderNode: (props) => {
10
- const { attributes, children, node } = props;
11
-
12
- if (node.object !== 'block' && node.object !== 'inline') {
13
- return;
14
- }
15
-
16
- const Tag = node.object === 'block' ? 'div' : 'span';
17
- const style = { position: 'relative' };
18
- const extraAttributes = node.data.get('attributes');
19
-
20
- return React.createElement(
21
- Tag,
22
- {
23
- ...attributes,
24
- ...extraAttributes,
25
- style: style,
26
- },
27
- children,
28
- );
29
- },
30
- };
31
- };
@@ -1,299 +0,0 @@
1
- import React from 'react';
2
- import debug from 'debug';
3
- import isUndefined from 'lodash/isUndefined';
4
-
5
- import InlineDropdown from './inline-dropdown';
6
- import DragInTheBlank from './drag-in-the-blank';
7
- import ExplicitConstructedResponse from './explicit-constructed-response';
8
- import MathTemplated from './math-templated';
9
- import { getDefaultElement } from './utils';
10
- import { ToolbarIcon } from './icons';
11
-
12
- const log = debug('@pie-lib:editable-html:plugins:respArea');
13
-
14
- const lastIndexMap = {};
15
- const elTypesMap = {
16
- 'inline-dropdown': 'inline_dropdown',
17
- 'explicit-constructed-response': 'explicit_constructed_response',
18
- 'math-templated': 'math_templated',
19
- 'drag-in-the-blank': 'drag_in_the_blank',
20
- };
21
- const elTypesArray = Object.values(elTypesMap);
22
-
23
- export default function ResponseAreaPlugin(opts) {
24
- const isOfCurrentType = (d) => d.type === opts.type || d.type === elTypesMap[opts.type];
25
-
26
- const toolbar = {
27
- icon: <ToolbarIcon />,
28
- buttonStyles: {
29
- margin: '0 20px 0 auto',
30
- },
31
- onClick: (value, onChange) => {
32
- log('[toolbar] onClick');
33
- const change = value.change();
34
- const currentRespAreaList = change.value.document.filterDescendants(isOfCurrentType);
35
-
36
- if (currentRespAreaList.size >= opts.maxResponseAreas) {
37
- return;
38
- }
39
-
40
- const type = opts.type.replace(/-/g, '_');
41
- const prevIndex = lastIndexMap[type];
42
- const newIndex = prevIndex === 0 ? prevIndex : prevIndex + 1;
43
- const newInline = getDefaultElement(opts, newIndex);
44
-
45
- lastIndexMap[type] += 1;
46
-
47
- if (newInline) {
48
- if (change.value.selection.startKey || change.value.selection.endKey) {
49
- change.insertInline(newInline);
50
- } else {
51
- // If the markup is empty and there's no focus
52
- const lastText = value.document.getLastText();
53
-
54
- if (!lastText) {
55
- return;
56
- }
57
- const parentNode = value.document.getParent(lastText.key);
58
-
59
- if (parentNode) {
60
- const index = parentNode.nodes.indexOf(lastText.key);
61
-
62
- if (parentNode.isVoid) return;
63
-
64
- change.insertNodeByKey(parentNode.key, index + 1, newInline);
65
- }
66
- }
67
-
68
- if (newInline.type === 'drag_in_the_blank') {
69
- const nextText = change.value.document.getNextText(newInline.key);
70
-
71
- if (nextText) {
72
- change.moveFocusTo(nextText.key, 0).moveAnchorTo(nextText.key, 0);
73
- }
74
- }
75
- if (newInline.type === 'math_templated') {
76
- const nextText = change.value.document.getNextText(newInline.key);
77
-
78
- if (nextText) {
79
- change.moveFocusTo(nextText.key, 0).moveAnchorTo(nextText.key, 0);
80
- }
81
- }
82
-
83
- onChange(change);
84
- }
85
- },
86
- customToolbar: opts.respAreaToolbar,
87
- supports: (node) => node.object === 'inline' && elTypesArray.indexOf(node.type) >= 0,
88
- showDone: false,
89
- };
90
-
91
- return {
92
- name: 'response_area',
93
- toolbar,
94
- filterPlugins: (node, plugins) => {
95
- if (
96
- node.type === 'explicit_constructed_response' ||
97
- node.type === 'math_templated' ||
98
- node.type === 'drag_in_the_blank'
99
- ) {
100
- return [];
101
- }
102
-
103
- return plugins.filter((p) => p.name !== 'response_area');
104
- },
105
- deleteNode: (e, node, value, onChange) => {
106
- e.preventDefault();
107
-
108
- const change = value.change().removeNodeByKey(node.key);
109
-
110
- onChange(change);
111
- },
112
- renderNode(props) {
113
- const { attributes, node: n, isFocused } = props;
114
-
115
- if (n.type === 'explicit_constructed_response') {
116
- const data = n.data.toJSON();
117
- let error;
118
-
119
- if (opts.error) {
120
- error = opts.error();
121
- }
122
-
123
- return (
124
- <ExplicitConstructedResponse
125
- attributes={attributes}
126
- isFocused={isFocused}
127
- value={data.value}
128
- error={error && error[data.index] && error[data.index][0]}
129
- />
130
- );
131
- }
132
-
133
- if (n.type === 'math_templated') {
134
- const data = n.data.toJSON();
135
- let error;
136
-
137
- if (opts.error) {
138
- error = opts.error();
139
- }
140
-
141
- // add 1 to index to display R 1 instead of R 0
142
- const keyToDisplay = `R ${parseInt(data.index) + 1}`;
143
-
144
- return (
145
- <MathTemplated
146
- attributes={attributes}
147
- keyToDisplay={keyToDisplay}
148
- value={data.value || ''}
149
- error={error && error[data.index] && error[data.index][0]}
150
- />
151
- );
152
- }
153
-
154
- if (n.type === 'drag_in_the_blank') {
155
- const data = n.data.toJSON();
156
-
157
- return <DragInTheBlank attributes={attributes} data={data} n={n} nodeProps={props} opts={opts} />;
158
- }
159
-
160
- if (n.type === 'inline_dropdown') {
161
- const data = n.data.toJSON();
162
-
163
- return <InlineDropdown attributes={attributes} selectedItem={data.value} />;
164
- }
165
- },
166
- onChange(change, editor) {
167
- const type = opts.type.replace(/-/g, '_');
168
-
169
- if (isUndefined(lastIndexMap[type])) {
170
- lastIndexMap[type] = 0;
171
-
172
- change.value.document.forEachDescendant((d) => {
173
- if (d.type === type) {
174
- const newIndex = parseInt(d.data.get('index'), 10);
175
-
176
- if (newIndex > lastIndexMap[type]) {
177
- lastIndexMap[type] = newIndex;
178
- }
179
- }
180
- });
181
- }
182
-
183
- if (!editor.value) {
184
- return;
185
- }
186
-
187
- const currentRespAreaList = change.value.document.filterDescendants(isOfCurrentType);
188
- const oldRespAreaList = editor.value.document.filterDescendants(isOfCurrentType);
189
-
190
- toolbar.disabled = currentRespAreaList.size >= opts.maxResponseAreas;
191
-
192
- const arrayToFilter = oldRespAreaList.size > currentRespAreaList.size ? oldRespAreaList : currentRespAreaList;
193
- const arrayToUseForFilter = arrayToFilter === oldRespAreaList ? currentRespAreaList : oldRespAreaList;
194
-
195
- const elementsWithChangedStatus = arrayToFilter.filter(
196
- (d) => !arrayToUseForFilter.find((e) => e.data.get('index') === d.data.get('index')),
197
- );
198
-
199
- if (elementsWithChangedStatus.size && oldRespAreaList.size > currentRespAreaList.size) {
200
- opts.onHandleAreaChange(elementsWithChangedStatus);
201
- }
202
- },
203
- onDrop(event, change, editor) {
204
- const closestEl = event.target.closest('[data-key]');
205
- const inline = editor.value.document.findDescendant((d) => d.key === closestEl.dataset.key);
206
-
207
- if (inline.type === 'drag_in_the_blank') {
208
- return false;
209
- }
210
- },
211
- };
212
- }
213
-
214
- export const serialization = {
215
- deserialize(el) {
216
- const type = el.dataset && el.dataset.type;
217
-
218
- switch (type) {
219
- case 'inline_dropdown':
220
- return {
221
- object: 'inline',
222
- type: 'inline_dropdown',
223
- isVoid: true,
224
- data: {
225
- index: el.dataset.index,
226
- value: el.dataset.value,
227
- },
228
- };
229
- case 'explicit_constructed_response':
230
- return {
231
- object: 'inline',
232
- type: 'explicit_constructed_response',
233
- isVoid: true,
234
- data: {
235
- index: el.dataset.index,
236
- value: el.dataset.value,
237
- },
238
- };
239
- case 'math_templated':
240
- return {
241
- object: 'inline',
242
- type: 'math_templated',
243
- isVoid: true,
244
- data: {
245
- index: el.dataset.index,
246
- value: el.dataset.value,
247
- },
248
- };
249
- case 'drag_in_the_blank':
250
- return {
251
- object: 'inline',
252
- type: 'drag_in_the_blank',
253
- isVoid: true,
254
- data: {
255
- index: el.dataset.index,
256
- id: el.dataset.id,
257
- value: el.dataset.value,
258
- inTable: el.dataset.inTable,
259
- },
260
- };
261
- }
262
- },
263
- serialize(object) {
264
- if (object.object !== 'inline') {
265
- return;
266
- }
267
-
268
- switch (object.type) {
269
- case 'inline_dropdown': {
270
- const data = object.data.toJSON();
271
-
272
- return <span data-type="inline_dropdown" data-index={data.index} data-value={data.value} />;
273
- }
274
- case 'explicit_constructed_response': {
275
- const data = object.data.toJSON();
276
-
277
- return <span data-type="explicit_constructed_response" data-index={data.index} data-value={data.value} />;
278
- }
279
- case 'math_templated': {
280
- const data = object.data.toJSON();
281
-
282
- return <span data-type="math_templated" data-index={data.index} data-value={data.value} />;
283
- }
284
- case 'drag_in_the_blank': {
285
- const data = object.data.toJSON();
286
-
287
- return (
288
- <span
289
- data-type="drag_in_the_blank"
290
- data-index={data.index}
291
- data-id={data.id}
292
- data-value={data.value}
293
- data-in-table={data.inTable}
294
- />
295
- );
296
- }
297
- }
298
- },
299
- };
@@ -1,104 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { withStyles } from '@material-ui/core/styles';
4
- import { mq } from '@pie-lib/math-input';
5
-
6
- const MathTemplated = ({ attributes, value, classes, keyToDisplay }) => (
7
- <span {...attributes} className={classes.spanContainer}>
8
- <div className={classes.responseBox}>{keyToDisplay}</div>
9
- <div className={classes.mathBlock}>
10
- <mq.Static latex={value} />
11
- </div>
12
- </span>
13
- );
14
-
15
- MathTemplated.propTypes = {
16
- attributes: PropTypes.object,
17
- classes: PropTypes.object.isRequired,
18
- value: PropTypes.string,
19
- keyToDisplay: PropTypes.string,
20
- };
21
-
22
- const styles = (theme) => ({
23
- responseBox: {
24
- background: theme.palette.grey['A100'],
25
- color: theme.palette.grey['A700'],
26
- display: 'inline-flex',
27
- borderRight: '2px solid #C0C3CF',
28
- boxSizing: 'border-box',
29
- overflow: 'hidden',
30
- fontSize: '12px',
31
- minHeight: '36px',
32
- height: '100%',
33
- alignItems: 'center',
34
- fontFamily: 'Symbola, Times New Roman, serif',
35
- padding: '0 2px',
36
- },
37
- spanContainer: {
38
- display: 'inline-flex',
39
- border: '1px solid #C0C3CF',
40
- margin: '1px 5px',
41
- cursor: 'pointer',
42
- alignItems: 'center',
43
- justifyContent: 'center',
44
- minWidth: '50px',
45
- minHeight: '36px',
46
- height: 'fit-content',
47
- },
48
- mathBlock: {
49
- flex: 8,
50
- color: 'var(--pie-text, black)',
51
- padding: '4px !important',
52
- display: 'flex',
53
- alignItems: 'center',
54
- justifyContent: 'center',
55
- backgroundColor: 'var(--pie-background, rgba(255, 255, 255, 0))',
56
- '& > .mq-math-mode sup.mq-nthroot': {
57
- fontSize: '70% !important',
58
- verticalAlign: '1em !important',
59
- },
60
- '& > .mq-math-mode .mq-sqrt-stem': {
61
- borderTop: '0.07em solid',
62
- marginLeft: '-1.5px',
63
- marginTop: '-2px !important',
64
- paddingTop: '5px !important',
65
- },
66
- '& .mq-overarrow-inner': {
67
- paddingTop: '0 !important',
68
- border: 'none !important',
69
- },
70
- '& .mq-overarrow.mq-arrow-both': {
71
- marginTop: '0px',
72
- minWidth: '1.23em',
73
- '& *': {
74
- lineHeight: '1 !important',
75
- },
76
- '&:before': {
77
- top: '-0.4em',
78
- left: '-1px',
79
- },
80
- '&:after': {
81
- top: '0px !important',
82
- position: 'absolute !important',
83
- right: '-2px',
84
- },
85
- '&.mq-empty:after': {
86
- top: '-0.45em',
87
- },
88
- },
89
- '& .mq-overarrow.mq-arrow-right': {
90
- '&:before': {
91
- top: '-0.4em',
92
- right: '-1px',
93
- },
94
- },
95
- '& .mq-overarrow-inner-right': {
96
- display: 'none !important',
97
- },
98
- '& .mq-overarrow-inner-left': {
99
- display: 'none !important',
100
- },
101
- },
102
- });
103
-
104
- export default withStyles(styles)(MathTemplated);
@@ -1,90 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom';
3
- import { Inline } from 'slate';
4
- import Snackbar from '@material-ui/core/Snackbar';
5
-
6
- export const isNumber = (val) => !isNaN(parseFloat(val)) && isFinite(val);
7
-
8
- export const insertSnackBar = (message) => {
9
- const prevSnacks = document.querySelectorAll('.response-area-alert');
10
-
11
- prevSnacks.forEach((s) => s.remove());
12
-
13
- const newEl = document.createElement('div');
14
-
15
- newEl.className = 'response-area-alert';
16
-
17
- const el = (
18
- <Snackbar
19
- anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
20
- open={true}
21
- ContentProps={{
22
- 'aria-describedby': 'message-id',
23
- }}
24
- message={<span id="message-id">{message}</span>}
25
- />
26
- );
27
-
28
- ReactDOM.render(el, newEl);
29
-
30
- document.body.appendChild(newEl);
31
-
32
- setTimeout(() => {
33
- newEl.remove();
34
- }, 2000);
35
- };
36
-
37
- export const defaultECR = (index) =>
38
- Inline.create({
39
- type: 'explicit_constructed_response',
40
- isVoid: true,
41
- data: {
42
- index,
43
- },
44
- });
45
- export const defaultMT = (index) =>
46
- Inline.create({
47
- type: 'math_templated',
48
- isVoid: true,
49
- data: {
50
- index,
51
- },
52
- });
53
-
54
- export const defaultDIB = (opts, index) =>
55
- Inline.create({
56
- type: 'drag_in_the_blank',
57
- isVoid: true,
58
- data: {
59
- index,
60
- duplicates: opts.options.duplicates,
61
- value: null,
62
- },
63
- });
64
-
65
- export const defaultIDD = (index) =>
66
- Inline.create({
67
- object: 'inline',
68
- type: 'inline_dropdown',
69
- isVoid: true,
70
- data: {
71
- index,
72
- },
73
- });
74
-
75
- export const getDefaultElement = (opts, index) => {
76
- switch (opts.type) {
77
- case 'explicit-constructed-response':
78
- return defaultECR(index);
79
-
80
- case 'math-templated':
81
- return defaultMT(index);
82
-
83
- case 'drag-in-the-blank':
84
- return defaultDIB(opts, index);
85
-
86
- default:
87
- // inline-dropdown
88
- return defaultIDD(index);
89
- }
90
- };
@@ -1,113 +0,0 @@
1
- import EditTable from 'slate-edit-table';
2
- import { isSelectionInTable } from 'slate-edit-table/dist/utils';
3
- import { onEnter, onModEnter, onTab, onUpDown } from 'slate-edit-table/dist/handlers';
4
- import TableOptions from 'slate-edit-table/dist/options';
5
- import { clearCell } from 'slate-edit-table/dist/changes';
6
-
7
- function onBackspace(event, change, editor, opts) {
8
- const { value } = change;
9
- const { startBlock, endBlock, selection, document } = value;
10
-
11
- const startCell = document.getClosest(startBlock.key, opts.isCell);
12
- const endCell = document.getClosest(endBlock.key, opts.isCell);
13
-
14
- const startBlockIndex = startCell?.nodes?.findIndex((block) => block.key == startBlock.key);
15
-
16
- // If a cursor is collapsed at the start of the first block, do nothing
17
- if (startBlockIndex === 0 && selection.isAtStartOf(startBlock)) {
18
- if (startBlock.isVoid) {
19
- // Delete the block normally if it is a void block
20
- return undefined;
21
- }
22
-
23
- event.preventDefault();
24
- return change;
25
- }
26
-
27
- // If "normal" deletion, we continue
28
- if (startCell === endCell) {
29
- return undefined;
30
- }
31
-
32
- // If cursor is between multiple blocks,
33
- // we clear the content of the cells.
34
- event.preventDefault();
35
-
36
- const { blocks } = value;
37
-
38
- // Get all cells that contains the selection
39
- const cells = blocks
40
- .map((node) =>
41
- node.type === opts.typeCell ? node : document.getClosest(node.key, (a) => a.type === opts.typeCell),
42
- )
43
- .toSet();
44
-
45
- // If the cursor is at the very end of the first cell, ignore it.
46
- // If the cursor is at the very start of the last cell, ignore it.
47
- // This behavior is to compensate hanging selection behaviors:
48
- // https://github.com/ianstormtaylor/slate/pull/1605
49
- const ignoreFirstCell = value.selection.collapseToStart().isAtEndOf(cells.first());
50
- const ignoreLastCell = value.selection.collapseToEnd().isAtStartOf(cells.last());
51
-
52
- let cellsToClear = cells;
53
- if (ignoreFirstCell) {
54
- cellsToClear = cellsToClear.rest();
55
- }
56
- if (ignoreLastCell) {
57
- cellsToClear = cellsToClear.butLast();
58
- }
59
-
60
- // Clear all the selection
61
- cellsToClear.forEach((cell) => clearCell(opts, change, cell));
62
-
63
- // Update the selection properly, and avoid reset of selection
64
- const updatedStartCell = change.value.document.getDescendant(cellsToClear.first().key);
65
- return change.collapseToStartOf(updatedStartCell);
66
- }
67
-
68
- const KEY_ENTER = 'Enter';
69
- const KEY_TAB = 'Tab';
70
- const KEY_BACKSPACE = 'Backspace';
71
- const KEY_DOWN = 'ArrowDown';
72
- const KEY_UP = 'ArrowUp';
73
-
74
- /**
75
- * User is pressing a key in the editor
76
- */
77
- function onKeyDown(opts, event, change, editor) {
78
- // Only handle events in cells
79
- if (!isSelectionInTable(opts, change.value)) {
80
- return undefined;
81
- }
82
-
83
- // Build arguments list
84
- const args = [event, change, editor, opts];
85
-
86
- switch (event.key) {
87
- case KEY_ENTER:
88
- if (event.metaKey && opts.exitBlockType) {
89
- return onModEnter(...args);
90
- }
91
- return onEnter(...args);
92
-
93
- case KEY_TAB:
94
- return onTab(...args);
95
- case KEY_BACKSPACE:
96
- return onBackspace(...args);
97
- case KEY_DOWN:
98
- case KEY_UP:
99
- return onUpDown(...args);
100
- default:
101
- return undefined;
102
- }
103
- }
104
-
105
- export default (opts) => {
106
- const core = EditTable(opts);
107
-
108
- const tableOpts = new TableOptions(opts);
109
-
110
- core.onKeyDown = onKeyDown.bind(null, tableOpts);
111
-
112
- return core;
113
- };