@aceshooting/lyra-ui 17.0.0 → 18.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 (107) hide show
  1. package/CHANGELOG.md +483 -0
  2. package/README.md +2 -2
  3. package/custom-elements.json +1 -1
  4. package/design-tokens.json +1 -1
  5. package/dist/cli/migration-contract.json +1 -1
  6. package/dist/components/conversation/message-actions/message-actions.class.d.ts +2 -1
  7. package/dist/components/conversation/streaming-text/streaming-text-core.class.d.ts +22 -0
  8. package/dist/components/conversation/streaming-text/streaming-text-core.class.js +1 -0
  9. package/dist/components/conversation/streaming-text/streaming-text.class.d.ts +22 -0
  10. package/dist/components/conversation/streaming-text/streaming-text.class.js +1 -0
  11. package/dist/components/conversation/thread-list/thread-list.class.js +1 -1
  12. package/dist/components/data/table/table.styles.js +1 -1
  13. package/dist/components/forms/combobox/combobox.class.d.ts +12 -2
  14. package/dist/components/forms/combobox/combobox.class.js +2 -2
  15. package/dist/components/forms/combobox/combobox.styles.js +1 -1
  16. package/dist/components/forms/icon-button/icon-button.class.d.ts +18 -9
  17. package/dist/components/forms/select/select.class.d.ts +63 -8
  18. package/dist/components/forms/select/select.class.js +4 -4
  19. package/dist/components/forms/select/select.styles.js +1 -1
  20. package/dist/components/layout/filter-bar/filter-bar.class.d.ts +148 -14
  21. package/dist/components/layout/filter-bar/filter-bar.class.js +12 -4
  22. package/dist/components/layout/filter-bar/filter-bar.styles.js +1 -1
  23. package/dist/components/layout/reorder-list/reorder-list.class.js +1 -1
  24. package/dist/components/layout/virtual-list/virtual-list.class.d.ts +154 -18
  25. package/dist/components/layout/virtual-list/virtual-list.class.js +12 -7
  26. package/dist/components/media/map/map.class.d.ts +269 -14
  27. package/dist/components/media/map/map.class.js +62 -30
  28. package/dist/components/media/map/map.styles.js +1 -1
  29. package/dist/components/utility/copy-button/copy-button.class.d.ts +4 -3
  30. package/dist/custom-elements-jsx.d.ts +1 -1
  31. package/dist/events.d.ts +13 -1
  32. package/dist/internal/package-metadata.d.ts +1 -1
  33. package/dist/internal/package-metadata.js +1 -1
  34. package/dist/internal/tokens.styles.js +1 -1
  35. package/dist/lyra.d.ts +1 -1
  36. package/dist/lyra.js +1 -1
  37. package/dist/styles/tokens-root.css +1 -1
  38. package/dist/svelte.d.ts +1 -1
  39. package/dist/testing/lyra-tag-event-map.js +1 -1
  40. package/dist/translations/ar/retrieval.js +1 -1
  41. package/dist/translations/ar/shared.js +1 -1
  42. package/dist/translations/de/retrieval.js +1 -1
  43. package/dist/translations/de/shared.js +1 -1
  44. package/dist/translations/es/retrieval.js +1 -1
  45. package/dist/translations/es/shared.js +1 -1
  46. package/dist/translations/fa/retrieval.js +1 -1
  47. package/dist/translations/fa/shared.js +1 -1
  48. package/dist/translations/fr/retrieval.js +1 -1
  49. package/dist/translations/fr/shared.js +1 -1
  50. package/dist/translations/he/retrieval.js +1 -1
  51. package/dist/translations/he/shared.js +1 -1
  52. package/dist/translations/it/retrieval.js +1 -1
  53. package/dist/translations/it/shared.js +1 -1
  54. package/dist/translations/ja/retrieval.js +1 -1
  55. package/dist/translations/ja/shared.js +1 -1
  56. package/dist/translations/pt-BR/retrieval.js +1 -1
  57. package/dist/translations/pt-BR/shared.js +1 -1
  58. package/dist/translations/ro/agent-tools.d.ts +1 -0
  59. package/dist/translations/ro/agent-tools.js +1 -0
  60. package/dist/translations/ro/charts.d.ts +1 -0
  61. package/dist/translations/ro/charts.js +1 -0
  62. package/dist/translations/ro/conversation.d.ts +1 -0
  63. package/dist/translations/ro/conversation.js +1 -0
  64. package/dist/translations/ro/data.d.ts +1 -0
  65. package/dist/translations/ro/data.js +1 -0
  66. package/dist/translations/ro/forms.d.ts +1 -0
  67. package/dist/translations/ro/forms.js +1 -0
  68. package/dist/translations/ro/layout.d.ts +1 -0
  69. package/dist/translations/ro/layout.js +1 -0
  70. package/dist/translations/ro/media.d.ts +1 -0
  71. package/dist/translations/ro/media.js +1 -0
  72. package/dist/translations/ro/overlays.d.ts +1 -0
  73. package/dist/translations/ro/overlays.js +1 -0
  74. package/dist/translations/ro/retrieval.d.ts +1 -0
  75. package/dist/translations/ro/retrieval.js +1 -0
  76. package/dist/translations/ro/shared.d.ts +1 -0
  77. package/dist/translations/ro/shared.js +1 -0
  78. package/dist/translations/ro/utility.d.ts +1 -0
  79. package/dist/translations/ro/utility.js +1 -0
  80. package/dist/translations/ro/viewers.d.ts +1 -0
  81. package/dist/translations/ro/viewers.js +5 -0
  82. package/dist/translations/ro.d.ts +1 -0
  83. package/dist/translations/ro.js +1 -0
  84. package/dist/translations/ru/retrieval.js +1 -1
  85. package/dist/translations/ru/shared.js +1 -1
  86. package/dist/translations/zh-CN/retrieval.js +1 -1
  87. package/dist/translations/zh-CN/shared.js +1 -1
  88. package/dist/vue.d.ts +1 -1
  89. package/llms/components/lr-button.md +5 -4
  90. package/llms/components/lr-card.md +2 -1
  91. package/llms/components/lr-combobox.md +11 -0
  92. package/llms/components/lr-filter-bar.md +123 -7
  93. package/llms/components/lr-icon-button.md +17 -8
  94. package/llms/components/lr-map.md +127 -8
  95. package/llms/components/lr-option.md +11 -0
  96. package/llms/components/lr-select.md +45 -3
  97. package/llms/components/lr-streaming-text-core.md +7 -3
  98. package/llms/components/lr-streaming-text.md +7 -2
  99. package/llms/components/lr-virtual-list.md +53 -0
  100. package/llms/shared.md +47 -3
  101. package/llms/tokens.md +7 -4
  102. package/llms-full.txt +465 -36
  103. package/package.json +28 -2
  104. package/registrations.json +1 -1
  105. package/vscode-css-data.json +1 -1
  106. package/vscode-html-data.json +1 -1
  107. package/web-types.json +1 -1
@@ -9,6 +9,28 @@ export interface LyraVirtualListGroup{key:string|number;label?:string;startIndex
9
9
  /** The ARIA role pairing each rendered row participates in -- see `itemRole`'s own doc for what
10
10
  * each value maps to. */
11
11
  export type LyraVirtualListItemRole='listitem'|'row';
12
+ /**
13
+ * Where `renderItem`'s output is instantiated.
14
+ *
15
+ * - `'shadow'` (the default) stamps it inside this component's shadow root, where only inherited
16
+ * custom properties and an explicitly exported part reach it.
17
+ * - `'light'` stamps it into the HOST'S OWN light DOM, assigned back into the windowed row wrapper
18
+ * through an internal named slot, so an ordinary document stylesheet styles a virtualized row.
19
+ * Windowing, measurement, spacer sizing, `scrollToIndex()`, the external-scroller mode and the
20
+ * ARIA contract all stay with this component either way.
21
+ */
22
+ export type LyraVirtualListRowProjection='shadow'|'light';
23
+ /**
24
+ * Reserved attribute marking a light-DOM row wrapper this component created in
25
+ * `row-projection="light"` mode, so consumer CSS, DOM diffing and snapshot tests can recognise a
26
+ * library-owned light-DOM node. `::part()` cannot address one -- a projected row is in the
27
+ * document's tree, not a shadow tree -- so this replaces `closest('[part="row"]')` for a delegated
28
+ * listener in that mode. Built through `tag()`, exactly like `ANNOUNCEMENT_SINK_ATTRIBUTE`.
29
+ */
30
+ export declare const VIRTUAL_LIST_ROW_ATTRIBUTE:string;
31
+ /** Reserved attribute marking the projected sticky-band wrapper. Same rationale as
32
+ * {@linkcode VIRTUAL_LIST_ROW_ATTRIBUTE}. */
33
+ export declare const VIRTUAL_LIST_STICKY_ATTRIBUTE:string;
12
34
  /** A fixed positive pixel height, or live per-row measurement. */
13
35
  export type LyraVirtualListRowHeight=number|'auto';type VirtualListKey=string|number;
14
36
  /** A random-access collection that does not have to materialize one JavaScript value per row. */
@@ -280,6 +302,12 @@ rowHeight:LyraVirtualListRowHeight;
280
302
  * `aria-rowindex` instead -- for a consumer composing a virtualized `role="table"` (see
281
303
  * `<lr-dataset-viewer>`). */
282
304
  itemRole:LyraVirtualListItemRole;
305
+ /** Where `renderItem`'s output is instantiated: `'shadow'` (the default) inside this component's
306
+ * shadow root, or `'light'` as a child of the host itself so ordinary document CSS reaches it.
307
+ * See the class doc's "Light-DOM row projection" section for the full contract. Unsupported
308
+ * attribute values and untyped property writes normalize back to `'shadow'`; the property is
309
+ * deliberately not reflected, matching `itemRole`. */
310
+ private _rowProjection;get rowProjection():LyraVirtualListRowProjection;set rowProjection(next:LyraVirtualListRowProjection);
283
311
  /** Added to a row's 1-based index to compute `aria-rowindex` in `item-role="row"` mode (e.g. `1`
284
312
  * when a consumer renders its own header row occupying `aria-rowindex="1"` outside this
285
313
  * component). No effect in `'listitem'` mode. */
@@ -367,6 +395,18 @@ get scrollContainer():HTMLElement|undefined;
367
395
  * update.
368
396
  */
369
397
  get renderedRows():HTMLElement[];
398
+ /**
399
+ * The projected light-DOM row wrappers (`[data-lr-virtual-list-row]`) that currently exist as
400
+ * direct children of this host, in item order — the `row-projection="light"` counterpart of
401
+ * {@linkcode renderedRows}, and always empty in the default `'shadow'` mode.
402
+ *
403
+ * Each one pairs 1:1 with the `[part="row"]` wrapper it is slotted into and mirrors that
404
+ * wrapper's `data-row-index`/`data-row-key`. Only direct children are considered, so a nested
405
+ * `<lr-virtual-list>` inside a projected row never contributes its own rows here. Treat the
406
+ * returned elements as read-only: their lifetime belongs to the windowing math, and any of them
407
+ * can be recycled or removed on the next update.
408
+ */
409
+ get projectedRows():HTMLElement[];
370
410
  /** The configured external scroller once it is usable, or `undefined` whenever this component
371
411
  * scrolls its own `[part="base"]` viewport. See `scrollElement` for why a non-`Element`,
372
412
  * non-`Window` assignment resolves to "no external scroller" instead of throwing. */
@@ -433,7 +473,29 @@ private offsetsDirty;
433
473
  * just `rowHeight`/`keyFunction`/a measurement) -- consumed by the next
434
474
  * `recomputeOffsets()` call to prune `measuredHeights` entries for keys
435
475
  * no longer present in `items`. */
436
- private itemsChangedPendingPrune;private renderStart;private renderEnd;private visibleStart;private visibleEnd;private lastEmittedStart;private lastEmittedEnd;
476
+ private itemsChangedPendingPrune;private renderStart;private renderEnd;
477
+ /** The window the most recent shadow `render()` emitted, with each row's identity already
478
+ * resolved. `row-projection="light"` renders the SAME array, keyed by the SAME identity, so the
479
+ * two sides can never disagree about which rows exist or what they are called. */
480
+ private renderedWindow;
481
+ /** Trailing comment bounding the light-DOM render part; also where lit-html caches that part. */
482
+ private projectionAnchor?;private projectionPart?;
483
+ /**
484
+ * True until the first render is safely past. A server render can never produce projected rows --
485
+ * `@lit-labs/ssr` calls `connectedCallback()`, `willUpdate()` and `render()`, never
486
+ * `update()`/`updated()`, and there is no DOM to render into -- so activating projection
487
+ * unconditionally would serialize this component's bounded deterministic first window EMPTY and
488
+ * make the browser's first render disagree with the markup it is hydrating.
489
+ *
490
+ * Released through `seedFirstRenderState()`, the same helper `renderUnmeasuredWindow` uses: a
491
+ * browser-only mount clears it synchronously inside `connectedCallback()` (so the very first
492
+ * render is already projected, with no flash and no extra update), while a hydrating mount keeps
493
+ * the server's shadow-rendered window for exactly its first render and swaps into the light DOM
494
+ * one task later.
495
+ */
496
+ private projectionDeferred;
497
+ /** Stable reference so `seedFirstRenderState()`'s pending set dedupes the re-arm below. */
498
+ private readonly releaseRowProjection;private visibleStart;private visibleEnd;private lastEmittedStart;private lastEmittedEnd;
437
499
  /** Re-armed whenever the window moves away from the end of `items` -- see the `lr-load-more` event doc. */
438
500
  private loadMoreArmed;
439
501
  /** Identity- and source-bound correction transaction for estimate-based programmatic scrolling. */
@@ -453,9 +515,18 @@ private viewportResizeTarget?;
453
515
  * frame below rather than once per native `scroll` event. */
