@pictogrammers/components 0.5.14 → 0.5.17

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 (153) hide show
  1. package/package.json +1 -1
  2. package/pg/autocompleteItem/__examples__/basic/basic.html +3 -0
  3. package/pg/autocompleteItem/autocompleteItem.css +55 -0
  4. package/pg/autocompleteItem/autocompleteItem.html +1 -0
  5. package/pg/autocompleteItem/autocompleteItem.ts +65 -0
  6. package/pg/button/button.css +5 -0
  7. package/pg/buttonMenu/buttonMenu.ts +1 -1
  8. package/pg/inputCombobox/__examples__/basic/basic.ts +33 -0
  9. package/pg/inputCombobox/inputCombobox.ts +158 -0
  10. package/pg/inputCombobox/inputCombobox.ts.tmp.44252.751480cb81cc +158 -0
  11. package/pg/inputCombobox/inputCombobox.ts.tmp.44252.dcea847c40a8 +156 -0
  12. package/pg/inputNumber/inputNumber.ts +31 -13
  13. package/pg/inputPill/inputPill.html +6 -0
  14. package/pg/inputPill/inputPill.html.tmp.26852.84ac63f4c46f +6 -0
  15. package/pg/inputPill/inputPill.ts +41 -0
  16. package/pg/inputPills/__examples__/basic/basic.html +9 -0
  17. package/pg/inputPills/__examples__/basic/basic.html.tmp.26852.4771e4cad5b7 +9 -0
  18. package/pg/inputPills/__examples__/basic/basic.ts.tmp.26852.d8fe41df18bd +0 -0
  19. package/pg/inputPixelEditor/README.md +104 -69
  20. package/pg/inputPixelEditor/README.md.tmp.42596.658de5f0a6f5 +0 -0
  21. package/pg/inputPixelEditor/__examples__/basic/basic.ts +6 -5
  22. package/pg/inputPixelEditor/inputPixelEditor.ts +95 -23
  23. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.38516.96529dd82670 +1703 -0
  24. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.42596.48ecc3ad9c72 +1724 -0
  25. package/pg/inputPixelEditor/utils/bitmapToMask.ts +113 -79
  26. package/pg/inputPixelEditor/utils/getLassoPixels.ts +51 -0
  27. package/pg/inputRange/inputRange.css +7 -0
  28. package/pg/inputSelect/__examples__/basic/basic.ts +2 -2
  29. package/pg/inputSelect/inputSelect.css +1 -1
  30. package/pg/inputSelect/inputSelect.ts +62 -5
  31. package/pg/inputText/README.md +6 -6
  32. package/pg/inputText/__examples__/basic/basic.ts +1 -1
  33. package/pg/inputText/inputText.css +2 -2
  34. package/pg/inputText copy/README.md +38 -0
  35. package/pg/inputText copy/inputText.css +41 -0
  36. package/pg/inputText copy/inputText.html +1 -0
  37. package/pg/inputText copy/inputText.spec.ts +59 -0
  38. package/pg/inputText copy/inputText.ts +67 -0
  39. package/pg/inputTextarea/README.md +39 -0
  40. package/pg/inputTextarea/__examples__/basic/basic.html +9 -0
  41. package/pg/inputTextarea/__examples__/basic/basic.ts +30 -0
  42. package/pg/inputTextarea/inputTextarea.ts +121 -0
  43. package/pg/inputTextarea copy/README.md +39 -0
  44. package/pg/inputTextarea copy/inputTextarea.css +41 -0
  45. package/pg/inputTextarea copy/inputTextarea.html +1 -0
  46. package/pg/inputTextarea copy/inputTextarea.spec.ts +59 -0
  47. package/pg/inputTextarea copy/inputTextarea.ts +79 -0
  48. package/pg/inputTextareaAutocomplete/README.md +70 -0
  49. package/pg/inputTextareaAutocomplete/__examples__/basic/basic.ts +67 -0
  50. package/pg/inputTextareaAutocomplete/inputTextareaAutocomplete.ts +267 -0
  51. package/pg/node/README.md +35 -0
  52. package/pg/node/__examples__/basic/basic.ts +34 -0
  53. package/pg/node/index.ts +3 -0
  54. package/pg/node/node.css +53 -0
  55. package/pg/node/node.html +5 -0
  56. package/pg/node/node.ts +270 -0
  57. package/pg/nodeEditorLink/nodeEditorLink.css +69 -0
  58. package/pg/nodeEditorLink/nodeEditorLink.css.tmp.1408.09e961fd0dcc +69 -0
  59. package/pg/nodeEditorLink/nodeEditorLink.html +9 -0
  60. package/pg/nodeEditorNumber/nodeEditorNumber.css +59 -0
  61. package/pg/nodeEditorNumber/nodeEditorNumber.ts +57 -0
  62. package/pg/nodeEditorRange/nodeEditorRange.css +23 -0
  63. package/pg/nodeEditorRange/nodeEditorRange.ts +69 -0
  64. package/pg/nodeEditorText/__examples__/basic/basic.html +9 -0
  65. package/pg/nodeEditorText/__examples__/basic/basic.ts +30 -0
  66. package/pg/nodeEditorText/nodeEditorText.css +17 -0
  67. package/pg/nodeEditorText/nodeEditorText.html +4 -0
  68. package/pg/nodeEditorText/nodeEditorText.ts +57 -0
  69. package/pg/nodeEditorText copy/README.md +35 -0
  70. package/pg/nodeEditorText copy/nodeEditorText.css +49 -0
  71. package/pg/nodeEditorText copy/nodeEditorText.html +4 -0
  72. package/pg/nodeEditorText copy/nodeEditorText.ts +50 -0
  73. package/pg/nodeEditorTextArray/nodeEditorTextArray.css +68 -0
  74. package/pg/nodeEditorTextArray/nodeEditorTextArray.html +9 -0
  75. package/pg/nodeEditorTextArray/nodeEditorTextArray.ts +162 -0
  76. package/pg/nodeEntry/nodeEntry.css +61 -0
  77. package/pg/nodeEntry/nodeEntry.ts +164 -0
  78. package/pg/nodeEntry/nodeEntry.ts.tmp.28724.dda67762bca5 +164 -0
  79. package/pg/nodeInputText/nodeInputText.css +75 -0
  80. package/pg/nodeInputText/nodeInputText.html +4 -0
  81. package/pg/nodeInputText/nodeInputText.ts +105 -0
  82. package/pg/nodeOutput/nodeOutput.css +32 -0
  83. package/pg/nodeResize/README.md +3 -0
  84. package/pg/nodeResize/THINKING.md +81 -0
  85. package/pg/nodeResize/THINKING.md.tmp.24812.99a70ba81062 +81 -0
  86. package/pg/nodeResize/basic/basic.ts +17 -0
  87. package/pg/nodeResize/dragUtil.ts +105 -0
  88. package/pg/nodeResize/dragUtil.ts.tmp.34372.787464c73309 +75 -0
  89. package/pg/nodeResize/nodeResize.css +187 -0
  90. package/pg/nodeResize/nodeResize.html +9 -0
  91. package/pg/nodeResize/nodeResize.ts +156 -0
  92. package/pg/nodes/README.md +177 -0
  93. package/pg/nodes/__examples__/basic/basic.html +33 -0
  94. package/pg/nodes/__examples__/basic/basic.ts +716 -0
  95. package/pg/nodes/__examples__/basic/exampleNodes.ts +129 -0
  96. package/pg/nodes/__examples__/basic/exampleScripts.ts +129 -0
  97. package/pg/nodes/__examples__/basic/keystore.ts +38 -0
  98. package/pg/nodes/executeInSandbox.ts +32 -0
  99. package/pg/nodes/index.ts +3 -0
  100. package/pg/nodes/nodes.css +69 -0
  101. package/pg/nodes/nodes.html +6 -0
  102. package/pg/nodes/nodes.ts +1240 -0
  103. package/pg/nodes copy/nodes.css +41 -0
  104. package/pg/nodes copy/nodes.html +1 -0
  105. package/pg/overlayContextMenu/__examples__/filter/filter.ts +87 -0
  106. package/pg/overlayContextMenu/overlayContextMenu.css +14 -0
  107. package/pg/overlayContextMenu/overlayContextMenu.html +4 -3
  108. package/pg/overlayContextMenu/overlayContextMenu.ts +6 -2
  109. package/pg/overlayContextMenu/overlayContextMenu.ts.tmp.37088.530ff1c0a321 +0 -0
  110. package/pg/overlayMenu/overlayMenu.css +3 -1
  111. package/pg/overlayMenu/overlayMenu.ts +11 -2
  112. package/pg/overlayMenu/overlayMenu.ts.tmp.44252.9bb22fd59ede +80 -0
  113. package/pg/overlaySelectMenu/overlaySelectMenu.css +2 -0
  114. package/pg/overlaySubMenu/overlaySubMenu.css +8 -6
  115. package/pg/poco/README.md +22 -0
  116. package/pg/poco/__examples__/basic/basic.html +11 -0
  117. package/pg/poco/__examples__/basic/basic.ts +95 -0
  118. package/pg/poco/__examples__/basic/examples.ts +258 -0
  119. package/pg/poco/__examples__/basic/myFont.ts +1300 -0
  120. package/pg/poco/index.ts +3 -0
  121. package/pg/poco/mockPoco.ts +640 -0
  122. package/pg/poco/poco.css +7 -0
  123. package/pg/poco/poco.html +1 -0
  124. package/pg/poco/poco.ts +75 -0
  125. package/pg/popover/README.md +47 -0
  126. package/pg/popover/__examples__/basic/basic.html +3 -0
  127. package/pg/popover/popover.html +3 -0
  128. package/pg/popover/popover.ts +44 -0
  129. package/pg/popoverAutocomplete/__examples__/basic/basic.html +4 -0
  130. package/pg/popoverAutocomplete/__examples__/basic/basic.ts +46 -0
  131. package/pg/popoverAutocomplete/popoverAutocomplete.css +25 -0
  132. package/pg/popoverAutocomplete/popoverAutocomplete.html +1 -0
  133. package/pg/popoverAutocomplete/popoverAutocomplete.ts +134 -0
  134. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.css +69 -0
  135. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.ts +90 -0
  136. package/pg/table/__examples__/basic/basic.ts +1 -0
  137. package/pg/tableCellFileLocal/tableCellFileLocal.html +3 -0
  138. package/pg/tableCellFileLocal/tableCellFileLocal.html.tmp.20484.68ee2e30710e +3 -0
  139. package/pg/tableCellFileLocal/tableCellFileLocal.ts +44 -0
  140. package/pg/tableCellSelect/tableCellSelect.html +3 -0
  141. package/pg/tableCellSelect/tableCellSelect.html.tmp.41808.99c1a6f14340 +3 -0
  142. package/pg/tableCellSelect/tableCellSelect.ts +51 -0
  143. package/pg/tree/__examples__/basic/basic.ts +12 -5
  144. package/pg/tree/tree.html +1 -1
  145. package/pg/tree/tree.ts +385 -227
  146. package/pg/tree/tree.ts.tmp.38376.07d376a04f41 +343 -0
  147. package/pg/tree/tree.ts.tmp.38376.2a04599ade9f +361 -0
  148. package/pg/tree/tree.ts.tmp.38376.6cb2c663d476 +0 -0
  149. package/pg/tree/tree.ts.tmp.38376.ac5af1aff2b0 +393 -0
  150. package/pg/tree/tree.ts.tmp.38376.ac9acfc4f95f +324 -0
  151. package/pg/treeItem/treeItem.ts +536 -558
  152. package/pg/treeItem/treeItem.ts.tmp.38376.145d3121d648 +530 -0
  153. package/pg/treeItem/treeItem.ts.tmp.38376.b5224d48e5c0 +0 -0
