Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Commit

Permalink
External node can now be dropped as tree child node as expected
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Vanlerberghe committed Feb 7, 2022
1 parent 53ce600 commit 14b5e9d
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 142 deletions.
283 changes: 143 additions & 140 deletions src/tree-node.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Children, cloneElement } from 'react'
import React, { Children, Component, cloneElement } from 'react'
import { ConnectDropTarget } from 'react-dnd'
import { classnames } from './utils/classnames'
import './tree-node.css'
Expand Down Expand Up @@ -49,164 +49,167 @@ const defaultProps = {
rowDirection: 'ltr',
}

const TreeNode: React.FC<TreeRendererProps> = (props) => {
props = { ...defaultProps, ...props }
const {
children,
listIndex,
swapFrom,
swapLength,
swapDepth,
scaffoldBlockPxWidth,
lowerSiblingCounts,
connectDropTarget,
isOver,
draggedNode,
canDrop,
treeIndex,
rowHeight,
treeId: _treeId, // Delete from otherProps
getPrevRow: _getPrevRow, // Delete from otherProps
node: _node, // Delete from otherProps
path: _path, // Delete from otherProps
rowDirection,
...otherProps
} = props

const rowDirectionClass = rowDirection === 'rtl' ? 'rst__rtl' : undefined

// Construct the scaffold representing the structure of the tree
const scaffoldBlockCount = lowerSiblingCounts.length
const scaffold: any[] = []
for (const [i, lowerSiblingCount] of lowerSiblingCounts.entries()) {
let lineClass = ''
if (lowerSiblingCount > 0) {
// At this level in the tree, the nodes had sibling nodes further down

if (listIndex === 0) {
// Top-left corner of the tree
class TreeNodeComponent extends Component<TreeRendererProps> {
render() {
const props = { ...defaultProps, ...this.props }
const {
children,
listIndex,
swapFrom,
swapLength,
swapDepth,
scaffoldBlockPxWidth,
lowerSiblingCounts,
connectDropTarget,
isOver,
draggedNode,
canDrop,
treeIndex,
rowHeight,
treeId: _treeId, // Delete from otherProps
getPrevRow: _getPrevRow, // Delete from otherProps
node: _node, // Delete from otherProps
path: _path, // Delete from otherProps
rowDirection,
...otherProps
} = props

const rowDirectionClass = rowDirection === 'rtl' ? 'rst__rtl' : undefined

// Construct the scaffold representing the structure of the tree
const scaffoldBlockCount = lowerSiblingCounts.length
const scaffold: any[] = []
for (const [i, lowerSiblingCount] of lowerSiblingCounts.entries()) {
let lineClass = ''
if (lowerSiblingCount > 0) {
// At this level in the tree, the nodes had sibling nodes further down

if (listIndex === 0) {
// Top-left corner of the tree
// +-----+
// | |
// | +--+
// | | |
// +--+--+
lineClass = 'rst__lineHalfHorizontalRight rst__lineHalfVerticalBottom'
} else if (i === scaffoldBlockCount - 1) {
// Last scaffold block in the row, right before the row content
// +--+--+
// | | |
// | +--+
// | | |
// +--+--+
lineClass = 'rst__lineHalfHorizontalRight rst__lineFullVertical'
} else {
// Simply connecting the line extending down to the next sibling on this level
// +--+--+
// | | |
// | | |
// | | |
// +--+--+
lineClass = 'rst__lineFullVertical'
}
} else if (listIndex === 0) {
// Top-left corner of the tree, but has no siblings
// +-----+
// | |
// | +--+
// | | |
// +--+--+
lineClass = 'rst__lineHalfHorizontalRight rst__lineHalfVerticalBottom'
// | |
// +-----+
lineClass = 'rst__lineHalfHorizontalRight'
} else if (i === scaffoldBlockCount - 1) {
// Last scaffold block in the row, right before the row content
// The last or only node in this level of the tree
// +--+--+
// | | |
// | +--+
// | | |
// +--+--+
lineClass = 'rst__lineHalfHorizontalRight rst__lineFullVertical'
} else {
// Simply connecting the line extending down to the next sibling on this level
// +--+--+
// | | |
// | | |
// | | |
// +--+--+
lineClass = 'rst__lineFullVertical'
}
} else if (listIndex === 0) {
// Top-left corner of the tree, but has no siblings
// +-----+
// | |
// | +--+
// | |
// +-----+
lineClass = 'rst__lineHalfHorizontalRight'
} else if (i === scaffoldBlockCount - 1) {
// The last or only node in this level of the tree
// +--+--+
// | | |
// | +--+
// | |
// +-----+
lineClass = 'rst__lineHalfVerticalTop rst__lineHalfHorizontalRight'
}

scaffold.push(
<div
key={`pre_${1 + i}`}
style={{ width: scaffoldBlockPxWidth }}
className={classnames(
'rst__lineBlock',
lineClass,
rowDirectionClass ?? ''
)}
/>
)

if (treeIndex !== listIndex && i === swapDepth) {
// This row has been shifted, and is at the depth of
// the line pointing to the new destination
let highlightLineClass = ''

if (listIndex === swapFrom! + swapLength! - 1) {
// This block is on the bottom (target) line
// This block points at the target block (where the row will go when released)
highlightLineClass = 'rst__highlightBottomLeftCorner'
} else if (treeIndex === swapFrom) {
// This block is on the top (source) line
highlightLineClass = 'rst__highlightTopLeftCorner'
} else {
// This block is between the bottom and top
highlightLineClass = 'rst__highlightLineVertical'
// | |
// +-----+
lineClass = 'rst__lineHalfVerticalTop rst__lineHalfHorizontalRight'
}

const style =
rowDirection === 'rtl'
? {
width: scaffoldBlockPxWidth,
right: scaffoldBlockPxWidth * i,
}
: {
width: scaffoldBlockPxWidth,
left: scaffoldBlockPxWidth * i,
}

scaffold.push(
<div
key={i}
style={style}
key={`pre_${1 + i}`}
style={{ width: scaffoldBlockPxWidth }}
className={classnames(
'rst__absoluteLineBlock',
highlightLineClass,
'rst__lineBlock',
lineClass,
rowDirectionClass ?? ''
)}
/>
)

if (treeIndex !== listIndex && i === swapDepth) {
// This row has been shifted, and is at the depth of
// the line pointing to the new destination
let highlightLineClass = ''

if (listIndex === swapFrom! + swapLength! - 1) {
// This block is on the bottom (target) line
// This block points at the target block (where the row will go when released)
highlightLineClass = 'rst__highlightBottomLeftCorner'
} else if (treeIndex === swapFrom) {
// This block is on the top (source) line
highlightLineClass = 'rst__highlightTopLeftCorner'
} else {
// This block is between the bottom and top
highlightLineClass = 'rst__highlightLineVertical'
}

const style =
rowDirection === 'rtl'
? {
width: scaffoldBlockPxWidth,
right: scaffoldBlockPxWidth * i,
}
: {
width: scaffoldBlockPxWidth,
left: scaffoldBlockPxWidth * i,
}

scaffold.push(
<div
key={i}
style={style}
className={classnames(
'rst__absoluteLineBlock',
highlightLineClass,
rowDirectionClass ?? ''
)}
/>
)
}
}
}

const style =
rowDirection === 'rtl'
? { right: scaffoldBlockPxWidth * scaffoldBlockCount }
: { left: scaffoldBlockPxWidth * scaffoldBlockCount }
const style =
rowDirection === 'rtl'
? { right: scaffoldBlockPxWidth * scaffoldBlockCount }
: { left: scaffoldBlockPxWidth * scaffoldBlockCount }

let calculatedRowHeight = rowHeight
if (typeof rowHeight === 'function') {
calculatedRowHeight = rowHeight(treeIndex, _node, _path)
}
return connectDropTarget(
<div
{...otherProps}
style={{ height: `${calculatedRowHeight}px` }}
className={classnames('rst__node', rowDirectionClass ?? '')}>
{scaffold}

<div className="rst__nodeContent" style={style}>
{Children.map(children, (child: any) =>
cloneElement(child, {
isOver,
canDrop,
draggedNode,
})
)}
let calculatedRowHeight = rowHeight
if (typeof rowHeight === 'function') {
calculatedRowHeight = rowHeight(treeIndex, _node, _path)
}
return connectDropTarget(
<div
{...otherProps}
style={{ height: `${calculatedRowHeight}px` }}
className={classnames('rst__node', rowDirectionClass ?? '')}
ref={(node) => (this.node = node)}>
{scaffold}

<div className="rst__nodeContent" style={style}>
{Children.map(children, (child: any) =>
cloneElement(child, {
isOver,
canDrop,
draggedNode,
})
)}
</div>
</div>
</div>
)
)
}
}

export default TreeNode
export default TreeNodeComponent
3 changes: 1 addition & 2 deletions src/utils/dnd-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ const getTargetDepth = (
dragSourceInitialDepth = 0

if (component) {
const rawComponent = component.getDecoratedComponentInstance()
const relativePosition = rawComponent.node.getBoundingClientRect()
const relativePosition = component.node.getBoundingClientRect()
const leftShift =
monitor.getSourceClientOffset().x - relativePosition.left
blocksOffset = Math.round(
Expand Down

0 comments on commit 14b5e9d

Please sign in to comment.