Skip to content

Commit

Permalink
Draft: JSK-11518: autoSnapRowsAfter, autoSnapRowsBefore option fronte…
Browse files Browse the repository at this point in the history
  • Loading branch information
d9k committed Feb 3, 2023
1 parent 3364883 commit 3f52e6c
Show file tree
Hide file tree
Showing 8 changed files with 2,885 additions and 810 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@uniweb/react-sortable-tree",
"version": "2.8.4",
"version": "2.9.0",
"description": "Drag-and-drop sortable component for nested data and hierarchies",
"scripts": {
"prebuild": "yarn run lint && yarn run clean",
Expand Down
9 changes: 8 additions & 1 deletion src/node-renderer-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import './node-renderer-default.css';
class NodeRendererDefault extends Component {
render() {
const {
autoSnapEnabled,
scaffoldBlockPxWidth,
toggleChildrenVisibility,
connectDragPreview,
connectDragSource,
isDragging,
canDrop,
canDrag,
lastCanDrop,
node,
title,
subtitle,
Expand All @@ -32,6 +34,7 @@ class NodeRendererDefault extends Component {
rowDirection,
...otherProps
} = this.props;

const nodeTitle = title || node.title;
const nodeSubtitle = subtitle || node.subtitle;
const rowDirectionClass = rowDirection === 'rtl' ? 'rst__rtl' : null;
Expand Down Expand Up @@ -66,7 +69,9 @@ class NodeRendererDefault extends Component {
}

const isDraggedDescendant = draggedNode && isDescendant(draggedNode, node);

const isLandingPadActive = !didDrop && isDragging;
const isLandingPadCancel = isLandingPadActive && (!canDrop && !(autoSnapEnabled && lastCanDrop));

let buttonStyle = { left: -0.5 * scaffoldBlockPxWidth };
if (rowDirection === 'rtl') {
Expand Down Expand Up @@ -112,7 +117,7 @@ class NodeRendererDefault extends Component {
className={classnames(
'rst__row',
isLandingPadActive && 'rst__rowLandingPad',
isLandingPadActive && !canDrop && 'rst__rowCancelPad',
isLandingPadCancel && 'rst__rowCancelPad',
isSearchMatch && 'rst__rowSearchMatch',
isSearchFocus && 'rst__rowSearchFocus',
rowDirectionClass,
Expand Down Expand Up @@ -181,6 +186,7 @@ class NodeRendererDefault extends Component {
}

NodeRendererDefault.defaultProps = {
autoSnapEnabled: false,
isSearchMatch: false,
isSearchFocus: false,
canDrag: false,
Expand All @@ -197,6 +203,7 @@ NodeRendererDefault.defaultProps = {
};

NodeRendererDefault.propTypes = {
autoSnapEnabled: PropTypes.bool,
node: PropTypes.shape({}).isRequired,
title: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
subtitle: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
Expand Down
71 changes: 59 additions & 12 deletions src/react-sortable-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class ReactSortableTree extends Component {
this.rowHeightRerunPlanned = false;

const {
autoSnapRowsAfter,
autoSnapRowsBefore,
dndType,
nodeContentRenderer,
treeNodeRenderer,
Expand All @@ -58,12 +60,13 @@ class ReactSortableTree extends Component {

this.dndManager = new DndManager(this);

this.autoSnapRowsAfter = autoSnapRowsAfter;
this.autoSnapRowsBefore = autoSnapRowsBefore;
// Wrapping classes for use with react-dnd
this.treeId = `rst__${treeIdCounter}`;
treeIdCounter += 1;
this.dndType = dndType || this.treeId;
this.nodeContentRenderer = this.dndManager.wrapSource(nodeContentRenderer);
this.firstRenderAfterDragStart = true;
this.treePlaceholderRenderer = this.dndManager.wrapPlaceholder(
TreePlaceholder
);
Expand Down Expand Up @@ -102,13 +105,18 @@ class ReactSortableTree extends Component {
this.dragHover = this.dragHover.bind(this);
this.endDrag = this.endDrag.bind(this);
this.drop = this.drop.bind(this);
this.getRows = this.getRows.bind(this);
this.rowHeightsVirtualListRecompute = this.rowHeightsVirtualListRecompute.bind(this);
this.rowHeightsVirtualListRecomputeRerunAfterDone = this.rowHeightsVirtualListRecomputeRerunAfterDone.bind(this);
this.rowHeightsVirtualListRecomputeRerunAfterDoneDebounced = debounce(this.rowHeightsVirtualListRecomputeRerunAfterDone, 100).bind(this);
this.rowHeightsRecomputeRequired = this.rowHeightsRecomputeRequired.bind(this);
this.handleDndMonitorChange = this.handleDndMonitorChange.bind(this);
}

get autoSnapEnabled() {
return !!(this.autoSnapRowsAfter || this.autoSnapRowsBefore);
}

componentDidMount() {
ReactSortableTree.loadLazyChildren(this.props, this.state);
const stateUpdate = ReactSortableTree.search(
Expand Down Expand Up @@ -176,8 +184,7 @@ class ReactSortableTree extends Component {
};

rowHeightsVirtualListRecompute() {
if (this.props.isVirtualized) {
if (!this.rowHeightRecomputing) {
if (this.props.isVirtualized && !this.rowHeightRecomputing) {
this.rowHeightRecomputing = true;

// TODO seems like calling recomputeRowHeights() immediately aborts dragging :c
Expand All @@ -187,7 +194,6 @@ class ReactSortableTree extends Component {
this.rowHeightRerunPlanned = false;
this.rowHeightsVirtualListRecompute();
}
}
} else {
// this.forceUpdate();
}
Expand Down Expand Up @@ -311,13 +317,17 @@ class ReactSortableTree extends Component {
});
}

moveNode({
node,
path: prevPath,
treeIndex: prevTreeIndex,
depth,
minimumTreeIndex,
}) {
moveNode(args) {
const {
node,
path: prevPath,
treeIndex: prevTreeIndex,
depth,
minimumTreeIndex,
} = args;

console.log('react-sortable-tree: moveNode():', args);

const {
treeData,
treeIndex,
Expand Down Expand Up @@ -450,7 +460,12 @@ class ReactSortableTree extends Component {
return;
}


console.log('react-sortable-tree: dragHover():', {draggedNode, draggedDepth, draggedMinimumTreeIndex});

this.setState(({ draggingTreeData, instanceProps }) => {
// console.log('react-sortable-tree: dragHover(): tree:', {draggingTreeData, treeData: instanceProps.treeData});

// Fall back to the tree data if something is being dragged in from
// an external element
const newDraggingTreeData = draggingTreeData || instanceProps.treeData;
Expand Down Expand Up @@ -552,7 +567,27 @@ class ReactSortableTree extends Component {
this.rowHeightsRecomputeRequired();
}

drop(dropResult) {
drop(dropResultRaw) {
let dropResult = {
...dropResultRaw,
}

if (this.dndManager.lastAutoSnapResult) {
const { path, targetDepth, targetIndex } = this.dndManager.lastAutoSnapResult;
dropResult = {
...dropResult,
depth: targetDepth,
path,
minimumTreeIndex: targetIndex,
}
}

console.log('react-sortable-tree: drop: ', {
dropResultRaw,
dropResult,
lastAutoSnaoResult: this.dndManager.lastAutoSnapResult
});

this.moveNode(dropResult);
this.rowHeightsRecomputeRequired();
}
Expand Down Expand Up @@ -627,6 +662,9 @@ class ReactSortableTree extends Component {
} = this.mergeTheme(this.props);
const TreeNodeRenderer = this.treeNodeRenderer;
const NodeContentRenderer = this.nodeContentRenderer;

const { autoSnapEnabled } = this;

const nodeKey = path[path.length - 1];
const isSearchMatch = nodeKey in matchKeys;
const isSearchFocus =
Expand Down Expand Up @@ -655,6 +693,8 @@ class ReactSortableTree extends Component {
rowDirection,
};

// console.log(`react-sortable-tree: renderRow(): ${JSON.stringify(sharedProps.path)}`, {nodeProps, sharedProps});

return (
<TreeNodeRenderer
style={style}
Expand All @@ -668,10 +708,12 @@ class ReactSortableTree extends Component {
{...sharedProps}
>
<NodeContentRenderer
autoSnapEnabled={autoSnapEnabled}
parentNode={parentNode}
isSearchMatch={isSearchMatch}
isSearchFocus={isSearchFocus}
canDrag={rowCanDrag}
lastCanDrop={this.dndManager.lastCanDrop}
toggleChildrenVisibility={this.toggleChildrenVisibility}
{...sharedProps}
{...nodeProps}
Expand Down Expand Up @@ -847,6 +889,9 @@ class ReactSortableTree extends Component {
}

ReactSortableTree.propTypes = {
autoSnapRowsAfter: PropTypes.number,
autoSnapRowsBefore: PropTypes.number,

dragDropManager: PropTypes.shape({
getMonitor: PropTypes.func,
}).isRequired,
Expand Down Expand Up @@ -981,6 +1026,8 @@ ReactSortableTree.propTypes = {
};

ReactSortableTree.defaultProps = {
autoSnapRowsAfter: 0,
autoSnapRowsBefore: 0,
canDrag: true,
canDrop: null,
canNodeHaveChildren: () => true,
Expand Down
Loading

0 comments on commit 3f52e6c

Please sign in to comment.