@contentful/field-editor-rich-text 2.0.0-next.20 → 2.0.0-next.23

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.
@@ -28,6 +28,7 @@ var tokens = _interopDefault(require('@contentful/f36-tokens'));
28
28
  var find = _interopDefault(require('lodash/find'));
29
29
  var flow = _interopDefault(require('lodash/flow'));
30
30
  var plateList = require('@udecode/plate-list');
31
+ var castArray = _interopDefault(require('lodash/castArray'));
31
32
  var plateBasicMarks = require('@udecode/plate-basic-marks');
32
33
  var isPlainObject = _interopDefault(require('is-plain-obj'));
33
34
  var plateParagraph = require('@udecode/plate-paragraph');
@@ -951,14 +952,22 @@ function FetchingWrappedEntryCard(props) {
951
952
  var onEntityFetchComplete = props.onEntityFetchComplete;
952
953
  React.useEffect(function () {
953
954
  if (!entry || entry === 'failed') return;
955
+ var subscribed = true;
954
956
  fieldEditorShared.entityHelpers.getEntryImage({
955
957
  entry: entry,
956
958
  contentType: contentType,
957
959
  localeCode: props.locale,
958
960
  defaultLocaleCode: defaultLocaleCode
959
- }, getOrLoadAsset).then(setFile)["catch"](function () {
960
- return setFile(null);
961
+ }, getOrLoadAsset)["catch"](function () {
962
+ return null;
963
+ }).then(function (file) {
964
+ if (subscribed) {
965
+ setFile(file);
966
+ }
961
967
  });
968
+ return function () {
969
+ subscribed = false;
970
+ };
962
971
  }, [entry, contentType, props.locale, defaultLocaleCode, props.sdk, file, getOrLoadAsset]);
963
972
  React.useEffect(function () {
964
973
  getOrLoadEntry(props.entryId);
@@ -1053,7 +1062,11 @@ function FetchingWrappedEntryCard(props) {
1053
1062
 
1054
1063
  var styles$3 = {
1055
1064
  root: /*#__PURE__*/emotion.css({
1056
- marginBottom: '1.25rem !important'
1065
+ marginBottom: '1.25rem !important',
1066
+ // The next 2 properties ensure Entity card won't be aligned above
1067
+ // a list item marker (i.e. bullet)
1068
+ display: 'inline-block',
1069
+ verticalAlign: 'text-top'
1057
1070
  })
1058
1071
  };
1059
1072
  function LinkedEntityBlock(props) {
@@ -2277,15 +2290,7 @@ function FetchingWrappedInlineEntryCard(props) {
2277
2290
  return /*#__PURE__*/React__default.createElement(f36Components.InlineEntryCard, {
2278
2291
  testId: Contentful.INLINES.EMBEDDED_ENTRY,
2279
2292
  isSelected: props.isSelected,
2280
- title: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("span", null, contentTypeName, " ", title), /*#__PURE__*/React__default.createElement(fieldEditorReference.ScheduledIconWithTooltip, {
2281
- getEntityScheduledActions: loadEntityScheduledActions,
2282
- entityType: "Entry",
2283
- entityId: entry.sys.id
2284
- }, /*#__PURE__*/React__default.createElement(f36Icons.ClockIcon, {
2285
- className: styles$5.scheduledIcon,
2286
- variant: "muted",
2287
- testId: "scheduled-icon"
2288
- }))),
2293
+ title: contentTypeName + ": " + title,
2289
2294
  status: status,
2290
2295
  actions: [/*#__PURE__*/React__default.createElement(f36Components.MenuItem, {
2291
2296
  key: "edit",
@@ -2297,7 +2302,15 @@ function FetchingWrappedInlineEntryCard(props) {
2297
2302
  disabled: props.isDisabled,
2298
2303
  testId: "card-action-remove"
2299
2304
  }, "Remove")]
2300
- });
2305
+ }, /*#__PURE__*/React__default.createElement(fieldEditorReference.ScheduledIconWithTooltip, {
2306
+ getEntityScheduledActions: loadEntityScheduledActions,
2307
+ entityType: "Entry",
2308
+ entityId: entry.sys.id
2309
+ }, /*#__PURE__*/React__default.createElement(f36Icons.ClockIcon, {
2310
+ className: styles$5.scheduledIcon,
2311
+ variant: "muted",
2312
+ testId: "scheduled-icon"
2313
+ })), /*#__PURE__*/React__default.createElement(f36Components.Text, null, title));
2301
2314
  }
2302
2315
 
2303
2316
  function createInlineEntryNode(id) {
@@ -2979,159 +2992,6 @@ var createHrPlugin = function createHrPlugin() {
2979
2992
  };
2980
2993
  };
2981
2994
 
2982
- function truncate(str, length) {
2983
- if (typeof str === 'string' && str.length > length) {
2984
- return str && str.substr(0, length + 1) // +1 to look ahead and be replaced below.
2985
- // Get rid of orphan letters but not one letter words (I, a, 2).
2986
- // Try to not have “.” as last character to avoid awkward “....”.
2987
- .replace(/(\s+\S(?=\S)|\s*)\.?.$/, '…');
2988
- }
2989
-
2990
- return str;
2991
- }
2992
-
2993
- function getEntityInfo(_ref) {
2994
- var entityTitle = _ref.entityTitle,
2995
- entityStatus = _ref.entityStatus,
2996
- contentTypeName = _ref.contentTypeName;
2997
- var title = truncate(entityTitle, 60) || 'Untitled';
2998
- return (contentTypeName || 'Asset') + " \"" + title + "\", " + entityStatus;
2999
- }
3000
-
3001
- function EntryAssetTooltip(_ref2) {
3002
- var id = _ref2.id,
3003
- type = _ref2.type,
3004
- sdk = _ref2.sdk;
3005
-
3006
- var _React$useState = React.useState(''),
3007
- entityTitle = _React$useState[0],
3008
- setEntityTitle = _React$useState[1];
3009
-
3010
- var _React$useState2 = React.useState(''),
3011
- entityStatus = _React$useState2[0],
3012
- setEntityStatus = _React$useState2[1];
3013
-
3014
- var _React$useState3 = React.useState([]),
3015
- jobs = _React$useState3[0],
3016
- setJobs = _React$useState3[1];
3017
-
3018
- var _React$useState4 = React.useState(true),
3019
- isLoading = _React$useState4[0],
3020
- setIsLoading = _React$useState4[1];
3021
-
3022
- var _React$useState5 = React.useState(false),
3023
- hasError = _React$useState5[0],
3024
- setHasError = _React$useState5[1];
3025
-
3026
- React.useEffect(function () {
3027
- function loadContent() {
3028
- return _loadContent.apply(this, arguments);
3029
- }
3030
-
3031
- function _loadContent() {
3032
- _loadContent = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
3033
- var actions, contentType, entity, contentTypeId, contentTypes, _entityTitle, _jobs, _entityStatus;
3034
-
3035
- return runtime_1.wrap(function _callee$(_context) {
3036
- while (1) {
3037
- switch (_context.prev = _context.next) {
3038
- case 0:
3039
- _context.prev = 0;
3040
- setIsLoading(true);
3041
- setHasError(false);
3042
- actions = {
3043
- Asset: {
3044
- getEntity: sdk.space.getAsset,
3045
- getEntityTitle: function getEntityTitle(args) {
3046
- return fieldEditorShared.entityHelpers.getAssetTitle(_extends({}, args, {
3047
- asset: args.entity
3048
- }));
3049
- }
3050
- },
3051
- Entry: {
3052
- getEntity: sdk.space.getEntry,
3053
- getEntityTitle: function getEntityTitle(args) {
3054
- return fieldEditorShared.entityHelpers.getEntryTitle(_extends({}, args, {
3055
- entry: args.entity
3056
- }));
3057
- }
3058
- }
3059
- };
3060
- _context.next = 6;
3061
- return actions[type].getEntity(id);
3062
-
3063
- case 6:
3064
- entity = _context.sent;
3065
-
3066
- if (entity.sys.contentType) {
3067
- contentTypeId = entity.sys.contentType.sys.id;
3068
- contentTypes = sdk.space.getCachedContentTypes();
3069
- contentType = contentTypes.find(function (ct) {
3070
- return ct.sys.id === contentTypeId;
3071
- });
3072
- }
3073
-
3074
- _entityTitle = actions[type].getEntityTitle({
3075
- entity: entity,
3076
- contentType: contentType,
3077
- localeCode: sdk.field.locale,
3078
- defaultLocaleCode: sdk.locales["default"],
3079
- entityType: type
3080
- });
3081
- _context.next = 11;
3082
- return sdk.space.getEntityScheduledActions(type, id);
3083
-
3084
- case 11:
3085
- _jobs = _context.sent;
3086
- _entityStatus = fieldEditorShared.entityHelpers.getEntryStatus(entity.sys);
3087
- setEntityTitle(_entityTitle);
3088
- setEntityStatus(_entityStatus);
3089
- setJobs(_jobs);
3090
- _context.next = 22;
3091
- break;
3092
-
3093
- case 18:
3094
- _context.prev = 18;
3095
- _context.t0 = _context["catch"](0);
3096
- console.log(_context.t0);
3097
- setHasError(true);
3098
-
3099
- case 22:
3100
- _context.prev = 22;
3101
- setIsLoading(false);
3102
- return _context.finish(22);
3103
-
3104
- case 25:
3105
- case "end":
3106
- return _context.stop();
3107
- }
3108
- }
3109
- }, _callee, null, [[0, 18, 22, 25]]);
3110
- }));
3111
- return _loadContent.apply(this, arguments);
3112
- }
3113
-
3114
- loadContent();
3115
- }, [id, type, sdk]);
3116
-
3117
- if (isLoading) {
3118
- return /*#__PURE__*/React.createElement(React.Fragment, null, "Loading " + type.toLowerCase() + "...");
3119
- }
3120
-
3121
- if (hasError) {
3122
- return /*#__PURE__*/React.createElement(React.Fragment, null, type + " missing or inaccessible");
3123
- }
3124
-
3125
- return /*#__PURE__*/React.createElement(React.Fragment, null, getEntityInfo({
3126
- entityTitle: entityTitle,
3127
- contentTypeName: type,
3128
- entityStatus: entityStatus
3129
- }), ' ', jobs.length > 0 ? fieldEditorReference.getScheduleTooltipContent({
3130
- job: jobs[0],
3131
- jobsCount: jobs.length
3132
- }) : '');
3133
- }
3134
-
3135
2995
  var _templateObject$3, _SYS_LINK_TYPES, _LINK_TYPE_SELECTION_;
