react-arborist 0.2.0 → 1.0.3

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.
package/src/tree-api.ts CHANGED
@@ -4,9 +4,12 @@ import { FixedSizeList } from "react-window";
4
4
  import { flattenTree } from "./data/flatten-tree";
5
5
  import { Cursor } from "./dnd/compute-drop";
6
6
  import { Action, actions } from "./reducer";
7
- import { Node, StateContext, TreeProviderProps } from "./types";
7
+ import { Node, StateContext, TreeProviderProps, EditResult } from "./types";
8
+ import ReactDOM from "react-dom";
8
9
 
9
10
  export class TreeApi<T = unknown> {
11
+ private edits = new Map<string, (args: EditResult) => void>();
12
+
10
13
  constructor(
11
14
  public dispatch: Dispatch<Action>,
12
15
  public state: StateContext,
@@ -36,14 +39,42 @@ export class TreeApi<T = unknown> {
36
39
  return this.state.selection.ids;
37
40
  }
38
41
 
39
- edit(id: string | number | null) {
40
- this.dispatch(actions.edit(id ? id.toString() : null));
42
+ edit(id: string | number): Promise<EditResult> {
43
+ const sid = id.toString();
44
+ this.resolveEdit(sid, { cancelled: true });
45
+ this.scrollToId(sid);
46
+ this.dispatch(actions.edit(sid));
47
+ return new Promise((resolve) => this.edits.set(sid, resolve));
48
+ }
49
+
50
+ submit(id: string | number, value: string) {
51
+ const sid = id.toString();
52
+ this.props.onEdit(sid, value);
53
+ this.dispatch(actions.edit(null));
54
+ this.resolveEdit(sid, { cancelled: false, value });
55
+ }
56
+
57
+ reset(id: string | number) {
58
+ const sid = id.toString();
59
+ this.dispatch(actions.edit(null));
60
+ this.resolveEdit(sid, { cancelled: true });
41
61
  }
42
62
 
43
- select(index: number | null, meta: boolean, shift: boolean) {
63
+ private resolveEdit(id: string, value: EditResult) {
64
+ const resolve = this.edits.get(id.toString());
65
+ if (resolve) resolve(value);
66
+ this.edits.delete(id);
67
+ }
68
+
69
+ select(index: number | null, meta = false, shift = false) {
44
70
  this.dispatch(actions.select(index, meta, shift));
45
71
  }
46
72
 
73
+ selectById(id: string | number, meta = false, shift = false) {
74
+ const index = this.idToIndex[id];
75
+ this.select(index, meta, shift);
76
+ }
77
+
47
78
  selectUpwards(shiftKey: boolean) {
48
79
  this.dispatch(actions.stepUp(shiftKey, this.visibleIds));
49
80
  }
@@ -67,11 +98,7 @@ export class TreeApi<T = unknown> {
67
98
  this.list.scrollToItem(index, "start");
68
99
  } else {
69
100
  this.openParents(id);
70
- // This appears to be synchronous
71
- // But I've only tested it in the console and
72
- // not in an event handler which will be batched...
73
- // We may need to wrap this in a timeout or trigger an effect somehow
74
- setTimeout(() => {
101
+ ReactDOM.flushSync(() => {
75
102
  const index = this.idToIndex[id];
76
103
  if (index) {
77
104
  this.list?.scrollToItem(index, "start");
package/src/types.ts CHANGED
@@ -53,15 +53,15 @@ export type NodeState = {
53
53
  isSelected: boolean;
54
54
  isHoveringOverChild: boolean;
55
55
  isDragging: boolean;
56
- isFirstOfSelected: boolean;
57
- isLastOfSelected: boolean;
56
+ isSelectedStart: boolean;
57
+ isSelectedEnd: boolean;
58
58
  isEditing: boolean;
59
59
  };
60
60
 
61
61
  export type NodeHandlers = {
62
62
  toggle: MouseEventHandler;
63
- select: (e: MouseEvent, selectOnClick?: boolean) => void;
64
- edit: () => void;
63
+ select: (e: MouseEvent, args: { selectOnClick: boolean }) => void;
64
+ edit: () => Promise<EditResult>;
65
65
  submit: (name: string) => void;
66
66
  reset: () => void;
67
67
  };
@@ -145,3 +145,7 @@ export type StaticContext<T> = TreeProviderProps<T> & {
145
145
  api: TreeApi<T>;
146
146
  list: MutableRefObject<FixedSizeList | undefined>;
147
147
  };
148
+
149
+ export type EditResult =
150
+ | { cancelled: true }
151
+ | { cancelled: false; value: string };