@strapi/admin 4.11.3 → 4.11.5

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 (115) hide show
  1. package/admin/src/components/AuthenticatedApp/index.js +2 -2
  2. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +8 -5
  3. package/admin/src/content-manager/components/Inputs/index.js +3 -47
  4. package/admin/src/content-manager/components/RelationInput/RelationInput.js +99 -178
  5. package/admin/src/content-manager/components/RelationInput/components/Option.js +17 -15
  6. package/admin/src/content-manager/components/RelationInput/components/RelationList.js +2 -2
  7. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +34 -37
  8. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +0 -27
  9. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +93 -14
  10. package/admin/src/content-manager/pages/ListView/index.js +65 -47
  11. package/admin/src/content-manager/pages/ListView/utils/buildValidGetParams.js +30 -0
  12. package/admin/src/content-manager/pages/ListView/utils/index.js +1 -1
  13. package/admin/src/hooks/useAdminUsers/useAdminUsers.js +3 -3
  14. package/admin/src/hooks/useEnterprise/useEnterprise.js +4 -4
  15. package/admin/src/hooks/useSettingsMenu/index.js +35 -21
  16. package/admin/src/pages/App/index.js +0 -3
  17. package/admin/src/pages/AuthPage/components/Register/index.js +5 -1
  18. package/admin/src/pages/ProfilePage/index.js +12 -12
  19. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +13 -11
  20. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +15 -1
  21. package/admin/src/pages/SettingsPage/components/Tokens/TokenBox/index.js +1 -1
  22. package/admin/src/pages/SettingsPage/pages/Roles/ProtectedEditPage/index.js +4 -10
  23. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -2
  24. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/utils/makeWebhookValidationSchema.js +11 -5
  25. package/admin/src/translations/ca.json +1 -0
  26. package/admin/src/translations/en.json +4 -1
  27. package/admin/src/translations/es.json +5 -0
  28. package/admin/src/translations/fr.json +1 -0
  29. package/admin/src/translations/zh-Hans.json +1 -1
  30. package/build/2799.cf9b491f.chunk.js +1 -0
  31. package/build/539.865446c0.chunk.js +1 -0
  32. package/build/{5542.64b623c9.chunk.js → 5542.c62d0daf.chunk.js} +1 -1
  33. package/build/{5563.86f9aa9c.chunk.js → 5563.27e2de0c.chunk.js} +3 -3
  34. package/build/5932.f8be7e31.chunk.js +1 -0
  35. package/build/7259.0e25ab5d.chunk.js +1 -0
  36. package/build/{6405.27e1bee5.chunk.js → 970.89601f27.chunk.js} +2 -2
  37. package/build/{9932.7e2b71de.chunk.js → 9932.9f3790a5.chunk.js} +81 -81
  38. package/build/9944.29289a16.chunk.js +26 -0
  39. package/build/Admin-authenticatedApp.7f04c595.chunk.js +79 -0
  40. package/build/{Admin_profilePage.2131eb68.chunk.js → Admin_profilePage.0adb571e.chunk.js} +2 -2
  41. package/build/{Admin_settingsPage.4069bb8a.chunk.js → Admin_settingsPage.36152558.chunk.js} +9 -9
  42. package/build/admin-app.3ea6009c.chunk.js +61 -0
  43. package/build/{admin-edit-roles-page.2040034a.chunk.js → admin-edit-roles-page.3fdd6b9d.chunk.js} +11 -11
  44. package/build/admin-edit-users.78552758.chunk.js +10 -0
  45. package/build/admin-users.c23322fc.chunk.js +11 -0
  46. package/build/api-tokens-list-page.a103f526.chunk.js +16 -0
  47. package/build/audit-logs-settings-page.37fe915c.chunk.js +1 -0
  48. package/build/ca-json.1fed5d8b.chunk.js +1 -0
  49. package/build/content-manager.552c7418.chunk.js +1094 -0
  50. package/build/{content-type-builder-list-view.0c3ceb4e.chunk.js → content-type-builder-list-view.82cfadc0.chunk.js} +7 -7
  51. package/build/content-type-builder.238687f9.chunk.js +166 -0
  52. package/build/{email-settings-page.6b38222d.chunk.js → email-settings-page.45695daa.chunk.js} +1 -1
  53. package/build/en-json.fb9f6ddd.chunk.js +1 -0
  54. package/build/es-json.42096084.chunk.js +1 -0
  55. package/build/fr-json.69789980.chunk.js +1 -0
  56. package/build/{i18n-settings-page.ff863f20.chunk.js → i18n-settings-page.29308d0b.chunk.js} +1 -1
  57. package/build/index.html +1 -1
  58. package/build/main.3d752c03.js +2927 -0
  59. package/build/runtime~main.87232977.js +2 -0
  60. package/build/sso-settings-page.0cdb96a6.chunk.js +1 -0
  61. package/build/transfer-tokens-list-page.7237443d.chunk.js +16 -0
  62. package/build/{upload-settings.43cf16cd.chunk.js → upload-settings.cb6c14c3.chunk.js} +1 -1
  63. package/build/{upload.72f8f8fc.chunk.js → upload.7e629643.chunk.js} +2 -2
  64. package/build/users-advanced-settings-page.750b1f76.chunk.js +9 -0
  65. package/build/{users-email-settings-page.33359797.chunk.js → users-email-settings-page.e9bcd865.chunk.js} +1 -1
  66. package/build/{users-providers-settings-page.1e7a4a71.chunk.js → users-providers-settings-page.a94253e9.chunk.js} +1 -1
  67. package/build/{users-roles-settings-page.235378b6.chunk.js → users-roles-settings-page.d286426a.chunk.js} +5 -5
  68. package/build/webhook-edit-page.77ef4f1a.chunk.js +33 -0
  69. package/build/{zh-Hans-json.4cfef87d.chunk.js → zh-Hans-json.fada6f40.chunk.js} +1 -1
  70. package/ee/admin/content-manager/{components/DynamicTable/CellContent/ReviewWorkflowsStage → pages/ListView/ReviewWorkflowsColumn}/ReviewWorkflowsStageEE.js +7 -2
  71. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +24 -0
  72. package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/index.js +1 -0
  73. package/ee/admin/hooks/useLicenseLimitNotification/index.js +17 -6
  74. package/ee/admin/hooks/useLicenseLimits/index.js +1 -32
  75. package/ee/admin/hooks/useLicenseLimits/useLicenseLimits.js +44 -0
  76. package/ee/admin/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +6 -4
  77. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useAuditLogsData.js +6 -4
  78. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/index.js +4 -9
  79. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +3 -5
  80. package/ee/admin/pages/SettingsPage/pages/SingleSignOn/index.js +4 -9
  81. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +9 -2
  82. package/ee/server/services/review-workflows/entity-service-decorator.js +20 -11
  83. package/package.json +14 -15
  84. package/server/content-types/User.js +10 -0
  85. package/server/strategies/api-token.js +9 -5
  86. package/server/strategies/data-transfer.js +9 -5
  87. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +0 -2
  88. package/admin/src/content-manager/components/RelationInput/components/Relation.js +0 -53
  89. package/admin/src/content-manager/pages/ListView/utils/buildQueryString.js +0 -36
  90. package/admin/src/content-manager/pages/ListView/utils/createPluginsFilter.js +0 -4
  91. package/admin/src/pages/App/utils/index.js +0 -3
  92. package/admin/src/pages/App/utils/unique-identifier.js +0 -12
  93. package/build/1799.84268ad3.chunk.js +0 -33
  94. package/build/5932.6a23b88c.chunk.js +0 -1
  95. package/build/7259.fb69d4bf.chunk.js +0 -1
  96. package/build/Admin-authenticatedApp.69855f1b.chunk.js +0 -79
  97. package/build/admin-app.fea867af.chunk.js +0 -61
  98. package/build/admin-edit-users.53e4290a.chunk.js +0 -10
  99. package/build/admin-users.3b12dca2.chunk.js +0 -11
  100. package/build/api-tokens-list-page.201fb67a.chunk.js +0 -16
  101. package/build/audit-logs-settings-page.b07ad202.chunk.js +0 -1
  102. package/build/ca-json.43e14418.chunk.js +0 -1
  103. package/build/content-manager.66cec770.chunk.js +0 -1094
  104. package/build/content-type-builder.e1b6d13b.chunk.js +0 -166
  105. package/build/en-json.f5fa476a.chunk.js +0 -1
  106. package/build/es-json.715b6fd8.chunk.js +0 -1
  107. package/build/fr-json.73494bf5.chunk.js +0 -1
  108. package/build/main.83edb3fc.js +0 -2926
  109. package/build/runtime~main.20c3cac6.js +0 -2
  110. package/build/sso-settings-page.35b67909.chunk.js +0 -1
  111. package/build/transfer-tokens-list-page.217573c3.chunk.js +0 -16
  112. package/build/users-advanced-settings-page.1911adf5.chunk.js +0 -9
  113. package/build/webhook-edit-page.1ee02c4b.chunk.js +0 -33
  114. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +0 -58
  115. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/index.js +0 -3