3136
2996
  var styles$b = {
3137
2997
  removeSelectionLabel: /*#__PURE__*/emotion.css(_templateObject$3 || (_templateObject$3 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n margin-left: ", ";\n "])), tokens.spacingS)
@@ -3443,11 +3303,213 @@ function _addOrEditLink() {
3443
3303
  return _addOrEditLink.apply(this, arguments);
3444
3304
  }
3445
3305
 
3306
+ function ToolbarHyperlinkButton(props) {
3307
+ var editor = useContentfulEditor();
3308
+ var isActive = !!(editor && isLinkActive(editor));
3309
+ var sdk = useSdkContext();
3310
+
3311
+ function handleClick() {
3312
+ return _handleClick.apply(this, arguments);
3313
+ }
3314
+
3315
+ function _handleClick() {
3316
+ _handleClick = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
3317
+ return runtime_1.wrap(function _callee$(_context) {
3318
+ while (1) {
3319
+ switch (_context.prev = _context.next) {
3320
+ case 0:
3321
+ if (editor) {
3322
+ _context.next = 2;
3323
+ break;
3324
+ }
3325
+
3326
+ return _context.abrupt("return");
3327
+
3328
+ case 2:
3329
+ if (isActive) {
3330
+ unwrapLink(editor);
3331
+ editor.tracking.onToolbarAction('unlinkHyperlinks');
3332
+ } else {
3333
+ addOrEditLink(editor, sdk, editor.tracking.onToolbarAction);
3334
+ }
3335
+
3336
+ case 3:
3337
+ case "end":
3338
+ return _context.stop();
3339
+ }
3340
+ }
3341
+ }, _callee);
3342
+ }));
3343
+ return _handleClick.apply(this, arguments);
3344
+ }
3345
+
3346
+ if (!editor) return null;
3347
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
3348
+ title: "Hyperlink",
3349
+ testId: "hyperlink-toolbar-button",
3350
+ onClick: handleClick,
3351
+ isActive: isActive,
3352
+ isDisabled: props.isDisabled
3353
+ }, /*#__PURE__*/React.createElement(f36Icons.LinkIcon, null));
3354
+ }
3355
+
3446
3356
  var hasText = function hasText(editor, entry) {
3447
3357
  var node = entry[0];
3448
3358
  return !plateCore.isAncestorEmpty(editor, node) && slate.Node.string(node).trim() !== '';
3449
3359
  };
3450
3360
 
