@nexora-ui/listbox-cdk
v0.1.2
Published
CDK virtual-scroll list panel used by **combobox** and **select** in built-in virtual mode. Registers with `NxrListboxVirtualScrollRegistry` so keyboard navigation targets the full logical list while the DOM stays windowed.
Downloads
629
Readme
@nexora-ui/listbox-cdk
CDK virtual-scroll list panel used by combobox and select in built-in virtual mode. Registers with NxrListboxVirtualScrollRegistry so keyboard navigation targets the full logical list while the DOM stays windowed.
Package layout
| Area | Path | Role |
| ----------------------------- | --------------------- | --------------------------------------------------------------------------------------------- |
| Public components | src/lib/components/ | ListboxCdkVirtualPanelComponent, built-in shell / dropdown, template directives |
| Overlay flex tokens | src/lib/layout/ | Shared nxr-listbox-cdk-overlay-flex-column styles (pane + hosts need a definite flex chain) |
| Portal | src/lib/portal/ | createListboxOverlayPanelPortal |
| Stateless virtual helpers | src/lib/virtual/ | Selection index math, scroll alignment, LRU labels, first-paint scheduling |
Root entry (@nexora-ui/listbox-cdk): components + NXR_LISTBOX_CDK_OVERLAY_FLEX_COLUMN_CLASS for advanced styling.
Internal entry (@nexora-ui/listbox-cdk/internal): portal, signals factory, scroll/index utilities, afterVirtualPanelFirstPaint. See internal/README.md.
Peers: @nexora-ui/listbox, @angular/cdk, @nexora-ui/overlay (portal).
When you use this
- Default:
virtualScroll+virtualItemson<nxr-combobox>/<nxr-select>— they hostnxr-builtin-virtual-dropdown-paneland wire overlay + listbox. Row/header/footer templates:nxrComboboxVirtual*/nxrSelectVirtual*. - Custom panel: embed
nxr-listbox-cdk-virtual-panelonly withNxrListboxOverlayPanelHostComponent’s injector (NXR_LISTBOX_CONTROLLER,NxrListboxVirtualScrollRegistry). Import the host/context symbols from@nexora-ui/listbox/internal, usechildOwnsScroll: true, and:viewportMaxHeightaligned with overlaymaxHeightfillAvailableHeightwhen the parent is a flex column under a capped panemergeVirtualDropdownPaneStyle+createListboxVirtualDropdownPanelStyle(from@nexora-ui/dropdown) on the pane somax-heightalone does not collapse flex children to 0- Optional: reuse
NXR_LISTBOX_CDK_OVERLAY_FLEX_COLUMN_CLASSon your hosts to match the built-in shell
Component inputs
| Input | Purpose |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| items | Logical array (e.g. filtered options). |
| itemSize | Row height in px (default 40). Must match rendered row CSS. |
| initialSelectedIndex | When ≥ 0, scrolls after layout and sets active option. |
| viewportMaxHeight | Viewport max-height (default 200px). With fillAvailableHeight, caps a flex-grown viewport. |
| fillAvailableHeight | Host joins the overlay flex column; viewport fills remaining space in the shell. |
| labelFor | Stable (item) => string reference preferred so the label LRU is not cleared every CD cycle. |
| trackByKey | Stable key per row; built-in combobox/select default to accessors().value when virtualTrackByKey is omitted. Duplicate keys → first index wins. |
| emptyMessage | Empty state copy (role="status", aria-live="polite"). |
| optionTemplate | TemplateRef context { $implicit: item }; labelFor still used where the listbox needs text. |
Behavior notes
- First paint:
afterVirtualPanelFirstPaintrunscheckViewportSizeafterafterNextRenderand again on the next frame when syncing initial selection — portaled viewports often measure 0×0 on the first tick. - ResizeObserver on the viewport is coalesced to one
checkViewportSizeper animation frame (createRafThrottledfrom@nexora-ui/core). getCurrentIndexuses a map fromitems+trackByKey(O(1) per lookup).- Labels: bounded LRU (512 entries); invalidates when
itemsreference orlabelForidentity changes. - “Nearest” scroll: uses overlap with the listbox found from
viewport.parentElement.closest('[role="listbox"]')so header/footer chrome does not fake “fully visible” rows.
Installation
npm install @nexora-ui/listbox-cdk @nexora-ui/listbox @angular/cdkTests
nx test listbox-cdk