@contentful/field-editor-rich-text 2.0.0-next.0 → 2.0.0-next.1

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.
@@ -24,10 +24,11 @@ var find = _interopDefault(require('lodash/find'));
24
24
  var flow = _interopDefault(require('lodash/flow'));
25
25
  var get = _interopDefault(require('lodash/get'));
26
26
  var plateList = require('@udecode/plate-list');
27
+ var richTextPlainTextRenderer = require('@contentful/rich-text-plain-text-renderer');
27
28
  var fieldEditorShared = require('@contentful/field-editor-shared');
28
29
  var mimetype = _interopDefault(require('@contentful/mimetype'));
29
30
  var plateTable = require('@udecode/plate-table');
30
- var richTextPlainTextRenderer = require('@contentful/rich-text-plain-text-renderer');
31
+ var plateAstSerializer = require('@udecode/plate-ast-serializer');
31
32
  var plateHtmlSerializer = require('@udecode/plate-html-serializer');
32
33
  var plateParagraph = require('@udecode/plate-paragraph');
33
34
  var plateBreak = require('@udecode/plate-break');
@@ -330,57 +331,40 @@ var styles$1 = {
330
331
  zIndex: /*#__PURE__*/Number(tokens.zIndexTooltip)
331
332
  })
332
333
  };
333
- var ToolbarButton = /*#__PURE__*/function (_Component) {
334
- _inheritsLoose(ToolbarButton, _Component);
335
-
336
- function ToolbarButton() {
337
- var _this;
338
-
339
- _this = _Component.apply(this, arguments) || this;
334
+ function ToolbarButton(props) {
335
+ var title = props.title,
336
+ testId = props.testId,
337
+ isActive = props.isActive,
338
+ children = props.children,
339
+ className = props.className,
340
+ _props$isDisabled = props.isDisabled,
341
+ isDisabled = _props$isDisabled === void 0 ? false : _props$isDisabled;
340
342
 
341
- _this.handleClick = function (event) {
342
- event.preventDefault();
343
+ var handleClick = function handleClick(event) {
344
+ event.preventDefault();
345
+ props.onClick();
346
+ };
343
347
 
344
- _this.props.onClick(event);
345
- };
348
+ var button = /*#__PURE__*/React__default.createElement(f36Components.Button, {
349
+ className: emotion.cx(styles$1.button, className),
350
+ isDisabled: isDisabled,
351
+ startIcon: children,
352
+ onClick: handleClick,
353
+ testId: testId,
354
+ variant: isActive ? 'secondary' : 'transparent',
355
+ size: "small"
356
+ });
346
357
 
347
- return _this;
358
+ if (title) {
359
+ return /*#__PURE__*/React__default.createElement(f36Components.Tooltip, {
360
+ className: styles$1.tooltip,
361
+ placement: "bottom",
362
+ content: title
363
+ }, button);
348
364
  }
349
365
 
350
- var _proto = ToolbarButton.prototype;
351
-
352
- _proto.render = function render() {
353
- var _this$props = this.props,
354
- title = _this$props.title,
355
- testId = _this$props.testId,
356
- isActive = _this$props.isActive,
357
- children = _this$props.children,
358
- className = _this$props.className,
359
- _this$props$isDisable = _this$props.isDisabled,
360
- isDisabled = _this$props$isDisable === void 0 ? false : _this$props$isDisable;
361
- var button = /*#__PURE__*/React__default.createElement(f36Components.Button, {
362
- className: emotion.cx(styles$1.button, className),
363
- isDisabled: isDisabled,
364
- startIcon: children,
365
- onClick: this.handleClick,
366
- testId: testId,
367
- variant: isActive ? 'secondary' : 'transparent',
368
- size: "small"
369
- });
370
-
371
- if (title) {
372
- return /*#__PURE__*/React__default.createElement(f36Components.Tooltip, {
373
- className: styles$1.tooltip,
374
- placement: "bottom",
375
- content: title
376
- }, button);
377
- }
378
-
379
- return button;
380
- };
381
-
382
- return ToolbarButton;
383
- }(React.Component);
366
+ return button;
367
+ }
384
368
 
385
369
  var LINK_TYPES = [Contentful.INLINES.HYPERLINK, Contentful.INLINES.ENTRY_HYPERLINK, Contentful.INLINES.ASSET_HYPERLINK];
386
370
  var LIST_TYPES = [Contentful.BLOCKS.OL_LIST, Contentful.BLOCKS.UL_LIST];
@@ -582,6 +566,57 @@ function unwrapFromRoot(editor) {
582
566
  at: ancestorPath
583
567
  });
584
568
  }
