igniteui-webcomponents 7.4.0 → 7.4.1

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 (97) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/components/checkbox/checkbox-base.d.ts +2 -0
  3. package/components/checkbox/checkbox-base.js +4 -0
  4. package/components/checkbox/checkbox-base.js.map +1 -1
  5. package/components/checkbox/checkbox.js +3 -11
  6. package/components/checkbox/checkbox.js.map +1 -1
  7. package/components/checkbox/switch.js +1 -8
  8. package/components/checkbox/switch.js.map +1 -1
  9. package/components/color-picker/color-picker.js +3 -3
  10. package/components/color-picker/color-picker.js.map +1 -1
  11. package/components/combo/combo.d.ts +6 -4
  12. package/components/combo/combo.js +13 -24
  13. package/components/combo/combo.js.map +1 -1
  14. package/components/date-picker/date-picker.base.d.ts +3 -3
  15. package/components/date-picker/date-picker.base.js +2 -2
  16. package/components/date-picker/date-picker.base.js.map +1 -1
  17. package/components/date-picker/date-picker.d.ts +1 -1
  18. package/components/date-range-picker/date-range-picker.d.ts +1 -1
  19. package/components/date-time-input/date-time-input.base.d.ts +4 -4
  20. package/components/date-time-input/date-time-input.base.js +3 -5
  21. package/components/date-time-input/date-time-input.base.js.map +1 -1
  22. package/components/file-input/file-input.d.ts +5 -0
  23. package/components/file-input/file-input.js +4 -0
  24. package/components/file-input/file-input.js.map +1 -1
  25. package/components/input/input-base.d.ts +2 -2
  26. package/components/input/input-base.js +3 -5
  27. package/components/input/input-base.js.map +1 -1
  28. package/components/input/input.d.ts +1 -1
  29. package/components/radio/radio.d.ts +2 -0
  30. package/components/radio/radio.js +7 -11
  31. package/components/radio/radio.js.map +1 -1
  32. package/components/rating/rating.d.ts +3 -0
  33. package/components/rating/rating.js +17 -18
  34. package/components/rating/rating.js.map +1 -1
  35. package/components/select/select.js +1 -1
  36. package/components/select/select.js.map +1 -1
  37. package/components/slider/range-slider.d.ts +0 -1
  38. package/components/slider/range-slider.js +6 -11
  39. package/components/slider/range-slider.js.map +1 -1
  40. package/components/slider/slider-base.d.ts +4 -1
  41. package/components/slider/slider-base.js +20 -18
  42. package/components/slider/slider-base.js.map +1 -1
  43. package/components/slider/slider.d.ts +2 -0
  44. package/components/slider/slider.js +5 -1
  45. package/components/slider/slider.js.map +1 -1
  46. package/components/textarea/textarea.d.ts +1 -4
  47. package/components/textarea/textarea.js +3 -5
  48. package/components/textarea/textarea.js.map +1 -1
  49. package/components/validation-container/validation-container.js +2 -1
  50. package/components/validation-container/validation-container.js.map +1 -1
  51. package/components/virtualization/engine.d.ts +35 -4
  52. package/components/virtualization/engine.js +126 -61
  53. package/components/virtualization/engine.js.map +1 -1
  54. package/components/virtualization/recycle.d.ts +13 -0
  55. package/components/virtualization/recycle.js +152 -0
  56. package/components/virtualization/recycle.js.map +1 -0
  57. package/components/virtualization/virtualization.d.ts +32 -11
  58. package/components/virtualization/virtualization.js +14 -11
  59. package/components/virtualization/virtualization.js.map +1 -1
  60. package/custom-elements.json +2382 -79
  61. package/igniteui-webcomponents.html-data.json +1 -1
  62. package/index.d.ts +1 -1
  63. package/index.js.map +1 -1
  64. package/internals/controllers/aria-projection.d.ts +61 -23
  65. package/internals/controllers/aria-projection.js +77 -26
  66. package/internals/controllers/aria-projection.js.map +1 -1
  67. package/internals/mixins/forms/associated.js +34 -0
  68. package/internals/mixins/forms/associated.js.map +1 -1
  69. package/internals/mixins/forms/types.d.ts +5 -0
  70. package/internals/mixins/forms/types.js.map +1 -1
  71. package/internals/templates/toggle-shell.d.ts +15 -14
  72. package/internals/templates/toggle-shell.js +12 -8
  73. package/internals/templates/toggle-shell.js.map +1 -1
  74. package/internals/utils/dom.d.ts +2 -2
  75. package/internals/utils/dom.js +2 -2
  76. package/internals/utils/dom.js.map +1 -1
  77. package/package.json +1 -1
  78. package/skills/README.md +2 -4
  79. package/skills/igniteui-wc-choose-components/SKILL.md +2 -1
  80. package/skills/igniteui-wc-customize-component-theme/SKILL.md +2 -1
  81. package/skills/igniteui-wc-figma-to-app/SKILL.md +133 -712
  82. package/skills/igniteui-wc-figma-to-app/references/asset-extraction.md +42 -62
  83. package/skills/igniteui-wc-figma-to-app/references/design-provenance.md +199 -0
  84. package/skills/igniteui-wc-figma-to-app/references/design-token-bridge.md +189 -107
  85. package/skills/igniteui-wc-figma-to-app/references/figma-component-map.md +129 -84
  86. package/skills/igniteui-wc-figma-to-app/references/figma-exploration.md +222 -0
  87. package/skills/igniteui-wc-figma-to-app/references/mcp-setup.md +81 -127
  88. package/skills/igniteui-wc-figma-to-app/references/project-setup.md +105 -0
  89. package/skills/igniteui-wc-figma-to-app/references/theme-generation.md +180 -0
  90. package/skills/igniteui-wc-figma-to-app/references/validation-patterns.md +74 -80
  91. package/skills/igniteui-wc-generate-from-image-design/SKILL.md +2 -1
  92. package/skills/igniteui-wc-generate-from-image-design/references/gotchas.md +3 -3
  93. package/skills/igniteui-wc-grids/SKILL.md +133 -0
  94. package/skills/igniteui-wc-integrate-with-framework/SKILL.md +2 -1
  95. package/skills/igniteui-wc-migrate-grid-lite-to-premium/SKILL.md +2 -1
  96. package/skills/igniteui-wc-optimize-bundle-size/SKILL.md +2 -1
  97. package/web-types.json +1 -1
@@ -3,6 +3,7 @@ import type { Constructor } from '#internals/mixins/constructor.js';
3
3
  import { VirtualScrollEngine } from './engine.js';
4
4
  import { type VirtualScrollDataRequest, VirtualScrollItemContext, type VirtualScrollState } from './types.js';
5
5
  export type VirtualScrollItemTemplate<T> = (context: VirtualScrollItemContext<T>) => TemplateResult | typeof nothing;
