Skip to content

Commit 8d789ed

Browse files
committed
feat: add method scrollToNode
1 parent 10091a6 commit 8d789ed

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

lib/HeTree.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,23 @@ export function useHeTree<T extends Record<string, any>>(
601601
}
602602
return index
603603
}
604-
return { visibleIds, attrsList, onDragOverRoot, onDropToRoot, onDragEndOnRoot }
604+
function scrollToNode(idOrNodeOrStat: Id | T | Stat<T>, block: 'start' | 'end' | 'center' | 'nearest' = 'start') {
605+
const stat = getStat(idOrNodeOrStat)
606+
if (!stat) {
607+
return false
608+
}
609+
let index = visibleIds.indexOf(stat.id)
610+
if (index === -1) {
611+
return false
612+
}
613+
if (virtualListRef.current) {
614+
virtualListRef.current.scrollToIndex(index, block)
615+
return true
616+
} else {
617+
return false
618+
}
619+
}
620+
return { visibleIds, attrsList, onDragOverRoot, onDropToRoot, onDragEndOnRoot, scrollToNode }
605621
}, [mainCache, indent, draggingStat,
606622
// watch placeholder position
607623
placeholder?.parentStat, placeholder?.index,
@@ -639,7 +655,7 @@ export function useHeTree<T extends Record<string, any>>(
639655
}, [props.keepPlaceholder])
640656
useAddEventListener(t2.getEl, 'dragover', t2.onDragOverWindow)
641657
//
642-
const { visibleIds, attrsList, onDragOverRoot, onDropToRoot, onDragEndOnRoot } = cacheForVisible
658+
const { visibleIds, attrsList, onDragOverRoot, onDropToRoot, onDragEndOnRoot, scrollToNode } = cacheForVisible
643659
const persistentIndices = useMemo(() => draggingStat ? [visibleIds.indexOf(draggingStat.id)] : [], [draggingStat, visibleIds]);
644660
// render
645661
const renderTree = (options?: { className?: string, style?: React.CSSProperties }): ReactNode => {
@@ -671,6 +687,8 @@ export function useHeTree<T extends Record<string, any>>(
671687
draggingStat, dragOverStat, placeholder,
672688
// render
673689
renderTree, renderHeTree: renderTree,
690+
// methods
691+
scrollToNode,
674692
}
675693
}
676694
// react components ==================================

src/PageLayout.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ export default function PageLayout(props: {}) {
6565
title: 'Big Data with Virtual List',
6666
path: '/virtual_list'
6767
},
68+
{
69+
title: 'Scroll to Node',
70+
path: '/scroll_to_node',
71+
},
6872
{
6973
title: 'Home',
7074
path: '/',

src/main.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const Pages = {
2323
dragopen: lazy(() => import("./pages/dragopen.tsx")),
2424
external_drag: lazy(() => import("./pages/external_drag.tsx")),
2525
virtual_list: lazy(() => import("./pages/virtual_list.tsx")),
26+
scroll_to_node: lazy(() => import("./pages/scroll_to_node.tsx")),
2627
}
2728
const router = createHashRouter([
2829
{
@@ -85,6 +86,10 @@ const router = createHashRouter([
8586
path: "/virtual_list",
8687
element: <Pages.virtual_list />,
8788
},
89+
{
90+
path: '/scroll_to_node',
91+
element: <Pages.scroll_to_node />
92+
},
8893
]
8994
},
9095
]);

src/pages/scroll_to_node.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { useHeTree, sortFlatData } from "he-tree-react";
2+
import type { Id } from "he-tree-react";
3+
import { useState } from 'react';
4+
5+
export default function BasePage() {
6+
const keys = { idKey: 'id', parentIdKey: 'pid' };
7+
// prettier-ignore
8+
const [data, setdata] = useState(() => sortFlatData(createData(), keys));
9+
const [openIds, setopenIds] = useState<Id[] | undefined>([]);
10+
const handleOpen = (id: Id, open: boolean) => {
11+
if (open) {
12+
setopenIds([...(openIds || allIds), id]);
13+
} else {
14+
setopenIds((openIds || allIds).filter((i) => i !== id));
15+
}
16+
}
17+
const { renderTree, allIds, scrollToNode } = useHeTree({
18+
...keys,
19+
data,
20+
dataType: 'flat',
21+
onChange: setdata,
22+
openIds,
23+
virtual: true,
24+
renderNode: ({ id, node, open, checked, draggable }) => <div>
25+
<button onClick={() => handleOpen(id, !open)}>{open ? '-' : '+'}</button>
26+
{id}
27+
</div>,
28+
})
29+
return <div>
30+
<button onClick={() => scrollToNode(910)}>Scroll to 910</button>
31+
{renderTree({ style: { width: '300px', height: '300px', border: '1px solid #555', padding: '20px' } })}
32+
</div>
33+
}
34+
35+
// generate 10000 nodes
36+
function createData() {
37+
const genId = () => result.length
38+
const result: { id: number, pid: number | null }[] = [];
39+
for (let i = 0; i < 1000; i++) {
40+
let id1 = genId()
41+
result.push({ id: id1, pid: null })
42+
for (let j = 0; j < 4; j++) {
43+
result.push({ id: genId(), pid: id1 })
44+
}
45+
let id2 = genId()
46+
result.push({ id: id2, pid: null })
47+
for (let j = 0; j < 4; j++) {
48+
result.push({ id: genId(), pid: id2 })
49+
}
50+
}
51+
return result;
52+
}

0 commit comments

Comments
 (0)