@strapi/content-manager 0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393 → 0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834

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 (113) hide show
  1. package/dist/admin/chunks/{ComponentConfigurationPage-Bn-SMKJG.js → ComponentConfigurationPage-B-gE3kXG.js} +5 -6
  2. package/dist/admin/chunks/{ComponentConfigurationPage-Bn-SMKJG.js.map → ComponentConfigurationPage-B-gE3kXG.js.map} +1 -1
  3. package/dist/admin/chunks/{ComponentConfigurationPage-Cqi5KqZa.mjs → ComponentConfigurationPage-R5N6EwIp.mjs} +5 -6
  4. package/dist/admin/chunks/{ComponentConfigurationPage-Cqi5KqZa.mjs.map → ComponentConfigurationPage-R5N6EwIp.mjs.map} +1 -1
  5. package/dist/admin/chunks/{EditConfigurationPage-Dm16gciL.mjs → EditConfigurationPage-0y9O2nBU.mjs} +5 -6
  6. package/dist/admin/chunks/{EditConfigurationPage-Dm16gciL.mjs.map → EditConfigurationPage-0y9O2nBU.mjs.map} +1 -1
  7. package/dist/admin/chunks/{EditConfigurationPage-CRxsqOhS.js → EditConfigurationPage-C62WuGTf.js} +5 -6
  8. package/dist/admin/chunks/{EditConfigurationPage-CRxsqOhS.js.map → EditConfigurationPage-C62WuGTf.js.map} +1 -1
  9. package/dist/admin/chunks/{EditViewPage-Dk8CeS40.js → EditViewPage-CiYAHBOX.js} +102 -95
  10. package/dist/admin/chunks/EditViewPage-CiYAHBOX.js.map +1 -0
  11. package/dist/admin/chunks/{EditViewPage-eTCSh2HB.mjs → EditViewPage-CkO2YLdg.mjs} +102 -95
  12. package/dist/admin/chunks/EditViewPage-CkO2YLdg.mjs.map +1 -0
  13. package/dist/admin/chunks/{Form-PB1sNax8.js → Form-DUs6lQ0C.js} +5 -5
  14. package/dist/admin/chunks/{Form-PB1sNax8.js.map → Form-DUs6lQ0C.js.map} +1 -1
  15. package/dist/admin/chunks/{Form-K_hq8zU4.mjs → Form-Db9A3cMO.mjs} +3 -3
  16. package/dist/admin/chunks/{Form-K_hq8zU4.mjs.map → Form-Db9A3cMO.mjs.map} +1 -1
  17. package/dist/admin/chunks/{History-CD5uVchr.mjs → History-BQ7IAJjV.mjs} +16 -12
  18. package/dist/admin/chunks/History-BQ7IAJjV.mjs.map +1 -0
  19. package/dist/admin/chunks/{History-CfsF-U-3.js → History-D99wxPry.js} +17 -13
  20. package/dist/admin/chunks/History-D99wxPry.js.map +1 -0
  21. package/dist/admin/chunks/{Input-grmHplxs.mjs → Input-CHDnpU3S.mjs} +1340 -55
  22. package/dist/admin/chunks/Input-CHDnpU3S.mjs.map +1 -0
  23. package/dist/admin/chunks/{Input-CU93J6dl.js → Input-Gop65dq6.js} +1352 -64
  24. package/dist/admin/chunks/Input-Gop65dq6.js.map +1 -0
  25. package/dist/admin/chunks/{ListConfigurationPage-Eo8txFp0.mjs → ListConfigurationPage-Bte99c0c.mjs} +4 -5
  26. package/dist/admin/chunks/{ListConfigurationPage-Eo8txFp0.mjs.map → ListConfigurationPage-Bte99c0c.mjs.map} +1 -1
  27. package/dist/admin/chunks/{ListConfigurationPage-nZti--Mw.js → ListConfigurationPage-pAdM7Lbn.js} +6 -7
  28. package/dist/admin/chunks/{ListConfigurationPage-nZti--Mw.js.map → ListConfigurationPage-pAdM7Lbn.js.map} +1 -1
  29. package/dist/admin/chunks/{ListViewPage-BBX-zSka.mjs → ListViewPage-7RTPaDs2.mjs} +3 -5
  30. package/dist/admin/chunks/ListViewPage-7RTPaDs2.mjs.map +1 -0
  31. package/dist/admin/chunks/{ListViewPage-DQYvHCxn.js → ListViewPage-CaBwwCVc.js} +7 -9
  32. package/dist/admin/chunks/ListViewPage-CaBwwCVc.js.map +1 -0
  33. package/dist/admin/chunks/{NoContentTypePage-C-rbOQO1.mjs → NoContentTypePage-CuTk3q_I.mjs} +2 -2
  34. package/dist/admin/chunks/{NoContentTypePage-C-rbOQO1.mjs.map → NoContentTypePage-CuTk3q_I.mjs.map} +1 -1
  35. package/dist/admin/chunks/{NoContentTypePage-ChYgz3sN.js → NoContentTypePage-DLD28j4F.js} +2 -2
  36. package/dist/admin/chunks/{NoContentTypePage-ChYgz3sN.js.map → NoContentTypePage-DLD28j4F.js.map} +1 -1
  37. package/dist/admin/chunks/{NoPermissionsPage-CuxrInhz.mjs → NoPermissionsPage-DSIlPmvv.mjs} +2 -2
  38. package/dist/admin/chunks/{NoPermissionsPage-CuxrInhz.mjs.map → NoPermissionsPage-DSIlPmvv.mjs.map} +1 -1
  39. package/dist/admin/chunks/{NoPermissionsPage-H4SAlJeF.js → NoPermissionsPage-iVMEcUp0.js} +2 -2
  40. package/dist/admin/chunks/{NoPermissionsPage-H4SAlJeF.js.map → NoPermissionsPage-iVMEcUp0.js.map} +1 -1
  41. package/dist/admin/chunks/{Preview-HqnNXn4S.mjs → Preview-35wsOM_p.mjs} +136 -211
  42. package/dist/admin/chunks/Preview-35wsOM_p.mjs.map +1 -0
  43. package/dist/admin/chunks/{Preview-Bz2dgOiw.js → Preview-CSU1sCSK.js} +134 -209
  44. package/dist/admin/chunks/Preview-CSU1sCSK.js.map +1 -0
  45. package/dist/admin/chunks/{en-CImiNxXE.mjs → en-C2zEwS3-.mjs} +4 -1
  46. package/dist/admin/chunks/{en-CImiNxXE.mjs.map → en-C2zEwS3-.mjs.map} +1 -1
  47. package/dist/admin/chunks/{en-CLf4SuMQ.js → en-G976DLsg.js} +4 -1
  48. package/dist/admin/chunks/{en-CLf4SuMQ.js.map → en-G976DLsg.js.map} +1 -1
  49. package/dist/admin/chunks/{index-DfX0uEQT.js → index-Cmh0Byay.js} +213 -129
  50. package/dist/admin/chunks/index-Cmh0Byay.js.map +1 -0
  51. package/dist/admin/chunks/{index-CS_nLuw2.mjs → index-DFvqTQvr.mjs} +212 -131
  52. package/dist/admin/chunks/index-DFvqTQvr.mjs.map +1 -0
  53. package/dist/admin/chunks/{layout-B4Uk0v1z.js → layout-DuH1v82S.js} +86 -13
  54. package/dist/admin/chunks/layout-DuH1v82S.js.map +1 -0
  55. package/dist/admin/chunks/{layout-BInXGFmo.mjs → layout-zQ9o6rg0.mjs} +78 -5
  56. package/dist/admin/chunks/layout-zQ9o6rg0.mjs.map +1 -0
  57. package/dist/admin/chunks/{useDragAndDrop-gcqEJMnO.js → objects-BJTP843m.js} +73 -1
  58. package/dist/admin/chunks/objects-BJTP843m.js.map +1 -0
  59. package/dist/admin/chunks/{useDragAndDrop-HYwNDExe.mjs → objects-D2z-IJgu.mjs} +72 -2
  60. package/dist/admin/chunks/objects-D2z-IJgu.mjs.map +1 -0
  61. package/dist/admin/chunks/{relations-9C5dQI9e.js → usePrev-B_pceXQ5.js} +18 -2
  62. package/dist/admin/chunks/usePrev-B_pceXQ5.js.map +1 -0
  63. package/dist/admin/chunks/{relations-CwL0ThH9.mjs → usePrev-CJFOGBK2.mjs} +18 -4
  64. package/dist/admin/chunks/usePrev-CJFOGBK2.mjs.map +1 -0
  65. package/dist/admin/chunks/{zh-Hans-CI0HKio3.mjs → zh-Hans-DEAhqI3x.mjs} +3 -2
  66. package/dist/admin/chunks/{zh-Hans-CI0HKio3.mjs.map → zh-Hans-DEAhqI3x.mjs.map} +1 -1
  67. package/dist/admin/chunks/{zh-Hans-JVK9x7xr.js → zh-Hans-Djj7eGpO.js} +3 -2
  68. package/dist/admin/chunks/{zh-Hans-JVK9x7xr.js.map → zh-Hans-Djj7eGpO.js.map} +1 -1
  69. package/dist/admin/index.js +1 -1
  70. package/dist/admin/index.mjs +1 -1
  71. package/dist/admin/src/content-manager.d.ts +3 -0
  72. package/dist/admin/src/features/DocumentContext.d.ts +53 -0
  73. package/dist/admin/src/features/DocumentRBAC.d.ts +3 -2
  74. package/dist/admin/src/hooks/useDocument.d.ts +2 -0
  75. package/dist/admin/src/hooks/useDocumentActions.d.ts +1 -1
  76. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
  77. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/RelationModal.d.ts +8 -0
  78. package/dist/admin/src/pages/EditView/components/FormInputs/{Relations.d.ts → Relations/Relations.d.ts} +9 -4
  79. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +8 -3
  80. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +7 -4
  81. package/dist/admin/src/preview/components/PreviewHeader.d.ts +1 -2
  82. package/package.json +6 -6
  83. package/dist/admin/chunks/EditViewPage-Dk8CeS40.js.map +0 -1
  84. package/dist/admin/chunks/EditViewPage-eTCSh2HB.mjs.map +0 -1
  85. package/dist/admin/chunks/History-CD5uVchr.mjs.map +0 -1
  86. package/dist/admin/chunks/History-CfsF-U-3.js.map +0 -1
  87. package/dist/admin/chunks/Input-CU93J6dl.js.map +0 -1
  88. package/dist/admin/chunks/Input-grmHplxs.mjs.map +0 -1
  89. package/dist/admin/chunks/ListViewPage-BBX-zSka.mjs.map +0 -1
  90. package/dist/admin/chunks/ListViewPage-DQYvHCxn.js.map +0 -1
  91. package/dist/admin/chunks/Preview-Bz2dgOiw.js.map +0 -1
  92. package/dist/admin/chunks/Preview-HqnNXn4S.mjs.map +0 -1
  93. package/dist/admin/chunks/Relations-BMvL4yMN.mjs +0 -1291
  94. package/dist/admin/chunks/Relations-BMvL4yMN.mjs.map +0 -1
  95. package/dist/admin/chunks/Relations-CbCAt692.js +0 -1318
  96. package/dist/admin/chunks/Relations-CbCAt692.js.map +0 -1
  97. package/dist/admin/chunks/index-CS_nLuw2.mjs.map +0 -1
  98. package/dist/admin/chunks/index-DfX0uEQT.js.map +0 -1
  99. package/dist/admin/chunks/layout-B4Uk0v1z.js.map +0 -1
  100. package/dist/admin/chunks/layout-BInXGFmo.mjs.map +0 -1
  101. package/dist/admin/chunks/objects-C3EebVVe.js +0 -76
  102. package/dist/admin/chunks/objects-C3EebVVe.js.map +0 -1
  103. package/dist/admin/chunks/objects-wl73iEma.mjs +0 -73
  104. package/dist/admin/chunks/objects-wl73iEma.mjs.map +0 -1
  105. package/dist/admin/chunks/relations-9C5dQI9e.js.map +0 -1
  106. package/dist/admin/chunks/relations-CwL0ThH9.mjs.map +0 -1
  107. package/dist/admin/chunks/useDragAndDrop-HYwNDExe.mjs.map +0 -1
  108. package/dist/admin/chunks/useDragAndDrop-gcqEJMnO.js.map +0 -1
  109. package/dist/admin/chunks/usePrev-Bjw2dhmq.mjs +0 -18
  110. package/dist/admin/chunks/usePrev-Bjw2dhmq.mjs.map +0 -1
  111. package/dist/admin/chunks/usePrev-DIYl-IAL.js +0 -21
  112. package/dist/admin/chunks/usePrev-DIYl-IAL.js.map +0 -1
  113. package/dist/admin/src/preview/components/PreviewContent.d.ts +0 -3