3361
+ function truncate(str, length) {
3362
+ if (typeof str === 'string' && str.length > length) {
3363
+ return str && str.substr(0, length + 1) // +1 to look ahead and be replaced below.
3364
+ // Get rid of orphan letters but not one letter words (I, a, 2).
3365
+ // Try to not have “.” as last character to avoid awkward “....”.
3366
+ .replace(/(\s+\S(?=\S)|\s*)\.?.$/, '…');
3367
+ }
3368
+
3369
+ return str;
3370
+ }
3371
+
3372
+ function getEntityInfo(data) {
3373
+ if (!data) {
3374
+ return '';
3375
+ }
3376
+
3377
+ var entityTitle = data.entityTitle,
3378
+ contentTypeName = data.contentTypeName,
3379
+ entityStatus = data.entityStatus,
3380
+ jobs = data.jobs;
3381
+ var title = truncate(entityTitle, 60) || 'Untitled';
3382
+ var scheduledActions = jobs.length > 0 ? fieldEditorReference.getScheduleTooltipContent({
3383
+ job: jobs[0],
3384
+ jobsCount: jobs.length
3385
+ }) : '';
3386
+ return (contentTypeName || 'Asset') + " \"" + title + "\", " + entityStatus + " " + scheduledActions;
3387
+ }
3388
+
3389
+ function fetchAllData(_x) {
3390
+ return _fetchAllData.apply(this, arguments);
3391
+ }
3392
+
3393
+ function _fetchAllData() {
3394
+ _fetchAllData = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(_ref) {
3395
+ var sdk, entityId, entityType, localeCode, defaultLocaleCode, contentType, getEntity, entity, contentTypeId, entityTitle, entityDescription, jobs, entityStatus;
3396
+ return runtime_1.wrap(function _callee$(_context) {
3397
+ while (1) {
3398
+ switch (_context.prev = _context.next) {
3399
+ case 0:
3400
+ sdk = _ref.sdk, entityId = _ref.entityId, entityType = _ref.entityType, localeCode = _ref.localeCode, defaultLocaleCode = _ref.defaultLocaleCode;
3401
+ getEntity = entityType === 'Entry' ? sdk.space.getEntry : sdk.space.getAsset;
3402
+ _context.next = 4;
3403
+ return getEntity(entityId);
3404
+
3405
+ case 4:
3406
+ entity = _context.sent;
3407
+
3408
+ if (entity.sys.contentType) {
3409
+ contentTypeId = entity.sys.contentType.sys.id;
3410
+ contentType = sdk.space.getCachedContentTypes().find(function (ct) {
3411
+ return ct.sys.id === contentTypeId;
3412
+ });
3413
+ }
3414
+
3415
+ entityTitle = entityType === 'Entry' ? fieldEditorShared.entityHelpers.getEntryTitle({
3416
+ entry: entity,
3417
+ contentType: contentType,
3418
+ localeCode: localeCode,
3419
+ defaultLocaleCode: defaultLocaleCode,
3420
+ defaultTitle: 'Untitled'
3421
+ }) : fieldEditorShared.entityHelpers.getAssetTitle({
3422
+ asset: entity,
3423
+ localeCode: localeCode,
3424
+ defaultLocaleCode: defaultLocaleCode,
3425
+ defaultTitle: 'Untitled'
3426
+ });
3427
+ entityDescription = fieldEditorShared.entityHelpers.getEntityDescription({
3428
+ entity: entity,
3429
+ contentType: contentType,
3430
+ localeCode: localeCode,
3431
+ defaultLocaleCode: defaultLocaleCode
3432
+ });
3433
+ _context.next = 10;
3434
+ return sdk.space.getEntityScheduledActions(entityType, entityId);
3435
+
3436
+ case 10:
3437
+ jobs = _context.sent;
3438
+ entityStatus = fieldEditorShared.entityHelpers.getEntryStatus(entity.sys);
3439
+ return _context.abrupt("return", {
3440
+ jobs: jobs,
3441
+ entity: entity,
3442
+ entityTitle: entityTitle,
3443
+ entityDescription: entityDescription,
3444
+ entityStatus: entityStatus,
3445
+ contentTypeName: contentType ? contentType.name : ''
3446
+ });
3447
+
3448
+ case 13:
3449
+ case "end":
3450
+ return _context.stop();
3451
+ }
3452
+ }
3453
+ }, _callee);
3454
+ }));
3455
+ return _fetchAllData.apply(this, arguments);
3456
+ }
3457
+
3458
+ function useRequestStatus(_ref2) {
3459
+ var sdk = _ref2.sdk,
3460
+ target = _ref2.target,
3461
+ onEntityFetchComplete = _ref2.onEntityFetchComplete;
3462
+
3463
+ var _useState = React.useState({
3464
+ type: 'loading'
3465
+ }),
3466
+ requestStatus = _useState[0],
3467
+ setRequestStatus = _useState[1];
3468
+
3469
+ React.useEffect(function () {
3470
+ if (target) {
3471
+ var _target$sys, _target$sys2;
3472
+
3473
+ fetchAllData({
3474
+ sdk: sdk,
3475
+ entityId: target == null ? void 0 : (_target$sys = target.sys) == null ? void 0 : _target$sys.id,
3476
+ entityType: target == null ? void 0 : (_target$sys2 = target.sys) == null ? void 0 : _target$sys2.linkType,
3477
+ localeCode: sdk.field.locale,
3478
+ defaultLocaleCode: sdk.locales["default"]
3479
+ }).then(function (entityInfo) {
3480
+ setRequestStatus({
3481
+ type: 'success',
3482
+ data: entityInfo
3483
+ });
3484
+ })["catch"](function (e) {
3485
+ console.log(e);
3486
+ setRequestStatus({
3487
+ type: 'error',
3488
+ error: e
3489
+ });
3490
+ })["finally"](function () {
3491
+ onEntityFetchComplete == null ? void 0 : onEntityFetchComplete();
3492
+ });
3493
+ }
3494
+ }, [sdk, target, onEntityFetchComplete]);
3495
+ return requestStatus;
3496
+ }
3497
+
3498
+ function useEntityInfo(props) {
3499
+ var status = useRequestStatus(props);
3500
+ var linkType = props.target.sys.linkType;
3501
+
3502
+ if (status.type === 'loading') {
3503
+ return "Loading " + linkType.toLowerCase() + "...";
3504
+ }
3505
+
3506
+ if (status.type === 'error') {
3507
+ return linkType + " missing or inaccessible";
3508
+ }
3509
+
3510
+ return getEntityInfo(status.data);
3511
+ }
3512
+
3451
3513
  var styles$c = {
3452
3514
  hyperlinkWrapper: /*#__PURE__*/emotion.css({
3453
3515
  display: 'inline',
@@ -3465,33 +3527,21 @@ var styles$c = {
3465
3527
  '&:focus': {
3466
3528
  fill: tokens.gray900
3467
3529
  }
3468
- }),
3469
- hyperlinkIEFallback: /*#__PURE__*/emotion.css({
3470
- color: '#1683d0',
3471
- textDecoration: 'underline'
3472
- }),
3473
- // TODO: use these styles once we can use the icon
3474
- hyperlinkIcon: /*#__PURE__*/emotion.css({
3475
- position: 'relative',
3476
- top: '4px',
3477
- height: '14px',
3478
- margin: '0 -2px 0 -1px',
3479
- webkitTransition: 'fill 100ms ease-in-out',
3480
- transition: 'fill 100ms ease-in-out',
3481
- '&:hover': {
3482
- fill: tokens.gray900
3483
- },
3484
- '&:focus': {
3485
- fill: tokens.gray900
3486
- }
3487
3530
  })
3488
3531
  };
3489
3532
 
3490
- function UrlHyperlink(props) {
3533
+ function EntityHyperlink(props) {
3491
3534
  var editor = useContentfulEditor();
3492
3535
  var isReadOnly = Slate.useReadOnly();
3493
3536
  var sdk = useSdkContext();
3494
- var uri = props.element.data.uri;
3537
+ var target = props.element.data.target;
3538
+ var onEntityFetchComplete = props.onEntityFetchComplete;
3539
+ var tooltipContent = useEntityInfo({
3540
+ target: target,
3541
+ sdk: sdk,
3542
+ onEntityFetchComplete: onEntityFetchComplete
3543
+ });
3544
+ if (!target) return null;
3495
3545
 
3496
3546
  function handleClick(event) {
3497
3547
  event.preventDefault();
@@ -3501,33 +3551,25 @@ function UrlHyperlink(props) {
3501
3551
  }
3502
3552
 
3503
3553
  return /*#__PURE__*/React.createElement(f36Components.Tooltip, {
3504
- content: uri,
3554
+ content: tooltipContent,
3505
3555
  targetWrapperClassName: styles$c.hyperlinkWrapper,
3506
3556
  placement: "bottom",
3507
3557
  maxWidth: "auto"
3508
3558
  }, /*#__PURE__*/React.createElement(f36Components.TextLink, {
3509
3559
  as: "a",
3510
- href: uri,
3511
- rel: "noopener noreferrer",
3512
3560
  onClick: handleClick,
3513
3561
  isDisabled: isReadOnly,
3514
- className: styles$c.hyperlink
3562
+ className: styles$c.hyperlink,
3563
+ "data-link-type": target.sys.linkType,
3564
+ "data-link-id": target.sys.id
3515
3565
  }, props.children));
3516
3566
  }
3517
3567
 
3518
- function EntityHyperlink(props) {
3568
+ function UrlHyperlink(props) {
3519
3569
  var editor = useContentfulEditor();
3520
3570
  var isReadOnly = Slate.useReadOnly();
3521
3571
  var sdk = useSdkContext();
3522
- var target = props.element.data.target;
3523
- var onEntityFetchComplete = props.onEntityFetchComplete;
3524
- React.useEffect(function () {
3525
- // The real entity loading happens in the tooltip
3526
- // Since that is deferred the link is considered rendered as soon
3527
- // the component mounts (link text displayed)
3528
- onEntityFetchComplete == null ? void 0 : onEntityFetchComplete();
3529
- }, [onEntityFetchComplete]);
3530
- if (!target) return null;
3572
+ var uri = props.element.data.uri;
3531
3573
 
3532
3574
  function handleClick(event) {
3533
3575
  event.preventDefault();
@@ -3537,74 +3579,20 @@ function EntityHyperlink(props) {
3537
3579
  }
3538
3580
 
3539
3581
  return /*#__PURE__*/React.createElement(f36Components.Tooltip, {
3540
- content: /*#__PURE__*/React.createElement(EntryAssetTooltip, {
3541
- id: target.sys.id,
3542
- type: target.sys.linkType,
3543
- sdk: sdk
3544
- }),
3582
+ content: uri,
3545
3583
  targetWrapperClassName: styles$c.hyperlinkWrapper,
3546
3584
  placement: "bottom",
3547
3585
  maxWidth: "auto"
3548
3586
  }, /*#__PURE__*/React.createElement(f36Components.TextLink, {
3549
3587
  as: "a",
3588
+ href: uri,
3589
+ rel: "noopener noreferrer",
3550
3590
  onClick: handleClick,
3551
3591
  isDisabled: isReadOnly,
3552
- className: styles$c.hyperlink,
3553
- "data-link-type": target.sys.linkType,
3554
- "data-link-id": target.sys.id
3592
+ className: styles$c.hyperlink
3555
3593
  }, props.children));
3556
3594
  }
3557
3595
 
3558
- function ToolbarHyperlinkButton(props) {
3559
- var editor = useContentfulEditor();
3560
- var isActive = !!(editor && isLinkActive(editor));
3561
- var sdk = useSdkContext();
3562
-
3563
- function handleClick() {
3564
- return _handleClick.apply(this, arguments);
3565
- }
3566
-
3567
- function _handleClick() {
3568
- _handleClick = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
3569
- return runtime_1.wrap(function _callee$(_context) {
3570
- while (1) {
3571
- switch (_context.prev = _context.next) {
3572
- case 0:
3573
- if (editor) {
3574
- _context.next = 2;
3575
- break;
3576
- }
3577
-
3578
- return _context.abrupt("return");
3579
-
3580
- case 2:
3581
- if (isActive) {
3582
- unwrapLink(editor);
3583
- editor.tracking.onToolbarAction('unlinkHyperlinks');
3584
- } else {
3585
- addOrEditLink(editor, sdk, editor.tracking.onToolbarAction);
3586
- }
3587
-
3588
- case 3:
3589
- case "end":
3590
- return _context.stop();
3591
- }
3592
- }
3593
- }, _callee);
3594
- }));
3595
- return _handleClick.apply(this, arguments);
3596
- }
3597
-
3598
- if (!editor) return null;
3599
- return /*#__PURE__*/React.createElement(ToolbarButton, {
3600
- title: "Hyperlink",
3601
- testId: "hyperlink-toolbar-button",
3602
- onClick: handleClick,
3603
- isActive: isActive,
3604
- isDisabled: props.isDisabled
3605
- }, /*#__PURE__*/React.createElement(f36Icons.LinkIcon, null));
3606
- }
3607
-
3608
3596
  var isAnchor = function isAnchor(element) {
3609
3597
  return element.nodeName === 'A' && !!element.getAttribute('href') && element.getAttribute('href') !== '#';
3610
3598
  };
@@ -3748,8 +3736,331 @@ function ListItem(props) {
3748
3736
  }), props.children);
