@cas-smartdesign/virtual-list 7.2.1 → 9.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-list.mjs","sources":["../list-util.ts","../data-provider.ts","../virtual-list.ts"],"sourcesContent":["export type ScrollToAlignment = \"auto\" | \"center\" | \"start\" | \"end\";\n\nexport interface IListUtil {\n getOffsetForIndexAndAlignment(\n index: number,\n alignment: ScrollToAlignment,\n scrollOffset: number,\n itemHeight: number,\n height: number,\n itemCount: number,\n ): number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n debounce(func: (...args: any) => void): () => void;\n}\n\nclass ListUtil implements IListUtil {\n public getOffsetForIndexAndAlignment(\n index: number,\n alignment: ScrollToAlignment,\n scrollOffset: number,\n itemHeight: number,\n height: number,\n itemCount: number,\n ): number {\n const lastItemOffset = Math.max(0, itemCount * itemHeight);\n const maxOffset = Math.min(lastItemOffset, index * itemHeight);\n const minOffset = Math.max(0, index * itemHeight - height + itemHeight);\n\n switch (alignment) {\n case \"start\":\n return maxOffset;\n case \"end\":\n return minOffset;\n case \"center\": {\n const middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);\n if (middleOffset < Math.ceil(height / 2)) {\n return 0;\n } else if (middleOffset > lastItemOffset + Math.floor(height / 2)) {\n return lastItemOffset;\n } else {\n return middleOffset;\n }\n }\n case \"auto\":\n default:\n if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {\n return scrollOffset;\n } else if (scrollOffset < minOffset) {\n return minOffset;\n } else {\n return maxOffset;\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public debounce(func: (...args: any) => void): (...args: unknown[]) => void {\n let timer: number;\n return (...args: unknown[]) => {\n if (timer) {\n window.cancelAnimationFrame(timer);\n }\n timer = window.requestAnimationFrame(() => {\n func(...args);\n timer = null;\n });\n };\n }\n}\n\nexport default new ListUtil();\n","import VirtualList from \"./virtual-list\";\n\nexport class ListDataProvider {\n public onDataRequest: (page: number) => void;\n\n private _finalSizeIsKnown = false;\n private _itemCache: unknown[] = [];\n private _lastRequestedFirstIndex = 0;\n private _lastRequestedLastIndex = 0;\n private _lastLoadedIndex = 0;\n private _list: VirtualList;\n private _itemCount: number;\n private _pendingDataRequest: boolean;\n\n constructor(\n public pageSize: number = 100,\n public preloadedItemsCount: number = 5,\n ) {\n this.itemCount = pageSize; // configure initial load\n }\n\n public get currentPage(): number {\n if (this.items.length == 0 && this.finalSizeIsKnown) {\n return 0; // Otherwise empty cache means we haven't fetched anything\n }\n // With pageSize 100\n // 0 => -1\n // 1 100 => 0\n // 101 200 => 1\n return Math.floor((this.items.length - 1) / this.pageSize);\n }\n\n public get finalSizeIsKnown(): boolean {\n return this._finalSizeIsKnown;\n }\n\n public set finalSizeIsKnown(value: boolean) {\n this._finalSizeIsKnown = value;\n if (value) {\n this.itemCount = this._itemCache.length;\n }\n if (this._list) {\n this._list.finalSizeIsKnown = value;\n }\n }\n\n private get itemCount(): number {\n return this._itemCount;\n }\n\n private set itemCount(count: number) {\n this._itemCount = count;\n if (this._list) {\n this._list.itemCount = count;\n }\n }\n\n public get items(): unknown[] {\n return this._itemCache;\n }\n\n public set items(items: unknown[]) {\n this._itemCache = items;\n this.onItemsChange();\n }\n\n public addItems(items: unknown[]): void {\n this._itemCache = this._itemCache.concat(items);\n this.onItemsChange();\n }\n\n public connectList(list: VirtualList): void {\n if (this._list) {\n this._list.removeEventListener(\"data-request\", this.handleListDataRequest);\n }\n this._list = list;\n list.itemCount = this.itemCount;\n list.addEventListener(\"data-request\", this.handleListDataRequest);\n list.finalSizeIsKnown = this._finalSizeIsKnown;\n }\n\n private onItemsChange(): void {\n this._pendingDataRequest = false;\n this._lastLoadedIndex = this._itemCache.length - 1;\n if (this.finalSizeIsKnown) {\n this.itemCount = this._itemCache.length;\n } else if (this._lastLoadedIndex > this.itemCount) {\n this.itemCount = this._lastLoadedIndex;\n }\n if (this._list) {\n this._list.items = this._itemCache.slice(this._lastRequestedFirstIndex, this._lastRequestedLastIndex + 1);\n }\n }\n\n private handleListDataRequest = (event: CustomEvent) => {\n const { startIndex, stopIndex } = event.detail;\n this._lastRequestedFirstIndex = startIndex;\n this._lastRequestedLastIndex = stopIndex;\n this._list.items = this._itemCache.slice(startIndex, stopIndex + 1);\n\n if (!this.finalSizeIsKnown && this._lastLoadedIndex < stopIndex + this.preloadedItemsCount) {\n this.requestData();\n }\n };\n\n private requestData(): void {\n if (this._pendingDataRequest) {\n return;\n }\n if (this.onDataRequest) {\n this._pendingDataRequest = true;\n this.onDataRequest(this.currentPage + 1);\n this._lastLoadedIndex += this.pageSize - 1;\n if (this._lastLoadedIndex > this.itemCount) {\n this.itemCount = this._lastLoadedIndex;\n }\n } else {\n throw Error(\n \"The final size is not yet known and the list would require item data from index \" +\n this._lastRequestedFirstIndex +\n \". to \" +\n this._lastRequestedLastIndex +\n \". which is not possible to load without a configured onDataRequest\",\n );\n }\n }\n}\n","import { LitElement, TemplateResult, html, unsafeCSS, PropertyValues, css } from \"lit\";\nimport { property } from \"lit/decorators/property.js\";\nimport ListUtil, { ScrollToAlignment } from \"./list-util\";\nimport ListItem, { generator } from \"@cas-smartdesign/list-item\";\nexport { ListDataProvider } from \"./data-provider\";\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [VirtualList.ID]: VirtualList;\n }\n}\n\nimport style from \"./style.scss?inline\";\n\nexport type ItemGenerator = (data: unknown, index: number) => HTMLElement;\nexport enum SelectionType {\n TriggerOnly = \"trigger-only\",\n Single = \"single\",\n Multi = \"multi\",\n}\n\ninterface ItemRenderData {\n index: number;\n top: number;\n physicalIndex: number;\n dataHash: string;\n data?: unknown;\n}\n\nlet idCounter = 0;\n\nexport interface IDataRequestEvent {\n startIndex: number;\n stopIndex: number;\n}\n\nexport interface ISelectionEvent {\n index: number;\n selected: boolean;\n originalEvent: Event;\n}\n\nexport interface CustomEventMap extends HTMLElementEventMap {\n \"data-request\": CustomEvent<IDataRequestEvent>;\n selection: CustomEvent<ISelectionEvent>;\n}\n\nexport default interface VirtualList {\n addEventListener<K extends keyof CustomEventMap>(\n event: K,\n listener: ((this: this, ev: CustomEventMap[K]) => unknown) | null,\n options?: AddEventListenerOptions | boolean,\n ): void;\n addEventListener(\n type: string,\n callback: EventListenerOrEventListenerObject | null,\n options?: AddEventListenerOptions | boolean,\n ): void;\n removeEventListener<K extends keyof CustomEventMap>(\n type: K,\n listener: (this: this, ev: CustomEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n dispatchEvent<EventType extends CustomEventMap[keyof CustomEventMap]>(event: EventType): boolean;\n}\n\nexport default class VirtualList extends LitElement {\n public static readonly ID = \"sd-virtual-list\";\n public static ensureDefined = (): void => {\n ListItem.ensureDefined();\n if (!customElements.get(VirtualList.ID)) {\n customElements.define(VirtualList.ID, VirtualList);\n }\n };\n\n @property({ type: Number, attribute: \"item-height\", reflect: true })\n public itemHeight: number;\n @property({ type: Number })\n public itemCount: number;\n @property({ type: Array, attribute: false })\n public items: unknown[] = [];\n @property({ type: String, attribute: \"selection-type\", reflect: true, noAccessor: true })\n public selectionType: SelectionType = SelectionType.TriggerOnly;\n @property({ type: String, attribute: true, reflect: true })\n public id: string = VirtualList.ID + \"_\" + idCounter++;\n\n // aria attributes\n @property({ type: String, reflect: true })\n public role = \"listbox\";\n\n public itemGenerator: ItemGenerator = generator;\n public finalSizeIsKnown: boolean;\n\n private _lastKnownScrollTop = 0;\n private _lastRenderedScrollTop = 0;\n\n private _itemsRenderData: ItemRenderData[] = [];\n private _elementCache: Map<string, HTMLElement> = new Map();\n\n private _firstVisibleIndex: number;\n private _lastVisibleIndex: number;\n private _visibleItemsNum = 0;\n\n private _selectedIndices: number[] = [];\n private _focusIndex = -1;\n private _resizeObserver: ResizeObserver;\n private _lastKnownHeight = 0;\n private _increaseWidthOnNextRenderIfNeeded: boolean;\n private _reachedMaxWidth: boolean;\n\n public get focusTarget(): boolean {\n return this.hasAttribute(\"focus-target\");\n }\n\n public set focusTarget(value: boolean) {\n this.toggleAttribute(\"focus-target\", value);\n }\n\n @property({ type: Number, attribute: \"focus-index\", reflect: true })\n public get focusIndex(): number {\n return this._focusIndex;\n }\n\n public set focusIndex(index: number) {\n if (index >= -1 && index < this.itemCount) {\n const oldValue = this._focusIndex;\n this._focusIndex = index;\n if (index <= this._firstVisibleIndex || this._lastVisibleIndex <= index) {\n this.scrollToItem(index);\n }\n if (oldValue != index) {\n if (index == -1) {\n this.removeAttribute(\"aria-activedescendant\");\n }\n this.requestUpdate(\"focusIndex\", oldValue);\n }\n }\n }\n\n @property({ type: Array, attribute: false })\n public get selectedIndices(): number[] {\n return this._selectedIndices;\n }\n\n public set selectedIndices(selectedIndices: number[]) {\n if (selectedIndices) {\n // Parse to primitive numbers as the virtual-list uses numbers and not objects for the indexOf(item-index) checks.\n this._selectedIndices = selectedIndices.map((index) => Number(index));\n } else {\n this._selectedIndices = [];\n }\n this.requestUpdate(\"selectedIndices\");\n }\n\n public scrollToItem(index: number, alignment: ScrollToAlignment = \"auto\"): void {\n this.scrollTop = ListUtil.getOffsetForIndexAndAlignment(\n this.normalizeIndex(index),\n alignment,\n this.scrollTop,\n this.itemHeight,\n this.height,\n this.itemCount,\n );\n // The render might have already been scheduled, but the onScroll event is dispatched later.\n // We need to update the _lastKnownScrollTop manually to ensure an up-to-date value is used even for the next render.\n this._lastKnownScrollTop = this.scrollTop;\n }\n\n public getListItem(index: number): HTMLElement {\n if (!this.shadowRoot || index < this._firstVisibleIndex || this._lastVisibleIndex < index) {\n return null;\n }\n return this.querySelector(`[item-index=\"${index}\"]`);\n }\n\n constructor() {\n super();\n this._resizeObserver = new ResizeObserver(() => {\n if (this._lastKnownHeight !== this.offsetHeight) {\n this._lastKnownHeight = this.offsetHeight;\n this.requestUpdate();\n }\n });\n }\n\n public connectedCallback(): void {\n super.connectedCallback();\n\n this._resizeObserver.observe(this);\n // these are needed because when reattaching the list to the DOM\n // then the scroll position is reset but no scroll event is called\n // so the list shows the items at incorrect position\n if (this.scrollTop !== this._lastKnownScrollTop) {\n this.scrollTop = this._lastKnownScrollTop;\n this.requestUpdate();\n }\n }\n\n public disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver.disconnect();\n }\n\n public firstUpdated(_changedProperties: PropertyValues): void {\n super.firstUpdated(_changedProperties);\n\n this.addEventListener(\"scroll\", this.onScroll);\n this.addEventListener(\"keydown\", this.handleKeyDown);\n this.addEventListener(\"click\", this.handleClick);\n this.addEventListener(\"mousedown\", (event) => {\n if (event.button == 1) {\n event.preventDefault();\n }\n });\n this.addEventListener(\"auxclick\", this.handleClick);\n this.addEventListener(\"focus\", () => {\n if (this.matches(\":focus-visible\")) {\n if (this.focusIndex == -1) {\n if (this.selectedIndices) {\n this.focusIndex = this.selectedIndices[0];\n }\n if (this.focusIndex == -1 && this.itemCount > 0) {\n this.focusIndex = 0;\n }\n } else {\n this.updateFocusedItemAttributes();\n }\n }\n });\n this.addEventListener(\"blur\", () => {\n if (this.focusIndex != -1) {\n this.updateFocusedItemAttributes();\n }\n });\n if (this.selectedIndices.length > 0) {\n this.scrollToItem(this.selectedIndices[0], \"center\");\n }\n }\n\n private updateFocusedItemAttributes() {\n const focusedElement = this.getListItem(this.focusIndex);\n if (focusedElement) {\n if (this.focusTarget || document.activeElement == this) {\n focusedElement.setAttribute(\"focused\", \"\");\n this.setAttribute(\"aria-activedescendant\", focusedElement.id);\n } else {\n focusedElement.removeAttribute(\"focused\");\n this.removeAttribute(\"aria-activedescendant\");\n }\n }\n }\n\n static get styles() {\n return [\n css`\n ${unsafeCSS(style)}\n `,\n ];\n }\n public render(): TemplateResult {\n this.updateItemsRenderData();\n return html`\n <div class=\"container\" style=\"height: ${this.itemCount * this.itemHeight}px\">\n <slot name=\"items\"></slot>\n </div>\n `;\n }\n\n public updated(_changedProperties: PropertyValues): void {\n super.updated(_changedProperties);\n this._lastRenderedScrollTop = this._lastKnownScrollTop;\n this.updateItems();\n\n if (\n (this._increaseWidthOnNextRenderIfNeeded || this._reachedMaxWidth) && //\n this._firstVisibleIndex < this._lastVisibleIndex\n ) {\n if (!this.querySelector(\"[item-index]\")) {\n // If ShadyDOM is in use, then it needs a delay, because dom mutations are not applied immediately.\n const observer = new MutationObserver(() => {\n this.adjustWidthIfNeeded();\n observer.disconnect();\n });\n observer.observe(this);\n } else {\n this.adjustWidthIfNeeded();\n }\n }\n }\n\n private adjustWidthIfNeeded() {\n if (this._increaseWidthOnNextRenderIfNeeded) {\n this._increaseWidthOnNextRenderIfNeeded = false;\n window.requestAnimationFrame(() => {\n const remainingWidth = Number.parseInt(getComputedStyle(this).maxWidth) - this.offsetWidth;\n if (remainingWidth == 0) {\n this._reachedMaxWidth = true;\n this.enableLineClampOnItemsIfNeeded();\n } else {\n this._reachedMaxWidth = false;\n const missingWidths = [...this.querySelectorAll(\"[item-index]\")].map((item) => {\n if (item instanceof ListItem) {\n item.enableLineClamp = false;\n const missingWidthForTexts = item.missingWidthForTexts;\n if (missingWidthForTexts > remainingWidth) {\n item.enableLineClamp = true;\n }\n return missingWidthForTexts;\n }\n const missingWidth = item.scrollWidth - item.clientWidth;\n if (missingWidth > 0) {\n return missingWidth + 1; // ensure ellipsis is not shown for subpixel rendering\n }\n return 0;\n });\n const additionalWidth = Math.max(...missingWidths);\n if (additionalWidth > 0) {\n this.style.width = `${this.offsetWidth + additionalWidth}px`;\n }\n }\n });\n } else if (this._reachedMaxWidth) {\n this.enableLineClampOnItemsIfNeeded();\n }\n }\n\n private enableLineClampOnItemsIfNeeded() {\n this.querySelectorAll(\"[item-index]\").forEach((item) => {\n if (item instanceof ListItem) {\n item.enableLineClamp = item.enableLineClamp || item.missingWidthForTexts > 0;\n }\n });\n }\n\n /**\n * Searches for list-items where there is a need for an additional width (ellipsis maybe shown) and increases the width of the list,\n * therefore all the content is visible without tooltips. As it can be an expensive task to retrieve the required details, calling\n * this function has an effect only on the very next render. Note that it only works if the virtual-list works with sd-list-item elements.\n * If the maximum width is reached, line clamp is enabled on list items as a last resort approach to show the content if possible.\n */\n public increaseWidthOnNextRenderIfNeeded(): void {\n this._increaseWidthOnNextRenderIfNeeded = true;\n }\n\n private updateItems() {\n const unusedItems: Element[] = [...this.querySelectorAll(\"[item-index]\")];\n const renderedItems: Map<string, HTMLElement> = new Map();\n\n const newItemsFragment = document.createDocumentFragment();\n for (const renderData of this._itemsRenderData) {\n const itemElement = this.renderItem(renderData);\n if (!itemElement.parentElement) {\n newItemsFragment.appendChild(itemElement);\n }\n renderedItems.set(renderData.dataHash, itemElement);\n const index = unusedItems.indexOf(itemElement);\n if (index !== -1) {\n unusedItems.splice(index, 1);\n }\n }\n this.appendChild(newItemsFragment);\n\n for (const unusedItemElement of unusedItems) {\n if (unusedItemElement instanceof ListItem) {\n unusedItemElement.enableLineClamp = false;\n }\n this.removeChild(unusedItemElement);\n }\n\n renderedItems.forEach((itemElement, dataHash) => {\n this._elementCache.set(dataHash, itemElement);\n });\n }\n\n private renderItem({ index, top, dataHash, data }: ItemRenderData): HTMLElement {\n let element: HTMLElement;\n if (data) {\n if (this._elementCache.has(dataHash)) {\n element = this._elementCache.get(dataHash);\n this._elementCache.delete(dataHash); // Allow to be rendered twice\n } else {\n element = this.itemGenerator(data, index);\n element.setAttribute(\"slot\", \"items\");\n // Do not add to cache yet, because the same item might need to be rendered twice\n }\n } else {\n element = document.createElement(\"div\");\n element.setAttribute(\"placeholder-item\", \"\");\n element.setAttribute(\"slot\", \"items\");\n }\n Object.assign(element.style, {\n transform: `translateY(${top}px)`,\n height: `${this.itemHeight}px`,\n });\n element.setAttribute(\"item-index\", index.toString());\n element.setAttribute(\"aria-setsize\", String(this.finalSizeIsKnown ? this.itemCount : -1));\n element.setAttribute(\"aria-posinset\", String(index + 1));\n if (!element.id || element.id.startsWith(this.id + \"_item_\")) {\n element.id = this.id + \"_item_\" + index;\n }\n if (this.itemCount - 1 == index) {\n element.setAttribute(\"last\", \"\");\n } else {\n element.removeAttribute(\"last\");\n }\n\n this.updateSelectedAttribute(index, element);\n this.updateFocusedAttribute(index, element);\n\n return element;\n }\n\n private onScroll = () => {\n this._lastKnownScrollTop = this.scrollTop;\n const delta = this._lastRenderedScrollTop - this._lastKnownScrollTop;\n if (Math.abs(delta) >= this.itemHeight) {\n this._lastRenderedScrollTop = this._lastKnownScrollTop;\n this.requestUpdate();\n }\n };\n\n private updateFocusedAttribute(index: number, itemElement: HTMLElement) {\n if (this.focusIndex == index && (this.focusTarget || document.activeElement == this)) {\n itemElement.setAttribute(\"focused\", \"\");\n this.setAttribute(\"aria-activedescendant\", itemElement.id);\n } else {\n itemElement.removeAttribute(\"focused\");\n }\n }\n\n private updateSelectedAttribute(index: number, itemElement: HTMLElement) {\n const selected = this.selectedIndices.indexOf(index) !== -1;\n if (selected) {\n itemElement.setAttribute(\"selected\", \"\");\n } else {\n itemElement.removeAttribute(\"selected\");\n }\n itemElement.setAttribute(\"aria-selected\", String(selected));\n }\n\n private updateItemsRenderData(): void {\n this._itemsRenderData = [];\n this._visibleItemsNum = Math.min(Math.ceil(this.height / this.itemHeight), this.itemCount);\n\n if (this._visibleItemsNum > 0) {\n this._firstVisibleIndex = this.normalizeIndex(Math.floor(this._lastKnownScrollTop / this.itemHeight));\n this._lastVisibleIndex = this.normalizeIndex(this._firstVisibleIndex + this._visibleItemsNum);\n\n const firstRenderedIndex = this.normalizeIndex(this._firstVisibleIndex - 2);\n const lastRenderedIndex = this.normalizeIndex(this._lastVisibleIndex + 2);\n\n // May update value of this.items, which could trigger another render if not called from a lifecycle callback where it is ignored\n this.requestData(firstRenderedIndex, lastRenderedIndex);\n\n for (let i = firstRenderedIndex; i <= lastRenderedIndex; i++) {\n const physicalIndex = i - firstRenderedIndex;\n const itemData = this.items[physicalIndex];\n let dataHash;\n if (itemData) {\n dataHash = JSON.stringify(itemData);\n } else {\n dataHash = `placeholder-${physicalIndex}`;\n }\n this._itemsRenderData.push({\n index: i,\n top: this.itemHeight * i,\n physicalIndex,\n dataHash,\n data: itemData,\n });\n }\n } else {\n this._firstVisibleIndex = 0;\n this._lastVisibleIndex = 0;\n }\n }\n\n private normalizeIndex(index: number): number {\n return Math.max(0, Math.min(index, this.itemCount - 1));\n }\n\n private get height(): number {\n return this.offsetHeight;\n }\n\n private requestData(firstRenderedIndex: number, lastRenderedIndex: number): void {\n if (!Number.isNaN(firstRenderedIndex) && !Number.isNaN(lastRenderedIndex)) {\n this.dispatchEvent(\n new CustomEvent<IDataRequestEvent>(\"data-request\", {\n detail: {\n startIndex: firstRenderedIndex,\n stopIndex: lastRenderedIndex,\n },\n }),\n );\n }\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n let shouldPrevent = true;\n switch (event.key) {\n case \"Down\":\n case \"ArrowDown\":\n this.focusIndex = (this.focusIndex + 1) % this.itemCount;\n break;\n case \"Up\":\n case \"ArrowUp\":\n if (this.focusIndex > 0) {\n this.focusIndex--;\n } else if (this.finalSizeIsKnown) {\n this.focusIndex = this.itemCount - 1;\n }\n break;\n case \"Enter\":\n this.handleSelection(this.focusIndex, event);\n break;\n case \"End\":\n this.focusIndex = this.itemCount - 1;\n break;\n case \"PageDown\":\n this.focusIndex = this.normalizeIndex(this.focusIndex + this._visibleItemsNum - 1);\n break;\n case \"Home\":\n this.focusIndex = 0;\n break;\n case \"PageUp\":\n this.focusIndex = this.normalizeIndex(this.focusIndex - this._visibleItemsNum + 1);\n break;\n default:\n shouldPrevent = false;\n break;\n }\n if (shouldPrevent) {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n private handleSelection(index: number, event: Event): void {\n if (index < 0 || this.itemCount <= index) {\n return;\n }\n const element = this.getListItem(index);\n if (element.getAttribute(\"aria-disabled\") == \"true\" || element.hasAttribute(\"disabled\")) {\n return;\n }\n let hasBeenSelected = true;\n if (this.selectionType !== SelectionType.TriggerOnly) {\n const existingIndex = this.selectedIndices.indexOf(index);\n hasBeenSelected = existingIndex == -1;\n if (hasBeenSelected) {\n if (this.selectionType === SelectionType.Single) {\n this.selectedIndices = [index];\n } else {\n this.selectedIndices.push(index);\n }\n } else {\n this.selectedIndices.splice(existingIndex, 1);\n }\n this.requestUpdate(\"selectedIndices\"); // altering inside of an array does not retrigger an update\n }\n this.focusIndex = index;\n this.dispatchSelectionEvent(index, hasBeenSelected, event);\n }\n\n private dispatchSelectionEvent(index: number, selected: boolean, originalEvent: Event): void {\n this.dispatchEvent(\n new CustomEvent<ISelectionEvent>(\"selection\", {\n detail: { index, selected, originalEvent },\n }),\n );\n }\n\n private handleClick(event: MouseEvent): void {\n const clickedElement = event\n .composedPath()\n .find((target: HTMLElement) => target.hasAttribute && target.hasAttribute(\"item-index\")) as HTMLElement;\n if (clickedElement) {\n const index = parseInt(clickedElement.getAttribute(\"item-index\"));\n if (Number.isInteger(index)) {\n if (event.button == 0 || event.button == 1) {\n this.handleSelection(index, event);\n }\n this.focusIndex = index;\n }\n }\n }\n}\n\nVirtualList.ensureDefined();\n"],"names":["ListUtil","index","alignment","scrollOffset","itemHeight","height","itemCount","lastItemOffset","maxOffset","minOffset","middleOffset","func","timer","args","ListUtil$1","ListDataProvider","pageSize","preloadedItemsCount","event","startIndex","stopIndex","value","count","items","list","SelectionType","idCounter","_VirtualList","_a","LitElement","generator","delta","shouldPrevent","oldValue","selectedIndices","_changedProperties","focusedElement","css","unsafeCSS","style","html","observer","remainingWidth","missingWidths","item","ListItem","missingWidthForTexts","missingWidth","additionalWidth","unusedItems","renderedItems","newItemsFragment","renderData","itemElement","unusedItemElement","dataHash","top","data","element","selected","firstRenderedIndex","lastRenderedIndex","physicalIndex","itemData","hasBeenSelected","existingIndex","originalEvent","clickedElement","target","__decorateClass","property","VirtualList"],"mappings":"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"}
1
+ {"version":3,"file":"virtual-list.mjs","names":[],"sources":["../list-util.ts","../data-provider.ts","../style.scss?inline","../virtual-list.ts"],"sourcesContent":["export type ScrollToAlignment = \"auto\" | \"center\" | \"start\" | \"end\";\n\nexport interface IListUtil {\n getOffsetForIndexAndAlignment(\n index: number,\n alignment: ScrollToAlignment,\n scrollOffset: number,\n itemHeight: number,\n height: number,\n itemCount: number,\n ): number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n debounce(func: (...args: any) => void): () => void;\n}\n\nclass ListUtil implements IListUtil {\n /**\n * Padding kept between a scrolled-to item and the viewport edge so the item's focus ring\n * stays visible. Must be kept in sync with `--list-item-focus-ring-width` in style.scss.\n */\n private static readonly FOCUS_RING_WIDTH = 3;\n\n public getOffsetForIndexAndAlignment(\n index: number,\n alignment: ScrollToAlignment,\n scrollOffset: number,\n itemHeight: number,\n height: number,\n itemCount: number,\n ): number {\n const focusRingWidth = ListUtil.FOCUS_RING_WIDTH;\n const lastItemOffset = Math.max(0, itemCount * itemHeight);\n const renderedTop = index * itemHeight + focusRingWidth;\n const rawMaxOffset = Math.min(lastItemOffset, renderedTop);\n const rawMinOffset = Math.max(0, renderedTop - height + itemHeight);\n const maxOffset = Math.max(0, rawMaxOffset - focusRingWidth);\n const minOffset = Math.min(lastItemOffset, rawMinOffset + focusRingWidth);\n\n switch (alignment) {\n case \"start\":\n return maxOffset;\n case \"end\":\n return minOffset;\n case \"center\": {\n const middleOffset = Math.round(rawMinOffset + (rawMaxOffset - rawMinOffset) / 2);\n if (middleOffset < Math.ceil(height / 2)) {\n return 0;\n } else if (middleOffset > lastItemOffset + Math.floor(height / 2)) {\n return lastItemOffset;\n } else {\n return middleOffset;\n }\n }\n case \"auto\":\n default:\n if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {\n return scrollOffset;\n } else if (scrollOffset < minOffset) {\n return minOffset;\n } else {\n return maxOffset;\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public debounce(func: (...args: any) => void): (...args: unknown[]) => void {\n let timer: number | null;\n return (...args: unknown[]) => {\n if (timer) {\n window.cancelAnimationFrame(timer);\n }\n timer = window.requestAnimationFrame(() => {\n func(...args);\n timer = null;\n });\n };\n }\n}\n\nexport default new ListUtil();\n","import VirtualList from \"./virtual-list\";\n\nexport class ListDataProvider {\n public onDataRequest?: (page: number) => void;\n\n private _finalSizeIsKnown = false;\n private _itemCache: unknown[] = [];\n private _lastRequestedFirstIndex = 0;\n private _lastRequestedLastIndex = 0;\n private _lastLoadedIndex = 0;\n private _list?: VirtualList;\n private _itemCount: number;\n private _pendingDataRequest: boolean = false;\n\n constructor(\n public pageSize: number = 100,\n public preloadedItemsCount: number = 5,\n ) {\n this._itemCount = pageSize; // configure initial load\n }\n\n public get currentPage(): number {\n if (this.items.length == 0 && this.finalSizeIsKnown) {\n return 0; // Otherwise empty cache means we haven't fetched anything\n }\n // With pageSize 100\n // 0 => -1\n // 1 100 => 0\n // 101 200 => 1\n return Math.floor((this.items.length - 1) / this.pageSize);\n }\n\n public get finalSizeIsKnown(): boolean {\n return this._finalSizeIsKnown;\n }\n\n public set finalSizeIsKnown(value: boolean) {\n this._finalSizeIsKnown = value;\n if (value) {\n this.itemCount = this._itemCache.length;\n }\n if (this._list) {\n this._list.finalSizeIsKnown = value;\n }\n }\n\n private get itemCount(): number {\n return this._itemCount;\n }\n\n private set itemCount(count: number) {\n this._itemCount = count;\n if (this._list) {\n this._list.itemCount = count;\n }\n }\n\n public get items(): unknown[] {\n return this._itemCache;\n }\n\n public set items(items: unknown[]) {\n this._itemCache = items;\n this.onItemsChange();\n }\n\n public addItems(items: unknown[]): void {\n this._itemCache = this._itemCache.concat(items);\n this.onItemsChange();\n }\n\n public connectList(list: VirtualList): void {\n if (this._list) {\n this._list.removeEventListener(\"sd-virtual-list-data-request\", this.handleListDataRequest);\n }\n this._list = list;\n list.itemCount = this.itemCount;\n list.addEventListener(\"sd-virtual-list-data-request\", this.handleListDataRequest);\n list.finalSizeIsKnown = this._finalSizeIsKnown;\n }\n\n private onItemsChange(): void {\n this._pendingDataRequest = false;\n this._lastLoadedIndex = this._itemCache.length - 1;\n if (this.finalSizeIsKnown) {\n this.itemCount = this._itemCache.length;\n } else if (this._lastLoadedIndex > this.itemCount) {\n this.itemCount = this._lastLoadedIndex;\n }\n if (this._list) {\n this._list.items = this._itemCache.slice(this._lastRequestedFirstIndex, this._lastRequestedLastIndex + 1);\n }\n }\n\n private handleListDataRequest = (event: CustomEvent) => {\n if (this._list == null) {\n return;\n }\n const { startIndex, stopIndex } = event.detail;\n this._lastRequestedFirstIndex = startIndex;\n this._lastRequestedLastIndex = stopIndex;\n this._list.items = this._itemCache.slice(startIndex, stopIndex + 1);\n\n if (!this.finalSizeIsKnown && this._lastLoadedIndex < stopIndex + this.preloadedItemsCount) {\n this.requestData();\n }\n };\n\n private requestData(): void {\n if (this._pendingDataRequest) {\n return;\n }\n if (this.onDataRequest) {\n this._pendingDataRequest = true;\n this.onDataRequest(this.currentPage + 1);\n this._lastLoadedIndex += this.pageSize - 1;\n if (this._lastLoadedIndex > this.itemCount) {\n this.itemCount = this._lastLoadedIndex;\n }\n } else {\n throw Error(\n \"The final size is not yet known and the list would require item data from index \" +\n this._lastRequestedFirstIndex +\n \". to \" +\n this._lastRequestedLastIndex +\n \". which is not possible to load without a configured onDataRequest\",\n );\n }\n }\n}\n",":host {\n\tdisplay: block;\n\tposition: relative;\n\tcontain: layout;\n\toverflow-y: auto;\n\toverflow-x: hidden;\n\t--list-item-focus-ring-width: 3px;\n\tscroll-padding: var(--list-item-focus-ring-width);\n}\n\n:host(:focus) {\n\toutline: none;\n}\n\n:host(:focus-visible) ::slotted([focused]) {\n\t--sd-list-item-focus-ring-offset-color: var(--color-bg-default, #ffffff);\n\t--sd-list-item-focus-ring-color: var(--color-border-interaction-focus, #111);\n\tborder-color: var(--color-rainbow-mono-weak, #ffffff);\n\tz-index: 1;\n}\n\n.scroll-container {\n\tdisplay: block;\n\tpadding: var(--list-item-focus-ring-width);\n\t/* join the list background with the scrollbar */\n\tbackground: linear-gradient(\n\t\t\tvar(--sd-virtual-list-background-color, var(--color-bg-default, #ffffff)),\n\t\t\tvar(--sd-virtual-list-background-color, var(--color-bg-default, #ffffff))\n\t\t)\n\t\tno-repeat right center / var(--list-item-focus-ring-width) calc(100% - 2 * var(--list-item-focus-ring-width));\n}\n\n.container {\n\twidth: 100%;\n\tposition: relative;\n\tbackground-color: var(--sd-virtual-list-background-color, var(--color-bg-default, #ffffff));\n\n\t& > ::slotted(*) {\n\t\twidth: 100%;\n\t\tposition: absolute;\n\t\tbox-sizing: border-box;\n\t}\n\n\t& > ::slotted(sd-list-item:not([last])) {\n\t\t--sd-list-item-bottom-border-color: var(--color-border-weak, #ededed);\n\t\tborder-bottom-color: var(--sd-list-item-bottom-border-color);\n\t}\n\n\t& > ::slotted(sd-list-item:is(:hover, [focused], :not([aria-disabled=\"true\"]):active, [selected])) {\n\t\t--sd-list-item-bottom-border-color: var(--color-rainbow-mono-weak, #ffffff);\n\t}\n\n\t& > ::slotted(sd-list-item[selected]) {\n\t\tborder-left-color: var(--color-rainbow-mono-weak, #ffffff);\n\t\tborder-right-color: var(--color-rainbow-mono-weak, #ffffff);\n\t}\n\n\t& > ::slotted(:not(:is(sd-list-item, [last]))) {\n\t\tborder-bottom: 1px solid var(--color-border-weak, #ededed);\n\t}\n}\n","import ListItem, { generator, type ItemData } from \"@cas-smartdesign/list-item\";\nimport { LitElement, type TemplateResult, html, unsafeCSS, type PropertyValues, css } from \"lit\";\nimport { property } from \"lit/decorators/property.js\";\n\nimport ListUtil, { type ScrollToAlignment } from \"./list-util\";\nexport { ListDataProvider } from \"./data-provider\";\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [VirtualList.ID]: VirtualList;\n }\n interface HTMLElementEventMap {\n \"sd-virtual-list-data-request\": CustomEvent<IDataRequestEvent>;\n \"sd-virtual-list-selection\": CustomEvent<ISelectionEvent>;\n }\n}\n\nimport style from \"./style.scss?inline\";\n\nexport type ItemGenerator = (data: ItemData, _index: number) => HTMLElement;\nexport enum SelectionType {\n TriggerOnly = \"trigger-only\",\n Single = \"single\",\n Multi = \"multi\",\n}\n\ninterface ItemRenderData {\n index: number;\n top: number;\n physicalIndex: number;\n dataHash: string;\n data?: unknown;\n}\n\nlet idCounter = 0;\n\nexport interface IDataRequestEvent {\n startIndex: number;\n stopIndex: number;\n}\n\nexport interface ISelectionEvent {\n index: number;\n selected: boolean;\n originalEvent: Event;\n}\n\nexport default class VirtualList extends LitElement {\n public static readonly ID = \"sd-virtual-list\";\n public static ensureDefined = (): void => {\n ListItem.ensureDefined();\n if (!customElements.get(VirtualList.ID)) {\n customElements.define(VirtualList.ID, VirtualList);\n }\n };\n\n @property({ type: Number, attribute: \"item-height\", reflect: true })\n public itemHeight: number = 48;\n @property({ type: Number })\n public itemCount: number = 0;\n @property({ type: Array, attribute: false })\n public items: unknown[] = [];\n @property({ type: String, attribute: \"selection-type\", reflect: true, noAccessor: true })\n public selectionType: SelectionType = SelectionType.TriggerOnly;\n @property({ type: String, attribute: true, reflect: true })\n public override id: string = VirtualList.ID + \"_\" + idCounter++;\n\n // aria attributes\n @property({ type: String, reflect: true })\n public override role = \"listbox\";\n\n public itemGenerator: ItemGenerator = generator;\n public finalSizeIsKnown?: boolean;\n\n private _lastKnownScrollTop = 0;\n private _lastRenderedScrollTop = 0;\n\n private _itemsRenderData: ItemRenderData[] = [];\n private _elementCache: Map<string, HTMLElement> = new Map();\n\n private _firstVisibleIndex: number = -1;\n private _lastVisibleIndex: number = -1;\n private _visibleItemsNum = 0;\n\n private _selectedIndices: number[] = [];\n private _focusIndex = -1;\n private _resizeObserver: ResizeObserver;\n private _lastKnownHeight = 0;\n private _increaseWidthOnNextRenderIfNeeded?: boolean;\n private _reachedMaxWidth?: boolean;\n\n public get focusTarget(): boolean {\n return this.hasAttribute(\"focus-target\");\n }\n\n public set focusTarget(value: boolean) {\n this.toggleAttribute(\"focus-target\", value);\n }\n\n @property({ type: Number, attribute: \"focus-index\", reflect: true })\n public get focusIndex(): number {\n return this._focusIndex;\n }\n\n public set focusIndex(index: number) {\n if (index >= -1 && index < this.itemCount) {\n const oldValue = this._focusIndex;\n this._focusIndex = index;\n if (index <= this._firstVisibleIndex || this._lastVisibleIndex <= index) {\n this.scrollToItem(index);\n }\n if (oldValue != index) {\n if (index == -1) {\n this.removeAttribute(\"aria-activedescendant\");\n }\n this.requestUpdate(\"focusIndex\", oldValue);\n }\n }\n }\n\n @property({ type: Array, attribute: false })\n public get selectedIndices(): number[] {\n return this._selectedIndices;\n }\n\n public set selectedIndices(selectedIndices: number[]) {\n if (selectedIndices) {\n // Parse to primitive numbers as the virtual-list uses numbers and not objects for the indexOf(item-index) checks.\n this._selectedIndices = selectedIndices.map((index) => Number(index));\n } else {\n this._selectedIndices = [];\n }\n this.requestUpdate(\"selectedIndices\");\n }\n\n public scrollToItem(index: number, alignment: ScrollToAlignment = \"auto\"): void {\n this.scrollTop = ListUtil.getOffsetForIndexAndAlignment(\n this.normalizeIndex(index),\n alignment,\n this.scrollTop,\n this.itemHeight,\n this.height,\n this.itemCount,\n );\n // The render might have already been scheduled, but the onScroll event is dispatched later.\n // We need to update the _lastKnownScrollTop manually to ensure an up-to-date value is used even for the next render.\n this._lastKnownScrollTop = this.scrollTop;\n }\n\n public getListItem(index: number): HTMLElement | null {\n if (!this.shadowRoot || index < this._firstVisibleIndex || this._lastVisibleIndex < index) {\n return null;\n }\n return this.querySelector(`[item-index=\"${index}\"]`);\n }\n\n constructor() {\n super();\n this._resizeObserver = new ResizeObserver(() => {\n if (this._lastKnownHeight !== this.offsetHeight) {\n this._lastKnownHeight = this.offsetHeight;\n this.requestUpdate();\n }\n });\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n\n this._resizeObserver.observe(this);\n // these are needed because when reattaching the list to the DOM\n // then the scroll position is reset but no scroll event is called\n // so the list shows the items at incorrect position\n if (this.scrollTop !== this._lastKnownScrollTop) {\n this.scrollTop = this._lastKnownScrollTop;\n this.requestUpdate();\n }\n }\n\n public override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver.disconnect();\n }\n\n public override firstUpdated(_changedProperties: PropertyValues): void {\n super.firstUpdated(_changedProperties);\n\n this.addEventListener(\"scroll\", this.onScroll);\n this.addEventListener(\"keydown\", this.handleKeyDown);\n this.addEventListener(\"click\", this.handleClick);\n this.addEventListener(\"mousedown\", (event) => {\n if (event.button == 1) {\n event.preventDefault();\n }\n });\n this.addEventListener(\"auxclick\", this.handleClick);\n this.addEventListener(\"focus\", () => {\n if (this.matches(\":focus-visible\")) {\n if (this.focusIndex == -1) {\n if (this.selectedIndices) {\n this.focusIndex = this.selectedIndices[0] ?? -1;\n }\n if (this.focusIndex == -1 && this.itemCount > 0) {\n this.focusIndex = 0;\n }\n } else {\n this.updateFocusedItemAttributes();\n }\n }\n });\n this.addEventListener(\"blur\", () => {\n if (this.focusIndex != -1) {\n this.updateFocusedItemAttributes();\n }\n });\n if (this.selectedIndices.length > 0) {\n this.scrollToItem(this.selectedIndices[0] ?? -1, \"center\");\n }\n }\n\n private updateFocusedItemAttributes() {\n const focusedElement = this.getListItem(this.focusIndex);\n if (focusedElement) {\n if (this.focusTarget || document.activeElement == this) {\n focusedElement.setAttribute(\"focused\", \"\");\n this.setAttribute(\"aria-activedescendant\", focusedElement.id);\n } else {\n focusedElement.removeAttribute(\"focused\");\n this.removeAttribute(\"aria-activedescendant\");\n }\n }\n }\n\n static override get styles() {\n return [\n css`\n ${unsafeCSS(style)}\n `,\n ];\n }\n public override render(): TemplateResult {\n this.updateItemsRenderData();\n return html`\n <div class=\"scroll-container\">\n <div class=\"container\" style=\"height: ${this.itemCount * this.itemHeight}px\">\n <slot name=\"items\"></slot>\n </div>\n </div>\n `;\n }\n\n public override updated(_changedProperties: PropertyValues): void {\n super.updated(_changedProperties);\n this._lastRenderedScrollTop = this._lastKnownScrollTop;\n this.updateItems();\n\n if (\n (this._increaseWidthOnNextRenderIfNeeded || this._reachedMaxWidth) && //\n this._firstVisibleIndex < this._lastVisibleIndex\n ) {\n this.adjustWidthIfNeeded();\n }\n }\n\n private adjustWidthIfNeeded() {\n if (this._increaseWidthOnNextRenderIfNeeded) {\n this._increaseWidthOnNextRenderIfNeeded = false;\n window.requestAnimationFrame(() => {\n const remainingWidth = Number.parseInt(getComputedStyle(this).maxWidth) - this.offsetWidth;\n if (remainingWidth == 0) {\n this._reachedMaxWidth = true;\n this.enableLineClampOnItemsIfNeeded();\n } else {\n this._reachedMaxWidth = false;\n const missingWidths = [...this.querySelectorAll(\"[item-index]\")].map((item) => {\n if (item instanceof ListItem) {\n item.enableLineClamp = false;\n const missingWidthForTexts = item.missingWidthForTexts;\n if (missingWidthForTexts > remainingWidth) {\n item.enableLineClamp = true;\n }\n return missingWidthForTexts;\n }\n const missingWidth = item.scrollWidth - item.clientWidth;\n if (missingWidth > 0) {\n return missingWidth + 1; // ensure ellipsis is not shown for subpixel rendering\n }\n return 0;\n });\n const additionalWidth = Math.max(...missingWidths);\n if (additionalWidth > 0) {\n this.style.width = `${this.offsetWidth + additionalWidth}px`;\n }\n }\n });\n } else if (this._reachedMaxWidth) {\n this.enableLineClampOnItemsIfNeeded();\n }\n }\n\n private enableLineClampOnItemsIfNeeded() {\n this.querySelectorAll(\"[item-index]\").forEach((item) => {\n if (item instanceof ListItem) {\n item.enableLineClamp = item.enableLineClamp || item.missingWidthForTexts > 0;\n }\n });\n }\n\n /**\n * Searches for list-items where there is a need for an additional width (ellipsis maybe shown) and increases the width of the list,\n * therefore all the content is visible without tooltips. As it can be an expensive task to retrieve the required details, calling\n * this function has an effect only on the very next render. Note that it only works if the virtual-list works with sd-list-item elements.\n * If the maximum width is reached, line clamp is enabled on list items as a last resort approach to show the content if possible.\n */\n public increaseWidthOnNextRenderIfNeeded(): void {\n this._increaseWidthOnNextRenderIfNeeded = true;\n }\n\n private updateItems() {\n const unusedItems: Element[] = [...this.querySelectorAll(\"[item-index]\")];\n const renderedItems: Map<string, HTMLElement> = new Map();\n\n const newItemsFragment = document.createDocumentFragment();\n for (const renderData of this._itemsRenderData) {\n const itemElement = this.renderItem(renderData);\n if (!itemElement.parentElement) {\n newItemsFragment.appendChild(itemElement);\n }\n renderedItems.set(renderData.dataHash, itemElement);\n const index = unusedItems.indexOf(itemElement);\n if (index !== -1) {\n unusedItems.splice(index, 1);\n }\n }\n this.appendChild(newItemsFragment);\n\n for (const unusedItemElement of unusedItems) {\n if (unusedItemElement instanceof ListItem) {\n unusedItemElement.enableLineClamp = false;\n }\n this.removeChild(unusedItemElement);\n }\n\n renderedItems.forEach((itemElement, dataHash) => {\n this._elementCache.set(dataHash, itemElement);\n });\n }\n\n private renderItem({ index, top, dataHash, data }: ItemRenderData): HTMLElement {\n let element: HTMLElement;\n if (data) {\n if (this._elementCache.has(dataHash)) {\n element = this._elementCache.get(dataHash)!;\n this._elementCache.delete(dataHash); // Allow to be rendered twice\n } else {\n element = this.itemGenerator(data, index);\n element.setAttribute(\"slot\", \"items\");\n // Do not add to cache yet, because the same item might need to be rendered twice\n }\n } else {\n element = document.createElement(\"div\");\n element.setAttribute(\"placeholder-item\", \"\");\n element.setAttribute(\"slot\", \"items\");\n }\n Object.assign(element.style, {\n transform: `translateY(${top}px)`,\n height: `${this.itemHeight}px`,\n });\n element.setAttribute(\"item-index\", index.toString());\n element.setAttribute(\"aria-setsize\", String(this.finalSizeIsKnown ? this.itemCount : -1));\n element.setAttribute(\"aria-posinset\", String(index + 1));\n if (!element.id || element.id.startsWith(this.id + \"_item_\")) {\n element.id = this.id + \"_item_\" + index;\n }\n if (this.itemCount - 1 == index) {\n element.setAttribute(\"last\", \"\");\n } else {\n element.removeAttribute(\"last\");\n }\n\n this.updateSelectedAttribute(index, element);\n this.updateFocusedAttribute(index, element);\n\n return element;\n }\n\n private onScroll = () => {\n this._lastKnownScrollTop = this.scrollTop;\n const delta = this._lastRenderedScrollTop - this._lastKnownScrollTop;\n if (Math.abs(delta) >= this.itemHeight) {\n this._lastRenderedScrollTop = this._lastKnownScrollTop;\n this.requestUpdate();\n }\n };\n\n private updateFocusedAttribute(index: number, itemElement: HTMLElement) {\n if (this.focusIndex == index && (this.focusTarget || document.activeElement == this)) {\n itemElement.setAttribute(\"focused\", \"\");\n this.setAttribute(\"aria-activedescendant\", itemElement.id);\n } else {\n itemElement.removeAttribute(\"focused\");\n }\n }\n\n private updateSelectedAttribute(index: number, itemElement: HTMLElement) {\n const selected = this.selectedIndices.indexOf(index) !== -1;\n if (selected) {\n itemElement.setAttribute(\"selected\", \"\");\n } else {\n itemElement.removeAttribute(\"selected\");\n }\n itemElement.setAttribute(\"aria-selected\", String(selected));\n }\n\n private updateItemsRenderData(): void {\n this._itemsRenderData = [];\n this._visibleItemsNum = Math.min(Math.ceil(this.height / this.itemHeight), this.itemCount);\n\n if (this._visibleItemsNum > 0) {\n this._firstVisibleIndex = this.normalizeIndex(Math.floor(this._lastKnownScrollTop / this.itemHeight));\n this._lastVisibleIndex = this.normalizeIndex(this._firstVisibleIndex + this._visibleItemsNum);\n\n const firstRenderedIndex = this.normalizeIndex(this._firstVisibleIndex - 2);\n const lastRenderedIndex = this.normalizeIndex(this._lastVisibleIndex + 2);\n\n // May update value of this.items, which could trigger another render if not called from a lifecycle callback where it is ignored\n this.requestData(firstRenderedIndex, lastRenderedIndex);\n\n for (let i = firstRenderedIndex; i <= lastRenderedIndex; i++) {\n const physicalIndex = i - firstRenderedIndex;\n const itemData = this.items[physicalIndex];\n let dataHash;\n if (itemData) {\n dataHash = JSON.stringify(itemData);\n } else {\n dataHash = `placeholder-${physicalIndex}`;\n }\n this._itemsRenderData.push({\n index: i,\n top: this.itemHeight * i,\n physicalIndex,\n dataHash,\n data: itemData,\n });\n }\n } else {\n this._firstVisibleIndex = 0;\n this._lastVisibleIndex = 0;\n }\n }\n\n private normalizeIndex(index: number): number {\n return Math.max(0, Math.min(index, this.itemCount - 1));\n }\n\n private get height(): number {\n return this.offsetHeight;\n }\n\n private requestData(firstRenderedIndex: number, lastRenderedIndex: number): void {\n if (!Number.isNaN(firstRenderedIndex) && !Number.isNaN(lastRenderedIndex)) {\n this.dispatchEvent(\n new CustomEvent<IDataRequestEvent>(\"sd-virtual-list-data-request\", {\n detail: {\n startIndex: firstRenderedIndex,\n stopIndex: lastRenderedIndex,\n },\n }),\n );\n }\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n let shouldPrevent = true;\n switch (event.key) {\n case \"Down\":\n case \"ArrowDown\":\n this.focusIndex = (this.focusIndex + 1) % this.itemCount;\n break;\n case \"Up\":\n case \"ArrowUp\":\n if (this.focusIndex > 0) {\n this.focusIndex--;\n } else if (this.finalSizeIsKnown) {\n this.focusIndex = this.itemCount - 1;\n }\n break;\n case \"Enter\":\n this.handleSelection(this.focusIndex, event);\n break;\n case \"End\":\n this.focusIndex = this.itemCount - 1;\n break;\n case \"PageDown\":\n this.focusIndex = this.normalizeIndex(this.focusIndex + this._visibleItemsNum - 1);\n break;\n case \"Home\":\n this.focusIndex = 0;\n break;\n case \"PageUp\":\n this.focusIndex = this.normalizeIndex(this.focusIndex - this._visibleItemsNum + 1);\n break;\n default:\n shouldPrevent = false;\n break;\n }\n if (shouldPrevent) {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n private handleSelection(index: number, event: Event): void {\n if (index < 0 || this.itemCount <= index) {\n return;\n }\n const element = this.getListItem(index);\n if (element == null || element.getAttribute(\"aria-disabled\") == \"true\" || element.hasAttribute(\"disabled\")) {\n return;\n }\n let hasBeenSelected = true;\n if (this.selectionType !== SelectionType.TriggerOnly) {\n const existingIndex = this.selectedIndices.indexOf(index);\n hasBeenSelected = existingIndex == -1;\n if (hasBeenSelected) {\n if (this.selectionType === SelectionType.Single) {\n this.selectedIndices = [index];\n } else {\n this.selectedIndices.push(index);\n }\n } else {\n this.selectedIndices.splice(existingIndex, 1);\n }\n this.requestUpdate(\"selectedIndices\"); // altering inside of an array does not retrigger an update\n }\n this.focusIndex = index;\n this.dispatchSelectionEvent(index, hasBeenSelected, event);\n }\n\n private dispatchSelectionEvent(index: number, selected: boolean, originalEvent: Event): void {\n this.dispatchEvent(\n new CustomEvent<ISelectionEvent>(\"sd-virtual-list-selection\", {\n detail: { index, selected, originalEvent },\n }),\n );\n }\n\n private handleClick = (event: MouseEvent) => {\n const clickedElement = event\n .composedPath()\n .find(\n (target) => target instanceof HTMLElement && target.hasAttribute && target.hasAttribute(\"item-index\"),\n ) as HTMLElement | undefined;\n if (clickedElement) {\n const itemIndexFromAttribute = clickedElement.getAttribute(\"item-index\");\n if (itemIndexFromAttribute != null) {\n const index = parseInt(itemIndexFromAttribute);\n if (Number.isInteger(index)) {\n if (event.button == 0 || event.button == 1) {\n this.handleSelection(index, event);\n }\n this.focusIndex = index;\n }\n }\n }\n };\n}\n\nVirtualList.ensureDefined();\n"],"mappings":"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"}
@@ -1,65 +1,55 @@
1
1
  {
2
- "@cypress/vite-dev-server@7.0.0": {
2
+ "@cypress/vite-dev-server@7.3.2": {
3
3
  "licenses": "MIT",
4
4
  "repository": "https://github.com/cypress-io/cypress",
5
5
  "licenseUrl": "https://github.com/cypress-io/cypress/tree/develop/npm/vite-dev-server#readme"
6
6
  },
7
- "@eslint/js@9.34.0": {
7
+ "@tsdown/css@0.21.7": {
8
8
  "licenses": "MIT",
9
- "repository": "https://github.com/eslint/eslint",
10
- "licenseUrl": "https://unpkg.com/@eslint/js@9.34.0/LICENSE"
11
- },
12
- "@rollup/plugin-node-resolve@16.0.1": {
13
- "licenses": "MIT",
14
- "repository": "https://github.com/rollup/plugins",
15
- "licenseUrl": "https://unpkg.com/@rollup/plugin-node-resolve@16.0.1/LICENSE"
9
+ "repository": "https://github.com/rolldown/tsdown",
10
+ "licenseUrl": "https://unpkg.com/@tsdown/css@0.21.7/LICENSE"
16
11
  },
17
12
  "@types/d3-color@3.1.3": {
18
13
  "licenses": "MIT",
19
14
  "repository": "https://github.com/DefinitelyTyped/DefinitelyTyped",
20
15
  "licenseUrl": "https://unpkg.com/@types/d3-color@3.1.3/LICENSE"
21
16
  },
22
- "@types/node@24.3.0": {
17
+ "@types/node@25.5.2": {
23
18
  "licenses": "MIT",
24
19
  "repository": "https://github.com/DefinitelyTyped/DefinitelyTyped",
25
- "licenseUrl": "https://unpkg.com/@types/node@24.3.0/LICENSE"
20
+ "licenseUrl": "https://unpkg.com/@types/node@25.5.2/LICENSE"
26
21
  },
27
22
  "@types/postcss-prefix-selector@1.16.3": {
28
23
  "licenses": "MIT",
29
24
  "repository": "https://github.com/DefinitelyTyped/DefinitelyTyped",
30
25
  "licenseUrl": "https://unpkg.com/@types/postcss-prefix-selector@1.16.3/LICENSE"
31
26
  },
32
- "@typescript-eslint/eslint-plugin@8.41.0": {
27
+ "@types/yargs@17.0.35": {
33
28
  "licenses": "MIT",
34
- "repository": "https://github.com/typescript-eslint/typescript-eslint",
35
- "licenseUrl": "https://unpkg.com/@typescript-eslint/eslint-plugin@8.41.0/LICENSE"
36
- },
37
- "@typescript-eslint/parser@8.41.0": {
38
- "licenses": "MIT",
39
- "repository": "https://github.com/typescript-eslint/typescript-eslint",
40
- "licenseUrl": "https://unpkg.com/@typescript-eslint/parser@8.41.0/LICENSE"
29
+ "repository": "https://github.com/DefinitelyTyped/DefinitelyTyped",
30
+ "licenseUrl": "https://unpkg.com/@types/yargs@17.0.35/LICENSE"
41
31
  },
42
- "@vitest/coverage-v8@4.0.18": {
32
+ "@vitest/coverage-v8@4.1.2": {
43
33
  "licenses": "MIT",
44
34
  "repository": "https://github.com/vitest-dev/vitest",
45
- "licenseUrl": "https://unpkg.com/@vitest/coverage-v8@4.0.18/LICENSE"
35
+ "licenseUrl": "https://unpkg.com/@vitest/coverage-v8@4.1.2/LICENSE"
46
36
  },
47
- "@vitest/ui@4.0.18": {
37
+ "@vitest/ui@4.1.2": {
48
38
  "licenses": "MIT",
49
39
  "repository": "https://github.com/vitest-dev/vitest",
50
- "licenseUrl": "https://unpkg.com/@vitest/ui@4.0.18/LICENSE"
40
+ "licenseUrl": "https://unpkg.com/@vitest/ui@4.1.2/LICENSE"
51
41
  },
52
- "axe-core@4.10.3": {
42
+ "axe-core@4.11.2": {
53
43
  "licenses": "MPL-2.0",
54
44
  "repository": "https://github.com/dequelabs/axe-core",
55
- "licenseUrl": "https://unpkg.com/axe-core@4.10.3/LICENSE"
45
+ "licenseUrl": "https://unpkg.com/axe-core@4.11.2/LICENSE"
56
46
  },
57
47
  "cypress-axe@1.7.0": {
58
48
  "licenses": "MIT",
59
49
  "repository": "https://github.com/component-driven/cypress-axe",
60
50
  "licenseUrl": "https://unpkg.com/cypress-axe@1.7.0/License.md"
61
51
  },
62
- "cypress@15.0.0": {
52
+ "cypress@15.13.0": {
63
53
  "licenses": "MIT",
64
54
  "repository": "https://github.com/cypress-io/cypress",
65
55
  "licenseUrl": "https://cypress.io"
@@ -69,30 +59,10 @@
69
59
  "repository": "https://github.com/d3/d3-color",
70
60
  "licenseUrl": "https://unpkg.com/d3-color@3.1.0/LICENSE"
71
61
  },
72
- "esbuild@0.27.2": {
73
- "licenses": "MIT",
74
- "repository": "https://github.com/evanw/esbuild",
75
- "licenseUrl": "https://unpkg.com/esbuild@0.27.2/LICENSE.md"
76
- },
77
- "eslint-config-google@0.14.0": {
78
- "licenses": "Apache-2.0",
79
- "repository": "https://github.com/google/eslint-config-google",
80
- "licenseUrl": "https://unpkg.com/eslint-config-google@0.14.0/LICENSE"
81
- },
82
- "eslint-config-prettier@10.1.8": {
83
- "licenses": "MIT",
84
- "repository": "https://github.com/prettier/eslint-config-prettier",
85
- "licenseUrl": "https://unpkg.com/eslint-config-prettier@10.1.8/LICENSE"
86
- },
87
- "eslint@9.34.0": {
88
- "licenses": "MIT",
89
- "repository": "https://github.com/eslint/eslint",
90
- "licenseUrl": "https://unpkg.com/eslint@9.34.0/LICENSE"
91
- },
92
- "github-markdown-css@5.8.1": {
62
+ "github-markdown-css@5.9.0": {
93
63
  "licenses": "MIT",
94
64
  "repository": "https://github.com/sindresorhus/github-markdown-css",
95
- "licenseUrl": "https://unpkg.com/github-markdown-css@5.8.1/license"
65
+ "licenseUrl": "https://unpkg.com/github-markdown-css@5.9.0/license"
96
66
  },
97
67
  "highlight.js@11.11.1": {
98
68
  "licenses": "BSD-3-Clause",
@@ -104,105 +74,85 @@
104
74
  "repository": "https://github.com/davidparsson/junit-report-builder",
105
75
  "licenseUrl": "https://unpkg.com/junit-report-builder@5.1.1/LICENSE"
106
76
  },
107
- "lint-staged@16.1.5": {
77
+ "lint-staged@16.4.0": {
108
78
  "licenses": "MIT",
109
79
  "repository": "https://github.com/lint-staged/lint-staged",
110
- "licenseUrl": "https://unpkg.com/lint-staged@16.1.5/LICENSE"
80
+ "licenseUrl": "https://unpkg.com/lint-staged@16.4.0/LICENSE"
111
81
  },
112
- "lit-html@3.3.1": {
82
+ "lit-html@3.3.2": {
113
83
  "licenses": "BSD-3-Clause",
114
84
  "repository": "https://github.com/lit/lit",
115
- "licenseUrl": "https://unpkg.com/lit-html@3.3.1/LICENSE"
85
+ "licenseUrl": "https://unpkg.com/lit-html@3.3.2/LICENSE"
116
86
  },
117
- "lit@3.3.1": {
87
+ "lit@3.3.2": {
118
88
  "licenses": "BSD-3-Clause",
119
89
  "repository": "https://github.com/lit/lit",
120
- "licenseUrl": "https://unpkg.com/lit@3.3.1/LICENSE"
90
+ "licenseUrl": "https://unpkg.com/lit@3.3.2/LICENSE"
121
91
  },
122
- "marked@16.2.1": {
92
+ "marked@18.0.0": {
123
93
  "licenses": "MIT",
124
94
  "repository": "https://github.com/markedjs/marked",
125
- "licenseUrl": "https://unpkg.com/marked@16.2.1/LICENSE.md"
95
+ "licenseUrl": "https://unpkg.com/marked@18.0.0/LICENSE.md"
126
96
  },
127
- "postcss-prefix-selector@2.1.1": {
97
+ "oxfmt@0.44.0": {
128
98
  "licenses": "MIT",
129
- "repository": "https://github.com/RadValentin/postcss-prefix-selector",
130
- "licenseUrl": "https://unpkg.com/postcss-prefix-selector@2.1.1/LICENSE"
99
+ "repository": "https://github.com/oxc-project/oxc",
100
+ "licenseUrl": "https://unpkg.com/oxfmt@0.44.0/LICENSE"
131
101
  },
132
- "postcss@8.5.6": {
102
+ "oxlint-tsgolint@0.20.0": {
133
103
  "licenses": "MIT",
134
- "repository": "https://github.com/postcss/postcss",
135
- "licenseUrl": "https://unpkg.com/postcss@8.5.6/LICENSE"
104
+ "repository": "https://github.com/oxc-project/tsgolint",
105
+ "licenseUrl": "https://unpkg.com/oxlint-tsgolint@0.20.0/LICENSE"
136
106
  },
137
- "prettier@3.8.1": {
107
+ "oxlint@1.59.0": {
138
108
  "licenses": "MIT",
139
- "repository": "https://github.com/prettier/prettier",
140
- "licenseUrl": "https://unpkg.com/prettier@3.8.1/LICENSE"
109
+ "repository": "https://github.com/oxc-project/oxc",
110
+ "licenseUrl": "https://unpkg.com/oxlint@1.59.0/LICENSE"
141
111
  },
142
- "resolve-pkg@2.0.0": {
143
- "licenses": "MIT",
144
- "repository": "https://github.com/sindresorhus/resolve-pkg",
145
- "licenseUrl": "https://unpkg.com/resolve-pkg@2.0.0/license"
146
- },
147
- "sass@1.91.0": {
148
- "licenses": "MIT",
149
- "repository": "https://github.com/sass/dart-sass",
150
- "licenseUrl": "https://unpkg.com/sass@1.91.0/LICENSE"
151
- },
152
- "stylelint-config-recommended-scss@16.0.0": {
112
+ "postcss-prefix-selector@2.1.1": {
153
113
  "licenses": "MIT",
154
- "repository": "https://github.com/stylelint-scss/stylelint-config-recommended-scss",
155
- "licenseUrl": "https://unpkg.com/stylelint-config-recommended-scss@16.0.0/LICENSE"
114
+ "repository": "https://github.com/RadValentin/postcss-prefix-selector",
115
+ "licenseUrl": "https://unpkg.com/postcss-prefix-selector@2.1.1/LICENSE"
156
116
  },
157
- "stylelint-config-standard@39.0.0": {
117
+ "postcss@8.5.8": {
158
118
  "licenses": "MIT",
159
- "repository": "https://github.com/stylelint/stylelint-config-standard",
160
- "licenseUrl": "https://unpkg.com/stylelint-config-standard@39.0.0/LICENSE"
119
+ "repository": "https://github.com/postcss/postcss",
120
+ "licenseUrl": "https://unpkg.com/postcss@8.5.8/LICENSE"
161
121
  },
162
- "stylelint-scss@6.12.1": {
122
+ "resolve-pkg@3.0.1": {
163
123
  "licenses": "MIT",
164
- "repository": "https://github.com/stylelint-scss/stylelint-scss",
165
- "licenseUrl": "https://unpkg.com/stylelint-scss@6.12.1/LICENSE"
124
+ "repository": "https://github.com/sindresorhus/resolve-pkg",
125
+ "licenseUrl": "https://unpkg.com/resolve-pkg@3.0.1/license"
166
126
  },
167
- "stylelint@16.23.1": {
127
+ "sass@1.99.0": {
168
128
  "licenses": "MIT",
169
- "repository": "https://github.com/stylelint/stylelint",
170
- "licenseUrl": "https://unpkg.com/stylelint@16.23.1/LICENSE"
129
+ "repository": "https://github.com/sass/dart-sass",
130
+ "licenseUrl": "https://unpkg.com/sass@1.99.0/LICENSE"
171
131
  },
172
- "tsup@8.5.1": {
132
+ "tsdown@0.21.7": {
173
133
  "licenses": "MIT",
174
- "repository": "https://github.com/egoist/tsup",
175
- "licenseUrl": "https://unpkg.com/tsup@8.5.1/LICENSE"
134
+ "repository": "https://github.com/rolldown/tsdown",
135
+ "licenseUrl": "https://unpkg.com/tsdown@0.21.7/LICENSE"
176
136
  },
177
- "turbo@2.5.6": {
137
+ "turbo@2.9.4": {
178
138
  "licenses": "MIT",
179
139
  "repository": "https://github.com/vercel/turborepo",
180
- "licenseUrl": "https://unpkg.com/turbo@2.5.6/LICENSE"
140
+ "licenseUrl": "https://unpkg.com/turbo@2.9.4/LICENSE"
181
141
  },
182
- "typescript-eslint@8.41.0": {
183
- "licenses": "MIT",
184
- "repository": "https://github.com/typescript-eslint/typescript-eslint",
185
- "licenseUrl": "https://unpkg.com/typescript-eslint@8.41.0/LICENSE"
186
- },
187
- "typescript@5.9.3": {
142
+ "typescript@6.0.2": {
188
143
  "licenses": "Apache-2.0",
189
144
  "repository": "https://github.com/microsoft/TypeScript",
190
- "licenseUrl": "https://unpkg.com/typescript@5.9.3/LICENSE.txt"
191
- },
192
- "vite-tsconfig-paths@5.1.4": {
193
- "licenses": "MIT",
194
- "repository": "https://github.com/aleclarson/vite-tsconfig-paths",
195
- "licenseUrl": "https://unpkg.com/vite-tsconfig-paths@5.1.4/LICENSE"
145
+ "licenseUrl": "https://unpkg.com/typescript@6.0.2/LICENSE.txt"
196
146
  },
197
- "vite@7.3.1": {
147
+ "vite@8.0.5": {
198
148
  "licenses": "MIT",
199
149
  "repository": "https://github.com/vitejs/vite",
200
- "licenseUrl": "https://unpkg.com/vite@7.3.1/LICENSE.md"
150
+ "licenseUrl": "https://unpkg.com/vite@8.0.5/LICENSE.md"
201
151
  },
202
- "vitest@4.0.18": {
152
+ "vitest@4.1.2": {
203
153
  "licenses": "MIT",
204
154
  "repository": "https://github.com/vitest-dev/vitest",
205
- "licenseUrl": "https://unpkg.com/vitest@4.0.18/LICENSE.md"
155
+ "licenseUrl": "https://unpkg.com/vitest@4.1.2/LICENSE.md"
206
156
  },
207
157
  "yargs@18.0.0": {
208
158
  "licenses": "MIT",
package/package.json CHANGED
@@ -1,27 +1,36 @@
1
1
  {
2
2
  "name": "@cas-smartdesign/virtual-list",
3
- "version": "7.2.1",
3
+ "version": "9.0.0",
4
4
  "description": "A virtualized list element with SmartDesign look and feel.",
5
- "main": "dist/virtual-list-with-externals.js",
6
- "module": "dist/virtual-list.mjs",
7
5
  "license": "SEE LICENSE IN LICENSE",
8
- "types": "dist/virtual-list.d.ts",
9
- "dependencies": {
10
- "lit": "^3.3.1",
11
- "@cas-smartdesign/list-item": "^7.8.0"
12
- },
13
- "devDependencies": {
14
- "@cas-smartdesign/element-preview": "^0.4.0",
15
- "@cas-smartdesign/element-utils": "^1.3.0",
16
- "@cas-smartdesign/license-generator": "^1.9.0"
17
- },
18
6
  "files": [
19
7
  "dist",
20
8
  "npm-third-party-licenses.json"
21
9
  ],
10
+ "type": "module",
11
+ "main": "dist/virtual-list.mjs",
12
+ "module": "dist/virtual-list.mjs",
13
+ "types": "dist/virtual-list.d.ts",
22
14
  "publishConfig": {
23
- "registry": "https://registry.npmjs.org/",
24
- "access": "public"
15
+ "access": "public",
16
+ "registry": "https://registry.npmjs.org/"
17
+ },
18
+ "dependencies": {
19
+ "lit": "^3.3.2",
20
+ "@cas-smartdesign/list-item": "^9.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@cas-smartdesign/element-preview": "^1.1.0",
24
+ "@cas-smartdesign/license-generator": "^1.10.0",
25
+ "@cas-smartdesign/element-utils": "^2.0.0"
26
+ },
27
+ "peerDependencies": {
28
+ "@cas-smartdesign/design-tokens": "^3.0.2"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "@cas-smartdesign/design-tokens": {
32
+ "optional": true
33
+ }
25
34
  },
26
35
  "scripts": {
27
36
  "version": "pnpm version",
package/readme.md CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  A list element with ui-virtualization and infinite scrolling.
4
4
 
5
+ This element must be used together with the design tokens of SmartDesign.
6
+ For an independent application, make sure to include the @cas-smartdesign/design-tokens package.
7
+ For a web app / web widget, refer to the official documentation about design token usage.
8
+
5
9
  ## Attributes
6
10
 
7
11
  - `item-height`
8
- - Defines the height in px of the list items.
12
+ - Defines the height in px of the list items. Defaults to 48.
9
13
  - `item-count`
10
14
  - Defines the virtual number of items in the list.
11
15
  - `selection-type`
@@ -13,8 +17,10 @@ A list element with ui-virtualization and infinite scrolling.
13
17
  - Available values: "trigger-only", "single", "multi"
14
18
  - `focus-index`
15
19
  - Defines the index of currently focused item
20
+ - `focus-target`
21
+ - When present, the item at `focus-index` is kept marked as `focused` even while the list itself does not have DOM focus.
16
22
  - `role`: string
17
- - Aria attribute, default value is "list"
23
+ - Aria attribute, default value is "listbox"
18
24
 
19
25
  ## Properties
20
26
 
@@ -24,30 +30,32 @@ The following properties are available:
24
30
  - Contains data for the currently rendered list items.
25
31
  - `itemGenerator` **_ItemGenerator (default is the generator inside the list-item element)_**
26
32
  - A method that renders the list items.
27
- - `itemHeight` **_number (default=50)_**
33
+ - `itemHeight` **_number (default=48)_**
28
34
  - Reflects the corresponding attribute
29
35
  - `itemCount` **_number (default=0)_**
30
36
  - Reflects the corresponding attribute
31
37
  - `selectionType` **_string (default="trigger-only")_**
32
38
  - Reflects the corresponding attribute
33
- - `focusIndex` **_number (default=undefined)_**
34
- - Reflects the corresponding attribute
39
+ - `focusIndex` **_number (default=-1)_**
40
+ - Reflects the corresponding attribute. `-1` means no item is focused.
35
41
  - `selectedIndices` **_number[] (default=empty)_**
36
42
  - Contains the indices of the selected items.
43
+ - `focusTarget` **_boolean (default=false)_**
44
+ - Reflects the `focus-target` attribute. Keeps the focused item marked even while the list does not have DOM focus.
45
+ - `finalSizeIsKnown` **_boolean (default=undefined)_**
46
+ - Indicates whether the total number of items is final. While false/undefined the list is in infinite-scrolling state and items report `aria-setsize="-1"`.
37
47
 
38
48
  ## CSS Custom Properties
39
49
 
40
- - `--sd-virtual-list-focus-highlight-color`
41
- - Defines the focus highlight color for list items, defaults to #1467ba
42
- - `--sd-virtual-list-item-separator-color`
43
- - Defines the separator color for list items, defaults to #d9d9d9
50
+ - `--sd-virtual-list-background-color`
51
+ - Defines the background color of the list (default is the `--color-bg-default` token, `#ffffff`)
44
52
 
45
53
  ## Custom events
46
54
 
47
- - `data-request`
55
+ - `sd-virtual-list-data-request`
48
56
  - Sent after scrolling the list
49
57
  - Contains the starting and ending index that is visible in the list
50
- - `selection`
58
+ - `sd-virtual-list-selection`
51
59
  - Dispatched when one of the items is selected/deselected
52
60
  - Contains the index of the item and a `selected` flag which is when false indicates that the item is deselected
53
61
  - The `originalEvent` a mouse or keyboard event that triggered the selection event.
@@ -58,7 +66,8 @@ The following properties are available:
58
66
  - Returns the DOM node that represents the item with the given index
59
67
  - Note that only visible items can be accessed this way
60
68
  - `scrollToItem`
61
- - Scrolls the list to the item with the given index
69
+ - Scrolls the list to the item with the given index.
70
+ - Accepts an optional alignment argument: `"auto"` (default), `"start"`, `"center"`, or `"end"`. A small padding is kept between the item and the viewport edge so the item's focus ring stays visible.
62
71
  - `increaseWidthOnNextRenderIfNeeded`
63
72
  - The width of the list is increased on the next rendering phase to an extent, that all texts in the list-items are visible without ellipsis.
64
73
  - If the list has already reached it's maximum width, then line clamp may be enabled on the items to wrap the content if possible.