diff --git a/packages/components/src/components/Divider/ContentfulDivider.css b/packages/components/src/components/Divider/ContentfulDivider.css index 1b4a103a6..e6e941df9 100644 --- a/packages/components/src/components/Divider/ContentfulDivider.css +++ b/packages/components/src/components/Divider/ContentfulDivider.css @@ -1,7 +1,11 @@ .cf-divider { + display: contents; position: relative; width: 100%; height: 100%; +} + +.cf-divider hr { border: none; } diff --git a/packages/components/src/components/Divider/ContentfulDivider.tsx b/packages/components/src/components/Divider/ContentfulDivider.tsx index b4e88289b..d1a6ba1fc 100644 --- a/packages/components/src/components/Divider/ContentfulDivider.tsx +++ b/packages/components/src/components/Divider/ContentfulDivider.tsx @@ -1,22 +1,14 @@ import React from 'react'; import './ContentfulDivider.css'; -import { css, cx } from 'emotion'; - -const styles = { - hr: css({ - border: 'none', - }), -}; export type ContentfulDividerProps = { className?: string; }; -export const ContentfulDivider = (props: ContentfulDividerProps) => { - const { className } = props; +export const ContentfulDivider = ({ className = '', ...props }: ContentfulDividerProps) => { return (
-
+
); }; diff --git a/packages/components/src/components/Image/Image.tsx b/packages/components/src/components/Image/Image.tsx index ca65d46a3..b3326759d 100644 --- a/packages/components/src/components/Image/Image.tsx +++ b/packages/components/src/components/Image/Image.tsx @@ -30,8 +30,10 @@ export const Image: React.FC = ({ className = '', src, cfImageAsset, ); } + const imageClasses = combineClasses('cf-image', className); + if (typeof cfImageAsset === 'string') { - return ; + return ; } if (cfImageAsset) { @@ -41,13 +43,13 @@ export const Image: React.FC = ({ className = '', src, cfImageAsset, srcSet={cfImageAsset.srcSet?.length ? cfImageAsset.srcSet?.join(', ') : undefined} sizes={cfImageAsset.sizes ? cfImageAsset.sizes : undefined} loading={cfImageAsset.loading} - className={'cf-image ' + className} + className={imageClasses} {...props} /> ); } if (src) { - return ; + return ; } }; diff --git a/packages/visual-editor/src/hooks/useComponent.tsx b/packages/visual-editor/src/hooks/useComponent.tsx index 90f091ef6..6a42c80ab 100644 --- a/packages/visual-editor/src/hooks/useComponent.tsx +++ b/packages/visual-editor/src/hooks/useComponent.tsx @@ -64,6 +64,10 @@ export const useComponent = ({ }, [node]); const componentId = node.data.id; + const isAssembly = node.type === 'assembly'; + const isStructureComponent = isContentfulStructureComponent(node.data.blockId); + const requiresDragWrapper = + !isAssembly && !isStructureComponent && !componentRegistration?.options?.wrapComponent; const { componentProps, wrapperStyles } = useComponentProps({ node, @@ -72,6 +76,7 @@ export const useComponent = ({ renderDropzone, definition: componentRegistration?.definition, userIsDragging, + requiresDragWrapper, }); const elementToRender = (props?: { dragProps?: DragWrapperProps; rest?: unknown }) => { @@ -88,14 +93,9 @@ export const useComponent = ({ ...customComponentProps } = componentProps; - const isStructureComponent = isContentfulStructureComponent(node.data.blockId); - const isAssembly = node.type === 'assembly'; const modifiedProps = isStructureComponent || isAssembly ? componentProps : customComponentProps; - const requiresDragWrapper = - !isStructureComponent && componentRegistration.options?.wrapComponent === false; - const element = React.createElement( ImportedComponentErrorBoundary, { componentId: node.data.blockId }, @@ -105,7 +105,7 @@ export const useComponent = ({ }), ); - if (!requiresDragWrapper || isAssembly) { + if (!requiresDragWrapper) { return element; } diff --git a/packages/visual-editor/src/hooks/useComponentProps.spec.ts b/packages/visual-editor/src/hooks/useComponentProps.spec.ts index fdc2c8297..ff62f4890 100644 --- a/packages/visual-editor/src/hooks/useComponentProps.spec.ts +++ b/packages/visual-editor/src/hooks/useComponentProps.spec.ts @@ -1,4 +1,4 @@ -import { ASSEMBLY_NODE_TYPE } from '@contentful/experiences-core/constants'; +import { ASSEMBLY_NODE_TYPE, CONTENTFUL_COMPONENTS } from '@contentful/experiences-core/constants'; import { useComponentProps } from './useComponentProps'; import { ComponentDefinition, ExperienceTreeNode } from '@contentful/experiences-core/types'; import { vi } from 'vitest'; @@ -102,8 +102,8 @@ describe('useComponentProps', () => { describe('structure components', () => { const definition: ComponentDefinition = { - id: 'contentful-section', - name: 'Section', + id: CONTENTFUL_COMPONENTS.section.id, + name: CONTENTFUL_COMPONENTS.section.name, variables: { cfWidth: { type: 'Text' }, cfHeight: { type: 'Text' }, @@ -113,7 +113,7 @@ describe('useComponentProps', () => { data: { id: 'id', // This block id will identify the component as a structure component - blockId: 'contentful-section', + blockId: CONTENTFUL_COMPONENTS.section.id, props: { cfWidth: { type: 'DesignValue', @@ -160,6 +160,8 @@ describe('useComponentProps', () => { variables: { cfWidth: { type: 'Text' }, cfHeight: { type: 'Text' }, + cfMaxWidth: { type: 'Text' }, + cfMargin: { type: 'Text' }, }, }; const node: ExperienceTreeNode = { @@ -180,6 +182,18 @@ describe('useComponentProps', () => { [desktop.id]: '50%', }, }, + cfMaxWidth: { + type: 'DesignValue', + valuesByBreakpoint: { + [desktop.id]: '50%', + }, + }, + cfMargin: { + type: 'DesignValue', + valuesByBreakpoint: { + [desktop.id]: '10px 0 10px 0', + }, + }, }, unboundValues: {}, dataSource: {}, @@ -189,7 +203,7 @@ describe('useComponentProps', () => { type: 'block', }; - it('should set the component size in wrapperStyles and set 100% size in componentStyles', () => { + it('should set the component size in wrapperStyles when drag wrapper is enabled', () => { const { result } = renderHook(() => useComponentProps({ node, @@ -197,14 +211,39 @@ describe('useComponentProps', () => { resolveDesignValue, renderDropzone, definition, + requiresDragWrapper: true, userIsDragging, }), ); expect(result.current.wrapperStyles.width).toEqual('50%'); expect(result.current.wrapperStyles.height).toEqual('50%'); + expect(result.current.wrapperStyles.maxWidth).toEqual('50%'); + expect(result.current.wrapperStyles.margin).toEqual('10px 0 10px 0'); + expect(result.current.componentStyles.width).toEqual('100%'); expect(result.current.componentStyles.height).toEqual('100%'); + expect(result.current.componentStyles.maxWidth).toEqual('none'); + expect(result.current.componentStyles.margin).toEqual('0'); + }); + + it('should set the component size in componentStyles when drag wrapper is disabled', () => { + const { result } = renderHook(() => + useComponentProps({ + node, + areEntitiesFetched, + resolveDesignValue, + renderDropzone, + definition, + requiresDragWrapper: false, + userIsDragging, + }), + ); + + expect(result.current.componentStyles.width).toEqual('50%'); + expect(result.current.componentStyles.height).toEqual('50%'); + expect(result.current.componentStyles.maxWidth).toEqual('50%'); + expect(result.current.componentStyles.margin).toEqual('10px 0 10px 0'); }); }); }); diff --git a/packages/visual-editor/src/hooks/useComponentProps.ts b/packages/visual-editor/src/hooks/useComponentProps.ts index 2572eff4f..9bef46b03 100644 --- a/packages/visual-editor/src/hooks/useComponentProps.ts +++ b/packages/visual-editor/src/hooks/useComponentProps.ts @@ -51,6 +51,7 @@ type UseComponentProps = { renderDropzone: RenderDropzoneFunction; userIsDragging: boolean; slotId?: string; + requiresDragWrapper?: boolean; }; export const useComponentProps = ({ @@ -60,6 +61,7 @@ export const useComponentProps = ({ renderDropzone, definition, userIsDragging, + requiresDragWrapper, }: UseComponentProps) => { const unboundValues = useEditorStore((state) => state.unboundValues); const hyperlinkPattern = useEditorStore((state) => state.hyperLinkPattern); @@ -223,18 +225,27 @@ export const useComponentProps = ({ // Move size styles to the wrapping div and override the component styles const overrideStyles: CSSProperties = {}; - const wrapperStyles: CSSProperties = { - width: cfStyles.width, - maxWidth: cfStyles.maxWidth, - }; - if (!isStructureComponent) { + const wrapperStyles: CSSProperties = {}; + if (requiresDragWrapper) { if (cfStyles.height) { wrapperStyles.height = cfStyles.height; overrideStyles.height = '100%'; } + if (cfStyles.width) { + wrapperStyles.width = cfStyles.width; overrideStyles.width = '100%'; } + + if (cfStyles.maxWidth) { + wrapperStyles.maxWidth = cfStyles.maxWidth; + overrideStyles.maxWidth = 'none'; + } + + if (cfStyles.margin) { + wrapperStyles.margin = cfStyles.margin; + overrideStyles.margin = '0'; + } } // Styles that will be applied to the component element