@ixfx/components 0.15.5 → 0.16.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/bundle/index.d.ts +917 -44
- package/bundle/index.js +702 -696
- package/dist/crumb-navigation-BbqfmkYs.d.ts +147 -0
- package/dist/crumb-navigation-YnFVFqrx.js +1290 -0
- package/dist/crumbs.d.ts +2 -115
- package/dist/crumbs.js +1 -1179
- package/dist/{data-grid-D7qzmMMp.d.ts → data-grid-CIG2DVip.d.ts} +45 -3
- package/dist/{data-grid-C1sZX6n9.js → data-grid-rMkLX2qo.js} +593 -206
- package/dist/data-grid.d.ts +3 -3
- package/dist/data-grid.js +1 -1
- package/dist/{detail-list-CKIKlszv.d.ts → detail-list-6iMTNP4N.d.ts} +34 -4
- package/dist/{detail-list-q8bs67BM.js → detail-list-C4pDSoI8.js} +218 -7
- package/dist/detail-list.d.ts +4 -4
- package/dist/detail-list.js +1 -1
- package/dist/{flat-list-DXMyDiSH.d.ts → flat-list-JPgQSmLW.d.ts} +27 -4
- package/dist/flat-list.d.ts +2 -2
- package/dist/flat-list.js +123 -4
- package/dist/{grid-list-y6dWJYu3.js → grid-list-CdEkScn-.js} +276 -75
- package/dist/{grid-list-0e7snW6t.d.ts → grid-list-D6n7WH8l.d.ts} +128 -22
- package/dist/grid-list.d.ts +3 -3
- package/dist/grid-list.js +1 -1
- package/dist/incr-search.d.ts +1 -1
- package/dist/index-9ttcdwlL.d.ts +71 -0
- package/dist/{index-DEVyVIn8.d.ts → index-Bx0BXPxI.d.ts} +52 -6
- package/dist/index-CYRc6Dah.d.ts +475 -0
- package/dist/{index-KN2MW_xD.d.ts → index-Dr80Zdl6.d.ts} +1 -1
- package/dist/index.d.ts +334 -23
- package/dist/index.js +2247 -867
- package/dist/{list-native-drag-controller-O2Nruqpi.d.ts → list-native-drag-controller-D_UrXipS.d.ts} +1 -1
- package/dist/{list-selection-controller-BeE70lbB.js → list-selection-controller-5L0Nj9tR.js} +87 -2
- package/dist/miller-BFRfn0ve.js +2237 -0
- package/dist/miller.d.ts +4 -437
- package/dist/miller.js +1 -1815
- package/dist/pending-BGidHppL.js +91 -0
- package/dist/scroll-hover-guard-Cjw6179Q.js +35 -0
- package/dist/{split-layout-JK3xWVX2.d.ts → split-layout-CophkNeU.d.ts} +41 -3
- package/dist/{split-layout-Deoxy47d.js → split-layout-DTY4PJRp.js} +251 -19
- package/dist/split-layout.d.ts +1 -1
- package/dist/split-layout.js +1 -1
- package/dist/sunburst-tree.d.ts +2 -2
- package/dist/sunburst-tree.js +1 -1
- package/dist/{sunbursttree-list-yXwS-uEI.js → sunbursttree-list-B_VxOHlo.js} +298 -79
- package/dist/{sunbursttree-list--Z0uyh8O.d.ts → sunbursttree-list-D6j5BxVQ.d.ts} +40 -3
- package/dist/tree-CftHwtEb.js +146 -0
- package/dist/{tree-D8VxvR9u.js → tree-Crdpl4nc.js} +275 -47
- package/dist/{tree-component-C6UHO-w9.d.ts → tree-component-DgfkxmVY.d.ts} +19 -8
- package/dist/tree.d.ts +3 -3
- package/dist/tree.js +1 -1
- package/dist/types-LU1u0CB8.d.ts +87 -0
- package/dist/vertical-list-1V1Vg2O5.js +1993 -0
- package/dist/{vertical-list-D8MksoTp.d.ts → vertical-list-BPDmZx6T.d.ts} +31 -3
- package/dist/vertical-list.d.ts +3 -3
- package/dist/vertical-list.js +1 -1789
- package/dist/view-state-controller-BdyXWUUM.js +305 -0
- package/docs-user/README.md +2 -0
- package/docs-user/crumbs.md +27 -0
- package/docs-user/data-grid.md +66 -1
- package/docs-user/detail-list.md +54 -0
- package/docs-user/dock.md +54 -12
- package/docs-user/flat-list.md +27 -0
- package/docs-user/grid-list.md +64 -11
- package/docs-user/hyperbolic-tree.md +31 -4
- package/docs-user/icicle-tree.md +36 -0
- package/docs-user/index.json +12 -2
- package/docs-user/llms.txt +2 -0
- package/docs-user/miller.md +52 -21
- package/docs-user/multicol-list.md +50 -8
- package/docs-user/split-layout.md +45 -17
- package/docs-user/sunburst-tree.md +32 -2
- package/docs-user/tree.md +45 -6
- package/docs-user/treemap.md +32 -0
- package/docs-user/twosplit-layout.md +22 -0
- package/docs-user/user-catalog.md +1 -1
- package/docs-user/vertical-list.md +55 -7
- package/llms.txt +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { a as capKeys, i as capFlags, n as EMPTY_KEYS } from "./pending-BGidHppL.js";
|
|
2
|
+
//#region src/common/view-state/tree.ts
|
|
3
|
+
/**
|
|
4
|
+
* - live expanded keys that are no longer loaded → pending `true`
|
|
5
|
+
* - pending keys that are now loaded → applied (`true` opens, `false` closes)
|
|
6
|
+
* - pending-open keys whose node can't open yet (`canOpen` false: children
|
|
7
|
+
* unloaded) stay pending and are listed in `needsLoad`
|
|
8
|
+
*/
|
|
9
|
+
function reconcileExpansion(live, pending, has, canOpen) {
|
|
10
|
+
let nextLive;
|
|
11
|
+
let nextPending;
|
|
12
|
+
const needsLoad = [];
|
|
13
|
+
for (const key of live) {
|
|
14
|
+
if (has(key)) continue;
|
|
15
|
+
nextLive ??= new Set(live);
|
|
16
|
+
nextLive.delete(key);
|
|
17
|
+
nextPending ??= new Map(pending);
|
|
18
|
+
nextPending.set(key, true);
|
|
19
|
+
}
|
|
20
|
+
for (const [key, open] of pending) {
|
|
21
|
+
if (!has(key)) continue;
|
|
22
|
+
if (open && !canOpen(key)) {
|
|
23
|
+
needsLoad.push(key);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
nextPending ??= new Map(pending);
|
|
27
|
+
nextPending.delete(key);
|
|
28
|
+
if (open !== (nextLive ?? live).has(key)) {
|
|
29
|
+
nextLive ??= new Set(live);
|
|
30
|
+
if (open) nextLive.add(key);
|
|
31
|
+
else nextLive.delete(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
live: nextLive ?? live,
|
|
36
|
+
pending: nextPending ? capFlags(nextPending) : pending,
|
|
37
|
+
needsLoad,
|
|
38
|
+
changed: nextLive !== void 0 || nextPending !== void 0
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Re-key the node selection onto the current tree: selected nodes are swapped
|
|
43
|
+
* for the loaded node with the same key, or go pending when the key is gone;
|
|
44
|
+
* pending keys that resolve (and pass `canSelect`) are selected. With
|
|
45
|
+
* `single`, at most one node stays selected (a restored key wins).
|
|
46
|
+
*/
|
|
47
|
+
function reconcileSelection(selected, pending, nodeByKey, canSelect, single) {
|
|
48
|
+
if (selected.size === 0 && pending.size === 0) return {
|
|
49
|
+
selected,
|
|
50
|
+
pending,
|
|
51
|
+
restored: false,
|
|
52
|
+
changed: false
|
|
53
|
+
};
|
|
54
|
+
const next = /* @__PURE__ */ new Set();
|
|
55
|
+
const nextPending = /* @__PURE__ */ new Set();
|
|
56
|
+
let changed = false;
|
|
57
|
+
for (const node of selected) {
|
|
58
|
+
const current = nodeByKey(node.item.key);
|
|
59
|
+
if (current) {
|
|
60
|
+
next.add(current);
|
|
61
|
+
if (current !== node) changed = true;
|
|
62
|
+
} else {
|
|
63
|
+
nextPending.add(node.item.key);
|
|
64
|
+
changed = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
let restored;
|
|
68
|
+
for (const key of pending) {
|
|
69
|
+
const node = nodeByKey(key);
|
|
70
|
+
if (node && canSelect(node)) {
|
|
71
|
+
next.add(node);
|
|
72
|
+
restored = node;
|
|
73
|
+
changed = true;
|
|
74
|
+
} else nextPending.add(key);
|
|
75
|
+
}
|
|
76
|
+
if (!changed) return {
|
|
77
|
+
selected,
|
|
78
|
+
pending,
|
|
79
|
+
restored: false,
|
|
80
|
+
changed: false
|
|
81
|
+
};
|
|
82
|
+
let finalSelected = next;
|
|
83
|
+
let finalPending = nextPending;
|
|
84
|
+
if (single && next.size > 0) {
|
|
85
|
+
finalSelected = /* @__PURE__ */ new Set([restored ?? [...next].at(-1)]);
|
|
86
|
+
finalPending = EMPTY_KEYS;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
selected: finalSelected,
|
|
90
|
+
pending: capKeys(finalPending),
|
|
91
|
+
restored: restored !== void 0,
|
|
92
|
+
changed: true
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Keyboard cursor: a cursor key that left the data goes pending (`clear`);
|
|
97
|
+
* a pending key that is now visible is applied (`apply`).
|
|
98
|
+
*/
|
|
99
|
+
function reconcileCursor(cursor, pending, has, isVisible) {
|
|
100
|
+
let nextPending = pending;
|
|
101
|
+
let clear = false;
|
|
102
|
+
if (cursor !== void 0 && !has(cursor)) {
|
|
103
|
+
nextPending ??= cursor;
|
|
104
|
+
clear = true;
|
|
105
|
+
}
|
|
106
|
+
if (nextPending !== void 0 && isVisible(nextPending)) return {
|
|
107
|
+
clear,
|
|
108
|
+
apply: nextPending,
|
|
109
|
+
pending: void 0
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
clear,
|
|
113
|
+
apply: void 0,
|
|
114
|
+
pending: nextPending
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Sanitise a JSON zoom / centre path: strings only, `undefined` when not an array. */
|
|
118
|
+
function pathFromJson(value) {
|
|
119
|
+
return Array.isArray(value) ? value.filter((k) => typeof k === `string`) : void 0;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Follow `keys` from the children of `root`. When the walk reaches a node
|
|
123
|
+
* whose children aren't loaded, reports it as `load` if `canLoad` allows.
|
|
124
|
+
*/
|
|
125
|
+
function resolveKeyPath(root, keys, canLoad) {
|
|
126
|
+
if (!root) return { status: `missing` };
|
|
127
|
+
const nodes = [];
|
|
128
|
+
let current = root;
|
|
129
|
+
for (const key of keys) {
|
|
130
|
+
if (current.children === void 0) return canLoad(current) ? {
|
|
131
|
+
status: `load`,
|
|
132
|
+
node: current,
|
|
133
|
+
depth: nodes.length - 1
|
|
134
|
+
} : { status: `missing` };
|
|
135
|
+
const next = current.children.find((c) => c.item.key === key);
|
|
136
|
+
if (!next) return { status: `missing` };
|
|
137
|
+
nodes.push(next);
|
|
138
|
+
current = next;
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
status: `found`,
|
|
142
|
+
nodes
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
146
|
+
export { resolveKeyPath as a, reconcileSelection as i, reconcileCursor as n, reconcileExpansion as r, pathFromJson as t };
|
|
@@ -4,8 +4,12 @@ import { t as themeFallbacks } from "./fallbacks-DQ_5OsmR.js";
|
|
|
4
4
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
5
5
|
import { i as ListSearchController, n as listSearchStyles, o as registerListSearchCommands, r as LIST_SEARCH_MODES, t as createTreeListSearchAdapter } from "./incr-search-JIhwB49y.js";
|
|
6
6
|
import { i as animateListItemOut, o as prefersReducedMotion, r as animateListItemIn, t as ListNativeDragController } from "./list-native-drag-controller-CcXoS0YX.js";
|
|
7
|
+
import { a as capKeys, c as keysAsFlags, f as withoutFlag, i as capFlags, l as keysToArray, n as EMPTY_KEYS, o as flagsFromRecord, s as flagsToRecord, t as EMPTY_FLAGS } from "./pending-BGidHppL.js";
|
|
8
|
+
import { n as createScrollHoverGuard } from "./scroll-hover-guard-Cjw6179Q.js";
|
|
7
9
|
import "./interaction-E-uMGHkJ.js";
|
|
8
10
|
import { t as collectDataResult } from "./data-provider-35TyWclX.js";
|
|
11
|
+
import { n as anchorFromRow, o as scrollToOffset, t as ViewStateController } from "./view-state-controller-BdyXWUUM.js";
|
|
12
|
+
import { i as reconcileSelection, r as reconcileExpansion } from "./tree-CftHwtEb.js";
|
|
9
13
|
import { LitElement, css, html, nothing } from "lit";
|
|
10
14
|
import { property, state } from "lit/decorators.js";
|
|
11
15
|
import { createCommandRegistry } from "@clinth/ui-commands";
|
|
@@ -1112,6 +1116,12 @@ function computeTreeWindow(params, scrollTop, overscan = 5) {
|
|
|
1112
1116
|
end: Math.min(count, Math.max(start, lastVisible + overscan))
|
|
1113
1117
|
};
|
|
1114
1118
|
}
|
|
1119
|
+
/** Index of the row whose slot contains content-space `y`, clamped to `[0, count - 1]`. */
|
|
1120
|
+
function treeIndexAt(params, y) {
|
|
1121
|
+
if (params.count <= 0) return -1;
|
|
1122
|
+
const index = Math.floor((y - params.listOffset) / treeStride(params));
|
|
1123
|
+
return Math.min(params.count - 1, Math.max(0, index));
|
|
1124
|
+
}
|
|
1115
1125
|
/**
|
|
1116
1126
|
* The scroll offset that brings row `index` fully into view with the least
|
|
1117
1127
|
* movement, leaving `topInset` px at the top clear (the sticky-header overlay).
|
|
@@ -1204,6 +1214,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1204
1214
|
this.interactionMode = `standard`;
|
|
1205
1215
|
this._selectedNodes = /* @__PURE__ */ new Set();
|
|
1206
1216
|
this.disableKeyboardNavigation = false;
|
|
1217
|
+
this.scrollHoverTickle = false;
|
|
1207
1218
|
this.registry = void 0;
|
|
1208
1219
|
this.itemDnd = `none`;
|
|
1209
1220
|
this.dndExpandHoverMs = 500;
|
|
@@ -1214,6 +1225,14 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1214
1225
|
this.animation = `auto`;
|
|
1215
1226
|
this.applyInternalDrop = true;
|
|
1216
1227
|
this._expandedKeys = /* @__PURE__ */ new Set();
|
|
1228
|
+
this.restoreLoads = true;
|
|
1229
|
+
this.#viewState = new ViewStateController(this, {
|
|
1230
|
+
kind: `tree-list`,
|
|
1231
|
+
capture: () => this.getViewState()
|
|
1232
|
+
});
|
|
1233
|
+
this.#pendingExpanded = EMPTY_FLAGS;
|
|
1234
|
+
this.#pendingSelected = EMPTY_KEYS;
|
|
1235
|
+
this.#reconciledVersion = -1;
|
|
1217
1236
|
this.#structureVersion = 0;
|
|
1218
1237
|
this._selectionVersion = 0;
|
|
1219
1238
|
this._scrollTop = 0;
|
|
@@ -1246,6 +1265,17 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1246
1265
|
this.setAttribute(`data-input-mode`, this.tickled.inputMode);
|
|
1247
1266
|
}
|
|
1248
1267
|
});
|
|
1268
|
+
this.#scrollHover = createScrollHoverGuard({
|
|
1269
|
+
host: this,
|
|
1270
|
+
enabled: () => !this.scrollHoverTickle,
|
|
1271
|
+
onResume: (x, y) => {
|
|
1272
|
+
const key = (this.shadowRoot?.elementFromPoint?.(x, y)?.closest(`li.item`))?.dataset.key;
|
|
1273
|
+
const flat = this.#getFlat();
|
|
1274
|
+
const idx = key === void 0 ? void 0 : flat.indexByKey.get(key);
|
|
1275
|
+
const row = idx === void 0 ? void 0 : flat.rows[idx];
|
|
1276
|
+
if (row) this._handleRowPointerEnter(row.node, row.depth);
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1249
1279
|
this._focusedDepth = 0;
|
|
1250
1280
|
this.search = new ListSearchController(this, { adapter: createTreeListSearchAdapter(this, {
|
|
1251
1281
|
labelSelector: `.tree-label`,
|
|
@@ -1278,6 +1308,9 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1278
1308
|
this.#stickyDirty = true;
|
|
1279
1309
|
this.#stickyRaf = 0;
|
|
1280
1310
|
this.#stickyScrollBound = false;
|
|
1311
|
+
this.#onViewStateScroll = () => {
|
|
1312
|
+
this.#viewState.notifyScroll();
|
|
1313
|
+
};
|
|
1281
1314
|
this.#selectOrigin = `user`;
|
|
1282
1315
|
this.#selectSilent = false;
|
|
1283
1316
|
this.#revealToken = 0;
|
|
@@ -1287,7 +1320,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1287
1320
|
if (nodes.length === 0) return;
|
|
1288
1321
|
if ((event.ctrlKey || event.metaKey) && event.key === `a`) {
|
|
1289
1322
|
event.preventDefault();
|
|
1290
|
-
this.selectAll();
|
|
1323
|
+
this.selectAll({ visibleOnly: true });
|
|
1291
1324
|
return;
|
|
1292
1325
|
}
|
|
1293
1326
|
if ([
|
|
@@ -1428,7 +1461,23 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1428
1461
|
this._expandedKeys = next;
|
|
1429
1462
|
this.#flat = void 0;
|
|
1430
1463
|
this.#stickyDirty = true;
|
|
1431
|
-
|
|
1464
|
+
this.#viewState.notify();
|
|
1465
|
+
}
|
|
1466
|
+
#viewState;
|
|
1467
|
+
/** Saved expansion for keys not (yet) loaded, or loaded but awaiting children. */
|
|
1468
|
+
#pendingExpanded;
|
|
1469
|
+
/** Saved selection for keys not (yet) loaded. */
|
|
1470
|
+
#pendingSelected;
|
|
1471
|
+
#pendingFocus;
|
|
1472
|
+
/**
|
|
1473
|
+
* Cursor key applied from saved state. Recorded as `focus` while the cursor
|
|
1474
|
+
* stays there, even though the input mode isn't `keyboard` (switching the
|
|
1475
|
+
* mode would reset the shared hover guard).
|
|
1476
|
+
*/
|
|
1477
|
+
#restoredFocus;
|
|
1478
|
+
/** Structure version the view state was last reconciled against. */
|
|
1479
|
+
#reconciledVersion;
|
|
1480
|
+
#viewStateScrollTarget;
|
|
1432
1481
|
#flat;
|
|
1433
1482
|
#flatRoot;
|
|
1434
1483
|
#flatFilter;
|
|
@@ -1623,6 +1672,25 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1623
1672
|
get _depthsWithIcons() {
|
|
1624
1673
|
return this.#getTreeIndex().depthsWithIcons;
|
|
1625
1674
|
}
|
|
1675
|
+
#scrollHover;
|
|
1676
|
+
/**
|
|
1677
|
+
* Row `pointerenter` funnel: moves the hover cursor unless a scroll gesture
|
|
1678
|
+
* is sliding rows beneath a stationary pointer (see `scrollHoverTickle`).
|
|
1679
|
+
* Subclasses rendering their own rows should call this rather than the
|
|
1680
|
+
* tickled controller directly.
|
|
1681
|
+
*/
|
|
1682
|
+
_handleRowPointerEnter(node, depth) {
|
|
1683
|
+
if (this.#scrollHover.suppressed()) return;
|
|
1684
|
+
this.tickled.handlePointerEnter(node.item.key);
|
|
1685
|
+
this.dispatchEvent(new CustomEvent(`tickle`, {
|
|
1686
|
+
detail: {
|
|
1687
|
+
node,
|
|
1688
|
+
depth
|
|
1689
|
+
},
|
|
1690
|
+
bubbles: true,
|
|
1691
|
+
composed: true
|
|
1692
|
+
}));
|
|
1693
|
+
}
|
|
1626
1694
|
#unregisterSearchCommands;
|
|
1627
1695
|
#effectiveSearchModes() {
|
|
1628
1696
|
const raw = this.searchModes?.trim();
|
|
@@ -1844,10 +1912,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1844
1912
|
}
|
|
1845
1913
|
this.#flat = void 0;
|
|
1846
1914
|
if (changedProps.has(`root`) || changedProps.has(`model`)) this.#structureVersion++;
|
|
1847
|
-
if (
|
|
1848
|
-
const { parentByKey } = this.#getTreeIndex();
|
|
1849
|
-
this.#setExpanded(withoutKeys(this._expandedKeys, (key) => !parentByKey.has(key)));
|
|
1850
|
-
}
|
|
1915
|
+
if (this.#reconciledVersion !== this.#structureVersion) this.#reconcileViewState();
|
|
1851
1916
|
this.#diffVisibleNodes(changedProps.has(`filterPredicate`));
|
|
1852
1917
|
const virtual = this.#virtualActive();
|
|
1853
1918
|
this.toggleAttribute(`data-virtual`, virtual);
|
|
@@ -1970,6 +2035,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1970
2035
|
updated(changedProps) {
|
|
1971
2036
|
this.#rowsCache = void 0;
|
|
1972
2037
|
this.#syncVirtualObservers();
|
|
2038
|
+
if (changedProps.has(`scrollHoverTickle`) && this.scrollHoverTickle) this.#scrollHover.end();
|
|
1973
2039
|
if (this.#scrollOnlyUpdate) {
|
|
1974
2040
|
this.#scrollOnlyUpdate = false;
|
|
1975
2041
|
this.#repaintSearchHighlights();
|
|
@@ -1978,8 +2044,6 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
1978
2044
|
this.#syncStickyScroll();
|
|
1979
2045
|
if (changedProps.has(`root`) && this.root) {
|
|
1980
2046
|
this.#abortPending();
|
|
1981
|
-
this.#clearSelectionInternal();
|
|
1982
|
-
this.tickled.clearTickled();
|
|
1983
2047
|
this._focusedDepth = 0;
|
|
1984
2048
|
this.#cancelAllLeavingAnimations();
|
|
1985
2049
|
this.#leaving.clear();
|
|
@@ -2004,7 +2068,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2004
2068
|
});
|
|
2005
2069
|
}
|
|
2006
2070
|
}
|
|
2007
|
-
if (changedProps.has(`interactionMode`)) {
|
|
2071
|
+
if (changedProps.has(`interactionMode`) && changedProps.get(`interactionMode`) !== void 0) {
|
|
2008
2072
|
this.#anchor = void 0;
|
|
2009
2073
|
this.clearSelection();
|
|
2010
2074
|
}
|
|
@@ -2018,6 +2082,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2018
2082
|
this.#repaintSearchHighlights();
|
|
2019
2083
|
} else this.#runItemAnimations();
|
|
2020
2084
|
this.#animationOverride = void 0;
|
|
2085
|
+
this.#syncViewStateAfterRender();
|
|
2021
2086
|
}
|
|
2022
2087
|
/** Highlights are painted on rendered labels, so they move with the window. */
|
|
2023
2088
|
#repaintSearchHighlights() {
|
|
@@ -2031,7 +2096,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2031
2096
|
id: `select-all`,
|
|
2032
2097
|
label: `Select All`,
|
|
2033
2098
|
description: `Select all visible items`,
|
|
2034
|
-
execute: () => this.selectAll()
|
|
2099
|
+
execute: () => this.selectAll({ visibleOnly: true })
|
|
2035
2100
|
});
|
|
2036
2101
|
registry.register({
|
|
2037
2102
|
id: `deselect-all`,
|
|
@@ -2433,6 +2498,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2433
2498
|
this.#postDragSuppressTimer = void 0;
|
|
2434
2499
|
}
|
|
2435
2500
|
this.#container()?.removeEventListener(`scroll`, this.#onContainerScroll);
|
|
2501
|
+
this.#scrollHover.end();
|
|
2436
2502
|
this.#teardownVirtualObservers();
|
|
2437
2503
|
if (this.#stickyScrollBound) {
|
|
2438
2504
|
this.#stickyScrollContainer?.removeEventListener(`scroll`, this.#onStickyScroll);
|
|
@@ -2461,6 +2527,145 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2461
2527
|
};
|
|
2462
2528
|
this.requestUpdate();
|
|
2463
2529
|
}
|
|
2530
|
+
/**
|
|
2531
|
+
* Snapshot selection, expansion, cursor and scroll as plain JSON, keyed by
|
|
2532
|
+
* `item.key`. Includes pending state for keys not currently loaded.
|
|
2533
|
+
*/
|
|
2534
|
+
getViewState(options) {
|
|
2535
|
+
const withPending = options?.includePending ?? true;
|
|
2536
|
+
const tickled = this.tickled.tickledId;
|
|
2537
|
+
const focus = this.tickled.inputMode === `keyboard` || tickled !== void 0 && tickled === this.#restoredFocus ? tickled : void 0;
|
|
2538
|
+
return this.#viewState.shape({
|
|
2539
|
+
selected: keysToArray([...this._selectedNodes].map((n) => n.item.key), withPending ? this.#pendingSelected : []),
|
|
2540
|
+
expanded: flagsToRecord(withPending ? this.#pendingExpanded : [], keysAsFlags(this._expandedKeys)),
|
|
2541
|
+
focus: focus ?? (withPending ? this.#pendingFocus : void 0),
|
|
2542
|
+
scroll: (withPending ? this.#viewState.pendingScroll : void 0) ?? this.#captureScroll()
|
|
2543
|
+
}, options);
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Apply saved view state. Fields present replace the current ones; keys
|
|
2547
|
+
* that aren't loaded yet are applied as they appear — including via
|
|
2548
|
+
* `loadChildren` / `model` for saved-open branches when `restoreLoads`.
|
|
2549
|
+
*/
|
|
2550
|
+
setViewState(state) {
|
|
2551
|
+
if (!this.#viewState.accepts(state)) return;
|
|
2552
|
+
this.#viewState.restoring(() => {
|
|
2553
|
+
if (state.expanded) {
|
|
2554
|
+
this.#pendingExpanded = capFlags(flagsFromRecord(state.expanded));
|
|
2555
|
+
this.#setExpanded(/* @__PURE__ */ new Set());
|
|
2556
|
+
}
|
|
2557
|
+
if (state.selected) {
|
|
2558
|
+
this.#pendingSelected = capKeys(new Set(state.selected));
|
|
2559
|
+
if (this._selectedNodes.size > 0) {
|
|
2560
|
+
const prev = new Set(this._selectedNodes);
|
|
2561
|
+
this.#clearSelectionInternal();
|
|
2562
|
+
this.#dispatchSelect(prev);
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
if (state.focus !== void 0) this.#pendingFocus = state.focus;
|
|
2566
|
+
if (state.scroll) this.#viewState.pendingScroll = state.scroll;
|
|
2567
|
+
this.#reconcileViewState();
|
|
2568
|
+
});
|
|
2569
|
+
this.requestUpdate();
|
|
2570
|
+
}
|
|
2571
|
+
clearPendingViewState() {
|
|
2572
|
+
this.#pendingExpanded = EMPTY_FLAGS;
|
|
2573
|
+
this.#pendingSelected = EMPTY_KEYS;
|
|
2574
|
+
this.#pendingFocus = void 0;
|
|
2575
|
+
this.#viewState.pendingScroll = void 0;
|
|
2576
|
+
}
|
|
2577
|
+
/** Move state for missing keys to pending; apply pending state for keys now loaded. */
|
|
2578
|
+
#reconcileViewState() {
|
|
2579
|
+
this.#reconciledVersion = this.#structureVersion;
|
|
2580
|
+
if (!this.root) return;
|
|
2581
|
+
const { parentByKey } = this.#getTreeIndex();
|
|
2582
|
+
const has = (key) => parentByKey.has(key);
|
|
2583
|
+
this.#viewState.restoring(() => {
|
|
2584
|
+
const exp = reconcileExpansion(this._expandedKeys, this.#pendingExpanded, has, (key) => this.#nodeByKey(key)?.children !== void 0);
|
|
2585
|
+
if (exp.changed) {
|
|
2586
|
+
let pending = exp.pending;
|
|
2587
|
+
for (const key of exp.needsLoad) if (this.#nodeByKey(key)?.item.isLeaf !== false) pending = withoutFlag(pending, key);
|
|
2588
|
+
this.#pendingExpanded = pending;
|
|
2589
|
+
if (exp.live !== this._expandedKeys) {
|
|
2590
|
+
this.#animationOverride ??= false;
|
|
2591
|
+
this.#setExpanded(exp.live);
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
const sel = reconcileSelection(this._selectedNodes, this.#pendingSelected, (key) => has(key) ? this.#nodeByKey(key) : void 0, (node) => this.#canSelect(node), this.interactionMode === `implicit`);
|
|
2595
|
+
if (sel.changed) {
|
|
2596
|
+
const prev = this._selectedNodes;
|
|
2597
|
+
this._selectedNodes = new Set(sel.selected);
|
|
2598
|
+
this.#pendingSelected = sel.pending;
|
|
2599
|
+
const selectedKey = this.selectedNode?.item.key;
|
|
2600
|
+
this.selectedNode = (selectedKey === void 0 ? void 0 : [...sel.selected].find((n) => n.item.key === selectedKey)) ?? [...sel.selected].at(-1);
|
|
2601
|
+
if (sel.restored) this.#dispatchSelect(prev);
|
|
2602
|
+
else this._selectionVersion++;
|
|
2603
|
+
}
|
|
2604
|
+
const tickled = this.tickled.tickledId;
|
|
2605
|
+
if (tickled !== void 0 && !has(tickled)) {
|
|
2606
|
+
this.#pendingFocus ??= tickled;
|
|
2607
|
+
this.tickled.clearTickled();
|
|
2608
|
+
}
|
|
2609
|
+
if (this.#pendingFocus !== void 0 && this.#getFlat().indexByKey.has(this.#pendingFocus)) {
|
|
2610
|
+
this.tickled.setTickled(this.#pendingFocus);
|
|
2611
|
+
this.#restoredFocus = this.#pendingFocus;
|
|
2612
|
+
this.#pendingFocus = void 0;
|
|
2613
|
+
}
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
/** Post-render: bind scroll tracking, apply a pending scroll, continue restore loads. */
|
|
2617
|
+
#syncViewStateAfterRender() {
|
|
2618
|
+
const container = this.#container();
|
|
2619
|
+
if (container && container !== this.#viewStateScrollTarget) {
|
|
2620
|
+
this.#viewStateScrollTarget?.removeEventListener(`scroll`, this.#onViewStateScroll);
|
|
2621
|
+
this.#viewStateScrollTarget = container;
|
|
2622
|
+
container.addEventListener(`scroll`, this.#onViewStateScroll, { passive: true });
|
|
2623
|
+
this.#viewState.observeScrollTarget(container);
|
|
2624
|
+
}
|
|
2625
|
+
this.#viewState.applyPendingScroll((scroll) => this.#applyScroll(scroll));
|
|
2626
|
+
this.#continueRestoreLoads();
|
|
2627
|
+
}
|
|
2628
|
+
#onViewStateScroll;
|
|
2629
|
+
#captureScroll() {
|
|
2630
|
+
const container = this.#container();
|
|
2631
|
+
if (!container) return void 0;
|
|
2632
|
+
const rows = this.#getFlat().rows;
|
|
2633
|
+
if (!this.#virtualActive()) this.#measureMetrics();
|
|
2634
|
+
const params = this.#layoutParams(rows.length);
|
|
2635
|
+
const top = container.scrollTop;
|
|
2636
|
+
const index = treeIndexAt(params, top);
|
|
2637
|
+
const key = index >= 0 ? rows[index]?.node.item.key : void 0;
|
|
2638
|
+
return anchorFromRow(top, key, index >= 0 ? treeRowTop(params, index) : 0);
|
|
2639
|
+
}
|
|
2640
|
+
/** Returns `true` once the saved position is fully reached. */
|
|
2641
|
+
#applyScroll(scroll) {
|
|
2642
|
+
const container = this.#container();
|
|
2643
|
+
if (!container) return false;
|
|
2644
|
+
let target = scroll.top;
|
|
2645
|
+
if (scroll.anchor) {
|
|
2646
|
+
const flat = this.#getFlat();
|
|
2647
|
+
const index = flat.indexByKey.get(scroll.anchor.key);
|
|
2648
|
+
if (index === void 0) return false;
|
|
2649
|
+
if (!this.#virtualActive()) this.#measureMetrics();
|
|
2650
|
+
target = treeRowTop(this.#layoutParams(flat.rows.length), index) + scroll.anchor.offset;
|
|
2651
|
+
}
|
|
2652
|
+
return scrollToOffset(container, target);
|
|
2653
|
+
}
|
|
2654
|
+
/** Open the next saved-open branch whose children aren't loaded (one load at a time). */
|
|
2655
|
+
#continueRestoreLoads() {
|
|
2656
|
+
if (!this.restoreLoads || this.#pendingNode || this.#pendingExpanded.size === 0 || !this.root || !this.#hasLoader()) return;
|
|
2657
|
+
const { parentByKey } = this.#getTreeIndex();
|
|
2658
|
+
for (const [key, open] of this.#pendingExpanded) {
|
|
2659
|
+
if (!open || !parentByKey.has(key)) continue;
|
|
2660
|
+
const node = this.#nodeByKey(key);
|
|
2661
|
+
if (node && node.children === void 0 && node.item.isLeaf === false) {
|
|
2662
|
+
let depth = 0;
|
|
2663
|
+
for (let k = parentByKey.get(key); k !== void 0 && k !== this.root.item.key; k = parentByKey.get(k)) depth++;
|
|
2664
|
+
this.#startLoad(node, depth);
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2464
2669
|
select(node) {
|
|
2465
2670
|
if (!this.#canSelect(node)) return;
|
|
2466
2671
|
const prev = new Set(this._selectedNodes);
|
|
@@ -2479,39 +2684,53 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2479
2684
|
this.requestUpdate();
|
|
2480
2685
|
}
|
|
2481
2686
|
clearSelection() {
|
|
2687
|
+
this.#pendingSelected = EMPTY_KEYS;
|
|
2482
2688
|
if (this._selectedNodes.size === 0) return;
|
|
2483
2689
|
const prev = new Set(this._selectedNodes);
|
|
2484
2690
|
this.#clearSelectionInternal();
|
|
2485
2691
|
this.#dispatchSelect(prev);
|
|
2486
2692
|
this.requestUpdate();
|
|
2487
2693
|
}
|
|
2488
|
-
|
|
2694
|
+
/**
|
|
2695
|
+
* Select every selectable node in the tree, or only the matches while a
|
|
2696
|
+
* `filterPredicate` is active. Nodes inside collapsed branches are included;
|
|
2697
|
+
* unloaded (lazy) children are not. With `visibleOnly`, only rows that are
|
|
2698
|
+
* showing are selected (Ctrl+A). In `checked` mode checking a row checks its
|
|
2699
|
+
* descendants, so `visibleOnly` makes no difference there.
|
|
2700
|
+
*/
|
|
2701
|
+
selectAll(options = {}) {
|
|
2489
2702
|
const prev = new Set(this._selectedNodes);
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
this.#applyCheckedToggle(node, true);
|
|
2493
|
-
}
|
|
2494
|
-
else {
|
|
2495
|
-
for (const { node } of this.#getFlat().rows) {
|
|
2496
|
-
if (!this.#canSelect(node)) continue;
|
|
2497
|
-
this._selectedNodes.add(node);
|
|
2498
|
-
}
|
|
2499
|
-
this.selectedNode = [...this._selectedNodes].at(-1);
|
|
2500
|
-
}
|
|
2703
|
+
for (const node of this.#bulkSelectionScope(options)) if (this.#canSelect(node)) this._selectedNodes.add(node);
|
|
2704
|
+
if (this.selectedNode === void 0 || !this._selectedNodes.has(this.selectedNode)) this.selectedNode = [...this._selectedNodes].at(-1);
|
|
2501
2705
|
this.#dispatchSelect(prev);
|
|
2502
2706
|
this.requestUpdate();
|
|
2503
2707
|
}
|
|
2504
|
-
|
|
2708
|
+
/** Mirror of {@link selectAll}: deselect the same set of nodes it would select. */
|
|
2709
|
+
deselectAll(options = {}) {
|
|
2505
2710
|
const prev = new Set(this._selectedNodes);
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
this.#applyCheckedToggle(node, false);
|
|
2509
|
-
}
|
|
2510
|
-
else this.#clearSelectionInternal();
|
|
2711
|
+
for (const node of this.#bulkSelectionScope(options)) this._selectedNodes.delete(node);
|
|
2712
|
+
if (this.selectedNode !== void 0 && !this._selectedNodes.has(this.selectedNode)) this.selectedNode = [...this._selectedNodes].at(-1);
|
|
2511
2713
|
this.#dispatchSelect(prev);
|
|
2512
2714
|
this.requestUpdate();
|
|
2513
2715
|
}
|
|
2514
2716
|
/**
|
|
2717
|
+
* Nodes `selectAll` / `deselectAll` act on (before `canSelect`): the showing
|
|
2718
|
+
* rows for `visibleOnly` outside `checked` mode, otherwise every loaded node
|
|
2719
|
+
* that the active filter (if any) matches.
|
|
2720
|
+
*/
|
|
2721
|
+
#bulkSelectionScope(options) {
|
|
2722
|
+
if (options.visibleOnly === true && this.interactionMode !== `checked`) return this.#getFlat().rows.map((r) => r.node);
|
|
2723
|
+
const matches = this.#getFilter()?.matches;
|
|
2724
|
+
const result = [];
|
|
2725
|
+
const visit = (node) => {
|
|
2726
|
+
if (matches && !matches.has(node.item.key)) return;
|
|
2727
|
+
result.push(node);
|
|
2728
|
+
node.children?.forEach(visit);
|
|
2729
|
+
};
|
|
2730
|
+
this.root?.children?.forEach(visit);
|
|
2731
|
+
return result;
|
|
2732
|
+
}
|
|
2733
|
+
/**
|
|
2515
2734
|
* Expand every already-loaded branch in a single update. With `maxDepth`,
|
|
2516
2735
|
* only branches at depth < `maxDepth` are expanded (the root's children are
|
|
2517
2736
|
* depth 0), so rows at depth `maxDepth` become visible but stay collapsed.
|
|
@@ -2680,6 +2899,8 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2680
2899
|
#selectSilent;
|
|
2681
2900
|
#dispatchSelect(previous) {
|
|
2682
2901
|
this._selectionVersion++;
|
|
2902
|
+
if (!this.#viewState.isRestoring) this.#pendingSelected = EMPTY_KEYS;
|
|
2903
|
+
this.#viewState.notify();
|
|
2683
2904
|
if (this.#selectSilent) return;
|
|
2684
2905
|
const detail = {
|
|
2685
2906
|
selected: new Set(this._selectedNodes),
|
|
@@ -2897,12 +3118,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2897
3118
|
}));
|
|
2898
3119
|
} else if (node.children === void 0) {
|
|
2899
3120
|
if (node.item.isLeaf !== false) return;
|
|
2900
|
-
if (this
|
|
2901
|
-
this.#pendingNode = node;
|
|
2902
|
-
const controller = new AbortController();
|
|
2903
|
-
this.#pendingController = controller;
|
|
2904
|
-
this.#invokeLoadChildren(node, depth, controller).catch(() => {});
|
|
2905
|
-
}
|
|
3121
|
+
if (this.#hasLoader()) this.#startLoad(node, depth);
|
|
2906
3122
|
} else {
|
|
2907
3123
|
this.#applyExclusivity(node.item.key);
|
|
2908
3124
|
this.#setExpanded(withKey(this._expandedKeys, node.item.key));
|
|
@@ -2970,6 +3186,15 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2970
3186
|
this.#dispatchSelect(prev);
|
|
2971
3187
|
}
|
|
2972
3188
|
}
|
|
3189
|
+
#hasLoader() {
|
|
3190
|
+
return this.model !== void 0 || this.loadChildren !== void 0;
|
|
3191
|
+
}
|
|
3192
|
+
#startLoad(node, depth) {
|
|
3193
|
+
this.#pendingNode = node;
|
|
3194
|
+
const controller = new AbortController();
|
|
3195
|
+
this.#pendingController = controller;
|
|
3196
|
+
this.#invokeLoadChildren(node, depth, controller).catch(() => {});
|
|
3197
|
+
}
|
|
2973
3198
|
async #invokeLoadChildren(node, depth, controller) {
|
|
2974
3199
|
try {
|
|
2975
3200
|
let children;
|
|
@@ -3114,6 +3339,8 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
3114
3339
|
const { node, depth } = nodes[index];
|
|
3115
3340
|
this.tickled.setTickled(node.item.key);
|
|
3116
3341
|
this._focusedDepth = depth;
|
|
3342
|
+
this.#pendingFocus = void 0;
|
|
3343
|
+
this.#viewState.notify();
|
|
3117
3344
|
this.dispatchEvent(new CustomEvent(`tickle`, {
|
|
3118
3345
|
detail: {
|
|
3119
3346
|
node,
|
|
@@ -3162,7 +3389,12 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
3162
3389
|
data-input-mode=${this.tickled.inputMode}
|
|
3163
3390
|
@keydown=${this.#onKeyDown}
|
|
3164
3391
|
@dblclick=${this.#onDblClick}
|
|
3165
|
-
@
|
|
3392
|
+
@scroll=${this.#scrollHover.onScroll}
|
|
3393
|
+
@pointermove=${this.#scrollHover.onPointerMove}
|
|
3394
|
+
@pointerleave=${(e) => {
|
|
3395
|
+
this.#scrollHover.onPointerLeave();
|
|
3396
|
+
this.tickled.handlePointerLeave(e);
|
|
3397
|
+
}}
|
|
3166
3398
|
tabindex="0"
|
|
3167
3399
|
>
|
|
3168
3400
|
${this.#renderStickyHeaders()}
|
|
@@ -3263,17 +3495,7 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
3263
3495
|
draggable=${dnd.draggable ? `true` : nothing}
|
|
3264
3496
|
part=${dnd.dropTarget ? `drop-target` : nothing}
|
|
3265
3497
|
@click=${(e) => this._handleItemClick(node, depth, e)}
|
|
3266
|
-
@pointerenter=${() =>
|
|
3267
|
-
this.tickled.handlePointerEnter(node.item.key);
|
|
3268
|
-
this.dispatchEvent(new CustomEvent(`tickle`, {
|
|
3269
|
-
detail: {
|
|
3270
|
-
node,
|
|
3271
|
-
depth
|
|
3272
|
-
},
|
|
3273
|
-
bubbles: true,
|
|
3274
|
-
composed: true
|
|
3275
|
-
}));
|
|
3276
|
-
}}
|
|
3498
|
+
@pointerenter=${() => this._handleRowPointerEnter(node, depth)}
|
|
3277
3499
|
>
|
|
3278
3500
|
${dnd.dropTarget && (dnd.dropPosition === `before` || dnd.dropPosition === `after`) ? html`<div
|
|
3279
3501
|
class="drop-line drop-line-${dnd.dropPosition}"
|
|
@@ -3535,6 +3757,11 @@ __decorate([property({
|
|
|
3535
3757
|
type: Boolean,
|
|
3536
3758
|
attribute: `disable-keyboard-navigation`
|
|
3537
3759
|
})], TreeBaseElement.prototype, "disableKeyboardNavigation", void 0);
|
|
3760
|
+
__decorate([property({
|
|
3761
|
+
type: Boolean,
|
|
3762
|
+
attribute: `scroll-hover-tickle`,
|
|
3763
|
+
reflect: true
|
|
3764
|
+
})], TreeBaseElement.prototype, "scrollHoverTickle", void 0);
|
|
3538
3765
|
__decorate([property({ attribute: false })], TreeBaseElement.prototype, "registry", void 0);
|
|
3539
3766
|
__decorate([property({
|
|
3540
3767
|
type: String,
|
|
@@ -3588,6 +3815,7 @@ __decorate([property({ attribute: false })], TreeBaseElement.prototype, "canDrop
|
|
|
3588
3815
|
__decorate([property({ attribute: false })], TreeBaseElement.prototype, "parseExternalDrop", void 0);
|
|
3589
3816
|
__decorate([property({ attribute: false })], TreeBaseElement.prototype, "applyInternalDrop", void 0);
|
|
3590
3817
|
__decorate([state()], TreeBaseElement.prototype, "_expandedKeys", void 0);
|
|
3818
|
+
__decorate([property({ attribute: false })], TreeBaseElement.prototype, "restoreLoads", void 0);
|
|
3591
3819
|
__decorate([state()], TreeBaseElement.prototype, "_scrollTop", void 0);
|
|
3592
3820
|
__decorate([state()], TreeBaseElement.prototype, "_focusedDepth", void 0);
|
|
3593
3821
|
__decorate([state()], TreeBaseElement.prototype, "_stickyKeys", void 0);
|
|
@@ -3689,7 +3917,7 @@ let TreeListElement = class TreeListElement extends TreeBaseElement {
|
|
|
3689
3917
|
draggable=${dnd.draggable ? `true` : nothing}
|
|
3690
3918
|
part=${dnd.dropTarget ? `drop-target` : nothing}
|
|
3691
3919
|
@click=${(e) => this._handleItemClick(node, depth, e)}
|
|
3692
|
-
@pointerenter=${() => this.
|
|
3920
|
+
@pointerenter=${() => this._handleRowPointerEnter(node, depth)}
|
|
3693
3921
|
>
|
|
3694
3922
|
${dnd.dropTarget && (dnd.dropPosition === `before` || dnd.dropPosition === `after`) ? html`<div
|
|
3695
3923
|
class="drop-line drop-line-${dnd.dropPosition}"
|