import React, { CSSProperties, HTMLAttributes, useMemo } from 'react'; import { AnimateLayoutChanges, UseSortableArguments, useSortable, } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { getIsOverParent, iOS } from './utilities'; import type { FlattenedItem, TreeItem, TreeItemComponentType } from './types'; import { UniqueIdentifier } from '@dnd-kit/core'; export interface TreeItemProps extends HTMLAttributes { childCount?: number; clone?: boolean; collapsed?: boolean; depth: number; disableInteraction?: boolean; disableSelection?: boolean; ghost?: boolean; handleProps?: any; indicator?: boolean; indentationWidth: number; item: TreeItem; isLast: boolean; parent: FlattenedItem | null; onCollapse?(id: UniqueIdentifier): void; onRemove?(id: UniqueIdentifier): void; wrapperRef?(node: HTMLLIElement): void; } const animateLayoutChanges: AnimateLayoutChanges = ({ isSorting, isDragging, }) => (isSorting || isDragging ? false : true); type SortableTreeItemProps< T, TElement extends HTMLElement > = TreeItemProps & { id: string; TreeItemComponent: TreeItemComponentType; disableSorting?: boolean; sortableProps?: Omit; keepGhostInPlace?: boolean; }; const SortableTreeItemNotMemoized = function SortableTreeItem< T, TElement extends HTMLElement >({ id, depth, isLast, TreeItemComponent, parent, disableSorting, sortableProps, keepGhostInPlace, ...props }: SortableTreeItemProps) { const { attributes, isDragging, isSorting, listeners, setDraggableNodeRef, setDroppableNodeRef, transform, transition, isOver, over, } = useSortable({ id, animateLayoutChanges, disabled: disableSorting, ...sortableProps, }); const isOverParent = useMemo( () => !!over?.id && getIsOverParent(parent, over.id), [over?.id] ); const style: CSSProperties = { transform: CSS.Translate.toString(transform), transition: transition ?? undefined, }; const localCollapse = useMemo(() => { if (!props.onCollapse) return undefined; return () => props.onCollapse?.(props.item.id); }, [props.item.id, props.onCollapse]); const localRemove = useMemo(() => { if (!props.onRemove) return undefined; return () => props.onRemove?.(props.item.id); }, [props.item.id, props.onRemove]); return ( ); }; export const SortableTreeItem = React.memo( SortableTreeItemNotMemoized ) as typeof SortableTreeItemNotMemoized;