Skip to content

Commit

Permalink
Add a treeApi.setSelection method.
Browse files Browse the repository at this point in the history
  • Loading branch information
jameskerr committed Jul 24, 2023
1 parent 87065fe commit 53686d8
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 13 deletions.
1 change: 0 additions & 1 deletion packages/react-arborist/src/components/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
TreeApiContext,
} from "../context";
import { TreeApi } from "../interfaces/tree-api";
import { IdObj } from "../types/utils";
import { initialState } from "../state/initial";
import { rootReducer, RootState } from "../state/root-reducer";
import { HTML5Backend } from "react-dnd-html5-backend";
Expand Down
24 changes: 18 additions & 6 deletions packages/react-arborist/src/interfaces/tree-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,21 +367,33 @@ export class TreeApi<T> {
}

deselectAll() {
this.dispatch(selection.clear());
this.dispatch(selection.anchor(null));
this.dispatch(selection.mostRecent(null));
this.setSelection({ ids: [], anchor: null, mostRecent: null });
safeRun(this.props.onSelect, this.selectedNodes);
}

selectAll() {
this.dispatch(selection.set(new Set(Object.keys(this.idToIndex))));
this.setSelection({
ids: Object.keys(this.idToIndex),
anchor: this.firstNode,
mostRecent: this.lastNode,
});
this.dispatch(focus(this.lastNode?.id));
this.dispatch(selection.anchor(this.firstNode));
this.dispatch(selection.mostRecent(this.lastNode));
if (this.focusedNode) safeRun(this.props.onFocus, this.focusedNode);
safeRun(this.props.onSelect, this.selectedNodes);
}

setSelection(args: {
ids: (IdObj | string)[] | null;
anchor: IdObj | string | null;
mostRecent: IdObj | string | null;
}) {
const ids = new Set(args.ids?.map(identify));
const anchor = identifyNull(args.anchor);
const mostRecent = identifyNull(args.mostRecent);
this.dispatch(selection.set({ ids, anchor, mostRecent }));
safeRun(this.props.onSelect, this.selectedNodes);
}

/* Drag and Drop */

get cursorParentId() {
Expand Down
15 changes: 12 additions & 3 deletions packages/react-arborist/src/state/selection-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ export const actions = {
ids: (Array.isArray(id) ? id : [id]).map(identify),
}),

set: (ids: Set<string>) => ({
set: (args: {
ids: Set<string>;
anchor: string | null;
mostRecent: string | null;
}) => ({
type: "SELECTION_SET" as const,
ids,
...args,
}),

mostRecent: (id: string | null | IdObj) => ({
Expand Down Expand Up @@ -64,7 +68,12 @@ export function reducer(
action.ids.forEach((id) => ids.delete(id));
return { ...state, ids: new Set(ids) };
case "SELECTION_SET":
return { ...state, ids: new Set(action.ids) };
return {
...state,
ids: action.ids,
mostRecent: action.mostRecent,
anchor: action.anchor,
};
case "SELECTION_MOST_RECENT":
return { ...state, mostRecent: action.id };
case "SELECTION_ANCHOR":
Expand Down
6 changes: 5 additions & 1 deletion packages/react-arborist/src/types/tree-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export interface TreeProps<T> {
disableMultiSelection?: boolean;
disableEdit?: string | boolean | BoolFunc<T>;
disableDrag?: string | boolean | BoolFunc<T>;
disableDrop?: string | boolean | BoolFunc<T> | ((node: NodeApi, dragNodes: NodeApi[]) => boolean);
disableDrop?:
| string
| boolean
| BoolFunc<T>
| ((node: NodeApi, dragNodes: NodeApi[]) => boolean);
childrenAccessor?: string | ((d: T) => T[] | null);
idAccessor?: string | ((d: T) => string);

Expand Down
16 changes: 14 additions & 2 deletions packages/showcase/pages/gmail.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import clsx from "clsx";
import { CursorProps, NodeApi, NodeRendererProps, Tree } from "react-arborist";
import {
CursorProps,
NodeApi,
NodeRendererProps,
Tree,
TreeApi,
} from "react-arborist";
import { gmailData, GmailItem } from "../data/gmail";
import * as icons from "react-icons/md";
import styles from "../styles/gmail.module.css";
import { FillFlexParent } from "../components/fill-flex-parent";
import { SiGmail } from "react-icons/si";
import { BsTree } from "react-icons/bs";
import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import Link from "next/link";

export default function GmailSidebar() {
const [term, setTerm] = useState("");
const globalTree = (tree: TreeApi<any> | null) => {
// @ts-ignore
window.tree = tree;
};

return (
<div className={styles.page}>
<div className={styles.mainContent}>
Expand All @@ -28,6 +39,7 @@ export default function GmailSidebar() {
{({ width, height }) => {
return (
<Tree
ref={globalTree}
initialData={gmailData}
width={width}
height={height}
Expand Down

0 comments on commit 53686d8

Please sign in to comment.