import { useEffect } from 'react'; import { useDrag, useDrop } from 'react-dnd'; import { StyledCollapse, StyledNodeLine, StyledTreeNodeContainer, StyledTreeNodeWrapper, } from './styles'; import type { Node, NodeLIneProps, TreeNodeItemProps, TreeNodeProps, } from './types'; const NodeLine = ({ node, onDrop, allowDrop = true, isTop = false, }: NodeLIneProps) => { const [{ isOver }, drop] = useDrop( () => ({ accept: 'node', drop: (item: Node, monitor) => { const didDrop = monitor.didDrop(); if (didDrop) { return; } onDrop?.(item.id, node.id, { internal: false, topLine: isTop, bottomLine: !isTop, }); }, collect: monitor => ({ isOver: monitor.isOver(), canDrop: monitor.canDrop(), }), }), [onDrop] ); return ; }; const TreeNodeItemWithDnd = ({ node, allowDrop, setCollapsed, ...otherProps }: TreeNodeItemProps) => { const { onAdd, onDelete, onDrop } = otherProps; const [{ canDrop, isOver }, drop] = useDrop( () => ({ accept: 'node', drop: (item: Node, monitor) => { const didDrop = monitor.didDrop(); if (didDrop || item.id === node.id || !allowDrop) { return; } onDrop?.(item.id, node.id, { internal: true, topLine: false, bottomLine: false, }); }, collect: monitor => ({ isOver: monitor.isOver(), canDrop: monitor.canDrop() && allowDrop, }), }), [onDrop, allowDrop] ); useEffect(() => { if (isOver && canDrop) { setCollapsed(node.id, false); } }, [isOver, canDrop, setCollapsed, node.id]); return ( ); }; const TreeNodeItem = ({ node, collapsed, setCollapsed, selectedId, isOver = false, canDrop = false, onAdd, onDelete, dropRef, disableCollapse, }: TreeNodeItemProps) => { return (
{node.render?.(node, { isOver: isOver && canDrop, onAdd: () => onAdd?.(node.id), onDelete: () => onDelete?.(node.id), collapsed, setCollapsed, isSelected: selectedId === node.id, disableCollapse, })}
); }; export const TreeNodeWithDnd = ( props: TreeNodeProps ) => { const [{ isDragging }, drag] = useDrag(() => ({ type: 'node', item: props.node, collect: monitor => ({ isDragging: monitor.isDragging(), }), })); return ; }; export const TreeNode = ({ node, index, isDragging = false, allowDrop = true, dragRef, ...otherProps }: TreeNodeProps) => { const { indent, enableDnd, collapsedIds } = otherProps; const collapsed = collapsedIds.includes(node.id); const { renderTopLine = true, renderBottomLine = true } = node; return ( {enableDnd && renderTopLine && index === 0 && ( )} {enableDnd ? ( ) : ( )} {enableDnd && renderBottomLine && (!node.children?.length || collapsed) && ( )} {node.children && node.children.map((childNode, index) => enableDnd ? ( ) : ( ) )} ); };