569
+ var isAtEndOfTextSelection = function isAtEndOfTextSelection(editor) {
570
+ var _editor$selection, _editor$selection2;
571
+
572
+ return ((_editor$selection = editor.selection) == null ? void 0 : _editor$selection.focus.offset) === plateCommon.getText(editor, (_editor$selection2 = editor.selection) == null ? void 0 : _editor$selection2.focus.path).length;
573
+ };
574
+ function currentSelectionStartsTableCell(editor) {
575
+ var _editor$selection3;
576
+
577
+ var _getNodeEntryFromSele2 = getNodeEntryFromSelection(editor, [Contentful.BLOCKS.TABLE_CELL, Contentful.BLOCKS.TABLE_HEADER_CELL]),
578
+ tableCellNode = _getNodeEntryFromSele2[0],
579
+ path = _getNodeEntryFromSele2[1];
580
+
581
+ return !!tableCellNode && (!plateCommon.getText(editor, path) || ((_editor$selection3 = editor.selection) == null ? void 0 : _editor$selection3.focus.offset) === 0);
582
+ }
583
+ /**
584
+ * This traversal strategy is unfortunately necessary because Slate doesn't
585
+ * expose something like Node.next(editor).
586
+ */
587
+
588
+ function getNextNode(editor) {
589
+ if (!editor.selection) {
590
+ return null;
591
+ }
592
+
593
+ var descendants = slate.Node.descendants(editor, {
594
+ from: editor.selection.focus.path
595
+ }); // eslint-disable-next-line no-constant-condition
596
+
597
+ while (true) {
598
+ var _descendants$next = descendants.next(),
599
+ done = _descendants$next.done,
600
+ value = _descendants$next.value;
601
+
602
+ if (done) {
603
+ return null;
604
+ }
605
+
606
+ var node = value[0],
607
+ path = value[1];
608
+
609
+ if (slate.Path.isCommon(path, editor.selection.focus.path)) {
610
+ continue;
611
+ }
612
+
613
+ return node;
614
+ }
615
+ }
616
+ function currentSelectionPrecedesTableCell(editor) {
617
+ var nextNode = getNextNode(editor);
618
+ return !!nextNode && Contentful.TABLE_BLOCKS.includes(nextNode.type) && isAtEndOfTextSelection(editor);
619
+ }
585
620
 
