Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/dynamic zone #214

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/old-suns-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@smile/haring-react-shared': minor
'@smile/haring-react': minor
---

Added DynamicZone component, related types and utilities, updated snapshot
1 change: 1 addition & 0 deletions packages/haring-react-shared/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type {
IThemeOverride,
IThemes,
IFilter,
IOmitRespectIndexSignature,
} from './types';
// type exports
export { mainTheme, primaryTheme, secondaryTheme, themes } from './theme';
1 change: 1 addition & 0 deletions packages/haring-react-shared/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './options';
export * from './theme';
export * from './filters';
export * from './items';
export * from './utility';
3 changes: 3 additions & 0 deletions packages/haring-react-shared/src/types/utility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type IOmitRespectIndexSignature<T, K extends PropertyKey> = {
[P in keyof T as Exclude<P, K>]: T[P];
};
4 changes: 3 additions & 1 deletion packages/haring-react/src/Components/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export function ActionBar<Data extends Record<string, unknown>>(
`${selectedElements} file(s) selected`,
...actionRowOverflowProps
} = props;
const numberOfSelectedElements = selectedElements.length;
const numberOfSelectedElements = Array.isArray(selectedElements)
? selectedElements.length
: [selectedElements].length;

return (
<div className={`${classes.actionBar} actionBarRef`}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { IActionListAction } from './ActionList';
import type { IThumbnail } from '../../types';
import type { Meta, StoryObj } from '@storybook/react';

import { ActionList as Cmp } from './ActionList';
Expand All @@ -16,19 +16,17 @@ const meta = {
type: { name: 'number' },
},
},
component: Cmp,
component: Cmp<IThumbnail>,
tags: ['autodocs'],
title: '3-custom/Components/ActionList',
} satisfies Meta<typeof Cmp>;
} satisfies Meta<typeof Cmp<IThumbnail>>;

export default meta;
type IStory = StoryObj<typeof meta>;

export const ActionList: IStory = {
args: {
actions: actionRowOverflowActionsMock as IActionListAction<
Record<string, unknown>
>[],
actions: actionRowOverflowActionsMock,
maxVisibleActions: 2,
selectedElements: actionRowOverflowSelectedMock,
},
Expand Down
20 changes: 10 additions & 10 deletions packages/haring-react/src/Components/ActionList/ActionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ const defaultTooltipProps = {
withArrow: true,
};

export type IActionListAction<Data extends Record<string, unknown>> = IAction<
Data[]
>;
export type IActionListAction<Data extends Record<string, unknown>> =
| IAction<Data[]>
| IAction<Data>;

export interface IActionListProps<Data extends Record<string, unknown>>
extends GroupProps {
Expand All @@ -41,7 +41,7 @@ export interface IActionListProps<Data extends Record<string, unknown>>
maxVisibleActions?: number;
modalProps?: Omit<ModalProps, 'title'>;
overflowMenuLabel?: string;
selectedElements: Data[];
selectedElements: Data | Data[];
}

export function ActionList<Data extends Record<string, unknown>>(
Expand Down Expand Up @@ -72,7 +72,7 @@ export function ActionList<Data extends Record<string, unknown>>(
children: action.confirmModalProps?.children,
confirmColor: action.confirmModalProps?.confirmColor,
confirmLabel: action.confirmModalProps?.confirmLabel,
onConfirm: () => action.onAction?.(selectedElements),
onConfirm: () => action.onAction?.(selectedElements as Data & Data[]),
title: action.confirmModalProps?.title,
});
}
Expand All @@ -85,7 +85,7 @@ export function ActionList<Data extends Record<string, unknown>>(
clearConfirmAction();
}

function handleModalButton(onAction?: (item: Data[]) => void): void {
function handleModalButton(onAction?: (item: Data | Data[]) => void): void {
onAction?.(selectedElements);
handleClose();
}
Expand All @@ -94,7 +94,7 @@ export function ActionList<Data extends Record<string, unknown>>(
if (action.confirmation) {
setModal(action);
} else {
action.onAction?.(selectedElements);
action.onAction?.(selectedElements as Data & Data[]);
}
}

Expand All @@ -103,7 +103,7 @@ export function ActionList<Data extends Record<string, unknown>>(
return '';
}
return typeof action.label === 'function'
? action.label(selectedElements)
? action.label(selectedElements as Data & Data[])
: action.label;
}

Expand All @@ -112,7 +112,7 @@ export function ActionList<Data extends Record<string, unknown>>(
return null;
}
return typeof action.icon === 'function'
? action.icon(selectedElements)
? action.icon(selectedElements as Data & Data[])
: action.icon;
}

Expand All @@ -123,7 +123,7 @@ export function ActionList<Data extends Record<string, unknown>>(
return undefined;
}
return typeof action.componentProps === 'function'
? action.componentProps(selectedElements)
? action.componentProps(selectedElements as Data & Data[])
: action.componentProps;
}