@@ -0,0 +1,393 @@
1
+ import { Component, Prop, Part, forEach, getProxyValue } from '@pictogrammers/element';
2
+
3
+ import PgTreeItem from '../treeItem/treeItem';
4
+
5
+ import template from './tree.html';
6
+ import style from './tree.css';
7
+
8
+ export type SelectedTreeItem = {
9
+ indexes: number[];
10
+ remove: () => void;
11
+ getData: () => any;
12
+ getParentData: () => any;
13
+ move: (item: SelectedTreeItem, position: string) => void;
14
+ }
15
+
16
+ @Component({
17
+ selector: 'pg-tree',
18
+ style,
19
+ template
20
+ })
21
+ export default class PgTree extends HTMLElement {
22
+ @Prop() items: any[] = [];
23
+
24
+ @Part() $items: HTMLDivElement;
25
+
26
+ #selectedIndexes = new Map();
27
+ #lastSelectedIndexes: number[] | null = null;
28
+ #draggingElements: Set<HTMLElement> = new Set();
29
+
30
+ connectedCallback() {
31
+ forEach({
32
+ container: this.$items,
33
+ items: this.items,
34
+ type: () => PgTreeItem
35
+ });
36
+ this.$items.addEventListener('action', (e: any) => {
37
+ e.stopPropagation();
38
+ this.dispatchEvent(new CustomEvent('action', {
39
+ detail: {
40
+ actionIndex: e.detail.actionIndex,
41
+ item: this.#wrap(e.detail.indexes),
42
+ }
43
+ }));
44
+ });
45
+ this.$items.addEventListener('move', (e: any) => {
46
+ e.stopPropagation();
47
+ const selectedIdxsList = [...this.#selectedIndexes.values()] as number[][];
48
+ this.#batchMove(selectedIdxsList, e.detail.indexes, e.detail.position);
49
+ this.dispatchEvent(new CustomEvent('move', {
50
+ detail: { position: e.detail.position }
51
+ }));
52
+ this.dispatchEvent(new CustomEvent('select', {
53
+ detail: {
54
+ items: [...this.#selectedIndexes.values()].map((idxs: any) => this.#wrap(idxs)),
55
+ }
56
+ }));
57
+ });
58
+ this.$items.addEventListener('rename', (e: any) => {
59
+ e.stopPropagation();
60
+ this.dispatchEvent(new CustomEvent('rename', {
61
+ detail: {
62
+ item: this.#wrap(e.detail.indexes),
63
+ label: e.detail.label,
64
+ }
65
+ }));
66
+ });
67
+ this.$items.addEventListener('toggle', (e: any) => {
68
+ const item = this.#getItem(e.detail.indexes);
69
+ item.expanded = !item.expanded;
70
+ });
71
+ this.$items.addEventListener('expand', (e: any) => {
72
+ this.#getItem(e.detail.indexes).expanded = true;
73
+ });
74
+ this.$items.addEventListener('menu', (e: any) => {
75
+ e.stopPropagation();
76
+ this.dispatchEvent(new CustomEvent('menu', {
77
+ detail: {
78
+ item: this.#wrap(e.detail.indexes),
79
+ x: e.detail.x,
80
+ y: e.detail.y,
81
+ }
82
+ }));
83
+ });
84
+ this.$items.addEventListener('select', (e: any) => {
85
+ e.stopPropagation();
86
+ const { indexes, type, ctrlKey, shiftKey } = e.detail;
87
+ const item = this.#getItem(indexes);
88
+ const unproxyItem = getProxyValue(item);
89
+
90
+ if (shiftKey && this.#lastSelectedIndexes) {
91
+ const visible = this.#getVisibleIndexes();
92
+ const lastPos = visible.findIndex(v => v.join(',') === this.#lastSelectedIndexes!.join(','));
93
+ const currPos = visible.findIndex(v => v.join(',') === indexes.join(','));
94
+ this.#selectedIndexes.forEach((x: any) => this.#getItem(x).selected = false);
95
+ this.#selectedIndexes.clear();
96
+ const start = Math.min(lastPos, currPos);
97
+ const end = Math.max(lastPos, currPos);
98
+ for (let i = start; i <= end; i++) {
99
+ const rangeItem = this.#getItem(visible[i]);
100
+ rangeItem.selected = true;
101
+ this.#selectedIndexes.set(getProxyValue(rangeItem), visible[i]);
102
+ }
103
+ } else {
104
+ if (!ctrlKey && this.#selectedIndexes.size && !this.#selectedIndexes.has(unproxyItem)) {
105
+ this.#selectedIndexes.forEach((x: any) => this.#getItem(x).selected = false);
106
+ this.#selectedIndexes.clear();
107
+ }
108
+ item.selected = type === 'rename' ? true : !item.selected;
109
+ if (item.selected) {
110
+ this.#selectedIndexes.set(unproxyItem, indexes);
111
+ this.#lastSelectedIndexes = indexes;
112
+ } else {
113
+ this.#selectedIndexes.delete(unproxyItem);
114
+ }
115
+ }
116
+
117
+ this.dispatchEvent(new CustomEvent('select', {
118
+ detail: {
119
+ items: [...this.#selectedIndexes.values()].map((idxs: any) => this.#wrap(idxs)),
120
+ }
121
+ }));
122
+ });
123
+ this.$items.addEventListener('up', (e: any) => {
124
+ e.stopPropagation();
125
+ const visible = this.#getVisibleIndexes();
126
+ const idx = visible.findIndex(v => v.join(',') === e.detail.indexes.join(','));
127
+ if (idx > 0) {
128
+ this.#focusItem(visible[idx - 1]);
129
+ }
130
+ });
131
+ this.$items.addEventListener('down', (e: any) => {
132
+ e.stopPropagation();
133
+ const visible = this.#getVisibleIndexes();
134
+ const idx = visible.findIndex(v => v.join(',') === e.detail.indexes.join(','));
135
+ if (idx < visible.length - 1) {
136
+ this.#focusItem(visible[idx + 1]);
137
+ }
138
+ });
139
+ this.$items.addEventListener('keydown', (e: any) => {
140
+ if (e.key === 'Escape') {
141
+ this.#selectedIndexes.forEach((idxs: any) => this.#getItem(idxs).selected = false);
142
+ this.#selectedIndexes.clear();
143
+ this.#lastSelectedIndexes = null;
144
+ this.dispatchEvent(new CustomEvent('select', {
145
+ detail: { items: [] }
146
+ }));
147
+ } else if (e.key === 'Delete') {
148
+ const toRemove = [...this.#selectedIndexes.values()] as number[][];
149
+ // Remove higher sibling indexes first to avoid index shifts
150
+ toRemove.sort((a, b) => {
151
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
152
+ const ai = i < a.length ? a[i] : -1;
153
+ const bi = i < b.length ? b[i] : -1;
154
+ if (ai !== bi) return bi - ai;
155
+ }
156
+ return 0;
157
+ });
158
+ toRemove.forEach((indexes: number[]) => this.#removeItem(indexes));
159
+ this.#selectedIndexes.clear();
160
+ this.#lastSelectedIndexes = null;
161
+ }
162
+ });
163
+ this.$items.addEventListener('itemdragstart', (e: any) => {
164
+ const { indexes, callback, ctrlKey } = e.detail;
165
+ const item = this.#getItem(indexes);
166
+ const unproxyItem = getProxyValue(item);
167
+ if (!ctrlKey && this.#selectedIndexes.size && !this.#selectedIndexes.has(unproxyItem)) {
168
+ this.#selectedIndexes.forEach((x: any) => this.#getItem(x).selected = false);
169
+ this.#selectedIndexes.clear();
170
+ }
171
+ item.selected = true;
172
+ this.#selectedIndexes.set(unproxyItem, indexes);
173
+ let count = 0;
174
+ this.#selectedIndexes.forEach((idxs: any) => {
175
+ count = this.#getDragCount(this.#getItem(idxs), count);
176
+ });
177
+ callback(count);
178
+ this.#draggingElements.clear();
179
+ this.#selectedIndexes.forEach((idxs: any) => {
180
+ const el = this.#getItemElement(idxs) as any;
181
+ if (el) {
182
+ el.$item.classList.add('dragging');
183
+ el.$items.classList.add('dragging');
184
+ this.#draggingElements.add(el.$item);
185
+ this.#draggingElements.add(el.$items);
186
+ }
187
+ });
188
+ this.$items.classList.toggle('dragging', true);
189
+ // Sync selection to consumers so #selectedItems reflects the dragged item
190
+ this.dispatchEvent(new CustomEvent('select', {
191
+ detail: {
192
+ items: [...this.#selectedIndexes.values()].map((idxs: any) => this.#wrap(idxs)),
193
+ }
194
+ }));
195
+ });
196
+ this.$items.addEventListener('itemdragend', () => {
197
+ this.#draggingElements.forEach(el => el.classList.remove('dragging'));
198
+ this.#draggingElements.clear();
199
+ this.$items.classList.toggle('dragging', false);
200
+ this.#clearDropHighlights(this.$items);
201
+ });
202
+ this.$items.addEventListener('itemdropenter', this.#handleDropEnter.bind(this));
203
+ }
204
+
205
+ #getDragCount(item: any, count: number): number {
206
+ count += 1;
207
+ if (item.items?.length) {
208
+ item.items.forEach((itm: any) => {
209
+ count = this.#getDragCount(itm, count);
210
+ });
211
+ }
212
+ return count;
213
+ }
214
+
215
+ #handleDropEnter(e: any) {
216
+ const { indexes, callback } = e.detail;
217
+ const excludes = this.#calculateDragExcludes();
218
+ const joined = indexes.join(',') as string;
219
+ // Use comma-terminated prefix to prevent "0,1" from matching "0,10"
220
+ const isInvalid = excludes.some(ex => joined === ex || joined.startsWith(ex + ','));
221
+ callback(!isInvalid);
222
+ }
223
+
224
+ #removeItem(indexes: number[]) {
225
+ const deleteIndex = indexes[indexes.length - 1];
226
+ const parentIndexes = indexes.slice(0, indexes.length - 1);
227
+ const parent = parentIndexes.reduce((acc: any, i) => acc.items[i], this);
228
+ parent.items.splice(deleteIndex, 1);
229
+ }
230
+
231
+ #getItem(indexes: number[]) {
232
+ return indexes.reduce((acc: any, i) => acc.items[i], this);
233
+ }
234
+
235
+ #getItemElement(indexes: number[]): PgTreeItem | null {
236
+ let container: HTMLElement = this.$items;
237
+ let element: PgTreeItem | null = null;
238
+ for (const i of indexes) {
239
+ element = container.children[i] as PgTreeItem;
240
+ if (!element) return null;
241
+ container = (element as any).$items;
242
+ if (!container) return null;
243
+ }
244
+ return element;
245
+ }
246
+
247
+ #focusItem(indexes: number[]) {
248
+ const element = this.#getItemElement(indexes);
249
+ if (element) {
250
+ (element as any).$labelButton.focus();
251
+ }
252
+ }
253
+
254
+ #getVisibleIndexes(): number[][] {
255
+ const result: number[][] = [];
256
+ const traverse = (items: any[], prefix: number[]) => {
257
+ items.forEach((item: any, i: number) => {
258
+ const indexes = [...prefix, i];
259
+ result.push(indexes);
260
+ if (item.expanded && item.items?.length) {
261
+ traverse(item.items, indexes);
262
+ }
263
+ });
264
+ };
265
+ traverse(this.items, []);
266
+ return result;
267
+ }
268
+
269
+ #clearDropHighlights(container: HTMLElement) {
270
+ Array.from(container.children).forEach((child: any) => {
271
+ if (child.$dropabove) {
272
+ child.$dropabove.classList.remove('drop');
273
+ child.$dropon.classList.remove('drop');
274
+ child.$dropbelow.classList.remove('drop');
275
+ }
276
+ if (child.$items) {
277
+ this.#clearDropHighlights(child.$items);
278
+ }
279
+ });
280
+ }
281
+
282
+ #batchMove(selectedIdxsList: number[][], targetIdxs: number[], position: string) {
283
+ if (selectedIdxsList.length === 0) return;
284
+
285
+ // Ascending order preserves the original relative order of dragged items on insertion
286
+ const ascending = [...selectedIdxsList].sort((a, b) => {
287
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
288
+ const av = i < a.length ? a[i] : -1;
289
+ const bv = i < b.length ? b[i] : -1;
290
+ if (av !== bv) return av - bv;
291
+ }
292
+ return 0;
293
+ });
294
+
295
+ // Capture data references before any structural changes
296
+ const caches = ascending.map(idxs => this.#getItem(idxs));
297
+
298
+ // Count how many selected siblings precede the target — each one shifts its index down after removal
299
+ const targetParentStr = targetIdxs.slice(0, -1).join(',');
300
+ let targetShift = 0;
301
+ for (const sidxs of ascending) {
302
+ if (sidxs.slice(0, -1).join(',') === targetParentStr &&
303
+ sidxs[sidxs.length - 1] < targetIdxs[targetIdxs.length - 1]) {
304
+ targetShift++;
305
+ }
306
+ }
307
+ const adjustedTargetIdxs = [
308
+ ...targetIdxs.slice(0, -1),
309
+ targetIdxs[targetIdxs.length - 1] - targetShift
310
+ ];
311
+
312
+ // Remove descending so higher sibling indexes don't shift lower ones mid-loop
313
+ [...ascending].reverse().forEach(idxs => this.#removeItem(idxs));
314
+
315
+ // Rebuild selection map with post-move positions so items stay selected
316
+ this.#selectedIndexes.clear();
317
+ this.#lastSelectedIndexes = null;
318
+
319
+ if (position === 'on') {
320
+ const targetData = this.#getItem(adjustedTargetIdxs);
321
+ const prevLen = Array.isArray(targetData.items) ? targetData.items.length : 0;
322
+ if (!Array.isArray(targetData.items)) targetData.items = [];
323
+ caches.forEach((cache, i) => {
324
+ targetData.items.push(cache);
325
+ const newIdxs = [...adjustedTargetIdxs, prevLen + i];
326
+ this.#selectedIndexes.set(getProxyValue(this.#getItem(newIdxs)), newIdxs);
327
+ });
328
+ targetData.expanded = true;
329
+ } else {
330
+ const adjustedParent = adjustedTargetIdxs.slice(0, -1);
331
+ const adjustedIdx = adjustedTargetIdxs[adjustedTargetIdxs.length - 1];
332
+ const insertAt = position === 'after' ? adjustedIdx + 1 : adjustedIdx;
333
+ if (adjustedParent.length === 0) {
334
+ this.items.splice(insertAt, 0, ...caches);
335
+ } else {
336
+ this.#getItem(adjustedParent).items.splice(insertAt, 0, ...caches);
337
+ }
338
+ caches.forEach((_, i) => {
339
+ const newIdxs = [...adjustedParent, insertAt + i];
340
+ this.#selectedIndexes.set(getProxyValue(this.#getItem(newIdxs)), newIdxs);
341
+ });
342
+ }
343
+
344
+ this.$items.classList.toggle('dragging', false);
345
+ }
346
+
347
+ #wrap(indexes: number[]): SelectedTreeItem {
348
+ return {
349
+ indexes,
350
+ remove: () => {
351
+ this.#removeItem(indexes);
352
+ this.#selectedIndexes.clear();
353
+ this.#lastSelectedIndexes = null;
354
+ },
355
+ getData: () => this.#getItem(indexes),
356
+ getParentData: () => {
357
+ const parent = indexes.slice(0, indexes.length - 1);
358
+ return parent.length === 0 ? this : this.#getItem(parent);
359
+ },
360
+ move: (item: SelectedTreeItem, position: string) => {
361
+ this.#batchMove([indexes], item.indexes, position);
362
+ }
363
+ };
364
+ }
365
+
366
+ unselect(indexes: number[]) {
367
+ const item = this.#getItem(indexes);
368
+ const unproxyItem = getProxyValue(item);
369
+ item.selected = false;
370
+ this.#selectedIndexes.delete(unproxyItem);
371
+ }
372
+
373
+ unselectAll() {
374
+ this.#selectedIndexes.forEach((idxs: any) => this.#getItem(idxs).selected = false);
375
+ this.#selectedIndexes.clear();
376
+ }
377
+
378
+ #dispatchSelect() {
379
+ this.dispatchEvent(new CustomEvent('select', {
380
+ detail: {
381
+ items: [...this.#selectedIndexes.values()].map((idxs: any) => this.#wrap(idxs)),
382
+ }
383
+ }));
384
+ }
385
+
386
+ #calculateDragExcludes(): string[] {
387
+ const exclude: string[] = [];
388
+ this.#selectedIndexes.forEach((indexes: number[]) => {
389
+ exclude.push(indexes.join(','));
390
+ });
391
+ return exclude;
392
+ }
393
+ }