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

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 (55) 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 +502 -359
  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 +505 -362
  8. package/dist/field-editor-rich-text.esm.js.map +1 -1
  9. package/dist/helpers/editor.d.ts +16 -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 +6 -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/Quote/toggleQuote.d.ts +5 -3
  35. package/dist/plugins/Table/actions/addColumn.d.ts +3 -3
  36. package/dist/plugins/Table/actions/addRow.d.ts +3 -3
  37. package/dist/plugins/Table/actions/setHeader.d.ts +2 -2
  38. package/dist/plugins/Table/addTableTrackingEvents.d.ts +2 -3
  39. package/dist/plugins/Table/createTablePlugin.d.ts +1 -2
  40. package/dist/plugins/Table/helpers.d.ts +7 -7
  41. package/dist/plugins/Tracking/createTrackingPlugin.d.ts +10 -0
  42. package/dist/plugins/Tracking/index.d.ts +1 -0
  43. package/dist/plugins/Tracking/utils.d.ts +2 -0
  44. package/dist/plugins/TrailingParagraph/index.d.ts +2 -1
  45. package/dist/plugins/Voids/transformVoid.d.ts +2 -2
  46. package/dist/plugins/index.d.ts +2 -2
  47. package/dist/plugins/links-tracking.d.ts +1 -2
  48. package/dist/test-utils/assertOutput.d.ts +2 -2
  49. package/dist/test-utils/createEditor.d.ts +5 -6
  50. package/dist/test-utils/mockPlugin.d.ts +1 -1
  51. package/dist/test-utils/setEmptyDataAttribute.d.ts +2 -2
  52. package/dist/types.d.ts +6 -2
  53. package/dist/useOnValueChanged.d.ts +7 -0
  54. package/package.json +1 -1
  55. 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) {
@@ -706,12 +619,14 @@ var focus = function focus(editor) {
706
619
  }
707
620
  };
708
621
 
709
- function withLinkTracking(tracking, Component) {
622
+ function withLinkTracking(Component) {
710
623
  return function ComponentWithTracking(props) {
624
+ var editor = useContentfulEditorRef();
625
+ var onEntityFetchComplete = React__default.useCallback(function () {
626
+ return editor.tracking.onViewportAction('linkRendered');
627
+ }, [editor]);
711
628
  return /*#__PURE__*/React__default.createElement(Component, Object.assign({}, props, {
712
- onEntityFetchComplete: function onEntityFetchComplete() {
713
- tracking.onViewportAction('linkRendered');
714
- }
629
+ onEntityFetchComplete: onEntityFetchComplete
715
630
  }));
716
631
  };
717
632
  }
@@ -725,9 +640,9 @@ function useSdk(_ref) {
725
640
  return sdkMemo;
726
641
  }
727
642
 
728
- var _constate$1 = /*#__PURE__*/constate(useSdk),
729
- SdkProvider = _constate$1[0],
730
- useSdkContext = _constate$1[1];
643
+ var _constate = /*#__PURE__*/constate(useSdk),
644
+ SdkProvider = _constate[0],
645
+ useSdkContext = _constate[1];
731
646
 
732
647
  var styles = {
733
648
  scheduleIcon: /*#__PURE__*/emotion.css({
@@ -1977,12 +1892,11 @@ function _selectEntityAndInsert() {
1977
1892
  config = _extends({}, baseConfig, {
1978
1893
  withCreate: true
1979
1894
  });
1980
- _context.prev = 5;
1981
1895
  selection = editor.selection;
1982
- _context.next = 9;
1896
+ _context.next = 8;
1983
1897
  return selectEntity(config);
1984
1898
 
1985
- case 9:
1899
+ case 8:
1986
1900
  entity = _context.sent;
1987
1901
 
1988
1902
  if (entity) {
@@ -1990,6 +1904,9 @@ function _selectEntityAndInsert() {
1990
1904
  break;
1991
1905
  }
1992
1906
 
1907
+ logAction('cancelCreateEmbedDialog', {
1908
+ nodeType: nodeType
1909
+ });
1993
1910
  return _context.abrupt("return");
1994
1911
 
1995
1912
  case 12:
@@ -1998,31 +1915,13 @@ function _selectEntityAndInsert() {
1998
1915
  logAction('insert', {
1999
1916
  nodeType: nodeType
2000
1917
  });
2001
- _context.next = 24;
2002
- break;
2003
-
2004
- case 17:
2005
- _context.prev = 17;
2006
- _context.t0 = _context["catch"](5);
2007
1918
 
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:
1919
+ case 15:
2021
1920
  case "end":
2022
1921
  return _context.stop();
2023
1922
  }
2024
1923
  }
2025
- }, _callee, null, [[5, 17]]);
1924
+ }, _callee);
2026
1925
  }));
2027
1926
  return _selectEntityAndInsert.apply(this, arguments);
2028
1927
  }
@@ -2069,7 +1968,6 @@ var styles$4 = {
2069
1968
  function EmbeddedEntityBlockToolbarIcon(_ref) {
2070
1969
  var isButton = _ref.isButton,
2071
1970
  isDisabled = _ref.isDisabled,
2072
- logAction = _ref.logAction,
2073
1971
  nodeType = _ref.nodeType,
2074
1972
  onClose = _ref.onClose;
2075
1973
  var editor = useContentfulEditor();
@@ -2078,7 +1976,7 @@ function EmbeddedEntityBlockToolbarIcon(_ref) {
2078
1976
  var handleClick = function handleClick(event) {
2079
1977
  event.preventDefault();
2080
1978
  onClose();
2081
- selectEntityAndInsert(nodeType, sdk, editor, logAction || noop);
1979
+ selectEntityAndInsert(nodeType, sdk, editor, editor.tracking.onToolbarAction);
2082
1980
  };
2083
1981
 
2084
1982
  var type = getEntityTypeFromNodeType(nodeType);
@@ -2145,20 +2043,20 @@ function getWithEmbeddedEntityEvents(nodeType, sdk) {
2145
2043
  }
2146
2044
 
2147
2045
  if (hotkey && isHotkey(hotkey, event)) {
2148
- selectEntityAndInsert(nodeType, sdk, editor, noop);
2046
+ selectEntityAndInsert(nodeType, sdk, editor, editor.tracking.onShortcutAction);
2149
2047
  }
2150
2048
  };
2151
2049
  };
2152
2050
  }
2153
2051
 
2154
2052
  var createEmbeddedEntityPlugin = function createEmbeddedEntityPlugin(nodeType, hotkey) {
2155
- return function (sdk, tracking) {
2053
+ return function (sdk) {
2156
2054
  return {
2157
2055
  key: nodeType,
2158
2056
  type: nodeType,
2159
2057
  isElement: true,
2160
2058
  isVoid: true,
2161
- component: withLinkTracking(tracking, LinkedEntityBlock),
2059
+ component: withLinkTracking(LinkedEntityBlock),
2162
2060
  options: {
2163
2061
  hotkey: hotkey
2164
2062
  },
@@ -2376,44 +2274,53 @@ function EmbeddedEntityInline(props) {
2376
2274
  })), props.children);
2377
2275
  }
