@contentful/field-editor-rich-text 4.19.3-alpha.0 → 4.19.3-canary.7

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.
@@ -101,7 +101,9 @@ const ConnectedRichTextEditor = (props)=>{
101
101
  }) : undefined, props.maxHeight !== undefined ? (0, _emotion.css)({
102
102
  maxHeight: props.maxHeight
103
103
  }) : undefined, props.isDisabled ? _RichTextEditorstyles.styles.disabled : _RichTextEditorstyles.styles.enabled, props.isToolbarHidden && _RichTextEditorstyles.styles.hiddenToolbar, direction === 'rtl' ? _RichTextEditorstyles.styles.rtl : _RichTextEditorstyles.styles.ltr);
104
- return /*#__PURE__*/ _react.createElement(_fieldeditorreference.EntityProvider, {
104
+ return /*#__PURE__*/ _react.createElement(_fieldeditorshared.SharedQueryClientProvider, {
105
+ client: props.queryClient
106
+ }, /*#__PURE__*/ _react.createElement(_fieldeditorreference.EntityProvider, {
105
107
  sdk: sdk
106
108
  }, /*#__PURE__*/ _react.createElement(_SdkProvider.SdkProvider, {
107
109
  sdk: sdk
@@ -128,10 +130,10 @@ const ConnectedRichTextEditor = (props)=>{
128
130
  className: classNames,
129
131
  readOnly: props.isDisabled,
130
132
  scrollSelectionIntoView: _editoroverrides.defaultScrollSelectionIntoView
131
- }), props.withCharValidation && /*#__PURE__*/ _react.createElement(_CharConstraints.CharConstraints, null))))));
133
+ }), props.withCharValidation && /*#__PURE__*/ _react.createElement(_CharConstraints.CharConstraints, null)))))));
132
134
  };
133
135
  const RichTextEditor = (props)=>{
134
- const { sdk, isInitiallyDisabled, onAction, restrictedMarks, onChange, isDisabled, ...otherProps } = props;
136
+ const { sdk, isInitiallyDisabled, onAction, restrictedMarks, onChange, isDisabled, queryClient, ...otherProps } = props;
135
137
  const isEmptyValue = _react.useCallback((value)=>!value || (0, _fastdeepequal.default)(value, _richtexttypes.EMPTY_DOCUMENT), []);
136
138
  _react.useEffect(()=>{
137
139
  if (!onChange) {
@@ -158,7 +160,8 @@ const RichTextEditor = (props)=>{
158
160
  isDisabled: disabled,
159
161
  onChange: setValue,
160
162
  restrictedMarks: restrictedMarks,
161
- withCharValidation: props.withCharValidation ?? true
163
+ withCharValidation: props.withCharValidation ?? true,
164
+ queryClient: queryClient
162
165
  }));
163
166
  };
164
167
  const _default = RichTextEditor;
@@ -106,7 +106,16 @@ function newReferenceEditorFakeSdk(props) {
106
106
  return _fixtures.contentTypes.published;
107
107
  }
108
108
  return Promise.reject({});
109
- }
109
+ },
110
+ getMany: async ()=>({
111
+ items: Object.values(_fixtures.contentTypes),
112
+ total: Object.values(_fixtures.contentTypes).length,
113
+ skip: 0,
114
+ limit: 1000,
115
+ sys: {
116
+ type: 'Array'
117
+ }
118
+ })
110
119
  },
111
120
  locale: {
112
121
  getMany: async ()=>_fixtures.locales.list
@@ -67,6 +67,16 @@ const useCommandList = (commandItems, container)=>{
67
67
  return commandItems[0].id;
68
68
  });
69
69
  const [isOpen, setIsOpen] = _react.useState(commandItems.length > 0);