6
+ export type VirtualScrollKeyFunction<T> = (item: T, index: number) => unknown;
6
7
  export interface IgcVirtualScrollComponentEventMap {
7
8
  igcStateChange: CustomEvent<VirtualScrollState>;
8
9
  igcDataRequest: CustomEvent<VirtualScrollDataRequest>;
@@ -32,10 +33,8 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
32
33
  private readonly _itemResizeController;
33
34
  private _currentRange;
34
35
  /**
35
- * The item index each wrapper element was last observed under. Lit keeps the
36
- * wrapper elements between renders, so after a scroll one element can hold a
37
- * different item at the same size, which a ResizeObserver does not report.
38
- * See `_scheduleItemMeasurement`.
36
+ * The item index each wrapper element was last observed under. See
37
+ * `_scheduleItemMeasurement`.
39
38
  */
40
39
  private readonly _observedItemIndexes;
41
40
  private _lastEmittedState;
@@ -82,6 +81,8 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
82
81
  /**
83
82
  * Estimated item size in pixels, used before an item is measured in the DOM.
84
83
  * After the first render of an item, the engine replaces the estimate with the measured size.
84
+ * The average measured size also replaces the estimate of the items that are not measured
85
+ * yet, so the scrollbar follows the real content.
85
86
  * @attr estimated-item-size
86
87
  * @default 50
87
88
  */
@@ -98,8 +99,26 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
98
99
  * infer an item's position from the markup. Templates that render a role
99
100
  * with set semantics (`option`, `listitem`, `row`, ...) should map the
100
101
  * context's `index` and `count` onto `aria-posinset` and `aria-setsize`.
102
+ *
103
+ * Item elements are recycled (see `keyFunction`), so DOM state that the
104
+ * template does not bind moves to another item, for example the state of a
105
+ * checkbox without a `checked` binding. Bind all item state. Lit compares a
106
+ * binding with the value that it set last, not with the element, so bind
107
+ * state that the user changes with Lit's `live` directive. Also write user
108
+ * changes back to the item, or they are lost when the item leaves the window.
109
+ * To get new DOM for each item, wrap the content in Lit's `keyed` directive
110
+ * with the item key: `` html`${keyed(ctx.value.id, content)}` ``.
101
111
  */
102
112
  itemTemplate: VirtualScrollItemTemplate<T> | null;
113
+ /**
114
+ * A function that returns a unique key for an item. Receives the item and its index in `data`.
115
+ *
116
+ * An item keeps its rendered element while its key stays in the rendered window. The elements
117
+ * of keys that leave the window are reused for keys that enter it. Without it, the index is the
118
+ * key, so after a `data` change an index keeps its element and shows its new item. Set it when
119
+ * items move within `data`, for example on sort, insert or remove.
120
+ */
121
+ keyFunction: VirtualScrollKeyFunction<T> | null;
103
122
  private _adoptStyles;
104
123
  constructor();
105
124
  /** @internal */
@@ -116,6 +135,8 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
116
135
  private get _normalizedItemSize();
117
136
  /** `data`, guarded against a nullish value set by the consumer. */
118
137
  private get _items();
138
+ /** The key that ties the item at `index` to its rendered element. */
139
+ private _keyOf;
119
140
  /**
120
141
  * The window to render for the current scroll position and viewport. Empty
121
142
  * until an `itemTemplate` is set, because nothing renders without one.
@@ -125,9 +146,6 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
125
146
  * The scroll offset that aligns `index` in the viewport, as `options` gives,
126
147
  * from the current size data of the engine. The same input can give a
127
148
  * different result as more items are measured.
128
- *
129
- * For `block: 'nearest'` on an item in view, returns the current offset, so
130
- * no scroll occurs.
131
149
  */
132
150
  private _getAlignedScrollOffset;
133
151
  /** Applies a scroll offset to the correct axis, accounting for RTL. */
@@ -188,10 +206,9 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
188
206
  * @remarks
189
207
  * `observe` on an already observed element does nothing, so a new
190
208
  * measurement needs `unobserve` and then `observe`. Do this for each element
191
- * whose `data-vs-index` changed. Lit keeps the wrapper elements between
192
- * renders, so after a scroll one element can hold a different item at the
193
- * same size. The observer does not report that, and the new index keeps its
194
- * estimated size.
209
+ * whose `data-vs-index` changed. The wrapper elements are recycled, so after
210
+ * a scroll one element can hold a different item at the same size. The
211
+ * observer does not report that, and the new index keeps its estimated size.
195
212
  */
196
213
  private _scheduleItemMeasurement;
197
214
  /**
@@ -228,6 +245,10 @@ export default class IgcVirtualScrollComponent<T = any> extends IgcVirtualScroll
228
245
  /**
229
246
  * Scrolls to the specified item index.
230
247
  *
248
+ * `block` (`inline` in the horizontal orientation) positions the item as in
249
+ * `scrollIntoView`, and defaults to `start`. With `nearest`, the item
250
+ * scrolls the smallest distance that brings it into view.
251
+ *
231
252
  * Items outside the rendered window have only an estimated size, so the
232
253
  * first jump can miss the target. The items at the landing point are then
233
254
  * measured, and the scroll position is corrected. This repeats until the
@@ -15,6 +15,7 @@ import { EventEmitterMixin } from '#internals/mixins/event-emitter.js';
15
15
  import { isLTR } from '#internals/utils/dom.js';
16
16
  import { asNumber, clamp } from '#internals/utils/math.js';
17
17
  import { VirtualScrollEngine } from './engine.js';
18
+ import { recycle } from './recycle.js';
18
19
  import { VirtualScrollItemContext, } from './types.js';
19
20
  const REMOTE_SCROLLING_THRESHOLD = 5;
20
21
  const MAX_LAYOUT_SETTLE_PASSES = 20;
@@ -131,6 +132,7 @@ export default class IgcVirtualScrollComponent extends EventEmitterMixin(LitElem
131
132
  this.overScan = 2;
132
133
  this.estimatedItemSize = DEFAULT_ESTIMATED_ITEM_SIZE;
133
134
  this.itemTemplate = null;
135
+ this.keyFunction = null;
134
136
  this._engine.onSizeChange = () => this.requestUpdate();
135
137
  this._handleScroll = this._handleScroll.bind(this);
136
138
  addHostListeners(this, {
@@ -206,12 +208,12 @@ export default class IgcVirtualScrollComponent extends EventEmitterMixin(LitElem
206
208
  role="presentation"
207
209
  style=${styleMap(contentStyle)}
208
210
  >
209
- ${visibleItems.map((item, i) => {
211
+ ${recycle(visibleItems, (item, i) => this._keyOf(item, range.startIndex + i), (item, i) => {
210
212
  const itemIndex = range.startIndex + i;
211
213
  const ctx = new VirtualScrollItemContext(item, itemIndex, count);
212
214
  return html `<div role="presentation" data-vs-index=${itemIndex}>
213
- ${this.itemTemplate(ctx)}
214
- </div>`;
215
+ ${this.itemTemplate(ctx)}
216
+ </div>`;
215
217
  })}
216
218
  </div>
217
219
  </div>
@@ -230,22 +232,19 @@ export default class IgcVirtualScrollComponent extends EventEmitterMixin(LitElem
230
232
  get _items() {
231
233
  return this.data ?? [];
232
234
  }
235
+ _keyOf(item, index) {
236
+ return this.keyFunction ? this.keyFunction(item, index) : index;
237
+ }
233
238
  _computeRange() {
234
239
  return this.itemTemplate
235
240
  ? this._engine.getVisibleRange(this._scrollPosition, this._viewportSize, this._normalizedOverScan)
236
241
  : EMPTY_RANGE;
237
242
  }
238
243
  _getAlignedScrollOffset(index, options) {
239
- const requested = this._isVertical
244
+ const position = this._isVertical
240
245
  ? (options?.block ?? 'start')
241
246
  : (options?.inline ?? options?.block ?? 'start');
242
- const current = this._currentAxisScroll();
243
- if (requested === 'nearest' &&
244
- this._engine.isIndexInView(index, current, this._viewportSize)) {
245
- return current;
246
- }
247
- const align = requested === 'center' || requested === 'end' ? requested : 'start';
248
- return this._engine.getAlignedScrollOffset(index, this._viewportSize, align);
247
+ return this._engine.resolveScrollOffset(index, this._currentAxisScroll(), this._viewportSize, position);
249
248
  }
250
249
  _applyScroll(offset, behavior) {
251
250
  if (this._isVertical) {
@@ -344,6 +343,7 @@ export default class IgcVirtualScrollComponent extends EventEmitterMixin(LitElem
344
343
  this._engine.measureItem(index, measured);
345
344
  }
346
345
  }
346
+ this._engine.adaptEstimate(this._currentRange.startIndex);
347
347
  }
348
348
  _scheduleItemMeasurement() {
349
349
  const content = this._contentRef.value;
@@ -480,4 +480,7 @@ __decorate([
480
480
  __decorate([
481
481
  property({ attribute: false })
482
482
  ], IgcVirtualScrollComponent.prototype, "itemTemplate", void 0);
483
+ __decorate([
484
+ property({ attribute: false })
485
+ ], IgcVirtualScrollComponent.prototype, "keyFunction", void 0);
483
486
  //# sourceMappingURL=virtualization.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"virtualization.js","sourceRoot":"","sources":["../../../src/components/virtualization/virtualization.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n html,\n isServer,\n LitElement,\n nothing,\n type PropertyValues,\n type TemplateResult,\n} from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref } from 'lit/directives/ref.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { addHostListeners } from '#internals/controllers/host-listeners.js';\nimport { createResizeObserverController } from '#internals/controllers/resize-observer.js';\nimport { registerComponent } from '#internals/definitions/register.js';\nimport type { Constructor } from '#internals/mixins/constructor.js';\nimport { EventEmitterMixin } from '#internals/mixins/event-emitter.js';\nimport { isLTR } from '#internals/utils/dom.js';\nimport { asNumber, clamp } from '#internals/utils/math.js';\nimport { VirtualScrollEngine } from './engine.js';\nimport {\n type ScrollAlignment,\n type VirtualScrollDataRequest,\n VirtualScrollItemContext,\n type VirtualScrollState,\n type VisibleRange,\n} from './types.js';\n\nexport type VirtualScrollItemTemplate<T> = (\n context: VirtualScrollItemContext<T>\n) => TemplateResult | typeof nothing;\n\nexport interface IgcVirtualScrollComponentEventMap {\n igcStateChange: CustomEvent<VirtualScrollState>;\n igcDataRequest: CustomEvent<VirtualScrollDataRequest>;\n}\n\nconst REMOTE_SCROLLING_THRESHOLD = 5;\nconst MAX_LAYOUT_SETTLE_PASSES = 20;\nconst MAX_SCROLL_CORRECTION_PASSES = 5;\nconst SCROLL_END_TIMEOUT_MS = 2000;\nconst SCROLL_OFFSET_EPSILON_PX = 1;\n/** Fallback for a non-positive `estimatedItemSize`. Equal to its default. */\nconst DEFAULT_ESTIMATED_ITEM_SIZE = 50;\n/** How long the scroll position must stay unchanged to count as settled. */\nconst SCROLL_IDLE_MS = 100;\n/**\n * Upper limit on one `requestAnimationFrame` wait. A hidden tab or a\n * disconnected element gets no frames, and `layoutComplete` must still\n * resolve there.\n */\nconst LAYOUT_FRAME_TIMEOUT_MS = 100;\n\n/**\n * `scrollend` reports exactly when a scroll has settled. Safari before 18.2\n * does not have it, and `_scrollAndWaitForEnd` falls back to a scroll-idle\n * timer there.\n */\nconst SUPPORTS_SCROLL_END = !isServer && 'onscrollend' in window;\n\nconst EMPTY_RANGE: VisibleRange = Object.freeze({\n startIndex: 0,\n endIndex: -1,\n});\n\n/**\n * A virtual scroll component for large lists. Only the items visible in the\n * viewport are rendered.\n *\n * @element igc-virtual-scroll\n *\n * @fires igcStateChange - Emitted when the rendered virtual window changes.\n * @fires igcDataRequest - Emitted when the rendered window comes within a few items of the end\n * of `data`. Also emitted on the first render, when the loaded items do not fill the viewport.\n *\n * @csspart virtualization-track - The full-size element that gives the host its scrollable extent.\n * @csspart virtualization-content - The wrapper that holds the rendered items, translated into\n * position within the track.\n */\nexport default class IgcVirtualScrollComponent<\n T = any,\n> extends EventEmitterMixin<\n IgcVirtualScrollComponentEventMap,\n Constructor<LitElement>\n>(LitElement) {\n public static readonly tagName = 'igc-virtual-scroll';\n\n /* blazorSuppress */\n public static register(): void {\n registerComponent(IgcVirtualScrollComponent);\n }\n\n private static _styleSheet: CSSStyleSheet | null = null;\n\n private static _getStyleSheet(): CSSStyleSheet {\n if (!IgcVirtualScrollComponent._styleSheet) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(`\n :where(igc-virtual-scroll) {\n display: block;\n position: relative;\n overflow: auto;\n height: 18.75rem;\n }\n\n :where(igc-virtual-scroll[orientation='vertical']) {\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) {\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n :where(igc-virtual-scroll) [part=\"virtualization-track\"] {\n position: relative;\n width: 100%;\n min-height: 100%;\n }\n\n :where(igc-virtual-scroll) [part=\"virtualization-content\"] {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n will-change: transform;\n contain: layout style paint;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) [part=\"virtualization-track\"] {\n height: 100%;\n width: auto;\n min-height: unset;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) [part=\"virtualization-content\"] {\n display: flex;\n flex-direction: row;\n height: 100%;\n width: auto;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) [part=\"virtualization-content\"] > [data-vs-index] {\n flex-shrink: 0;\n height: 100%;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']):dir(rtl) [part=\"virtualization-content\"] {\n left: auto;\n right: 0;\n }\n `);\n IgcVirtualScrollComponent._styleSheet = sheet;\n }\n return IgcVirtualScrollComponent._styleSheet;\n }\n\n //#region Internal state\n\n protected readonly _engine = new VirtualScrollEngine();\n private readonly _contentRef = createRef<HTMLDivElement>();\n private readonly _itemResizeController = createResizeObserverController(\n this,\n {\n callback: this._handleItemResize,\n target: null,\n requestUpdate: false,\n }\n );\n\n private _currentRange: VisibleRange = EMPTY_RANGE;\n\n /**\n * The item index each wrapper element was last observed under. Lit keeps the\n * wrapper elements between renders, so after a scroll one element can hold a\n * different item at the same size, which a ResizeObserver does not report.\n * See `_scheduleItemMeasurement`.\n */\n private readonly _observedItemIndexes = new WeakMap<Element, number>();\n private _lastEmittedState: VirtualScrollState | null = null;\n private _hasPendingDataRequest = false;\n private _layoutCompletePromise: Promise<void> | null = null;\n private _scrollRequestId = 0;\n\n /**\n * The `startIndex` of the last `igcDataRequest`, which is also the item count\n * at that emit. See `_checkDataRequest`.\n *\n * Kept across a disconnect, as `_hasPendingDataRequest` is. A move in the DOM\n * does not cancel what the consumer was already asked for, and clearing only\n * one of the two opens the request loop again on reconnect.\n */\n private _lastDataRequestIndex = -1;\n\n /**\n * The live scroll offset on the active axis. Not reactive: `render` reads it\n * only through `_currentRange`, so `_handleScroll` schedules an update only\n * if the window moves.\n */\n private _scrollPosition = 0;\n\n @state()\n private _viewportSize = 0;\n\n //#endregion\n\n //#region Public properties\n\n /**\n * The array of items to virtualize.\n *\n * Compared by reference: a mutation in place (`data.push(...)`) causes no\n * update. Assign a new array instead. The `igcDataRequest` flow also\n * expects a new array.\n */\n @property({ attribute: false })\n public data: T[] = [];\n\n /**\n * Scroll orientation of the virtual scroll.\n * @attr orientation\n * @default 'vertical'\n */\n @property({ reflect: true })\n public orientation: 'vertical' | 'horizontal' = 'vertical';\n\n /**\n * Number of extra items to render beyond the visible area of the viewport.\n * Higher values reduce blank flashes during fast scrolling but can lower performance.\n * @attr over-scan\n * @default 2\n */\n @property({ type: Number, attribute: 'over-scan' })\n public overScan = 2;\n\n /**\n * Estimated item size in pixels, used before an item is measured in the DOM.\n * After the first render of an item, the engine replaces the estimate with the measured size.\n * @attr estimated-item-size\n * @default 50\n */\n @property({ type: Number, attribute: 'estimated-item-size' })\n public estimatedItemSize = DEFAULT_ESTIMATED_ITEM_SIZE;\n\n /**\n * A function that renders each item in the virtual scroll list.\n * Receives a VirtualScrollItemContext<T> with the item data, its index, and the total count.\n * Without it, nothing is rendered.\n *\n * Items are measured by their border box, so margins accumulate as drift\n * down the list. Use padding on the item, or a gap on a wrapper, instead.\n *\n * Only the current window is in the DOM, so assistive technology cannot\n * infer an item's position from the markup. Templates that render a role\n * with set semantics (`option`, `listitem`, `row`, ...) should map the\n * context's `index` and `count` onto `aria-posinset` and `aria-setsize`.\n */\n @property({ attribute: false })\n public itemTemplate: VirtualScrollItemTemplate<T> | null = null;\n\n //#endregion\n\n private _adoptStyles(): void {\n /* c8 ignore next 3 */\n if (isServer) {\n return;\n }\n\n const root = this.getRootNode() as Document | ShadowRoot;\n const sheet = IgcVirtualScrollComponent._getStyleSheet();\n if (!root.adoptedStyleSheets.includes(sheet)) {\n root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];\n }\n }\n\n constructor() {\n super();\n this._engine.onSizeChange = () => this.requestUpdate();\n this._handleScroll = this._handleScroll.bind(this);\n\n addHostListeners(this, {\n events: ['scroll'],\n listener: this._handleScroll,\n options: { passive: true },\n });\n\n // Viewport resize observer\n createResizeObserverController(this, {\n callback: this._measureViewport,\n });\n }\n\n //#region Lit lifecycle\n\n /** @internal */\n public override createRenderRoot(): HTMLElement | DocumentFragment {\n return this;\n }\n\n /** @internal */\n public override connectedCallback(): void {\n super.connectedCallback();\n this._adoptStyles();\n this._engine.initMaxBrowserSize(this.ownerDocument);\n this._measureViewport();\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n // TODO: Either fix this in the theming controller or come up with some other solution.\n\n // Checked on each update, not only in `connectedCallback`, and does\n // nothing if the sheet is there. A host that renders this component in its\n // own shadow root, such as combo, can replace that root's\n // `adoptedStyleSheets` from its theming logic. That drops this sheet while\n // the element stays connected.\n this._adoptStyles();\n\n if (changed.has('data')) {\n this._engine.resize(\n this._items.length,\n this._normalizedItemSize,\n this._firstChangedIndex(changed.get('data'))\n );\n this._hasPendingDataRequest = false;\n }\n\n if (changed.has('estimatedItemSize')) {\n this._engine.updateEstimatedSize(this._normalizedItemSize);\n }\n\n if (changed.has('orientation')) {\n this._measureViewport();\n this._scrollPosition = this._currentAxisScroll();\n }\n\n this._currentRange = this._computeRange();\n }\n\n protected override updated(_changed: PropertyValues<this>): void {\n this._scheduleItemMeasurement();\n this._checkDataRequest();\n this._emitStateChange();\n }\n\n protected override render(): TemplateResult {\n if (!this.itemTemplate) {\n return html`${nothing}`;\n }\n\n const items = this._items;\n const range = this._currentRange;\n const count = items.length;\n const isVertical = this._isVertical;\n\n const trackStyle = isVertical\n ? { height: `${this._engine.domSize}px` }\n : { width: `${this._engine.domSize}px` };\n\n // The content wrapper is absolutely positioned at the origin of a track of\n // `domSize` px. A translation to the scroll offset of the first rendered\n // item puts that item at its virtual position.\n let contentPosition = this._engine.getScrollOffsetForIndex(\n range.startIndex\n );\n const physicalRangeSize = this._engine.getPhysicalRangeSize(\n range.startIndex,\n range.endIndex\n );\n contentPosition = clamp(\n contentPosition,\n 0,\n this._engine.domSize - physicalRangeSize\n );\n const isRTL = !isVertical && !isLTR(this);\n const contentStyle = {\n transform: isVertical\n ? `translateY(${contentPosition}px)`\n : `translateX(${isRTL ? -contentPosition : contentPosition}px)`,\n };\n\n const visibleItems =\n range.endIndex >= range.startIndex\n ? items.slice(range.startIndex, range.endIndex + 1)\n : [];\n\n return html`\n <div\n part=\"virtualization-track\"\n role=\"presentation\"\n style=${styleMap(trackStyle)}\n >\n <div\n ${ref(this._contentRef)}\n part=\"virtualization-content\"\n role=\"presentation\"\n style=${styleMap(contentStyle)}\n >\n ${visibleItems.map((item, i) => {\n const itemIndex = range.startIndex + i;\n const ctx = new VirtualScrollItemContext(item, itemIndex, count);\n return html`<div role=\"presentation\" data-vs-index=${itemIndex}>\n ${this.itemTemplate!(ctx)}\n </div>`;\n })}\n </div>\n </div>\n `;\n }\n\n //#endregion\n\n //#region Internal API\n\n private get _isVertical(): boolean {\n return this.orientation === 'vertical';\n }\n\n /** The configured `overScan`, normalized to a non-negative integer. */\n private get _normalizedOverScan(): number {\n return Math.max(0, Math.floor(asNumber(this.overScan, 2)));\n }\n\n /** The configured `estimatedItemSize`, normalized to a positive number. */\n private get _normalizedItemSize(): number {\n const size = asNumber(this.estimatedItemSize);\n return size > 0 ? size : DEFAULT_ESTIMATED_ITEM_SIZE;\n }\n\n /** `data`, guarded against a nullish value set by the consumer. */\n private get _items(): T[] {\n return this.data ?? [];\n }\n\n /**\n * The window to render for the current scroll position and viewport. Empty\n * until an `itemTemplate` is set, because nothing renders without one.\n */\n private _computeRange(): VisibleRange {\n return this.itemTemplate\n ? this._engine.getVisibleRange(\n this._scrollPosition,\n this._viewportSize,\n this._normalizedOverScan\n )\n : EMPTY_RANGE;\n }\n\n /**\n * The scroll offset that aligns `index` in the viewport, as `options` gives,\n * from the current size data of the engine. The same input can give a\n * different result as more items are measured.\n *\n * For `block: 'nearest'` on an item in view, returns the current offset, so\n * no scroll occurs.\n */\n private _getAlignedScrollOffset(\n index: number,\n options?: ScrollIntoViewOptions\n ): number {\n const requested = this._isVertical\n ? (options?.block ?? 'start')\n : (options?.inline ?? options?.block ?? 'start');\n const current = this._currentAxisScroll();\n\n if (\n requested === 'nearest' &&\n this._engine.isIndexInView(index, current, this._viewportSize)\n ) {\n return current;\n }\n\n const align: ScrollAlignment =\n requested === 'center' || requested === 'end' ? requested : 'start';\n\n return this._engine.getAlignedScrollOffset(\n index,\n this._viewportSize,\n align\n );\n }\n\n /** Applies a scroll offset to the correct axis, accounting for RTL. */\n private _applyScroll(offset: number, behavior: ScrollBehavior): void {\n if (this._isVertical) {\n this.scrollTo({ top: offset, behavior });\n } else {\n this.scrollTo({ left: isLTR(this) ? offset : -offset, behavior });\n }\n }\n\n /** The current real scroll position on the active axis, normalized for RTL. */\n private _currentAxisScroll(): number {\n return this._isVertical\n ? this.scrollTop\n : isLTR(this)\n ? this.scrollLeft\n : -this.scrollLeft;\n }\n\n /**\n * Applies a scroll offset to the active axis, and waits for the scroll to\n * settle.\n *\n * @remarks\n * `scrollend` does not fire if the offset does not move the scroll position,\n * so that case resolves immediately. The timeout covers an event that never\n * arrives, for example when the element disconnects during the scroll.\n */\n private _scrollAndWaitForEnd(\n offset: number,\n behavior: ScrollBehavior\n ): Promise<void> {\n if (\n Math.abs(this._currentAxisScroll() - offset) < SCROLL_OFFSET_EPSILON_PX\n ) {\n return Promise.resolve();\n }\n\n return this._withDeadline(SCROLL_END_TIMEOUT_MS, (signal) => {\n const settled = SUPPORTS_SCROLL_END\n ? this._waitForScrollEnd(signal)\n : this._waitForScrollIdle(signal);\n\n // Applied only after the listener is attached, so an instant scroll\n // cannot settle before something watches for it.\n this._applyScroll(offset, behavior);\n return settled;\n });\n }\n\n /**\n * Resolves with `task`, or with a deadline of `ms`, whichever is first. The\n * signal then stops the other, so no timer or listener stays alive.\n */\n private _withDeadline(\n ms: number,\n task: (signal: AbortSignal) => Promise<void>\n ): Promise<void> {\n const controller = new AbortController();\n\n return Promise.race([\n task(controller.signal),\n this._timeout(ms, controller.signal),\n ]).finally(() => controller.abort());\n }\n\n private _waitForScrollEnd(signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n this.addEventListener('scrollend', () => resolve(), {\n once: true,\n signal,\n });\n });\n }\n\n /**\n * Resolves if no `scroll` event arrives for `SCROLL_IDLE_MS`, which is the\n * closest replacement for `scrollend`. The first timer starts immediately, so\n * a scroll that does not move also settles.\n */\n private _waitForScrollIdle(signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n let id = setTimeout(resolve, SCROLL_IDLE_MS);\n\n this.addEventListener(\n 'scroll',\n () => {\n clearTimeout(id);\n id = setTimeout(resolve, SCROLL_IDLE_MS);\n },\n { passive: true, signal }\n );\n\n signal.addEventListener('abort', () => clearTimeout(id), { once: true });\n });\n }\n\n private _timeout(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const id = setTimeout(resolve, ms);\n signal.addEventListener('abort', () => clearTimeout(id), { once: true });\n });\n }\n\n private _measureViewport(): void {\n this._viewportSize = this._isVertical\n ? this.clientHeight\n : this.clientWidth;\n }\n\n /**\n * Records the new scroll offset. Schedules a render only if the rendered\n * window moves.\n *\n * @remarks\n * `render` reads `_currentRange`, not the scroll offset. Without the guard,\n * a scroll inside one item runs each item template again for the same\n * result. `willUpdate` recomputes `_currentRange` for the other triggers,\n * so this skips only the redundant passes.\n */\n private _handleScroll(): void {\n this._scrollPosition = this._currentAxisScroll();\n\n const { startIndex, endIndex } = this._computeRange();\n if (\n startIndex !== this._currentRange.startIndex ||\n endIndex !== this._currentRange.endIndex\n ) {\n this.requestUpdate();\n }\n }\n\n /**\n * The length of the prefix that a `data` change keeps: the first index at\n * which the old and the new items differ, or the length of the shorter array\n * if neither differs. Measurements below that index stay valid. An append\n * keeps all the previous items. A filter or a replacement keeps fewer.\n *\n * @remarks\n * The test is item identity. An item that changes in place keeps its\n * measured size.\n */\n private _firstChangedIndex(previous: T[] | undefined): number {\n if (!previous) {\n return 0;\n }\n\n const items = this._items;\n const shared = Math.min(previous.length, items.length);\n for (let i = 0; i < shared; i++) {\n if (previous[i] !== items[i]) {\n return i;\n }\n }\n return shared;\n }\n\n private _handleItemResize(entries: ResizeObserverEntry[]): void {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const index = asNumber(el.dataset.vsIndex, -1);\n if (index < 0) continue;\n\n const measured = this._isVertical\n ? (entry.borderBoxSize?.[0]?.blockSize ?? entry.contentRect.height)\n : (entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width);\n\n if (measured > 0) {\n this._engine.measureItem(index, measured);\n }\n }\n }\n\n /**\n * Syncs the item observer with the rendered window, and applies only the\n * difference.\n *\n * @remarks\n * `observe` on an already observed element does nothing, so a new\n * measurement needs `unobserve` and then `observe`. Do this for each element\n * whose `data-vs-index` changed. Lit keeps the wrapper elements between\n * renders, so after a scroll one element can hold a different item at the\n * same size. The observer does not report that, and the new index keeps its\n * estimated size.\n */\n private _scheduleItemMeasurement(): void {\n const content = this._contentRef.value;\n if (!content) return;\n\n const observed = this._itemResizeController.targets;\n\n for (const element of observed) {\n if (element.parentNode !== content) {\n this._itemResizeController.unobserve(element);\n }\n }\n\n for (const element of content.children) {\n const index = asNumber((element as HTMLElement).dataset.vsIndex, -1);\n const isObserved = observed.has(element);\n\n if (isObserved && this._observedItemIndexes.get(element) === index) {\n continue;\n }\n\n if (isObserved) {\n this._itemResizeController.unobserve(element);\n }\n this._itemResizeController.observe(element);\n this._observedItemIndexes.set(element, index);\n }\n }\n\n /**\n * Emits `igcStateChange`. Does nothing if the window is empty or equal to\n * the last reported one, because a measurement pass renders again with no\n * window change.\n */\n private _emitStateChange(): void {\n const { startIndex, endIndex } = this._currentRange;\n if (endIndex < startIndex) return;\n\n const previous = this._lastEmittedState;\n const detail: VirtualScrollState = {\n startIndex,\n endIndex,\n viewportSize: this._viewportSize,\n totalSize: this._engine.totalSize,\n };\n\n if (\n previous &&\n previous.startIndex === detail.startIndex &&\n previous.endIndex === detail.endIndex &&\n previous.viewportSize === detail.viewportSize &&\n previous.totalSize === detail.totalSize\n ) {\n return;\n }\n\n this._lastEmittedState = { ...detail };\n this.emitEvent('igcStateChange', { detail });\n }\n\n private _checkDataRequest(): void {\n if (this._hasPendingDataRequest) return;\n\n const range = this._currentRange;\n const total = this._items.length;\n\n if (total === 0 || range.endIndex < total - REMOTE_SCROLLING_THRESHOLD) {\n return;\n }\n\n // Each `data` change clears `_hasPendingDataRequest`, also one that\n // appends nothing. Without this second guard, a consumer whose source is\n // exhausted and that assigns `data` again for each request gets that same\n // request again.\n if (this._lastDataRequestIndex === total) {\n return;\n }\n\n this._hasPendingDataRequest = true;\n this._lastDataRequestIndex = total;\n\n this.emitEvent('igcDataRequest', {\n detail: {\n startIndex: total,\n count: Math.max(this._normalizedOverScan * 4, 20),\n },\n });\n }\n\n /**\n * Resolves on the next animation frame, or after `LAYOUT_FRAME_TIMEOUT_MS` if\n * no frame arrives. A hidden tab or a disconnected element gets no frames,\n * and `layoutComplete` must still settle. Such a state has no layout to wait\n * for, so an early resolve is safe.\n */\n private _nextFrame(): Promise<void> {\n return this._withDeadline(\n LAYOUT_FRAME_TIMEOUT_MS,\n (signal) =>\n new Promise((resolve) => {\n const id = requestAnimationFrame(() => resolve());\n signal.addEventListener('abort', () => cancelAnimationFrame(id), {\n once: true,\n });\n })\n );\n }\n\n /**\n * Waits for the current update, then lets the ResizeObserver measurements\n * run. If those schedule one more render, for example when a measured size\n * replaces an estimate, the wait repeats until nothing is pending, up to a\n * safety cap.\n */\n private async _resolveLayoutComplete(): Promise<void> {\n try {\n await this.updateComplete;\n\n for (let i = 0; i < MAX_LAYOUT_SETTLE_PASSES; i++) {\n await this._nextFrame();\n\n if (!this.isUpdatePending) {\n break;\n }\n\n await this.updateComplete;\n }\n } finally {\n // Cleared here, not after the loop, so a run that throws cannot leave\n // the getter with a permanently rejected promise.\n this._layoutCompletePromise = null;\n }\n }\n\n //#endregion\n\n //#region Public API\n\n /* blazorSuppress */\n /**\n * Resolves when the virtual scroll has settled: the current render pass is\n * complete, the item-size measurements it triggers are complete, and so\n * are the renders those measurements schedule.\n *\n * `updateComplete` covers one Lit render pass. This covers `data` changes,\n * scrolls, and viewport resizes, where the stable DOM state comes after\n * one or more follow-up renders.\n */\n public get layoutComplete(): Promise<void> {\n if (!this._layoutCompletePromise) {\n this._layoutCompletePromise = this._resolveLayoutComplete();\n }\n return this._layoutCompletePromise;\n }\n\n /**\n * Scrolls to the specified item index.\n *\n * Items outside the rendered window have only an estimated size, so the\n * first jump can miss the target. The items at the landing point are then\n * measured, and the scroll position is corrected. This repeats until the\n * offset is stable.\n *\n * The returned promise resolves when the scroll settles on the final,\n * corrected offset. Callers that need only the first, approximate scroll\n * can ignore it.\n */\n public async scrollToIndex(\n index: number,\n options?: ScrollIntoViewOptions\n ): Promise<void> {\n const maxIndex = Math.max(0, this._items.length - 1);\n const clampedIndex = clamp(index, 0, maxIndex);\n const behavior = options?.behavior ?? 'auto';\n\n // A newer call supersedes a correction loop that still runs for a\n // previous call, for example under rapid, repeated calls.\n const requestId = ++this._scrollRequestId;\n\n let offset = this._getAlignedScrollOffset(clampedIndex, options);\n await this._scrollAndWaitForEnd(offset, behavior);\n\n for (let i = 0; i < MAX_SCROLL_CORRECTION_PASSES; i++) {\n await this.layoutComplete;\n\n if (requestId !== this._scrollRequestId) {\n return;\n }\n\n const corrected = this._getAlignedScrollOffset(clampedIndex, options);\n if (Math.abs(corrected - offset) < SCROLL_OFFSET_EPSILON_PX) {\n break;\n }\n\n offset = corrected;\n await this._scrollAndWaitForEnd(offset, 'auto');\n\n if (requestId !== this._scrollRequestId) {\n return;\n }\n }\n }\n\n //#endregion\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-virtual-scroll': IgcVirtualScrollComponent;\n }\n}\n"]}
1
+ {"version":3,"file":"virtualization.js","sourceRoot":"","sources":["../../../src/components/virtualization/virtualization.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n html,\n isServer,\n LitElement,\n nothing,\n type PropertyValues,\n type TemplateResult,\n} from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref } from 'lit/directives/ref.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { addHostListeners } from '#internals/controllers/host-listeners.js';\nimport { createResizeObserverController } from '#internals/controllers/resize-observer.js';\nimport { registerComponent } from '#internals/definitions/register.js';\nimport type { Constructor } from '#internals/mixins/constructor.js';\nimport { EventEmitterMixin } from '#internals/mixins/event-emitter.js';\nimport { isLTR } from '#internals/utils/dom.js';\nimport { asNumber, clamp } from '#internals/utils/math.js';\nimport { VirtualScrollEngine } from './engine.js';\nimport { recycle } from './recycle.js';\nimport {\n type VirtualScrollDataRequest,\n VirtualScrollItemContext,\n type VirtualScrollState,\n type VisibleRange,\n} from './types.js';\n\nexport type VirtualScrollItemTemplate<T> = (\n context: VirtualScrollItemContext<T>\n) => TemplateResult | typeof nothing;\n\nexport type VirtualScrollKeyFunction<T> = (item: T, index: number) => unknown;\n\nexport interface IgcVirtualScrollComponentEventMap {\n igcStateChange: CustomEvent<VirtualScrollState>;\n igcDataRequest: CustomEvent<VirtualScrollDataRequest>;\n}\n\nconst REMOTE_SCROLLING_THRESHOLD = 5;\nconst MAX_LAYOUT_SETTLE_PASSES = 20;\nconst MAX_SCROLL_CORRECTION_PASSES = 5;\nconst SCROLL_END_TIMEOUT_MS = 2000;\nconst SCROLL_OFFSET_EPSILON_PX = 1;\n/** Fallback for a non-positive `estimatedItemSize`. Equal to its default. */\nconst DEFAULT_ESTIMATED_ITEM_SIZE = 50;\n/** How long the scroll position must stay unchanged to count as settled. */\nconst SCROLL_IDLE_MS = 100;\n/**\n * Upper limit on one `requestAnimationFrame` wait. A hidden tab or a\n * disconnected element gets no frames, and `layoutComplete` must still\n * resolve there.\n */\nconst LAYOUT_FRAME_TIMEOUT_MS = 100;\n\n/**\n * `scrollend` reports exactly when a scroll has settled. Safari before 18.2\n * does not have it, and `_scrollAndWaitForEnd` falls back to a scroll-idle\n * timer there.\n */\nconst SUPPORTS_SCROLL_END = !isServer && 'onscrollend' in window;\n\nconst EMPTY_RANGE: VisibleRange = Object.freeze({\n startIndex: 0,\n endIndex: -1,\n});\n\n/**\n * A virtual scroll component for large lists. Only the items visible in the\n * viewport are rendered.\n *\n * @element igc-virtual-scroll\n *\n * @fires igcStateChange - Emitted when the rendered virtual window changes.\n * @fires igcDataRequest - Emitted when the rendered window comes within a few items of the end\n * of `data`. Also emitted on the first render, when the loaded items do not fill the viewport.\n *\n * @csspart virtualization-track - The full-size element that gives the host its scrollable extent.\n * @csspart virtualization-content - The wrapper that holds the rendered items, translated into\n * position within the track.\n */\nexport default class IgcVirtualScrollComponent<\n T = any,\n> extends EventEmitterMixin<\n IgcVirtualScrollComponentEventMap,\n Constructor<LitElement>\n>(LitElement) {\n public static readonly tagName = 'igc-virtual-scroll';\n\n /* blazorSuppress */\n public static register(): void {\n registerComponent(IgcVirtualScrollComponent);\n }\n\n private static _styleSheet: CSSStyleSheet | null = null;\n\n private static _getStyleSheet(): CSSStyleSheet {\n if (!IgcVirtualScrollComponent._styleSheet) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(`\n :where(igc-virtual-scroll) {\n display: block;\n position: relative;\n overflow: auto;\n height: 18.75rem;\n }\n\n :where(igc-virtual-scroll[orientation='vertical']) {\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) {\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n :where(igc-virtual-scroll) [part=\"virtualization-track\"] {\n position: relative;\n width: 100%;\n min-height: 100%;\n }\n\n :where(igc-virtual-scroll) [part=\"virtualization-content\"] {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n will-change: transform;\n contain: layout style paint;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) [part=\"virtualization-track\"] {\n height: 100%;\n width: auto;\n min-height: unset;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) [part=\"virtualization-content\"] {\n display: flex;\n flex-direction: row;\n height: 100%;\n width: auto;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']) [part=\"virtualization-content\"] > [data-vs-index] {\n flex-shrink: 0;\n height: 100%;\n }\n\n :where(igc-virtual-scroll[orientation='horizontal']):dir(rtl) [part=\"virtualization-content\"] {\n left: auto;\n right: 0;\n }\n `);\n IgcVirtualScrollComponent._styleSheet = sheet;\n }\n return IgcVirtualScrollComponent._styleSheet;\n }\n\n //#region Internal state\n\n protected readonly _engine = new VirtualScrollEngine();\n private readonly _contentRef = createRef<HTMLDivElement>();\n private readonly _itemResizeController = createResizeObserverController(\n this,\n {\n callback: this._handleItemResize,\n target: null,\n requestUpdate: false,\n }\n );\n\n private _currentRange: VisibleRange = EMPTY_RANGE;\n\n /**\n * The item index each wrapper element was last observed under. See\n * `_scheduleItemMeasurement`.\n */\n private readonly _observedItemIndexes = new WeakMap<Element, number>();\n private _lastEmittedState: VirtualScrollState | null = null;\n private _hasPendingDataRequest = false;\n private _layoutCompletePromise: Promise<void> | null = null;\n private _scrollRequestId = 0;\n\n /**\n * The `startIndex` of the last `igcDataRequest`, which is also the item count\n * at that emit. See `_checkDataRequest`.\n *\n * Kept across a disconnect, as `_hasPendingDataRequest` is. A move in the DOM\n * does not cancel what the consumer was already asked for, and clearing only\n * one of the two opens the request loop again on reconnect.\n */\n private _lastDataRequestIndex = -1;\n\n /**\n * The live scroll offset on the active axis. Not reactive: `render` reads it\n * only through `_currentRange`, so `_handleScroll` schedules an update only\n * if the window moves.\n */\n private _scrollPosition = 0;\n\n @state()\n private _viewportSize = 0;\n\n //#endregion\n\n //#region Public properties\n\n /**\n * The array of items to virtualize.\n *\n * Compared by reference: a mutation in place (`data.push(...)`) causes no\n * update. Assign a new array instead. The `igcDataRequest` flow also\n * expects a new array.\n */\n @property({ attribute: false })\n public data: T[] = [];\n\n /**\n * Scroll orientation of the virtual scroll.\n * @attr orientation\n * @default 'vertical'\n */\n @property({ reflect: true })\n public orientation: 'vertical' | 'horizontal' = 'vertical';\n\n /**\n * Number of extra items to render beyond the visible area of the viewport.\n * Higher values reduce blank flashes during fast scrolling but can lower performance.\n * @attr over-scan\n * @default 2\n */\n @property({ type: Number, attribute: 'over-scan' })\n public overScan = 2;\n\n /**\n * Estimated item size in pixels, used before an item is measured in the DOM.\n * After the first render of an item, the engine replaces the estimate with the measured size.\n * The average measured size also replaces the estimate of the items that are not measured\n * yet, so the scrollbar follows the real content.\n * @attr estimated-item-size\n * @default 50\n */\n @property({ type: Number, attribute: 'estimated-item-size' })\n public estimatedItemSize = DEFAULT_ESTIMATED_ITEM_SIZE;\n\n /**\n * A function that renders each item in the virtual scroll list.\n * Receives a VirtualScrollItemContext<T> with the item data, its index, and the total count.\n * Without it, nothing is rendered.\n *\n * Items are measured by their border box, so margins accumulate as drift\n * down the list. Use padding on the item, or a gap on a wrapper, instead.\n *\n * Only the current window is in the DOM, so assistive technology cannot\n * infer an item's position from the markup. Templates that render a role\n * with set semantics (`option`, `listitem`, `row`, ...) should map the\n * context's `index` and `count` onto `aria-posinset` and `aria-setsize`.\n *\n * Item elements are recycled (see `keyFunction`), so DOM state that the\n * template does not bind moves to another item, for example the state of a\n * checkbox without a `checked` binding. Bind all item state. Lit compares a\n * binding with the value that it set last, not with the element, so bind\n * state that the user changes with Lit's `live` directive. Also write user\n * changes back to the item, or they are lost when the item leaves the window.\n * To get new DOM for each item, wrap the content in Lit's `keyed` directive\n * with the item key: `` html`${keyed(ctx.value.id, content)}` ``.\n */\n @property({ attribute: false })\n public itemTemplate: VirtualScrollItemTemplate<T> | null = null;\n\n /* blazorSuppress */\n /**\n * A function that returns a unique key for an item. Receives the item and its index in `data`.\n *\n * An item keeps its rendered element while its key stays in the rendered window. The elements\n * of keys that leave the window are reused for keys that enter it. Without it, the index is the\n * key, so after a `data` change an index keeps its element and shows its new item. Set it when\n * items move within `data`, for example on sort, insert or remove.\n */\n @property({ attribute: false })\n public keyFunction: VirtualScrollKeyFunction<T> | null = null;\n\n //#endregion\n\n private _adoptStyles(): void {\n /* c8 ignore next 3 */\n if (isServer) {\n return;\n }\n\n const root = this.getRootNode() as Document | ShadowRoot;\n const sheet = IgcVirtualScrollComponent._getStyleSheet();\n if (!root.adoptedStyleSheets.includes(sheet)) {\n root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];\n }\n }\n\n constructor() {\n super();\n this._engine.onSizeChange = () => this.requestUpdate();\n this._handleScroll = this._handleScroll.bind(this);\n\n addHostListeners(this, {\n events: ['scroll'],\n listener: this._handleScroll,\n options: { passive: true },\n });\n\n // Viewport resize observer\n createResizeObserverController(this, {\n callback: this._measureViewport,\n });\n }\n\n //#region Lit lifecycle\n\n /** @internal */\n public override createRenderRoot(): HTMLElement | DocumentFragment {\n return this;\n }\n\n /** @internal */\n public override connectedCallback(): void {\n super.connectedCallback();\n this._adoptStyles();\n this._engine.initMaxBrowserSize(this.ownerDocument);\n this._measureViewport();\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n // TODO: Either fix this in the theming controller or come up with some other solution.\n\n // Checked on each update, not only in `connectedCallback`, and does\n // nothing if the sheet is there. A host that renders this component in its\n // own shadow root, such as combo, can replace that root's\n // `adoptedStyleSheets` from its theming logic. That drops this sheet while\n // the element stays connected.\n this._adoptStyles();\n\n if (changed.has('data')) {\n this._engine.resize(\n this._items.length,\n this._normalizedItemSize,\n this._firstChangedIndex(changed.get('data'))\n );\n this._hasPendingDataRequest = false;\n }\n\n if (changed.has('estimatedItemSize')) {\n this._engine.updateEstimatedSize(this._normalizedItemSize);\n }\n\n if (changed.has('orientation')) {\n this._measureViewport();\n this._scrollPosition = this._currentAxisScroll();\n }\n\n this._currentRange = this._computeRange();\n }\n\n protected override updated(_changed: PropertyValues<this>): void {\n this._scheduleItemMeasurement();\n this._checkDataRequest();\n this._emitStateChange();\n }\n\n protected override render(): TemplateResult {\n if (!this.itemTemplate) {\n return html`${nothing}`;\n }\n\n const items = this._items;\n const range = this._currentRange;\n const count = items.length;\n const isVertical = this._isVertical;\n\n const trackStyle = isVertical\n ? { height: `${this._engine.domSize}px` }\n : { width: `${this._engine.domSize}px` };\n\n // The content wrapper is absolutely positioned at the origin of a track of\n // `domSize` px. A translation to the scroll offset of the first rendered\n // item puts that item at its virtual position.\n let contentPosition = this._engine.getScrollOffsetForIndex(\n range.startIndex\n );\n const physicalRangeSize = this._engine.getPhysicalRangeSize(\n range.startIndex,\n range.endIndex\n );\n contentPosition = clamp(\n contentPosition,\n 0,\n this._engine.domSize - physicalRangeSize\n );\n const isRTL = !isVertical && !isLTR(this);\n const contentStyle = {\n transform: isVertical\n ? `translateY(${contentPosition}px)`\n : `translateX(${isRTL ? -contentPosition : contentPosition}px)`,\n };\n\n const visibleItems =\n range.endIndex >= range.startIndex\n ? items.slice(range.startIndex, range.endIndex + 1)\n : [];\n\n return html`\n <div\n part=\"virtualization-track\"\n role=\"presentation\"\n style=${styleMap(trackStyle)}\n >\n <div\n ${ref(this._contentRef)}\n part=\"virtualization-content\"\n role=\"presentation\"\n style=${styleMap(contentStyle)}\n >\n ${recycle(\n visibleItems,\n (item, i) => this._keyOf(item, range.startIndex + i),\n (item, i) => {\n const itemIndex = range.startIndex + i;\n const ctx = new VirtualScrollItemContext(item, itemIndex, count);\n return html`<div role=\"presentation\" data-vs-index=${itemIndex}>\n ${this.itemTemplate!(ctx)}\n </div>`;\n }\n )}\n </div>\n </div>\n `;\n }\n\n //#endregion\n\n //#region Internal API\n\n private get _isVertical(): boolean {\n return this.orientation === 'vertical';\n }\n\n /** The configured `overScan`, normalized to a non-negative integer. */\n private get _normalizedOverScan(): number {\n return Math.max(0, Math.floor(asNumber(this.overScan, 2)));\n }\n\n /** The configured `estimatedItemSize`, normalized to a positive number. */\n private get _normalizedItemSize(): number {\n const size = asNumber(this.estimatedItemSize);\n return size > 0 ? size : DEFAULT_ESTIMATED_ITEM_SIZE;\n }\n\n /** `data`, guarded against a nullish value set by the consumer. */\n private get _items(): T[] {\n return this.data ?? [];\n }\n\n /** The key that ties the item at `index` to its rendered element. */\n private _keyOf(item: T, index: number): unknown {\n return this.keyFunction ? this.keyFunction(item, index) : index;\n }\n\n /**\n * The window to render for the current scroll position and viewport. Empty\n * until an `itemTemplate` is set, because nothing renders without one.\n */\n private _computeRange(): VisibleRange {\n return this.itemTemplate\n ? this._engine.getVisibleRange(\n this._scrollPosition,\n this._viewportSize,\n this._normalizedOverScan\n )\n : EMPTY_RANGE;\n }\n\n /**\n * The scroll offset that aligns `index` in the viewport, as `options` gives,\n * from the current size data of the engine. The same input can give a\n * different result as more items are measured.\n */\n private _getAlignedScrollOffset(\n index: number,\n options?: ScrollIntoViewOptions\n ): number {\n const position = this._isVertical\n ? (options?.block ?? 'start')\n : (options?.inline ?? options?.block ?? 'start');\n\n return this._engine.resolveScrollOffset(\n index,\n this._currentAxisScroll(),\n this._viewportSize,\n position\n );\n }\n\n /** Applies a scroll offset to the correct axis, accounting for RTL. */\n private _applyScroll(offset: number, behavior: ScrollBehavior): void {\n if (this._isVertical) {\n this.scrollTo({ top: offset, behavior });\n } else {\n this.scrollTo({ left: isLTR(this) ? offset : -offset, behavior });\n }\n }\n\n /** The current real scroll position on the active axis, normalized for RTL. */\n private _currentAxisScroll(): number {\n return this._isVertical\n ? this.scrollTop\n : isLTR(this)\n ? this.scrollLeft\n : -this.scrollLeft;\n }\n\n /**\n * Applies a scroll offset to the active axis, and waits for the scroll to\n * settle.\n *\n * @remarks\n * `scrollend` does not fire if the offset does not move the scroll position,\n * so that case resolves immediately. The timeout covers an event that never\n * arrives, for example when the element disconnects during the scroll.\n */\n private _scrollAndWaitForEnd(\n offset: number,\n behavior: ScrollBehavior\n ): Promise<void> {\n if (\n Math.abs(this._currentAxisScroll() - offset) < SCROLL_OFFSET_EPSILON_PX\n ) {\n return Promise.resolve();\n }\n\n return this._withDeadline(SCROLL_END_TIMEOUT_MS, (signal) => {\n const settled = SUPPORTS_SCROLL_END\n ? this._waitForScrollEnd(signal)\n : this._waitForScrollIdle(signal);\n\n // Applied only after the listener is attached, so an instant scroll\n // cannot settle before something watches for it.\n this._applyScroll(offset, behavior);\n return settled;\n });\n }\n\n /**\n * Resolves with `task`, or with a deadline of `ms`, whichever is first. The\n * signal then stops the other, so no timer or listener stays alive.\n */\n private _withDeadline(\n ms: number,\n task: (signal: AbortSignal) => Promise<void>\n ): Promise<void> {\n const controller = new AbortController();\n\n return Promise.race([\n task(controller.signal),\n this._timeout(ms, controller.signal),\n ]).finally(() => controller.abort());\n }\n\n private _waitForScrollEnd(signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n this.addEventListener('scrollend', () => resolve(), {\n once: true,\n signal,\n });\n });\n }\n\n /**\n * Resolves if no `scroll` event arrives for `SCROLL_IDLE_MS`, which is the\n * closest replacement for `scrollend`. The first timer starts immediately, so\n * a scroll that does not move also settles.\n */\n private _waitForScrollIdle(signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n let id = setTimeout(resolve, SCROLL_IDLE_MS);\n\n this.addEventListener(\n 'scroll',\n () => {\n clearTimeout(id);\n id = setTimeout(resolve, SCROLL_IDLE_MS);\n },\n { passive: true, signal }\n );\n\n signal.addEventListener('abort', () => clearTimeout(id), { once: true });\n });\n }\n\n private _timeout(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const id = setTimeout(resolve, ms);\n signal.addEventListener('abort', () => clearTimeout(id), { once: true });\n });\n }\n\n private _measureViewport(): void {\n this._viewportSize = this._isVertical\n ? this.clientHeight\n : this.clientWidth;\n }\n\n /**\n * Records the new scroll offset. Schedules a render only if the rendered\n * window moves.\n *\n * @remarks\n * `render` reads `_currentRange`, not the scroll offset. Without the guard,\n * a scroll inside one item runs each item template again for the same\n * result. `willUpdate` recomputes `_currentRange` for the other triggers,\n * so this skips only the redundant passes.\n */\n private _handleScroll(): void {\n this._scrollPosition = this._currentAxisScroll();\n\n const { startIndex, endIndex } = this._computeRange();\n if (\n startIndex !== this._currentRange.startIndex ||\n endIndex !== this._currentRange.endIndex\n ) {\n this.requestUpdate();\n }\n }\n\n /**\n * The length of the prefix that a `data` change keeps: the first index at\n * which the old and the new items differ, or the length of the shorter array\n * if neither differs. Measurements below that index stay valid. An append\n * keeps all the previous items. A filter or a replacement keeps fewer.\n *\n * @remarks\n * The test is item identity. An item that changes in place keeps its\n * measured size.\n */\n private _firstChangedIndex(previous: T[] | undefined): number {\n if (!previous) {\n return 0;\n }\n\n const items = this._items;\n const shared = Math.min(previous.length, items.length);\n for (let i = 0; i < shared; i++) {\n if (previous[i] !== items[i]) {\n return i;\n }\n }\n return shared;\n }\n\n private _handleItemResize(entries: ResizeObserverEntry[]): void {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const index = asNumber(el.dataset.vsIndex, -1);\n if (index < 0) continue;\n\n const measured = this._isVertical\n ? (entry.borderBoxSize?.[0]?.blockSize ?? entry.contentRect.height)\n : (entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width);\n\n if (measured > 0) {\n this._engine.measureItem(index, measured);\n }\n }\n\n this._engine.adaptEstimate(this._currentRange.startIndex);\n }\n\n /**\n * Syncs the item observer with the rendered window, and applies only the\n * difference.\n *\n * @remarks\n * `observe` on an already observed element does nothing, so a new\n * measurement needs `unobserve` and then `observe`. Do this for each element\n * whose `data-vs-index` changed. The wrapper elements are recycled, so after\n * a scroll one element can hold a different item at the same size. The\n * observer does not report that, and the new index keeps its estimated size.\n */\n private _scheduleItemMeasurement(): void {\n const content = this._contentRef.value;\n if (!content) return;\n\n const observed = this._itemResizeController.targets;\n\n for (const element of observed) {\n if (element.parentNode !== content) {\n this._itemResizeController.unobserve(element);\n }\n }\n\n for (const element of content.children) {\n const index = asNumber((element as HTMLElement).dataset.vsIndex, -1);\n const isObserved = observed.has(element);\n\n if (isObserved && this._observedItemIndexes.get(element) === index) {\n continue;\n }\n\n if (isObserved) {\n this._itemResizeController.unobserve(element);\n }\n this._itemResizeController.observe(element);\n this._observedItemIndexes.set(element, index);\n }\n }\n\n /**\n * Emits `igcStateChange`. Does nothing if the window is empty or equal to\n * the last reported one, because a measurement pass renders again with no\n * window change.\n */\n private _emitStateChange(): void {\n const { startIndex, endIndex } = this._currentRange;\n if (endIndex < startIndex) return;\n\n const previous = this._lastEmittedState;\n const detail: VirtualScrollState = {\n startIndex,\n endIndex,\n viewportSize: this._viewportSize,\n totalSize: this._engine.totalSize,\n };\n\n if (\n previous &&\n previous.startIndex === detail.startIndex &&\n previous.endIndex === detail.endIndex &&\n previous.viewportSize === detail.viewportSize &&\n previous.totalSize === detail.totalSize\n ) {\n return;\n }\n\n this._lastEmittedState = { ...detail };\n this.emitEvent('igcStateChange', { detail });\n }\n\n private _checkDataRequest(): void {\n if (this._hasPendingDataRequest) return;\n\n const range = this._currentRange;\n const total = this._items.length;\n\n if (total === 0 || range.endIndex < total - REMOTE_SCROLLING_THRESHOLD) {\n return;\n }\n\n // Each `data` change clears `_hasPendingDataRequest`, also one that\n // appends nothing. Without this second guard, a consumer whose source is\n // exhausted and that assigns `data` again for each request gets that same\n // request again.\n if (this._lastDataRequestIndex === total) {\n return;\n }\n\n this._hasPendingDataRequest = true;\n this._lastDataRequestIndex = total;\n\n this.emitEvent('igcDataRequest', {\n detail: {\n startIndex: total,\n count: Math.max(this._normalizedOverScan * 4, 20),\n },\n });\n }\n\n /**\n * Resolves on the next animation frame, or after `LAYOUT_FRAME_TIMEOUT_MS` if\n * no frame arrives. A hidden tab or a disconnected element gets no frames,\n * and `layoutComplete` must still settle. Such a state has no layout to wait\n * for, so an early resolve is safe.\n */\n private _nextFrame(): Promise<void> {\n return this._withDeadline(\n LAYOUT_FRAME_TIMEOUT_MS,\n (signal) =>\n new Promise((resolve) => {\n const id = requestAnimationFrame(() => resolve());\n signal.addEventListener('abort', () => cancelAnimationFrame(id), {\n once: true,\n });\n })\n );\n }\n\n /**\n * Waits for the current update, then lets the ResizeObserver measurements\n * run. If those schedule one more render, for example when a measured size\n * replaces an estimate, the wait repeats until nothing is pending, up to a\n * safety cap.\n */\n private async _resolveLayoutComplete(): Promise<void> {\n try {\n await this.updateComplete;\n\n for (let i = 0; i < MAX_LAYOUT_SETTLE_PASSES; i++) {\n await this._nextFrame();\n\n if (!this.isUpdatePending) {\n break;\n }\n\n await this.updateComplete;\n }\n } finally {\n // Cleared here, not after the loop, so a run that throws cannot leave\n // the getter with a permanently rejected promise.\n this._layoutCompletePromise = null;\n }\n }\n\n //#endregion\n\n //#region Public API\n\n /* blazorSuppress */\n /**\n * Resolves when the virtual scroll has settled: the current render pass is\n * complete, the item-size measurements it triggers are complete, and so\n * are the renders those measurements schedule.\n *\n * `updateComplete` covers one Lit render pass. This covers `data` changes,\n * scrolls, and viewport resizes, where the stable DOM state comes after\n * one or more follow-up renders.\n */\n public get layoutComplete(): Promise<void> {\n if (!this._layoutCompletePromise) {\n this._layoutCompletePromise = this._resolveLayoutComplete();\n }\n return this._layoutCompletePromise;\n }\n\n /**\n * Scrolls to the specified item index.\n *\n * `block` (`inline` in the horizontal orientation) positions the item as in\n * `scrollIntoView`, and defaults to `start`. With `nearest`, the item\n * scrolls the smallest distance that brings it into view.\n *\n * Items outside the rendered window have only an estimated size, so the\n * first jump can miss the target. The items at the landing point are then\n * measured, and the scroll position is corrected. This repeats until the\n * offset is stable.\n *\n * The returned promise resolves when the scroll settles on the final,\n * corrected offset. Callers that need only the first, approximate scroll\n * can ignore it.\n */\n public async scrollToIndex(\n index: number,\n options?: ScrollIntoViewOptions\n ): Promise<void> {\n const maxIndex = Math.max(0, this._items.length - 1);\n const clampedIndex = clamp(index, 0, maxIndex);\n const behavior = options?.behavior ?? 'auto';\n\n // A newer call supersedes a correction loop that still runs for a\n // previous call, for example under rapid, repeated calls.\n const requestId = ++this._scrollRequestId;\n\n let offset = this._getAlignedScrollOffset(clampedIndex, options);\n await this._scrollAndWaitForEnd(offset, behavior);\n\n for (let i = 0; i < MAX_SCROLL_CORRECTION_PASSES; i++) {\n await this.layoutComplete;\n\n if (requestId !== this._scrollRequestId) {\n return;\n }\n\n const corrected = this._getAlignedScrollOffset(clampedIndex, options);\n if (Math.abs(corrected - offset) < SCROLL_OFFSET_EPSILON_PX) {\n break;\n }\n\n offset = corrected;\n await this._scrollAndWaitForEnd(offset, 'auto');\n\n if (requestId !== this._scrollRequestId) {\n return;\n }\n }\n }\n\n //#endregion\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-virtual-scroll': IgcVirtualScrollComponent;\n }\n}\n"]}