feat: support pivots menu (#1755)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useDrag, useDrop } from 'react-dnd';
|
||||
|
||||
import {
|
||||
@@ -14,21 +14,21 @@ import type {
|
||||
TreeNodeProps,
|
||||
} from './types';
|
||||
|
||||
const NodeLine = <N,>({
|
||||
const NodeLine = <RenderProps,>({
|
||||
node,
|
||||
onDrop,
|
||||
allowDrop = true,
|
||||
isTop = false,
|
||||
}: NodeLIneProps<N>) => {
|
||||
}: NodeLIneProps<RenderProps>) => {
|
||||
const [{ isOver }, drop] = useDrop(
|
||||
() => ({
|
||||
accept: 'node',
|
||||
drop: (item: Node<N>, monitor) => {
|
||||
drop: (item: Node<RenderProps>, monitor) => {
|
||||
const didDrop = monitor.didDrop();
|
||||
if (didDrop) {
|
||||
return;
|
||||
}
|
||||
onDrop?.(item, node, {
|
||||
onDrop?.(item.id, node.id, {
|
||||
internal: false,
|
||||
topLine: isTop,
|
||||
bottomLine: !isTop,
|
||||
@@ -44,24 +44,23 @@ const NodeLine = <N,>({
|
||||
|
||||
return <StyledNodeLine ref={drop} show={isOver && allowDrop} isTop={isTop} />;
|
||||
};
|
||||
const TreeNodeItem = <N,>({
|
||||
const TreeNodeItemWithDnd = <RenderProps,>({
|
||||
node,
|
||||
allowDrop,
|
||||
collapsed,
|
||||
setCollapsed,
|
||||
...otherProps
|
||||
}: TreeNodeItemProps<N>) => {
|
||||
}: TreeNodeItemProps<RenderProps>) => {
|
||||
const { onAdd, onDelete, onDrop } = otherProps;
|
||||
|
||||
const [{ canDrop, isOver }, drop] = useDrop(
|
||||
() => ({
|
||||
accept: 'node',
|
||||
drop: (item: Node<N>, monitor) => {
|
||||
drop: (item: Node<RenderProps>, monitor) => {
|
||||
const didDrop = monitor.didDrop();
|
||||
if (didDrop || item.id === node.id || !allowDrop) {
|
||||
return;
|
||||
}
|
||||
onDrop?.(item, node, {
|
||||
onDrop?.(item.id, node.id, {
|
||||
internal: true,
|
||||
topLine: false,
|
||||
bottomLine: false,
|
||||
@@ -77,44 +76,79 @@ const TreeNodeItem = <N,>({
|
||||
|
||||
useEffect(() => {
|
||||
if (isOver && canDrop) {
|
||||
setCollapsed(false);
|
||||
setCollapsed(node.id, false);
|
||||
}
|
||||
}, [isOver, canDrop]);
|
||||
|
||||
return (
|
||||
<div ref={drop}>
|
||||
<TreeNodeItem
|
||||
dropRef={drop}
|
||||
onAdd={onAdd}
|
||||
onDelete={onDelete}
|
||||
node={node}
|
||||
allowDrop={allowDrop}
|
||||
setCollapsed={setCollapsed}
|
||||
isOver={isOver}
|
||||
canDrop={canDrop}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const TreeNodeItem = <RenderProps,>({
|
||||
node,
|
||||
collapsed,
|
||||
setCollapsed,
|
||||
selectedId,
|
||||
isOver = false,
|
||||
canDrop = false,
|
||||
onAdd,
|
||||
onDelete,
|
||||
dropRef,
|
||||
}: TreeNodeItemProps<RenderProps>) => {
|
||||
return (
|
||||
<div ref={dropRef}>
|
||||
{node.render?.(node, {
|
||||
isOver: !!(isOver && canDrop),
|
||||
isOver: isOver && canDrop,
|
||||
onAdd: () => onAdd?.(node),
|
||||
onDelete: () => onDelete?.(node),
|
||||
collapsed,
|
||||
setCollapsed,
|
||||
isSelected: selectedId === node.id,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const TreeNode = <N,>({
|
||||
node,
|
||||
index,
|
||||
allowDrop = true,
|
||||
...otherProps
|
||||
}: TreeNodeProps<N>) => {
|
||||
const { indent } = otherProps;
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
export const TreeNodeWithDnd = <RenderProps,>(
|
||||
props: TreeNodeProps<RenderProps>
|
||||
) => {
|
||||
const [{ isDragging }, drag] = useDrag(() => ({
|
||||
type: 'node',
|
||||
item: node,
|
||||
item: props.node,
|
||||
collect: monitor => ({
|
||||
isDragging: monitor.isDragging(),
|
||||
}),
|
||||
}));
|
||||
|
||||
return <TreeNode dragRef={drag} isDragging={isDragging} {...props} />;
|
||||
};
|
||||
|
||||
export const TreeNode = <RenderProps,>({
|
||||
node,
|
||||
index,
|
||||
isDragging = false,
|
||||
allowDrop = true,
|
||||
dragRef,
|
||||
...otherProps
|
||||
}: TreeNodeProps<RenderProps>) => {
|
||||
const { indent, enableDnd, collapsedIds } = otherProps;
|
||||
const collapsed = collapsedIds.includes(node.id);
|
||||
|
||||
return (
|
||||
<StyledTreeNodeContainer ref={drag} isDragging={isDragging}>
|
||||
<StyledTreeNodeContainer ref={dragRef} isDragging={isDragging}>
|
||||
<StyledTreeNodeWrapper>
|
||||
{index === 0 && (
|
||||
{enableDnd && index === 0 && (
|
||||
<NodeLine
|
||||
node={node}
|
||||
{...otherProps}
|
||||
@@ -122,15 +156,25 @@ export const TreeNode = <N,>({
|
||||
isTop={true}
|
||||
/>
|
||||
)}
|
||||
<TreeNodeItem
|
||||
node={node}
|
||||
index={index}
|
||||
allowDrop={allowDrop}
|
||||
collapsed={collapsed}
|
||||
setCollapsed={setCollapsed}
|
||||
{...otherProps}
|
||||
/>
|
||||
{(!node.children?.length || collapsed) && (
|
||||
{enableDnd ? (
|
||||
<TreeNodeItemWithDnd
|
||||
node={node}
|
||||
index={index}
|
||||
allowDrop={allowDrop}
|
||||
collapsed={collapsed}
|
||||
{...otherProps}
|
||||
/>
|
||||
) : (
|
||||
<TreeNodeItem
|
||||
node={node}
|
||||
index={index}
|
||||
allowDrop={allowDrop}
|
||||
collapsed={collapsed}
|
||||
{...otherProps}
|
||||
/>
|
||||
)}
|
||||
|
||||
{enableDnd && (!node.children?.length || collapsed) && (
|
||||
<NodeLine
|
||||
node={node}
|
||||
{...otherProps}
|
||||
@@ -140,18 +184,26 @@ export const TreeNode = <N,>({
|
||||
</StyledTreeNodeWrapper>
|
||||
<StyledCollapse in={!collapsed} indent={indent}>
|
||||
{node.children &&
|
||||
node.children.map((childNode, index) => (
|
||||
<TreeNode
|
||||
key={childNode.id}
|
||||
node={childNode}
|
||||
index={index}
|
||||
allowDrop={isDragging ? false : allowDrop}
|
||||
{...otherProps}
|
||||
/>
|
||||
))}
|
||||
node.children.map((childNode, index) =>
|
||||
enableDnd ? (
|
||||
<TreeNodeWithDnd
|
||||
key={childNode.id}
|
||||
node={childNode}
|
||||
index={index}
|
||||
allowDrop={isDragging ? false : allowDrop}
|
||||
{...otherProps}
|
||||
/>
|
||||
) : (
|
||||
<TreeNode
|
||||
key={childNode.id}
|
||||
node={childNode}
|
||||
index={index}
|
||||
allowDrop={false}
|
||||
{...otherProps}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</StyledCollapse>
|
||||
</StyledTreeNodeContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default TreeNode;
|
||||
|
||||
Reference in New Issue
Block a user