slate-react 0.57.2 → 0.57.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/dist/components/editable.d.ts.map +1 -1
- package/dist/components/slate.d.ts.map +1 -1
- package/dist/index.es.js +146 -140
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +145 -139
- package/dist/index.js.map +1 -1
- package/dist/plugin/react-editor.d.ts +5 -0
- package/dist/plugin/react-editor.d.ts.map +1 -1
- package/dist/plugin/with-react.d.ts.map +1 -1
- package/dist/slate-react.js +159 -144
- package/dist/slate-react.min.js +1 -1
- package/dist/utils/dom.d.ts +7 -0
- package/dist/utils/dom.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -216,6 +216,34 @@ var getEditableChild = (parent, index, direction) => {
|
|
|
216
216
|
|
|
217
217
|
return child;
|
|
218
218
|
};
|
|
219
|
+
/**
|
|
220
|
+
* Get a plaintext representation of the content of a node, accounting for block
|
|
221
|
+
* elements which get a newline appended.
|
|
222
|
+
*
|
|
223
|
+
* The domNode must be attached to the DOM.
|
|
224
|
+
*/
|
|
225
|
+
|
|
226
|
+
var getPlainText = domNode => {
|
|
227
|
+
var text = '';
|
|
228
|
+
|
|
229
|
+
if (isDOMText(domNode) && domNode.nodeValue) {
|
|
230
|
+
return domNode.nodeValue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (isDOMElement(domNode)) {
|
|
234
|
+
for (var childNode of Array.from(domNode.childNodes)) {
|
|
235
|
+
text += getPlainText(childNode);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
var display = getComputedStyle(domNode).getPropertyValue('display');
|
|
239
|
+
|
|
240
|
+
if (display === 'block' || display === 'list' || domNode.tagName === 'BR') {
|
|
241
|
+
text += '\n';
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return text;
|
|
246
|
+
};
|
|
219
247
|
|
|
220
248
|
var ReactEditor = {
|
|
221
249
|
/**
|
|
@@ -357,6 +385,13 @@ var ReactEditor = {
|
|
|
357
385
|
editor.insertData(data);
|
|
358
386
|
},
|
|
359
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Sets data from the currently selected fragment on a `DataTransfer`.
|
|
390
|
+
*/
|
|
391
|
+
setFragmentData(editor, data) {
|
|
392
|
+
editor.setFragmentData(data);
|
|
393
|
+
},
|
|
394
|
+
|
|
360
395
|
/**
|
|
361
396
|
* Find the native DOM element from a Slate node.
|
|
362
397
|
*/
|
|
@@ -433,13 +468,21 @@ var ReactEditor = {
|
|
|
433
468
|
anchor,
|
|
434
469
|
focus
|
|
435
470
|
} = range;
|
|
471
|
+
var isBackward = slate.Range.isBackward(range);
|
|
436
472
|
var domAnchor = ReactEditor.toDOMPoint(editor, anchor);
|
|
437
473
|
var domFocus = slate.Range.isCollapsed(range) ? domAnchor : ReactEditor.toDOMPoint(editor, focus);
|
|
438
474
|
var domRange = window.document.createRange();
|
|
439
|
-
var
|
|
440
|
-
var
|
|
441
|
-
|
|
442
|
-
|
|
475
|
+
var [startNode, startOffset] = isBackward ? domFocus : domAnchor;
|
|
476
|
+
var [endNode, endOffset] = isBackward ? domAnchor : domFocus; // A slate Point at zero-width Leaf always has an offset of 0 but a native DOM selection at
|
|
477
|
+
// zero-width node has an offset of 1 so we have to check if we are in a zero-width node and
|
|
478
|
+
// adjust the offset accordingly.
|
|
479
|
+
|
|
480
|
+
var startEl = isDOMElement(startNode) ? startNode : startNode.parentElement;
|
|
481
|
+
var isStartAtZeroWidth = !!startEl.getAttribute('data-slate-zero-width');
|
|
482
|
+
var endEl = isDOMElement(endNode) ? endNode : endNode.parentElement;
|
|
483
|
+
var isEndAtZeroWidth = !!endEl.getAttribute('data-slate-zero-width');
|
|
484
|
+
domRange.setStart(startNode, isStartAtZeroWidth ? 1 : startOffset);
|
|
485
|
+
domRange.setEnd(endNode, isEndAtZeroWidth ? 1 : endOffset);
|
|
443
486
|
return domRange;
|
|
444
487
|
},
|
|
445
488
|
|
|
@@ -712,6 +755,11 @@ var Slate = props => {
|
|
|
712
755
|
setKey(key + 1);
|
|
713
756
|
}, [key, onChange]);
|
|
714
757
|
EDITOR_TO_ON_CHANGE.set(editor, onContextChange);
|
|
758
|
+
React.useEffect(() => {
|
|
759
|
+
return () => {
|
|
760
|
+
EDITOR_TO_ON_CHANGE.set(editor, () => {});
|
|
761
|
+
};
|
|
762
|
+
}, []);
|
|
715
763
|
return React__default.createElement(SlateContext.Provider, {
|
|
716
764
|
value: context
|
|
717
765
|
}, React__default.createElement(EditorContext.Provider, {
|
|
@@ -801,6 +849,91 @@ var withReact = editor => {
|
|
|
801
849
|
}
|
|
802
850
|
};
|
|
803
851
|
|
|
852
|
+
e.setFragmentData = data => {
|
|
853
|
+
var {
|
|
854
|
+
selection
|
|
855
|
+
} = e;
|
|
856
|
+
|
|
857
|
+
if (!selection) {
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
var [start, end] = slate.Range.edges(selection);
|
|
862
|
+
var startVoid = slate.Editor.void(e, {
|
|
863
|
+
at: start.path
|
|
864
|
+
});
|
|
865
|
+
var endVoid = slate.Editor.void(e, {
|
|
866
|
+
at: end.path
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
if (slate.Range.isCollapsed(selection) && !startVoid) {
|
|
870
|
+
return;
|
|
871
|
+
} // Create a fake selection so that we can add a Base64-encoded copy of the
|
|
872
|
+
// fragment to the HTML, to decode on future pastes.
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
var domRange = ReactEditor.toDOMRange(e, selection);
|
|
876
|
+
var contents = domRange.cloneContents();
|
|
877
|
+
var attach = contents.childNodes[0]; // Make sure attach is non-empty, since empty nodes will not get copied.
|
|
878
|
+
|
|
879
|
+
contents.childNodes.forEach(node => {
|
|
880
|
+
if (node.textContent && node.textContent.trim() !== '') {
|
|
881
|
+
attach = node;
|
|
882
|
+
}
|
|
883
|
+
}); // COMPAT: If the end node is a void node, we need to move the end of the
|
|
884
|
+
// range from the void node's spacer span, to the end of the void node's
|
|
885
|
+
// content, since the spacer is before void's content in the DOM.
|
|
886
|
+
|
|
887
|
+
if (endVoid) {
|
|
888
|
+
var [voidNode] = endVoid;
|
|
889
|
+
var r = domRange.cloneRange();
|
|
890
|
+
var domNode = ReactEditor.toDOMNode(e, voidNode);
|
|
891
|
+
r.setEndAfter(domNode);
|
|
892
|
+
contents = r.cloneContents();
|
|
893
|
+
} // COMPAT: If the start node is a void node, we need to attach the encoded
|
|
894
|
+
// fragment to the void node's content node instead of the spacer, because
|
|
895
|
+
// attaching it to empty `<div>/<span>` nodes will end up having it erased by
|
|
896
|
+
// most browsers. (2018/04/27)
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
if (startVoid) {
|
|
900
|
+
attach = contents.querySelector('[data-slate-spacer]');
|
|
901
|
+
} // Remove any zero-width space spans from the cloned DOM so that they don't
|
|
902
|
+
// show up elsewhere when pasted.
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
Array.from(contents.querySelectorAll('[data-slate-zero-width]')).forEach(zw => {
|
|
906
|
+
var isNewline = zw.getAttribute('data-slate-zero-width') === 'n';
|
|
907
|
+
zw.textContent = isNewline ? '\n' : '';
|
|
908
|
+
}); // Set a `data-slate-fragment` attribute on a non-empty node, so it shows up
|
|
909
|
+
// in the HTML, and can be used for intra-Slate pasting. If it's a text
|
|
910
|
+
// node, wrap it in a `<span>` so we have something to set an attribute on.
|
|
911
|
+
|
|
912
|
+
if (isDOMText(attach)) {
|
|
913
|
+
var span = document.createElement('span'); // COMPAT: In Chrome and Safari, if we don't add the `white-space` style
|
|
914
|
+
// then leading and trailing spaces will be ignored. (2017/09/21)
|
|
915
|
+
|
|
916
|
+
span.style.whiteSpace = 'pre';
|
|
917
|
+
span.appendChild(attach);
|
|
918
|
+
contents.appendChild(span);
|
|
919
|
+
attach = span;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
var fragment = e.getFragment();
|
|
923
|
+
var string = JSON.stringify(fragment);
|
|
924
|
+
var encoded = window.btoa(encodeURIComponent(string));
|
|
925
|
+
attach.setAttribute('data-slate-fragment', encoded);
|
|
926
|
+
data.setData('application/x-slate-fragment', encoded); // Add the content to a <div> so that we can get its inner HTML.
|
|
927
|
+
|
|
928
|
+
var div = document.createElement('div');
|
|
929
|
+
div.appendChild(contents);
|
|
930
|
+
div.setAttribute('hidden', 'true');
|
|
931
|
+
document.body.appendChild(div);
|
|
932
|
+
data.setData('text/html', div.innerHTML);
|
|
933
|
+
data.setData('text/plain', getPlainText(div));
|
|
934
|
+
document.body.removeChild(div);
|
|
935
|
+
};
|
|
936
|
+
|
|
804
937
|
e.insertData = data => {
|
|
805
938
|
var fragment = data.getData('application/x-slate-fragment');
|
|
806
939
|
|
|
@@ -1408,11 +1541,10 @@ var Editable = props => {
|
|
|
1408
1541
|
|
|
1409
1542
|
if (!selection && !hasDomSelection) {
|
|
1410
1543
|
return;
|
|
1411
|
-
}
|
|
1544
|
+
} // If the DOM selection is already correct, we're done.
|
|
1412
1545
|
|
|
1413
|
-
var newDomRange = selection && ReactEditor.toDOMRange(editor, selection); // If the DOM selection is already correct, we're done.
|
|
1414
1546
|
|
|
1415
|
-
if (hasDomSelection &&
|
|
1547
|
+
if (hasDomSelection && selection && slate.Range.equals(ReactEditor.toSlateRange(editor, domSelection), selection)) {
|
|
1416
1548
|
return;
|
|
1417
1549
|
} // Otherwise the DOM selection is out of sync, so update it.
|
|
1418
1550
|
|
|
@@ -1420,6 +1552,7 @@ var Editable = props => {
|
|
|
1420
1552
|
var el = ReactEditor.toDOMNode(editor, editor);
|
|
1421
1553
|
state.isUpdatingSelection = true;
|
|
1422
1554
|
domSelection.removeAllRanges();
|
|
1555
|
+
var newDomRange = selection && ReactEditor.toDOMRange(editor, selection);
|
|
1423
1556
|
|
|
1424
1557
|
if (newDomRange) {
|
|
1425
1558
|
domSelection.addRange(newDomRange);
|
|
@@ -1623,7 +1756,6 @@ var Editable = props => {
|
|
|
1623
1756
|
} = window.document;
|
|
1624
1757
|
var el = ReactEditor.toDOMNode(editor, editor);
|
|
1625
1758
|
var domSelection = window.getSelection();
|
|
1626
|
-
var domRange = domSelection && domSelection.rangeCount > 0 && domSelection.getRangeAt(0);
|
|
1627
1759
|
|
|
1628
1760
|
if (activeElement === el) {
|
|
1629
1761
|
state.latestElement = activeElement;
|
|
@@ -1632,8 +1764,8 @@ var Editable = props => {
|
|
|
1632
1764
|
IS_FOCUSED.delete(editor);
|
|
1633
1765
|
}
|
|
1634
1766
|
|
|
1635
|
-
if (
|
|
1636
|
-
var range = ReactEditor.toSlateRange(editor,
|
|
1767
|
+
if (domSelection && hasEditableTarget(editor, domSelection.anchorNode) && hasEditableTarget(editor, domSelection.focusNode)) {
|
|
1768
|
+
var range = ReactEditor.toSlateRange(editor, domSelection);
|
|
1637
1769
|
slate.Transforms.select(editor, range);
|
|
1638
1770
|
} else {
|
|
1639
1771
|
slate.Transforms.deselect(editor);
|
|
@@ -1778,13 +1910,13 @@ var Editable = props => {
|
|
|
1778
1910
|
onCopy: React.useCallback(event => {
|
|
1779
1911
|
if (hasEditableTarget(editor, event.target) && !isEventHandled(event, attributes.onCopy)) {
|
|
1780
1912
|
event.preventDefault();
|
|
1781
|
-
setFragmentData(event.clipboardData
|
|
1913
|
+
ReactEditor.setFragmentData(editor, event.clipboardData);
|
|
1782
1914
|
}
|
|
1783
1915
|
}, [attributes.onCopy]),
|
|
1784
1916
|
onCut: React.useCallback(event => {
|
|
1785
1917
|
if (!readOnly && hasEditableTarget(editor, event.target) && !isEventHandled(event, attributes.onCut)) {
|
|
1786
1918
|
event.preventDefault();
|
|
1787
|
-
setFragmentData(event.clipboardData
|
|
1919
|
+
ReactEditor.setFragmentData(editor, event.clipboardData);
|
|
1788
1920
|
var {
|
|
1789
1921
|
selection
|
|
1790
1922
|
} = editor;
|
|
@@ -1820,7 +1952,7 @@ var Editable = props => {
|
|
|
1820
1952
|
slate.Transforms.select(editor, range);
|
|
1821
1953
|
}
|
|
1822
1954
|
|
|
1823
|
-
setFragmentData(event.dataTransfer
|
|
1955
|
+
ReactEditor.setFragmentData(editor, event.dataTransfer);
|
|
1824
1956
|
}
|
|
1825
1957
|
}, [attributes.onDragStart]),
|
|
1826
1958
|
onDrop: React.useCallback(event => {
|
|
@@ -2101,14 +2233,6 @@ var Editable = props => {
|
|
|
2101
2233
|
*/
|
|
2102
2234
|
|
|
2103
2235
|
var defaultDecorate = () => [];
|
|
2104
|
-
/**
|
|
2105
|
-
* Check if two DOM range objects are equal.
|
|
2106
|
-
*/
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
var isRangeEqual = (a, b) => {
|
|
2110
|
-
return a.startContainer === b.startContainer && a.startOffset === b.startOffset && a.endContainer === b.endContainer && a.endOffset === b.endOffset || a.startContainer === b.endContainer && a.startOffset === b.endOffset && a.endContainer === b.startContainer && a.endOffset === b.startOffset;
|
|
2111
|
-
};
|
|
2112
2236
|
/**
|
|
2113
2237
|
* Check if the target is in the editor.
|
|
2114
2238
|
*/
|
|
@@ -2153,124 +2277,6 @@ var isDOMEventHandled = (event, handler) => {
|
|
|
2153
2277
|
handler(event);
|
|
2154
2278
|
return event.defaultPrevented;
|
|
2155
2279
|
};
|
|
2156
|
-
/**
|
|
2157
|
-
* Set the currently selected fragment to the clipboard.
|
|
2158
|
-
*/
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
var setFragmentData = (dataTransfer, editor) => {
|
|
2162
|
-
var {
|
|
2163
|
-
selection
|
|
2164
|
-
} = editor;
|
|
2165
|
-
|
|
2166
|
-
if (!selection) {
|
|
2167
|
-
return;
|
|
2168
|
-
}
|
|
2169
|
-
|
|
2170
|
-
var [start, end] = slate.Range.edges(selection);
|
|
2171
|
-
var startVoid = slate.Editor.void(editor, {
|
|
2172
|
-
at: start.path
|
|
2173
|
-
});
|
|
2174
|
-
var endVoid = slate.Editor.void(editor, {
|
|
2175
|
-
at: end.path
|
|
2176
|
-
});
|
|
2177
|
-
|
|
2178
|
-
if (slate.Range.isCollapsed(selection) && !startVoid) {
|
|
2179
|
-
return;
|
|
2180
|
-
} // Create a fake selection so that we can add a Base64-encoded copy of the
|
|
2181
|
-
// fragment to the HTML, to decode on future pastes.
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
var domRange = ReactEditor.toDOMRange(editor, selection);
|
|
2185
|
-
var contents = domRange.cloneContents();
|
|
2186
|
-
var attach = contents.childNodes[0]; // Make sure attach is non-empty, since empty nodes will not get copied.
|
|
2187
|
-
|
|
2188
|
-
contents.childNodes.forEach(node => {
|
|
2189
|
-
if (node.textContent && node.textContent.trim() !== '') {
|
|
2190
|
-
attach = node;
|
|
2191
|
-
}
|
|
2192
|
-
}); // COMPAT: If the end node is a void node, we need to move the end of the
|
|
2193
|
-
// range from the void node's spacer span, to the end of the void node's
|
|
2194
|
-
// content, since the spacer is before void's content in the DOM.
|
|
2195
|
-
|
|
2196
|
-
if (endVoid) {
|
|
2197
|
-
var [voidNode] = endVoid;
|
|
2198
|
-
var r = domRange.cloneRange();
|
|
2199
|
-
var domNode = ReactEditor.toDOMNode(editor, voidNode);
|
|
2200
|
-
r.setEndAfter(domNode);
|
|
2201
|
-
contents = r.cloneContents();
|
|
2202
|
-
} // COMPAT: If the start node is a void node, we need to attach the encoded
|
|
2203
|
-
// fragment to the void node's content node instead of the spacer, because
|
|
2204
|
-
// attaching it to empty `<div>/<span>` nodes will end up having it erased by
|
|
2205
|
-
// most browsers. (2018/04/27)
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
if (startVoid) {
|
|
2209
|
-
attach = contents.querySelector('[data-slate-spacer]');
|
|
2210
|
-
} // Remove any zero-width space spans from the cloned DOM so that they don't
|
|
2211
|
-
// show up elsewhere when pasted.
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
Array.from(contents.querySelectorAll('[data-slate-zero-width]')).forEach(zw => {
|
|
2215
|
-
var isNewline = zw.getAttribute('data-slate-zero-width') === 'n';
|
|
2216
|
-
zw.textContent = isNewline ? '\n' : '';
|
|
2217
|
-
}); // Set a `data-slate-fragment` attribute on a non-empty node, so it shows up
|
|
2218
|
-
// in the HTML, and can be used for intra-Slate pasting. If it's a text
|
|
2219
|
-
// node, wrap it in a `<span>` so we have something to set an attribute on.
|
|
2220
|
-
|
|
2221
|
-
if (isDOMText(attach)) {
|
|
2222
|
-
var span = document.createElement('span'); // COMPAT: In Chrome and Safari, if we don't add the `white-space` style
|
|
2223
|
-
// then leading and trailing spaces will be ignored. (2017/09/21)
|
|
2224
|
-
|
|
2225
|
-
span.style.whiteSpace = 'pre';
|
|
2226
|
-
span.appendChild(attach);
|
|
2227
|
-
contents.appendChild(span);
|
|
2228
|
-
attach = span;
|
|
2229
|
-
}
|
|
2230
|
-
|
|
2231
|
-
var fragment = slate.Node.fragment(editor, selection);
|
|
2232
|
-
var string = JSON.stringify(fragment);
|
|
2233
|
-
var encoded = window.btoa(encodeURIComponent(string));
|
|
2234
|
-
attach.setAttribute('data-slate-fragment', encoded);
|
|
2235
|
-
dataTransfer.setData('application/x-slate-fragment', encoded); // Add the content to a <div> so that we can get its inner HTML.
|
|
2236
|
-
|
|
2237
|
-
var div = document.createElement('div');
|
|
2238
|
-
div.appendChild(contents);
|
|
2239
|
-
div.setAttribute('hidden', 'true');
|
|
2240
|
-
document.body.appendChild(div);
|
|
2241
|
-
dataTransfer.setData('text/html', div.innerHTML);
|
|
2242
|
-
dataTransfer.setData('text/plain', getPlainText(div));
|
|
2243
|
-
document.body.removeChild(div);
|
|
2244
|
-
};
|
|
2245
|
-
/**
|
|
2246
|
-
* Get a plaintext representation of the content of a node, accounting for block
|
|
2247
|
-
* elements which get a newline appended.
|
|
2248
|
-
*
|
|
2249
|
-
* The domNode must be attached to the DOM.
|
|
2250
|
-
*/
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
var getPlainText = domNode => {
|
|
2254
|
-
var text = '';
|
|
2255
|
-
|
|
2256
|
-
if (isDOMText(domNode) && domNode.nodeValue) {
|
|
2257
|
-
return domNode.nodeValue;
|
|
2258
|
-
}
|
|
2259
|
-
|
|
2260
|
-
if (isDOMElement(domNode)) {
|
|
2261
|
-
for (var childNode of Array.from(domNode.childNodes)) {
|
|
2262
|
-
text += getPlainText(childNode);
|
|
2263
|
-
}
|
|
2264
|
-
|
|
2265
|
-
var display = getComputedStyle(domNode).getPropertyValue('display');
|
|
2266
|
-
|
|
2267
|
-
if (display === 'block' || display === 'list' || domNode.tagName === 'BR') {
|
|
2268
|
-
text += '\n';
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2271
|
-
|
|
2272
|
-
return text;
|
|
2273
|
-
};
|
|
2274
2280
|
|
|
2275
2281
|
exports.DefaultElement = DefaultElement;
|
|
2276
2282
|
exports.DefaultLeaf = DefaultLeaf;
|