react-arborist 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ import { ElementType, MouseEventHandler } from "react";
5
5
  import { ListOnScrollProps } from "react-window";
6
6
  import { NodeApi } from "../interfaces/node-api";
7
7
  import { OpenMap } from "../state/open-slice";
8
+ import { useDragDropManager } from "react-dnd";
8
9
  export interface TreeProps<T> {
9
10
  data?: readonly T[];
10
11
  initialData?: readonly T[];
@@ -51,4 +52,5 @@ export interface TreeProps<T> {
51
52
  dndRootElement?: globalThis.Node | null;
52
53
  onClick?: MouseEventHandler;
53
54
  onContextMenu?: MouseEventHandler;
55
+ dndManager?: ReturnType<typeof useDragDropManager>;
54
56
  }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "react-arborist",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "license": "MIT",
5
5
  "source": "src/index.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/module.js",
8
8
  "types": "dist/index.d.ts",
9
+ "sideEffects": false,
9
10
  "scripts": {
10
- "start": "run-p 'watch:**'",
11
+ "start": "run-p 'start:**'",
11
12
  "build": "npm-run-all clean -p 'build:**'",
12
13
  "test": "jest",
13
14
  "build:js": "parcel build --target main --target module",
@@ -65,7 +65,7 @@ export function TreeProvider<T>({
65
65
  /* Change selection based on props */
66
66
  useEffect(() => {
67
67
  if (api.props.selection) {
68
- api.select(api.props.selection);
68
+ api.select(api.props.selection, { focus: false });
69
69
  } else {
70
70
  api.deselectAll();
71
71
  }
@@ -86,6 +86,7 @@ export function TreeProvider<T>({
86
86
  <DndProvider
87
87
  backend={HTML5Backend}
88
88
  options={{ rootElement: api.props.dndRootElement || undefined }}
89
+ {...(treeProps.dndManager && { manager: treeProps.dndManager })}
89
90
  >
90
91
  {children}
91
92
  </DndProvider>
@@ -29,24 +29,35 @@ function flattenAndFilterTree<T>(
29
29
  root: NodeApi<T>,
30
30
  isMatch: (n: NodeApi<T>) => boolean
31
31
  ): NodeApi<T>[] {
32
- function collect(node: NodeApi<T>) {
33
- let result: NodeApi<T>[] = [];
34
- const yes = !node.isRoot && isMatch(node);
32
+ const matches: Record<string, boolean> = {};
33
+ const list: NodeApi<T>[] = [];
35
34
 
36
- if (node.children) {
37
- for (let child of node.children) {
38
- result = result.concat(collect(child));
35
+ function markMatch(node: NodeApi<T>) {
36
+ const yes = !node.isRoot && isMatch(node);
37
+ if (yes) {
38
+ matches[node.id] = true;
39
+ let parent = node.parent;
40
+ while (parent) {
41
+ matches[parent.id] = true;
42
+ parent = parent.parent;
39
43
  }
40
44
  }
41
- if (result.length) {
42
- if (!node.isRoot) result.unshift(node);
43
- return result;
45
+ if (node.children) {
46
+ for (let child of node.children) markMatch(child);
44
47
  }
45
- if (yes) return [node];
46
- else return [];
47
48
  }
48
49
 
49
- const list = collect(root).filter((n) => n.parent?.isOpen);
50
+ function collect(node: NodeApi<T>) {
51
+ if (node.level >= 0 && matches[node.id]) {
52
+ list.push(node);
53
+ }
54
+ if (node.isOpen) {
55
+ node.children?.forEach(collect);
56
+ }
57
+ }
58
+
59
+ markMatch(root);
60
+ collect(root);
50
61
  list.forEach(assignRowIndex);
51
62
  return list;
52
63
  }
@@ -323,15 +323,18 @@ export class TreeApi<T> {
323
323
  this.focus(this.at(index));
324
324
  }
325
325
 
326
- select(node: Identity, opts: { align?: Align } = {}) {
326
+ select(node: Identity, opts: { align?: Align; focus?: boolean } = {}) {
327
327
  if (!node) return;
328
+ const changeFocus = opts.focus !== false;
328
329
  const id = identify(node);
329
- this.dispatch(focus(id));
330
+ if (changeFocus) this.dispatch(focus(id));
330
331
  this.dispatch(selection.only(id));
331
332
  this.dispatch(selection.anchor(id));
332
333
  this.dispatch(selection.mostRecent(id));
333
334
  this.scrollTo(id, opts.align);
334
- if (this.focusedNode) safeRun(this.props.onFocus, this.focusedNode);
335
+ if (this.focusedNode && changeFocus) {
336
+ safeRun(this.props.onFocus, this.focusedNode);
337
+ }
335
338
  safeRun(this.props.onSelect, this.selectedNodes);
336
339
  }
337
340
 
@@ -5,6 +5,7 @@ import { ElementType, MouseEventHandler } from "react";
5
5
  import { ListOnScrollProps } from "react-window";
6
6
  import { NodeApi } from "../interfaces/node-api";
7
7
  import { OpenMap } from "../state/open-slice";
8
+ import { useDragDropManager } from "react-dnd"
8
9
 
9
10
  export interface TreeProps<T> {
10
11
  /* Data Options */
@@ -75,4 +76,5 @@ export interface TreeProps<T> {
75
76
  dndRootElement?: globalThis.Node | null;
76
77
  onClick?: MouseEventHandler;
77
78
  onContextMenu?: MouseEventHandler;
79
+ dndManager?: ReturnType<typeof useDragDropManager>
78
80
  }