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 ae57e02 commit e50562f
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 14 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 @@ -370,21 +370,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
4 changes: 2 additions & 2 deletions packages/react-arborist/src/types/tree-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ElementType, MouseEventHandler } from "react";
import { ListOnScrollProps } from "react-window";
import { NodeApi } from "../interfaces/node-api";
import { OpenMap } from "../state/open-slice";
import { useDragDropManager } from "react-dnd"
import { useDragDropManager } from "react-dnd";

export interface TreeProps<T> {
/* Data Options */
Expand Down Expand Up @@ -76,5 +76,5 @@ export interface TreeProps<T> {
dndRootElement?: globalThis.Node | null;
onClick?: MouseEventHandler;
onContextMenu?: MouseEventHandler;
dndManager?: ReturnType<typeof useDragDropManager>
dndManager?: ReturnType<typeof useDragDropManager>;
}
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 e50562f

Please sign in to comment.