react-arborist 3.3.1 → 3.4.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/main/dnd/compute-drop.d.ts +0 -1
- package/dist/main/dnd/compute-drop.js +37 -23
- package/dist/main/utils.d.ts +1 -0
- package/dist/main/utils.js +6 -1
- package/dist/module/dnd/compute-drop.d.ts +0 -1
- package/dist/module/dnd/compute-drop.js +38 -24
- package/dist/module/utils.d.ts +1 -0
- package/dist/module/utils.js +4 -0
- package/package.json +1 -1
- package/src/dnd/compute-drop.ts +46 -29
- package/src/utils.ts +4 -0
|
@@ -31,7 +31,6 @@ export type HighlightCursor = ReturnType<typeof highlightCursor>;
|
|
|
31
31
|
export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
32
32
|
/**
|
|
33
33
|
* This is the most complex, tricky function in the whole repo.
|
|
34
|
-
* It could be simplified and made more understandable.
|
|
35
34
|
*/
|
|
36
35
|
export declare function computeDrop(args: Args): ComputedDrop;
|
|
37
36
|
export {};
|
|
@@ -41,23 +41,6 @@ function getNodesAroundCursor(node, prev, next, hover) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
function getDropLevel(hovering, aboveCursor, belowCursor, indent) {
|
|
45
|
-
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
|
|
46
|
-
let min, max;
|
|
47
|
-
if (!aboveCursor) {
|
|
48
|
-
max = 0;
|
|
49
|
-
min = 0;
|
|
50
|
-
}
|
|
51
|
-
else if (!belowCursor) {
|
|
52
|
-
max = aboveCursor.level;
|
|
53
|
-
min = 0;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
max = aboveCursor.level;
|
|
57
|
-
min = belowCursor.level;
|
|
58
|
-
}
|
|
59
|
-
return (0, utils_1.bound)(hoverLevel, min, max);
|
|
60
|
-
}
|
|
61
44
|
function dropAt(parentId, index) {
|
|
62
45
|
return { parentId: parentId || null, index };
|
|
63
46
|
}
|
|
@@ -91,11 +74,12 @@ function walkUpFrom(node, level) {
|
|
|
91
74
|
}
|
|
92
75
|
/**
|
|
93
76
|
* This is the most complex, tricky function in the whole repo.
|
|
94
|
-
* It could be simplified and made more understandable.
|
|
95
77
|
*/
|
|
96
78
|
function computeDrop(args) {
|
|
97
79
|
var _a;
|
|
98
80
|
const hover = measureHover(args.element, args.offset);
|
|
81
|
+
const indent = args.indent;
|
|
82
|
+
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
|
|
99
83
|
const { node, nextNode, prevNode } = args;
|
|
100
84
|
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);
|
|
101
85
|
/* Hovering over the middle of a folder */
|
|
@@ -105,22 +89,52 @@ function computeDrop(args) {
|
|
|
105
89
|
cursor: highlightCursor(node.id),
|
|
106
90
|
};
|
|
107
91
|
}
|
|
108
|
-
/*
|
|
92
|
+
/*
|
|
93
|
+
* Now we only need to care about the node above the cursor
|
|
94
|
+
* ----------- -------
|
|
95
|
+
*/
|
|
96
|
+
/* There is no node above the cursor line */
|
|
109
97
|
if (!above) {
|
|
110
98
|
return {
|
|
111
99
|
drop: dropAt((_a = below === null || below === void 0 ? void 0 : below.parent) === null || _a === void 0 ? void 0 : _a.id, 0),
|
|
112
100
|
cursor: lineCursor(0, 0),
|
|
113
101
|
};
|
|
114
102
|
}
|
|
115
|
-
/* The above
|
|
116
|
-
if ((0, utils_1.isItem)(above)
|
|
117
|
-
const level =
|
|
103
|
+
/* The node above the cursor line is an item */
|
|
104
|
+
if ((0, utils_1.isItem)(above)) {
|
|
105
|
+
const level = (0, utils_1.bound)(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
106
|
+
return {
|
|
107
|
+
drop: walkUpFrom(above, level),
|
|
108
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/* The node above the cursor line is a closed folder */
|
|
112
|
+
if ((0, utils_1.isClosed)(above)) {
|
|
113
|
+
const level = (0, utils_1.bound)(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
118
114
|
return {
|
|
119
115
|
drop: walkUpFrom(above, level),
|
|
120
116
|
cursor: lineCursor(above.rowIndex + 1, level),
|
|
121
117
|
};
|
|
122
118
|
}
|
|
123
|
-
/* The above
|
|
119
|
+
/* The node above the cursor line is an open folder with no children */
|
|
120
|
+
if ((0, utils_1.isOpenWithEmptyChildren)(above)) {
|
|
121
|
+
const level = (0, utils_1.bound)(hoverLevel, 0, above.level + 1);
|
|
122
|
+
if (level > above.level) {
|
|
123
|
+
/* Will be the first child of the empty folder */
|
|
124
|
+
return {
|
|
125
|
+
drop: dropAt(above.id, 0),
|
|
126
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
/* Will be a sibling or grandsibling of the empty folder */
|
|
131
|
+
return {
|
|
132
|
+
drop: walkUpFrom(above, level),
|
|
133
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/* The node above the cursor is a an open folder with children */
|
|
124
138
|
return {
|
|
125
139
|
drop: dropAt(above === null || above === void 0 ? void 0 : above.id, 0),
|
|
126
140
|
cursor: lineCursor(above.rowIndex + 1, above.level + 1),
|
package/dist/main/utils.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { IdObj } from "./types/utils";
|
|
|
4
4
|
export declare function bound(n: number, min: number, max: number): number;
|
|
5
5
|
export declare function isItem(node: NodeApi<any> | null): boolean | null;
|
|
6
6
|
export declare function isClosed(node: NodeApi<any> | null): boolean | null;
|
|
7
|
+
export declare function isOpenWithEmptyChildren(node: NodeApi<any> | null): boolean | null;
|
|
7
8
|
/**
|
|
8
9
|
* Is first param a descendant of the second param
|
|
9
10
|
*/
|
package/dist/main/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getInsertParentId = exports.getInsertIndex = exports.waitFor = exports.safeRun = exports.mergeRefs = exports.identify = exports.identifyNull = exports.access = exports.focusPrevElement = exports.focusNextElement = exports.walk = exports.dfs = exports.noop = exports.indexOf = exports.isDescendant = exports.isClosed = exports.isItem = exports.bound = void 0;
|
|
3
|
+
exports.getInsertParentId = exports.getInsertIndex = exports.waitFor = exports.safeRun = exports.mergeRefs = exports.identify = exports.identifyNull = exports.access = exports.focusPrevElement = exports.focusNextElement = exports.walk = exports.dfs = exports.noop = exports.indexOf = exports.isDescendant = exports.isOpenWithEmptyChildren = exports.isClosed = exports.isItem = exports.bound = void 0;
|
|
4
4
|
function bound(n, min, max) {
|
|
5
5
|
return Math.max(Math.min(n, max), min);
|
|
6
6
|
}
|
|
@@ -13,6 +13,11 @@ function isClosed(node) {
|
|
|
13
13
|
return node && node.isInternal && !node.isOpen;
|
|
14
14
|
}
|
|
15
15
|
exports.isClosed = isClosed;
|
|
16
|
+
function isOpenWithEmptyChildren(node) {
|
|
17
|
+
var _a;
|
|
18
|
+
return node && node.isOpen && !((_a = node.children) === null || _a === void 0 ? void 0 : _a.length);
|
|
19
|
+
}
|
|
20
|
+
exports.isOpenWithEmptyChildren = isOpenWithEmptyChildren;
|
|
16
21
|
/**
|
|
17
22
|
* Is first param a descendant of the second param
|
|
18
23
|
*/
|
|
@@ -31,7 +31,6 @@ export type HighlightCursor = ReturnType<typeof highlightCursor>;
|
|
|
31
31
|
export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
32
32
|
/**
|
|
33
33
|
* This is the most complex, tricky function in the whole repo.
|
|
34
|
-
* It could be simplified and made more understandable.
|
|
35
34
|
*/
|
|
36
35
|
export declare function computeDrop(args: Args): ComputedDrop;
|
|
37
36
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bound, indexOf, isClosed, isItem } from "../utils";
|
|
1
|
+
import { bound, indexOf, isClosed, isItem, isOpenWithEmptyChildren, } from "../utils";
|
|
2
2
|
function measureHover(el, offset) {
|
|
3
3
|
const rect = el.getBoundingClientRect();
|
|
4
4
|
const x = offset.x - Math.round(rect.x);
|
|
@@ -38,23 +38,6 @@ function getNodesAroundCursor(node, prev, next, hover) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
function getDropLevel(hovering, aboveCursor, belowCursor, indent) {
|
|
42
|
-
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
|
|
43
|
-
let min, max;
|
|
44
|
-
if (!aboveCursor) {
|
|
45
|
-
max = 0;
|
|
46
|
-
min = 0;
|
|
47
|
-
}
|
|
48
|
-
else if (!belowCursor) {
|
|
49
|
-
max = aboveCursor.level;
|
|
50
|
-
min = 0;
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
max = aboveCursor.level;
|
|
54
|
-
min = belowCursor.level;
|
|
55
|
-
}
|
|
56
|
-
return bound(hoverLevel, min, max);
|
|
57
|
-
}
|
|
58
41
|
function dropAt(parentId, index) {
|
|
59
42
|
return { parentId: parentId || null, index };
|
|
60
43
|
}
|
|
@@ -88,11 +71,12 @@ function walkUpFrom(node, level) {
|
|
|
88
71
|
}
|
|
89
72
|
/**
|
|
90
73
|
* This is the most complex, tricky function in the whole repo.
|
|
91
|
-
* It could be simplified and made more understandable.
|
|
92
74
|
*/
|
|
93
75
|
export function computeDrop(args) {
|
|
94
76
|
var _a;
|
|
95
77
|
const hover = measureHover(args.element, args.offset);
|
|
78
|
+
const indent = args.indent;
|
|
79
|
+
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
|
|
96
80
|
const { node, nextNode, prevNode } = args;
|
|
97
81
|
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);
|
|
98
82
|
/* Hovering over the middle of a folder */
|
|
@@ -102,22 +86,52 @@ export function computeDrop(args) {
|
|
|
102
86
|
cursor: highlightCursor(node.id),
|
|
103
87
|
};
|
|
104
88
|
}
|
|
105
|
-
/*
|
|
89
|
+
/*
|
|
90
|
+
* Now we only need to care about the node above the cursor
|
|
91
|
+
* ----------- -------
|
|
92
|
+
*/
|
|
93
|
+
/* There is no node above the cursor line */
|
|
106
94
|
if (!above) {
|
|
107
95
|
return {
|
|
108
96
|
drop: dropAt((_a = below === null || below === void 0 ? void 0 : below.parent) === null || _a === void 0 ? void 0 : _a.id, 0),
|
|
109
97
|
cursor: lineCursor(0, 0),
|
|
110
98
|
};
|
|
111
99
|
}
|
|
112
|
-
/* The above
|
|
113
|
-
if (isItem(above)
|
|
114
|
-
const level =
|
|
100
|
+
/* The node above the cursor line is an item */
|
|
101
|
+
if (isItem(above)) {
|
|
102
|
+
const level = bound(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
103
|
+
return {
|
|
104
|
+
drop: walkUpFrom(above, level),
|
|
105
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/* The node above the cursor line is a closed folder */
|
|
109
|
+
if (isClosed(above)) {
|
|
110
|
+
const level = bound(hoverLevel, (below === null || below === void 0 ? void 0 : below.level) || 0, above.level);
|
|
115
111
|
return {
|
|
116
112
|
drop: walkUpFrom(above, level),
|
|
117
113
|
cursor: lineCursor(above.rowIndex + 1, level),
|
|
118
114
|
};
|
|
119
115
|
}
|
|
120
|
-
/* The above
|
|
116
|
+
/* The node above the cursor line is an open folder with no children */
|
|
117
|
+
if (isOpenWithEmptyChildren(above)) {
|
|
118
|
+
const level = bound(hoverLevel, 0, above.level + 1);
|
|
119
|
+
if (level > above.level) {
|
|
120
|
+
/* Will be the first child of the empty folder */
|
|
121
|
+
return {
|
|
122
|
+
drop: dropAt(above.id, 0),
|
|
123
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
/* Will be a sibling or grandsibling of the empty folder */
|
|
128
|
+
return {
|
|
129
|
+
drop: walkUpFrom(above, level),
|
|
130
|
+
cursor: lineCursor(above.rowIndex + 1, level),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/* The node above the cursor is a an open folder with children */
|
|
121
135
|
return {
|
|
122
136
|
drop: dropAt(above === null || above === void 0 ? void 0 : above.id, 0),
|
|
123
137
|
cursor: lineCursor(above.rowIndex + 1, above.level + 1),
|
package/dist/module/utils.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { IdObj } from "./types/utils";
|
|
|
4
4
|
export declare function bound(n: number, min: number, max: number): number;
|
|
5
5
|
export declare function isItem(node: NodeApi<any> | null): boolean | null;
|
|
6
6
|
export declare function isClosed(node: NodeApi<any> | null): boolean | null;
|
|
7
|
+
export declare function isOpenWithEmptyChildren(node: NodeApi<any> | null): boolean | null;
|
|
7
8
|
/**
|
|
8
9
|
* Is first param a descendant of the second param
|
|
9
10
|
*/
|
package/dist/module/utils.js
CHANGED
|
@@ -7,6 +7,10 @@ export function isItem(node) {
|
|
|
7
7
|
export function isClosed(node) {
|
|
8
8
|
return node && node.isInternal && !node.isOpen;
|
|
9
9
|
}
|
|
10
|
+
export function isOpenWithEmptyChildren(node) {
|
|
11
|
+
var _a;
|
|
12
|
+
return node && node.isOpen && !((_a = node.children) === null || _a === void 0 ? void 0 : _a.length);
|
|
13
|
+
}
|
|
10
14
|
/**
|
|
11
15
|
* Is first param a descendant of the second param
|
|
12
16
|
*/
|
package/package.json
CHANGED
package/src/dnd/compute-drop.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { XYCoord } from "react-dnd";
|
|
2
2
|
import { NodeApi } from "../interfaces/node-api";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
bound,
|
|
5
|
+
indexOf,
|
|
6
|
+
isClosed,
|
|
7
|
+
isItem,
|
|
8
|
+
isOpenWithEmptyChildren,
|
|
9
|
+
} from "../utils";
|
|
4
10
|
import { DropResult } from "./drop-hook";
|
|
5
11
|
|
|
6
12
|
function measureHover(el: HTMLElement, offset: XYCoord) {
|
|
@@ -56,28 +62,6 @@ type Args = {
|
|
|
56
62
|
nextNode: NodeApi | null;
|
|
57
63
|
};
|
|
58
64
|
|
|
59
|
-
function getDropLevel(
|
|
60
|
-
hovering: HoverData,
|
|
61
|
-
aboveCursor: NodeApi | null,
|
|
62
|
-
belowCursor: NodeApi | null,
|
|
63
|
-
indent: number
|
|
64
|
-
) {
|
|
65
|
-
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
|
|
66
|
-
let min, max;
|
|
67
|
-
if (!aboveCursor) {
|
|
68
|
-
max = 0;
|
|
69
|
-
min = 0;
|
|
70
|
-
} else if (!belowCursor) {
|
|
71
|
-
max = aboveCursor.level;
|
|
72
|
-
min = 0;
|
|
73
|
-
} else {
|
|
74
|
-
max = aboveCursor.level;
|
|
75
|
-
min = belowCursor.level;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return bound(hoverLevel, min, max);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
65
|
export type ComputedDrop = {
|
|
82
66
|
drop: DropResult | null;
|
|
83
67
|
cursor: Cursor | null;
|
|
@@ -128,10 +112,11 @@ export type Cursor = LineCursor | NoCursor | HighlightCursor;
|
|
|
128
112
|
|
|
129
113
|
/**
|
|
130
114
|
* This is the most complex, tricky function in the whole repo.
|
|
131
|
-
* It could be simplified and made more understandable.
|
|
132
115
|
*/
|
|
133
116
|
export function computeDrop(args: Args): ComputedDrop {
|
|
134
117
|
const hover = measureHover(args.element, args.offset);
|
|
118
|
+
const indent = args.indent;
|
|
119
|
+
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
|
|
135
120
|
const { node, nextNode, prevNode } = args;
|
|
136
121
|
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);
|
|
137
122
|
|
|
@@ -143,7 +128,12 @@ export function computeDrop(args: Args): ComputedDrop {
|
|
|
143
128
|
};
|
|
144
129
|
}
|
|
145
130
|
|
|
146
|
-
/*
|
|
131
|
+
/*
|
|
132
|
+
* Now we only need to care about the node above the cursor
|
|
133
|
+
* ----------- -------
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/* There is no node above the cursor line */
|
|
147
137
|
if (!above) {
|
|
148
138
|
return {
|
|
149
139
|
drop: dropAt(below?.parent?.id, 0),
|
|
@@ -151,16 +141,43 @@ export function computeDrop(args: Args): ComputedDrop {
|
|
|
151
141
|
};
|
|
152
142
|
}
|
|
153
143
|
|
|
154
|
-
/* The above
|
|
155
|
-
if (isItem(above)
|
|
156
|
-
const level =
|
|
144
|
+
/* The node above the cursor line is an item */
|
|
145
|
+
if (isItem(above)) {
|
|
146
|
+
const level = bound(hoverLevel, below?.level || 0, above.level);
|
|
147
|
+
return {
|
|
148
|
+
drop: walkUpFrom(above, level),
|
|
149
|
+
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* The node above the cursor line is a closed folder */
|
|
154
|
+
if (isClosed(above)) {
|
|
155
|
+
const level = bound(hoverLevel, below?.level || 0, above.level);
|
|
157
156
|
return {
|
|
158
157
|
drop: walkUpFrom(above, level),
|
|
159
158
|
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
160
159
|
};
|
|
161
160
|
}
|
|
162
161
|
|
|
163
|
-
/* The above
|
|
162
|
+
/* The node above the cursor line is an open folder with no children */
|
|
163
|
+
if (isOpenWithEmptyChildren(above)) {
|
|
164
|
+
const level = bound(hoverLevel, 0, above.level + 1);
|
|
165
|
+
if (level > above.level) {
|
|
166
|
+
/* Will be the first child of the empty folder */
|
|
167
|
+
return {
|
|
168
|
+
drop: dropAt(above.id, 0),
|
|
169
|
+
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
170
|
+
};
|
|
171
|
+
} else {
|
|
172
|
+
/* Will be a sibling or grandsibling of the empty folder */
|
|
173
|
+
return {
|
|
174
|
+
drop: walkUpFrom(above, level),
|
|
175
|
+
cursor: lineCursor(above.rowIndex! + 1, level),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* The node above the cursor is a an open folder with children */
|
|
164
181
|
return {
|
|
165
182
|
drop: dropAt(above?.id, 0),
|
|
166
183
|
cursor: lineCursor(above.rowIndex! + 1, above.level + 1),
|
package/src/utils.ts
CHANGED
|
@@ -14,6 +14,10 @@ export function isClosed(node: NodeApi<any> | null) {
|
|
|
14
14
|
return node && node.isInternal && !node.isOpen;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function isOpenWithEmptyChildren(node: NodeApi<any> | null) {
|
|
18
|
+
return node && node.isOpen && !node.children?.length;
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
/**
|
|
18
22
|
* Is first param a descendant of the second param
|
|
19
23
|
*/
|