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(ListItemView): ability to pass custom react node as a content prop #1726

Merged
Merged
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
2 changes: 1 addition & 1 deletion src/components/Table/__stories__/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ const WithTableActionsTemplate: StoryFn<TableProps<DataItem>> = (args) => {
<TreeSelect
items={items}
size="s"
mapItemDataToProps={(title) => ({title})}
mapItemDataToContentProps={(title) => ({title})}
title="Actions select example"
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type {
} from '../../../../TreeSelect/types';
import {TextInput} from '../../../../controls/TextInput';
import {Flex} from '../../../../layout/Flex/Flex';
import type {ListItemCommonProps, ListItemViewProps} from '../../../../useList';
import type {ListItemViewContentType, ListItemViewProps} from '../../../../useList';
import {ListContainerView, ListItemView, useListFilter} from '../../../../useList';
import {block} from '../../../../utils/cn';
import type {TableColumnConfig} from '../../../Table';
Expand Down Expand Up @@ -190,16 +190,18 @@ const useDndRenderItem = (sortable: boolean | undefined) => {
}) => {
const isDragDisabled = sortable === false || renderContainerProps?.isDragDisabled === true;
const endSlot = isDragDisabled ? undefined : <Icon data={Grip} size={16} />;
const hasSelectionIcon = !item.isRequired;
const startSlot = item.isRequired ? <Icon data={Lock} /> : undefined;
const selected = item.isRequired ? false : props.selected;

const commonProps: ListItemViewProps = {
...props,
selected,
startSlot,
hasSelectionIcon,
endSlot,
selectionViewType: item.isRequired ? 'single' : 'multiple',
content: {
...props.content,
startSlot,
endSlot,
},
};

if (isDragDisabled) {
Expand Down Expand Up @@ -241,7 +243,7 @@ export type TableColumnSetupItem = TableSetting & {
sticky?: TableColumnConfig<unknown>['sticky'];
};

const mapItemDataToProps = (item: TableColumnSetupItem): ListItemCommonProps => {
const mapItemDataToContentProps = (item: TableColumnSetupItem): ListItemViewContentType => {
return {
title: item.title,
};
Expand Down Expand Up @@ -435,7 +437,7 @@ export const TableColumnSetup = (props: TableColumnSetupProps) => {
return (
<TreeSelect
className={b(null, className)}
mapItemDataToProps={mapItemDataToProps}
mapItemDataToContentProps={mapItemDataToContentProps}
multiple
size="l"
open={open}
Expand Down
4 changes: 2 additions & 2 deletions src/components/TreeList/TreeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const TreeList = <T,>({
renderItem: propsRenderItem,
renderContainer = ListContainer,
onItemClick: propsOnItemClick,
mapItemDataToProps,
mapItemDataToContentProps,
}: TreeListProps<T>) => {
const uniqId = useUniqId();
const treeListId = id ?? uniqId;
Expand Down Expand Up @@ -71,7 +71,7 @@ export const TreeList = <T,>({
id: itemId,
size,
multiple,
mapItemDataToProps,
mapItemDataToContentProps,
onItemClick,
list,
});
Expand Down
28 changes: 14 additions & 14 deletions src/components/TreeList/__stories__/TreeListDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const items: ListItemType<string>[] = ['one', 'two', 'free', 'four', 'five'];

const list = useList({items});

<TreeList list={list} mapItemDataToProps={(item) => ({title: item})} />;
<TreeList list={list} mapItemDataToContentProps={(item) => ({title: item})} />;
```

### Example with state:
Expand Down Expand Up @@ -56,26 +56,26 @@ const Component = () => {
<TreeList
list={list}
onItemClick={handleItemClick}
mapItemDataToProps={({title}) => ({title})}
mapItemDataToContentProps={({title}) => ({title})}
/>
);
};
```

## Props:

| Name | Description | Type | Default |
| :----------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------: | :-----: |
| list | result of [list](/docs/lab-uselist--docs#uselist) hook. | `UseListResult` | |
| containerRef | a reference to the DOM element of the List container inside which to search for its elements; | `React.RefObject<HTMLDivElement \| HTMLUlElement>` | |
| qa | Selector for tests | `string` | |
| size | The size of the element. This also affects the rounding radius of the list element | `s \| m \| l \| xl` | `m` |
| mapItemDataToProps | Map list item data (`T`) to `ListItemView` props | `(data: T) => ListItemCommonProps` | |
| multiple | One or multiple elements selected list | `boolean` | `false` |
| id | id attribute | `string` | |
| renderItem | Redefine the rendering of a list item. For example, add dividers between list items or wrap an item in a link component. As a view component to display a list item, use [ListItemView](/docs/lab-uselist--docs#listitemview); | `(props: TreeListRenderItem<T, P>) => React.JSX.Element` | |
| renderContainer | Render custom list container. | `(props: TreeListRenderContainer<T>) => React.JSX.Element` | |
| onItemClick | Override default on click behavior. Pass `null` to disable on click handler | `(props: {id: ListItemId; list: UseListResult<T>}, e: React.SyntheticEvent) => void \| null` | |
| Name | Description | Type | Default |
| :------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------: | :-----: |
| list | result of [list](/docs/lab-uselist--docs#uselist) hook. | `UseListResult` | |
| containerRef | a reference to the DOM element of the List container inside which to search for its elements; | `React.RefObject<HTMLDivElement \| HTMLUlElement>` | |
| qa | Selector for tests | `string` | |
| size | The size of the element. This also affects the rounding radius of the list element | `s \| m \| l \| xl` | `m` |
| mapItemDataToContentProps | Map list item data (`T`) to `ListItemView` `content` prop | `(data: T) => ListItemViewContentProps` | |
| multiple | One or multiple elements selected list | `boolean` | `false` |
| id | id attribute | `string` | |
| renderItem | Redefine the rendering of a list item. For example, add dividers between list items or wrap an item in a link component. As a view component to display a list item, use [ListItemView](/docs/lab-uselist--docs#listitemview); | `(props: TreeListRenderItem<T, P>) => React.JSX.Element` | |
| renderContainer | Render custom list container. | `(props: TreeListRenderContainer<T>) => React.JSX.Element` | |
| onItemClick | Override default on click behavior. Pass `null` to disable on click handler | `(props: {id: ListItemId; list: UseListResult<T>}, e: React.SyntheticEvent) => void \| null` | |

### TreeListRenderItem props:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function identity<T>(value: T): T {
}

export interface DefaultStoryProps
extends Omit<TreeListProps<{title: string}>, 'items' | 'mapItemDataToProps'> {
extends Omit<TreeListProps<{title: string}>, 'items' | 'mapItemDataToContentProps'> {
itemsCount?: number;
}

Expand All @@ -34,7 +34,7 @@ export const DefaultStory = ({itemsCount = 5, ...props}: DefaultStoryProps) => {
{...props}
list={listWithGroups}
onItemClick={null}
mapItemDataToProps={identity}
mapItemDataToContentProps={identity}
/>
</Flex>
<Flex direction={'column'} gap="3">
Expand All @@ -46,7 +46,7 @@ export const DefaultStory = ({itemsCount = 5, ...props}: DefaultStoryProps) => {
{...props}
list={listWithNoGroups}
onItemClick={null}
mapItemDataToProps={identity}
mapItemDataToContentProps={identity}
/>
</Flex>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function identity<T>(value: T): T {
export interface InfinityScrollStoryProps
extends Omit<
TreeListProps<Entity>,
'value' | 'onUpdate' | 'items' | 'multiple' | 'size' | 'mapItemDataToProps'
'value' | 'onUpdate' | 'items' | 'multiple' | 'size' | 'mapItemDataToContentProps'
> {
itemsCount?: number;
}
Expand All @@ -44,13 +44,18 @@ export const InfinityScrollStory = ({itemsCount = 3, ...storyProps}: InfinityScr
{...storyProps}
size="l"
list={list}
mapItemDataToProps={identity}
mapItemDataToContentProps={identity}
multiple={multiple}
renderItem={({props, context: {isLastItem, childrenIds}}) => {
const node = (
<ListItemView
{...props}
endSlot={childrenIds ? <Label>{childrenIds.length}</Label> : undefined}
content={{
...props.content,
endSlot: childrenIds ? (
<Label>{childrenIds.length}</Label>
) : undefined,
}}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {TreeList} from '../../TreeList';
import type {TreeListProps} from '../../types';

export interface WithDisabledElementsStoryProps
extends Omit<TreeListProps<{text: string}>, 'items' | 'mapItemDataToProps'> {}
extends Omit<TreeListProps<{text: string}>, 'items' | 'mapItemDataToContentProps'> {}

const items: ListItemType<{text: string}>[] = [
{
Expand Down Expand Up @@ -50,7 +50,7 @@ export const WithDisabledElementsStory = ({...storyProps}: WithDisabledElementsS
{...storyProps}
list={list}
containerRef={containerRef}
mapItemDataToProps={({text}) => ({title: text})}
mapItemDataToContentProps={({text}) => ({title: text})}
onItemClick={({id}) => {
getListItemClickHandler({list})({id});
alert(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const randomItems: CustomDataType[] = createRandomizedData({
}).map(({data}, idx) => ({someRandomKey: data, id: String(idx)}));

export interface WithDndListStoryProps
extends Omit<TreeListProps<CustomDataType>, 'items' | 'mapItemDataToProps'> {}
extends Omit<TreeListProps<CustomDataType>, 'items' | 'mapItemDataToContentProps'> {}

export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
const [items, setItems] = React.useState(randomItems);
Expand Down Expand Up @@ -117,10 +117,13 @@ export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
index,
renderContainerProps,
}) => {
const commonProps = {
const commonProps: ListItemViewProps = {
...props,
title: data.someRandomKey,
endSlot: <Icon data={Grip} size={16} />,
content: {
...props.content,
title: data.someRandomKey,
endSlot: <Icon data={Grip} size={16} />,
},
};

// here passed props from `renderContainer` method.
Expand Down Expand Up @@ -151,7 +154,7 @@ export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
{...storyProps}
list={list}
containerRef={containerRef}
mapItemDataToProps={({someRandomKey}) => ({title: someRandomKey})}
mapItemDataToContentProps={({someRandomKey}) => ({title: someRandomKey})}
renderContainer={renderContainer}
renderItem={renderItem}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ interface Entity {
}

export interface WithFiltrationAndControlsStoryProps
extends Omit<TreeListProps<Entity>, 'value' | 'onUpdate' | 'items' | 'mapItemDataToProps'> {
extends Omit<
TreeListProps<Entity>,
'value' | 'onUpdate' | 'items' | 'mapItemDataToContentProps'
> {
itemsCount?: number;
}

Expand Down Expand Up @@ -59,7 +62,7 @@ export const WithFiltrationAndControlsStory = ({
<TreeList
{...treeSelectProps}
list={list}
mapItemDataToProps={(x) => x}
mapItemDataToContentProps={(x) => x}
renderContainer={renderContainer}
/>
<Flex gap="2" className={spacing({px: 2, py: 1})}>
Expand Down
Loading
Loading