tree-element 0.2.0 → 0.3.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/README.md +12 -4
- package/lib/animation.d.ts +2 -2
- package/lib/animation.d.ts.map +1 -1
- package/lib/animation.js +13 -9
- package/lib/animation.js.map +1 -1
- package/lib/dataLoader.d.ts +1 -0
- package/lib/dataLoader.d.ts.map +1 -1
- package/lib/dataLoader.js +8 -0
- package/lib/dataLoader.js.map +1 -1
- package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -1
- package/lib/dragAndDropHandler/dragElement.js +2 -1
- package/lib/dragAndDropHandler/dragElement.js.map +1 -1
- package/lib/dragAndDropHandler/index.d.ts.map +1 -1
- package/lib/dragAndDropHandler/index.js +56 -65
- package/lib/dragAndDropHandler/index.js.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.js +16 -15
- package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -1
- package/lib/elementsRenderer.d.ts +5 -1
- package/lib/elementsRenderer.d.ts.map +1 -1
- package/lib/elementsRenderer.js +62 -39
- package/lib/elementsRenderer.js.map +1 -1
- package/lib/events.d.ts +44 -11
- package/lib/events.d.ts.map +1 -1
- package/lib/index.d.ts +31 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +162 -122
- package/lib/index.js.map +1 -1
- package/lib/keyHandler.d.ts +11 -5
- package/lib/keyHandler.d.ts.map +1 -1
- package/lib/keyHandler.js +87 -33
- package/lib/keyHandler.js.map +1 -1
- package/lib/methodTypes.d.ts +2 -2
- package/lib/methodTypes.d.ts.map +1 -1
- package/lib/mouseHandler.d.ts +1 -1
- package/lib/mouseHandler.d.ts.map +1 -1
- package/lib/mouseHandler.js +10 -7
- package/lib/mouseHandler.js.map +1 -1
- package/lib/node.d.ts +45 -15
- package/lib/node.d.ts.map +1 -1
- package/lib/node.js +136 -139
- package/lib/node.js.map +1 -1
- package/lib/nodeElement/folderElement.d.ts +1 -1
- package/lib/nodeElement/folderElement.d.ts.map +1 -1
- package/lib/nodeElement/folderElement.js +46 -57
- package/lib/nodeElement/folderElement.js.map +1 -1
- package/lib/nodeElement/ghostDropHint.d.ts.map +1 -1
- package/lib/nodeElement/ghostDropHint.js +8 -4
- package/lib/nodeElement/ghostDropHint.js.map +1 -1
- package/lib/nodeElement/index.d.ts.map +1 -1
- package/lib/nodeElement/index.js +6 -6
- package/lib/nodeElement/index.js.map +1 -1
- package/lib/nodeUtils.d.ts.map +1 -1
- package/lib/nodeUtils.js +1 -1
- package/lib/nodeUtils.js.map +1 -1
- package/lib/options.d.ts +19 -3
- package/lib/options.d.ts.map +1 -1
- package/lib/requestUrl.d.ts.map +1 -1
- package/lib/requestUrl.js +2 -11
- package/lib/requestUrl.js.map +1 -1
- package/lib/saveStateHandler.d.ts.map +1 -1
- package/lib/saveStateHandler.js +21 -41
- package/lib/saveStateHandler.js.map +1 -1
- package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/containerScrollParent.js +3 -8
- package/lib/scrollHandler/containerScrollParent.js.map +1 -1
- package/lib/scrollHandler/createScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/createScrollParent.js +4 -5
- package/lib/scrollHandler/createScrollParent.js.map +1 -1
- package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/documentScrollParent.js +3 -9
- package/lib/scrollHandler/documentScrollParent.js.map +1 -1
- package/lib/scrollHandler/scrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/scrollParent.js +19 -17
- package/lib/scrollHandler/scrollParent.js.map +1 -1
- package/lib/selectNodeHandler.d.ts +3 -1
- package/lib/selectNodeHandler.d.ts.map +1 -1
- package/lib/selectNodeHandler.js +27 -37
- package/lib/selectNodeHandler.js.map +1 -1
- package/lib/setDefaultOptions.d.ts.map +1 -1
- package/lib/setDefaultOptions.js +11 -10
- package/lib/setDefaultOptions.js.map +1 -1
- package/lib/util.d.ts.map +1 -1
- package/lib/util.js +1 -1
- package/lib/util.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +42 -33
- package/src/animation.ts +13 -11
- package/src/dataLoader.ts +11 -0
- package/src/dragAndDropHandler/dragElement.ts +2 -1
- package/src/dragAndDropHandler/index.ts +70 -75
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +18 -16
- package/src/elementsRenderer.ts +76 -46
- package/src/events.ts +44 -11
- package/src/index.ts +210 -150
- package/src/keyHandler.ts +95 -41
- package/src/methodTypes.ts +3 -3
- package/src/mouseHandler.ts +10 -7
- package/src/node.ts +155 -148
- package/src/nodeElement/folderElement.ts +54 -63
- package/src/nodeElement/ghostDropHint.ts +4 -2
- package/src/nodeElement/index.ts +9 -15
- package/src/nodeUtils.ts +1 -1
- package/src/options.ts +19 -3
- package/src/requestUrl.ts +4 -11
- package/src/saveStateHandler.ts +29 -43
- package/src/scrollHandler/containerScrollParent.ts +3 -9
- package/src/scrollHandler/createScrollParent.ts +1 -2
- package/src/scrollHandler/documentScrollParent.ts +5 -11
- package/src/scrollHandler/scrollParent.ts +29 -25
- package/src/selectNodeHandler.ts +34 -38
- package/src/setDefaultOptions.ts +19 -10
- package/src/util.ts +1 -2
- package/src/version.ts +1 -1
- package/tree_element.css +87 -69
- package/tree_element.debug.js +706 -639
- package/tree_element.debug.js.map +1 -1
- package/tree_element.js +2 -2
- package/tree_element.js.map +1 -1
|
@@ -20,13 +20,15 @@ class GhostDropHint implements DropHint {
|
|
|
20
20
|
this.ghost = this.createGhostElement();
|
|
21
21
|
|
|
22
22
|
switch (position) {
|
|
23
|
-
case "after":
|
|
23
|
+
case "after": {
|
|
24
24
|
this.moveAfter();
|
|
25
25
|
break;
|
|
26
|
+
}
|
|
26
27
|
|
|
27
|
-
case "before":
|
|
28
|
+
case "before": {
|
|
28
29
|
this.moveBefore();
|
|
29
30
|
break;
|
|
31
|
+
}
|
|
30
32
|
|
|
31
33
|
case "inside": {
|
|
32
34
|
if (node.isFolder() && node.is_open) {
|
package/src/nodeElement/index.ts
CHANGED
|
@@ -40,20 +40,9 @@ class NodeElement {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
public addDropHint(position: Position): DropHint {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.getScrollLeft(),
|
|
47
|
-
this.classNames,
|
|
48
|
-
);
|
|
49
|
-
} else {
|
|
50
|
-
return new GhostDropHint(
|
|
51
|
-
this.node,
|
|
52
|
-
this.element,
|
|
53
|
-
position,
|
|
54
|
-
this.classNames,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
43
|
+
return this.mustShowBorderDropHint(position)
|
|
44
|
+
? new BorderDropHint(this.element, this.getScrollLeft(), this.classNames)
|
|
45
|
+
: new GhostDropHint(this.node, this.element, position, this.classNames);
|
|
57
46
|
}
|
|
58
47
|
|
|
59
48
|
public deselect(): void {
|
|
@@ -64,7 +53,12 @@ class NodeElement {
|
|
|
64
53
|
this.element.classList.remove(this.classNames.selected);
|
|
65
54
|
|
|
66
55
|
const titleSpan = this.getTitleSpan();
|
|
67
|
-
|
|
56
|
+
|
|
57
|
+
// Check for null or undefined
|
|
58
|
+
if (this.tabIndex != null) {
|
|
59
|
+
titleSpan.setAttribute("tabindex", "-1");
|
|
60
|
+
}
|
|
61
|
+
|
|
68
62
|
titleSpan.setAttribute("aria-selected", "false");
|
|
69
63
|
|
|
70
64
|
titleSpan.blur();
|
package/src/nodeUtils.ts
CHANGED
package/src/options.ts
CHANGED
|
@@ -36,10 +36,25 @@ export interface TreeElementOptions {
|
|
|
36
36
|
* The duration of the slide animation: `"fast"` is 200ms, `"slow"` is
|
|
37
37
|
* 600ms, a number is milliseconds.
|
|
38
38
|
*
|
|
39
|
-
* @defaultValue `"fast"`
|
|
39
|
+
* @defaultValue `"fast"`, or `0` when the user prefers reduced motion
|
|
40
|
+
* (`prefers-reduced-motion: reduce`).
|
|
40
41
|
* @group Appearance
|
|
41
42
|
*/
|
|
42
43
|
animationSpeed: AnimationSpeed;
|
|
44
|
+
/**
|
|
45
|
+
* The accessible name of the tree, set as `aria-label` on the root `ul`.
|
|
46
|
+
* Use `ariaLabelledBy` instead when the name is visible on the page.
|
|
47
|
+
*
|
|
48
|
+
* @group Appearance
|
|
49
|
+
*/
|
|
50
|
+
ariaLabel?: string;
|
|
51
|
+
/**
|
|
52
|
+
* The id of the element that names the tree, set as `aria-labelledby` on
|
|
53
|
+
* the root `ul`.
|
|
54
|
+
*
|
|
55
|
+
* @group Appearance
|
|
56
|
+
*/
|
|
57
|
+
ariaLabelledBy?: string;
|
|
43
58
|
/**
|
|
44
59
|
* Escape node names. With `false`, names are inserted as html — only do
|
|
45
60
|
* that for data you control.
|
|
@@ -129,7 +144,7 @@ export interface TreeElementOptions {
|
|
|
129
144
|
*/
|
|
130
145
|
dragAndDrop: boolean;
|
|
131
146
|
/**
|
|
132
|
-
* Handle the
|
|
147
|
+
* Handle the keyboard when the focus is on the tree. See
|
|
133
148
|
* [Selection](/guide/selection#keyboard-navigation).
|
|
134
149
|
*
|
|
135
150
|
* @defaultValue `true`
|
|
@@ -302,7 +317,8 @@ export interface TreeElementOptions {
|
|
|
302
317
|
startDndDelay?: number;
|
|
303
318
|
/**
|
|
304
319
|
* The `tabindex` of the selected node's title, which is what makes the
|
|
305
|
-
* tree focusable.
|
|
320
|
+
* tree focusable. When no node is selected, the first node gets it. The
|
|
321
|
+
* other nodes get `-1`.
|
|
306
322
|
*
|
|
307
323
|
* @defaultValue `0`
|
|
308
324
|
* @group Selection
|
package/src/requestUrl.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
// Url class for absolute and relative urls.
|
|
2
2
|
|
|
3
3
|
const isAbsoluteUrl = (inputUrl: string) => {
|
|
4
|
-
|
|
5
|
-
new URL(inputUrl);
|
|
6
|
-
return true;
|
|
7
|
-
} catch {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
4
|
+
return URL.canParse(inputUrl);
|
|
10
5
|
};
|
|
11
6
|
|
|
12
7
|
const LOCALHOST = "http://localhost";
|
|
@@ -30,11 +25,9 @@ class RequestUrl {
|
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
value() {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return this.url.href.slice(LOCALHOST.length);
|
|
37
|
-
}
|
|
28
|
+
return this.isAbsolute
|
|
29
|
+
? this.url.href
|
|
30
|
+
: this.url.href.slice(LOCALHOST.length);
|
|
38
31
|
}
|
|
39
32
|
}
|
|
40
33
|
|
package/src/saveStateHandler.ts
CHANGED
|
@@ -73,11 +73,7 @@ export default class SaveStateHandler {
|
|
|
73
73
|
|
|
74
74
|
const state = this.getStateFromStorage();
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
return state.selected_node[0] ?? null;
|
|
78
|
-
} else {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
76
|
+
return state?.selected_node ? (state.selected_node[0] ?? null) : null;
|
|
81
77
|
}
|
|
82
78
|
|
|
83
79
|
public getState(): SavedState {
|
|
@@ -97,11 +93,11 @@ export default class SaveStateHandler {
|
|
|
97
93
|
const getSelectedNodeIds = (): NodeId[] => {
|
|
98
94
|
const selectedNodeIds: NodeId[] = [];
|
|
99
95
|
|
|
100
|
-
this.getSelectedNodes()
|
|
96
|
+
for (const node of this.getSelectedNodes()) {
|
|
101
97
|
if (node.id != null) {
|
|
102
98
|
selectedNodeIds.push(node.id);
|
|
103
99
|
}
|
|
104
|
-
}
|
|
100
|
+
}
|
|
105
101
|
|
|
106
102
|
return selectedNodeIds;
|
|
107
103
|
};
|
|
@@ -119,11 +115,7 @@ export default class SaveStateHandler {
|
|
|
119
115
|
|
|
120
116
|
const jsonData = this.loadFromStorage();
|
|
121
117
|
|
|
122
|
-
|
|
123
|
-
return this.parseState(jsonData);
|
|
124
|
-
} else {
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
118
|
+
return jsonData ? this.parseState(jsonData) : null;
|
|
127
119
|
}
|
|
128
120
|
|
|
129
121
|
public saveState(): void {
|
|
@@ -147,11 +139,9 @@ export default class SaveStateHandler {
|
|
|
147
139
|
result: must load on demand (boolean)
|
|
148
140
|
*/
|
|
149
141
|
public setInitialState(state: SavedState): boolean {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
mustLoadOnDemand = this.openInitialNodes(state.open_nodes);
|
|
154
|
-
}
|
|
142
|
+
const mustLoadOnDemand = state.open_nodes
|
|
143
|
+
? this.openInitialNodes(state.open_nodes)
|
|
144
|
+
: false;
|
|
155
145
|
|
|
156
146
|
this.resetSelection();
|
|
157
147
|
|
|
@@ -175,9 +165,7 @@ export default class SaveStateHandler {
|
|
|
175
165
|
for (const nodeId of nodeIds) {
|
|
176
166
|
const node = this.getNodeById(nodeId);
|
|
177
167
|
|
|
178
|
-
if (
|
|
179
|
-
newNodesIds.push(nodeId);
|
|
180
|
-
} else {
|
|
168
|
+
if (node) {
|
|
181
169
|
if (!node.is_loading) {
|
|
182
170
|
if (node.load_on_demand) {
|
|
183
171
|
await loadAndOpenNode(node);
|
|
@@ -185,15 +173,15 @@ export default class SaveStateHandler {
|
|
|
185
173
|
await this.openNode(node, false);
|
|
186
174
|
}
|
|
187
175
|
}
|
|
176
|
+
} else {
|
|
177
|
+
newNodesIds.push(nodeId);
|
|
188
178
|
}
|
|
189
179
|
}
|
|
190
180
|
|
|
191
181
|
nodeIds = newNodesIds;
|
|
192
182
|
|
|
193
|
-
if (state.selected_node) {
|
|
194
|
-
|
|
195
|
-
this.refreshElements(null);
|
|
196
|
-
}
|
|
183
|
+
if (state.selected_node && this.selectInitialNodes(state.selected_node)) {
|
|
184
|
+
this.refreshElements(null);
|
|
197
185
|
}
|
|
198
186
|
};
|
|
199
187
|
|
|
@@ -206,19 +194,15 @@ export default class SaveStateHandler {
|
|
|
206
194
|
}
|
|
207
195
|
|
|
208
196
|
private getKeyName(): string {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return "tree";
|
|
213
|
-
}
|
|
197
|
+
return typeof this.saveStateOption === "string"
|
|
198
|
+
? this.saveStateOption
|
|
199
|
+
: "tree";
|
|
214
200
|
}
|
|
215
201
|
|
|
216
202
|
private loadFromStorage(): null | string {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return localStorage.getItem(this.getKeyName());
|
|
221
|
-
}
|
|
203
|
+
return this.onGetStateFromStorage
|
|
204
|
+
? this.onGetStateFromStorage()
|
|
205
|
+
: localStorage.getItem(this.getKeyName());
|
|
222
206
|
}
|
|
223
207
|
|
|
224
208
|
private openInitialNodes(nodeIds: NodeId[]): boolean {
|
|
@@ -228,10 +212,10 @@ export default class SaveStateHandler {
|
|
|
228
212
|
const node = this.getNodeById(nodeId);
|
|
229
213
|
|
|
230
214
|
if (node) {
|
|
231
|
-
if (
|
|
232
|
-
node.is_open = true;
|
|
233
|
-
} else {
|
|
215
|
+
if (node.load_on_demand) {
|
|
234
216
|
mustLoadOnDemand = true;
|
|
217
|
+
} else {
|
|
218
|
+
node.is_open = true;
|
|
235
219
|
}
|
|
236
220
|
}
|
|
237
221
|
}
|
|
@@ -254,9 +238,9 @@ export default class SaveStateHandler {
|
|
|
254
238
|
private resetSelection(): void {
|
|
255
239
|
const selectedNodes = this.getSelectedNodes();
|
|
256
240
|
|
|
257
|
-
|
|
241
|
+
for (const node of selectedNodes) {
|
|
258
242
|
this.removeFromSelection(node);
|
|
259
|
-
}
|
|
243
|
+
}
|
|
260
244
|
}
|
|
261
245
|
|
|
262
246
|
private selectInitialNodes(nodeIds: NodeId[]): boolean {
|
|
@@ -265,11 +249,13 @@ export default class SaveStateHandler {
|
|
|
265
249
|
for (const nodeId of nodeIds) {
|
|
266
250
|
const node = this.getNodeById(nodeId);
|
|
267
251
|
|
|
268
|
-
if (node) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.addToSelection(node);
|
|
252
|
+
if (!node) {
|
|
253
|
+
continue;
|
|
272
254
|
}
|
|
255
|
+
|
|
256
|
+
selectCount += 1;
|
|
257
|
+
|
|
258
|
+
this.addToSelection(node);
|
|
273
259
|
}
|
|
274
260
|
|
|
275
261
|
return selectCount !== 0;
|
|
@@ -26,15 +26,13 @@ export default class ContainerScrollParent extends ScrollParent {
|
|
|
26
26
|
const rightEdge = scrollParentOffset.left + containerWidth;
|
|
27
27
|
const leftEdge = scrollParentOffset.left;
|
|
28
28
|
const isNearRightEdge = pageX > rightEdge - 20;
|
|
29
|
-
const isNearLeftEdge = pageX < leftEdge + 20;
|
|
30
29
|
|
|
31
30
|
if (isNearRightEdge) {
|
|
32
31
|
return "right";
|
|
33
|
-
} else if (isNearLeftEdge) {
|
|
34
|
-
return "left";
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
const isNearLeftEdge = pageX < leftEdge + 20;
|
|
35
|
+
return isNearLeftEdge ? "left" : undefined;
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
protected getNewVerticalScrollDirection(
|
|
@@ -44,11 +42,7 @@ export default class ContainerScrollParent extends ScrollParent {
|
|
|
44
42
|
return "top";
|
|
45
43
|
}
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
return "bottom";
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return undefined;
|
|
45
|
+
return pageY > this.getScrollParentBottom() ? "bottom" : undefined;
|
|
52
46
|
}
|
|
53
47
|
|
|
54
48
|
private getScrollParentBottom() {
|
|
@@ -43,9 +43,8 @@ const createScrollParent = (
|
|
|
43
43
|
container,
|
|
44
44
|
refreshHitAreas,
|
|
45
45
|
});
|
|
46
|
-
} else {
|
|
47
|
-
return new DocumentScrollParent({ refreshHitAreas, treeElement });
|
|
48
46
|
}
|
|
47
|
+
return new DocumentScrollParent({ refreshHitAreas, treeElement });
|
|
49
48
|
};
|
|
50
49
|
|
|
51
50
|
export default createScrollParent;
|
|
@@ -42,17 +42,13 @@ export default class DocumentScrollParent extends ScrollParent {
|
|
|
42
42
|
const windowWidth = window.innerWidth;
|
|
43
43
|
|
|
44
44
|
const isNearRightEdge = pageX > windowWidth - 20;
|
|
45
|
-
const isNearLeftEdge = pageX - scrollLeft < 20;
|
|
46
45
|
|
|
47
46
|
if (isNearRightEdge && this.canScrollRight()) {
|
|
48
47
|
return "right";
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return undefined;
|
|
50
|
+
const isNearLeftEdge = pageX - scrollLeft < 20;
|
|
51
|
+
return isNearLeftEdge ? "left" : undefined;
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
protected getNewVerticalScrollDirection(
|
|
@@ -67,11 +63,9 @@ export default class DocumentScrollParent extends ScrollParent {
|
|
|
67
63
|
|
|
68
64
|
const windowHeight = window.innerHeight;
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return undefined;
|
|
66
|
+
return windowHeight - (pageY - scrollTop) < 20 && this.canScrollDown()
|
|
67
|
+
? "bottom"
|
|
68
|
+
: undefined;
|
|
75
69
|
}
|
|
76
70
|
|
|
77
71
|
private canScrollDown() {
|
|
@@ -24,19 +24,21 @@ export abstract class ScrollParent {
|
|
|
24
24
|
const newHorizontalScrollDirection =
|
|
25
25
|
this.getNewHorizontalScrollDirection(pageX);
|
|
26
26
|
|
|
27
|
-
if (this.horizontalScrollDirection
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
if (this.horizontalScrollDirection === newHorizontalScrollDirection) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.horizontalScrollDirection = newHorizontalScrollDirection;
|
|
32
|
+
|
|
33
|
+
if (this.horizontalScrollTimeout != null) {
|
|
34
|
+
window.clearTimeout(this.horizontalScrollTimeout);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (newHorizontalScrollDirection) {
|
|
38
|
+
this.horizontalScrollTimeout = window.setTimeout(
|
|
39
|
+
this.scrollHorizontally.bind(this),
|
|
40
|
+
40,
|
|
41
|
+
);
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -44,20 +46,22 @@ export abstract class ScrollParent {
|
|
|
44
46
|
const newVerticalScrollDirection =
|
|
45
47
|
this.getNewVerticalScrollDirection(pageY);
|
|
46
48
|
|
|
47
|
-
if (this.verticalScrollDirection
|
|
48
|
-
|
|
49
|
+
if (this.verticalScrollDirection === newVerticalScrollDirection) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
this.verticalScrollDirection = newVerticalScrollDirection;
|
|
54
|
+
|
|
55
|
+
if (this.verticalScrollTimeout != null) {
|
|
56
|
+
window.clearTimeout(this.verticalScrollTimeout);
|
|
57
|
+
this.verticalScrollTimeout = undefined;
|
|
58
|
+
}
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
60
|
+
if (newVerticalScrollDirection) {
|
|
61
|
+
this.verticalScrollTimeout = window.setTimeout(
|
|
62
|
+
this.scrollVertically.bind(this),
|
|
63
|
+
40,
|
|
64
|
+
);
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
|
package/src/selectNodeHandler.ts
CHANGED
|
@@ -20,6 +20,7 @@ interface SelectNodeHandlerParameters {
|
|
|
20
20
|
openParents: OpenParents;
|
|
21
21
|
saveState: () => void;
|
|
22
22
|
triggerEvent: TriggerEvent;
|
|
23
|
+
updateTabStop: () => void;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export default class SelectNodeHandler {
|
|
@@ -32,6 +33,7 @@ export default class SelectNodeHandler {
|
|
|
32
33
|
private selectedNodes: Set<NodeId>;
|
|
33
34
|
private selectedSingleNode: Node | null;
|
|
34
35
|
private triggerEvent: TriggerEvent;
|
|
36
|
+
private updateTabStop: () => void;
|
|
35
37
|
|
|
36
38
|
constructor({
|
|
37
39
|
getNodeById,
|
|
@@ -41,6 +43,7 @@ export default class SelectNodeHandler {
|
|
|
41
43
|
openParents,
|
|
42
44
|
saveState,
|
|
43
45
|
triggerEvent,
|
|
46
|
+
updateTabStop,
|
|
44
47
|
}: SelectNodeHandlerParameters) {
|
|
45
48
|
this.getNodeById = getNodeById;
|
|
46
49
|
this.getNodeElementForNode = getNodeElementForNode;
|
|
@@ -51,13 +54,14 @@ export default class SelectNodeHandler {
|
|
|
51
54
|
this.selectedNodes = new Set<NodeId>();
|
|
52
55
|
this.selectedSingleNode = null;
|
|
53
56
|
this.triggerEvent = triggerEvent;
|
|
57
|
+
this.updateTabStop = updateTabStop;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
public addToSelection(node: Node): void {
|
|
57
|
-
if (node.id
|
|
58
|
-
this.selectedNodes.add(node.id);
|
|
59
|
-
} else {
|
|
61
|
+
if (node.id == null) {
|
|
60
62
|
this.selectedSingleNode = node;
|
|
63
|
+
} else {
|
|
64
|
+
this.selectedNodes.add(node.id);
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
|
|
@@ -69,59 +73,50 @@ export default class SelectNodeHandler {
|
|
|
69
73
|
public getSelectedNode(): Node | null {
|
|
70
74
|
const selectedNodes = this.getSelectedNodes();
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
return selectedNodes[0] ?? null;
|
|
74
|
-
} else {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
76
|
+
return selectedNodes.length ? (selectedNodes[0] ?? null) : null;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
public getSelectedNodes(): Node[] {
|
|
80
80
|
if (this.selectedSingleNode) {
|
|
81
81
|
return [this.selectedSingleNode];
|
|
82
|
-
}
|
|
83
|
-
const selectedNodes: Node[] = [];
|
|
82
|
+
}
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
const node = this.getNodeById(id);
|
|
87
|
-
if (node) {
|
|
88
|
-
selectedNodes.push(node);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
84
|
+
const selectedNodes: Node[] = [];
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
this.selectedNodes.forEach((id) => {
|
|
87
|
+
const node = this.getNodeById(id);
|
|
88
|
+
if (node) {
|
|
89
|
+
selectedNodes.push(node);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return selectedNodes;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
public getSelectedNodesUnder(parent: Node): Node[] {
|
|
97
97
|
if (this.selectedSingleNode) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
const selectedNodes: Node[] = [];
|
|
98
|
+
return parent.isParentOf(this.selectedSingleNode)
|
|
99
|
+
? [this.selectedSingleNode]
|
|
100
|
+
: [];
|
|
101
|
+
}
|
|
105
102
|
|
|
106
|
-
|
|
107
|
-
const node = this.getNodeById(id);
|
|
108
|
-
if (node && parent.isParentOf(node)) {
|
|
109
|
-
selectedNodes.push(node);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
103
|
+
const selectedNodes: Node[] = [];
|
|
112
104
|
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
this.selectedNodes.forEach((id) => {
|
|
106
|
+
const node = this.getNodeById(id);
|
|
107
|
+
if (node && parent.isParentOf(node)) {
|
|
108
|
+
selectedNodes.push(node);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return selectedNodes;
|
|
115
113
|
}
|
|
116
114
|
|
|
117
115
|
public isNodeSelected(node: Node): boolean {
|
|
118
116
|
if (node.id != null) {
|
|
119
117
|
return this.selectedNodes.has(node.id);
|
|
120
|
-
} else if (this.selectedSingleNode) {
|
|
121
|
-
return this.selectedSingleNode === node;
|
|
122
|
-
} else {
|
|
123
|
-
return false;
|
|
124
118
|
}
|
|
119
|
+
return this.selectedSingleNode ? this.selectedSingleNode === node : false;
|
|
125
120
|
}
|
|
126
121
|
|
|
127
122
|
public removeFromSelection(node: Node, includeChildren = false): void {
|
|
@@ -155,7 +150,7 @@ export default class SelectNodeHandler {
|
|
|
155
150
|
*/
|
|
156
151
|
public selectSingleNode(node: Node, optionsParam?: SelectNodeOptions) {
|
|
157
152
|
const defaultOptions = { mustSetFocus: true, mustToggle: true };
|
|
158
|
-
const selectOptions = { ...defaultOptions, ...
|
|
153
|
+
const selectOptions = { ...defaultOptions, ...optionsParam };
|
|
159
154
|
|
|
160
155
|
const canSelect = (): boolean => {
|
|
161
156
|
if (!this.getSelectable()) {
|
|
@@ -197,6 +192,7 @@ export default class SelectNodeHandler {
|
|
|
197
192
|
});
|
|
198
193
|
}
|
|
199
194
|
|
|
195
|
+
this.updateTabStop();
|
|
200
196
|
this.saveState();
|
|
201
197
|
}
|
|
202
198
|
}
|
package/src/setDefaultOptions.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AnimationSpeed } from "./animation";
|
|
1
2
|
import type { TreeElementOptions } from "./options";
|
|
2
3
|
|
|
3
4
|
import { DEFAULT_CLASS_PREFIX } from "./classNames";
|
|
@@ -10,7 +11,7 @@ const defaults: TreeElementOptions = {
|
|
|
10
11
|
buttonLeft: true,
|
|
11
12
|
classPrefix: DEFAULT_CLASS_PREFIX, // the prefix of all css classes
|
|
12
13
|
// The symbol to use for a closed node - ► BLACK RIGHT-POINTING POINTER
|
|
13
|
-
//
|
|
14
|
+
// https://www.fileformat.info/info/unicode/char/25ba/index.htm
|
|
14
15
|
// closedIcon: undefined,
|
|
15
16
|
// commonClassName: undefined, // the class of every element; the default is "<classPrefix>-common"
|
|
16
17
|
// data: undefined,
|
|
@@ -31,7 +32,7 @@ const defaults: TreeElementOptions = {
|
|
|
31
32
|
// openedIcon: undefined,
|
|
32
33
|
openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds
|
|
33
34
|
// The symbol to use for an open node - ▼ BLACK DOWN-POINTING TRIANGLE
|
|
34
|
-
//
|
|
35
|
+
// https://www.fileformat.info/info/unicode/char/25bc/index.htm
|
|
35
36
|
// rtl: undefined, // right-to-left support; true / false (default)
|
|
36
37
|
saveState: false, // true / false / string (local storage key; the default key is "tree")
|
|
37
38
|
selectable: true,
|
|
@@ -47,7 +48,11 @@ const setDefaultOptions = (
|
|
|
47
48
|
htmlElement: HTMLElement,
|
|
48
49
|
inputOptions: Partial<TreeElementOptions>,
|
|
49
50
|
): TreeElementOptions => {
|
|
50
|
-
const options = {
|
|
51
|
+
const options = {
|
|
52
|
+
...defaults,
|
|
53
|
+
...inputOptions,
|
|
54
|
+
animationSpeed: inputOptions.animationSpeed ?? getDefaultAnimationSpeed(),
|
|
55
|
+
};
|
|
51
56
|
|
|
52
57
|
options.dataUrl ??= htmlElement.dataset.url;
|
|
53
58
|
options.rtl ??= getRtlOptionFromHTMLElement(htmlElement);
|
|
@@ -57,14 +62,21 @@ const setDefaultOptions = (
|
|
|
57
62
|
return options;
|
|
58
63
|
};
|
|
59
64
|
|
|
65
|
+
// No animation when the user asked the system for reduced motion
|
|
66
|
+
const getDefaultAnimationSpeed = (): AnimationSpeed =>
|
|
67
|
+
prefersReducedMotion() ? 0 : defaults.animationSpeed;
|
|
68
|
+
|
|
69
|
+
const prefersReducedMotion = (): boolean =>
|
|
70
|
+
typeof window.matchMedia === "function" &&
|
|
71
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
72
|
+
|
|
60
73
|
const getDefaultClosedIcon = (options: TreeElementOptions): string => {
|
|
61
74
|
if (options.rtl) {
|
|
62
75
|
// triangle to the left
|
|
63
76
|
return "◀";
|
|
64
|
-
} else {
|
|
65
|
-
// triangle to the right
|
|
66
|
-
return "►";
|
|
67
77
|
}
|
|
78
|
+
// triangle to the right
|
|
79
|
+
return "►";
|
|
68
80
|
};
|
|
69
81
|
|
|
70
82
|
const getRtlOptionFromHTMLElement = (htmlElement: HTMLElement): boolean => {
|
|
@@ -72,11 +84,8 @@ const getRtlOptionFromHTMLElement = (htmlElement: HTMLElement): boolean => {
|
|
|
72
84
|
|
|
73
85
|
if (dataRtl == "") {
|
|
74
86
|
return true;
|
|
75
|
-
} else if (dataRtl === "false") {
|
|
76
|
-
return false;
|
|
77
|
-
} else {
|
|
78
|
-
return Boolean(dataRtl);
|
|
79
87
|
}
|
|
88
|
+
return dataRtl === "false" ? false : Boolean(dataRtl);
|
|
80
89
|
};
|
|
81
90
|
|
|
82
91
|
export default setDefaultOptions;
|
package/src/util.ts
CHANGED
package/src/version.ts
CHANGED