@pie-lib/editable-html-tip-tap 1.0.2 → 1.0.4

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 (165) hide show
  1. package/lib/components/CharacterPicker.js +221 -0
  2. package/lib/components/CharacterPicker.js.map +1 -0
  3. package/lib/components/EditableHtml.js +323 -0
  4. package/lib/components/EditableHtml.js.map +1 -0
  5. package/lib/components/MenuBar.js +694 -0
  6. package/lib/components/MenuBar.js.map +1 -0
  7. package/lib/components/TiptapContainer.js +90 -0
  8. package/lib/components/TiptapContainer.js.map +1 -0
  9. package/lib/components/buttons/done-button.js +53 -0
  10. package/lib/components/characters/characterUtils.js +112 -0
  11. package/lib/components/characters/characterUtils.js.map +1 -0
  12. package/lib/components/characters/custom-popper.js +73 -0
  13. package/lib/components/characters/custom-popper.js.map +1 -0
  14. package/lib/components/common/done-button.js +53 -0
  15. package/lib/components/common/done-button.js.map +1 -0
  16. package/lib/components/common/toolbar-buttons.js +194 -0
  17. package/lib/components/icons/CssIcon.js +37 -0
  18. package/lib/components/icons/CssIcon.js.map +1 -0
  19. package/lib/components/icons/RespArea.js +95 -0
  20. package/lib/components/icons/RespArea.js.map +1 -0
  21. package/lib/components/icons/TableIcons.js +69 -0
  22. package/lib/components/icons/TableIcons.js.map +1 -0
  23. package/lib/components/icons/TextAlign.js +194 -0
  24. package/lib/components/icons/TextAlign.js.map +1 -0
  25. package/lib/components/icons/index.js +194 -0
  26. package/lib/components/image/AltDialog.js +129 -0
  27. package/lib/components/image/ImageToolbar.js +177 -0
  28. package/lib/components/image/ImageToolbar.js.map +1 -0
  29. package/lib/components/image/InsertImageHandler.js +115 -0
  30. package/lib/components/image/InsertImageHandler.js.map +1 -0
  31. package/lib/components/image/alt-dialog.js +2 -0
  32. package/lib/components/media/MediaDialog.js +709 -0
  33. package/lib/components/media/MediaDialog.js.map +1 -0
  34. package/lib/components/media/MediaToolbar.js +101 -0
  35. package/lib/components/media/MediaToolbar.js.map +1 -0
  36. package/lib/components/media/MediaWrapper.js +93 -0
  37. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js +94 -0
  38. package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js.map +1 -0
  39. package/lib/components/respArea/DragInTheBlank/choice.js +289 -0
  40. package/lib/components/respArea/DragInTheBlank/choice.js.map +1 -0
  41. package/lib/components/respArea/DragInTheBlank.js +94 -0
  42. package/lib/components/respArea/ExplicitConstructedResponse.js +120 -0
  43. package/lib/components/respArea/ExplicitConstructedResponse.js.map +1 -0
  44. package/lib/components/respArea/InlineDropdown.js +126 -0
  45. package/lib/components/respArea/InlineDropdown.js.map +1 -0
  46. package/lib/components/respArea/ToolbarIcon.js +105 -0
  47. package/lib/components/respArea/ToolbarIcon.js.map +1 -0
  48. package/lib/components/respArea/choice.js +2 -0
  49. package/lib/constants.js.map +1 -0
  50. package/lib/extensions/component.js +5 -5
  51. package/lib/extensions/component.js.map +1 -0
  52. package/lib/extensions/css.js.map +1 -0
  53. package/lib/extensions/custom-toolbar-wrapper.js +2 -4
  54. package/lib/extensions/custom-toolbar-wrapper.js.map +1 -0
  55. package/lib/extensions/extended-table.js +30 -0
  56. package/lib/extensions/extended-table.js.map +1 -0
  57. package/lib/extensions/image.js +2 -8
  58. package/lib/extensions/image.js.map +1 -0
  59. package/lib/extensions/index.js +52 -0
  60. package/lib/extensions/index.js.map +1 -0
  61. package/lib/extensions/math.js.map +1 -0
  62. package/lib/extensions/media.js +7 -7
  63. package/lib/extensions/media.js.map +1 -0
  64. package/lib/extensions/responseArea.js +7 -7
  65. package/lib/extensions/responseArea.js.map +1 -0
  66. package/lib/index.js +16 -1481
  67. package/lib/index.js.map +1 -0
  68. package/lib/plugins/index.js +8 -80
  69. package/lib/styles/editorContainerStyles.js +200 -0
  70. package/lib/styles/editorContainerStyles.js.map +1 -0
  71. package/lib/theme.js.map +1 -0
  72. package/lib/utils/size.js +34 -0
  73. package/lib/utils/size.js.map +1 -0
  74. package/package.json +1 -1
  75. package/src/components/CharacterPicker.jsx +185 -0
  76. package/src/components/EditableHtml.jsx +306 -0
  77. package/src/components/MenuBar.jsx +630 -0
  78. package/src/components/TiptapContainer.jsx +96 -0
  79. package/src/components/characters/characterUtils.js +127 -0
  80. package/src/{plugins/image/image-toolbar.jsx → components/image/ImageToolbar.jsx} +2 -2
  81. package/src/{plugins/image/insert-image-handler.js → components/image/InsertImageHandler.js} +0 -1
  82. package/src/{plugins/media/media-dialog.js → components/media/MediaDialog.js} +2 -2
  83. package/src/{plugins/respArea/drag-in-the-blank → components/respArea/DragInTheBlank}/choice.jsx +1 -1
  84. package/src/{plugins/respArea/inline-dropdown/index.jsx → components/respArea/InlineDropdown.jsx} +1 -1
  85. package/src/components/respArea/ToolbarIcon.jsx +68 -0
  86. package/src/extensions/component.jsx +2 -2
  87. package/src/extensions/custom-toolbar-wrapper.jsx +6 -7
  88. package/src/extensions/extended-table.js +27 -0
  89. package/src/extensions/image.js +2 -2
  90. package/src/extensions/index.js +76 -0
  91. package/src/extensions/media.js +12 -7
  92. package/src/extensions/responseArea.js +7 -7
  93. package/src/index.jsx +3 -1440
  94. package/src/styles/editorContainerStyles.js +203 -0
  95. package/src/utils/size.js +32 -0
  96. package/src/__tests__/editor.test.jsx +0 -363
  97. package/src/__tests__/serialization.test.js +0 -291
  98. package/src/block-tags.js +0 -17
  99. package/src/editor.jsx +0 -1197
  100. package/src/extensions/characters.js +0 -46
  101. package/src/old-index.jsx +0 -162
  102. package/src/parse-html.js +0 -8
  103. package/src/plugins/README.md +0 -27
  104. package/src/plugins/characters/index.jsx +0 -284
  105. package/src/plugins/characters/utils.js +0 -447
  106. package/src/plugins/css/index.jsx +0 -340
  107. package/src/plugins/customPlugin/index.jsx +0 -85
  108. package/src/plugins/html/icons/index.jsx +0 -19
  109. package/src/plugins/html/index.jsx +0 -72
  110. package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +0 -51
  111. package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +0 -27
  112. package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +0 -44
  113. package/src/plugins/image/__tests__/component.test.jsx +0 -41
  114. package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +0 -42
  115. package/src/plugins/image/__tests__/image-toolbar.test.jsx +0 -11
  116. package/src/plugins/image/__tests__/index.test.js +0 -95
  117. package/src/plugins/image/__tests__/insert-image-handler.test.js +0 -113
  118. package/src/plugins/image/__tests__/mock-change.js +0 -15
  119. package/src/plugins/image/component.jsx +0 -343
  120. package/src/plugins/image/index.jsx +0 -227
  121. package/src/plugins/index.jsx +0 -377
  122. package/src/plugins/list/__tests__/index.test.js +0 -54
  123. package/src/plugins/list/index.jsx +0 -305
  124. package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +0 -48
  125. package/src/plugins/math/__tests__/index.test.jsx +0 -245
  126. package/src/plugins/math/index.jsx +0 -379
  127. package/src/plugins/media/__tests__/index.test.js +0 -75
  128. package/src/plugins/media/index.jsx +0 -325
  129. package/src/plugins/rendering/index.js +0 -31
  130. package/src/plugins/respArea/index.jsx +0 -299
  131. package/src/plugins/respArea/math-templated/index.jsx +0 -104
  132. package/src/plugins/respArea/utils.jsx +0 -90
  133. package/src/plugins/table/CustomTablePlugin.js +0 -113
  134. package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +0 -44
  135. package/src/plugins/table/__tests__/index.test.jsx +0 -401
  136. package/src/plugins/table/__tests__/table-toolbar.test.jsx +0 -42
  137. package/src/plugins/table/index.jsx +0 -427
  138. package/src/plugins/table/table-toolbar.jsx +0 -136
  139. package/src/plugins/textAlign/index.jsx +0 -23
  140. package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +0 -923
  141. package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +0 -20
  142. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +0 -36
  143. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +0 -46
  144. package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +0 -94
  145. package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +0 -37
  146. package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +0 -51
  147. package/src/plugins/toolbar/__tests__/toolbar.test.jsx +0 -106
  148. package/src/plugins/toolbar/default-toolbar.jsx +0 -206
  149. package/src/plugins/toolbar/editor-and-toolbar.jsx +0 -257
  150. package/src/plugins/toolbar/index.jsx +0 -23
  151. package/src/plugins/toolbar/toolbar.jsx +0 -338
  152. package/src/plugins/utils.js +0 -31
  153. package/src/serialization.jsx +0 -621
  154. /package/src/{plugins → components}/characters/custom-popper.js +0 -0
  155. /package/src/{plugins/toolbar → components/common}/done-button.jsx +0 -0
  156. /package/src/{plugins/toolbar → components/common}/toolbar-buttons.jsx +0 -0
  157. /package/src/{plugins/css/icons/index.jsx → components/icons/CssIcon.jsx} +0 -0
  158. /package/src/{plugins/respArea/icons/index.jsx → components/icons/RespArea.jsx} +0 -0
  159. /package/src/{plugins/table/icons/index.jsx → components/icons/TableIcons.jsx} +0 -0
  160. /package/src/{plugins/textAlign/icons/index.jsx → components/icons/TextAlign.jsx} +0 -0
  161. /package/src/{plugins/image/alt-dialog.jsx → components/image/AltDialog.jsx} +0 -0
  162. /package/src/{plugins/media/media-toolbar.jsx → components/media/MediaToolbar.jsx} +0 -0
  163. /package/src/{plugins/media/media-wrapper.jsx → components/media/MediaWrapper.jsx} +0 -0
  164. /package/src/{plugins/respArea/drag-in-the-blank/index.jsx → components/respArea/DragInTheBlank/DragInTheBlank.jsx} +0 -0
  165. /package/src/{plugins/respArea/explicit-constructed-response/index.jsx → components/respArea/ExplicitConstructedResponse.jsx} +0 -0
