diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js
similarity index 98%
rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/index.js
rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js
index cd3cbf3800..57a4e352a7 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/index.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js
@@ -13,7 +13,8 @@ import { BaseButton } from '@strapi/design-system/BaseButton';
import { Box } from '@strapi/design-system/Box';
import { Flex } from '@strapi/design-system/Flex';
import { Typography } from '@strapi/design-system/Typography';
-import { getTrad } from '../../../../utils';
+
+import { getTrad } from '../../../utils';
const StyledAddIcon = styled(PlusCircle)`
transform: ${({ $isOpen }) => ($isOpen ? 'rotate(45deg)' : 'rotate(0deg)')};
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/__snapshots__/index.test.js.snap b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/__snapshots__/index.test.js.snap
deleted file mode 100644
index 07f1ec7652..0000000000
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/__snapshots__/index.test.js.snap
+++ /dev/null
@@ -1,763 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` displays the name of the dz when the label is empty 1`] = `
-.c10 {
- border: 0;
- -webkit-clip: rect(0 0 0 0);
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-.c1 {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- cursor: pointer;
- padding: 8px;
- border-radius: 4px;
- background: #ffffff;
- border: 1px solid #dcdce4;
- position: relative;
- outline: none;
-}
-
-.c1 svg {
- height: 12px;
- width: 12px;
-}
-
-.c1 svg > g,
-.c1 svg path {
- fill: #ffffff;
-}
-
-.c1[aria-disabled='true'] {
- pointer-events: none;
-}
-
-.c1:after {
- -webkit-transition-property: all;
- transition-property: all;
- -webkit-transition-duration: 0.2s;
- transition-duration: 0.2s;
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -4px;
- bottom: -4px;
- left: -4px;
- right: -4px;
- border: 2px solid transparent;
-}
-
-.c1:focus-visible {
- outline: none;
-}
-
-.c1:focus-visible:after {
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -5px;
- bottom: -5px;
- left: -5px;
- right: -5px;
- border: 2px solid #4945ff;
-}
-
-.c4 {
- padding-right: 8px;
-}
-
-.c0 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c3 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c9 {
- font-weight: 600;
- color: #8e8ea9;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c7 {
- -webkit-transform: rotate(0deg);
- -ms-transform: rotate(0deg);
- transform: rotate(0deg);
-}
-
-.c7 > circle {
- fill: #eaeaef;
-}
-
-.c7 > path {
- fill: #666687;
-}
-
-.c2 {
- border-radius: 26px;
- border-color: #eaeaef;
- background: #ffffff;
- padding-top: 12px;
- padding-right: 16px;
- padding-bottom: 12px;
- padding-left: 16px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-}
-
-.c2 svg {
- height: 24px;
- width: 24px;
-}
-
-.c2 svg > path {
- fill: #666687;
-}
-
-.c2:hover {
- color: #4945ff !important;
-}
-
-.c2:hover .c8 {
- color: #4945ff !important;
-}
-
-.c2:hover .c6 > circle {
- fill: #4945ff;
-}
-
-.c2:hover .c6 > path {
- fill: #f6f6f9;
-}
-
-.c2:active .c8 {
- color: #4945ff;
-}
-
-.c2:active .c6 > circle {
- fill: #4945ff;
-}
-
-.c2:active .c6 > path {
- fill: #f6f6f9;
-}
-
-.c5 {
- height: 100%;
-}
-
-
-
-
-
-
-
-
-
-`;
-
-exports[` renders and matches the snapshot 1`] = `
-.c10 {
- border: 0;
- -webkit-clip: rect(0 0 0 0);
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-.c1 {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- cursor: pointer;
- padding: 8px;
- border-radius: 4px;
- background: #ffffff;
- border: 1px solid #dcdce4;
- position: relative;
- outline: none;
-}
-
-.c1 svg {
- height: 12px;
- width: 12px;
-}
-
-.c1 svg > g,
-.c1 svg path {
- fill: #ffffff;
-}
-
-.c1[aria-disabled='true'] {
- pointer-events: none;
-}
-
-.c1:after {
- -webkit-transition-property: all;
- transition-property: all;
- -webkit-transition-duration: 0.2s;
- transition-duration: 0.2s;
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -4px;
- bottom: -4px;
- left: -4px;
- right: -4px;
- border: 2px solid transparent;
-}
-
-.c1:focus-visible {
- outline: none;
-}
-
-.c1:focus-visible:after {
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -5px;
- bottom: -5px;
- left: -5px;
- right: -5px;
- border: 2px solid #4945ff;
-}
-
-.c4 {
- padding-right: 8px;
-}
-
-.c0 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c3 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c9 {
- font-weight: 600;
- color: #8e8ea9;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c7 {
- -webkit-transform: rotate(0deg);
- -ms-transform: rotate(0deg);
- transform: rotate(0deg);
-}
-
-.c7 > circle {
- fill: #eaeaef;
-}
-
-.c7 > path {
- fill: #666687;
-}
-
-.c2 {
- border-radius: 26px;
- border-color: #eaeaef;
- background: #ffffff;
- padding-top: 12px;
- padding-right: 16px;
- padding-bottom: 12px;
- padding-left: 16px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-}
-
-.c2 svg {
- height: 24px;
- width: 24px;
-}
-
-.c2 svg > path {
- fill: #666687;
-}
-
-.c2:hover {
- color: #4945ff !important;
-}
-
-.c2:hover .c8 {
- color: #4945ff !important;
-}
-
-.c2:hover .c6 > circle {
- fill: #4945ff;
-}
-
-.c2:hover .c6 > path {
- fill: #f6f6f9;
-}
-
-.c2:active .c8 {
- color: #4945ff;
-}
-
-.c2:active .c6 > circle {
- fill: #4945ff;
-}
-
-.c2:active .c6 > path {
- fill: #f6f6f9;
-}
-
-.c5 {
- height: 100%;
-}
-
-
-
-
-
-
-
-
-
-`;
-
-exports[` renders and matches the snapshot when the isOpen prop is truthy 1`] = `
-.c10 {
- border: 0;
- -webkit-clip: rect(0 0 0 0);
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-.c1 {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- cursor: pointer;
- padding: 8px;
- border-radius: 4px;
- background: #ffffff;
- border: 1px solid #dcdce4;
- position: relative;
- outline: none;
-}
-
-.c1 svg {
- height: 12px;
- width: 12px;
-}
-
-.c1 svg > g,
-.c1 svg path {
- fill: #ffffff;
-}
-
-.c1[aria-disabled='true'] {
- pointer-events: none;
-}
-
-.c1:after {
- -webkit-transition-property: all;
- transition-property: all;
- -webkit-transition-duration: 0.2s;
- transition-duration: 0.2s;
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -4px;
- bottom: -4px;
- left: -4px;
- right: -4px;
- border: 2px solid transparent;
-}
-
-.c1:focus-visible {
- outline: none;
-}
-
-.c1:focus-visible:after {
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -5px;
- bottom: -5px;
- left: -5px;
- right: -5px;
- border: 2px solid #4945ff;
-}
-
-.c4 {
- padding-right: 8px;
-}
-
-.c0 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c3 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c9 {
- font-weight: 600;
- color: #8e8ea9;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c7 {
- -webkit-transform: rotate(45deg);
- -ms-transform: rotate(45deg);
- transform: rotate(45deg);
-}
-
-.c7 > circle {
- fill: #eaeaef;
-}
-
-.c7 > path {
- fill: #666687;
-}
-
-.c2 {
- border-radius: 26px;
- border-color: #eaeaef;
- background: #ffffff;
- padding-top: 12px;
- padding-right: 16px;
- padding-bottom: 12px;
- padding-left: 16px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-}
-
-.c2 svg {
- height: 24px;
- width: 24px;
-}
-
-.c2 svg > path {
- fill: #666687;
-}
-
-.c2:hover {
- color: #4945ff !important;
-}
-
-.c2:hover .c8 {
- color: #4945ff !important;
-}
-
-.c2:hover .c6 > circle {
- fill: #4945ff;
-}
-
-.c2:hover .c6 > path {
- fill: #f6f6f9;
-}
-
-.c2:active .c8 {
- color: #4945ff;
-}
-
-.c2:active .c6 > circle {
- fill: #4945ff;
-}
-
-.c2:active .c6 > path {
- fill: #f6f6f9;
-}
-
-.c5 {
- height: 100%;
-}
-
-
-`;
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component.js
similarity index 56%
rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/index.js
rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component.js
index 599d01a1e4..0fac57e5b1 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/index.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component.js
@@ -1,23 +1,23 @@
-import React, { memo, Suspense, useMemo } from 'react';
+import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
-import isEqual from 'react-fast-compare';
import { useIntl } from 'react-intl';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
import { Accordion, AccordionToggle, AccordionContent } from '@strapi/design-system/Accordion';
import { IconButton } from '@strapi/design-system/IconButton';
-import { FocusTrap } from '@strapi/design-system/FocusTrap';
import { Box } from '@strapi/design-system/Box';
import { Flex } from '@strapi/design-system/Flex';
import { Stack } from '@strapi/design-system/Stack';
-import { Loader } from '@strapi/design-system/Loader';
+
import Trash from '@strapi/icons/Trash';
import ArrowDown from '@strapi/icons/ArrowDown';
import ArrowUp from '@strapi/icons/ArrowUp';
-import { useContentTypeLayout } from '../../../../hooks';
-import { getTrad } from '../../../../utils';
-import FieldComponent from '../../../FieldComponent';
-import Rectangle from './Rectangle';
+
+import { useContentTypeLayout } from '../../../hooks';
+import { getTrad } from '../../../utils';
+
+import FieldComponent from '../../FieldComponent';
const ActionStack = styled(Stack)`
svg {
@@ -42,20 +42,24 @@ const AccordionContentRadius = styled(Box)`
border-radius: 0 0 ${({ theme }) => theme.spaces[1]} ${({ theme }) => theme.spaces[1]};
`;
-const Component = ({
+const Rectangle = styled(Box)`
+ width: ${({ theme }) => theme.spaces[2]};
+ height: ${({ theme }) => theme.spaces[4]};
+`;
+
+const DynamicZoneComponent = ({
componentUid,
formErrors,
index,
- isOpen,
isFieldAllowed,
- moveComponentDown,
- moveComponentUp,
+ onMoveComponentDownClick,
+ onMoveComponentUpClick,
name,
- onToggle,
- removeComponentFromDynamicZone,
+ onRemoveComponentClick,
showDownIcon,
showUpIcon,
}) => {
+ const [isOpen, setIsOpen] = useState(true);
const { formatMessage } = useIntl();
const { getComponentLayout } = useContentTypeLayout();
const { icon, friendlyName } = useMemo(() => {
@@ -66,31 +70,7 @@ const Component = ({
return { friendlyName: displayName, icon };
}, [componentUid, getComponentLayout]);
- const handleMoveComponentDown = () => moveComponentDown(name, index);
-
- const handleMoveComponentUp = () => moveComponentUp(name, index);
-
- const handleRemove = () => removeComponentFromDynamicZone(name, index);
-
- const downLabel = formatMessage({
- id: getTrad('components.DynamicZone.move-down-label'),
- defaultMessage: 'Move component down',
- });
- const upLabel = formatMessage({
- id: getTrad('components.DynamicZone.move-up-label'),
- defaultMessage: 'Move component down',
- });
- const deleteLabel = formatMessage(
- {
- id: getTrad('components.DynamicZone.delete-label'),
- defaultMessage: 'Delete {name}',
- },
- { name: friendlyName }
- );
-
- const formErrorsKeys = Object.keys(formErrors);
-
- const fieldsErrors = formErrorsKeys.filter((errorKey) => {
+ const fieldsErrors = Object.keys(formErrors).filter((errorKey) => {
const errorKeysArray = errorKey.split('.');
if (`${errorKeysArray[0]}.${errorKeysArray[1]}` === `${name}.${index}`) {
@@ -109,11 +89,17 @@ const Component = ({
});
}
+ const handleToggle = () => {
+ setIsOpen((s) => !s);
+ };
+
return (
-
+
+
+
- onToggle(index)} size="S" error={errorMessage}>
+
}
action={
@@ -121,24 +107,36 @@ const Component = ({
{showDownIcon && (
}
/>
)}
{showUpIcon && (
}
/>
)}
{isFieldAllowed && (
}
/>
)}
@@ -149,22 +147,12 @@ const Component = ({
/>
-
- Loading content.
-
- }
- >
- onToggle(index)}>
-
-
-
+
@@ -173,19 +161,17 @@ const Component = ({
);
};
-Component.propTypes = {
+DynamicZoneComponent.propTypes = {
componentUid: PropTypes.string.isRequired,
formErrors: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
isFieldAllowed: PropTypes.bool.isRequired,
- isOpen: PropTypes.bool.isRequired,
- moveComponentDown: PropTypes.func.isRequired,
- moveComponentUp: PropTypes.func.isRequired,
+ onMoveComponentDownClick: PropTypes.func.isRequired,
+ onMoveComponentUpClick: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
- onToggle: PropTypes.func.isRequired,
- removeComponentFromDynamicZone: PropTypes.func.isRequired,
+ onRemoveComponentClick: PropTypes.func.isRequired,
showDownIcon: PropTypes.bool.isRequired,
showUpIcon: PropTypes.bool.isRequired,
};
-export default memo(Component, isEqual);
+export default DynamicZoneComponent;
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js
deleted file mode 100644
index 528af02f42..0000000000
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import styled from 'styled-components';
-import { Box } from '@strapi/design-system/Box';
-import { Flex } from '@strapi/design-system/Flex';
-
-const StyledBox = styled(Box)`
- width: ${({ theme }) => theme.spaces[2]};
- height: ${({ theme }) => theme.spaces[4]};
-`;
-
-const Rectangle = () => {
- return (
-
-
-
- );
-};
-
-export default Rectangle;
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js
similarity index 79%
rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js
rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js
index 6f9ab169a2..99270c2306 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js
@@ -6,13 +6,13 @@
import React from 'react';
import PropTypes from 'prop-types';
+import styled from 'styled-components';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
import { Box } from '@strapi/design-system/Box';
import { Typography } from '@strapi/design-system/Typography';
import { Stack } from '@strapi/design-system/Stack';
import { pxToRem } from '@strapi/helper-plugin';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import styled from 'styled-components';
-import { useIntl } from 'react-intl';
const StyledFontAwesomeIcon = styled(FontAwesomeIcon)`
width: ${pxToRem(32)} !important;
@@ -53,19 +53,14 @@ const ComponentBox = styled(Box)`
}
`;
-function ComponentCard({ componentUid, intlLabel, icon, onClick }) {
- const { formatMessage } = useIntl();
- const handleClick = () => {
- onClick(componentUid);
- };
-
+export default function ComponentCard({ children, icon, onClick }) {
return (
-
@@ -108,4 +101,4 @@ ComponentPicker.propTypes = {
onClickAddComponent: PropTypes.func.isRequired,
};
-export default memo(ComponentPicker);
+export default ComponentPicker;
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js
similarity index 90%
rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/index.js
rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js
index cfdaff39d5..0df2d4104f 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/index.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js
@@ -17,7 +17,14 @@ const StyledBox = styled(Box)`
border-radius: ${pxToRem(26)};
`;
-const DzLabel = ({ label, labelAction, name, numberOfComponents, required, intlDescription }) => {
+const DynamicZoneLabel = ({
+ label,
+ labelAction,
+ name,
+ numberOfComponents,
+ required,
+ intlDescription,
+}) => {
const { formatMessage } = useIntl();
const intlLabel = formatMessage({ id: label || name, defaultMessage: label || name });
@@ -58,14 +65,14 @@ const DzLabel = ({ label, labelAction, name, numberOfComponents, required, intlD
);
};
-DzLabel.defaultProps = {
+DynamicZoneLabel.defaultProps = {
intlDescription: undefined,
label: '',
labelAction: undefined,
required: false,
};
-DzLabel.propTypes = {
+DynamicZoneLabel.propTypes = {
intlDescription: PropTypes.shape({
id: PropTypes.string.isRequired,
defaultMessage: PropTypes.string.isRequired,
@@ -77,4 +84,4 @@ DzLabel.propTypes = {
required: PropTypes.bool,
};
-export default DzLabel;
+export default DynamicZoneLabel;
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/__snapshots__/index.test.js.snap b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/__snapshots__/index.test.js.snap
deleted file mode 100644
index 8ae1035a48..0000000000
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/__snapshots__/index.test.js.snap
+++ /dev/null
@@ -1,530 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` displays the labelAction correctly 1`] = `
-.c10 {
- border: 0;
- -webkit-clip: rect(0 0 0 0);
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-.c4 {
- max-width: 22.25rem;
-}
-
-.c0 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c3 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c5 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c6 {
- font-weight: 600;
- color: #666687;
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c7 {
- font-weight: 600;
- color: #666687;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c1 {
- background: #ffffff;
- color: #8e8ea9;
- padding-top: 12px;
- padding-right: 16px;
- padding-bottom: 12px;
- padding-left: 16px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-}
-
-.c8 {
- padding-left: 4px;
-}
-
-.c2 {
- border-radius: 1.625rem;
-}
-
-.c9 {
- border: none;
- padding: 0;
- background: transparent;
-}
-
-.c9 svg {
- width: 12px;
- height: 12px;
- fill: #8e8ea9;
-}
-
-.c9 svg path {
- fill: #8e8ea9;
-}
-
-
-
-
-
-
-
-
- dz
-
-
-
- (
- 1
- )
-
-
-
-
-
-
-
-
-
-`;
-
-exports[` displays the name of the dz when the label is empty 1`] = `
-.c8 {
- border: 0;
- -webkit-clip: rect(0 0 0 0);
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-.c4 {
- max-width: 22.25rem;
-}
-
-.c0 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c3 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c5 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c6 {
- font-weight: 600;
- color: #666687;
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c7 {
- font-weight: 600;
- color: #666687;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c1 {
- background: #ffffff;
- color: #8e8ea9;
- padding-top: 12px;
- padding-right: 16px;
- padding-bottom: 12px;
- padding-left: 16px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-}
-
-.c2 {
- border-radius: 1.625rem;
-}
-
-
-
-
-
-
-
-
- test
-
-
-
- (
- 1
- )
-
-
-
-
-
-
-
-
-`;
-
-exports[` renders and matches the snapshot 1`] = `
-.c8 {
- border: 0;
- -webkit-clip: rect(0 0 0 0);
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-.c4 {
- max-width: 22.25rem;
-}
-
-.c0 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c3 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c5 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c6 {
- font-weight: 600;
- color: #666687;
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c7 {
- font-weight: 600;
- color: #666687;
- font-size: 0.75rem;
- line-height: 1.33;
-}
-
-.c1 {
- background: #ffffff;
- color: #8e8ea9;
- padding-top: 12px;
- padding-right: 16px;
- padding-bottom: 12px;
- padding-left: 16px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-}
-
-.c2 {
- border-radius: 1.625rem;
-}
-
-
-
-
-
-
-
-
- dz
-
-
-
- (
- 1
- )
-
-
-
-
-
-
-
-
-`;
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/index.test.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.js
similarity index 97%
rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/index.test.js
rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.js
index 736b473757..eb73cae3ff 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/index.test.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.js
@@ -8,7 +8,7 @@ import React from 'react';
import { render } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/design-system';
import { IntlProvider } from 'react-intl';
-import AddComponentButton from '../index';
+import AddComponentButton from '../AddComponentButton';
describe('', () => {
it('renders and matches the snapshot', () => {
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/index.test.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.js
similarity index 80%
rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/index.test.js
rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.js
index eb9bb7437d..1fb177f3ee 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/index.test.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.js
@@ -10,7 +10,7 @@ import { ThemeProvider, lightTheme, Tooltip } from '@strapi/design-system';
import Earth from '@strapi/icons/Earth';
import { IntlProvider } from 'react-intl';
import styled from 'styled-components';
-import DzLabel from '../index';
+import DynamicZoneLabel from '../DynamicZoneLabel';
const Button = styled.button`
border: none;
@@ -36,12 +36,12 @@ const LabelAction = () => {
);
};
-describe('', () => {
+describe('DynamicZoneLabel', () => {
it('renders and matches the snapshot', () => {
const { container } = render(
-
+
);
@@ -53,7 +53,7 @@ describe('', () => {
const { container } = render(
-
+
);
@@ -65,7 +65,12 @@ describe('', () => {
const { container } = render(
- } />
+ }
+ />
);
diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js
index faac4490f5..a1cbf0b8e7 100644
--- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js
+++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js
@@ -1,25 +1,23 @@
-import React, { memo, useCallback, useMemo, useState, useEffect } from 'react';
+import React, { memo, useMemo, useState } from 'react';
import get from 'lodash/get';
import isEqual from 'react-fast-compare';
import PropTypes from 'prop-types';
import { Stack } from '@strapi/design-system/Stack';
import { Box } from '@strapi/design-system/Box';
import { NotAllowedInput, useNotification } from '@strapi/helper-plugin';
+
import { getTrad } from '../../utils';
+
import connect from './utils/connect';
import select from './utils/select';
+
+import DynamicZoneComponent from './components/Component';
import AddComponentButton from './components/AddComponentButton';
-import DzLabel from './components/DzLabel';
-import Component from './components/Component';
-
+import DynamicZoneLabel from './components/DynamicZoneLabel';
import ComponentPicker from './components/ComponentPicker';
+
import { useContentTypeLayout } from '../../hooks';
-/* eslint-disable react/no-array-index-key */
-
-const createCollapses = (arrayLength) =>
- Array.from({ length: arrayLength }).map(() => ({ isOpen: false }));
-
const DynamicZone = ({
name,
// Passed with the select function
@@ -36,39 +34,16 @@ const DynamicZone = ({
fieldSchema,
metadatas,
}) => {
+ const [addComponentIsOpen, setAddComponentIsOpen] = useState(false);
+
const toggleNotification = useNotification();
- const [isOpen, setIsOpen] = useState(false);
- const [shouldOpenAddedComponent, setShouldOpenAddedComponent] = useState(false);
const { getComponentLayout, components } = useContentTypeLayout();
+
const dynamicDisplayedComponentsLength = dynamicDisplayedComponents.length;
const intlDescription = metadatas.description
? { id: metadatas.description, defaultMessage: metadatas.description }
: null;
- const [componentCollapses, setComponentsCollapses] = useState(
- createCollapses(dynamicDisplayedComponentsLength)
- );
-
- useEffect(() => {
- setComponentsCollapses(createCollapses(dynamicDisplayedComponentsLength));
- }, [dynamicDisplayedComponentsLength]);
-
- useEffect(() => {
- if (shouldOpenAddedComponent) {
- setComponentsCollapses((prev) =>
- prev.map((collapse, index) => {
- if (index === prev.length - 1) {
- return { ...collapse, isOpen: true };
- }
-
- return collapse;
- })
- );
-
- setShouldOpenAddedComponent(false);
- }
- }, [shouldOpenAddedComponent]);
-
// We cannot use the default props here
const { max = Infinity, min = -Infinity } = fieldSchema;
const dynamicZoneErrors = useMemo(() => {
@@ -79,8 +54,6 @@ const DynamicZone = ({
.map((key) => formErrors[key]);
}, [formErrors, name]);
- const dynamicZoneAvailableComponents = useMemo(() => fieldSchema.components || [], [fieldSchema]);
-
const missingComponentNumber = min - dynamicDisplayedComponentsLength;
const hasError = dynamicZoneErrors.length > 0;
@@ -90,21 +63,17 @@ const DynamicZone = ({
const hasMaxError =
hasError && get(dynamicZoneErrors, [0, 'id'], '') === 'components.Input.error.validation.max';
- const handleAddComponent = useCallback(
- (componentUid) => {
- setIsOpen(false);
+ const handleAddComponent = (componentUid) => {
+ setAddComponentIsOpen(false);
- const componentLayoutData = getComponentLayout(componentUid);
+ const componentLayoutData = getComponentLayout(componentUid);
- addComponentToDynamicZone(name, componentLayoutData, components, hasError);
- setShouldOpenAddedComponent(true);
- },
- [addComponentToDynamicZone, hasError, name, components, getComponentLayout]
- );
+ addComponentToDynamicZone(name, componentLayoutData, components, hasError);
+ };
const handleClickOpenPicker = () => {
if (dynamicDisplayedComponentsLength < max) {
- setIsOpen((prev) => !prev);
+ setAddComponentIsOpen((prev) => !prev);
} else {
toggleNotification({
type: 'info',
@@ -113,68 +82,19 @@ const DynamicZone = ({
}
};
- const handleToggleComponent = (indexToToggle) => {
- setComponentsCollapses((prev) =>
- prev.map(({ isOpen }, index) => {
- if (index === indexToToggle) {
- return { isOpen: !isOpen };
- }
-
- return { isOpen };
- })
- );
+ const handleMoveComponentDown = (name, componentIndex) => () => {
+ moveComponentDown(name, componentIndex);
};
- const handleMoveComponentDown = (name, currentIndex) => {
- moveComponentDown(name, currentIndex);
- setComponentsCollapses((prev) => {
- return prev.map(({ isOpen }, index, refArray) => {
- if (index === currentIndex + 1) {
- return { isOpen: refArray[currentIndex].isOpen };
- }
-
- if (index === currentIndex) {
- return { isOpen: refArray[index + 1].isOpen };
- }
-
- return { isOpen };
- });
- });
+ const handleMoveComponentUp = (name, componentIndex) => () => {
+ moveComponentUp(name, componentIndex);
};
- const handleMoveComponentUp = (name, currentIndex) => {
- moveComponentUp(name, currentIndex);
- setComponentsCollapses((prev) => {
- return prev.map(({ isOpen }, index, refArray) => {
- if (index === currentIndex - 1) {
- return { isOpen: refArray[currentIndex].isOpen };
- }
-
- if (index === currentIndex) {
- return { isOpen: refArray[index - 1].isOpen };
- }
-
- return { isOpen };
- });
- });
- };
-
- const handleRemoveComponent = (name, currentIndex) => {
+ const handleRemoveComponent = (name, currentIndex) => () => {
removeComponentFromDynamicZone(name, currentIndex);
};
- if (!isFieldAllowed && isCreatingEntry) {
- return (
-
- );
- }
-
- if (!isFieldAllowed && !isFieldReadable && !isCreatingEntry) {
+ if (!isFieldAllowed && (isCreatingEntry || (!isFieldReadable && !isCreatingEntry))) {
return (
{dynamicDisplayedComponentsLength > 0 && (
-
{dynamicDisplayedComponents.map((componentUid, index) => {
- const showDownIcon =
- isFieldAllowed &&
- dynamicDisplayedComponentsLength > 0 &&
- index < dynamicDisplayedComponentsLength - 1;
- const showUpIcon = isFieldAllowed && dynamicDisplayedComponentsLength > 0 && index > 0;
- const isOpen = componentCollapses[index]?.isOpen || false;
+ const showDownIcon = isFieldAllowed && index < dynamicDisplayedComponentsLength - 1;
+ const showUpIcon = isFieldAllowed && index > 0;
return (
-
@@ -233,13 +148,13 @@ const DynamicZone = ({
isDisabled={!isFieldAllowed}
label={metadatas.label}
missingComponentNumber={missingComponentNumber}
- isOpen={isOpen}
+ isOpen={addComponentIsOpen}
name={name}
onClick={handleClickOpenPicker}
/>