@contentful/field-editor-rich-text 2.0.0-next.13 → 2.0.0-next.16

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.
Files changed (56) hide show
  1. package/dist/ContentfulEditorProvider.d.ts +6 -5
  2. package/dist/RichTextEditor.d.ts +1 -1
  3. package/dist/field-editor-rich-text.cjs.development.js +559 -396
  4. package/dist/field-editor-rich-text.cjs.development.js.map +1 -1
  5. package/dist/field-editor-rich-text.cjs.production.min.js +1 -1
  6. package/dist/field-editor-rich-text.cjs.production.min.js.map +1 -1
  7. package/dist/field-editor-rich-text.esm.js +562 -399
  8. package/dist/field-editor-rich-text.esm.js.map +1 -1
  9. package/dist/helpers/editor.d.ts +14 -17
  10. package/dist/helpers/extractNodes.d.ts +2 -3
  11. package/dist/helpers/transformers.d.ts +6 -6
  12. package/dist/plugins/EmbeddedEntityBlock/ToolbarIcon.d.ts +1 -2
  13. package/dist/plugins/EmbeddedEntityBlock/Util.d.ts +2 -1
  14. package/dist/plugins/EmbeddedEntityBlock/index.d.ts +2 -3
  15. package/dist/plugins/EmbeddedEntityInline/index.d.ts +1 -2
  16. package/dist/plugins/Hr/index.d.ts +2 -3
  17. package/dist/plugins/Hyperlink/HyperlinkModal.d.ts +3 -4
  18. package/dist/plugins/Hyperlink/index.d.ts +1 -2
  19. package/dist/plugins/Hyperlink/utils.d.ts +2 -2
  20. package/dist/plugins/List/insertListBreak.d.ts +2 -2
  21. package/dist/plugins/List/insertListFragment.d.ts +3 -2
  22. package/dist/plugins/List/transforms/insertListItem.d.ts +2 -2
  23. package/dist/plugins/List/utils.d.ts +8 -7
  24. package/dist/plugins/List/withList.d.ts +2 -1
  25. package/dist/plugins/Marks/Bold.d.ts +7 -5
  26. package/dist/plugins/Marks/Code.d.ts +7 -5
  27. package/dist/plugins/Marks/Italic.d.ts +7 -5
  28. package/dist/plugins/Marks/Underline.d.ts +7 -5
  29. package/dist/plugins/Marks/components/MarkToolbarButton.d.ts +13 -0
  30. package/dist/plugins/Marks/helpers.d.ts +4 -0
  31. package/dist/plugins/Normalizer/types.d.ts +4 -3
  32. package/dist/plugins/Normalizer/utils.d.ts +2 -2
  33. package/dist/plugins/Normalizer/withNormalizer.d.ts +2 -2
  34. package/dist/plugins/PasteHTML/createPasteHTMLPlugin.d.ts +6 -0
  35. package/dist/plugins/Quote/toggleQuote.d.ts +5 -3
  36. package/dist/plugins/Table/actions/addColumn.d.ts +3 -3
  37. package/dist/plugins/Table/actions/addRow.d.ts +3 -3
  38. package/dist/plugins/Table/actions/setHeader.d.ts +2 -2
  39. package/dist/plugins/Table/addTableTrackingEvents.d.ts +2 -3
  40. package/dist/plugins/Table/createTablePlugin.d.ts +1 -2
  41. package/dist/plugins/Table/helpers.d.ts +7 -7
  42. package/dist/plugins/Tracking/createTrackingPlugin.d.ts +10 -0
  43. package/dist/plugins/Tracking/index.d.ts +1 -0
  44. package/dist/plugins/Tracking/utils.d.ts +2 -0
  45. package/dist/plugins/TrailingParagraph/index.d.ts +2 -1
  46. package/dist/plugins/Voids/transformVoid.d.ts +2 -2
  47. package/dist/plugins/index.d.ts +2 -2
  48. package/dist/plugins/links-tracking.d.ts +1 -2
  49. package/dist/test-utils/assertOutput.d.ts +2 -2
  50. package/dist/test-utils/createEditor.d.ts +5 -6
  51. package/dist/test-utils/mockPlugin.d.ts +1 -1
  52. package/dist/test-utils/setEmptyDataAttribute.d.ts +2 -2
  53. package/dist/types.d.ts +6 -2
  54. package/dist/useOnValueChanged.d.ts +7 -0
  55. package/package.json +1 -1
  56. package/dist/TrackingProvider.d.ts +0 -11
@@ -6,7 +6,6 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
6
6
 
7
7
  var React = require('react');
8
8
  var React__default = _interopDefault(React);
9
- var contentfulSlatejsAdapter = require('@contentful/contentful-slatejs-adapter');
10
9
  var fieldEditorReference = require('@contentful/field-editor-reference');
11
10
  var fieldEditorShared = require('@contentful/field-editor-shared');
12
11
  var Contentful = require('@contentful/rich-text-types');
@@ -14,12 +13,12 @@ var plateCore = require('@udecode/plate-core');
14
13
  var emotion = require('emotion');
15
14
  var deepEquals = _interopDefault(require('fast-deep-equal'));
16
15
  var noop = _interopDefault(require('lodash/noop'));
17
- var constate = _interopDefault(require('constate'));
18
16
  var plateSerializerDocx = require('@udecode/plate-serializer-docx');
19
17
  var plateBreak = require('@udecode/plate-break');
20
18
  var isHotkey = _interopDefault(require('is-hotkey'));
21
19
  var slate = require('slate');
22
20
  var Slate = require('slate-react');
21
+ var constate = _interopDefault(require('constate'));
23
22
  var f36Components = require('@contentful/f36-components');
24
23
  var mimetype = _interopDefault(require('@contentful/mimetype'));
25
24
  var get = _interopDefault(require('lodash/get'));
@@ -34,7 +33,10 @@ var isPlainObject = _interopDefault(require('is-plain-obj'));
34
33
  var plateParagraph = require('@udecode/plate-paragraph');
35
34
  var plateSelect = require('@udecode/plate-select');
36
35
  var plateTable = require('@udecode/plate-table');
36
+ var contentfulSlateJSAdapter = require('@contentful/contentful-slatejs-adapter');
37
+ var richTextPlainTextRenderer = require('@contentful/rich-text-plain-text-renderer');
37
38
  var plateTrailingBlock = require('@udecode/plate-trailing-block');
39
+ var debounce = _interopDefault(require('lodash/debounce'));
38
40
  var PropTypes = _interopDefault(require('prop-types'));
39
41
 
40
42
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -244,126 +246,37 @@ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
244
246
  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
245
247
  }
246
248
 
247
- var _extends2, _extends4, _inlines;
248
- var inlines = /*#__PURE__*/Object.values(Contentful.INLINES).map(function (type) {
249
- return {
250
- type: type
251
- };
252
- });
253
- var schema = {
254
- document: {
255
- nodes: [{
256
- types: /*#__PURE__*/Contentful.TOP_LEVEL_BLOCKS.map(function (type) {
257
- return {
258
- type: type
259
- };
260
- })
261
- }]
262
- },
263
- blocks: /*#__PURE__*/_extends((_extends2 = {}, _extends2[Contentful.BLOCKS.PARAGRAPH] = {
264
- nodes: [{
265
- match: /*#__PURE__*/[].concat(inlines, [{
266
- object: 'text'
267
- }])
268
- }]
269
- }, _extends2[Contentful.BLOCKS.HEADING_1] = {
270
- nodes: [{
271
- match: /*#__PURE__*/[].concat(inlines, [{
272
- object: 'text'
273
- }])
274
- }]
275
- }, _extends2[Contentful.BLOCKS.HEADING_2] = {
276
- nodes: [{
277
- match: /*#__PURE__*/[].concat(inlines, [{
278
- object: 'text'
279
- }])
280
- }]
281
- }, _extends2[Contentful.BLOCKS.HEADING_3] = {
282
- nodes: [{
283
- match: /*#__PURE__*/[].concat(inlines, [{
284
- object: 'text'
285
- }])
286
- }]
287
- }, _extends2[Contentful.BLOCKS.HEADING_4] = {
288
- nodes: [{
289
- match: /*#__PURE__*/[].concat(inlines, [{
290
- object: 'text'
291
- }])
292
- }]
293
- }, _extends2[Contentful.BLOCKS.HEADING_5] = {
294
- nodes: [{
295
- match: /*#__PURE__*/[].concat(inlines, [{
296
- object: 'text'
297
- }])
298
- }]
299
- }, _extends2[Contentful.BLOCKS.HEADING_6] = {
300
- nodes: [{
301
- match: /*#__PURE__*/[].concat(inlines, [{
302
- object: 'text'
303
- }])
304
- }]
305
- }, _extends2), /*#__PURE__*/Contentful.VOID_BLOCKS.reduce(function (blocks, nodeType) {
306
- var _extends3;
307
-
308
- return _extends({}, blocks, (_extends3 = {}, _extends3[nodeType] = {
309
- isVoid: true
310
- }, _extends3));
311
- }, {}), (_extends4 = {}, _extends4[Contentful.BLOCKS.QUOTE] = {
312
- nodes: [{
313
- match: [/*#__PURE__*/Contentful.CONTAINERS[Contentful.BLOCKS.QUOTE].map(function (type) {
314
- return {
315
- type: type
316
- };
317
- })],
318
- min: 1
319
- }],
320
- normalize: function normalize(editor, error) {
321
- if (error.code === 'child_type_invalid') {
322
- return editor.unwrapBlockByKey(error.node.key, Contentful.BLOCKS.QUOTE);
323
- }
324
- }
325
- }, _extends4)),
326
- inlines: (_inlines = {}, _inlines[Contentful.INLINES.HYPERLINK] = {
327
- nodes: [{
328
- match: [{
329
- object: 'text'
330
- }]
331
- }]
332
- }, _inlines[Contentful.INLINES.ENTRY_HYPERLINK] = {
333
- nodes: [{
334
- match: [{
335
- object: 'text'
336
- }]
337
- }]
338
- }, _inlines[Contentful.INLINES.ASSET_HYPERLINK] = {
339
- nodes: [{
340
- match: [{
341
- object: 'text'
342
- }]
343
- }]
344
- }, _inlines[Contentful.INLINES.EMBEDDED_ENTRY] = {
345
- isVoid: true
346
- }, _inlines)
347
- };
348
-
349
249
  function getContentfulEditorId(sdk) {
350
250
  var entry = sdk.entry,
351
251
  field = sdk.field;
352
252
  var sys = entry.getSys();
353
253
  return "rich-text-editor-" + sys.id + "-" + field.id + "-" + field.locale;
354
254
  }