@@ -6,7 +6,7 @@ var strapiAdmin = require('@strapi/admin/strapi-admin');
6
6
  var designSystem = require('@strapi/design-system');
7
7
  var Icons = require('@strapi/icons');
8
8
  var reactIntl = require('react-intl');
9
- var index = require('./index-DfX0uEQT.js');
9
+ var index = require('./index-Cmh0Byay.js');
10
10
  var styledComponents = require('styled-components');
11
11
  var slate = require('slate');
12
12
  var slateHistory = require('slate-history');
@@ -62,16 +62,15 @@ require('prismjs/components/prism-typescript');
62
62
  require('prismjs/components/prism-tsx');
63
63
  require('prismjs/components/prism-vbnet');
64
64
  require('prismjs/components/prism-yaml');
65
- var usePrev = require('./usePrev-DIYl-IAL.js');
66
- var useDragAndDrop = require('./useDragAndDrop-gcqEJMnO.js');
65
+ var usePrev = require('./usePrev-B_pceXQ5.js');
66
+ var objects = require('./objects-BJTP843m.js');
67
67
  var Toolbar = require('@radix-ui/react-toolbar');
68
68
  var reactDndHtml5Backend = require('react-dnd-html5-backend');
69
69
  var reactRouterDom = require('react-router-dom');
70
- var objects = require('./objects-C3EebVVe.js');
71
- var Relations = require('./Relations-CbCAt692.js');
72
70
  var pipe$1 = require('lodash/fp/pipe');
73
71
  var ComponentIcon = require('./ComponentIcon-C-EjOUPA.js');
74
- var relations = require('./relations-9C5dQI9e.js');
72
+ var fractionalIndexing = require('fractional-indexing');
73
+ var reactWindow = require('react-window');
75
74
  var CodeMirror = require('codemirror5');
76
75
  var sanitizeHtml = require('sanitize-html');
77
76
  var highlight_js = require('highlight.js');
