@ixfx/components 0.9.8 → 0.10.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.
- package/bundle/index.d.ts +747 -4
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +12240 -9065
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/{ac-token-TCLAZeVg.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
- package/dist/{ac-token-TCLAZeVg.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/button.d.ts +1 -1
- package/dist/button.d.ts.map +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/crumbs.d.ts +2 -2
- package/dist/{data-grid-BUeZjnvj.d.ts → data-grid-C5hk_pzK.d.ts} +5 -4
- package/dist/{data-grid-BUeZjnvj.d.ts.map → data-grid-C5hk_pzK.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +2 -2
- package/dist/data-grid.js +3 -1
- package/dist/data-grid.js.map +1 -1
- package/dist/{detail-list-CQguZg9h.d.ts → detail-list-CxPpv89T.d.ts} +6 -5
- package/dist/detail-list-CxPpv89T.d.ts.map +1 -0
- package/dist/detail-list.d.ts +3 -3
- package/dist/detail-list.js +3 -1
- package/dist/detail-list.js.map +1 -1
- package/dist/{grid-list-lTwg4lp7.d.ts → grid-list-BGvoWbZz.d.ts} +28 -4
- package/dist/{grid-list-lTwg4lp7.d.ts.map → grid-list-BGvoWbZz.d.ts.map} +1 -1
- package/dist/{grid-list-40blkeza.js → grid-list-DSnYOGh7.js} +60 -2
- package/dist/grid-list-DSnYOGh7.js.map +1 -0
- package/dist/grid-list.d.ts +2 -2
- package/dist/grid-list.js +1 -1
- package/dist/{grouped-item-lister-CEZ72VOs.d.ts → grouped-item-lister-fdZHVxFM.d.ts} +2 -2
- package/dist/{grouped-item-lister-CEZ72VOs.d.ts.map → grouped-item-lister-fdZHVxFM.d.ts.map} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{icon-DR_3rSyZ.d.ts → icon-CDGprSdE.d.ts} +2 -2
- package/dist/icon-CDGprSdE.d.ts.map +1 -0
- package/dist/icons.d.ts +2 -2
- package/dist/incr-search.d.ts +1 -1
- package/dist/{index--qnhBWZJ.d.ts → index--5BSdbnL.d.ts} +2 -2
- package/dist/{index--qnhBWZJ.d.ts.map → index--5BSdbnL.d.ts.map} +1 -1
- package/dist/{index-C59-JEPl.d.ts → index-9AhaHIT2.d.ts} +3 -3
- package/dist/{index-C59-JEPl.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
- package/dist/{index-DsjpDksO.d.ts → index-CS9yM8L-.d.ts} +2 -2
- package/dist/{index-DsjpDksO.d.ts.map → index-CS9yM8L-.d.ts.map} +1 -1
- package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +2 -2
- package/dist/{index-BUB5SICW.d.ts.map → index-CoqtMSd9.d.ts.map} +1 -1
- package/dist/{index-CJ5fshD3.d.ts → index-UvnoZUAo.d.ts} +2 -2
- package/dist/{index-CJ5fshD3.d.ts.map → index-UvnoZUAo.d.ts.map} +1 -1
- package/dist/{index-BOUaDIW-.d.ts → index-tq6f8007.d.ts} +2 -2
- package/dist/{index-BOUaDIW-.d.ts.map → index-tq6f8007.d.ts.map} +1 -1
- package/dist/index.d.ts +647 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4804 -2313
- package/dist/index.js.map +1 -1
- package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +2 -2
- package/dist/{labelled-input-base-Dp_9KP0G.d.ts.map → labelled-input-base-DiTme1JO.d.ts.map} +1 -1
- package/dist/labelled-radial-input.d.ts +2 -2
- package/dist/labelled-radial-input.d.ts.map +1 -1
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-slider-input.d.ts +1 -1
- package/dist/{list-native-drag-controller-B0hWdbtM.js → list-native-drag-controller-D97TYjn1.js} +36 -5
- package/dist/list-native-drag-controller-D97TYjn1.js.map +1 -0
- package/dist/{list-native-drag-controller-Cmpx7jnx.d.ts → list-native-drag-controller-DWiXQZou.d.ts} +3 -2
- package/dist/list-native-drag-controller-DWiXQZou.d.ts.map +1 -0
- package/dist/{menu-item-ZmkXNjek.d.ts → menu-item-CZi9vy5O.d.ts} +2 -2
- package/dist/{menu-item-ZmkXNjek.d.ts.map → menu-item-CZi9vy5O.d.ts.map} +1 -1
- package/dist/menu.d.ts +2 -2
- package/dist/miller.d.ts +2 -2
- package/dist/panel.d.ts +1 -1
- package/dist/{split-layout-C5SYbDrq.d.ts → split-layout-JK3xWVX2.d.ts} +2 -2
- package/dist/{split-layout-C5SYbDrq.d.ts.map → split-layout-JK3xWVX2.d.ts.map} +1 -1
- package/dist/split-layout.d.ts +1 -1
- package/dist/{tab-list-DbMIL520.d.ts → tab-list-CGyPt07Z.d.ts} +2 -2
- package/dist/{tab-list-DbMIL520.d.ts.map → tab-list-CGyPt07Z.d.ts.map} +1 -1
- package/dist/tabs.d.ts +1 -1
- package/dist/{titlebar-B5zSTZnF.d.ts → titlebar-Tqu-VvMU.d.ts} +2 -2
- package/dist/{titlebar-B5zSTZnF.d.ts.map → titlebar-Tqu-VvMU.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/{tree-CVj7TIk2.js → tree-C25xYUa6.js} +4 -2
- package/dist/tree-C25xYUa6.js.map +1 -0
- package/dist/{tree-component-BW2iCFq9.d.ts → tree-component-mw8x-n2Y.d.ts} +4 -2
- package/dist/tree-component-mw8x-n2Y.d.ts.map +1 -0
- package/dist/tree.d.ts +4 -3
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +1 -1
- package/dist/{vertical-list-CHrXmmQ3.d.ts → vertical-list--tFanQwM.d.ts} +92 -4
- package/dist/vertical-list--tFanQwM.d.ts.map +1 -0
- package/dist/vertical-list.d.ts +2 -2
- package/dist/vertical-list.js +617 -28
- package/dist/vertical-list.js.map +1 -1
- package/docs-user/grid-list.md +14 -0
- package/docs-user/index.json +1 -1
- package/package.json +1 -1
- package/dist/detail-list-CQguZg9h.d.ts.map +0 -1
- package/dist/grid-list-40blkeza.js.map +0 -1
- package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
- package/dist/list-native-drag-controller-B0hWdbtM.js.map +0 -1
- package/dist/list-native-drag-controller-Cmpx7jnx.d.ts.map +0 -1
- package/dist/tree-CVj7TIk2.js.map +0 -1
- package/dist/tree-component-BW2iCFq9.d.ts.map +0 -1
- package/dist/vertical-list-CHrXmmQ3.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertical-list.js","names":["#dragSelect","#nativeDrag","#wrappedElements","#prepareNativeDrag","#nativeDragging","#startPostDragSuppressTimer","#marqueeHitTest","#marqueeRect","#postDragSuppressTimer","#searchRegistry","#effectiveSearchModes","#unregisterSearchCommands","#animatedItems","#itemObserver","#onItemsMutated","#syncSearchCommands","#customWrappers","#itemForKey","#marqueeStyle","customElement"],"sources":["../src/vertical-list/vertical-list.ts"],"sourcesContent":["import type { CommandId, CommandRegistry } from '@clinth/ui-commands';\nimport type { PropertyValues } from 'lit';\nimport type { ListSearchMode } from '../incr-search/index.js';\nimport type { DragSelectRect } from '../interaction/list-drag-select-controller.js';\nimport type { ListDragEntry, ListDragPreviewRenderer, ListNativeDragStartEvent } from '../interaction/list-drag-types.js';\nimport type {\n ListActivateDetail,\n ListElementEventMap,\n ListInteractionMode,\n ListItemClickDetail,\n ListSelectDetail,\n ListSelectionMode,\n ListTickleDetail,\n} from '../interaction/list-selection-types.js';\nimport { createCommandRegistry } from '@clinth/ui-commands';\nimport { css, html, LitElement, render } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport {\n createElementListSearchAdapter,\n LIST_SEARCH_MODES,\n ListSearchController,\n listSearchStyles,\n registerListSearchCommands,\n} from '../incr-search/index.js';\nimport { keyForElement } from '../interaction/keyed-list.js';\nimport { ListDragSelectController } from '../interaction/list-drag-select-controller.js';\nimport { animateListItemIn, animateListItemOut } from '../interaction/list-item-animation.js';\nimport { ListNativeDragController } from '../interaction/list-native-drag-controller.js';\nimport { ListSelectionController } from '../interaction/list-selection-controller.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type {\n ListDragEntry,\n ListDragPreview,\n ListDragPreviewContext,\n ListDragPreviewRenderer,\n ListDragSource,\n ListNativeDragStartDetail,\n ListNativeDragStartEvent,\n} from '../interaction/list-drag-types.js';\nexport type {\n ListActivateDetail,\n ListActivateEvent,\n ListElementEventMap,\n ListInteractionMode,\n ListItemClickDetail,\n ListItemClickEvent,\n ListSelectDetail,\n ListSelectEvent,\n ListSelectionMode,\n ListTickleDetail,\n ListTickleEvent,\n} from './types.js';\n\nexport interface CustomCheckboxOptions {\n renderer: (checked: boolean) => unknown;\n margin?: string;\n width?: string;\n}\n\nexport interface AddItemOptions {\n /**\n * In `checked` interaction mode, adds the item without a checkbox column and\n * without the ability to be checked/selected. Equivalent to setting the\n * `not-checked` attribute on the item. Ignored outside `checked` mode.\n */\n notChecked?: boolean;\n}\n\nconst ITEM_SELECTOR = `li, [data-list-item]`;\n\n@customElement(`ixfx-vertical-list`)\nexport class VerticalListElement extends LitElement {\n @property({ type: String, attribute: `selection-mode` })\n selectionMode: ListSelectionMode = `single`;\n\n @property({ type: String, attribute: `interaction-mode` })\n interactionMode: ListInteractionMode = `standard`;\n\n @property({ attribute: false })\n filterPredicate: ((el: Element) => boolean) | undefined;\n\n /**\n * Whether keyboard navigation wraps from last to first and vice versa.\n * - 'stop' (default): navigation stops at the boundary\n * - 'wrap': navigation wraps around\n */\n @property({ type: String, attribute: `item-wrap` })\n itemWrap: `stop` | `wrap` = `stop`;\n\n /**\n * Optional renderer for the checkbox shown in `checked` interactionMode.\n * Receives the current `checked` state and returns a Lit template result.\n *\n * When set, the per-row checkbox becomes a `<span role=\"checkbox\">` whose\n * contents are whatever this returns (rendered with `lit`'s `render()`).\n * When unset, a native `<input type=\"checkbox\">` is used.\n *\n * @example\n * list.checkboxRenderer = (checked) => checked\n * ? html`<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\"\n * fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\n * stroke-linecap=\"round\" stroke-linejoin=\"round\"\n * style=\"opacity:0.5\">\n * <polyline points=\"3,8 7,12 13,4\" />\n * </svg>`\n * : html``;\n */\n @property({ attribute: false })\n checkboxRenderer: ((checked: boolean) => unknown) | CustomCheckboxOptions | undefined;\n\n /**\n * Space-separated subset of `navigate select filter` — limits which\n * incremental-search modes are offered. Unset ⇒ all three; empty ⇒ search\n * disabled. See `docs/infra-incremental.md`.\n */\n @property({ type: String, attribute: `search-modes`, reflect: true })\n searchModes: string | undefined;\n\n /**\n * Enable native browser drag-and-drop for selectable items. When true,\n * selectable rows become draggable and the list emits\n * `list-native-drag-start` when a drag begins.\n */\n @property({ type: Boolean, attribute: `items-draggable`, reflect: true })\n itemsDraggable = false;\n\n /**\n * Custom drag preview renderer (synchronous). Defaults to the shared\n * built-in HTML+canvas preview.\n */\n @property({ attribute: false })\n dragPreviewRenderer: ListDragPreviewRenderer<Element> | undefined;\n\n #customWrappers = new Map<HTMLLIElement, Element>();\n #wrappedElements = new Set<Element>();\n\n /** Watches for items added to the light DOM so they can be animated in. */\n #itemObserver: MutationObserver | undefined;\n /** Items that have already played (or been skipped for) their enter animation. */\n #animatedItems = new WeakSet<Element>();\n\n private readonly selection = new ListSelectionController<Element>({\n getOrderedItems: () => this._getVisibleItems(),\n isSelectable: el => this._isCheckable(el),\n getModes: () => ({ selectionMode: this.selectionMode, interactionMode: this.interactionMode }),\n getKey: keyForElement,\n onChange: (selected, previous) => {\n this._syncItemStates();\n this._dispatch<ListSelectDetail>(`list-select`, {\n selected,\n previous,\n selectedKeys: this.selection.selectedKeys,\n });\n },\n });\n\n private tickled = new TickledController<Element>(this, {\n getItems: () => this._getVisibleItems().map(el => ({\n id: el,\n enabled: !el.hasAttribute(`not-checked`),\n })),\n onTickle: (id) => {\n if (id !== undefined) {\n this._dispatch<ListTickleDetail>(`list-tickle`, { item: id });\n }\n },\n onStateChange: () => this._syncItemStates(),\n itemWrap: this.itemWrap,\n hoverDisabled: () => this.#dragSelect.isDragging || this.#nativeDrag.isDragging,\n });\n\n #nativeDragging = false;\n #postDragSuppressTimer = 0;\n\n readonly #nativeDrag = new ListNativeDragController<Element>(this, {\n source: `vertical-list`,\n isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this._getVisibleItems().length > 0,\n resolveEventToKey: (target) => {\n if (!(target instanceof Element))\n return undefined;\n const item = target.closest?.(ITEM_SELECTOR) as Element | null;\n if (!item || !this.contains(item) || this.#wrappedElements.has(item))\n return undefined;\n return keyForElement(item);\n },\n prepareSelection: originKey => this.#prepareNativeDrag(originKey),\n getMetrics: () => ({}),\n getRenderer: () => this.dragPreviewRenderer,\n dispatch: detail => this._dispatchCancelable(`list-native-drag-start`, detail),\n onActiveChange: (active, originKey) => {\n this.#nativeDragging = active;\n this.toggleAttribute(`data-native-dragging`, active);\n for (const el of this._getVisibleItems())\n el.toggleAttribute(`data-drag-origin`, active && originKey !== undefined && keyForElement(el) === originKey);\n if (active) {\n const count = this.selection.selected.size;\n this.setAttribute(`aria-label`, count <= 1 ? `Dragging 1 item` : `Dragging ${count} items`);\n } else {\n this.removeAttribute(`aria-label`);\n }\n this.requestUpdate();\n },\n onEnd: () => {\n this.#nativeDragging = false;\n this.toggleAttribute(`data-native-dragging`, false);\n this.removeAttribute(`aria-label`);\n for (const el of this._getVisibleItems())\n el.removeAttribute(`data-drag-origin`);\n this.#startPostDragSuppressTimer();\n },\n syncLightDomDraggable: () => this._syncNativeDraggable(),\n });\n\n #prepareNativeDrag(originKey: string): { origin: ListDragEntry<Element>; selected: Array<ListDragEntry<Element>> } | undefined {\n const visible = this._getVisibleItems();\n const originEl = visible.find(el => keyForElement(el) === originKey);\n if (!originEl || !this._isCheckable(originEl))\n return undefined;\n if (!this.selection.selected.has(originEl))\n this.selection.replace(originEl);\n const selected: Array<ListDragEntry<Element>> = [];\n visible.forEach((el, index) => {\n if (!this.selection.selected.has(el))\n return;\n selected.push({ key: keyForElement(el) ?? originKey, index, item: el, element: el });\n });\n const origin = selected.find(entry => entry.key === originKey);\n if (!origin)\n return undefined;\n return { origin, selected };\n }\n\n private _syncNativeDraggable(): void {\n if (!this.isConnected)\n return;\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n if (el instanceof HTMLElement)\n el.draggable = this.itemsDraggable && this._isCheckable(el);\n }\n }\n\n #startPostDragSuppressTimer(): void {\n if (this.#postDragSuppressTimer)\n clearTimeout(this.#postDragSuppressTimer);\n this.#postDragSuppressTimer = window.setTimeout(() => {\n this.#postDragSuppressTimer = 0;\n }, 0);\n }\n\n /** Live drag-select preview rect (surface-relative); the covered items carry `data-marquee`. */\n #marqueeRect: DragSelectRect | undefined;\n\n readonly #dragSelect = new ListDragSelectController<Element>(this, {\n getSurface: () => this.renderRoot.querySelector(`.container`) as HTMLElement | undefined,\n isEnabled: () =>\n this.selection.canDragSelect()\n && this._getVisibleItems().length > 0\n && !this.hasAttribute(`disable-drag-select`),\n hitTest: rect => this.#marqueeHitTest(rect),\n getBaseSelection: () => this.selection.selected,\n onPreview: (preview, rect) => {\n this.#marqueeRect = rect;\n for (const el of this._getVisibleItems())\n el.toggleAttribute(`data-marquee`, preview.has(el));\n this.requestUpdate();\n },\n onCommit: (finalSet) => {\n this.selection.applyDragSelection(finalSet);\n for (const el of this._getVisibleItems())\n el.removeAttribute(`data-marquee`);\n this.#marqueeRect = undefined;\n this.requestUpdate();\n },\n autoScroll: (_dx, dy) => {\n const list = this.renderRoot.querySelector(`ul`);\n if (list)\n list.scrollTop += dy;\n },\n });\n\n /** Collect visible items whose surface-relative box intersects `rect`. */\n #marqueeHitTest(rect: DragSelectRect): Element[] {\n const surface = this.renderRoot.querySelector(`.container`);\n if (!surface)\n return [];\n const box = surface.getBoundingClientRect();\n const rx0 = rect.x;\n const ry0 = rect.y;\n const rx1 = rect.x + rect.width;\n const ry1 = rect.y + rect.height;\n const out: Element[] = [];\n for (const el of this._getVisibleItems()) {\n const r = el.getBoundingClientRect();\n const left = r.left - box.left;\n const top = r.top - box.top;\n if (left <= rx1 && left + r.width >= rx0 && top <= ry1 && top + r.height >= ry0)\n out.push(el);\n }\n return out;\n }\n\n #marqueeStyle(rect: DragSelectRect): string {\n return `left:${rect.x}px;top:${rect.y}px;width:${Math.max(0, rect.width)}px;height:${Math.max(0, rect.height)}px`;\n }\n\n /** Incremental search (navigate / select / filter). See `docs/infra-incremental.md`. */\n readonly search = new ListSearchController<Element>(this, {\n adapter: createElementListSearchAdapter(this, {\n itemSelector: ITEM_SELECTOR,\n getLabel: el => el.getAttribute(`data-search-label`) ?? el.textContent?.trim() ?? ``,\n highlightKey: `vertical-list-search`,\n }),\n });\n\n #searchRegistry: CommandRegistry<unknown> | undefined;\n #unregisterSearchCommands: (() => void) | undefined;\n\n /** Command registry carrying this list's `list.search.*` commands. */\n get registry(): CommandRegistry<unknown> | undefined {\n return this.#searchRegistry;\n }\n\n #effectiveSearchModes(): ListSearchMode[] {\n const raw = this.searchModes?.trim();\n if (raw === undefined)\n return [...LIST_SEARCH_MODES];\n const requested = new Set(raw.split(/\\s+/));\n return LIST_SEARCH_MODES.filter(m => requested.has(m));\n }\n\n #syncSearchCommands(): void {\n if (!this.#searchRegistry)\n return;\n this.search.setModes(this.#effectiveSearchModes());\n this.#unregisterSearchCommands?.();\n this.#unregisterSearchCommands = registerListSearchCommands(this.#searchRegistry, this.search);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute(`tabindex`))\n this.tabIndex = 0;\n this.addEventListener(`pointerover`, this._onPointerOver);\n this.addEventListener(`pointerleave`, this._onPointerLeave);\n this.addEventListener(`keydown`, this._onKeyDown);\n this.addEventListener(`click`, this._onClick);\n this.addEventListener(`dblclick`, this._onDblClick);\n // Mark whatever's already here as \"known\" so the first populate doesn't\n // animate; anything added later collapses in.\n for (const el of this.querySelectorAll(ITEM_SELECTOR))\n this.#animatedItems.add(el);\n this.#itemObserver ??= new MutationObserver(records => this.#onItemsMutated(records));\n this.#itemObserver.observe(this, { childList: true });\n this.#searchRegistry ??= createCommandRegistry();\n this.#syncSearchCommands();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`pointerover`, this._onPointerOver);\n this.removeEventListener(`pointerleave`, this._onPointerLeave);\n this.removeEventListener(`keydown`, this._onKeyDown);\n this.removeEventListener(`click`, this._onClick);\n this.removeEventListener(`dblclick`, this._onDblClick);\n this.#itemObserver?.disconnect();\n this.#unregisterSearchCommands?.();\n this.#unregisterSearchCommands = undefined;\n this.#searchRegistry = undefined;\n if (this.#postDragSuppressTimer) {\n clearTimeout(this.#postDragSuppressTimer);\n this.#postDragSuppressTimer = 0;\n }\n }\n\n /**\n * Animate in items appended to the light DOM (however they got there —\n * {@link addItem}, direct `appendChild`, a framework binding). A bulk populate\n * (roughly everything at once) is left alone, as are the wrapper `<li>`s the\n * checked-mode plumbing shuffles around.\n */\n #onItemsMutated(records: MutationRecord[]): void {\n if (!this.isConnected)\n return;\n const fresh: HTMLElement[] = [];\n for (const record of records) {\n for (const node of record.addedNodes) {\n if (!(node instanceof HTMLElement) || node.parentElement !== this)\n continue;\n if (!node.matches(ITEM_SELECTOR))\n continue;\n if (this.#animatedItems.has(node) || this.#customWrappers.has(node as HTMLLIElement) || this.#wrappedElements.has(node))\n continue;\n this.#animatedItems.add(node);\n fresh.push(node);\n }\n }\n if (fresh.length === 0)\n return;\n const total = this.querySelectorAll(ITEM_SELECTOR).length;\n if (fresh.length >= total)\n return; // first populate / wholesale replace — don't animate\n for (const el of fresh)\n animateListItemIn(el);\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n if (changed.has(`searchModes`)) {\n this.#syncSearchCommands();\n }\n if (changed.has(`interactionMode`)) {\n this.selection.clearAnchor();\n const previousSelected = this.selection.selected;\n // Save wrapper→inner map before _syncCheckboxes() clears it on unwrap\n const leavingChecked = (changed.get(`interactionMode`) as ListInteractionMode) === `checked`;\n const savedWrappers = leavingChecked ? new Map(this.#customWrappers) : null;\n\n this._syncCheckboxes();\n\n // Remap the selection across the wrap/unwrap element-reference boundary\n if (previousSelected.size > 0) {\n if (savedWrappers && savedWrappers.size > 0) {\n // Leaving checked: wrapper refs → inner element refs\n this.selection.remap(el => savedWrappers.get(el as HTMLLIElement) ?? el);\n } else if (this.#customWrappers.size > 0) {\n // Entering checked: inner element refs → wrapper refs\n const innerToWrapper = new Map([...this.#customWrappers].map(([w, i]) => [i, w]));\n this.selection.remap(el => innerToWrapper.get(el) ?? el);\n }\n }\n\n this._syncItemStates();\n } else if (changed.has(`checkboxRenderer`) && this.interactionMode === `checked`) {\n this._syncCheckboxes();\n }\n if (changed.has(`itemsDraggable`) || changed.has(`interactionMode`)) {\n this._syncNativeDraggable();\n this.#nativeDrag.refreshDraggable();\n }\n }\n\n // --- Public API ---\n\n /** The most recently selected item, or `undefined` if nothing is selected. */\n get selectedItem(): Element | undefined {\n return [...this.selection.selected].at(-1);\n }\n\n /** The full current selection set (read-only). */\n get selectedItems(): ReadonlySet<Element> {\n return this.selection.selected;\n }\n\n addItem(item: Element | string, options?: AddItemOptions): void {\n let el: Element;\n if (typeof item === `string`) {\n const li = document.createElement(`li`);\n li.textContent = item;\n el = li;\n } else {\n el = item;\n }\n if (options?.notChecked)\n el.setAttribute(`not-checked`, ``);\n this.appendChild(el);\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n }\n\n /**\n * Collapse + fade `item` out, then detach it. The rows below slide up to\n * close the gap. Resolves once the element has actually been removed.\n * Under `prefers-reduced-motion: reduce` it's removed immediately.\n */\n removeItem(item: Element): Promise<void> {\n this.selection.deselect(item);\n const done = animateListItemOut(item as HTMLElement).then(() => {\n item.remove();\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n });\n return done;\n }\n\n /** {@link removeItem} for several items at once. */\n removeItems(items: Iterable<Element>): Promise<void> {\n return Promise.all([...items].map(item => this.removeItem(item))).then(() => undefined);\n }\n\n clearItems(): void {\n this.#customWrappers.clear();\n this.replaceChildren();\n this.selection.reset();\n this._syncItemStates();\n }\n\n /**\n * Replace the entire item list in one call.\n * Equivalent to `clearItems()` followed by `addItem()` for each element.\n * Preserves `interactionMode` checkbox wrapping.\n */\n setItems(items: readonly Element[]): void {\n this.clearItems();\n for (const item of items) {\n this.appendChild(item);\n }\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n }\n\n /**\n * Dispatch a command to this list — used by `ixfx-grouped-item-lister` to\n * forward commands to all sub-components. Routes through the command registry\n * (so `list.search.*` and any other registered commands work).\n */\n dispatch(commandId: CommandId, args?: Record<string, unknown>): void {\n this.#searchRegistry?.invoke(commandId, args);\n }\n\n select(item: Element): void {\n this.selection.replace(item);\n }\n\n selectMany(items: Iterable<Element>): void {\n this.selection.selectMany(items);\n }\n\n deselect(item: Element): void {\n this.selection.deselect(item);\n }\n\n clearSelection(): void {\n this.selection.clear();\n }\n\n selectAll(): void {\n if (this.selection.canSelectAll())\n this.selection.selectAll();\n }\n\n // --- Key-based selection & cursor ---\n\n /** The selection as stable `data-key` / `data-value` strings. */\n get selectedKeys(): ReadonlySet<string> {\n return this.selection.selectedKeys;\n }\n\n /** The key of the item under the cursor, or `undefined`. */\n get tickledKey(): string | undefined {\n const id = this.tickled.tickledId;\n return id ? keyForElement(id) : undefined;\n }\n\n /** Replace the selection with the items carrying these keys (unknown keys ignored). */\n selectKeys(keys: Iterable<string>): void {\n this.selection.selectKeys(keys, key => this.#itemForKey(key));\n }\n\n /** Add items by key to the selection (multi-select modes only). */\n addSelectedKeys(keys: Iterable<string>): void {\n this.selection.addKeys(keys, key => this.#itemForKey(key));\n }\n\n /** Remove items by key from the selection. */\n removeSelectedKeys(keys: Iterable<string>): void {\n this.selection.removeKeys(keys, key => this.#itemForKey(key));\n }\n\n /** Move the cursor to the item with this key and scroll it into view. */\n focusKey(key: string): void {\n const el = this.#itemForKey(key);\n if (!el)\n return;\n this.tickled.focus(el);\n el.scrollIntoView({ block: `nearest`, inline: `nearest` });\n }\n\n #itemForKey(key: string): Element | undefined {\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n if (keyForElement(el) === key)\n return el;\n }\n return undefined;\n }\n\n * selectedFilter(kind: `selected` | `checked` | `either`): Generator<Element> {\n const wanted = (el: Element) => {\n switch (kind) {\n case `selected`: return el.hasAttribute(`data-selected`);\n case `checked`: return el.hasAttribute(`data-checked`);\n case `either`: return el.hasAttribute(`data-selected`) || el.hasAttribute(`data-checked`);\n }\n };\n\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n if ((el as HTMLElement).hidden)\n continue;\n if (wanted(el))\n yield el;\n }\n }\n\n // --- Helpers ---\n\n private _getVisibleItems(): Element[] {\n return Array.from(this.querySelectorAll(ITEM_SELECTOR)).filter((el) => {\n if (this.#wrappedElements.has(el))\n return false;\n if ((el as HTMLElement).hidden)\n return false;\n if (this.filterPredicate && !this.filterPredicate(el))\n return false;\n return true;\n });\n }\n\n // Whether an item participates in checked-mode selection. Items carrying the\n // `not-checked` attribute are skipped; outside `checked` mode it has no effect.\n // For wrapped custom elements the flag lives on the inner element, so resolve\n // through the wrapper map.\n private _isCheckable(item: Element): boolean {\n if (this.interactionMode !== `checked`)\n return true;\n const real = this.#customWrappers.get(item as HTMLLIElement) ?? item;\n return !real.hasAttribute(`not-checked`);\n }\n\n private _syncItemStates(): void {\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n const item = this.#customWrappers.get(el as HTMLLIElement) ?? el;\n el.toggleAttribute(`data-tickled`, this.tickled.isTickled(el));\n el.toggleAttribute(`data-selected`, this.selection.selected.has(el));\n if (this.interactionMode === `checked`) {\n el.toggleAttribute(`data-checked`, !item.hasAttribute(`not-checked`) && this.selection.selected.has(el));\n } else {\n el.removeAttribute(`data-checked`);\n }\n }\n this.dataset.inputMode = this.tickled.inputMode;\n this._syncCheckboxes();\n }\n\n private _syncCheckboxes(): void {\n const inCheckedMode = this.interactionMode === `checked`;\n const wantsCustom = typeof this.checkboxRenderer === `function`;\n\n if (inCheckedMode) {\n for (const inner of Array.from(this.children)) {\n if (!inner.hasAttribute(`data-list-item`))\n continue;\n if (inner.parentElement !== this)\n continue; // idempotency: already wrapped\n const wrapper = document.createElement(`li`);\n wrapper.className = `ixfx-custom-row`;\n const key = inner.getAttribute(`data-key`);\n const label = inner.getAttribute(`data-search-label`);\n if (key !== null)\n wrapper.setAttribute(`data-key`, key);\n if (label !== null)\n wrapper.setAttribute(`data-search-label`, label);\n inner.removeAttribute(`data-list-item`);\n this.insertBefore(wrapper, inner);\n wrapper.appendChild(inner);\n this.#customWrappers.set(wrapper, inner);\n this.#wrappedElements.add(inner);\n }\n } else {\n for (const [wrapper, inner] of this.#customWrappers) {\n if (wrapper.parentElement !== this)\n continue;\n inner.setAttribute(`data-list-item`, ``);\n this.insertBefore(inner, wrapper);\n wrapper.remove();\n }\n this.#customWrappers.clear();\n this.#wrappedElements.clear();\n }\n\n for (const el of this.querySelectorAll<HTMLElement>(`li`)) {\n const existing = el.querySelector<HTMLElement>(`.ixfx-list-checkbox`);\n if (!inCheckedMode) {\n if (existing)\n existing.remove();\n continue;\n }\n // Rows marked `not-checked` get no checkbox column and can't be checked\n const itemEl = this.#customWrappers.get(el as HTMLLIElement) ?? el;\n if (itemEl.hasAttribute(`not-checked`)) {\n if (existing)\n existing.remove();\n continue;\n }\n\n // In checked mode: if the existing checkbox is the wrong variant, drop it.\n const existingIsCustom = existing?.classList.contains(`ixfx-list-checkbox-custom`) ?? false;\n if (existing && existingIsCustom !== wantsCustom)\n existing.remove();\n\n let cb: HTMLElement | null = el.querySelector<HTMLElement>(`.ixfx-list-checkbox`);\n if (!cb) {\n if (wantsCustom) {\n const opts = this.checkboxRenderer as CustomCheckboxOptions;\n const margin = opts.margin ?? `0`;\n const width = opts.width ?? `24px`;\n cb = this._createCustomCheckbox(el, margin, width);\n } else {\n cb = this._createNativeCheckboxCell(el);\n }\n el.prepend(cb);\n }\n\n const checked = this.selection.selected.has(el);\n if (wantsCustom) {\n cb.setAttribute(`aria-checked`, String(checked));\n cb.toggleAttribute(`data-checked`, checked);\n if (this.checkboxRenderer) {\n const renderer = typeof this.checkboxRenderer === `function`\n ? this.checkboxRenderer\n : (this.checkboxRenderer as CustomCheckboxOptions).renderer;\n render(renderer(checked), cb);\n }\n } else {\n const input = cb.querySelector<HTMLInputElement>(`input.ixfx-list-checkbox`);\n if (input)\n input.checked = checked;\n }\n }\n }\n\n /**\n * Native checkbox cell: a span that stretches to the row's full cross-axis\n * (so the entire column height is a click target) with a real `<input>`\n * centred inside. The span owns the click; the input is purely visual and\n * has `pointer-events:none` so a single click produces one toggle.\n */\n private _createNativeCheckboxCell(el: HTMLElement): HTMLSpanElement {\n const cell = document.createElement(`span`);\n cell.className = `ixfx-list-checkbox ixfx-list-checkbox-native`;\n cell.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:18px;margin:0 6px 0 0;cursor:pointer;pointer-events:auto`;\n cell.tabIndex = -1;\n cell.setAttribute(`role`, `checkbox`);\n cell.setAttribute(`part`, `checkbox`);\n cell.addEventListener(`click`, (e) => {\n e.stopPropagation();\n this.selection.toggle(el);\n });\n const input = document.createElement(`input`);\n input.type = `checkbox`;\n input.className = `ixfx-list-checkbox`;\n input.style.cssText = `pointer-events:none;cursor:pointer;margin:0`;\n cell.appendChild(input);\n return cell;\n }\n\n /**\n * Custom checkbox cell: same shape as the native cell (a stretching span)\n * so behaviour is identical. The renderer's content goes inside.\n */\n private _createCustomCheckbox(el: HTMLElement, margin: string, width: string): HTMLSpanElement {\n const span = document.createElement(`span`);\n span.className = `ixfx-list-checkbox ixfx-list-checkbox-custom`;\n span.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:${width};margin:${margin};cursor:pointer;pointer-events:auto`;\n span.tabIndex = -1;\n span.setAttribute(`role`, `checkbox`);\n span.setAttribute(`part`, `checkbox`);\n span.addEventListener(`click`, (e) => {\n e.stopPropagation();\n this.selection.toggle(el);\n });\n return span;\n }\n\n private _findListItem(path: EventTarget[]): Element | undefined {\n for (const target of path) {\n if (!(target instanceof Element))\n continue;\n if (target === this)\n break;\n if (target.parentElement === this && target.matches(ITEM_SELECTOR))\n return target;\n }\n return undefined;\n }\n\n private _dispatch<T>(name: keyof ListElementEventMap, detail: T): void {\n this.dispatchEvent(new CustomEvent<T>(name as string, {\n detail,\n bubbles: true,\n composed: true,\n }));\n }\n\n private _dispatchCancelable<T>(name: string, detail: T): boolean {\n return this.dispatchEvent(new CustomEvent<T>(name, {\n detail,\n bubbles: true,\n composed: true,\n cancelable: true,\n }));\n }\n\n // --- Event handlers ---\n\n private _onPointerOver = (e: PointerEvent): void => {\n const item = this._findListItem(e.composedPath());\n if (item)\n this.tickled.handlePointerEnter(item);\n };\n\n private _onPointerLeave = (e: PointerEvent): void => {\n this.tickled.handlePointerLeave(e);\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (this.search.isOpen)\n return;\n if ((e.ctrlKey || e.metaKey) && e.key === `a`) {\n if (this.selection.canSelectAll()) {\n e.preventDefault();\n this.selection.selectAll();\n }\n return;\n }\n\n switch (e.key) {\n case `ArrowDown`: {\n e.preventDefault();\n this.tickled.handleKeyboardNavigation(`next`);\n // vscode: Shift+Arrow extends range from anchor\n if (e.shiftKey && this.interactionMode === `vscode`) {\n const cur = this.tickled.tickledId;\n if (cur)\n this.selection.rangeTo(cur);\n }\n break;\n }\n case `ArrowUp`: {\n e.preventDefault();\n this.tickled.handleKeyboardNavigation(`previous`);\n if (e.shiftKey && this.interactionMode === `vscode`) {\n const cur = this.tickled.tickledId;\n if (cur)\n this.selection.rangeTo(cur);\n }\n break;\n }\n case `Enter`: {\n const id = this.tickled.tickledId;\n if (id) {\n e.preventDefault();\n this._dispatch<ListItemClickDetail>(`list-item-click`, { item: id });\n this._activateItem(id);\n }\n break;\n }\n case ` `: {\n const id = this.tickled.tickledId;\n if (id) {\n e.preventDefault();\n this.selection.handleSpace(id);\n }\n break;\n }\n case `Escape`:\n this.selection.clear();\n break;\n }\n };\n\n private _onClick = (e: MouseEvent): void => {\n if (this.#dragSelect.isDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0)\n return;\n const item = this._findListItem(e.composedPath());\n if (!item)\n return;\n this._dispatch<ListItemClickDetail>(`list-item-click`, { item });\n this.selection.handleClick(item, e);\n };\n\n private _onDblClick = (e: MouseEvent): void => {\n const item = this._findListItem(e.composedPath());\n if (item)\n this._activateItem(item);\n };\n\n private _activateItem(item: Element): void {\n // manual mode: never auto-select; just fire the event\n if (this.interactionMode !== `manual`) {\n this.selection.replace(item);\n }\n this._dispatch<ListActivateDetail>(`list-activate`, { item });\n }\n\n // --- Styles ---\n\n static override styles = [themeFallbacks, listSearchStyles, css`\n :host {\n display: block;\n position: relative;\n background: var(--list-bg, var(--surface-3));\n color: var(--list-text, var(--surface-3-text));\n border-radius: var(--list-radius, var(--radius-s));\n border: 1px solid var(--list-border, var(--border));\n width: 100%;\n height: 100%;\n overflow: hidden;\n box-sizing: border-box;\n outline: none;\n --ixfx-list-item-padding: var(--ixfx-list-item-padding, var(--list-item-padding, 4px var(--space-m, 8px)));\n }\n\n :host(:focus-visible) {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n box-sizing: border-box;\n /* Scrollbar theming: end users override these CSS variables to control\n the native scrollbar (scrollbar-width, scrollbar-gutter, scrollbar-color). */\n scrollbar-width: var(--list-scrollbar-width, auto);\n scrollbar-gutter: var(--list-scrollbar-gutter, auto);\n scrollbar-color: var(--list-scrollbar-color, auto);\n }\n\n ::slotted([hidden]) {\n display: none !important;\n }\n\n ::slotted(li) {\n display: flex;\n align-items: center;\n padding: var(--ixfx-list-item-padding);\n /* Inset each row from the scroll container's edges (margin, not padding:\n padding is inside the border box, so the tickle/selection outlines\n would still sit flush against the edge and be clipped). */\n margin: 0 var(--list-gutter, 4px);\n min-height: var(--list-item-height, 28px);\n cursor: pointer;\n user-select: none;\n transition: background var(--transition, 0.1s ease-out),\n outline-color var(--transition, 0.1s ease-out);\n box-sizing: border-box;\n outline: 1px solid transparent;\n }\n\n /* Custom shadow-DOM components handle their own internal layout/padding */\n ::slotted([data-list-item]) {\n display: block;\n margin: 0 var(--list-gutter, 4px);\n cursor: pointer;\n user-select: none;\n transition: background var(--transition, 0.1s ease-out),\n outline-color var(--transition, 0.1s ease-out);\n outline: 1px solid transparent;\n }\n\n /* In checked mode, only the checkbox column is clickable; the row body\n gets a default cursor so it doesn't suggest otherwise. */\n :host([interaction-mode=\"checked\"]) ::slotted(li),\n :host([interaction-mode=\"checked\"]) ::slotted([data-list-item]) {\n cursor: default;\n }\n\n /* Wrapper inserted around custom [data-list-item] elements in checked mode.\n Provides the flex layout so the injected checkbox can stretch to the\n row's full height via align-self:stretch. */\n .ixfx-custom-row {\n display: flex;\n align-items: center;\n min-height: var(--list-item-height, 28px);\n box-sizing: border-box;\n cursor: default;\n user-select: none;\n }\n\n ::slotted([data-tickled]) {\n background: var(--item-bg-tickled);\n outline: var(--item-border-tickled);\n }\n\n ::slotted([data-selected]) {\n background: var(--item-bg-selected);\n color: var(--item-text-selected);\n outline: 1px solid transparent;\n }\n\n ::slotted([data-selected][data-tickled]) {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n\n /* Drag-select (marquee) rectangle + covered-row preview.\n Style hooks: part=\"marquee\", --vertical-list-marquee-border,\n --vertical-list-marquee-fill. */\n .marquee {\n position: absolute;\n pointer-events: none;\n z-index: 5;\n border: 1px solid var(--vertical-list-marquee-border, var(--accent));\n background: var(--vertical-list-marquee-fill, color-mix(in srgb, var(--accent) 15%, transparent));\n }\n\n ::slotted([data-marquee]) {\n background: var(--item-bg-selected);\n color: var(--item-text-selected);\n }\n\n ::slotted([data-drag-origin]) {\n opacity: 0.6;\n }\n\n /* checked mode: checkbox (injected into li) communicates selection — suppress bg highlight */\n :host([interaction-mode=\"checked\"]) ::slotted([data-selected]) {\n background: transparent;\n color: inherit;\n outline: 1px solid transparent;\n }\n\n :host([interaction-mode=\"checked\"]) ::slotted([data-selected][data-tickled]) {\n background: var(--item-bg-tickled);\n color: inherit;\n outline: var(--item-border-tickled);\n }\n `];\n\n // --- Render ---\n\n override render() {\n return html`\n <div class=\"container\">\n <ul part=\"list\">\n <slot></slot>\n </ul>\n ${this.#marqueeRect\n ? html`<div class=\"marquee\" part=\"marquee\" style=${this.#marqueeStyle(this.#marqueeRect)}></div>`\n : ``}\n ${this.search.renderField()}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-vertical-list': VerticalListElement;\n }\n\n interface HTMLElementEventMap extends VerticalListElementEventMap {}\n}\n\nexport interface VerticalListElementEventMap extends ListElementEventMap {\n 'list-native-drag-start': ListNativeDragStartEvent<Element>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vertical-list.js","names":["#selectionOrder","#dragSelect","#nativeDrag","#wrappedElements","#prepareNativeDrag","#nativeDragging","#startPostDragSuppressTimer","#virtualActive","#marqueeHitTest","#marqueeRect","#scrollRaf","#syncVirtualWindow","#postDragSuppressTimer","#searchRegistry","#effectiveSearchModes","#unregisterSearchCommands","#animatedItems","#itemObserver","#onItemsMutated","#syncSearchCommands","#ensureResizeObserved","#resizeObserver","#reconcileRecords","#customWrappers","#isBulkPopulate","#pool","#allItems","#pendingAnimate","#teardownVirtualWindow","#virtualWarned","#suspendAdapterRebuild","#rebuildAdapterVirtual","#rebuildFromAdapter","#registryIndexOf","#cleanupWrapperRefs","#itemForKey","#windowStart","#windowEnd","#itemData","#adapterIndexOf","#fillAdapterItem","#isRowElement","#stampAdapterKey","#swapRegistry","#adapterProperty","#createAdapterItem","#topSpacer","#bottomSpacer","#globalIndexForAttached","#lastViewportH","#scrollList","#drainMutations","#measureViewport","#ensureSpacers","#applyRowState","#onScroll","#marqueeStyle","customElement"],"sources":["../src/vertical-list/vertical-list.ts"],"sourcesContent":["import type { CommandId, CommandRegistry } from '@clinth/ui-commands';\nimport type { PropertyValues } from 'lit';\nimport type { ListSearchMode } from '../incr-search/index.js';\nimport type { DragSelectRect } from '../interaction/list-drag-select-controller.js';\nimport type { ListDragEntry, ListDragPreviewRenderer, ListDragPreviewSourceResolver, ListNativeDragStartEvent } from '../interaction/list-drag-types.js';\nimport type {\n ListActivateDetail,\n ListElementEventMap,\n ListInteractionMode,\n ListItemClickDetail,\n ListSelectDetail,\n ListSelectionMode,\n ListTickleDetail,\n} from '../interaction/list-selection-types.js';\nimport { createCommandRegistry } from '@clinth/ui-commands';\nimport { css, html, LitElement, render } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport {\n createElementListSearchAdapter,\n LIST_SEARCH_MODES,\n ListSearchController,\n listSearchStyles,\n registerListSearchCommands,\n} from '../incr-search/index.js';\nimport { keyForElement } from '../interaction/keyed-list.js';\nimport { ListDragSelectController } from '../interaction/list-drag-select-controller.js';\nimport { animateListItemIn, animateListItemOut } from '../interaction/list-item-animation.js';\nimport { ListNativeDragController } from '../interaction/list-native-drag-controller.js';\nimport { ListSelectionController } from '../interaction/list-selection-controller.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type {\n ListDragEntry,\n ListDragPreview,\n ListDragPreviewContext,\n ListDragPreviewRenderer,\n ListDragSource,\n ListNativeDragStartDetail,\n ListNativeDragStartEvent,\n} from '../interaction/list-drag-types.js';\nexport type {\n ListActivateDetail,\n ListActivateEvent,\n ListElementEventMap,\n ListInteractionMode,\n ListItemClickDetail,\n ListItemClickEvent,\n ListSelectDetail,\n ListSelectEvent,\n ListSelectionMode,\n ListTickleDetail,\n ListTickleEvent,\n} from './types.js';\n\nexport interface CustomCheckboxOptions {\n renderer: (checked: boolean) => unknown;\n margin?: string;\n width?: string;\n}\n\nexport interface AddItemOptions {\n /**\n * In `checked` interaction mode, adds the item without a checkbox column and\n * without the ability to be checked/selected. Equivalent to setting the\n * `not-checked` attribute on the item. Ignored outside `checked` mode.\n */\n notChecked?: boolean;\n}\n\nconst ITEM_SELECTOR = `li:not([data-virtual-spacer]), [data-list-item]:not([data-virtual-spacer])`;\n\n/**\n * Rows rendered above/below the viewport as scroll margin. Grid-list uses 2;\n * vertical rows are shorter relative to the viewport, so 3.\n */\nconst VIRTUAL_OVERSCAN = 3;\n\n@customElement(`ixfx-vertical-list`)\nexport class VerticalListElement extends LitElement {\n @property({ type: String, attribute: `selection-mode` })\n selectionMode: ListSelectionMode = `single`;\n\n @property({ type: String, attribute: `interaction-mode` })\n interactionMode: ListInteractionMode = `standard`;\n\n @property({ attribute: false })\n filterPredicate: ((el: Element) => boolean) | undefined;\n\n /**\n * Whether keyboard navigation wraps from last to first and vice versa.\n * - 'stop' (default): navigation stops at the boundary\n * - 'wrap': navigation wraps around\n */\n @property({ type: String, attribute: `item-wrap` })\n itemWrap: `stop` | `wrap` = `stop`;\n\n /**\n * Optional renderer for the checkbox shown in `checked` interactionMode.\n * Receives the current `checked` state and returns a Lit template result.\n *\n * When set, the per-row checkbox becomes a `<span role=\"checkbox\">` whose\n * contents are whatever this returns (rendered with `lit`'s `render()`).\n * When unset, a native `<input type=\"checkbox\">` is used.\n *\n * @example\n * list.checkboxRenderer = (checked) => checked\n * ? html`<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\"\n * fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\n * stroke-linecap=\"round\" stroke-linejoin=\"round\"\n * style=\"opacity:0.5\">\n * <polyline points=\"3,8 7,12 13,4\" />\n * </svg>`\n * : html``;\n */\n @property({ attribute: false })\n checkboxRenderer: ((checked: boolean) => unknown) | CustomCheckboxOptions | undefined;\n\n /**\n * Space-separated subset of `navigate select filter` — limits which\n * incremental-search modes are offered. Unset ⇒ all three; empty ⇒ search\n * disabled. See `docs/infra-incremental.md`.\n */\n @property({ type: String, attribute: `search-modes`, reflect: true })\n searchModes: string | undefined;\n\n /**\n * Enable native browser drag-and-drop for selectable items. When true,\n * selectable rows become draggable and the list emits\n * `list-native-drag-start` when a drag begins.\n */\n @property({ type: Boolean, attribute: `items-draggable`, reflect: true })\n itemsDraggable = false;\n\n /**\n * Custom drag preview renderer (synchronous). Defaults to the shared\n * built-in HTML+canvas preview.\n */\n @property({ attribute: false })\n dragPreviewRenderer: ListDragPreviewRenderer<Element> | undefined;\n\n @property({ attribute: false })\n dragPreviewSource: ListDragPreviewSourceResolver<Element> | undefined;\n\n /**\n * Object/adapter item mode (mirrors `ixfx-detail-list`). When set, the list\n * builds one `<li>` per entry and owns its light-DOM children; `formatter`\n * renders each entry and `keyProperty` stamps `data-key` so `selectKeys` /\n * `focusKey` / `getItemByKey` keep working.\n *\n * Additive: `addItem(element)` / `setItems(elements)` keep working while\n * `items` is unset. While `items` is set, a rebuild (on `items` /\n * `formatter` / `keyProperty` change) discards hand-added children.\n */\n @property({ attribute: false })\n items: readonly unknown[] | undefined;\n\n /**\n * Property name on each `items` entry used for stable identity — stamped\n * as `data-key` on the built row. Preserves selection across rebuilds.\n */\n @property({ type: String, attribute: `key-property` })\n keyProperty = ``;\n\n /**\n * Renders one adapter-mode entry. The result may be a `string` (row text),\n * a `Node` (appended into the row `<li>`), a full row `Element` (an `<li>`\n * or a `[data-list-item]` custom element, used directly), or a Lit template\n * result (rendered into the row `<li>` with `render()`). Without a\n * formatter, string entries become row text and `Node` entries are\n * appended.\n */\n @property({ attribute: false })\n formatter: ((item: unknown, index: number) => unknown) | undefined;\n\n /**\n * Virtualize the list: only the overscanned viewport window exists in the\n * DOM; offscreen rows are recycled through an off-DOM pool as the list\n * scrolls. Works for hand-supplied elements AND adapter (`items`) rows —\n * both are detached/reattached by identity, so selection, cursor and\n * component state survive scrolling.\n *\n * Requires `item-height`: every row must be exactly that tall (use\n * `--list-item-height` to match). `data-key`s are required for the key\n * APIs (`selectKeys`, `focusKey`, `renderedKeys`); selection by reference\n * (click, `select()`) works regardless.\n *\n * Limitations while active: drag-select is disabled (the window shifts\n * under a drag), and incremental-search `filter` mode is excluded (it\n * collapses rows via `hidden`, corrupting the fixed-stride geometry).\n * Keyboard navigation stays within the rendered window — scroll first.\n */\n @property({ type: Boolean, attribute: `virtualize`, reflect: true })\n virtualize = false;\n\n /**\n * Fixed row height in px. Required for `virtualize` — the window math is\n * pure stride arithmetic (no DOM measurement), mirroring\n * `ixfx-grid-list`'s `itemSize`.\n */\n @property({ type: Number, attribute: `item-height` })\n itemHeight = 0;\n\n #customWrappers = new Map<HTMLLIElement, Element>();\n #wrappedElements = new Set<Element>();\n\n /** Source object behind each adapter-built row (`items` mode). */\n #itemData = new WeakMap<Element, unknown>();\n\n /** Watches for items added to the light DOM so they can be animated in. */\n #itemObserver: MutationObserver | undefined;\n /** Items that have already played (or been skipped for) their enter animation. */\n #animatedItems = new WeakSet<Element>();\n\n // --- Virtualization (option 2: true element recycling) ---\n\n /**\n * Global row order while virtualized — the source of truth both modes\n * write to. Holds canonical rows (checked-mode wrappers, not inners).\n * Non-virtualized mode ignores it and reads the DOM directly.\n */\n #allItems: Element[] = [];\n /** Off-DOM pool for recycled offscreen rows. `querySelectorAll` works on it. */\n #pool: DocumentFragment = document.createDocumentFragment();\n /** Current rendered window as registry indices `[start, end)`. */\n #windowStart = 0;\n #windowEnd = 0;\n /** Window rows queued for their enter animation after placement. */\n #pendingAnimate: Element[] = [];\n /** Skip one adapter rebuild (updateItem's write-through to `items`). */\n #suspendAdapterRebuild = false;\n #scrollRaf = 0;\n #resizeObserver: ResizeObserver | undefined;\n #topSpacer: HTMLLIElement | undefined;\n #bottomSpacer: HTMLLIElement | undefined;\n /** Last measured viewport height — kept so a 0 read can't collapse the window. */\n #lastViewportH = 0;\n #virtualWarned = false;\n\n private readonly selection = new ListSelectionController<Element>({\n getOrderedItems: () => this.#selectionOrder(),\n isSelectable: el => this._isCheckable(el),\n getModes: () => ({ selectionMode: this.selectionMode, interactionMode: this.interactionMode }),\n getKey: keyForElement,\n onChange: (selected, previous) => {\n this._syncItemStates();\n this._dispatch<ListSelectDetail>(`list-select`, {\n selected,\n previous,\n selectedKeys: this.selection.selectedKeys,\n });\n },\n });\n\n private tickled = new TickledController<Element>(this, {\n getItems: () => this._getVisibleItems().map(el => ({\n id: el,\n enabled: !el.hasAttribute(`not-checked`),\n })),\n onTickle: (id) => {\n if (id !== undefined) {\n this._dispatch<ListTickleDetail>(`list-tickle`, { item: id });\n }\n },\n onStateChange: () => this._syncItemStates(),\n itemWrap: this.itemWrap,\n hoverDisabled: () => this.#dragSelect.isDragging || this.#nativeDrag.isDragging,\n });\n\n #nativeDragging = false;\n #postDragSuppressTimer = 0;\n\n readonly #nativeDrag = new ListNativeDragController<Element>(this, {\n source: `vertical-list`,\n isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this._getVisibleItems().length > 0,\n resolveEventToKey: (target) => {\n if (!(target instanceof Element))\n return undefined;\n const item = target.closest?.(ITEM_SELECTOR) as Element | null;\n if (!item || !this.contains(item) || this.#wrappedElements.has(item))\n return undefined;\n return keyForElement(item);\n },\n prepareSelection: originKey => this.#prepareNativeDrag(originKey),\n getMetrics: () => ({}),\n getRenderer: () => this.dragPreviewRenderer,\n getDragPreviewSourceResolver: () => this.dragPreviewSource,\n dispatch: detail => this._dispatchCancelable(`list-native-drag-start`, detail),\n onActiveChange: (active, originKey) => {\n this.#nativeDragging = active;\n this.toggleAttribute(`data-native-dragging`, active);\n for (const el of this._getVisibleItems())\n el.toggleAttribute(`data-drag-origin`, active && originKey !== undefined && keyForElement(el) === originKey);\n if (active) {\n const count = this.selection.selected.size;\n this.setAttribute(`aria-label`, count <= 1 ? `Dragging 1 item` : `Dragging ${count} items`);\n } else {\n this.removeAttribute(`aria-label`);\n }\n this.requestUpdate();\n },\n onEnd: () => {\n this.#nativeDragging = false;\n this.toggleAttribute(`data-native-dragging`, false);\n this.removeAttribute(`aria-label`);\n for (const el of this._getVisibleItems())\n el.removeAttribute(`data-drag-origin`);\n this.#startPostDragSuppressTimer();\n },\n syncLightDomDraggable: () => this._syncNativeDraggable(),\n });\n\n #prepareNativeDrag(originKey: string): { origin: ListDragEntry<Element>; selected: Array<ListDragEntry<Element>> } | undefined {\n const visible = this._getVisibleItems();\n const originEl = visible.find(el => keyForElement(el) === originKey);\n if (!originEl || !this._isCheckable(originEl))\n return undefined;\n if (!this.selection.selected.has(originEl))\n this.selection.replace(originEl);\n const selected: Array<ListDragEntry<Element>> = [];\n visible.forEach((el, index) => {\n if (!this.selection.selected.has(el))\n return;\n selected.push({ key: keyForElement(el) ?? originKey, index, item: el, element: el });\n });\n const origin = selected.find(entry => entry.key === originKey);\n if (!origin)\n return undefined;\n return { origin, selected };\n }\n\n private _syncNativeDraggable(): void {\n if (!this.isConnected)\n return;\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n if (el instanceof HTMLElement)\n el.draggable = this.itemsDraggable && this._isCheckable(el);\n }\n }\n\n #startPostDragSuppressTimer(): void {\n if (this.#postDragSuppressTimer)\n clearTimeout(this.#postDragSuppressTimer);\n this.#postDragSuppressTimer = window.setTimeout(() => {\n this.#postDragSuppressTimer = 0;\n }, 0);\n }\n\n /** Live drag-select preview rect (surface-relative); the covered items carry `data-marquee`. */\n #marqueeRect: DragSelectRect | undefined;\n\n readonly #dragSelect = new ListDragSelectController<Element>(this, {\n getSurface: () => this.renderRoot.querySelector(`.container`) as HTMLElement | undefined,\n isEnabled: () =>\n !this.#virtualActive()\n && this.selection.canDragSelect()\n && this._getVisibleItems().length > 0\n && !this.hasAttribute(`disable-drag-select`),\n hitTest: rect => this.#marqueeHitTest(rect),\n getBaseSelection: () => this.selection.selected,\n onPreview: (preview, rect) => {\n this.#marqueeRect = rect;\n for (const el of this._getVisibleItems())\n el.toggleAttribute(`data-marquee`, preview.has(el));\n this.requestUpdate();\n },\n onCommit: (finalSet) => {\n this.selection.applyDragSelection(finalSet);\n for (const el of this._getVisibleItems())\n el.removeAttribute(`data-marquee`);\n this.#marqueeRect = undefined;\n this.requestUpdate();\n },\n autoScroll: (_dx, dy) => {\n const list = this.renderRoot.querySelector(`ul`);\n if (list)\n list.scrollTop += dy;\n },\n });\n\n /** Collect visible items whose surface-relative box intersects `rect`. */\n #marqueeHitTest(rect: DragSelectRect): Element[] {\n const surface = this.renderRoot.querySelector(`.container`);\n if (!surface)\n return [];\n const box = surface.getBoundingClientRect();\n const rx0 = rect.x;\n const ry0 = rect.y;\n const rx1 = rect.x + rect.width;\n const ry1 = rect.y + rect.height;\n const out: Element[] = [];\n for (const el of this._getVisibleItems()) {\n const r = el.getBoundingClientRect();\n const left = r.left - box.left;\n const top = r.top - box.top;\n if (left <= rx1 && left + r.width >= rx0 && top <= ry1 && top + r.height >= ry0)\n out.push(el);\n }\n return out;\n }\n\n #marqueeStyle(rect: DragSelectRect): string {\n return `left:${rect.x}px;top:${rect.y}px;width:${Math.max(0, rect.width)}px;height:${Math.max(0, rect.height)}px`;\n }\n\n /** Incremental search (navigate / select / filter). See `docs/infra-incremental.md`. */\n readonly search = new ListSearchController<Element>(this, {\n adapter: createElementListSearchAdapter(this, {\n itemSelector: ITEM_SELECTOR,\n getLabel: el => el.getAttribute(`data-search-label`) ?? el.textContent?.trim() ?? ``,\n highlightKey: `vertical-list-search`,\n }),\n });\n\n #searchRegistry: CommandRegistry<unknown> | undefined;\n #unregisterSearchCommands: (() => void) | undefined;\n\n /** Command registry carrying this list's `list.search.*` commands. */\n get registry(): CommandRegistry<unknown> | undefined {\n return this.#searchRegistry;\n }\n\n #effectiveSearchModes(): ListSearchMode[] {\n const raw = this.searchModes?.trim();\n let modes: ListSearchMode[];\n if (raw === undefined) {\n modes = [...LIST_SEARCH_MODES];\n } else {\n const requested = new Set(raw.split(/\\s+/));\n modes = LIST_SEARCH_MODES.filter(m => requested.has(m));\n }\n // Filter mode collapses rows via `hidden`, which corrupts the\n // fixed-stride geometry — exclude it while virtualized (setModes closes\n // an active filter search).\n return this.#virtualActive() ? modes.filter(m => m !== `filter`) : modes;\n }\n\n #syncSearchCommands(): void {\n if (!this.#searchRegistry)\n return;\n this.search.setModes(this.#effectiveSearchModes());\n this.#unregisterSearchCommands?.();\n this.#unregisterSearchCommands = registerListSearchCommands(this.#searchRegistry, this.search);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute(`tabindex`))\n this.tabIndex = 0;\n this.addEventListener(`pointerover`, this._onPointerOver);\n this.addEventListener(`pointerleave`, this._onPointerLeave);\n this.addEventListener(`keydown`, this._onKeyDown);\n this.addEventListener(`click`, this._onClick);\n this.addEventListener(`dblclick`, this._onDblClick);\n // Mark whatever's already here as \"known\" so the first populate doesn't\n // animate; anything added later collapses in.\n for (const el of this.querySelectorAll(ITEM_SELECTOR))\n this.#animatedItems.add(el);\n this.#itemObserver ??= new MutationObserver(records => this.#onItemsMutated(records));\n this.#itemObserver.observe(this, { childList: true });\n this.#searchRegistry ??= createCommandRegistry();\n this.#syncSearchCommands();\n // Reconnecting keeps registry + pool + attached window intact; just make\n // sure the resize observer is watching the (persisted) shadow list again.\n this.#ensureResizeObserved();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`pointerover`, this._onPointerOver);\n this.removeEventListener(`pointerleave`, this._onPointerLeave);\n this.removeEventListener(`keydown`, this._onKeyDown);\n this.removeEventListener(`click`, this._onClick);\n this.removeEventListener(`dblclick`, this._onDblClick);\n this.#itemObserver?.disconnect();\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n if (this.#scrollRaf !== 0) {\n cancelAnimationFrame(this.#scrollRaf);\n this.#scrollRaf = 0;\n }\n this.#unregisterSearchCommands?.();\n this.#unregisterSearchCommands = undefined;\n this.#searchRegistry = undefined;\n if (this.#postDragSuppressTimer) {\n clearTimeout(this.#postDragSuppressTimer);\n this.#postDragSuppressTimer = 0;\n }\n }\n\n /**\n * Animate in items appended to the light DOM (however they got there —\n * {@link addItem}, direct `appendChild`, a framework binding). A bulk populate\n * (roughly everything at once) is left alone, as are the wrapper `<li>`s the\n * checked-mode plumbing shuffles around.\n */\n #onItemsMutated(records: MutationRecord[]): void {\n if (!this.isConnected)\n return;\n if (this.#virtualActive()) {\n // Consumer-side DOM edits (append/insert/remove, framework bindings).\n // Our own window moves reconcile to no-ops; placement is skipped when\n // the window didn't move.\n this.#syncVirtualWindow(this.#reconcileRecords(records));\n return;\n }\n const fresh: HTMLElement[] = [];\n for (const record of records) {\n for (const node of record.addedNodes) {\n if (!(node instanceof HTMLElement) || node.parentElement !== this)\n continue;\n if (!node.matches(ITEM_SELECTOR))\n continue;\n if (this.#animatedItems.has(node) || this.#customWrappers.has(node as HTMLLIElement) || this.#wrappedElements.has(node))\n continue;\n this.#animatedItems.add(node);\n fresh.push(node);\n }\n }\n if (fresh.length === 0)\n return;\n if (this.#isBulkPopulate(fresh.length))\n return; // first populate / wholesale replace — don't animate\n for (const el of fresh)\n animateListItemIn(el);\n }\n\n /**\n * Whether `freshCount` newly-added rows amount to a bulk populate (first\n * render / wholesale replace) rather than an incremental add — the single\n * threshold both the virtual and non-virtual mutation-observer paths use\n * to decide whether to skip the enter animation.\n */\n #isBulkPopulate(freshCount: number): boolean {\n const total = this.querySelectorAll(ITEM_SELECTOR).length;\n return freshCount >= total;\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n if (changed.has(`searchModes`)) {\n this.#syncSearchCommands();\n }\n if (changed.has(`virtualize`) || changed.has(`itemHeight`)) {\n const wasActive = (changed.has(`virtualize`)\n ? (changed.get(`virtualize`) as boolean | undefined)\n : this.virtualize) === true\n && ((changed.has(`itemHeight`)\n ? (changed.get(`itemHeight`) as number | undefined)\n : this.itemHeight) ?? 0) > 0;\n if (this.#virtualActive()) {\n if (!wasActive) {\n // Entering: snapshot the current DOM order as the registry. (Pool\n // is empty whenever we're inactive, so nothing is lost.)\n this.#pool = document.createDocumentFragment();\n this.#allItems = [...this.querySelectorAll(ITEM_SELECTOR)];\n for (const el of this.#allItems)\n this.#animatedItems.add(el);\n this.#pendingAnimate = [];\n }\n this.#syncVirtualWindow(true);\n } else if (wasActive) {\n this.#teardownVirtualWindow();\n } else if (this.virtualize && !this.#virtualWarned) {\n this.#virtualWarned = true;\n console.warn(`ixfx-vertical-list: virtualize needs item-height > 0 — running non-virtualized.`);\n }\n this.#syncSearchCommands();\n }\n if (\n (changed.has(`items`) || changed.has(`formatter`) || changed.has(`keyProperty`))\n && this.items !== undefined\n ) {\n if (this.#suspendAdapterRebuild) {\n // updateItem's write-through to `items` — DOM already updated in place.\n this.#suspendAdapterRebuild = false;\n } else if (this.#virtualActive()) {\n this.#rebuildAdapterVirtual();\n } else {\n this.#rebuildFromAdapter();\n }\n }\n if (changed.has(`interactionMode`)) {\n this.selection.clearAnchor();\n const previousSelected = this.selection.selected;\n // Save wrapper→inner map before _syncCheckboxes() clears it on unwrap\n const leavingChecked = (changed.get(`interactionMode`) as ListInteractionMode) === `checked`;\n const savedWrappers = leavingChecked ? new Map(this.#customWrappers) : null;\n\n this._syncCheckboxes();\n\n // Remap the selection across the wrap/unwrap element-reference boundary\n if (previousSelected.size > 0) {\n if (savedWrappers && savedWrappers.size > 0) {\n // Leaving checked: wrapper refs → inner element refs\n this.selection.remap(el => savedWrappers.get(el as HTMLLIElement) ?? el);\n } else if (this.#customWrappers.size > 0) {\n // Entering checked: inner element refs → wrapper refs\n const innerToWrapper = new Map([...this.#customWrappers].map(([w, i]) => [i, w]));\n this.selection.remap(el => innerToWrapper.get(el) ?? el);\n }\n }\n\n this._syncItemStates();\n } else if (changed.has(`checkboxRenderer`) && this.interactionMode === `checked`) {\n this._syncCheckboxes();\n }\n if (changed.has(`itemsDraggable`) || changed.has(`interactionMode`)) {\n this._syncNativeDraggable();\n this.#nativeDrag.refreshDraggable();\n }\n }\n\n // --- Public API ---\n\n /** The most recently selected item, or `undefined` if nothing is selected. */\n get selectedItem(): Element | undefined {\n return [...this.selection.selected].at(-1);\n }\n\n /** The full current selection set (read-only). */\n get selectedItems(): ReadonlySet<Element> {\n return this.selection.selected;\n }\n\n addItem(item: Element | string, options?: AddItemOptions): void {\n let el: Element;\n if (typeof item === `string`) {\n const li = document.createElement(`li`);\n li.textContent = item;\n el = li;\n } else {\n el = item;\n }\n if (options?.notChecked)\n el.setAttribute(`not-checked`, ``);\n this.appendChild(el);\n if (this.#virtualActive()) {\n // Registry insert (end — it landed after the bottom spacer) +\n // placement + enter animation if in-window all happen in the sync.\n this.#syncVirtualWindow(true);\n return;\n }\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n }\n\n /**\n * Collapse + fade `item` out, then detach it. The rows below slide up to\n * close the gap. Resolves once the element has actually been removed.\n * Under `prefers-reduced-motion: reduce` it's removed immediately.\n * A pooled (offscreen) row under virtualization is removed immediately.\n */\n removeItem(item: Element): Promise<void> {\n this.selection.deselect(item);\n if (this.#virtualActive()) {\n const pooled = item.parentNode !== this;\n const done = pooled\n ? Object.assign(Promise.resolve(), { animation: undefined })\n : animateListItemOut(item as HTMLElement);\n return done.then(() => {\n const idx = this.#registryIndexOf(item);\n if (idx >= 0)\n this.#allItems.splice(idx, 1);\n this.#cleanupWrapperRefs(item);\n item.remove();\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n this.#syncVirtualWindow(true);\n });\n }\n const done = animateListItemOut(item as HTMLElement).then(() => {\n item.remove();\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n });\n return done;\n }\n\n /** {@link removeItem} for several items at once. */\n removeItems(items: Iterable<Element>): Promise<void> {\n return Promise.all([...items].map(item => this.removeItem(item))).then(() => undefined);\n }\n\n clearItems(): void {\n this.#customWrappers.clear();\n if (this.#virtualActive()) {\n this.#allItems = [];\n this.#pool = document.createDocumentFragment();\n this.#pendingAnimate = [];\n }\n this.replaceChildren();\n this.selection.reset();\n this._syncItemStates();\n if (this.#virtualActive())\n this.#syncVirtualWindow(true);\n }\n\n /**\n * Replace the entire item list in one call.\n * Equivalent to `clearItems()` followed by `addItem()` for each element.\n * Preserves `interactionMode` checkbox wrapping.\n */\n setItems(items: readonly Element[]): void {\n if (this.#virtualActive()) {\n this.#customWrappers.clear();\n this.#pool = document.createDocumentFragment();\n this.#pendingAnimate = [];\n this.#allItems = [...items];\n for (const el of this.#allItems)\n this.#animatedItems.add(el);\n this.selection.reset();\n this.#syncVirtualWindow(true);\n return;\n }\n for (const item of items) {\n this.appendChild(item);\n }\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n }\n\n /**\n * Dispatch a command to this list — used by `ixfx-grouped-item-lister` to\n * forward commands to all sub-components. Routes through the command registry\n * (so `list.search.*` and any other registered commands work).\n */\n dispatch(commandId: CommandId, args?: Record<string, unknown>): void {\n this.#searchRegistry?.invoke(commandId, args);\n }\n\n select(item: Element): void {\n this.selection.replace(item);\n }\n\n selectMany(items: Iterable<Element>): void {\n this.selection.selectMany(items);\n }\n\n deselect(item: Element): void {\n this.selection.deselect(item);\n }\n\n clearSelection(): void {\n this.selection.clear();\n }\n\n selectAll(): void {\n if (this.selection.canSelectAll())\n this.selection.selectAll();\n }\n\n // --- Key-based selection & cursor ---\n\n /** The selection as stable `data-key` / `data-value` strings. */\n get selectedKeys(): ReadonlySet<string> {\n return this.selection.selectedKeys;\n }\n\n /** The key of the item under the cursor, or `undefined`. */\n get tickledKey(): string | undefined {\n const id = this.tickled.tickledId;\n return id ? keyForElement(id) : undefined;\n }\n\n /** Replace the selection with the items carrying these keys (unknown keys ignored). */\n selectKeys(keys: Iterable<string>): void {\n this.selection.selectKeys(keys, key => this.#itemForKey(key));\n }\n\n /** Add items by key to the selection (multi-select modes only). */\n addSelectedKeys(keys: Iterable<string>): void {\n this.selection.addKeys(keys, key => this.#itemForKey(key));\n }\n\n /** Remove items by key from the selection. */\n removeSelectedKeys(keys: Iterable<string>): void {\n this.selection.removeKeys(keys, key => this.#itemForKey(key));\n }\n\n /**\n * Move the cursor to the item with this key and scroll it into view.\n * Under virtualization the key's index is scrolled into the rendered\n * window first (a no-op for unknown keys).\n */\n focusKey(key: string): void {\n if (this.#virtualActive()) {\n const index = this.#allItems.findIndex(el => keyForElement(el) === key);\n if (index < 0)\n return;\n const ul = this.renderRoot.querySelector(`ul`);\n if (ul) {\n ul.scrollTop = index * this.itemHeight;\n this.#syncVirtualWindow(true);\n }\n }\n const el = this.#itemForKey(key);\n if (!el || el.parentNode !== this)\n return;\n this.tickled.focus(el);\n el.scrollIntoView({ block: `nearest`, inline: `nearest` });\n }\n\n #itemForKey(key: string): Element | undefined {\n // Virtualized: offscreen rows have no DOM node — scan the registry.\n if (this.#virtualActive())\n return this.#allItems.find(el => keyForElement(el) === key);\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n if (keyForElement(el) === key)\n return el;\n }\n return undefined;\n }\n\n /** The item carrying this `data-key`, or `undefined`. */\n getItemByKey(key: string): Element | undefined {\n return this.#itemForKey(key);\n }\n\n /**\n * Keys of items currently intersecting the viewport — for prioritising\n * viewport-first work (e.g. metadata/thumbnail fetches). A rect-intersection\n * test against the scroll container over the already-created rows (the same\n * cheap trick as `ixfx-detail-list.visibleKeys()`); hidden (filtered-out)\n * and keyless items are omitted.\n */\n visibleKeys(): string[] {\n const container = this.renderRoot.querySelector(`ul`);\n if (!container)\n return [];\n const box = container.getBoundingClientRect();\n const out: string[] = [];\n for (const el of this._getVisibleItems()) {\n const key = keyForElement(el);\n if (key === undefined)\n continue;\n const r = el.getBoundingClientRect();\n if (r.bottom > box.top && r.top < box.bottom)\n out.push(key);\n }\n return out;\n }\n\n /**\n * Keys of the currently rendered window (viewport + overscan) — the\n * priority set for prefetching, mirroring `ixfx-grid-list.renderedKeys()`.\n * Use {@link visibleKeys} for the strict viewport intersection. Keyless\n * rows are omitted. Without virtualization, every visible row's key.\n */\n renderedKeys(): string[] {\n if (!this.#virtualActive()) {\n const out: string[] = [];\n for (const el of this._getVisibleItems()) {\n const key = keyForElement(el);\n if (key !== undefined)\n out.push(key);\n }\n return out;\n }\n const out: string[] = [];\n for (let i = this.#windowStart; i < this.#windowEnd; i++) {\n const el = this.#allItems[i];\n if (!el)\n continue;\n const key = keyForElement(el);\n if (key !== undefined)\n out.push(key);\n }\n return out;\n }\n\n * selectedFilter(kind: `selected` | `checked` | `either`): Generator<Element> {\n // Controller-derived (not attribute-derived) so pooled rows under\n // virtualization report their live state; attributes only mirror the\n // attached window. `data-checked` always implies selected, hence `either`\n // reduces to the selection — same as the attribute version.\n const source: Iterable<Element> = this.#virtualActive() ? this.#allItems : this.querySelectorAll(ITEM_SELECTOR);\n const isChecked = (el: Element): boolean => {\n if (this.interactionMode !== `checked`)\n return false;\n const real = this.#customWrappers.get(el as HTMLLIElement) ?? el;\n return !real.hasAttribute(`not-checked`) && this.selection.selected.has(el);\n };\n for (const el of source) {\n if (!this.#virtualActive() && this.#wrappedElements.has(el))\n continue;\n if ((el as HTMLElement).hidden)\n continue;\n switch (kind) {\n case `selected`: {\n if (this.selection.selected.has(el))\n yield el;\n break;\n }\n case `checked`: {\n if (isChecked(el))\n yield el;\n break;\n }\n case `either`: {\n if (this.selection.selected.has(el) || isChecked(el))\n yield el;\n break;\n }\n }\n }\n }\n\n // --- Object/adapter items ---\n\n /**\n * Get the source object behind a row built from `items`. Returns\n * `undefined` for declarative / programmatic elements.\n */\n getItemData(item: Element): unknown {\n return this.#itemData.get(item);\n }\n\n /**\n * Adapter mode: re-render the row carrying `key` in place — scroll and\n * selection are untouched. Unknown keys, and keys on rows not built from\n * `items`, are ignored. A no-op unless `items` is set.\n *\n * Rows whose formatter returns a full row element are swapped for the fresh\n * element; `<li>` rows are refilled. (A custom-element row with a\n * non-element formatter result cannot be re-rendered in place and is left\n * alone — have the formatter return a replacement element instead.)\n */\n updateItem(key: string, data: unknown): void {\n if (this.items === undefined)\n return;\n const el = this.getItemByKey(key);\n if (!el || !this.#itemData.has(el))\n return;\n const index = this.#adapterIndexOf(el);\n const fresh = this.formatter ? this.formatter(data, index) : data;\n if (el instanceof HTMLLIElement) {\n for (const child of [...el.childNodes])\n child.remove();\n this.#fillAdapterItem(el, fresh, data);\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n this._syncItemStates();\n } else if (fresh instanceof Element && this.#isRowElement(fresh)) {\n if (fresh.tagName !== `LI` && !fresh.hasAttribute(`data-list-item`))\n fresh.setAttribute(`data-list-item`, ``);\n this.#stampAdapterKey(fresh, data);\n this.#itemData.set(fresh, data);\n this.#itemData.delete(el);\n this.selection.remap(item => (item === el ? fresh : item));\n // Keep the registry pointing at the live row when virtualized.\n if (this.#virtualActive())\n this.#swapRegistry(el, fresh);\n el.replaceWith(fresh);\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n this._syncItemStates();\n }\n // Write through to the source array (grid-list parity) so the edit\n // survives a later full rebuild — and so offscreen virtual rows render\n // fresh when scrolled into view. Skips the rebuild this triggers.\n if (this.keyProperty) {\n const sourceIndex = this.items.findIndex(\n entry => this.#adapterProperty(entry, this.keyProperty) !== undefined\n && String(this.#adapterProperty(entry, this.keyProperty)) === key,\n );\n if (sourceIndex >= 0) {\n const next = [...this.items];\n next[sourceIndex] = data;\n this.#suspendAdapterRebuild = true;\n this.items = next;\n }\n }\n }\n\n #rebuildFromAdapter(): void {\n const source = this.items ?? [];\n const keyOf = (el: Element): string | null => el.getAttribute(`data-key`);\n const previousKeys = new Set(\n [...this.selection.selected].map(keyOf).filter((k): k is string => k !== null),\n );\n const anchorKey = this.selection.anchor ? keyOf(this.selection.anchor) : null;\n\n // Discard checked-mode wrappers along with the old rows (mirrors clearItems)\n this.#customWrappers.clear();\n this.replaceChildren(...source.map((item, index) => this.#createAdapterItem(item, index)));\n\n // Re-select by key so selection survives the element-identity rebuild\n if (previousKeys.size > 0 || anchorKey !== null) {\n const next: Element[] = [];\n let anchor: Element | undefined;\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n const key = keyOf(el);\n if (key !== null && previousKeys.has(key))\n next.push(el);\n if (key !== null && key === anchorKey)\n anchor = el;\n }\n this.selection.seed(next, anchor);\n }\n\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n this._syncItemStates();\n this._syncNativeDraggable();\n this.#nativeDrag.refreshDraggable();\n }\n\n #createAdapterItem(item: unknown, index: number): Element {\n const content = this.formatter ? this.formatter(item, index) : item;\n if (content instanceof Element && this.#isRowElement(content)) {\n // Full-row mode: the formatter owns the row (e.g. an x-file-row-item).\n if (content.tagName !== `LI` && !content.hasAttribute(`data-list-item`))\n content.setAttribute(`data-list-item`, ``);\n this.#stampAdapterKey(content, item);\n this.#itemData.set(content, item);\n return content;\n }\n const li = document.createElement(`li`);\n this.#fillAdapterItem(li, content, item);\n return li;\n }\n\n #fillAdapterItem(li: HTMLLIElement, content: unknown, item: unknown): void {\n if (typeof content === `string`) {\n li.textContent = content;\n } else if (content instanceof Node) {\n li.appendChild(content);\n } else if (this.formatter && content !== undefined && content !== null) {\n render(content, li);\n }\n this.#stampAdapterKey(li, item);\n this.#itemData.set(li, item);\n }\n\n /**\n * Whether a formatter-produced element is a whole row (used directly)\n * rather than row content (rendered into a `<li>`): an `<li>`, already\n * marked `[data-list-item]`, or a custom element.\n */\n #isRowElement(content: Element): boolean {\n return content.tagName === `LI`\n || content.hasAttribute(`data-list-item`)\n || content.tagName.includes(`-`);\n }\n\n #stampAdapterKey(el: Element, item: unknown): void {\n if (!this.keyProperty)\n return;\n const key = this.#adapterProperty(item, this.keyProperty);\n if (key !== undefined && key !== null)\n el.setAttribute(`data-key`, String(key));\n }\n\n #adapterProperty(item: unknown, prop: string): unknown {\n if (typeof item !== `object` || item === null || !(prop in item))\n return undefined;\n return (item as Record<string, unknown>)[prop];\n }\n\n /** Ordinal of an adapter-built row among adapter-built rows in DOM order. */\n #adapterIndexOf(el: Element): number {\n if (this.#virtualActive())\n return this.#registryIndexOf(el);\n let index = 0;\n for (const item of this.querySelectorAll(ITEM_SELECTOR)) {\n if (item === el)\n return index;\n if (this.#itemData.has(item))\n index++;\n }\n return index;\n }\n\n /**\n * Adapter rebuild for the virtualized window: same content as\n * {@link #rebuildFromAdapter} but rows become the recycle registry and\n * only the window attaches.\n */\n #rebuildAdapterVirtual(): void {\n const source = this.items ?? [];\n const keyOf = (el: Element): string | null => el.getAttribute(`data-key`);\n const previousKeys = new Set(\n [...this.selection.selected].map(keyOf).filter((k): k is string => k !== null),\n );\n const anchorKey = this.selection.anchor ? keyOf(this.selection.anchor) : null;\n\n // New identities throughout — drop wrappers, pool and pending animates.\n this.#customWrappers.clear();\n this.#pool = document.createDocumentFragment();\n this.#pendingAnimate = [];\n this.#allItems = source.map((item, index) => this.#createAdapterItem(item, index));\n for (const el of this.#allItems)\n this.#animatedItems.add(el);\n\n // Re-select by key so selection survives the element-identity rebuild.\n if (previousKeys.size > 0 || anchorKey !== null) {\n const next: Element[] = [];\n let anchor: Element | undefined;\n for (const el of this.#allItems) {\n const key = keyOf(el);\n if (key !== null && previousKeys.has(key))\n next.push(el);\n if (key !== null && key === anchorKey)\n anchor = el;\n }\n this.selection.seed(next, anchor);\n }\n\n this.#syncVirtualWindow(true);\n }\n\n // --- Virtualization (true element recycling) ---\n\n #virtualActive(): boolean {\n return this.virtualize && this.itemHeight > 0;\n }\n\n /**\n * Selection order: the full registry while virtualized (so `selectAll` and\n * range operations span pooled rows too — they hold live element refs), the\n * attached rows otherwise.\n */\n #selectionOrder(): Element[] {\n if (!this.#virtualActive())\n return this._getVisibleItems();\n return this.#allItems.filter((el) => {\n if ((el as HTMLElement).hidden)\n return false;\n if (this.filterPredicate && !this.filterPredicate(el))\n return false;\n return true;\n });\n }\n\n /** Registry index of a row, resolving wrapped inners to their wrapper. */\n #registryIndexOf(el: Element): number {\n const direct = this.#allItems.indexOf(el);\n if (direct >= 0)\n return direct;\n if (this.#wrappedElements.has(el)) {\n for (const [wrapper, inner] of this.#customWrappers) {\n if (inner === el)\n return this.#allItems.indexOf(wrapper);\n }\n }\n return -1;\n }\n\n #swapRegistry(oldEl: Element, newEl: Element): void {\n const i = this.#allItems.indexOf(oldEl);\n if (i >= 0)\n this.#allItems[i] = newEl;\n }\n\n #cleanupWrapperRefs(el: Element): void {\n if (this.#customWrappers.has(el as HTMLLIElement)) {\n const inner = this.#customWrappers.get(el as HTMLLIElement);\n this.#customWrappers.delete(el as HTMLLIElement);\n if (inner)\n this.#wrappedElements.delete(inner);\n }\n if (this.#wrappedElements.has(el)) {\n for (const [wrapper, inner] of this.#customWrappers) {\n if (inner === el) {\n this.#customWrappers.delete(wrapper);\n break;\n }\n }\n this.#wrappedElements.delete(el);\n }\n }\n\n /**\n * Global registry index for an attached row, derived from its DOM position:\n * nodes after the bottom spacer are end-of-list appends, nodes before the\n * top spacer are prepends, otherwise window-start plus preceding rows.\n */\n #globalIndexForAttached(el: Element): number {\n let count = 0;\n let sib: Element | null = el.previousElementSibling;\n while (sib) {\n if (sib === this.#topSpacer)\n return this.#windowStart + count;\n if (sib === this.#bottomSpacer)\n return this.#allItems.length;\n if (sib.matches(ITEM_SELECTOR))\n count++;\n sib = sib.previousElementSibling;\n }\n // No spacers (e.g. first rows of an empty list): attached order is global.\n return count;\n }\n\n /**\n * Fold consumer-side DOM edits into the registry. Our own window moves\n * reconcile to no-ops (known nodes already pooled or correctly placed);\n * genuinely new nodes are spliced by DOM position; removed-then-gone nodes\n * are dropped. Returns whether the registry changed.\n */\n #reconcileRecords(records: MutationRecord[]): boolean {\n let changed = false;\n const fresh: Element[] = [];\n for (const record of records) {\n for (const node of record.addedNodes) {\n if (!(node instanceof Element) || node.parentNode !== this)\n continue;\n if (node.hasAttribute(`data-virtual-spacer`) || !node.matches(ITEM_SELECTOR))\n continue;\n const known = this.#registryIndexOf(node);\n if (known < 0) {\n const at = Math.min(this.#globalIndexForAttached(node), this.#allItems.length);\n this.#allItems.splice(at, 0, node);\n fresh.push(node);\n changed = true;\n } else if (this.#globalIndexForAttached(node) !== known) {\n const at = Math.min(this.#globalIndexForAttached(node), this.#allItems.length - 1);\n this.#allItems.splice(known, 1);\n this.#allItems.splice(at, 0, node);\n changed = true;\n }\n }\n for (const node of record.removedNodes) {\n if (!(node instanceof Element) || node.hasAttribute(`data-virtual-spacer`))\n continue;\n const known = this.#registryIndexOf(node);\n if (known < 0)\n continue;\n if (node.parentNode === this.#pool || node.parentNode === this)\n continue; // our own detach / re-insert\n this.#allItems.splice(known, 1);\n changed = true;\n }\n }\n if (fresh.length > 0) {\n // Bulk populates don't animate (shares #isBulkPopulate with the\n // non-virtual bail-out); incremental adds play their enter animation\n // once placed.\n if (this.#isBulkPopulate(fresh.length)) {\n for (const el of fresh)\n this.#animatedItems.add(el);\n } else {\n this.#pendingAnimate.push(...fresh);\n }\n }\n if (changed && this.interactionMode === `checked`)\n this._syncCheckboxes();\n return changed;\n }\n\n /** Consume queued observer records first so a sync never drops a row. */\n #drainMutations(): boolean {\n const pending = this.#itemObserver?.takeRecords() ?? [];\n return pending.length > 0 ? this.#reconcileRecords(pending) : false;\n }\n\n #scrollList(): HTMLUListElement | null {\n return this.renderRoot.querySelector(`ul`);\n }\n\n #measureViewport(ul: HTMLUListElement | null): number {\n if (!ul)\n return this.#lastViewportH;\n const h = ul.clientHeight || ul.getBoundingClientRect().height || 0;\n if (h > 0)\n this.#lastViewportH = h;\n return this.#lastViewportH;\n }\n\n #ensureSpacers(): void {\n if (this.#topSpacer && this.#bottomSpacer)\n return;\n const make = (): HTMLLIElement => {\n const li = document.createElement(`li`);\n li.setAttribute(`data-virtual-spacer`, ``);\n li.setAttribute(`aria-hidden`, `true`);\n return li;\n };\n this.#topSpacer = make();\n this.#bottomSpacer = make();\n }\n\n #ensureResizeObserved(): void {\n const ul = this.#scrollList();\n if (!ul)\n return;\n this.#resizeObserver ??= new ResizeObserver(() => {\n this.#syncVirtualWindow();\n });\n this.#resizeObserver.observe(ul);\n }\n\n #onScroll = (): void => {\n if (!this.#virtualActive())\n return;\n if (this.#scrollRaf !== 0)\n return;\n // Coalesce to one window sync per frame, like ixfx-grid-list.\n this.#scrollRaf = requestAnimationFrame(() => {\n this.#scrollRaf = 0;\n this.#syncVirtualWindow();\n });\n };\n\n /**\n * Reconcile the attached light DOM with the overscanned window. Rows are\n * moved by identity (never recreated); selection, cursor and component\n * state travel with them.\n */\n #syncVirtualWindow(force = false): void {\n if (!this.#virtualActive() || !this.isConnected)\n return;\n const changed = this.#drainMutations() || force;\n this.#ensureResizeObserved();\n const count = this.#allItems.length;\n const ul = this.#scrollList();\n const stride = this.itemHeight;\n const viewportH = this.#measureViewport(ul);\n const maxScroll = Math.max(0, count * stride - viewportH);\n const offset = Math.min(Math.max(0, ul ? ul.scrollTop : 0), maxScroll);\n if (ul && Math.abs(ul.scrollTop - offset) > 0.5)\n ul.scrollTop = offset;\n const firstVisible = Math.floor(offset / stride);\n const lastVisible = Math.ceil((offset + viewportH) / stride);\n const start = count === 0 ? 0 : Math.max(0, firstVisible - VIRTUAL_OVERSCAN);\n const end = Math.min(count, lastVisible + VIRTUAL_OVERSCAN);\n if (!changed && start === this.#windowStart && end === this.#windowEnd)\n return; // steady — no DOM churn for in-window scroll frames\n if (count === 0) {\n if (this.#allItems.length > 0)\n this.#pool.append(...this.#allItems);\n this.replaceChildren();\n } else {\n this.#ensureSpacers();\n const top = this.#topSpacer;\n const bottom = this.#bottomSpacer;\n if (!top || !bottom)\n return;\n top.style.height = `${start * stride}px`;\n bottom.style.height = `${Math.max(0, (count - end) * stride)}px`;\n const rows = this.#allItems.slice(start, end);\n // Park out-of-window rows in the pool FIRST — otherwise the observer\n // mistakes the placement's removals for consumer deletes and eats the\n // registry. Pool moves aren't observed (fragment), light-DOM moves\n // reconcile to no-ops via the parent checks.\n const parked = [...this.#allItems.slice(0, start), ...this.#allItems.slice(end)];\n if (parked.length > 0)\n this.#pool.append(...parked);\n this.replaceChildren(top, ...rows, bottom);\n }\n this.#windowStart = start;\n this.#windowEnd = end;\n if (this.interactionMode === `checked`)\n this._syncCheckboxes();\n this._syncItemStates();\n for (let i = start; i < end; i++) {\n const el = this.#allItems[i];\n if (el)\n this.#applyRowState(el);\n }\n const pending = this.#pendingAnimate;\n this.#pendingAnimate = [];\n for (const el of pending) {\n this.#animatedItems.add(el);\n if (el.parentNode === this)\n animateListItemIn(el as HTMLElement);\n }\n }\n\n /** Per-attach state the attached sweep can't cover (it only sees the window). */\n #applyRowState(el: Element): void {\n if (el instanceof HTMLElement)\n el.draggable = this.itemsDraggable && this._isCheckable(el);\n el.removeAttribute(`data-marquee`);\n el.removeAttribute(`data-drag-origin`);\n }\n\n /**\n * Leave virtualization: reattach every registry row in order and drop the\n * spacers and pool. Selection (live refs) and cursor survive untouched.\n */\n #teardownVirtualWindow(): void {\n for (const el of this.#allItems)\n this.#animatedItems.add(el);\n if (this.#allItems.length > 0)\n this.replaceChildren(...this.#allItems);\n else\n this.replaceChildren();\n this.#pool = document.createDocumentFragment();\n this.#topSpacer = undefined;\n this.#bottomSpacer = undefined;\n this.#windowStart = 0;\n this.#windowEnd = 0;\n this.#pendingAnimate = [];\n this._syncCheckboxes();\n this._syncItemStates();\n this._syncNativeDraggable();\n this.#nativeDrag.refreshDraggable();\n }\n\n // --- Helpers ---\n\n private _getVisibleItems(): Element[] {\n return Array.from(this.querySelectorAll(ITEM_SELECTOR)).filter((el) => {\n if (this.#wrappedElements.has(el))\n return false;\n if ((el as HTMLElement).hidden)\n return false;\n if (this.filterPredicate && !this.filterPredicate(el))\n return false;\n return true;\n });\n }\n\n // Whether an item participates in checked-mode selection. Items carrying the\n // `not-checked` attribute are skipped; outside `checked` mode it has no effect.\n // For wrapped custom elements the flag lives on the inner element, so resolve\n // through the wrapper map.\n private _isCheckable(item: Element): boolean {\n if (this.interactionMode !== `checked`)\n return true;\n const real = this.#customWrappers.get(item as HTMLLIElement) ?? item;\n return !real.hasAttribute(`not-checked`);\n }\n\n private _syncItemStates(): void {\n for (const el of this.querySelectorAll(ITEM_SELECTOR)) {\n if (this.#wrappedElements.has(el))\n continue;\n const item = this.#customWrappers.get(el as HTMLLIElement) ?? el;\n el.toggleAttribute(`data-tickled`, this.tickled.isTickled(el));\n el.toggleAttribute(`data-selected`, this.selection.selected.has(el));\n if (this.interactionMode === `checked`) {\n el.toggleAttribute(`data-checked`, !item.hasAttribute(`not-checked`) && this.selection.selected.has(el));\n } else {\n el.removeAttribute(`data-checked`);\n }\n }\n this.dataset.inputMode = this.tickled.inputMode;\n this._syncCheckboxes();\n }\n\n private _syncCheckboxes(): void {\n const inCheckedMode = this.interactionMode === `checked`;\n const wantsCustom = typeof this.checkboxRenderer === `function`;\n // Virtualized: pooled rows wrap/unwrap alongside attached ones so every\n // row is canonical whichever root it lives in.\n const roots: Array<Element | DocumentFragment> = this.#virtualActive() ? [this, this.#pool] : [this];\n\n if (inCheckedMode) {\n for (const root of roots) {\n for (const inner of Array.from(root.children)) {\n if (!inner.hasAttribute(`data-list-item`))\n continue;\n if (inner.parentNode !== root)\n continue; // idempotency: already wrapped\n const wrapper = document.createElement(`li`);\n wrapper.className = `ixfx-custom-row`;\n const key = inner.getAttribute(`data-key`);\n const label = inner.getAttribute(`data-search-label`);\n if (key !== null)\n wrapper.setAttribute(`data-key`, key);\n if (label !== null)\n wrapper.setAttribute(`data-search-label`, label);\n inner.removeAttribute(`data-list-item`);\n root.insertBefore(wrapper, inner);\n wrapper.appendChild(inner);\n this.#customWrappers.set(wrapper, inner);\n this.#wrappedElements.add(inner);\n // Adapter-built rows: keep getItemData() working on the visible wrapper\n if (this.#itemData.has(inner))\n this.#itemData.set(wrapper, this.#itemData.get(inner));\n if (this.#virtualActive())\n this.#swapRegistry(inner, wrapper);\n }\n }\n } else {\n for (const [wrapper, inner] of this.#customWrappers) {\n if (wrapper.parentNode !== this && wrapper.parentNode !== this.#pool)\n continue;\n inner.setAttribute(`data-list-item`, ``);\n const parent = wrapper.parentNode;\n if (parent)\n parent.insertBefore(inner, wrapper);\n wrapper.remove();\n this.#itemData.delete(wrapper);\n if (this.#virtualActive())\n this.#swapRegistry(wrapper, inner);\n }\n this.#customWrappers.clear();\n this.#wrappedElements.clear();\n }\n\n for (const el of this.querySelectorAll<HTMLElement>(`li`)) {\n const existing = el.querySelector<HTMLElement>(`.ixfx-list-checkbox`);\n if (!inCheckedMode) {\n if (existing)\n existing.remove();\n continue;\n }\n // Rows marked `not-checked` get no checkbox column and can't be checked\n const itemEl = this.#customWrappers.get(el as HTMLLIElement) ?? el;\n if (itemEl.hasAttribute(`not-checked`)) {\n if (existing)\n existing.remove();\n continue;\n }\n\n // In checked mode: if the existing checkbox is the wrong variant, drop it.\n const existingIsCustom = existing?.classList.contains(`ixfx-list-checkbox-custom`) ?? false;\n if (existing && existingIsCustom !== wantsCustom)\n existing.remove();\n\n let cb: HTMLElement | null = el.querySelector<HTMLElement>(`.ixfx-list-checkbox`);\n if (!cb) {\n if (wantsCustom) {\n const opts = this.checkboxRenderer as CustomCheckboxOptions;\n const margin = opts.margin ?? `0`;\n const width = opts.width ?? `24px`;\n cb = this._createCustomCheckbox(el, margin, width);\n } else {\n cb = this._createNativeCheckboxCell(el);\n }\n el.prepend(cb);\n }\n\n const checked = this.selection.selected.has(el);\n if (wantsCustom) {\n cb.setAttribute(`aria-checked`, String(checked));\n cb.toggleAttribute(`data-checked`, checked);\n if (this.checkboxRenderer) {\n const renderer = typeof this.checkboxRenderer === `function`\n ? this.checkboxRenderer\n : (this.checkboxRenderer as CustomCheckboxOptions).renderer;\n render(renderer(checked), cb);\n }\n } else {\n const input = cb.querySelector<HTMLInputElement>(`input.ixfx-list-checkbox`);\n if (input)\n input.checked = checked;\n }\n }\n }\n\n /**\n * Native checkbox cell: a span that stretches to the row's full cross-axis\n * (so the entire column height is a click target) with a real `<input>`\n * centred inside. The span owns the click; the input is purely visual and\n * has `pointer-events:none` so a single click produces one toggle.\n */\n private _createNativeCheckboxCell(el: HTMLElement): HTMLSpanElement {\n const cell = document.createElement(`span`);\n cell.className = `ixfx-list-checkbox ixfx-list-checkbox-native`;\n cell.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:18px;margin:0 6px 0 0;cursor:pointer;pointer-events:auto`;\n cell.tabIndex = -1;\n cell.setAttribute(`role`, `checkbox`);\n cell.setAttribute(`part`, `checkbox`);\n cell.addEventListener(`click`, (e) => {\n e.stopPropagation();\n this.selection.toggle(el);\n });\n const input = document.createElement(`input`);\n input.type = `checkbox`;\n input.className = `ixfx-list-checkbox`;\n input.style.cssText = `pointer-events:none;cursor:pointer;margin:0`;\n cell.appendChild(input);\n return cell;\n }\n\n /**\n * Custom checkbox cell: same shape as the native cell (a stretching span)\n * so behaviour is identical. The renderer's content goes inside.\n */\n private _createCustomCheckbox(el: HTMLElement, margin: string, width: string): HTMLSpanElement {\n const span = document.createElement(`span`);\n span.className = `ixfx-list-checkbox ixfx-list-checkbox-custom`;\n span.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:${width};margin:${margin};cursor:pointer;pointer-events:auto`;\n span.tabIndex = -1;\n span.setAttribute(`role`, `checkbox`);\n span.setAttribute(`part`, `checkbox`);\n span.addEventListener(`click`, (e) => {\n e.stopPropagation();\n this.selection.toggle(el);\n });\n return span;\n }\n\n private _findListItem(path: EventTarget[]): Element | undefined {\n for (const target of path) {\n if (!(target instanceof Element))\n continue;\n if (target === this)\n break;\n if (target.parentElement === this && target.matches(ITEM_SELECTOR))\n return target;\n }\n return undefined;\n }\n\n private _dispatch<T>(name: keyof ListElementEventMap, detail: T): void {\n this.dispatchEvent(new CustomEvent<T>(name as string, {\n detail,\n bubbles: true,\n composed: true,\n }));\n }\n\n private _dispatchCancelable<T>(name: string, detail: T): boolean {\n return this.dispatchEvent(new CustomEvent<T>(name, {\n detail,\n bubbles: true,\n composed: true,\n cancelable: true,\n }));\n }\n\n // --- Event handlers ---\n\n private _onPointerOver = (e: PointerEvent): void => {\n const item = this._findListItem(e.composedPath());\n if (item)\n this.tickled.handlePointerEnter(item);\n };\n\n private _onPointerLeave = (e: PointerEvent): void => {\n this.tickled.handlePointerLeave(e);\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (this.search.isOpen)\n return;\n if ((e.ctrlKey || e.metaKey) && e.key === `a`) {\n if (this.selection.canSelectAll()) {\n e.preventDefault();\n this.selection.selectAll();\n }\n return;\n }\n\n switch (e.key) {\n case `ArrowDown`: {\n e.preventDefault();\n this.tickled.handleKeyboardNavigation(`next`);\n // vscode: Shift+Arrow extends range from anchor\n if (e.shiftKey && this.interactionMode === `vscode`) {\n const cur = this.tickled.tickledId;\n if (cur)\n this.selection.rangeTo(cur);\n }\n break;\n }\n case `ArrowUp`: {\n e.preventDefault();\n this.tickled.handleKeyboardNavigation(`previous`);\n if (e.shiftKey && this.interactionMode === `vscode`) {\n const cur = this.tickled.tickledId;\n if (cur)\n this.selection.rangeTo(cur);\n }\n break;\n }\n case `Enter`: {\n const id = this.tickled.tickledId;\n if (id) {\n e.preventDefault();\n this._dispatch<ListItemClickDetail>(`list-item-click`, { item: id });\n this._activateItem(id);\n }\n break;\n }\n case ` `: {\n const id = this.tickled.tickledId;\n if (id) {\n e.preventDefault();\n this.selection.handleSpace(id);\n }\n break;\n }\n case `Escape`:\n this.selection.clear();\n break;\n }\n };\n\n private _onClick = (e: MouseEvent): void => {\n if (this.#dragSelect.isDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0)\n return;\n const item = this._findListItem(e.composedPath());\n if (!item)\n return;\n this._dispatch<ListItemClickDetail>(`list-item-click`, { item });\n this.selection.handleClick(item, e);\n };\n\n private _onDblClick = (e: MouseEvent): void => {\n const item = this._findListItem(e.composedPath());\n if (item)\n this._activateItem(item);\n };\n\n private _activateItem(item: Element): void {\n // manual mode: never auto-select; just fire the event\n if (this.interactionMode !== `manual`) {\n this.selection.replace(item);\n }\n this._dispatch<ListActivateDetail>(`list-activate`, { item });\n }\n\n // --- Styles ---\n\n static override styles = [themeFallbacks, listSearchStyles, css`\n :host {\n display: block;\n position: relative;\n background: var(--list-bg, var(--surface-3));\n color: var(--list-text, var(--surface-3-text));\n border-radius: var(--list-radius, var(--radius-s));\n border: 1px solid var(--list-border, var(--border));\n width: 100%;\n height: 100%;\n overflow: hidden;\n box-sizing: border-box;\n outline: none;\n --ixfx-list-item-padding: var(--ixfx-list-item-padding, var(--list-item-padding, 4px var(--space-m, 8px)));\n }\n\n :host(:focus-visible) {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n box-sizing: border-box;\n /* Scrollbar theming: end users override these CSS variables to control\n the native scrollbar (scrollbar-width, scrollbar-gutter, scrollbar-color). */\n scrollbar-width: var(--list-scrollbar-width, auto);\n scrollbar-gutter: var(--list-scrollbar-gutter, auto);\n scrollbar-color: var(--list-scrollbar-color, auto);\n }\n\n ::slotted([hidden]) {\n display: none !important;\n }\n\n ::slotted(li) {\n display: flex;\n align-items: center;\n padding: var(--ixfx-list-item-padding);\n /* Inset each row from the scroll container's edges (margin, not padding:\n padding is inside the border box, so the tickle/selection outlines\n would still sit flush against the edge and be clipped). */\n margin: 0 var(--list-gutter, 4px);\n min-height: var(--list-item-height, 28px);\n cursor: pointer;\n user-select: none;\n transition: background var(--transition, 0.1s ease-out),\n outline-color var(--transition, 0.1s ease-out);\n box-sizing: border-box;\n outline: 1px solid transparent;\n }\n\n /* Custom shadow-DOM components handle their own internal layout/padding.\n Wrapped in :where() so the selector stays at zero specificity and a\n consumer's own :host rule (e.g. display: flex) wins without\n needing !important. */\n :where(::slotted([data-list-item])) {\n display: block;\n margin: 0 var(--list-gutter, 4px);\n cursor: pointer;\n user-select: none;\n transition: background var(--transition, 0.1s ease-out),\n outline-color var(--transition, 0.1s ease-out);\n outline: 1px solid transparent;\n }\n\n /* Virtualization spacers: plain height holders bracketing the rendered\n window. Attribute specificity beats ::slotted(li) so none of the row\n layout (flex, padding, min-height, gutters) applies; pointer events are\n off so clicks land on the scroll container, not a phantom row. */\n ::slotted([data-virtual-spacer]) {\n display: block;\n padding: 0;\n margin: 0;\n border: none;\n min-height: 0;\n overflow: hidden;\n cursor: default;\n pointer-events: none;\n outline: none;\n user-select: none;\n }\n\n /* In checked mode, only the checkbox column is clickable; the row body\n gets a default cursor so it doesn't suggest otherwise. */\n :host([interaction-mode=\"checked\"]) ::slotted(li),\n :host([interaction-mode=\"checked\"]) ::slotted([data-list-item]) {\n cursor: default;\n }\n\n /* Wrapper inserted around custom [data-list-item] elements in checked mode.\n Provides the flex layout so the injected checkbox can stretch to the\n row's full height via align-self:stretch. */\n .ixfx-custom-row {\n display: flex;\n align-items: center;\n min-height: var(--list-item-height, 28px);\n box-sizing: border-box;\n cursor: default;\n user-select: none;\n }\n\n ::slotted([data-tickled]) {\n background: var(--item-bg-tickled);\n outline: var(--item-border-tickled);\n }\n\n ::slotted([data-selected]) {\n background: var(--item-bg-selected);\n color: var(--item-text-selected);\n outline: 1px solid transparent;\n }\n\n ::slotted([data-selected][data-tickled]) {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n\n /* Drag-select (marquee) rectangle + covered-row preview.\n Style hooks: part=\"marquee\", --vertical-list-marquee-border,\n --vertical-list-marquee-fill. */\n .marquee {\n position: absolute;\n pointer-events: none;\n z-index: 5;\n border: 1px solid var(--vertical-list-marquee-border, var(--accent));\n background: var(--vertical-list-marquee-fill, color-mix(in srgb, var(--accent) 15%, transparent));\n }\n\n ::slotted([data-marquee]) {\n background: var(--item-bg-selected);\n color: var(--item-text-selected);\n }\n\n ::slotted([data-drag-origin]) {\n opacity: 0.6;\n }\n\n /* checked mode: checkbox (injected into li) communicates selection — suppress bg highlight */\n :host([interaction-mode=\"checked\"]) ::slotted([data-selected]) {\n background: transparent;\n color: inherit;\n outline: 1px solid transparent;\n }\n\n :host([interaction-mode=\"checked\"]) ::slotted([data-selected][data-tickled]) {\n background: var(--item-bg-tickled);\n color: inherit;\n outline: var(--item-border-tickled);\n }\n `];\n\n // --- Render ---\n\n override render() {\n return html`\n <div class=\"container\">\n <ul part=\"list\" @scroll=${this.#onScroll}>\n <slot></slot>\n </ul>\n ${this.#marqueeRect\n ? html`<div class=\"marquee\" part=\"marquee\" style=${this.#marqueeStyle(this.#marqueeRect)}></div>`\n : ``}\n ${this.search.renderField()}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-vertical-list': VerticalListElement;\n }\n\n interface HTMLElementEventMap extends VerticalListElementEventMap {}\n}\n\nexport interface VerticalListElementEventMap extends ListElementEventMap {\n 'list-native-drag-start': ListNativeDragStartEvent<Element>;\n}\n"],"mappings":"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"}
|
package/docs-user/grid-list.md
CHANGED
|
@@ -130,6 +130,20 @@ positions the pill in `separate`.
|
|
|
130
130
|
`row` is the virtualised horizontal strip; `column` is the recommended
|
|
131
131
|
large-list replacement for `ixfx-vertical-list`.
|
|
132
132
|
|
|
133
|
+
### Snap-to-item
|
|
134
|
+
|
|
135
|
+
`snap-to-item` (`false` by default) — opt in to settle the viewport on the
|
|
136
|
+
nearest item boundary (`row`) or row boundary (`column`) once scrolling stops.
|
|
137
|
+
No effect in `grid` orientation.
|
|
138
|
+
|
|
139
|
+
This isn't implemented with native CSS `scroll-snap-type`: cells are
|
|
140
|
+
virtualised (only the visible window + overscan exist in the DOM, absolutely
|
|
141
|
+
positioned via `transform`), so the browser has no boxes to snap to once you
|
|
142
|
+
scroll a screen away, and the snap target would pop in/out of existence as the
|
|
143
|
+
window shifts. Instead, a short debounce after the last `scroll` event fires a
|
|
144
|
+
`scrollTo({ behavior: 'smooth' })` to the nearest boundary, computed the same
|
|
145
|
+
way the virtual window is (stride arithmetic — no measurement needed).
|
|
146
|
+
|
|
133
147
|
---
|
|
134
148
|
|
|
135
149
|
## Selection
|
package/docs-user/index.json
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detail-list-CQguZg9h.d.ts","names":[],"sources":["../src/detail-list/types.ts","../src/detail-list/detail-list.ts"],"mappings":";;;;;;;;;;KACY;;KAGA;WACD,SAAS;WACT;WACA;;;KAIC,wBAAwB,GAAG,gBAAgB,GAAG;;KAG9C,mBAAmB,eAAe,2BAA2B;;;;;;;;;;;;;;;;;;;;cC6E5D,0BAA0B;;EAErC,eAAe;EAGf,iBAAiB;EAGjB,MAAM;EAGN;EAGA,gBAAgB;EAGhB;EAGA,UAAU;EAGV;EAGA,WAAW;EAGX;EAGA;EAGA,mBAAmB,IAAI;;;;;;EAQvB;;EAIA,oBAAoB,gCAAgC;;;;;;EAQpD;;;;;;EAQA;;;;;EAOA,qBAAqB,wBAAwB;UAGrC;mBAgBS;UAeT;UAkFA;;WAyEC,QAAM,qBAAA;;MAYX,YAAY;EAoBP;EA4DA;EAsBA;EASA,QAAQ,SAAS;;MA0CtB,gBAAgB;;MAKhB,iBAAiB,YAAY;;;;;;EASjC;EAIA,QAAQ,MAAM,kBAAkB,UAAU;;;;;EAuB1C,WAAW,MAAM,UAAU;;EAW3B,YAAY,OAAO,SAAS,WAAW;EAIvC;;;;;EAYA,SAAS,gBAAgB;;;;;EAgBzB,YAAY,MAAM;;;;;;;;;;EAalB;;;;;;EAsBA,SAAS,WAAW,WAAW,OAAO;EAItC,OAAO,MAAM;EAIb,WAAW,OAAO,SAAS;EAI3B,SAAS,MAAM;EAIf;EAIA;;MAQI,gBAAgB;;MAKhB;;EAMJ,WAAW,MAAM;;EAKjB,gBAAgB,MAAM;;EAKtB,mBAAmB,MAAM;;EAKzB,SAAS;EAgBP,eAAe,0CAA0C,UAAU;UAwa7D;;;;;;;;;EAkBF,kBAAkB;UAwBhB;UAMA;UAgCA;UAiBA;;;;;;;UA2DA;;UAoBA;UAcA;UAYA;UAQA;UAWA;UAMA;UAIA;UA4EA;UAWA;UAMA;UAKA;SAUQ,sBAAM;EAiJb,wBAAM;;QAsBT;YACI;IACR,oBAAoB;;YAGZ,4BAA4B;;UAGvB,kCAAkC;EACjD,0BAA0B,yBAAyB"}
|