tree-element 0.1.1 → 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 +43 -31
- package/lib/animation.d.ts +2 -2
- package/lib/animation.d.ts.map +1 -1
- package/lib/animation.js +16 -12
- package/lib/animation.js.map +1 -1
- package/lib/classNames.d.ts.map +1 -1
- package/lib/classNames.js +2 -2
- package/lib/classNames.js.map +1 -1
- package/lib/dataLoader.d.ts +1 -0
- package/lib/dataLoader.d.ts.map +1 -1
- package/lib/dataLoader.js +22 -20
- package/lib/dataLoader.js.map +1 -1
- package/lib/dragAndDropHandler/binarySearch.js +3 -3
- package/lib/dragAndDropHandler/binarySearch.js.map +1 -1
- package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -1
- package/lib/dragAndDropHandler/dragElement.js +11 -13
- package/lib/dragAndDropHandler/dragElement.js.map +1 -1
- package/lib/dragAndDropHandler/generateHitAreas.d.ts.map +1 -1
- package/lib/dragAndDropHandler/generateHitAreas.js +25 -25
- package/lib/dragAndDropHandler/generateHitAreas.js.map +1 -1
- package/lib/dragAndDropHandler/index.d.ts.map +1 -1
- package/lib/dragAndDropHandler/index.js +125 -158
- package/lib/dragAndDropHandler/index.js.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -1
- package/lib/dragAndDropHandler/iterateVisibleNodes.js +23 -22
- package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -1
- package/lib/dragAndDropHandler/types.d.ts.map +1 -1
- package/lib/elementsRenderer.d.ts +20 -7
- package/lib/elementsRenderer.d.ts.map +1 -1
- package/lib/elementsRenderer.js +195 -136
- 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 +36 -13
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +386 -349
- package/lib/index.js.map +1 -1
- package/lib/keyHandler.d.ts +13 -8
- package/lib/keyHandler.d.ts.map +1 -1
- package/lib/keyHandler.js +106 -51
- package/lib/keyHandler.js.map +1 -1
- package/lib/methodTypes.d.ts +3 -3
- 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 +36 -49
- package/lib/mouseHandler.js.map +1 -1
- package/lib/mouseUtils.d.ts.map +1 -1
- package/lib/mouseUtils.js +2 -2
- package/lib/mouseUtils.js.map +1 -1
- package/lib/node.d.ts +47 -16
- package/lib/node.d.ts.map +1 -1
- package/lib/node.js +169 -171
- package/lib/node.js.map +1 -1
- package/lib/nodeElement/borderDropHint.d.ts.map +1 -1
- package/lib/nodeElement/borderDropHint.js +4 -5
- package/lib/nodeElement/borderDropHint.js.map +1 -1
- package/lib/nodeElement/folderElement.d.ts +8 -5
- package/lib/nodeElement/folderElement.d.ts.map +1 -1
- package/lib/nodeElement/folderElement.js +75 -67
- package/lib/nodeElement/folderElement.js.map +1 -1
- package/lib/nodeElement/ghostDropHint.d.ts.map +1 -1
- package/lib/nodeElement/ghostDropHint.js +13 -13
- package/lib/nodeElement/ghostDropHint.js.map +1 -1
- package/lib/nodeElement/index.d.ts +2 -1
- package/lib/nodeElement/index.d.ts.map +1 -1
- package/lib/nodeElement/index.js +38 -30
- 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/positionUtils.js +3 -3
- package/lib/positionUtils.js.map +1 -1
- package/lib/requestUrl.d.ts +1 -1
- package/lib/requestUrl.d.ts.map +1 -1
- package/lib/requestUrl.js +6 -17
- package/lib/requestUrl.js.map +1 -1
- package/lib/saveStateHandler.d.ts.map +1 -1
- package/lib/saveStateHandler.js +59 -89
- package/lib/saveStateHandler.js.map +1 -1
- package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/containerScrollParent.js +11 -18
- package/lib/scrollHandler/containerScrollParent.js.map +1 -1
- package/lib/scrollHandler/createScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/createScrollParent.js +12 -13
- package/lib/scrollHandler/createScrollParent.js.map +1 -1
- package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/documentScrollParent.js +18 -27
- package/lib/scrollHandler/documentScrollParent.js.map +1 -1
- package/lib/scrollHandler/scrollParent.d.ts.map +1 -1
- package/lib/scrollHandler/scrollParent.js +30 -34
- package/lib/scrollHandler/scrollParent.js.map +1 -1
- package/lib/scrollHandler.d.ts.map +1 -1
- package/lib/scrollHandler.js +11 -14
- package/lib/scrollHandler.js.map +1 -1
- package/lib/selectNodeHandler.d.ts +4 -2
- package/lib/selectNodeHandler.d.ts.map +1 -1
- package/lib/selectNodeHandler.js +64 -83
- package/lib/selectNodeHandler.js.map +1 -1
- package/lib/setDefaultOptions.d.ts.map +1 -1
- package/lib/setDefaultOptions.js +34 -38
- package/lib/setDefaultOptions.js.map +1 -1
- package/lib/triggerCustomEvent.d.ts.map +1 -1
- package/lib/triggerCustomEvent.js +2 -2
- package/lib/triggerCustomEvent.js.map +1 -1
- package/lib/util.d.ts.map +1 -1
- package/lib/util.js +2 -2
- 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 +43 -32
- package/src/animation.ts +14 -12
- package/src/classNames.ts +52 -52
- package/src/dataLoader.ts +79 -71
- package/src/dragAndDropHandler/binarySearch.ts +17 -17
- package/src/dragAndDropHandler/dragElement.ts +51 -50
- package/src/dragAndDropHandler/generateHitAreas.ts +156 -161
- package/src/dragAndDropHandler/index.ts +334 -348
- package/src/dragAndDropHandler/iterateVisibleNodes.ts +61 -63
- package/src/dragAndDropHandler/types.ts +5 -5
- package/src/elementsRenderer.ts +377 -294
- package/src/events.ts +241 -208
- package/src/header.txt +1 -1
- package/src/index.ts +259 -229
- package/src/keyHandler.ts +179 -115
- package/src/methodTypes.ts +7 -10
- package/src/mouseHandler.ts +316 -316
- package/src/mouseUtils.ts +14 -14
- package/src/node.ts +773 -771
- package/src/nodeElement/borderDropHint.ts +25 -25
- package/src/nodeElement/folderElement.ts +116 -102
- package/src/nodeElement/ghostDropHint.ts +64 -62
- package/src/nodeElement/index.ts +81 -73
- package/src/nodeUtils.ts +5 -5
- package/src/options.ts +25 -5
- package/src/requestUrl.ts +7 -14
- package/src/saveStateHandler.ts +191 -207
- package/src/scrollHandler/containerScrollParent.ts +40 -49
- package/src/scrollHandler/createScrollParent.ts +26 -27
- package/src/scrollHandler/documentScrollParent.ts +66 -72
- package/src/scrollHandler/scrollParent.ts +90 -86
- package/src/scrollHandler.ts +45 -45
- package/src/selectNodeHandler.ts +171 -165
- package/src/setDefaultOptions.ts +44 -32
- package/src/triggerCustomEvent.ts +7 -3
- package/src/util.ts +2 -3
- package/src/version.ts +1 -1
- package/tree_element.css +87 -69
- package/tree_element.debug.js +3866 -3831
- package/tree_element.debug.js.map +1 -1
- package/tree_element.js +2 -2
- package/tree_element.js.map +1 -1
|
@@ -2,36 +2,36 @@ import type { ClassNames } from "../classNames";
|
|
|
2
2
|
import type { DropHint } from "../dragAndDropHandler/types";
|
|
3
3
|
|
|
4
4
|
class BorderDropHint implements DropHint {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
private hint?: HTMLElement;
|
|
6
|
+
|
|
7
|
+
constructor(
|
|
8
|
+
element: HTMLElement,
|
|
9
|
+
scrollLeft: number,
|
|
10
|
+
classNames: ClassNames,
|
|
11
|
+
) {
|
|
12
|
+
const div = element.querySelector(`:scope > .${classNames.element}`);
|
|
13
|
+
|
|
14
|
+
if (!div) {
|
|
15
|
+
this.hint = undefined;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
19
|
+
const width = Math.max(element.offsetWidth + scrollLeft - 4, 0);
|
|
20
|
+
const height = Math.max(element.clientHeight - 4, 0);
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
const hint = document.createElement("span");
|
|
23
|
+
hint.className = classNames.border;
|
|
24
|
+
hint.style.width = `${width}px`;
|
|
25
|
+
hint.style.height = `${height}px`;
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
hint.className = classNames.border;
|
|
24
|
-
hint.style.width = `${width}px`;
|
|
25
|
-
hint.style.height = `${height}px`;
|
|
27
|
+
this.hint = hint;
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
div.append(this.hint);
|
|
30
|
+
}
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
public remove(): void {
|
|
33
|
-
this.hint?.remove();
|
|
34
|
-
}
|
|
32
|
+
public remove(): void {
|
|
33
|
+
this.hint?.remove();
|
|
34
|
+
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export default BorderDropHint;
|
|
@@ -1,140 +1,154 @@
|
|
|
1
1
|
import type { AnimationSpeed } from "../animation";
|
|
2
2
|
import type { TriggerEvent } from "../methodTypes";
|
|
3
|
-
import type { Position } from "../node";
|
|
3
|
+
import type { Node, Position } from "../node";
|
|
4
4
|
import type { NodeElementParams } from "./index";
|
|
5
5
|
|
|
6
6
|
import { slideDown, slideUp } from "../animation";
|
|
7
7
|
import NodeElement from "./index";
|
|
8
8
|
|
|
9
|
+
export type RenderChildren = (node: Node) => HTMLUListElement | null;
|
|
10
|
+
|
|
9
11
|
interface FolderElementParams extends NodeElementParams {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
closedIconElement?: globalThis.Node;
|
|
13
|
+
openedIconElement?: globalThis.Node;
|
|
14
|
+
renderChildren: RenderChildren;
|
|
15
|
+
triggerEvent: TriggerEvent;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
class FolderElement extends NodeElement {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
19
|
+
private closedIconElement?: globalThis.Node;
|
|
20
|
+
private openedIconElement?: globalThis.Node;
|
|
21
|
+
private renderChildren: RenderChildren;
|
|
22
|
+
private triggerEvent: TriggerEvent;
|
|
23
|
+
|
|
24
|
+
constructor({
|
|
25
|
+
classNames,
|
|
26
|
+
closedIconElement,
|
|
27
|
+
getScrollLeft,
|
|
28
|
+
node,
|
|
29
|
+
openedIconElement,
|
|
30
|
+
renderChildren,
|
|
31
|
+
tabIndex,
|
|
32
|
+
treeElement,
|
|
33
|
+
triggerEvent,
|
|
34
|
+
}: FolderElementParams) {
|
|
35
|
+
super({
|
|
36
|
+
classNames,
|
|
37
|
+
getScrollLeft,
|
|
38
|
+
node,
|
|
39
|
+
tabIndex,
|
|
40
|
+
treeElement,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.closedIconElement = closedIconElement;
|
|
44
|
+
this.openedIconElement = openedIconElement;
|
|
45
|
+
this.renderChildren = renderChildren;
|
|
46
|
+
this.triggerEvent = triggerEvent;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public async close(
|
|
50
|
+
slide: boolean,
|
|
51
|
+
animationSpeed: AnimationSpeed,
|
|
52
|
+
): Promise<void> {
|
|
53
|
+
if (!this.node.is_open) {
|
|
54
|
+
return;
|
|
41
55
|
}
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
this.node.is_open = false;
|
|
58
|
+
|
|
59
|
+
if (!this.isRendered()) {
|
|
60
|
+
this.triggerEvent("tree.close", { node: this.node });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
47
63
|
|
|
48
|
-
|
|
64
|
+
const button = this.getButton();
|
|
65
|
+
button.classList.add(this.classNames.closed);
|
|
66
|
+
button.replaceChildren();
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
button.classList.add(this.classNames.closed);
|
|
52
|
-
button.innerHTML = "";
|
|
68
|
+
const closedIconElement = this.closedIconElement;
|
|
53
69
|
|
|
54
|
-
|
|
70
|
+
if (closedIconElement) {
|
|
71
|
+
const icon = closedIconElement.cloneNode(true);
|
|
72
|
+
button.append(icon);
|
|
73
|
+
}
|
|
55
74
|
|
|
56
|
-
|
|
57
|
-
const icon = closedIconElement.cloneNode(true);
|
|
58
|
-
button.appendChild(icon);
|
|
59
|
-
}
|
|
75
|
+
const ul = this.getUl();
|
|
60
76
|
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
if (ul) {
|
|
78
|
+
if (slide) {
|
|
79
|
+
await slideUp(ul, animationSpeed);
|
|
80
|
+
} else {
|
|
81
|
+
ul.style.display = "none";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
63
84
|
|
|
64
|
-
|
|
65
|
-
titleSpan.setAttribute("aria-expanded", "false");
|
|
85
|
+
this.element.classList.add(this.classNames.closed);
|
|
66
86
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
});
|
|
70
|
-
};
|
|
87
|
+
const titleSpan = this.getTitleSpan();
|
|
88
|
+
titleSpan.setAttribute("aria-expanded", "false");
|
|
71
89
|
|
|
72
|
-
|
|
90
|
+
this.triggerEvent("tree.close", {
|
|
91
|
+
node: this.node,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
73
94
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
95
|
+
public async open(
|
|
96
|
+
slide: boolean,
|
|
97
|
+
animationSpeed: AnimationSpeed,
|
|
98
|
+
): Promise<void> {
|
|
99
|
+
if (this.node.is_open) {
|
|
100
|
+
return;
|
|
80
101
|
}
|
|
81
102
|
|
|
82
|
-
|
|
83
|
-
slide: boolean,
|
|
84
|
-
animationSpeed: AnimationSpeed,
|
|
85
|
-
): Promise<void> {
|
|
86
|
-
return new Promise(resolve => {
|
|
87
|
-
if (this.node.is_open) {
|
|
88
|
-
resolve();
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
this.node.is_open = true;
|
|
103
|
+
this.node.is_open = true;
|
|
93
104
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
if (!this.isRendered()) {
|
|
106
|
+
// The folder is rendered open when its parent is opened
|
|
107
|
+
this.triggerEvent("tree.open", { node: this.node });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
97
110
|
|
|
98
|
-
|
|
111
|
+
const button = this.getButton();
|
|
112
|
+
button.classList.remove(this.classNames.closed);
|
|
113
|
+
button.replaceChildren();
|
|
99
114
|
|
|
100
|
-
|
|
101
|
-
const icon = openedIconElement.cloneNode(true);
|
|
102
|
-
button.appendChild(icon);
|
|
103
|
-
}
|
|
115
|
+
const openedIconElement = this.openedIconElement;
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
if (openedIconElement) {
|
|
118
|
+
const icon = openedIconElement.cloneNode(true);
|
|
119
|
+
button.append(icon);
|
|
120
|
+
}
|
|
107
121
|
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
// The children are rendered the first time the folder is opened
|
|
123
|
+
const ul = this.getUl() ?? this.renderChildren(this.node);
|
|
110
124
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
125
|
+
if (ul) {
|
|
126
|
+
if (slide) {
|
|
127
|
+
await slideDown(ul, animationSpeed);
|
|
128
|
+
} else {
|
|
129
|
+
ul.style.display = "block";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
114
132
|
|
|
115
|
-
|
|
116
|
-
};
|
|
133
|
+
this.element.classList.remove(this.classNames.closed);
|
|
117
134
|
|
|
118
|
-
|
|
135
|
+
const titleSpan = this.getTitleSpan();
|
|
136
|
+
titleSpan.setAttribute("aria-expanded", "true");
|
|
119
137
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
doOpen();
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
}
|
|
138
|
+
this.triggerEvent("tree.open", {
|
|
139
|
+
node: this.node,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
protected mustShowBorderDropHint(position: Position): boolean {
|
|
144
|
+
return !this.node.is_open && position === "inside";
|
|
145
|
+
}
|
|
132
146
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
147
|
+
private getButton(): HTMLElement {
|
|
148
|
+
return this.element.querySelector(
|
|
149
|
+
`:scope > .${this.classNames.element} > .${this.classNames.toggler}`,
|
|
150
|
+
) as HTMLElement;
|
|
151
|
+
}
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
export default FolderElement;
|
|
@@ -3,82 +3,84 @@ import type { DropHint } from "../dragAndDropHandler/types";
|
|
|
3
3
|
import type { Node, Position } from "../node";
|
|
4
4
|
|
|
5
5
|
class GhostDropHint implements DropHint {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
6
|
+
private classNames: ClassNames;
|
|
7
|
+
private element: HTMLElement;
|
|
8
|
+
private ghost: HTMLElement;
|
|
9
|
+
private node: Node;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
node: Node,
|
|
13
|
+
element: HTMLElement,
|
|
14
|
+
position: Position,
|
|
15
|
+
classNames: ClassNames,
|
|
16
|
+
) {
|
|
17
|
+
this.classNames = classNames;
|
|
18
|
+
this.element = element;
|
|
19
|
+
this.node = node;
|
|
20
|
+
this.ghost = this.createGhostElement();
|
|
21
|
+
|
|
22
|
+
switch (position) {
|
|
23
|
+
case "after": {
|
|
24
|
+
this.moveAfter();
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
case "before": {
|
|
29
|
+
this.moveBefore();
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
case "inside": {
|
|
34
|
+
if (node.isFolder() && node.is_open) {
|
|
35
|
+
this.moveInsideOpenFolder();
|
|
36
|
+
} else {
|
|
37
|
+
this.moveInside();
|
|
38
38
|
}
|
|
39
|
+
}
|
|
39
40
|
}
|
|
41
|
+
}
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
public remove(): void {
|
|
44
|
+
this.ghost.remove();
|
|
45
|
+
}
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
private createGhostElement() {
|
|
48
|
+
const { circle, common, ghost: ghostClass, line } = this.classNames;
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
const ghost = document.createElement("li");
|
|
51
|
+
ghost.className = `${common} ${ghostClass}`;
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
const circleSpan = document.createElement("span");
|
|
54
|
+
circleSpan.className = `${common} ${circle}`;
|
|
55
|
+
ghost.append(circleSpan);
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
const lineSpan = document.createElement("span");
|
|
58
|
+
lineSpan.className = `${common} ${line}`;
|
|
59
|
+
ghost.append(lineSpan);
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
return ghost;
|
|
62
|
+
}
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
private moveAfter(): void {
|
|
65
|
+
this.element.after(this.ghost);
|
|
66
|
+
}
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
private moveBefore(): void {
|
|
69
|
+
this.element.before(this.ghost);
|
|
70
|
+
}
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
private moveInside(): void {
|
|
73
|
+
this.element.after(this.ghost);
|
|
74
|
+
this.ghost.classList.add(this.classNames.inside);
|
|
75
|
+
}
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
private moveInsideOpenFolder(): void {
|
|
78
|
+
const childElement = this.node.children[0]?.element;
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
80
|
+
if (childElement) {
|
|
81
|
+
childElement.before(this.ghost);
|
|
81
82
|
}
|
|
83
|
+
}
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
export default GhostDropHint;
|
package/src/nodeElement/index.ts
CHANGED
|
@@ -7,97 +7,105 @@ import BorderDropHint from "./borderDropHint";
|
|
|
7
7
|
import GhostDropHint from "./ghostDropHint";
|
|
8
8
|
|
|
9
9
|
export interface NodeElementParams {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
classNames: ClassNames;
|
|
11
|
+
getScrollLeft: GetScrollLeft;
|
|
12
|
+
node: Node;
|
|
13
|
+
tabIndex?: number;
|
|
14
|
+
treeElement: HTMLElement;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
class NodeElement {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return new GhostDropHint(
|
|
52
|
-
this.node,
|
|
53
|
-
this.element,
|
|
54
|
-
position,
|
|
55
|
-
this.classNames,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
18
|
+
public element: HTMLElement;
|
|
19
|
+
public node: Node;
|
|
20
|
+
protected classNames: ClassNames;
|
|
21
|
+
private getScrollLeft: GetScrollLeft;
|
|
22
|
+
private tabIndex?: number;
|
|
23
|
+
private treeElement: HTMLElement;
|
|
24
|
+
|
|
25
|
+
constructor({
|
|
26
|
+
classNames,
|
|
27
|
+
getScrollLeft,
|
|
28
|
+
node,
|
|
29
|
+
tabIndex,
|
|
30
|
+
treeElement,
|
|
31
|
+
}: NodeElementParams) {
|
|
32
|
+
this.classNames = classNames;
|
|
33
|
+
this.getScrollLeft = getScrollLeft;
|
|
34
|
+
this.node = node;
|
|
35
|
+
this.tabIndex = tabIndex;
|
|
36
|
+
this.treeElement = treeElement;
|
|
37
|
+
|
|
38
|
+
// The root node has no element of its own; it uses the tree element.
|
|
39
|
+
this.element = node.element ?? this.treeElement;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public addDropHint(position: Position): DropHint {
|
|
43
|
+
return this.mustShowBorderDropHint(position)
|
|
44
|
+
? new BorderDropHint(this.element, this.getScrollLeft(), this.classNames)
|
|
45
|
+
: new GhostDropHint(this.node, this.element, position, this.classNames);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public deselect(): void {
|
|
49
|
+
if (!this.isRendered()) {
|
|
50
|
+
return;
|
|
58
51
|
}
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
this.element.classList.remove(this.classNames.selected);
|
|
53
|
+
this.element.classList.remove(this.classNames.selected);
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
titleSpan.removeAttribute("tabindex");
|
|
65
|
-
titleSpan.setAttribute("aria-selected", "false");
|
|
55
|
+
const titleSpan = this.getTitleSpan();
|
|
66
56
|
|
|
67
|
-
|
|
57
|
+
// Check for null or undefined
|
|
58
|
+
if (this.tabIndex != null) {
|
|
59
|
+
titleSpan.setAttribute("tabindex", "-1");
|
|
68
60
|
}
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
this.element.classList.add(this.classNames.selected);
|
|
62
|
+
titleSpan.setAttribute("aria-selected", "false");
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
titleSpan.blur();
|
|
65
|
+
}
|
|
75
66
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
public select(mustSetFocus: boolean): void {
|
|
68
|
+
if (!this.isRendered()) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
80
71
|
|
|
81
|
-
|
|
72
|
+
this.element.classList.add(this.classNames.selected);
|
|
82
73
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
}
|
|
74
|
+
const titleSpan = this.getTitleSpan();
|
|
75
|
+
const tabIndex = this.tabIndex;
|
|
87
76
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
) as HTMLSpanElement;
|
|
77
|
+
// Check for null or undefined
|
|
78
|
+
if (tabIndex != null) {
|
|
79
|
+
titleSpan.setAttribute("tabindex", tabIndex.toString());
|
|
92
80
|
}
|
|
93
81
|
|
|
94
|
-
|
|
95
|
-
return this.element.querySelector(":scope > ul") as HTMLUListElement;
|
|
96
|
-
}
|
|
82
|
+
titleSpan.setAttribute("aria-selected", "true");
|
|
97
83
|
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
if (mustSetFocus) {
|
|
85
|
+
titleSpan.focus();
|
|
100
86
|
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
protected getTitleSpan(): HTMLSpanElement {
|
|
90
|
+
return this.element.querySelector(
|
|
91
|
+
`:scope > .${this.classNames.element} > span.${this.classNames.title}`,
|
|
92
|
+
) as HTMLSpanElement;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected getUl(): HTMLUListElement | null {
|
|
96
|
+
return this.element.querySelector(":scope > ul");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* A node inside a closed folder is not rendered. Its selected and open
|
|
100
|
+
* state is applied when it is rendered.
|
|
101
|
+
*/
|
|
102
|
+
protected isRendered(): boolean {
|
|
103
|
+
return Boolean(this.node.element);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected mustShowBorderDropHint(position: Position): boolean {
|
|
107
|
+
return position === "inside";
|
|
108
|
+
}
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
export default NodeElement;
|
package/src/nodeUtils.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { NodeData, NodeRecord } from "./node";
|
|
2
2
|
|
|
3
3
|
interface NodeRecordWithChildren extends NodeRecord {
|
|
4
|
-
|
|
4
|
+
children: NodeData[];
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export const isNodeRecordWithChildren = (
|
|
8
|
-
|
|
8
|
+
data: NodeData,
|
|
9
9
|
): data is NodeRecordWithChildren =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
typeof data === "object" &&
|
|
11
|
+
"children" in data &&
|
|
12
|
+
Array.isArray(data.children);
|