70
+ _react.useEffect(()=>{
71
+ if (!commandItems.length) {
72
+ setSelectedItem('');
73
+ return;
74
+ }
75
+ const firstItemId = 'group' in commandItems[0] ? commandItems[0].commands[0].id : commandItems[0].id;
76
+ setSelectedItem(firstItemId);
77
+ }, [
78
+ commandItems
79
+ ]);
70
80
  _react.useEffect(()=>{
71
81
  if (!container.current) {
72
82
  return;
@@ -74,10 +84,8 @@ const useCommandList = (commandItems, container)=>{
74
84
  const buttons = Array.from(container.current.querySelectorAll('button'));
75
85
  const currBtn = buttons.find((btn)=>btn.id === selectedItem);
76
86
  const currIndex = currBtn ? buttons.indexOf(currBtn) : 0;
77
- const shouldSelectFirstBtn = !currBtn && buttons.length;
78
- if (shouldSelectFirstBtn) {
79
- setSelectedItem(buttons[0].id);
80
- buttons[0].scrollIntoView({
87
+ if (currBtn) {
88
+ currBtn.scrollIntoView({
81
89
  block: 'nearest',
82
90
  inline: 'start'
83
91
  });
@@ -17,6 +17,7 @@ _export(exports, {
17
17
  }
18
18
  });
19
19
  const _react = require("react");
20
+ const _fieldeditorshared = require("@contentful/field-editor-shared");
20
21
  const _richtexttypes = require("@contentful/rich-text-types");
21
22
  const _editor = require("../../helpers/editor");
22
23
  const _validations = require("../../helpers/validations");
@@ -85,7 +86,7 @@ const getAllowedContentTypesFromValidation = (validations)=>{
85
86
  }, {});
86
87
  };
87
88
  const useCommands = (sdk, query, editor)=>{
88
- const contentTypes = sdk.space.getCachedContentTypes();
89
+ const { contentTypes } = (0, _fieldeditorshared.useContentTypes)(sdk);
89
90
  const { inlineAllowed, entriesAllowed, assetsAllowed } = getCommandPermissions(sdk, editor);
90
91
  const allowedContentTypesFromValidation = getAllowedContentTypesFromValidation(sdk.field.validations);
91
92
  const filterContentTypesByValidation = (type)=>contentTypes.filter((contentType)=>allowedContentTypesFromValidation[type]?.[contentType.sys.id]);
@@ -95,7 +96,8 @@ const useCommands = (sdk, query, editor)=>{
95
96
  const blockContentTypesToUse = getContentTypeToUse(entriesAllowed, filteredBlockContentTypes.length > 0, filteredBlockContentTypes);
96
97
  const inlineContentTypesToUse = getContentTypeToUse(inlineAllowed, filteredInlineContentTypes.length > 0, filteredInlineContentTypes);
97
98
  const relevantContentTypes = contentTypes.filter((ct)=>blockContentTypesToUse.includes(ct) || inlineContentTypesToUse.includes(ct));
98
- const [commands, setCommands] = (0, _react.useState)(()=>{
99
+ const [commands, setCommands] = (0, _react.useState)([]);
100
+ const initialCommands = (0, _react.useMemo)(()=>{
99
101
  const getEmbedEntry = (contentType)=>{
100
102
  return {
101
103
  id: contentType.sys.id,
@@ -234,8 +236,19 @@ const useCommands = (sdk, query, editor)=>{
234
236
  ];
235
237
  }
236
238
  return contentTypeCommands;
237
- });
238
- return query ? commands.reduce((list, nextItem)=>{
239
+ }, [
240
+ relevantContentTypes,
241
+ entriesAllowed,
242
+ inlineAllowed,
243
+ assetsAllowed,
244
+ blockContentTypesToUse,
245
+ inlineContentTypesToUse,
246
+ sdk,
247
+ editor,
248
+ query
249
+ ]);
250
+ const displayCommands = commands.length > 0 ? commands : initialCommands;
251
+ return query ? displayCommands.reduce((list, nextItem)=>{
239
252
  if ('group' in nextItem) {
240
253
  const subcommands = nextItem.commands.filter((command)=>{
241
254
  return command.label.toLowerCase().includes(query.toLowerCase());
@@ -249,5 +262,5 @@ const useCommands = (sdk, query, editor)=>{
249
262
  }
250
263
  }
251
264
  return list;
252
- }, []) : commands;
265
+ }, []) : displayCommands;
253
266
  };
@@ -121,6 +121,7 @@ function InternalFetchingWrappedInlineEntryCard({ entry, allContentTypes, locale
121
121
  function FetchingWrappedInlineEntryCard(props) {
122
122
  const { data: entry, status: requestStatus } = (0, _fieldeditorreference.useEntity)('Entry', props.entryId);
123
123
  const { getEntityScheduledActions } = (0, _fieldeditorreference.useEntityLoader)();
124
+ const { contentTypes: allContentTypes } = (0, _fieldeditorshared.useContentTypes)(props.sdk);
124
125
  const { onEntityFetchComplete } = props;
125
126
  _react.useEffect(()=>{
126
127
  if (requestStatus !== 'success') {
@@ -159,7 +160,7 @@ function FetchingWrappedInlineEntryCard(props) {
159
160
  });
160
161
  }
161
162
  return /*#__PURE__*/ _react.createElement(InternalFetchingWrappedInlineEntryCard, {
162
- allContentTypes: props.sdk.space.getCachedContentTypes(),
163
+ allContentTypes: allContentTypes,
163
164
  getEntityScheduledActions: ()=>getEntityScheduledActions('Entry', props.entryId),
164
165
  locale: props.sdk.field.locale,
165
166
  defaultLocale: props.sdk.locales.default,
@@ -12,16 +12,12 @@ const _react = require("react");
12
12
  const _fieldeditorshared = require("@contentful/field-editor-shared");
13
13
  const _utils = require("./utils");
14
14
  async function fetchAllData({ sdk, entityId, entityType, localeCode, defaultLocaleCode }) {
15
- let contentType;
16
15
  const entity = await (entityType === 'Entry' ? sdk.cma.entry.get({
17
16
  entryId: entityId
18
17
  }) : sdk.cma.asset.get({
19
18
  assetId: entityId
20
19
  }));
21
- if (entity.sys.contentType) {
22
- const contentTypeId = entity.sys.contentType.sys.id;
23
- contentType = sdk.space.getCachedContentTypes().find((ct)=>ct.sys.id === contentTypeId);
24
- }
20
+ const contentType = entity.sys.contentType ? await (0, _fieldeditorshared.fetchContentType)(sdk, entity.sys.contentType.sys.id) : undefined;
25
21
  const entityTitle = entityType === 'Entry' ? _fieldeditorshared.entityHelpers.getEntryTitle({
26
22
  entry: entity,
27
23
  contentType,
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { EntityProvider } from '@contentful/field-editor-reference';
3
- import { FieldConnector } from '@contentful/field-editor-shared';
3
+ import { FieldConnector, SharedQueryClientProvider } from '@contentful/field-editor-shared';
4
4
  import * as Contentful from '@contentful/rich-text-types';
5
5
  import { PlateContent, Plate } from '@udecode/plate-common';
6
6
  import { css, cx } from 'emotion';
@@ -37,7 +37,9 @@ export const ConnectedRichTextEditor = (props)=>{
37
37
  }) : undefined, props.maxHeight !== undefined ? css({
38
38
  maxHeight: props.maxHeight
39
39
  }) : undefined, props.isDisabled ? styles.disabled : styles.enabled, props.isToolbarHidden && styles.hiddenToolbar, direction === 'rtl' ? styles.rtl : styles.ltr);
40
- return /*#__PURE__*/ React.createElement(EntityProvider, {
40
+ return /*#__PURE__*/ React.createElement(SharedQueryClientProvider, {
41
+ client: props.queryClient
42
+ }, /*#__PURE__*/ React.createElement(EntityProvider, {
41
43
  sdk: sdk
42
44
  }, /*#__PURE__*/ React.createElement(SdkProvider, {
43
45
  sdk: sdk
@@ -64,10 +66,10 @@ export const ConnectedRichTextEditor = (props)=>{
64
66
  className: classNames,
65
67
  readOnly: props.isDisabled,
66
68
  scrollSelectionIntoView: defaultScrollSelectionIntoView
67
- }), props.withCharValidation && /*#__PURE__*/ React.createElement(CharConstraints, null))))));
69
+ }), props.withCharValidation && /*#__PURE__*/ React.createElement(CharConstraints, null)))))));
68
70
  };
69
71
  const RichTextEditor = (props)=>{
70
- const { sdk, isInitiallyDisabled, onAction, restrictedMarks, onChange, isDisabled, ...otherProps } = props;
72
+ const { sdk, isInitiallyDisabled, onAction, restrictedMarks, onChange, isDisabled, queryClient, ...otherProps } = props;
71
73
  const isEmptyValue = React.useCallback((value)=>!value || deepEquals(value, Contentful.EMPTY_DOCUMENT), []);
72
74
  React.useEffect(()=>{
73
75
  if (!onChange) {
@@ -94,7 +96,8 @@ const RichTextEditor = (props)=>{
94
96
  isDisabled: disabled,
95
97
  onChange: setValue,
96
98
  restrictedMarks: restrictedMarks,
97
- withCharValidation: props.withCharValidation ?? true
99
+ withCharValidation: props.withCharValidation ?? true,
100
+ queryClient: queryClient
98
101
  }));
99
102
  };
100
103
  export default RichTextEditor;
@@ -96,7 +96,16 @@ export function newReferenceEditorFakeSdk(props) {
96
96
  return contentTypes.published;
97
97
  }
98
98
  return Promise.reject({});
99
- }
99
+ },
100
+ getMany: async ()=>({
101
+ items: Object.values(contentTypes),
102
+ total: Object.values(contentTypes).length,
103
+ skip: 0,
104
+ limit: 1000,
105
+ sys: {
106
+ type: 'Array'
107
+ }
108
+ })
100
109
  },
101
110
  locale: {
102
111
  getMany: async ()=>localesFixtures.list
@@ -11,6 +11,16 @@ export const useCommandList = (commandItems, container)=>{
11
11
  return commandItems[0].id;
12
12
  });
13
13
  const [isOpen, setIsOpen] = React.useState(commandItems.length > 0);
14
+ React.useEffect(()=>{
15
+ if (!commandItems.length) {
16
+ setSelectedItem('');
17
+ return;
18
+ }
19
+ const firstItemId = 'group' in commandItems[0] ? commandItems[0].commands[0].id : commandItems[0].id;
20
+ setSelectedItem(firstItemId);
21
+ }, [
22
+ commandItems
23
+ ]);
14
24
  React.useEffect(()=>{
15
25
  if (!container.current) {
16
26
  return;
@@ -18,10 +28,8 @@ export const useCommandList = (commandItems, container)=>{
18
28
  const buttons = Array.from(container.current.querySelectorAll('button'));
19
29
  const currBtn = buttons.find((btn)=>btn.id === selectedItem);
20
30
  const currIndex = currBtn ? buttons.indexOf(currBtn) : 0;
21
- const shouldSelectFirstBtn = !currBtn && buttons.length;
22
- if (shouldSelectFirstBtn) {
23
- setSelectedItem(buttons[0].id);
24
- buttons[0].scrollIntoView({
31
+ if (currBtn) {
32
+ currBtn.scrollIntoView({
25
33
  block: 'nearest',
26
34
  inline: 'start'
27
35
  });
@@ -1,4 +1,5 @@
1
- import { useState } from 'react';
1
+ import { useMemo, useState } from 'react';
2
+ import { useContentTypes } from '@contentful/field-editor-shared';
2
3
  import { BLOCKS, INLINES } from '@contentful/rich-text-types';
3
4
  import { isNodeTypeSelected } from '../../helpers/editor';
4
5
  import { isNodeTypeEnabled } from '../../helpers/validations';
@@ -67,7 +68,7 @@ const getAllowedContentTypesFromValidation = (validations)=>{
67
68
  }, {});
68
69
  };
69
70
  export const useCommands = (sdk, query, editor)=>{
70
- const contentTypes = sdk.space.getCachedContentTypes();
71
+ const { contentTypes } = useContentTypes(sdk);
71
72
  const { inlineAllowed, entriesAllowed, assetsAllowed } = getCommandPermissions(sdk, editor);
72
73
  const allowedContentTypesFromValidation = getAllowedContentTypesFromValidation(sdk.field.validations);
73
74
  const filterContentTypesByValidation = (type)=>contentTypes.filter((contentType)=>allowedContentTypesFromValidation[type]?.[contentType.sys.id]);
@@ -77,7 +78,8 @@ export const useCommands = (sdk, query, editor)=>{
77
78
  const blockContentTypesToUse = getContentTypeToUse(entriesAllowed, filteredBlockContentTypes.length > 0, filteredBlockContentTypes);
78
79
  const inlineContentTypesToUse = getContentTypeToUse(inlineAllowed, filteredInlineContentTypes.length > 0, filteredInlineContentTypes);
79
80
  const relevantContentTypes = contentTypes.filter((ct)=>blockContentTypesToUse.includes(ct) || inlineContentTypesToUse.includes(ct));
80
- const [commands, setCommands] = useState(()=>{
81
+ const [commands, setCommands] = useState([]);
82
+ const initialCommands = useMemo(()=>{
81
83
  const getEmbedEntry = (contentType)=>{
82
84
  return {
83
85
  id: contentType.sys.id,
@@ -216,8 +218,19 @@ export const useCommands = (sdk, query, editor)=>{
216
218
  ];
217
219
  }
218
220
  return contentTypeCommands;
219
- });
220
- return query ? commands.reduce((list, nextItem)=>{
221
+ }, [
222
+ relevantContentTypes,
223
+ entriesAllowed,
224
+ inlineAllowed,
225
+ assetsAllowed,
226
+ blockContentTypesToUse,
227
+ inlineContentTypesToUse,
228
+ sdk,
229
+ editor,
230
+ query
231
+ ]);
232
+ const displayCommands = commands.length > 0 ? commands : initialCommands;
233
+ return query ? displayCommands.reduce((list, nextItem)=>{
221
234
  if ('group' in nextItem) {
222
235
  const subcommands = nextItem.commands.filter((command)=>{
223
236
  return command.label.toLowerCase().includes(query.toLowerCase());
@@ -231,5 +244,5 @@ export const useCommands = (sdk, query, editor)=>{
231
244
  }
232
245
  }
233
246
  return list;
234
- }, []) : commands;
247
+ }, []) : displayCommands;
235
248
  };
@@ -3,7 +3,7 @@ import { InlineEntryCard, MenuItem, Text } from '@contentful/f36-components';
3
3
  import { ClockIcon } from '@contentful/f36-icons';
4
4
  import tokens from '@contentful/f36-tokens';
5
5
  import { ScheduledIconWithTooltip, useEntity, useEntityLoader } from '@contentful/field-editor-reference';
6
- import { entityHelpers } from '@contentful/field-editor-shared';
6
+ import { entityHelpers, useContentTypes } from '@contentful/field-editor-shared';
7
7
  import { INLINES } from '@contentful/rich-text-types';
8
8
  import { css } from 'emotion';
9
9
  const { getEntryTitle, getEntityStatus } = entityHelpers;
@@ -65,6 +65,7 @@ function InternalFetchingWrappedInlineEntryCard({ entry, allContentTypes, locale
65
65
  export function FetchingWrappedInlineEntryCard(props) {
66
66
  const { data: entry, status: requestStatus } = useEntity('Entry', props.entryId);
67
67
  const { getEntityScheduledActions } = useEntityLoader();
68
+ const { contentTypes: allContentTypes } = useContentTypes(props.sdk);
68
69
  const { onEntityFetchComplete } = props;
69
70
  React.useEffect(()=>{
70
71
  if (requestStatus !== 'success') {
@@ -103,7 +104,7 @@ export function FetchingWrappedInlineEntryCard(props) {
103
104
  });
104
105
  }
105
106
  return /*#__PURE__*/ React.createElement(InternalFetchingWrappedInlineEntryCard, {
106
- allContentTypes: props.sdk.space.getCachedContentTypes(),
107
+ allContentTypes: allContentTypes,
107
108
  getEntityScheduledActions: ()=>getEntityScheduledActions('Entry', props.entryId),
108
109
  locale: props.sdk.field.locale,
109
110
  defaultLocale: props.sdk.locales.default,
@@ -1,17 +1,13 @@
1
1
  import { useEffect, useState } from 'react';
2
- import { entityHelpers } from '@contentful/field-editor-shared';
2
+ import { entityHelpers, fetchContentType } from '@contentful/field-editor-shared';
3
3
  import { getEntityInfo } from './utils';
4
4
  async function fetchAllData({ sdk, entityId, entityType, localeCode, defaultLocaleCode }) {
5
- let contentType;
6
5
  const entity = await (entityType === 'Entry' ? sdk.cma.entry.get({
7
6
  entryId: entityId
8
7
  }) : sdk.cma.asset.get({
9
8
  assetId: entityId
10
9
  }));
11
- if (entity.sys.contentType) {
12
- const contentTypeId = entity.sys.contentType.sys.id;
13
- contentType = sdk.space.getCachedContentTypes().find((ct)=>ct.sys.id === contentTypeId);
14
- }
10
+ const contentType = entity.sys.contentType ? await fetchContentType(sdk, entity.sys.contentType.sys.id) : undefined;
15
11
  const entityTitle = entityType === 'Entry' ? entityHelpers.getEntryTitle({
16
12
  entry: entity,
17
13
  contentType,
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { FieldAppSDK } from '@contentful/app-sdk';
3
3
  import * as Contentful from '@contentful/rich-text-types';
4
+ import { QueryClient } from '@tanstack/react-query';
4
5
  import { RichTextTrackingActionHandler } from './plugins/Tracking';
5
6
  type RichTextProps = {
6
7
  sdk: FieldAppSDK;
@@ -18,6 +19,7 @@ type RichTextProps = {
18
19
  */
19
20
  onChange?: (doc: Contentful.Document) => unknown;
20
21
  withCharValidation?: boolean;
22
+ queryClient?: QueryClient;
21
23
  };
22
24
  type ConnectedRichTextProps = {
23
25
  sdk: FieldAppSDK;
@@ -32,6 +34,7 @@ type ConnectedRichTextProps = {
32
34
  actionsDisabled?: boolean;
33
35
  stickyToolbarOffset?: number;
34
36
  withCharValidation?: boolean;
37
+ queryClient?: QueryClient;
35
38
  };
36
39
  export declare const ConnectedRichTextEditor: (props: ConnectedRichTextProps) => React.JSX.Element;
37
40
  declare const RichTextEditor: (props: RichTextProps) => React.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/field-editor-rich-text",
3
- "version": "4.19.3-alpha.0",
3
+ "version": "4.19.3-canary.7+54b401aa",
4
4
  "source": "./src/index.tsx",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -44,8 +44,8 @@
44
44
  "@contentful/f36-icons": "^5.4.1",
45
45
  "@contentful/f36-tokens": "^5.1.0",
46
46
  "@contentful/f36-utils": "^5.1.0",
47
- "@contentful/field-editor-reference": "^6.19.2-alpha.0",
48
- "@contentful/field-editor-shared": "^2.17.1-alpha.0",
47
+ "@contentful/field-editor-reference": "^6.19.2-canary.7+54b401aa",
48
+ "@contentful/field-editor-shared": "^2.17.1-canary.59+54b401aa",
49
49
  "@contentful/rich-text-plain-text-renderer": "^17.0.0",
50
50
  "@contentful/rich-text-types": "^17.2.5",
51
51
  "@popperjs/core": "^2.11.5",
@@ -86,13 +86,10 @@
86
86
  "@types/is-hotkey": "^0.1.6",
87
87
  "@udecode/plate-test-utils": "^3.2.0",
88
88
  "prism-react-renderer": "2.4.1",
89
- "react": "18.3.1",
90
- "slate": "0.118.1",
91
- "slate-dom": "0.118.1",
92
- "slate-react": "0.118.2"
89
+ "react": "18.3.1"
93
90
  },
94
91
  "publishConfig": {
95
92
  "registry": "https://npm.pkg.github.com/"
96
93
  },
97
- "gitHead": "447875c5a2ef25eb4552c29b990d90ec40bc6985"
94
+ "gitHead": "54b401aa9908c8380c3801bf25fa38e23dff72d2"
98
95
  }