tree-element 0.1.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.
Files changed (182) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +221 -0
  3. package/lib/animation.d.ts +5 -0
  4. package/lib/animation.d.ts.map +1 -0
  5. package/lib/animation.js +39 -0
  6. package/lib/animation.js.map +1 -0
  7. package/lib/classNames.d.ts +34 -0
  8. package/lib/classNames.d.ts.map +1 -0
  9. package/lib/classNames.js +39 -0
  10. package/lib/classNames.js.map +1 -0
  11. package/lib/dataLoader.d.ts +25 -0
  12. package/lib/dataLoader.d.ts.map +1 -0
  13. package/lib/dataLoader.js +69 -0
  14. package/lib/dataLoader.js.map +1 -0
  15. package/lib/dragAndDropHandler/binarySearch.d.ts +3 -0
  16. package/lib/dragAndDropHandler/binarySearch.d.ts.map +1 -0
  17. package/lib/dragAndDropHandler/binarySearch.js +23 -0
  18. package/lib/dragAndDropHandler/binarySearch.js.map +1 -0
  19. package/lib/dragAndDropHandler/dragElement.d.ts +20 -0
  20. package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -0
  21. package/lib/dragAndDropHandler/dragElement.js +39 -0
  22. package/lib/dragAndDropHandler/dragElement.js.map +1 -0
  23. package/lib/dragAndDropHandler/generateHitAreas.d.ts +13 -0
  24. package/lib/dragAndDropHandler/generateHitAreas.d.ts.map +1 -0
  25. package/lib/dragAndDropHandler/generateHitAreas.js +130 -0
  26. package/lib/dragAndDropHandler/generateHitAreas.js.map +1 -0
  27. package/lib/dragAndDropHandler/index.d.ts +76 -0
  28. package/lib/dragAndDropHandler/index.d.ts.map +1 -0
  29. package/lib/dragAndDropHandler/index.js +311 -0
  30. package/lib/dragAndDropHandler/index.js.map +1 -0
  31. package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts +11 -0
  32. package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -0
  33. package/lib/dragAndDropHandler/iterateVisibleNodes.js +54 -0
  34. package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -0
  35. package/lib/dragAndDropHandler/types.d.ts +11 -0
  36. package/lib/dragAndDropHandler/types.d.ts.map +1 -0
  37. package/lib/elementsRenderer.d.ts +53 -0
  38. package/lib/elementsRenderer.d.ts.map +1 -0
  39. package/lib/elementsRenderer.js +251 -0
  40. package/lib/elementsRenderer.js.map +1 -0
  41. package/lib/events.d.ts +224 -0
  42. package/lib/events.d.ts.map +1 -0
  43. package/lib/index.d.ts +367 -0
  44. package/lib/index.d.ts.map +1 -0
  45. package/lib/index.js +1098 -0
  46. package/lib/index.js.map +1 -0
  47. package/lib/keyHandler.d.ts +29 -0
  48. package/lib/keyHandler.d.ts.map +1 -0
  49. package/lib/keyHandler.js +107 -0
  50. package/lib/keyHandler.js.map +1 -0
  51. package/lib/methodTypes.d.ts +21 -0
  52. package/lib/methodTypes.d.ts.map +1 -0
  53. package/lib/mouseHandler.d.ts +60 -0
  54. package/lib/mouseHandler.d.ts.map +1 -0
  55. package/lib/mouseHandler.js +283 -0
  56. package/lib/mouseHandler.js.map +1 -0
  57. package/lib/mouseUtils.d.ts +9 -0
  58. package/lib/mouseUtils.d.ts.map +1 -0
  59. package/lib/mouseUtils.js +15 -0
  60. package/lib/mouseUtils.js.map +1 -0
  61. package/lib/node.d.ts +320 -0
  62. package/lib/node.d.ts.map +1 -0
  63. package/lib/node.js +737 -0
  64. package/lib/node.js.map +1 -0
  65. package/lib/nodeElement/borderDropHint.d.ts +9 -0
  66. package/lib/nodeElement/borderDropHint.d.ts.map +1 -0
  67. package/lib/nodeElement/borderDropHint.js +24 -0
  68. package/lib/nodeElement/borderDropHint.js.map +1 -0
  69. package/lib/nodeElement/folderElement.d.ts +22 -0
  70. package/lib/nodeElement/folderElement.d.ts.map +1 -0
  71. package/lib/nodeElement/folderElement.js +100 -0
  72. package/lib/nodeElement/folderElement.js.map +1 -0
  73. package/lib/nodeElement/ghostDropHint.d.ts +18 -0
  74. package/lib/nodeElement/ghostDropHint.d.ts.map +1 -0
  75. package/lib/nodeElement/ghostDropHint.js +67 -0
  76. package/lib/nodeElement/ghostDropHint.js.map +1 -0
  77. package/lib/nodeElement/index.d.ts +28 -0
  78. package/lib/nodeElement/index.d.ts.map +1 -0
  79. package/lib/nodeElement/index.js +66 -0
  80. package/lib/nodeElement/index.js.map +1 -0
  81. package/lib/nodeUtils.d.ts +7 -0
  82. package/lib/nodeUtils.d.ts.map +1 -0
  83. package/lib/nodeUtils.js +4 -0
  84. package/lib/nodeUtils.js.map +1 -0
  85. package/lib/options.d.ts +310 -0
  86. package/lib/options.d.ts.map +1 -0
  87. package/lib/package.json +3 -0
  88. package/lib/positionUtils.d.ts +8 -0
  89. package/lib/positionUtils.d.ts.map +1 -0
  90. package/lib/positionUtils.js +14 -0
  91. package/lib/positionUtils.js.map +1 -0
  92. package/lib/requestUrl.d.ts +9 -0
  93. package/lib/requestUrl.d.ts.map +1 -0
  94. package/lib/requestUrl.js +37 -0
  95. package/lib/requestUrl.js.map +1 -0
  96. package/lib/saveStateHandler.d.ts +46 -0
  97. package/lib/saveStateHandler.d.ts.map +1 -0
  98. package/lib/saveStateHandler.js +204 -0
  99. package/lib/saveStateHandler.js.map +1 -0
  100. package/lib/scrollHandler/containerScrollParent.d.ts +12 -0
  101. package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -0
  102. package/lib/scrollHandler/containerScrollParent.js +49 -0
  103. package/lib/scrollHandler/containerScrollParent.js.map +1 -0
  104. package/lib/scrollHandler/createScrollParent.d.ts +4 -0
  105. package/lib/scrollHandler/createScrollParent.d.ts.map +1 -0
  106. package/lib/scrollHandler/createScrollParent.js +38 -0
  107. package/lib/scrollHandler/createScrollParent.js.map +1 -0
  108. package/lib/scrollHandler/documentScrollParent.d.ts +22 -0
  109. package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -0
  110. package/lib/scrollHandler/documentScrollParent.js +71 -0
  111. package/lib/scrollHandler/documentScrollParent.js.map +1 -0
  112. package/lib/scrollHandler/scrollParent.d.ts +26 -0
  113. package/lib/scrollHandler/scrollParent.d.ts.map +1 -0
  114. package/lib/scrollHandler/scrollParent.js +79 -0
  115. package/lib/scrollHandler/scrollParent.js.map +1 -0
  116. package/lib/scrollHandler.d.ts +20 -0
  117. package/lib/scrollHandler.d.ts.map +1 -0
  118. package/lib/scrollHandler.js +41 -0
  119. package/lib/scrollHandler.js.map +1 -0
  120. package/lib/selectNodeHandler.d.ts +38 -0
  121. package/lib/selectNodeHandler.d.ts.map +1 -0
  122. package/lib/selectNodeHandler.js +166 -0
  123. package/lib/selectNodeHandler.js.map +1 -0
  124. package/lib/setDefaultOptions.d.ts +4 -0
  125. package/lib/setDefaultOptions.d.ts.map +1 -0
  126. package/lib/setDefaultOptions.js +86 -0
  127. package/lib/setDefaultOptions.js.map +1 -0
  128. package/lib/triggerCustomEvent.d.ts +3 -0
  129. package/lib/triggerCustomEvent.d.ts.map +1 -0
  130. package/lib/triggerCustomEvent.js +13 -0
  131. package/lib/triggerCustomEvent.js.map +1 -0
  132. package/lib/util.d.ts +3 -0
  133. package/lib/util.d.ts.map +1 -0
  134. package/lib/util.js +5 -0
  135. package/lib/util.js.map +1 -0
  136. package/lib/version.d.ts +3 -0
  137. package/lib/version.d.ts.map +1 -0
  138. package/lib/version.js +5 -0
  139. package/lib/version.js.map +1 -0
  140. package/package.json +110 -0
  141. package/src/animation.ts +48 -0
  142. package/src/classNames.ts +70 -0
  143. package/src/dataLoader.ts +92 -0
  144. package/src/dragAndDropHandler/binarySearch.ts +27 -0
  145. package/src/dragAndDropHandler/dragElement.ts +62 -0
  146. package/src/dragAndDropHandler/generateHitAreas.ts +195 -0
  147. package/src/dragAndDropHandler/index.ts +442 -0
  148. package/src/dragAndDropHandler/iterateVisibleNodes.ts +91 -0
  149. package/src/dragAndDropHandler/types.ts +12 -0
  150. package/src/elementsRenderer.ts +367 -0
  151. package/src/events.ts +237 -0
  152. package/src/header.txt +16 -0
  153. package/src/index.ts +1290 -0
  154. package/src/keyHandler.ts +139 -0
  155. package/src/methodTypes.ts +44 -0
  156. package/src/mouseHandler.ts +391 -0
  157. package/src/mouseUtils.ts +23 -0
  158. package/src/node.ts +831 -0
  159. package/src/nodeElement/borderDropHint.ts +37 -0
  160. package/src/nodeElement/folderElement.ts +140 -0
  161. package/src/nodeElement/ghostDropHint.ts +84 -0
  162. package/src/nodeElement/index.ts +103 -0
  163. package/src/nodeUtils.ts +12 -0
  164. package/src/options.ts +325 -0
  165. package/src/positionUtils.ts +18 -0
  166. package/src/requestUrl.ts +41 -0
  167. package/src/saveStateHandler.ts +279 -0
  168. package/src/scrollHandler/containerScrollParent.ts +71 -0
  169. package/src/scrollHandler/createScrollParent.ts +51 -0
  170. package/src/scrollHandler/documentScrollParent.ts +104 -0
  171. package/src/scrollHandler/scrollParent.ts +117 -0
  172. package/src/scrollHandler.ts +55 -0
  173. package/src/selectNodeHandler.ts +192 -0
  174. package/src/setDefaultOptions.ts +79 -0
  175. package/src/triggerCustomEvent.ts +14 -0
  176. package/src/util.ts +5 -0
  177. package/src/version.ts +4 -0
  178. package/tree_element.css +195 -0
  179. package/tree_element.debug.js +4153 -0
  180. package/tree_element.debug.js.map +1 -0
  181. package/tree_element.js +21 -0
  182. package/tree_element.js.map +1 -0