3749
3737
  }
3750
3738
 
3751
- var isList = function isList(node) {
3752
- return [Contentful.BLOCKS.OL_LIST, Contentful.BLOCKS.UL_LIST].includes(node.type);
3739
+ /**
3740
+ * Credit: Modified version of Plate's list plugin
3741
+ * See: https://github.com/udecode/plate/blob/main/packages/nodes/list
3742
+ */
3743
+ var moveListItemDown = function moveListItemDown(editor, _ref) {
3744
+ var list = _ref.list,
3745
+ listItem = _ref.listItem;
3746
+ var listNode = list[0];
3747
+ var listItemPath = listItem[1];
3748
+ var previousListItemPath;
3749
+
3750
+ try {
3751
+ previousListItemPath = slate.Path.previous(listItemPath);
3752
+ } catch (e) {
3753
+ return;
3754
+ } // Previous sibling is the new parent
3755
+
3756
+
3757
+ var previousSiblingItem = slate.Editor.node(editor, previousListItemPath);
3758
+
3759
+ if (previousSiblingItem) {
3760
+ var previousPath = previousSiblingItem[1];
3761
+ var subList = Array.from(slate.Node.children(editor, previousPath)).find(function (_ref2) {
3762
+ var n = _ref2[0];
3763
+ return plateCore.match(n, {
3764
+ type: plateList.getListTypes(editor)
3765
+ });
3766
+ });
3767
+ var newPath = slate.Path.next(plateCore.getLastChildPath(subList != null ? subList : previousSiblingItem));
3768
+ slate.Editor.withoutNormalizing(editor, function () {
3769
+ if (!subList) {
3770
+ // Create new sub-list
3771
+ plateCore.wrapNodes(editor, {
3772
+ type: listNode.type,
3773
+ children: [],
3774
+ data: {}
3775
+ }, {
3776
+ at: listItemPath
3777
+ });
3778
+ } // Move the current item to the sub-list
3779
+
3780
+
3781
+ slate.Transforms.moveNodes(editor, {
3782
+ at: listItemPath,
3783
+ to: newPath
3784
+ });
3785
+ });
3786
+ }
3787
+ };
3788
+
3789
+ /**
3790
+ * Credit: Modified version of Plate's list plugin
3791
+ * See: https://github.com/udecode/plate/blob/main/packages/nodes/list
3792
+ */
3793
+ var moveListItems = function moveListItems(editor, _temp) {
3794
+ var _editor$selection;
3795
+
3796
+ var _ref = _temp === void 0 ? {} : _temp,
3797
+ _ref$increase = _ref.increase,
3798
+ increase = _ref$increase === void 0 ? true : _ref$increase,
3799
+ _ref$at = _ref.at,
3800
+ at = _ref$at === void 0 ? (_editor$selection = editor.selection) != null ? _editor$selection : undefined : _ref$at;
3801
+
3802
+ var _nodes = plateCore.getNodes(editor, {
3803
+ at: at,
3804
+ match: {
3805
+ type: plateCore.getPluginType(editor, plateList.ELEMENT_LIC)
3806
+ }
3807
+ }); // Get the selected lic
3808
+
3809
+
3810
+ var lics = Array.from(_nodes);
3811
+ if (!lics.length) return;
3812
+ var highestLicPaths = [];
3813
+ var highestLicPathRefs = []; // Filter out the nested lic, we just need to move the highest ones
3814
+
3815
+ lics.forEach(function (lic) {
3816
+ var licPath = lic[1];
3817
+ var liPath = slate.Path.parent(licPath);
3818
+ var isAncestor = highestLicPaths.some(function (path) {
3819
+ var highestLiPath = slate.Path.parent(path);
3820
+ return slate.Path.isAncestor(highestLiPath, liPath);
3821
+ });
3822
+
3823
+ if (!isAncestor) {
3824
+ highestLicPaths.push(licPath);
3825
+ highestLicPathRefs.push(slate.Editor.pathRef(editor, licPath));
3826
+ }
3827
+ });
3828
+ var licPathRefsToMove = increase ? highestLicPathRefs : highestLicPathRefs.reverse();
3829
+ slate.Editor.withoutNormalizing(editor, function () {
3830
+ licPathRefsToMove.forEach(function (licPathRef) {
3831
+ var licPath = licPathRef.unref();
3832
+ if (!licPath) return;
3833
+ var liEntry = plateList.getListItemEntry(editor, {
3834
+ at: licPath
3835
+ });
3836
+
3837
+ if (!liEntry) {
3838
+ return;
3839
+ }
3840
+
3841
+ if (increase) {
3842
+ moveListItemDown(editor, liEntry);
3843
+ } else if (plateList.isListNested(editor, liEntry.list[1])) {
3844
+ plateList.moveListItemUp(editor, liEntry);
3845
+ }
3846
+ });
3847
+ });
3848
+ };
3849
+
3850
+ /**
3851
+ * Credit: Modified version of Plate's list plugin
3852
+ * See: https://github.com/udecode/plate/blob/main/packages/nodes/list
3853
+ */
3854
+ var listTypes = [Contentful.BLOCKS.UL_LIST, Contentful.BLOCKS.OL_LIST];
3855
+ var unwrapList = function unwrapList(editor, _temp) {
3856
+ var _ref = _temp === void 0 ? {} : _temp,
3857
+ at = _ref.at;
3858
+
3859
+ slate.Editor.withoutNormalizing(editor, function () {
3860
+ do {
3861
+ plateCore.unwrapNodes(editor, {
3862
+ at: at,
3863
+ match: {
3864
+ type: Contentful.BLOCKS.LIST_ITEM
3865
+ },
3866
+ split: true
3867
+ });
3868
+ plateCore.unwrapNodes(editor, {
3869
+ at: at,
3870
+ match: {
3871
+ type: listTypes
3872
+ },
3873
+ split: true
3874
+ });
3875
+ } while (plateCore.getAbove(editor, {
3876
+ match: {
3877
+ type: listTypes,
3878
+ at: at
3879
+ }
3880
+ }));
3881
+ });
3882
+ };
3883
+
3884
+ var listTypes$1 = [Contentful.BLOCKS.UL_LIST, Contentful.BLOCKS.OL_LIST];
3885
+ var toggleList = function toggleList(editor, _ref) {
3886
+ var type = _ref.type;
3887
+ return slate.Editor.withoutNormalizing(editor, function () {
3888
+ if (!editor.selection) {
3889
+ return;
3890
+ }
3891
+
3892
+ if (plateCore.isCollapsed(editor.selection) || !plateCore.isRangeAcrossBlocks(editor)) {
3893
+ // selection is collapsed
3894
+ var res = plateList.getListItemEntry(editor);
3895
+
3896
+ if (res) {
3897
+ var list = res.list;
3898
+
3899
+ if (list[0].type !== type) {
3900
+ plateCore.setNodes(editor, {
3901
+ type: type
3902
+ }, {
3903
+ at: editor.selection,
3904
+ match: function match(n) {
3905
+ return listTypes$1.includes(n.type);
3906
+ },
3907
+ mode: 'lowest'
3908
+ });
3909
+ } else {
3910
+ unwrapList(editor);
3911
+ }
3912
+ } else {
3913
+ var _list = {
3914
+ type: type,
3915
+ children: [],
3916
+ data: {}
3917
+ };
3918
+ plateCore.wrapNodes(editor, _list);
3919
+ var nodes = [].concat(plateCore.getNodes(editor, {
3920
+ match: {
3921
+ type: plateCore.getPluginType(editor, plateCore.ELEMENT_DEFAULT)
3922
+ }
3923
+ }));
3924
+ var listItem = {
3925
+ type: Contentful.BLOCKS.LIST_ITEM,
3926
+ children: [],
3927
+ data: {}
3928
+ };
3929
+
3930
+ for (var _iterator = _createForOfIteratorHelperLoose(nodes), _step; !(_step = _iterator()).done;) {
3931
+ var _step$value = _step.value,
3932
+ path = _step$value[1];
3933
+ plateCore.wrapNodes(editor, listItem, {
3934
+ at: path
3935
+ });
3936
+ }
3937
+ }
3938
+ } else {
3939
+ // selection is a range
3940
+ var _Range$edges = slate.Range.edges(editor.selection),
3941
+ startPoint = _Range$edges[0],
3942
+ endPoint = _Range$edges[1];
3943
+
3944
+ var commonEntry = slate.Node.common(editor, startPoint.path, endPoint.path);
3945
+
3946
+ if (listTypes$1.includes(commonEntry[0].type) || commonEntry[0].type === Contentful.BLOCKS.LIST_ITEM) {
3947
+ if (commonEntry[0].type !== type) {
3948
+ var startList = plateCore.findNode(editor, {
3949
+ at: slate.Range.start(editor.selection),
3950
+ match: {
3951
+ type: listTypes$1
3952
+ },
3953
+ mode: 'lowest'
3954
+ });
3955
+ var endList = plateCore.findNode(editor, {
3956
+ at: slate.Range.end(editor.selection),
3957
+ match: {
3958
+ type: listTypes$1
3959
+ },
3960
+ mode: 'lowest'
3961
+ });
3962
+
3963
+ if (!startList || !endList) {
3964
+ return;
3965
+ }
3966
+
3967
+ var rangeLength = Math.min(startList[1].length, endList[1].length);
3968
+ plateCore.setNodes(editor, {
3969
+ type: type
3970
+ }, {
3971
+ at: editor.selection,
3972
+ match: function match(n, path) {
3973
+ return listTypes$1.includes(n.type) && path.length >= rangeLength;
3974
+ },
3975
+ mode: 'all'
3976
+ });
3977
+ } else {
3978
+ unwrapList(editor);
3979
+ }
3980
+ } else {
3981
+ var rootPathLength = commonEntry[1].length;
3982
+
3983
+ var _nodes = Array.from(plateCore.getNodes(editor, {
3984
+ mode: 'all'
3985
+ })).filter(function (_ref2) {
3986
+ var path = _ref2[1];
3987
+ return path.length === rootPathLength + 1;
3988
+ }).reverse();
3989
+
3990
+ _nodes.forEach(function (n) {
3991
+ if (listTypes$1.includes(n[0].type)) {
3992
+ plateCore.setNodes(editor, {
3993
+ type: type
3994
+ }, {
3995
+ at: n[1]
3996
+ });
3997
+ } else {
3998
+ plateCore.setNodes(editor, {
3999
+ type: plateCore.getPluginType(editor, plateList.ELEMENT_LIC)
4000
+ }, {
4001
+ at: n[1]
4002
+ });
4003
+ var _listItem = {
4004
+ type: Contentful.BLOCKS.LIST_ITEM,
4005
+ children: [],
4006
+ data: {}
4007
+ };
4008
+ plateCore.wrapNodes(editor, _listItem, {
4009
+ at: n[1]
4010
+ });
4011
+ var _list2 = {
4012
+ type: type,
4013
+ children: [],
4014
+ data: {}
4015
+ };
4016
+ plateCore.wrapNodes(editor, _list2, {
4017
+ at: n[1]
4018
+ });
4019
+ }
4020
+ });
4021
+ }
4022
+ }
4023
+ });
4024
+ };
4025
+
4026
+ var onKeyDownList = function onKeyDownList(editor, _ref) {
4027
+ var type = _ref.type,
4028
+ hotkey = _ref.options.hotkey;
4029
+ return function (e) {
4030
+ if (e.key === 'Tab' && editor.selection) {
4031
+ var listSelected = plateCore.getAbove(editor, {
4032
+ at: editor.selection,
4033
+ match: {
4034
+ type: type
4035
+ }
4036
+ });
4037
+
4038
+ if (listSelected) {
4039
+ e.preventDefault();
4040
+ moveListItems(editor, {
4041
+ increase: !e.shiftKey
4042
+ });
4043
+ return;
4044
+ }
4045
+ }
4046
+
4047
+ if (!hotkey) return;
4048
+ var hotkeys = castArray(hotkey);
4049
+
4050
+ for (var _iterator = _createForOfIteratorHelperLoose(hotkeys), _step; !(_step = _iterator()).done;) {
4051
+ var _hotkey = _step.value;
4052
+
4053
+ if (isHotkey(_hotkey)(e)) {
4054
+ toggleList(editor, {
4055
+ type: type
4056
+ });
4057
+ }
4058
+ }
4059
+ };
4060
+ };
4061
+
4062
+ var isList = function isList(node) {
4063
+ return [Contentful.BLOCKS.OL_LIST, Contentful.BLOCKS.UL_LIST].includes(node.type);
3753
4064
  };
3754
4065
 
3755
4066
  var hasListAsDirectParent = function hasListAsDirectParent(editor, _ref) {
@@ -4117,50 +4428,16 @@ var insertListFragment = function insertListFragment(editor) {
4117
4428
  select: true
4118
4429
  });
4119
4430
  return slate.Transforms.insertNodes(editor, blocks, {
4120
- at: editor.selection,
4121
- select: true
4122
- });
4123
- }
4124
-
4125
- var filtered = isListRoot(fragment[0]) ? [{
4126
- text: ''
4127
- }].concat(fragment) : fragment;
4128
- return insertFragment(filtered);
4129
- };
4130
- };
4131
-
4132
- /**
4133
- * Credit: Modified version of Plate's list plugin
4134
- * See: https://github.com/udecode/plate/blob/main/packages/nodes/list
4135
- */
4136
- var listTypes = [Contentful.BLOCKS.UL_LIST, Contentful.BLOCKS.OL_LIST];
4137
- var unwrapList = function unwrapList(editor, _temp) {
4138
- var _ref = _temp === void 0 ? {} : _temp,
4139
- at = _ref.at;
4140
-
4141
- slate.Editor.withoutNormalizing(editor, function () {
4142
- do {
4143
- plateCore.unwrapNodes(editor, {
4144
- at: at,
4145
- match: {
4146
- type: Contentful.BLOCKS.LIST_ITEM
4147
- },
4148
- split: true
4149
- });
4150
- plateCore.unwrapNodes(editor, {
4151
- at: at,
4152
- match: {
4153
- type: listTypes
4154
- },
4155
- split: true
4156
- });
4157
- } while (plateCore.getAbove(editor, {
4158
- match: {
4159
- type: listTypes,
4160
- at: at
4161
- }
4162
- }));
4163
- });
4431
+ at: editor.selection,
4432
+ select: true
4433
+ });
4434
+ }
4435
+
4436
+ var filtered = isListRoot(fragment[0]) ? [{
4437
+ text: ''
4438
+ }].concat(fragment) : fragment;
4439
+ return insertFragment(filtered);
4440
+ };
4164
4441
  };
