react-arborist 0.2.0 → 1.0.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.
- package/dist/index.js +54 -27
- package/dist/index.js.map +1 -1
- package/dist/module.js +54 -27
- package/dist/module.js.map +1 -1
- package/dist/tree-api.d.ts +8 -3
- package/dist/types.d.ts +12 -4
- package/package.json +2 -3
- package/src/components/preview.tsx +3 -3
- package/src/components/row.tsx +10 -15
- package/src/tree-api.ts +36 -9
- package/src/types.ts +8 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-arborist",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,6 +31,5 @@
|
|
|
31
31
|
"react": "^17.0.2",
|
|
32
32
|
"react-dom": "^17.0.2",
|
|
33
33
|
"typescript": "^4.6.2"
|
|
34
|
-
}
|
|
35
|
-
"stableVersion": "0.2.0-beta.0"
|
|
34
|
+
}
|
|
36
35
|
}
|
|
@@ -91,13 +91,13 @@ const PreviewNode = memo(function PreviewNode(props: {
|
|
|
91
91
|
isDragging: false,
|
|
92
92
|
isEditing: false,
|
|
93
93
|
isSelected: false,
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
isSelectedStart: false,
|
|
95
|
+
isSelectedEnd: false,
|
|
96
96
|
isHoveringOverChild: false,
|
|
97
97
|
isOpen: node.isOpen,
|
|
98
98
|
}}
|
|
99
99
|
handlers={{
|
|
100
|
-
edit: () => {},
|
|
100
|
+
edit: () => Promise.resolve({ cancelled: true }),
|
|
101
101
|
select: () => {},
|
|
102
102
|
toggle: () => {},
|
|
103
103
|
submit: () => {},
|
package/src/components/row.tsx
CHANGED
|
@@ -37,8 +37,8 @@ export const Row = React.memo(function Row({ index, style }: Props) {
|
|
|
37
37
|
return {
|
|
38
38
|
isEditing,
|
|
39
39
|
isDragging,
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
isSelectedStart: isSelected && !prevSelected,
|
|
41
|
+
isSelectedEnd: isSelected && !nextSelected,
|
|
42
42
|
isSelected,
|
|
43
43
|
isHoveringOverChild,
|
|
44
44
|
isOpen,
|
|
@@ -54,9 +54,6 @@ export const Row = React.memo(function Row({ index, style }: Props) {
|
|
|
54
54
|
isDragging,
|
|
55
55
|
isOverFolder,
|
|
56
56
|
]);
|
|
57
|
-
if (isSelected) {
|
|
58
|
-
console.log({id: node.id, state})
|
|
59
|
-
}
|
|
60
57
|
|
|
61
58
|
const ref = useCallback(
|
|
62
59
|
(n: HTMLDivElement | null) => {
|
|
@@ -76,9 +73,12 @@ export const Row = React.memo(function Row({ index, style }: Props) {
|
|
|
76
73
|
|
|
77
74
|
const handlers = useMemo(() => {
|
|
78
75
|
return {
|
|
79
|
-
select: (
|
|
76
|
+
select: (
|
|
77
|
+
e: React.MouseEvent,
|
|
78
|
+
args: { selectOnClick: boolean } = { selectOnClick: true }
|
|
79
|
+
) => {
|
|
80
80
|
if (node.rowIndex === null) return;
|
|
81
|
-
if (selectOnClick || e.metaKey || e.shiftKey) {
|
|
81
|
+
if (args.selectOnClick || e.metaKey || e.shiftKey) {
|
|
82
82
|
tree.api.select(node.rowIndex, e.metaKey, e.shiftKey);
|
|
83
83
|
} else {
|
|
84
84
|
tree.api.select(null, false, false);
|
|
@@ -88,16 +88,11 @@ export const Row = React.memo(function Row({ index, style }: Props) {
|
|
|
88
88
|
e.stopPropagation();
|
|
89
89
|
tree.onToggle(node.id, !node.isOpen);
|
|
90
90
|
},
|
|
91
|
-
edit: () =>
|
|
92
|
-
tree.api.edit(node.id);
|
|
93
|
-
},
|
|
91
|
+
edit: () => tree.api.edit(node.id),
|
|
94
92
|
submit: (name: string) => {
|
|
95
|
-
|
|
96
|
-
tree.api.edit(null);
|
|
97
|
-
},
|
|
98
|
-
reset: () => {
|
|
99
|
-
tree.api.edit(null);
|
|
93
|
+
name.trim() ? tree.api.submit(node.id, name) : tree.api.reset(node.id);
|
|
100
94
|
},
|
|
95
|
+
reset: () => tree.api.reset(node.id),
|
|
101
96
|
};
|
|
102
97
|
}, [tree, node]);
|
|
103
98
|
|
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
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
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
|
|
64
|
-
edit: () =>
|
|
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 };
|