@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.
- package/lib/components/CharacterPicker.js +221 -0
- package/lib/components/EditableHtml.js +323 -0
- package/lib/components/MenuBar.js +693 -0
- package/lib/components/TiptapContainer.js +90 -0
- package/lib/components/buttons/done-button.js +53 -0
- package/lib/components/characters/characterUtils.js +112 -0
- package/lib/components/characters/custom-popper.js +73 -0
- package/lib/components/common/done-button.js +53 -0
- package/lib/components/icons/CssIcon.js +37 -0
- package/lib/components/icons/RespArea.js +95 -0
- package/lib/components/icons/TableIcons.js +69 -0
- package/lib/components/icons/TextAlign.js +194 -0
- package/lib/components/icons/index.js +194 -0
- package/lib/components/image/ImageToolbar.js +16 -0
- package/lib/components/image/InsertImageHandler.js +16 -0
- package/lib/components/media/MediaDialog.js +16 -0
- package/lib/components/media/MediaToolbar.js +16 -0
- package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js +94 -0
- package/lib/components/respArea/DragInTheBlank/choice.js +289 -0
- package/lib/components/respArea/DragInTheBlank.js +94 -0
- package/lib/components/respArea/ExplicitConstructedResponse.js +120 -0
- package/lib/components/respArea/InlineDropdown.js +126 -0
- package/lib/components/respArea/ToolbarIcon.js +105 -0
- package/lib/components/respArea/choice.js +2 -0
- package/lib/extensions/component.js +5 -5
- package/lib/extensions/custom-toolbar-wrapper.js +2 -4
- package/lib/extensions/extended-table.js +30 -0
- package/lib/extensions/index.js +52 -0
- package/lib/extensions/media.js +5 -5
- package/lib/extensions/responseArea.js +7 -7
- package/lib/index.js +16 -1454
- package/lib/plugins/index.js +10 -82
- package/lib/styles/editorContainerStyles.js +200 -0
- package/lib/utils/size.js +34 -0
- package/package.json +1 -1
- package/src/components/CharacterPicker.jsx +185 -0
- package/src/components/EditableHtml.jsx +306 -0
- package/src/components/MenuBar.jsx +630 -0
- package/src/components/TiptapContainer.jsx +96 -0
- package/src/components/characters/characterUtils.js +127 -0
- package/src/components/image/ImageToolbar.jsx +1 -0
- package/src/components/image/InsertImageHandler.js +1 -0
- package/src/components/media/MediaDialog.js +1 -0
- package/src/components/media/MediaToolbar.jsx +1 -0
- package/src/{plugins/respArea/drag-in-the-blank → components/respArea/DragInTheBlank}/choice.jsx +1 -1
- package/src/{plugins/respArea/inline-dropdown/index.jsx → components/respArea/InlineDropdown.jsx} +1 -1
- package/src/components/respArea/ToolbarIcon.jsx +68 -0
- package/src/extensions/component.jsx +2 -2
- package/src/extensions/custom-toolbar-wrapper.jsx +6 -7
- package/src/extensions/extended-table.js +27 -0
- package/src/extensions/index.js +76 -0
- package/src/extensions/media.js +10 -4
- package/src/extensions/responseArea.js +7 -7
- package/src/index.jsx +3 -1409
- package/src/styles/editorContainerStyles.js +203 -0
- package/src/utils/size.js +32 -0
- package/src/__tests__/editor.test.jsx +0 -363
- package/src/__tests__/serialization.test.js +0 -291
- package/src/block-tags.js +0 -17
- package/src/editor.jsx +0 -1197
- package/src/extensions/characters.js +0 -46
- package/src/old-index.jsx +0 -162
- package/src/parse-html.js +0 -8
- package/src/plugins/README.md +0 -27
- package/src/plugins/characters/index.jsx +0 -284
- package/src/plugins/characters/utils.js +0 -447
- package/src/plugins/css/index.jsx +0 -340
- package/src/plugins/customPlugin/index.jsx +0 -85
- package/src/plugins/html/icons/index.jsx +0 -19
- package/src/plugins/html/index.jsx +0 -72
- package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +0 -51
- package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +0 -27
- package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +0 -44
- package/src/plugins/image/__tests__/component.test.jsx +0 -41
- package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +0 -42
- package/src/plugins/image/__tests__/image-toolbar.test.jsx +0 -11
- package/src/plugins/image/__tests__/index.test.js +0 -95
- package/src/plugins/image/__tests__/insert-image-handler.test.js +0 -113
- package/src/plugins/image/__tests__/mock-change.js +0 -15
- package/src/plugins/image/alt-dialog.jsx +0 -82
- package/src/plugins/image/component.jsx +0 -343
- package/src/plugins/image/image-toolbar.jsx +0 -100
- package/src/plugins/image/index.jsx +0 -227
- package/src/plugins/image/insert-image-handler.js +0 -79
- package/src/plugins/index.jsx +0 -377
- package/src/plugins/list/__tests__/index.test.js +0 -54
- package/src/plugins/list/index.jsx +0 -305
- package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +0 -48
- package/src/plugins/math/__tests__/index.test.jsx +0 -245
- package/src/plugins/math/index.jsx +0 -379
- package/src/plugins/media/__tests__/index.test.js +0 -75
- package/src/plugins/media/index.jsx +0 -325
- package/src/plugins/media/media-dialog.js +0 -624
- package/src/plugins/media/media-toolbar.jsx +0 -56
- package/src/plugins/media/media-wrapper.jsx +0 -43
- package/src/plugins/rendering/index.js +0 -31
- package/src/plugins/respArea/index.jsx +0 -299
- package/src/plugins/respArea/math-templated/index.jsx +0 -104
- package/src/plugins/respArea/utils.jsx +0 -90
- package/src/plugins/table/CustomTablePlugin.js +0 -113
- package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +0 -44
- package/src/plugins/table/__tests__/index.test.jsx +0 -401
- package/src/plugins/table/__tests__/table-toolbar.test.jsx +0 -42
- package/src/plugins/table/index.jsx +0 -427
- package/src/plugins/table/table-toolbar.jsx +0 -136
- package/src/plugins/textAlign/index.jsx +0 -23
- package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +0 -923
- package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +0 -20
- package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +0 -36
- package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +0 -46
- package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +0 -94
- package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +0 -37
- package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +0 -51
- package/src/plugins/toolbar/__tests__/toolbar.test.jsx +0 -106
- package/src/plugins/toolbar/default-toolbar.jsx +0 -206
- package/src/plugins/toolbar/editor-and-toolbar.jsx +0 -257
- package/src/plugins/toolbar/index.jsx +0 -23
- package/src/plugins/toolbar/toolbar-buttons.jsx +0 -138
- package/src/plugins/toolbar/toolbar.jsx +0 -338
- package/src/plugins/utils.js +0 -31
- package/src/serialization.jsx +0 -621
- /package/src/{plugins → components}/characters/custom-popper.js +0 -0
- /package/src/{plugins/toolbar → components/common}/done-button.jsx +0 -0
- /package/src/{plugins/css/icons/index.jsx → components/icons/CssIcon.jsx} +0 -0
- /package/src/{plugins/respArea/icons/index.jsx → components/icons/RespArea.jsx} +0 -0
- /package/src/{plugins/table/icons/index.jsx → components/icons/TableIcons.jsx} +0 -0
- /package/src/{plugins/textAlign/icons/index.jsx → components/icons/TextAlign.jsx} +0 -0
- /package/src/{plugins/respArea/drag-in-the-blank/index.jsx → components/respArea/DragInTheBlank/DragInTheBlank.jsx} +0 -0
- /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
package/src/plugins/README.md
DELETED
|
@@ -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
|
-
}
|