From 2fe84f523881766f1be7c8ae0867304c7cf7d9e2 Mon Sep 17 00:00:00 2001 From: AustinMKerr Date: Tue, 16 Apr 2024 07:51:47 -0400 Subject: [PATCH 1/3] added itemsHeightArray to replace ItemHeight and refactored the code using this new const to make the drag and drop functions use a dynamic height of each tree's exact items instead using the static height of the first item then multiplying it as they had with itemHeight. I didn't delete itemHeight in case any function uses it, but likely nothing uses it. --- .../src/controlledEnvironment/layoutUtils.ts | 13 ++++++++ .../core/src/drag/DragAndDropProvider.tsx | 3 ++ packages/core/src/drag/useDraggingPosition.ts | 33 ++++++++++++++++--- packages/core/src/tree/DragBetweenLine.tsx | 4 +-- packages/core/src/types.ts | 1 + packages/docs/docs/guides/multiple-trees.mdx | 2 ++ 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/core/src/controlledEnvironment/layoutUtils.ts b/packages/core/src/controlledEnvironment/layoutUtils.ts index c2648002e..a8ce214db 100644 --- a/packages/core/src/controlledEnvironment/layoutUtils.ts +++ b/packages/core/src/controlledEnvironment/layoutUtils.ts @@ -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(`[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 || diff --git a/packages/core/src/drag/DragAndDropProvider.tsx b/packages/core/src/drag/DragAndDropProvider.tsx index 101c9f5ad..3ea08d926 100644 --- a/packages/core/src/drag/DragAndDropProvider.tsx +++ b/packages/core/src/drag/DragAndDropProvider.tsx @@ -41,6 +41,7 @@ export const DragAndDropProvider: React.FC = ({ draggingItems, getDraggingPosition, itemHeight, + itemsHeightArray, } = useDraggingPosition(); const resetProgrammaticDragIndexForCurrentTree = useCallback( @@ -285,6 +286,7 @@ export const DragAndDropProvider: React.FC = ({ draggingItems, draggingPosition, itemHeight: itemHeight.current, + itemsHeightArray: itemsHeightArray.current, isProgrammaticallyDragging, onDragOverTreeHandler, viableDragPositions, @@ -296,6 +298,7 @@ export const DragAndDropProvider: React.FC = ({ draggingPosition, isProgrammaticallyDragging, itemHeight, + itemsHeightArray, onDragOverTreeHandler, onStartDraggingItems, programmaticDragDown, diff --git a/packages/core/src/drag/useDraggingPosition.ts b/packages/core/src/drag/useDraggingPosition.ts index 672bbd814..a267421b4 100644 --- a/packages/core/src/drag/useDraggingPosition.ts +++ b/packages/core/src/drag/useDraggingPosition.ts @@ -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'; @@ -16,6 +17,7 @@ export const useDraggingPosition = () => { undefined ); const itemHeight = useRef(0); + const itemsHeightArray = useRef([0]); const env = useTreeEnvironment(); const getParentOfLinearItem = useGetGetParentOfLinearItem(); @@ -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 { @@ -149,6 +167,8 @@ export const useDraggingPosition = () => { setDraggingItems(items); dragCode.current = 'initial'; itemHeight.current = computeItemHeight(treeId); + itemsHeightArray.current = computeItemHeightArray(treeId); + } ); @@ -156,6 +176,8 @@ export const useDraggingPosition = () => { setDraggingItems(undefined); dragCode.current = 'initial'; itemHeight.current = 0; + itemsHeightArray.current = [0]; + }); return { @@ -164,5 +186,6 @@ export const useDraggingPosition = () => { draggingItems, getDraggingPosition, itemHeight, + itemsHeightArray, }; }; diff --git a/packages/core/src/tree/DragBetweenLine.tsx b/packages/core/src/tree/DragBetweenLine.tsx index 5d32b1e41..afc8fd1c2 100644 --- a/packages/core/src/tree/DragBetweenLine.tsx +++ b/packages/core/src/tree/DragBetweenLine.tsx @@ -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 = @@ -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({ diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index d8a2fda0d..3dfb367b4 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -312,6 +312,7 @@ export interface DragAndDropContextProps { onStartDraggingItems: (items: TreeItem[], treeId: string) => void; draggingItems?: TreeItem[]; itemHeight: number; + itemsHeightArray: number[]; isProgrammaticallyDragging?: boolean; startProgrammaticDrag: () => void; abortProgrammaticDrag: () => void; diff --git a/packages/docs/docs/guides/multiple-trees.mdx b/packages/docs/docs/guides/multiple-trees.mdx index 3f057da8a..9b8cc0e5c 100644 --- a/packages/docs/docs/guides/multiple-trees.mdx +++ b/packages/docs/docs/guides/multiple-trees.mdx @@ -70,6 +70,8 @@ still show different contents. canDragAndDrop={true} canDropOnFolder={true} canReorderItems={true} + renderItemTitle={({ title }) =>
+ {title} {title} {title} {title}
} dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))} getItemTitle={item => item.data} viewState={{}} From 18d358c49eae4a5cbc9a439e8ef0005e89127ff4 Mon Sep 17 00:00:00 2001 From: AustinMKerr Date: Tue, 16 Apr 2024 08:06:54 -0400 Subject: [PATCH 2/3] removed a modification to one of the doc environments I used to test code. --- packages/docs/docs/guides/multiple-trees.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/docs/docs/guides/multiple-trees.mdx b/packages/docs/docs/guides/multiple-trees.mdx index 9b8cc0e5c..3f057da8a 100644 --- a/packages/docs/docs/guides/multiple-trees.mdx +++ b/packages/docs/docs/guides/multiple-trees.mdx @@ -70,8 +70,6 @@ still show different contents. canDragAndDrop={true} canDropOnFolder={true} canReorderItems={true} - renderItemTitle={({ title }) =>
- {title} {title} {title} {title}
} dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))} getItemTitle={item => item.data} viewState={{}} From 615aba96192250504d5930a43fd324e9966bea5a Mon Sep 17 00:00:00 2001 From: AustinMKerr Date: Tue, 16 Apr 2024 21:29:05 -0400 Subject: [PATCH 3/3] updated next release notes --- next-release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next-release-notes.md b/next-release-notes.md index f77d5bd6a..6d44c05fb 100644 --- a/next-release-notes.md +++ b/next-release-notes.md @@ -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 --> \ No newline at end of file