tree-element 0.2.0 → 0.3.1
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 +14 -6
- 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 +23 -6
- package/lib/options.d.ts.map +1 -1
- package/lib/requestUrl.d.ts +0 -1
- package/lib/requestUrl.d.ts.map +1 -1
- package/lib/requestUrl.js +4 -22
- 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 +3 -0
- package/lib/setDefaultOptions.d.ts.map +1 -1
- package/lib/setDefaultOptions.js +21 -20
- 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 +44 -35
- 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 +23 -6
- package/src/requestUrl.ts +4 -25
- 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 +31 -19
- package/src/util.ts +1 -2
- package/src/version.ts +1 -1
- package/tree_element.css +87 -69
- package/tree_element.debug.js +717 -659
- 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.
|
|
@@ -82,8 +97,8 @@ export interface TreeElementOptions {
|
|
|
82
97
|
*
|
|
83
98
|
* Type: `HTMLElement | string`
|
|
84
99
|
*
|
|
85
|
-
* @defaultValue
|
|
86
|
-
* true.
|
|
100
|
+
* @defaultValue An svg triangle pointing right, or left when `rtl` is
|
|
101
|
+
* true. It is sized in em and filled with `currentColor`.
|
|
87
102
|
* @group Appearance
|
|
88
103
|
*/
|
|
89
104
|
closedIcon?: IconElement;
|
|
@@ -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`
|
|
@@ -243,7 +258,8 @@ export interface TreeElementOptions {
|
|
|
243
258
|
*
|
|
244
259
|
* Type: `HTMLElement | string`
|
|
245
260
|
*
|
|
246
|
-
* @defaultValue
|
|
261
|
+
* @defaultValue An svg triangle pointing down, sized in em and filled with
|
|
262
|
+
* `currentColor`.
|
|
247
263
|
* @group Appearance
|
|
248
264
|
*/
|
|
249
265
|
openedIcon?: IconElement;
|
|
@@ -302,7 +318,8 @@ export interface TreeElementOptions {
|
|
|
302
318
|
startDndDelay?: number;
|
|
303
319
|
/**
|
|
304
320
|
* The `tabindex` of the selected node's title, which is what makes the
|
|
305
|
-
* tree focusable.
|
|
321
|
+
* tree focusable. When no node is selected, the first node gets it. The
|
|
322
|
+
* other nodes get `-1`.
|
|
306
323
|
*
|
|
307
324
|
* @defaultValue `0`
|
|
308
325
|
* @group Selection
|
package/src/requestUrl.ts
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
|
-
// Url
|
|
2
|
-
|
|
3
|
-
const isAbsoluteUrl = (inputUrl: string) => {
|
|
4
|
-
try {
|
|
5
|
-
new URL(inputUrl);
|
|
6
|
-
return true;
|
|
7
|
-
} catch {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const LOCALHOST = "http://localhost";
|
|
1
|
+
// Url of a request. A relative url is resolved against the page, like a link
|
|
2
|
+
// or `fetch` would, so it also works when the page is in a subdirectory.
|
|
13
3
|
|
|
14
4
|
class RequestUrl {
|
|
15
|
-
private isAbsolute: boolean;
|
|
16
5
|
private url: URL;
|
|
17
6
|
|
|
18
7
|
constructor(inputUrl: string) {
|
|
19
|
-
|
|
20
|
-
this.url = new URL(inputUrl);
|
|
21
|
-
this.isAbsolute = true;
|
|
22
|
-
} else {
|
|
23
|
-
this.url = new URL(inputUrl, LOCALHOST);
|
|
24
|
-
this.isAbsolute = false;
|
|
25
|
-
}
|
|
8
|
+
this.url = new URL(inputUrl, document.baseURI);
|
|
26
9
|
}
|
|
27
10
|
|
|
28
11
|
setSearchParam(key: string, value: string) {
|
|
@@ -30,11 +13,7 @@ class RequestUrl {
|
|
|
30
13
|
}
|
|
31
14
|
|
|
32
15
|
value() {
|
|
33
|
-
|
|
34
|
-
return this.url.href;
|
|
35
|
-
} else {
|
|
36
|
-
return this.url.href.slice(LOCALHOST.length);
|
|
37
|
-
}
|
|
16
|
+
return this.url.href;
|
|
38
17
|
}
|
|
39
18
|
}
|
|
40
19
|
|
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
|
}
|