@contentful/field-editor-rich-text 2.0.0-next.41 → 2.0.0-next.44

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.
@@ -1,10 +1,10 @@
1
- import React__default, { createContext, useContext, useMemo, useEffect, createElement, useState, memo, Fragment, useCallback } from 'react';
1
+ import React__default, { createContext, useContext, useMemo, useState, useEffect, memo, createElement, Fragment, useCallback } from 'react';
2
2
  import { useEntities, MissingEntityCard, WrappedAssetCard, WrappedEntryCard, ScheduledIconWithTooltip, EntityProvider, getScheduleTooltipContent } from '@contentful/field-editor-reference';
3
3
  import { entityHelpers, ModalDialogLauncher, FieldConnector } from '@contentful/field-editor-shared';
4
4
  import { BLOCKS, INLINES, TEXT_CONTAINERS, HEADINGS, LIST_ITEM_BLOCKS, MARKS, CONTAINERS, TOP_LEVEL_BLOCKS, VOID_BLOCKS, EMPTY_DOCUMENT } from '@contentful/rich-text-types';
5
5
  import { usePlateEditorRef, usePlateEditorState, getNodes, toggleNodeType, getText, getAbove, setNodes, isAncestorEmpty, match, getLastChildPath, wrapNodes, getPluginType, unwrapNodes, isCollapsed, isRangeAcrossBlocks, ELEMENT_DEFAULT, findNode, getParent, getBlockAbove, isSelectionAtBlockStart, isSelectionAtBlockEnd, isFirstChild, insertNodes, moveChildren, isBlockAboveEmpty, mockPlugin, deleteFragment, isMarkActive, toggleMark, someHtmlElement, KEY_DESERIALIZE_HTML, hasSingleChild, isLastChild, someNode, getChildren as getChildren$1, queryNode, createDeserializeHtmlPlugin, createDeserializeAstPlugin, createPlateEditor, getPlateSelectors, getPlateActions, Plate } from '@udecode/plate-core';
6
6
  import { css, cx } from 'emotion';
7
- import deepEquals from 'fast-deep-equal';
7
+ import areEqual from 'fast-deep-equal';
8
8
  import noop from 'lodash-es/noop';
9
9
  import { createDeserializeDocxPlugin } from '@udecode/plate-serializer-docx';
10
10
  import { createSoftBreakPlugin as createSoftBreakPlugin$1, createExitBreakPlugin as createExitBreakPlugin$1 } from '@udecode/plate-break';
@@ -393,17 +393,8 @@ function getParents(el) {
393
393
  return parents;
394
394
  }
395
395
 
396
- // "modern" Edge was released at 79.x
397
- var IS_EDGE_LEGACY = typeof navigator !== 'undefined' && /*#__PURE__*/ /Edge?\/(?:[0-6][0-9]|[0-7][0-8])/i.test(navigator.userAgent); // Native `beforeInput` events don't work well with react on Chrome 75
398
- // and older, Chrome 76+ can use `beforeInput` though.
399
-
400
- var IS_CHROME_LEGACY = typeof navigator !== 'undefined' && /*#__PURE__*/ /Chrome?\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent); // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
401
- // Chrome Legacy doesn't support `beforeinput` correctly
402
-
403
- var HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY && !IS_EDGE_LEGACY && // globalThis is undefined in older browsers
404
- typeof globalThis !== 'undefined' && globalThis.InputEvent && typeof globalThis.InputEvent.prototype.getTargetRanges === 'function'; // The `getTargetRanges` property isn't recognized.
405
-
406
396
  var IS_SAFARI = typeof navigator !== 'undefined' && /*#__PURE__*/ /Version\/[\d.]+.*Safari/.test(navigator.userAgent);
397
+ var IS_CHROME = /*#__PURE__*/ /(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9.]+)(:?\s|$)/.test(navigator.userAgent);
407
398
 
408
399
  var LINK_TYPES = [INLINES.HYPERLINK, INLINES.ENTRY_HYPERLINK, INLINES.ASSET_HYPERLINK];