586
621
  function deserializeLeaf(type, rules) {
587
622
  return function (editor) {
@@ -616,7 +651,7 @@ function getContentfulEditorId(sdk) {
616
651
  function useContentfulEditorHook(_ref) {
617
652
  var sdk = _ref.sdk;
618
653
  var editorId = getContentfulEditorId(sdk);
619
- var editor = plateCore.useStoreEditorRef(editorId);
654
+ var editor = plateCore.usePlateEditorRef(editorId);
620
655
  return editor;
621
656
  }
622
657
 
@@ -658,8 +693,7 @@ function withHrEvents(editor) {
658
693
  function ToolbarHrButton(props) {
659
694
  var editor = useContentfulEditor();
660
695
 
661
- function handleOnClick(event) {
662
- event.preventDefault();
696
+ function handleOnClick() {
663
697
  if (!(editor != null && editor.selection)) return;
664
698
 
665
699
  if (shouldUnwrapBlockquote(editor, Contentful.BLOCKS.HR)) {
@@ -1075,8 +1109,7 @@ function withQuoteEvents(editor) {
1075
1109
  function ToolbarQuoteButton(props) {
1076
1110
  var editor = useContentfulEditor();
1077
1111
 
1078
- function handleOnClick(event) {
1079
- event.preventDefault();
1112
+ function handleOnClick() {
1080
1113
  if (!editor) return;
1081
1114
  createBlockQuote(editor);
1082
1115
  Slate.ReactEditor.focus(editor);
@@ -1111,14 +1144,97 @@ var withQuoteOptions = (_withQuoteOptions = {}, _withQuoteOptions[Contentful.BLO
1111
1144
  component: Quote
1112
1145
  }, _withQuoteOptions);
1113
1146
 
1147
+ /**
1148
+ * A copy of Plate's list plugin with a few adjustments
1149
+ * to fix pasting text inside lists.
1150
+ */
1151
+
1152
+ var slateNodesToText = function slateNodesToText(nodes) {
1153
+ var contentfulNode = contentfulSlatejsAdapter.toContentfulDocument({
1154
+ document: nodes,
1155
+ schema: schema
1156
+ });
1157
+ return richTextPlainTextRenderer.documentToPlainTextString(contentfulNode);
1158
+ };
1159
+
1160
+ var getListInsertFragment = function getListInsertFragment(editor) {
1161
+ var insertFragment = editor.insertFragment;
1162
+ var li = plateCore.getPlatePluginOptions(editor, plateList.ELEMENT_LI);
1163
+ var ul = plateCore.getPlatePluginOptions(editor, plateList.ELEMENT_UL);
1164
+ var ol = plateCore.getPlatePluginOptions(editor, plateList.ELEMENT_OL);
1165
+
1166
+ var isListRoot = function isListRoot(node) {
1167
+ return [ul.type, ol.type].includes(node.type);
1168
+ };
1169
+
1170
+ var getFirstAncestorOfType = function getFirstAncestorOfType(root, entry, _ref) {
1171
+ var type = _ref.type;
1172
+ var ancestor = slate.Path.parent(entry[1]);
1173
+
1174
+ while (slate.Node.get(root, ancestor).type !== type) {
1175
+ ancestor = slate.Path.parent(ancestor);
1176
+ }
1177
+
1178
+ return [slate.Node.get(root, ancestor), ancestor];
1179
+ };
1180
+ /**
1181
+ * Removes the "empty" leading lis. Empty in this context means lis only with other lis as children.
1182
+ *
1183
+ * @returns If argument is not a list root, returns it, otherwise returns ul[] or li[].
1184
+ */
1185
+
1186
+
1187
+ var trimList = function trimList(listRoot) {
1188
+ if (!isListRoot(listRoot)) {
1189
+ return [listRoot];
1190
+ }
1191
+
1192
+ var textEntries = Array.from(slate.Node.texts(listRoot));
1193
+ var commonAncestorEntry = textEntries.reduce(function (commonAncestor, textEntry) {
1194
+ return slate.Path.isAncestor(commonAncestor[1], textEntry[1]) ? commonAncestor : slate.Node.common(listRoot, textEntry[1], commonAncestor[1]);
1195
+ }, // any list item would do, we grab the first one
1196
+ getFirstAncestorOfType(listRoot, textEntries[0], li));
1197
+ return isListRoot(commonAncestorEntry[0]) ? commonAncestorEntry[0].children : [commonAncestorEntry[0]];
1198
+ };
1199
+
1200
+ return function (fragment) {
1201
+ var liEntry = plateCommon.findNode(editor, {
1202
+ match: {
1203
+ type: li.type
1204
+ },
1205
+ mode: 'lowest'
1206
+ });
1207
+
1208
+ if (liEntry) {
1209
+ var liPath = liEntry[1]; // FIXME: this is a temporarily workaround and needs a follow-up to properly
1210
+ // non-text elements
1211
+
1212
+ var nodes = fragment.flatMap(function (node) {
1213
+ return trimList(node);
1214
+ });
1215
+ var text = slateNodesToText(nodes);
1216
+ return slate.Transforms.insertNodes(editor, [{
1217
+ text: text
1218
+ }], {
1219
+ at: editor.selection || slate.Path.next(liPath),
1220
+ select: true
1221
+ });
1222
+ }
1223
+
1224
+ var filtered = isListRoot(fragment[0]) ? [{
1225
+ text: ''
1226
+ }].concat(fragment) : fragment;
1227
+ return insertFragment(filtered);
1228
+ };
1229
+ };
1230
+
1114
1231
  var _templateObject$2, _templateObject2$2, _templateObject3$2, _styles, _withListOptions;
1115
1232
  function ToolbarListButton(props) {
1116
1233
  var sdk = useSdkContext();
1117
1234
  var editor = useContentfulEditor();
1118
1235
 
1119
1236
  function handleClick(type) {
1120
- return function (event) {
1121
- event.preventDefault();
1237
+ return function () {
1122
1238
  if (!(editor != null && editor.selection)) return;
1123
1239
 
1124
1240
  if (shouldUnwrapBlockquote(editor, type)) {
@@ -1171,18 +1287,34 @@ var withListOptions = (_withListOptions = {}, _withListOptions[plateList.ELEMENT
1171
1287
  type: Contentful.BLOCKS.OL_LIST,
1172
1288
  component: OL
1173
1289
  }, _withListOptions);
1290
+
1291
+ var withCustomList = function withCustomList(options) {
1292
+ var withDefaultOverrides = plateList.withList(options);
1293
+ return function (editor) {
1294
+ var insertFragment = editor.insertFragment;
1295
+ withDefaultOverrides(editor); // Reverts any overrides to insertFragment
1296
+
1297
+ editor.insertFragment = insertFragment; // Use our custom getListInsertFragment
1298
+
1299
+ editor.insertFragment = getListInsertFragment(editor);
1300
+ return editor;
1301
+ };
1302
+ };
1303
+
1174
1304
  var createListPlugin = function createListPlugin() {
1175
- return plateList.createListPlugin({
1305
+ var options = {
1176
1306
  validLiChildrenTypes: Contentful.LIST_ITEM_BLOCKS
1177
- });
1307
+ };
1308
+ var plugin = plateList.createListPlugin(options);
1309
+ plugin.withOverrides = withCustomList(options);
1310
+ return plugin;
1178
1311
  };
1179
1312
 
1180
1313
  var _withBoldOptions;
1181
1314
  function ToolbarBoldButton(props) {
1182
1315
  var editor = useContentfulEditor();
1183
1316
 
1184
- function handleClick(event) {
1185
- event.preventDefault();
1317
+ function handleClick() {
1186
1318
  if (!(editor != null && editor.selection)) return;
1187
1319
  plateCommon.toggleMark(editor, Contentful.MARKS.BOLD);
1188
1320
  Slate.ReactEditor.focus(editor);
@@ -1240,8 +1372,7 @@ var _withCodeOptions;
1240
1372
  function ToolbarCodeButton(props) {
1241
1373
  var editor = useContentfulEditor();
1242
1374
 
1243
- function handleClick(event) {
1244
- event.preventDefault();
1375
+ function handleClick() {
1245
1376
  if (!(editor != null && editor.selection)) return;
1246
1377
  plateCommon.toggleMark(editor, Contentful.MARKS.CODE);
1247
1378
  Slate.ReactEditor.focus(editor);
@@ -1292,8 +1423,7 @@ var _withItalicOptions;
1292
1423
  function ToolbarItalicButton(props) {
1293
1424
  var editor = useContentfulEditor();
1294
1425
 
1295
- function handleClick(event) {
1296
- event.preventDefault();
1426
+ function handleClick() {
1297
1427
  if (!(editor != null && editor.selection)) return;
1298
1428
  plateCommon.toggleMark(editor, Contentful.MARKS.ITALIC);
1299
1429
  Slate.ReactEditor.focus(editor);
@@ -1343,8 +1473,7 @@ var _withUnderlineOptions;
1343
1473
  function ToolbarUnderlineButton(props) {
1344
1474
  var editor = useContentfulEditor();
1345
1475
 
1346
- function handleClick(event) {
1347
- event.preventDefault();
1476
+ function handleClick() {
1348
1477
  if (!(editor != null && editor.selection)) return;
1349
1478
  plateCommon.toggleMark(editor, Contentful.MARKS.UNDERLINE);
1350
1479
  Slate.ReactEditor.focus(editor);
@@ -3180,33 +3309,31 @@ function ToolbarHyperlinkButton(props) {
3180
3309
  var isActive = !!(editor && isLinkActive(editor));
3181
3310
  var sdk = useSdkContext();
3182
3311
 
3183
- function handleClick(_x3) {
3312
+ function handleClick() {
3184
3313
  return _handleClick3.apply(this, arguments);
3185
3314
  }
3186
3315
 
3187
3316
  function _handleClick3() {
3188
- _handleClick3 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(event) {
3317
+ _handleClick3 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3() {
3189
3318
  return runtime_1.wrap(function _callee3$(_context3) {
3190
3319
  while (1) {
3191
3320
  switch (_context3.prev = _context3.next) {
3192
3321
  case 0:
3193
- event.preventDefault();
3194
-
3195
3322
  if (editor) {
3196
- _context3.next = 3;
3323
+ _context3.next = 2;
3197
3324
  break;
3198
3325
  }
3199
3326
 
3200
3327
  return _context3.abrupt("return");
3201
3328
 
3202
- case 3:
3329
+ case 2:
3203
3330
  if (isActive) {
3204
3331
  unwrapLink(editor);
3205
3332
  } else {
3206
3333
  addOrEditLink(editor, sdk);
3207
3334
  }
3208
3335
 
3209
- case 4:
3336
+ case 3:
3210
3337
  case "end":
3211
3338
  return _context3.stop();
3212
3339
  }
@@ -3703,7 +3830,19 @@ function createWithTableEvents(tracking) {
3703
3830
  return function withTableEvents(editor) {
3704
3831
  addTableTrackingEvents(editor, tracking);
3705
3832
  addTableNormalization(editor);
3706
- return plateTable.getTableOnKeyDown()(editor);
3833
+ var handleKeyDownFromPlateUdecode = plateTable.getTableOnKeyDown()(editor);
3834
+ return function handleKeyDown(event) {
3835
+ if (event.key === 'Backspace' && currentSelectionStartsTableCell(editor) || event.key === 'Delete' && currentSelectionPrecedesTableCell(editor)) {
3836
+ // The default behavior here would be to delete the preceding or forthcoming
3837
+ // leaf node, in this case a cell or header cell. But we don't want to do that,
3838
+ // because it would leave us with a non-standard number of table cells.
3839
+ event.preventDefault();
3840
+ event.stopPropagation();
3841
+ return;
3842
+ }
3843
+
3844
+ handleKeyDownFromPlateUdecode(event);
3845
+ };
3707
3846
  };
3708
3847
  }
3709
3848
 
@@ -3747,31 +3886,29 @@ function ToolbarTableButton(props) {
3747
3886
 
3748
3887
  var isActive = editor && isTableActive(editor);
3749
3888
 
3750
- function handleClick(_x) {
3889
+ function handleClick() {
3751
3890
  return _handleClick.apply(this, arguments);
3752
3891
  }
3753
3892
 
3754
3893
  function _handleClick() {
3755
- _handleClick = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(event) {
3894
+ _handleClick = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
3756
3895
  return runtime_1.wrap(function _callee$(_context) {
3757
3896
  while (1) {
3758
3897
  switch (_context.prev = _context.next) {
3759
3898
  case 0:
3760
- event.preventDefault();
3761
-
3762
3899
  if (editor) {
3763
- _context.next = 3;
3900
+ _context.next = 2;
3764
3901
  break;
3765
3902
  }
3766
3903
 
3767
3904
  return _context.abrupt("return");
3768
3905
 
3769
- case 3:
3906
+ case 2:
3770
3907
  onViewportAction('insertTable');
3771
3908
  insertTableAndFocusFirstCell(editor);
3772
3909
  Slate.ReactEditor.focus(editor);
3773
3910
 
3774
- case 6:
3911
+ case 5:
3775
3912
  case "end":
3776
3913
  return _context.stop();
3777
3914
  }
@@ -3815,6 +3952,16 @@ function EmbeddedEntityDropdownButton(_ref) {
3815
3952
  }, children));
3816
3953
  }
3817
3954
 
3955
+ // "modern" Edge was released at 79.x
3956
+ var IS_EDGE_LEGACY = typeof navigator !== 'undefined' && /*#__PURE__*/ /Edge?\/(?:[0-6][0-9]|[0-7][0-8])/i.test(navigator.userAgent); // Native `beforeInput` events don't work well with react on Chrome 75
3957
+ // and older, Chrome 76+ can use `beforeInput` though.
3958
+
3959
+ var IS_CHROME_LEGACY = typeof navigator !== 'undefined' && /*#__PURE__*/ /Chrome?\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent); // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
3960
+ // Chrome Legacy doesn't support `beforeinput` correctly
3961
+
3962
+ var HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY && !IS_EDGE_LEGACY && // globalThis is undefined in older browsers
3963
+ typeof globalThis !== 'undefined' && globalThis.InputEvent && typeof globalThis.InputEvent.prototype.getTargetRanges === 'function'; // The `getTargetRanges` property isn't recognized.
3964
+
3818
3965
  var styles$g = {
3819
3966
  root: /*#__PURE__*/emotion.css({
3820
3967
  marginBottom: '1.25rem'
@@ -3850,9 +3997,14 @@ function LinkedEntityBlock(props) {
3850
3997
  return /*#__PURE__*/React__default.createElement("div", Object.assign({}, attributes, {
3851
3998
  className: styles$g.root,
3852
3999
  "data-entity-type": entityType,
3853
- "data-entity-id": entityId
4000
+ "data-entity-id": entityId,
4001
+ // COMPAT: This makes copy & paste work for Firefox
4002
+ contentEditable: !HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
4003
+ draggable: !HAS_BEFORE_INPUT_SUPPORT ? true : undefined
3854
4004
  }), /*#__PURE__*/React__default.createElement("div", {
3855
- contentEditable: false
4005
+ // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari
4006
+ contentEditable: HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
4007
+ draggable: HAS_BEFORE_INPUT_SUPPORT ? true : undefined
3856
4008
  }, entityType === 'Entry' && /*#__PURE__*/React__default.createElement(FetchingWrappedEntryCard, {
3857
4009
  sdk: sdk,
3858
4010
  entryId: entityId,
@@ -4259,7 +4411,7 @@ function FetchingWrappedInlineEntryCard(props) {
4259
4411
  key: "edit",
4260
4412
  onClick: props.onEdit
4261
4413
  }, "Edit"), /*#__PURE__*/React__default.createElement(f36Components.MenuItem, {
4262
- key: "edit",
4414
+ key: "remove",
4263
4415
  onClick: props.onRemove,
4264
4416
  disabled: props.isDisabled,
4265
4417
  testId: "card-action-remove"
@@ -4325,9 +4477,14 @@ function EmbeddedEntityInline(props) {
4325
4477
 
4326
4478
  return /*#__PURE__*/React.createElement("span", Object.assign({}, props.attributes, {
4327
4479
  className: styles$j.root,
4328
- "data-embedded-entity-inline-id": entryId
4480
+ "data-embedded-entity-inline-id": entryId,
4481
+ // COMPAT: This makes copy & paste work for Firefox
4482
+ contentEditable: !HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
4483
+ draggable: !HAS_BEFORE_INPUT_SUPPORT ? true : undefined
4329
4484
  }), /*#__PURE__*/React.createElement("span", {
4330
- contentEditable: false
4485
+ // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari
4486
+ contentEditable: HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
4487
+ draggable: HAS_BEFORE_INPUT_SUPPORT ? true : undefined
4331
4488
  }, /*#__PURE__*/React.createElement(FetchingWrappedInlineEntryCard, {
4332
4489
  sdk: sdk,
4333
4490
  entryId: entryId,
@@ -4449,6 +4606,7 @@ function createEmbeddedEntityInlinePlugin(sdk) {
4449
4606
  renderElement: plateCore.getRenderElement(Contentful.INLINES.EMBEDDED_ENTRY),
4450
4607
  pluginKeys: Contentful.INLINES.EMBEDDED_ENTRY,
4451
4608
  inlineTypes: plateCore.getPlatePluginTypes(Contentful.INLINES.EMBEDDED_ENTRY),
4609
+ voidTypes: plateCore.getPlatePluginTypes(Contentful.INLINES.EMBEDDED_ENTRY),
4452
4610
  onKeyDown: getWithEmbeddedEntryInlineEvents(sdk),
4453
4611
  deserialize: function deserialize(editor) {
4454
4612
  var options = plateCore.getPlatePluginOptions(editor, Contentful.INLINES.EMBEDDED_ENTRY);
@@ -4501,6 +4659,7 @@ var EmbedEntityWidget = function EmbedEntityWidget(_ref) {
4501
4659
  var isDisabled = _ref.isDisabled,
4502
4660
  canInsertBlocks = _ref.canInsertBlocks;
4503
4661
  var sdk = useSdkContext();
4662
+ var editor = useContentfulEditor();
4504
4663
 
4505
4664
  var _useState = React.useState(false),
4506
4665
  isEmbedDropdownOpen = _useState[0],
@@ -4539,7 +4698,7 @@ var EmbedEntityWidget = function EmbedEntityWidget(_ref) {
4539
4698
  onClose: onCloseEntityDropdown,
4540
4699
  isButton: !shouldDisplayDropdown
4541
4700
  }), inlineEntryEmbedEnabled && /*#__PURE__*/React__default.createElement(ToolbarEmbeddedEntityInlineButton, {
4542
- isDisabled: !!isDisabled,
4701
+ isDisabled: !!isDisabled || isLinkActive(editor),
4543
4702
  onClose: onCloseEntityDropdown,
4544
4703
  isButton: !shouldDisplayDropdown
4545
4704
  }), blockAssetEmbedEnabled && /*#__PURE__*/React__default.createElement(EmbeddedEntityBlockToolbarIcon, {
@@ -4846,6 +5005,8 @@ var createPastePlugin = function createPastePlugin() {
4846
5005
  };
4847
5006
  };
4848
5007
 
5008
+ var _excluded = ["element"];
5009
+
4849
5010
  var _templateObject$6, _styles$2, _withParagraphOptions;
4850
5011
  var styles$m = (_styles$2 = {}, _styles$2[Contentful.BLOCKS.PARAGRAPH] = /*#__PURE__*/emotion.css(_templateObject$6 || (_templateObject$6 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n line-height: ", ";\n margin-bottom: 1.5em;\n "])), tokens.lineHeightDefault), _styles$2);
4851
5012
  function Paragraph(props) {
@@ -4853,15 +5014,71 @@ function Paragraph(props) {
4853
5014
  className: styles$m[Contentful.BLOCKS.PARAGRAPH]
4854
5015
  }), props.children);
4855
5016
  }
5017
+
5018
+ function isEmbed(element) {
5019
+ return element.hasAttribute('data-embedded-entity-inline-id') || element.hasAttribute('data-entity-type');
5020
+ }
5021
+
5022
+ function isEmpty(element) {
5023
+ return element.textContent === '';
5024
+ }
5025
+
4856
5026
  function createParagraphPlugin() {
4857
5027
  var elementKeys = [plateParagraph.ELEMENT_PARAGRAPH, Contentful.BLOCKS.PARAGRAPH];
5028
+ var deserializer = deserializeElement(Contentful.BLOCKS.PARAGRAPH, [{
5029
+ nodeNames: ['P', 'DIV']
5030
+ }]);
4858
5031
  return {
4859
5032
  renderElement: plateCore.getRenderElement(elementKeys),
4860
5033
  pluginKeys: elementKeys,
4861
5034
  onKeyDown: plateCommon.getToggleElementOnKeyDown(Contentful.BLOCKS.PARAGRAPH),
4862
- deserialize: deserializeElement(Contentful.BLOCKS.PARAGRAPH, [{
4863
- nodeNames: ['P']
4864
- }])
5035
+ deserialize: function deserialize(editor) {
5036
+ var _deserializer = deserializer(editor),
5037
+ element = _deserializer.element,
5038
+ rest = _objectWithoutPropertiesLoose(_deserializer, _excluded);
5039
+
5040
+ return _extends({}, rest, {
5041
+ element: element == null ? void 0 : element.map(function (deserializeNode) {
5042
+ return _extends({}, deserializeNode, {
5043
+ deserialize: function deserialize(el) {
5044
+ if (isEmpty(el) || isEmbed(el)) {
5045
+ return;
5046
+ }
5047
+
5048
+ return deserializeNode.deserialize(el);
5049
+ }
5050
+ });
5051
+ })
5052
+ });
5053
+ },
5054
+ withOverrides: function withOverrides(editor) {
5055
+ var normalizeNode = editor.normalizeNode;
5056
+
5057
+ editor.normalizeNode = function (entry) {
5058
+ var node = entry[0],
5059
+ path = entry[1]; // If the element is a paragraph, ensure its children are valid.
5060
+
5061
+ if (slate.Element.isElement(node) && node.type === Contentful.BLOCKS.PARAGRAPH) {
5062
+ for (var _iterator = _createForOfIteratorHelperLoose(slate.Node.children(editor, path)), _step; !(_step = _iterator()).done;) {
5063
+ var _step$value = _step.value,
5064
+ child = _step$value[0],
5065
+ childPath = _step$value[1];
5066
+
5067
+ if (slate.Element.isElement(child) && !editor.isInline(child)) {
5068
+ slate.Transforms.unwrapNodes(editor, {
5069
+ at: childPath
5070
+ });
5071
+ return;
5072
+ }
5073
+ }
5074
+ } // Fall back to the original `normalizeNode` to enforce other constraints.
5075
+
5076
+
5077
+ normalizeNode(entry);
5078
+ };
5079
+
5080
+ return editor;
5081
+ }
4865
5082
  };
4866
5083
  }
4867
5084
  var withParagraphOptions = (_withParagraphOptions = {}, _withParagraphOptions[plateParagraph.ELEMENT_PARAGRAPH] = {
@@ -4905,6 +5122,15 @@ function createInsertBeforeFirstVoidBlockPlugin() {
4905
5122
  return isFirstChild(path) && !!node.isVoid;
4906
5123
  }
4907
5124
  }
5125
+ }, {
5126
+ hotkey: 'enter',
5127
+ query: {
5128
+ filter: function filter(_ref2) {
5129
+ var node = _ref2[0],
5130
+ path = _ref2[1];
5131
+ return !isFirstChild(path) && !!node.isVoid;
5132
+ }
5133
+ }
4908
5134
  }]
4909
5135
  };
4910
5136
  return plateBreak.createExitBreakPlugin(optionsExitBreakPlugin);
@@ -5010,19 +5236,108 @@ var createTrailingParagraphPlugin = function createTrailingParagraphPlugin() {
5010
5236
  });
5011
5237
  };
5012
5238
 
5013
- var _excluded = ["sdk", "isInitiallyDisabled", "onAction"];
5239
+ function createDragAndDropPlugin() {
5240
+ var _DND_BLOCKED_ELEMENTS;
5241
+
5242
+ // Elements that don't allow other elements to be dragged into them and which callback should be used
5243
+ var DND_BLOCKED_ELEMENTS = (_DND_BLOCKED_ELEMENTS = {}, _DND_BLOCKED_ELEMENTS[Contentful.BLOCKS.TABLE] = slate.Transforms.removeNodes, _DND_BLOCKED_ELEMENTS[Contentful.BLOCKS.QUOTE] = slate.Transforms.liftNodes, _DND_BLOCKED_ELEMENTS);
5244
+ var DRAGGABLE_TYPES = [Contentful.BLOCKS.EMBEDDED_ENTRY, Contentful.BLOCKS.EMBEDDED_ASSET, Contentful.INLINES.EMBEDDED_ENTRY];
5245
+ /**
5246
+ * HTML node names where dropping should be allowed
5247
+ * Usually for elements where `Transforms.removeNodes` is needed
5248
+ * TODO: looking up for html nodes is not the best solution and it won't scale but it works fine for our current cases/elements
5249
+ */
5250
+
5251
+ var ON_DROP_ALLOWED_TYPES = {
5252
+ TABLE: [Contentful.INLINES.EMBEDDED_ENTRY]
5253
+ };
5254
+ return {
5255
+ withOverrides: function withOverrides(editor) {
5256
+ var normalizeNode = editor.normalizeNode;
5257
+
5258
+ editor.normalizeNode = function (entry) {
5259
+ var node = entry[0],
5260
+ path = entry[1];
5261
+ Object.keys(DND_BLOCKED_ELEMENTS).forEach(function (blockedElementType) {
5262
+ var nodeType = node.type;
5263
+
5264
+ if (slate.Node.isNode(node) && nodeType === blockedElementType) {
5265
+ for (var _iterator = _createForOfIteratorHelperLoose(slate.Node.children(editor, path)), _step; !(_step = _iterator()).done;) {
5266
+ var _step$value = _step.value,
5267
+ child = _step$value[0],
5268
+ childPath = _step$value[1];
5269
+ var childType = child.type;
5270
+ if (!Contentful.CONTAINERS[blockedElementType]) return;
5271
+
5272
+ if (!Contentful.CONTAINERS[blockedElementType].includes(childType)) {
5273
+ var callback = DND_BLOCKED_ELEMENTS[blockedElementType];
5274
+ callback(editor, {
5275
+ at: childPath,
5276
+ match: function match(matchNode) {
5277
+ return slate.Node.isNode(matchNode) && DRAGGABLE_TYPES.includes(matchNode.type);
5278
+ }
5279
+ });
5280
+ return;
5281
+ }
5282
+ }
5283
+ }
5284
+ });
5285
+ normalizeNode(entry);
5286
+ };
5287
+
5288
+ return editor;
5289
+ },
5290
+ // If true, the next handlers will be skipped.
5291
+ onDrop: function onDrop(editor) {
5292
+ return function (event) {
5293
+ var _Array$from = Array.from(plateCommon.getNodes(editor, {
5294
+ match: function match(node) {
5295
+ return slate.Editor.isBlock(editor, node) && DRAGGABLE_TYPES.includes(node.type);
5296
+ }
5297
+ })),
5298
+ draggingBlock = _Array$from[0];
5299
+
5300
+ if (!draggingBlock) return false;
5301
+ var draggingNode = draggingBlock[0];
5302
+ if (!event.nativeEvent.target) return false; // TODO: looking up for html nodes is not the best solution and it won't scale, we need to find a way to know the dropping target slate element
5303
+
5304
+ return getParents(event.nativeEvent.target).some(function (node) {
5305
+ var _ON_DROP_ALLOWED_TYPE;
5306
+
5307
+ return ON_DROP_ALLOWED_TYPES[node.nodeName] ? !((_ON_DROP_ALLOWED_TYPE = ON_DROP_ALLOWED_TYPES[node.nodeName]) != null && _ON_DROP_ALLOWED_TYPE.includes(draggingNode.type)) : false;
5308
+ });
5309
+ };
5310
+ }
5311
+ };
5312
+ }
5313
+
5314
+ function getParents(el) {
5315
+ var parents = [];
5316
+ parents.push(el);
5317
+
5318
+ while (el.parentNode) {
5319
+ parents.unshift(el.parentNode);
5320
+ el = el.parentNode;
5321
+ }
5322
+
5323
+ return parents;
5324
+ }
5325
+
5326
+ var _excluded$1 = ["sdk", "isInitiallyDisabled", "onAction"];
5014
5327
 
5015
5328
  var getPlugins = function getPlugins(sdk, tracking) {
5016
5329
  var plugins = [// Core
5017
5330
  plateCore.createReactPlugin(), plateCore.createHistoryPlugin(), // Behavior
5018
5331
  createPastePlugin(), // Global shortcuts
5019
- createNewLinePlugin(), createInsertBeforeFirstVoidBlockPlugin(), // Block Elements
5332
+ createNewLinePlugin(), createInsertBeforeFirstVoidBlockPlugin(), createDragAndDropPlugin(), // Block Elements
5020
5333
  createParagraphPlugin(), createListPlugin(), createHrPlugin(), createHeadingPlugin(), createQuotePlugin(), createTablePlugin(tracking), createEmbeddedEntryBlockPlugin(sdk), createEmbeddedAssetBlockPlugin(sdk), // Inline elements
5021
5334
  createHyperlinkPlugin(sdk), createEmbeddedEntityInlinePlugin(sdk), // Marks
5022
5335
  createBoldPlugin(), createCodePlugin(), createItalicPlugin(), createUnderlinePlugin(), // Other
5023
5336
  createTrailingParagraphPlugin()];
5024
5337
  return plugins.concat([plateHtmlSerializer.createDeserializeHTMLPlugin({
5025
5338
  plugins: plugins
5339
+ }), plateAstSerializer.createDeserializeAstPlugin({
5340
+ plugins: plugins
5026
5341
  })]);
5027
5342
  };
5028
5343
 
@@ -5079,7 +5394,7 @@ var RichTextEditor = function RichTextEditor(props) {
5079
5394
  var sdk = props.sdk,
5080
5395
  isInitiallyDisabled = props.isInitiallyDisabled,
5081
5396
  onAction = props.onAction,
5082
- otherProps = _objectWithoutPropertiesLoose(props, _excluded);
5397
+ otherProps = _objectWithoutPropertiesLoose(props, _excluded$1);
5083
5398
 
5084
5399
  var isEmptyValue = React.useCallback(function (value) {
5085
5400
  return !value || deepEquals(value, Contentful.EMPTY_DOCUMENT);