@ixfx/components 0.11.7 → 0.11.8
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 +153 -2
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +1129 -164
- package/bundle/index.js.map +1 -1
- package/dist/{detail-list-CgkOHYOa.d.ts → detail-list-lE_5UWVl.d.ts} +34 -3
- package/dist/detail-list-lE_5UWVl.d.ts.map +1 -0
- package/dist/detail-list.d.ts +3 -2
- package/dist/detail-list.js +271 -6
- package/dist/detail-list.js.map +1 -1
- package/dist/{grid-list-D6AfWfwn.d.ts → grid-list-Bc-RkDoO.d.ts} +42 -1
- package/dist/grid-list-Bc-RkDoO.d.ts.map +1 -0
- package/dist/{grid-list-3fGhdaFA.js → grid-list-Bwaf61is.js} +659 -158
- package/dist/grid-list-Bwaf61is.js.map +1 -0
- package/dist/grid-list.d.ts +3 -2
- package/dist/grid-list.js +2 -1
- package/dist/grouping-CUKgmkMm.d.ts +63 -0
- package/dist/grouping-CUKgmkMm.d.ts.map +1 -0
- package/dist/grouping-RYPnHkrS.js +53 -0
- package/dist/grouping-RYPnHkrS.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/list-group-header.d.ts +26 -0
- package/dist/list-group-header.d.ts.map +1 -0
- package/dist/list-group-header.js +122 -0
- package/dist/list-group-header.js.map +1 -0
- package/dist/{list-selection-controller-SA4piSBi.js → list-selection-controller-BeE70lbB.js} +42 -4
- package/dist/list-selection-controller-BeE70lbB.js.map +1 -0
- package/dist/vertical-list.js +1 -1
- package/docs-user/README.md +1 -0
- package/docs-user/detail-list.md +28 -0
- package/docs-user/grid-list.md +35 -3
- package/docs-user/index.json +7 -2
- package/docs-user/list-group-header.md +14 -0
- package/docs-user/llms.txt +1 -0
- package/llms.txt +1 -0
- package/package.json +5 -1
- package/dist/detail-list-CgkOHYOa.d.ts.map +0 -1
- package/dist/grid-list-3fGhdaFA.js.map +0 -1
- package/dist/grid-list-D6AfWfwn.d.ts.map +0 -1
- package/dist/list-selection-controller-SA4piSBi.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid-list-Bwaf61is.js","names":["ITEM_SELECTOR","#host","#effectiveIndices","#items","#itemKey","#keysCache","#captionFor","#predicate","#searchKeys","#recomputeEffective","#grouping","#groups","#groupByKey","#slotNames","#seq","#syntheticKeys","#applyGroupingTo","#adapter","#sourceElement","#source","#emitSelect","#stopActiveCaptionPan","#emitItemEvent","#itemWrap","#dragSelect","#nativeDrag","#prepareNativeDrag","#rowHeight","#nativeDragging","#dragOriginKey","#clearNativeDragState","#startPostDragSuppressTimer","#isCellBlankPress","#viewportRef","#marqueeHitTest","#marqueePreview","#marqueeRect","#markScrollHoverSuppress","#cancelScrollRaf","#scrollRaf","#emitViewportChange","#scheduleSnap","#lastPointerX","#lastPointerY","#scrollHoverSuppress","#endScrollHoverSuppress","#currentWindow","#layout","#scrollItemIntoView","#onCellActivate","#renderedCellForKey","#searchMode","#searchFilterKeys","#searchRegistry","#effectiveSearchModes","#unregisterSearchCommands","#syncAriaMultiselectable","#onHostPointerMove","#onHostPointerLeave","#mutationObserver","#onChildrenChanged","#ensureSearch","#syncSearchCommands","#resizeObserver","#cancelSnapTimer","#reflowTimer","#items","#syncItems","#noteChildMutation","#entering","#openReflowWindow","#lastViewportRenderedKeys","#lastViewportVisibleKeys","#rebuildSource","#measureViewport","#groupingConfig","#applyFilters","#zoomAnchor","#groupByChanged","#applyGroupingToSource","#dropUnreachableCursor","#captureCentreAnchor","#applyZoomAnchor","#activateTickledPan","#buildLayout","#rawIndexOfKey","#windowKeys","#layoutParams","#layoutCache","#selectedSnapshot","#onScroll","#onWheel","#onViewportClick","#renderDataCells","#renderElementCells","#renderHeaders","#marqueeStyle","#renderDataCell","#onCellClick","#handleCellPointerEnter","#colorStyle","#renderCaption","#activeCaptionPan","#renderCell","#captionFor","#snapTimer","#snapToNearestLine","#postDragSuppressTimer","customElement"],"sources":["../src/grid-list/grid-list-layout.ts","../src/grid-list/grid-list-source.ts","../src/grid-list/grid-list.ts"],"sourcesContent":["import type { GridListOrientation } from './types.js';\n\n/**\n * Pure layout model for `ixfx-grid-list`: maps effective item indices to\n * pixel positions and computes the virtualised window.\n *\n * The list is a sequence of *sections*. An ungrouped list is one headerless\n * section; a grouped list has one section per group, each preceded by a header.\n * Within a section items form a uniform grid, so per-scroll work is a binary\n * search over sections plus arithmetic — nothing is precomputed per item.\n */\n\n/** Geometry of a single uniform grid (one section). */\nexport type SectionWindow = {\n readonly cols: number;\n readonly rows: number;\n /** Spacer height in px (vertical orientations); 0 when CSS controls it. */\n readonly totalHeight: number;\n /** Spacer width in px (`row` orientation); 0 when CSS controls it. */\n readonly totalWidth: number;\n readonly startIndex: number;\n readonly endIndex: number;\n /** Distance between the left edges of adjacent columns (item width + gap). */\n readonly colStride: number;\n /** Distance between the top edges of adjacent rows (row height + gap). */\n readonly rowStride: number;\n /** `true` for `row` orientation — the list scrolls along the x axis. */\n readonly horizontal: boolean;\n};\n\n/**\n * `itemWidth` is the square's width; `rowHeight` is the full cell height\n * (square, plus the caption band in `separate` / `under` styles).\n * `scrollOffset` is `scrollTop` for `grid`/`column` and `scrollLeft` for `row`.\n */\nexport function computeGridWindow(\n count: number,\n itemWidth: number,\n rowHeight: number,\n gap: number,\n viewportWidth: number,\n viewportHeight: number,\n scrollOffset: number,\n orientation: GridListOrientation,\n overscan = 2,\n): SectionWindow {\n const w = Math.max(1, itemWidth);\n const h = Math.max(1, rowHeight);\n const g = Math.max(0, gap);\n const colStride = w + g;\n const rowStride = h + g;\n const offset = Math.max(0, scrollOffset);\n\n if (orientation === `row`) {\n const rows = count === 0 ? 0 : 1;\n const totalWidth = count === 0 ? 0 : (count - 1) * colStride + w;\n if (count === 0 || viewportWidth <= 0) {\n return { cols: count, rows, totalHeight: 0, totalWidth, startIndex: 0, endIndex: 0, colStride, rowStride, horizontal: true };\n }\n const firstVisible = Math.max(0, Math.floor(offset / colStride));\n const lastVisible = Math.ceil((offset + viewportWidth) / colStride);\n return {\n cols: count,\n rows,\n totalHeight: 0,\n totalWidth,\n startIndex: Math.max(0, firstVisible - overscan),\n endIndex: Math.min(count, lastVisible + overscan),\n colStride,\n rowStride,\n horizontal: true,\n };\n }\n\n const cols = orientation === `column`\n ? 1\n : Math.max(1, Math.floor((Math.max(0, viewportWidth) + g) / colStride));\n const rows = count === 0 ? 0 : Math.ceil(count / cols);\n const totalHeight = rows === 0 ? 0 : (rows - 1) * rowStride + h;\n\n if (count === 0 || viewportHeight <= 0) {\n return { cols, rows, totalHeight, totalWidth: 0, startIndex: 0, endIndex: 0, colStride, rowStride, horizontal: false };\n }\n\n const firstVisibleRow = Math.max(0, Math.floor(offset / rowStride));\n const lastVisibleRow = Math.ceil((offset + viewportHeight) / rowStride);\n const rowStart = Math.max(0, firstVisibleRow - overscan);\n const rowEnd = Math.min(rows, lastVisibleRow + overscan);\n\n return {\n cols,\n rows,\n totalHeight,\n totalWidth: 0,\n startIndex: rowStart * cols,\n endIndex: Math.min(count, rowEnd * cols),\n colStride,\n rowStride,\n horizontal: false,\n };\n}\n\n/** One group, as supplied to the layout. `count` is the group's full size. */\nexport type LayoutGroupInput = {\n readonly key: string;\n readonly label: string;\n readonly count: number;\n readonly collapsed: boolean;\n};\n\nexport type LayoutParams = {\n /** Effective item count (collapsed groups already excluded). Ignored when `groups` is set. */\n readonly count: number;\n /** Groups in display order. Omit for an ungrouped list. */\n readonly groups?: readonly LayoutGroupInput[];\n readonly itemWidth: number;\n readonly rowHeight: number;\n readonly gap: number;\n readonly viewportWidth: number;\n readonly viewportHeight: number;\n readonly orientation: GridListOrientation;\n /** Header height in px for `grid` / `column` orientations. */\n readonly headerHeight: number;\n /** Header width in px for `row` orientation. */\n readonly headerWidth: number;\n};\n\n/** A header to render, positioned along the main axis. */\nexport type HeaderSlot = {\n readonly key: string;\n readonly label: string;\n readonly count: number;\n readonly collapsed: boolean;\n /** Main-axis offset in px (`y` for vertical orientations, `x` for `row`). */\n readonly offset: number;\n /** Main-axis size in px. */\n readonly size: number;\n};\n\n/** The virtual window: what to render for a given scroll offset. */\nexport type GridWindow = SectionWindow & {\n readonly headers: readonly HeaderSlot[];\n /** Half-open `[start, end)` effective-index ranges, ascending. */\n readonly ranges: ReadonlyArray<readonly [number, number]>;\n};\n\nexport type ItemPosition = {\n readonly x: number;\n readonly y: number;\n readonly col: number;\n /** Line within the item's section (row for vertical orientations). */\n readonly line: number;\n readonly section: number;\n};\n\ntype Section = {\n readonly group: LayoutGroupInput | undefined;\n /** Effective index of the section's first item. */\n readonly first: number;\n /** Visible items (0 when collapsed). */\n readonly count: number;\n readonly headerOffset: number;\n readonly itemsOffset: number;\n readonly end: number;\n};\n\nexport type GridLayout = {\n readonly horizontal: boolean;\n readonly cols: number;\n readonly colStride: number;\n readonly rowStride: number;\n readonly grouped: boolean;\n readonly count: number;\n /** Total main-axis extent in px. */\n readonly totalExtent: number;\n window: (offset: number, overscan?: number) => GridWindow;\n positionOf: (index: number) => ItemPosition;\n /** Main-axis `[start, end)` an item occupies, including its header when it heads its group. */\n extentOf: (index: number) => readonly [number, number];\n /** Vertical arrow: same column one line up/down, hopping headers and clamping ragged rows. */\n neighbour: (index: number, dLine: -1 | 1) => number;\n /** Indices whose cell intersects the given content-space rectangle. */\n hitTest: (x0: number, x1: number, y0: number, y1: number) => number[];\n /** Effective index (and line fraction) nearest the given main-axis offset. */\n anchorAt: (mainOffset: number) => { index: number; lineFrac: number };\n /** Main-axis offset of `lineFrac` into the line holding `index`. */\n offsetOfAnchor: (index: number, lineFrac: number) => number;\n /** Nearest snap boundary (header or item line) to `offset`. */\n snapTarget: (offset: number) => number;\n};\n\nfunction buildSections(p: LayoutParams, cols: number, stride: number, itemExtent: number): { sections: Section[]; total: number; count: number } {\n const g = Math.max(0, p.gap);\n const horizontal = p.orientation === `row`;\n const lineCount = (n: number): number => (horizontal ? n : Math.ceil(n / cols));\n const extentFor = (n: number): number => (n === 0 ? 0 : (lineCount(n) - 1) * stride + itemExtent);\n\n if (!p.groups) {\n const end = extentFor(p.count);\n return { sections: [{ group: undefined, first: 0, count: p.count, headerOffset: 0, itemsOffset: 0, end }], total: end, count: p.count };\n }\n const headerSize = horizontal ? p.headerWidth : p.headerHeight;\n const sections: Section[] = [];\n let cursor = 0;\n let first = 0;\n for (const group of p.groups) {\n const count = group.collapsed ? 0 : group.count;\n const itemsOffset = cursor + headerSize + g;\n const end = count === 0 ? cursor + headerSize : itemsOffset + extentFor(count);\n sections.push({ group, first, count, headerOffset: cursor, itemsOffset, end });\n first += count;\n cursor = end + g;\n }\n const total = sections.length === 0 ? 0 : sections[sections.length - 1].end;\n return { sections, total, count: first };\n}\n\n/** Index of the last section whose `headerOffset` is <= `offset` (0 when before all). */\nfunction sectionAtOffset(sections: readonly Section[], offset: number): number {\n let lo = 0;\n let hi = sections.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (sections[mid].headerOffset <= offset)\n lo = mid;\n else\n hi = mid - 1;\n }\n return lo;\n}\n\n/** Index of the section holding effective item `index` (skips empty sections). */\nfunction sectionOfIndex(sections: readonly Section[], index: number): number {\n let lo = 0;\n let hi = sections.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (sections[mid].first <= index)\n lo = mid;\n else\n hi = mid - 1;\n }\n // Empty (collapsed) sections share `first` with their successor — step forward.\n let s = lo;\n while (s < sections.length - 1 && sections[s].count === 0)\n s++;\n return s;\n}\n\nexport function buildLayout(p: LayoutParams): GridLayout {\n const horizontal = p.orientation === `row`;\n const w = Math.max(1, p.itemWidth);\n const h = Math.max(1, p.rowHeight);\n const g = Math.max(0, p.gap);\n const colStride = w + g;\n const rowStride = h + g;\n const cols = horizontal\n ? 1\n : p.orientation === `column`\n ? 1\n : Math.max(1, Math.floor((Math.max(0, p.viewportWidth) + g) / colStride));\n const stride = horizontal ? colStride : rowStride;\n const itemExtent = horizontal ? w : h;\n const { sections, total, count } = buildSections(p, cols, stride, itemExtent);\n const grouped = p.groups !== undefined;\n const headerSize = horizontal ? p.headerWidth : p.headerHeight;\n const viewportMain = horizontal ? p.viewportWidth : p.viewportHeight;\n const cellHeight = rowStride - g;\n const rowY = Math.max(0, (p.viewportHeight - cellHeight) / 2);\n\n const positionOf = (index: number): ItemPosition => {\n const si = sectionOfIndex(sections, index);\n const s = sections[si];\n const local = Math.max(0, index - s.first);\n if (horizontal)\n return { x: s.itemsOffset + local * colStride, y: rowY, col: 0, line: local, section: si };\n const col = cols <= 1 ? 0 : local % cols;\n const line = cols <= 1 ? local : Math.floor(local / cols);\n return { x: col * colStride, y: s.itemsOffset + line * rowStride, col, line, section: si };\n };\n\n const window = (offset: number, overscan = 2): GridWindow => {\n const off = Math.max(0, offset);\n const headers: HeaderSlot[] = [];\n const ranges: Array<readonly [number, number]> = [];\n const lo = off - overscan * stride;\n const hi = off + viewportMain + overscan * stride;\n let firstSection = 0;\n if (sections.length > 1) {\n // First section whose end could reach the window.\n let a = 0;\n let b = sections.length - 1;\n while (a < b) {\n const mid = (a + b) >> 1;\n if (sections[mid].end >= lo)\n b = mid;\n else\n a = mid + 1;\n }\n firstSection = a;\n }\n if (viewportMain > 0) {\n for (let si = firstSection; si < sections.length; si++) {\n const s = sections[si];\n if (s.headerOffset > hi)\n break;\n if (s.group && s.headerOffset + headerSize >= lo) {\n headers.push({ key: s.group.key, label: s.group.label, count: s.group.count, collapsed: s.group.collapsed, offset: s.headerOffset, size: headerSize });\n }\n if (s.count === 0)\n continue;\n const rel = off - s.itemsOffset;\n // Shrink the viewport by the part of it that sits above this section's items.\n const viewport = rel < 0 ? viewportMain + rel : viewportMain;\n if (viewport <= 0)\n continue;\n const sw = computeGridWindow(\n s.count,\n w,\n h,\n g,\n horizontal ? viewport : p.viewportWidth,\n horizontal ? p.viewportHeight : viewport,\n Math.max(0, rel),\n p.orientation,\n overscan,\n );\n if (sw.endIndex > sw.startIndex)\n ranges.push([s.first + sw.startIndex, s.first + sw.endIndex]);\n }\n }\n return {\n cols: horizontal ? count : cols,\n rows: 0,\n totalHeight: horizontal ? 0 : total,\n totalWidth: horizontal ? total : 0,\n startIndex: ranges.length > 0 ? ranges[0][0] : 0,\n endIndex: ranges.length > 0 ? ranges[ranges.length - 1][1] : 0,\n colStride,\n rowStride,\n horizontal,\n headers,\n ranges,\n };\n };\n\n const extentOf = (index: number): readonly [number, number] => {\n const { line, section } = positionOf(index);\n const s = sections[section];\n const start = s.itemsOffset + line * stride;\n const begin = line === 0 && s.group ? s.headerOffset : start;\n return [begin, start + itemExtent];\n };\n\n const neighbour = (index: number, dLine: -1 | 1): number => {\n if (count === 0)\n return index;\n const si = sectionOfIndex(sections, index);\n const s = sections[si];\n const local = index - s.first;\n const col = local % cols;\n if (dLine > 0) {\n const t = local + cols;\n if (t <= s.count - 1)\n return s.first + t;\n const lastLine = Math.floor((s.count - 1) / cols);\n if (Math.floor(local / cols) < lastLine)\n return s.first + s.count - 1;\n for (let n = si + 1; n < sections.length; n++) {\n if (sections[n].count > 0)\n return sections[n].first + Math.min(col, sections[n].count - 1);\n }\n return s.first + s.count - 1;\n }\n const t = local - cols;\n if (t >= 0)\n return s.first + t;\n for (let n = si - 1; n >= 0; n--) {\n const prev = sections[n];\n if (prev.count > 0) {\n const line = Math.floor((prev.count - 1) / cols);\n return prev.first + Math.min(line * cols + col, prev.count - 1);\n }\n }\n return s.first;\n };\n\n const hitTest = (x0: number, x1: number, y0: number, y1: number): number[] => {\n const out: number[] = [];\n if (count === 0)\n return out;\n const main0 = horizontal ? x0 : y0;\n const main1 = horizontal ? x1 : y1;\n const start = sectionAtOffset(sections, main0 - stride);\n for (let si = Math.max(0, start); si < sections.length; si++) {\n const s = sections[si];\n if (s.itemsOffset > main1)\n break;\n if (s.count === 0 || s.end < main0)\n continue;\n if (horizontal) {\n const a = Math.max(0, Math.floor((x0 - s.itemsOffset) / colStride));\n const b = Math.min(s.count - 1, Math.floor((x1 - s.itemsOffset) / colStride));\n for (let i = a; i <= b; i++)\n out.push(s.first + i);\n } else {\n const colLo = Math.max(0, Math.floor(x0 / colStride));\n const colHi = Math.min(cols - 1, Math.floor(x1 / colStride));\n const rowLo = Math.max(0, Math.floor((y0 - s.itemsOffset) / rowStride));\n const rowHi = Math.floor((y1 - s.itemsOffset) / rowStride);\n for (let row = rowLo; row <= rowHi; row++) {\n for (let col = colLo; col <= colHi; col++) {\n const local = row * cols + col;\n if (local >= 0 && local < s.count)\n out.push(s.first + local);\n }\n }\n }\n }\n return out;\n };\n\n const anchorAt = (mainOffset: number): { index: number; lineFrac: number } => {\n if (count === 0)\n return { index: 0, lineFrac: 0 };\n let si = sectionAtOffset(sections, mainOffset);\n while (si < sections.length - 1 && sections[si].count === 0)\n si++;\n const s = sections[si];\n if (s.count === 0)\n return { index: 0, lineFrac: 0 };\n const centreLine = Math.max(0, mainOffset - s.itemsOffset) / stride;\n const lineFloor = Math.max(0, Math.floor(centreLine));\n const local = horizontal\n ? Math.min(s.count - 1, lineFloor)\n : Math.min(s.count - 1, lineFloor * cols + Math.max(0, Math.floor((cols - 1) / 2)));\n return { index: s.first + local, lineFrac: centreLine - lineFloor };\n };\n\n const offsetOfAnchor = (index: number, lineFrac: number): number => {\n const { line, section } = positionOf(index);\n return sections[section].itemsOffset + (line + lineFrac) * stride;\n };\n\n const snapTarget = (offset: number): number => {\n const si = sectionAtOffset(sections, offset);\n const s = sections[si];\n let rel = Math.round((offset - s.itemsOffset) / stride);\n if (grouped) {\n const lines = s.count === 0 ? 0 : (horizontal ? s.count : Math.ceil(s.count / cols));\n rel = Math.max(0, Math.min(Math.max(0, lines - 1), rel));\n }\n const candidates = [s.itemsOffset + rel * stride];\n if (grouped) {\n candidates.push(s.headerOffset);\n if (si + 1 < sections.length)\n candidates.push(sections[si + 1].headerOffset);\n }\n return candidates.reduce((best, c) => (Math.abs(c - offset) < Math.abs(best - offset) ? c : best));\n };\n\n return {\n horizontal,\n cols,\n colStride,\n rowStride,\n grouped,\n count,\n totalExtent: total,\n window,\n positionOf,\n extentOf,\n neighbour,\n hitTest,\n anchorAt,\n offsetOfAnchor,\n snapTarget,\n };\n}\n","import type { ListGroupInfo, ListGroupLabel } from '../interaction/grouping.js';\nimport type { GridListDataAdapter } from './types.js';\nimport { html } from 'lit';\nimport { partitionByGroup } from '../interaction/grouping.js';\nimport { keyForElement } from '../interaction/keyed-list.js';\n\n/**\n * Uniform view over a grid-list's items, in either mode:\n *\n * - element mode ({@link ElementGridListSource}) — light-DOM children projected\n * through named `<slot>`s;\n * - data mode ({@link DataGridListSource}) — a plain array plus a\n * {@link GridListDataAdapter}.\n *\n * Everything else in `GridListElement` addresses items by **effective index**\n * (0…`count`, after `[hidden]` / filter / search) and **key**, and never\n * branches on the mode.\n */\nexport interface GridListSource {\n /** After `[hidden]`, the filter predicate and the live search filter. */\n readonly count: number;\n /** Before the filter predicate / search filter (element mode still drops `[hidden]`). */\n readonly rawCount: number;\n\n /** Effective index → key. Includes synthetic keys for keyless light-DOM items. */\n keyAt(index: number): string;\n /** Effective index of `key`, or `-1`. First match wins on duplicates. */\n indexOfKey(key: string): number;\n /** Every effective key, in order (synthetic keys included). */\n keys(): string[];\n\n /** Caption text for a cell. */\n labelAt(index: number): string;\n /** Raw (unfiltered) index → key — used by search, which sees the whole collection. */\n rawKeyAt(index: number): string;\n /** Raw (unfiltered) index → fzf haystack (falls back to the label). */\n rawSearchTextAt(index: number): string;\n\n /** `false` for `not-checked` / `disabled` items. */\n isSelectable(index: number): boolean;\n\n /** Lit-renderable cell content (element mode: a named `<slot>`; data mode: `adapter.render`). */\n renderCellContent(index: number): unknown;\n\n /** Per-item icon content, or `undefined` (element mode: always `undefined`). */\n iconAt(index: number): unknown;\n /** CSS colour for the per-item icon, or `undefined`. */\n iconColorAt(index: number): string | undefined;\n /** CSS colour for the cell's caption, or `undefined`. */\n textColorAt(index: number): string | undefined;\n /** Finder-style badge content, or `undefined`. */\n badgeAt(index: number): unknown;\n\n /** Push the current filter predicate / search-filter key set; recomputes the effective order. */\n setFilters(opts: { predicate?: ((index: number) => boolean) | undefined; searchKeys?: ReadonlySet<string> | undefined }): void;\n /** Re-read the underlying data. */\n refresh(): void;\n\n /** Group items by `groupKeyOf` (raw index → key); collapsed groups drop out of the effective order. `undefined` ungroups. */\n setGrouping(config: GridListGrouping | undefined): void;\n /** Groups in display order (empty when ungrouped). `count` includes collapsed items. */\n groups(): readonly ListGroupInfo[];\n /** Group key of the item with `key` (collapsed items included), or `null`. */\n groupKeyOfKey(key: string): string | null;\n\n /** The Element for `key`, if this source has one. */\n resolveKeyToElement(key: string): Element | undefined;\n /** The data value for `key`, if this source has one. */\n resolveKeyToData(key: string): unknown;\n}\n\n/** Grouping applied on top of the filtered order. */\nexport type GridListGrouping = {\n /** Group key for a raw (unfiltered) index. */\n readonly groupKeyOf: (rawIndex: number) => string;\n /** Item (Element or data) at a raw index — handed to `labelOf`. */\n readonly itemAt: (rawIndex: number) => unknown;\n readonly labelOf?: ListGroupLabel | undefined;\n readonly collapsed: ReadonlySet<string>;\n};\n\ntype GroupedOrder = {\n readonly order: number[];\n readonly groups: ListGroupInfo[];\n readonly groupByKey: Map<string, string>;\n};\n\n/** Reorder `effective` raw indices into contiguous groups, dropping collapsed ones. */\nfunction applyGrouping(effective: readonly number[], cfg: GridListGrouping, keyOfRaw: (raw: number) => string): GroupedOrder {\n const parts = partitionByGroup(\n effective,\n raw => cfg.groupKeyOf(raw),\n cfg.labelOf ? (key, raws) => cfg.labelOf!(key, (raws as number[]).map(r => cfg.itemAt(r))) : undefined,\n );\n const order: number[] = [];\n const groups: ListGroupInfo[] = [];\n const groupByKey = new Map<string, string>();\n for (const part of parts) {\n const collapsed = cfg.collapsed.has(part.key);\n groups.push({ key: part.key, label: part.label, count: part.items.length, collapsed });\n for (const raw of part.items) {\n groupByKey.set(keyOfRaw(raw), part.key);\n if (!collapsed)\n order.push(raw);\n }\n }\n return { order, groups, groupByKey };\n}\n\nconst ITEM_SELECTOR = `:scope > *`;\nconst SYNTHETIC_PREFIX = `gl-auto-`;\n\n/** Whether `key` is an auto-assigned key for a keyless light-DOM item. */\nexport function isSyntheticKey(key: string): boolean {\n return key.startsWith(SYNTHETIC_PREFIX);\n}\n\nfunction warnDuplicateKeys(keys: readonly string[]): void {\n const seen = new Set<string>();\n const dupes = new Set<string>();\n for (const k of keys) {\n if (isSyntheticKey(k))\n continue;\n if (seen.has(k))\n dupes.add(k);\n else\n seen.add(k);\n }\n if (dupes.size > 0) {\n console.warn(\n `ixfx-grid-list: duplicate item key(s) ${[...dupes].map(k => `\"${k}\"`).join(`, `)} — the first occurrence wins for key-based operations.`,\n );\n }\n}\n\nexport class ElementGridListSource implements GridListSource {\n readonly #host: HTMLElement;\n #items: Element[] = [];\n #slotNames = new WeakMap<Element, string>();\n #syntheticKeys = new WeakMap<Element, string>();\n #seq = 0;\n #predicate: ((index: number) => boolean) | undefined;\n #searchKeys: ReadonlySet<string> | undefined;\n #effectiveIndices: number[] = [];\n #keysCache: string[] | undefined;\n #grouping: GridListGrouping | undefined;\n #groups: readonly ListGroupInfo[] = [];\n #groupByKey = new Map<string, string>();\n\n constructor(host: HTMLElement) {\n this.#host = host;\n this.refresh();\n }\n\n get count(): number {\n return this.#effectiveIndices.length;\n }\n\n get rawCount(): number {\n return this.#items.length;\n }\n\n keyAt(index: number): string {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? `` : this.#itemKey(this.#items[eff]);\n }\n\n indexOfKey(key: string): number {\n return this.#effectiveIndices.findIndex(i => this.#itemKey(this.#items[i]) === key);\n }\n\n keys(): string[] {\n this.#keysCache ??= this.#effectiveIndices.map(i => this.#itemKey(this.#items[i]));\n return this.#keysCache;\n }\n\n labelAt(index: number): string {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? `` : this.#captionFor(this.#items[eff]);\n }\n\n rawKeyAt(index: number): string {\n const el = this.#items[index];\n return el === undefined ? `` : this.#itemKey(el);\n }\n\n rawSearchTextAt(index: number): string {\n const el = this.#items[index];\n if (el === undefined)\n return ``;\n return (\n el.getAttribute(`data-search-label`)\n ?? el.getAttribute(`data-label`)\n ?? el.querySelector(`[data-grid-list-caption]`)?.textContent?.trim()\n ?? el.textContent?.trim()\n ?? ``\n );\n }\n\n isSelectable(index: number): boolean {\n const eff = this.#effectiveIndices[index];\n return eff !== undefined && !this.#items[eff].hasAttribute(`not-checked`);\n }\n\n renderCellContent(index: number): unknown {\n const eff = this.#effectiveIndices[index];\n if (eff === undefined)\n return undefined;\n return html`<slot name=${this.slotNameFor(this.#items[eff])}></slot>`;\n }\n\n // Element mode: the consumer owns the light-DOM markup, so they can already\n // set colours and include badge markup. Nothing to resolve here.\n iconAt(_index: number): undefined {\n return undefined;\n }\n\n iconColorAt(_index: number): undefined {\n return undefined;\n }\n\n textColorAt(_index: number): undefined {\n return undefined;\n }\n\n badgeAt(_index: number): undefined {\n return undefined;\n }\n\n setFilters(opts: { predicate?: ((index: number) => boolean) | undefined; searchKeys?: ReadonlySet<string> | undefined }): void {\n if (`predicate` in opts)\n this.#predicate = opts.predicate;\n if (`searchKeys` in opts)\n this.#searchKeys = opts.searchKeys;\n this.#recomputeEffective();\n }\n\n setGrouping(config: GridListGrouping | undefined): void {\n this.#grouping = config;\n this.#recomputeEffective();\n }\n\n groups(): readonly ListGroupInfo[] {\n return this.#groups;\n }\n\n groupKeyOfKey(key: string): string | null {\n return this.#groupByKey.get(key) ?? null;\n }\n\n refresh(): void {\n this.#items = Array.from(this.#host.querySelectorAll(ITEM_SELECTOR)).filter(\n el => !(el as HTMLElement).hidden,\n );\n for (const el of this.#items) {\n const name = this.slotNameFor(el);\n if (el.getAttribute(`slot`) !== name)\n el.setAttribute(`slot`, name);\n }\n warnDuplicateKeys(this.#items.map(el => this.#itemKey(el)));\n this.#recomputeEffective();\n }\n\n /** Effective-order elements — the array `GridListElement` renders and slices. */\n effectiveElements(): Element[] {\n return this.#effectiveIndices.map(i => this.#items[i]);\n }\n\n /** Raw-order element at `index`, or `undefined`. */\n rawElementAt(index: number): Element | undefined {\n return this.#items[index];\n }\n\n /** Stable per-element `<slot>` name. */\n slotNameFor(el: Element): string {\n let name = this.#slotNames.get(el);\n if (name === undefined) {\n this.#seq += 1;\n name = `gl-item-${this.#seq}`;\n this.#slotNames.set(el, name);\n }\n return name;\n }\n\n resolveKeyToElement(key: string): Element | undefined {\n if (isSyntheticKey(key))\n return this.#items.find(el => this.#syntheticKeys.get(el) === key);\n return this.#items.find(el => keyForElement(el) === key);\n }\n\n resolveKeyToData(_key: string): undefined {\n return undefined;\n }\n\n #recomputeEffective(): void {\n const effective: number[] = [];\n for (let i = 0; i < this.#items.length; i++) {\n if (this.#predicate !== undefined && !this.#predicate(i))\n continue;\n if (this.#searchKeys !== undefined) {\n const key = this.#itemKey(this.#items[i]);\n if (!isSyntheticKey(key) && !this.#searchKeys.has(key))\n continue;\n }\n effective.push(i);\n }\n this.#applyGroupingTo(effective);\n this.#keysCache = undefined;\n }\n\n #applyGroupingTo(effective: number[]): void {\n if (this.#grouping === undefined) {\n this.#effectiveIndices = effective;\n this.#groups = [];\n this.#groupByKey = new Map();\n return;\n }\n const grouped = applyGrouping(effective, this.#grouping, raw => this.#itemKey(this.#items[raw]));\n this.#effectiveIndices = grouped.order;\n this.#groups = grouped.groups;\n this.#groupByKey = grouped.groupByKey;\n }\n\n #itemKey(el: Element): string {\n const userKey = keyForElement(el);\n if (userKey !== undefined)\n return userKey;\n let synthetic = this.#syntheticKeys.get(el);\n if (synthetic === undefined) {\n this.#seq += 1;\n synthetic = `${SYNTHETIC_PREFIX}${this.#seq}`;\n this.#syntheticKeys.set(el, synthetic);\n }\n return synthetic;\n }\n\n #captionFor(el: Element): string {\n return (\n el.getAttribute(`data-label`)\n ?? el.querySelector(`[data-grid-list-caption]`)?.textContent?.trim()\n ?? ``\n );\n }\n}\n\nexport class DataGridListSource<T> implements GridListSource {\n #items: readonly T[];\n readonly #adapter: GridListDataAdapter<T>;\n #predicate: ((index: number) => boolean) | undefined;\n #searchKeys: ReadonlySet<string> | undefined;\n #effectiveIndices: number[] = [];\n #keysCache: string[] | undefined;\n #grouping: GridListGrouping | undefined;\n #groups: readonly ListGroupInfo[] = [];\n #groupByKey = new Map<string, string>();\n\n constructor(items: readonly T[], adapter: GridListDataAdapter<T>) {\n this.#items = items;\n this.#adapter = adapter;\n warnDuplicateKeys(items.map((it, i) => adapter.key(it, i)));\n this.#recomputeEffective();\n }\n\n get count(): number {\n return this.#effectiveIndices.length;\n }\n\n get rawCount(): number {\n return this.#items.length;\n }\n\n keyAt(index: number): string {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? `` : this.#adapter.key(this.#items[eff], eff);\n }\n\n indexOfKey(key: string): number {\n return this.#effectiveIndices.findIndex(i => this.#adapter.key(this.#items[i], i) === key);\n }\n\n keys(): string[] {\n this.#keysCache ??= this.#effectiveIndices.map(i => this.#adapter.key(this.#items[i], i));\n return this.#keysCache;\n }\n\n labelAt(index: number): string {\n const eff = this.#effectiveIndices[index];\n if (eff === undefined)\n return ``;\n return this.#adapter.label?.(this.#items[eff], eff) ?? this.#adapter.key(this.#items[eff], eff);\n }\n\n rawKeyAt(index: number): string {\n return index < 0 || index >= this.#items.length ? `` : this.#adapter.key(this.#items[index], index);\n }\n\n rawSearchTextAt(index: number): string {\n if (index < 0 || index >= this.#items.length)\n return ``;\n const item = this.#items[index];\n return this.#adapter.searchableText?.(item, index) ?? this.#adapter.label?.(item, index) ?? ``;\n }\n\n isSelectable(index: number): boolean {\n const eff = this.#effectiveIndices[index];\n return eff !== undefined && !this.#adapter.disabled?.(this.#items[eff], eff);\n }\n\n renderCellContent(index: number): unknown {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? undefined : this.#adapter.render(this.#items[eff], eff);\n }\n\n iconAt(index: number): unknown {\n const eff = this.#effectiveIndices[index];\n return eff === undefined || this.#adapter.icon === undefined\n ? undefined\n : this.#adapter.icon(this.#items[eff], eff);\n }\n\n iconColorAt(index: number): string | undefined {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? undefined : this.#adapter.iconColor?.(this.#items[eff], eff);\n }\n\n textColorAt(index: number): string | undefined {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? undefined : this.#adapter.textColor?.(this.#items[eff], eff);\n }\n\n badgeAt(index: number): unknown {\n const eff = this.#effectiveIndices[index];\n return eff === undefined || this.#adapter.badge === undefined\n ? undefined\n : this.#adapter.badge(this.#items[eff], eff);\n }\n\n setFilters(opts: { predicate?: ((index: number) => boolean) | undefined; searchKeys?: ReadonlySet<string> | undefined }): void {\n if (`predicate` in opts)\n this.#predicate = opts.predicate;\n if (`searchKeys` in opts)\n this.#searchKeys = opts.searchKeys;\n this.#recomputeEffective();\n }\n\n setGrouping(config: GridListGrouping | undefined): void {\n this.#grouping = config;\n this.#recomputeEffective();\n }\n\n groups(): readonly ListGroupInfo[] {\n return this.#groups;\n }\n\n groupKeyOfKey(key: string): string | null {\n return this.#groupByKey.get(key) ?? null;\n }\n\n refresh(): void {\n this.#recomputeEffective();\n }\n\n /** Raw-order item at `index`, or `undefined`. */\n rawItemAt(index: number): T | undefined {\n return this.#items[index];\n }\n\n /** Effective-order item at `index`, or `undefined`. */\n getItemAt(index: number): T | undefined {\n const eff = this.#effectiveIndices[index];\n return eff === undefined ? undefined : this.#items[eff];\n }\n\n resolveKeyToElement(_key: string): undefined {\n return undefined;\n }\n\n resolveKeyToData(key: string): T | undefined {\n const idx = this.#items.findIndex((item, i) => this.#adapter.key(item, i) === key);\n return idx >= 0 ? this.#items[idx] : undefined;\n }\n\n #recomputeEffective(): void {\n const effective: number[] = [];\n for (let i = 0; i < this.#items.length; i++) {\n if (this.#predicate !== undefined && !this.#predicate(i))\n continue;\n if (this.#searchKeys !== undefined && !this.#searchKeys.has(this.#adapter.key(this.#items[i], i)))\n continue;\n effective.push(i);\n }\n if (this.#grouping === undefined) {\n this.#effectiveIndices = effective;\n this.#groups = [];\n this.#groupByKey = new Map();\n } else {\n const grouped = applyGrouping(effective, this.#grouping, raw => this.#adapter.key(this.#items[raw], raw));\n this.#effectiveIndices = grouped.order;\n this.#groups = grouped.groups;\n this.#groupByKey = grouped.groupByKey;\n }\n this.#keysCache = undefined;\n }\n}\n","/* eslint-disable ts/no-unsafe-declaration-merging */\nimport type { CommandRegistry } from '@clinth/ui-commands';\nimport type { PropertyValues } from 'lit';\nimport type { DataListSearchItem, ListSearchMode } from '../incr-search/index.js';\nimport type { ListGroupBy, ListGroupChangeDetail, ListGroupInfo, ListGroupLabel, ListGroupToggleDetail } from '../interaction/grouping.js';\nimport type {\n DragSelectRect,\n ListDragEntry,\n ListDragPreviewRenderer,\n ListDragPreviewSourceResolver,\n ListNativeDragStartDetail,\n} from '../interaction/index.js';\nimport type { ListInteractionMode, ListSelectionMode } from '../interaction/list-selection-types.js';\nimport type { PanTextElement } from '../pan-text/pan-text.js';\nimport type { GridLayout, GridWindow, LayoutParams } from './grid-list-layout.js';\nimport type { GridListGrouping, GridListSource } from './grid-list-source.js';\nimport type {\n GridListCaptionAlign,\n GridListCaptionBackdrop,\n GridListCaptionPosition,\n GridListCaptionStyle,\n GridListDataAdapter as GridListDataAdapterType,\n GridListFullElementEventMap,\n GridListItemClickDetail,\n GridListOrientation,\n GridListSelectDetail,\n GridListViewportChangeDetail,\n} from './types.js';\nimport { createCommandRegistry } from '@clinth/ui-commands';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref } from 'lit/directives/ref.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { appearanceAbsent, appearanceColor } from '../common/item-appearance.js';\nimport {\n createDataListSearchAdapter,\n createElementListSearchAdapter,\n LIST_SEARCH_MODES,\n ListSearchController,\n listSearchStyles,\n registerListSearchCommands,\n} from '../incr-search/index.js';\nimport { resolveGroupKey } from '../interaction/grouping.js';\nimport { listItemFadeKeyframes, tickledItemStyles, tickledStyles } from '../interaction/index.js';\nimport { keyForElement } from '../interaction/keyed-list.js';\nimport { ListDragSelectController } from '../interaction/list-drag-select-controller.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 { scrollFadeStyles } from '../styles/scroll-fade.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport { buildLayout } from './grid-list-layout.js';\nimport { DataGridListSource, ElementGridListSource, isSyntheticKey } from './grid-list-source.js';\nimport '../list-group-header/list-group-header.js';\nimport '../pan-text/pan-text.js';\n\nexport type {\n GridListActivateDetail,\n GridListActivateEvent,\n GridListCaptionAlign,\n GridListCaptionBackdrop,\n GridListCaptionPosition,\n GridListCaptionStyle,\n GridListDataAdapter,\n GridListElementEventMap,\n GridListFullElementEventMap,\n GridListItemClickDetail,\n GridListItemClickEvent,\n GridListItemEventDetail,\n GridListOrientation,\n GridListSelectDetail,\n GridListSelectEvent,\n GridListTickleDetail,\n GridListTickleEvent,\n GridListViewportChangeDetail,\n GridListViewportChangeEvent,\n ListDragEntry,\n ListDragPreview,\n ListDragPreviewContext,\n ListDragPreviewRenderer,\n ListDragSource,\n ListGroupBy,\n ListGroupChangeDetail,\n ListGroupChangeEvent,\n ListGroupInfo,\n ListGroupLabel,\n ListGroupToggleDetail,\n ListGroupToggleEvent,\n ListInteractionMode,\n ListNativeDragStartDetail,\n ListNativeDragStartEvent,\n ListSelectionMode,\n} from './types.js';\n\nconst ITEM_SELECTOR = `:scope > *`;\n\nconst MIN_ITEM_SIZE = 16;\n\n/** How long scrolling must be idle before `snap-to-item` settles the viewport. */\nconst SNAP_DEBOUNCE_MS = 120;\n\n/**\n * How long the host keeps the `[reflowing]` attribute after items are inserted\n * mid-list — long enough for the cell move-transition and the enter animation\n * to finish. Kept a touch above the default `--grid-list-item-move-duration`.\n */\nconst REFLOW_WINDOW_MS = 320;\n\nfunction readProperty(item: unknown, name: string): unknown {\n return typeof item === `object` && item !== null ? (item as Record<string, unknown>)[name] : undefined;\n}\n\nfunction readAttribute(el: Element, name: string): unknown {\n return el.getAttribute(`data-${name}`);\n}\n\n/** Shallow key-array equality, treating `undefined` (never dispatched) as different. */\nfunction sameKeys(a: readonly string[] | undefined, b: readonly string[]): boolean {\n if (a === undefined || a.length !== b.length)\n return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i])\n return false;\n }\n return true;\n}\n\n@customElement(`ixfx-grid-list`)\nexport class GridListElement<T = unknown> extends LitElement {\n static override styles = [\n themeFallbacks,\n tickledStyles,\n tickledItemStyles,\n // Both axes are registered; `render()` applies whichever one matches the\n // current orientation to the viewport (see the `scroll-fade-*` class there).\n scrollFadeStyles(`x`),\n scrollFadeStyles(`y`),\n listItemFadeKeyframes,\n listSearchStyles,\n css`\n :host {\n --grid-list-item-bg: var(--item-bg);\n --grid-list-radius: var(--radius-m);\n --grid-list-gap: var(--space-xs);\n --grid-list-padding: var(--space-xs);\n position: relative;\n display: block;\n height: 100%;\n min-height: 2em;\n overflow: hidden;\n user-select: none;\n background: var(--surface-3);\n color: var(--surface-3-text);\n border-radius: var(--radius-s);\n border: 1px solid var(--border);\n }\n :host(:focus-visible) {\n outline: 2px solid var(--accent);\n outline-offset: -2px;\n }\n .viewport {\n position: relative;\n box-sizing: border-box;\n height: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--grid-list-padding);\n /* Consumer control over the native scrollbar (both orientations): set\n --grid-list-scrollbar-width to \"none\" to hide it or \"thin\" to slim it.\n The container is also exposed as ::part(viewport). */\n scrollbar-width: var(--grid-list-scrollbar-width, auto);\n scrollbar-gutter: var(--grid-list-scrollbar-gutter, auto);\n scrollbar-color: var(--grid-list-scrollbar-color, auto);\n }\n :host([orientation=\"row\"]) .viewport {\n overflow-x: auto;\n overflow-y: hidden;\n }\n .spacer {\n position: relative;\n width: 100%;\n }\n .group-header {\n position: absolute;\n inset: 0 auto auto 0;\n z-index: 1;\n }\n .cell {\n position: absolute;\n inset: 0 auto auto 0;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n contain: layout style;\n border-radius: var(--grid-list-radius);\n }\n\n /* The square that holds the slotted content — the \"image well\". Its\n background is a set of consumer-settable variables so a Finder-style\n look is possible: on selection the caption takes the accent colouring\n while the well takes a tint of the surface colour. Each variable is\n unset by default, so the fallback (today's look) applies until a\n consumer opts in.\n --grid-list-thumb-bg idle well background\n --grid-list-thumb-bg-tickled under the cursor\n --grid-list-thumb-bg-selected when the cell is selected\n --grid-list-thumb-bg-selected-tickled selected + under the cursor\n --grid-list-thumb-selection-wash colour of the box-mode wash (default: --accent)\n --grid-list-thumb-selection-wash-opacity strength of that wash (default: 0.18; set 0 to drop it) */\n .thumb {\n position: relative;\n flex: 1;\n min-height: 0;\n display: flex;\n align-items: stretch;\n box-sizing: border-box;\n overflow: hidden;\n border-radius: 0;\n background: var(--grid-list-thumb-bg, transparent);\n border: 1px solid transparent;\n transition: background var(--transition), border-color var(--transition);\n }\n .thumb ::slotted(*) {\n flex: 1;\n min-width: 0;\n min-height: 0;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n }\n .thumb ::slotted(*:empty)::after {\n content: \"Empty\";\n color: var(--surface-muted-text);\n font-size: var(--text-s);\n }\n ::slotted([hidden]) {\n display: none !important;\n }\n\n /* Selection / cursor wash — sits over the slotted content so it reads\n on photos and arbitrary DOM alike. Set\n --grid-list-thumb-selection-wash-opacity: 0 to drop it in favour of a\n --grid-list-thumb-bg-selected tint. */\n .thumb::after {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n border-radius: inherit;\n background: var(--grid-list-thumb-selection-wash, var(--accent));\n opacity: 0;\n transition: opacity var(--transition, 0.1s ease-out);\n }\n .cell.selected .thumb::after {\n opacity: var(--grid-list-thumb-selection-wash-opacity, 0.18);\n }\n :host(:not([caption-style=\"separate\"])) .cell.selected .thumb {\n background: var(--grid-list-thumb-bg-selected, var(--grid-list-thumb-bg, transparent));\n }\n :host(:not([caption-style=\"separate\"])) .cell.selected.tickled .thumb {\n background: var(--grid-list-thumb-bg-selected-tickled, var(--grid-list-thumb-bg-selected, var(--grid-list-thumb-bg, transparent)));\n }\n\n /* ---- Caption (base) ---- */\n .caption {\n box-sizing: border-box;\n flex: none;\n padding: 3px 6px;\n font-size: var(--text-s, 0.8rem);\n line-height: 1.3;\n text-align: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--surface-3-text);\n }\n :host([caption-align=\"left\"]) .caption { text-align: left; }\n :host([caption-align=\"right\"]) .caption { text-align: right; }\n /* Tickled captions swap their plain label for an ixfx-pan-text in loop\n mode so a truncated label scrolls instead of staying an ellipsis. The\n pan fills the caption band (flex in 'separate', block otherwise) and\n inherits its alignment. */\n .caption ixfx-pan-text {\n display: block;\n flex: 1;\n min-width: 0;\n max-width: 100%;\n font: inherit;\n color: inherit;\n }\n\n /* ---- Per-item icon (data mode) ----\n Only [has-icon] switches to a column, so a cell without an icon keeps\n exactly the layout it had before. The main content stays stretched;\n the icon centres itself above it. */\n .content.has-icon {\n display: flex;\n flex-direction: column;\n min-height: 0;\n gap: var(--grid-list-icon-gap, 2px);\n }\n .cell-icon {\n flex: none;\n align-self: center;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--grid-list-icon-size, 1.25em);\n height: var(--grid-list-icon-size, 1.25em);\n }\n\n /* ---- Per-item badge (data mode) ----\n Finder thumbnails put the tag inline, immediately before the name, so\n the caption becomes a flex row. The text is wrapped in its own\n shrinkable box so the ellipsis survives. */\n .caption.has-badge {\n display: flex;\n align-items: center;\n gap: var(--grid-list-badge-gap, 3px);\n text-align: initial;\n }\n :host([caption-align=\"left\"]) .caption.has-badge { justify-content: flex-start; }\n :host([caption-align=\"right\"]) .caption.has-badge { justify-content: flex-end; }\n .caption.has-badge .caption-text {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .caption .badge {\n flex: none;\n display: inline-flex;\n align-items: center;\n }\n\n /* ---- Box modes (hidden / under / overlaid): the cell is one box with a\n single selection outline ---- */\n :host(:not([caption-style=\"separate\"])) .cell {\n background: var(--grid-list-item-bg);\n border: 1px solid transparent;\n overflow: hidden;\n transition: background var(--transition), border-color var(--transition);\n }\n :host(:not([caption-style=\"separate\"])) .cell.tickled,\n /* [data-scroll-hover-suppress] is set while a scroll gesture moves\n cells beneath a stationary pointer (see disable-scroll-hover-tickle):\n the :hover highlight is gated so the visual cursor holds still too. */\n :host(:not([caption-style=\"separate\"]):not([disable-hover-tickle]):not([data-scroll-hover-suppress])) .cell:hover {\n background: var(--item-bg-tickled);\n border: var(--item-border-tickled);\n }\n :host(:not([caption-style=\"separate\"])) .cell.selected {\n outline: 2px solid var(--accent);\n outline-offset: -2px;\n }\n :host(:not([caption-style=\"separate\"])) .cell.selected.tickled {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n\n /* under: caption is a strip inside the box, below the content */\n :host([caption-style=\"under\"]) .caption {\n border-top: 1px solid var(--border, rgba(128, 128, 128, 0.3));\n background: var(--surface-4, transparent);\n }\n :host([caption-style=\"under\"][caption-position=\"top\"]) .caption {\n order: -1;\n border-top: none;\n border-bottom: 1px solid var(--border, rgba(128, 128, 128, 0.3));\n }\n\n /* overlaid: caption floats over the content */\n :host([caption-style=\"overlaid\"]) .caption {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n color: #fff;\n }\n :host([caption-style=\"overlaid\"][caption-position=\"top\"]) .caption {\n top: 0;\n bottom: auto;\n }\n :host([caption-style=\"overlaid\"][caption-position=\"middle\"]) .caption {\n top: 50%;\n bottom: auto;\n transform: translateY(-50%);\n }\n /* overlaid backdrop */\n :host([caption-style=\"overlaid\"][caption-backdrop=\"scrim\"]) .caption {\n background: rgba(0, 0, 0, 0.55);\n }\n :host([caption-style=\"overlaid\"][caption-backdrop=\"gradient\"]) .caption {\n background: linear-gradient(to top, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));\n padding-block: 10px 4px;\n }\n :host([caption-style=\"overlaid\"][caption-backdrop=\"gradient\"][caption-position=\"top\"]) .caption {\n background: linear-gradient(to bottom, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));\n padding-block: 4px 10px;\n }\n :host([caption-style=\"overlaid\"][caption-backdrop=\"gradient\"][caption-position=\"middle\"]) .caption {\n background: rgba(0, 0, 0, 0.5);\n padding-block: 3px;\n }\n :host([caption-style=\"overlaid\"][caption-backdrop=\"blur\"]) .caption {\n background: rgba(20, 20, 20, 0.3);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n }\n :host([caption-style=\"overlaid\"][caption-backdrop=\"none\"]) .caption {\n background: none;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95), 0 0 6px rgba(0, 0, 0, 0.7);\n }\n\n /* ---- separate mode: square + detached caption, each highlighted ---- */\n :host([caption-style=\"separate\"]) .thumb {\n flex: none;\n border-radius: var(--grid-list-radius);\n background: var(--grid-list-thumb-bg, var(--grid-list-item-bg));\n border: 1px solid transparent;\n }\n :host([caption-style=\"separate\"]) .cell.tickled .thumb,\n :host([caption-style=\"separate\"]:not([disable-hover-tickle]):not([data-scroll-hover-suppress])) .cell:hover .thumb {\n background: var(--grid-list-thumb-bg-tickled, var(--item-bg-tickled));\n border: var(--item-border-tickled);\n }\n :host([caption-style=\"separate\"]) .caption {\n display: flex;\n align-items: center;\n align-self: center;\n max-width: 100%;\n margin-top: 4px;\n border-radius: var(--radius-s, 4px);\n }\n :host([caption-style=\"separate\"][caption-align=\"left\"]) .caption { align-self: flex-start; }\n :host([caption-style=\"separate\"][caption-align=\"right\"]) .caption { align-self: flex-end; }\n :host([caption-style=\"separate\"][caption-position=\"top\"]) .caption {\n order: -1;\n margin-top: 0;\n margin-bottom: 4px;\n }\n /* Inset the selection ring (negative offset) so it is never clipped by the\n scroll viewport's overflow when the cell sits against an edge. */\n :host([caption-style=\"separate\"]) .cell.selected .thumb {\n background: var(--grid-list-thumb-bg-selected, var(--grid-list-thumb-bg, var(--grid-list-item-bg)));\n outline: 2px solid var(--accent);\n outline-offset: -2px;\n }\n :host([caption-style=\"separate\"]) .cell.selected.tickled .thumb {\n background: var(--grid-list-thumb-bg-selected-tickled, var(--item-bg-selected-tickled));\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n :host([caption-style=\"separate\"]) .cell.selected .caption {\n background: var(--accent);\n color: var(--accent-text, #000);\n }\n :host([caption-style=\"separate\"]) .cell.tickled .caption {\n background: var(--item-bg-tickled);\n outline: var(--item-border-tickled);\n }\n :host([caption-style=\"separate\"]) .cell.selected.tickled .caption {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n\n /* ---- Insertion / removal animation ----\n Active only while the host carries [reflowing] — the ~0.3s window after\n the child list changes mid-list (see #noteChildMutation). Kept out of\n the base rules so it never fires during scroll virtualisation, where\n cells are recycled to wildly different positions every frame. Placed\n last so it wins over the earlier cell transition rule regardless of\n specificity. Survivors slide to their new slot; a freshly inserted cell\n also fades in. (A removed item's element is already gone, so there's\n nothing left to fade — the gap simply closes as the others slide.) */\n :host([reflowing]) .group-header {\n transition: transform var(--grid-list-item-move-duration, 200ms) cubic-bezier(0.2, 0, 0, 1);\n }\n :host([reflowing]) .cell {\n transition:\n transform var(--grid-list-item-move-duration, 200ms) cubic-bezier(0.2, 0, 0, 1),\n background var(--transition),\n border-color var(--transition);\n }\n .cell.entering {\n animation: ixfx-list-item-in var(--grid-list-item-move-duration, 200ms) ease both;\n }\n @media (prefers-reduced-motion: reduce) {\n :host([reflowing]) .group-header { transition: none; }\n :host([reflowing]) .cell { transition: background var(--transition), border-color var(--transition); }\n .cell.entering { animation: none; }\n }\n\n /* Drag-select (marquee) rectangle + covered-cell preview. The preview\n reuses the selection wash so covered cells read as \"about to be\n selected\". Style hooks: part=\"marquee\", --grid-list-marquee-border,\n --grid-list-marquee-fill. */\n .marquee {\n position: absolute;\n pointer-events: none;\n z-index: 5;\n border: 1px solid var(--grid-list-marquee-border, var(--accent));\n background: var(--grid-list-marquee-fill, color-mix(in srgb, var(--accent) 15%, transparent));\n }\n .cell.marquee .thumb::after {\n opacity: var(--grid-list-thumb-selection-wash-opacity, 0.18);\n }\n\n /* Native item drag origin cell. */\n .cell.dragging-origin {\n opacity: 0.6;\n }\n `,\n ];\n\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 /**\n * Disable hover tickling: pointer hover no longer moves the cursor, fires\n * `list-tickle`, or changes where keyboard navigation resumes from. Keyboard\n * navigation, selection, and `focusKey()` are unaffected.\n */\n @property({ type: Boolean, attribute: `disable-hover-tickle`, reflect: true })\n disableHoverTickle = false;\n\n /**\n * Ignore hover-target changes caused by scrolling. With virtualisation, a\n * wheel / trackpad gesture replaces the cell beneath a stationary pointer,\n * and the freshly rendered cell's `pointerenter` would move the cursor and\n * emit `list-tickle` even though the pointer never moved. With this set,\n * `pointerenter`-driven tickling is suppressed while a scroll gesture is\n * active — the host also carries a `data-scroll-hover-suppress` attribute\n * that gates the CSS `:hover` highlight, so the visual cursor holds still\n * too. Hover resumes on the next real pointer movement, or after the pointer\n * leaves and re-enters the list. Click selection, keyboard navigation, and\n * `focusKey()` are unaffected.\n */\n @property({ type: Boolean, attribute: `disable-scroll-hover-tickle`, reflect: true })\n disableScrollHoverTickle = false;\n\n @property({ type: Number, attribute: `item-size` })\n itemSize = 160;\n\n @property({ type: Number })\n gap = 8;\n\n /**\n * Layout / scroll direction.\n * - `grid` (default): items wrap across as many columns as fit, scrolls vertically.\n * - `row`: a single row of items, scrolls horizontally.\n * - `column`: a single column of items, scrolls vertically.\n */\n @property({ type: String, reflect: true })\n orientation: GridListOrientation = `grid`;\n\n /**\n * How the caption relates to the content — see {@link GridListCaptionStyle}.\n * - `hidden`: no caption.\n * - `separate`: detached label below the square, each highlighted on its own.\n * - `under` (default): one box, content on top, caption strip below it inside.\n * - `overlaid`: caption floats over the content.\n */\n @property({ type: String, attribute: `caption-style`, reflect: true })\n captionStyle: GridListCaptionStyle = `under`;\n\n /** Horizontal alignment of the caption text: `left`, `middle` (default), `right`. */\n @property({ type: String, attribute: `caption-align`, reflect: true })\n captionAlign: GridListCaptionAlign = `middle`;\n\n /** Vertical placement of caption: `top`, `middle` (default), `bottom`. `middle` only has effect for `overlaid` style. */\n @property({ type: String, attribute: `caption-position`, reflect: true })\n captionPosition: GridListCaptionPosition = `bottom`;\n\n /** `overlaid` only — backdrop behind the caption: `scrim` (default), `gradient`, `blur`, `none`. */\n @property({ type: String, attribute: `caption-backdrop`, reflect: true })\n captionBackdrop: GridListCaptionBackdrop = `scrim`;\n\n /**\n * Height reserved for the caption in `separate` / `under` styles, in pixels.\n * Ignored by `overlaid` and `hidden`.\n */\n @property({ type: Number, attribute: `caption-height` })\n captionHeight = 24;\n\n @property({ type: String, attribute: `item-wrap` })\n itemWrap: `stop` | `wrap` = `stop`;\n\n /**\n * Element-mode filter predicate (also driven by incremental filter-search).\n * Light-DOM items for which it returns `false` are removed from layout and\n * navigation. For data mode use {@link itemFilterPredicate}.\n */\n @property({ attribute: false })\n filterPredicate: ((el: Element) => boolean) | undefined;\n\n /**\n * Data-mode filter predicate. Items for which it returns `false` are removed\n * from layout and navigation without any element being materialised.\n */\n @property({ attribute: false })\n itemFilterPredicate: ((item: T, index: number) => boolean) | undefined;\n\n /**\n * Space-separated subset of `navigate select filter` — limits which\n * incremental-search modes are offered (as commands and in-popover switches).\n * Unset ⇒ all three; empty ⇒ search disabled. See `docs/infra-incremental.md`.\n */\n /**\n * Enable native browser drag-and-drop for selectable items. When true,\n * selectable cells become draggable and the grid 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 * Allow a marquee (region) selection to start from a cell's blank well area —\n * a press that lands on the cell's content container (`.content` / `.thumb`)\n * itself rather than on the item content, caption, or an interactive control.\n * The same press is prevented from starting the cell's native drag.\n *\n * Off by default. The consumer must ensure blank areas are not covered by\n * pointer-eventful slotted nodes (size content to its box and/or set\n * `pointer-events: none` on filler), otherwise the blank area still counts as\n * content and this has no effect.\n */\n @property({ type: Boolean, attribute: `marquee-from-cell-blank`, reflect: true })\n marqueeFromCellBlank = false;\n\n /**\n * Custom drag preview renderer. Receives the selection snapshot and returns\n * an element for `DataTransfer.setDragImage()` plus an optional pre-painted\n * canvas for native hosts. Synchronous by contract — pre-decode thumbnails\n * as selection changes. Defaults to the shared built-in preview.\n */\n @property({ attribute: false })\n dragPreviewRenderer: ListDragPreviewRenderer<T> | undefined;\n\n /**\n * Optional synchronous resolver that supplies an already-loaded\n * `CanvasImageSource` for each drag entry's preview thumbnail.\n *\n * Called before the default descendant-`<img>` lookup. Must return an\n * already-decoded image (e.g. `<img>`, `<canvas>`, `<video>`, `ImageBitmap`)\n * or `undefined`. Returning `undefined` defers to standard DOM discovery.\n * The consumer owns the returned source and its lifetime.\n *\n * This allows consumers to provide images that live inside their own shadow\n * roots or other encapsulated contexts without grid-list needing to\n * traverse those boundaries.\n */\n @property({ attribute: false })\n dragPreviewSource: ListDragPreviewSourceResolver<T> | undefined;\n\n @property({ type: String, attribute: `search-modes`, reflect: true })\n searchModes: string | undefined;\n\n /**\n * Opt-in scroll snapping for `row` / `column` orientations (no effect in\n * `grid`). Cells are virtualized — only the visible window is ever in the\n * DOM, absolutely positioned via transform — so native CSS\n * `scroll-snap-type` can't be used (it can only snap to boxes that actually\n * exist, and the snap target would pop in/out as the window shifts).\n * Instead, once scrolling settles, the viewport is nudged with a smooth\n * `scrollTo` to the nearest item/row boundary.\n */\n @property({ type: Boolean, attribute: `snap-to-item`, reflect: true })\n snapToItem = false;\n\n /**\n * Data items for data-backed mode. When set along with `itemAdapter`, the\n * component operates in data mode instead of element mode.\n */\n @property({ attribute: false })\n items: readonly T[] = [];\n\n /**\n * Adapter for data-backed mode. When set, the component renders items from\n * the `items` array using this adapter instead of projecting light-DOM children.\n */\n @property({ attribute: false })\n itemAdapter: GridListDataAdapterType<T> | undefined;\n\n /**\n * Group items under collapsible headers. A string names an item property\n * (data mode) or `data-<name>` attribute (element mode); a function derives\n * the key (`Element` in element mode). `null` = ungrouped. Groups appear in\n * first-encounter order; see `ixfx-data-grid` for the reference behaviour.\n */\n @property({ attribute: `group-by` })\n groupBy: ListGroupBy<T> | null = null;\n\n /** Header label for a group. Defaults to the key (`(none)` for the empty key). */\n @property({ attribute: false })\n groupLabel: ListGroupLabel | undefined;\n\n /**\n * Let selection span groups. When `false` (default) selecting in one group\n * clears the others and Shift-range / select-all stay inside one group.\n */\n @property({ type: Boolean, attribute: `cross-group-selection`, reflect: true })\n crossGroupSelection = false;\n\n /** Header height in px (`grid` / `column` orientations). */\n @property({ type: Number, attribute: `group-header-height` })\n groupHeaderHeight = 28;\n\n /** Header width in px (`row` orientation). */\n @property({ type: Number, attribute: `group-header-width` })\n groupHeaderWidth = 120;\n\n @state() private _collapsedGroups: ReadonlySet<string> = new Set();\n @state() private _scrollTop = 0;\n @state() private _scrollLeft = 0;\n @state() private _viewportHeight = 0;\n @state() private _viewportWidth = 0;\n\n #viewportRef = createRef<HTMLDivElement>();\n\n #resizeObserver?: ResizeObserver;\n #mutationObserver?: MutationObserver;\n #scrollRaf = 0;\n /** Debounce handle for {@link snapToItem} — fires once scrolling settles. */\n #snapTimer = 0;\n #items: Element[] = [];\n #itemWrap: `stop` | `wrap` = `stop`;\n\n /** Items added mid-list that are still playing their enter animation. */\n #entering = new Set<Element>();\n /** Timer that ends the `[reflowing]` window opened by a mid-list insertion. */\n #reflowTimer = 0;\n\n /**\n * When cell geometry changes (zoom), the item nearest the viewport centre is\n * captured here in `willUpdate` and the scroll position is corrected in\n * `updated` so that item stays put — rather than the grid anchoring to its\n * top-left corner.\n */\n #zoomAnchor?: { index: number; lineFrac: number };\n\n /**\n * The active view over the items. Element mode projects light-DOM children\n * through named `<slot>`s (owned by {@link ElementGridListSource}); data mode\n * renders from {@link items} via {@link itemAdapter}. Everything else here\n * addresses items by effective index + key and never branches on the mode.\n *\n * Initialised eagerly (element mode) so the public getters — `count`,\n * `selectedKeys`, … — are safe to touch before the first Lit update. The\n * first `willUpdate` rebuilds it once the light DOM / `itemAdapter` is known.\n */\n #sourceElement: ElementGridListSource | undefined = new ElementGridListSource(this);\n #source: GridListSource = this.#sourceElement!;\n\n readonly selection: ListSelectionController<string> = new ListSelectionController<string>({\n getOrderedItems: () => this.#source.keys(),\n isSelectable: (k) => {\n const i = this.#source.indexOfKey(k);\n return i >= 0 && this.#source.isSelectable(i);\n },\n getModes: () => ({ selectionMode: this.selectionMode, interactionMode: this.interactionMode }),\n getKey: k => k,\n getGroupKey: k => (this.groupBy === null ? null : this.#source.groupKeyOfKey(k)),\n crossGroupSelection: () => this.crossGroupSelection,\n getFallbackGroupKey: (): string | null => {\n const k = this.tickled.tickledId;\n return k !== undefined && this.groupBy !== null ? this.#source.groupKeyOfKey(k) : null;\n },\n onChange: (selected, previous) => {\n this._syncItemStates();\n this.requestUpdate();\n this.#emitSelect(selected, previous);\n },\n });\n\n readonly tickled: TickledController<string> = new TickledController<string>(this, {\n // `keys()` is in effective order, so position === effective index — avoid a\n // per-key `indexOfKey` lookup (that would make this O(n²) for large lists).\n getItems: () =>\n this.#source.keys().map((k, i) => ({\n id: k,\n enabled: this.#source.isSelectable(i),\n })),\n onTickle: (k) => {\n // Stop the previous caption pan immediately so two labels never scroll\n // together during the re-render window; `updated()` starts the new one.\n this.#stopActiveCaptionPan();\n if (k !== undefined)\n this.#emitItemEvent(`list-tickle`, k);\n },\n onStateChange: () => this._syncItemStates(),\n itemWrap: this.#itemWrap,\n hoverDisabled: () => this.disableHoverTickle || this.#dragSelect.isDragging || this.#nativeDrag.isDragging,\n });\n\n /**\n * True while cell `pointerenter` tickling is suppressed by an active or\n * just-finished scroll gesture (`disable-scroll-hover-tickle`). While set,\n * the host carries `[data-scroll-hover-suppress]`, which gates the CSS\n * `:hover` highlight so the visual cursor does not churn either.\n */\n #scrollHoverSuppress = false;\n /** Last pointer position seen over the host; real movement ends suppression. */\n #lastPointerX = Number.NaN;\n #lastPointerY = Number.NaN;\n\n /** Live drag-select preview: covered keys + the surface-relative rect. */\n #marqueePreview: ReadonlySet<string> = new Set();\n #marqueeRect: DragSelectRect | undefined;\n\n /** Native item drag state: true while a drag is active. */\n #nativeDragging = false;\n /** Key of the cell that originated the native drag. */\n #dragOriginKey: string | undefined = undefined;\n /** Timer handle for post-drag click suppression. */\n #postDragSuppressTimer = 0;\n\n readonly #nativeDrag = new ListNativeDragController<T>(this, {\n source: `grid-list`,\n isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this.#source.count > 0,\n resolveEventToKey: (target) => {\n if (target instanceof Element) {\n const cell = target.closest?.(`.cell`) as HTMLElement | null;\n const key = cell?.dataset.key;\n if (key)\n return key;\n const keyed = (target.closest?.(`[data-key]`) as HTMLElement | null)?.dataset.key\n ?? (target as HTMLElement).dataset?.key\n ?? keyForElement(target);\n if (keyed)\n return keyed;\n }\n return undefined;\n },\n prepareSelection: originKey => this.#prepareNativeDrag(originKey),\n getMetrics: () => ({\n itemSize: this.itemSize,\n captionStyle: this.captionStyle,\n captionHeight: this.captionHeight,\n rowHeight: this.#rowHeight(),\n }),\n getRenderer: () => this.dragPreviewRenderer,\n getDragPreviewSourceResolver: () => this.dragPreviewSource,\n dispatch: detail => this._dispatch<ListNativeDragStartDetail<T>>(`list-native-drag-start`, detail, true),\n onActiveChange: (active, originKey) => {\n this.#nativeDragging = active;\n this.#dragOriginKey = active ? originKey : undefined;\n this.toggleAttribute(`data-native-dragging`, active);\n if (active) {\n const count = [...this.selection.selectedKeys].filter(k => !isSyntheticKey(k)).length;\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.#clearNativeDragState();\n this.#startPostDragSuppressTimer();\n },\n syncLightDomDraggable: () => {\n for (const child of this.children) {\n if (child instanceof HTMLElement)\n child.draggable = this.itemsDraggable;\n }\n },\n shouldStart: event =>\n !(this.marqueeFromCellBlank && this.#isCellBlankPress(event)),\n });\n\n /** Origin rule + display-ordered entry resolution for native drag-out (both modes). */\n #renderedCellForKey(key: string): HTMLElement | undefined {\n const selector = `.cell[data-key=\"${CSS.escape(key)}\"]`;\n return this.renderRoot.querySelector<HTMLElement>(selector) ?? undefined;\n }\n\n #prepareNativeDrag(originKey: string): { origin: ListDragEntry<T>; selected: Array<ListDragEntry<T>> } | undefined {\n const index = this.#source.indexOfKey(originKey);\n if (index < 0 || !this.#source.isSelectable(index))\n return undefined;\n if (!this.selection.selectedKeys.has(originKey))\n this.selection.replace(originKey);\n const ordered = this.#source.keys().filter(k => !isSyntheticKey(k) && this.selection.selectedKeys.has(k));\n const selected: Array<ListDragEntry<T>> = [];\n for (const key of ordered) {\n const entryIndex = this.#source.indexOfKey(key);\n if (entryIndex < 0)\n continue;\n const data = this.#source.resolveKeyToData(key) as T | undefined;\n const sourceElement = this.#source.resolveKeyToElement(key);\n // Data mode has no source element — expose the currently rendered\n // virtual cell (when present) as the synchronous presentation scope so\n // `dragPreviewSource` can reach adapter output (e.g. a consumer\n // custom-element host) without traversing shadow roots. Off-screen keys\n // have no cell and keep `element` undefined; starting a drag must not\n // expand the virtual window or render missing cells.\n const renderedElement = sourceElement\n ?? (this.#source instanceof DataGridListSource ? this.#renderedCellForKey(key) : undefined);\n const item = (data ?? sourceElement) as T | Element;\n if (item === undefined)\n continue;\n selected.push({\n key,\n index: entryIndex,\n item,\n ...(renderedElement ? { element: renderedElement } : {}),\n });\n }\n const origin = selected.find(entry => entry.key === originKey);\n if (!origin)\n return undefined;\n return { origin, selected };\n }\n\n /**\n * The single caption pan-text currently scrolling. At most one caption is\n * a pan-text in loop mode at a time — when tickle moves, the old one is\n * stopped before the new one starts (see `#activateTickledPan`).\n */\n #activeCaptionPan: PanTextElement | null = null;\n\n readonly #dragSelect = new ListDragSelectController<string>(this, {\n getSurface: () => this.#viewportRef.value,\n isEnabled: () =>\n this.selection.canDragSelect()\n && this.#source.count > 0\n && !this.hasAttribute(`disable-drag-select`),\n hitTest: rect => this.#marqueeHitTest(rect),\n getBaseSelection: () => this.selection.selected,\n onPreview: (preview, rect) => {\n this.#marqueePreview = preview;\n this.#marqueeRect = rect;\n this.requestUpdate();\n },\n onCommit: (finalSet) => {\n this.selection.applyDragSelection(finalSet);\n this.#marqueePreview = new Set();\n this.#marqueeRect = undefined;\n this.requestUpdate();\n },\n autoScroll: (dx, dy) => {\n const vp = this.#viewportRef.value;\n if (!vp)\n return;\n if (dx !== 0) {\n vp.scrollLeft += dx;\n this._scrollLeft = vp.scrollLeft;\n }\n if (dy !== 0) {\n vp.scrollTop += dy;\n this._scrollTop = vp.scrollTop;\n }\n },\n shouldStart: (event) => {\n if (this.marqueeFromCellBlank && this.#isCellBlankPress(event))\n return true;\n for (const node of event.composedPath()) {\n if (node instanceof Element && (node.classList.contains(`cell`) || node.classList.contains(`group-header`)))\n return false;\n }\n return true;\n },\n });\n\n /**\n * True when a pointer / drag event landed on a cell's blank well: the event\n * target is the cell's content container itself (`.content` / `.thumb`) — i.e.\n * nothing of the item's own content sat under the pointer. Relies on the\n * consumer setting `pointer-events: none` on the blank filler around its cell\n * content so that filler presses land on the well, not on the item element.\n */\n #isCellBlankPress(event: Event): boolean {\n for (const node of event.composedPath()) {\n if (!(node instanceof Element))\n continue;\n if (node.classList.contains(`caption`))\n return false;\n if (node.matches?.(`input,button,a,select,textarea,[contenteditable]`))\n return false;\n // Reached the well with nothing between it and the event target.\n if (node.classList.contains(`content`) || node.classList.contains(`thumb`))\n return true;\n if (node.classList.contains(`cell`))\n return false; // reached the cell without a well — be conservative\n // Any other element seen before the well is the item's own content\n // (glyph / thumbnail / caption text) — this press belongs to the item.\n return false;\n }\n return false;\n }\n\n /**\n * Map a surface-relative (viewport-visible) rect to covered item keys using\n * the same `computeGridWindow` geometry the renderer uses — pure arithmetic,\n * so virtualized off-screen items are covered without DOM measurement.\n */\n #marqueeHitTest(rect: DragSelectRect): string[] {\n const count = this.#source.count;\n if (count === 0)\n return [];\n const horizontal = this.orientation === `row`;\n const x0 = rect.x + this._scrollLeft;\n const x1 = x0 + rect.width;\n const y0 = horizontal ? 0 : rect.y + this._scrollTop;\n const y1 = horizontal ? 0 : y0 + rect.height;\n const out = this.#layout().hitTest(x0, x1, y0, y1);\n const keys: string[] = [];\n for (const index of out) {\n const key = this.#source.keyAt(index);\n if (!key || isSyntheticKey(key))\n continue;\n if (!this.#source.isSelectable(index))\n continue;\n keys.push(key);\n }\n return keys;\n }\n\n /**\n * Incremental search (navigate / select / filter). Element- or data-backed\n * depending on the mode; the mode-agnostic surface (`renderField`, `open`,\n * `close`, `setModes`, …) is the same either way. See `docs/infra-incremental.md`.\n */\n search!: ListSearchController<unknown>;\n\n #searchMode: `element` | `data` | undefined;\n #searchFilterKeys: ReadonlySet<string> | undefined;\n\n /** (Re)build {@link search} for the current mode; a no-op if it already matches. */\n #ensureSearch(): void {\n const mode = this.itemAdapter !== undefined ? `data` : `element`;\n if (this.#searchMode === mode && this.search !== undefined)\n return;\n\n const previous = this.search as ListSearchController<unknown> | undefined;\n if (previous) {\n previous.hostDisconnected();\n this.removeController(previous);\n }\n\n this.search = (mode === `data`\n ? new ListSearchController<DataListSearchItem>(this, {\n adapter: createDataListSearchAdapter(this, {\n rawCount: () => this.#source?.rawCount ?? 0,\n rawKeyAt: i => this.#source?.rawKeyAt(i) ?? ``,\n rawSearchTextAt: i => this.#source?.rawSearchTextAt(i) ?? ``,\n onFilterChange: (keys) => {\n this.#searchFilterKeys = keys;\n this.#source?.setFilters({ searchKeys: keys });\n this.requestUpdate();\n void this.updateComplete.then(() => this.#emitViewportChange());\n },\n onActivate: key => this.#onCellActivate(key),\n getHighlightRoot: () => this.renderRoot as ShadowRoot | Element,\n }),\n })\n : new ListSearchController<Element>(this, {\n adapter: createElementListSearchAdapter(this, {\n itemSelector: ITEM_SELECTOR,\n getLabel: el =>\n el.getAttribute(`data-label`)\n ?? el.querySelector(`[data-grid-list-caption]`)?.textContent?.trim()\n ?? el.getAttribute(`data-search-label`)\n ?? el.textContent?.trim()\n ?? ``,\n highlightKey: `grid-list-search`,\n }),\n })) as ListSearchController<unknown>;\n this.#searchMode = mode;\n }\n\n #searchRegistry: CommandRegistry<unknown> | undefined;\n #unregisterSearchCommands: (() => void) | undefined;\n\n /** Command registry carrying this grid's `list.search.*` commands. */\n get registry(): CommandRegistry<unknown> | undefined {\n return this.#searchRegistry;\n }\n\n /** Effective search modes: this component's capability (all three) ∩ the `search-modes` attribute. */\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 || !this.search)\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 }\n if (!this.hasAttribute(`role`)) {\n this.setAttribute(`role`, `listbox`);\n }\n this.#syncAriaMultiselectable();\n // Reflect caption defaults up-front so the `:host([caption-*])` style rules\n // apply even when the consumer never sets the attributes.\n for (const [attr, value] of [\n [`caption-style`, this.captionStyle],\n [`caption-align`, this.captionAlign],\n [`caption-position`, this.captionPosition],\n [`caption-backdrop`, this.captionBackdrop],\n ] as const) {\n if (!this.hasAttribute(attr)) {\n this.setAttribute(attr, value);\n }\n }\n this.addEventListener(`keydown`, this._onKeyDown as EventListener);\n this.addEventListener(`pointermove`, this.#onHostPointerMove as EventListener, { passive: true });\n this.addEventListener(`pointerleave`, this.#onHostPointerLeave as EventListener);\n this.#mutationObserver ??= new MutationObserver(records => this.#onChildrenChanged(records));\n this.#mutationObserver.observe(this, { childList: true, attributeFilter: [`hidden`] });\n this.#searchRegistry ??= createCommandRegistry();\n this.#ensureSearch();\n this.#syncSearchCommands();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#stopActiveCaptionPan();\n this.removeEventListener(`keydown`, this._onKeyDown as EventListener);\n this.removeEventListener(`pointermove`, this.#onHostPointerMove as EventListener);\n this.removeEventListener(`pointerleave`, this.#onHostPointerLeave as EventListener);\n this.#endScrollHoverSuppress();\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n this.#mutationObserver?.disconnect();\n this.#cancelScrollRaf();\n this.#cancelSnapTimer();\n this.#unregisterSearchCommands?.();\n this.#unregisterSearchCommands = undefined;\n this.#searchRegistry = undefined;\n if (this.#reflowTimer) {\n clearTimeout(this.#reflowTimer);\n this.#reflowTimer = 0;\n }\n if (this.#nativeDragging || this.#nativeDrag.isDragging) {\n this.#clearNativeDragState();\n }\n }\n\n #onChildrenChanged(records?: MutationRecord[]): void {\n const previousLength = this.#items.length;\n this.#syncItems();\n // Prune selection / cursor for elements that were actually removed. Read the\n // records directly rather than diffing `keys()` before/after: a pending\n // `requestUpdate()` can let `updated()` re-sync the source before this\n // callback runs, which would hide the removal from a diff.\n const removedKeys: string[] = [];\n for (const record of records ?? []) {\n for (const node of record.removedNodes) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n continue;\n const key = keyForElement(node as Element);\n if (key !== undefined)\n removedKeys.push(key);\n }\n }\n if (removedKeys.length > 0) {\n const present = new Set(this.#source.keys());\n const gone = removedKeys.filter(k => !present.has(k));\n if (gone.length > 0)\n this.selection.removeKeys(gone, k => k);\n const tickledId = this.tickled.tickledId;\n if (tickledId && gone.includes(tickledId))\n this.tickled.focus(undefined);\n }\n this._syncItemStates();\n this.#noteChildMutation(previousLength, records);\n this.requestUpdate();\n void this.updateComplete.then(() => this.#emitViewportChange());\n }\n\n /**\n * When the child list changes mid-list — not a first populate or a wholesale\n * replace — mark any newcomers for an enter animation and open a short\n * `[reflowing]` window so the cells that shift slide to their new position\n * instead of snapping. Removals get the same window (the survivors slide to\n * close the gap). The window is bounded in time so the transform transition\n * never bleeds into scroll virtualisation.\n *\n * Reads the `MutationRecord`s directly rather than diffing `#items`, because a\n * `requestUpdate()` between the DOM change and this callback (e.g. a caller\n * that clears the selection before removing) lets `updated()` re-sync `#items`\n * first, which would hide the change from a naive diff.\n */\n #noteChildMutation(previousLength: number, records?: MutationRecord[]): void {\n if (!this.hasUpdated || !records || records.length === 0)\n return;\n const currentSet = new Set(this.#items);\n const added: Element[] = [];\n let removedCount = 0;\n for (const record of records) {\n for (const node of record.addedNodes) {\n if (node.nodeType === Node.ELEMENT_NODE && currentSet.has(node as Element))\n added.push(node as Element);\n }\n for (const node of record.removedNodes) {\n if (node.nodeType === Node.ELEMENT_NODE)\n removedCount++;\n }\n }\n // Nothing to animate, a first populate, or a wholesale replace (every\n // current item is new) — leave it alone.\n if (added.length === 0 && removedCount === 0)\n return;\n if (previousLength === 0 && removedCount === 0)\n return;\n if (added.length > 0 && added.length === this.#items.length)\n return;\n for (const el of added)\n this.#entering.add(el);\n this.#openReflowWindow();\n }\n\n /** Open (or extend) the `[reflowing]` window so moved cells and headers slide. */\n #openReflowWindow(): void {\n this.toggleAttribute(`reflowing`, true);\n if (this.#reflowTimer)\n clearTimeout(this.#reflowTimer);\n this.#reflowTimer = window.setTimeout(() => {\n this.#reflowTimer = 0;\n this.#entering.clear();\n this.toggleAttribute(`reflowing`, false);\n this.requestUpdate();\n }, REFLOW_WINDOW_MS);\n }\n\n /** Key sets as of the last `grid-list-viewport-change` dispatch, for dedupe. */\n #lastViewportRenderedKeys: readonly string[] | undefined;\n #lastViewportVisibleKeys: readonly string[] | undefined;\n\n /**\n * Dispatch `grid-list-viewport-change` with the current key sets — unless\n * neither set changed since the last dispatch, so coalesced frames and\n * no-op scrolls stay silent.\n */\n #emitViewportChange(): void {\n const renderedKeys = this.renderedKeys();\n const visibleKeys = this.visibleKeys();\n if (sameKeys(this.#lastViewportRenderedKeys, renderedKeys) && sameKeys(this.#lastViewportVisibleKeys, visibleKeys))\n return;\n this.#lastViewportRenderedKeys = renderedKeys;\n this.#lastViewportVisibleKeys = visibleKeys;\n this._dispatch<GridListViewportChangeDetail>(`grid-list-viewport-change`, {\n renderedKeys,\n visibleKeys,\n });\n }\n\n protected override firstUpdated(): void {\n if (!this.#source)\n this.#rebuildSource();\n const el = this.#viewportRef.value;\n if (!el)\n return;\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const w = entry.contentRect.width;\n const h = entry.contentRect.height;\n // A zero-sized observation (e.g. an inactive dock tab) must never\n // replace the last usable geometry — see #measureViewport / refreshLayout.\n if (w <= 0 || h <= 0)\n return;\n this._viewportWidth = w;\n this._viewportHeight = h;\n }\n });\n this.#resizeObserver.observe(el);\n this.#measureViewport(false);\n this.#syncItems();\n this.requestUpdate();\n this.#nativeDrag.refreshDraggable();\n }\n\n /** (Re)construct {@link #source} for the current mode and re-apply the filters. */\n #rebuildSource(): void {\n if (this.itemAdapter !== undefined) {\n this.#source = new DataGridListSource<T>(this.items, this.itemAdapter);\n this.#sourceElement = undefined;\n } else {\n this.#sourceElement = new ElementGridListSource(this);\n this.#source = this.#sourceElement;\n }\n this.#source.setGrouping(this.#groupingConfig());\n this.#applyFilters();\n if (this.#searchFilterKeys)\n this.#source.setFilters({ searchKeys: this.#searchFilterKeys });\n }\n\n /** Push the current filter predicate into whichever source is active. */\n #applyFilters(): void {\n if (this.#source instanceof ElementGridListSource) {\n const fp = this.filterPredicate;\n const src = this.#source;\n src.setFilters({ predicate: fp ? i => fp(src.rawElementAt(i)!) : undefined });\n this.#items = src.effectiveElements();\n } else if (this.#source instanceof DataGridListSource) {\n const ip = this.itemFilterPredicate;\n const src = this.#source as DataGridListSource<T>;\n src.setFilters({ predicate: ip ? i => ip(src.rawItemAt(i) as T, i) : undefined });\n }\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n if (changed.has(`searchModes`)) {\n this.#syncSearchCommands();\n }\n if (changed.has(`filterPredicate`) || changed.has(`itemFilterPredicate`)) {\n this.#applyFilters();\n void this.updateComplete.then(() => this.#emitViewportChange());\n }\n\n const dataModeChanged = changed.has(`items`) || changed.has(`itemAdapter`);\n if (dataModeChanged) {\n this.#zoomAnchor = undefined;\n const prevKeys = this.#source?.keys() ?? [];\n const modeFlipped = (this.itemAdapter !== undefined)\n !== (this.#source instanceof DataGridListSource);\n this.#rebuildSource();\n const nextKeys = this.#source.keys();\n const nextKeySet = new Set(nextKeys);\n const removedKeys = prevKeys.filter(k => !nextKeySet.has(k));\n if (removedKeys.length > 0)\n this.selection.removeKeys(removedKeys, k => k);\n const tickledId = this.tickled.tickledId;\n if (tickledId && !nextKeySet.has(tickledId))\n this.tickled.focus(undefined);\n this._syncItemStates();\n // No requestUpdate() here — we're already in willUpdate, the render that\n // follows picks up the rebuilt source.\n void this.updateComplete.then(() => this.#emitViewportChange());\n if (modeFlipped) {\n this.#ensureSearch();\n this.#syncSearchCommands();\n }\n this.search?.refresh();\n }\n\n const groupsChanged = changed.has(`groupBy`) || changed.has(`groupLabel`)\n || (changed as Map<PropertyKey, unknown>).has(`_collapsedGroups`);\n if (groupsChanged && this.hasUpdated) {\n if (changed.has(`groupBy`)) {\n if (this._collapsedGroups.size > 0)\n this._collapsedGroups = new Set();\n this.#groupByChanged = true;\n }\n this.#applyGroupingToSource();\n this.#dropUnreachableCursor();\n this.#openReflowWindow();\n void this.updateComplete.then(() => this.#emitViewportChange());\n } else if (groupsChanged) {\n this.#applyGroupingToSource();\n }\n\n if (changed.has(`itemSize`) || changed.has(`gap`)) {\n this.itemSize = Math.max(MIN_ITEM_SIZE, Math.round(this.itemSize));\n this.gap = Math.max(0, Math.round(this.gap));\n }\n if (changed.has(`captionHeight`)) {\n this.captionHeight = Math.max(0, Math.round(this.captionHeight));\n }\n if (changed.has(`itemWrap`)) {\n this.#itemWrap = this.itemWrap;\n }\n\n const geometryChanged = changed.has(`itemSize`) || changed.has(`gap`)\n || changed.has(`captionStyle`) || changed.has(`captionHeight`)\n || changed.has(`orientation`);\n if (geometryChanged && this.hasUpdated && this.#source.count > 0) {\n const prevOrientation = (changed.get(`orientation`) as GridListOrientation | undefined) ?? this.orientation;\n const horizontal = prevOrientation === `row`;\n const prevOffset = horizontal ? this._scrollLeft : this._scrollTop;\n const prevExtent = horizontal ? this._viewportWidth : this._viewportHeight;\n if (prevExtent > 0 && prevOffset > 1) {\n const prevItemSize = (changed.get(`itemSize`) as number | undefined) ?? this.itemSize;\n const prevGap = (changed.get(`gap`) as number | undefined) ?? this.gap;\n const prevCaptionStyle = (changed.get(`captionStyle`) as GridListCaptionStyle | undefined) ?? this.captionStyle;\n const prevCaptionHeight = (changed.get(`captionHeight`) as number | undefined) ?? this.captionHeight;\n this.#captureCentreAnchor(prevOffset, prevExtent, prevItemSize, prevGap, prevCaptionStyle, prevCaptionHeight, prevOrientation);\n }\n }\n }\n\n // --- Grouping ---\n\n #groupByChanged = false;\n\n /** Grouping config for the active source, or `undefined` when ungrouped. */\n #groupingConfig(): GridListGrouping | undefined {\n const by = this.groupBy;\n if (by === null || by === undefined || by === ``)\n return undefined;\n const collapsed = this._collapsedGroups;\n const src = this.#source;\n if (src instanceof DataGridListSource) {\n return {\n groupKeyOf: raw => resolveGroupKey(by, src.rawItemAt(raw) as T, raw, readProperty),\n itemAt: raw => src.rawItemAt(raw),\n labelOf: this.groupLabel,\n collapsed,\n };\n }\n const elements = src as ElementGridListSource;\n return {\n groupKeyOf: raw => resolveGroupKey(by as ListGroupBy<Element>, elements.rawElementAt(raw)!, raw, readAttribute),\n itemAt: raw => elements.rawElementAt(raw),\n labelOf: this.groupLabel,\n collapsed,\n };\n }\n\n /** Push the current grouping into the source and refresh the element-mode item cache. */\n #applyGroupingToSource(): void {\n this.#source.setGrouping(this.#groupingConfig());\n if (this.#source instanceof ElementGridListSource)\n this.#items = this.#source.effectiveElements();\n }\n\n /** The cursor can't stay on an item that a collapsed group just removed. */\n #dropUnreachableCursor(): void {\n const id = this.tickled.tickledId;\n if (id !== undefined && this.#source.indexOfKey(id) < 0)\n this.tickled.focus(undefined);\n }\n\n /** Groups in display order (empty when ungrouped). */\n get groups(): readonly ListGroupInfo[] {\n return this.groupBy === null ? [] : this.#source.groups();\n }\n\n /** Collapse or expand one group. Fires `list-group-toggle` when the state changes. */\n setGroupCollapsed(groupKey: string, collapsed: boolean): void {\n if (this._collapsedGroups.has(groupKey) === collapsed)\n return;\n const next = new Set(this._collapsedGroups);\n if (collapsed)\n next.add(groupKey);\n else\n next.delete(groupKey);\n this._collapsedGroups = next;\n this._dispatch<ListGroupToggleDetail>(`list-group-toggle`, { groupKey, collapsed });\n }\n\n toggleGroup(groupKey: string): void {\n this.setGroupCollapsed(groupKey, !this._collapsedGroups.has(groupKey));\n }\n\n collapseAllGroups(): void {\n for (const g of this.groups)\n this.setGroupCollapsed(g.key, true);\n }\n\n expandAllGroups(): void {\n for (const key of [...this._collapsedGroups])\n this.setGroupCollapsed(key, false);\n }\n\n #syncAriaMultiselectable(): void {\n this.setAttribute(\n `aria-multiselectable`,\n this.selection.canSelectMultiple() ? `true` : `false`,\n );\n }\n\n /** Full cell height: the square, plus a caption band in `separate` / `under`. */\n #rowHeight(): number {\n const captionBand = this.captionStyle === `separate` || this.captionStyle === `under`;\n return this.itemSize + (captionBand ? this.captionHeight : 0);\n }\n\n #captionFor(el: Element): string {\n return (\n el.getAttribute(`data-label`)\n ?? el.querySelector(`[data-grid-list-caption]`)?.textContent?.trim()\n ?? ``\n );\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n super.updated(changed);\n this.#syncItems();\n if (changed.has(`selectionMode`) || changed.has(`interactionMode`)) {\n this.selection.clearAnchor();\n this.#syncAriaMultiselectable();\n }\n if (changed.has(`disableScrollHoverTickle`) && !this.disableScrollHoverTickle) {\n this.#endScrollHoverSuppress();\n }\n if (changed.has(`itemsDraggable`)) {\n this.#nativeDrag.refreshDraggable();\n }\n if (changed.has(`orientation`)) {\n // Reset the axis that's no longer scrollable so a later switch back\n // doesn't inherit a stale offset.\n const vp = this.#viewportRef.value;\n if (vp) {\n if (this.orientation === `row`) {\n vp.scrollTop = 0;\n this._scrollTop = 0;\n } else {\n vp.scrollLeft = 0;\n this._scrollLeft = 0;\n }\n }\n }\n const vp = this.#viewportRef.value;\n if (vp) {\n if (Math.abs(vp.scrollTop - this._scrollTop) > 0.5) {\n vp.scrollTop = this._scrollTop;\n }\n if (Math.abs(vp.scrollLeft - this._scrollLeft) > 0.5) {\n vp.scrollLeft = this._scrollLeft;\n }\n }\n this.#applyZoomAnchor();\n this.#activateTickledPan();\n if (this.#groupByChanged) {\n this.#groupByChanged = false;\n this._dispatch<ListGroupChangeDetail>(`list-group-change`, { groupBy: this.groupBy as ListGroupBy<unknown> | null });\n }\n }\n\n /** Re-anchor the scroll so the item captured in `willUpdate` stays centred. */\n #applyZoomAnchor(): void {\n if (!this.#zoomAnchor)\n return;\n const { index, lineFrac } = this.#zoomAnchor;\n this.#zoomAnchor = undefined;\n\n const vp = this.#viewportRef.value;\n if (!vp)\n return;\n const layout = this.#layout();\n const horizontal = layout.horizontal;\n const extent = horizontal ? this._viewportWidth : this._viewportHeight;\n if (extent <= 0)\n return;\n const targetCenter = layout.offsetOfAnchor(index, lineFrac);\n const maxScroll = Math.max(0, layout.totalExtent - extent);\n const next = Math.min(maxScroll, Math.max(0, targetCenter - extent / 2));\n if (horizontal) {\n if (Math.abs(vp.scrollLeft - next) > 0.5) {\n vp.scrollLeft = next;\n this._scrollLeft = next;\n }\n } else if (Math.abs(vp.scrollTop - next) > 0.5) {\n vp.scrollTop = next;\n this._scrollTop = next;\n }\n }\n\n #captureCentreAnchor(prevOffset: number, prevExtent: number, prevItemSize: number, prevGap: number, prevCaptionStyle: GridListCaptionStyle, prevCaptionHeight: number, prevOrientation: GridListOrientation): void {\n const count = this.#source?.count ?? 0;\n if (count === 0)\n return;\n const prevBand = prevCaptionStyle === `separate` || prevCaptionStyle === `under`;\n const prevRowHeight = prevItemSize + (prevBand ? prevCaptionHeight : 0);\n const prev = this.#buildLayout({\n itemWidth: prevItemSize,\n rowHeight: prevRowHeight,\n gap: prevGap,\n orientation: prevOrientation,\n });\n this.#zoomAnchor = prev.anchorAt(prevOffset + prevExtent / 2);\n }\n\n /**\n * Re-read the viewport after an ancestor's visibility/layout changed.\n * Safe while hidden (zero-sized reads are ignored); forces a repaint of the\n * virtual window even when the size is unchanged.\n */\n refreshLayout(): void {\n this.#measureViewport(true);\n }\n\n /** Alias of {@link refreshLayout}. */\n remeasure(): void {\n this.#measureViewport(true);\n }\n\n #measureViewport(forceRender = false): void {\n const vp = this.#viewportRef.value;\n if (!vp)\n return;\n const w = vp.clientWidth;\n const h = vp.clientHeight;\n if (w <= 0 || h <= 0)\n return;\n const horizontal = this.orientation === `row`;\n const changed = w !== this._viewportWidth || h !== this._viewportHeight;\n if (changed) {\n const prevOffset = horizontal ? this._scrollLeft : this._scrollTop;\n const prevExtent = horizontal ? w : h;\n this.#captureCentreAnchor(\n prevOffset,\n prevExtent,\n this.itemSize,\n this.gap,\n this.captionStyle,\n this.captionHeight,\n this.orientation,\n );\n this._viewportWidth = w;\n this._viewportHeight = h;\n }\n if (forceRender && !changed) {\n this.#captureCentreAnchor(\n horizontal ? this._scrollLeft : this._scrollTop,\n horizontal ? w : h,\n this.itemSize,\n this.gap,\n this.captionStyle,\n this.captionHeight,\n this.orientation,\n );\n this.requestUpdate();\n }\n if (changed || forceRender) {\n void this.updateComplete.then(() => this.#emitViewportChange());\n }\n }\n\n /**\n * Element mode only: re-read the light DOM into the source and refresh the\n * `#items` cache + filter. A no-op in data mode (the source is rebuilt through\n * `#rebuildSource` when `items` / `itemAdapter` change).\n */\n #syncItems(): void {\n if (this.#source instanceof ElementGridListSource) {\n this.#source.refresh();\n this.#applyFilters();\n }\n }\n\n get count(): number {\n return this.#source.count;\n }\n\n /**\n * Number of cells currently rendered in the shadow DOM. With virtualization\n * this is roughly the visible rows plus overscan, regardless of how large\n * `count` is — useful for demos/diagnostics.\n */\n get renderedCount(): number {\n return this.renderRoot.querySelectorAll(`.cell`).length;\n }\n\n get selectedItems(): ReadonlySet<Element> {\n const els = new Set<Element>();\n for (const key of this.selection.selectedKeys) {\n const el = this.#source.resolveKeyToElement(key);\n if (el)\n els.add(el);\n }\n return els;\n }\n\n /**\n * The selection as stable `data-key` / `data-value` strings. Auto-assigned\n * keys for keyless light-DOM items are omitted (they are not a stable contract\n * for the consumer).\n */\n get selectedKeys(): ReadonlySet<string> {\n const out = new Set<string>();\n for (const k of this.selection.selectedKeys) {\n if (!isSyntheticKey(k))\n out.add(k);\n }\n return out;\n }\n\n select(item: Element): void {\n const key = keyForElement(item);\n if (key)\n this.selection.replace(key);\n }\n\n selectMany(items: Iterable<Element>): void {\n const keys: string[] = [];\n for (const item of items) {\n const key = keyForElement(item);\n if (key)\n keys.push(key);\n }\n this.selection.selectMany(keys);\n }\n\n deselect(item: Element): void {\n const key = keyForElement(item);\n if (key)\n this.selection.deselect(key);\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\n /**\n * Replace the selection with the items carrying these keys. Unknown keys are\n * ignored; survives the host rebuilding the item set. Requires each item to\n * have a `data-key` (or `data-value`).\n */\n selectKeys(keys: Iterable<string>): void {\n this.selection.selectKeys(keys, k => k);\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, k => k);\n }\n\n /** Remove items by key from the selection. */\n removeSelectedKeys(keys: Iterable<string>): void {\n this.selection.removeKeys(keys, k => k);\n }\n\n /**\n * Data mode only: raw index of `key` in `this.items`, or `-1`. Data-mode keys\n * come straight from the adapter, so this is exact even under a filter/search.\n */\n #rawIndexOfKey(key: string): number {\n const adapter = this.itemAdapter;\n if (!adapter)\n return -1;\n return this.items.findIndex((it, i) => adapter.key(it, i) === key);\n }\n\n /**\n * Data mode: replace the whole item array. Selection and cursor keep any key\n * that is still present; keys that vanish are dropped (one `list-select`).\n * A no-op in element mode.\n */\n setItems(items: readonly T[]): void {\n if (this.itemAdapter)\n this.items = items;\n }\n\n /**\n * Data mode: append items to the end. Scroll position, selection and cursor\n * are untouched; appended items don't play the mid-list `[reflowing]` slide.\n * A no-op in element mode.\n */\n appendItems(items: readonly T[]): void {\n if (this.itemAdapter && items.length > 0)\n this.items = [...this.items, ...items];\n }\n\n /**\n * Data mode: replace the item carrying `key`. A visible cell re-renders in\n * place (the keyed subtree is kept); an offscreen item shows its new content\n * when scrolled into view. Scroll and selection are untouched. Unknown keys\n * are ignored.\n */\n updateItem(key: string, item: T): void {\n if (!this.itemAdapter)\n return;\n const idx = this.#rawIndexOfKey(key);\n if (idx < 0)\n return;\n const next = [...this.items];\n next[idx] = item;\n this.items = next;\n }\n\n /**\n * Data mode: remove the items carrying these keys. Removed keys are dropped\n * from selection and cursor (via the `items` change). A no-op in element mode.\n */\n removeItems(keys: Iterable<string>): void {\n if (!this.itemAdapter)\n return;\n const adapter = this.itemAdapter;\n const keySet = new Set(keys);\n this.items = this.items.filter((it, i) => !keySet.has(adapter.key(it, i)));\n }\n\n /**\n * Data mode: drop every item. Selection and cursor are reset and one\n * `list-select` with empty sets is emitted. A no-op in element mode.\n */\n clearItems(): void {\n if (!this.itemAdapter)\n return;\n this.selection.reset();\n this.tickled.focus(undefined);\n this.items = [];\n this.#emitSelect(new Set(), new Set());\n }\n\n /** Move the cursor to the item with this key and scroll it into view. */\n focusKey(key: string): void {\n const index = this.#source.indexOfKey(key);\n if (index < 0)\n return;\n this.tickled.focus(key);\n this.#scrollItemIntoView(key);\n }\n\n /** The key of the item under the cursor, or `undefined`. */\n get tickledKey(): string | undefined {\n return this.tickled.tickledId;\n }\n\n /** Element mode: the light-DOM element carrying `key`, or `undefined`. */\n getItem(key: string): Element | undefined {\n return this.#source.resolveKeyToElement(key);\n }\n\n /** Element mode: the light-DOM element at effective index `index`. */\n getItemByIndex(index: number): Element | undefined {\n return this.#items[index];\n }\n\n /** Data mode: the data value carrying `key`, or `undefined`. */\n getData(key: string): T | undefined {\n return this.#source.resolveKeyToData(key) as T | undefined;\n }\n\n getKey(item: Element): string | undefined {\n return keyForElement(item);\n }\n\n /**\n * Keys of items in the rendered window (viewport + overscan) — the priority\n * set for prefetching. Use {@link visibleKeys} for the strict viewport\n * intersection. Auto-assigned keyless-item keys are omitted.\n */\n renderedKeys(): string[] {\n return this.#windowKeys(this.#currentWindow());\n }\n\n /**\n * Keys of items actually intersecting the viewport (no overscan).\n * Auto-assigned keyless-item keys are omitted.\n */\n visibleKeys(): string[] {\n return this.#windowKeys(this.#currentWindow(true));\n }\n\n #windowKeys(win: GridWindow): string[] {\n const keys = this.#source.keys();\n const out: string[] = [];\n for (const [start, end] of win.ranges) {\n for (let i = start; i < end; i++) {\n if (!isSyntheticKey(keys[i]))\n out.push(keys[i]);\n }\n }\n return out;\n }\n\n /** Layout params for the current geometry, with optional overrides (used for zoom anchoring). */\n #layoutParams(over: Partial<LayoutParams> = {}): LayoutParams {\n return {\n count: this.#source.count,\n groups: this.groupBy === null ? undefined : this.#source.groups(),\n itemWidth: this.itemSize,\n rowHeight: this.#rowHeight(),\n gap: this.gap,\n viewportWidth: this._viewportWidth,\n viewportHeight: this._viewportHeight,\n orientation: this.orientation,\n headerHeight: this.groupHeaderHeight,\n headerWidth: this.groupHeaderWidth,\n ...over,\n };\n }\n\n #buildLayout(over: Partial<LayoutParams> = {}): GridLayout {\n return buildLayout(this.#layoutParams(over));\n }\n\n #layoutCache: { params: LayoutParams; layout: GridLayout } | undefined;\n\n /** The current layout, rebuilt only when its inputs change (never per scroll). */\n #layout(): GridLayout {\n const params = this.#layoutParams();\n const cached = this.#layoutCache;\n if (cached) {\n const a = cached.params;\n let same = a.groups === params.groups;\n for (const k of Object.keys(params) as Array<keyof LayoutParams>) {\n if (!same)\n break;\n same = a[k] === params[k];\n }\n if (same)\n return cached.layout;\n }\n const layout = buildLayout(params);\n this.#layoutCache = { params, layout };\n return layout;\n }\n\n #currentWindow(noOverscan = false): GridWindow {\n return this.#layout().window(\n this.orientation === `row` ? this._scrollLeft : this._scrollTop,\n noOverscan ? 0 : 2,\n );\n }\n\n /** Adjust the scroll offset so `key` is fully within the viewport. */\n #scrollItemIntoView(key: string): void {\n const index = this.#source.indexOfKey(key);\n const vp = this.#viewportRef.value;\n if (index < 0 || !vp)\n return;\n const [start, end] = this.#layout().extentOf(index);\n\n if (this.orientation === `row`) {\n const viewLeft = vp.scrollLeft;\n let next = viewLeft;\n if (start < viewLeft)\n next = start;\n else if (end > viewLeft + this._viewportWidth)\n next = end - this._viewportWidth;\n if (next !== viewLeft) {\n vp.scrollLeft = next;\n this._scrollLeft = next;\n }\n return;\n }\n\n const viewTop = vp.scrollTop;\n let next = viewTop;\n if (start < viewTop)\n next = start;\n else if (end > viewTop + this._viewportHeight)\n next = end - this._viewportHeight;\n if (next !== viewTop) {\n vp.scrollTop = next;\n this._scrollTop = next;\n }\n }\n\n private _syncItemStates(): void {\n const selected = this.selection.selectedKeys;\n for (const el of this.#items) {\n const key = keyForElement(el);\n el.toggleAttribute(`data-tickled`, key !== undefined && this.tickled.isTickled(key));\n el.toggleAttribute(`data-selected`, key !== undefined && selected.has(key));\n }\n this.setAttribute(`data-input-mode`, this.tickled.inputMode);\n }\n\n #emitSelect(selected: ReadonlySet<string>, previous: ReadonlySet<string>): void {\n const selectedEls = new Set<Element>();\n const previousEls = new Set<Element>();\n for (const key of selected) {\n const el = this.#source.resolveKeyToElement(key);\n if (el)\n selectedEls.add(el);\n }\n for (const key of previous) {\n const el = this.#source.resolveKeyToElement(key);\n if (el)\n previousEls.add(el);\n }\n this._dispatch<GridListSelectDetail>(`list-select`, {\n selected: selectedEls,\n previous: previousEls,\n selectedKeys: this.selectedKeys,\n previousKeys: new Set([...previous].filter(k => !isSyntheticKey(k))),\n });\n }\n\n #emitItemEvent(name: `list-tickle` | `list-item-click` | `list-activate`, key: string): void {\n const index = this.#source.indexOfKey(key);\n const element = this.#source.resolveKeyToElement(key);\n const item = element ?? this.#source.resolveKeyToData(key);\n this._dispatch<GridListItemClickDetail>(name, { item, key, index, element });\n }\n\n private _dispatch<T>(name: string, detail: T, cancelable = false): boolean {\n return this.dispatchEvent(\n new CustomEvent<T>(name, {\n detail,\n bubbles: true,\n composed: true,\n cancelable,\n }),\n );\n }\n\n /** Selected keys, snapshotted once per render so the cell renderers don't each rebuild the set. */\n #selectedSnapshot: ReadonlySet<string> = new Set();\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 protected override render(): ReturnType<typeof html> {\n const win = this.#currentWindow();\n this.#selectedSnapshot = this.selection.selectedKeys;\n const spacerStyle = win.horizontal\n ? `width:${win.totalWidth}px;height:100%`\n : `height:${win.totalHeight}px`;\n // Fade the edge that can still be scrolled towards (see ../styles/scroll-fade.ts).\n const scrollFade = win.horizontal ? `scroll-fade-x` : `scroll-fade-y`;\n return html`\n <div\n class=\"viewport ${scrollFade}\"\n part=\"viewport\"\n ${ref(this.#viewportRef)}\n data-input-mode=${this.tickled.inputMode}\n @scroll=${this.#onScroll}\n @wheel=${this.#onWheel}\n @click=${this.#onViewportClick}\n >\n <div class=\"spacer\" style=${spacerStyle}>\n ${this.#source instanceof DataGridListSource\n ? this.#renderDataCells(win)\n : this.#renderElementCells(win)}\n ${this.#renderHeaders(win)}\n </div>\n ${this.#marqueeRect\n ? html`<div class=\"marquee\" part=\"marquee\" style=${this.#marqueeStyle(this.#marqueeRect)}></div>`\n : ``}\n </div>\n ${this.search?.renderField()}\n `;\n }\n\n #renderDataCells(win: GridWindow): ReturnType<typeof html> {\n const slice = win.ranges.flatMap(([start, end]) => Array.from({ length: end - start }, (_, i) => start + i));\n return repeat(\n slice,\n index => this.#source.keyAt(index),\n index => this.#renderDataCell(index, win),\n ) as ReturnType<typeof html>;\n }\n\n #renderDataCell(index: number, win: GridWindow): ReturnType<typeof html> {\n const key = this.#source.keyAt(index);\n const selected = this.#selectedSnapshot.has(key);\n const marquee = this.#marqueePreview.has(key);\n const tickled = this.tickled.isTickled(key);\n const selectable = this.#source.isSelectable(index);\n const draggable = this.itemsDraggable && selectable;\n const style = this.captionStyle;\n const separate = style === `separate`;\n const caption = style === `hidden` ? `` : this.#source.labelAt(index);\n const showCaption = caption !== ``;\n const cellHeight = win.rowStride - this.gap;\n const { x, y } = this.#layout().positionOf(index);\n const captionCss = separate\n ? `height:${Math.max(0, this.captionHeight - 4)}px`\n : style === `under`\n ? `height:${this.captionHeight}px`\n : ``;\n const rawIcon = this.#source.iconAt(index);\n const icon = appearanceAbsent(rawIcon) ? undefined : rawIcon;\n return html`\n <div\n class=\"cell${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}${marquee ? ` marquee` : ``}${this.#nativeDragging && key === this.#dragOriginKey ? ` dragging-origin` : ``}\"\n part=\"item${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}\"\n role=\"option\"\n aria-selected=${selected ? `true` : `false`}\n style=\"width:${this.itemSize}px;height:${cellHeight}px;transform:translate(${x}px,${y}px)\"\n data-index=${index}\n data-key=${key}\n draggable=${draggable ? `true` : `false`}\n ?data-selected=${selected}\n ?data-tickled=${tickled}\n ?data-marquee=${marquee}\n @click=${(e: MouseEvent) => this.#onCellClick(e, key)}\n @dblclick=${() => this.#onCellActivate(key)}\n @pointerenter=${() => this.#handleCellPointerEnter(key)}\n >\n <div class=\"content${icon === undefined ? `` : ` has-icon`}\" part=\"content\">\n ${icon === undefined\n ? nothing\n : html`<span class=\"cell-icon\" part=\"icon\" style=${this.#colorStyle(this.#source.iconColorAt(index))}>${icon}</span>`}\n ${this.#source.renderCellContent(index)}\n </div>\n ${showCaption ? this.#renderCaption(caption, captionCss, tickled, this.#source.badgeAt(index), this.#source.textColorAt(index)) : ``}\n </div>\n `;\n }\n\n /**\n * A tickled cell swaps its plain label for an `ixfx-pan-text` in loop mode\n * so a truncated label scrolls instead of staying an ellipsis. Unticked\n * cells keep the cheap plain-text caption.\n *\n * With no `badge` and no `textColor` the DOM is exactly as it was — the\n * flex row (and its extra `<span>` around the text) only appears when a\n * badge needs to sit inline ahead of the name.\n */\n #renderCaption(caption: string, captionCss: string, tickled: boolean, badge?: unknown, textColor?: string): ReturnType<typeof html> {\n const color = appearanceColor(textColor);\n // `captionCss` is a bare declaration list with no trailing `;` — append\n // one before adding to it, or the two declarations run together.\n const style = color === undefined\n ? captionCss\n : `${captionCss}${captionCss.length > 0 ? `;` : ``}color:${color};`;\n if (appearanceAbsent(badge)) {\n if (tickled) {\n return html`<div class=\"caption\" part=\"caption\" style=${style} title=${caption}><ixfx-pan-text mode=\"loop\">${caption}</ixfx-pan-text></div>`;\n }\n return html`<div class=\"caption\" part=\"caption\" style=${style} title=${caption}>${caption}</div>`;\n }\n const label = tickled\n ? html`<ixfx-pan-text mode=\"loop\">${caption}</ixfx-pan-text>`\n : html`<span class=\"caption-text\">${caption}</span>`;\n return html`<div class=\"caption has-badge\" part=\"caption\" style=${style} title=${caption}><span class=\"badge\" part=\"badge\">${badge}</span>${label}</div>`;\n }\n\n /** `color:<c>;` for a non-empty colour, else `nothing` (attribute removed). */\n #colorStyle(color: unknown): unknown {\n const c = appearanceColor(color);\n return c === undefined ? nothing : `color:${c};`;\n }\n\n /** Stop the active caption pan, if any, and forget it. */\n #stopActiveCaptionPan(): void {\n const active = this.#activeCaptionPan;\n this.#activeCaptionPan = null;\n try {\n active?.stopLoop?.();\n } catch {\n // A disconnected element may throw on update — it is already gone.\n }\n }\n\n /**\n * Enforce a single scrolling caption: the tickled cell's pan-text loops,\n * every other pan-text is stopped. The pan-text also auto-starts when\n * `mode=\"loop\"` is set; this covers the case where the element was already\n * connected before overflow was measured.\n */\n #activateTickledPan(): void {\n const tickledCell = this.renderRoot.querySelector(`.cell[data-tickled]`);\n const pans = [...this.renderRoot.querySelectorAll(`ixfx-pan-text[mode=\"loop\"]`)] as unknown as PanTextElement[];\n const current = (tickledCell?.querySelector(`ixfx-pan-text[mode=\"loop\"]`) ?? null) as unknown as PanTextElement | null;\n\n for (const pan of pans) {\n if (pan !== current) {\n try {\n pan.stopLoop?.();\n } catch {\n // Already disconnected — nothing left to stop.\n }\n }\n }\n\n const active = this.#activeCaptionPan;\n if (active && active !== current) {\n try {\n active.stopLoop?.();\n } catch {\n // Already disconnected — nothing left to stop.\n }\n }\n\n if (!current) {\n this.#activeCaptionPan = null;\n return;\n }\n this.#activeCaptionPan = current;\n current.startLoop?.();\n }\n\n #renderElementCells(win: GridWindow): ReturnType<typeof html> {\n const slice = win.ranges.flatMap(([start, end]) => Array.from({ length: end - start }, (_, i) => start + i));\n return repeat(\n slice,\n index => this.#source.keyAt(index),\n index => this.#renderCell(this.#items[index], index, win),\n ) as ReturnType<typeof html>;\n }\n\n #renderHeaders(win: GridWindow): ReturnType<typeof html> | typeof nothing {\n if (win.headers.length === 0)\n return nothing;\n const horizontal = win.horizontal;\n return repeat(\n win.headers,\n h => `__group__${h.key}`,\n h => html`\n <ixfx-list-group-header\n class=\"group-header\"\n part=\"group-header\"\n data-group-key=${h.key}\n label=${h.label}\n count=${h.count}\n orientation=${horizontal ? `vertical` : `horizontal`}\n ?collapsed=${h.collapsed}\n style=${horizontal\n ? `width:${h.size}px;height:100%;transform:translate(${h.offset}px,0)`\n : `width:100%;height:${h.size}px;transform:translate(0,${h.offset}px)`}\n @click=${() => this.toggleGroup(h.key)}\n ></ixfx-list-group-header>\n `,\n ) as ReturnType<typeof html>;\n }\n\n #renderCell(el: Element, index: number, win: GridWindow): ReturnType<typeof html> {\n const key = this.#source.keyAt(index);\n const selected = this.#selectedSnapshot.has(key);\n const marquee = this.#marqueePreview.has(key);\n const tickled = this.tickled.isTickled(key);\n const entering = this.#entering.has(el);\n const selectable = this.#source.isSelectable(index);\n const draggable = this.itemsDraggable && selectable;\n const style = this.captionStyle;\n const separate = style === `separate`;\n const caption = style === `hidden` ? `` : this.#captionFor(el);\n const showCaption = caption !== ``;\n const cellHeight = win.rowStride - this.gap;\n // `row`: a single row, vertically centred in the viewport.\n const { x, y } = this.#layout().positionOf(index);\n const thumbStyle = separate ? `height:${this.itemSize}px` : ``;\n const captionCss = separate\n ? `height:${Math.max(0, this.captionHeight - 4)}px`\n : style === `under`\n ? `height:${this.captionHeight}px`\n : ``;\n return html`\n <div\n class=\"cell${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}${entering ? ` entering` : ``}${marquee ? ` marquee` : ``}${this.#nativeDragging && key === this.#dragOriginKey ? ` dragging-origin` : ``}\"\n part=\"item${selected ? ` selected` : ``}${tickled ? ` tickled` : ``}\"\n role=\"option\"\n aria-selected=${selected ? `true` : `false`}\n style=\"width:${this.itemSize}px;height:${cellHeight}px;transform:translate(${x}px,${y}px)\"\n data-index=${index}\n data-key=${key}\n draggable=${draggable ? `true` : `false`}\n ?data-selected=${selected}\n ?data-tickled=${tickled}\n ?data-marquee=${marquee}\n @click=${(e: MouseEvent) => this.#onCellClick(e, key)}\n @dblclick=${() => this.#onCellActivate(key)}\n @pointerenter=${() => this.#handleCellPointerEnter(key)}\n >\n <div class=\"thumb\" part=\"thumb\" style=${thumbStyle}>\n ${this.#source.renderCellContent(index)}\n </div>\n ${showCaption ? this.#renderCaption(caption, captionCss, tickled) : ``}\n </div>\n `;\n }\n\n #onScroll = (e: Event): void => {\n const el = e.target as HTMLDivElement;\n this.#markScrollHoverSuppress();\n this.#cancelScrollRaf();\n this.#scrollRaf = requestAnimationFrame(() => {\n this.#scrollRaf = 0;\n this._scrollTop = el.scrollTop;\n this._scrollLeft = el.scrollLeft;\n this.#emitViewportChange();\n });\n this.#scheduleSnap();\n };\n\n /**\n * Translate vertical wheel deltas into horizontal scroll when the list runs\n * in `row` orientation. Without this the default browser behaviour needs\n * Shift+wheel or a physical horizontal wheel — neither of which most users\n * reach for on a single-row strip.\n *\n * Only kicks in for a plain vertical wheel over a viewport that can actually\n * scroll horizontally; native horizontal deltas (trackpad, Shift+wheel) are\n * left to the browser when there is no vertical component.\n */\n #onWheel = (e: WheelEvent): void => {\n if (this.orientation !== `row`)\n return;\n // Pinch-zoom (Ctrl+wheel) and friends must keep their native behaviour.\n if (e.ctrlKey || e.metaKey)\n return;\n if (e.deltaY === 0)\n return;\n const vp = this.#viewportRef.value ?? (e.currentTarget as HTMLElement | null);\n if (!vp)\n return;\n if (vp.scrollWidth <= vp.clientWidth + 1)\n return;\n // `preventDefault()` also swallows the native handling of `deltaX`, so\n // apply both components manually to keep diagonal trackpad gestures whole.\n this.#markScrollHoverSuppress();\n vp.scrollLeft += e.deltaX + e.deltaY;\n e.preventDefault();\n };\n\n /**\n * Cell `pointerenter` funnel. While a scroll gesture moves cells beneath a\n * stationary pointer (`disable-scroll-hover-tickle`), the freshly\n * virtualised cell's enter event is ignored so the cursor holds still.\n */\n #handleCellPointerEnter(key: string): void {\n if (this.#scrollHoverSuppress)\n return;\n this.tickled.handlePointerEnter(key);\n }\n\n /** Open the scroll-hover suppression window (no-op unless opted in and not already open). */\n #markScrollHoverSuppress(): void {\n if (!this.disableScrollHoverTickle || this.#scrollHoverSuppress)\n return;\n this.#scrollHoverSuppress = true;\n this.toggleAttribute(`data-scroll-hover-suppress`, true);\n }\n\n #endScrollHoverSuppress(): void {\n if (!this.#scrollHoverSuppress)\n return;\n this.#scrollHoverSuppress = false;\n this.toggleAttribute(`data-scroll-hover-suppress`, false);\n }\n\n /**\n * A real pointer movement ends scroll-hover suppression. The first\n * `pointerenter` on a real move is swallowed by design (it can be\n * indistinguishable from a virtualisation enter), so the cell already under\n * the pointer is re-tickled here — otherwise the cursor would lag one cell\n * boundary behind the pointer. The very first tracked `pointermove` only\n * establishes the baseline; it cannot know the pointer moved.\n */\n #onHostPointerMove = (e: PointerEvent): void => {\n const moved = !Number.isNaN(this.#lastPointerX)\n && (e.clientX !== this.#lastPointerX || e.clientY !== this.#lastPointerY);\n this.#lastPointerX = e.clientX;\n this.#lastPointerY = e.clientY;\n if (!moved || !this.#scrollHoverSuppress)\n return;\n this.#endScrollHoverSuppress();\n if (this.disableHoverTickle)\n return;\n // Optional call + null-safe chain: synthetic environments may not\n // implement ShadowRoot.elementFromPoint at all.\n const key = this.shadowRoot?.elementFromPoint?.(e.clientX, e.clientY)?.closest(`.cell`)?.getAttribute(`data-key`);\n if (key)\n this.tickled.handlePointerEnter(key);\n };\n\n /** The pointer leaving the list ends suppression, so re-entry hovers normally. */\n #onHostPointerLeave = (): void => {\n this.#endScrollHoverSuppress();\n };\n\n #cancelScrollRaf(): void {\n if (this.#scrollRaf !== 0) {\n cancelAnimationFrame(this.#scrollRaf);\n this.#scrollRaf = 0;\n }\n }\n\n #cancelSnapTimer(): void {\n if (this.#snapTimer !== 0) {\n clearTimeout(this.#snapTimer);\n this.#snapTimer = 0;\n }\n }\n\n #scheduleSnap(): void {\n if (!this.snapToItem || (this.orientation !== `row` && this.orientation !== `column`))\n return;\n this.#cancelSnapTimer();\n this.#snapTimer = window.setTimeout(() => {\n this.#snapTimer = 0;\n this.#snapToNearestLine();\n }, SNAP_DEBOUNCE_MS);\n }\n\n /**\n * Settle the viewport on the nearest item (`row` orientation) or row\n * (`column` orientation) boundary, using the same stride arithmetic as\n * {@link computeGridWindow} — no DOM measurement needed since off-screen\n * lines are never rendered.\n */\n #snapToNearestLine(): void {\n const vp = this.#viewportRef.value;\n if (!vp)\n return;\n const layout = this.#layout();\n const horizontal = layout.horizontal;\n const offset = horizontal ? vp.scrollLeft : vp.scrollTop;\n const viewportExtent = horizontal ? this._viewportWidth : this._viewportHeight;\n const maxScroll = Math.max(0, layout.totalExtent - viewportExtent);\n const target = Math.min(maxScroll, Math.max(0, layout.snapTarget(offset)));\n if (Math.abs(target - offset) < 0.5)\n return;\n vp.scrollTo(horizontal ? { left: target, behavior: `smooth` } : { top: target, behavior: `smooth` });\n }\n\n #onCellClick(e: MouseEvent, key: string): void {\n if (this.#dragSelect.isDragging || this.#nativeDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0)\n return;\n this.selection.handleClick(key, e);\n this.#emitItemEvent(`list-item-click`, key);\n }\n\n /**\n * A click that lands on the viewport without touching a cell — the empty\n * space between/around items — clears the selection (Finder-style). The\n * guard mirrors `#onCellClick`: a trailing click after a marquee or native\n * drag is swallowed so it cannot undo the selection that drag just made.\n * In `manual` interaction mode the consumer owns selection, so nothing is\n * cleared. Cell clicks route through `#onCellClick` and are skipped here.\n */\n #onViewportClick(e: MouseEvent): void {\n const mode = this.interactionMode;\n if (mode === `manual`)\n return;\n if (this.selectionMode === `none` && mode !== `checked` && mode !== `sticky`)\n return;\n if (this.#dragSelect.isDragging || this.#nativeDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0)\n return;\n for (const node of e.composedPath()) {\n if (node instanceof Element && (node.classList.contains(`cell`) || node.classList.contains(`group-header`)))\n return;\n }\n this.selection.clear();\n }\n\n #startPostDragSuppressTimer(): void {\n if (this.#postDragSuppressTimer) {\n clearTimeout(this.#postDragSuppressTimer);\n }\n this.#postDragSuppressTimer = window.setTimeout(() => {\n this.#postDragSuppressTimer = 0;\n }, 0);\n }\n\n #clearNativeDragState(): void {\n this.#nativeDragging = false;\n this.#dragOriginKey = undefined;\n this.toggleAttribute(`data-native-dragging`, false);\n this.removeAttribute(`aria-label`);\n }\n\n #onCellActivate(key: string): void {\n if (this.interactionMode !== `manual`) {\n this.selection.replace(key);\n }\n this.#emitItemEvent(`list-activate`, key);\n }\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if ((e.ctrlKey || e.metaKey) && e.key === `f`) {\n return;\n }\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 const count = this.#source.count;\n if (count === 0)\n return;\n\n const win = this.#currentWindow();\n const layout = this.#layout();\n const current = (): number => (this.tickled.tickledId ? this.#source.indexOfKey(this.tickled.tickledId) : -1);\n const goto = (nextIndex: number): void => {\n const nextKey = this.#source.keyAt(nextIndex);\n if (nextKey) {\n this.tickled.handleKeyboardNavigation(nextKey);\n this.#scrollItemIntoView(nextKey);\n }\n };\n const move = (delta: number): void => goto(Math.max(0, Math.min(count - 1, current() + delta)));\n // Grid: a vertical arrow keeps the column, hopping group headers and ragged rows.\n const moveLines = (dir: -1 | 1, lines = 1): void => {\n let index = current();\n if (index < 0) {\n move(dir * lines * win.cols);\n return;\n }\n for (let i = 0; i < lines; i++)\n index = layout.neighbour(index, dir);\n goto(index);\n };\n\n // In `grid` a vertical arrow jumps a whole row; in `row`/`column` every\n // arrow just steps one item along the single line.\n const perLine = this.orientation === `grid` ? win.cols : 1;\n\n switch (e.key) {\n case `ArrowLeft`:\n move(-1);\n break;\n case `ArrowRight`:\n move(1);\n break;\n case `ArrowUp`:\n if (this.orientation === `grid`)\n moveLines(-1);\n else\n move(-perLine);\n break;\n case `ArrowDown`:\n if (this.orientation === `grid`)\n moveLines(1);\n else\n move(perLine);\n break;\n case `Home`:\n this.tickled.handleKeyboardNavigation(`first`);\n if (this.tickled.tickledId) {\n this.#scrollItemIntoView(this.tickled.tickledId);\n }\n break;\n case `End`:\n this.tickled.handleKeyboardNavigation(`last`);\n if (this.tickled.tickledId) {\n this.#scrollItemIntoView(this.tickled.tickledId);\n }\n break;\n case `PageUp`:\n case `PageDown`: {\n const mainExtent = win.horizontal ? this._viewportWidth : this._viewportHeight;\n const mainStride = win.horizontal ? win.colStride : win.rowStride;\n const visibleLines = Math.max(1, Math.floor(mainExtent / mainStride));\n if (this.orientation === `grid`)\n moveLines(e.key === `PageDown` ? 1 : -1, visibleLines);\n else\n move((e.key === `PageDown` ? 1 : -1) * visibleLines * perLine);\n break;\n }\n case `Enter`: {\n const id = this.tickled.tickledId;\n if (id) {\n e.preventDefault();\n this.#emitItemEvent(`list-item-click`, id);\n this.#onCellActivate(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 if (this.#nativeDragging) {\n this.#clearNativeDragState();\n }\n this.selection.clear();\n break;\n default:\n return;\n }\n e.preventDefault();\n };\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-grid-list': GridListElement;\n }\n}\n\nexport interface GridListElement {\n addEventListener<K extends keyof GridListFullElementEventMap>(\n type: K,\n listener: (this: GridListElement, ev: GridListFullElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n}\n"],"mappings":"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"}
|
package/dist/grid-list.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { I as ListDragSource, L as ListNativeDragStartDetail, M as ListDragPreview, N as ListDragPreviewContext, P as ListDragPreviewRenderer, R as ListNativeDragStartEvent, j as ListDragEntry } from "./tree-component-DukLqesg.js";
|
|
2
|
+
import { i as ListGroupChangeEvent, l as ListGroupToggleDetail, n as ListGroupBy, o as ListGroupInfo, r as ListGroupChangeDetail, s as ListGroupLabel, u as ListGroupToggleEvent } from "./grouping-CUKgmkMm.js";
|
|
2
3
|
import { i as ListInteractionMode, l as ListSelectionMode } from "./list-selection-types-PjKdhF-a.js";
|
|
3
|
-
import { _ as GridListTickleDetail, a as GridListCaptionBackdrop, b as GridListViewportChangeEvent, c as GridListDataAdapter, d as GridListItemClickDetail, f as GridListItemClickEvent, g as GridListSelectEvent, h as GridListSelectDetail, i as GridListCaptionAlign, l as GridListElementEventMap, m as GridListOrientation, n as GridListActivateDetail, o as GridListCaptionPosition, p as GridListItemEventDetail, r as GridListActivateEvent, s as GridListCaptionStyle, t as GridListElement, u as GridListFullElementEventMap, v as GridListTickleEvent, y as GridListViewportChangeDetail } from "./grid-list-
|
|
4
|
-
export { type GridListActivateDetail, type GridListActivateEvent, type GridListCaptionAlign, type GridListCaptionBackdrop, type GridListCaptionPosition, type GridListCaptionStyle, type GridListDataAdapter, GridListElement, type GridListElementEventMap, type GridListFullElementEventMap, type GridListItemClickDetail, type GridListItemClickEvent, type GridListItemEventDetail, type GridListOrientation, type GridListSelectDetail, type GridListSelectEvent, type GridListTickleDetail, type GridListTickleEvent, type GridListViewportChangeDetail, type GridListViewportChangeEvent, type ListDragEntry, type ListDragPreview, type ListDragPreviewContext, type ListDragPreviewRenderer, type ListDragSource, type ListInteractionMode, type ListNativeDragStartDetail, type ListNativeDragStartEvent, type ListSelectionMode };
|
|
4
|
+
import { _ as GridListTickleDetail, a as GridListCaptionBackdrop, b as GridListViewportChangeEvent, c as GridListDataAdapter, d as GridListItemClickDetail, f as GridListItemClickEvent, g as GridListSelectEvent, h as GridListSelectDetail, i as GridListCaptionAlign, l as GridListElementEventMap, m as GridListOrientation, n as GridListActivateDetail, o as GridListCaptionPosition, p as GridListItemEventDetail, r as GridListActivateEvent, s as GridListCaptionStyle, t as GridListElement, u as GridListFullElementEventMap, v as GridListTickleEvent, y as GridListViewportChangeDetail } from "./grid-list-Bc-RkDoO.js";
|
|
5
|
+
export { type GridListActivateDetail, type GridListActivateEvent, type GridListCaptionAlign, type GridListCaptionBackdrop, type GridListCaptionPosition, type GridListCaptionStyle, type GridListDataAdapter, GridListElement, type GridListElementEventMap, type GridListFullElementEventMap, type GridListItemClickDetail, type GridListItemClickEvent, type GridListItemEventDetail, type GridListOrientation, type GridListSelectDetail, type GridListSelectEvent, type GridListTickleDetail, type GridListTickleEvent, type GridListViewportChangeDetail, type GridListViewportChangeEvent, type ListDragEntry, type ListDragPreview, type ListDragPreviewContext, type ListDragPreviewRenderer, type ListDragSource, type ListGroupBy, type ListGroupChangeDetail, type ListGroupChangeEvent, type ListGroupInfo, type ListGroupLabel, type ListGroupToggleDetail, type ListGroupToggleEvent, type ListInteractionMode, type ListNativeDragStartDetail, type ListNativeDragStartEvent, type ListSelectionMode };
|
package/dist/grid-list.js
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/interaction/grouping.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared, DOM-free grouping helpers for list components
|
|
4
|
+
* (`ixfx-grid-list`, `ixfx-detail-list`). Semantics mirror `ixfx-data-grid`:
|
|
5
|
+
* groups appear in first-encounter order, keys are `String(value ?? '')`.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* How to derive an item's group key: a property (or `data-*` attribute) name,
|
|
9
|
+
* or a function of the item.
|
|
10
|
+
*/
|
|
11
|
+
type ListGroupBy<T = unknown> = string | ((item: T, index: number) => string);
|
|
12
|
+
/** Turns a group key and its items into the header label. */
|
|
13
|
+
type ListGroupLabel = (groupKey: string, items: readonly unknown[]) => string;
|
|
14
|
+
/** Read-only description of one rendered group. */
|
|
15
|
+
type ListGroupInfo = {
|
|
16
|
+
readonly key: string;
|
|
17
|
+
readonly label: string;
|
|
18
|
+
/** Visible (post-filter) items, including those hidden by collapse. */
|
|
19
|
+
readonly count: number;
|
|
20
|
+
readonly collapsed: boolean;
|
|
21
|
+
};
|
|
22
|
+
type ListGroupToggleDetail = {
|
|
23
|
+
readonly groupKey: string;
|
|
24
|
+
readonly collapsed: boolean;
|
|
25
|
+
};
|
|
26
|
+
type ListGroupChangeDetail = {
|
|
27
|
+
readonly groupBy: ListGroupBy<unknown> | null;
|
|
28
|
+
};
|
|
29
|
+
type ListGroupToggleEvent = CustomEvent<ListGroupToggleDetail>;
|
|
30
|
+
type ListGroupChangeEvent = CustomEvent<ListGroupChangeDetail>;
|
|
31
|
+
interface ListGroupEventMap {
|
|
32
|
+
'list-group-toggle': ListGroupToggleEvent;
|
|
33
|
+
'list-group-change': ListGroupChangeEvent;
|
|
34
|
+
}
|
|
35
|
+
/** One group produced by {@link partitionByGroup}. */
|
|
36
|
+
type ListGroupPartition<T> = {
|
|
37
|
+
readonly key: string;
|
|
38
|
+
readonly label: string;
|
|
39
|
+
readonly items: T[];
|
|
40
|
+
/** Index (in the input array) of the group's first item. */
|
|
41
|
+
readonly firstIndex: number;
|
|
42
|
+
};
|
|
43
|
+
/** Label shown for the empty group key. */
|
|
44
|
+
declare const EMPTY_GROUP_LABEL = "(none)";
|
|
45
|
+
/** Default header label: the key, or `(none)` for the empty key. */
|
|
46
|
+
declare function defaultGroupLabel(key: string): string;
|
|
47
|
+
/** Coerce a raw group value to a key, as data-grid does. */
|
|
48
|
+
declare function toGroupKey(value: unknown): string;
|
|
49
|
+
/**
|
|
50
|
+
* Group key for `item`. A string `groupBy` is resolved through `readNamed`
|
|
51
|
+
* (property or `data-*` lookup, supplied by the host); a function is called.
|
|
52
|
+
*/
|
|
53
|
+
declare function resolveGroupKey<T>(groupBy: ListGroupBy<T>, item: T, index: number, readNamed: (item: T, name: string) => unknown): string;
|
|
54
|
+
/**
|
|
55
|
+
* Split `items` into groups in first-encounter order. Single pass, O(n).
|
|
56
|
+
* Item order within a group is preserved.
|
|
57
|
+
*/
|
|
58
|
+
declare function partitionByGroup<T>(items: readonly T[], keyOf: (item: T, index: number) => string, labelOf?: ListGroupLabel): Array<ListGroupPartition<T>>;
|
|
59
|
+
/** Immutable toggle of `key` in `set`. */
|
|
60
|
+
declare function toggleInSet(set: ReadonlySet<string>, key: string): Set<string>;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { ListGroupEventMap as a, ListGroupPartition as c, defaultGroupLabel as d, partitionByGroup as f, toggleInSet as h, ListGroupChangeEvent as i, ListGroupToggleDetail as l, toGroupKey as m, ListGroupBy as n, ListGroupInfo as o, resolveGroupKey as p, ListGroupChangeDetail as r, ListGroupLabel as s, EMPTY_GROUP_LABEL as t, ListGroupToggleEvent as u };
|
|
63
|
+
//# sourceMappingURL=grouping-CUKgmkMm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grouping-CUKgmkMm.d.ts","names":[],"sources":["../src/interaction/grouping.ts"],"mappings":";;;;;;;;;;KAUY,YAAY,0BAA0B,MAAM,GAAG;;KAG/C,kBAAkB,kBAAkB;;KAGpC;WACD;WACA;;WAEA;WACA;;KAGC;WACD;WACA;;KAGC;WACD,SAAS;;KAGR,uBAAuB,YAAY;KACnC,uBAAuB,YAAY;UAE9B;EACf,qBAAqB;EACrB,qBAAqB;;;KAIX,mBAAmB;WACpB;WACA;WACA,OAAO;;WAEP;;;cAIE;;iBAGG,kBAAkB;;iBAKlB,WAAW;;;;;iBAQX,gBAAgB,GAC9B,SAAS,YAAY,IACrB,MAAM,GACN,eACA,YAAY,MAAM,GAAG;;;;;iBAWP,iBAAiB,GAC/B,gBAAgB,KAChB,QAAQ,MAAM,GAAG,0BACjB,UAAU,iBACT,MAAM,mBAAmB;;iBAmBZ,YAAY,KAAK,qBAAqB,cAAc"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/interaction/grouping.ts
|
|
2
|
+
/** Label shown for the empty group key. */
|
|
3
|
+
const EMPTY_GROUP_LABEL = `(none)`;
|
|
4
|
+
/** Default header label: the key, or `(none)` for the empty key. */
|
|
5
|
+
function defaultGroupLabel(key) {
|
|
6
|
+
return key === `` ? EMPTY_GROUP_LABEL : key;
|
|
7
|
+
}
|
|
8
|
+
/** Coerce a raw group value to a key, as data-grid does. */
|
|
9
|
+
function toGroupKey(value) {
|
|
10
|
+
return String(value ?? ``);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Group key for `item`. A string `groupBy` is resolved through `readNamed`
|
|
14
|
+
* (property or `data-*` lookup, supplied by the host); a function is called.
|
|
15
|
+
*/
|
|
16
|
+
function resolveGroupKey(groupBy, item, index, readNamed) {
|
|
17
|
+
if (typeof groupBy === `string`) return toGroupKey(readNamed(item, groupBy));
|
|
18
|
+
return toGroupKey(groupBy(item, index));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Split `items` into groups in first-encounter order. Single pass, O(n).
|
|
22
|
+
* Item order within a group is preserved.
|
|
23
|
+
*/
|
|
24
|
+
function partitionByGroup(items, keyOf, labelOf) {
|
|
25
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
26
|
+
for (let i = 0; i < items.length; i++) {
|
|
27
|
+
const key = keyOf(items[i], i);
|
|
28
|
+
const existing = byKey.get(key);
|
|
29
|
+
if (existing) existing.items.push(items[i]);
|
|
30
|
+
else byKey.set(key, {
|
|
31
|
+
key,
|
|
32
|
+
items: [items[i]],
|
|
33
|
+
firstIndex: i
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return [...byKey.values()].map((g) => ({
|
|
37
|
+
key: g.key,
|
|
38
|
+
items: g.items,
|
|
39
|
+
firstIndex: g.firstIndex,
|
|
40
|
+
label: labelOf ? labelOf(g.key, g.items) : defaultGroupLabel(g.key)
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
/** Immutable toggle of `key` in `set`. */
|
|
44
|
+
function toggleInSet(set, key) {
|
|
45
|
+
const next = new Set(set);
|
|
46
|
+
if (next.has(key)) next.delete(key);
|
|
47
|
+
else next.add(key);
|
|
48
|
+
return next;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { toGroupKey as a, resolveGroupKey as i, defaultGroupLabel as n, toggleInSet as o, partitionByGroup as r, EMPTY_GROUP_LABEL as t };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=grouping-RYPnHkrS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grouping-RYPnHkrS.js","names":[],"sources":["../src/interaction/grouping.ts"],"sourcesContent":["/**\n * Shared, DOM-free grouping helpers for list components\n * (`ixfx-grid-list`, `ixfx-detail-list`). Semantics mirror `ixfx-data-grid`:\n * groups appear in first-encounter order, keys are `String(value ?? '')`.\n */\n\n/**\n * How to derive an item's group key: a property (or `data-*` attribute) name,\n * or a function of the item.\n */\nexport type ListGroupBy<T = unknown> = string | ((item: T, index: number) => string);\n\n/** Turns a group key and its items into the header label. */\nexport type ListGroupLabel = (groupKey: string, items: readonly unknown[]) => string;\n\n/** Read-only description of one rendered group. */\nexport type ListGroupInfo = {\n readonly key: string;\n readonly label: string;\n /** Visible (post-filter) items, including those hidden by collapse. */\n readonly count: number;\n readonly collapsed: boolean;\n};\n\nexport type ListGroupToggleDetail = {\n readonly groupKey: string;\n readonly collapsed: boolean;\n};\n\nexport type ListGroupChangeDetail = {\n readonly groupBy: ListGroupBy<unknown> | null;\n};\n\nexport type ListGroupToggleEvent = CustomEvent<ListGroupToggleDetail>;\nexport type ListGroupChangeEvent = CustomEvent<ListGroupChangeDetail>;\n\nexport interface ListGroupEventMap {\n 'list-group-toggle': ListGroupToggleEvent;\n 'list-group-change': ListGroupChangeEvent;\n}\n\n/** One group produced by {@link partitionByGroup}. */\nexport type ListGroupPartition<T> = {\n readonly key: string;\n readonly label: string;\n readonly items: T[];\n /** Index (in the input array) of the group's first item. */\n readonly firstIndex: number;\n};\n\n/** Label shown for the empty group key. */\nexport const EMPTY_GROUP_LABEL = `(none)`;\n\n/** Default header label: the key, or `(none)` for the empty key. */\nexport function defaultGroupLabel(key: string): string {\n return key === `` ? EMPTY_GROUP_LABEL : key;\n}\n\n/** Coerce a raw group value to a key, as data-grid does. */\nexport function toGroupKey(value: unknown): string {\n return String(value ?? ``);\n}\n\n/**\n * Group key for `item`. A string `groupBy` is resolved through `readNamed`\n * (property or `data-*` lookup, supplied by the host); a function is called.\n */\nexport function resolveGroupKey<T>(\n groupBy: ListGroupBy<T>,\n item: T,\n index: number,\n readNamed: (item: T, name: string) => unknown,\n): string {\n if (typeof groupBy === `string`)\n return toGroupKey(readNamed(item, groupBy));\n return toGroupKey(groupBy(item, index));\n}\n\n/**\n * Split `items` into groups in first-encounter order. Single pass, O(n).\n * Item order within a group is preserved.\n */\nexport function partitionByGroup<T>(\n items: readonly T[],\n keyOf: (item: T, index: number) => string,\n labelOf?: ListGroupLabel,\n): Array<ListGroupPartition<T>> {\n const byKey = new Map<string, { key: string; items: T[]; firstIndex: number }>();\n for (let i = 0; i < items.length; i++) {\n const key = keyOf(items[i], i);\n const existing = byKey.get(key);\n if (existing)\n existing.items.push(items[i]);\n else\n byKey.set(key, { key, items: [items[i]], firstIndex: i });\n }\n return [...byKey.values()].map(g => ({\n key: g.key,\n items: g.items,\n firstIndex: g.firstIndex,\n label: labelOf ? labelOf(g.key, g.items) : defaultGroupLabel(g.key),\n }));\n}\n\n/** Immutable toggle of `key` in `set`. */\nexport function toggleInSet(set: ReadonlySet<string>, key: string): Set<string> {\n const next = new Set(set);\n if (next.has(key))\n next.delete(key);\n else\n next.add(key);\n return next;\n}\n"],"mappings":";;AAmDA,MAAa,oBAAoB;;AAGjC,SAAgB,kBAAkB,KAAqB;CACrD,OAAO,QAAQ,KAAK,oBAAoB;AAC1C;;AAGA,SAAgB,WAAW,OAAwB;CACjD,OAAO,OAAO,SAAS,EAAE;AAC3B;;;;;AAMA,SAAgB,gBACd,SACA,MACA,OACA,WACQ;CACR,IAAI,OAAO,YAAY,UACrB,OAAO,WAAW,UAAU,MAAM,OAAO,CAAC;CAC5C,OAAO,WAAW,QAAQ,MAAM,KAAK,CAAC;AACxC;;;;;AAMA,SAAgB,iBACd,OACA,OACA,SAC8B;CAC9B,MAAM,wBAAQ,IAAI,IAA6D;CAC/E,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,MAAM,MAAM,IAAI,CAAC;EAC7B,MAAM,WAAW,MAAM,IAAI,GAAG;EAC9B,IAAI,UACF,SAAS,MAAM,KAAK,MAAM,EAAE;OAE5B,MAAM,IAAI,KAAK;GAAE;GAAK,OAAO,CAAC,MAAM,EAAE;GAAG,YAAY;EAAE,CAAC;CAC5D;CACA,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,KAAI,OAAM;EACnC,KAAK,EAAE;EACP,OAAO,EAAE;EACT,YAAY,EAAE;EACd,OAAO,UAAU,QAAQ,EAAE,KAAK,EAAE,KAAK,IAAI,kBAAkB,EAAE,GAAG;CACpE,EAAE;AACJ;;AAGA,SAAgB,YAAY,KAA0B,KAA0B;CAC9E,MAAM,OAAO,IAAI,IAAI,GAAG;CACxB,IAAI,KAAK,IAAI,GAAG,GACd,KAAK,OAAO,GAAG;MAEf,KAAK,IAAI,GAAG;CACd,OAAO;AACT"}
|