Expand Down
87 changes: 87 additions & 0 deletions packages/haring-react/src/Form/DynamicZone/DynamicZone.mock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type { IDynamicZoneBlockReference } from './DynamicZoneBlock/DynamicZoneBlock';
import type { IBaseBlock, IBaseBlockButton } from '../../types';
import type { IAction } from '@smile/haring-react-shared';

import {
Alien,
ArrowDown,
ArrowUp,
Leaf,
Trash,
TreasureChest,
} from '@phosphor-icons/react';
import { action } from '@storybook/addon-actions';

const dynamicZoneBlockActionsMock: IAction<IDynamicZoneBlockReference>[] = [
{
color: 'white',
icon: <ArrowUp size={16} />,
id: 'move-up',
label: 'Move Up',
onAction: action('Move block up'),
},
{
color: 'white',
icon: <ArrowDown size={16} />,
id: 'move-down',
label: 'Move Down',
onAction: action('Move block down'),
},
{
color: 'white',
icon: <Trash size={16} />,
id: 'delete',
label: 'Delete',
onAction: action('Delete block'),
},
];

export const dynamicZoneBlocks: IBaseBlock[] = [
{
blockActions: dynamicZoneBlockActionsMock,
blockHeader: (
<>
<Alien />
First
</>
),
blockType: 'default',
id: '1',
opened: false,
value: 'initial',
},
{
blockActions: dynamicZoneBlockActionsMock,
blockFooter: 'footer',
blockHeader: (
<>
<Leaf />
Second
</>
),
blockType: 'default',
id: '2',
opened: true,
value: 'initial',
},
{
blockActions: dynamicZoneBlockActionsMock,
blockFooter: 'footer',
blockHeader: (
<>
<TreasureChest />
Third
</>
),
blockType: 'default',
id: '3',
opened: false,
value: 'initial',
},
];

export const dynamicZoneButtons: IBaseBlockButton[] = [
{ blockType: 'default', label: 'Default', leftSection: <Alien /> },
{ blockType: 'other', label: 'Other', leftSection: <Leaf /> },
{ blockType: 'stuff', label: 'Stuff', leftSection: <TreasureChest /> },
];
12 changes: 12 additions & 0 deletions packages/haring-react/src/Form/DynamicZone/DynamicZone.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.buttonsContainer {
border-radius: 0.5rem;
border: 1px dashed black;
}

.buttonsLabel {
&:empty {
display: none;
}

margin-bottom: 10px;
}
35 changes: 35 additions & 0 deletions packages/haring-react/src/Form/DynamicZone/DynamicZone.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Meta, StoryObj } from '@storybook/react';

import { action } from '@storybook/addon-actions';

import { DynamicZone as Cmp } from './DynamicZone';
import { dynamicZoneBlocks, dynamicZoneButtons } from './DynamicZone.mock';

const meta = {
component: Cmp,
tags: ['autodocs'],
title: '3-custom/Form/DynamicZone',
} satisfies Meta<typeof Cmp>;

export default meta;
type IStory = StoryObj<typeof meta>;

export const DynamicZone: IStory = {
args: {
blockOptions: dynamicZoneButtons,
blocks: dynamicZoneBlocks,
buttonsText: 'Ajouter un block',
internalBlockCardProps: {
headerCardSectionProps: {
bg: 'cadetblue',
c: 'white',
},
toggleComponentProps: {
actionIconProps: { color: 'white', variant: 'subtle' },
},
},
onAppendBlock: action('onAppendBlock, id'),
onRenderBlockContent: (_b, index) => <input key={index} />,
onToggleBlock: action('onToggleBlock'),
},
};
27 changes: 27 additions & 0 deletions packages/haring-react/src/Form/DynamicZone/DynamicZone.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { IBaseBlock } from '../../types';
import type { ReactElement } from 'react';

import { renderWithProviders } from '@smile/haring-react-shared/test-utils';
import { action } from '@storybook/addon-actions';
import { expect } from '@storybook/jest';

import { DynamicZone } from './DynamicZone';
import { dynamicZoneBlocks, dynamicZoneButtons } from './DynamicZone.mock';

describe('DynamicZone', () => {
it('matches snapshot', () => {
const onRender = (_b: IBaseBlock, index: number): ReactElement => (
<input key={index} />
);
const { container } = renderWithProviders(
<DynamicZone
blockOptions={dynamicZoneButtons}
blocks={dynamicZoneBlocks}
onAppendBlock={action('onAppendBlock, id')}
onRenderBlockContent={onRender}
onToggleBlock={action('onToggleBlock')}
/>,
);
expect(container).toMatchSnapshot();
});
});
Loading
Loading