Skip to content

made item height for drag position dynamic #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion next-release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
### Features

### Bug Fixes and Improvements

- Fixes a bug where drag positions would be off and not work properly when you make trees have different heights for each item or each item has different heights (#338)
### Other Changes
-->
13 changes: 13 additions & 0 deletions packages/core/src/controlledEnvironment/layoutUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ export const computeItemHeight = (treeId: string) => {
return firstItem?.offsetHeight ?? 5;
};

export const computeItemHeightArray = (treeId: string): number[] => {
const document = getDocument();
if (!document) {
console.log("Document not found");
return [];
}
const items = document.querySelectorAll<HTMLElement>(`[data-rct-tree="${treeId}"] [data-rct-item-container="true"]`);
const itemHeights = Array.from(items).map(item => item.offsetHeight);

console.log({ itemHeights });
return itemHeights;
};

export const isOutsideOfContainer = (e: DragEvent, treeBb: DOMRect) =>
e.clientX < treeBb.left ||
e.clientX > treeBb.right ||
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/drag/DragAndDropProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
draggingItems,
getDraggingPosition,
itemHeight,
itemsHeightArray,
} = useDraggingPosition();

const resetProgrammaticDragIndexForCurrentTree = useCallback(
Expand Down Expand Up @@ -285,6 +286,7 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
draggingItems,
draggingPosition,
itemHeight: itemHeight.current,
itemsHeightArray: itemsHeightArray.current,
isProgrammaticallyDragging,
onDragOverTreeHandler,
viableDragPositions,
Expand All @@ -296,6 +298,7 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
draggingPosition,
isProgrammaticallyDragging,
itemHeight,
itemsHeightArray,
onDragOverTreeHandler,
onStartDraggingItems,
programmaticDragDown,
Expand Down
33 changes: 28 additions & 5 deletions packages/core/src/drag/useDraggingPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DraggingPosition, HoveringPosition, TreeItem } from '../types';
import {
computeItemHeight,
isOutsideOfContainer,
computeItemHeightArray,
} from '../controlledEnvironment/layoutUtils';
import { useTreeEnvironment } from '../controlledEnvironment/ControlledTreeEnvironment';
import { useStableHandler } from '../useStableHandler';
Expand All @@ -16,6 +17,7 @@ export const useDraggingPosition = () => {
undefined
);
const itemHeight = useRef(0);
const itemsHeightArray = useRef([0]);
const env = useTreeEnvironment();
const getParentOfLinearItem = useGetGetParentOfLinearItem();

Expand Down Expand Up @@ -55,19 +57,35 @@ export const useDraggingPosition = () => {
return undefined;
}

itemsHeightArray.current = computeItemHeightArray(treeId);

const treeBb = containerRef.current.getBoundingClientRect();

if (isOutsideOfContainer(e, treeBb)) {
return undefined;
}

const hoveringPosition = (e.clientY - treeBb.top) / itemHeight.current;
const clientYRelativeToTreeTop = e.clientY - treeBb.top;
let cumulativeHeight = 0;
let linearIndex = 0;
let hoveringPosition = 0;

for (let i = 0; i < itemsHeightArray.current.length; i++) {
cumulativeHeight += itemsHeightArray.current[i];
if (clientYRelativeToTreeTop <= cumulativeHeight) {
linearIndex = i;
// Calculate hovering position as a fraction within the current item
const previousItemsHeight = cumulativeHeight - itemsHeightArray.current[i];
hoveringPosition = linearIndex + (clientYRelativeToTreeTop - previousItemsHeight) / itemsHeightArray.current[i];
break;
}
}

const treeLinearItems = env.linearItems[treeId];
const linearIndex = Math.min(
Math.max(0, Math.floor(hoveringPosition)),
treeLinearItems.length - 1
);
// const linearIndexx = Math.min(
// Math.max(0, Math.floor(hoveringPosition)),
// treeLinearItems.length - 1
// );

if (treeLinearItems.length === 0) {
return {
Expand Down Expand Up @@ -149,13 +167,17 @@ export const useDraggingPosition = () => {
setDraggingItems(items);
dragCode.current = 'initial';
itemHeight.current = computeItemHeight(treeId);
itemsHeightArray.current = computeItemHeightArray(treeId);

}
);

const resetDraggingPosition = useStableHandler(() => {
setDraggingItems(undefined);
dragCode.current = 'initial';
itemHeight.current = 0;
itemsHeightArray.current = [0];

});

return {
Expand All @@ -164,5 +186,6 @@ export const useDraggingPosition = () => {
draggingItems,
getDraggingPosition,
itemHeight,
itemsHeightArray,
};
};
4 changes: 2 additions & 2 deletions packages/core/src/tree/DragBetweenLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useDragAndDrop } from '../drag/DragAndDropProvider';
export const DragBetweenLine: React.FC<{
treeId: string;
}> = ({ treeId }) => {
const { draggingPosition, itemHeight } = useDragAndDrop();
const { draggingPosition, itemHeight, itemsHeightArray } = useDragAndDrop();
const { renderers } = useTree();

const shouldDisplay =
Expand All @@ -28,7 +28,7 @@ export const DragBetweenLine: React.FC<{
position: 'absolute',
left: '0',
right: '0',
top: `${(draggingPosition?.linearIndex ?? 0) * itemHeight}px`,
top: `${itemsHeightArray.slice(0, draggingPosition?.linearIndex ?? 0).reduce((acc, height) => acc + height, 0)}px`,
}}
>
{renderers.renderDragBetweenLine({
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ export interface DragAndDropContextProps<T = any> {
onStartDraggingItems: (items: TreeItem<T>[], treeId: string) => void;
draggingItems?: TreeItem<T>[];
itemHeight: number;
itemsHeightArray: number[];
isProgrammaticallyDragging?: boolean;
startProgrammaticDrag: () => void;
abortProgrammaticDrag: () => void;
Expand Down