255
+ var editorContext = /*#__PURE__*/React.createContext('');
256
+ var ContentfulEditorIdProvider = editorContext.Provider;
257
+ function useContentfulEditorId() {
258
+ var id = React.useContext(editorContext);
355
259
 
356
- function useContentfulEditorHook(_ref) {
357
- var sdk = _ref.sdk;
358
- var editorId = getContentfulEditorId(sdk);
260
+ if (!id) {
261
+ throw new Error('could not find editor id. Please ensure the component is wrapped in <ContentfulEditorIdProvider> ');
262
+ }
263
+
264
+ return id;
265
+ } // This hook re-renders when the value changes
266
+ // Use case: Toolbar icons, for example
267
+
268
+ function useContentfulEditor() {
269
+ var editorId = useContentfulEditorId();
270
+ var editor = plateCore.usePlateEditorState(editorId);
271
+ return editor;
272
+ } // This doesn't re-render when the value changes
273
+
274
+ function useContentfulEditorRef() {
275
+ var editorId = useContentfulEditorId();
359
276
  var editor = plateCore.usePlateEditorRef(editorId);
360
277
  return editor;
361
278
  }
362
279
 
363
- var _constate = /*#__PURE__*/constate(useContentfulEditorHook),
364
- ContentfulEditorProvider = _constate[0],
365
- useContentfulEditor = _constate[1];
366
-
367
280
  var createSoftBreakPlugin = function createSoftBreakPlugin() {
368
281
  return plateBreak.createSoftBreakPlugin({
369
282
  then: function then(editor) {
@@ -626,17 +539,6 @@ function getAncestorPathFromSelection(editor) {
626
539
  return level.length === 1;
627
540
  });
628
541
  }
629
- function shouldUnwrapBlockquote(editor, type) {
630
- var isQuoteSelected = isBlockSelected(editor, Contentful.BLOCKS.QUOTE);
631
- var isValidType = [].concat(Contentful.HEADINGS, [Contentful.BLOCKS.OL_LIST, Contentful.BLOCKS.UL_LIST, Contentful.BLOCKS.HR]).includes(type);
632
- return isQuoteSelected && isValidType;
633
- }
634
- function unwrapFromRoot(editor) {
635
- var ancestorPath = getAncestorPathFromSelection(editor);
636
- slate.Transforms.unwrapNodes(editor, {
637
- at: ancestorPath
638
- });
639
- }
640
542
  var isAtEndOfTextSelection = function isAtEndOfTextSelection(editor) {
641
543
  var _editor$selection, _editor$selection2;
642
544
 
@@ -706,12 +608,14 @@ var focus = function focus(editor) {
706
608
  }
707
609
  };
708
610
 
709
- function withLinkTracking(tracking, Component) {
611
+ function withLinkTracking(Component) {
710
612
  return function ComponentWithTracking(props) {
613
+ var editor = useContentfulEditorRef();
614
+ var onEntityFetchComplete = React__default.useCallback(function () {
615
+ return editor.tracking.onViewportAction('linkRendered');
616
+ }, [editor]);
711
617
  return /*#__PURE__*/React__default.createElement(Component, Object.assign({}, props, {
712
- onEntityFetchComplete: function onEntityFetchComplete() {
713
- tracking.onViewportAction('linkRendered');
714
- }
618
+ onEntityFetchComplete: onEntityFetchComplete
715
619
  }));
716
620
  };
717
621
  }
@@ -725,9 +629,9 @@ function useSdk(_ref) {
725
629
  return sdkMemo;
726
630
  }
727
631
 
728
- var _constate$1 = /*#__PURE__*/constate(useSdk),
729
- SdkProvider = _constate$1[0],
730
- useSdkContext = _constate$1[1];
632
+ var _constate = /*#__PURE__*/constate(useSdk),
633
+ SdkProvider = _constate[0],
634
+ useSdkContext = _constate[1];
731
635
 
732
636
  var styles = {
733
637
  scheduleIcon: /*#__PURE__*/emotion.css({
@@ -1977,12 +1881,11 @@ function _selectEntityAndInsert() {
1977
1881
  config = _extends({}, baseConfig, {
1978
1882
  withCreate: true
1979
1883
  });
1980
- _context.prev = 5;
1981
1884
  selection = editor.selection;
1982
- _context.next = 9;
1885
+ _context.next = 8;
1983
1886
  return selectEntity(config);
1984
1887
 
1985
- case 9:
1888
+ case 8:
1986
1889
  entity = _context.sent;
1987
1890
 
1988
1891
  if (entity) {
@@ -1990,6 +1893,9 @@ function _selectEntityAndInsert() {
1990
1893
  break;
1991
1894
  }
1992
1895
 
1896
+ logAction('cancelCreateEmbedDialog', {
1897
+ nodeType: nodeType
1898
+ });
1993
1899
  return _context.abrupt("return");
1994
1900
 
1995
1901
  case 12:
@@ -1998,31 +1904,13 @@ function _selectEntityAndInsert() {
1998
1904
  logAction('insert', {
1999
1905
  nodeType: nodeType
2000
1906
  });
2001
- _context.next = 24;
2002
- break;
2003
-
2004
- case 17:
2005
- _context.prev = 17;
2006
- _context.t0 = _context["catch"](5);
2007
1907
 
2008
- if (!_context.t0) {
2009
- _context.next = 23;
2010
- break;
2011
- }
2012
-
2013
- throw _context.t0;
2014
-
2015
- case 23:
2016
- logAction('cancelCreateEmbedDialog', {
2017
- nodeType: nodeType
2018
- });
2019
-
2020
- case 24:
1908
+ case 15:
2021
1909
  case "end":
2022
1910
  return _context.stop();
2023
1911
  }
2024
1912
  }
2025
- }, _callee, null, [[5, 17]]);
1913
+ }, _callee);
2026
1914
  }));
2027
1915
  return _selectEntityAndInsert.apply(this, arguments);
2028
1916
  }
@@ -2069,7 +1957,6 @@ var styles$4 = {
2069
1957
  function EmbeddedEntityBlockToolbarIcon(_ref) {
2070
1958
  var isButton = _ref.isButton,
2071
1959
  isDisabled = _ref.isDisabled,
2072
- logAction = _ref.logAction,
2073
1960
  nodeType = _ref.nodeType,
2074
1961
  onClose = _ref.onClose;
2075
1962
  var editor = useContentfulEditor();
@@ -2078,7 +1965,7 @@ function EmbeddedEntityBlockToolbarIcon(_ref) {
2078
1965
  var handleClick = function handleClick(event) {
2079
1966
  event.preventDefault();
2080
1967
  onClose();
2081
- selectEntityAndInsert(nodeType, sdk, editor, logAction || noop);
1968
+ selectEntityAndInsert(nodeType, sdk, editor, editor.tracking.onToolbarAction);
2082
1969
  };
2083
1970
 
2084
1971
  var type = getEntityTypeFromNodeType(nodeType);
@@ -2145,20 +2032,20 @@ function getWithEmbeddedEntityEvents(nodeType, sdk) {
2145
2032
  }
2146
2033
 
2147
2034
  if (hotkey && isHotkey(hotkey, event)) {
2148
- selectEntityAndInsert(nodeType, sdk, editor, noop);
2035
+ selectEntityAndInsert(nodeType, sdk, editor, editor.tracking.onShortcutAction);
2149
2036
  }
2150
2037
  };
2151
2038
  };
2152
2039
  }
2153
2040
 
2154
2041
  var createEmbeddedEntityPlugin = function createEmbeddedEntityPlugin(nodeType, hotkey) {
2155
- return function (sdk, tracking) {
2042
+ return function (sdk) {
2156
2043
  return {
2157
2044
  key: nodeType,
2158
2045
  type: nodeType,
2159
2046
  isElement: true,
2160
2047
  isVoid: true,
2161
- component: withLinkTracking(tracking, LinkedEntityBlock),
2048
+ component: withLinkTracking(LinkedEntityBlock),
2162
2049
  options: {
2163
2050
  hotkey: hotkey
2164
2051
  },
@@ -2376,44 +2263,53 @@ function EmbeddedEntityInline(props) {
2376
2263
  })), props.children);
2377
2264
  }
2378
2265
 