@@ -38,7 +38,7 @@ const AuthenticatedApp = () => {
38
38
  const [
39
39
  { data: appInfos, status },
40
40
  { data: tagName, isLoading },
41
- { data: permissions, status: fetchPermissionsStatus, refetch, isFetched, isFetching },
41
+ { data: permissions, status: fetchPermissionsStatus, refetch, isFetching },
42
42
  { data: userRoles },
43
43
  ] = useQueries([
44
44
  { queryKey: 'app-infos', queryFn: fetchAppInfo },
@@ -86,7 +86,7 @@ const AuthenticatedApp = () => {
86
86
  // We don't need to wait for the release query to be fetched before rendering the plugins
87
87
  // however, we need the appInfos and the permissions
88
88
  const shouldShowNotDependentQueriesLoader =
89
- (isFetching && isFetched) || status === 'loading' || fetchPermissionsStatus === 'loading';
89
+ isFetching || status === 'loading' || fetchPermissionsStatus === 'loading';
90
90
 
91
91
  const shouldShowLoader = isLoading || shouldShowNotDependentQueriesLoader;
92
92
 
@@ -43,7 +43,7 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
43
43
  const { setCurrentStep } = useGuidedTour();
44
44
  const { trackUsage } = useTracking();
45
45
  const { push, replace } = useHistory();
46
- const [{ rawQuery }] = useQueryParams();
46
+ const [{ query, rawQuery }] = useQueryParams();
47
47
  const dispatch = useDispatch();
48
48
  const { componentsDataStructure, contentTypeDataStructure, data, isLoading, status } =
49
49
  useSelector(selectCrudReducer);
@@ -244,13 +244,15 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
244
244
  */
245
245
  const endPoint =
246
246
  typeof origin === 'string'
247
- ? `${getRequestUrl(`collection-types/${slug}/clone/${origin}`)}${rawQuery}`
248
- : `${getRequestUrl(`collection-types/${slug}`)}${rawQuery}`;
247
+ ? getRequestUrl(`collection-types/${slug}/clone/${origin}`)
248
+ : getRequestUrl(`collection-types/${slug}`);
249
249
  try {
250
250
  // Show a loading button in the EditView/Header.js && lock the app => no navigation
251
251
  dispatch(setStatus('submit-pending'));
252
252
 
253
- const { data } = await post(endPoint, body);
253
+ const { data } = await post(endPoint, body, {
254
+ params: query,
255
+ });
254
256
 
255
257
  trackUsageRef.current('didCreateEntry', trackerProperty);
256
258
  toggleNotification({
@@ -286,11 +288,12 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
286
288
  replace,
287
289
  slug,
288
290
  dispatch,
289
- rawQuery,
291
+ query,
290
292
  toggleNotification,
291
293
  setCurrentStep,
292
294
  queryClient,
293
295
  post,
296
+ rawQuery,
294
297
  ]
295
298
  );
296
299
 
@@ -75,20 +75,9 @@ function Inputs({
75
75
  return foundAttributeType === 'dynamiczone';
76
76
  }, [currentContentTypeLayout, fieldName]);
77
77
 
78
- const inputType = useMemo(() => {
79
- return getInputType(type);
80
- }, [type]);
81
-
82
- const inputValue = useMemo(() => {
83
- // Fix for input file multipe
84
- if (type === 'media' && !value) {
85
- return [];
86
- }
87
-
88
- return value;
89
- }, [type, value]);
78
+ const inputType = getInputType(type);
90
79
 
91
- const step = getStep(type);
80
+ const inputValue = type === 'media' && !value ? [] : value;
92
81
 
93
82
  const isUserAllowedToEditField = useMemo(() => {
94
83
  const joinedName = fieldName.join('.');
@@ -159,36 +148,6 @@ function Inputs({
159
148
 
160
149
  const { label, description, placeholder, visible } = metadatas;
161
150
 
162
- /**
163
- * It decides whether using the default `step` accoding to its `inputType` or the one
164
- * obtained from `metadatas`.
165
- *
166
- * The `metadatas.step` is returned when the `inputValue` is divisible by it or when the
167
- * `inputValue` is empty, otherwise the default `step` is returned.
168
- */
169
- const inputStep = useMemo(() => {
170
- if (!metadatas.step || (inputType !== 'datetime' && inputType !== 'time')) {
171
- return step;
172
- }
173
-
174
- if (!inputValue) {
175
- return metadatas.step;
176
- }
177
-
178
- let minutes;
179
-
180
- /**
181
- * Wtf is this?
182
- */
183
- if (inputType === 'datetime') {
184
- minutes = parseInt(inputValue.substr(14, 2), 10);
185
- } else if (inputType === 'time') {
186
- minutes = parseInt(inputValue.slice(-2), 10);
187
- }
188
-
189
- return minutes % metadatas.step === 0 ? metadatas.step : step;
190
- }, [inputType, inputValue, metadatas.step, step]);
191
-
192
151
  if (visible === false) {
193
152
  return null;
194
153
  }
@@ -271,7 +230,7 @@ function Inputs({
271
230
  options={options}
272
231
  placeholder={placeholder ? { id: placeholder, defaultMessage: placeholder } : null}
273
232
  required={fieldSchema.required || false}
274
- step={inputStep}
233
+ step={getStep(type)}
275
234
  type={customFieldUid || inputType}
276
235
  // validations={validations}
277
236
  value={inputValue}
@@ -317,9 +276,6 @@ const getStep = (type) => {
317
276
  case 'float':
318
277
  case 'decimal':
319
278
  return 0.01;
320
- case 'time':
321
- case 'datetime':
322
- return 15;
323
279
  default:
324
280
  return 1;
325
281
  }
@@ -1,24 +1,17 @@
1
- import React, { useEffect, useMemo, useRef, useState } from 'react';
1
+ import React, { useRef, useState, useMemo, useEffect } from 'react';
2
2
 
3
3
  import {
4
+ Status,
4
5
  Box,
5
- Field,
6
- FieldError,
7
- FieldHint,
8
- FieldLabel,
9
- Icon,
10
6
  Link,
11
- Status,
7
+ Icon,
8
+ Flex,
12
9
  TextButton,
13
- Tooltip,
14
10
  Typography,
11
+ Tooltip,
15
12
  VisuallyHidden,
13
+ Combobox,
16
14
  } from '@strapi/design-system';
17
- /**
18
- * TODO: this will come in another PR.
19
- */
20
- // eslint-disable-next-line no-restricted-imports
21
- import { ReactSelect } from '@strapi/helper-plugin';
22
15
  import { Cross, Refresh } from '@strapi/icons';
23
16
  import PropTypes from 'prop-types';
24
17
  import { FixedSizeList as List } from 'react-window';
@@ -27,7 +20,6 @@ import styled from 'styled-components';
27
20
  import { usePrev } from '../../hooks';
28
21
 
29
22
  import { Option } from './components/Option';
30
- import { Relation } from './components/Relation';
31
23
  import { RelationItem } from './components/RelationItem';
32
24
  import { RelationList } from './components/RelationList';
33
25
  import { RELATION_GUTTER, RELATION_ITEM_HEIGHT } from './constants';
@@ -88,7 +80,7 @@ const RelationInput = ({
88
80
  searchResults,
89
81
  size,
90
82
  }) => {
91
- const [value, setValue] = useState(null);
83
+ const [textValue, setTextValue] = useState('');
92
84
  const [overflow, setOverflow] = useState('');
93
85
 
94
86
  const listRef = useRef();
@@ -158,71 +150,10 @@ const RelationInput = ({
158
150
  };
159
151
  }, [paginatedRelations, relations, numberOfRelationsToDisplay, totalNumberOfRelations]);
160
152
 
161
- /**
162
- * --- ReactSelect Workaround START ---
163
- */
164
- /**
165
- * This code is being isolated because it's a hack to fix a placement bug in
166
- * `react-select` where when the options prop is updated the position of the
167
- * menu is not recalculated.
168
- */
169
- const [isMenuOpen, setIsMenuOpen] = useState(false);
170
-
171
- const timeoutRef = useRef();
172
- const previousOptions = useRef([]);
173
-
174
- useEffect(() => {
175
- /**
176
- * We only really want this effect to fire once when the options
177
- * change from an empty array to an array with values.
178
- * Otherwise, it'll fire when the infinite scrolling happens causing
179
- * the menu to jump to the top all the time when loading more.
180
- */
181
- if (options.length > 0 && previousOptions.current.length === 0) {
182
- setIsMenuOpen((isCurrentlyOpened) => {
183
- /**
184
- * If we're currently open and the options changed
185
- * we want to close and open to ensure the menu's
186
- * position is correctly calculated
187
- */
188
- if (isCurrentlyOpened) {
189
- timeoutRef.current = setTimeout(() => {
190
- setIsMenuOpen(true);
191
- }, 10);
192
-
193
- return false;
194
- }
195
-
196
- return false;
197
- });
153
+ const handleMenuOpen = (isOpen) => {
154
+ if (isOpen) {
155
+ onSearch();
198
156
  }
199
-
200
- return () => {
201
- previousOptions.current = options || [];
202
- };
203
- }, [options]);
204
-
205
- useEffect(() => {
206
- return () => {
207
- /**
208
- * If the component unmounts and a timer is set we should clear that timer
209
- */
210
- if (timeoutRef.current) {
211
- clearTimeout(timeoutRef.current);
212
- }
213
- };
214
- }, []);
215
-
216
- const handleMenuClose = () => {
217
- setIsMenuOpen(false);
218
- };
219
- /**
220
- * --- ReactSelect Workaround END ---
221
- */
222
-
223
- const handleMenuOpen = () => {
224
- setIsMenuOpen(true);
225
- onSearch();
226
157
  };
227
158
 
228
159
  /**
@@ -250,122 +181,112 @@ const RelationInput = ({
250
181
  };
251
182
 
252
183
  useEffect(() => {
184
+ if (updatedRelationsWith.current === 'onChange') {
185
+ setTextValue('');
186
+ }
187
+
253
188
  if (
254
189
  updatedRelationsWith.current === 'onChange' &&
255
190
  relations.length !== previewRelationsLength
256
191
  ) {
257
192
  listRef.current.scrollToItem(relations.length, 'end');
193
+ updatedRelationsWith.current = undefined;
258
194
  } else if (
259
195
  updatedRelationsWith.current === 'loadMore' &&
260
196
  relations.length !== previewRelationsLength
261
197
  ) {
262
198
  listRef.current.scrollToItem(0, 'start');
199
+ updatedRelationsWith.current = undefined;
263
200
  }
264
-
265
- updatedRelationsWith.current = undefined;
266
201
  }, [previewRelationsLength, relations]);
267
202
 
268
203
  const ariaDescriptionId = `${name}-item-instructions`;
269
204
 
270
205
  return (
271
- <Field error={error} name={name} hint={description} id={id} required={required}>
272
- <Relation
273
- totalNumberOfRelations={totalNumberOfRelations}
274
- size={size}
275
- search={
276
- <>
277
- <FieldLabel action={labelAction}>{label}</FieldLabel>
278
- <ReactSelect
279
- // position fixed doesn't update position on scroll
280
- // react select doesn't update menu position on options change
281
- menuPosition="absolute"
282
- menuPlacement="auto"
283
- components={{ Option }}
284
- options={options}
285
- isDisabled={disabled}
286
- isLoading={searchResults.isLoading}
287
- error={error}
288
- inputId={id}
289
- isSearchable
290
- isClear
291
- loadingMessage={() => loadingMessage}
292
- onChange={(relation) => {
293
- setValue(null);
294
- onRelationConnect(relation);
295
- updatedRelationsWith.current = 'onChange';
296
- }}
297
- onInputChange={(value) => {
298
- setValue(value);
299
- onSearch(value);
300
- }}
301
- onMenuClose={handleMenuClose}
302
- onMenuOpen={handleMenuOpen}
303
- menuIsOpen={isMenuOpen}
304
- noOptionsMessage={() => noRelationsMessage}
305
- onMenuScrollToBottom={() => {
306
- if (searchResults.hasNextPage) {
307
- onSearchNextPage();
308
- }
309
- }}
310
- placeholder={placeholder}
311
- name={name}
312
- value={value}
313
- />
314
- </>
315
- }
316
- loadMore={
317
- shouldDisplayLoadMoreButton && (
318
- <TextButton
319
- disabled={paginatedRelations.isLoading || paginatedRelations.isFetchingNextPage}
320
- onClick={handleLoadMore}
321
- loading={paginatedRelations.isLoading || paginatedRelations.isFetchingNextPage}
322
- startIcon={<Refresh />}
323
- >
324
- {labelLoadMore}
325
- </TextButton>
326
- )
327
- }
328
- >
329
- {relations.length > 0 && (
330
- <RelationList overflow={overflow}>
331
- <VisuallyHidden id={ariaDescriptionId}>{listAriaDescription}</VisuallyHidden>
332
- <VisuallyHidden aria-live="assertive">{liveText}</VisuallyHidden>
333
- <List
334
- height={dynamicListHeight}
335
- ref={listRef}
336
- outerRef={outerListRef}
337
- itemCount={totalNumberOfRelations}
338
- itemSize={RELATION_ITEM_HEIGHT + RELATION_GUTTER}
339
- itemData={{
340
- name,
341
- ariaDescribedBy: ariaDescriptionId,
342
- canDrag: canReorder,
343
- disabled,
344
- handleCancel: onCancel,
345
- handleDropItem: onDropItem,
346
- handleGrabItem: onGrabItem,
347
- iconButtonAriaLabel,
348
- labelDisconnectRelation,
349
- onRelationDisconnect,
350
- publicationStateTranslations,
351
- relations,
352
- updatePositionOfRelation: handleUpdatePositionOfRelation,
353
- }}
354
- itemKey={(index) => `${relations[index].mainField}_${relations[index].id}`}
355
- innerElementType="ol"
356
- >
357
- {ListItem}
358
- </List>
359
- </RelationList>
360
- )}
361
- {(description || error) && (
362
- <Box paddingTop={2}>
363
- <FieldHint />
364
- <FieldError />
365
- </Box>
206
+ <Flex gap={3} justifyContent="space-between" alignItems="end" wrap="wrap">
207
+ <Flex direction="column" alignItems="stretch" basis={size <= 6 ? '100%' : '70%'} gap={2}>
208
+ <Combobox
209
+ autocomplete="list"
210
+ error={error}
211
+ name={name}
212
+ hint={description}
213
+ id={id}
214
+ required={required}
215
+ label={label}
216
+ labelAction={labelAction}
217
+ disabled={disabled}
218
+ placeholder={placeholder}
219
+ hasMoreItems={searchResults.hasNextPage}
220
+ loading={searchResults.isLoading}
221
+ onOpenChange={handleMenuOpen}
222
+ noOptionsMessage={() => noRelationsMessage}
223
+ loadingMessage={loadingMessage}
224
+ onLoadMore={() => {
225
+ onSearchNextPage();
226
+ }}
227
+ textValue={textValue}
228
+ onChange={(relationId) => {
229
+ if (!relationId) {
230
+ return;
231
+ }
232
+ onRelationConnect(options.find((opt) => opt.id === relationId));
233
+ updatedRelationsWith.current = 'onChange';
234
+ }}
235
+ onTextValueChange={(text) => {
236
+ setTextValue(text);
237
+ }}
238
+ onInputChange={(event) => {
239
+ onSearch(event.currentTarget.value);
240
+ }}
241
+ >
242
+ {options.map((opt) => {
243
+ return <Option key={opt.id} {...opt} />;
244
+ })}
245
+ </Combobox>
246
+ {shouldDisplayLoadMoreButton && (
247
+ <TextButton
248
+ disabled={paginatedRelations.isLoading || paginatedRelations.isFetchingNextPage}
249
+ onClick={handleLoadMore}
250
+ loading={paginatedRelations.isLoading || paginatedRelations.isFetchingNextPage}
251
+ startIcon={<Refresh />}
252
+ >
253
+ {labelLoadMore}
254
+ </TextButton>
366
255
  )}
367
- </Relation>
368
- </Field>
256
+ </Flex>
257
+ {relations.length > 0 && (
258
+ <RelationList overflow={overflow}>
259
+ <VisuallyHidden id={ariaDescriptionId}>{listAriaDescription}</VisuallyHidden>
260
+ <VisuallyHidden aria-live="assertive">{liveText}</VisuallyHidden>
261
+ <List
262
+ height={dynamicListHeight}
263
+ ref={listRef}
264
+ outerRef={outerListRef}
265
+ itemCount={totalNumberOfRelations}
266
+ itemSize={RELATION_ITEM_HEIGHT + RELATION_GUTTER}
267
+ itemData={{
268
+ name,
269
+ ariaDescribedBy: ariaDescriptionId,
270
+ canDrag: canReorder,
271
+ disabled,
272
+ handleCancel: onCancel,
273
+ handleDropItem: onDropItem,
274
+ handleGrabItem: onGrabItem,
275
+ iconButtonAriaLabel,
276
+ labelDisconnectRelation,
277
+ onRelationDisconnect,
278
+ publicationStateTranslations,
279
+ relations,
280
+ updatePositionOfRelation: handleUpdatePositionOfRelation,
281
+ }}
282
+ itemKey={(index) => `${relations[index].mainField}_${relations[index].id}`}
283
+ innerElementType="ol"
284
+ >
285
+ {ListItem}
286
+ </List>
287
+ </RelationList>
288
+ )}
289
+ </Flex>
369
290
  );
370
291
  };
371
292
 
@@ -1,10 +1,9 @@
1
1
  import React from 'react';
2
2
 
3
- import { Flex, Typography } from '@strapi/design-system';
3
+ import { Flex, Typography, ComboboxOption } from '@strapi/design-system';
4
4
  import { pxToRem } from '@strapi/helper-plugin';
5
5
  import PropTypes from 'prop-types';
6
6
  import { useIntl } from 'react-intl';
7
- import { components } from 'react-select';
8
7
  import styled from 'styled-components';
9
8
 
10
9
  import { getTrad } from '../../../utils';
@@ -19,10 +18,8 @@ const StyledBullet = styled.div`
19
18
  border-radius: 50%;
20
19
  `;
21
20
 
22
- export const Option = (props) => {
21
+ export const Option = ({ publicationState, mainField, id }) => {
23
22
  const { formatMessage } = useIntl();
24
- const Component = components.Option;
25
- const { publicationState, mainField, id } = props.data;
26
23
 
27
24
  if (publicationState) {
28
25
  const isDraft = publicationState === 'draft';
@@ -37,24 +34,29 @@ export const Option = (props) => {
37
34
  const title = isDraft ? formatMessage(draftMessage) : formatMessage(publishedMessage);
38
35
 
39
36
  return (
40
- <Component {...props}>
37
+ <ComboboxOption value={id} textValue={mainField ?? id}>
41
38
  <Flex>
42
39
  <StyledBullet title={title} isDraft={isDraft} />
43
40
  <Typography ellipsis>{mainField ?? id}</Typography>
44
41
  </Flex>
45
- </Component>
42
+ </ComboboxOption>
46
43
  );
47
44
  }
48
45
 
49
- return <Component {...props}>{mainField ?? id}</Component>;
46
+ return (
47
+ <ComboboxOption value={id} textValue={mainField ?? id}>
48
+ {mainField ?? id}
49
+ </ComboboxOption>
50
+ );
51
+ };
52
+
53
+ Option.defaultProps = {
54
+ mainField: undefined,
55
+ publicationState: undefined,
50
56
  };
51
57
 
52
58
  Option.propTypes = {
53
- isFocused: PropTypes.bool.isRequired,
54
- data: PropTypes.shape({
55
- id: PropTypes.number.isRequired,
56
- isDraft: PropTypes.bool,
57
- mainField: PropTypes.string,
58
- publicationState: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
59
- }).isRequired,
59
+ id: PropTypes.number.isRequired,
60
+ mainField: PropTypes.string,
61
+ publicationState: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
60
62
  };
@@ -6,8 +6,8 @@ import styled from 'styled-components';
6
6
 
7
7
  const ShadowBox = styled(Box)`
8
8
  position: relative;
9
- overflow-x: hidden;
10
- overflow-y: auto;
9
+ overflow: hidden;
10
+ flex: 1;
11
11
 
12
12
  &:before,
13
13
  &:after {