@pie-lib/editable-html 10.0.0-beta.6 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +1 -1
- package/CHANGELOG.md +81 -0
- package/LICENSE.md +5 -0
- package/lib/editor.js +410 -543
- package/lib/editor.js.map +1 -1
- package/lib/index.js +200 -101
- package/lib/index.js.map +1 -1
- package/lib/parse-html.js +5 -6
- package/lib/parse-html.js.map +1 -1
- package/lib/plugins/characters/custom-popper.js +12 -2
- package/lib/plugins/characters/custom-popper.js.map +1 -1
- package/lib/plugins/characters/index.js +71 -19
- package/lib/plugins/characters/index.js.map +1 -1
- package/lib/plugins/characters/utils.js.map +1 -1
- package/lib/plugins/html/icons/index.js +38 -0
- package/lib/plugins/html/icons/index.js.map +1 -0
- package/lib/plugins/html/index.js +75 -0
- package/lib/plugins/html/index.js.map +1 -0
- package/lib/plugins/image/alt-dialog.js +26 -0
- package/lib/plugins/image/alt-dialog.js.map +1 -1
- package/lib/plugins/image/component.js +124 -90
- package/lib/plugins/image/component.js.map +1 -1
- package/lib/plugins/image/image-toolbar.js +45 -7
- package/lib/plugins/image/image-toolbar.js.map +1 -1
- package/lib/plugins/image/index.js +91 -113
- package/lib/plugins/image/index.js.map +1 -1
- package/lib/plugins/image/insert-image-handler.js +54 -72
- package/lib/plugins/image/insert-image-handler.js.map +1 -1
- package/lib/plugins/index.js +71 -31
- package/lib/plugins/index.js.map +1 -1
- package/lib/plugins/list/index.js +129 -58
- package/lib/plugins/list/index.js.map +1 -1
- package/lib/plugins/math/index.js +152 -118
- package/lib/plugins/math/index.js.map +1 -1
- package/lib/plugins/media/index.js +185 -168
- package/lib/plugins/media/index.js.map +1 -1
- package/lib/plugins/media/media-dialog.js +197 -110
- package/lib/plugins/media/media-dialog.js.map +1 -1
- package/lib/plugins/media/media-toolbar.js +24 -4
- package/lib/plugins/media/media-toolbar.js.map +1 -1
- package/lib/plugins/media/media-wrapper.js +65 -23
- package/lib/plugins/media/media-wrapper.js.map +1 -1
- package/lib/plugins/respArea/drag-in-the-blank/choice.js +50 -10
- package/lib/plugins/respArea/drag-in-the-blank/choice.js.map +1 -1
- package/lib/plugins/respArea/drag-in-the-blank/index.js +22 -9
- package/lib/plugins/respArea/drag-in-the-blank/index.js.map +1 -1
- package/lib/plugins/respArea/explicit-constructed-response/index.js +9 -4
- package/lib/plugins/respArea/explicit-constructed-response/index.js.map +1 -1
- package/lib/plugins/respArea/icons/index.js +18 -1
- package/lib/plugins/respArea/icons/index.js.map +1 -1
- package/lib/plugins/respArea/index.js +133 -122
- package/lib/plugins/respArea/index.js.map +1 -1
- package/lib/plugins/respArea/inline-dropdown/index.js +10 -4
- package/lib/plugins/respArea/inline-dropdown/index.js.map +1 -1
- package/lib/plugins/respArea/utils.js +33 -15
- package/lib/plugins/respArea/utils.js.map +1 -1
- package/lib/plugins/table/icons/index.js +7 -0
- package/lib/plugins/table/icons/index.js.map +1 -1
- package/lib/plugins/table/index.js +279 -390
- package/lib/plugins/table/index.js.map +1 -1
- package/lib/plugins/table/table-toolbar.js +47 -14
- package/lib/plugins/table/table-toolbar.js.map +1 -1
- package/lib/plugins/toolbar/default-toolbar.js +63 -51
- package/lib/plugins/toolbar/default-toolbar.js.map +1 -1
- package/lib/plugins/toolbar/done-button.js +9 -1
- package/lib/plugins/toolbar/done-button.js.map +1 -1
- package/lib/plugins/toolbar/editor-and-toolbar.js +140 -83
- package/lib/plugins/toolbar/editor-and-toolbar.js.map +1 -1
- package/lib/plugins/toolbar/index.js +5 -0
- package/lib/plugins/toolbar/index.js.map +1 -1
- package/lib/plugins/toolbar/toolbar-buttons.js +39 -8
- package/lib/plugins/toolbar/toolbar-buttons.js.map +1 -1
- package/lib/plugins/toolbar/toolbar.js +261 -225
- package/lib/plugins/toolbar/toolbar.js.map +1 -1
- package/lib/plugins/utils.js +16 -19
- package/lib/plugins/utils.js.map +1 -1
- package/lib/serialization.js +70 -11
- package/lib/serialization.js.map +1 -1
- package/lib/theme.js.map +1 -1
- package/package.json +18 -17
- package/src/editor.jsx +140 -450
- package/src/index.jsx +96 -62
- package/src/plugins/characters/index.jsx +18 -14
- package/src/plugins/html/icons/index.jsx +19 -0
- package/src/plugins/html/index.jsx +68 -0
- package/src/plugins/image/component.jsx +41 -67
- package/src/plugins/image/index.jsx +43 -108
- package/src/plugins/image/insert-image-handler.js +27 -62
- package/src/plugins/index.jsx +39 -21
- package/src/plugins/list/index.jsx +91 -66
- package/src/plugins/math/index.jsx +71 -84
- package/src/plugins/media/index.jsx +118 -147
- package/src/plugins/media/media-dialog.js +9 -10
- package/src/plugins/media/media-wrapper.jsx +27 -29
- package/src/plugins/respArea/drag-in-the-blank/index.jsx +7 -10
- package/src/plugins/respArea/explicit-constructed-response/index.jsx +2 -3
- package/src/plugins/respArea/index.jsx +90 -138
- package/src/plugins/respArea/inline-dropdown/index.jsx +2 -3
- package/src/plugins/respArea/utils.jsx +28 -23
- package/src/plugins/table/index.jsx +216 -340
- package/src/plugins/table/table-toolbar.jsx +5 -9
- package/src/plugins/toolbar/default-toolbar.jsx +31 -51
- package/src/plugins/toolbar/editor-and-toolbar.jsx +114 -121
- package/src/plugins/toolbar/toolbar.jsx +224 -258
- package/src/plugins/utils.js +2 -19
- package/src/serialization.jsx +1 -1
- package/lib/components.js +0 -92
- package/lib/components.js.map +0 -1
- package/lib/new-serialization.js +0 -280
- package/lib/new-serialization.js.map +0 -1
- package/lib/plugins/hotKeys/index.js +0 -60
- package/lib/plugins/hotKeys/index.js.map +0 -1
- package/lib/test-serializer.js +0 -138
- package/lib/test-serializer.js.map +0 -1
- package/src/components.js +0 -135
- package/src/new-serialization.jsx +0 -310
- package/src/plugins/hotKeys/index.js +0 -54
- package/src/test-serializer.js +0 -132
package/src/index.jsx
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { useSlate } from 'slate-react';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
3
|
import Editor, { DEFAULT_PLUGINS, ALL_PLUGINS } from './editor';
|
|
5
|
-
import { htmlToValue, valueToHtml } from './
|
|
4
|
+
import { htmlToValue, valueToHtml } from './serialization';
|
|
6
5
|
import { parseDegrees } from './parse-html';
|
|
7
6
|
import debug from 'debug';
|
|
8
7
|
import { Range } from 'slate';
|
|
@@ -13,43 +12,87 @@ const log = debug('@pie-lib:editable-html');
|
|
|
13
12
|
*/
|
|
14
13
|
export { htmlToValue, valueToHtml, Editor, DEFAULT_PLUGINS, ALL_PLUGINS };
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Wrapper around the editor that exposes a `markup` and `onChange(markup:string)` api.
|
|
17
|
+
* Because of the mismatch between the markup and the `Value` we need to convert the incoming markup to a value and
|
|
18
|
+
* compare it. TODO: This is an interim fix, we'll need to strip back `Editor` and look how best to maintain the
|
|
19
|
+
* `markup` api whilst avoiding the serialization mismatch. We should be making better use of schemas w/ normalize.
|
|
20
|
+
*/
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
const reduceMultipleBrs = (markup) => {
|
|
23
|
+
try {
|
|
24
|
+
return markup.replace(/(<br\s*\/?>){3,}/gi, '<br>');
|
|
25
|
+
} catch (e) {
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
27
|
+
console.log("Couldn't remove <br/> tags: ", e);
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
setHasBeenCalled(true);
|
|
30
|
+
return markup;
|
|
25
31
|
};
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
export default class EditableHtml extends React.Component {
|
|
34
|
+
static propTypes = {
|
|
35
|
+
error: PropTypes.any,
|
|
36
|
+
onChange: PropTypes.func.isRequired,
|
|
37
|
+
onDone: PropTypes.func,
|
|
38
|
+
markup: PropTypes.string.isRequired,
|
|
39
|
+
allowValidation: PropTypes.bool,
|
|
40
|
+
toolbarOpts: PropTypes.object,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
static defaultProps = {
|
|
44
|
+
onDone: () => {},
|
|
45
|
+
allowValidation: false,
|
|
46
|
+
};
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
constructor(props) {
|
|
49
|
+
super(props);
|
|
33
50
|
const v = htmlToValue(props.markup);
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
this.state = {
|
|
52
|
+
value: v,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line react/no-deprecated
|
|
57
|
+
componentWillReceiveProps(props) {
|
|
58
|
+
if (!props.allowValidation && props.markup === this.props.markup) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const v = htmlToValue(reduceMultipleBrs(props.markup));
|
|
63
|
+
const current = htmlToValue(reduceMultipleBrs(this.props.markup));
|
|
64
|
+
|
|
65
|
+
if (v.equals && !v.equals(current)) {
|
|
66
|
+
this.setState({ value: v });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
runSerializationOnMarkup = () => {
|
|
71
|
+
if (!this.props.markup) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const v = htmlToValue(reduceMultipleBrs(this.props.markup));
|
|
36
76
|
|
|
37
|
-
|
|
77
|
+
this.setState({ value: v });
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
onChange = (value, done) => {
|
|
38
81
|
const html = valueToHtml(value);
|
|
39
82
|
const htmlParsed = parseDegrees(html);
|
|
40
83
|
|
|
41
84
|
log('value as html: ', html);
|
|
42
85
|
|
|
43
|
-
if (html !== props.markup) {
|
|
44
|
-
props.onChange(htmlParsed);
|
|
86
|
+
if (html !== this.props.markup) {
|
|
87
|
+
this.props.onChange(htmlParsed);
|
|
45
88
|
}
|
|
46
89
|
|
|
47
90
|
if (done) {
|
|
48
|
-
props.onDone(htmlParsed);
|
|
91
|
+
this.props.onDone(htmlParsed);
|
|
49
92
|
}
|
|
50
93
|
};
|
|
51
94
|
|
|
52
|
-
|
|
95
|
+
focus = (position, node, select = false) => {
|
|
53
96
|
if (this.editorRef) {
|
|
54
97
|
this.editorRef.change((c) => {
|
|
55
98
|
const lastText = node ? c.value.document.getNextText(node.key) : c.value.document.getLastText();
|
|
@@ -84,48 +127,39 @@ const EditableHtml = React.forwardRef((props, forwardedRef) => {
|
|
|
84
127
|
}
|
|
85
128
|
};
|
|
86
129
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const newProps = {
|
|
94
|
-
...props,
|
|
95
|
-
markup: null,
|
|
96
|
-
value,
|
|
97
|
-
onChange,
|
|
98
|
-
focus,
|
|
130
|
+
finishEditing = () => {
|
|
131
|
+
if (this.editorRef) {
|
|
132
|
+
this.editorRef.props.onEditingDone();
|
|
133
|
+
}
|
|
99
134
|
};
|
|
100
135
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
onRef={ref => {
|
|
105
|
-
if (ref) {
|
|
106
|
-
rootRef.current = ref;
|
|
136
|
+
render() {
|
|
137
|
+
const { value } = this.state;
|
|
138
|
+
const { toolbarOpts, error } = this.props;
|
|
107
139
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
}}
|
|
113
|
-
editorRef={ref => ref && (editorRef.current = ref)}
|
|
114
|
-
/>
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
EditableHtml.propTypes = {
|
|
119
|
-
onChange: PropTypes.func.isRequired,
|
|
120
|
-
onDone: PropTypes.func,
|
|
121
|
-
onEditor: PropTypes.func,
|
|
122
|
-
markup: PropTypes.string.isRequired,
|
|
123
|
-
allowValidation: PropTypes.bool
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
EditableHtml.defaultProps = {
|
|
127
|
-
onDone: () => {},
|
|
128
|
-
allowValidation: false
|
|
129
|
-
};
|
|
140
|
+
if (toolbarOpts) {
|
|
141
|
+
toolbarOpts.error = error;
|
|
142
|
+
}
|
|
130
143
|
|
|
131
|
-
|
|
144
|
+
const props = {
|
|
145
|
+
...this.props,
|
|
146
|
+
markup: null,
|
|
147
|
+
value,
|
|
148
|
+
onChange: this.onChange,
|
|
149
|
+
focus: this.focus,
|
|
150
|
+
runSerializationOnMarkup: this.runSerializationOnMarkup,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<Editor
|
|
155
|
+
onRef={(ref) => {
|
|
156
|
+
if (ref) {
|
|
157
|
+
this.rootRef = ref;
|
|
158
|
+
}
|
|
159
|
+
}}
|
|
160
|
+
editorRef={(ref) => ref && (this.editorRef = ref)}
|
|
161
|
+
{...props}
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { ReactEditor } from 'slate-react';
|
|
3
|
-
import { Editor } from 'slate';
|
|
4
2
|
import ReactDOM from 'react-dom';
|
|
5
|
-
import PropTypes from 'prop-types';
|
|
6
3
|
import debug from 'debug';
|
|
7
4
|
import get from 'lodash/get';
|
|
8
5
|
|
|
@@ -11,6 +8,7 @@ import { PureToolbar } from '@pie-lib/math-toolbar';
|
|
|
11
8
|
import CustomPopper from './custom-popper';
|
|
12
9
|
import { insertSnackBar } from '../respArea/utils';
|
|
13
10
|
import { characterIcons, spanishConfig, specialConfig } from './utils';
|
|
11
|
+
import PropTypes from 'prop-types';
|
|
14
12
|
const log = debug('@pie-lib:editable-html:plugins:characters');
|
|
15
13
|
|
|
16
14
|
const removePopOvers = () => {
|
|
@@ -28,7 +26,7 @@ export const removeDialogs = () => {
|
|
|
28
26
|
removePopOvers();
|
|
29
27
|
};
|
|
30
28
|
|
|
31
|
-
const insertDialog = ({
|
|
29
|
+
const insertDialog = ({ editorDOM, value, callback, opts }) => {
|
|
32
30
|
const newEl = document.createElement('div');
|
|
33
31
|
|
|
34
32
|
log('[characters:insertDialog]');
|
|
@@ -107,9 +105,7 @@ const insertDialog = ({ editor, callback, opts }) => {
|
|
|
107
105
|
// this toolbar is added on the mousedown event
|
|
108
106
|
// so right after mouseup, the click will be triggered
|
|
109
107
|
if (firstCallMade) {
|
|
110
|
-
const focusIsInModals =
|
|
111
|
-
newEl.contains(e.target) || (popoverEl && popoverEl.contains(e.target));
|
|
112
|
-
const editorDOM = ReactEditor.toDOMNode(editor, editor);
|
|
108
|
+
const focusIsInModals = newEl.contains(e.target) || (popoverEl && popoverEl.contains(e.target));
|
|
113
109
|
const focusIsInEditor = editorDOM.contains(e.target);
|
|
114
110
|
|
|
115
111
|
if (!(focusIsInModals || focusIsInEditor)) {
|
|
@@ -174,8 +170,7 @@ const insertDialog = ({ editor, callback, opts }) => {
|
|
|
174
170
|
);
|
|
175
171
|
|
|
176
172
|
ReactDOM.render(el, newEl, () => {
|
|
177
|
-
const
|
|
178
|
-
const cursorItem = ReactEditor.toDOMNode(editor, nodeAtSelection);
|
|
173
|
+
const cursorItem = document.querySelector(`[data-key="${value.anchorKey}"]`);
|
|
179
174
|
|
|
180
175
|
if (cursorItem) {
|
|
181
176
|
const bodyRect = document.body.getBoundingClientRect();
|
|
@@ -242,21 +237,30 @@ export default function CharactersPlugin(opts) {
|
|
|
242
237
|
name: 'characters',
|
|
243
238
|
toolbar: {
|
|
244
239
|
icon: <CharacterIcon letter={opts.characterIcon || characterIcons[opts.language] || 'ñ'} />,
|
|
245
|
-
onClick:
|
|
240
|
+
onClick: (value, onChange, getFocusedValue) => {
|
|
241
|
+
const editorDOM = document.querySelector(`[data-key="${value.document.key}"]`);
|
|
242
|
+
let valueToUse = value;
|
|
246
243
|
const callback = (char, focus) => {
|
|
244
|
+
valueToUse = getFocusedValue();
|
|
245
|
+
|
|
247
246
|
if (char) {
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
const change = valueToUse.change().insertTextByKey(valueToUse.anchorKey, valueToUse.anchorOffset, char);
|
|
248
|
+
|
|
249
|
+
valueToUse = change.value;
|
|
250
|
+
log('[characters:insert]: ', value);
|
|
251
|
+
onChange(change);
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
log('[characters:click]');
|
|
253
255
|
|
|
254
256
|
if (focus) {
|
|
255
|
-
|
|
257
|
+
if (editorDOM) {
|
|
258
|
+
editorDOM.focus();
|
|
259
|
+
}
|
|
256
260
|
}
|
|
257
261
|
};
|
|
258
262
|
|
|
259
|
-
insertDialog({
|
|
263
|
+
insertDialog({ editorDOM, value: valueToUse, callback, opts });
|
|
260
264
|
},
|
|
261
265
|
},
|
|
262
266
|
|
|
@@ -0,0 +1,19 @@
|
|
|
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);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import HtmlModeIcon from './icons';
|
|
3
|
+
import { htmlToValue, valueToHtml } from './../../serialization';
|
|
4
|
+
|
|
5
|
+
const toggleToRichText = (value, onChange) => {
|
|
6
|
+
const plainText = value.document.text;
|
|
7
|
+
const slateValue = 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, isEdited, toggleHtmlMode, handleAlertDialog } = opts;
|
|
19
|
+
|
|
20
|
+
const handleHtmlModeOn = (value, onChange) => {
|
|
21
|
+
const dialogProps = {
|
|
22
|
+
title: 'Warning',
|
|
23
|
+
text: 'Returning to rich text mode may cause edits to be lost.',
|
|
24
|
+
onConfirm: () => {
|
|
25
|
+
toggleToRichText(value, onChange);
|
|
26
|
+
handleAlertDialog(false);
|
|
27
|
+
},
|
|
28
|
+
onClose: () => {
|
|
29
|
+
handleAlertDialog(false);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
handleAlertDialog(true, dialogProps);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleHtmlModeOff = (value, onChange) => {
|
|
37
|
+
const change = value
|
|
38
|
+
.change()
|
|
39
|
+
.selectAll()
|
|
40
|
+
.delete()
|
|
41
|
+
.insertText(valueToHtml(value));
|
|
42
|
+
onChange(change);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
name: 'html',
|
|
47
|
+
toolbar: {
|
|
48
|
+
icon: <HtmlModeIcon isHtmlMode={isHtmlMode} />,
|
|
49
|
+
buttonStyles: {
|
|
50
|
+
margin: '0 20px 0 auto',
|
|
51
|
+
},
|
|
52
|
+
type: 'html',
|
|
53
|
+
onClick: (value, onChange) => {
|
|
54
|
+
if (isHtmlMode) {
|
|
55
|
+
if (isEdited) {
|
|
56
|
+
handleHtmlModeOn(value, onChange);
|
|
57
|
+
} else {
|
|
58
|
+
toggleToRichText(value, onChange);
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
handleHtmlModeOff(value, onChange);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
toggleHtmlMode();
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import LinearProgress from '@material-ui/core/LinearProgress';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import React from 'react';
|
|
3
4
|
import classNames from 'classnames';
|
|
4
5
|
import debug from 'debug';
|
|
5
|
-
import isEqual from 'lodash/isEqual';
|
|
6
|
-
import cloneDeep from 'lodash/cloneDeep';
|
|
7
|
-
import LinearProgress from '@material-ui/core/LinearProgress';
|
|
8
6
|
import { withStyles } from '@material-ui/core/styles';
|
|
9
|
-
import
|
|
7
|
+
import SlatePropTypes from 'slate-prop-types';
|
|
10
8
|
|
|
11
9
|
const log = debug('@pie-lib:editable-html:plugins:image:component');
|
|
12
10
|
|
|
@@ -14,12 +12,7 @@ const size = (s) => (s ? `${s}px` : 'auto');
|
|
|
14
12
|
|
|
15
13
|
export class Component extends React.Component {
|
|
16
14
|
static propTypes = {
|
|
17
|
-
node:
|
|
18
|
-
type: PropTypes.string,
|
|
19
|
-
children: PropTypes.array,
|
|
20
|
-
data: PropTypes.object
|
|
21
|
-
}).isRequired,
|
|
22
|
-
focused: PropTypes.bool,
|
|
15
|
+
node: SlatePropTypes.node.isRequired,
|
|
23
16
|
editor: PropTypes.shape({
|
|
24
17
|
change: PropTypes.func.isRequired,
|
|
25
18
|
value: PropTypes.object,
|
|
@@ -50,27 +43,17 @@ export class Component extends React.Component {
|
|
|
50
43
|
applySizeData = () => {
|
|
51
44
|
const { node, editor } = this.props;
|
|
52
45
|
|
|
53
|
-
let update =
|
|
54
|
-
|
|
55
|
-
const w = update.width;
|
|
46
|
+
let update = node.data;
|
|
56
47
|
|
|
48
|
+
const w = update.get('width');
|
|
57
49
|
if (w) {
|
|
58
|
-
update = update.resizePercent
|
|
50
|
+
update = update.set('resizePercent', this.getPercentFromWidth(w));
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
log('[applySizeData] update: ', update);
|
|
62
54
|
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
editor.apply({
|
|
67
|
-
type: 'set_node',
|
|
68
|
-
path: nodePath,
|
|
69
|
-
properties: {
|
|
70
|
-
data: node.data
|
|
71
|
-
},
|
|
72
|
-
newProperties: { data: update }
|
|
73
|
-
});
|
|
55
|
+
if (!update.equals(node.data)) {
|
|
56
|
+
editor.change((c) => c.setNodeByKey(node.key, { data: update }));
|
|
74
57
|
}
|
|
75
58
|
};
|
|
76
59
|
|
|
@@ -95,8 +78,8 @@ export class Component extends React.Component {
|
|
|
95
78
|
|
|
96
79
|
getSize(data) {
|
|
97
80
|
return {
|
|
98
|
-
width: size(data.width),
|
|
99
|
-
height: size(data.height),
|
|
81
|
+
width: size(data.get('width')),
|
|
82
|
+
height: size(data.get('height')),
|
|
100
83
|
objectFit: 'contain',
|
|
101
84
|
};
|
|
102
85
|
}
|
|
@@ -133,22 +116,13 @@ export class Component extends React.Component {
|
|
|
133
116
|
|
|
134
117
|
const { node, editor } = this.props;
|
|
135
118
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
update.width = width;
|
|
139
|
-
update.height = height;
|
|
119
|
+
let update = node.data;
|
|
140
120
|
|
|
141
|
-
|
|
142
|
-
|
|
121
|
+
update = update.set('width', width);
|
|
122
|
+
update = update.set('height', height);
|
|
143
123
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
path: nodePath,
|
|
147
|
-
properties: {
|
|
148
|
-
data: node.data,
|
|
149
|
-
},
|
|
150
|
-
newProperties: { data: update },
|
|
151
|
-
});
|
|
124
|
+
if (!update.equals(node.data)) {
|
|
125
|
+
editor.change((c) => c.setNodeByKey(node.key, { data: update }));
|
|
152
126
|
}
|
|
153
127
|
}
|
|
154
128
|
};
|
|
@@ -227,10 +201,14 @@ export class Component extends React.Component {
|
|
|
227
201
|
};
|
|
228
202
|
|
|
229
203
|
render() {
|
|
230
|
-
const { node,
|
|
231
|
-
const active =
|
|
232
|
-
const
|
|
233
|
-
const
|
|
204
|
+
const { node, editor, classes, attributes, onFocus } = this.props;
|
|
205
|
+
const active = editor.value.isFocused && editor.value.selection.hasEdgeIn(node);
|
|
206
|
+
const src = node.data.get('src');
|
|
207
|
+
const loaded = node.data.get('loaded') !== false;
|
|
208
|
+
const deleteStatus = node.data.get('deleteStatus');
|
|
209
|
+
const alignment = node.data.get('alignment');
|
|
210
|
+
const percent = node.data.get('percent');
|
|
211
|
+
const alt = node.data.get('alt');
|
|
234
212
|
let justifyContent;
|
|
235
213
|
|
|
236
214
|
switch (alignment) {
|
|
@@ -256,26 +234,22 @@ export class Component extends React.Component {
|
|
|
256
234
|
|
|
257
235
|
log('[render] style:', size);
|
|
258
236
|
|
|
259
|
-
const className = classNames(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
<div onFocus={onFocus} className={className} style={{ justifyContent }}
|
|
270
|
-
{
|
|
271
|
-
<LinearProgress
|
|
272
|
-
mode="determinate"
|
|
273
|
-
value={percent > 0 ? percent : 0}
|
|
274
|
-
className={progressClasses}
|
|
275
|
-
/>
|
|
237
|
+
const className = classNames(
|
|
238
|
+
classes.root,
|
|
239
|
+
!loaded && classes.loading,
|
|
240
|
+
deleteStatus === 'pending' && classes.pendingDelete,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const progressClasses = classNames(classes.progress, loaded && classes.hideProgress);
|
|
244
|
+
|
|
245
|
+
return [
|
|
246
|
+
<span key={'sp1'}> </span>,
|
|
247
|
+
<div key={'comp'} onFocus={onFocus} className={className} style={{ justifyContent }}>
|
|
248
|
+
<LinearProgress mode="determinate" value={percent > 0 ? percent : 0} className={progressClasses} />
|
|
276
249
|
<div className={classes.imageContainer}>
|
|
277
250
|
<img
|
|
278
|
-
|
|
251
|
+
{...attributes}
|
|
252
|
+
className={classNames(classes.image, active && classes.active)}
|
|
279
253
|
ref={(ref) => {
|
|
280
254
|
this.img = ref;
|
|
281
255
|
}}
|
|
@@ -291,8 +265,9 @@ export class Component extends React.Component {
|
|
|
291
265
|
className={classNames(classes.resize, 'resize')}
|
|
292
266
|
/>
|
|
293
267
|
</div>
|
|
294
|
-
</div
|
|
295
|
-
|
|
268
|
+
</div>,
|
|
269
|
+
<span key={'sp2'}> </span>,
|
|
270
|
+
];
|
|
296
271
|
}
|
|
297
272
|
}
|
|
298
273
|
|
|
@@ -332,7 +307,6 @@ const styles = (theme) => ({
|
|
|
332
307
|
border: `solid 1px ${theme.palette.common.white}`,
|
|
333
308
|
display: 'flex',
|
|
334
309
|
transition: 'opacity 200ms linear',
|
|
335
|
-
width: '100%',
|
|
336
310
|
},
|
|
337
311
|
delete: {
|
|
338
312
|
position: 'absolute',
|