diff --git a/src/components/TreeSelect/DndTreeSelect.tsx b/src/components/TreeSelect/DndTreeSelect.tsx new file mode 100644 index 0000000000..d3ad302d1e --- /dev/null +++ b/src/components/TreeSelect/DndTreeSelect.tsx @@ -0,0 +1,104 @@ +import React from 'react'; + +import {Grip} from '@gravity-ui/icons'; +import {DragDropContext, Draggable, Droppable} from 'react-beautiful-dnd'; +import type {OnDragEndResponder} from 'react-beautiful-dnd'; + +import {Icon} from '../Icon'; +import {ListContainerView} from '../useList'; +import type {ListItemType} from '../useList'; +import {reorderArray} from '../useList/__stories__/utils/reorderArray'; + +import {TreeSelect} from './TreeSelect'; +import {TreeSelectItem} from './TreeSelectItem'; +import type {RenderContainerProps, RenderItem, TreeSelectProps} from './types'; + +const renderDndItem: RenderItem = (item, state) => { + const commonProps = { + ...state, + title: item, + 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; + + style.left = undefined; + style.top = undefined; + } + + return ( + + ); + }} + + ); +}; + +export type DndTreeSelectProps = Omit< + TreeSelectProps, + 'items' | 'renderContainer' | 'renderItem' +> & { + items: ListItemType[]; + setItems: (_: ListItemType[]) => void; +}; +export function DndTreeSelect({ + items, + setItems, + ...treeSelectNativeProps +}: DndTreeSelectProps) { + const renderContainer = React.useCallback( + ({renderItem, visibleFlattenIds, containerRef, id}: RenderContainerProps) => { + const handleDrugEnd: OnDragEndResponder = ({destination, source}) => { + if (destination?.index && destination?.index !== source.index) { + const newItemsOrder = reorderArray(items, source.index, destination.index); + setItems(newItemsOrder); + } + }; + + const visibleFlattenItemList = visibleFlattenIds.map((visibleFlattenId) => + renderItem(visibleFlattenId), + ); + + return ( + + + + {(droppableProvided) => { + return ( +
+ {visibleFlattenItemList} + {droppableProvided.placeholder} +
+ ); + }} +
+
+
+ ); + }, + [items, setItems], + ); + + return ( + + ); +} diff --git a/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx b/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx index ca9e4ce45b..8e0d36381a 100644 --- a/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx +++ b/src/components/TreeSelect/__stories__/components/WithDndListExample.tsx @@ -1,39 +1,10 @@ import React from 'react'; -import {Grip} from '@gravity-ui/icons'; -import {DragDropContext, Draggable, Droppable} from 'react-beautiful-dnd'; -import type { - DraggableProvided, - DraggableRubric, - DraggableStateSnapshot, - DroppableProvided, - OnDragEndResponder, -} from 'react-beautiful-dnd'; - -import {Icon} from '../../../Icon'; import {Flex} from '../../../layout'; -import {ListContainerView} from '../../../useList'; import {createRandomizedData} from '../../../useList/__stories__/utils/makeData'; -import {reorderArray} from '../../../useList/__stories__/utils/reorderArray'; -import {TreeSelect} from '../../TreeSelect'; -import {TreeSelectItem} from '../../TreeSelectItem'; -import type {TreeSelectItemProps} from '../../TreeSelectItem'; +import {DndTreeSelect} from '../../DndTreeSelect'; import type {TreeSelectProps} from '../../types'; -const DraggableListItem = ({ - provided, - ...props -}: {provided?: DraggableProvided} & TreeSelectItemProps) => { - return ( - - ); -}; - export interface WithDndListExampleProps extends Omit, 'value' | 'onUpdate' | 'items' | 'getItemContent'> {} @@ -41,90 +12,10 @@ export const WithDndListExample = (props: WithDndListExampleProps) => { const [items, setItems] = React.useState(() => createRandomizedData({num: 10, depth: 0, getData: (title) => title}), ); - const [value, setValue] = React.useState([]); - - const handleDrugEnd: OnDragEndResponder = ({destination, source}) => { - if (destination?.index && destination?.index !== source.index) { - setItems((items) => reorderArray(items, source.index, destination.index)); - } - }; return ( - { - if (!isGroup && !disabled) { - setValue([id]); - } - }} - renderContainer={({renderItem, visibleFlattenIds, containerRef, id}) => { - return ( - - { - return renderItem(visibleFlattenIds[rubric.source.index], { - provided, - active: snapshot.isDragging, - }); - }} - > - {(droppableProvided: DroppableProvided) => ( - -
- {visibleFlattenIds.map((id) => renderItem(id))} - {droppableProvided.placeholder} -
-
- )} -
-
- ); - }} - renderItem={(item, state, _listContext, renderContextProps) => { - const commonProps = { - ...state, - title: item, - endSlot: , - }; - - // here passed props from `renderContainer` method. - if (renderContextProps) { - return ( - - ); - } - return ( - - {(provided: DraggableProvided, snapshot: DraggableStateSnapshot) => ( - - )} - - ); - }} - /> +
); };