@contentful/field-editor-rich-text 2.0.0-next.28 → 2.0.0-next.30
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/field-editor-rich-text.cjs.development.js +427 -144
- package/dist/field-editor-rich-text.cjs.development.js.map +1 -1
- package/dist/field-editor-rich-text.cjs.production.min.js +1 -1
- package/dist/field-editor-rich-text.cjs.production.min.js.map +1 -1
- package/dist/field-editor-rich-text.esm.js +431 -148
- package/dist/field-editor-rich-text.esm.js.map +1 -1
- package/dist/plugins/SlashCommands/SlashCommandsPalette.d.ts +5 -0
- package/dist/plugins/SlashCommands/createSlashCommandsPlugin.d.ts +2 -0
- package/dist/plugins/SlashCommands/helpers.d.ts +6 -0
- package/dist/plugins/SlashCommands/index.d.ts +2 -0
- package/dist/plugins/Table/insertTableFragment.d.ts +3 -0
- package/dist/plugins/Table/onKeyDownTable.d.ts +3 -0
- package/dist/plugins/Tracking/createTrackingPlugin.d.ts +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import React__default, { createContext, useContext, useMemo, createElement, useE
|
|
|
2
2
|
import { useEntities, ScheduledIconWithTooltip, MissingEntityCard, AssetThumbnail, EntityProvider, getScheduleTooltipContent } from '@contentful/field-editor-reference';
|
|
3
3
|
import { entityHelpers, shortenStorageUnit, isValidImage, ModalDialogLauncher, FieldConnector } from '@contentful/field-editor-shared';
|
|
4
4
|
import { BLOCKS, INLINES, TEXT_CONTAINERS, HEADINGS, LIST_ITEM_BLOCKS, MARKS, CONTAINERS, TOP_LEVEL_BLOCKS, VOID_BLOCKS, EMPTY_DOCUMENT } from '@contentful/rich-text-types';
|
|
5
|
-
import { usePlateEditorRef, usePlateEditorState, getNodes, toggleNodeType, getText, getAbove, setNodes, isAncestorEmpty, match, getLastChildPath, wrapNodes, getPluginType, unwrapNodes, isCollapsed, isRangeAcrossBlocks, ELEMENT_DEFAULT, findNode, getParent, getBlockAbove, isSelectionAtBlockStart, isSelectionAtBlockEnd, isFirstChild, insertNodes, moveChildren, isBlockAboveEmpty, mockPlugin, deleteFragment, isMarkActive, toggleMark, someHtmlElement, KEY_DESERIALIZE_HTML, hasSingleChild, isLastChild,
|
|
5
|
+
import { usePlateEditorRef, usePlateEditorState, getNodes, toggleNodeType, getText, getAbove, setNodes, isAncestorEmpty, match, getLastChildPath, wrapNodes, getPluginType, unwrapNodes, isCollapsed, isRangeAcrossBlocks, ELEMENT_DEFAULT, findNode, getParent, getBlockAbove, isSelectionAtBlockStart, isSelectionAtBlockEnd, isFirstChild, insertNodes, moveChildren, isBlockAboveEmpty, mockPlugin, deleteFragment, isMarkActive, toggleMark, someHtmlElement, KEY_DESERIALIZE_HTML, hasSingleChild, isLastChild, getChildren as getChildren$1, someNode, createDeserializeHtmlPlugin, createDeserializeAstPlugin, createPlateEditor, getPlateSelectors, getPlateActions, Plate } from '@udecode/plate-core';
|
|
6
6
|
import { css, cx } from 'emotion';
|
|
7
7
|
import deepEquals from 'fast-deep-equal';
|
|
8
8
|
import noop from 'lodash-es/noop';
|
|
@@ -13,7 +13,7 @@ import isHotkey from 'is-hotkey';
|
|
|
13
13
|
import { Text, Element, Editor, Transforms, Range, Path, Node, Point } from 'slate';
|
|
14
14
|
import { ReactEditor, useSelected, useReadOnly, useFocused } from 'slate-react';
|
|
15
15
|
import constate from 'constate';
|
|
16
|
-
import { AssetCard, Menu, Text as Text$1, Notification, EntryCard, MenuItem, Button, Flex, Icon, InlineEntryCard, Tooltip, ModalContent, Form, FormControl, TextInput, Select, FormLabel, TextLink, ModalControls, IconButton } from '@contentful/f36-components';
|
|
16
|
+
import { AssetCard, Menu, Text as Text$1, Notification, EntryCard, MenuItem, Button, Flex, Icon, InlineEntryCard, Tooltip, ModalContent, Form, FormControl, TextInput, Select, FormLabel, TextLink, ModalControls, Card, IconButton } from '@contentful/f36-components';
|
|
17
17
|
import mimetype from '@contentful/mimetype';
|
|
18
18
|
import get from 'lodash-es/get';
|
|
19
19
|
import { ClockIcon, AssetIcon, EmbeddedEntryBlockIcon, EmbeddedEntryInlineIcon, ChevronDownIcon, HorizontalRuleIcon, LinkIcon, ListBulletedIcon, ListNumberedIcon, FormatBoldIcon, CodeIcon, FormatItalicIcon, FormatUnderlinedIcon, QuoteIcon, TableIcon, PlusIcon } from '@contentful/f36-icons';
|
|
@@ -26,7 +26,7 @@ import { createBoldPlugin as createBoldPlugin$1, createCodePlugin as createCodeP
|
|
|
26
26
|
import isPlainObject from 'is-plain-obj';
|
|
27
27
|
import { createParagraphPlugin as createParagraphPlugin$1 } from '@udecode/plate-paragraph';
|
|
28
28
|
import { createSelectOnBackspacePlugin as createSelectOnBackspacePlugin$1 } from '@udecode/plate-select';
|
|
29
|
-
import { ELEMENT_TABLE,
|
|
29
|
+
import { ELEMENT_TABLE, ELEMENT_TH, ELEMENT_TR, ELEMENT_TD, insertTable, getEmptyRowNode, getEmptyCellNode, deleteRow, deleteColumn, deleteTable, onKeyDownTable as onKeyDownTable$1, getTableCellEntry, createTablePlugin as createTablePlugin$1, withTable } from '@udecode/plate-table';
|
|
30
30
|
import { toContentfulDocument, toSlatejsDocument } from '@contentful/contentful-slatejs-adapter';
|
|
31
31
|
import { documentToPlainTextString } from '@contentful/rich-text-plain-text-renderer';
|
|
32
32
|
import { createTrailingBlockPlugin } from '@udecode/plate-trailing-block';
|
|
@@ -5442,6 +5442,295 @@ var createSelectOnBackspacePlugin = function createSelectOnBackspacePlugin() {
|
|
|
5442
5442
|
});
|
|
5443
5443
|
};
|
|
5444
5444
|
|
|
5445
|
+
function getCaretTopPoint() {
|
|
5446
|
+
var sel = document.getSelection();
|
|
5447
|
+
if (!sel) return;
|
|
5448
|
+
var r = sel.getRangeAt(0);
|
|
5449
|
+
var rect;
|
|
5450
|
+
var r2; // supposed to be textNode in most cases
|
|
5451
|
+
// but div[contenteditable] when empty
|
|
5452
|
+
|
|
5453
|
+
var node = r.startContainer;
|
|
5454
|
+
var offset = r.startOffset;
|
|
5455
|
+
|
|
5456
|
+
if (offset > 0) {
|
|
5457
|
+
// new range, don't influence DOM state
|
|
5458
|
+
r2 = document.createRange();
|
|
5459
|
+
r2.setStart(node, offset - 1);
|
|
5460
|
+
r2.setEnd(node, offset); // https://developer.mozilla.org/en-US/docs/Web/API/range.getBoundingClientRect
|
|
5461
|
+
// IE9, Safari?(but look good in Safari 8)
|
|
5462
|
+
|
|
5463
|
+
rect = r2.getBoundingClientRect();
|
|
5464
|
+
return {
|
|
5465
|
+
left: rect.right,
|
|
5466
|
+
top: rect.top
|
|
5467
|
+
}; // @ts-expect-error
|
|
5468
|
+
} else if (offset < node.length) {
|
|
5469
|
+
r2 = document.createRange(); // similar but select next on letter
|
|
5470
|
+
|
|
5471
|
+
r2.setStart(node, offset);
|
|
5472
|
+
r2.setEnd(node, offset + 1);
|
|
5473
|
+
rect = r2.getBoundingClientRect();
|
|
5474
|
+
return {
|
|
5475
|
+
left: rect.left,
|
|
5476
|
+
top: rect.top
|
|
5477
|
+
};
|
|
5478
|
+
} else {
|
|
5479
|
+
// textNode has length
|
|
5480
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect
|
|
5481
|
+
// @ts-expect-error
|
|
5482
|
+
rect = node.getBoundingClientRect(); // @ts-expect-error
|
|
5483
|
+
|
|
5484
|
+
var styles = getComputedStyle(node);
|
|
5485
|
+
var lineHeight = parseInt(styles.lineHeight);
|
|
5486
|
+
var fontSize = parseInt(styles.fontSize); // roughly half the whitespace... but not exactly
|
|
5487
|
+
|
|
5488
|
+
var delta = (lineHeight - fontSize) / 2;
|
|
5489
|
+
return {
|
|
5490
|
+
left: rect.left,
|
|
5491
|
+
top: rect.top + delta
|
|
5492
|
+
};
|
|
5493
|
+
}
|
|
5494
|
+
}
|
|
5495
|
+
function closePanel(editorId) {
|
|
5496
|
+
document.dispatchEvent(new CustomEvent('close-rte-palette-commands', {
|
|
5497
|
+
detail: {
|
|
5498
|
+
editorId: editorId
|
|
5499
|
+
}
|
|
5500
|
+
}));
|
|
5501
|
+
}
|
|
5502
|
+
function openPanel(editorId) {
|
|
5503
|
+
document.dispatchEvent(new CustomEvent('open-rte-palette-commands', {
|
|
5504
|
+
detail: {
|
|
5505
|
+
editorId: editorId
|
|
5506
|
+
}
|
|
5507
|
+
}));
|
|
5508
|
+
}
|
|
5509
|
+
|
|
5510
|
+
// import debounce from 'lodash/debounce';
|
|
5511
|
+
var SLASH_COMMANDS_PLUGIN_KEY = 'SlashCommands'; // TODO: Explore a solution using marks and ReactDOM.createPortal to activate the commands panel
|
|
5512
|
+
|
|
5513
|
+
function createSlashCommandsPlugin() {
|
|
5514
|
+
return {
|
|
5515
|
+
key: SLASH_COMMANDS_PLUGIN_KEY,
|
|
5516
|
+
type: SLASH_COMMANDS_PLUGIN_KEY,
|
|
5517
|
+
handlers: {
|
|
5518
|
+
onClick: function onClick(editor) {
|
|
5519
|
+
return function () {
|
|
5520
|
+
closePanel(editor.id);
|
|
5521
|
+
};
|
|
5522
|
+
},
|
|
5523
|
+
onKeyDown: function onKeyDown(editor) {
|
|
5524
|
+
return function (event) {
|
|
5525
|
+
closePanel(editor.id);
|
|
5526
|
+
|
|
5527
|
+
if (event.key === '/') {
|
|
5528
|
+
openPanel(editor.id);
|
|
5529
|
+
}
|
|
5530
|
+
};
|
|
5531
|
+
}
|
|
5532
|
+
}
|
|
5533
|
+
};
|
|
5534
|
+
}
|
|
5535
|
+
|
|
5536
|
+
var style$2 = {
|
|
5537
|
+
container: function container(_ref) {
|
|
5538
|
+
var top = _ref.top,
|
|
5539
|
+
left = _ref.left;
|
|
5540
|
+
return css({
|
|
5541
|
+
position: 'fixed',
|
|
5542
|
+
top: top - 14,
|
|
5543
|
+
left: left + 10,
|
|
5544
|
+
zIndex: 1,
|
|
5545
|
+
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.15)',
|
|
5546
|
+
borderRadius: '8px',
|
|
5547
|
+
userSelect: 'none'
|
|
5548
|
+
});
|
|
5549
|
+
}
|
|
5550
|
+
};
|
|
5551
|
+
function SlashCommandsPalette(_ref2) {
|
|
5552
|
+
var editorId = _ref2.editorId;
|
|
5553
|
+
|
|
5554
|
+
var _React$useState = useState(null),
|
|
5555
|
+
position = _React$useState[0],
|
|
5556
|
+
setPosition = _React$useState[1];
|
|
5557
|
+
|
|
5558
|
+
var _React$useState2 = useState(false),
|
|
5559
|
+
isOpen = _React$useState2[0],
|
|
5560
|
+
setIsOpen = _React$useState2[1]; // The user is not annoyed every time they type `/`
|
|
5561
|
+
|
|
5562
|
+
|
|
5563
|
+
var MAX_TRIES = 3;
|
|
5564
|
+
|
|
5565
|
+
var _React$useState3 = useState(0),
|
|
5566
|
+
currentTries = _React$useState3[0],
|
|
5567
|
+
setCurrentTries = _React$useState3[1];
|
|
5568
|
+
|
|
5569
|
+
useEffect(function () {
|
|
5570
|
+
function handler(event) {
|
|
5571
|
+
if (editorId !== event.detail.editorId) return;
|
|
5572
|
+
var topLeft = getCaretTopPoint();
|
|
5573
|
+
if (!topLeft) return;
|
|
5574
|
+
setPosition(topLeft);
|
|
5575
|
+
setIsOpen(true);
|
|
5576
|
+
setCurrentTries(function (curr) {
|
|
5577
|
+
return curr + 1;
|
|
5578
|
+
});
|
|
5579
|
+
}
|
|
5580
|
+
|
|
5581
|
+
document.addEventListener('open-rte-palette-commands', handler);
|
|
5582
|
+
return function () {
|
|
5583
|
+
document.removeEventListener('open-rte-palette-commands', handler);
|
|
5584
|
+
};
|
|
5585
|
+
}, [editorId]);
|
|
5586
|
+
useEffect(function () {
|
|
5587
|
+
function handler(event) {
|
|
5588
|
+
if (editorId !== event.detail.editorId) return;
|
|
5589
|
+
closePanel();
|
|
5590
|
+
}
|
|
5591
|
+
|
|
5592
|
+
document.addEventListener('close-rte-palette-commands', handler);
|
|
5593
|
+
return function () {
|
|
5594
|
+
return document.removeEventListener('close-rte-palette-commands', handler);
|
|
5595
|
+
};
|
|
5596
|
+
}, [editorId]);
|
|
5597
|
+
useEffect(function () {
|
|
5598
|
+
if (!isOpen) return;
|
|
5599
|
+
|
|
5600
|
+
function handler() {
|
|
5601
|
+
closePanel();
|
|
5602
|
+
}
|
|
5603
|
+
|
|
5604
|
+
window.addEventListener('resize', handler);
|
|
5605
|
+
window.addEventListener('scroll', handler, true);
|
|
5606
|
+
return function () {
|
|
5607
|
+
window.removeEventListener('resize', handler);
|
|
5608
|
+
window.removeEventListener('scroll', handler, true);
|
|
5609
|
+
};
|
|
5610
|
+
}, [isOpen]);
|
|
5611
|
+
|
|
5612
|
+
function closePanel() {
|
|
5613
|
+
setIsOpen(false);
|
|
5614
|
+
setPosition(null);
|
|
5615
|
+
}
|
|
5616
|
+
|
|
5617
|
+
if (!isOpen || !position || currentTries > MAX_TRIES) return null;
|
|
5618
|
+
return /*#__PURE__*/createElement("div", {
|
|
5619
|
+
className: style$2.container(position),
|
|
5620
|
+
"data-test-id": "rte-slash-commands"
|
|
5621
|
+
}, /*#__PURE__*/createElement(Card, null, /*#__PURE__*/createElement(Text$1, null, "Slash commands are temporarily unavailable.")));
|
|
5622
|
+
}
|
|
5623
|
+
|
|
5624
|
+
function insertTableAndFocusFirstCell(editor) {
|
|
5625
|
+
insertTable(editor, {
|
|
5626
|
+
header: true
|
|
5627
|
+
});
|
|
5628
|
+
replaceEmptyParagraphWithTable(editor);
|
|
5629
|
+
}
|
|
5630
|
+
function isTableActive(editor) {
|
|
5631
|
+
var tableElements = [ELEMENT_TABLE, ELEMENT_TH, ELEMENT_TR, ELEMENT_TD];
|
|
5632
|
+
return tableElements.some(function (el) {
|
|
5633
|
+
return isBlockSelected(editor, el);
|
|
5634
|
+
});
|
|
5635
|
+
}
|
|
5636
|
+
function isTableHeaderEnabled(editor) {
|
|
5637
|
+
var tableItem = getAbove(editor, {
|
|
5638
|
+
match: {
|
|
5639
|
+
type: BLOCKS.TABLE
|
|
5640
|
+
}
|
|
5641
|
+
});
|
|
5642
|
+
|
|
5643
|
+
if (!tableItem) {
|
|
5644
|
+
return false;
|
|
5645
|
+
}
|
|
5646
|
+
|
|
5647
|
+
var firstRow = getChildren$1(tableItem)[0];
|
|
5648
|
+
|
|
5649
|
+
if (!firstRow) {
|
|
5650
|
+
return false;
|
|
5651
|
+
}
|
|
5652
|
+
|
|
5653
|
+
return getChildren$1(firstRow).every(function (_ref) {
|
|
5654
|
+
var node = _ref[0];
|
|
5655
|
+
return node.type === BLOCKS.TABLE_HEADER_CELL;
|
|
5656
|
+
});
|
|
5657
|
+
}
|
|
5658
|
+
function replaceEmptyParagraphWithTable(editor) {
|
|
5659
|
+
var tablePath = getAncestorPathFromSelection(editor);
|
|
5660
|
+
if (!tablePath || isFirstChild(tablePath)) return;
|
|
5661
|
+
var previousPath = Path.previous(tablePath);
|
|
5662
|
+
if (!previousPath) return;
|
|
5663
|
+
|
|
5664
|
+
var _Editor$nodes = Editor.nodes(editor, {
|
|
5665
|
+
at: previousPath,
|
|
5666
|
+
match: function match(node) {
|
|
5667
|
+
return node.type === BLOCKS.PARAGRAPH;
|
|
5668
|
+
}
|
|
5669
|
+
}),
|
|
5670
|
+
nodes = _Editor$nodes[0];
|
|
5671
|
+
|
|
5672
|
+
if (!nodes) return;
|
|
5673
|
+
var previousNode = nodes[0];
|
|
5674
|
+
var isPreviousNodeTextEmpty = isAncestorEmpty(editor, previousNode);
|
|
5675
|
+
|
|
5676
|
+
if (isPreviousNodeTextEmpty) {
|
|
5677
|
+
// Switch table with previous empty paragraph
|
|
5678
|
+
Transforms.moveNodes(editor, {
|
|
5679
|
+
at: tablePath,
|
|
5680
|
+
to: previousPath
|
|
5681
|
+
}); // Remove previous paragraph that now is under the table
|
|
5682
|
+
|
|
5683
|
+
Transforms.removeNodes(editor, {
|
|
5684
|
+
at: tablePath
|
|
5685
|
+
});
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
/**
|
|
5689
|
+
* Returns the number of cells in a given row vs the table width
|
|
5690
|
+
*
|
|
5691
|
+
* Note: We should only get different table rows cell counts in between
|
|
5692
|
+
* normalization cycles.
|
|
5693
|
+
*/
|
|
5694
|
+
|
|
5695
|
+
var getNoOfMissingTableCellsInRow = function getNoOfMissingTableCellsInRow(editor, _ref2) {
|
|
5696
|
+
var rowPath = _ref2[1];
|
|
5697
|
+
var parent = getParent(editor, rowPath); // This is ensured by normalization. The error is here just in case
|
|
5698
|
+
|
|
5699
|
+
if (!parent) {
|
|
5700
|
+
throw new Error('table rows must be wrapped in a table node');
|
|
5701
|
+
}
|
|
5702
|
+
|
|
5703
|
+
var tablePath = parent[1]; // The longest table row determines its width
|
|
5704
|
+
|
|
5705
|
+
var tableWidth = Math.max.apply(Math, Array.from(Node.children(editor, tablePath)).map(function (_ref3) {
|
|
5706
|
+
var path = _ref3[1];
|
|
5707
|
+
return Array.from(Node.children(editor, path)).length;
|
|
5708
|
+
}));
|
|
5709
|
+
var rowWidth = Array.from(Node.children(editor, rowPath)).length;
|
|
5710
|
+
return tableWidth - rowWidth;
|
|
5711
|
+
};
|
|
5712
|
+
var createEmptyTableCells = function createEmptyTableCells(count) {
|
|
5713
|
+
var emptyTableCell = {
|
|
5714
|
+
type: BLOCKS.TABLE_CELL,
|
|
5715
|
+
data: {},
|
|
5716
|
+
children: [{
|
|
5717
|
+
type: BLOCKS.PARAGRAPH,
|
|
5718
|
+
data: {},
|
|
5719
|
+
children: [{
|
|
5720
|
+
text: ''
|
|
5721
|
+
}]
|
|
5722
|
+
}]
|
|
5723
|
+
};
|
|
5724
|
+
return new Array(count).fill(emptyTableCell);
|
|
5725
|
+
};
|
|
5726
|
+
var isNotEmpty = function isNotEmpty(editor, _ref4) {
|
|
5727
|
+
var path = _ref4[1];
|
|
5728
|
+
return Array.from(Node.children(editor, path)).length !== 0;
|
|
5729
|
+
};
|
|
5730
|
+
var isTable = function isTable(node) {
|
|
5731
|
+
return Element.isElement(node) && node.type === BLOCKS.TABLE;
|
|
5732
|
+
};
|
|
5733
|
+
|
|
5445
5734
|
function hasTables(nodes) {
|
|
5446
5735
|
return nodes.some(function (_ref) {
|
|
5447
5736
|
var type = _ref.type;
|
|
@@ -5454,6 +5743,10 @@ var isTableHeaderCell = function isTableHeaderCell(_ref2) {
|
|
|
5454
5743
|
return type === BLOCKS.TABLE_HEADER_CELL;
|
|
5455
5744
|
};
|
|
5456
5745
|
|
|
5746
|
+
var isTableCellOrHeader = function isTableCellOrHeader(node) {
|
|
5747
|
+
return Element.isElement(node) && [BLOCKS.TABLE_HEADER_CELL, BLOCKS.TABLE_CELL].includes(node.type);
|
|
5748
|
+
};
|
|
5749
|
+
|
|
5457
5750
|
function hasHeadersOutsideFirstRow(nodes) {
|
|
5458
5751
|
return nodes.filter(function (_ref3) {
|
|
5459
5752
|
var type = _ref3.type;
|
|
@@ -5467,6 +5760,32 @@ function hasHeadersOutsideFirstRow(nodes) {
|
|
|
5467
5760
|
});
|
|
5468
5761
|
}
|
|
5469
5762
|
|
|
5763
|
+
function trackInvalidTableCellChildren(editor, table) {
|
|
5764
|
+
var cells = table.children.flatMap(function (row) {
|
|
5765
|
+
var _row$children;
|
|
5766
|
+
|
|
5767
|
+
return (_row$children = row.children) != null ? _row$children : [];
|
|
5768
|
+
}).filter(isTableCellOrHeader); // get invalid direct children
|
|
5769
|
+
|
|
5770
|
+
var invalidNodeTypes = cells.flatMap(function (cell) {
|
|
5771
|
+
// Only paragraphs are allowed inside tables at the moment
|
|
5772
|
+
return cell.children.filter(function (node) {
|
|
5773
|
+
return Element.isElement(node) && node.type !== BLOCKS.PARAGRAPH;
|
|
5774
|
+
}).map(function (node) {
|
|
5775
|
+
return node.type;
|
|
5776
|
+
});
|
|
5777
|
+
});
|
|
5778
|
+
|
|
5779
|
+
for (var _iterator = _createForOfIteratorHelperLoose(new Set(invalidNodeTypes)), _step; !(_step = _iterator()).done;) {
|
|
5780
|
+
var _editor$tracking;
|
|
5781
|
+
|
|
5782
|
+
var nodeType = _step.value;
|
|
5783
|
+
(_editor$tracking = editor.tracking) == null ? void 0 : _editor$tracking.onViewportAction('invalidTablePaste', {
|
|
5784
|
+
nodeType: nodeType
|
|
5785
|
+
});
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
|
|
5470
5789
|
function addTableTrackingEvents(editor) {
|
|
5471
5790
|
var insertData = editor.insertData;
|
|
5472
5791
|
|
|
@@ -5491,6 +5810,19 @@ function addTableTrackingEvents(editor) {
|
|
|
5491
5810
|
insertData(data);
|
|
5492
5811
|
}
|
|
5493
5812
|
};
|
|
5813
|
+
|
|
5814
|
+
var insertFragment = editor.insertFragment;
|
|
5815
|
+
|
|
5816
|
+
editor.insertFragment = function (fragment) {
|
|
5817
|
+
var tables = fragment.filter(isTable);
|
|
5818
|
+
|
|
5819
|
+
for (var _iterator2 = _createForOfIteratorHelperLoose(tables), _step2; !(_step2 = _iterator2()).done;) {
|
|
5820
|
+
var table = _step2.value;
|
|
5821
|
+
trackInvalidTableCellChildren(editor, table);
|
|
5822
|
+
}
|
|
5823
|
+
|
|
5824
|
+
return insertFragment(fragment);
|
|
5825
|
+
};
|
|
5494
5826
|
}
|
|
5495
5827
|
|
|
5496
5828
|
var addRow = function addRow(editor, getNextRowPath) {
|
|
@@ -5612,116 +5944,6 @@ var setHeader = function setHeader(editor, enable) {
|
|
|
5612
5944
|
});
|
|
5613
5945
|
};
|
|
5614
5946
|
|
|
5615
|
-
function insertTableAndFocusFirstCell(editor) {
|
|
5616
|
-
insertTable(editor, {
|
|
5617
|
-
header: true
|
|
5618
|
-
});
|
|
5619
|
-
replaceEmptyParagraphWithTable(editor);
|
|
5620
|
-
}
|
|
5621
|
-
function isTableActive(editor) {
|
|
5622
|
-
var tableElements = [ELEMENT_TABLE, ELEMENT_TH, ELEMENT_TR, ELEMENT_TD];
|
|
5623
|
-
return tableElements.some(function (el) {
|
|
5624
|
-
return isBlockSelected(editor, el);
|
|
5625
|
-
});
|
|
5626
|
-
}
|
|
5627
|
-
function isTableHeaderEnabled(editor) {
|
|
5628
|
-
var tableItem = getAbove(editor, {
|
|
5629
|
-
match: {
|
|
5630
|
-
type: BLOCKS.TABLE
|
|
5631
|
-
}
|
|
5632
|
-
});
|
|
5633
|
-
|
|
5634
|
-
if (!tableItem) {
|
|
5635
|
-
return false;
|
|
5636
|
-
}
|
|
5637
|
-
|
|
5638
|
-
var firstRow = getChildren$1(tableItem)[0];
|
|
5639
|
-
|
|
5640
|
-
if (!firstRow) {
|
|
5641
|
-
return false;
|
|
5642
|
-
}
|
|
5643
|
-
|
|
5644
|
-
return getChildren$1(firstRow).every(function (_ref) {
|
|
5645
|
-
var node = _ref[0];
|
|
5646
|
-
return node.type === BLOCKS.TABLE_HEADER_CELL;
|
|
5647
|
-
});
|
|
5648
|
-
}
|
|
5649
|
-
function replaceEmptyParagraphWithTable(editor) {
|
|
5650
|
-
var tablePath = getAncestorPathFromSelection(editor);
|
|
5651
|
-
if (!tablePath || isFirstChild(tablePath)) return;
|
|
5652
|
-
var previousPath = Path.previous(tablePath);
|
|
5653
|
-
if (!previousPath) return;
|
|
5654
|
-
|
|
5655
|
-
var _Editor$nodes = Editor.nodes(editor, {
|
|
5656
|
-
at: previousPath,
|
|
5657
|
-
match: function match(node) {
|
|
5658
|
-
return node.type === BLOCKS.PARAGRAPH;
|
|
5659
|
-
}
|
|
5660
|
-
}),
|
|
5661
|
-
nodes = _Editor$nodes[0];
|
|
5662
|
-
|
|
5663
|
-
if (!nodes) return;
|
|
5664
|
-
var previousNode = nodes[0];
|
|
5665
|
-
var isPreviousNodeTextEmpty = isAncestorEmpty(editor, previousNode);
|
|
5666
|
-
|
|
5667
|
-
if (isPreviousNodeTextEmpty) {
|
|
5668
|
-
// Switch table with previous empty paragraph
|
|
5669
|
-
Transforms.moveNodes(editor, {
|
|
5670
|
-
at: tablePath,
|
|
5671
|
-
to: previousPath
|
|
5672
|
-
}); // Remove previous paragraph that now is under the table
|
|
5673
|
-
|
|
5674
|
-
Transforms.removeNodes(editor, {
|
|
5675
|
-
at: tablePath
|
|
5676
|
-
});
|
|
5677
|
-
}
|
|
5678
|
-
}
|
|
5679
|
-
/**
|
|
5680
|
-
* Returns the number of cells in a given row vs the table width
|
|
5681
|
-
*
|
|
5682
|
-
* Note: We should only get different table rows cell counts in between
|
|
5683
|
-
* normalization cycles.
|
|
5684
|
-
*/
|
|
5685
|
-
|
|
5686
|
-
var getNoOfMissingTableCellsInRow = function getNoOfMissingTableCellsInRow(editor, _ref2) {
|
|
5687
|
-
var rowPath = _ref2[1];
|
|
5688
|
-
var parent = getParent(editor, rowPath); // This is ensured by normalization. The error is here just in case
|
|
5689
|
-
|
|
5690
|
-
if (!parent) {
|
|
5691
|
-
throw new Error('table rows must be wrapped in a table node');
|
|
5692
|
-
}
|
|
5693
|
-
|
|
5694
|
-
var tablePath = parent[1]; // The longest table row determines its width
|
|
5695
|
-
|
|
5696
|
-
var tableWidth = Math.max.apply(Math, Array.from(Node.children(editor, tablePath)).map(function (_ref3) {
|
|
5697
|
-
var path = _ref3[1];
|
|
5698
|
-
return Array.from(Node.children(editor, path)).length;
|
|
5699
|
-
}));
|
|
5700
|
-
var rowWidth = Array.from(Node.children(editor, rowPath)).length;
|
|
5701
|
-
return tableWidth - rowWidth;
|
|
5702
|
-
};
|
|
5703
|
-
var createEmptyTableCells = function createEmptyTableCells(count) {
|
|
5704
|
-
var emptyTableCell = {
|
|
5705
|
-
type: BLOCKS.TABLE_CELL,
|
|
5706
|
-
data: {},
|
|
5707
|
-
children: [{
|
|
5708
|
-
type: BLOCKS.PARAGRAPH,
|
|
5709
|
-
data: {},
|
|
5710
|
-
children: [{
|
|
5711
|
-
text: ''
|
|
5712
|
-
}]
|
|
5713
|
-
}]
|
|
5714
|
-
};
|
|
5715
|
-
return new Array(count).fill(emptyTableCell);
|
|
5716
|
-
};
|
|
5717
|
-
var isNotEmpty = function isNotEmpty(editor, _ref4) {
|
|
5718
|
-
var path = _ref4[1];
|
|
5719
|
-
return Array.from(Node.children(editor, path)).length !== 0;
|
|
5720
|
-
};
|
|
5721
|
-
var isTable = function isTable(node) {
|
|
5722
|
-
return Element.isElement(node) && node.type === BLOCKS.TABLE;
|
|
5723
|
-
};
|
|
5724
|
-
|
|
5725
5947
|
var styles$i = {
|
|
5726
5948
|
topRight: /*#__PURE__*/css({
|
|
5727
5949
|
position: 'absolute',
|
|
@@ -5836,43 +6058,102 @@ var TableActions = function TableActions() {
|
|
|
5836
6058
|
};
|
|
5837
6059
|
|
|
5838
6060
|
var _templateObject$7;
|
|
5839
|
-
var style$
|
|
6061
|
+
var style$3 = /*#__PURE__*/css(_templateObject$7 || (_templateObject$7 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n border: 1px solid ", ";\n border-collapse: collapse;\n padding: 10px 12px;\n min-width: 48px;\n position: relative;\n vertical-align: top;\n\n div:last-child {\n margin-bottom: 0;\n }\n"])), tokens.gray400);
|
|
5840
6062
|
var Cell = function Cell(props) {
|
|
5841
6063
|
var isSelected = useSelected();
|
|
5842
6064
|
return /*#__PURE__*/createElement("td", Object.assign({}, props.attributes, props.element.data, {
|
|
5843
|
-
className: style$
|
|
6065
|
+
className: style$3
|
|
5844
6066
|
}), isSelected && /*#__PURE__*/createElement(TableActions, null), props.children);
|
|
5845
6067
|
};
|
|
5846
6068
|
|
|
5847
6069
|
var _templateObject$8;
|
|
5848
|
-
var style$
|
|
6070
|
+
var style$4 = /*#__PURE__*/css(_templateObject$8 || (_templateObject$8 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n background-color: ", ";\n border: 1px solid ", ";\n border-collapse: collapse;\n padding: 10px 12px;\n font-weight: ", ";\n text-align: left;\n min-width: 48px;\n position: relative;\n\n div:last-child {\n margin-bottom: 0;\n }\n"])), tokens.gray200, tokens.gray400, tokens.fontWeightNormal);
|
|
5849
6071
|
var HeaderCell = function HeaderCell(props) {
|
|
5850
6072
|
var isSelected = useSelected();
|
|
5851
6073
|
return /*#__PURE__*/createElement("th", Object.assign({}, props.attributes, props.element.data, {
|
|
5852
|
-
className: style$
|
|
6074
|
+
className: style$4
|
|
5853
6075
|
}), isSelected && /*#__PURE__*/createElement(TableActions, null), props.children);
|
|
5854
6076
|
};
|
|
5855
6077
|
|
|
5856
6078
|
var _templateObject$9;
|
|
5857
|
-
var style$
|
|
6079
|
+
var style$5 = /*#__PURE__*/css(_templateObject$9 || (_templateObject$9 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n border: 1px solid ", ";\n border-collapse: collapse;\n\n &:hover td {\n background-color: transparent !important;\n }\n"])), tokens.gray400);
|
|
5858
6080
|
var Row = function Row(props) {
|
|
5859
6081
|
return /*#__PURE__*/createElement("tr", Object.assign({}, props.attributes, {
|
|
5860
|
-
className: style$
|
|
6082
|
+
className: style$5
|
|
5861
6083
|
}), props.children);
|
|
5862
6084
|
};
|
|
5863
6085
|
|
|
5864
6086
|
var _templateObject$a;
|
|
5865
|
-
var style$
|
|
6087
|
+
var style$6 = /*#__PURE__*/css(_templateObject$a || (_templateObject$a = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n margin-bottom: 1.5em;\n border-collapse: collapse;\n border-radius: 5px;\n border-style: hidden;\n box-shadow: 0 0 0 1px ", ";\n width: 100%;\n table-layout: fixed;\n overflow: hidden;\n"])), tokens.gray400);
|
|
5866
6088
|
var Table = function Table(props) {
|
|
5867
6089
|
return /*#__PURE__*/createElement("div", {
|
|
5868
6090
|
"data-block-type": BLOCKS.TABLE
|
|
5869
6091
|
}, /*#__PURE__*/createElement("table", Object.assign({
|
|
5870
|
-
className: style$
|
|
6092
|
+
className: style$6
|
|
5871
6093
|
}, props.attributes), /*#__PURE__*/createElement("tbody", null, props.children)));
|
|
5872
6094
|
};
|
|
5873
6095
|
|
|
5874
|
-
|
|
5875
|
-
|
|
6096
|
+
/**
|
|
6097
|
+
* Removes table wrappers when pasting a single table cell
|
|
6098
|
+
*
|
|
6099
|
+
* In Plate/Slate, copying the content of a table cell wraps
|
|
6100
|
+
* it in a <table><tr><td>{content}</td></tr></table> even
|
|
6101
|
+
* when copying partial cell content.
|
|
6102
|
+
*
|
|
6103
|
+
* That's really annoying as there is no way to remove the table
|
|
6104
|
+
* wrappers in that case.
|
|
6105
|
+
*/
|
|
6106
|
+
|
|
6107
|
+
var trimUnnecessaryTableWrapper = function trimUnnecessaryTableWrapper(node) {
|
|
6108
|
+
if (!Element.isElement(node)) {
|
|
6109
|
+
return [node];
|
|
6110
|
+
} // must be a table with a single row
|
|
6111
|
+
|
|
6112
|
+
|
|
6113
|
+
if (node.type !== BLOCKS.TABLE || node.children.length !== 1) {
|
|
6114
|
+
return [node];
|
|
6115
|
+
}
|
|
6116
|
+
|
|
6117
|
+
var row = node.children[0]; // the row must contain a single cell
|
|
6118
|
+
|
|
6119
|
+
if (row.children.length !== 1) {
|
|
6120
|
+
return [node];
|
|
6121
|
+
}
|
|
6122
|
+
|
|
6123
|
+
var cell = row.children[0];
|
|
6124
|
+
return cell.children;
|
|
6125
|
+
};
|
|
6126
|
+
|
|
6127
|
+
var insertTableFragment = function insertTableFragment(editor) {
|
|
6128
|
+
var insertFragment = editor.insertFragment;
|
|
6129
|
+
return function (fragments) {
|
|
6130
|
+
var _editor$selection;
|
|
6131
|
+
|
|
6132
|
+
if (!editor.selection) {
|
|
6133
|
+
return;
|
|
6134
|
+
}
|
|
6135
|
+
|
|
6136
|
+
fragments = fragments.flatMap(trimUnnecessaryTableWrapper); // We need to make sure we have a new, empty and clean paragraph in order to paste tables as-is due to how Slate behaves
|
|
6137
|
+
// More info: https://github.com/ianstormtaylor/slate/pull/4489 and https://github.com/ianstormtaylor/slate/issues/4542
|
|
6138
|
+
|
|
6139
|
+
var isInsertingTable = fragments.some(function (fragment) {
|
|
6140
|
+
return isTable(fragment);
|
|
6141
|
+
});
|
|
6142
|
+
var isTableFirstFragment = fragments.findIndex(function (fragment) {
|
|
6143
|
+
return isTable(fragment);
|
|
6144
|
+
}) === 0;
|
|
6145
|
+
var currentLineHasText = getText(editor, (_editor$selection = editor.selection) == null ? void 0 : _editor$selection.focus.path) !== '';
|
|
6146
|
+
|
|
6147
|
+
if (isInsertingTable && isTableFirstFragment && currentLineHasText) {
|
|
6148
|
+
insertEmptyParagraph(editor);
|
|
6149
|
+
}
|
|
6150
|
+
|
|
6151
|
+
return insertFragment(fragments);
|
|
6152
|
+
};
|
|
6153
|
+
};
|
|
6154
|
+
|
|
6155
|
+
var onKeyDownTable = function onKeyDownTable(editor, plugin) {
|
|
6156
|
+
var defaultHandler = onKeyDownTable$1(editor, plugin);
|
|
5876
6157
|
return function (event) {
|
|
5877
6158
|
// This fixes `Cannot resolve a Slate point from DOM point: [object HTMLDivElement]` when typing while the cursor is before table
|
|
5878
6159
|
var windowSelection = window.getSelection();
|
|
@@ -5904,6 +6185,27 @@ var createTableOnKeyDown = function createTableOnKeyDown(editor, plugin) {
|
|
|
5904
6185
|
event.stopPropagation();
|
|
5905
6186
|
return;
|
|
5906
6187
|
}
|
|
6188
|
+
} // Pressing Tab on the last cell creates a new row
|
|
6189
|
+
// Otherwise, jumping between cells is handled in the defaultKeyDownTable
|
|
6190
|
+
|
|
6191
|
+
|
|
6192
|
+
if (event.key === 'Tab' && !event.shiftKey) {
|
|
6193
|
+
event.preventDefault();
|
|
6194
|
+
var res = getTableCellEntry(editor, {});
|
|
6195
|
+
|
|
6196
|
+
if (res) {
|
|
6197
|
+
var tableElement = res.tableElement,
|
|
6198
|
+
tableRow = res.tableRow,
|
|
6199
|
+
tableCell = res.tableCell;
|
|
6200
|
+
var isLastCell = isLastChild(tableRow, tableCell[1]);
|
|
6201
|
+
var isLastRow = isLastChild(tableElement, tableRow[1]);
|
|
6202
|
+
|
|
6203
|
+
if (isLastRow && isLastCell) {
|
|
6204
|
+
addRowBelow(editor); // skip default handler
|
|
6205
|
+
|
|
6206
|
+
return;
|
|
6207
|
+
}
|
|
6208
|
+
}
|
|
5907
6209
|
}
|
|
5908
6210
|
|
|
5909
6211
|
defaultHandler(event);
|
|
@@ -5916,34 +6218,13 @@ var createTablePlugin = function createTablePlugin() {
|
|
|
5916
6218
|
return createTablePlugin$1({
|
|
5917
6219
|
type: BLOCKS.TABLE,
|
|
5918
6220
|
handlers: {
|
|
5919
|
-
onKeyDown:
|
|
6221
|
+
onKeyDown: onKeyDownTable
|
|
5920
6222
|
},
|
|
5921
6223
|
withOverrides: function withOverrides(editor, plugin) {
|
|
5922
6224
|
// injects important fixes from plate's original table plugin
|
|
5923
6225
|
withTable(editor, plugin);
|
|
5924
6226
|
addTableTrackingEvents(editor);
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
editor.insertFragment = function (fragments) {
|
|
5928
|
-
var _editor$selection;
|
|
5929
|
-
|
|
5930
|
-
// We need to make sure we have a new, empty and clean paragraph in order to paste tables as-is due to how Slate behaves
|
|
5931
|
-
// More info: https://github.com/ianstormtaylor/slate/pull/4489 and https://github.com/ianstormtaylor/slate/issues/4542
|
|
5932
|
-
var isInsertingTable = fragments.some(function (fragment) {
|
|
5933
|
-
return isTable(fragment);
|
|
5934
|
-
});
|
|
5935
|
-
var isTableFirstFragment = fragments.findIndex(function (fragment) {
|
|
5936
|
-
return isTable(fragment);
|
|
5937
|
-
}) === 0;
|
|
5938
|
-
var currentLineHasText = getText(editor, (_editor$selection = editor.selection) == null ? void 0 : _editor$selection.focus.path) !== '';
|
|
5939
|
-
|
|
5940
|
-
if (isInsertingTable && isTableFirstFragment && currentLineHasText) {
|
|
5941
|
-
insertEmptyParagraph(editor);
|
|
5942
|
-
}
|
|
5943
|
-
|
|
5944
|
-
insertFragment(fragments);
|
|
5945
|
-
};
|
|
5946
|
-
|
|
6227
|
+
editor.insertFragment = insertTableFragment(editor);
|
|
5947
6228
|
return editor;
|
|
5948
6229
|
},
|
|
5949
6230
|
overrideByKey: (_overrideByKey = {}, _overrideByKey[ELEMENT_TABLE] = {
|
|
@@ -6391,7 +6672,7 @@ var getPlugins = function getPlugins(sdk, onAction) {
|
|
|
6391
6672
|
return [// AST must come after the HTML deserializer
|
|
6392
6673
|
createDeserializeHtmlPlugin(), createDeserializeAstPlugin(), createDeserializeDocxPlugin(), // Tracking - This should come first so all plugins below will have access to `editor.tracking`
|
|
6393
6674
|
createTrackingPlugin(onAction), // Global / Global shortcuts
|
|
6394
|
-
createDragAndDropPlugin(), // Block Elements
|
|
6675
|
+
createDragAndDropPlugin(), createSlashCommandsPlugin(), // Block Elements
|
|
6395
6676
|
createParagraphPlugin(), createListPlugin(), createHrPlugin(), createHeadingPlugin(), createQuotePlugin(), createTablePlugin(), createEmbeddedEntryBlockPlugin(sdk), createEmbeddedAssetBlockPlugin(sdk), // Inline elements
|
|
6396
6677
|
createHyperlinkPlugin(sdk), createEmbeddedEntityInlinePlugin(sdk), // Marks
|
|
6397
6678
|
createMarksPlugin(), // Other
|
|
@@ -6869,7 +7150,9 @@ var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
|
|
|
6869
7150
|
isDisabled: props.isDisabled
|
|
6870
7151
|
}, /*#__PURE__*/React__default.createElement(Toolbar, {
|
|
6871
7152
|
isDisabled: props.isDisabled
|
|
6872
|
-
}))
|
|
7153
|
+
})), /*#__PURE__*/React__default.createElement(SlashCommandsPalette, {
|
|
7154
|
+
editorId: id
|
|
7155
|
+
})))));
|
|
6873
7156
|
};
|
|
6874
7157
|
|
|
6875
7158
|
var RichTextEditor = function RichTextEditor(props) {
|