2378
2276
 
2379
- function selectEntityAndInsert$1(_x, _x2) {
2277
+ function selectEntityAndInsert$1(_x, _x2, _x3) {
2380
2278
  return _selectEntityAndInsert$1.apply(this, arguments);
2381
2279
  }
2382
2280
 
2383
2281
  function _selectEntityAndInsert$1() {
2384
- _selectEntityAndInsert$1 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(editor, sdk) {
2282
+ _selectEntityAndInsert$1 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(editor, sdk, logAction) {
2385
2283
  var config, selection, entry, inlineEntryNode;
2386
2284
  return runtime_1.wrap(function _callee2$(_context2) {
2387
2285
  while (1) {
2388
2286
  switch (_context2.prev = _context2.next) {
2389
2287
  case 0:
2288
+ logAction('openCreateEmbedDialog', {
2289
+ nodeType: Contentful.INLINES.EMBEDDED_ENTRY
2290
+ });
2390
2291
  config = _extends({}, newEntitySelectorConfigFromRichTextField(sdk.field, Contentful.INLINES.EMBEDDED_ENTRY), {
2391
2292
  withCreate: true
2392
2293
  });
2393
2294
  selection = editor.selection;
2394
- _context2.next = 4;
2295
+ _context2.next = 5;
2395
2296
  return sdk.dialogs.selectSingleEntry(config);
2396
2297
 
2397
- case 4:
2298
+ case 5:
2398
2299
  entry = _context2.sent;
2399
2300
  focus(editor); // Dialog steals focus from editor, return it.
2400
2301
 
2401
2302
  if (entry) {
2402
- _context2.next = 8;
2303
+ _context2.next = 10;
2403
2304
  break;
2404
2305
  }
2405
2306
 
2307
+ logAction('cancelCreateEmbedDialog', {
2308
+ nodeType: Contentful.INLINES.EMBEDDED_ENTRY
2309
+ });
2406
2310
  return _context2.abrupt("return");
2407
2311
 
2408
- case 8:
2312
+ case 10:
2409
2313
  inlineEntryNode = createInlineEntryNode(entry.sys.id); // Got to wait until focus is really back on the editor or setSelection() won't work.
2410
2314
 
2411
2315
  setTimeout(function () {
2412
2316
  slate.Transforms.setSelection(editor, selection);
2413
2317
  slate.Transforms.insertNodes(editor, inlineEntryNode);
2414
2318
  }, 0);
2319
+ logAction('insert', {
2320
+ nodeType: Contentful.INLINES.EMBEDDED_ENTRY
2321
+ });
2415
2322
 
2416
- case 10:
2323
+ case 13:
2417
2324
  case "end":
2418
2325
  return _context2.stop();
2419
2326
  }
@@ -2427,7 +2334,7 @@ function ToolbarEmbeddedEntityInlineButton(props) {
2427
2334
  var editor = useContentfulEditor();
2428
2335
  var sdk = useSdkContext();
2429
2336
 
2430
- function handleClick(_x3) {
2337
+ function handleClick(_x4) {
2431
2338
  return _handleClick.apply(this, arguments);
2432
2339
  }
2433
2340
 
@@ -2449,7 +2356,7 @@ function ToolbarEmbeddedEntityInlineButton(props) {
2449
2356
  case 3:
2450
2357
  props.onClose();
2451
2358
  _context.next = 6;
2452
- return selectEntityAndInsert$1(editor, sdk);
2359
+ return selectEntityAndInsert$1(editor, sdk, editor.tracking.onToolbarAction);
2453
2360
 
2454
2361
  case 6:
2455
2362
  case "end":
@@ -2482,7 +2389,7 @@ function ToolbarEmbeddedEntityInlineButton(props) {
2482
2389
  className: "rich-text__embedded-entry-list-icon " + styles$6.icon
2483
2390
  }), /*#__PURE__*/React.createElement("span", null, "Inline entry")));
2484
2391
  }
2485
- function createEmbeddedEntityInlinePlugin(sdk, tracking) {
2392
+ function createEmbeddedEntityInlinePlugin(sdk) {
2486
2393
  var htmlAttributeName = 'data-embedded-entity-inline-id';
2487
2394
  return {
2488
2395
  key: Contentful.INLINES.EMBEDDED_ENTRY,
@@ -2490,7 +2397,7 @@ function createEmbeddedEntityInlinePlugin(sdk, tracking) {
2490
2397
  isElement: true,
2491
2398
  isInline: true,
2492
2399
  isVoid: true,
2493
- component: withLinkTracking(tracking, EmbeddedEntityInline),
2400
+ component: withLinkTracking(EmbeddedEntityInline),
2494
2401
  options: {
2495
2402
  hotkey: 'mod+shift+2'
2496
2403
  },
@@ -2516,7 +2423,7 @@ function getWithEmbeddedEntryInlineEvents(sdk) {
2516
2423
  if (!editor) return;
2517
2424
 
2518
2425
  if (hotkey && isHotkey(hotkey, event)) {
2519
- selectEntityAndInsert$1(editor, sdk);
2426
+ selectEntityAndInsert$1(editor, sdk, editor.tracking.onShortcutAction);
2520
2427
  }
2521
2428
  };
2522
2429
  };
@@ -2619,6 +2526,10 @@ function ToolbarHeadingButton(props) {
2619
2526
  prevOnChange.apply(void 0, arguments);
2620
2527
  };
2621
2528
 
2529
+ var isActive = isBlockSelected(editor, type);
2530
+ editor.tracking.onToolbarAction(isActive ? 'remove' : 'insert', {
2531
+ nodeType: type
2532
+ });
2622
2533
  plateCore.toggleNodeType(editor, {
2623
2534
  activeType: type,
2624
2535
  inactiveType: type
@@ -2740,6 +2651,24 @@ function createHeading(Tag, block) {
2740
2651
 
2741
2652
  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
2653
 
2654
+ var buildHeadingEventHandler = function buildHeadingEventHandler(type) {
2655
+ return function (editor, _ref) {
2656
+ var hotkey = _ref.options.hotkey;
2657
+ return function (event) {
2658
+ if (editor.selection && hotkey && isHotkey(hotkey, event)) {
2659
+ var isActive = isBlockSelected(editor, type);
2660
+ editor.tracking.onShortcutAction(isActive ? 'remove' : 'insert', {
2661
+ nodeType: type
2662
+ });
2663
+ plateCore.toggleNodeType(editor, {
2664
+ activeType: type,
2665
+ inactiveType: Contentful.BLOCKS.PARAGRAPH
2666
+ });
2667
+ }
2668
+ };
2669
+ };
2670
+ };
2671
+
2743
2672
  var createHeadingPlugin = function createHeadingPlugin() {
2744
2673
  var _transform;
2745
2674
 
@@ -2756,8 +2685,8 @@ var createHeadingPlugin = function createHeadingPlugin() {
2756
2685
  match: {
2757
2686
  type: Contentful.HEADINGS
2758
2687
  },
2759
- validChildren: function validChildren(_, _ref) {
2760
- var node = _ref[0];
2688
+ validChildren: function validChildren(_, _ref2) {
2689
+ var node = _ref2[0];
2761
2690
  return isInlineOrText(node);
2762
2691
  },
2763
2692
  transform: (_transform = {}, _transform[Contentful.BLOCKS.PARAGRAPH] = transformUnwrap, _transform["default"] = transformLift, _transform)
@@ -2774,8 +2703,8 @@ var createHeadingPlugin = function createHeadingPlugin() {
2774
2703
  start: true,
2775
2704
  // Exclude headings inside lists as it interferes with the list's
2776
2705
  // insertBreak implementation
2777
- filter: function filter(_ref2) {
2778
- var path = _ref2[1];
2706
+ filter: function filter(_ref3) {
2707
+ var path = _ref3[1];
2779
2708
  return !plateCore.getAbove(editor, {
2780
2709
  at: path,
2781
2710
  match: {
@@ -2799,7 +2728,7 @@ var createHeadingPlugin = function createHeadingPlugin() {
2799
2728
  hotkey: ["mod+alt+" + level]
2800
2729
  },
2801
2730
  handlers: {
2802
- onKeyDown: plateCore.onKeyDownToggleElement
2731
+ onKeyDown: buildHeadingEventHandler(nodeType)
2803
2732
  },
2804
2733
  deserializeHtml: {
2805
2734
  rules: [{
@@ -3329,13 +3258,15 @@ function HyperlinkModal(props) {
3329
3258
  testId: "confirm-cta"
3330
3259
  }, props.linkType ? 'Update' : 'Insert'))));
3331
3260
  }
3332
- function addOrEditLink(_x, _x2) {
3261
+ function addOrEditLink(_x, _x2, _x3) {
3333
3262
  return _addOrEditLink.apply(this, arguments);
3334
3263
  }
3335
3264
 
3336
3265
  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;
3266
+ _addOrEditLink = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(editor, sdk, logAction) {
3267
+ var _target$sys$linkType;
3268
+
3269
+ var linkType, linkText, linkTarget, linkEntity, _getNodeEntryFromSele, node, path, selectionBeforeBlur, currentLinkText, isEditing, data, text, url, type, target;
3339
3270
 
3340
3271
  return runtime_1.wrap(function _callee3$(_context3) {
3341
3272
  while (1) {
@@ -3360,9 +3291,11 @@ function _addOrEditLink() {
3360
3291
 
3361
3292
  selectionBeforeBlur = _extends({}, editor.selection);
3362
3293
  currentLinkText = linkText || slate.Editor.string(editor, editor.selection);
3363
- _context3.next = 8;
3294
+ isEditing = Boolean(node && path);
3295
+ logAction(isEditing ? 'openEditHyperlinkDialog' : 'openCreateHyperlinkDialog');
3296
+ _context3.next = 10;
3364
3297
  return fieldEditorShared.ModalDialogLauncher.openDialog({
3365
- title: linkType ? 'Edit hyperlink' : 'Insert hyperlink',
3298
+ title: isEditing ? 'Edit hyperlink' : 'Insert hyperlink',
3366
3299
  width: 'large',
3367
3300
  shouldCloseOnEscapePress: true,
3368
3301
  shouldCloseOnOverlayClick: true,
@@ -3379,17 +3312,18 @@ function _addOrEditLink() {
3379
3312
  });
3380
3313
  });
3381
3314
 
3382
- case 8:
3315
+ case 10:
3383
3316
  data = _context3.sent;
3384
3317
 
3385
3318
  if (data) {
3386
- _context3.next = 11;
3319
+ _context3.next = 14;
3387
3320
  break;
3388
3321
  }
3389
3322
 
3323
+ logAction(isEditing ? 'cancelEditHyperlinkDialog' : 'cancelCreateHyperlinkDialog');
3390
3324
  return _context3.abrupt("return");
3391
3325
 
3392
- case 11:
3326
+ case 14:
3393
3327
  text = data.linkText, url = data.linkTarget, type = data.linkType, target = data.linkEntity;
3394
3328
  slate.Transforms.select(editor, selectionBeforeBlur);
3395
3329
  slate.Editor.withoutNormalizing(editor, function () {
@@ -3401,9 +3335,13 @@ function _addOrEditLink() {
3401
3335
  path: path
3402
3336
  });
3403
3337
  });
3338
+ logAction(isEditing ? 'edit' : 'insert', {
3339
+ nodeType: type,
3340
+ linkType: (_target$sys$linkType = target == null ? void 0 : target.sys.linkType) != null ? _target$sys$linkType : 'uri'
3341
+ });
3404
3342
  focus(editor);
3405
3343
 
3406
- case 15:
3344
+ case 19:
3407
3345
  case "end":
3408
3346
  return _context3.stop();
3409
3347
  }
@@ -3467,7 +3405,7 @@ function UrlHyperlink(props) {
3467
3405
  event.preventDefault();
3468
3406
  event.stopPropagation();
3469
3407
  if (!editor) return;
3470
- addOrEditLink(editor, sdk);
3408
+ addOrEditLink(editor, sdk, editor.tracking.onViewportAction);
3471
3409
  }
3472
3410
 
3473
3411
  return /*#__PURE__*/React.createElement(f36Components.Tooltip, {
@@ -3503,7 +3441,7 @@ function EntityHyperlink(props) {
3503
3441
  event.preventDefault();
3504
3442
  event.stopPropagation();
3505
3443
  if (!editor) return;
3506
- addOrEditLink(editor, sdk);
3444
+ addOrEditLink(editor, sdk, editor.tracking.onViewportAction);
3507
3445
  }
3508
3446
 
3509
3447
  return /*#__PURE__*/React.createElement(f36Components.Tooltip, {
@@ -3550,8 +3488,9 @@ function ToolbarHyperlinkButton(props) {
3550
3488
  case 2:
3551
3489
  if (isActive) {
3552
3490
  unwrapLink(editor);
3491
+ editor.tracking.onToolbarAction('unlinkHyperlinks');
3553
3492
  } else {
3554
- addOrEditLink(editor, sdk);
3493
+ addOrEditLink(editor, sdk, editor.tracking.onToolbarAction);
3555
3494
  }
3556
3495
 
3557
3496
  case 3:
@@ -3600,8 +3539,9 @@ var buildHyperlinkEventHandler = function buildHyperlinkEventHandler(sdk) {
3600
3539
 
3601
3540
  if (isLinkActive(editor)) {
3602
3541
  unwrapLink(editor);
3542
+ editor.tracking.onShortcutAction('unlinkHyperlinks');
3603
3543
  } else {
3604
- addOrEditLink(editor, sdk);
3544
+ addOrEditLink(editor, sdk, editor.tracking.onShortcutAction);
3605
3545
  }
3606
3546
  };
3607
3547
  };
@@ -3627,7 +3567,7 @@ var getNodeOfType = function getNodeOfType(type) {
3627
3567
  };
3628
3568
  };
3629
3569
 
3630
- var createHyperlinkPlugin = function createHyperlinkPlugin(sdk, tracking) {
3570
+ var createHyperlinkPlugin = function createHyperlinkPlugin(sdk) {
3631
3571
  var common = {
3632
3572
  isElement: true,
3633
3573
  isInline: true
@@ -3658,7 +3598,7 @@ var createHyperlinkPlugin = function createHyperlinkPlugin(sdk, tracking) {
3658
3598
  _extends({}, common, {
3659
3599
  key: Contentful.INLINES.ENTRY_HYPERLINK,
3660
3600
  type: Contentful.INLINES.ENTRY_HYPERLINK,
3661
- component: withLinkTracking(tracking, EntityHyperlink),
3601
+ component: withLinkTracking(EntityHyperlink),
3662
3602
  deserializeHtml: {
3663
3603
  rules: [{
3664
3604
  validNodeName: ['A']
@@ -3672,7 +3612,7 @@ var createHyperlinkPlugin = function createHyperlinkPlugin(sdk, tracking) {
3672
3612
  _extends({}, common, {
3673
3613
  key: Contentful.INLINES.ASSET_HYPERLINK,
3674
3614
  type: Contentful.INLINES.ASSET_HYPERLINK,
3675
- component: withLinkTracking(tracking, EntityHyperlink),
3615
+ component: withLinkTracking(EntityHyperlink),
3676
3616
  deserializeHtml: {
3677
3617
  rules: [{
3678
3618
  validNodeName: ['A']
@@ -4146,6 +4086,7 @@ var createListPlugin = function createListPlugin() {
4146
4086
  }, _overrideByKey[plateList.ELEMENT_LI] = {
4147
4087
  type: Contentful.BLOCKS.LIST_ITEM,
4148
4088
  component: ListItem,
4089
+ // @ts-expect-error
4149
4090
  normalizer: [{
4150
4091
  validNode: hasListAsDirectParent,
4151
4092
  transform: normalizeOrphanedListItem
@@ -4198,26 +4139,62 @@ function ToolbarListButton(props) {
4198
4139
  }, /*#__PURE__*/React.createElement(f36Icons.ListNumberedIcon, null)));
4199
4140
  }
4200
4141
 
4201
- function ToolbarBoldButton(props) {
4202
- var editor = useContentfulEditor();
4142
+ var createMarkToolbarButton = function createMarkToolbarButton(_ref) {
4143
+ var mark = _ref.mark,
4144
+ title = _ref.title,
4145
+ icon = _ref.icon;
4203
4146
 
4204
- function handleClick() {
4205
- if (!(editor != null && editor.selection)) return;
4206
- plateCore.toggleMark(editor, {
4207
- key: Contentful.MARKS.BOLD
4208
- });
4209
- focus(editor);
4210
- }
4147
+ var Mark = function Mark(_ref2) {
4148
+ var isDisabled = _ref2.isDisabled;
4149
+ var editor = useContentfulEditor();
4150
+ var handleClick = React.useCallback(function () {
4151
+ if (!(editor != null && editor.selection)) return;
4152
+ var isActive = plateCore.isMarkActive(editor, mark);
4153
+ editor.tracking.onToolbarAction(isActive ? 'unmark' : 'mark', {
4154
+ markType: mark
4155
+ });
4156
+ plateCore.toggleMark(editor, {
4157
+ key: mark
4158
+ });
4159
+ focus(editor);
4160
+ }, [editor]);
4161
+ if (!editor) return null;
4162
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
4163
+ title: title,
4164
+ testId: mark + "-toolbar-button",
4165
+ onClick: handleClick,
4166
+ isActive: plateCore.isMarkActive(editor, mark),
4167
+ isDisabled: isDisabled
4168
+ }, icon);
4169
+ };
4211
4170
 
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
- }
4171
+ Mark.displayName = mark;
4172
+ return Mark;
4173
+ };
4174
+
4175
+ var buildMarkEventHandler = function buildMarkEventHandler(type) {
4176
+ return function (editor, _ref) {
4177
+ var hotkey = _ref.options.hotkey;
4178
+ return function (event) {
4179
+ if (editor.selection && hotkey && isHotkey(hotkey, event)) {
4180
+ event.preventDefault();
4181
+ var isActive = plateCore.isMarkActive(editor, type);
4182
+ editor.tracking.onShortcutAction(isActive ? 'unmark' : 'mark', {
4183
+ markType: type
4184
+ });
4185
+ plateCore.toggleMark(editor, {
4186
+ key: type
4187
+ });
4188
+ }
4189
+ };
4190
+ };
4191
+ };
4192
+
4193
+ var ToolbarBoldButton = /*#__PURE__*/createMarkToolbarButton({
4194
+ title: 'Bold',
4195
+ mark: Contentful.MARKS.BOLD,
4196
+ icon: /*#__PURE__*/React.createElement(f36Icons.FormatBoldIcon, null)
4197
+ });
4221
4198
  var styles$e = {
4222
4199
  bold: /*#__PURE__*/emotion.css({
4223
4200
  fontWeight: 600
@@ -4240,6 +4217,9 @@ var createBoldPlugin = function createBoldPlugin() {
4240
4217
  options: {
4241
4218
  hotkey: ['mod+b']
4242
4219
  },
4220
+ handlers: {
4221
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.BOLD)
4222
+ },
4243
4223
  deserializeHtml: {
4244
4224
  rules: [{
4245
4225
  validNodeName: ['STRONG', 'B']
@@ -4257,26 +4237,11 @@ var createBoldPlugin = function createBoldPlugin() {
4257
4237
  });
4258
4238
  };
4259
4239
 
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
- }
4240
+ var ToolbarCodeButton = /*#__PURE__*/createMarkToolbarButton({
4241
+ title: 'Code',
4242
+ mark: Contentful.MARKS.CODE,
4243
+ icon: /*#__PURE__*/React.createElement(f36Icons.CodeIcon, null)
4244
+ });
4280
4245
  var styles$f = {
4281
4246
  code: /*#__PURE__*/emotion.css({
4282
4247
  fontFamily: 'monospace',
@@ -4295,6 +4260,9 @@ var createCodePlugin = function createCodePlugin() {
4295
4260
  options: {
4296
4261
  hotkey: ['mod+/']
4297
4262
  },
4263
+ handlers: {
4264
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.CODE)
4265
+ },
4298
4266
  deserializeHtml: {
4299
4267
  rules: [{
4300
4268
  validNodeName: ['CODE', 'PRE']
@@ -4307,26 +4275,11 @@ var createCodePlugin = function createCodePlugin() {
4307
4275
  });
4308
4276
  };
4309
4277
 
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
- }
4278
+ var ToolbarItalicButton = /*#__PURE__*/createMarkToolbarButton({
4279
+ title: 'Italic',
4280
+ mark: Contentful.MARKS.ITALIC,
4281
+ icon: /*#__PURE__*/React.createElement(f36Icons.FormatItalicIcon, null)
4282
+ });
4330
4283
  var styles$g = {
4331
4284
  italic: /*#__PURE__*/emotion.css({
4332
4285
  fontStyle: 'italic'
@@ -4344,6 +4297,9 @@ var createItalicPlugin = function createItalicPlugin() {
4344
4297
  options: {
4345
4298
  hotkey: ['mod+i']
4346
4299
  },
4300
+ handlers: {
4301
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.ITALIC)
4302
+ },
4347
4303
  deserializeHtml: {
4348
4304
  rules: [{
4349
4305
  validNodeName: ['I', 'EM']
@@ -4361,26 +4317,11 @@ var createItalicPlugin = function createItalicPlugin() {
4361
4317
  });
4362
4318
  };
4363
4319
 
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
- }
4320
+ var ToolbarUnderlineButton = /*#__PURE__*/createMarkToolbarButton({
4321
+ title: 'Underline',
4322
+ mark: Contentful.MARKS.UNDERLINE,
4323
+ icon: /*#__PURE__*/React.createElement(f36Icons.FormatUnderlinedIcon, null)
4324
+ });
4384
4325
  function Underline(props) {
4385
4326
  return /*#__PURE__*/React.createElement("u", Object.assign({}, props.attributes), props.children);
4386
4327
  }
@@ -4391,6 +4332,9 @@ var createUnderlinePlugin = function createUnderlinePlugin() {
4391
4332
  options: {
4392
4333
  hotkey: ['mod+u']
4393
4334
  },
4335
+ handlers: {
4336
+ onKeyDown: buildMarkEventHandler(Contentful.MARKS.UNDERLINE)
4337
+ },
4394
4338
  deserializeHtml: {
4395
4339
  rules: [{
4396
4340
  validNodeName: ['U']
@@ -4613,6 +4557,7 @@ var withNormalizer = function withNormalizer(editor) {
4613
4557
  var createNormalizerPlugin = function createNormalizerPlugin() {
4614
4558
  return {
4615
4559
  key: 'NormalizerPlugin',
4560
+ // @ts-expect-error
4616
4561
  withOverrides: withNormalizer
4617
4562
  };
4618
4563
  };
@@ -4790,9 +4735,12 @@ function Quote(props) {
4790
4735
  }), props.children);
4791
4736
  }
4792
4737
 
4793
- function toggleQuote(editor) {
4738
+ function toggleQuote(editor, logAction) {
4794
4739
  if (!editor.selection) return;
4795
4740
  var isActive = isBlockSelected(editor, Contentful.BLOCKS.QUOTE);
4741
+ logAction(isActive ? 'remove' : 'insert', {
4742
+ nodeType: Contentful.BLOCKS.QUOTE
4743
+ });
4796
4744
  slate.Editor.withoutNormalizing(editor, function () {
4797
4745
  if (!editor.selection) return;
4798
4746
  slate.Transforms.unwrapNodes(editor, {
@@ -4824,7 +4772,7 @@ var onKeyDownToggleQuote = function onKeyDownToggleQuote(editor, plugin) {
4824
4772
 
4825
4773
  if (hotkey && isHotkey(hotkey, event)) {
4826
4774
  event.preventDefault();
4827
- toggleQuote(editor);
4775
+ toggleQuote(editor, editor.tracking.onShortcutAction);
4828
4776
  }
4829
4777
  };
4830
4778
  };
@@ -4851,7 +4799,54 @@ function createQuotePlugin() {
4851
4799
  normalizer: [{
4852
4800
  validChildren: Contentful.CONTAINERS[Contentful.BLOCKS.QUOTE],
4853
4801
  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
- }]
4802
+ }],
4803
+ withOverrides: function withOverrides(editor) {
4804
+ var insertFragment = editor.insertFragment;
4805
+
4806
+ editor.insertFragment = function (fragment) {
4807
+ var startingNode = fragment.length && fragment[0];
4808
+ var startsWithBlockquote = slate.Element.isElement(startingNode) && startingNode.type === Contentful.BLOCKS.QUOTE;
4809
+ var containerEntry = plateCore.getAbove(editor, {
4810
+ match: {
4811
+ type: Contentful.TEXT_CONTAINERS
4812
+ }
4813
+ });
4814
+ var containerIsNotEmpty = containerEntry && slate.Node.string(containerEntry[0]) !== '';
4815
+
4816
+ if (startsWithBlockquote && containerIsNotEmpty) {
4817
+ var selection = editor.selection;
4818
+
4819
+ var isContentSelected = function isContentSelected(selection) {
4820
+ return !!selection && slate.Point.compare(selection.anchor, selection.focus) !== 0;
4821
+ }; // if something is selected (highlighted) we replace the selection
4822
+
4823
+
4824
+ if (isContentSelected(selection)) {
4825
+ slate.Transforms["delete"](editor, {
4826
+ at: selection
4827
+ });
4828
+ } // get the cursor entry again, it may be different after deletion
4829
+
4830
+
4831
+ var _containerEntry = plateCore.getAbove(editor, {
4832
+ match: {
4833
+ type: Contentful.TEXT_CONTAINERS
4834
+ }
4835
+ });
4836
+
4837
+ var _containerIsNotEmpty = _containerEntry && slate.Node.string(_containerEntry[0]) !== '';
4838
+
4839
+ if (_containerIsNotEmpty) {
4840
+ slate.Transforms.insertNodes(editor, fragment);
4841
+ return;
4842
+ }
4843
+ }
4844
+
4845
+ insertFragment(fragment);
4846
+ };
4847
+
4848
+ return editor;
4849
+ }
4855
4850
  };
4856
4851
  }
4857
4852
 
@@ -4860,7 +4855,7 @@ function ToolbarQuoteButton(props) {
4860
4855
 
4861
4856
  function handleOnClick() {
4862
4857
  if (!editor) return;
4863
- toggleQuote(editor);
4858
+ toggleQuote(editor, editor.tracking.onToolbarAction);
4864
4859
  focus(editor);
4865
4860
  }
4866
4861
 
@@ -4909,8 +4904,7 @@ function hasHeadersOutsideFirstRow(nodes) {
4909
4904
  });
4910
4905
  }
4911
4906
 
4912
- function addTableTrackingEvents(editor, _ref6) {
4913
- var onViewportAction = _ref6.onViewportAction;
4907
+ function addTableTrackingEvents(editor) {
4914
4908
  var insertData = editor.insertData;
4915
4909
 
4916
4910
  editor.insertData = function (data) {
@@ -4924,7 +4918,7 @@ function addTableTrackingEvents(editor, _ref6) {
4924
4918
  if (hasTables(markupBefore)) return;
4925
4919
 
4926
4920
  if (hasTables(markupAfter)) {
4927
- onViewportAction('paste', {
4921
+ editor.tracking.onViewportAction('paste', {
4928
4922
  tablePasted: true,
4929
4923
  hasHeadersOutsideFirstRow: hasHeadersOutsideFirstRow(markupAfter)
4930
4924
  });
@@ -4936,29 +4930,6 @@ function addTableTrackingEvents(editor, _ref6) {
4936
4930
  };
4937
4931
  }
4938
4932
 
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
4933
  var addRow = function addRow(editor, getNextRowPath) {
4963
4934
  if (plateCore.someNode(editor, {
4964
4935
  match: {
@@ -5204,9 +5175,6 @@ var TableActions = function TableActions() {
5204
5175
  var editor = useContentfulEditor();
5205
5176
  var isDisabled = Slate.useReadOnly();
5206
5177
 
5207
- var _useTrackingContext = useTrackingContext(),
5208
- onViewportAction = _useTrackingContext.onViewportAction;
5209
-
5210
5178
  var _React$useState = React__default.useState(false),
5211
5179
  isOpen = _React$useState[0],
5212
5180
  setOpen = _React$useState[1];
@@ -5256,11 +5224,11 @@ var TableActions = function TableActions() {
5256
5224
  }); // Tracking
5257
5225
 
5258
5226
  var actionName = type + "Table" + (element === 'Table' ? '' : element);
5259
- onViewportAction(actionName, {
5227
+ editor.tracking.onViewportAction(actionName, {
5260
5228
  tableSize: tableSize
5261
5229
  });
5262
5230
  };
5263
- }, [editor, isHeaderEnabled, close, onViewportAction]);
5231
+ }, [editor, isHeaderEnabled, close]);
5264
5232
 
5265
5233
  if (isDisabled) {
5266
5234
  return null;
@@ -5351,7 +5319,7 @@ var createTableOnKeyDown = function createTableOnKeyDown(editor, plugin) {
5351
5319
  };
5352
5320
  };
5353
5321
 
5354
- var createTablePlugin = function createTablePlugin(tracking) {
5322
+ var createTablePlugin = function createTablePlugin() {
5355
5323
  var _overrideByKey;
5356
5324
 
5357
5325
  return plateTable.createTablePlugin({
@@ -5360,7 +5328,7 @@ var createTablePlugin = function createTablePlugin(tracking) {
5360
5328
  onKeyDown: createTableOnKeyDown
5361
5329
  },
5362
5330
  withOverrides: function withOverrides(editor) {
5363
- addTableTrackingEvents(editor, tracking);
5331
+ addTableTrackingEvents(editor);
5364
5332
  var insertFragment = editor.insertFragment;
5365
5333
 
5366
5334
  editor.insertFragment = function (fragments) {
@@ -5460,10 +5428,6 @@ var createTablePlugin = function createTablePlugin(tracking) {
5460
5428
 
5461
5429
  function ToolbarTableButton(props) {
5462
5430
  var editor = useContentfulEditor();
5463
-
5464
- var _useTrackingContext = useTrackingContext(),
5465
- onViewportAction = _useTrackingContext.onViewportAction;
5466
-
5467
5431
  var isActive = editor && isTableActive(editor);
5468
5432
 
5469
5433
  function handleClick() {
@@ -5484,7 +5448,7 @@ function ToolbarTableButton(props) {
5484
5448
  return _context.abrupt("return");
5485
5449
 
5486
5450
  case 2:
5487
- onViewportAction('insertTable');
5451
+ editor.tracking.onToolbarAction('insertTable');
5488
5452
  insertTableAndFocusFirstCell(editor);
5489
5453
  focus(editor);
5490
5454
 
@@ -5589,35 +5553,199 @@ function deleteEmptyParagraph(unit, editor, deleteFunction) {
5589
5553
  }
5590
5554
  }
5591
5555
 
5592
- var createTrailingParagraphPlugin = function createTrailingParagraphPlugin() {
5593
- return plateTrailingBlock.createTrailingBlockPlugin({
5594
- options: {
5595
- type: Contentful.BLOCKS.PARAGRAPH,
5596
- level: 0
5556
+ var _extends2, _extends4, _inlines;
5557
+ var inlines = /*#__PURE__*/Object.values(Contentful.INLINES).map(function (type) {
5558
+ return {
5559
+ type: type
5560
+ };
5561
+ });
5562
+ var schema = {
5563
+ document: {
5564
+ nodes: [{
5565
+ types: /*#__PURE__*/Contentful.TOP_LEVEL_BLOCKS.map(function (type) {
5566
+ return {
5567
+ type: type
5568
+ };
5569
+ })
5570
+ }]
5571
+ },
5572
+ blocks: /*#__PURE__*/_extends((_extends2 = {}, _extends2[Contentful.BLOCKS.PARAGRAPH] = {
5573
+ nodes: [{
5574
+ match: /*#__PURE__*/[].concat(inlines, [{
5575
+ object: 'text'
5576
+ }])
5577
+ }]
5578
+ }, _extends2[Contentful.BLOCKS.HEADING_1] = {
5579
+ nodes: [{
5580
+ match: /*#__PURE__*/[].concat(inlines, [{
5581
+ object: 'text'
5582
+ }])
5583
+ }]
5584
+ }, _extends2[Contentful.BLOCKS.HEADING_2] = {
5585
+ nodes: [{
5586
+ match: /*#__PURE__*/[].concat(inlines, [{
5587
+ object: 'text'
5588
+ }])
5589
+ }]
5590
+ }, _extends2[Contentful.BLOCKS.HEADING_3] = {
5591
+ nodes: [{
5592
+ match: /*#__PURE__*/[].concat(inlines, [{
5593
+ object: 'text'
5594
+ }])
5595
+ }]
5596
+ }, _extends2[Contentful.BLOCKS.HEADING_4] = {
5597
+ nodes: [{
5598
+ match: /*#__PURE__*/[].concat(inlines, [{
5599
+ object: 'text'
5600
+ }])
5601
+ }]
5602
+ }, _extends2[Contentful.BLOCKS.HEADING_5] = {
5603
+ nodes: [{
5604
+ match: /*#__PURE__*/[].concat(inlines, [{
5605
+ object: 'text'
5606
+ }])
5607
+ }]
5608
+ }, _extends2[Contentful.BLOCKS.HEADING_6] = {
5609
+ nodes: [{
5610
+ match: /*#__PURE__*/[].concat(inlines, [{
5611
+ object: 'text'
5612
+ }])
5613
+ }]
5614
+ }, _extends2), /*#__PURE__*/Contentful.VOID_BLOCKS.reduce(function (blocks, nodeType) {
5615
+ var _extends3;
5616
+
5617
+ return _extends({}, blocks, (_extends3 = {}, _extends3[nodeType] = {
5618
+ isVoid: true
5619
+ }, _extends3));
5620
+ }, {}), (_extends4 = {}, _extends4[Contentful.BLOCKS.QUOTE] = {
5621
+ nodes: [{
5622
+ match: [/*#__PURE__*/Contentful.CONTAINERS[Contentful.BLOCKS.QUOTE].map(function (type) {
5623
+ return {
5624
+ type: type
5625
+ };
5626
+ })],
5627
+ min: 1
5628
+ }],
5629
+ normalize: function normalize(editor, error) {
5630
+ if (error.code === 'child_type_invalid') {
5631
+ return editor.unwrapBlockByKey(error.node.key, Contentful.BLOCKS.QUOTE);
5632
+ }
5597
5633
  }
5634
+ }, _extends4)),
5635
+ inlines: (_inlines = {}, _inlines[Contentful.INLINES.HYPERLINK] = {
5636
+ nodes: [{
5637
+ match: [{
5638
+ object: 'text'
5639
+ }]
5640
+ }]
5641
+ }, _inlines[Contentful.INLINES.ENTRY_HYPERLINK] = {
5642
+ nodes: [{
5643
+ match: [{
5644
+ object: 'text'
5645
+ }]
5646
+ }]
5647
+ }, _inlines[Contentful.INLINES.ASSET_HYPERLINK] = {
5648
+ nodes: [{
5649
+ match: [{
5650
+ object: 'text'
5651
+ }]
5652
+ }]
5653
+ }, _inlines[Contentful.INLINES.EMBEDDED_ENTRY] = {
5654
+ isVoid: true
5655
+ }, _inlines)
5656
+ };
5657
+
5658
+ function getCharacterCount(editor) {
5659
+ var document = contentfulSlateJSAdapter.toContentfulDocument({
5660
+ document: editor.children,
5661
+ schema: schema
5598
5662
  });
5663
+ return richTextPlainTextRenderer.documentToPlainTextString(document).length;
5664
+ }
5665
+
5666
+ var actionOrigin = {
5667
+ TOOLBAR: 'toolbar-icon',
5668
+ SHORTCUT: 'shortcut',
5669
+ VIEWPORT: 'viewport-interaction',
5670
+ COMMAND_PALETTE: 'command-palette'
5599
5671
  };
5672
+ var createTrackingPlugin = function createTrackingPlugin(onAction) {
5673
+ var trackingActions = {
5674
+ onViewportAction: function onViewportAction(actionName, data) {
5675
+ if (data === void 0) {
5676
+ data = {};
5677
+ }
5600
5678
 
5601
- /**
5602
- * Re-creates a void node with valid children.
5603
- */
5679
+ return onAction(actionName, _extends({
5680
+ origin: actionOrigin.VIEWPORT
5681
+ }, data));
5682
+ },
5683
+ onShortcutAction: function onShortcutAction(actionName, data) {
5684
+ if (data === void 0) {
5685
+ data = {};
5686
+ }
5604
5687
 
5605
- var transformVoid = function transformVoid(editor, _ref) {
5606
- var node = _ref[0],
5607
- path = _ref[1];
5688
+ return onAction(actionName, _extends({
5689
+ origin: actionOrigin.SHORTCUT
5690
+ }, data));
5691
+ },
5692
+ onToolbarAction: function onToolbarAction(actionName, data) {
5693
+ if (data === void 0) {
5694
+ data = {};
5695
+ }
5608
5696
 
5609
- var validVoid = _extends({}, node, {
5610
- children: [{
5611
- text: ''
5612
- }]
5613
- }); // A workaround because Slate doesn't allow adjusting void nodes children
5697
+ return onAction(actionName, _extends({
5698
+ origin: actionOrigin.TOOLBAR
5699
+ }, data));
5700
+ },
5701
+ onCommandPaletteAction: function onCommandPaletteAction(actionName, data) {
5702
+ if (data === void 0) {
5703
+ data = {};
5704
+ }
5614
5705
 
5706
+ return onAction(actionName, _extends({
5707
+ origin: actionOrigin.COMMAND_PALETTE
5708
+ }, data));
5709
+ }
5710
+ };
5711
+ return {
5712
+ key: 'TrackingPlugin',
5713
+ withOverrides: function withOverrides(editor) {
5714
+ var insertData = editor.insertData;
5715
+ editor.tracking = trackingActions;
5716
+
5717
+ editor.insertData = function (data) {
5718
+ var isCopyAndPaste = data.types.length !== 0;
5719
+
5720
+ if (isCopyAndPaste) {
5721
+ var _window$getSelection;
5722
+
5723
+ var characterCountSelection = (_window$getSelection = window.getSelection()) == null ? void 0 : _window$getSelection.toString().length;
5724
+ var characterCountBefore = getCharacterCount(editor);
5725
+ setTimeout(function () {
5726
+ var characterCountAfter = getCharacterCount(editor);
5727
+ trackingActions.onShortcutAction('paste', {
5728
+ characterCountAfter: characterCountAfter,
5729
+ characterCountBefore: characterCountBefore,
5730
+ characterCountSelection: characterCountSelection
5731
+ });
5732
+ });
5733
+ }
5615
5734
 
5616
- slate.Transforms.removeNodes(editor, {
5617
- at: path
5618
- });
5619
- slate.Transforms.insertNodes(editor, [validVoid], {
5620
- at: path
5735
+ insertData(data);
5736
+ };
5737
+
5738
+ return editor;
5739
+ }
5740
+ };
5741
+ };
5742
+
5743
+ var createTrailingParagraphPlugin = function createTrailingParagraphPlugin() {
5744
+ return plateTrailingBlock.createTrailingBlockPlugin({
5745
+ options: {
5746
+ type: Contentful.BLOCKS.PARAGRAPH,
5747
+ level: 0
5748
+ }
5621
5749
  });
5622
5750
  };
5623
5751
 
@@ -5649,34 +5777,17 @@ var createVoidsPlugin = function createVoidsPlugin() {
5649
5777
  return !(isRootLevel(path) && plateCore.isFirstChild(path)) && !!node.isVoid;
5650
5778
  }
5651
5779
  }
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
5780
  }]
5671
5781
  };
5672
5782
  };
5673
5783
 
5674
- var getPlugins = function getPlugins(sdk, tracking) {
5784
+ var getPlugins = function getPlugins(sdk, onAction) {
5675
5785
  return [// AST must come after the HTML deserializer
5676
- plateCore.createDeserializeHtmlPlugin(), plateCore.createDeserializeAstPlugin(), plateSerializerDocx.createDeserializeDocxPlugin(), // Global shortcuts
5786
+ plateCore.createDeserializeHtmlPlugin(), plateCore.createDeserializeAstPlugin(), plateSerializerDocx.createDeserializeDocxPlugin(), // Tracking - This should come first so all plugins below will have access to `editor.tracking`
5787
+ createTrackingPlugin(onAction), // Global / Global shortcuts
5677
5788
  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
5789
+ createParagraphPlugin(), createListPlugin(), createHrPlugin(), createHeadingPlugin(), createQuotePlugin(), createTablePlugin(), createEmbeddedEntryBlockPlugin(sdk), createEmbeddedAssetBlockPlugin(sdk), // Inline elements
5790
+ createHyperlinkPlugin(sdk), createEmbeddedEntityInlinePlugin(sdk), // Marks
5680
5791
  createMarksPlugin(), // Other
5681
5792
  createTrailingParagraphPlugin(), createTextPlugin(), createVoidsPlugin(), createSelectOnBackspacePlugin(), // Pasting content from other sources
5682
5793
  createPasteHTMLPlugin(), // These plugins drive their configurations from the list of plugins
@@ -5971,7 +6082,7 @@ var useNormalizedSlateValue = function useNormalizedSlateValue(_ref) {
5971
6082
  plugins: plugins,
5972
6083
  disableCorePlugins: disableCorePlugins
5973
6084
  });
5974
- var doc = contentfulSlatejsAdapter.toSlatejsDocument({
6085
+ var doc = contentfulSlateJSAdapter.toSlatejsDocument({
5975
6086
  document: hasContent(incomingDoc) ? incomingDoc : Contentful.EMPTY_DOCUMENT,
5976
6087
  schema: schema
5977
6088
  }); // Sets editor value & kicks normalization
@@ -5985,18 +6096,56 @@ var useNormalizedSlateValue = function useNormalizedSlateValue(_ref) {
5985
6096
  }, [id, plugins, incomingDoc]);
5986
6097
  };
5987
6098
 
6099
+ /**
6100
+ * Returns whether a given operation is relevant enough to trigger a save.
6101
+ */
6102
+
6103
+ var isRelevantOperation = function isRelevantOperation(op) {
6104
+ if (op.type === 'set_selection') {
6105
+ return false;
6106
+ }
6107
+
6108
+ return true;
6109
+ };
6110
+
6111
+ var useOnValueChanged = function useOnValueChanged(_ref) {
6112
+ var editor = _ref.editor,
6113
+ handler = _ref.handler;
6114
+ var onChange = React.useMemo(function () {
6115
+ return debounce(function (document) {
6116
+ handler == null ? void 0 : handler(contentfulSlateJSAdapter.toContentfulDocument({
6117
+ document: document,
6118
+ schema: schema
6119
+ }));
6120
+ }, 500);
6121
+ }, [handler]);
6122
+ return React.useCallback(function (value) {
6123
+ var operations = editor.operations.filter(isRelevantOperation);
6124
+
6125
+ if (operations.length > 0) {
6126
+ onChange(value);
6127
+ }
6128
+ }, [editor, onChange]);
6129
+ };
6130
+
5988
6131
  var _excluded = ["sdk", "isInitiallyDisabled", "onAction"];
5989
6132
  var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
5990
- var id = getContentfulEditorId(props.sdk);
5991
- var tracking = useTrackingContext();
6133
+ var id = useContentfulEditorId();
6134
+ var editor = useContentfulEditor();
5992
6135
  var plugins = React__default.useMemo(function () {
5993
- return getPlugins(props.sdk, tracking);
5994
- }, [props.sdk, tracking]);
6136
+ var _props$onAction;
6137
+
6138
+ return getPlugins(props.sdk, (_props$onAction = props.onAction) != null ? _props$onAction : noop);
6139
+ }, [props.sdk, props.onAction]);
5995
6140
  var initialValue = useNormalizedSlateValue({
5996
6141
  id: id,
5997
6142
  incomingDoc: props.value,
5998
6143
  plugins: plugins
5999
6144
  });
6145
+ var onValueChanged = useOnValueChanged({
6146
+ editor: editor,
6147
+ handler: props.onChange
6148
+ });
6000
6149
  var classNames = emotion.cx(styles$j.editor, props.minHeight !== undefined ? emotion.css({
6001
6150
  minHeight: props.minHeight
6002
6151
  }) : undefined, props.isDisabled ? styles$j.disabled : styles$j.enabled, props.isToolbarHidden && styles$j.hiddenToolbar);
@@ -6012,12 +6161,7 @@ var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
6012
6161
  className: classNames,
6013
6162
  readOnly: props.isDisabled
6014
6163
  },
6015
- onChange: function onChange(document) {
6016
- props.onChange == null ? void 0 : props.onChange(contentfulSlatejsAdapter.toContentfulDocument({
6017
- document: document,
6018
- schema: schema
6019
- }));
6020
- }
6164
+ onChange: onValueChanged
6021
6165
  }, !props.isToolbarHidden && /*#__PURE__*/React__default.createElement(StickyToolbarWrapper, {
6022
6166
  isDisabled: props.isDisabled
6023
6167
  }, /*#__PURE__*/React__default.createElement(Toolbar, {
@@ -6034,12 +6178,11 @@ var RichTextEditor = function RichTextEditor(props) {
6034
6178
  var isEmptyValue = React.useCallback(function (value) {
6035
6179
  return !value || deepEquals(value, Contentful.EMPTY_DOCUMENT);
6036
6180
  }, []);
6181
+ var editorId = getContentfulEditorId(sdk);
6037
6182
  return /*#__PURE__*/React__default.createElement(fieldEditorReference.EntityProvider, {
6038
6183
  sdk: sdk
6039
6184
  }, /*#__PURE__*/React__default.createElement(SdkProvider, {
6040
6185
  sdk: sdk
6041
- }, /*#__PURE__*/React__default.createElement(TrackingProvider, {
6042
- onAction: onAction || noop
6043
6186
  }, /*#__PURE__*/React__default.createElement(fieldEditorShared.FieldConnector, {
6044
6187
  throttle: 0,
6045
6188
  field: sdk.field,
@@ -6051,17 +6194,17 @@ var RichTextEditor = function RichTextEditor(props) {
6051
6194
  disabled = _ref.disabled,
6052
6195
  setValue = _ref.setValue,
6053
6196
  externalReset = _ref.externalReset;
6054
- return /*#__PURE__*/React__default.createElement(ContentfulEditorProvider, {
6055
- sdk: sdk
6197
+ return /*#__PURE__*/React__default.createElement(ContentfulEditorIdProvider, {
6198
+ value: editorId
6056
6199
  }, /*#__PURE__*/React__default.createElement(ConnectedRichTextEditor, Object.assign({}, otherProps, {
6057
6200
  key: "rich-text-editor-" + externalReset,
6058
6201
  value: lastRemoteValue,
6059
6202
  sdk: sdk,
6060
- onAction: onAction || noop,
6203
+ onAction: onAction,
6061
6204
  isDisabled: disabled,
6062
6205
  onChange: setValue
6063
6206
  })));
6064
- }))));
6207
+ })));
6065
6208
  };
6066
6209
 
6067
6210
  var LINK_TYPES$1 = {