4165
4442
 
4166
4443
  /**
@@ -4272,12 +4549,18 @@ var createListPlugin = function createListPlugin() {
4272
4549
  overrideByKey: (_overrideByKey = {}, _overrideByKey[plateList.ELEMENT_UL] = {
4273
4550
  type: Contentful.BLOCKS.UL_LIST,
4274
4551
  component: ListUL,
4552
+ handlers: {
4553
+ onKeyDown: onKeyDownList
4554
+ },
4275
4555
  // The withList is added on ELEMENT_UL plugin in upstream code
4276
4556
  // so we need to override it here
4277
4557
  withOverrides: withList
4278
4558
  }, _overrideByKey[plateList.ELEMENT_OL] = {
4279
4559
  type: Contentful.BLOCKS.OL_LIST,
4280
- component: ListOL
4560
+ component: ListOL,
4561
+ handlers: {
4562
+ onKeyDown: onKeyDownList
4563
+ }
4281
4564
  }, _overrideByKey[plateList.ELEMENT_LIC] = {
4282
4565
  type: Contentful.BLOCKS.PARAGRAPH
4283
4566
  }, _overrideByKey[plateList.ELEMENT_LI] = {
@@ -4301,148 +4584,6 @@ var createListPlugin = function createListPlugin() {
4301
4584
  });
4302
4585
  };
4303
4586
 
4304
- var listTypes$1 = [Contentful.BLOCKS.UL_LIST, Contentful.BLOCKS.OL_LIST];
4305
- var toggleList = function toggleList(editor, _ref) {
4306
- var type = _ref.type;
4307
- return slate.Editor.withoutNormalizing(editor, function () {
4308
- if (!editor.selection) {
4309
- return;
4310
- }
4311
-
4312
- if (plateCore.isCollapsed(editor.selection) || !plateCore.isRangeAcrossBlocks(editor)) {
4313
- // selection is collapsed
4314
- var res = plateList.getListItemEntry(editor);
4315
-
4316
- if (res) {
4317
- var list = res.list;
4318
-
4319
- if (list[0].type !== type) {
4320
- plateCore.setNodes(editor, {
4321
- type: type
4322
- }, {
4323
- at: editor.selection,
4324
- match: function match(n) {
4325
- return listTypes$1.includes(n.type);
4326
- },
4327
- mode: 'lowest'
4328
- });
4329
- } else {
4330
- unwrapList(editor);
4331
- }
4332
- } else {
4333
- var _list = {
4334
- type: type,
4335
- children: [],
4336
- data: {}
4337
- };
4338
- plateCore.wrapNodes(editor, _list);
4339
- var nodes = [].concat(plateCore.getNodes(editor, {
4340
- match: {
4341
- type: plateCore.getPluginType(editor, plateCore.ELEMENT_DEFAULT)
4342
- }
4343
- }));
4344
- var listItem = {
4345
- type: Contentful.BLOCKS.LIST_ITEM,
4346
- children: [],
4347
- data: {}
4348
- };
4349
-
4350
- for (var _iterator = _createForOfIteratorHelperLoose(nodes), _step; !(_step = _iterator()).done;) {
4351
- var _step$value = _step.value,
4352
- path = _step$value[1];
4353
- plateCore.wrapNodes(editor, listItem, {
4354
- at: path
4355
- });
4356
- }
4357
- }
4358
- } else {
4359
- // selection is a range
4360
- var _Range$edges = slate.Range.edges(editor.selection),
4361
- startPoint = _Range$edges[0],
4362
- endPoint = _Range$edges[1];
4363
-
4364
- var commonEntry = slate.Node.common(editor, startPoint.path, endPoint.path);
4365
-
4366
- if (listTypes$1.includes(commonEntry[0].type) || commonEntry[0].type === Contentful.BLOCKS.LIST_ITEM) {
4367
- if (commonEntry[0].type !== type) {
4368
- var startList = plateCore.findNode(editor, {
4369
- at: slate.Range.start(editor.selection),
4370
- match: {
4371
- type: listTypes$1
4372
- },
4373
- mode: 'lowest'
4374
- });
4375
- var endList = plateCore.findNode(editor, {
4376
- at: slate.Range.end(editor.selection),
4377
- match: {
4378
- type: listTypes$1
4379
- },
4380
- mode: 'lowest'
4381
- });
4382
-
4383
- if (!startList || !endList) {
4384
- return;
4385
- }
4386
-
4387
- var rangeLength = Math.min(startList[1].length, endList[1].length);
4388
- plateCore.setNodes(editor, {
4389
- type: type
4390
- }, {
4391
- at: editor.selection,
4392
- match: function match(n, path) {
4393
- return listTypes$1.includes(n.type) && path.length >= rangeLength;
4394
- },
4395
- mode: 'all'
4396
- });
4397
- } else {
4398
- unwrapList(editor);
4399
- }
4400
- } else {
4401
- var rootPathLength = commonEntry[1].length;
4402
-
4403
- var _nodes = Array.from(plateCore.getNodes(editor, {
4404
- mode: 'all'
4405
- })).filter(function (_ref2) {
4406
- var path = _ref2[1];
4407
- return path.length === rootPathLength + 1;
4408
- }).reverse();
4409
-
4410
- _nodes.forEach(function (n) {
4411
- if (listTypes$1.includes(n[0].type)) {
4412
- plateCore.setNodes(editor, {
4413
- type: type
4414
- }, {
4415
- at: n[1]
4416
- });
4417
- } else {
4418
- plateCore.setNodes(editor, {
4419
- type: plateCore.getPluginType(editor, plateList.ELEMENT_LIC)
4420
- }, {
4421
- at: n[1]
4422
- });
4423
- var _listItem = {
4424
- type: Contentful.BLOCKS.LIST_ITEM,
4425
- children: [],
4426
- data: {}
4427
- };
4428
- plateCore.wrapNodes(editor, _listItem, {
4429
- at: n[1]
4430
- });
4431
- var _list2 = {
4432
- type: type,
4433
- children: [],
4434
- data: {}
4435
- };
4436
- plateCore.wrapNodes(editor, _list2, {
4437
- at: n[1]
4438
- });
4439
- }
4440
- });
4441
- }
4442
- }
4443
- });
4444
- };
4445
-
4446
4587
  function ToolbarListButton(props) {
4447
4588
  var sdk = useSdkContext();
4448
4589
  var editor = useContentfulEditor();
@@ -6244,6 +6385,80 @@ var disableCorePlugins = {
6244
6385
  eventEditor: true
6245
6386
  };
6246
6387
 
6388
+ /**
6389
+ * For legacy reasons, a document may not have any content at all
6390
+ * e.g:
6391
+ *
6392
+ * {nodeType: document, data: {}, content: []}
6393
+ *
6394
+ * Rendering such document will break the Slate editor
6395
+ */
6396
+
6397
+ var hasContent = function hasContent(doc) {
6398
+ if (!doc) {
6399
+ return false;
6400
+ }
6401
+
6402
+ return doc.content.length > 0;
6403
+ };
6404
+ /*
6405
+ Plate api doesn't allow to modify (easily) the editor value programmatically
6406
+ after the editor instance is created
6407
+
6408
+ This function is inspired to https://github.com/udecode/plate/issues/1269#issuecomment-1057643622
6409
+ */
6410
+
6411
+ var setEditorContent = function setEditorContent(editor, nodes) {
6412
+ // Replaces editor content while keeping change history
6413
+ slate.Editor.withoutNormalizing(editor, function () {
6414
+ var children = [].concat(editor.children);
6415
+ children.forEach(function (node) {
6416
+ return editor.apply({
6417
+ type: 'remove_node',
6418
+ path: [0],
6419
+ node: node
6420
+ });
6421
+ });
6422
+
6423
+ if (nodes) {
6424
+ var nodesArray = slate.Node.isNode(nodes) ? [nodes] : nodes;
6425
+ nodesArray.forEach(function (node, i) {
6426
+ return editor.apply({
6427
+ type: 'insert_node',
6428
+ path: [i],
6429
+ node: node
6430
+ });
6431
+ });
6432
+ }
6433
+
6434
+ var point = slate.Editor.end(editor, []);
6435
+
6436
+ if (point) {
6437
+ slate.Transforms.select(editor, point);
6438
+ }
6439
+ });
6440
+ };
6441
+ /**
6442
+ * Converts a contenful rich text document to the corresponding slate editor
6443
+ * value
6444
+ */
6445
+
6446
+ var documentToEditorValue = function documentToEditorValue(doc) {
6447
+ return contentfulSlateJSAdapter.toSlatejsDocument({
6448
+ document: hasContent(doc) ? doc : Contentful.EMPTY_DOCUMENT,
6449
+ // TODO: get rid of schema, https://github.com/contentful/field-editors/pull/1065#discussion_r826723248
6450
+ schema: schema
6451
+ });
6452
+ };
6453
+ var normalizeEditorValue = function normalizeEditorValue(value, options) {
6454
+ var editor = plateCore.createPlateEditor(options);
6455
+ editor.children = value;
6456
+ slate.Editor.normalize(editor, {
6457
+ force: true
6458
+ });
6459
+ return editor.children;
6460
+ };
6461
+
6247
6462
  var STYLE_EDITOR_BORDER = "1px solid " + tokens.gray400;