@@ -1801,6 +1800,7 @@ const EditorToolbarObserver = ({ observedComponents, menuTriggerVariant = 'ghost
1801
1800
  maxHeight: "100%",
1802
1801
  minWidth: "256px",
1803
1802
  popoverPlacement: "bottom-end",
1803
+ zIndex: 2,
1804
1804
  children: observedComponents.slice(menuIndex).map((component)=>/*#__PURE__*/ jsxRuntime.jsx(React__namespace.Fragment, {
1805
1805
  children: component.menu
1806
1806
  }, component.key))
@@ -2428,8 +2428,8 @@ const DropPlaceholder = styledComponents.styled(designSystem.Box)`
2428
2428
 
2429
2429
  // Show drop placeholder 8px above or below the drop target
2430
2430
  ${({ dragDirection, theme, placeholderMargin })=>styledComponents.css`
2431
- top: ${dragDirection === useDragAndDrop.DIRECTIONS.UPWARD && `-${theme.spaces[placeholderMargin]}`};
2432
- bottom: ${dragDirection === useDragAndDrop.DIRECTIONS.DOWNWARD && `-${theme.spaces[placeholderMargin]}`};
2431
+ top: ${dragDirection === objects.DIRECTIONS.UPWARD && `-${theme.spaces[placeholderMargin]}`};
2432
+ bottom: ${dragDirection === objects.DIRECTIONS.DOWNWARD && `-${theme.spaces[placeholderMargin]}`};
2433
2433
  `}
2434
2434
  `;
2435
2435
  const DragItem = styledComponents.styled(designSystem.Flex)`
@@ -2513,8 +2513,8 @@ const DragAndDropElement = ({ children, index: index$1, setDragDirection, dragDi
2513
2513
  name1,
2514
2514
  setLiveText
2515
2515
  ]);
2516
- const [{ handlerId, isDragging, isOverDropTarget, direction }, blockRef, dropRef, dragRef] = useDragAndDrop.useDragAndDrop(!disabled, {
2517
- type: `${useDragAndDrop.ItemTypes.BLOCKS}_${name1}`,
2516
+ const [{ handlerId, isDragging, isOverDropTarget, direction }, blockRef, dropRef, dragRef] = objects.useDragAndDrop(!disabled, {
2517
+ type: `${objects.ItemTypes.BLOCKS}_${name1}`,
2518
2518
  index: index$1,
2519
2519
  item: {
2520
2520
  index: index$1,
@@ -3485,6 +3485,20 @@ const Initializer = ({ disabled, name, onClick })=>{
3485
3485
  });
3486
3486
  };
3487
3487
 
3488
+ /**
3489
+ * We use this component to wrap any individual component field in the Edit View,
3490
+ * this could be a component field in a dynamic zone, a component within a repeatable space,
3491
+ * or even nested components.
3492
+ *
3493
+ * We primarily need this to provide the component id to the components so that they can
3494
+ * correctly fetch their relations.
3495
+ */ const [ComponentProvider, useComponent] = strapiAdmin.createContext('ComponentContext', {
3496
+ id: undefined,
3497
+ level: -1,
3498
+ uid: undefined,
3499
+ type: undefined
3500
+ });
3501
+
3488
3502
  const AddComponentButton = ({ hasError, isDisabled, isOpen, children, onClick })=>{
3489
3503
  return /*#__PURE__*/ jsxRuntime.jsx(StyledButton, {
3490
3504
  type: "button",
@@ -3590,15 +3604,24 @@ const ComponentCategory = ({ category, components = [], variant = 'primary', onA
3590
3604
  const ResponsiveAccordionContent = styledComponents.styled(designSystem.Accordion.Content)`
3591
3605
  container-type: inline-size;
3592
3606
  `;
3593
- const Grid = styledComponents.styled(designSystem.Box)`
3594
- display: grid;
3595
- grid-template-columns: repeat(auto-fill, 100%);
3596
- grid-gap: ${({ theme })=>theme.spaces[1]};
3597
-
3598
- @container (min-width: ${()=>RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
3599
- grid-template-columns: repeat(auto-fill, 14rem);
3600
- }
3601
- `;
3607
+ /**
3608
+ * TODO:
3609
+ * JSDOM cannot handle container queries.
3610
+ * This is a temporary workaround so that tests do not fail in the CI when jestdom throws an error
3611
+ * for failing to parse the stylesheet.
3612
+ */ const Grid = process.env.NODE_ENV !== 'test' ? styledComponents.styled(designSystem.Box)`
3613
+ display: grid;
3614
+ grid-template-columns: repeat(auto-fill, 100%);
3615
+ grid-gap: 4px;
3616
+
3617
+ @container (min-width: ${()=>RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
3618
+ grid-template-columns: repeat(auto-fill, 14rem);
3619
+ }
3620
+ ` : styledComponents.styled(designSystem.Box)`
3621
+ display: grid;
3622
+ grid-template-columns: repeat(auto-fill, 100%);
3623
+ grid-gap: 4px;
3624
+ `;
3602
3625
  const ComponentBox = styledComponents.styled(designSystem.Flex)`
3603
3626
  color: ${({ theme })=>theme.colors.neutral600};
3604
3627
  cursor: pointer;
@@ -3663,7 +3686,19 @@ const ComponentPicker = ({ dynamicComponentsByCategory = {}, isOpen, onClickAddC
3663
3686
  const DynamicComponent = ({ componentUid, disabled, index: index$1, name, onRemoveComponentClick, onMoveComponent, onGrabItem, onDropItem, onCancel, dynamicComponentsByCategory = {}, onAddComponent, children })=>{
3664
3687
  const { formatMessage } = reactIntl.useIntl();
3665
3688
  const formValues = strapiAdmin.useForm('DynamicComponent', (state)=>state.values);
3666
- const { edit: { components } } = index.useDocLayout();
3689
+ const documentMeta = index.useDocumentContext('DynamicComponent', (state)=>state.meta);
3690
+ const rootDocumentMeta = index.useDocumentContext('DynamicComponent', (state)=>state.rootDocumentMeta);
3691
+ const { edit: { components: rootComponents } } = index.useDocumentLayout(rootDocumentMeta.model);
3692
+ const { edit: { components: relatedComponents } } = index.useDocumentLayout(documentMeta.model);
3693
+ // Merge the root level components and related components
3694
+ const components = React__namespace.useMemo(()=>({
3695
+ ...rootComponents,
3696
+ ...relatedComponents
3697
+ }), [
3698
+ rootComponents,
3699
+ relatedComponents
3700
+ ]);
3701
+ const document = index.useDocumentContext('DynamicComponent', (state)=>state.document);
3667
3702
  const title = React__namespace.useMemo(()=>{
3668
3703
  const { mainField } = components[componentUid]?.settings ?? {
3669
3704
  mainField: 'id'
@@ -3693,8 +3728,8 @@ const DynamicComponent = ({ componentUid, disabled, index: index$1, name, onRemo
3693
3728
  componentUid,
3694
3729
  dynamicComponentsByCategory
3695
3730
  ]);
3696
- const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop.useDragAndDrop(!disabled, {
3697
- type: `${useDragAndDrop.ItemTypes.DYNAMIC_ZONE}_${name}`,
3731
+ const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = objects.useDragAndDrop(!disabled, {
3732
+ type: `${objects.ItemTypes.DYNAMIC_ZONE}_${name}`,
3698
3733
  index: index$1,
3699
3734
  item: {
3700
3735
  index: index$1,
@@ -3895,9 +3930,11 @@ const DynamicComponent = ({ componentUid, disabled, index: index$1, name, onRemo
3895
3930
  alignItems: "stretch",
3896
3931
  children: children ? children({
3897
3932
  ...fieldWithTranslatedLabel,
3933
+ document,
3898
3934
  name: fieldName
3899
3935
  }) : /*#__PURE__*/ jsxRuntime.jsx(MemoizedInputRenderer, {
3900
3936
  ...fieldWithTranslatedLabel,
3937
+ document: document,
3901
3938
  name: fieldName
3902
3939
  })
3903
3940
  }, fieldName);
@@ -4015,7 +4052,8 @@ const DynamicZone = ({ attribute, disabled: disabledProp, hint, label, labelActi
4015
4052
  const { max = Infinity, min = -Infinity } = attribute ?? {};
4016
4053
  const [addComponentIsOpen, setAddComponentIsOpen] = React__namespace.useState(false);
4017
4054
  const [liveText, setLiveText] = React__namespace.useState('');
4018
- const { components, isLoading } = index.useDoc();
4055
+ const document = index.useDocumentContext('DynamicZone', (state)=>state.document);
4056
+ const { components, isLoading } = document;
4019
4057
  const disabled = disabledProp || isLoading;
4020
4058
  const { addFieldRow, removeFieldRow, moveFieldRow } = strapiAdmin.useForm('DynamicZone', ({ addFieldRow, removeFieldRow, moveFieldRow })=>({
4021
4059
  addFieldRow,
@@ -4143,7 +4181,7 @@ const DynamicZone = ({ attribute, disabled: disabledProp, hint, label, labelActi
4143
4181
  componentName: label || name
4144
4182
  });
4145
4183
  };
4146
- const level = Relations.useComponent('DynamicZone', (state)=>state.level);
4184
+ const level = useComponent('DynamicZone', (state)=>state.level);
4147
4185
  const ariaDescriptionId = React__namespace.useId();
4148
4186
  return /*#__PURE__*/ jsxRuntime.jsx(DynamicZoneProvider, {
4149
4187
  isInDynamicZone: true,
@@ -4175,7 +4213,7 @@ const DynamicZone = ({ attribute, disabled: disabledProp, hint, label, labelActi
4175
4213
  }),
4176
4214
  /*#__PURE__*/ jsxRuntime.jsx("ol", {
4177
4215
  "aria-describedby": ariaDescriptionId,
4178
- children: value.map((field, index)=>/*#__PURE__*/ jsxRuntime.jsx(Relations.ComponentProvider, {
4216
+ children: value.map((field, index)=>/*#__PURE__*/ jsxRuntime.jsx(ComponentProvider, {
4179
4217
  level: level + 1,
4180
4218
  uid: field.__component,
4181
4219
  // id is always a number in a dynamic zone.
@@ -4248,6 +4286,1241 @@ const NotAllowedInput = ({ hint, label, required, name })=>{
4248
4286
  });
4249
4287
  };
4250
4288
 
4289
+ function getCollectionType(url) {
4290
+ const regex = new RegExp(`(${index.COLLECTION_TYPES}|${index.SINGLE_TYPES})`);
4291
+ const match = url.match(regex);
4292
+ return match ? match[1] : undefined;
4293
+ }
4294
+ const CustomModalContent = styledComponents.styled(designSystem.Modal.Content)`
4295
+ width: 90%;
4296
+ max-width: 100%;
4297
+ height: 90%;
4298
+ max-height: 100%;
4299
+ `;
4300
+ const [RelationModalProvider, useRelationModal] = strapiAdmin.createContext('RelationModal', {
4301
+ parentModified: false,
4302
+ depth: 0
4303
+ });
4304
+ const RelationModalForm = ({ relation, triggerButtonLabel })=>{
4305
+ const navigate = reactRouterDom.useNavigate();
4306
+ const { pathname, search } = reactRouterDom.useLocation();
4307
+ const { formatMessage } = reactIntl.useIntl();
4308
+ const [triggerRefetchDocument] = index.useLazyGetDocumentQuery();
4309
+ const currentDocument = index.useDocumentContext('RelationModalForm', (state)=>state.document);
4310
+ const rootDocumentMeta = index.useDocumentContext('RelationModalForm', (state)=>state.rootDocumentMeta);
4311
+ const currentDocumentMeta = index.useDocumentContext('RelationModalForm', (state)=>state.meta);
4312
+ const changeDocument = index.useDocumentContext('RelationModalForm', (state)=>state.changeDocument);
4313
+ const documentHistory = index.useDocumentContext('RelationModalForm', (state)=>state.documentHistory);
4314
+ const setDocumentHistory = index.useDocumentContext('RelationModalForm', (state)=>state.setDocumentHistory);
4315
+ const [isConfirmationOpen, setIsConfirmationOpen] = React__namespace.useState(false);
4316
+ const [actionPosition, setActionPosition] = React__namespace.useState('cancel');
4317
+ const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
4318
+ // NOTE: Not sure about this relation modal context, maybe we should move this to DocumentContext?
4319
+ // Get parent modal context if it exists
4320
+ const parentContext = useRelationModal('RelationModalForm', (state)=>state);
4321
+ // Get depth of nested modals
4322
+ const depth = parentContext ? parentContext.depth + 1 : 0;
4323
+ // Check if this is a nested modal
4324
+ const isNested = depth > 0;
4325
+ const addDocumentToHistory = (document)=>setDocumentHistory((prev)=>[
4326
+ ...prev,
4327
+ document
4328
+ ]);
4329
+ const getPreviousDocument = ()=>{
4330
+ if (documentHistory.length === 0) return undefined;
4331
+ const lastDocument = documentHistory[documentHistory.length - 1];
4332
+ return lastDocument;
4333
+ };
4334
+ const removeLastDocumentFromHistory = ()=>{
4335
+ setDocumentHistory((prev)=>[
4336
+ ...prev
4337
+ ].slice(0, prev.length - 1));
4338
+ };
4339
+ const handleToggleModal = ()=>{
4340
+ if (isModalOpen) {
4341
+ setIsModalOpen(false);
4342
+ const document = {
4343
+ collectionType: rootDocumentMeta.collectionType,
4344
+ model: rootDocumentMeta.model,
4345
+ documentId: rootDocumentMeta.documentId
4346
+ };
4347
+ // Change back to the root document
4348
+ changeDocument(document);
4349
+ // Reset the document history
4350
+ setDocumentHistory([]);
4351
+ // Reset action position
4352
+ setActionPosition('cancel');
4353
+ // Read from cache or refetch root document
4354
+ triggerRefetchDocument(document, // Favor the cache
4355
+ true);
4356
+ } else {
4357
+ changeDocument(relation);
4358
+ setIsModalOpen(true);
4359
+ }
4360
+ };
4361
+ const getFullPageLink = ()=>{
4362
+ const isSingleType = currentDocumentMeta.collectionType === index.SINGLE_TYPES;
4363
+ const queryParams = currentDocumentMeta.params?.locale ? `?plugins[i18n][locale]=${currentDocumentMeta.params.locale}` : '';
4364
+ return `/content-manager/${currentDocumentMeta.collectionType}/${currentDocumentMeta.model}${isSingleType ? '' : '/' + currentDocumentMeta.documentId}${queryParams}`;
4365
+ };
4366
+ const handleRedirection = ()=>{
4367
+ const editViewUrl = `${pathname}${search}`;
4368
+ const isRootDocumentUrl = editViewUrl.includes(getFullPageLink());
4369
+ if (isRootDocumentUrl) {
4370
+ handleToggleModal();
4371
+ } else {
4372
+ navigate(getFullPageLink());
4373
+ }
4374
+ };
4375
+ const handleConfirm = ()=>{
4376
+ if (actionPosition === 'navigate') {
4377
+ handleRedirection();
4378
+ } else if (actionPosition === 'back') {
4379
+ const previousRelation = getPreviousDocument();
4380
+ if (previousRelation) {
4381
+ removeLastDocumentFromHistory();
4382
+ changeDocument(previousRelation);
4383
+ }
4384
+ } else {
4385
+ // Add current relation to history before opening a new one in case we are opening a new one
4386
+ if (currentDocumentMeta && Object.keys(currentDocumentMeta).length > 0) {
4387
+ addDocumentToHistory(currentDocumentMeta);
4388
+ }
4389
+ handleToggleModal();
4390
+ }
4391
+ };
4392
+ return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Form, {
4393
+ method: "PUT",
4394
+ initialValues: currentDocument.getInitialFormValues(),
4395
+ validate: (values, options)=>{
4396
+ const yupSchema = index.createYupSchema(currentDocument.schema?.attributes, currentDocument.components, {
4397
+ status: currentDocument.document?.status,
4398
+ ...options
4399
+ });
4400
+ return yupSchema.validate(values, {
4401
+ abortEarly: false
4402
+ });
4403
+ },
4404
+ children: ({ modified, isSubmitting, resetForm })=>{
4405
+ // We don't count the root document, so history starts after 1
4406
+ const hasHistory = documentHistory.length > 1;
4407
+ return /*#__PURE__*/ jsxRuntime.jsxs(RelationModalProvider, {
4408
+ parentModified: modified,
4409
+ depth: depth,
4410
+ children: [
4411
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Root, {
4412
+ open: isModalOpen,
4413
+ onOpenChange: ()=>{
4414
+ if (isModalOpen) {
4415
+ if (modified && !isSubmitting) {
4416
+ setIsConfirmationOpen(true);
4417
+ } else {
4418
+ handleToggleModal();
4419
+ }
4420
+ }
4421
+ },
4422
+ children: [
4423
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Trigger, {
4424
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
4425
+ description: triggerButtonLabel,
4426
+ children: /*#__PURE__*/ jsxRuntime.jsx(CustomTextButton, {
4427
+ onClick: ()=>{
4428
+ // Check if parent modal has unsaved changes
4429
+ if (isNested && parentContext.parentModified) {
4430
+ setIsConfirmationOpen(true);
4431
+ // Return early to avoid opening the modal
4432
+ return;
4433
+ } else {
4434
+ if (modified && !isSubmitting) {
4435
+ setIsConfirmationOpen(true);
4436
+ } else {
4437
+ // Add current relation to history before opening a new one
4438
+ if (currentDocumentMeta && Object.keys(currentDocumentMeta).length > 0) {
4439
+ addDocumentToHistory(currentDocumentMeta);
4440
+ }
4441
+ handleToggleModal();
4442
+ }
4443
+ if (!isModalOpen) {
4444
+ setIsModalOpen(true);
4445
+ }
4446
+ }
4447
+ },
4448
+ width: "100%",
4449
+ children: triggerButtonLabel
4450
+ })
4451
+ })
4452
+ }),
4453
+ /*#__PURE__*/ jsxRuntime.jsxs(CustomModalContent, {
4454
+ children: [
4455
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
4456
+ gap: 2,
4457
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
4458
+ justifyContent: "space-between",
4459
+ alignItems: "center",
4460
+ width: "100%",
4461
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
4462
+ gap: 2,
4463
+ children: [
4464
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
4465
+ withTooltip: false,
4466
+ label: "Back",
4467
+ variant: "ghost",
4468
+ disabled: !hasHistory,
4469
+ onClick: ()=>{
4470
+ setActionPosition('back');
4471
+ if (modified && !isSubmitting) {
4472
+ setIsConfirmationOpen(true);
4473
+ } else {
4474
+ const previousRelation = getPreviousDocument();
4475
+ if (previousRelation) {
4476
+ removeLastDocumentFromHistory();
4477
+ changeDocument(previousRelation);
4478
+ }
4479
+ }
4480
+ },
4481
+ marginRight: 1,
4482
+ children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowLeft, {})
4483
+ }),
4484
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
4485
+ tag: "span",
4486
+ fontWeight: 600,
4487
+ children: formatMessage({
4488
+ id: 'content-manager.components.RelationInputModal.modal-title',
4489
+ defaultMessage: 'Edit a relation'
4490
+ })
4491
+ })
4492
+ ]
4493
+ })
4494
+ })
4495
+ }),
4496
+ /*#__PURE__*/ jsxRuntime.jsx(RelationModalBody, {
4497
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
4498
+ onClick: ()=>{
4499
+ setActionPosition('navigate');
4500
+ if (modified && !isSubmitting) {
4501
+ setIsConfirmationOpen(true);
4502
+ } else {
4503
+ navigate(getFullPageLink());
4504
+ }
4505
+ },
4506
+ variant: "tertiary",
4507
+ label: formatMessage({
4508
+ id: 'content-manager.components.RelationInputModal.button-fullpage',
4509
+ defaultMessage: 'Go to entry'
4510
+ }),
4511
+ children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowsOut, {})
4512
+ })
4513
+ }),
4514
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Footer, {
4515
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
4516
+ onClick: ()=>{
4517
+ if (modified && !isSubmitting) {
4518
+ setIsConfirmationOpen(true);
4519
+ } else {
4520
+ handleToggleModal();
4521
+ }
4522
+ },
4523
+ variant: "tertiary",
4524
+ children: formatMessage({
4525
+ id: 'app.components.Button.cancel',
4526
+ defaultMessage: 'Cancel'
4527
+ })
4528
+ })
4529
+ })
4530
+ ]
4531
+ })
4532
+ ]
4533
+ }),
4534
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Root, {
4535
+ open: isConfirmationOpen,
4536
+ onOpenChange: setIsConfirmationOpen,
4537
+ children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.ConfirmDialog, {
4538
+ onConfirm: ()=>{
4539
+ handleConfirm();
4540
+ setIsConfirmationOpen(false);
4541
+ resetForm();
4542
+ },
4543
+ onCancel: ()=>{
4544
+ setIsConfirmationOpen(false);
4545
+ },
4546
+ variant: "danger",
4547
+ children: formatMessage({
4548
+ id: 'content-manager.components.RelationInputModal.confirmation-message',
4549
+ defaultMessage: 'Some changes were not saved. Are you sure you want to close this relation? All changes that were not saved will be lost.'
4550
+ })
4551
+ })
4552
+ })
4553
+ ]
4554
+ });
4555
+ }
4556
+ });
4557
+ };
4558
+ const CustomTextButton = styledComponents.styled(designSystem.TextButton)`
4559
+ & > span {
4560
+ font-size: ${({ theme })=>theme.fontSizes[2]};
4561
+ width: inherit;
4562
+ overflow: hidden;
4563
+ white-space: nowrap;
4564
+ text-overflow: ellipsis;
4565
+ }
4566
+ `;
4567
+ const RelationModalBody = ({ children })=>{
4568
+ const { formatMessage } = reactIntl.useIntl();
4569
+ const documentMeta = index.useDocumentContext('RelationModalBody', (state)=>state.meta);
4570
+ const documentResponse = index.useDocumentContext('RelationModalBody', (state)=>state.document);
4571
+ const onPreview = index.useDocumentContext('RelationModalBody', (state)=>state.onPreview);
4572
+ const documentLayoutResponse = index.useDocumentLayout(documentMeta.model);
4573
+ const plugins = strapiAdmin.useStrapiApp('RelationModalBody', (state)=>state.plugins);
4574
+ const initialValues = documentResponse.getInitialFormValues();
4575
+ const { permissions = [], isLoading: isLoadingPermissions, error } = strapiAdmin.useRBAC(index.PERMISSIONS.map((action)=>({
4576
+ action,
4577
+ subject: documentMeta.model
4578
+ })));
4579
+ const isLoading = isLoadingPermissions || documentLayoutResponse.isLoading || documentResponse.isLoading;
4580
+ if (isLoading && !documentResponse.document?.documentId) {
4581
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
4582
+ small: true,
4583
+ children: formatMessage({
4584
+ id: 'content-manager.ListViewTable.relation-loading',
4585
+ defaultMessage: 'Relations are loading'
4586
+ })
4587
+ });
4588
+ }
4589
+ if (error || !documentMeta.model || documentLayoutResponse.error || !documentResponse.document || !documentResponse.meta || !documentResponse.schema || !initialValues) {
4590
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
4591
+ alignItems: "center",
4592
+ height: "100%",
4593
+ justifyContent: "center",
4594
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.EmptyStateLayout, {
4595
+ icon: /*#__PURE__*/ jsxRuntime.jsx(Icons.WarningCircle, {
4596
+ width: "16rem"
4597
+ }),
4598
+ content: formatMessage({
4599
+ id: 'anErrorOccurred',
4600
+ defaultMessage: 'Whoops! Something went wrong. Please, try again.'
4601
+ })
4602
+ })
4603
+ });
4604
+ }
4605
+ const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);
4606
+ const hasDraftAndPublished = documentResponse.schema?.options?.draftAndPublish ?? false;
4607
+ const props = {
4608
+ activeTab: 'draft',
4609
+ collectionType: documentMeta.collectionType,
4610
+ model: documentMeta.model,
4611
+ documentId: documentMeta.documentId,
4612
+ document: documentResponse.document,
4613
+ meta: documentResponse.meta,
4614
+ onPreview,
4615
+ fromRelationModal: true,
4616
+ fromPreview: onPreview !== undefined
4617
+ };
4618
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
4619
+ children: /*#__PURE__*/ jsxRuntime.jsxs(index.DocumentRBAC, {
4620
+ permissions: permissions,
4621
+ model: documentMeta.model,
4622
+ children: [
4623
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
4624
+ alignItems: "flex-start",
4625
+ direction: "column",
4626
+ gap: 2,
4627
+ children: [
4628
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
4629
+ width: "100%",
4630
+ justifyContent: "space-between",
4631
+ gap: 2,
4632
+ children: [
4633
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
4634
+ tag: "h2",
4635
+ variant: "alpha",
4636
+ children: documentTitle
4637
+ }),
4638
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
4639
+ gap: 2,
4640
+ children: [
4641
+ children,
4642
+ /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.DescriptionComponentRenderer, {
4643
+ props: props,
4644
+ descriptions: plugins['content-manager'].apis.getDocumentActions('relation-modal'),
4645
+ children: (actions)=>{
4646
+ const filteredActions = actions.filter((action)=>{
4647
+ return [
4648
+ action.position
4649
+ ].flat().includes('relation-modal');
4650
+ });
4651
+ const [primaryAction, secondaryAction] = filteredActions;
4652
+ if (!primaryAction && !secondaryAction) return null;
4653
+ // Both actions are available when draft and publish enabled
4654
+ if (primaryAction && secondaryAction) {
4655
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
4656
+ children: [
4657
+ /*#__PURE__*/ jsxRuntime.jsx(index.DocumentActionButton, {
4658
+ ...secondaryAction,
4659
+ variant: secondaryAction.variant || 'secondary'
4660
+ }),
4661
+ /*#__PURE__*/ jsxRuntime.jsx(index.DocumentActionButton, {
4662
+ ...primaryAction,
4663
+ variant: primaryAction.variant || 'default'
4664
+ })
4665
+ ]
4666
+ });
4667
+ }
4668
+ // Otherwise we just have the save action
4669
+ return /*#__PURE__*/ jsxRuntime.jsx(index.DocumentActionButton, {
4670
+ ...primaryAction,
4671
+ variant: primaryAction.variant || 'secondary'
4672
+ });
4673
+ }
4674
+ })
4675
+ ]
4676
+ })
4677
+ ]
4678
+ }),
4679
+ hasDraftAndPublished ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
4680
+ children: /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
4681
+ status: documentResponse.document?.status
4682
+ })
4683
+ }) : null
4684
+ ]
4685
+ }),
4686
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
4687
+ flex: 1,
4688
+ overflow: "auto",
4689
+ alignItems: "stretch",
4690
+ paddingTop: 7,
4691
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
4692
+ overflow: "auto",
4693
+ flex: 1,
4694
+ children: /*#__PURE__*/ jsxRuntime.jsx(FormLayout, {
4695
+ layout: documentLayoutResponse.edit.layout,
4696
+ document: documentResponse,
4697
+ hasBackground: false
4698
+ })
4699
+ })
4700
+ })
4701
+ ]
4702
+ })
4703
+ });
4704
+ };
4705
+
4706
+ /**
4707
+ * Remove a relation, whether it's been already saved or not.
4708
+ * It's used both in RelationsList, where the "remove relation" button is, and in the input,
4709
+ * because we sometimes need to remove a previous relation when selecting a new one.
4710
+ */ function useHandleDisconnect(fieldName, consumerName) {
4711
+ const field = strapiAdmin.useField(fieldName);
4712
+ const removeFieldRow = strapiAdmin.useForm(consumerName, (state)=>state.removeFieldRow);
4713
+ const addFieldRow = strapiAdmin.useForm(consumerName, (state)=>state.addFieldRow);
4714
+ const handleDisconnect = (relation)=>{
4715
+ if (field.value && field.value.connect) {
4716
+ /**
4717
+ * A relation will exist in the `connect` array _if_ it has
4718
+ * been added without saving. In this case, we just remove it
4719
+ * from the connect array
4720
+ */ const indexOfRelationInConnectArray = field.value.connect.findIndex((rel)=>rel.id === relation.id);
4721
+ if (indexOfRelationInConnectArray >= 0) {
4722
+ removeFieldRow(`${fieldName}.connect`, indexOfRelationInConnectArray);
4723
+ return;
4724
+ }
4725
+ }
4726
+ addFieldRow(`${fieldName}.disconnect`, {
4727
+ id: relation.id,
4728
+ apiData: {
4729
+ id: relation.id,
4730
+ documentId: relation.documentId,
4731
+ locale: relation.locale
4732
+ }
4733
+ });
4734
+ };
4735
+ return handleDisconnect;
4736
+ }
4737
+ /* -------------------------------------------------------------------------------------------------
4738
+ * RelationsField
4739
+ * -----------------------------------------------------------------------------------------------*/ const RELATIONS_TO_DISPLAY = 5;
4740
+ const ONE_WAY_RELATIONS = [
4741
+ 'oneWay',
4742
+ 'oneToOne',
4743
+ 'manyToOne',
4744
+ 'oneToManyMorph',
4745
+ 'oneToOneMorph'
4746
+ ];
4747
+ /**
4748
+ * TODO: we get a rather ugly flash when we remove a single relation from the list leaving
4749
+ * no other relations when we press save. The initial relation re-renders, probably because
4750
+ * of the lag in the Form cleaning it's "disconnect" array, whilst our data has not been invalidated.
4751
+ *
4752
+ * Could we invalidate relation data on the document actions? Should we?
4753
+ */ /**
4754
+ * @internal
4755
+ * @description The relations field holds a lot of domain logic for handling relations which is rather complicated
4756
+ * At present we do not expose this to plugin developers, however, they are able to overwrite it themselves should
4757
+ * they wish to do so.
4758
+ */ const RelationsField = /*#__PURE__*/ React__namespace.forwardRef(({ disabled, label, ...props }, ref)=>{
4759
+ const currentDocumentMeta = index.useDocumentContext('RelationsField', (state)=>state.meta);
4760
+ const currentDocument = index.useDocumentContext('RelationsField', (state)=>state.document);
4761
+ const rootDocumentMeta = index.useDocumentContext('RelationsField', (state)=>state.rootDocumentMeta);
4762
+ const [currentPage, setCurrentPage] = React__namespace.useState(1);
4763
+ const isRootDocument = rootDocumentMeta.documentId === currentDocumentMeta.documentId;
4764
+ const documentMeta = isRootDocument ? rootDocumentMeta : currentDocumentMeta;
4765
+ // Use the documentId from the actual document, not the params (meta)
4766
+ const documentId = currentDocument.document?.documentId;
4767
+ const { formatMessage } = reactIntl.useIntl();
4768
+ const [{ query }] = strapiAdmin.useQueryParams();
4769
+ const params = documentMeta.params ?? index.buildValidParams(query);
4770
+ const isMorph = props.attribute.relation.toLowerCase().includes('morph');
4771
+ const isDisabled = isMorph || disabled;
4772
+ const { componentId, componentUID } = useComponent('RelationsField', ({ uid, id })=>({
4773
+ componentId: id,
4774
+ componentUID: uid
4775
+ }));
4776
+ const isSubmitting = strapiAdmin.useForm('RelationsList', (state)=>state.isSubmitting);
4777
+ React__namespace.useEffect(()=>{
4778
+ setCurrentPage(1);
4779
+ }, [
4780
+ isSubmitting
4781
+ ]);
4782
+ const component = componentUID && currentDocument.components[componentUID];
4783
+ /**
4784
+ * We'll always have a documentId in a created entry, so we look for a componentId first.
4785
+ * Same with `uid` and `documentModel`.
4786
+ */ const model = component ? component.uid : documentMeta.model;
4787
+ const id = component && componentId ? componentId.toString() : documentId;
4788
+ /**
4789
+ * The `name` prop is a complete path to the field, e.g. `field1.field2.field3`.
4790
+ * Where the above example would a nested field within two components, however
4791
+ * we only require the field on the component not the complete path since we query
4792
+ * individual components. Therefore we split the string and take the last item.
4793
+ */ const [targetField] = props.name.split('.').slice(-1);
4794
+ const schemaAttributes = component ? component.attributes ?? {} : currentDocument.schema?.attributes ?? {};
4795
+ /**
4796
+ * Confirm the target field is related to the current document.
4797
+ * Since relations can exist in a modal on top of the root document,
4798
+ * we need to ensure we are fetching relations for the correct document (root document vs related document),
4799
+ */ const isRelatedToCurrentDocument = Object.values(schemaAttributes).filter((attribute)=>attribute.type === 'relation' && 'target' in attribute && 'target' in props.attribute && attribute.target === props.attribute.target).length > 0;
4800
+ const { data, isLoading, isFetching } = usePrev.useGetRelationsQuery({
4801
+ model,
4802
+ targetField,
4803
+ // below we don't run the query if there is no id.
4804
+ id,
4805
+ params: {
4806
+ ...params,
4807
+ pageSize: RELATIONS_TO_DISPLAY,
4808
+ page: currentPage
4809
+ }
4810
+ }, {
4811
+ refetchOnMountOrArgChange: true,
4812
+ skip: !id || !isRelatedToCurrentDocument,
4813
+ selectFromResult: (result)=>{
4814
+ return {
4815
+ ...result,
4816
+ data: {
4817
+ ...result.data,
4818
+ results: result.data?.results ? result.data.results : []
4819
+ }
4820
+ };
4821
+ }
4822
+ });
4823
+ const handleLoadMore = ()=>{
4824
+ setCurrentPage((prev)=>prev + 1);
4825
+ };
4826
+ const field = strapiAdmin.useField(props.name);
4827
+ const isFetchingMoreRelations = isLoading || isFetching;
4828
+ const realServerRelationsCount = 'pagination' in data && data.pagination ? data.pagination.total : 0;
4829
+ /**
4830
+ * Items that are already connected, but reordered would be in
4831
+ * this list, so to get an accurate figure, we remove them.
4832
+ */ const relationsConnected = (field.value?.connect ?? []).filter((rel)=>data.results.findIndex((relation)=>relation.id === rel.id) === -1).length ?? 0;
4833
+ const relationsDisconnected = field.value?.disconnect?.length ?? 0;
4834
+ const relationsCount = realServerRelationsCount + relationsConnected - relationsDisconnected;
4835
+ /**
4836
+ * This is it, the source of truth for reordering in conjunction with partial loading & updating
4837
+ * of relations. Relations on load are given __temp_key__ when fetched, because we don't want to
4838
+ * create brand new keys everytime the data updates, just keep adding them onto the newly loaded ones.
4839
+ */ const relations = React__namespace.useMemo(()=>{
4840
+ const ctx = {
4841
+ field: field.value,
4842
+ // @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
4843
+ href: `../${index.COLLECTION_TYPES}/${props.attribute.targetModel}`,
4844
+ mainField: props.mainField
4845
+ };
4846
+ /**
4847
+ * Tidy up our data.
4848
+ */ const transformations = pipe$1(removeConnected(ctx), removeDisconnected(ctx), addLabelAndHref(ctx));
4849
+ const transformedRels = transformations([
4850
+ ...data.results
4851
+ ]);
4852
+ /**
4853
+ * THIS IS CRUCIAL. If you don't sort by the __temp_key__ which comes from fractional indexing
4854
+ * then the list will be in the wrong order.
4855
+ */ return [
4856
+ ...transformedRels,
4857
+ ...field.value?.connect ?? []
4858
+ ].sort((a, b)=>{
4859
+ if (a.__temp_key__ < b.__temp_key__) return -1;
4860
+ if (a.__temp_key__ > b.__temp_key__) return 1;
4861
+ return 0;
4862
+ });
4863
+ }, [
4864
+ data.results,
4865
+ field.value,
4866
+ // @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
4867
+ props.attribute.targetModel,
4868
+ props.mainField
4869
+ ]);
4870
+ const handleDisconnect = useHandleDisconnect(props.name, 'RelationsField');
4871
+ const handleConnect = (relation)=>{
4872
+ const [lastItemInList] = relations.slice(-1);
4873
+ const item = {
4874
+ id: relation.id,
4875
+ apiData: {
4876
+ id: relation.id,
4877
+ documentId: relation.documentId,
4878
+ locale: relation.locale
4879
+ },
4880
+ status: relation.status,
4881
+ /**
4882
+ * If there's a last item, that's the first key we use to generate out next one.
4883
+ */ __temp_key__: fractionalIndexing.generateNKeysBetween(lastItemInList?.__temp_key__ ?? null, null, 1)[0],
4884
+ // Fallback to `id` if there is no `mainField` value, which will overwrite the above `id` property with the exact same data.
4885
+ [props.mainField?.name ?? 'documentId']: relation[props.mainField?.name ?? 'documentId'],
4886
+ label: usePrev.getRelationLabel(relation, props.mainField),
4887
+ // @ts-expect-error – targetModel does exist on the attribute, but it's not typed.
4888
+ href: `../${index.COLLECTION_TYPES}/${props.attribute.targetModel}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
4889
+ };
4890
+ if (ONE_WAY_RELATIONS.includes(props.attribute.relation)) {
4891
+ // Remove any existing relation so they can be replaced with the new one
4892
+ field.value?.connect?.forEach(handleDisconnect);
4893
+ relations.forEach(handleDisconnect);
4894
+ field.onChange(`${props.name}.connect`, [
4895
+ item
4896
+ ]);
4897
+ } else {
4898
+ field.onChange(`${props.name}.connect`, [
4899
+ ...field.value?.connect ?? [],
4900
+ item
4901
+ ]);
4902
+ }
4903
+ };
4904
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
4905
+ ref: ref,
4906
+ direction: "column",
4907
+ gap: 3,
4908
+ justifyContent: "space-between",
4909
+ alignItems: "stretch",
4910
+ wrap: "wrap",
4911
+ children: [
4912
+ /*#__PURE__*/ jsxRuntime.jsxs(StyledFlex, {
4913
+ direction: "column",
4914
+ alignItems: "start",
4915
+ gap: 2,
4916
+ width: "100%",
4917
+ children: [
4918
+ /*#__PURE__*/ jsxRuntime.jsx(RelationsInput, {
4919
+ disabled: isDisabled,
4920
+ // NOTE: we should not default to using the documentId if the component is being created (componentUID is undefined)
4921
+ id: componentUID && component ? componentId ? `${componentId}` : '' : documentId,
4922
+ label: `${label} ${relationsCount > 0 ? `(${relationsCount})` : ''}`,
4923
+ model: model,
4924
+ onChange: handleConnect,
4925
+ isRelatedToCurrentDocument: isRelatedToCurrentDocument,
4926
+ ...props
4927
+ }),
4928
+ 'pagination' in data && data.pagination && data.pagination.pageCount > data.pagination.page ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.TextButton, {
4929
+ disabled: isFetchingMoreRelations,
4930
+ onClick: handleLoadMore,
4931
+ loading: isFetchingMoreRelations,
4932
+ startIcon: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowClockwise, {}),
4933
+ // prevent the label from line-wrapping
4934
+ shrink: 0,
4935
+ children: formatMessage({
4936
+ id: index.getTranslation('relation.loadMore'),
4937
+ defaultMessage: 'Load More'
4938
+ })
4939
+ }) : null
4940
+ ]
4941
+ }),
4942
+ /*#__PURE__*/ jsxRuntime.jsx(RelationsList, {
4943
+ data: relations,
4944
+ serverData: data.results,
4945
+ disabled: isDisabled,
4946
+ name: props.name,
4947
+ isLoading: isFetchingMoreRelations,
4948
+ relationType: props.attribute.relation,
4949
+ // @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
4950
+ targetModel: props.attribute.targetModel
4951
+ })
4952
+ ]
4953
+ });
4954
+ });
4955
+ /**
4956
+ * TODO: this can be removed once we stop shipping Inputs with
4957
+ * labels wrapped round in DS@2.
4958
+ */ const StyledFlex = styledComponents.styled(designSystem.Flex)`
4959
+ & > div {
4960
+ width: 100%;
4961
+ }
4962
+ `;
4963
+ /**
4964
+ * If it's in the connected array, it can get out of our data array,
4965
+ * we'll be putting it back in later and sorting it anyway.
4966
+ */ const removeConnected = ({ field })=>(relations)=>{
4967
+ return relations.filter((relation)=>{
4968
+ const connectedRelations = field?.connect ?? [];
4969
+ return connectedRelations.findIndex((rel)=>rel.id === relation.id) === -1;
4970
+ });
4971
+ };
4972
+ /**
4973
+ * @description Removes relations that are in the `disconnect` array of the field
4974
+ */ const removeDisconnected = ({ field })=>(relations)=>relations.filter((relation)=>{
4975
+ const disconnectedRelations = field?.disconnect ?? [];
4976
+ return disconnectedRelations.findIndex((rel)=>rel.id === relation.id) === -1;
4977
+ });
4978
+ /**
4979
+ * @description Adds a label and href to the relation object we use this to render
4980
+ * a better UI where we can link to the relation and display a human-readable label.
4981
+ */ const addLabelAndHref = ({ mainField, href })=>(relations)=>relations.map((relation)=>{
4982
+ return {
4983
+ ...relation,
4984
+ // Fallback to `id` if there is no `mainField` value, which will overwrite the above `documentId` property with the exact same data.
4985
+ [mainField?.name ?? 'documentId']: relation[mainField?.name ?? 'documentId'],
4986
+ label: usePrev.getRelationLabel(relation, mainField),
4987
+ href: `${href}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
4988
+ };
4989
+ });
4990
+ /**
4991
+ * @description Contains all the logic for the combobox that can search
4992
+ * for relations and then add them to the field's connect array.
4993
+ */ const RelationsInput = ({ hint, id, model, label, labelAction, name, mainField, placeholder, required, unique: _unique, 'aria-label': _ariaLabel, onChange, isRelatedToCurrentDocument, ...props })=>{
4994
+ const [textValue, setTextValue] = React__namespace.useState('');
4995
+ const [searchParams, setSearchParams] = React__namespace.useState({
4996
+ _q: '',
4997
+ page: 1
4998
+ });
4999
+ const { toggleNotification } = strapiAdmin.useNotification();
5000
+ const [{ query }] = strapiAdmin.useQueryParams();
5001
+ const currentDocumentMeta = index.useDocumentContext('RelationsInput', (state)=>state.meta);
5002
+ const rootDocumentMeta = index.useDocumentContext('RelationsInput', (state)=>state.rootDocumentMeta);
5003
+ const isRootDocument = rootDocumentMeta.documentId === currentDocumentMeta.documentId;
5004
+ const documentMeta = isRootDocument ? rootDocumentMeta : currentDocumentMeta;
5005
+ const { formatMessage } = reactIntl.useIntl();
5006
+ const fieldRef = strapiAdmin.useFocusInputField(name);
5007
+ const field = strapiAdmin.useField(name);
5008
+ const searchParamsDebounced = usePrev.useDebounce(searchParams, 300);
5009
+ const [searchForTrigger, { data, isLoading }] = usePrev.useLazySearchRelationsQuery();
5010
+ /**
5011
+ * Because we're using a lazy query, we need to trigger the search
5012
+ * when the component mounts and when the search params change.
5013
+ * We also need to trigger the search when the field value changes
5014
+ * so that we can filter out the relations that are already connected.
5015
+ */ React__namespace.useEffect(()=>{
5016
+ /**
5017
+ * The `name` prop is a complete path to the field, e.g. `field1.field2.field3`.
5018
+ * Where the above example would a nested field within two components, however
5019
+ * we only require the field on the component not the complete path since we query
5020
+ * individual components. Therefore we split the string and take the last item.
5021
+ */ const [targetField] = name.split('.').slice(-1);
5022
+ // Return early if there is no relation to the document
5023
+ if (!isRelatedToCurrentDocument) return;
5024
+ const params = documentMeta.params ?? index.buildValidParams(query);
5025
+ searchForTrigger({
5026
+ model,
5027
+ targetField,
5028
+ params: {
5029
+ ...params,
5030
+ id: id ?? '',
5031
+ pageSize: 10,
5032
+ idsToInclude: field.value?.disconnect?.map((rel)=>rel.id.toString()) ?? [],
5033
+ idsToOmit: field.value?.connect?.map((rel)=>rel.id.toString()) ?? [],
5034
+ ...searchParamsDebounced
5035
+ }
5036
+ });
5037
+ }, [
5038
+ field.value?.connect,
5039
+ field.value?.disconnect,
5040
+ id,
5041
+ model,
5042
+ name,
5043
+ query,
5044
+ searchForTrigger,
5045
+ searchParamsDebounced,
5046
+ isRelatedToCurrentDocument,
5047
+ documentMeta
5048
+ ]);
5049
+ const handleSearch = async (search)=>{
5050
+ setSearchParams((s)=>({
5051
+ ...s,
5052
+ _q: search,
5053
+ page: 1
5054
+ }));
5055
+ };
5056
+ const hasNextPage = data?.pagination ? data.pagination.page < data.pagination.pageCount : false;
5057
+ const options = data?.results ?? [];
5058
+ const handleChange = (relationId)=>{
5059
+ if (!relationId) {
5060
+ return;
5061
+ }
5062
+ const relation = options.find((opt)=>opt.id.toString() === relationId);
5063
+ if (!relation) {
5064
+ // This is very unlikely to happen, but it ensures we don't have any data for.
5065
+ console.error("You've tried to add a relation with an id that does not exist in the options you can see, this is likely a bug with Strapi. Please open an issue.");
5066
+ toggleNotification({
5067
+ message: formatMessage({
5068
+ id: index.getTranslation('relation.error-adding-relation'),
5069
+ defaultMessage: 'An error occurred while trying to add the relation.'
5070
+ }),
5071
+ type: 'danger'
5072
+ });
5073
+ return;
5074
+ }
5075
+ /**
5076
+ * You need to give this relation a correct _temp_key_ but
5077
+ * this component doesn't know about those ones, you can't rely
5078
+ * on the connect array because that doesn't hold items that haven't
5079
+ * moved. So use a callback to fill in the gaps when connecting.
5080
+ *
5081
+ */ onChange(relation);
5082
+ };
5083
+ const handleLoadMore = ()=>{
5084
+ if (!data || !data.pagination) {
5085
+ return;
5086
+ } else if (data.pagination.page < data.pagination.pageCount) {
5087
+ setSearchParams((s)=>({
5088
+ ...s,
5089
+ page: s.page + 1
5090
+ }));
5091
+ }
5092
+ };
5093
+ React__namespace.useLayoutEffect(()=>{
5094
+ setTextValue('');
5095
+ }, [
5096
+ field.value
5097
+ ]);
5098
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
5099
+ error: field.error,
5100
+ hint: hint,
5101
+ name: name,
5102
+ required: required,
5103
+ children: [
5104
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Label, {
5105
+ action: labelAction,
5106
+ children: label
5107
+ }),
5108
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Combobox, {
5109
+ ref: fieldRef,
5110
+ name: name,
5111
+ autocomplete: "list",
5112
+ placeholder: placeholder || formatMessage({
5113
+ id: index.getTranslation('relation.add'),
5114
+ defaultMessage: 'Add relation'
5115
+ }),
5116
+ hasMoreItems: hasNextPage,
5117
+ loading: isLoading,
5118
+ onOpenChange: ()=>{
5119
+ handleSearch(textValue ?? '');
5120
+ },
5121
+ noOptionsMessage: ()=>formatMessage({
5122
+ id: index.getTranslation('relation.notAvailable'),
5123
+ defaultMessage: 'No relations available'
5124
+ }),
5125
+ loadingMessage: formatMessage({
5126
+ id: index.getTranslation('relation.isLoading'),
5127
+ defaultMessage: 'Relations are loading'
5128
+ }),
5129
+ onLoadMore: handleLoadMore,
5130
+ textValue: textValue,
5131
+ onChange: handleChange,
5132
+ onTextValueChange: (text)=>{
5133
+ setTextValue(text);
5134
+ },
5135
+ onInputChange: (event)=>{
5136
+ handleSearch(event.currentTarget.value);
5137
+ },
5138
+ ...props,
5139
+ children: options.map((opt)=>{
5140
+ const textValue = usePrev.getRelationLabel(opt, mainField);
5141
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.ComboboxOption, {
5142
+ value: opt.id.toString(),
5143
+ textValue: textValue,
5144
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
5145
+ gap: 2,
5146
+ justifyContent: "space-between",
5147
+ children: [
5148
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
5149
+ ellipsis: true,
5150
+ children: textValue
5151
+ }),
5152
+ opt.status ? /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
5153
+ status: opt.status
5154
+ }) : null
5155
+ ]
5156
+ })
5157
+ }, opt.id);
5158
+ })
5159
+ }),
5160
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Error, {}),
5161
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
5162
+ ]
5163
+ });
5164
+ };
5165
+ /* -------------------------------------------------------------------------------------------------
5166
+ * RelationsList
5167
+ * -----------------------------------------------------------------------------------------------*/ const RELATION_ITEM_HEIGHT = 50;
5168
+ const RELATION_GUTTER = 4;
5169
+ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationType, targetModel })=>{
5170
+ const ariaDescriptionId = React__namespace.useId();
5171
+ const { formatMessage } = reactIntl.useIntl();
5172
+ const listRef = React__namespace.useRef(null);
5173
+ const outerListRef = React__namespace.useRef(null);
5174
+ const [overflow, setOverflow] = React__namespace.useState();
5175
+ const [liveText, setLiveText] = React__namespace.useState('');
5176
+ const field = strapiAdmin.useField(name);
5177
+ React__namespace.useEffect(()=>{
5178
+ if (data.length <= RELATIONS_TO_DISPLAY) {
5179
+ return setOverflow(undefined);
5180
+ }
5181
+ const handleNativeScroll = (e)=>{
5182
+ const el = e.target;
5183
+ const parentScrollContainerHeight = el.parentNode.scrollHeight;
5184
+ const maxScrollBottom = el.scrollHeight - el.scrollTop;
5185
+ if (el.scrollTop === 0) {
5186
+ return setOverflow('bottom');
5187
+ }
5188
+ if (maxScrollBottom === parentScrollContainerHeight) {
5189
+ return setOverflow('top');
5190
+ }
5191
+ return setOverflow('top-bottom');
5192
+ };
5193
+ const outerListRefCurrent = outerListRef?.current;
5194
+ if (!isLoading && data.length > 0 && outerListRefCurrent) {
5195
+ outerListRef.current.addEventListener('scroll', handleNativeScroll);
5196
+ }
5197
+ return ()=>{
5198
+ if (outerListRefCurrent) {
5199
+ outerListRefCurrent.removeEventListener('scroll', handleNativeScroll);
5200
+ }
5201
+ };
5202
+ }, [
5203
+ isLoading,
5204
+ data.length
5205
+ ]);
5206
+ const getItemPos = (index)=>`${index + 1} of ${data.length}`;
5207
+ const handleMoveItem = (newIndex, oldIndex)=>{
5208
+ const item = data[oldIndex];
5209
+ setLiveText(formatMessage({
5210
+ id: index.getTranslation('dnd.reorder'),
5211
+ defaultMessage: '{item}, moved. New position in list: {position}.'
5212
+ }, {
5213
+ item: item.label ?? item.documentId,
5214
+ position: getItemPos(newIndex)
5215
+ }));
5216
+ /**
5217
+ * Splicing mutates the array, so we need to create a new array
5218
+ */ const newData = [
5219
+ ...data
5220
+ ];
5221
+ const currentRow = data[oldIndex];
5222
+ const startKey = oldIndex > newIndex ? newData[newIndex - 1]?.__temp_key__ : newData[newIndex]?.__temp_key__;
5223
+ const endKey = oldIndex > newIndex ? newData[newIndex]?.__temp_key__ : newData[newIndex + 1]?.__temp_key__;
5224
+ /**
5225
+ * We're moving the relation between two other relations, so
5226
+ * we need to generate a new key that keeps the order
5227
+ */ const [newKey] = fractionalIndexing.generateNKeysBetween(startKey, endKey, 1);
5228
+ newData.splice(oldIndex, 1);
5229
+ newData.splice(newIndex, 0, {
5230
+ ...currentRow,
5231
+ __temp_key__: newKey
5232
+ });
5233
+ /**
5234
+ * Now we diff against the server to understand what's different so we
5235
+ * can keep the connect array nice and tidy. It also needs reversing because
5236
+ * we reverse the relations from the server in the first place.
5237
+ */ const connectedRelations = newData.reduce((acc, relation, currentIndex, array)=>{
5238
+ const relationOnServer = serverData.find((oldRelation)=>oldRelation.id === relation.id);
5239
+ const relationInFront = array[currentIndex + 1];
5240
+ if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) {
5241
+ const position = relationInFront ? {
5242
+ before: relationInFront.documentId,
5243
+ locale: relationInFront.locale,
5244
+ status: 'publishedAt' in relationInFront && relationInFront.publishedAt ? 'published' : 'draft'
5245
+ } : {
5246
+ end: true
5247
+ };
5248
+ const relationWithPosition = {
5249
+ ...relation,
5250
+ ...{
5251
+ apiData: {
5252
+ id: relation.id,
5253
+ documentId: relation.documentId ?? relation.apiData?.documentId ?? '',
5254
+ locale: relation.locale || relation.apiData?.locale,
5255
+ position
5256
+ }
5257
+ }
5258
+ };
5259
+ return [
5260
+ ...acc,
5261
+ relationWithPosition
5262
+ ];
5263
+ }
5264
+ return acc;
5265
+ }, []).toReversed();
5266
+ field.onChange(`${name}.connect`, connectedRelations);
5267
+ };
5268
+ const handleGrabItem = (index$1)=>{
5269
+ const item = data[index$1];
5270
+ setLiveText(formatMessage({
5271
+ id: index.getTranslation('dnd.grab-item'),
5272
+ defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
5273
+ }, {
5274
+ item: item.label ?? item.documentId,
5275
+ position: getItemPos(index$1)
5276
+ }));
5277
+ };
5278
+ const handleDropItem = (index$1)=>{
5279
+ const { href: _href, label, ...item } = data[index$1];
5280
+ setLiveText(formatMessage({
5281
+ id: index.getTranslation('dnd.drop-item'),
5282
+ defaultMessage: `{item}, dropped. Final position in list: {position}.`
5283
+ }, {
5284
+ item: label ?? item.documentId,
5285
+ position: getItemPos(index$1)
5286
+ }));
5287
+ };
5288
+ const handleCancel = (index$1)=>{
5289
+ const item = data[index$1];
5290
+ setLiveText(formatMessage({
5291
+ id: index.getTranslation('dnd.cancel-item'),
5292
+ defaultMessage: '{item}, dropped. Re-order cancelled.'
5293
+ }, {
5294
+ item: item.label ?? item.documentId
5295
+ }));
5296
+ };
5297
+ const handleDisconnect = useHandleDisconnect(name, 'RelationsList');
5298
+ /**
5299
+ * These relation types will only ever have one item
5300
+ * in their list, so you can't reorder a single item!
5301
+ */ const canReorder = !ONE_WAY_RELATIONS.includes(relationType);
5302
+ const dynamicListHeight = data.length > RELATIONS_TO_DISPLAY ? Math.min(data.length, RELATIONS_TO_DISPLAY) * (RELATION_ITEM_HEIGHT + RELATION_GUTTER) + RELATION_ITEM_HEIGHT / 2 : Math.min(data.length, RELATIONS_TO_DISPLAY) * (RELATION_ITEM_HEIGHT + RELATION_GUTTER);
5303
+ return /*#__PURE__*/ jsxRuntime.jsxs(ShadowBox, {
5304
+ $overflowDirection: overflow,
5305
+ children: [
5306
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
5307
+ id: ariaDescriptionId,
5308
+ children: formatMessage({
5309
+ id: index.getTranslation('dnd.instructions'),
5310
+ defaultMessage: `Press spacebar to grab and re-order`
5311
+ })
5312
+ }),
5313
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
5314
+ "aria-live": "assertive",
5315
+ children: liveText
5316
+ }),
5317
+ /*#__PURE__*/ jsxRuntime.jsx(reactWindow.FixedSizeList, {
5318
+ height: dynamicListHeight,
5319
+ ref: listRef,
5320
+ outerRef: outerListRef,
5321
+ itemCount: data.length,
5322
+ itemSize: RELATION_ITEM_HEIGHT + RELATION_GUTTER,
5323
+ itemData: {
5324
+ ariaDescribedBy: ariaDescriptionId,
5325
+ canDrag: canReorder,
5326
+ disabled,
5327
+ handleCancel,
5328
+ handleDropItem,
5329
+ handleGrabItem,
5330
+ handleMoveItem,
5331
+ name,
5332
+ handleDisconnect,
5333
+ relations: data,
5334
+ targetModel
5335
+ },
5336
+ itemKey: (index)=>data[index].id,
5337
+ innerElementType: "ol",
5338
+ children: ListItem
5339
+ })
5340
+ ]
5341
+ });
5342
+ };
5343
+ const ShadowBox = styledComponents.styled(designSystem.Box)`
5344
+ position: relative;
5345
+ overflow: hidden;
5346
+ flex: 1;
5347
+
5348
+ &:before,
5349
+ &:after {
5350
+ position: absolute;
5351
+ width: 100%;
5352
+ height: 4px;
5353
+ z-index: 1;
5354
+ }
5355
+
5356
+ &:before {
5357
+ /* TODO: as for DS Table component we would need this to be handled by the DS theme */
5358
+ content: '';
5359
+ background: linear-gradient(rgba(3, 3, 5, 0.2) 0%, rgba(0, 0, 0, 0) 100%);
5360
+ top: 0;
5361
+ opacity: ${({ $overflowDirection })=>$overflowDirection === 'top-bottom' || $overflowDirection === 'top' ? 1 : 0};
5362
+ transition: opacity 0.2s ease-in-out;
5363
+ }
5364
+
5365
+ &:after {
5366
+ /* TODO: as for DS Table component we would need this to be handled by the DS theme */
5367
+ content: '';
5368
+ background: linear-gradient(0deg, rgba(3, 3, 5, 0.2) 0%, rgba(0, 0, 0, 0) 100%);
5369
+ bottom: 0;
5370
+ opacity: ${({ $overflowDirection })=>$overflowDirection === 'top-bottom' || $overflowDirection === 'bottom' ? 1 : 0};
5371
+ transition: opacity 0.2s ease-in-out;
5372
+ }
5373
+ `;
5374
+ const ListItem = ({ data, index: index$1, style })=>{
5375
+ const { ariaDescribedBy, canDrag = false, disabled = false, handleCancel, handleDisconnect, handleDropItem, handleGrabItem, handleMoveItem, name, relations, targetModel } = data;
5376
+ const { formatMessage } = reactIntl.useIntl();
5377
+ const { href, id, label, status, documentId, apiData, locale } = relations[index$1];
5378
+ const [{ handlerId, isDragging, handleKeyDown }, relationRef, dropRef, dragRef, dragPreviewRef] = objects.useDragAndDrop(canDrag && !disabled, {
5379
+ type: `${objects.ItemTypes.RELATION}_${name}`,
5380
+ index: index$1,
5381
+ item: {
5382
+ displayedValue: label,
5383
+ status,
5384
+ id: id,
5385
+ index: index$1
5386
+ },
5387
+ onMoveItem: handleMoveItem,
5388
+ onDropItem: handleDropItem,
5389
+ onGrabItem: handleGrabItem,
5390
+ onCancel: handleCancel,
5391
+ dropSensitivity: objects.DROP_SENSITIVITY.REGULAR
5392
+ });
5393
+ const composedRefs = designSystem.useComposedRefs(relationRef, dragRef);
5394
+ React__namespace.useEffect(()=>{
5395
+ dragPreviewRef(reactDndHtml5Backend.getEmptyImage());
5396
+ }, [
5397
+ dragPreviewRef
5398
+ ]);
5399
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
5400
+ style: style,
5401
+ tag: "li",
5402
+ ref: dropRef,
5403
+ "aria-describedby": ariaDescribedBy,
5404
+ cursor: canDrag ? 'all-scroll' : 'default',
5405
+ children: isDragging ? /*#__PURE__*/ jsxRuntime.jsx(RelationItemPlaceholder, {}) : /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
5406
+ paddingTop: 2,
5407
+ paddingBottom: 2,
5408
+ paddingLeft: canDrag ? 2 : 4,
5409
+ paddingRight: 4,
5410
+ hasRadius: true,
5411
+ borderColor: "neutral200",
5412
+ background: disabled ? 'neutral150' : 'neutral0',
5413
+ justifyContent: "space-between",
5414
+ ref: composedRefs,
5415
+ "data-handler-id": handlerId,
5416
+ children: [
5417
+ /*#__PURE__*/ jsxRuntime.jsxs(FlexWrapper, {
5418
+ gap: 1,
5419
+ children: [
5420
+ canDrag ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
5421
+ tag: "div",
5422
+ role: "button",
5423
+ tabIndex: 0,
5424
+ withTooltip: false,
5425
+ label: formatMessage({
5426
+ id: index.getTranslation('components.RelationInput.icon-button-aria-label'),
5427
+ defaultMessage: 'Drag'
5428
+ }),
5429
+ variant: "ghost",
5430
+ onKeyDown: handleKeyDown,
5431
+ disabled: disabled,
5432
+ children: /*#__PURE__*/ jsxRuntime.jsx(Icons.Drag, {})
5433
+ }) : null,
5434
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
5435
+ width: "100%",
5436
+ minWidth: 0,
5437
+ justifyContent: "space-between",
5438
+ children: [
5439
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
5440
+ minWidth: 0,
5441
+ paddingTop: 1,
5442
+ paddingBottom: 1,
5443
+ paddingRight: 4,
5444
+ children: /*#__PURE__*/ jsxRuntime.jsx(RelationModalForm, {
5445
+ triggerButtonLabel: label,
5446
+ relation: {
5447
+ documentId: documentId ?? apiData?.documentId,
5448
+ model: targetModel,
5449
+ collectionType: getCollectionType(href),
5450
+ params: {
5451
+ locale: locale || apiData?.locale || null
5452
+ }
5453
+ }
5454
+ })
5455
+ }),
5456
+ status ? /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
5457
+ status: status
5458
+ }) : null
5459
+ ]
5460
+ })
5461
+ ]
5462
+ }),
5463
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
5464
+ paddingLeft: 4,
5465
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
5466
+ onClick: ()=>handleDisconnect(relations[index$1]),
5467
+ disabled: disabled,
5468
+ label: formatMessage({
5469
+ id: index.getTranslation('relation.disconnect'),
5470
+ defaultMessage: 'Remove'
5471
+ }),
5472
+ variant: "ghost",
5473
+ size: "S",
5474
+ children: /*#__PURE__*/ jsxRuntime.jsx(Icons.Cross, {})
5475
+ })
5476
+ })
5477
+ ]
5478
+ })
5479
+ });
5480
+ };
5481
+ const FlexWrapper = styledComponents.styled(designSystem.Flex)`
5482
+ width: 100%;
5483
+ /* Used to prevent endAction to be pushed out of container */
5484
+ min-width: 0;
5485
+
5486
+ & > div[role='button'] {
5487
+ cursor: all-scroll;
5488
+ }
5489
+ `;
5490
+ const DisconnectButton = styledComponents.styled.button`
5491
+ svg path {
5492
+ fill: ${({ theme, disabled })=>disabled ? theme.colors.neutral600 : theme.colors.neutral500};
5493
+ }
5494
+
5495
+ &:hover svg path,
5496
+ &:focus svg path {
5497
+ fill: ${({ theme, disabled })=>!disabled && theme.colors.neutral600};
5498
+ }
5499
+ `;
5500
+ const LinkEllipsis = styledComponents.styled(designSystem.Link)`
5501
+ display: block;
5502
+
5503
+ & > span {
5504
+ white-space: nowrap;
5505
+ overflow: hidden;
5506
+ text-overflow: ellipsis;
5507
+ display: block;
5508
+ }
5509
+ `;
5510
+ const RelationItemPlaceholder = ()=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
5511
+ paddingTop: 2,
5512
+ paddingBottom: 2,
5513
+ paddingLeft: 4,
5514
+ paddingRight: 4,
5515
+ hasRadius: true,
5516
+ borderStyle: "dashed",
5517
+ borderColor: "primary600",
5518
+ borderWidth: "1px",
5519
+ background: "primary100",
5520
+ height: `calc(100% - ${RELATION_GUTTER}px)`
5521
+ });
5522
+ const MemoizedRelationsField = /*#__PURE__*/ React__namespace.memo(RelationsField);
5523
+
4251
5524
  const uidApi = index.contentManagerApi.injectEndpoints({
4252
5525
  endpoints: (builder)=>({
4253
5526
  getDefaultUID: builder.query({
@@ -4304,7 +5577,7 @@ const UIDInput = /*#__PURE__*/ React__namespace.forwardRef(({ hint, label, label
4304
5577
  const [showRegenerate, setShowRegenerate] = React__namespace.useState(false);
4305
5578
  const isCloning = reactRouterDom.useMatch(index.CLONE_PATH) !== null;
4306
5579
  const field = strapiAdmin.useField(name);
4307
- const debouncedValue = relations.useDebounce(field.value, 300);
5580
+ const debouncedValue = usePrev.useDebounce(field.value, 300);
4308
5581
  const hasChanged = debouncedValue !== field.initialValue;
4309
5582
  const { toggleNotification } = strapiAdmin.useNotification();
4310
5583
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
@@ -6423,17 +7696,25 @@ const MemoizedWysiwyg = /*#__PURE__*/ React__namespace.memo(Wysiwyg);
6423
7696
  * specifically to be used in the EditView of the content-manager this understands
6424
7697
  * the complete EditFieldLayout and will handle RBAC conditions and rendering CM specific
6425
7698
  * components such as Blocks / Relations.
6426
- */ const InputRenderer = ({ visible, hint: providedHint, ...props })=>{
6427
- const { id, document, collectionType } = index.useDoc();
6428
- const isFormDisabled = strapiAdmin.useForm('InputRenderer', (state)=>state.disabled);
7699
+ */ const InputRenderer = ({ visible, hint: providedHint, document, ...props })=>{
7700
+ const { model: rootModel } = index.useDoc();
7701
+ const rootDocumentMeta = index.useDocumentContext('DynamicComponent', (state)=>state.rootDocumentMeta);
7702
+ const { edit: { components: rootComponents } } = index.useDocumentLayout(rootDocumentMeta.model);
7703
+ const { edit: { components: relatedComponents } } = index.useDocumentLayout(document.schema?.uid ?? rootModel);
7704
+ const components = {
7705
+ ...rootComponents,
7706
+ ...relatedComponents
7707
+ };
7708
+ const collectionType = document.schema?.kind === 'collectionType' ? 'collection-types' : 'single-types';
6429
7709
  const isInDynamicZone = useDynamicZone('isInDynamicZone', (state)=>state.isInDynamicZone);
7710
+ const isFormDisabled = strapiAdmin.useForm('InputRenderer', (state)=>state.disabled);
6430
7711
  const canCreateFields = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canCreateFields);
6431
7712
  const canReadFields = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canReadFields);
6432
7713
  const canUpdateFields = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canUpdateFields);
6433
7714
  const canUserAction = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canUserAction);
6434
- let idToCheck = id;
7715
+ let idToCheck = document.document?.documentId;
6435
7716
  if (collectionType === index.SINGLE_TYPES) {
6436
- idToCheck = document?.documentId;
7717
+ idToCheck = document?.document?.documentId;
6437
7718
  }
6438
7719
  const editableFields = idToCheck ? canUpdateFields : canCreateFields;
6439
7720
  const readableFields = idToCheck ? canReadFields : canCreateFields;
@@ -6447,7 +7728,6 @@ const MemoizedWysiwyg = /*#__PURE__*/ React__namespace.memo(Wysiwyg);
6447
7728
  props.attribute.customField
6448
7729
  ] : undefined);
6449
7730
  const hint = useFieldHint(providedHint, props.attribute);
6450
- const { edit: { components } } = index.useDocLayout();
6451
7731
  // We pass field in case of Custom Fields to keep backward compatibility
6452
7732
  const field = strapiAdmin.useField(props.name);
6453
7733
  if (!visible) {
@@ -6524,14 +7804,7 @@ const MemoizedWysiwyg = /*#__PURE__*/ React__namespace.memo(Wysiwyg);
6524
7804
  disabled: fieldIsDisabled
6525
7805
  });
6526
7806
  case 'relation':
6527
- if (window.strapi.future.isEnabled('unstableRelationsOnTheFly')) {
6528
- return /*#__PURE__*/ jsxRuntime.jsx(Relations.MemoizedUnstableRelationsField, {
6529
- ...props,
6530
- hint: hint,
6531
- disabled: fieldIsDisabled
6532
- });
6533
- }
6534
- return /*#__PURE__*/ jsxRuntime.jsx(Relations.MemoizedRelationsField, {
7807
+ return /*#__PURE__*/ jsxRuntime.jsx(MemoizedRelationsField, {
6535
7808
  ...props,
6536
7809
  hint: hint,
6537
7810
  disabled: fieldIsDisabled
@@ -6628,7 +7901,7 @@ const getMinMax = (attribute)=>{
6628
7901
  };
6629
7902
  }
6630
7903
  };
6631
- const MemoizedInputRenderer = /*#__PURE__*/ React.memo(InputRenderer);
7904
+ const MemoizedInputRenderer = /*#__PURE__*/ React__namespace.memo(InputRenderer);
6632
7905
 
6633
7906
  const RESPONSIVE_CONTAINER_BREAKPOINTS = {
6634
7907
  sm: '27.5rem'
@@ -6636,16 +7909,22 @@ const RESPONSIVE_CONTAINER_BREAKPOINTS = {
6636
7909
  const ResponsiveGridRoot = styledComponents.styled(designSystem.Grid.Root)`
6637
7910
  container-type: inline-size;
6638
7911
  `;
6639
- const ResponsiveGridItem = styledComponents.styled(designSystem.Grid.Item)`
6640
- grid-column: span 12;
6641
-
6642
- @container (min-width: ${RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
6643
- ${({ col })=>col && `grid-column: span ${col};`}
6644
- }
6645
- `;
6646
- const FormLayout = ({ layout, hasBackground = false })=>{
7912
+ const ResponsiveGridItem = /**
7913
+ * TODO:
7914
+ * JSDOM cannot handle container queries.
7915
+ * This is a temporary workaround so that tests do not fail in the CI when jestdom throws an error
7916
+ * for failing to parse the stylesheet.
7917
+ */ process.env.NODE_ENV !== 'test' ? styledComponents.styled(designSystem.Grid.Item)`
7918
+ grid-column: span 12;
7919
+ @container (min-width: ${RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
7920
+ ${({ col })=>col && `grid-column: span ${col};`}
7921
+ }
7922
+ ` : styledComponents.styled(designSystem.Grid.Item)`
7923
+ grid-column: span 12;
7924
+ `;
7925
+ const FormLayout = ({ layout, document, hasBackground = true })=>{
6647
7926
  const { formatMessage } = reactIntl.useIntl();
6648
- const { model } = index.useDoc();
7927
+ const model = document.schema?.modelName;
6649
7928
  return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
6650
7929
  direction: "column",
6651
7930
  alignItems: "stretch",
@@ -6670,13 +7949,14 @@ const FormLayout = ({ layout, hasBackground = false })=>{
6670
7949
  direction: "column",
6671
7950
  alignItems: "stretch",
6672
7951
  children: /*#__PURE__*/ jsxRuntime.jsx(MemoizedInputRenderer, {
6673
- ...fieldWithTranslatedLabel
7952
+ ...fieldWithTranslatedLabel,
7953
+ document: document
6674
7954
  })
6675
7955
  })
6676
7956
  }, field.name);
6677
7957
  }
6678
7958
  return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
6679
- ...!hasBackground && {
7959
+ ...hasBackground && {
6680
7960
  padding: 6,
6681
7961
  borderColor: 'neutral150',
6682
7962
  background: 'neutral0',
@@ -6704,7 +7984,8 @@ const FormLayout = ({ layout, hasBackground = false })=>{
6704
7984
  direction: "column",
6705
7985
  alignItems: "stretch",
6706
7986
  children: /*#__PURE__*/ jsxRuntime.jsx(MemoizedInputRenderer, {
6707
- ...fieldWithTranslatedLabel
7987
+ ...fieldWithTranslatedLabel,
7988
+ document: document
6708
7989
  })
6709
7990
  }, field.name);
6710
7991
  })
@@ -6718,9 +7999,10 @@ const FormLayout = ({ layout, hasBackground = false })=>{
6718
7999
  const NonRepeatableComponent = ({ attribute, name, children, layout })=>{
6719
8000
  const { formatMessage } = reactIntl.useIntl();
6720
8001
  const { value } = strapiAdmin.useField(name);
6721
- const level = Relations.useComponent('NonRepeatableComponent', (state)=>state.level);
8002
+ const level = useComponent('NonRepeatableComponent', (state)=>state.level);
6722
8003
  const isNested = level > 0;
6723
- return /*#__PURE__*/ jsxRuntime.jsx(Relations.ComponentProvider, {
8004
+ const currentDocument = index.useDocumentContext('NonRepeatableComponent', (state)=>state.document);
8005
+ return /*#__PURE__*/ jsxRuntime.jsx(ComponentProvider, {
6724
8006
  id: value?.id,
6725
8007
  uid: attribute.component,
6726
8008
  level: level + 1,
@@ -6760,7 +8042,8 @@ const NonRepeatableComponent = ({ attribute, name, children, layout })=>{
6760
8042
  children: children({
6761
8043
  ...field,
6762
8044
  label: translatedLabel,
6763
- name: completeFieldName
8045
+ name: completeFieldName,
8046
+ document: currentDocument
6764
8047
  })
6765
8048
  }, completeFieldName);
6766
8049
  })
@@ -6778,7 +8061,8 @@ const RepeatableComponent = ({ attribute, disabled, name, mainField, children, l
6778
8061
  const search = React__namespace.useMemo(()=>new URLSearchParams(searchString), [
6779
8062
  searchString
6780
8063
  ]);
6781
- const { components } = index.useDoc();
8064
+ const currentDocument = index.useDocumentContext('RepeatableComponent', (state)=>state.document);
8065
+ const components = currentDocument.components;
6782
8066
  const { value = [], error, rawError } = strapiAdmin.useField(name);
6783
8067
  const addFieldRow = strapiAdmin.useForm('RepeatableComponent', (state)=>state.addFieldRow);
6784
8068
  const moveFieldRow = strapiAdmin.useForm('RepeatableComponent', (state)=>state.moveFieldRow);
@@ -6906,7 +8190,7 @@ const RepeatableComponent = ({ attribute, disabled, name, mainField, children, l
6906
8190
  }));
6907
8191
  };
6908
8192
  const ariaDescriptionId = React__namespace.useId();
6909
- const level = Relations.useComponent('RepeatableComponent', (state)=>state.level);
8193
+ const level = useComponent('RepeatableComponent', (state)=>state.level);
6910
8194
  if (value.length === 0) {
6911
8195
  return /*#__PURE__*/ jsxRuntime.jsx(Initializer, {
6912
8196
  disabled: disabled,
@@ -6936,7 +8220,7 @@ const RepeatableComponent = ({ attribute, disabled, name, mainField, children, l
6936
8220
  children: [
6937
8221
  value.map(({ __temp_key__: key, id }, index)=>{
6938
8222
  const nameWithIndex = `${name}.${index}`;
6939
- return /*#__PURE__*/ jsxRuntime.jsx(Relations.ComponentProvider, {
8223
+ return /*#__PURE__*/ jsxRuntime.jsx(ComponentProvider, {
6940
8224
  // id is always a number in a component
6941
8225
  id: id,
6942
8226
  uid: attribute.component,
@@ -6981,7 +8265,8 @@ const RepeatableComponent = ({ attribute, disabled, name, mainField, children, l
6981
8265
  children: children({
6982
8266
  ...field,
6983
8267
  label: translatedLabel,
6984
- name: completeFieldName
8268
+ name: completeFieldName,
8269
+ document: currentDocument
6985
8270
  })
6986
8271
  }, completeFieldName);
6987
8272
  })
@@ -7052,8 +8337,8 @@ const Component = ({ disabled, index: index$1, name, mainField = {
7052
8337
  * components are not affected by the drag and drop of the parent component in
7053
8338
  * their own re-ordering context.
7054
8339
  */ const componentKey = name.split('.').slice(0, -1).join('.');
7055
- const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop.useDragAndDrop(!disabled, {
7056
- type: `${useDragAndDrop.ItemTypes.COMPONENT}_${componentKey}`,
8340
+ const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = objects.useDragAndDrop(!disabled, {
8341
+ type: `${objects.ItemTypes.COMPONENT}_${componentKey}`,
7057
8342
  index: index$1,
7058
8343
  item: {
7059
8344
  index: index$1,
@@ -7143,7 +8428,7 @@ const ComponentInput = ({ label, required, name, attribute, disabled, labelActio
7143
8428
  const { formatMessage } = reactIntl.useIntl();
7144
8429
  const field = strapiAdmin.useField(name);
7145
8430
  const showResetComponent = !attribute.repeatable && field.value && !disabled;
7146
- const { components } = index.useDoc();
8431
+ const components = index.useDocumentContext('ComponentInput', (state)=>state.document.components);
7147
8432
  const handleInitialisationClick = ()=>{
7148
8433
  const schema = components[attribute.component];
7149
8434
  const form = index.createDefaultForm(schema, components);
@@ -7208,8 +8493,11 @@ const ComponentInput = ({ label, required, name, attribute, disabled, labelActio
7208
8493
  };
7209
8494
  const MemoizedComponentInput = /*#__PURE__*/ React__namespace.memo(ComponentInput);
7210
8495
 
8496
+ exports.DisconnectButton = DisconnectButton;
7211
8497
  exports.DynamicZone = DynamicZone;
8498
+ exports.FlexWrapper = FlexWrapper;
7212
8499
  exports.FormLayout = FormLayout;
8500
+ exports.LinkEllipsis = LinkEllipsis;
7213
8501
  exports.MemoizedBlocksInput = MemoizedBlocksInput;
7214
8502
  exports.MemoizedComponentInput = MemoizedComponentInput;
7215
8503
  exports.MemoizedUIDInput = MemoizedUIDInput;
@@ -7218,4 +8506,4 @@ exports.NotAllowedInput = NotAllowedInput;
7218
8506
  exports.useDynamicZone = useDynamicZone;
7219
8507
  exports.useFieldHint = useFieldHint;
7220
8508
  exports.useLazyComponents = useLazyComponents;
7221
- //# sourceMappingURL=Input-CU93J6dl.js.map
8509
+ //# sourceMappingURL=Input-Gop65dq6.js.map