2379
- function selectEntityAndInsert$1(_x, _x2) {
2266
+ function selectEntityAndInsert$1(_x, _x2, _x3) {
2380
2267
  return _selectEntityAndInsert$1.apply(this, arguments);
2381
2268
  }
2382
2269
 
2383
2270
  function _selectEntityAndInsert$1() {
2384
- _selectEntityAndInsert$1 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(editor, sdk) {
2271
+ _selectEntityAndInsert$1 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(editor, sdk, logAction) {
2385
2272
  var config, selection, entry, inlineEntryNode;
2386
2273
  return runtime_1.wrap(function _callee2$(_context2) {
2387
2274
  while (1) {
2388
2275
  switch (_context2.prev = _context2.next) {
2389
2276
  case 0:
2277
+ logAction('openCreateEmbedDialog', {
2278
+ nodeType: Contentful.INLINES.EMBEDDED_ENTRY
2279
+ });
2390
2280
  config = _extends({}, newEntitySelectorConfigFromRichTextField(sdk.field, Contentful.INLINES.EMBEDDED_ENTRY), {
2391
2281
  withCreate: true
2392
2282
  });
2393
2283
  selection = editor.selection;
2394
- _context2.next = 4;
2284
+ _context2.next = 5;
2395
2285
  return sdk.dialogs.selectSingleEntry(config);
2396
2286
 
2397
- case 4:
2287
+ case 5:
2398
2288
  entry = _context2.sent;
2399
2289
  focus(editor); // Dialog steals focus from editor, return it.
2400
2290
 
2401
2291
  if (entry) {
2402
- _context2.next = 8;
2292
+ _context2.next = 10;
2403
2293
  break;
2404
2294
  }
2405
2295
 
2296
+ logAction('cancelCreateEmbedDialog', {
2297
+ nodeType: Contentful.INLINES.EMBEDDED_ENTRY
2298
+ });
2406
2299
  return _context2.abrupt("return");
2407
2300
 
2408
- case 8:
2301
+ case 10:
2409
2302
  inlineEntryNode = createInlineEntryNode(entry.sys.id); // Got to wait until focus is really back on the editor or setSelection() won't work.
2410
2303
 
2411
2304
  setTimeout(function () {
2412
2305
  slate.Transforms.setSelection(editor, selection);
2413
2306
  slate.Transforms.insertNodes(editor, inlineEntryNode);
2414
2307
  }, 0);
2308
+ logAction('insert', {
2309
+ nodeType: Contentful.INLINES.EMBEDDED_ENTRY
2310
+ });
2415
2311
 
2416
- case 10:
2312
+ case 13:
2417
2313
  case "end":
2418
2314
  return _context2.stop();
2419
2315
  }
@@ -2427,7 +2323,7 @@ function ToolbarEmbeddedEntityInlineButton(props) {
2427
2323
  var editor = useContentfulEditor();
2428
2324
  var sdk = useSdkContext();
2429
2325
 
2430
- function handleClick(_x3) {
2326
+ function handleClick(_x4) {
2431
2327
  return _handleClick.apply(this, arguments);
2432
2328
  }
2433
2329
 
@@ -2449,7 +2345,7 @@ function ToolbarEmbeddedEntityInlineButton(props) {
2449
2345
  case 3:
2450
2346
  props.onClose();
2451
2347
  _context.next = 6;
2452
- return selectEntityAndInsert$1(editor, sdk);
2348
+ return selectEntityAndInsert$1(editor, sdk, editor.tracking.onToolbarAction);
2453
2349
 
2454
2350
  case 6:
2455
2351
  case "end":
@@ -2482,7 +2378,7 @@ function ToolbarEmbeddedEntityInlineButton(props) {
2482
2378
  className: "rich-text__embedded-entry-list-icon " + styles$6.icon
2483
2379
  }), /*#__PURE__*/React.createElement("span", null, "Inline entry")));
2484
2380
  }
2485
- function createEmbeddedEntityInlinePlugin(sdk, tracking) {
2381
+ function createEmbeddedEntityInlinePlugin(sdk) {
2486
2382
  var htmlAttributeName = 'data-embedded-entity-inline-id';
2487
2383
  return {
2488
2384
  key: Contentful.INLINES.EMBEDDED_ENTRY,
@@ -2490,7 +2386,7 @@ function createEmbeddedEntityInlinePlugin(sdk, tracking) {
2490
2386
  isElement: true,
2491
2387
  isInline: true,
2492
2388
  isVoid: true,
2493
- component: withLinkTracking(tracking, EmbeddedEntityInline),
2389
+ component: withLinkTracking(EmbeddedEntityInline),
2494
2390
  options: {
2495
2391
  hotkey: 'mod+shift+2'
2496
2392
  },
@@ -2516,7 +2412,7 @@ function getWithEmbeddedEntryInlineEvents(sdk) {
2516
2412
  if (!editor) return;
2517
2413
 
2518
2414
  if (hotkey && isHotkey(hotkey, event)) {
2519
- selectEntityAndInsert$1(editor, sdk);
2415
+ selectEntityAndInsert$1(editor, sdk, editor.tracking.onShortcutAction);
2520
2416
  }
2521
2417
  };
2522
2418
  };
@@ -2599,11 +2495,6 @@ function ToolbarHeadingButton(props) {
2599
2495
  if (!(editor != null && editor.selection)) return;
2600
2496
  setSelected(type);
2601
2497
  setOpen(false);
2602
-
2603
- if (shouldUnwrapBlockquote(editor, type)) {
2604
- unwrapFromRoot(editor);
2605
- }
2606
-
2607
2498
  var prevOnChange = editor.onChange;
2608
2499
  /*
2609
2500
  The focus might happen at point in time when
@@ -2619,6 +2510,10 @@ function ToolbarHeadingButton(props) {
2619
2510
  prevOnChange.apply(void 0, arguments);
2620
2511
  };
2621
2512
 
2513
+ var isActive = isBlockSelected(editor, type);
2514
+ editor.tracking.onToolbarAction(isActive ? 'remove' : 'insert', {
2515
+ nodeType: type
2516
+ });
2622
2517
  plateCore.toggleNodeType(editor, {
2623
2518
  activeType: type,
2624
2519
  inactiveType: type
@@ -2740,6 +2635,24 @@ function createHeading(Tag, block) {
2740
2635
 
2741
2636
  var HeadingComponents = (_HeadingComponents = {}, _HeadingComponents[Contentful.BLOCKS.HEADING_1] = /*#__PURE__*/React.memo( /*#__PURE__*/createHeading('h1', Contentful.BLOCKS.HEADING_1)), _HeadingComponents[Contentful.BLOCKS.HEADING_2] = /*#__PURE__*/React.memo( /*#__PURE__*/createHeading('h2', Contentful.BLOCKS.HEADING_2)), _HeadingComponents[Contentful.BLOCKS.HEADING_3] = /*#__PURE__*/React.memo( /*#__PURE__*/createHeading('h3', Contentful.BLOCKS.HEADING_3)), _HeadingComponents[Contentful.BLOCKS.HEADING_4] = /*#__PURE__*/React.memo( /*#__PURE__*/createHeading('h4', Contentful.BLOCKS.HEADING_4)), _HeadingComponents[Contentful.BLOCKS.HEADING_5] = /*#__PURE__*/React.memo( /*#__PURE__*/createHeading('h5', Contentful.BLOCKS.HEADING_5)), _HeadingComponents[Contentful.BLOCKS.HEADING_6] = /*#__PURE__*/React.memo( /*#__PURE__*/createHeading('h6', Contentful.BLOCKS.HEADING_6)), _HeadingComponents);
2742
2637
 
2638
+ var buildHeadingEventHandler = function buildHeadingEventHandler(type) {
2639
+ return function (editor, _ref) {
2640
+ var hotkey = _ref.options.hotkey;
2641
+ return function (event) {
2642
+ if (editor.selection && hotkey && isHotkey(hotkey, event)) {
2643
+ var isActive = isBlockSelected(editor, type);
2644
+ editor.tracking.onShortcutAction(isActive ? 'remove' : 'insert', {
2645
+ nodeType: type
2646
+ });
2647
+ plateCore.toggleNodeType(editor, {
2648
+ activeType: type,
2649
+ inactiveType: Contentful.BLOCKS.PARAGRAPH
2650
+ });
2651
+ }
2652
+ };
2653
+ };
2654
+ };
2655
+
2743
2656
  var createHeadingPlugin = function createHeadingPlugin() {
2744
2657
  var _transform;
2745
2658
 
@@ -2756,8 +2669,8 @@ var createHeadingPlugin = function createHeadingPlugin() {
2756
2669
  match: {
2757
2670
  type: Contentful.HEADINGS
2758
2671
  },
2759
- validChildren: function validChildren(_, _ref) {
2760
- var node = _ref[0];
2672
+ validChildren: function validChildren(_, _ref2) {
2673
+ var node = _ref2[0];
2761
2674
  return isInlineOrText(node);
2762
2675
  },
2763
2676
  transform: (_transform = {}, _transform[Contentful.BLOCKS.PARAGRAPH] = transformUnwrap, _transform["default"] = transformLift, _transform)
@@ -2774,8 +2687,8 @@ var createHeadingPlugin = function createHeadingPlugin() {
2774
2687
  start: true,
2775
2688
  // Exclude headings inside lists as it interferes with the list's
2776
2689
  // insertBreak implementation
2777
- filter: function filter(_ref2) {
2778
- var path = _ref2[1];
2690
+ filter: function filter(_ref3) {
2691
+ var path = _ref3[1];
2779
2692
  return !plateCore.getAbove(editor, {
2780
2693
  at: path,
2781
2694
  match: {
@@ -2799,7 +2712,7 @@ var createHeadingPlugin = function createHeadingPlugin() {
2799
2712
  hotkey: ["mod+alt+" + level]
2800
2713
  },
2801
2714
  handlers: {
2802
- onKeyDown: plateCore.onKeyDownToggleElement
2715
+ onKeyDown: buildHeadingEventHandler(nodeType)
2803
2716
  },
2804
2717
  deserializeHtml: {
2805
2718
  rules: [{
@@ -2871,10 +2784,6 @@ function withHrEvents(editor) {
2871
2784
  pathToSelectedHr = _getNodeEntryFromSele[1];
2872
2785
 
2873
2786
  if (pathToSelectedHr) {
2874
- if (shouldUnwrapBlockquote(editor, Contentful.BLOCKS.HR)) {
2875
- unwrapFromRoot(editor);
2876
- }
2877
-
2878
2787
  var isBackspace = event.key === 'Backspace';
2879
2788
  var isDelete = event.key === 'Delete';
2880
2789
 
@@ -2892,11 +2801,6 @@ function ToolbarHrButton(props) {
2892
2801
 
2893
2802
  function handleOnClick() {
2894
2803
  if (!(editor != null && editor.selection)) return;
2895
-
2896
- if (shouldUnwrapBlockquote(editor, Contentful.BLOCKS.HR)) {
2897
- unwrapFromRoot(editor);
2898
- }
2899
-
2900
2804
  var hr = {
2901
2805
  type: Contentful.BLOCKS.HR,
2902
2806
  data: {},
@@ -3329,13 +3233,15 @@ function HyperlinkModal(props) {
3329
3233
  testId: "confirm-cta"
3330
3234
  }, props.linkType ? 'Update' : 'Insert'))));
3331
3235
  }
3332
- function addOrEditLink(_x, _x2) {
3236
+ function addOrEditLink(_x, _x2, _x3) {
3333
3237
  return _addOrEditLink.apply(this, arguments);
3334
3238
  }
3335
3239
 
3336
3240
  function _addOrEditLink() {
3337
- _addOrEditLink = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(editor, sdk) {
3338
- var linkType, linkText, linkTarget, linkEntity, _getNodeEntryFromSele, node, path, selectionBeforeBlur, currentLinkText, data, text, url, type, target;
3241
+ _addOrEditLink = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(editor, sdk, logAction) {
3242
+ var _target$sys$linkType;
3243
+
3244
+ var linkType, linkText, linkTarget, linkEntity, _getNodeEntryFromSele, node, path, selectionBeforeBlur, currentLinkText, isEditing, data, text, url, type, target;
3339
3245
 
3340
3246
  return runtime_1.wrap(function _callee3$(_context3) {
3341
3247
  while (1) {
@@ -3360,9 +3266,11 @@ function _addOrEditLink() {
3360
3266
 
3361
3267
  selectionBeforeBlur = _extends({}, editor.selection);
3362
3268
  currentLinkText = linkText || slate.Editor.string(editor, editor.selection);
3363
- _context3.next = 8;
3269
+ isEditing = Boolean(node && path);
3270
+ logAction(isEditing ? 'openEditHyperlinkDialog' : 'openCreateHyperlinkDialog');
3271
+ _context3.next = 10;
3364
3272
  return fieldEditorShared.ModalDialogLauncher.openDialog({
3365
- title: linkType ? 'Edit hyperlink' : 'Insert hyperlink',
3273
+ title: isEditing ? 'Edit hyperlink' : 'Insert hyperlink',
3366
3274
  width: 'large',
3367
3275
  shouldCloseOnEscapePress: true,
3368
3276
  shouldCloseOnOverlayClick: true,
@@ -3379,17 +3287,18 @@ function _addOrEditLink() {
3379
3287
  });
3380
3288
  });
3381
3289
 
3382
- case 8:
3290
+ case 10:
3383
3291
  data = _context3.sent;
3384
3292
 
3385
3293
  if (data) {
3386
- _context3.next = 11;
3294
+ _context3.next = 14;
3387
3295
  break;
3388
3296
  }
3389
3297
 
3298
+ logAction(isEditing ? 'cancelEditHyperlinkDialog' : 'cancelCreateHyperlinkDialog');
3390
3299
  return _context3.abrupt("return");
3391
3300
 
3392
- case 11:
3301
+ case 14:
3393
3302
  text = data.linkText, url = data.linkTarget, type = data.linkType, target = data.linkEntity;
3394
3303
  slate.Transforms.select(editor, selectionBeforeBlur);
3395
3304
  slate.Editor.withoutNormalizing(editor, function () {
@@ -3401,9 +3310,13 @@ function _addOrEditLink() {
3401
3310
  path: path
3402
3311
  });
3403
3312
  });
3313
+ logAction(isEditing ? 'edit' : 'insert', {
3314
+ nodeType: type,
3315
+ linkType: (_target$sys$linkType = target == null ? void 0 : target.sys.linkType) != null ? _target$sys$linkType : 'uri'
3316
+ });
3404
3317
  focus(editor);
3405
3318
 
3406
- case 15:
3319
+ case 19:
3407
3320
  case "end":
3408
3321
  return _context3.stop();
3409
3322
  }
@@ -3467,7 +3380,7 @@ function UrlHyperlink(props) {
3467
3380
  event.preventDefault();
3468
3381
  event.stopPropagation();
3469
3382
  if (!editor) return;
3470
- addOrEditLink(editor, sdk);
3383
+ addOrEditLink(editor, sdk, editor.tracking.onViewportAction);
3471
3384
  }
3472
3385
 
3473
3386
  return /*#__PURE__*/React.createElement(f36Components.Tooltip, {
@@ -3503,7 +3416,7 @@ function EntityHyperlink(props) {
3503
3416
  event.preventDefault();
3504
3417
  event.stopPropagation();
3505
3418
  if (!editor) return;
3506
- addOrEditLink(editor, sdk);
3419
+ addOrEditLink(editor, sdk, editor.tracking.onViewportAction);
3507
3420
  }
3508
3421
 
3509
3422
  return /*#__PURE__*/React.createElement(f36Components.Tooltip, {
@@ -3550,8 +3463,9 @@ function ToolbarHyperlinkButton(props) {
3550
3463
  case 2:
3551
3464
  if (isActive) {
3552
3465
  unwrapLink(editor);
3466
+ editor.tracking.onToolbarAction('unlinkHyperlinks');
3553
3467
  } else {
3554
- addOrEditLink(editor, sdk);
3468
+ addOrEditLink(editor, sdk, editor.tracking.onToolbarAction);
3555
3469
  }
3556
3470
 
3557
3471
  case 3:
@@ -3600,8 +3514,9 @@ var buildHyperlinkEventHandler = function buildHyperlinkEventHandler(sdk) {
3600
3514
 
3601
3515
  if (isLinkActive(editor)) {
3602
3516
  unwrapLink(editor);
3517
+ editor.tracking.onShortcutAction('unlinkHyperlinks');
3603
3518
  } else {
3604
- addOrEditLink(editor, sdk);
3519
+ addOrEditLink(editor, sdk, editor.tracking.onShortcutAction);
3605
3520
  }
3606
3521
  };
3607
3522
  };
@@ -3627,7 +3542,7 @@ var getNodeOfType = function getNodeOfType(type) {
3627
3542
  };
3628
3543
  };
3629
3544
 
3630
- var createHyperlinkPlugin = function createHyperlinkPlugin(sdk, tracking) {
3545
+ var createHyperlinkPlugin = function createHyperlinkPlugin(sdk) {
3631
3546
  var common = {
3632
3547
  isElement: true,
3633
3548
  isInline: true
@@ -3658,7 +3573,7 @@ var createHyperlinkPlugin = function createHyperlinkPlugin(sdk, tracking) {
3658
3573
  _extends({}, common, {
3659
3574
  key: Contentful.INLINES.ENTRY_HYPERLINK,
3660
3575
  type: Contentful.INLINES.ENTRY_HYPERLINK,
3661
- component: withLinkTracking(tracking, EntityHyperlink),
3576
+ component: withLinkTracking(EntityHyperlink),
3662
3577
  deserializeHtml: {
3663
3578
  rules: [{
3664
3579
  validNodeName: ['A']
@@ -3672,7 +3587,7 @@ var createHyperlinkPlugin = function createHyperlinkPlugin(sdk, tracking) {
3672
3587
  _extends({}, common, {
3673
3588
  key: Contentful.INLINES.ASSET_HYPERLINK,
3674
3589
  type: Contentful.INLINES.ASSET_HYPERLINK,
3675
- component: withLinkTracking(tracking, EntityHyperlink),
3590
+ component: withLinkTracking(EntityHyperlink),
3676
3591
  deserializeHtml: {
3677
3592
  rules: [{
3678
3593
  validNodeName: ['A']
@@ -3795,6 +3710,16 @@ var replaceNodeWithListItems = function replaceNodeWithListItems(editor, entry)
3795
3710
  at: path
3796
3711
  });
3797
3712
  };
3713
+ var isListTypeActive = function isListTypeActive(editor, type) {
3714
+ // Lists can be nested. Here, we take the list type at the lowest level
3715
+ var listNode = plateCore.getBlockAbove(editor, {
3716
+ match: {
3717
+ type: [Contentful.BLOCKS.OL_LIST, Contentful.BLOCKS.UL_LIST]
3718
+ },
3719
+ mode: 'lowest'
3720
+ });
3721
+ return (listNode == null ? void 0 : listNode[0].type) === type;
3722
+ };
3798
3723
 
3799
3724
  /**
3800
3725
  * Build a new list item node while preserving marks
@@ -4146,6 +4071,7 @@ var createListPlugin = function createListPlugin() {
4146
4071
  }, _overrideByKey[plateList.ELEMENT_LI] = {
4147
4072
  type: Contentful.BLOCKS.LIST_ITEM,
4148
4073
  component: ListItem,
4074
+ // @ts-expect-error
4149
4075
  normalizer: [{
4150
4076
  validNode: hasListAsDirectParent,
4151
4077
  transform: normalizeOrphanedListItem
@@ -4170,11 +4096,6 @@ function ToolbarListButton(props) {
4170
4096
  function handleClick(type) {
4171
4097
  return function () {
4172
4098
  if (!(editor != null && editor.selection)) return;
4173
-
4174
- if (shouldUnwrapBlockquote(editor, type)) {
4175
- unwrapFromRoot(editor);
4176
- }
4177
-
4178
4099
  plateList.toggleList(editor, {
4179
4100
  type: type
4180
4101
  });
@@ -4187,37 +4108,73 @@ function ToolbarListButton(props) {
4187
4108
  title: "UL",
4188
4109
  testId: "ul-toolbar-button",
4189
4110
  onClick: handleClick(Contentful.BLOCKS.UL_LIST),
4190
- isActive: isBlockSelected(editor, Contentful.BLOCKS.UL_LIST),
4111
+ isActive: isListTypeActive(editor, Contentful.BLOCKS.UL_LIST),
4191
4112
  isDisabled: props.isDisabled
4192
4113
  }, /*#__PURE__*/React.createElement(f36Icons.ListBulletedIcon, null)), isNodeTypeEnabled(sdk.field, Contentful.BLOCKS.OL_LIST) && /*#__PURE__*/React.createElement(ToolbarButton, {
4193
4114
  title: "OL",
4194
4115
  testId: "ol-toolbar-button",
4195
4116
  onClick: handleClick(Contentful.BLOCKS.OL_LIST),
4196
- isActive: isBlockSelected(editor, Contentful.BLOCKS.OL_LIST),
4117
+ isActive: isListTypeActive(editor, Contentful.BLOCKS.OL_LIST),
4197
4118
  isDisabled: props.isDisabled
4198
4119
  }, /*#__PURE__*/React.createElement(f36Icons.ListNumberedIcon, null)));
4199
4120
  }
4200
4121
 
4201
- function ToolbarBoldButton(props) {
4202
- var editor = useContentfulEditor();
4122
+ var createMarkToolbarButton = function createMarkToolbarButton(_ref) {
4123
+ var mark = _ref.mark,
4124
+ title = _ref.title,
4125
+ icon = _ref.icon;
4203
4126
 
4204
- function handleClick() {
4205
- if (!(editor != null && editor.selection)) return;
4206
- plateCore.toggleMark(editor, {
4207
- key: Contentful.MARKS.BOLD
4208
- });
4209
- focus(editor);
4210
- }
4127
+ var Mark = function Mark(_ref2) {
4128
+ var isDisabled = _ref2.isDisabled;
4129
+ var editor = useContentfulEditor();
4130
+ var handleClick = React.useCallback(function () {
4131
+ if (!(editor != null && editor.selection)) return;
4132
+ var isActive = plateCore.isMarkActive(editor, mark);
4133
+ editor.tracking.onToolbarAction(isActive ? 'unmark' : 'mark', {
4134
+ markType: mark
4135
+ });
4136
+ plateCore.toggleMark(editor, {
4137
+ key: mark
4138
+ });
4139
+ focus(editor);
4140
+ }, [editor]);
4141
+ if (!editor) return null;
4142
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
4143
+ title: title,
4144
+ testId: mark + "-toolbar-button",
4145
+ onClick: handleClick,
4146
+ isActive: plateCore.isMarkActive(editor, mark),
4147
+ isDisabled: isDisabled
4148
+ }, icon);
4149
+ };
4211
4150
 
4212
- if (!editor) return null;
4213
- return /*#__PURE__*/React.createElement(ToolbarButton, {
4214
- title: "Bold",
4215
- testId: "bold-toolbar-button",
4216
- onClick: handleClick,
4217
- isActive: plateCore.isMarkActive(editor, Contentful.MARKS.BOLD),
4218
- isDisabled: props.isDisabled
4219
- }, /*#__PURE__*/React.createElement(f36Icons.FormatBoldIcon, null));
4220
- }
4151
+ Mark.displayName = mark;
4152
+ return Mark;
4153
+ };
4154
+
4155
+ var buildMarkEventHandler = function buildMarkEventHandler(type) {
4156
+ return function (editor, _ref) {
4157
+ var hotkey = _ref.options.hotkey;
4158
+ return function (event) {
4159
+ if (editor.selection && hotkey && isHotkey(hotkey, event)) {
4160
+ event.preventDefault();
4161
+ var isActive = plateCore.isMarkActive(editor, type);
4162
+ editor.tracking.onShortcutAction(isActive ? 'unmark' : 'mark', {
4163
+ markType: type
4164
+ });
4165
+ plateCore.toggleMark(editor, {
4166
+ key: type
4167
+ });
4168
+ }
4169
+ };
4170
+ };
4171
+ };
4172
+
4173
+ var ToolbarBoldButton = /*#__PURE__*/createMarkToolbarButton({
4174
+ title: 'Bold',
4175
+ mark: Contentful.MARKS.BOLD,
4176
+ icon: /*#__PURE__*/React.createElement(f36Icons.FormatBoldIcon, null)
4177
+ });
4221
4178
  var styles$e = {
4222
4179
  bold: /*#__PURE__*/emotion.css({
4223
4180
  fontWeight: 600
@@ -4240,6 +4197,9 @@ var createBoldPlugin = function createBoldPlugin() {
4240
4197
  options: {
4241
4198
  hotkey: ['mod+b']
4242
4199
  },
4200
+ handlers: {
4201
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.BOLD)
4202
+ },
4243
4203
  deserializeHtml: {
4244
4204
  rules: [{
4245
4205
  validNodeName: ['STRONG', 'B']
@@ -4257,26 +4217,11 @@ var createBoldPlugin = function createBoldPlugin() {
4257
4217
  });
4258
4218
  };
4259
4219
 
4260
- function ToolbarCodeButton(props) {
4261
- var editor = useContentfulEditor();
4262
-
4263
- function handleClick() {
4264
- if (!(editor != null && editor.selection)) return;
4265
- plateCore.toggleMark(editor, {
4266
- key: Contentful.MARKS.CODE
4267
- });
4268
- focus(editor);
4269
- }
4270
-
4271
- if (!editor) return null;
4272
- return /*#__PURE__*/React.createElement(ToolbarButton, {
4273
- title: "Code",
4274
- testId: "code-toolbar-button",
4275
- onClick: handleClick,
4276
- isActive: plateCore.isMarkActive(editor, Contentful.MARKS.CODE),
4277
- isDisabled: props.isDisabled
4278
- }, /*#__PURE__*/React.createElement(f36Icons.CodeIcon, null));
4279
- }
4220
+ var ToolbarCodeButton = /*#__PURE__*/createMarkToolbarButton({
4221
+ title: 'Code',
4222
+ mark: Contentful.MARKS.CODE,
4223
+ icon: /*#__PURE__*/React.createElement(f36Icons.CodeIcon, null)
4224
+ });
4280
4225
  var styles$f = {
4281
4226
  code: /*#__PURE__*/emotion.css({
4282
4227
  fontFamily: 'monospace',
@@ -4295,6 +4240,9 @@ var createCodePlugin = function createCodePlugin() {
4295
4240
  options: {
4296
4241
  hotkey: ['mod+/']
4297
4242
  },
4243
+ handlers: {
4244
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.CODE)
4245
+ },
4298
4246
  deserializeHtml: {
4299
4247
  rules: [{
4300
4248
  validNodeName: ['CODE', 'PRE']
@@ -4307,26 +4255,11 @@ var createCodePlugin = function createCodePlugin() {
4307
4255
  });
4308
4256
  };
4309
4257
 
4310
- function ToolbarItalicButton(props) {
4311
- var editor = useContentfulEditor();
4312
-
4313
- function handleClick() {
4314
- if (!(editor != null && editor.selection)) return;
4315
- plateCore.toggleMark(editor, {
4316
- key: Contentful.MARKS.ITALIC
4317
- });
4318
- focus(editor);
4319
- }
4320
-
4321
- if (!editor) return null;
4322
- return /*#__PURE__*/React.createElement(ToolbarButton, {
4323
- title: "Italic",
4324
- testId: "italic-toolbar-button",
4325
- onClick: handleClick,
4326
- isActive: plateCore.isMarkActive(editor, Contentful.MARKS.ITALIC),
4327
- isDisabled: props.isDisabled
4328
- }, /*#__PURE__*/React.createElement(f36Icons.FormatItalicIcon, null));
4329
- }
4258
+ var ToolbarItalicButton = /*#__PURE__*/createMarkToolbarButton({
4259
+ title: 'Italic',
4260
+ mark: Contentful.MARKS.ITALIC,
4261
+ icon: /*#__PURE__*/React.createElement(f36Icons.FormatItalicIcon, null)
4262
+ });
4330
4263
  var styles$g = {
4331
4264
  italic: /*#__PURE__*/emotion.css({
4332
4265
  fontStyle: 'italic'
@@ -4344,6 +4277,9 @@ var createItalicPlugin = function createItalicPlugin() {
4344
4277
  options: {
4345
4278
  hotkey: ['mod+i']
4346
4279
  },
4280
+ handlers: {
4281
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.ITALIC)
4282
+ },
4347
4283
  deserializeHtml: {
4348
4284
  rules: [{
4349
4285
  validNodeName: ['I', 'EM']
@@ -4361,26 +4297,11 @@ var createItalicPlugin = function createItalicPlugin() {
4361
4297
  });
4362
4298
  };
4363
4299
 
4364
- function ToolbarUnderlineButton(props) {
4365
- var editor = useContentfulEditor();
4366
-
4367
- function handleClick() {
4368
- if (!(editor != null && editor.selection)) return;
4369
- plateCore.toggleMark(editor, {
4370
- key: Contentful.MARKS.UNDERLINE
4371
- });
4372
- focus(editor);
4373
- }
4374
-
4375
- if (!editor) return null;
4376
- return /*#__PURE__*/React.createElement(ToolbarButton, {
4377
- title: "Underline",
4378
- testId: "underline-toolbar-button",
4379
- onClick: handleClick,
4380
- isActive: plateCore.isMarkActive(editor, Contentful.MARKS.UNDERLINE),
4381
- isDisabled: props.isDisabled
4382
- }, /*#__PURE__*/React.createElement(f36Icons.FormatUnderlinedIcon, null));
4383
- }
4300
+ var ToolbarUnderlineButton = /*#__PURE__*/createMarkToolbarButton({
4301
+ title: 'Underline',
4302
+ mark: Contentful.MARKS.UNDERLINE,
4303
+ icon: /*#__PURE__*/React.createElement(f36Icons.FormatUnderlinedIcon, null)
4304
+ });
4384
4305
  function Underline(props) {
4385
4306
  return /*#__PURE__*/React.createElement("u", Object.assign({}, props.attributes), props.children);
4386
4307
  }
@@ -4391,6 +4312,9 @@ var createUnderlinePlugin = function createUnderlinePlugin() {
4391
4312
  options: {
4392
4313
  hotkey: ['mod+u']
4393
4314
  },
4315
+ handlers: {
4316
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.UNDERLINE)
4317
+ },
4394
4318
  deserializeHtml: {
4395
4319
  rules: [{
4396
4320
  validNodeName: ['U']
@@ -4613,6 +4537,7 @@ var withNormalizer = function withNormalizer(editor) {
4613
4537
  var createNormalizerPlugin = function createNormalizerPlugin() {
4614
4538
  return {
4615
4539
  key: 'NormalizerPlugin',
4540
+ // @ts-expect-error
4616
4541
  withOverrides: withNormalizer
4617
4542
  };
4618
4543
  };
@@ -4756,11 +4681,54 @@ var sanitizeHTML = function sanitizeHTML(html) {
4756
4681
  return doc.body.innerHTML.replace(/>\s+</g, '><');
4757
4682
  };
4758
4683
 
4684
+ /**
4685
+ * Get x-slate-fragment attribute from data-slate-fragment
4686
+ */
4687
+
4688
+ var catchSlateFragment = /data-slate-fragment="(.+?)"/m;
4689
+ var getSlateFragmentAttribute = function getSlateFragmentAttribute(dataTransfer) {
4690
+ var htmlData = dataTransfer.getData('text/html');
4691
+
4692
+ var _ref = htmlData.match(catchSlateFragment) || [],
4693
+ fragment = _ref[1];
4694
+
4695
+ return fragment;
4696
+ };
4697
+ /**
4698
+ * Get the x-slate-fragment attribute that exist in text/html data
4699
+ * and append it to the DataTransfer object
4700
+ */
4701
+
4702
+ var ensureXSlateFragment = function ensureXSlateFragment(dataTransfer) {
4703
+ if (!dataTransfer.getData('application/x-slate-fragment')) {
4704
+ var fragment = getSlateFragmentAttribute(dataTransfer);
4705
+
4706
+ if (fragment) {
4707
+ var clipboardData = new DataTransfer();
4708
+ dataTransfer.types.forEach(function (type) {
4709
+ clipboardData.setData(type, dataTransfer.getData(type));
4710
+ });
4711
+ clipboardData.setData('application/x-slate-fragment', fragment);
4712
+ return clipboardData;
4713
+ }
4714
+ }
4715
+
4716
+ return dataTransfer;
4717
+ };
4759
4718
  var createPasteHTMLPlugin = function createPasteHTMLPlugin() {
4760
4719
  var _pluginsByKey;
4761
4720
 
4762
4721
  return {
4763
4722
  key: 'PasteHTMLPlugin',
4723
+ withOverrides: function withOverrides(editor) {
4724
+ var insertData = editor.insertData;
4725
+
4726
+ editor.insertData = function (data) {
4727
+ return insertData(ensureXSlateFragment(data));
4728
+ };
4729
+
4730
+ return editor;
4731
+ },
4764
4732
  inject: {
4765
4733
  pluginsByKey: (_pluginsByKey = {}, _pluginsByKey[plateCore.KEY_DESERIALIZE_HTML] = {
4766
4734
  editor: {
@@ -4779,10 +4747,7 @@ var style$1 = /*#__PURE__*/emotion.css({
4779
4747
  margin: '0 0 1.3125rem',
4780
4748
  borderLeft: "6px solid " + tokens.gray200,
4781
4749
  paddingLeft: '0.875rem',
4782
- fontStyle: 'normal',
4783
- '& a': {
4784
- color: 'inherit'
4785
- }
4750
+ fontStyle: 'normal'
4786
4751
  });
4787
4752
  function Quote(props) {
4788
4753
  return /*#__PURE__*/React.createElement("blockquote", Object.assign({}, props.attributes, {
@@ -4790,9 +4755,12 @@ function Quote(props) {
4790
4755
  }), props.children);
4791
4756
  }
4792
4757
 
4793
- function toggleQuote(editor) {
4758
+ function toggleQuote(editor, logAction) {
4794
4759
  if (!editor.selection) return;
4795
4760
  var isActive = isBlockSelected(editor, Contentful.BLOCKS.QUOTE);
4761
+ logAction(isActive ? 'remove' : 'insert', {
4762
+ nodeType: Contentful.BLOCKS.QUOTE
4763
+ });
4796
4764
  slate.Editor.withoutNormalizing(editor, function () {
4797
4765
  if (!editor.selection) return;
4798
4766
  slate.Transforms.unwrapNodes(editor, {
@@ -4824,7 +4792,7 @@ var onKeyDownToggleQuote = function onKeyDownToggleQuote(editor, plugin) {
4824
4792
 
4825
4793
  if (hotkey && isHotkey(hotkey, event)) {
4826
4794
  event.preventDefault();
4827
- toggleQuote(editor);
4795
+ toggleQuote(editor, editor.tracking.onShortcutAction);
4828
4796
  }
4829
4797
  };
4830
4798
  };
@@ -4850,8 +4818,55 @@ function createQuotePlugin() {
4850
4818
  },
4851
4819
  normalizer: [{
4852
4820
  validChildren: Contentful.CONTAINERS[Contentful.BLOCKS.QUOTE],
4853
- transform: (_transform = {}, _transform[Contentful.BLOCKS.QUOTE] = transformUnwrap, _transform[Contentful.BLOCKS.HEADING_1] = transformUnwrap, _transform[Contentful.BLOCKS.HEADING_2] = transformUnwrap, _transform[Contentful.BLOCKS.HEADING_3] = transformUnwrap, _transform[Contentful.BLOCKS.HEADING_4] = transformUnwrap, _transform[Contentful.BLOCKS.HEADING_5] = transformUnwrap, _transform[Contentful.BLOCKS.HEADING_6] = transformUnwrap, _transform["default"] = transformLift, _transform)
4854
- }]
4821
+ transform: (_transform = {}, _transform[Contentful.BLOCKS.QUOTE] = transformUnwrap, _transform["default"] = transformLift, _transform)
4822
+ }],
4823
+ withOverrides: function withOverrides(editor) {
4824
+ var insertFragment = editor.insertFragment;
4825
+
4826
+ editor.insertFragment = function (fragment) {
4827
+ var startingNode = fragment.length && fragment[0];
4828
+ var startsWithBlockquote = slate.Element.isElement(startingNode) && startingNode.type === Contentful.BLOCKS.QUOTE;
4829
+ var containerEntry = plateCore.getAbove(editor, {
4830
+ match: {
4831
+ type: Contentful.TEXT_CONTAINERS
4832
+ }
4833
+ });
4834
+ var containerIsNotEmpty = containerEntry && slate.Node.string(containerEntry[0]) !== '';
4835
+
4836
+ if (startsWithBlockquote && containerIsNotEmpty) {
4837
+ var selection = editor.selection;
4838
+
4839
+ var isContentSelected = function isContentSelected(selection) {
4840
+ return !!selection && slate.Point.compare(selection.anchor, selection.focus) !== 0;
4841
+ }; // if something is selected (highlighted) we replace the selection
4842
+
4843
+
4844
+ if (isContentSelected(selection)) {
4845
+ slate.Transforms["delete"](editor, {
4846
+ at: selection
4847
+ });
4848
+ } // get the cursor entry again, it may be different after deletion
4849
+
4850
+
4851
+ var _containerEntry = plateCore.getAbove(editor, {
4852
+ match: {
4853
+ type: Contentful.TEXT_CONTAINERS
4854
+ }
4855
+ });
4856
+
4857
+ var _containerIsNotEmpty = _containerEntry && slate.Node.string(_containerEntry[0]) !== '';
4858
+
4859
+ if (_containerIsNotEmpty) {
4860
+ slate.Transforms.insertNodes(editor, fragment);
4861
+ return;
4862
+ }
4863
+ }
4864
+
4865
+ insertFragment(fragment);
4866
+ };
4867
+
4868
+ return editor;
4869
+ }
4855
4870
  };
4856
4871
  }
4857
4872
 
@@ -4860,7 +4875,7 @@ function ToolbarQuoteButton(props) {
4860
4875
 
4861
4876
  function handleOnClick() {
4862
4877
  if (!editor) return;
4863
- toggleQuote(editor);
4878
+ toggleQuote(editor, editor.tracking.onToolbarAction);
4864
4879
  focus(editor);
4865
4880
  }
4866
4881
 
@@ -4909,8 +4924,7 @@ function hasHeadersOutsideFirstRow(nodes) {
4909
4924
  });
4910
4925
  }
4911
4926
 
4912
- function addTableTrackingEvents(editor, _ref6) {
4913
- var onViewportAction = _ref6.onViewportAction;
4927
+ function addTableTrackingEvents(editor) {
4914
4928
  var insertData = editor.insertData;
4915
4929
 
4916
4930
  editor.insertData = function (data) {
@@ -4924,7 +4938,7 @@ function addTableTrackingEvents(editor, _ref6) {
4924
4938
  if (hasTables(markupBefore)) return;
4925
4939
 
4926
4940
  if (hasTables(markupAfter)) {
4927
- onViewportAction('paste', {
4941
+ editor.tracking.onViewportAction('paste', {
4928
4942
  tablePasted: true,
4929
4943
  hasHeadersOutsideFirstRow: hasHeadersOutsideFirstRow(markupAfter)
4930
4944
  });
@@ -4936,29 +4950,6 @@ function addTableTrackingEvents(editor, _ref6) {
4936
4950
  };
4937
4951
  }
4938
4952
 
4939
- function useTracking(_ref) {
4940
- var onAction = _ref.onAction;
4941
- var trackingMemo = React.useMemo(function () {
4942
- return {
4943
- onViewportAction: function onViewportAction(actionName, data) {
4944
- if (data === void 0) {
4945
- data = {};
4946
- }
4947
-
4948
- return onAction(actionName, _extends({
4949
- origin: 'viewport-interaction'
4950
- }, data));
4951
- }
4952
- };
4953
- }, [] // eslint-disable-line
4954
- );
4955
- return trackingMemo;
4956
- }
4957
-
4958
- var _constate$2 = /*#__PURE__*/constate(useTracking),
4959
- TrackingProvider = _constate$2[0],
4960
- useTrackingContext = _constate$2[1];
4961
-
4962
4953
  var addRow = function addRow(editor, getNextRowPath) {
4963
4954
  if (plateCore.someNode(editor, {
4964
4955
  match: {
@@ -5204,9 +5195,6 @@ var TableActions = function TableActions() {
5204
5195
  var editor = useContentfulEditor();
5205
5196
  var isDisabled = Slate.useReadOnly();
5206
5197
 
5207
- var _useTrackingContext = useTrackingContext(),
5208
- onViewportAction = _useTrackingContext.onViewportAction;
5209
-
5210
5198
  var _React$useState = React__default.useState(false),
5211
5199
  isOpen = _React$useState[0],
5212
5200
  setOpen = _React$useState[1];
@@ -5256,11 +5244,11 @@ var TableActions = function TableActions() {
5256
5244
  }); // Tracking
5257
5245
 
5258
5246
  var actionName = type + "Table" + (element === 'Table' ? '' : element);
5259
- onViewportAction(actionName, {
5247
+ editor.tracking.onViewportAction(actionName, {
5260
5248
  tableSize: tableSize
5261
5249
  });
5262
5250
  };
5263
- }, [editor, isHeaderEnabled, close, onViewportAction]);
5251
+ }, [editor, isHeaderEnabled, close]);
5264
5252
 
5265
5253
  if (isDisabled) {
5266
5254
  return null;
@@ -5351,7 +5339,7 @@ var createTableOnKeyDown = function createTableOnKeyDown(editor, plugin) {
5351
5339
  };
5352
5340
  };
5353
5341
 
5354
- var createTablePlugin = function createTablePlugin(tracking) {
5342
+ var createTablePlugin = function createTablePlugin() {
5355
5343
  var _overrideByKey;
5356
5344
 
5357
5345
  return plateTable.createTablePlugin({
@@ -5360,7 +5348,7 @@ var createTablePlugin = function createTablePlugin(tracking) {
5360
5348
  onKeyDown: createTableOnKeyDown
5361
5349
  },
5362
5350
  withOverrides: function withOverrides(editor) {
5363
- addTableTrackingEvents(editor, tracking);
5351
+ addTableTrackingEvents(editor);
5364
5352
  var insertFragment = editor.insertFragment;
5365
5353
 
5366
5354
  editor.insertFragment = function (fragments) {
@@ -5460,10 +5448,6 @@ var createTablePlugin = function createTablePlugin(tracking) {
5460
5448
 
5461
5449
  function ToolbarTableButton(props) {
5462
5450
  var editor = useContentfulEditor();
5463
-
5464
- var _useTrackingContext = useTrackingContext(),
5465
- onViewportAction = _useTrackingContext.onViewportAction;
5466
-
5467
5451
  var isActive = editor && isTableActive(editor);
5468
5452
 
5469
5453
  function handleClick() {
@@ -5484,7 +5468,7 @@ function ToolbarTableButton(props) {
5484
5468
  return _context.abrupt("return");
5485
5469
 
5486
5470
  case 2:
5487
- onViewportAction('insertTable');
5471
+ editor.tracking.onToolbarAction('insertTable');
5488
5472
  insertTableAndFocusFirstCell(editor);
5489
5473
  focus(editor);
5490
5474
 
@@ -5589,35 +5573,199 @@ function deleteEmptyParagraph(unit, editor, deleteFunction) {
5589
5573
  }
5590
5574
  }
5591
5575
 
5592
- var createTrailingParagraphPlugin = function createTrailingParagraphPlugin() {
5593
- return plateTrailingBlock.createTrailingBlockPlugin({
5594
- options: {
5595
- type: Contentful.BLOCKS.PARAGRAPH,
5596
- level: 0
5576
+ var _extends2, _extends4, _inlines;
5577
+ var inlines = /*#__PURE__*/Object.values(Contentful.INLINES).map(function (type) {
5578
+ return {
5579
+ type: type
5580
+ };
5581
+ });
5582
+ var schema = {
5583
+ document: {
5584
+ nodes: [{
5585
+ types: /*#__PURE__*/Contentful.TOP_LEVEL_BLOCKS.map(function (type) {
5586
+ return {
5587
+ type: type
5588
+ };
5589
+ })
5590
+ }]
5591
+ },
5592
+ blocks: /*#__PURE__*/_extends((_extends2 = {}, _extends2[Contentful.BLOCKS.PARAGRAPH] = {
5593
+ nodes: [{
5594
+ match: /*#__PURE__*/[].concat(inlines, [{
5595
+ object: 'text'
5596
+ }])
5597
+ }]
5598
+ }, _extends2[Contentful.BLOCKS.HEADING_1] = {
5599
+ nodes: [{
5600
+ match: /*#__PURE__*/[].concat(inlines, [{
5601
+ object: 'text'
5602
+ }])
5603
+ }]
5604
+ }, _extends2[Contentful.BLOCKS.HEADING_2] = {
5605
+ nodes: [{
5606
+ match: /*#__PURE__*/[].concat(inlines, [{
5607
+ object: 'text'
5608
+ }])
5609
+ }]
5610
+ }, _extends2[Contentful.BLOCKS.HEADING_3] = {
5611
+ nodes: [{
5612
+ match: /*#__PURE__*/[].concat(inlines, [{
5613
+ object: 'text'
5614
+ }])
5615
+ }]
5616
+ }, _extends2[Contentful.BLOCKS.HEADING_4] = {
5617
+ nodes: [{
5618
+ match: /*#__PURE__*/[].concat(inlines, [{
5619
+ object: 'text'
5620
+ }])
5621
+ }]
5622
+ }, _extends2[Contentful.BLOCKS.HEADING_5] = {
5623
+ nodes: [{
5624
+ match: /*#__PURE__*/[].concat(inlines, [{
5625
+ object: 'text'
5626
+ }])
5627
+ }]
5628
+ }, _extends2[Contentful.BLOCKS.HEADING_6] = {
5629
+ nodes: [{
5630
+ match: /*#__PURE__*/[].concat(inlines, [{
5631
+ object: 'text'
5632
+ }])
5633
+ }]
5634
+ }, _extends2), /*#__PURE__*/Contentful.VOID_BLOCKS.reduce(function (blocks, nodeType) {
5635
+ var _extends3;
5636
+
5637
+ return _extends({}, blocks, (_extends3 = {}, _extends3[nodeType] = {
5638
+ isVoid: true
5639
+ }, _extends3));
5640
+ }, {}), (_extends4 = {}, _extends4[Contentful.BLOCKS.QUOTE] = {
5641
+ nodes: [{
5642
+ match: [/*#__PURE__*/Contentful.CONTAINERS[Contentful.BLOCKS.QUOTE].map(function (type) {
5643
+ return {
5644
+ type: type
5645
+ };
5646
+ })],
5647
+ min: 1
5648
+ }],
5649
+ normalize: function normalize(editor, error) {
5650
+ if (error.code === 'child_type_invalid') {
5651
+ return editor.unwrapBlockByKey(error.node.key, Contentful.BLOCKS.QUOTE);
5652
+ }
5597
5653
  }
5654
+ }, _extends4)),
5655
+ inlines: (_inlines = {}, _inlines[Contentful.INLINES.HYPERLINK] = {
5656
+ nodes: [{
5657
+ match: [{
5658
+ object: 'text'
5659
+ }]
5660
+ }]
5661
+ }, _inlines[Contentful.INLINES.ENTRY_HYPERLINK] = {
5662
+ nodes: [{
5663
+ match: [{
5664
+ object: 'text'
5665
+ }]
5666
+ }]
5667
+ }, _inlines[Contentful.INLINES.ASSET_HYPERLINK] = {
5668
+ nodes: [{
5669
+ match: [{
5670
+ object: 'text'
5671
+ }]
5672
+ }]
5673
+ }, _inlines[Contentful.INLINES.EMBEDDED_ENTRY] = {
5674
+ isVoid: true
5675
+ }, _inlines)
5676
+ };
5677
+
5678
+ function getCharacterCount(editor) {
5679
+ var document = contentfulSlateJSAdapter.toContentfulDocument({
5680
+ document: editor.children,
5681
+ schema: schema
5598
5682
  });
5683
+ return richTextPlainTextRenderer.documentToPlainTextString(document).length;
5684
+ }
5685
+
5686
+ var actionOrigin = {
5687
+ TOOLBAR: 'toolbar-icon',
5688
+ SHORTCUT: 'shortcut',
5689
+ VIEWPORT: 'viewport-interaction',
5690
+ COMMAND_PALETTE: 'command-palette'
5599
5691
  };
5692
+ var createTrackingPlugin = function createTrackingPlugin(onAction) {
5693
+ var trackingActions = {
5694
+ onViewportAction: function onViewportAction(actionName, data) {
5695
+ if (data === void 0) {
5696
+ data = {};
5697
+ }
5600
5698
 
5601
- /**
5602
- * Re-creates a void node with valid children.
5603
- */
5699
+ return onAction(actionName, _extends({
5700
+ origin: actionOrigin.VIEWPORT
5701
+ }, data));
5702
+ },
5703
+ onShortcutAction: function onShortcutAction(actionName, data) {
5704
+ if (data === void 0) {
5705
+ data = {};
5706
+ }
5604
5707
 
5605
- var transformVoid = function transformVoid(editor, _ref) {
5606
- var node = _ref[0],
5607
- path = _ref[1];
5708
+ return onAction(actionName, _extends({
5709
+ origin: actionOrigin.SHORTCUT
5710
+ }, data));
5711
+ },
5712
+ onToolbarAction: function onToolbarAction(actionName, data) {
5713
+ if (data === void 0) {
5714
+ data = {};
5715
+ }
5608
5716
 
5609
- var validVoid = _extends({}, node, {
5610
- children: [{
5611
- text: ''
5612
- }]
5613
- }); // A workaround because Slate doesn't allow adjusting void nodes children
5717
+ return onAction(actionName, _extends({
5718
+ origin: actionOrigin.TOOLBAR
5719
+ }, data));
5720
+ },
5721
+ onCommandPaletteAction: function onCommandPaletteAction(actionName, data) {
5722
+ if (data === void 0) {
5723
+ data = {};
5724
+ }
5725
+
5726
+ return onAction(actionName, _extends({
5727
+ origin: actionOrigin.COMMAND_PALETTE
5728
+ }, data));
5729
+ }
5730
+ };
5731
+ return {
5732
+ key: 'TrackingPlugin',
5733
+ withOverrides: function withOverrides(editor) {
5734
+ var insertData = editor.insertData;
5735
+ editor.tracking = trackingActions;
5736
+
5737
+ editor.insertData = function (data) {
5738
+ var isCopyAndPaste = data.types.length !== 0;
5739
+
5740
+ if (isCopyAndPaste) {
5741
+ var _window$getSelection;
5742
+
5743
+ var characterCountSelection = (_window$getSelection = window.getSelection()) == null ? void 0 : _window$getSelection.toString().length;
5744
+ var characterCountBefore = getCharacterCount(editor);
5745
+ setTimeout(function () {
5746
+ var characterCountAfter = getCharacterCount(editor);
5747
+ trackingActions.onShortcutAction('paste', {
5748
+ characterCountAfter: characterCountAfter,
5749
+ characterCountBefore: characterCountBefore,
5750
+ characterCountSelection: characterCountSelection
5751
+ });
5752
+ });
5753
+ }
5614
5754
 
5755
+ insertData(data);
5756
+ };
5615
5757
 
5616
- slate.Transforms.removeNodes(editor, {
5617
- at: path
5618
- });
5619
- slate.Transforms.insertNodes(editor, [validVoid], {
5620
- at: path
5758
+ return editor;
5759
+ }
5760
+ };
5761
+ };
5762
+
5763
+ var createTrailingParagraphPlugin = function createTrailingParagraphPlugin() {
5764
+ return plateTrailingBlock.createTrailingBlockPlugin({
5765
+ options: {
5766
+ type: Contentful.BLOCKS.PARAGRAPH,
5767
+ level: 0
5768
+ }
5621
5769
  });
5622
5770
  };
5623
5771
 
@@ -5649,34 +5797,17 @@ var createVoidsPlugin = function createVoidsPlugin() {
5649
5797
  return !(isRootLevel(path) && plateCore.isFirstChild(path)) && !!node.isVoid;
5650
5798
  }
5651
5799
  }
5652
- }],
5653
- normalizer: [{
5654
- match: {
5655
- isVoid: true
5656
- },
5657
- validNode: function validNode(editor, _ref3) {
5658
- var path = _ref3[1];
5659
- var children = Array.from(slate.Node.children(editor, path));
5660
-
5661
- if (children.length !== 1) {
5662
- return false;
5663
- }
5664
-
5665
- var _children$ = children[0],
5666
- textNode = _children$[0];
5667
- return slate.Text.isText(textNode) && textNode.text === '';
5668
- },
5669
- transform: transformVoid
5670
5800
  }]
5671
5801
  };
5672
5802
  };
5673
5803
 
5674
- var getPlugins = function getPlugins(sdk, tracking) {
5804
+ var getPlugins = function getPlugins(sdk, onAction) {
5675
5805
  return [// AST must come after the HTML deserializer
5676
- plateCore.createDeserializeHtmlPlugin(), plateCore.createDeserializeAstPlugin(), plateSerializerDocx.createDeserializeDocxPlugin(), // Global shortcuts
5806
+ plateCore.createDeserializeHtmlPlugin(), plateCore.createDeserializeAstPlugin(), plateSerializerDocx.createDeserializeDocxPlugin(), // Tracking - This should come first so all plugins below will have access to `editor.tracking`
5807
+ createTrackingPlugin(onAction), // Global / Global shortcuts
5677
5808
  createDragAndDropPlugin(), // Block Elements
5678
- createParagraphPlugin(), createListPlugin(), createHrPlugin(), createHeadingPlugin(), createQuotePlugin(), createTablePlugin(tracking), createEmbeddedEntryBlockPlugin(sdk, tracking), createEmbeddedAssetBlockPlugin(sdk, tracking), // Inline elements
5679
- createHyperlinkPlugin(sdk, tracking), createEmbeddedEntityInlinePlugin(sdk, tracking), // Marks
5809
+ createParagraphPlugin(), createListPlugin(), createHrPlugin(), createHeadingPlugin(), createQuotePlugin(), createTablePlugin(), createEmbeddedEntryBlockPlugin(sdk), createEmbeddedAssetBlockPlugin(sdk), // Inline elements
5810
+ createHyperlinkPlugin(sdk), createEmbeddedEntityInlinePlugin(sdk), // Marks
5680
5811
  createMarksPlugin(), // Other
5681
5812
  createTrailingParagraphPlugin(), createTextPlugin(), createVoidsPlugin(), createSelectOnBackspacePlugin(), // Pasting content from other sources
5682
5813
  createPasteHTMLPlugin(), // These plugins drive their configurations from the list of plugins
@@ -5971,7 +6102,7 @@ var useNormalizedSlateValue = function useNormalizedSlateValue(_ref) {
5971
6102
  plugins: plugins,
5972
6103
  disableCorePlugins: disableCorePlugins
5973
6104
  });
5974
- var doc = contentfulSlatejsAdapter.toSlatejsDocument({
6105
+ var doc = contentfulSlateJSAdapter.toSlatejsDocument({
5975
6106
  document: hasContent(incomingDoc) ? incomingDoc : Contentful.EMPTY_DOCUMENT,
5976
6107
  schema: schema
5977
6108
  }); // Sets editor value & kicks normalization
@@ -5985,18 +6116,56 @@ var useNormalizedSlateValue = function useNormalizedSlateValue(_ref) {
5985
6116
  }, [id, plugins, incomingDoc]);
5986
6117
  };
5987
6118
 
6119
+ /**
6120
+ * Returns whether a given operation is relevant enough to trigger a save.
6121
+ */
6122
+
6123
+ var isRelevantOperation = function isRelevantOperation(op) {
6124
+ if (op.type === 'set_selection') {
6125
+ return false;
6126
+ }
6127
+
6128
+ return true;
6129
+ };
6130
+
6131
+ var useOnValueChanged = function useOnValueChanged(_ref) {
6132
+ var editor = _ref.editor,
6133
+ handler = _ref.handler;
6134
+ var onChange = React.useMemo(function () {
6135
+ return debounce(function (document) {
6136
+ handler == null ? void 0 : handler(contentfulSlateJSAdapter.toContentfulDocument({
6137
+ document: document,
6138
+ schema: schema
6139
+ }));
6140
+ }, 500);
6141
+ }, [handler]);
6142
+ return React.useCallback(function (value) {
6143
+ var operations = editor.operations.filter(isRelevantOperation);
6144
+
6145
+ if (operations.length > 0) {
6146
+ onChange(value);
6147
+ }
6148
+ }, [editor, onChange]);
6149
+ };
6150
+
5988
6151
  var _excluded = ["sdk", "isInitiallyDisabled", "onAction"];
5989
6152
  var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
5990
- var id = getContentfulEditorId(props.sdk);
5991
- var tracking = useTrackingContext();
6153
+ var id = useContentfulEditorId();
6154
+ var editor = useContentfulEditor();
5992
6155
  var plugins = React__default.useMemo(function () {
5993
- return getPlugins(props.sdk, tracking);
5994
- }, [props.sdk, tracking]);
6156
+ var _props$onAction;
6157
+
6158
+ return getPlugins(props.sdk, (_props$onAction = props.onAction) != null ? _props$onAction : noop);
6159
+ }, [props.sdk, props.onAction]);
5995
6160
  var initialValue = useNormalizedSlateValue({
5996
6161
  id: id,
5997
6162
  incomingDoc: props.value,
5998
6163
  plugins: plugins
5999
6164
  });
6165
+ var onValueChanged = useOnValueChanged({
6166
+ editor: editor,
6167
+ handler: props.onChange
6168
+ });
6000
6169
  var classNames = emotion.cx(styles$j.editor, props.minHeight !== undefined ? emotion.css({
6001
6170
  minHeight: props.minHeight
6002
6171
  }) : undefined, props.isDisabled ? styles$j.disabled : styles$j.enabled, props.isToolbarHidden && styles$j.hiddenToolbar);
@@ -6012,12 +6181,7 @@ var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
6012
6181
  className: classNames,
6013
6182
  readOnly: props.isDisabled
6014
6183
  },
6015
- onChange: function onChange(document) {
6016
- props.onChange == null ? void 0 : props.onChange(contentfulSlatejsAdapter.toContentfulDocument({
6017
- document: document,
6018
- schema: schema
6019
- }));
6020
- }
6184
+ onChange: onValueChanged
6021
6185
  }, !props.isToolbarHidden && /*#__PURE__*/React__default.createElement(StickyToolbarWrapper, {
6022
6186
  isDisabled: props.isDisabled
6023
6187
  }, /*#__PURE__*/React__default.createElement(Toolbar, {
@@ -6034,12 +6198,11 @@ var RichTextEditor = function RichTextEditor(props) {
6034
6198
  var isEmptyValue = React.useCallback(function (value) {
6035
6199
  return !value || deepEquals(value, Contentful.EMPTY_DOCUMENT);
6036
6200
  }, []);
6201
+ var editorId = getContentfulEditorId(sdk);
6037
6202
  return /*#__PURE__*/React__default.createElement(fieldEditorReference.EntityProvider, {
6038
6203
  sdk: sdk
6039
6204
  }, /*#__PURE__*/React__default.createElement(SdkProvider, {
6040
6205
  sdk: sdk
6041
- }, /*#__PURE__*/React__default.createElement(TrackingProvider, {
6042
- onAction: onAction || noop
6043
6206
  }, /*#__PURE__*/React__default.createElement(fieldEditorShared.FieldConnector, {
6044
6207
  throttle: 0,
6045
6208
  field: sdk.field,
@@ -6051,17 +6214,17 @@ var RichTextEditor = function RichTextEditor(props) {
6051
6214
  disabled = _ref.disabled,
6052
6215
  setValue = _ref.setValue,
6053
6216
  externalReset = _ref.externalReset;
6054
- return /*#__PURE__*/React__default.createElement(ContentfulEditorProvider, {
6055
- sdk: sdk
6217
+ return /*#__PURE__*/React__default.createElement(ContentfulEditorIdProvider, {
6218
+ value: editorId
6056
6219
  }, /*#__PURE__*/React__default.createElement(ConnectedRichTextEditor, Object.assign({}, otherProps, {
6057
6220
  key: "rich-text-editor-" + externalReset,
6058
6221
  value: lastRemoteValue,
6059
6222
  sdk: sdk,
6060
- onAction: onAction || noop,
6223
+ onAction: onAction,
6061
6224
  isDisabled: disabled,
6062
6225
  onChange: setValue
6063
6226
  })));
6064
- }))));
6227
+ })));
6065
6228
  };
6066
6229
 
6067
6230
  var LINK_TYPES$1 = {