454
516
  private externalMetricsPending;private ownerRealmGeneration;
455
517
  /** True for the remainder of the frame in which any of this component's `ResizeObserver`s
456
- * delivered -- so `syncRowObservers()` can tell that the re-render it is running inside is still
457
- * part of the browser's current resize-observation loop. See `beginResizeDelivery()`. */
518
+ * delivered -- so `syncRowObservers()` can tell that a re-render it is running inside is still
519
+ * part of the browser's current resize-observation loop, and the measurement callbacks can tell
520
+ * that folding a new height into the offsets would resize an observed box from inside one. See
521
+ * `beginResizeDelivery()`. */
458
522
  private inResizeDelivery;
523
+ /** Row heights observed during a delivery whose offsets rebuild waits for the frame flush, keyed
524
+ * by row identity exactly like `measuredHeights`. A raw observation, not yet a measurement: the
525
+ * 0.5px compare, the cache write, and the scroll anchoring all still happen in one place, in
526
+ * `applyPendingRowMeasurements()`. See `beginResizeDelivery()`. */
527
+ private readonly pendingRowMeasurements;
528
+ /** The same, for real group markers, keyed by `startIndex` like `measuredGroupHeights`. */
529
+ private readonly pendingGroupMeasurements;
459
530
  /** Rows that entered the window during such a re-render: already owned by `observedRows`, but not
460
531
  * yet handed to `rowResizeObserver`. Always a subset of `observedRows` -- `syncRowObservers()`
461
532
  * drops an entry here whenever it drops the same identity there. */
@@ -505,7 +576,16 @@ offsetForIndex(index:number):number;
505
576
  * Returns `-1` when the effective source is empty. Same `row-height="auto"` estimate caveat as
506
577
  * `offsetForIndex()`.
507
578
  */
508
- indexAtOffset(px:number):number;private computeRange;private attachContainerListeners;private detachContainerListeners;private onExternalViewportResize;private onUserScrollIntent;private onScroll;private onRowsResized;private onGroupsResized;
579
+ indexAtOffset(px:number):number;private computeRange;private attachContainerListeners;private detachContainerListeners;private onExternalViewportResize;private onUserScrollIntent;private onScroll;private onRowsResized;
580
+ /** Folds every stashed row observation into `measuredHeights`, anchoring and re-rendering once
581
+ * for the batch. Byte-for-byte the work `onRowsResized()` used to do inline. */
582
+ private applyPendingRowMeasurements;private onGroupsResized;
583
+ /** The group-marker half of `applyPendingRowMeasurements()`, on the same terms. */
584
+ private applyPendingGroupMeasurements;
585
+ /** True while folding a fresh measurement into the offsets would resize a box one of this
586
+ * component's own `ResizeObserver`s is watching, from inside that observer's own delivery.
587
+ * See `beginResizeDelivery()`. */
588
+ private get defersMeasurementApplication();
509
589
  /**
510
590
  * Marks the rest of this frame as "inside a resize-observation delivery", and schedules the
511
591
  * flush that ends it. Called from every one of this component's `ResizeObserver` callbacks,
@@ -513,19 +593,32 @@ indexAtOffset(px:number):number;private computeRange;private attachContainerList
513
593
  * `viewportHeight`, `stickyHeight`) and so can re-render the list -- and a re-render can move the
514
594
  * window.
515
595
  *
516
- * Re-rendering from inside a resize callback is inherent to `row-height="auto"` and is fine;
517
- * calling `observe()` from inside one is not. A brand-new observation is always active, and the
518
- * browser has already broadcast that DOM depth for this frame, so it is recorded as a *skipped*
519
- * observation and the loop ends by dispatching an uncaught `ErrorEvent` reading "ResizeObserver
520
- * loop completed with undelivered notifications". Nothing is actually wrong -- but the error is
521
- * uncaught, so it lands on whatever is running at the time, which is why it showed up as
522
- * unattributable flake in this component's *consumers* rather than here.
523
- *
524
- * Holding just those `observe()` calls until the next frame is the whole fix. The offsets
525
- * rebuild, the re-render, and the scroll-anchor correction all still happen synchronously, so
526
- * what gets painted is unchanged; only the moment the *newly windowed* rows start being measured
527
- * moves by a frame, during which they render at the same `DEFAULT_ROW_ESTIMATE_PX` they already
528
- * would have.
596
+ * Two things must not happen inside a delivery, and both end the same way. Calling `observe()`
597
+ * registers a brand-new observation, which is always active at a DOM depth the browser has
598
+ * already broadcast this frame. Changing the list's *extent* does the same from the other
599
+ * direction: `render()` writes it as `[part="spacer"]`'s block size, and under an external
600
+ * `scrollElement` `[part="base"][data-external-scroll]` takes its own block size from that spacer
601
+ * while `containerResizeObserver` watches it -- a box shallower in the tree than the rows just
602
+ * broadcast. Either way the observation is recorded as a *skipped* one, the loop ends, and an
603
+ * uncaught `ErrorEvent` reading "ResizeObserver loop completed with undelivered notifications" is
604
+ * dispatched. Nothing is actually wrong -- but the error is uncaught, so it lands on whatever is
605
+ * running at the time, which is why it showed up as unattributable flake in this component's
606
+ * *consumers* rather than here.
607
+ *
608
+ * So this frame carries the deferred `observe()` calls and the stashed measurements, and the
609
+ * measurement callbacks only *read* while the delivery is in flight. Renders are never held: an
610
+ * update that lands mid-delivery re-reads offsets nothing has changed, so it writes the extent
611
+ * already in the DOM, resizes no observed box, and cannot produce a skipped observation. That
612
+ * matters beyond this component -- holding a render would move this element's `updateComplete`
613
+ * out from under every parent composing it, which used to resolve in the same microtask run.
614
+ *
615
+ * Only the external-`scrollElement` case defers, because that is the only one where the extent
616
+ * write reaches an observed box; with this component's own viewport scrolling, `[part="base"]`
617
+ * takes its block size from `--lr-virtual-list-height` instead, so every measurement there stays
618
+ * exactly as immediate as it was. What a row whose measurement is waiting shows during that one
619
+ * frame is the same `DEFAULT_ROW_ESTIMATE_PX` geometry it already would have shown, and the
620
+ * scroll-anchor correction travels with the measurement that causes it, so no frame is ever
621
+ * painted with one applied and the other still pending.
529
622
  */
530
623
  private beginResizeDelivery;
531
624
  /** Keeps the row `ResizeObserver` watching exactly the currently-rendered
@@ -553,7 +646,50 @@ private get stickyInset();private scrollActiveIntoView;
553
646
  * and key function, and is canceled by replacement data, a new target, manual scroll intent, or
554
647
  * disconnect, so a late observation can never drag a newer view back to a stale row.
555
648
  */
556
- scrollToIndex(index:number,options?:{align?:'start'|'end'|'auto';behavior?:'auto'|'smooth';}):void;private hasUnmeasuredGroupThrough;private beginPendingScrollCorrection;private performScrollTo;private maybeCorrectPendingScroll;private emitRangeChangeIfNeeded;private maybeFireLoadMore;private renderRow;
649
+ scrollToIndex(index:number,options?:{align?:'start'|'end'|'auto';behavior?:'auto'|'smooth';}):void;private hasUnmeasuredGroupThrough;private beginPendingScrollCorrection;private performScrollTo;private maybeCorrectPendingScroll;private emitRangeChangeIfNeeded;private maybeFireLoadMore;
650
+ /** True whenever `renderItem`'s output belongs in the host's light DOM for THIS render. */
651
+ private get projectionActive();
652
+ /** The internal slot name pairing one shadow row wrapper with its projected light-DOM row.
653
+ * Keyed by the component's own row identity -- already the `repeat()` key on both sides -- so a
654
+ * scroll or a reorder moves rows without rewriting a single `slot`/`name` attribute. Slot
655
+ * matching is exact whole-value string comparison, so an identity containing a space or a colon
656
+ * still pairs correctly, and the name is never empty so it can never collide with a default
657
+ * slot (of which this component renders none). */
658
+ private rowSlotName;
659
+ /**
660
+ * Mounts, updates or tears down the light-DOM render root that holds `renderItem`'s output in
661
+ * `row-projection="light"` mode.
662
+ *
663
+ * The container is the HOST ITSELF — a slottable must be a direct child of the host — bounded by
664
+ * a trailing comment anchor, so the part only ever owns `[startMarker … anchor)`. Anything a
665
+ * consumer appends to this element later lands after the anchor and is never cleared by a
666
+ * re-render, which is also what keeps a server-rendered light child alive across hydration.
667
+ * `host: this` matches `ReactiveElement`'s own render options, so a `renderItem` template whose
668
+ * event binding is a method reference gets the same `this` it gets in shadow mode.
669
+ */
670
+ private syncRowProjection;private ensureProjectionAnchor;
671
+ /**
672
+ * Removes the projection completely, using public API only: `render(nothing, …)` so lit-html
673
+ * detaches its own child parts and their directives, then the part's start marker, then the
674
+ * anchor. Discarding the anchor discards lit's cached root part with it (the cache lives on the
675
+ * `renderBefore` node), so no private-field poking is ever required and a later re-projection
676
+ * starts from a genuinely fresh part.
677
+ *
678
+ * After this the host's light DOM holds exactly what the consumer put there: no rows, no lit
679
+ * markers, no anchor. The accepted cost is that per-row DOM state inside a projected row does not
680
+ * survive a disconnect/reconnect; scroll position, measurements and the window are unaffected,
681
+ * because they live in component state rather than in the rows.
682
+ */
683
+ private teardownRowProjection;
684
+ /**
685
+ * One light-DOM wrapper per windowed row, over the same array and keyed by the same identity the
686
+ * shadow window used. The wrapper carries no `part` (a `part` attribute outside a shadow tree is
687
+ * inert), no `role` and no inline positioning — the `[part="row"]` wrapper it is slotted into
688
+ * keeps sole ownership of absolute positioning, the per-frame transform and every ARIA
689
+ * attribute, so consumer CSS cannot break windowing. `data-row-index`/`data-row-key` are mirrored
690
+ * so document CSS and delegated listeners can still address a specific row.
691
+ */
692
+ private renderProjectedRows;private renderRow;
557
693
  /** Normalizes group definitions only when their inputs change. */
558
694
  private recomputeGroups;private renderGroups;