409
400
  function isBlockSelected(editor, type) {
@@ -631,26 +622,56 @@ var _constate = /*#__PURE__*/constate(useSdk),
631
622
  SdkProvider = _constate[0],
632
623
  useSdkContext = _constate[1];
633
624
 
634
- function FetchingWrappedAssetCard(props) {
635
- var onEntityFetchComplete = props.onEntityFetchComplete,
636
- assetId = props.assetId;
625
+ function useFetchedEntity(_ref) {
626
+ var type = _ref.type,
627
+ id = _ref.id,
628
+ onEntityFetchComplete = _ref.onEntityFetchComplete;
637
629
 
638
630
  var _useEntities = useEntities(),
639
- getOrLoadAsset = _useEntities.getOrLoadAsset,
640
- loadEntityScheduledActions = _useEntities.loadEntityScheduledActions,
641
- assets = _useEntities.assets;
631
+ entries = _useEntities.entries,
632
+ assets = _useEntities.assets,
633
+ getOrLoadEntry = _useEntities.getOrLoadEntry,
634
+ getOrLoadAsset = _useEntities.getOrLoadAsset;
635
+
636
+ var store = type === 'Entry' ? entries : assets;
637
+
638
+ var _useState = useState(store[id]),
639
+ entity = _useState[0],
640
+ setEntity = _useState[1]; // Deep compare the entity value to keep re-rendering to minimal
641
+
642
642
 
643
643
  useEffect(function () {
644
- getOrLoadAsset(assetId);
645
- }, [getOrLoadAsset, assetId]);
646
- var asset = assets[assetId];
644
+ var newValue = store[id];
645
+
646
+ if (!areEqual(entity, newValue)) {
647
+ setEntity(newValue);
648
+ }
649
+ }, [store, entity, id]); // Fetch the entity if needed
650
+
647
651
  useEffect(function () {
648
- if (asset) {
652
+ (type === 'Entry' ? getOrLoadEntry : getOrLoadAsset)(id); // "getOrLoadEntry" and "getOrLoadAsset" instances change with every
653
+ // entity store update causing page lag on initial load
654
+ // TODO: consider rewriting useEntities() hook to avoid that happening in
655
+ // first place.
656
+ // eslint-disable-next-line react-hooks/exhaustive-deps
657
+ }, [type, id]);
658
+ useEffect(function () {
659
+ if (entity) {
649
660
  onEntityFetchComplete == null ? void 0 : onEntityFetchComplete();
650
661
  }
651
- }, [onEntityFetchComplete, asset]);
662
+ }, [onEntityFetchComplete, entity]);
663
+ return entity;
664
+ }
665
+
666
+ var InternalAssetCard = /*#__PURE__*/memo(function (props) {
667
+ if (props.asset === undefined) {
668
+ return /*#__PURE__*/createElement(AssetCard, {
669
+ size: "default",
670
+ isLoading: true
671
+ });
672
+ }
652
673
 
653
- if (asset === 'failed') {
674
+ if (props.asset === 'failed') {
654
675
  return /*#__PURE__*/createElement(MissingEntityCard, {
655
676
  entityType: "Asset",
656
677
  isDisabled: props.isDisabled,
@@ -658,45 +679,48 @@ function FetchingWrappedAssetCard(props) {
658
679
  });
659
680
  }
660
681
 
661
- if (asset === undefined) {
662
- return /*#__PURE__*/createElement(AssetCard, {
663
- size: "default",
664
- isLoading: true
665
- });
666
- }
667
-
668
682
  return /*#__PURE__*/createElement(WrappedAssetCard, {
669
- getEntityScheduledActions: loadEntityScheduledActions,
683
+ getEntityScheduledActions: props.loadEntityScheduledActions,
670
684
  size: "small",
671
685
  isSelected: props.isSelected,
672
686
  isDisabled: props.isDisabled,
673
687
  localeCode: props.locale,
674
688
  defaultLocaleCode: props.sdk.locales["default"],
675
- asset: asset,
689
+ asset: props.asset,
676
690
  onEdit: props.onEdit,
677
691
  onRemove: props.isDisabled ? undefined : props.onRemove,
678
692
  isClickable: false
679
693
  });
680
- }
681
-
682
- function FetchingWrappedEntryCard(props) {
683
- var entryId = props.entryId,
684
- onEntityFetchComplete = props.onEntityFetchComplete;
694
+ }, areEqual);
695
+ InternalAssetCard.displayName = 'InternalAssetCard';
696
+ function FetchingWrappedAssetCard(props) {
697
+ var onEntityFetchComplete = props.onEntityFetchComplete,
698
+ assetId = props.assetId;
685
699
 
686
700
  var _useEntities = useEntities(),
687
- getOrLoadEntry = _useEntities.getOrLoadEntry,
688
- loadEntityScheduledActions = _useEntities.loadEntityScheduledActions,
689
- entries = _useEntities.entries;
701
+ loadEntityScheduledActions = _useEntities.loadEntityScheduledActions;
690
702
 
691
- useEffect(function () {
692
- getOrLoadEntry(entryId);
693
- }, [getOrLoadEntry, entryId]);
694
- var entry = entries[entryId];
695
- useEffect(function () {
696
- if (entry) {
697
- onEntityFetchComplete == null ? void 0 : onEntityFetchComplete();
698
- }
699
- }, [onEntityFetchComplete, entry]);
703
+ var asset = useFetchedEntity({
704
+ type: 'Asset',
705
+ id: assetId,
706
+ onEntityFetchComplete: onEntityFetchComplete
707
+ });
708
+ return /*#__PURE__*/createElement(InternalAssetCard, {
709
+ asset: asset,
710
+ sdk: props.sdk,
711
+ isDisabled: props.isDisabled,
712
+ isSelected: props.isSelected,
713
+ loadEntityScheduledActions: loadEntityScheduledActions,
714
+ locale: props.locale,
715
+ onEdit: props.onEdit,
716
+ onRemove: props.onRemove
717
+ });
718
+ }
719
+
720
+ var InternalEntryCard = /*#__PURE__*/memo(function (props) {
721
+ var entry = props.entry,
722
+ sdk = props.sdk,
723
+ loadEntityScheduledActions = props.loadEntityScheduledActions;
700
724
 
701
725
  if (entry === undefined) {
702
726
  return /*#__PURE__*/createElement(EntryCard, {
@@ -712,7 +736,7 @@ function FetchingWrappedEntryCard(props) {
712
736
  });
713
737
  }
714
738
 
715
- var contentType = props.sdk.space.getCachedContentTypes().find(function (contentType) {
739
+ var contentType = sdk.space.getCachedContentTypes().find(function (contentType) {
716
740
  return contentType.sys.id === entry.sys.contentType.sys.id;
717
741
  });
718
742
  return /*#__PURE__*/createElement(WrappedEntryCard, {
@@ -729,7 +753,31 @@ function FetchingWrappedEntryCard(props) {
729
753
  onRemove: props.isDisabled ? undefined : props.onRemove,
730
754
  isClickable: false
731
755
  });
732
- }
756
+ }, areEqual);
757
+ InternalEntryCard.displayName = 'ReferenceCard';
758
+ var FetchingWrappedEntryCard = function FetchingWrappedEntryCard(props) {
759
+ var entryId = props.entryId,
760
+ onEntityFetchComplete = props.onEntityFetchComplete;
761
+
762
+ var _useEntities = useEntities(),
763
+ loadEntityScheduledActions = _useEntities.loadEntityScheduledActions;
764
+
765
+ var entry = useFetchedEntity({
766
+ type: 'Entry',
767
+ id: entryId,
768
+ onEntityFetchComplete: onEntityFetchComplete
769
+ });
770
+ return /*#__PURE__*/createElement(InternalEntryCard, {
771
+ entry: entry,
772
+ sdk: props.sdk,
773
+ locale: props.locale,
774
+ isDisabled: props.isDisabled,
775
+ isSelected: props.isSelected,
776
+ onEdit: props.onEdit,
777
+ onRemove: props.onRemove,
778
+ loadEntityScheduledActions: loadEntityScheduledActions
779
+ });
780
+ };
733
781
 
734
782
  var styles = {
735
783
  root: /*#__PURE__*/css({
@@ -756,33 +804,30 @@ function LinkedEntityBlock(props) {
756
804
  var _element$data$target$ = element.data.target.sys,
757
805
  entityId = _element$data$target$.id,
758
806
  entityType = _element$data$target$.linkType;
759
-
760
- var handleEditClick = function handleEditClick() {
807
+ var handleEditClick = React__default.useCallback(function () {
761
808
  var openEntity = entityType === 'Asset' ? sdk.navigator.openAsset : sdk.navigator.openEntry;
762
809
  return openEntity(entityId, {
763
810
  slideIn: true
764
811
  });
765
- };
766
-
767
- var handleRemoveClick = function handleRemoveClick() {
812
+ }, [sdk, entityId, entityType]);
813
+ var handleRemoveClick = React__default.useCallback(function () {
768
814
  if (!editor) return;
769
815
  var pathToElement = ReactEditor.findPath(editor, element);
770
816
  Transforms.removeNodes(editor, {
771
817
  at: pathToElement
772
818
  });
773
- };
774
-
819
+ }, [editor, element]);
775
820
  return /*#__PURE__*/React__default.createElement("div", Object.assign({}, attributes, {
776
821
  className: styles.root,
777
822
  "data-entity-type": entityType,
778
823
  "data-entity-id": entityId,
779
824
  // COMPAT: This makes copy & paste work for Firefox
780
- contentEditable: !HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
781
- draggable: !HAS_BEFORE_INPUT_SUPPORT ? true : undefined
825
+ contentEditable: IS_CHROME ? undefined : false,
826
+ draggable: IS_CHROME ? true : undefined
782
827
  }), /*#__PURE__*/React__default.createElement("div", {
783
828
  // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari
784
- contentEditable: HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
785
- draggable: HAS_BEFORE_INPUT_SUPPORT ? true : undefined,
829
+ contentEditable: IS_CHROME ? false : undefined,
830
+ draggable: IS_CHROME ? true : undefined,
786
831
  className: styles.container
787
832
  }, entityType === 'Entry' && /*#__PURE__*/React__default.createElement(FetchingWrappedEntryCard, {
788
833
  sdk: sdk,
@@ -2036,12 +2081,12 @@ function EmbeddedEntityInline(props) {
2036
2081
  className: styles$3.root,
2037
2082
  "data-embedded-entity-inline-id": entryId,
2038
2083
  // COMPAT: This makes copy & paste work for Firefox
2039
- contentEditable: !HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
2040
- draggable: !HAS_BEFORE_INPUT_SUPPORT ? true : undefined
2084
+ contentEditable: IS_CHROME ? undefined : false,
2085
+ draggable: IS_CHROME ? true : undefined
2041
2086
  }), /*#__PURE__*/createElement("span", {
2042
2087
  // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari
2043
- contentEditable: HAS_BEFORE_INPUT_SUPPORT ? false : undefined,
2044
- draggable: HAS_BEFORE_INPUT_SUPPORT ? true : undefined
2088
+ contentEditable: IS_CHROME ? false : undefined,
2089
+ draggable: IS_CHROME ? true : undefined
2045
2090
  }, /*#__PURE__*/createElement(FetchingWrappedInlineEntryCard, {
2046
2091
  sdk: sdk,
2047
2092
  entryId: entryId,
@@ -6950,7 +6995,7 @@ var RichTextEditor = function RichTextEditor(props) {
6950
6995
  otherProps = _objectWithoutPropertiesLoose(props, _excluded);
6951
6996
 
6952
6997
  var isEmptyValue = useCallback(function (value) {
6953
- return !value || deepEquals(value, EMPTY_DOCUMENT);
6998
+ return !value || areEqual(value, EMPTY_DOCUMENT);
6954
6999
  }, []);
6955
7000
  var id = getContentfulEditorId(props.sdk);
6956
7001
  return /*#__PURE__*/React__default.createElement(EntityProvider, {
@@ -6960,7 +7005,7 @@ var RichTextEditor = function RichTextEditor(props) {
6960
7005
  field: sdk.field,
6961
7006
  isInitiallyDisabled: isInitiallyDisabled,
6962
7007
  isEmptyValue: isEmptyValue,
6963
- isEqualValues: deepEquals
7008
+ isEqualValues: areEqual
6964
7009
  }, function (_ref) {
6965
7010
  var lastRemoteValue = _ref.lastRemoteValue,
6966
7011
  disabled = _ref.disabled,