@ixfx/components 0.13.1 → 0.13.3
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 +100 -14
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +2211 -636
- package/bundle/index.js.map +1 -1
- package/dist/ac-token.js +1 -1
- package/dist/{data-grid-Ck1Qx2H1.d.ts → data-grid-DHWJN66w.d.ts} +7 -5
- package/dist/{data-grid-Ck1Qx2H1.d.ts.map → data-grid-DHWJN66w.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +210 -120
- package/dist/data-grid.js.map +1 -1
- package/dist/detail-list-C96B5Txz.js +2001 -0
- package/dist/detail-list-C96B5Txz.js.map +1 -0
- package/dist/{detail-list-C1xzr1z7.d.ts → detail-list-dX7jLO6b.d.ts} +12 -3
- package/dist/{detail-list-C1xzr1z7.d.ts.map → detail-list-dX7jLO6b.d.ts.map} +1 -1
- package/dist/detail-list.d.ts +2 -2
- package/dist/detail-list.js +1 -1680
- package/dist/{flat-list-DEDG6epz.d.ts → flat-list-Y98IqH00.d.ts} +5 -2
- package/dist/flat-list-Y98IqH00.d.ts.map +1 -0
- package/dist/flat-list.d.ts +1 -1
- package/dist/flat-list.js +33 -1
- package/dist/flat-list.js.map +1 -1
- package/dist/{grid-list-pefLORIr.d.ts → grid-list-CoT9e1jB.d.ts} +9 -2
- package/dist/{grid-list-pefLORIr.d.ts.map → grid-list-CoT9e1jB.d.ts.map} +1 -1
- package/dist/{grid-list-DjIl910A.js → grid-list-DeqAd9-h.js} +189 -40
- package/dist/grid-list-DeqAd9-h.js.map +1 -0
- package/dist/grid-list.d.ts +1 -1
- package/dist/grid-list.js +1 -1
- package/dist/{incr-search-D91M4Ozq.js → incr-search-JIhwB49y.js} +27 -5
- package/dist/incr-search-JIhwB49y.js.map +1 -0
- package/dist/incr-search.d.ts +1 -1
- package/dist/incr-search.js +1 -1
- package/dist/index-CnQPCywE.d.ts +325 -0
- package/dist/index-CnQPCywE.d.ts.map +1 -0
- package/dist/{index-CxZ61DO1.d.ts → index-Dlah7Zfi.d.ts} +8 -1
- package/dist/{index-CxZ61DO1.d.ts.map → index-Dlah7Zfi.d.ts.map} +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -25
- package/dist/index.js.map +1 -1
- package/dist/miller.d.ts +1 -1
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +146 -100
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.js +1 -1
- package/dist/split-layout-C5SYbDrq.d.ts.map +1 -1
- package/dist/{split-layout-CXotkdbx.js → split-layout-Deoxy47d.js} +6 -1
- package/dist/{split-layout-CXotkdbx.js.map → split-layout-Deoxy47d.js.map} +1 -1
- package/dist/split-layout.js +1 -1
- package/dist/{tab-list-v8mKX7Fu.d.ts → tab-list-D_dmImJM.d.ts} +2 -3
- package/dist/tab-list-D_dmImJM.d.ts.map +1 -0
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +22 -0
- package/dist/tabs.js.map +1 -1
- package/dist/{tree-DGveys4K.js → tree-DD8OaqsK.js} +1010 -230
- package/dist/tree-DD8OaqsK.js.map +1 -0
- package/dist/tree.d.ts +4 -267
- package/dist/tree.js +1 -1
- package/dist/{vertical-list-CqBc-t8w.d.ts → vertical-list-lj_19DCx.d.ts} +3 -2
- package/dist/{vertical-list-CqBc-t8w.d.ts.map → vertical-list-lj_19DCx.d.ts.map} +1 -1
- package/dist/vertical-list.d.ts +1 -1
- package/dist/vertical-list.js +113 -24
- package/dist/vertical-list.js.map +1 -1
- package/docs-user/data-grid.md +74 -4
- package/docs-user/detail-list.md +65 -0
- package/docs-user/flat-list.md +14 -2
- package/docs-user/grid-list.md +81 -4
- package/docs-user/index.json +2 -2
- package/docs-user/miller.md +59 -3
- package/docs-user/tree.md +63 -2
- package/docs-user/vertical-list.md +9 -1
- package/package.json +6 -1
- package/dist/detail-list.js.map +0 -1
- package/dist/flat-list-DEDG6epz.d.ts.map +0 -1
- package/dist/grid-list-DjIl910A.js.map +0 -1
- package/dist/incr-search-D91M4Ozq.js.map +0 -1
- package/dist/tab-list-v8mKX7Fu.d.ts.map +0 -1
- package/dist/tree-DGveys4K.js.map +0 -1
- package/dist/tree.d.ts.map +0 -1
|
@@ -2,7 +2,7 @@ import { t as TickledController } from "./tickled-controller-D-HZymaZ.js";
|
|
|
2
2
|
import { n as tickledStyles, t as tickledItemStyles } from "./tickled-styles-BrAHEj1q.js";
|
|
3
3
|
import { t as themeFallbacks } from "./fallbacks-DQ_5OsmR.js";
|
|
4
4
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
5
|
-
import { c as createElementListSearchAdapter, d as createDataListSearchAdapter, i as ListSearchController, n as listSearchStyles, o as registerListSearchCommands, r as LIST_SEARCH_MODES, u as keyForElement } from "./incr-search-
|
|
5
|
+
import { c as createElementListSearchAdapter, d as createDataListSearchAdapter, i as ListSearchController, n as listSearchStyles, o as registerListSearchCommands, r as LIST_SEARCH_MODES, u as keyForElement } from "./incr-search-JIhwB49y.js";
|
|
6
6
|
import { i as resolveGroupKey, r as partitionByGroup } from "./grouping-RYPnHkrS.js";
|
|
7
7
|
import { t as ListNativeDragController } from "./list-native-drag-controller-B9xO0XWn.js";
|
|
8
8
|
import { r as ListDragSelectController, t as ListSelectionController } from "./list-selection-controller-BeE70lbB.js";
|
|
@@ -401,16 +401,24 @@ function warnDuplicateKeys(keys) {
|
|
|
401
401
|
}
|
|
402
402
|
if (dupes.size > 0) console.warn(`ixfx-grid-list: duplicate item key(s) ${[...dupes].map((k) => `"${k}"`).join(`, `)} — the first occurrence wins for key-based operations.`);
|
|
403
403
|
}
|
|
404
|
+
/** Key → first effective index, built from `keys` (first occurrence wins on duplicates). */
|
|
405
|
+
function indexByKey(keys) {
|
|
406
|
+
const index = /* @__PURE__ */ new Map();
|
|
407
|
+
keys.forEach((k, i) => {
|
|
408
|
+
if (!index.has(k)) index.set(k, i);
|
|
409
|
+
});
|
|
410
|
+
return index;
|
|
411
|
+
}
|
|
404
412
|
var ElementGridListSource = class {
|
|
405
413
|
#host;
|
|
406
414
|
#items = [];
|
|
407
|
-
#slotNames = /* @__PURE__ */ new WeakMap();
|
|
408
415
|
#syntheticKeys = /* @__PURE__ */ new WeakMap();
|
|
409
416
|
#seq = 0;
|
|
410
417
|
#predicate;
|
|
411
418
|
#searchKeys;
|
|
412
419
|
#effectiveIndices = [];
|
|
413
420
|
#keysCache;
|
|
421
|
+
#indexCache;
|
|
414
422
|
#grouping;
|
|
415
423
|
#groups = [];
|
|
416
424
|
#groupByKey = /* @__PURE__ */ new Map();
|
|
@@ -429,7 +437,8 @@ var ElementGridListSource = class {
|
|
|
429
437
|
return eff === void 0 ? `` : this.#itemKey(this.#items[eff]);
|
|
430
438
|
}
|
|
431
439
|
indexOfKey(key) {
|
|
432
|
-
|
|
440
|
+
this.#indexCache ??= indexByKey(this.keys());
|
|
441
|
+
return this.#indexCache.get(key) ?? -1;
|
|
433
442
|
}
|
|
434
443
|
keys() {
|
|
435
444
|
this.#keysCache ??= this.#effectiveIndices.map((i) => this.#itemKey(this.#items[i]));
|
|
@@ -452,11 +461,11 @@ var ElementGridListSource = class {
|
|
|
452
461
|
const eff = this.#effectiveIndices[index];
|
|
453
462
|
return eff !== void 0 && !this.#items[eff].hasAttribute(`not-checked`);
|
|
454
463
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
464
|
+
/**
|
|
465
|
+
* Element mode cells project their item through a per-cell `<slot>` that
|
|
466
|
+
* `GridListElement` renders and assigns itself (see its `#applyCellSlots`).
|
|
467
|
+
*/
|
|
468
|
+
renderCellContent(_index) {}
|
|
460
469
|
iconAt(_index) {}
|
|
461
470
|
iconColorAt(_index) {}
|
|
462
471
|
textColorAt(_index) {}
|
|
@@ -478,10 +487,6 @@ var ElementGridListSource = class {
|
|
|
478
487
|
}
|
|
479
488
|
refresh() {
|
|
480
489
|
this.#items = Array.from(this.#host.querySelectorAll(ITEM_SELECTOR$1)).filter((el) => !el.hidden);
|
|
481
|
-
for (const el of this.#items) {
|
|
482
|
-
const name = this.slotNameFor(el);
|
|
483
|
-
if (el.getAttribute(`slot`) !== name) el.setAttribute(`slot`, name);
|
|
484
|
-
}
|
|
485
490
|
warnDuplicateKeys(this.#items.map((el) => this.#itemKey(el)));
|
|
486
491
|
this.#recomputeEffective();
|
|
487
492
|
}
|
|
@@ -493,16 +498,6 @@ var ElementGridListSource = class {
|
|
|
493
498
|
rawElementAt(index) {
|
|
494
499
|
return this.#items[index];
|
|
495
500
|
}
|
|
496
|
-
/** Stable per-element `<slot>` name. */
|
|
497
|
-
slotNameFor(el) {
|
|
498
|
-
let name = this.#slotNames.get(el);
|
|
499
|
-
if (name === void 0) {
|
|
500
|
-
this.#seq += 1;
|
|
501
|
-
name = `gl-item-${this.#seq}`;
|
|
502
|
-
this.#slotNames.set(el, name);
|
|
503
|
-
}
|
|
504
|
-
return name;
|
|
505
|
-
}
|
|
506
501
|
resolveKeyToElement(key) {
|
|
507
502
|
if (isSyntheticKey(key)) return this.#items.find((el) => this.#syntheticKeys.get(el) === key);
|
|
508
503
|
return this.#items.find((el) => keyForElement(el) === key);
|
|
@@ -520,6 +515,7 @@ var ElementGridListSource = class {
|
|
|
520
515
|
}
|
|
521
516
|
this.#applyGroupingTo(effective);
|
|
522
517
|
this.#keysCache = void 0;
|
|
518
|
+
this.#indexCache = void 0;
|
|
523
519
|
}
|
|
524
520
|
#applyGroupingTo(effective) {
|
|
525
521
|
if (this.#grouping === void 0) {
|
|
@@ -555,6 +551,7 @@ var DataGridListSource = class {
|
|
|
555
551
|
#searchKeys;
|
|
556
552
|
#effectiveIndices = [];
|
|
557
553
|
#keysCache;
|
|
554
|
+
#indexCache;
|
|
558
555
|
#grouping;
|
|
559
556
|
#groups = [];
|
|
560
557
|
#groupByKey = /* @__PURE__ */ new Map();
|
|
@@ -575,7 +572,8 @@ var DataGridListSource = class {
|
|
|
575
572
|
return eff === void 0 ? `` : this.#adapter.key(this.#items[eff], eff);
|
|
576
573
|
}
|
|
577
574
|
indexOfKey(key) {
|
|
578
|
-
|
|
575
|
+
this.#indexCache ??= indexByKey(this.keys());
|
|
576
|
+
return this.#indexCache.get(key) ?? -1;
|
|
579
577
|
}
|
|
580
578
|
keys() {
|
|
581
579
|
this.#keysCache ??= this.#effectiveIndices.map((i) => this.#adapter.key(this.#items[i], i));
|
|
@@ -668,6 +666,7 @@ var DataGridListSource = class {
|
|
|
668
666
|
this.#groupByKey = grouped.groupByKey;
|
|
669
667
|
}
|
|
670
668
|
this.#keysCache = void 0;
|
|
669
|
+
this.#indexCache = void 0;
|
|
671
670
|
}
|
|
672
671
|
};
|
|
673
672
|
//#endregion
|
|
@@ -694,6 +693,15 @@ function sameKeys(a, b) {
|
|
|
694
693
|
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
695
694
|
return true;
|
|
696
695
|
}
|
|
696
|
+
/**
|
|
697
|
+
* Set `attr` on exactly the elements in `now`, removing it from those in
|
|
698
|
+
* `previous` that no longer qualify. Returns the new marked set.
|
|
699
|
+
*/
|
|
700
|
+
function syncMarker(attr, previous, now) {
|
|
701
|
+
for (const el of previous) if (!now.has(el)) el.removeAttribute(attr);
|
|
702
|
+
for (const el of now) if (!el.hasAttribute(attr)) el.setAttribute(attr, ``);
|
|
703
|
+
return now;
|
|
704
|
+
}
|
|
697
705
|
let GridListElement = class GridListElement extends LitElement {
|
|
698
706
|
constructor(..._args) {
|
|
699
707
|
super(..._args);
|
|
@@ -728,6 +736,11 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
728
736
|
this.#snapTimer = 0;
|
|
729
737
|
this.#items = [];
|
|
730
738
|
this.#itemWrap = `stop`;
|
|
739
|
+
this.#cellIds = /* @__PURE__ */ new Map();
|
|
740
|
+
this.#nextCellId = 0;
|
|
741
|
+
this.#recycledKeys = /* @__PURE__ */ new Set();
|
|
742
|
+
this.#windowSlots = [];
|
|
743
|
+
this.#slottedItems = /* @__PURE__ */ new Map();
|
|
731
744
|
this.#entering = /* @__PURE__ */ new Set();
|
|
732
745
|
this.#reflowTimer = 0;
|
|
733
746
|
this.#sourceElement = new ElementGridListSource(this);
|
|
@@ -851,6 +864,8 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
851
864
|
}
|
|
852
865
|
});
|
|
853
866
|
this.#groupByChanged = false;
|
|
867
|
+
this.#markedTickled = /* @__PURE__ */ new Set();
|
|
868
|
+
this.#markedSelected = /* @__PURE__ */ new Set();
|
|
854
869
|
this.#selectedSnapshot = /* @__PURE__ */ new Set();
|
|
855
870
|
this.#onScroll = (e) => {
|
|
856
871
|
const el = e.target;
|
|
@@ -1340,6 +1355,14 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1340
1355
|
.cell.entering {
|
|
1341
1356
|
animation: ixfx-list-item-in var(--grid-list-item-move-duration, 200ms) ease both;
|
|
1342
1357
|
}
|
|
1358
|
+
/* A recycled cell has just been handed from one item to another (see
|
|
1359
|
+
#assignCellIds); it must not animate from the previous item's state
|
|
1360
|
+
or position. */
|
|
1361
|
+
.cell.recycled,
|
|
1362
|
+
.cell.recycled > .thumb,
|
|
1363
|
+
.cell.recycled > .thumb::after {
|
|
1364
|
+
transition: none !important;
|
|
1365
|
+
}
|
|
1343
1366
|
@media (prefers-reduced-motion: reduce) {
|
|
1344
1367
|
:host([reflowing]) .group-header { transition: none; }
|
|
1345
1368
|
:host([reflowing]) .cell { transition: background var(--transition), border-color var(--transition); }
|
|
@@ -1371,11 +1394,39 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1371
1394
|
#viewportRef;
|
|
1372
1395
|
#resizeObserver;
|
|
1373
1396
|
#mutationObserver;
|
|
1397
|
+
/**
|
|
1398
|
+
* Watches item (direct child) attributes that change the item set: `hidden`
|
|
1399
|
+
* drops an item from layout, `data-key` / `data-value` change its identity.
|
|
1400
|
+
* Separate from {@link #mutationObserver} because attribute observation of
|
|
1401
|
+
* children needs `subtree`, which must not apply to the child list.
|
|
1402
|
+
*/
|
|
1403
|
+
#itemAttrObserver;
|
|
1374
1404
|
#scrollRaf;
|
|
1375
1405
|
/** Debounce handle for {@link snapToItem} — fires once scrolling settles. */
|
|
1376
1406
|
#snapTimer;
|
|
1377
1407
|
#items;
|
|
1378
1408
|
#itemWrap;
|
|
1409
|
+
/**
|
|
1410
|
+
* Cell recycling. Each rendered key holds a stable cell id, and `repeat` is
|
|
1411
|
+
* keyed by that id rather than the item key, so a cell scrolled out of the
|
|
1412
|
+
* window hands its DOM to an item scrolling in instead of being destroyed and
|
|
1413
|
+
* recreated. Item-keyed `repeat` gets steadily slower in Chrome when every key
|
|
1414
|
+
* in the window is new (a scrollbar drag / fling), and recreating ~100 cells a
|
|
1415
|
+
* frame is costly in any case. See {@link #assignCellIds}.
|
|
1416
|
+
*/
|
|
1417
|
+
#cellIds;
|
|
1418
|
+
#nextCellId;
|
|
1419
|
+
/** Keys whose cell was taken over from another item in the latest render. */
|
|
1420
|
+
#recycledKeys;
|
|
1421
|
+
/**
|
|
1422
|
+
* Element mode: each cell has a fixed `<slot name="gl-cell-<id>">`, and the
|
|
1423
|
+
* light-DOM item it shows is pointed at it via its `slot` attribute. Moving
|
|
1424
|
+
* that attribute is far cheaper than renaming slots, which makes the browser
|
|
1425
|
+
* re-match every light-DOM child. `#windowSlots` is the assignment the latest
|
|
1426
|
+
* render wants (applied in `updated()`); `#slottedItems` is what's applied.
|
|
1427
|
+
*/
|
|
1428
|
+
#windowSlots;
|
|
1429
|
+
#slottedItems;
|
|
1379
1430
|
/** Items added mid-list that are still playing their enter animation. */
|
|
1380
1431
|
#entering;
|
|
1381
1432
|
/** Timer that ends the `[reflowing]` window opened by a mid-list insertion. */
|
|
@@ -1563,9 +1614,15 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1563
1614
|
this.addEventListener(`pointermove`, this.#onHostPointerMove, { passive: true });
|
|
1564
1615
|
this.addEventListener(`pointerleave`, this.#onHostPointerLeave);
|
|
1565
1616
|
this.#mutationObserver ??= new MutationObserver((records) => this.#onChildrenChanged(records));
|
|
1566
|
-
this.#mutationObserver.observe(this, {
|
|
1567
|
-
|
|
1568
|
-
|
|
1617
|
+
this.#mutationObserver.observe(this, { childList: true });
|
|
1618
|
+
this.#itemAttrObserver ??= new MutationObserver((records) => this.#onItemAttributesChanged(records));
|
|
1619
|
+
this.#itemAttrObserver.observe(this, {
|
|
1620
|
+
subtree: true,
|
|
1621
|
+
attributeFilter: [
|
|
1622
|
+
`hidden`,
|
|
1623
|
+
`data-key`,
|
|
1624
|
+
`data-value`
|
|
1625
|
+
]
|
|
1569
1626
|
});
|
|
1570
1627
|
this.#searchRegistry ??= createCommandRegistry();
|
|
1571
1628
|
this.#ensureSearch();
|
|
@@ -1581,6 +1638,7 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1581
1638
|
this.#resizeObserver?.disconnect();
|
|
1582
1639
|
this.#resizeObserver = void 0;
|
|
1583
1640
|
this.#mutationObserver?.disconnect();
|
|
1641
|
+
this.#itemAttrObserver?.disconnect();
|
|
1584
1642
|
this.#cancelScrollRaf();
|
|
1585
1643
|
this.#cancelSnapTimer();
|
|
1586
1644
|
this.#unregisterSearchCommands?.();
|
|
@@ -1592,6 +1650,10 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1592
1650
|
}
|
|
1593
1651
|
if (this.#nativeDragging || this.#nativeDrag.isDragging) this.#clearNativeDragState();
|
|
1594
1652
|
}
|
|
1653
|
+
/** Only attribute changes on items themselves matter, not on their content. */
|
|
1654
|
+
#onItemAttributesChanged(records) {
|
|
1655
|
+
if (records.some((r) => r.target.parentNode === this)) this.#onChildrenChanged([]);
|
|
1656
|
+
}
|
|
1595
1657
|
#onChildrenChanged(records) {
|
|
1596
1658
|
const previousLength = this.#items.length;
|
|
1597
1659
|
this.#syncItems();
|
|
@@ -1608,7 +1670,7 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1608
1670
|
const tickledId = this.tickled.tickledId;
|
|
1609
1671
|
if (tickledId && gone.includes(tickledId)) this.tickled.focus(void 0);
|
|
1610
1672
|
}
|
|
1611
|
-
this._syncItemStates();
|
|
1673
|
+
this._syncItemStates(true);
|
|
1612
1674
|
this.#noteChildMutation(previousLength, records);
|
|
1613
1675
|
this.requestUpdate();
|
|
1614
1676
|
this.updateComplete.then(() => this.#emitViewportChange());
|
|
@@ -1680,6 +1742,11 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1680
1742
|
const w = entry.contentRect.width;
|
|
1681
1743
|
const h = entry.contentRect.height;
|
|
1682
1744
|
if (w <= 0 || h <= 0) return;
|
|
1745
|
+
if (w === this._viewportWidth && h === this._viewportHeight) continue;
|
|
1746
|
+
const horizontal = this.orientation === `row`;
|
|
1747
|
+
const prevOffset = horizontal ? this._scrollLeft : this._scrollTop;
|
|
1748
|
+
const prevExtent = horizontal ? this._viewportWidth : this._viewportHeight;
|
|
1749
|
+
if (prevExtent > 0 && prevOffset > 1) this.#captureCentreAnchor(prevOffset, prevExtent, this.itemSize, this.gap, this.captionStyle, this.captionHeight, this.orientation);
|
|
1683
1750
|
this._viewportWidth = w;
|
|
1684
1751
|
this._viewportHeight = h;
|
|
1685
1752
|
}
|
|
@@ -1841,7 +1908,11 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
1841
1908
|
}
|
|
1842
1909
|
updated(changed) {
|
|
1843
1910
|
super.updated(changed);
|
|
1844
|
-
this.#
|
|
1911
|
+
const pending = this.#mutationObserver?.takeRecords();
|
|
1912
|
+
const pendingAttrs = this.#itemAttrObserver?.takeRecords();
|
|
1913
|
+
if (pending !== void 0 && pending.length > 0) this.#onChildrenChanged(pending);
|
|
1914
|
+
else if (pendingAttrs !== void 0 && pendingAttrs.length > 0) this.#onItemAttributesChanged(pendingAttrs);
|
|
1915
|
+
if (this.#source instanceof ElementGridListSource) this.#applyCellSlots();
|
|
1845
1916
|
if (changed.has(`selectionMode`) || changed.has(`interactionMode`)) {
|
|
1846
1917
|
this.selection.clearAnchor();
|
|
1847
1918
|
this.#syncAriaMultiselectable();
|
|
@@ -2193,13 +2264,36 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2193
2264
|
this._scrollTop = next;
|
|
2194
2265
|
}
|
|
2195
2266
|
}
|
|
2196
|
-
|
|
2267
|
+
/** Light-DOM items currently carrying `data-tickled` / `data-selected`. */
|
|
2268
|
+
#markedTickled;
|
|
2269
|
+
#markedSelected;
|
|
2270
|
+
/**
|
|
2271
|
+
* Mirror cursor / selection onto the light-DOM items as `data-tickled` /
|
|
2272
|
+
* `data-selected`. Only the items whose state changed are touched, so a
|
|
2273
|
+
* cursor move costs O(selection), not O(items). `full` re-checks every item —
|
|
2274
|
+
* used when the child list changes, so markers set before the item was
|
|
2275
|
+
* ours (or left on a removed item) are corrected.
|
|
2276
|
+
*/
|
|
2277
|
+
_syncItemStates(full = false) {
|
|
2197
2278
|
const selected = this.selection.selectedKeys;
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2279
|
+
const tickledId = this.tickled.tickledId;
|
|
2280
|
+
const elementFor = (key) => {
|
|
2281
|
+
if (isSyntheticKey(key)) return void 0;
|
|
2282
|
+
const index = this.#source.indexOfKey(key);
|
|
2283
|
+
return index < 0 ? void 0 : this.#items[index];
|
|
2284
|
+
};
|
|
2285
|
+
const tickledEl = tickledId === void 0 ? void 0 : elementFor(tickledId);
|
|
2286
|
+
const selectedEls = /* @__PURE__ */ new Set();
|
|
2287
|
+
for (const key of selected) {
|
|
2288
|
+
const el = elementFor(key);
|
|
2289
|
+
if (el) selectedEls.add(el);
|
|
2202
2290
|
}
|
|
2291
|
+
if (full) for (const el of this.#items) {
|
|
2292
|
+
this.#markedTickled.add(el);
|
|
2293
|
+
this.#markedSelected.add(el);
|
|
2294
|
+
}
|
|
2295
|
+
this.#markedTickled = syncMarker(`data-tickled`, this.#markedTickled, tickledEl ? /* @__PURE__ */ new Set([tickledEl]) : /* @__PURE__ */ new Set());
|
|
2296
|
+
this.#markedSelected = syncMarker(`data-selected`, this.#markedSelected, selectedEls);
|
|
2203
2297
|
this.setAttribute(`data-input-mode`, this.tickled.inputMode);
|
|
2204
2298
|
}
|
|
2205
2299
|
#emitSelect(selected, previous) {
|
|
@@ -2269,8 +2363,57 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2269
2363
|
`;
|
|
2270
2364
|
}
|
|
2271
2365
|
#renderDataCells(win) {
|
|
2366
|
+
const slice = this.#windowSlice(win);
|
|
2367
|
+
return repeat(slice, (index) => this.#cellIds.get(this.#source.keyAt(index)), (index) => this.#renderDataCell(index, win));
|
|
2368
|
+
}
|
|
2369
|
+
#cellSlotName(key) {
|
|
2370
|
+
return `gl-cell-${this.#cellIds.get(key)}`;
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* Element mode: point each rendered item's `slot` at its cell, and clear it on
|
|
2374
|
+
* items that left the window (or the DOM) so they project nowhere.
|
|
2375
|
+
*/
|
|
2376
|
+
#applyCellSlots() {
|
|
2377
|
+
const next = /* @__PURE__ */ new Map();
|
|
2378
|
+
for (const [el, name] of this.#windowSlots) {
|
|
2379
|
+
next.set(el, name);
|
|
2380
|
+
if (el.getAttribute(`slot`) !== name) el.setAttribute(`slot`, name);
|
|
2381
|
+
}
|
|
2382
|
+
for (const el of this.#slottedItems.keys()) if (!next.has(el)) el.removeAttribute(`slot`);
|
|
2383
|
+
this.#slottedItems = next;
|
|
2384
|
+
}
|
|
2385
|
+
/** Effective indices in the rendered window, with cell ids assigned to their keys. */
|
|
2386
|
+
#windowSlice(win) {
|
|
2272
2387
|
const slice = win.ranges.flatMap(([start, end]) => Array.from({ length: end - start }, (_, i) => start + i));
|
|
2273
|
-
|
|
2388
|
+
this.#assignCellIds(slice.map((index) => this.#source.keyAt(index)));
|
|
2389
|
+
return slice;
|
|
2390
|
+
}
|
|
2391
|
+
/**
|
|
2392
|
+
* Give every key in the window a cell id: keys already rendered keep theirs;
|
|
2393
|
+
* new keys take the ids freed by keys that left the window (recycling that
|
|
2394
|
+
* cell's DOM), and only mint a fresh id when none is free.
|
|
2395
|
+
*/
|
|
2396
|
+
#assignCellIds(keys) {
|
|
2397
|
+
const inWindow = new Set(keys);
|
|
2398
|
+
const free = [];
|
|
2399
|
+
for (const [key, id] of this.#cellIds) if (!inWindow.has(key)) free.push(id);
|
|
2400
|
+
const next = /* @__PURE__ */ new Map();
|
|
2401
|
+
for (const key of keys) {
|
|
2402
|
+
const id = this.#cellIds.get(key);
|
|
2403
|
+
if (id !== void 0) next.set(key, id);
|
|
2404
|
+
}
|
|
2405
|
+
const recycled = /* @__PURE__ */ new Set();
|
|
2406
|
+
for (const key of keys) {
|
|
2407
|
+
if (next.has(key)) continue;
|
|
2408
|
+
const id = free.pop();
|
|
2409
|
+
if (id === void 0) next.set(key, this.#nextCellId++);
|
|
2410
|
+
else {
|
|
2411
|
+
next.set(key, id);
|
|
2412
|
+
recycled.add(key);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
this.#cellIds = next;
|
|
2416
|
+
this.#recycledKeys = recycled;
|
|
2274
2417
|
}
|
|
2275
2418
|
#renderDataCell(index, win) {
|
|
2276
2419
|
const key = this.#source.keyAt(index);
|
|
@@ -2290,10 +2433,12 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2290
2433
|
const icon = appearanceAbsent(rawIcon) ? void 0 : rawIcon;
|
|
2291
2434
|
return html`
|
|
2292
2435
|
<div
|
|
2293
|
-
class="cell${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}${marquee ? ` marquee` : ``}${this.#nativeDragging && key === this.#dragOriginKey ? ` dragging-origin` : ``}"
|
|
2436
|
+
class="cell${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}${marquee ? ` marquee` : ``}${this.#recycledKeys.has(key) ? ` recycled` : ``}${this.#nativeDragging && key === this.#dragOriginKey ? ` dragging-origin` : ``}"
|
|
2294
2437
|
part="item${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}"
|
|
2295
2438
|
role="option"
|
|
2296
2439
|
aria-selected=${selected ? `true` : `false`}
|
|
2440
|
+
aria-setsize=${this.#source.count}
|
|
2441
|
+
aria-posinset=${index + 1}
|
|
2297
2442
|
style="width:${this.itemSize}px;height:${cellHeight}px;transform:translate(${x}px,${y}px)"
|
|
2298
2443
|
data-index=${index}
|
|
2299
2444
|
data-key=${key}
|
|
@@ -2370,8 +2515,9 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2370
2515
|
current.startLoop?.();
|
|
2371
2516
|
}
|
|
2372
2517
|
#renderElementCells(win) {
|
|
2373
|
-
const slice = win
|
|
2374
|
-
|
|
2518
|
+
const slice = this.#windowSlice(win);
|
|
2519
|
+
this.#windowSlots = slice.map((index) => [this.#items[index], this.#cellSlotName(this.#source.keyAt(index))]);
|
|
2520
|
+
return repeat(slice, (index) => this.#cellIds.get(this.#source.keyAt(index)), (index) => this.#renderCell(this.#items[index], index, win));
|
|
2375
2521
|
}
|
|
2376
2522
|
#renderHeaders(win) {
|
|
2377
2523
|
if (win.headers.length === 0) return nothing;
|
|
@@ -2380,6 +2526,7 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2380
2526
|
<ixfx-list-group-header
|
|
2381
2527
|
class="group-header"
|
|
2382
2528
|
part="group-header"
|
|
2529
|
+
role="presentation"
|
|
2383
2530
|
data-group-key=${h.key}
|
|
2384
2531
|
label=${h.label}
|
|
2385
2532
|
count=${h.count}
|
|
@@ -2408,10 +2555,12 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2408
2555
|
const captionCss = separate ? `height:${Math.max(0, this.captionHeight - 4)}px` : style === `under` ? `height:${this.captionHeight}px` : ``;
|
|
2409
2556
|
return html`
|
|
2410
2557
|
<div
|
|
2411
|
-
class="cell${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}${entering ? ` entering` : ``}${marquee ? ` marquee` : ``}${this.#nativeDragging && key === this.#dragOriginKey ? ` dragging-origin` : ``}"
|
|
2558
|
+
class="cell${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}${entering ? ` entering` : ``}${marquee ? ` marquee` : ``}${this.#recycledKeys.has(key) ? ` recycled` : ``}${this.#nativeDragging && key === this.#dragOriginKey ? ` dragging-origin` : ``}"
|
|
2412
2559
|
part="item${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}"
|
|
2413
2560
|
role="option"
|
|
2414
2561
|
aria-selected=${selected ? `true` : `false`}
|
|
2562
|
+
aria-setsize=${this.#source.count}
|
|
2563
|
+
aria-posinset=${index + 1}
|
|
2415
2564
|
style="width:${this.itemSize}px;height:${cellHeight}px;transform:translate(${x}px,${y}px)"
|
|
2416
2565
|
data-index=${index}
|
|
2417
2566
|
data-key=${key}
|
|
@@ -2424,7 +2573,7 @@ let GridListElement = class GridListElement extends LitElement {
|
|
|
2424
2573
|
@pointerenter=${() => this.#handleCellPointerEnter(key)}
|
|
2425
2574
|
>
|
|
2426
2575
|
<div class="thumb" part="thumb" style=${thumbStyle}>
|
|
2427
|
-
|
|
2576
|
+
<slot name=${this.#cellSlotName(key)}></slot>
|
|
2428
2577
|
</div>
|
|
2429
2578
|
${showCaption ? this.#renderCaption(caption, captionCss, tickled) : ``}
|
|
2430
2579
|
</div>
|
|
@@ -2660,4 +2809,4 @@ GridListElement = __decorate([safeCustomElement(`ixfx-grid-list`)], GridListElem
|
|
|
2660
2809
|
//#endregion
|
|
2661
2810
|
export { GridListElement as t };
|
|
2662
2811
|
|
|
2663
|
-
//# sourceMappingURL=grid-list-
|
|
2812
|
+
//# sourceMappingURL=grid-list-DeqAd9-h.js.map
|