559
695
  /** The group the viewport is currently inside -- the last one whose first row's offset is at or
@@ -1,4 +1,9 @@
1
- var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r};import{html,nothing}from"lit";import{property,state}from"lit/decorators.js";import{repeat}from"lit/directives/repeat.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{prefersReducedMotion}from"../../../internal/motion.js";import{finiteAdd,finiteCount,finiteInteger,finiteNumber}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{getOwnDataDescriptor,MISSING_OWN_DATA_DESCRIPTOR,UNSAFE_OWN_DATA_DESCRIPTOR}from"../../../internal/data-descriptors.js";import{styles}from"./virtual-list.styles.js";const DEFAULT_ROW_ESTIMATE_PX=48,DEFAULT_GROUP_ESTIMATE_PX=32,DEFAULT_OVERSCAN_ROWS=6,MAX_OVERSCAN_ROWS=100,MAX_VIRTUAL_LIST_GROUPS=1e4,EMPTY_VIRTUAL_LIST_GROUPS=Object.freeze([]);function normalizeOverscan(value){if(value===null)return DEFAULT_OVERSCAN_ROWS;const numeric=typeof value=="number"?value:Number(value);return Number.isFinite(numeric)?Math.min(MAX_OVERSCAN_ROWS,Math.max(0,Math.floor(numeric))):DEFAULT_OVERSCAN_ROWS}const overscanConverter={fromAttribute(value){return normalizeOverscan(value)}};function virtualListGroupsChanged(value,oldValue){if(value===oldValue)return!1;const next=value,previous=oldValue;if(next==null||previous==null)return next!==previous;if(next.length!==previous.length)return!0;for(let index=0;index<next.length;index+=1){const a=next[index],b=previous[index];if(a.key!==b.key||a.label!==b.label||a.startIndex!==b.startIndex)return!0}return!1}function normalizeRowHeight(value){if(value==="auto")return"auto";const numeric=typeof value=="number"?value:Number(value);return Number.isFinite(numeric)&&numeric>0?numeric:"auto"}const rowHeightConverter={fromAttribute(value){return value===null?"auto":normalizeRowHeight(value)}};function isIndexedSource(source){return!Array.isArray(source)}const ELEMENT_NODE_TYPE=1;function isWindowScroller(target){return target.window===target}function domKeyToken(key){if(typeof key=="number"){if(Number.isNaN(key))return"number:NaN";if(Object.is(key,-0))return"number:-0"}return`${typeof key}:${String(key)}`}class LyraVirtualList extends LyraElement{constructor(){super(...arguments),this.items=[],this.renderItem=()=>nothing,this.rowHeight="auto",this.itemRole="listitem",this.rowIndexOffset=0,this.overscan=DEFAULT_OVERSCAN_ROWS,this.activeItemId="",this.loading=!1,this.hasMore=!1,this.containerScrollTop=0,this.viewportHeight=0,this.renderUnmeasuredWindow=!0,this.offsets=[0],this.rowIdentities=[],this.fixedRowHeight=null,this.measuredHeights=new Map,this.measuredIndices=new Map,this.indexedMeasurementIndices=[],this.indexedMeasurementDeltaPrefix=[0],this.indexedMeasurementIndexDirty=!0,this.offsetsDirty=!0,this.itemsChangedPendingPrune=!1,this.renderStart=0,this.renderEnd=-1,this.visibleStart=0,this.visibleEnd=-1,this.lastEmittedStart=-1,this.lastEmittedEnd=-1,this.loadMoreArmed=!0,this.measurementGeneration=0,this.isFirstUpdate=!0,this.stickyHeight=0,this.observedRows=new Map,this.observedRowKeys=new WeakMap,this.observedRowIndices=new WeakMap,this.observedGroups=new Map,this.observedGroupIndices=new WeakMap,this.externalMetricsPending=!1,this.ownerRealmGeneration=0,this.inResizeDelivery=!1,this.deferredRowObservations=new Map,this.deferredGroupObservations=new Map,this.activeIndexForLength=-1,this.activeIndexForId="",this.activeIndexCache=-1,this.pendingScrollTop=null,this.normalizedGroups=EMPTY_VIRTUAL_LIST_GROUPS,this.normalizedGroupByIndex=new Map,this.measuredGroupHeights=new Map,this.groupHeightPrefix=[0],this.onExternalViewportResize=()=>{this.syncExternalScrollMetrics()},this.onUserScrollIntent=event=>{event instanceof KeyboardEvent&&!new Set(["ArrowUp","ArrowDown","PageUp","PageDown","Home","End"," "]).has(event.key)||(this.pendingScrollCorrection=void 0)},this.onScroll=e=>{if(this.externalScroller?(this.pendingScrollTop=null,this.externalMetricsPending=!0):this.pendingScrollTop=e.currentTarget.scrollTop,this.scrollRafId!==void 0)return;const ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView;if(!ownerWindow||!this.isConnected)return;const generation=this.ownerRealmGeneration,handle=ownerWindow.requestAnimationFrame(()=>{if(!(this.scrollRafId!==handle||this.scrollRafOwner!==ownerWindow||this.scrollRafDocument!==ownerDocument||!this.isCurrentOwnerWork(ownerDocument,generation))){if(this.scrollRafId=void 0,this.scrollRafOwner=void 0,this.scrollRafDocument=void 0,this.externalMetricsPending){this.externalMetricsPending=!1;const metrics=this.readScrollMetrics();metrics&&(this.pendingScrollTop=metrics.scrollTop,this.viewportHeight!==metrics.viewportHeight&&(this.viewportHeight=metrics.viewportHeight))}if(this.pendingScrollTop!==null){const scrollTop=this.pendingScrollTop;this.pendingScrollTop=null;const moved=this.containerScrollTop!==scrollTop;this.containerScrollTop=scrollTop,moved&&this.emit("lr-virtual-scroll",{scrollTop,viewportHeight:this.viewportHeight})}}});this.scrollRafId=handle,this.scrollRafOwner=ownerWindow,this.scrollRafDocument=ownerDocument},this.onRowsResized=entries=>{if(this.beginResizeDelivery(),this.fixedRowHeight!=null)return;const base=this.scrollContainer,oldScrollTop=this.readScrollMetrics()?.rawScrollTop??this.containerScrollTop;let scrollAdjustment=0,changed=!1;for(const entry of entries){const row=entry.target,key=this.observedRowKeys.get(row),index=this.observedRowIndices.get(row);if(key===void 0||index===void 0)continue;const height=entry.borderBoxSize?.[0]?.blockSize??entry.target.getBoundingClientRect().height,prev=this.measuredHeights.get(key);if(prev===void 0||Math.abs(prev-height)>.5){const oldBottom=this.rowBottomAt(index);this.measuredHeights.set(key,height),this.measuredIndices.set(key,index);const oldHeight=prev??DEFAULT_ROW_ESTIMATE_PX;oldBottom<=oldScrollTop&&(scrollAdjustment+=height-oldHeight),changed=!0}}if(changed){if(this.indexedMeasurementIndexDirty=!0,base&&scrollAdjustment!==0){const nextScrollTop=oldScrollTop+scrollAdjustment;this.applyScrollPosition(nextScrollTop),this.containerScrollTop=Math.max(0,nextScrollTop),this.pendingScrollTop=null}this.offsetsDirty=!0,this.measurementGeneration+=1,this.requestUpdate()}},this.onGroupsResized=entries=>{this.beginResizeDelivery();const base=this.scrollContainer,oldScrollTop=this.readScrollMetrics()?.rawScrollTop??this.containerScrollTop;let scrollAdjustment=0,changed=!1;for(const entry of entries){const marker=entry.target,index=this.observedGroupIndices.get(marker);if(index===void 0||!this.normalizedGroupByIndex.has(index))continue;const height=entry.borderBoxSize?.[0]?.blockSize??entry.target.getBoundingClientRect().height;if(!Number.isFinite(height)||height<0)continue;const previous=this.measuredGroupHeights.get(index)??DEFAULT_GROUP_ESTIMATE_PX;if(Math.abs(previous-height)<=.5)continue;const oldRowTop=this.offsetAt(index);this.measuredGroupHeights.set(index,height),oldRowTop<=oldScrollTop&&(scrollAdjustment+=height-previous),changed=!0}if(changed){if(base&&scrollAdjustment!==0){const nextScrollTop=oldScrollTop+scrollAdjustment;this.applyScrollPosition(nextScrollTop),this.containerScrollTop=Math.max(0,nextScrollTop),this.pendingScrollTop=null}this.offsetsDirty=!0,this.measurementGeneration+=1,this.requestUpdate()}},this.onStickyResized=entries=>{this.beginResizeDelivery();const entry=entries[0];if(!entry)return;const height=entry.borderBoxSize?.[0]?.blockSize??entry.contentRect.height;Math.abs(this.stickyHeight-height)>.5&&(this.stickyHeight=height)}}static{this.ownedCollectionProperties=Object.freeze(["items","source","groups"])}static{this.identityCollectionProperties=Object.freeze(["items","source"])}static{this.identityCollectionObjectProperties=Object.freeze(["source"])}static{this.styles=[LyraElement.styles,styles]}get scrollContainer(){return this.renderRoot?.querySelector('[part="base"]')??void 0}get renderedRows(){const root=this.renderRoot;return root?[...root.querySelectorAll('[part="row"]')]:[]}get externalScroller(){const target=this.scrollElement;if(target!=null)return isWindowScroller(target)||target.nodeType===ELEMENT_NODE_TYPE?target:void 0}get spacerElement(){return this.renderRoot?.querySelector('[part="spacer"]')??void 0}readScrollMetrics(){const base=this.scrollContainer;if(!base)return null;const external=this.externalScroller;if(!external)return{scrollTop:base.scrollTop,rawScrollTop:base.scrollTop,viewportHeight:base.clientHeight};const spacerTop=(this.spacerElement??base).getBoundingClientRect().top;if(isWindowScroller(external)){const documentHeight=finiteNumber(external.document?.documentElement?.clientHeight??0,0),rawScrollTop2=finiteNumber(-spacerTop,0);return{scrollTop:Math.max(0,rawScrollTop2),rawScrollTop:rawScrollTop2,viewportHeight:documentHeight>0?documentHeight:finiteNumber(external.innerHeight,0)}}const scrollerTop=external.getBoundingClientRect().top,rawScrollTop=finiteNumber(scrollerTop-spacerTop,0);return{scrollTop:Math.max(0,rawScrollTop),rawScrollTop,viewportHeight:finiteNumber(external.clientHeight,0)}}applyScrollPosition(top,behavior){const external=this.externalScroller;if(!external){const base=this.scrollContainer;if(!base)return;const next2=Math.max(0,finiteNumber(top,0));behavior===void 0?base.scrollTop=next2:base.scrollTo({top:next2,behavior});return}const metrics=this.readScrollMetrics();if(!metrics)return;const delta=finiteNumber(top,metrics.rawScrollTop)-metrics.rawScrollTop;if(isWindowScroller(external)){const options={top:Math.max(0,finiteNumber(external.scrollY+delta,0))};behavior!==void 0&&(options.behavior=behavior),external.scrollTo(options);return}const next=Math.max(0,finiteNumber(external.scrollTop+delta,0));behavior===void 0?external.scrollTop=next:external.scrollTo({top:next,behavior})}syncExternalScrollMetrics(){const metrics=this.readScrollMetrics();metrics&&(this.viewportHeight!==metrics.viewportHeight&&(this.viewportHeight=metrics.viewportHeight),this.containerScrollTop!==metrics.scrollTop&&(this.containerScrollTop=metrics.scrollTop))}get safeRowIndexOffset(){return finiteCount(this.rowIndexOffset)}computedAriaRowIndex(index){return finiteInteger(finiteAdd(index+1,this.safeRowIndexOffset),1,1,Number.MAX_SAFE_INTEGER)}get activeIndex(){if(this.activeItemId==="")return-1;const source=this.effectiveSource,count=this.itemCount;if(this.activeIndexFor===source&&this.activeIndexForLength===count&&Object.is(this.activeIndexForId,this.activeItemId)&&this.activeIndexForKeyFn===this.keyFunction)return this.activeIndexCache;if(this.activeIndexFor=source,this.activeIndexForLength=count,this.activeIndexForId=this.activeItemId,this.activeIndexForKeyFn=this.keyFunction,this.activeIndexCache=-1,isIndexedSource(source)){if(!this.keyFunction&&source.indexOfKey){const candidate=source.indexOfKey(this.activeItemId);Number.isInteger(candidate)&&candidate>=0&&candidate<count&&(this.activeIndexCache=candidate)}return this.activeIndexCache}for(let index=0;index<count;index++){const item=this.itemAt(index);if(Object.is(this.keyOf(item,index),this.activeItemId)){this.activeIndexCache=index;break}}return this.activeIndexCache}connectedCallback(){super.connectedCallback(),this.ownerDocument.defaultView&&this.seedFirstRenderState(()=>{this.renderUnmeasuredWindow=!1,this.requestUpdate()}),this.resetOwnerRealmWork();const ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView,generation=this.ownerRealmGeneration,ResizeObserverCtor=ownerWindow?.ResizeObserver;if(ResizeObserverCtor){const rowObserver=new ResizeObserverCtor(entries=>{this.rowResizeObserver!==rowObserver||!this.isCurrentOwnerWork(ownerDocument,generation)||this.onRowsResized(entries)}),groupObserver=new ResizeObserverCtor(entries=>{this.groupResizeObserver!==groupObserver||!this.isCurrentOwnerWork(ownerDocument,generation)||this.onGroupsResized(entries)}),stickyObserver=new ResizeObserverCtor(entries=>{this.stickyResizeObserver!==stickyObserver||!this.isCurrentOwnerWork(ownerDocument,generation)||this.onStickyResized(entries)});this.rowResizeObserver=rowObserver,this.groupResizeObserver=groupObserver,this.stickyResizeObserver=stickyObserver}this.hasUpdated&&(this.attachContainerListeners(),this.syncRowObservers(),this.syncGroupObservers(),this.syncStickyOverlay())}disconnectedCallback(){this.resetOwnerRealmWork(),super.disconnectedCallback()}adoptedCallback(){super.adoptedCallback(),this.resetOwnerRealmWork()}isCurrentOwnerWork(ownerDocument,generation){return this.ownerRealmGeneration===generation&&this.isConnected&&this.ownerDocument===ownerDocument}resetOwnerRealmWork(){this.ownerRealmGeneration+=1,this.rowResizeObserver?.disconnect(),this.rowResizeObserver=void 0,this.groupResizeObserver?.disconnect(),this.groupResizeObserver=void 0,this.observedRows.clear(),this.observedGroups.clear(),this.deferredRowObservations.clear(),this.deferredGroupObservations.clear(),this.inResizeDelivery=!1,this.rowObserveRafId!==void 0&&this.rowObserveRafOwner?.cancelAnimationFrame(this.rowObserveRafId),this.rowObserveRafId=void 0,this.rowObserveRafOwner=void 0,this.rowObserveRafDocument=void 0,this.containerResizeObserver?.disconnect(),this.containerResizeObserver=void 0,this.stickyResizeObserver?.disconnect(),this.stickyResizeObserver=void 0,this.observedSticky=void 0,this.scrollRafId!==void 0&&this.scrollRafOwner?.cancelAnimationFrame(this.scrollRafId),this.scrollRafId=void 0,this.scrollRafOwner=void 0,this.scrollRafDocument=void 0,this.pendingScrollTop=null,this.externalMetricsPending=!1,this.pendingScrollCorrection=void 0,this.detachContainerListeners(),this.scrollListenerTarget=void 0}firstUpdated(changed){super.firstUpdated(changed),this.attachContainerListeners()}willUpdate(changed){super.willUpdate(changed),this.isFirstUpdate=!this.hasUpdated,(changed.has("items")||changed.has("source")||changed.has("keyFunction")||changed.has("rowHeight")||changed.has("groups")||changed.has("activeItemId")||changed.has("scrollElement"))&&(this.pendingScrollCorrection=void 0),(changed.has("items")||changed.has("source")||changed.has("rowHeight")||changed.has("keyFunction")||changed.has("groups"))&&(this.offsetsDirty=!0),(changed.has("items")||changed.has("source"))&&(this.itemsChangedPendingPrune=!0),(changed.has("keyFunction")||isIndexedSource(this.effectiveSource)&&(changed.has("items")||changed.has("source")))&&(this.measuredHeights.clear(),this.measuredIndices.clear(),this.indexedMeasurementIndexDirty=!0),changed.has("groups")&&this.measuredGroupHeights.clear(),(changed.has("items")||changed.has("source")||changed.has("groups"))&&this.recomputeGroups(),changed.has("rowHeight")&&(this.fixedRowHeight=this.parseRowHeight(this.rowHeight),this.fixedRowHeight!=null&&(this.measuredHeights.clear(),this.measuredIndices.clear(),this.indexedMeasurementIndexDirty=!0)),this.offsetsDirty&&(this.recomputeOffsets(),this.offsetsDirty=!1),this.computeRange()}updated(changed){super.updated(changed),this.syncRowObservers(),this.syncGroupObservers(),this.syncStickyOverlay(),changed.has("scrollElement")&&!this.isFirstUpdate&&this.attachContainerListeners(),changed.has("activeItemId")&&!this.isFirstUpdate&&this.scrollActiveIntoView(),this.emitRangeChangeIfNeeded(),this.maybeFireLoadMore(),this.maybeCorrectPendingScroll()}parseRowHeight(value){const normalized=normalizeRowHeight(value);return normalized==="auto"?null:normalized}get effectiveSource(){return this.source??this.items}get itemCount(){const source=this.effectiveSource;return isIndexedSource(source)?finiteCount(source.count):source.length}itemAt(index){const source=this.effectiveSource;return isIndexedSource(source)?source.itemAt(index):source[index]}keyOf(item,index){const source=this.effectiveSource,key=this.keyFunction?this.keyFunction(item,index):isIndexedSource(source)?source.keyAt?.(index)??index:index;return typeof key=="string"||typeof key=="number"?key:index}rowIdentity(key,occurrence){const token=domKeyToken(key);return`${token.length}:${token}:${occurrence}`}identityAt(index,item=this.itemAt(index)){return isIndexedSource(this.effectiveSource)?this.rowIdentity(this.keyOf(item,index),index):this.rowIdentities[index]??this.rowIdentity(this.keyOf(item,index),index)}groupHeightAt(index){const group=this.normalizedGroupByIndex.get(index);return!group||group.label===""?0:this.measuredGroupHeights.get(index)??DEFAULT_GROUP_ESTIMATE_PX}rowHeightAt(index){return this.fixedRowHeight!=null?this.fixedRowHeight:this.measuredHeights.get(this.identityAt(index))??DEFAULT_ROW_ESTIMATE_PX}groupContributionThrough(index){let low=0,high=this.normalizedGroups.length;for(;low<high;){const middle=low+high>>1;this.normalizedGroups[middle].startIndex<=index?low=middle+1:high=middle}return this.groupHeightPrefix[low]??0}recomputeGroupHeightPrefix(){const prefix=new Array(this.normalizedGroups.length+1);prefix[0]=0;for(let index=0;index<this.normalizedGroups.length;index++){const group=this.normalizedGroups[index],height=group.label===""?0:this.measuredGroupHeights.get(group.startIndex)??DEFAULT_GROUP_ESTIMATE_PX;prefix[index+1]=finiteAdd(prefix[index],height)}this.groupHeightPrefix=prefix}indexedOffsetForIndex(index){const baseHeight=this.fixedRowHeight??DEFAULT_ROW_ESTIMATE_PX;let offset=index>Number.MAX_VALUE/baseHeight?Number.MAX_VALUE:index*baseHeight;if(this.fixedRowHeight==null){this.rebuildIndexedMeasurementIndex();let low=0,high=this.indexedMeasurementIndices.length;for(;low<high;){const middle=low+high>>1;this.indexedMeasurementIndices[middle]<index?low=middle+1:high=middle}offset=finiteAdd(offset,this.indexedMeasurementDeltaPrefix[low]??0)}return Math.max(0,finiteAdd(offset,this.groupContributionThrough(index)))}rebuildIndexedMeasurementIndex(){if(!this.indexedMeasurementIndexDirty)return;const retained=[];for(const[identity,index]of this.measuredIndices){const height=this.measuredHeights.get(identity);height!==void 0&&retained.push({index,delta:height-DEFAULT_ROW_ESTIMATE_PX})}retained.sort((a,b)=>a.index-b.index);const indices=new Array(retained.length),prefix=new Array(retained.length+1);prefix[0]=0;for(let position=0;position<retained.length;position++){const measurement=retained[position];indices[position]=measurement.index,prefix[position+1]=finiteAdd(prefix[position],measurement.delta)}this.indexedMeasurementIndices=indices,this.indexedMeasurementDeltaPrefix=prefix,this.indexedMeasurementIndexDirty=!1}pruneIndexedMeasurements(){if(!isIndexedSource(this.effectiveSource)||this.fixedRowHeight!=null||this.renderEnd<this.renderStart)return!1;const renderedCount=this.renderEnd-this.renderStart+1,retentionRows=Math.max(renderedCount,normalizeOverscan(this.overscan)*4),firstRetained=Math.max(0,this.renderStart-retentionRows),lastRetained=Math.min(this.itemCount-1,this.renderEnd+retentionRows);let removedDeltaBeforeWindow=0,pruned=!1;for(const[identity,measuredIndex]of this.measuredIndices)if(measuredIndex<firstRetained||measuredIndex>lastRetained){const height=this.measuredHeights.get(identity);height!==void 0&&measuredIndex<firstRetained&&(removedDeltaBeforeWindow=finiteAdd(removedDeltaBeforeWindow,height-DEFAULT_ROW_ESTIMATE_PX)),this.measuredIndices.delete(identity),this.measuredHeights.delete(identity),pruned=!0}if(pruned&&(this.indexedMeasurementIndexDirty=!0,removedDeltaBeforeWindow!==0)){const nextScrollTop=(this.readScrollMetrics()?.rawScrollTop??this.containerScrollTop)-removedDeltaBeforeWindow;this.applyScrollPosition(nextScrollTop),this.containerScrollTop=Math.max(0,nextScrollTop),this.pendingScrollTop=null}return pruned}offsetAt(index){return isIndexedSource(this.effectiveSource)?this.indexedOffsetForIndex(index):this.offsets[index]??0}recomputeOffsets(){const n=this.itemCount;if(this.recomputeGroupHeightPrefix(),isIndexedSource(this.effectiveSource)){this.offsets=[0],this.rowIdentities=[],this.itemsChangedPendingPrune=!1;return}const offsets=new Array(n+1);let cursor=0;const liveKeys=this.itemsChangedPendingPrune&&this.fixedRowHeight==null?new Set:null,occurrences=new Map,identities=new Array(n);for(let i=0;i<n;i++){cursor=finiteAdd(cursor,this.groupHeightAt(i)),offsets[i]=cursor;const key=this.keyOf(this.itemAt(i),i),token=domKeyToken(key),occurrence=occurrences.get(token)??0;occurrences.set(token,occurrence+1);const identity=this.rowIdentity(key,occurrence);identities[i]=identity;let h;this.fixedRowHeight!=null?h=this.fixedRowHeight:(liveKeys?.add(identity),h=this.measuredHeights.get(identity)??DEFAULT_ROW_ESTIMATE_PX),cursor=finiteAdd(cursor,h)}if(offsets[n]=cursor,this.offsets=offsets,this.rowIdentities=identities,this.itemsChangedPendingPrune=!1,liveKeys){for(const key of this.measuredHeights.keys())liveKeys.has(key)||(this.measuredHeights.delete(key),this.measuredIndices.delete(key),this.indexedMeasurementIndexDirty=!0);for(const key of this.measuredIndices.keys())liveKeys.has(key)||(this.measuredIndices.delete(key),this.indexedMeasurementIndexDirty=!0)}}groupTopAt(index){return Math.max(0,this.offsetAt(index)-this.groupHeightAt(index))}rowBottomAt(index){return finiteAdd(this.offsetAt(index),this.rowHeightAt(index))}entryTopAt(index){return this.groupTopAt(index)}findIndexAtOrAfter(offset){let lo=0,hi=this.itemCount-1;for(;lo<hi;){const mid=lo+Math.floor((hi-lo)/2);this.rowBottomAt(mid)<=offset?lo=mid+1:hi=mid}return lo}findIndexAtOrBefore(offset){let lo=0,hi=this.itemCount-1;for(;lo<hi;){const mid=lo+Math.ceil((hi-lo)/2);this.entryTopAt(mid)<offset?lo=mid:hi=mid-1}return lo}offsetForIndex(index){const clamped=Math.min(this.itemCount,Math.max(0,Math.trunc(index)||0));return this.offsetAt(clamped)}indexAtOffset(px){const n=this.itemCount;return n===0?-1:Number.isFinite(px)?Math.min(n-1,Math.max(0,this.findIndexAtOrAfter(px))):px>0?n-1:0}computeRange(){const n=this.itemCount;if(n===0){this.visibleStart=0,this.visibleEnd=-1,this.renderStart=0,this.renderEnd=-1;return}if(this.viewportHeight<=0){if(!this.renderUnmeasuredWindow){this.visibleStart=0,this.visibleEnd=-1,this.renderStart=0,this.renderEnd=-1;return}this.visibleStart=0,this.visibleEnd=0,this.renderStart=0,this.renderEnd=Math.min(n-1,normalizeOverscan(this.overscan));return}const viewTop=this.containerScrollTop,viewBottom=viewTop+this.viewportHeight;this.visibleStart=this.findIndexAtOrAfter(viewTop),this.visibleEnd=this.findIndexAtOrBefore(viewBottom);const overscan=normalizeOverscan(this.overscan);this.renderStart=Math.max(0,this.visibleStart-overscan),this.renderEnd=Math.min(n-1,this.visibleEnd+overscan),this.pruneIndexedMeasurements()&&this.computeRange()}attachContainerListeners(){const base=this.scrollContainer,ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView;if(!base||!this.isConnected||!ownerWindow)return;this.containerResizeObserver?.disconnect(),this.containerResizeObserver=void 0,this.detachContainerListeners();const external=this.externalScroller,scrollTarget=external??base,generation=this.ownerRealmGeneration,ResizeObserverCtor=ownerWindow.ResizeObserver;if(ResizeObserverCtor){const observer=new ResizeObserverCtor(entries=>{if(this.containerResizeObserver!==observer||this.scrollListenerTarget!==scrollTarget||!this.isCurrentOwnerWork(ownerDocument,generation))return;if(this.beginResizeDelivery(),external){this.syncExternalScrollMetrics();return}const entry=entries[0];entry&&(this.viewportHeight=entry.borderBoxSize?.[0]?.blockSize??entry.contentRect.height)});this.containerResizeObserver=observer,observer.observe(base),external&&!isWindowScroller(external)&&observer.observe(external)}scrollTarget.addEventListener("scroll",this.onScroll,{passive:!0}),scrollTarget.addEventListener("wheel",this.onUserScrollIntent,{passive:!0}),scrollTarget.addEventListener("pointerdown",this.onUserScrollIntent,{passive:!0}),scrollTarget.addEventListener("touchstart",this.onUserScrollIntent,{passive:!0}),scrollTarget.addEventListener("keydown",this.onUserScrollIntent),this.scrollListenerTarget=scrollTarget,external&&isWindowScroller(external)&&(external.addEventListener("resize",this.onExternalViewportResize,{passive:!0}),this.viewportResizeTarget=external),ownerWindow.queueMicrotask(()=>{if(this.scrollListenerTarget!==scrollTarget||this.scrollContainer!==base||!this.isCurrentOwnerWork(ownerDocument,generation))return;const metrics=this.readScrollMetrics();metrics&&(this.viewportHeight!==metrics.viewportHeight&&(this.viewportHeight=metrics.viewportHeight),this.containerScrollTop!==metrics.scrollTop&&(this.containerScrollTop=metrics.scrollTop))})}detachContainerListeners(){const viewportTarget=this.viewportResizeTarget;viewportTarget&&(viewportTarget.removeEventListener("resize",this.onExternalViewportResize),this.viewportResizeTarget=void 0);const target=this.scrollListenerTarget;target&&(target.removeEventListener("scroll",this.onScroll),target.removeEventListener("wheel",this.onUserScrollIntent),target.removeEventListener("pointerdown",this.onUserScrollIntent),target.removeEventListener("touchstart",this.onUserScrollIntent),target.removeEventListener("keydown",this.onUserScrollIntent))}beginResizeDelivery(){if(this.inResizeDelivery=!0,this.rowObserveRafId!==void 0)return;const ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView;if(!ownerWindow||!this.isConnected){this.inResizeDelivery=!1;return}const generation=this.ownerRealmGeneration,handle=ownerWindow.requestAnimationFrame(()=>{if(this.rowObserveRafId!==handle||this.rowObserveRafOwner!==ownerWindow||this.rowObserveRafDocument!==ownerDocument||!this.isCurrentOwnerWork(ownerDocument,generation))return;this.rowObserveRafId=void 0,this.rowObserveRafOwner=void 0,this.rowObserveRafDocument=void 0,this.inResizeDelivery=!1;const ro=this.rowResizeObserver;for(const[identity,el]of this.deferredRowObservations)ro&&this.observedRows.get(identity)===el&&ro.observe(el);this.deferredRowObservations.clear();const groupObserver=this.groupResizeObserver;for(const[index,el]of this.deferredGroupObservations)groupObserver&&this.observedGroups.get(index)===el&&groupObserver.observe(el);this.deferredGroupObservations.clear()});this.rowObserveRafId=handle,this.rowObserveRafOwner=ownerWindow,this.rowObserveRafDocument=ownerDocument}syncRowObservers(){const ro=this.rowResizeObserver;if(!ro)return;if(this.fixedRowHeight!=null){for(const el of this.observedRows.values())ro.unobserve(el);this.observedRows.clear(),this.deferredRowObservations.clear();return}const current=new Map;this.renderRoot.querySelectorAll('[part="row"]').forEach(el=>{const index=Number(el.getAttribute("data-row-index"));if(!Number.isInteger(index)||index<0||index>=this.itemCount)return;const identity=this.identityAt(index);current.set(identity,el),this.observedRowKeys.set(el,identity),this.observedRowIndices.set(el,index)});for(const[identity,el]of this.observedRows)current.get(identity)!==el&&(ro.unobserve(el),this.observedRows.delete(identity),this.deferredRowObservations.delete(identity));for(const[identity,el]of current)this.observedRows.has(identity)||(this.observedRows.set(identity,el),this.inResizeDelivery?this.deferredRowObservations.set(identity,el):ro.observe(el))}syncGroupObservers(){const observer=this.groupResizeObserver;if(!observer)return;const current=new Map;this.renderRoot.querySelectorAll('[part="group"][data-group-index]').forEach(marker=>{const index=Number(marker.dataset.groupIndex);!Number.isInteger(index)||!this.normalizedGroupByIndex.has(index)||(current.set(index,marker),this.observedGroupIndices.set(marker,index))});for(const[index,marker]of this.observedGroups)current.get(index)!==marker&&(observer.unobserve(marker),this.observedGroups.delete(index),this.deferredGroupObservations.delete(index));for(const[index,marker]of current)this.observedGroups.has(index)||(this.observedGroups.set(index,marker),this.inResizeDelivery?this.deferredGroupObservations.set(index,marker):observer.observe(marker))}get stickyInset(){return this.renderStickyGroup?this.stickyHeight:0}scrollActiveIntoView(){const index=this.activeIndex;if(index<0)return;const behavior=prefersReducedMotion(this.ownerDocument.defaultView)?"auto":"smooth";this.performScrollTo(index,"auto",behavior)&&this.beginPendingScrollCorrection(index,"auto",behavior,this.activeItemId)}scrollToIndex(index,options){const n=this.itemCount;if(n===0)return;const clamped=finiteInteger(index,0,0,n-1),align=options?.align??"auto",behavior=prefersReducedMotion(this.ownerDocument.defaultView)?"auto":options?.behavior??"smooth";this.performScrollTo(clamped,align,behavior)?this.beginPendingScrollCorrection(clamped,align,behavior):this.pendingScrollCorrection=void 0}hasUnmeasuredGroupThrough(index){return this.normalizedGroups.some(group=>group.startIndex<=index&&group.label!==""&&!this.measuredGroupHeights.has(group.startIndex))}beginPendingScrollCorrection(index,align,behavior,activeItemId){if(this.fixedRowHeight!=null&&!this.hasUnmeasuredGroupThrough(index)){this.pendingScrollCorrection=void 0;return}this.pendingScrollCorrection={identity:this.identityAt(index),index,align,behavior,source:this.effectiveSource,keyFunction:this.keyFunction,activeItemId:activeItemId===""?void 0:activeItemId,lastMeasurementGeneration:this.measurementGeneration}}performScrollTo(index,align,behavior){const metrics=this.readScrollMetrics();if(!metrics)return!1;const inset=this.stickyInset,top=this.offsetAt(index),bottom=this.rowBottomAt(index),viewTop=metrics.rawScrollTop,viewBottom=viewTop+metrics.viewportHeight;let target=null;return align==="start"?target=top-inset:align==="end"?target=bottom-metrics.viewportHeight:top-inset<viewTop?target=top-inset:bottom>viewBottom&&(target=bottom-metrics.viewportHeight),target===null?!1:(this.applyScrollPosition(target,behavior),!0)}maybeCorrectPendingScroll(){const pending=this.pendingScrollCorrection;if(!pending||pending.lastMeasurementGeneration>=this.measurementGeneration)return;if(pending.source!==this.effectiveSource||pending.keyFunction!==this.keyFunction||pending.activeItemId!==void 0&&!Object.is(pending.activeItemId,this.activeItemId)){this.pendingScrollCorrection=void 0;return}const index=pending.activeItemId!==void 0?this.activeIndex:isIndexedSource(this.effectiveSource)?pending.index:this.rowIdentities.indexOf(pending.identity);if(index<0||index>=this.itemCount||this.identityAt(index)!==pending.identity){this.pendingScrollCorrection=void 0;return}this.performScrollTo(index,pending.align,pending.behavior),pending.index=index,pending.lastMeasurementGeneration=this.measurementGeneration,(this.fixedRowHeight!=null||this.measuredHeights.has(pending.identity))&&!this.hasUnmeasuredGroupThrough(index)&&(this.pendingScrollCorrection=void 0)}emitRangeChangeIfNeeded(){if(this.visibleEnd<this.visibleStart){this.lastEmittedStart=-1,this.lastEmittedEnd=-1;return}this.visibleStart===this.lastEmittedStart&&this.visibleEnd===this.lastEmittedEnd||(this.lastEmittedStart=this.visibleStart,this.lastEmittedEnd=this.visibleEnd,this.emit("lr-visible-range-change",{start:this.visibleStart,end:this.visibleEnd}))}maybeFireLoadMore(){const n=this.itemCount;if(!(n>0&&this.visibleEnd>=n-1)){this.loadMoreArmed=!0;return}!this.hasMore||this.loading||!this.loadMoreArmed||(this.loadMoreArmed=!1,this.emit("lr-load-more"))}renderRow(item,index,total,activeIndex){const key=this.keyOf(item,index),top=this.offsetAt(index),isActive=index===activeIndex,isRowMode=this.itemRole==="row";return html`
1
+ var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r};import{html,nothing,render}from"lit";import{html as staticHtml,unsafeStatic}from"lit/static-html.js";import{property,state}from"lit/decorators.js";import{repeat}from"lit/directives/repeat.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{literalSetConverter}from"../../../internal/converters.js";import{tag}from"../../../internal/prefix.js";import{prefersReducedMotion}from"../../../internal/motion.js";import{finiteAdd,finiteCount,finiteInteger,finiteNumber}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{getOwnDataDescriptor,MISSING_OWN_DATA_DESCRIPTOR,UNSAFE_OWN_DATA_DESCRIPTOR}from"../../../internal/data-descriptors.js";import{styles}from"./virtual-list.styles.js";const DEFAULT_ROW_ESTIMATE_PX=48,DEFAULT_GROUP_ESTIMATE_PX=32,DEFAULT_OVERSCAN_ROWS=6,MAX_OVERSCAN_ROWS=100,MAX_VIRTUAL_LIST_GROUPS=1e4,EMPTY_VIRTUAL_LIST_GROUPS=Object.freeze([]);function normalizeOverscan(value){if(value===null)return DEFAULT_OVERSCAN_ROWS;const numeric=typeof value=="number"?value:Number(value);return Number.isFinite(numeric)?Math.min(MAX_OVERSCAN_ROWS,Math.max(0,Math.floor(numeric))):DEFAULT_OVERSCAN_ROWS}const overscanConverter={fromAttribute(value){return normalizeOverscan(value)}};function virtualListGroupsChanged(value,oldValue){if(value===oldValue)return!1;const next=value,previous=oldValue;if(next==null||previous==null)return next!==previous;if(next.length!==previous.length)return!0;for(let index=0;index<next.length;index+=1){const a=next[index],b=previous[index];if(a.key!==b.key||a.label!==b.label||a.startIndex!==b.startIndex)return!0}return!1}const ROW_PROJECTION=literalSetConverter(["shadow","light"],"shadow"),VIRTUAL_LIST_ROW_ATTRIBUTE=`data-${tag("virtual-list-row")}`,VIRTUAL_LIST_STICKY_ATTRIBUTE=`data-${tag("virtual-list-sticky")}`,ROW_ATTRIBUTE_STATIC=unsafeStatic(VIRTUAL_LIST_ROW_ATTRIBUTE),PROJECTION_ANCHOR_MARKER=`${tag("virtual-list")}-projection`;function normalizeRowHeight(value){if(value==="auto")return"auto";const numeric=typeof value=="number"?value:Number(value);return Number.isFinite(numeric)&&numeric>0?numeric:"auto"}const rowHeightConverter={fromAttribute(value){return value===null?"auto":normalizeRowHeight(value)}};function isIndexedSource(source){return!Array.isArray(source)}const ELEMENT_NODE_TYPE=1;function isWindowScroller(target){return target.window===target}function domKeyToken(key){if(typeof key=="number"){if(Number.isNaN(key))return"number:NaN";if(Object.is(key,-0))return"number:-0"}return`${typeof key}:${String(key)}`}class LyraVirtualList extends LyraElement{constructor(){super(...arguments),this.items=[],this.renderItem=()=>nothing,this.rowHeight="auto",this.itemRole="listitem",this._rowProjection="shadow",this.rowIndexOffset=0,this.overscan=DEFAULT_OVERSCAN_ROWS,this.activeItemId="",this.loading=!1,this.hasMore=!1,this.containerScrollTop=0,this.viewportHeight=0,this.renderUnmeasuredWindow=!0,this.offsets=[0],this.rowIdentities=[],this.fixedRowHeight=null,this.measuredHeights=new Map,this.measuredIndices=new Map,this.indexedMeasurementIndices=[],this.indexedMeasurementDeltaPrefix=[0],this.indexedMeasurementIndexDirty=!0,this.offsetsDirty=!0,this.itemsChangedPendingPrune=!1,this.renderStart=0,this.renderEnd=-1,this.renderedWindow=[],this.projectionDeferred=!0,this.releaseRowProjection=()=>{this.projectionDeferred=!1,this.requestUpdate()},this.visibleStart=0,this.visibleEnd=-1,this.lastEmittedStart=-1,this.lastEmittedEnd=-1,this.loadMoreArmed=!0,this.measurementGeneration=0,this.isFirstUpdate=!0,this.stickyHeight=0,this.observedRows=new Map,this.observedRowKeys=new WeakMap,this.observedRowIndices=new WeakMap,this.observedGroups=new Map,this.observedGroupIndices=new WeakMap,this.externalMetricsPending=!1,this.ownerRealmGeneration=0,this.inResizeDelivery=!1,this.pendingRowMeasurements=new Map,this.pendingGroupMeasurements=new Map,this.deferredRowObservations=new Map,this.deferredGroupObservations=new Map,this.activeIndexForLength=-1,this.activeIndexForId="",this.activeIndexCache=-1,this.pendingScrollTop=null,this.normalizedGroups=EMPTY_VIRTUAL_LIST_GROUPS,this.normalizedGroupByIndex=new Map,this.measuredGroupHeights=new Map,this.groupHeightPrefix=[0],this.onExternalViewportResize=()=>{this.syncExternalScrollMetrics()},this.onUserScrollIntent=event=>{event instanceof KeyboardEvent&&!new Set(["ArrowUp","ArrowDown","PageUp","PageDown","Home","End"," "]).has(event.key)||(this.pendingScrollCorrection=void 0)},this.onScroll=e=>{if(this.externalScroller?(this.pendingScrollTop=null,this.externalMetricsPending=!0):this.pendingScrollTop=e.currentTarget.scrollTop,this.scrollRafId!==void 0)return;const ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView;if(!ownerWindow||!this.isConnected)return;const generation=this.ownerRealmGeneration,handle=ownerWindow.requestAnimationFrame(()=>{if(!(this.scrollRafId!==handle||this.scrollRafOwner!==ownerWindow||this.scrollRafDocument!==ownerDocument||!this.isCurrentOwnerWork(ownerDocument,generation))){if(this.scrollRafId=void 0,this.scrollRafOwner=void 0,this.scrollRafDocument=void 0,this.externalMetricsPending){this.externalMetricsPending=!1;const metrics=this.readScrollMetrics();metrics&&(this.pendingScrollTop=metrics.scrollTop,this.viewportHeight!==metrics.viewportHeight&&(this.viewportHeight=metrics.viewportHeight))}if(this.pendingScrollTop!==null){const scrollTop=this.pendingScrollTop;this.pendingScrollTop=null;const moved=this.containerScrollTop!==scrollTop;this.containerScrollTop=scrollTop,moved&&this.emit("lr-virtual-scroll",{scrollTop,viewportHeight:this.viewportHeight})}}});this.scrollRafId=handle,this.scrollRafOwner=ownerWindow,this.scrollRafDocument=ownerDocument},this.onRowsResized=entries=>{if(this.beginResizeDelivery(),this.fixedRowHeight==null){for(const entry of entries){const row=entry.target,key=this.observedRowKeys.get(row),index=this.observedRowIndices.get(row);if(key===void 0||index===void 0)continue;const height=entry.borderBoxSize?.[0]?.blockSize??entry.target.getBoundingClientRect().height;this.pendingRowMeasurements.set(key,{index,height})}this.defersMeasurementApplication||this.applyPendingRowMeasurements()}},this.onGroupsResized=entries=>{this.beginResizeDelivery();for(const entry of entries){const marker=entry.target,index=this.observedGroupIndices.get(marker);if(index===void 0||!this.normalizedGroupByIndex.has(index))continue;const height=entry.borderBoxSize?.[0]?.blockSize??entry.target.getBoundingClientRect().height;!Number.isFinite(height)||height<0||this.pendingGroupMeasurements.set(index,height)}this.defersMeasurementApplication||this.applyPendingGroupMeasurements()},this.onStickyResized=entries=>{this.beginResizeDelivery();const entry=entries[0];if(!entry)return;const height=entry.borderBoxSize?.[0]?.blockSize??entry.contentRect.height;Math.abs(this.stickyHeight-height)>.5&&(this.stickyHeight=height)}}static{this.ownedCollectionProperties=Object.freeze(["items","source","groups"])}static{this.identityCollectionProperties=Object.freeze(["items","source"])}static{this.identityCollectionObjectProperties=Object.freeze(["source"])}static{this.styles=[LyraElement.styles,styles]}get rowProjection(){return this._rowProjection}set rowProjection(next){const normalized=ROW_PROJECTION.normalize(next),previous=this._rowProjection;previous!==normalized&&(this._rowProjection=normalized,this.requestUpdate("rowProjection",previous))}get scrollContainer(){return this.renderRoot?.querySelector('[part="base"]')??void 0}get renderedRows(){const root=this.renderRoot;return root?[...root.querySelectorAll('[part="row"]')]:[]}get projectedRows(){const rows=[];for(const child of this.children)child.hasAttribute(VIRTUAL_LIST_ROW_ATTRIBUTE)&&rows.push(child);return rows}get externalScroller(){const target=this.scrollElement;if(target!=null)return isWindowScroller(target)||target.nodeType===ELEMENT_NODE_TYPE?target:void 0}get spacerElement(){return this.renderRoot?.querySelector('[part="spacer"]')??void 0}readScrollMetrics(){const base=this.scrollContainer;if(!base)return null;const external=this.externalScroller;if(!external)return{scrollTop:base.scrollTop,rawScrollTop:base.scrollTop,viewportHeight:base.clientHeight};const spacerTop=(this.spacerElement??base).getBoundingClientRect().top;if(isWindowScroller(external)){const documentHeight=finiteNumber(external.document?.documentElement?.clientHeight??0,0),rawScrollTop2=finiteNumber(-spacerTop,0);return{scrollTop:Math.max(0,rawScrollTop2),rawScrollTop:rawScrollTop2,viewportHeight:documentHeight>0?documentHeight:finiteNumber(external.innerHeight,0)}}const scrollerTop=external.getBoundingClientRect().top,rawScrollTop=finiteNumber(scrollerTop-spacerTop,0);return{scrollTop:Math.max(0,rawScrollTop),rawScrollTop,viewportHeight:finiteNumber(external.clientHeight,0)}}applyScrollPosition(top,behavior){const external=this.externalScroller;if(!external){const base=this.scrollContainer;if(!base)return;const next2=Math.max(0,finiteNumber(top,0));behavior===void 0?base.scrollTop=next2:base.scrollTo({top:next2,behavior});return}const metrics=this.readScrollMetrics();if(!metrics)return;const delta=finiteNumber(top,metrics.rawScrollTop)-metrics.rawScrollTop;if(isWindowScroller(external)){const options={top:Math.max(0,finiteNumber(external.scrollY+delta,0))};behavior!==void 0&&(options.behavior=behavior),external.scrollTo(options);return}const next=Math.max(0,finiteNumber(external.scrollTop+delta,0));behavior===void 0?external.scrollTop=next:external.scrollTo({top:next,behavior})}syncExternalScrollMetrics(){const metrics=this.readScrollMetrics();metrics&&(this.viewportHeight!==metrics.viewportHeight&&(this.viewportHeight=metrics.viewportHeight),this.containerScrollTop!==metrics.scrollTop&&(this.containerScrollTop=metrics.scrollTop))}get safeRowIndexOffset(){return finiteCount(this.rowIndexOffset)}computedAriaRowIndex(index){return finiteInteger(finiteAdd(index+1,this.safeRowIndexOffset),1,1,Number.MAX_SAFE_INTEGER)}get activeIndex(){if(this.activeItemId==="")return-1;const source=this.effectiveSource,count=this.itemCount;if(this.activeIndexFor===source&&this.activeIndexForLength===count&&Object.is(this.activeIndexForId,this.activeItemId)&&this.activeIndexForKeyFn===this.keyFunction)return this.activeIndexCache;if(this.activeIndexFor=source,this.activeIndexForLength=count,this.activeIndexForId=this.activeItemId,this.activeIndexForKeyFn=this.keyFunction,this.activeIndexCache=-1,isIndexedSource(source)){if(!this.keyFunction&&source.indexOfKey){const candidate=source.indexOfKey(this.activeItemId);Number.isInteger(candidate)&&candidate>=0&&candidate<count&&(this.activeIndexCache=candidate)}return this.activeIndexCache}for(let index=0;index<count;index++){const item=this.itemAt(index);if(Object.is(this.keyOf(item,index),this.activeItemId)){this.activeIndexCache=index;break}}return this.activeIndexCache}connectedCallback(){super.connectedCallback(),this.ownerDocument.defaultView&&(this.seedFirstRenderState(()=>{this.renderUnmeasuredWindow=!1,this.requestUpdate()}),this.seedFirstRenderState(this.releaseRowProjection),this.hasUpdated&&(this.projectionDeferred=!1)),this.resetOwnerRealmWork();const ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView,generation=this.ownerRealmGeneration,ResizeObserverCtor=ownerWindow?.ResizeObserver;if(ResizeObserverCtor){const rowObserver=new ResizeObserverCtor(entries=>{this.rowResizeObserver!==rowObserver||!this.isCurrentOwnerWork(ownerDocument,generation)||this.onRowsResized(entries)}),groupObserver=new ResizeObserverCtor(entries=>{this.groupResizeObserver!==groupObserver||!this.isCurrentOwnerWork(ownerDocument,generation)||this.onGroupsResized(entries)}),stickyObserver=new ResizeObserverCtor(entries=>{this.stickyResizeObserver!==stickyObserver||!this.isCurrentOwnerWork(ownerDocument,generation)||this.onStickyResized(entries)});this.rowResizeObserver=rowObserver,this.groupResizeObserver=groupObserver,this.stickyResizeObserver=stickyObserver}this.hasUpdated&&(this.syncRowProjection(),this.attachContainerListeners(),this.syncRowObservers(),this.syncGroupObservers(),this.syncStickyOverlay())}disconnectedCallback(){this.teardownRowProjection(),this.resetOwnerRealmWork(),super.disconnectedCallback()}adoptedCallback(){super.adoptedCallback(),this.teardownRowProjection(),this.resetOwnerRealmWork()}isCurrentOwnerWork(ownerDocument,generation){return this.ownerRealmGeneration===generation&&this.isConnected&&this.ownerDocument===ownerDocument}resetOwnerRealmWork(){this.ownerRealmGeneration+=1,this.rowResizeObserver?.disconnect(),this.rowResizeObserver=void 0,this.groupResizeObserver?.disconnect(),this.groupResizeObserver=void 0,this.observedRows.clear(),this.observedGroups.clear(),this.deferredRowObservations.clear(),this.deferredGroupObservations.clear(),this.inResizeDelivery=!1,this.pendingRowMeasurements.clear(),this.pendingGroupMeasurements.clear(),this.rowObserveRafId!==void 0&&this.rowObserveRafOwner?.cancelAnimationFrame(this.rowObserveRafId),this.rowObserveRafId=void 0,this.rowObserveRafOwner=void 0,this.rowObserveRafDocument=void 0,this.containerResizeObserver?.disconnect(),this.containerResizeObserver=void 0,this.stickyResizeObserver?.disconnect(),this.stickyResizeObserver=void 0,this.observedSticky=void 0,this.scrollRafId!==void 0&&this.scrollRafOwner?.cancelAnimationFrame(this.scrollRafId),this.scrollRafId=void 0,this.scrollRafOwner=void 0,this.scrollRafDocument=void 0,this.pendingScrollTop=null,this.externalMetricsPending=!1,this.pendingScrollCorrection=void 0,this.detachContainerListeners(),this.scrollListenerTarget=void 0}firstUpdated(changed){super.firstUpdated(changed),this.attachContainerListeners()}willUpdate(changed){super.willUpdate(changed),this.projectionDeferred&&!this.hasUpdated&&this.ownerDocument?.defaultView&&this.seedFirstRenderState(this.releaseRowProjection),this.isFirstUpdate=!this.hasUpdated,(changed.has("items")||changed.has("source")||changed.has("keyFunction")||changed.has("rowHeight")||changed.has("groups")||changed.has("activeItemId")||changed.has("scrollElement"))&&(this.pendingScrollCorrection=void 0),(changed.has("items")||changed.has("source")||changed.has("rowHeight")||changed.has("keyFunction")||changed.has("groups"))&&(this.offsetsDirty=!0),(changed.has("items")||changed.has("source"))&&(this.itemsChangedPendingPrune=!0),(changed.has("keyFunction")||isIndexedSource(this.effectiveSource)&&(changed.has("items")||changed.has("source")))&&(this.measuredHeights.clear(),this.measuredIndices.clear(),this.pendingRowMeasurements.clear(),this.indexedMeasurementIndexDirty=!0),changed.has("groups")&&(this.measuredGroupHeights.clear(),this.pendingGroupMeasurements.clear()),(changed.has("items")||changed.has("source")||changed.has("groups"))&&this.recomputeGroups(),changed.has("rowHeight")&&(this.fixedRowHeight=this.parseRowHeight(this.rowHeight),this.fixedRowHeight!=null&&(this.measuredHeights.clear(),this.measuredIndices.clear(),this.pendingRowMeasurements.clear(),this.indexedMeasurementIndexDirty=!0)),this.offsetsDirty&&(this.recomputeOffsets(),this.offsetsDirty=!1),this.computeRange()}updated(changed){super.updated(changed),this.syncRowProjection(),this.syncRowObservers(),this.syncGroupObservers(),this.syncStickyOverlay(),changed.has("scrollElement")&&!this.isFirstUpdate&&this.attachContainerListeners(),changed.has("activeItemId")&&!this.isFirstUpdate&&this.scrollActiveIntoView(),this.emitRangeChangeIfNeeded(),this.maybeFireLoadMore(),this.maybeCorrectPendingScroll()}parseRowHeight(value){const normalized=normalizeRowHeight(value);return normalized==="auto"?null:normalized}get effectiveSource(){return this.source??this.items}get itemCount(){const source=this.effectiveSource;return isIndexedSource(source)?finiteCount(source.count):source.length}itemAt(index){const source=this.effectiveSource;return isIndexedSource(source)?source.itemAt(index):source[index]}keyOf(item,index){const source=this.effectiveSource,key=this.keyFunction?this.keyFunction(item,index):isIndexedSource(source)?source.keyAt?.(index)??index:index;return typeof key=="string"||typeof key=="number"?key:index}rowIdentity(key,occurrence){const token=domKeyToken(key);return`${token.length}:${token}:${occurrence}`}identityAt(index,item=this.itemAt(index)){return isIndexedSource(this.effectiveSource)?this.rowIdentity(this.keyOf(item,index),index):this.rowIdentities[index]??this.rowIdentity(this.keyOf(item,index),index)}groupHeightAt(index){const group=this.normalizedGroupByIndex.get(index);return!group||group.label===""?0:this.measuredGroupHeights.get(index)??DEFAULT_GROUP_ESTIMATE_PX}rowHeightAt(index){return this.fixedRowHeight!=null?this.fixedRowHeight:this.measuredHeights.get(this.identityAt(index))??DEFAULT_ROW_ESTIMATE_PX}groupContributionThrough(index){let low=0,high=this.normalizedGroups.length;for(;low<high;){const middle=low+high>>1;this.normalizedGroups[middle].startIndex<=index?low=middle+1:high=middle}return this.groupHeightPrefix[low]??0}recomputeGroupHeightPrefix(){const prefix=new Array(this.normalizedGroups.length+1);prefix[0]=0;for(let index=0;index<this.normalizedGroups.length;index++){const group=this.normalizedGroups[index],height=group.label===""?0:this.measuredGroupHeights.get(group.startIndex)??DEFAULT_GROUP_ESTIMATE_PX;prefix[index+1]=finiteAdd(prefix[index],height)}this.groupHeightPrefix=prefix}indexedOffsetForIndex(index){const baseHeight=this.fixedRowHeight??DEFAULT_ROW_ESTIMATE_PX;let offset=index>Number.MAX_VALUE/baseHeight?Number.MAX_VALUE:index*baseHeight;if(this.fixedRowHeight==null){this.rebuildIndexedMeasurementIndex();let low=0,high=this.indexedMeasurementIndices.length;for(;low<high;){const middle=low+high>>1;this.indexedMeasurementIndices[middle]<index?low=middle+1:high=middle}offset=finiteAdd(offset,this.indexedMeasurementDeltaPrefix[low]??0)}return Math.max(0,finiteAdd(offset,this.groupContributionThrough(index)))}rebuildIndexedMeasurementIndex(){if(!this.indexedMeasurementIndexDirty)return;const retained=[];for(const[identity,index]of this.measuredIndices){const height=this.measuredHeights.get(identity);height!==void 0&&retained.push({index,delta:height-DEFAULT_ROW_ESTIMATE_PX})}retained.sort((a,b)=>a.index-b.index);const indices=new Array(retained.length),prefix=new Array(retained.length+1);prefix[0]=0;for(let position=0;position<retained.length;position++){const measurement=retained[position];indices[position]=measurement.index,prefix[position+1]=finiteAdd(prefix[position],measurement.delta)}this.indexedMeasurementIndices=indices,this.indexedMeasurementDeltaPrefix=prefix,this.indexedMeasurementIndexDirty=!1}pruneIndexedMeasurements(){if(!isIndexedSource(this.effectiveSource)||this.fixedRowHeight!=null||this.renderEnd<this.renderStart)return!1;const renderedCount=this.renderEnd-this.renderStart+1,retentionRows=Math.max(renderedCount,normalizeOverscan(this.overscan)*4),firstRetained=Math.max(0,this.renderStart-retentionRows),lastRetained=Math.min(this.itemCount-1,this.renderEnd+retentionRows);let removedDeltaBeforeWindow=0,pruned=!1;for(const[identity,measuredIndex]of this.measuredIndices)if(measuredIndex<firstRetained||measuredIndex>lastRetained){const height=this.measuredHeights.get(identity);height!==void 0&&measuredIndex<firstRetained&&(removedDeltaBeforeWindow=finiteAdd(removedDeltaBeforeWindow,height-DEFAULT_ROW_ESTIMATE_PX)),this.measuredIndices.delete(identity),this.measuredHeights.delete(identity),pruned=!0}if(pruned&&(this.indexedMeasurementIndexDirty=!0,removedDeltaBeforeWindow!==0)){const nextScrollTop=(this.readScrollMetrics()?.rawScrollTop??this.containerScrollTop)-removedDeltaBeforeWindow;this.applyScrollPosition(nextScrollTop),this.containerScrollTop=Math.max(0,nextScrollTop),this.pendingScrollTop=null}return pruned}offsetAt(index){return isIndexedSource(this.effectiveSource)?this.indexedOffsetForIndex(index):this.offsets[index]??0}recomputeOffsets(){const n=this.itemCount;if(this.recomputeGroupHeightPrefix(),isIndexedSource(this.effectiveSource)){this.offsets=[0],this.rowIdentities=[],this.itemsChangedPendingPrune=!1;return}const offsets=new Array(n+1);let cursor=0;const liveKeys=this.itemsChangedPendingPrune&&this.fixedRowHeight==null?new Set:null,occurrences=new Map,identities=new Array(n);for(let i=0;i<n;i++){cursor=finiteAdd(cursor,this.groupHeightAt(i)),offsets[i]=cursor;const key=this.keyOf(this.itemAt(i),i),token=domKeyToken(key),occurrence=occurrences.get(token)??0;occurrences.set(token,occurrence+1);const identity=this.rowIdentity(key,occurrence);identities[i]=identity;let h;this.fixedRowHeight!=null?h=this.fixedRowHeight:(liveKeys?.add(identity),h=this.measuredHeights.get(identity)??DEFAULT_ROW_ESTIMATE_PX),cursor=finiteAdd(cursor,h)}if(offsets[n]=cursor,this.offsets=offsets,this.rowIdentities=identities,this.itemsChangedPendingPrune=!1,liveKeys){for(const key of this.measuredHeights.keys())liveKeys.has(key)||(this.measuredHeights.delete(key),this.measuredIndices.delete(key),this.indexedMeasurementIndexDirty=!0);for(const key of this.measuredIndices.keys())liveKeys.has(key)||(this.measuredIndices.delete(key),this.indexedMeasurementIndexDirty=!0)}}groupTopAt(index){return Math.max(0,this.offsetAt(index)-this.groupHeightAt(index))}rowBottomAt(index){return finiteAdd(this.offsetAt(index),this.rowHeightAt(index))}entryTopAt(index){return this.groupTopAt(index)}findIndexAtOrAfter(offset){let lo=0,hi=this.itemCount-1;for(;lo<hi;){const mid=lo+Math.floor((hi-lo)/2);this.rowBottomAt(mid)<=offset?lo=mid+1:hi=mid}return lo}findIndexAtOrBefore(offset){let lo=0,hi=this.itemCount-1;for(;lo<hi;){const mid=lo+Math.ceil((hi-lo)/2);this.entryTopAt(mid)<offset?lo=mid:hi=mid-1}return lo}offsetForIndex(index){const clamped=Math.min(this.itemCount,Math.max(0,Math.trunc(index)||0));return this.offsetAt(clamped)}indexAtOffset(px){const n=this.itemCount;return n===0?-1:Number.isFinite(px)?Math.min(n-1,Math.max(0,this.findIndexAtOrAfter(px))):px>0?n-1:0}computeRange(){const n=this.itemCount;if(n===0){this.visibleStart=0,this.visibleEnd=-1,this.renderStart=0,this.renderEnd=-1;return}if(this.viewportHeight<=0){if(!this.renderUnmeasuredWindow){this.visibleStart=0,this.visibleEnd=-1,this.renderStart=0,this.renderEnd=-1;return}this.visibleStart=0,this.visibleEnd=0,this.renderStart=0,this.renderEnd=Math.min(n-1,normalizeOverscan(this.overscan));return}const viewTop=this.containerScrollTop,viewBottom=viewTop+this.viewportHeight;this.visibleStart=this.findIndexAtOrAfter(viewTop),this.visibleEnd=this.findIndexAtOrBefore(viewBottom);const overscan=normalizeOverscan(this.overscan);this.renderStart=Math.max(0,this.visibleStart-overscan),this.renderEnd=Math.min(n-1,this.visibleEnd+overscan),this.pruneIndexedMeasurements()&&this.computeRange()}attachContainerListeners(){const base=this.scrollContainer,ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView;if(!base||!this.isConnected||!ownerWindow)return;this.containerResizeObserver?.disconnect(),this.containerResizeObserver=void 0,this.detachContainerListeners();const external=this.externalScroller,scrollTarget=external??base,generation=this.ownerRealmGeneration,ResizeObserverCtor=ownerWindow.ResizeObserver;if(ResizeObserverCtor){const observer=new ResizeObserverCtor(entries=>{if(this.containerResizeObserver!==observer||this.scrollListenerTarget!==scrollTarget||!this.isCurrentOwnerWork(ownerDocument,generation))return;if(this.beginResizeDelivery(),external){this.syncExternalScrollMetrics();return}const entry=entries[0];entry&&(this.viewportHeight=entry.borderBoxSize?.[0]?.blockSize??entry.contentRect.height)});this.containerResizeObserver=observer,observer.observe(base),external&&!isWindowScroller(external)&&observer.observe(external)}scrollTarget.addEventListener("scroll",this.onScroll,{passive:!0}),scrollTarget.addEventListener("wheel",this.onUserScrollIntent,{passive:!0}),scrollTarget.addEventListener("pointerdown",this.onUserScrollIntent,{passive:!0}),scrollTarget.addEventListener("touchstart",this.onUserScrollIntent,{passive:!0}),scrollTarget.addEventListener("keydown",this.onUserScrollIntent),this.scrollListenerTarget=scrollTarget,external&&isWindowScroller(external)&&(external.addEventListener("resize",this.onExternalViewportResize,{passive:!0}),this.viewportResizeTarget=external),ownerWindow.queueMicrotask(()=>{if(this.scrollListenerTarget!==scrollTarget||this.scrollContainer!==base||!this.isCurrentOwnerWork(ownerDocument,generation))return;const metrics=this.readScrollMetrics();metrics&&(this.viewportHeight!==metrics.viewportHeight&&(this.viewportHeight=metrics.viewportHeight),this.containerScrollTop!==metrics.scrollTop&&(this.containerScrollTop=metrics.scrollTop))})}detachContainerListeners(){const viewportTarget=this.viewportResizeTarget;viewportTarget&&(viewportTarget.removeEventListener("resize",this.onExternalViewportResize),this.viewportResizeTarget=void 0);const target=this.scrollListenerTarget;target&&(target.removeEventListener("scroll",this.onScroll),target.removeEventListener("wheel",this.onUserScrollIntent),target.removeEventListener("pointerdown",this.onUserScrollIntent),target.removeEventListener("touchstart",this.onUserScrollIntent),target.removeEventListener("keydown",this.onUserScrollIntent))}applyPendingRowMeasurements(){if(this.pendingRowMeasurements.size===0)return;const observations=[...this.pendingRowMeasurements];if(this.pendingRowMeasurements.clear(),this.fixedRowHeight!=null)return;const base=this.scrollContainer,oldScrollTop=this.readScrollMetrics()?.rawScrollTop??this.containerScrollTop;let scrollAdjustment=0,changed=!1;for(const[key,{index,height}]of observations){const prev=this.measuredHeights.get(key);if(prev===void 0||Math.abs(prev-height)>.5){const oldBottom=this.rowBottomAt(index);this.measuredHeights.set(key,height),this.measuredIndices.set(key,index);const oldHeight=prev??DEFAULT_ROW_ESTIMATE_PX;oldBottom<=oldScrollTop&&(scrollAdjustment+=height-oldHeight),changed=!0}}if(changed){if(this.indexedMeasurementIndexDirty=!0,base&&scrollAdjustment!==0){const nextScrollTop=oldScrollTop+scrollAdjustment;this.applyScrollPosition(nextScrollTop),this.containerScrollTop=Math.max(0,nextScrollTop),this.pendingScrollTop=null}this.offsetsDirty=!0,this.measurementGeneration+=1,this.requestUpdate()}}applyPendingGroupMeasurements(){if(this.pendingGroupMeasurements.size===0)return;const observations=[...this.pendingGroupMeasurements];this.pendingGroupMeasurements.clear();const base=this.scrollContainer,oldScrollTop=this.readScrollMetrics()?.rawScrollTop??this.containerScrollTop;let scrollAdjustment=0,changed=!1;for(const[index,height]of observations){if(!this.normalizedGroupByIndex.has(index))continue;const previous=this.measuredGroupHeights.get(index)??DEFAULT_GROUP_ESTIMATE_PX;if(Math.abs(previous-height)<=.5)continue;const oldRowTop=this.offsetAt(index);this.measuredGroupHeights.set(index,height),oldRowTop<=oldScrollTop&&(scrollAdjustment+=height-previous),changed=!0}if(changed){if(base&&scrollAdjustment!==0){const nextScrollTop=oldScrollTop+scrollAdjustment;this.applyScrollPosition(nextScrollTop),this.containerScrollTop=Math.max(0,nextScrollTop),this.pendingScrollTop=null}this.offsetsDirty=!0,this.measurementGeneration+=1,this.requestUpdate()}}get defersMeasurementApplication(){return this.inResizeDelivery&&this.externalScroller!==void 0}beginResizeDelivery(){if(this.inResizeDelivery=!0,this.rowObserveRafId!==void 0)return;const ownerDocument=this.ownerDocument,ownerWindow=ownerDocument.defaultView;if(!ownerWindow||!this.isConnected){this.inResizeDelivery=!1;return}const generation=this.ownerRealmGeneration,handle=ownerWindow.requestAnimationFrame(()=>{if(this.rowObserveRafId!==handle||this.rowObserveRafOwner!==ownerWindow||this.rowObserveRafDocument!==ownerDocument||!this.isCurrentOwnerWork(ownerDocument,generation))return;this.rowObserveRafId=void 0,this.rowObserveRafOwner=void 0,this.rowObserveRafDocument=void 0,this.inResizeDelivery=!1;const ro=this.rowResizeObserver;for(const[identity,el]of this.deferredRowObservations)ro&&this.observedRows.get(identity)===el&&ro.observe(el);this.deferredRowObservations.clear();const groupObserver=this.groupResizeObserver;for(const[index,el]of this.deferredGroupObservations)groupObserver&&this.observedGroups.get(index)===el&&groupObserver.observe(el);this.deferredGroupObservations.clear(),this.applyPendingRowMeasurements(),this.applyPendingGroupMeasurements()});this.rowObserveRafId=handle,this.rowObserveRafOwner=ownerWindow,this.rowObserveRafDocument=ownerDocument}syncRowObservers(){const ro=this.rowResizeObserver;if(!ro)return;if(this.fixedRowHeight!=null){for(const el of this.observedRows.values())ro.unobserve(el);this.observedRows.clear(),this.deferredRowObservations.clear();return}const current=new Map;this.renderRoot.querySelectorAll('[part="row"]').forEach(el=>{const index=Number(el.getAttribute("data-row-index"));if(!Number.isInteger(index)||index<0||index>=this.itemCount)return;const identity=this.identityAt(index);current.set(identity,el),this.observedRowKeys.set(el,identity),this.observedRowIndices.set(el,index)});for(const[identity,el]of this.observedRows)current.get(identity)!==el&&(ro.unobserve(el),this.observedRows.delete(identity),this.deferredRowObservations.delete(identity));for(const[identity,el]of current)this.observedRows.has(identity)||(this.observedRows.set(identity,el),this.inResizeDelivery?this.deferredRowObservations.set(identity,el):ro.observe(el))}syncGroupObservers(){const observer=this.groupResizeObserver;if(!observer)return;const current=new Map;this.renderRoot.querySelectorAll('[part="group"][data-group-index]').forEach(marker=>{const index=Number(marker.dataset.groupIndex);!Number.isInteger(index)||!this.normalizedGroupByIndex.has(index)||(current.set(index,marker),this.observedGroupIndices.set(marker,index))});for(const[index,marker]of this.observedGroups)current.get(index)!==marker&&(observer.unobserve(marker),this.observedGroups.delete(index),this.deferredGroupObservations.delete(index));for(const[index,marker]of current)this.observedGroups.has(index)||(this.observedGroups.set(index,marker),this.inResizeDelivery?this.deferredGroupObservations.set(index,marker):observer.observe(marker))}get stickyInset(){return this.renderStickyGroup?this.stickyHeight:0}scrollActiveIntoView(){const index=this.activeIndex;if(index<0)return;const behavior=prefersReducedMotion(this.ownerDocument.defaultView)?"auto":"smooth";this.performScrollTo(index,"auto",behavior)&&this.beginPendingScrollCorrection(index,"auto",behavior,this.activeItemId)}scrollToIndex(index,options){const n=this.itemCount;if(n===0)return;const clamped=finiteInteger(index,0,0,n-1),align=options?.align??"auto",behavior=prefersReducedMotion(this.ownerDocument.defaultView)?"auto":options?.behavior??"smooth";this.performScrollTo(clamped,align,behavior)?this.beginPendingScrollCorrection(clamped,align,behavior):this.pendingScrollCorrection=void 0}hasUnmeasuredGroupThrough(index){return this.normalizedGroups.some(group=>group.startIndex<=index&&group.label!==""&&!this.measuredGroupHeights.has(group.startIndex))}beginPendingScrollCorrection(index,align,behavior,activeItemId){if(this.fixedRowHeight!=null&&!this.hasUnmeasuredGroupThrough(index)){this.pendingScrollCorrection=void 0;return}this.pendingScrollCorrection={identity:this.identityAt(index),index,align,behavior,source:this.effectiveSource,keyFunction:this.keyFunction,activeItemId:activeItemId===""?void 0:activeItemId,lastMeasurementGeneration:this.measurementGeneration}}performScrollTo(index,align,behavior){const metrics=this.readScrollMetrics();if(!metrics)return!1;const inset=this.stickyInset,top=this.offsetAt(index),bottom=this.rowBottomAt(index),viewTop=metrics.rawScrollTop,viewBottom=viewTop+metrics.viewportHeight;let target=null;return align==="start"?target=top-inset:align==="end"?target=bottom-metrics.viewportHeight:top-inset<viewTop?target=top-inset:bottom>viewBottom&&(target=bottom-metrics.viewportHeight),target===null?!1:(this.applyScrollPosition(target,behavior),!0)}maybeCorrectPendingScroll(){const pending=this.pendingScrollCorrection;if(!pending||pending.lastMeasurementGeneration>=this.measurementGeneration)return;if(pending.source!==this.effectiveSource||pending.keyFunction!==this.keyFunction||pending.activeItemId!==void 0&&!Object.is(pending.activeItemId,this.activeItemId)){this.pendingScrollCorrection=void 0;return}const index=pending.activeItemId!==void 0?this.activeIndex:isIndexedSource(this.effectiveSource)?pending.index:this.rowIdentities.indexOf(pending.identity);if(index<0||index>=this.itemCount||this.identityAt(index)!==pending.identity){this.pendingScrollCorrection=void 0;return}this.performScrollTo(index,pending.align,pending.behavior),pending.index=index,pending.lastMeasurementGeneration=this.measurementGeneration,(this.fixedRowHeight!=null||this.measuredHeights.has(pending.identity))&&!this.hasUnmeasuredGroupThrough(index)&&(this.pendingScrollCorrection=void 0)}emitRangeChangeIfNeeded(){if(this.visibleEnd<this.visibleStart){this.lastEmittedStart=-1,this.lastEmittedEnd=-1;return}this.visibleStart===this.lastEmittedStart&&this.visibleEnd===this.lastEmittedEnd||(this.lastEmittedStart=this.visibleStart,this.lastEmittedEnd=this.visibleEnd,this.emit("lr-visible-range-change",{start:this.visibleStart,end:this.visibleEnd}))}maybeFireLoadMore(){const n=this.itemCount;if(!(n>0&&this.visibleEnd>=n-1)){this.loadMoreArmed=!0;return}!this.hasMore||this.loading||!this.loadMoreArmed||(this.loadMoreArmed=!1,this.emit("lr-load-more"))}get projectionActive(){return!this.projectionDeferred&&this.rowProjection==="light"}rowSlotName(identity){return`${tag("virtual-list")}-row-${identity}`}syncRowProjection(){if(!this.projectionActive||!this.isConnected){this.projectionAnchor!==void 0&&this.teardownRowProjection();return}const anchor=this.ensureProjectionAnchor();this.projectionPart=render(this.renderProjectedRows(),this,{renderBefore:anchor,host:this})}ensureProjectionAnchor(){const existing=this.projectionAnchor;if(existing!==void 0&&existing.parentNode===this&&existing.ownerDocument===this.ownerDocument)return existing;existing!==void 0&&this.teardownRowProjection();const anchor=this.ownerDocument.createComment(PROJECTION_ANCHOR_MARKER);return this.append(anchor),this.projectionAnchor=anchor,this.projectionPart=void 0,anchor}teardownRowProjection(){const anchor=this.projectionAnchor,part=this.projectionPart;if(this.projectionAnchor=void 0,this.projectionPart=void 0,anchor!==void 0){if(part!==void 0){const container=anchor.parentNode;container!==null&&render(nothing,container,{renderBefore:anchor,host:this});const start=part.startNode;start?.parentNode?.removeChild(start)}anchor.parentNode?.removeChild(anchor)}}renderProjectedRows(){return repeat(this.renderedWindow,w=>w.identity,w=>staticHtml`<div
2
+ ${ROW_ATTRIBUTE_STATIC}
3
+ slot=${this.rowSlotName(w.identity)}
4
+ data-row-index=${w.index}
5
+ data-row-key=${domKeyToken(this.keyOf(w.item,w.index))}
6
+ >${this.renderItem(w.item,w.index)}</div>`)}renderRow(item,index,total,activeIndex,identity){const key=this.keyOf(item,index),top=this.offsetAt(index),isActive=index===activeIndex,isRowMode=this.itemRole==="row";return html`
2
7
  <div
3
8
  part="row"
4
9
  role=${isRowMode?"row":"listitem"}
@@ -10,7 +15,7 @@ var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3
10
15
  aria-current=${isActive?"true":"false"}
11
16
  style=${styleMap({transform:`translateY(${top}px)`})}
12
17
  >
13
- ${this.renderItem(item,index)}
18
+ ${this.projectionActive?html`<slot name=${this.rowSlotName(identity)}></slot>`:this.renderItem(item,index)}
14
19
  </div>
15
20
  `}recomputeGroups(){const normalized=[],seen=new Set;try{const groups=this.groups;if(!Array.isArray(groups))throw new TypeError("groups must be an array");const length=getOwnDataDescriptor(groups,"length");if(length===MISSING_OWN_DATA_DESCRIPTOR||length===UNSAFE_OWN_DATA_DESCRIPTOR||typeof length.value!="number"||!Number.isSafeInteger(length.value)||length.value<0)throw new TypeError("groups must have a bounded length");for(let position=0;position<Math.min(length.value,MAX_VIRTUAL_LIST_GROUPS);position+=1){const entry=getOwnDataDescriptor(groups,String(position));if(entry===MISSING_OWN_DATA_DESCRIPTOR||entry===UNSAFE_OWN_DATA_DESCRIPTOR||entry.value===null||typeof entry.value!="object"||Array.isArray(entry.value))continue;const key=getOwnDataDescriptor(entry.value,"key"),label=getOwnDataDescriptor(entry.value,"label"),startIndex=getOwnDataDescriptor(entry.value,"startIndex");if(key===MISSING_OWN_DATA_DESCRIPTOR||key===UNSAFE_OWN_DATA_DESCRIPTOR||startIndex===MISSING_OWN_DATA_DESCRIPTOR||startIndex===UNSAFE_OWN_DATA_DESCRIPTOR||label===UNSAFE_OWN_DATA_DESCRIPTOR||typeof key.value!="string"&&typeof key.value!="number"||typeof startIndex.value!="number"||!Number.isInteger(startIndex.value)||startIndex.value<0||startIndex.value>=this.itemCount||seen.has(startIndex.value))continue;const labelValue=label===MISSING_OWN_DATA_DESCRIPTOR||typeof label.value!="string"?void 0:label.value;seen.add(startIndex.value),normalized.push(Object.freeze({key:key.value,startIndex:startIndex.value,...labelValue===void 0?{}:{label:labelValue}}))}}catch{}this.normalizedGroups=Object.freeze(normalized.sort((a,b)=>a.startIndex-b.startIndex)),this.normalizedGroupByIndex.clear();for(const group of this.normalizedGroups)this.normalizedGroupByIndex.set(group.startIndex,group)}renderGroups(){return this.normalizedGroups.filter(group=>group.startIndex>=this.renderStart&&group.startIndex<=this.renderEnd).filter(group=>group.label!=="").map(group=>html`
16
21
  <div
@@ -20,7 +25,7 @@ var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3
20
25
  >
21
26
  ${group.label??(typeof group.key=="number"?getNumberFormat(this.effectiveLocale).format(group.key):group.key)}
22
27
  </div>
23
- `)}currentStickyGroup(){const groups=this.normalizedGroups;if(groups.length===0)return null;const scrollTop=this.containerScrollTop;let low=0,high=groups.length-1,current=-1;for(;low<=high;){const middle=low+high>>1;this.groupTopAt(groups[middle].startIndex)<=scrollTop?(current=middle,low=middle+1):high=middle-1}if(current<0)return{group:groups[0],shift:0,active:!1};const next=groups[current+1];let shift=0;if(next&&this.stickyHeight>0){const distance=this.groupTopAt(next.startIndex)-scrollTop;distance<this.stickyHeight&&(shift=Math.min(0,distance-this.stickyHeight))}return{group:groups[current],shift,active:!0}}renderStickyLayer(){const render=this.renderStickyGroup;if(!render)return nothing;const state2=this.currentStickyGroup();return state2?html`
28
+ `)}currentStickyGroup(){const groups=this.normalizedGroups;if(groups.length===0)return null;const scrollTop=this.containerScrollTop;let low=0,high=groups.length-1,current=-1;for(;low<=high;){const middle=low+high>>1;this.groupTopAt(groups[middle].startIndex)<=scrollTop?(current=middle,low=middle+1):high=middle-1}if(current<0)return{group:groups[0],shift:0,active:!1};const next=groups[current+1];let shift=0;if(next&&this.stickyHeight>0){const distance=this.groupTopAt(next.startIndex)-scrollTop;distance<this.stickyHeight&&(shift=Math.min(0,distance-this.stickyHeight))}return{group:groups[current],shift,active:!0}}renderStickyLayer(){const render2=this.renderStickyGroup;if(!render2)return nothing;const state2=this.currentStickyGroup();return state2?html`
24
29
  <div
25
30
  part="sticky-group"
26
31
  aria-hidden="true"
@@ -28,9 +33,9 @@ var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3
28
33
  ?data-inactive=${!state2.active}
29
34
  style=${state2.shift!==0?`transform:translateY(${state2.shift}px)`:nothing}
30
35
  >
31
- ${render(state2.group)}
36
+ ${render2(state2.group)}
32
37
  </div>
33
- `:nothing}syncStickyOverlay(){const overlay=this.renderRoot.querySelector('[part="sticky-group"]');overlay!==this.observedSticky&&(this.observedSticky&&this.stickyResizeObserver?.unobserve(this.observedSticky),this.observedSticky=overlay??void 0,overlay&&this.stickyResizeObserver?.observe(overlay))}render(){const n=this.itemCount,totalHeight=this.offsetAt(n),windowed=[];for(let i=this.renderStart;i<=this.renderEnd;i++)windowed.push({item:this.itemAt(i),index:i});const isRowMode=this.itemRole==="row",stickyInset=this.stickyInset,activeIndex=this.activeIndex,isExternallyScrolled=this.externalScroller!==void 0;return html`
38
+ `:nothing}syncStickyOverlay(){const overlay=this.renderRoot.querySelector('[part="sticky-group"]');overlay!==this.observedSticky&&(this.observedSticky&&this.stickyResizeObserver?.unobserve(this.observedSticky),this.observedSticky=overlay??void 0,overlay&&this.stickyResizeObserver?.observe(overlay))}render(){const n=this.itemCount,totalHeight=this.offsetAt(n),windowed=[];for(let i=this.renderStart;i<=this.renderEnd;i++){const item=this.itemAt(i);windowed.push({item,index:i,identity:this.identityAt(i,item)})}this.renderedWindow=windowed;const isRowMode=this.itemRole==="row",stickyInset=this.stickyInset,activeIndex=this.activeIndex,isExternallyScrolled=this.externalScroller!==void 0;return html`
34
39
  <div
35
40
  part="base"
36
41
  role=${isRowMode?"rowgroup":"list"}
@@ -46,8 +51,8 @@ var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3
46
51
  style=${styleMap({height:`${totalHeight}px`})}
47
52
  >
48
53
  ${this.renderGroups()}
49
- ${repeat(windowed,w=>this.identityAt(w.index,w.item),w=>this.renderRow(w.item,w.index,n,activeIndex))}
54
+ ${repeat(windowed,w=>w.identity,w=>this.renderRow(w.item,w.index,n,activeIndex,w.identity))}
50
55
  ${this.renderStickyLayer()}
51
56
  </div>
52
57
  </div>
53
- `}}__decorate([property({attribute:!1})],LyraVirtualList.prototype,"items",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"source",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"renderItem",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"keyFunction",void 0),__decorate([property({attribute:!1,hasChanged:virtualListGroupsChanged})],LyraVirtualList.prototype,"groups",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"renderStickyGroup",void 0),__decorate([property({attribute:"row-height",converter:rowHeightConverter})],LyraVirtualList.prototype,"rowHeight",void 0),__decorate([property({attribute:"item-role"})],LyraVirtualList.prototype,"itemRole",void 0),__decorate([property({type:Number,attribute:"row-index-offset"})],LyraVirtualList.prototype,"rowIndexOffset",void 0),__decorate([property({converter:overscanConverter})],LyraVirtualList.prototype,"overscan",void 0),__decorate([property({attribute:"active-item-id"})],LyraVirtualList.prototype,"activeItemId",void 0),__decorate([property({type:Boolean,reflect:!0})],LyraVirtualList.prototype,"loading",void 0),__decorate([property({type:Boolean,attribute:"has-more",reflect:!0})],LyraVirtualList.prototype,"hasMore",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"scrollElement",void 0),__decorate([state()],LyraVirtualList.prototype,"containerScrollTop",void 0),__decorate([state()],LyraVirtualList.prototype,"viewportHeight",void 0),__decorate([state()],LyraVirtualList.prototype,"stickyHeight",void 0);export{LyraVirtualList,MAX_OVERSCAN_ROWS};
58
+ `}}__decorate([property({attribute:!1})],LyraVirtualList.prototype,"items",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"source",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"renderItem",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"keyFunction",void 0),__decorate([property({attribute:!1,hasChanged:virtualListGroupsChanged})],LyraVirtualList.prototype,"groups",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"renderStickyGroup",void 0),__decorate([property({attribute:"row-height",converter:rowHeightConverter})],LyraVirtualList.prototype,"rowHeight",void 0),__decorate([property({attribute:"item-role"})],LyraVirtualList.prototype,"itemRole",void 0),__decorate([property({attribute:"row-projection",converter:ROW_PROJECTION})],LyraVirtualList.prototype,"rowProjection",null),__decorate([property({type:Number,attribute:"row-index-offset"})],LyraVirtualList.prototype,"rowIndexOffset",void 0),__decorate([property({converter:overscanConverter})],LyraVirtualList.prototype,"overscan",void 0),__decorate([property({attribute:"active-item-id"})],LyraVirtualList.prototype,"activeItemId",void 0),__decorate([property({type:Boolean,reflect:!0})],LyraVirtualList.prototype,"loading",void 0),__decorate([property({type:Boolean,attribute:"has-more",reflect:!0})],LyraVirtualList.prototype,"hasMore",void 0),__decorate([property({attribute:!1})],LyraVirtualList.prototype,"scrollElement",void 0),__decorate([state()],LyraVirtualList.prototype,"containerScrollTop",void 0),__decorate([state()],LyraVirtualList.prototype,"viewportHeight",void 0),__decorate([state()],LyraVirtualList.prototype,"stickyHeight",void 0);export{LyraVirtualList,MAX_OVERSCAN_ROWS,VIRTUAL_LIST_ROW_ATTRIBUTE,VIRTUAL_LIST_STICKY_ATTRIBUTE};