@@ -0,0 +1,92 @@
1
+ import type { ClassNames } from "./classNames";
2
+ import type { LoadData, TriggerEvent } from "./methodTypes";
3
+ import type { Node, NodeData } from "./node";
4
+ import type { DataFilter } from "./options";
5
+ import type RequestUrl from "./requestUrl";
6
+
7
+ interface DataLoaderParams {
8
+ classNames: ClassNames;
9
+ dataFilter?: DataFilter;
10
+ loadData: LoadData;
11
+ treeElement: HTMLElement;
12
+ triggerEvent: TriggerEvent;
13
+ }
14
+
15
+ export default class DataLoader {
16
+ private abortController: AbortController;
17
+ private classNames: ClassNames;
18
+ private dataFilter?: DataFilter;
19
+ private loadData: LoadData;
20
+ private treeElement: HTMLElement;
21
+ private triggerEvent: TriggerEvent;
22
+
23
+ constructor({
24
+ classNames,
25
+ dataFilter,
26
+ loadData,
27
+ treeElement,
28
+ triggerEvent,
29
+ }: DataLoaderParams) {
30
+ this.abortController = new AbortController();
31
+ this.classNames = classNames;
32
+ this.dataFilter = dataFilter;
33
+ this.loadData = loadData;
34
+ this.treeElement = treeElement;
35
+ this.triggerEvent = triggerEvent;
36
+ }
37
+
38
+ public deinit(): void {
39
+ this.abortController.abort();
40
+ }
41
+
42
+ public async loadFromUrl(
43
+ url: RequestUrl,
44
+ node?: Node,
45
+ ): Promise<void> {
46
+ const element = node?.element ?? this.treeElement;
47
+ element.classList.add(this.classNames.loading);
48
+
49
+ this.triggerEvent("tree.loading_data", {
50
+ element,
51
+ node,
52
+ });
53
+
54
+ const stopLoading = (): void => {
55
+ element.classList.remove(this.classNames.loading);
56
+ this.triggerEvent("tree.loaded_data", {
57
+ element,
58
+ node,
59
+ });
60
+ };
61
+
62
+ const handleResponse = async (response: Response): Promise<void> => {
63
+ if (response.ok) {
64
+ const data = (await response.json()) as NodeData[];
65
+
66
+ stopLoading();
67
+ this.loadData(
68
+ this.dataFilter ? this.dataFilter(data) : data,
69
+ node
70
+ );
71
+ } else {
72
+ stopLoading();
73
+
74
+ this.triggerEvent("tree.load_failed", { response });
75
+ }
76
+ };
77
+
78
+ const signal = this.abortController.signal;
79
+ url.setSearchParam("_", Date.now().toString());
80
+
81
+ return fetch(url.toString(), { headers: { "Content-Type": "application/json" }, signal })
82
+ .then(handleResponse)
83
+ .catch((error: unknown) => {
84
+ if (this.abortController.signal.aborted) {
85
+ // The request was aborted by deinit.
86
+ return;
87
+ }
88
+
89
+ throw error;
90
+ });
91
+ }
92
+ }
@@ -0,0 +1,27 @@
1
+ function binarySearch<T>(items: T[], compareFn: (a: T) => number): null | T {
2
+ let low = 0;
3
+ let high = items.length;
4
+
5
+ while (low < high) {
6
+ const mid = (low + high) >> 1;
7
+ const item = items[mid];
8
+
9
+ if (item === undefined) {
10
+ return null;
11
+ }
12
+
13
+ const compareResult = compareFn(item);
14
+
15
+ if (compareResult > 0) {
16
+ high = mid;
17
+ } else if (compareResult < 0) {
18
+ low = mid + 1;
19
+ } else {
20
+ return item;
21
+ }
22
+ }
23
+
24
+ return null;
25
+ }
26
+
27
+ export default binarySearch;
@@ -0,0 +1,62 @@
1
+ import type { ClassNames } from "../classNames";
2
+
3
+ interface DragElementParams {
4
+ autoEscape: boolean;
5
+ classNames: ClassNames;
6
+ nodeName: string;
7
+ offsetX: number;
8
+ offsetY: number;
9
+ treeElement: HTMLElement;
10
+ }
11
+
12
+ class DragElement {
13
+ private element: HTMLElement;
14
+ private offsetX: number;
15
+ private offsetY: number;
16
+
17
+ constructor({
18
+ autoEscape,
19
+ classNames,
20
+ nodeName,
21
+ offsetX,
22
+ offsetY,
23
+ treeElement,
24
+ }: DragElementParams) {
25
+ this.offsetX = offsetX;
26
+ this.offsetY = offsetY;
27
+
28
+ this.element = this.createElement(nodeName, autoEscape, classNames);
29
+
30
+ treeElement.appendChild(this.element);
31
+ }
32
+
33
+ public move(pageX: number, pageY: number): void {
34
+ this.element.style.left = `${pageX - this.offsetX}px`;
35
+ this.element.style.top = `${pageY - this.offsetY}px`;
36
+ }
37
+
38
+ public remove(): void {
39
+ this.element.remove();
40
+ }
41
+
42
+ private createElement(
43
+ nodeName: string,
44
+ autoEscape: boolean,
45
+ classNames: ClassNames,
46
+ ) {
47
+ const element = document.createElement("span");
48
+ element.classList.add(classNames.title, classNames.dragging);
49
+
50
+ if (autoEscape) {
51
+ element.textContent = nodeName;
52
+ } else {
53
+ element.innerHTML = nodeName;
54
+ }
55
+
56
+ element.style.position = "absolute";
57
+
58
+ return element;
59
+ }
60
+ }
61
+
62
+ export default DragElement;
@@ -0,0 +1,195 @@
1
+ import type { Node, Position } from "../node";
2
+ import type { HitArea } from "./types";
3
+
4
+ import { getOffsetTop } from "../positionUtils";
5
+ import iterateVisibleNodes from "./iterateVisibleNodes";
6
+
7
+ interface HitPosition {
8
+ node: Node;
9
+ position: null | Position;
10
+ top: number;
11
+ }
12
+
13
+ export const generateHitPositions = (
14
+ tree: Node,
15
+ currentNode: Node,
16
+ ): HitPosition[] => {
17
+ const hitPositions: HitPosition[] = [];
18
+ let lastTop = 0;
19
+
20
+ const addHitPosition = (
21
+ node: Node,
22
+ position: null | Position,
23
+ top: number,
24
+ ) => {
25
+ hitPositions.push({
26
+ node,
27
+ position,
28
+ top,
29
+ });
30
+ lastTop = top;
31
+ };
32
+
33
+ const handleAfterOpenFolder = (node: Node, nextNode: Node | null) => {
34
+ if (node === currentNode || nextNode === currentNode) {
35
+ // Cannot move before or after current item
36
+ addHitPosition(node, null, lastTop);
37
+ } else {
38
+ addHitPosition(node, "after", lastTop);
39
+ }
40
+ };
41
+
42
+ const handleClosedFolder = (
43
+ node: Node,
44
+ nextNode: Node | null,
45
+ element: HTMLElement,
46
+ ) => {
47
+ const top = getOffsetTop(element);
48
+
49
+ if (node === currentNode) {
50
+ // Cannot move after current item
51
+ addHitPosition(node, null, top);
52
+ } else {
53
+ addHitPosition(node, "inside", top);
54
+
55
+ // Cannot move before current item
56
+ if (nextNode !== currentNode) {
57
+ addHitPosition(node, "after", top);
58
+ }
59
+ }
60
+ };
61
+
62
+ const handleFirstNode = (node: Node) => {
63
+ if (node !== currentNode && node.element) {
64
+ addHitPosition(node, "before", getOffsetTop(node.element));
65
+ }
66
+ };
67
+
68
+ const handleNode = (
69
+ node: Node,
70
+ nextNode: Node | null,
71
+ element: HTMLElement,
72
+ ) => {
73
+ const top = getOffsetTop(element);
74
+
75
+ if (node === currentNode) {
76
+ // Cannot move inside current item
77
+ addHitPosition(node, null, top);
78
+ } else {
79
+ addHitPosition(node, "inside", top);
80
+ }
81
+
82
+ if (nextNode === currentNode || node === currentNode) {
83
+ // Cannot move before or after current item
84
+ addHitPosition(node, null, top);
85
+ } else {
86
+ addHitPosition(node, "after", top);
87
+ }
88
+ };
89
+
90
+ const handleOpenFolder = (node: Node, element: HTMLElement) => {
91
+ if (node === currentNode) {
92
+ // Cannot move inside current item
93
+
94
+ // Dnd over the current element is not possible: add a position with type None for the top and the bottom.
95
+ const top = getOffsetTop(element);
96
+ const height = element.clientHeight;
97
+ addHitPosition(node, null, top);
98
+
99
+ if (height > 5) {
100
+ // Subtract 5 pixels to allow more space for the next element.
101
+ addHitPosition(node, null, top + height - 5);
102
+ }
103
+
104
+ // Stop iterating
105
+ return false;
106
+ }
107
+
108
+ // Cannot move before current item
109
+ if (node.children[0] !== currentNode) {
110
+ addHitPosition(node, "inside", getOffsetTop(element));
111
+ }
112
+
113
+ // Continue iterating
114
+ return true;
115
+ };
116
+
117
+ iterateVisibleNodes(tree, {
118
+ handleAfterOpenFolder,
119
+ handleClosedFolder,
120
+ handleFirstNode,
121
+ handleNode,
122
+ handleOpenFolder,
123
+ });
124
+
125
+ return hitPositions;
126
+ };
127
+
128
+ export const generateHitAreasForGroup = (
129
+ hitAreas: HitArea[],
130
+ positionsInGroup: HitPosition[],
131
+ top: number,
132
+ bottom: number,
133
+ ) => {
134
+ // limit positions in group
135
+ const positionCount = Math.min(positionsInGroup.length, 4);
136
+
137
+ const areaHeight = Math.round((bottom - top) / positionCount);
138
+ let areaTop = top;
139
+
140
+ for (let i = 0; i < positionCount; i++) {
141
+ const position = positionsInGroup[i] as HitPosition;
142
+
143
+ if (position.position) {
144
+ hitAreas.push({
145
+ bottom: areaTop + areaHeight,
146
+ node: position.node,
147
+ position: position.position,
148
+ top: areaTop,
149
+ });
150
+ }
151
+
152
+ areaTop += areaHeight;
153
+ }
154
+ };
155
+
156
+ export const generateHitAreasFromPositions = (
157
+ hitPositions: HitPosition[],
158
+ treeBottom: number,
159
+ ): HitArea[] => {
160
+ if (!hitPositions.length) {
161
+ return [];
162
+ }
163
+
164
+ let previousTop = (hitPositions[0] as HitPosition).top;
165
+ let group: HitPosition[] = [];
166
+ const hitAreas: HitArea[] = [];
167
+
168
+ for (const position of hitPositions) {
169
+ if (position.top !== previousTop && group.length) {
170
+ generateHitAreasForGroup(
171
+ hitAreas,
172
+ group,
173
+ previousTop,
174
+ position.top,
175
+ );
176
+
177
+ previousTop = position.top;
178
+ group = [];
179
+ }
180
+
181
+ group.push(position);
182
+ }
183
+
184
+ generateHitAreasForGroup(hitAreas, group, previousTop, treeBottom);
185
+
186
+ return hitAreas;
187
+ };
188
+
189
+ const generateHitAreas = (tree: Node, currentNode: Node, treeBottom: number) =>
190
+ generateHitAreasFromPositions(
191
+ generateHitPositions(tree, currentNode),
192
+ treeBottom,
193
+ );
194
+
195
+ export default generateHitAreas;