6248
6463
  var styles$j = {
6249
6464
  root: /*#__PURE__*/emotion.css({
@@ -6340,7 +6555,17 @@ var EmbedEntityWidget = function EmbedEntityWidget(_ref) {
6340
6555
  setCanAccessAssets = _useState2[1];
6341
6556
 
6342
6557
  React__default.useEffect(function () {
6343
- sdk.access.can('read', 'Asset').then(setCanAccessAssets);
6558
+ var subscribed = true;
6559
+ sdk.access.can('read', 'Asset').then(function (can) {
6560
+ if (!subscribed) {
6561
+ return;
6562
+ }
6563
+
6564
+ setCanAccessAssets(can);
6565
+ });
6566
+ return function () {
6567
+ subscribed = false;
6568
+ };
6344
6569
  }, [sdk]);
6345
6570
  var inlineEntryEmbedEnabled = isNodeTypeEnabled(sdk.field, Contentful.INLINES.EMBEDDED_ENTRY);
6346
6571
  var blockEntryEmbedEnabled = isNodeTypeEnabled(sdk.field, Contentful.BLOCKS.EMBEDDED_ENTRY) && canInsertBlocks;
@@ -6495,50 +6720,6 @@ var StickyToolbarWrapper = function StickyToolbarWrapper(_ref) {
6495
6720
  }, children);
6496
6721
  };
6497
6722
 
6498
- /**
6499
- * For legacy reasons, a document may not have any content at all
6500
- * e.g:
6501
- *
6502
- * {nodeType: document, data: {}, content: []}
6503
- *
6504
- * Rendering such document will break the Slate editor
6505
- */
6506
-
6507
- var hasContent = function hasContent(doc) {
6508
- if (!doc) {
6509
- return false;
6510
- }
6511
-
6512
- return doc.content.length > 0;
6513
- };
6514
-
6515
- var useNormalizedSlateValue = function useNormalizedSlateValue(_ref) {
6516
- var id = _ref.id,
6517
- incomingDoc = _ref.incomingDoc,
6518
- plugins = _ref.plugins;
6519
- return React.useMemo(function () {
6520
- var editor = plateCore.createPlateEditor({
6521
- id: id,
6522
- plugins: plugins,
6523
- disableCorePlugins: disableCorePlugins
6524
- });
6525
- var doc = contentfulSlateJSAdapter.toSlatejsDocument({
6526
- document: hasContent(incomingDoc) ? incomingDoc : Contentful.EMPTY_DOCUMENT,
6527
- schema: schema
6528
- }); // Sets editor value & kicks normalization
6529
-
6530
- editor.children = doc;
6531
- slate.Editor.normalize(editor, {
6532
- force: true
6533
- }); // TODO: return the editor itself to avoid recompiling & initializing all
6534
- // of the plugins again. It's currently not possible due to a bug in Plate
6535
- // with initialValues
6536
- // See: https://slate-js.slack.com/archives/C013QHXSCG1/p1645112799942819
6537
-
6538
- return editor.children;
6539
- }, [id, plugins, incomingDoc]);
6540
- };
6541
-
6542
6723
  /**
6543
6724
  * Returns whether a given operation is relevant enough to trigger a save.
6544
6725
  */
@@ -6552,8 +6733,10 @@ var isRelevantOperation = function isRelevantOperation(op) {
6552
6733
  };
6553
6734
 
6554
6735
  var useOnValueChanged = function useOnValueChanged(_ref) {
6555
- var editor = _ref.editor,
6556
- handler = _ref.handler;
6736
+ var editorId = _ref.editorId,
6737
+ handler = _ref.handler,
6738
+ skip = _ref.skip,
6739
+ onSkip = _ref.onSkip;
6557
6740
  var onChange = React.useMemo(function () {
6558
6741
  return debounce(function (document) {
6559
6742
  handler == null ? void 0 : handler(contentfulSlateJSAdapter.toContentfulDocument({
@@ -6563,45 +6746,84 @@ var useOnValueChanged = function useOnValueChanged(_ref) {
6563
6746
  }, 500);
6564
6747
  }, [handler]);
6565
6748
  return React.useCallback(function (value) {
6566
- var operations = editor.operations.filter(isRelevantOperation);
6749
+ var editor = plateCore.getPlateSelectors(editorId).editor();
6750
+
6751
+ if (!editor) {
6752
+ throw new Error('Editor change callback called but editor not defined. Editor id: ' + editorId);
6753
+ }
6754
+
6755
+ var operations = editor == null ? void 0 : editor.operations.filter(isRelevantOperation);
6567
6756
 
6568
6757
  if (operations.length > 0) {
6758
+ if (skip) {
6759
+ onSkip == null ? void 0 : onSkip();
6760
+ return;
6761
+ }
6762
+
6569
6763
  onChange(value);
6570
6764
  }
6571
- }, [editor, onChange]);
6765
+ }, [editorId, onChange, skip, onSkip]);
6572
6766
  };
6573
6767
 
6574
6768
  var _excluded = ["sdk", "isInitiallyDisabled", "onAction"];
6575
6769
  var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
6576
- var id = getContentfulEditorId(props.sdk); // TODO: remove in favor of getting the editor from useNormalizedSlateValue after upgrading to Plate v10
6577
-
6578
- var editor = useContentfulEditor(id);
6770
+ var id = getContentfulEditorId(props.sdk);
6579
6771
  var plugins = React__default.useMemo(function () {
6580
6772
  var _props$onAction;
6581
6773
 
6582
6774
  return getPlugins(props.sdk, (_props$onAction = props.onAction) != null ? _props$onAction : noop);
6583
6775
  }, [props.sdk, props.onAction]);
6584
- var initialValue = useNormalizedSlateValue({
6585
- id: id,
6586
- incomingDoc: props.value,
6587
- plugins: plugins
6588
- });
6776
+
6777
+ var _useState = React.useState(true),
6778
+ isFirstRender = _useState[0],
6779
+ setIsFirstRender = _useState[1];
6780
+
6781
+ var _useState2 = React.useState(false),
6782
+ pendingExternalUpdate = _useState2[0],
6783
+ setPendingExternalUpdate = _useState2[1];
6784
+
6589
6785
  var onValueChanged = useOnValueChanged({
6590
- editor: editor,
6591
- handler: props.onChange
6786
+ editorId: id,
6787
+ handler: props.onChange,
6788
+ skip: pendingExternalUpdate || isFirstRender,
6789
+ onSkip: function onSkip() {
6790
+ return setPendingExternalUpdate(false);
6791
+ }
6592
6792
  });
6793
+ React.useEffect(function () {
6794
+ /*
6795
+ This effect is called when the value prop changes. Normally
6796
+ this happens when the value is changed outside of the editor,
6797
+ like in snapshots restoration or remote updates
6798
+ Plate won't update the displayed value on its own, see:
6799
+ - https://github.com/ianstormtaylor/slate/pull/4540
6800
+ - https://github.com/udecode/plate/issues/1169
6801
+ The content is forcely set to the new value and it's ensured
6802
+ the change listener isn't invoked
6803
+ */
6804
+ setIsFirstRender(false);
6805
+ var editor = plateCore.getPlateSelectors(id).editor();
6806
+
6807
+ if (!editor) {
6808
+ return;
6809
+ }
6810
+
6811
+ setPendingExternalUpdate(true);
6812
+ setEditorContent(editor, documentToEditorValue(props.value));
6813
+ }, [props.value, id]);
6593
6814
  var classNames = emotion.cx(styles$j.editor, props.minHeight !== undefined ? emotion.css({
6594
6815
  minHeight: props.minHeight
6595
6816
  }) : undefined, props.isDisabled ? styles$j.disabled : styles$j.enabled, props.isToolbarHidden && styles$j.hiddenToolbar);
6596
6817
  React.useEffect(function () {
6597
- // Ensure the plate state is cleared after the component unmounts
6598
- // This prevent new editors for the same field to display old outdated values
6599
- // Typical scenario: coming back to the entry editor after restoring a previous entry version
6600
- plateCore.getPlateActions(id).enabled(true);
6601
- return function () {
6602
- return plateCore.getPlateActions(id).enabled(false);
6603
- };
6604
- }, [id]);
6818
+ if (!isFirstRender) {
6819
+ return;
6820
+ }
6821
+
6822
+ plateCore.getPlateActions(id).value(normalizeEditorValue(documentToEditorValue(props.value), {
6823
+ plugins: plugins,
6824
+ disableCorePlugins: disableCorePlugins
6825
+ }));
6826
+ }, [isFirstRender, plugins, id, props.value]);
6605
6827
  return /*#__PURE__*/React__default.createElement(SdkProvider, {
6606
6828
  sdk: props.sdk
6607
6829
  }, /*#__PURE__*/React__default.createElement(ContentfulEditorIdProvider, {
@@ -6611,7 +6833,6 @@ var ConnectedRichTextEditor = function ConnectedRichTextEditor(props) {
6611
6833
  "data-test-id": "rich-text-editor"
6612
6834
  }, /*#__PURE__*/React__default.createElement(plateCore.Plate, {
6613
6835
  id: id,
6614
- initialValue: initialValue,
6615
6836
  plugins: plugins,
6616
6837
  disableCorePlugins: disableCorePlugins,
6617
6838
  editableProps: {
@@ -6635,6 +6856,7 @@ var RichTextEditor = function RichTextEditor(props) {
6635
6856
  var isEmptyValue = React.useCallback(function (value) {
6636
6857
  return !value || deepEquals(value, Contentful.EMPTY_DOCUMENT);
6637
6858
  }, []);
6859
+ var id = getContentfulEditorId(props.sdk);
6638
6860
  return /*#__PURE__*/React__default.createElement(fieldEditorReference.EntityProvider, {
6639
6861
  sdk: sdk
6640
6862
  }, /*#__PURE__*/React__default.createElement(fieldEditorShared.FieldConnector, {
@@ -6646,10 +6868,9 @@ var RichTextEditor = function RichTextEditor(props) {
6646
6868
  }, function (_ref) {
6647
6869
  var lastRemoteValue = _ref.lastRemoteValue,
6648
6870
  disabled = _ref.disabled,
6649
- setValue = _ref.setValue,
6650
- externalReset = _ref.externalReset;
6871
+ setValue = _ref.setValue;
6651
6872
  return /*#__PURE__*/React__default.createElement(ConnectedRichTextEditor, Object.assign({}, otherProps, {
6652
- key: "rich-text-editor-" + externalReset,
6873
+ key: "rich-text-editor-" + id,
6653
6874
  value: lastRemoteValue,
6654
6875
  sdk: sdk,
6655
6876
  onAction: onAction,