@@ -1,46 +0,0 @@
1
- // InlineNodes.js
2
- import React from 'react';
3
- import { Node, ReactNodeViewRenderer } from '@tiptap/react';
4
- import ExplicitConstructedResponse from '../plugins/respArea/explicit-constructed-response';
5
- import DragInTheBlank from '../plugins/respArea/drag-in-the-blank';
6
- import InlineDropdown from '../plugins/respArea/inline-dropdown';
7
-
8
- /**
9
- * ExplicitConstructedResponse Node
10
- */
11
- export const ExplicitConstructedResponseNode = Node.create({
12
- name: 'explicit_constructed_response',
13
- group: 'inline',
14
- inline: true,
15
- atom: true,
16
- addAttributes() {
17
- return {
18
- index: { default: null },
19
- value: { default: '' },
20
- };
21
- },
22
- parseHTML() {
23
- return [
24
- {
25
- tag: 'span[data-type="explicit_constructed_response"]',
26
- getAttrs: (el) => ({
27
- index: el.dataset.index,
28
- value: el.dataset.value,
29
- }),
30
- },
31
- ];
32
- },
33
- renderHTML({ HTMLAttributes }) {
34
- return [
35
- 'span',
36
- {
37
- 'data-type': 'explicit_constructed_response',
38
- 'data-index': HTMLAttributes.index,
39
- 'data-value': HTMLAttributes.value,
40
- },
41
- ];
42
- },
43
- addNodeView() {
44
- return ReactNodeViewRenderer(ExplicitConstructedResponse);
45
- },
46
- });
package/src/old-index.jsx DELETED
@@ -1,162 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import Editor, { DEFAULT_PLUGINS, ALL_PLUGINS } from './editor';
4
- import { extraCSSRulesOpts, htmlToValue, valueToHtml, reduceMultipleBrs } from './serialization';
5
- import { parseDegrees } from './parse-html';
6
- import constants from './constants';
7
- import debug from 'debug';
8
- import { Range } from 'slate';
9
-
10
- const log = debug('@pie-lib:editable-html');
11
-
12
- /**
13
- * Wrapper around the editor that exposes a `markup` and `onChange(markup:string)` api.
14
- * Because of the mismatch between the markup and the `Value` we need to convert the incoming markup to a value and
15
- * compare it. TODO: This is an interim fix, we'll need to strip back `Editor` and look how best to maintain the
16
- * `markup` api whilst avoiding the serialization mismatch. We should be making better use of schemas w/ normalize.
17
- */
18
- export default class EditableHtml extends React.Component {
19
- static propTypes = {
20
- error: PropTypes.any,
21
- onChange: PropTypes.func.isRequired,
22
- onDone: PropTypes.func,
23
- markup: PropTypes.string.isRequired,
24
- allowValidation: PropTypes.bool,
25
- toolbarOpts: PropTypes.object,
26
- extraCSSRules: PropTypes.shape({
27
- names: PropTypes.arrayOf(PropTypes.string),
28
- rules: PropTypes.string,
29
- }),
30
- };
31
-
32
- static defaultProps = {
33
- onDone: () => {},
34
- allowValidation: false,
35
- };
36
-
37
- constructor(props) {
38
- super(props);
39
-
40
- if (props.extraCSSRules) {
41
- Object.assign(extraCSSRulesOpts, this.props.extraCSSRules);
42
- }
43
-
44
- const v = htmlToValue(props.markup);
45
- this.state = {
46
- value: v,
47
- };
48
- }
49
-
50
- // eslint-disable-next-line react/no-deprecated
51
- componentWillReceiveProps(props) {
52
- if (!props.allowValidation && props.markup === this.props.markup) {
53
- return;
54
- }
55
-
56
- const v = htmlToValue(props.markup);
57
- const current = htmlToValue(this.props.markup);
58
-
59
- if (v.equals && !v.equals(current)) {
60
- this.setState({ value: v });
61
- }
62
- }
63
-
64
- runSerializationOnMarkup = () => {
65
- if (!this.props.markup) {
66
- return;
67
- }
68
-
69
- const v = htmlToValue(reduceMultipleBrs(this.props.markup));
70
-
71
- this.setState({ value: v });
72
- };
73
-
74
- onChange = (value, done) => {
75
- const html = valueToHtml(value);
76
- const htmlParsed = parseDegrees(html);
77
-
78
- if (htmlParsed !== this.props.markup && this.props.onChange) {
79
- this.props.onChange(htmlParsed);
80
- }
81
-
82
- if (done && this.props.onDone) {
83
- this.props.onDone(htmlParsed);
84
- }
85
- };
86
-
87
- focus = (position, node, select = false) => {
88
- if (this.editorRef) {
89
- this.editorRef.change((c) => {
90
- const lastText = node ? c.value.document.getNextText(node.key) : c.value.document.getLastText();
91
- const editorDOM = document.querySelector(`[data-key="${this.editorRef.value.document.key}"]`);
92
-
93
- if (editorDOM !== document.activeElement) {
94
- document.activeElement.blur();
95
- }
96
-
97
- c.focus();
98
-
99
- if (position === 'end' && lastText) {
100
- c.moveFocusTo(lastText.key, lastText.text?.length).moveAnchorTo(lastText.key, lastText.text?.length);
101
- if (select) {
102
- const range = Range.fromJSON({
103
- anchorKey: lastText.key,
104
- anchorOffset: 0,
105
- focusKey: lastText.key,
106
- focusOffset: lastText.text?.length,
107
- isFocused: true,
108
- isBackward: false,
109
- });
110
- c.select(range);
111
- }
112
- }
113
-
114
- if (position === 'beginning' && lastText) {
115
- c.moveFocusTo(lastText.key, 0).moveAnchorTo(lastText.key, 0);
116
- }
117
- editorDOM.focus();
118
- });
119
- }
120
- };
121
-
122
- finishEditing = () => {
123
- if (this.editorRef) {
124
- this.editorRef.props.onEditingDone();
125
- }
126
- };
127
-
128
- render() {
129
- const { value } = this.state;
130
- const { toolbarOpts, error } = this.props;
131
-
132
- if (toolbarOpts) {
133
- toolbarOpts.error = error;
134
- }
135
-
136
- const props = {
137
- ...this.props,
138
- markup: null,
139
- value,
140
- onChange: this.onChange,
141
- focus: this.focus,
142
- runSerializationOnMarkup: this.runSerializationOnMarkup,
143
- };
144
-
145
- return (
146
- <Editor
147
- onRef={(ref) => {
148
- if (ref) {
149
- this.rootRef = ref;
150
- }
151
- }}
152
- editorRef={(ref) => ref && (this.editorRef = ref)}
153
- {...props}
154
- />
155
- );
156
- }
157
- }
158
-
159
- /**
160
- * Export lower level Editor and serialization functions.
161
- */
162
- export { htmlToValue, valueToHtml, Editor, DEFAULT_PLUGINS, ALL_PLUGINS, constants };
package/src/parse-html.js DELETED
@@ -1,8 +0,0 @@
1
- export const parseDegrees = (html) =>
2
- html
3
- // removes \( use case: 50°
4
- .replace(/\\[(]/g, '')
5
- // removes \) use case: 50°+m<1
6
- .replace(/\\[)]/g, '')
7
- // removes \degree use case: 50°
8
- .replace(/\\degree/g, '&deg;');
@@ -1,27 +0,0 @@
1
- # plugins
2
-
3
- ## Custom toolbar
4
-
5
- To create a custom toolbar you need to add the following methods to the toolbar object:
6
-
7
- ```typescript
8
- type ChangeFn = (key:string, update : object) : void;
9
-
10
- type Toolbar = {
11
- /**
12
- * return true if this plugin supports this node type
13
- */
14
- supports : (node: Slate.Node) : Boolean;
15
- /**
16
- * return a React component to edit the data within the node,
17
- * call toolbarDone to finish editing, call toolbarChange to update
18
- * the main editor without closing editing.
19
- */
20
- customToolbar: (node: Slate.Node, toolbarDone : ChangeFn, toolbarChange: ChangeFn),
21
- /**
22
- * Takes the output of the `customToolbar#toolbarDone` call
23
- * and passes in a value so that you can create a Slate.Change.
24
- */
25
- applyChange: (key: string, data: object, value: Slate.Value) : Slate.Change | undefined
26
- }
27
- ```
@@ -1,284 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom';
3
- import debug from 'debug';
4
- import get from 'lodash/get';
5
-
6
- import { PureToolbar } from '@pie-lib/math-toolbar';
7
-
8
- import CustomPopper from './custom-popper';
9
- import { insertSnackBar } from '../respArea/utils';
10
- import { characterIcons, spanishConfig, specialConfig } from './utils';
11
- import PropTypes from 'prop-types';
12
-
13
- const log = debug('@pie-lib:editable-html:plugins:characters');
14
-
15
- const removePopOvers = () => {
16
- const prevPopOvers = document.querySelectorAll('#mouse-over-popover');
17
-
18
- log('[characters:removePopOvers]');
19
- prevPopOvers.forEach((s) => s.remove());
20
- };
21
-
22
- export const removeDialogs = () => {
23
- const prevDialogs = document.querySelectorAll('.insert-character-dialog');
24
-
25
- log('[characters:removeDialogs]');
26
- prevDialogs.forEach((s) => s.remove());
27
- removePopOvers();
28
- };
29
-
30
- const insertDialog = ({ editorDOM, value, callback, opts }) => {
31
- const newEl = document.createElement('div');
32
-
33
- log('[characters:insertDialog]');
34
-
35
- removeDialogs();
36
-
37
- newEl.className = 'insert-character-dialog';
38
-
39
- let configToUse;
40
-
41
- switch (true) {
42
- case opts.language === 'spanish':
43
- configToUse = spanishConfig;
44
- break;
45
- case opts.language === 'special':
46
- configToUse = specialConfig;
47
- break;
48
- default:
49
- configToUse = opts;
50
- }
51
-
52
- if (!configToUse.characters) {
53
- insertSnackBar('No characters provided or language not recognized');
54
- return;
55
- }
56
-
57
- const layoutForCharacters = configToUse.characters.reduce(
58
- (obj, arr) => {
59
- if (arr.length >= obj.columns) {
60
- obj.columns = arr.length;
61
- }
62
-
63
- return obj;
64
- },
65
- { rows: configToUse.characters.length, columns: 0 },
66
- );
67
-
68
- let popoverEl;
69
-
70
- const closePopOver = () => {
71
- if (popoverEl) {
72
- popoverEl.remove();
73
- }
74
-
75
- removePopOvers();
76
- };
77
-
78
- const renderPopOver = (event, el) => {
79
- if (!event) {
80
- return;
81
- }
82
-
83
- const infoStyle = { fontSize: '20px', lineHeight: '20px' };
84
-
85
- closePopOver();
86
-
87
- popoverEl = document.createElement('div');
88
- ReactDOM.render(
89
- <CustomPopper onClose={closePopOver} anchorEl={event.currentTarget}>
90
- <div>{el.label}</div>
91
-
92
- <div style={infoStyle}>{el.description}</div>
93
-
94
- <div style={infoStyle}>{el.unicode}</div>
95
- </CustomPopper>,
96
- popoverEl,
97
- );
98
-
99
- document.body.appendChild(newEl);
100
- };
101
-
102
- let firstCallMade = false;
103
-
104
- const listener = (e) => {
105
- // this will be triggered right after setting it because
106
- // this toolbar is added on the mousedown event
107
- // so right after mouseup, the click will be triggered
108
- if (firstCallMade) {
109
- const focusIsInModals = newEl.contains(e.target) || (popoverEl && popoverEl.contains(e.target));
110
- const focusIsInEditor = editorDOM.contains(e.target);
111
-
112
- if (!(focusIsInModals || focusIsInEditor)) {
113
- handleClose();
114
- }
115
- } else {
116
- firstCallMade = true;
117
- }
118
- };
119
-
120
- const handleClose = () => {
121
- callback(undefined, true);
122
- newEl.remove();
123
- closePopOver();
124
- document.body.removeEventListener('click', listener);
125
- };
126
-
127
- const handleChange = (val) => {
128
- if (typeof val === 'string') {
129
- callback(val, true);
130
- }
131
- };
132
-
133
- const el = (
134
- <PureToolbar
135
- keyPadCharacterRef={opts.keyPadCharacterRef}
136
- setKeypadInteraction={opts.setKeypadInteraction}
137
- autoFocus
138
- noDecimal
139
- hideInput
140
- noLatexHandling
141
- hideDoneButtonBackground
142
- layoutForKeyPad={layoutForCharacters}
143
- additionalKeys={configToUse.characters.reduce((arr, n) => {
144
- arr = [
145
- ...arr,
146
- ...n.map((k) => ({
147
- name: get(k, 'name') || k,
148
- write: get(k, 'write') || k,
149
- label: get(k, 'label') || k,
150
- category: 'character',
151
- extraClass: 'character',
152
- extraProps: {
153
- ...(k.extraProps || {}),
154
- style: {
155
- ...(k.extraProps || {}).style,
156
- border: '1px solid #000',
157
- },
158
- },
159
- ...(configToUse.hasPreview
160
- ? {
161
- actions: { onMouseEnter: (ev) => renderPopOver(ev, k), onMouseLeave: closePopOver },
162
- }
163
- : {}),
164
- })),
165
- ];
166
-
167
- return arr;
168
- }, [])}
169
- keypadMode="language"
170
- onChange={handleChange}
171
- onDone={handleClose}
172
- />
173
- );
174
-
175
- ReactDOM.render(el, newEl, () => {
176
- const cursorItem = document.querySelector(`[data-key="${value.anchorKey}"]`);
177
-
178
- if (cursorItem) {
179
- const bodyRect = document.body.getBoundingClientRect();
180
- const boundRect = cursorItem.getBoundingClientRect();
181
-
182
- document.body.appendChild(newEl);
183
-
184
- // when height of toolbar exceeds screen - can happen in scrollable contexts
185
- let additionalTopOffset = 0;
186
- if (boundRect.y < newEl.offsetHeight) {
187
- additionalTopOffset = newEl.offsetHeight - boundRect.y + 10;
188
- }
189
-
190
- newEl.style.maxWidth = '500px';
191
- newEl.style.position = 'absolute';
192
- newEl.style.top = `${boundRect.top + Math.abs(bodyRect.top) - newEl.offsetHeight - 10 + additionalTopOffset}px`;
193
- newEl.style.zIndex = 99999;
194
-
195
- const leftValue = `${boundRect.left + Math.abs(bodyRect.left) + cursorItem.offsetWidth + 10}px`;
196
-
197
- const rightValue = `${boundRect.x}px`;
198
-
199
- newEl.style.left = leftValue;
200
-
201
- const leftAlignedWidth = newEl.offsetWidth;
202
-
203
- newEl.style.left = 'unset';
204
- newEl.style.right = rightValue;
205
-
206
- const rightAlignedWidth = newEl.offsetWidth;
207
-
208
- newEl.style.left = 'unset';
209
- newEl.style.right = 'unset';
210
-
211
- if (leftAlignedWidth >= rightAlignedWidth) {
212
- newEl.style.left = leftValue;
213
- } else {
214
- newEl.style.right = rightValue;
215
- }
216
-
217
- document.body.addEventListener('click', listener);
218
- }
219
- });
220
- };
221
-
222
- const CharacterIcon = ({ letter }) => (
223
- <div
224
- style={{
225
- fontSize: '24px',
226
- lineHeight: '24px',
227
- }}
228
- >
229
- {letter}
230
- </div>
231
- );
232
-
233
- CharacterIcon.propTypes = {
234
- letter: PropTypes.string,
235
- };
236
-
237
- export default function CharactersPlugin(opts) {
238
- removeDialogs();
239
-
240
- return {
241
- name: 'characters',
242
- toolbar: {
243
- icon: <CharacterIcon letter={opts.characterIcon || characterIcons[opts.language] || 'ñ'} />,
244
- ariaLabel: `${opts.language} characters Toolbar`,
245
- onClick: (value, onChange, getFocusedValue) => {
246
- const editorDOM = document.querySelector(`[data-key="${value.document.key}"]`);
247
- let valueToUse = value;
248
-
249
- const callback = (char, focus) => {
250
- if (getFocusedValue) {
251
- valueToUse = getFocusedValue() || valueToUse;
252
- }
253
-
254
- if (char) {
255
- const change = valueToUse.change().insertTextByKey(valueToUse.anchorKey, valueToUse.anchorOffset, char);
256
-
257
- valueToUse = change.value;
258
- log('[characters:insert]: ', value);
259
- onChange(change);
260
- }
261
-
262
- log('[characters:click]');
263
-
264
- if (focus) {
265
- if (editorDOM) {
266
- editorDOM.focus();
267
- }
268
- }
269
- };
270
-
271
- insertDialog({ editorDOM, value: valueToUse, callback, opts });
272
- },
273
- },
274
-
275
- pluginStyles: (node, parentNode, p) => {
276
- if (p) {
277
- return {
278
- position: 'absolute',
279
- top: 'initial',
280
- };
281
- }
282
- },
283
- };
284
- }