From aea9fe5de56269fa32c8a433752facccaffca603 Mon Sep 17 00:00:00 2001 From: GermanVor Date: Wed, 7 Feb 2024 23:21:53 +0100 Subject: [PATCH] chore: dndTreeSelect types --- src/components/TreeSelect/DndTreeSelect.tsx | 61 +++++++++++++------ .../components/WithDndListExample.tsx | 14 ++++- src/components/TreeSelect/types.ts | 6 +- 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/components/TreeSelect/DndTreeSelect.tsx b/src/components/TreeSelect/DndTreeSelect.tsx index d3ad302d1e..63c01838d0 100644 --- a/src/components/TreeSelect/DndTreeSelect.tsx +++ b/src/components/TreeSelect/DndTreeSelect.tsx @@ -11,22 +11,24 @@ import {reorderArray} from '../useList/__stories__/utils/reorderArray'; import {TreeSelect} from './TreeSelect'; import {TreeSelectItem} from './TreeSelectItem'; -import type {RenderContainerProps, RenderItem, TreeSelectProps} from './types'; +import type {RenderContainerType, RenderItem, TreeSelectProps} from './types'; -const renderDndItem: RenderItem = (item, state) => { +const renderDndItem: RenderItem = (item, state, _, idx) => { const commonProps = { ...state, - title: item, + title: item.content, endSlot: , }; return ( - + {(provided, snapshot) => { - // not expected offset appears, one way to fix - remove this offsets explicitly - if (snapshot.isDragging && provided.draggableProps.style) { - const style = provided.draggableProps.style as React.CSSProperties; + const style: React.CSSProperties = { + ...provided.draggableProps.style, + }; + // not expected offset appears, one way to fix - remove this offsets explicitly + if (snapshot.isDragging) { style.left = undefined; style.top = undefined; } @@ -37,6 +39,7 @@ const renderDndItem: RenderItem = (item, state) => { {...commonProps} {...provided.draggableProps} {...provided.dragHandleProps} + style={style} active={snapshot.isDragging} /> ); @@ -45,35 +48,57 @@ const renderDndItem: RenderItem = (item, state) => { ); }; +export type DndTreeSelectItemType = { + id: string; + content: React.ReactNode; +}; + +export type RenderDndContainerType = (container: { + renderList: () => React.JSX.Element; +}) => React.ReactElement; + +const DEFAULT_RENDER_CONTAINER: RenderDndContainerType = ({renderList}) => renderList(); + +let dndTreeSelectCount = 0; + export type DndTreeSelectProps = Omit< TreeSelectProps, 'items' | 'renderContainer' | 'renderItem' > & { items: ListItemType[]; setItems: (_: ListItemType[]) => void; + renderContainer?: RenderDndContainerType; + initialDroppableId?: string; }; export function DndTreeSelect({ items, setItems, + initialDroppableId, + renderContainer: propsRenderContainer = DEFAULT_RENDER_CONTAINER, ...treeSelectNativeProps -}: DndTreeSelectProps) { - const renderContainer = React.useCallback( - ({renderItem, visibleFlattenIds, containerRef, id}: RenderContainerProps) => { +}: DndTreeSelectProps) { + const [droppableId] = React.useState( + () => initialDroppableId || `default-droppable-id-${dndTreeSelectCount++}`, + ); + + const renderContainer = React.useCallback>( + ({renderItem, visibleFlattenIds, items: _items, containerRef, id}) => { const handleDrugEnd: OnDragEndResponder = ({destination, source}) => { - if (destination?.index && destination?.index !== source.index) { + if (destination?.index !== undefined && destination?.index !== source.index) { const newItemsOrder = reorderArray(items, source.index, destination.index); + setItems(newItemsOrder); } }; - const visibleFlattenItemList = visibleFlattenIds.map((visibleFlattenId) => - renderItem(visibleFlattenId), + const visibleFlattenItemList = visibleFlattenIds.map((visibleFlattenId, idx) => + renderItem(visibleFlattenId, idx), ); - return ( + const renderList = () => ( - + {(droppableProvided) => { return (
); + + return propsRenderContainer({renderList}); }, - [items, setItems], + [items, setItems, propsRenderContainer], ); return ( - {...treeSelectNativeProps} items={items} renderContainer={renderContainer} diff --git a/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx b/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx index 8e0d36381a..d74520b7d3 100644 --- a/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx +++ b/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx @@ -3,14 +3,24 @@ import React from 'react'; import {Flex} from '../../../layout'; import {createRandomizedData} from '../../../useList/__stories__/utils/makeData'; import {DndTreeSelect} from '../../DndTreeSelect'; +import type {DndTreeSelectItemType} from '../../DndTreeSelect'; import type {TreeSelectProps} from '../../types'; export interface WithDndListExampleProps - extends Omit, 'value' | 'onUpdate' | 'items' | 'getItemContent'> {} + extends Omit< + TreeSelectProps, + 'value' | 'onUpdate' | 'items' | 'getItemContent' | 'renderContainer' + > {} + +let i = 0; export const WithDndListExample = (props: WithDndListExampleProps) => { const [items, setItems] = React.useState(() => - createRandomizedData({num: 10, depth: 0, getData: (title) => title}), + createRandomizedData({ + num: 10, + depth: 0, + getData: (title) => ({id: `id-${i++}`, content: title}), + }), ); return ( diff --git a/src/components/TreeSelect/types.ts b/src/components/TreeSelect/types.ts index de0d86cec1..b763d12743 100644 --- a/src/components/TreeSelect/types.ts +++ b/src/components/TreeSelect/types.ts @@ -1,5 +1,6 @@ import type React from 'react'; +import type {PopperPlacement} from '../../hooks/private'; import type {QAProps} from '../types'; import type { KnownItemStructure, @@ -42,6 +43,8 @@ export type RenderContainerProps = ListParsedState & className?: string; }; +export type RenderContainerType = (props: RenderContainerProps) => React.JSX.Element; + interface TreeSelectBaseProps extends QAProps, Partial> { value?: ListItemId[]; defaultOpen?: boolean; @@ -50,6 +53,7 @@ interface TreeSelectBaseProps extends QAProps, Partial extends QAProps, Partial): React.JSX.Element; + renderContainer?: RenderContainerType; /** * If you wont to disable default behavior pass `disabled` as a value; */