@k2b/ui 0.45.0 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/actions/Dropdown.js +8 -1
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/FilterChip.js +11 -5
- package/dist/browser/actions/FilterChip.js.map +1 -1
- package/dist/browser/actions/ViewTabs.js +225 -93
- package/dist/browser/actions/ViewTabs.js.map +1 -1
- package/dist/browser/chat/ChatDecision.js +10 -6
- package/dist/browser/chat/ChatDecision.js.map +1 -1
- package/dist/browser/content/FileGrid.js +125 -99
- package/dist/browser/content/FileGrid.js.map +1 -1
- package/dist/browser/content/VirtualFeed.js +26 -21
- package/dist/browser/content/VirtualFeed.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +14 -6
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/choice.js +36 -9
- package/dist/browser/inputs/choice.js.map +1 -1
- package/dist/browser/layout/AnchoredPopover.js +2 -1
- package/dist/browser/layout/AnchoredPopover.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +348 -444
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/AppWorkspaceSidebarItemStatus.js +113 -0
- package/dist/browser/layout/AppWorkspaceSidebarItemStatus.js.map +1 -0
- package/dist/browser/layout/DetailPanel.js +130 -108
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/DetailSections.js +1123 -0
- package/dist/browser/layout/DetailSections.js.map +1 -0
- package/dist/browser/layout/DetailsToggle.js +32 -0
- package/dist/browser/layout/DetailsToggle.js.map +1 -0
- package/dist/browser/layout/Discussion.js +3 -0
- package/dist/browser/layout/Discussion.js.map +1 -1
- package/dist/browser/layout/MobileShell.js +141 -102
- package/dist/browser/layout/MobileShell.js.map +1 -1
- package/dist/browser/layout/PageTitle.js +33 -10
- package/dist/browser/layout/PageTitle.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +12 -0
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/detail-sections-messages.js +127 -0
- package/dist/browser/layout/detail-sections-messages.js.map +1 -0
- package/dist/browser/layout/index.js +3 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/surfaces/Avatar.js +3 -1
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/browser/surfaces/AvatarStack.js +95 -61
- package/dist/browser/surfaces/AvatarStack.js.map +1 -1
- package/dist/browser/surfaces/ChangeList.js +77 -0
- package/dist/browser/surfaces/ChangeList.js.map +1 -0
- package/dist/browser/surfaces/index.js +2 -1
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/browser/text-editor/TextEditor.js +19 -8
- package/dist/browser/text-editor/TextEditor.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +6 -0
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/FilterChip.js +1 -1
- package/dist/ssr/actions/FilterChip.js.map +1 -1
- package/dist/ssr/actions/ViewTabs.js +144 -37
- package/dist/ssr/actions/ViewTabs.js.map +1 -1
- package/dist/ssr/chat/ChatDecision.js +10 -6
- package/dist/ssr/chat/ChatDecision.js.map +1 -1
- package/dist/ssr/content/FileGrid.js +36 -22
- package/dist/ssr/content/FileGrid.js.map +1 -1
- package/dist/ssr/content/VirtualFeed.js +26 -21
- package/dist/ssr/content/VirtualFeed.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js +6 -3
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/choice.js +36 -9
- package/dist/ssr/inputs/choice.js.map +1 -1
- package/dist/ssr/layout/AnchoredPopover.js +2 -1
- package/dist/ssr/layout/AnchoredPopover.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +66 -132
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/AppWorkspaceSidebarItemStatus.js +76 -0
- package/dist/ssr/layout/AppWorkspaceSidebarItemStatus.js.map +1 -0
- package/dist/ssr/layout/DetailPanel.js +18 -1
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/DetailSections.js +838 -0
- package/dist/ssr/layout/DetailSections.js.map +1 -0
- package/dist/ssr/layout/DetailsToggle.js +29 -0
- package/dist/ssr/layout/DetailsToggle.js.map +1 -0
- package/dist/ssr/layout/Discussion.js +3 -0
- package/dist/ssr/layout/Discussion.js.map +1 -1
- package/dist/ssr/layout/MobileShell.js +60 -29
- package/dist/ssr/layout/MobileShell.js.map +1 -1
- package/dist/ssr/layout/PageTitle.js +29 -6
- package/dist/ssr/layout/PageTitle.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +12 -0
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/detail-sections-messages.js +127 -0
- package/dist/ssr/layout/detail-sections-messages.js.map +1 -0
- package/dist/ssr/layout/index.js +3 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/surfaces/Avatar.js +3 -1
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/surfaces/AvatarStack.js +61 -32
- package/dist/ssr/surfaces/AvatarStack.js.map +1 -1
- package/dist/ssr/surfaces/ChangeList.js +37 -0
- package/dist/ssr/surfaces/ChangeList.js.map +1 -0
- package/dist/ssr/surfaces/index.js +2 -1
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/ssr/text-editor/TextEditor.js +19 -8
- package/dist/ssr/text-editor/TextEditor.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/FilterChip.d.ts +4 -0
- package/dist/types/actions/ViewTabs.d.ts +11 -1
- package/dist/types/chat/ChatDecision.d.ts +5 -0
- package/dist/types/content/FileGrid.d.ts +6 -0
- package/dist/types/inputs/Combobox.d.ts +2 -0
- package/dist/types/inputs/choice.d.ts +9 -3
- package/dist/types/layout/AppWorkspace.d.ts +2 -28
- package/dist/types/layout/AppWorkspaceSidebarItemStatus.d.ts +30 -0
- package/dist/types/layout/DetailPanel.d.ts +9 -0
- package/dist/types/layout/DetailSections.d.ts +186 -0
- package/dist/types/layout/DetailsToggle.d.ts +13 -0
- package/dist/types/layout/MobileShell.d.ts +12 -0
- package/dist/types/layout/PageTitle.d.ts +7 -0
- package/dist/types/layout/detail-sections-messages.d.ts +61 -0
- package/dist/types/layout/index.d.ts +5 -1
- package/dist/types/surfaces/Avatar.d.ts +3 -0
- package/dist/types/surfaces/AvatarStack.d.ts +20 -1
- package/dist/types/surfaces/ChangeList.d.ts +20 -0
- package/dist/types/surfaces/index.d.ts +5 -3
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/VirtualFeed.tsx"],"sourcesContent":["import { type Accessor, createEffect, createRoot, createSignal, getOwner, type JSX, on, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { useFeedMessages } from \"./feed-messages\";\n\n/**\n * The tallest loaded window in px. Firefox renders an element taller than about 17.9 M px with a height of 0, so the\n * feed lays out at most this much and drops far items while it keeps the reading position.\n */\nconst MAX_WINDOW = 8_000_000;\n/** How much the loaded window grows at once when the reader nears one of its edges. */\nconst WINDOW_STEP = 2_000_000;\n/** Rows rendered above and below the visible part, in px. */\nconst OVERSCAN = 600;\n/** Distance from the end, in px, that still counts as being at the end. */\nconst END_TOLERANCE = 2;\n/** Part of an item, in px, that may be cut off while it still counts as fully in view: rounding, not a hidden line. */\nconst VISIBLE_TOLERANCE = 1;\n/**\n * Rows mounted during one correction reach the ResizeObserver a frame late; measure up to this many passes at once.\n * A last pass places the rows; the observer measures what that pass mounted.\n */\nconst MEASURE_PASSES = 4;\nconst ANNOUNCE_MS = 1_000;\nconst HIGHLIGHT_MS = 1_600;\n/** In engines without `scrollend`, the reader's scroll has ended after this long without moving. */\nconst QUIET_MS = 300;\n/** The longest wait for the `scrollend` of the reader's scroll after it last moved, or of a write of the feed. */\nconst END_WAIT_MS = 1_000;\n\nexport type VirtualFeedScrollOptions = {\n /** Where the item lands in the visible area. Defaults to `\"center\"`. */\n align?: \"start\" | \"center\";\n /** Tints the item briefly so the reader finds it. */\n highlight?: boolean;\n};\n\nexport type VirtualFeedController = {\n /**\n * Scrolls to a loaded item, also when the reader's scroll still coasts. Returns false when no loaded item has this\n * key, so the caller can load around it first.\n */\n scrollToKey: (key: string, options?: VirtualFeedScrollOptions) => boolean;\n /**\n * Follows the end again, also when the reader's scroll still coasts. When newer items exist but are not loaded, it\n * asks `onLoadNewest` for them first.\n */\n scrollToEnd: () => void;\n /** Whether the reader is at the end and new items keep the feed there. */\n isAtEnd: () => boolean;\n};\n\nexport type VirtualFeedProps<T> = {\n /** Loaded items, oldest first. Replace the array to add, remove, or change items. */\n items: readonly T[];\n /** Stable, unique identity of an item across updates. */\n getKey: (item: T) => string;\n /** Height in px before the item was measured. Close estimates mean fewer corrections while scrolling. */\n estimateSize: (item: T) => number;\n /** Content of one item, created once per item object as with Solid's `For`. `index` is its position in `items`. */\n children: (item: T, index: Accessor<number>) => JSX.Element;\n /** Accessible name of the feed. */\n label: string;\n /** Accessible name of one item, for example its author and time. */\n itemLabel?: (item: T) => string | undefined;\n /**\n * Label shown above an item, for example when the day changes. Return nothing for no separator. While `hasOlder` is\n * set, the first loaded item has no known predecessor and gets none.\n */\n separator?: (item: T, previous: T | undefined) => JSX.Element;\n /** Key of the first item the reader has not seen; a marker appears above it. */\n markerKey?: string | null;\n /** Text of that marker. Defaults to \"New\". */\n markerLabel?: string;\n /** Older items exist that `items` does not contain yet. */\n hasOlder?: boolean;\n /** Newer items exist that `items` does not contain yet. */\n hasNewer?: boolean;\n /** Called near the start of the loaded items while `hasOlder` is true. Prepend the next older page to `items`. */\n onLoadOlder?: () => unknown;\n /** Called near the end of the loaded items while `hasNewer` is true. Append the next newer page to `items`. */\n onLoadNewer?: () => unknown;\n /** Called by \"Jump to latest\" while `hasNewer` is true. Replace `items` with the newest page. */\n onLoadNewest?: () => unknown;\n /** Marks the feed as busy for assistive technology, for example during the first load. */\n busy?: boolean;\n /** Number of items in the whole feed when known. */\n totalCount?: number;\n /** One-based position of `items[0]` in the whole feed when known. */\n firstPosition?: number;\n /**\n * Count shown on \"Jump to latest\". Defaults to the new items added while the reader was away from the end, which\n * excludes pages of older history loaded toward the end.\n */\n newCount?: number;\n /** Text announced for new items added at the end, bundled per second. Return nothing to stay silent. */\n announce?: (added: readonly T[]) => string | undefined;\n /** Called when the reader reaches or leaves the end. */\n onEndChange?: (atEnd: boolean) => void;\n /**\n * Called when the items in view change: the first and last item whose whole height is in view. An item taller\n * than the view counts while it covers the view. `null` while no item is in view.\n */\n onVisibleChange?: (visible: { first: T; last: T } | null) => void;\n /** Receives the controller once the feed is mounted. */\n controller?: (controller: VirtualFeedController) => void;\n /** Shown while `items` is empty. */\n empty?: JSX.Element;\n class?: string;\n};\n\n/**\n * One mounted row. Rows are created and removed but never moved, so focus, media, and frames inside them survive.\n * `lead` is the measured height of the separator and marker above the content.\n */\ntype Row<T> = { item: T; node: HTMLElement; index: number; lead?: number; setIndex: (index: number) => void; dispose: () => void };\n\nconst runsMatch = (before: readonly string[], after: readonly string[], shift: number) => {\n for (let index = 0; index < before.length; index++) if (before[index] !== after[index + shift]) return false;\n return true;\n};\n\n/** Height of the separator and marker that a row shows above its content. */\nconst leadOf = (node: HTMLElement) => {\n let height = 0;\n for (const child of node.children) {\n if (!child.classList.contains(\"k2b-virtual-feed__separator\") && !child.classList.contains(\"k2b-virtual-feed__marker\")) break;\n height += child.getBoundingClientRect().height;\n }\n return height;\n};\n\n/**\n * A virtualized feed of items with variable heights that grows at both ends and keeps the reading position: it stays\n * at the end while the reader is there, and otherwise keeps the item in view where it is, whatever loads, grows, or\n * resizes around it.\n */\nexport function VirtualFeed<T>(props: VirtualFeedProps<T>): JSX.Element {\n const messages = useUiMessages();\n const feedMessages = useFeedMessages();\n let viewport!: HTMLDivElement;\n let feed!: HTMLDivElement;\n let log!: HTMLDivElement;\n\n // Layout: one size per item and prefix sums over the loaded window [lo, hi).\n let list: readonly T[] = [];\n let keys: string[] = [];\n let sizes = new Float64Array(0);\n let lo = 0;\n let hi = 0;\n let offsets = new Float64Array(1);\n let dirtyFrom = 0;\n\n // Reading position: follow the end, or keep one item (index) at a pixel distance (delta) below the visible top.\n let stick = true;\n let anchor = { index: 0, delta: 0 };\n /** Key of the last item while no newer items existed; items appended after it are new. */\n let endKey: string | undefined;\n /** The last scrollTop the feed wrote or accounted for; any other value comes from the reader. */\n let lastTop = 0;\n /** The viewport height the reading position was last applied to. */\n let lastHeight = 0;\n /**\n * While the reader scrolls, the feed does not write scrollTop, which would fight a finger, momentum, or a scroll\n * animation. It moves the rows by this much instead: the logical position minus the physical scrollTop.\n */\n let deferred = 0;\n /** Touches that began in the feed and have not ended. */\n const fingers = new Set<number>();\n /** Where those touches began. Their touchend still goes there after the feed removed the row. */\n const touched = new Set<EventTarget>();\n /** The reader's scroll runs, from its first move until its scrollend, or a quiet time where the engine has none. */\n let scrolling = false;\n /** A jump by the application ended the reader's scroll; what is left of its momentum is put back. */\n let overriding = false;\n let lastMove = 0;\n let endedAt = Number.NEGATIVE_INFINITY;\n /**\n * Until then, the next `scrollend` belongs to the feed's last write that moved the position. iOS delivers it late\n * enough to land in a later scroll of the reader, also in a pause of a slow momentum tail.\n */\n let owedUntil = 0;\n let endTimer: ReturnType<typeof setTimeout> | undefined;\n let hasScrollEnd = false;\n /** First item appended while the reader scrolls away from the end; reaching the end is judged before it. */\n let appendedFrom = -1;\n let focusIndex = -1;\n let fresh: HTMLElement[] = [];\n let restoring = false;\n let restoreAgain = false;\n let pendingAnnouncement: T[] = [];\n let announceTimer: ReturnType<typeof setTimeout> | undefined;\n let highlightTimer: ReturnType<typeof setTimeout> | undefined;\n /** \"Jump to latest\" asked for the newest page; it waits for running loads and stops new paging until it settles. */\n let newest: \"waiting\" | \"loading\" | undefined;\n let disposed = false;\n let observeRow: (row: HTMLElement) => void = () => {};\n /** Set while the ResizeObserver callback runs. */\n let observing = false;\n let unobserveRow: (row: HTMLElement) => void = () => {};\n const owner = getOwner();\n const rows = new Map<string, Row<T>>();\n const rowOf = new WeakMap<Element, Row<T>>();\n\n const [version, setVersion] = createSignal(0);\n /** Changes with every new `items` array, so separators see a replaced predecessor. */\n const [listVersion, setListVersion] = createSignal(0);\n const [tabStop, setTabStop] = createSignal(-1);\n // Known on the server too, so the empty slot never flashes for a feed that has items.\n const [count, setCount] = createSignal(untrack(() => props.items.length));\n const [atEnd, setAtEnd] = createSignal(true);\n const [unseen, setUnseen] = createSignal(0);\n const [highlighted, setHighlighted] = createSignal<string>();\n const [loadingOlder, setLoadingOlder] = createSignal(false);\n const [loadingNewer, setLoadingNewer] = createSignal(false);\n\n const estimate = (item: T) => {\n const size = props.estimateSize(item);\n return size > 0 ? size : 1;\n };\n\n const recompute = () => {\n const length = hi - lo;\n if (offsets.length !== length + 1) {\n offsets = new Float64Array(length + 1);\n dirtyFrom = 0;\n }\n for (let j = dirtyFrom; j < length; j++) offsets[j + 1] = offsets[j]! + sizes[lo + j]!;\n dirtyFrom = length;\n };\n const total = () => offsets[hi - lo]!;\n const offsetOf = (index: number) => offsets[Math.min(hi - lo, Math.max(0, index - lo))]!;\n /** The loaded item whose bottom edge lies below `y`. */\n const indexAt = (y: number) => {\n let low = 0;\n let high = hi - lo - 1;\n while (low < high) {\n const middle = (low + high) >> 1;\n if (offsets[middle + 1]! <= y) low = middle + 1;\n else high = middle;\n }\n return lo + Math.max(0, low);\n };\n\n const anchorAt = (top: number) => {\n const index = indexAt(top);\n return { index, delta: offsetOf(index) - top };\n };\n const logicalTop = () => viewport.scrollTop + deferred;\n const setStick = (value: boolean) => {\n // The anchor is not maintained while following the end; leaving the end keeps what is visible now.\n if (stick && !value && hi > lo) anchor = anchorAt(logicalTop());\n stick = value;\n if (value) setUnseen(0);\n if (atEnd() === value) return;\n setAtEnd(value);\n props.onEndChange?.(value);\n };\n /**\n * Whether `top` shows the end. It is judged in the geometry the position was last applied to: a viewport resize\n * not yet handled, and items appended while the reader scrolls away from the end, do not count yet.\n */\n const reachesEnd = (top: number) =>\n hi === list.length && !props.hasNewer && (appendedFrom >= 0 ? offsetOf(appendedFrom) : total()) - (top + lastHeight) <= END_TOLERANCE;\n\n const deferring = () => fingers.size > 0 || scrolling;\n /**\n * Whether the rows may stand in for the logical position `top` while the reader scrolls. Near the start they may\n * not: rows moved down would show empty space above the first item, and rows moved up would put the first items\n * out of the scroll range's reach. The margin is the overscan, so the write lands before the engine draws there.\n */\n const mayDefer = (top: number) => deferring() && Math.min(viewport.scrollTop, top) > OVERSCAN;\n /** Scrolls to `target`, within what the layout can reach, and returns the position the reader gets. */\n const writeTop = (target: number, immediate: boolean) => {\n const next = Math.min(Math.max(0, total() - viewport.clientHeight), Math.max(0, target));\n if (!immediate && mayDefer(next)) {\n // The rows move instead; the scroll range stays the same, so the engine clamps nothing.\n lastTop = viewport.scrollTop;\n deferred = next - lastTop;\n feed.style.height = `${total() - deferred}px`;\n return next;\n }\n deferred = 0;\n feed.style.height = `${total()}px`;\n const from = viewport.scrollTop;\n if (Math.abs(from - next) > 0.5) viewport.scrollTop = next;\n lastTop = viewport.scrollTop;\n if (Math.abs(lastTop - from) > 0.5) owedUntil = performance.now() + END_WAIT_MS;\n return next;\n };\n\n let visibleKeys: { first: string; last: string } | null | undefined;\n const reportVisible = () => {\n if (!props.onVisibleChange) return;\n const top = logicalTop();\n const bottom = top + viewport.clientHeight;\n let first = -1;\n let last = -1;\n if (bottom > top && hi > lo)\n for (let index = indexAt(top); index < hi && offsetOf(index) < bottom; index++) {\n const from = offsetOf(index);\n const to = offsetOf(index + 1);\n // Rounded scroll positions may cut a fully shown item by a fraction of a pixel.\n if ((from > top - VISIBLE_TOLERANCE && to < bottom + VISIBLE_TOLERANCE) || (from <= top && to >= bottom)) {\n if (first < 0) first = index;\n last = index;\n }\n }\n const next = first < 0 ? null : { first: keys[first]!, last: keys[last]! };\n if (visibleKeys !== undefined && next?.first === visibleKeys?.first && next?.last === visibleKeys?.last) return;\n visibleKeys = next;\n props.onVisibleChange(first < 0 ? null : { first: list[first]!, last: list[last]! });\n };\n\n const updateRange = () => {\n const top = logicalTop();\n const height = viewport.clientHeight;\n const indices: number[] = [];\n if (hi > lo) {\n const start = indexAt(top - OVERSCAN);\n const end = indexAt(top + height + OVERSCAN);\n // The focused row stays mounted wherever it is, so focus never falls back to the document.\n const focused = focusIndex >= lo && focusIndex < hi;\n if (focused && focusIndex < start) indices.push(focusIndex);\n for (let index = start; index <= end; index++) indices.push(index);\n if (focused && focusIndex > end) indices.push(focusIndex);\n }\n renderRows(indices);\n setTabStop(focusIndex >= lo && focusIndex < hi ? focusIndex : hi > lo ? indexAt(top + height - 1) : -1);\n // Newly mounted rows still have estimates; report only after their heights are measured.\n if (!restoring && !fresh.some((node) => node.isConnected)) reportVisible();\n };\n\n const measure = (measured: ReadonlyArray<readonly [HTMLElement, number]>) => {\n let changed = false;\n for (const [node, size] of measured) {\n const row = rowOf.get(node);\n if (!row || row.index < lo || row.index >= hi) continue;\n const index = row.index;\n // The anchor keeps the content of its row in place: a separator or marker that appears or goes away above it\n // moves the row's top instead.\n const lead = leadOf(node);\n if (!stick && index === anchor.index && row.lead !== undefined) anchor = { index, delta: anchor.delta + row.lead - lead };\n row.lead = lead;\n if (Math.abs(sizes[index]! - size) > 0.1) {\n sizes[index] = size;\n dirtyFrom = Math.min(dirtyFrom, index - lo);\n changed = true;\n }\n }\n return changed;\n };\n\n const position = (index: number) =>\n props.firstPosition !== undefined ? props.firstPosition + index : props.hasOlder ? undefined : index + 1;\n const setSize = () => props.totalCount ?? (props.hasOlder || props.hasNewer ? -1 : count());\n\n const createRow = (item: T, key: string, at: number): Row<T> =>\n createRoot((dispose) => {\n const [index, setIndex] = createSignal(at);\n // While older items may come, the first loaded item's predecessor is unknown, so it gets no separator yet.\n const separator = () => (listVersion(), index() === 0 && props.hasOlder ? undefined : props.separator?.(item, list[index() - 1]));\n // Created once, as Solid's For does, so signals that the content reads while rendering never rebuild it.\n const content = untrack(() => props.children(item, index));\n const node = (\n <div\n class=\"k2b-virtual-feed__item\"\n role=\"article\"\n data-index={index()}\n data-key={key}\n data-highlighted={highlighted() === key ? \"\" : undefined}\n tabindex={index() === tabStop() ? 0 : -1}\n aria-label={props.itemLabel?.(item)}\n aria-posinset={position(index())}\n aria-setsize={setSize()}\n style={{ transform: `translateY(${(version(), offsetOf(index()) - deferred)}px)` }}\n >\n <Show when={separator()}>\n {(content) => (\n <div class=\"k2b-virtual-feed__separator\">\n <span>{content()}</span>\n </div>\n )}\n </Show>\n <Show when={props.markerKey === key}>\n <div class=\"k2b-virtual-feed__marker\">\n <span>{props.markerLabel ?? feedMessages().feedNewMarker}</span>\n </div>\n </Show>\n {content}\n </div>\n ) as HTMLElement;\n const row: Row<T> = {\n item,\n node,\n index: at,\n setIndex: (next) => {\n row.index = next;\n setIndex(next);\n },\n dispose,\n };\n return row;\n }, owner);\n\n /** Mounts exactly these items in this order; rows that stay keep their node in place. */\n const renderRows = (indices: readonly number[]) => {\n const wanted = new Map<string, number>();\n for (const index of indices) wanted.set(keys[index]!, index);\n const active = feed.contains(document.activeElement) ? (document.activeElement as HTMLElement) : undefined;\n let focusedKey: string | undefined;\n for (const [key, row] of rows) {\n const index = wanted.get(key);\n if (index !== undefined && list[index] === row.item) continue;\n if (active && row.node.contains(active)) focusedKey = key;\n unobserveRow(row.node);\n row.node.remove();\n row.dispose();\n rows.delete(key);\n }\n let cursor = feed.firstChild;\n for (const index of indices) {\n const key = keys[index]!;\n let row = rows.get(key);\n if (row) row.setIndex(index);\n else {\n row = createRow(list[index]!, key, index);\n rows.set(key, row);\n rowOf.set(row.node, row);\n observeRow(row.node);\n fresh.push(row.node);\n }\n if (row.node === cursor) cursor = cursor.nextSibling;\n else feed.insertBefore(row.node, cursor);\n }\n // A reordered item moves its node, which blurs it, and a replaced item gets a new row: focus stays on the item.\n // Only when the item is gone does it fall back to the scroll area.\n if (active && document.activeElement !== active) {\n const replaced = focusedKey === undefined ? undefined : rows.get(focusedKey)?.node;\n (active.isConnected ? active : (replaced ?? viewport)).focus({ preventScroll: true });\n }\n };\n\n /**\n * Puts the reading position back after sizes, items, or the viewport changed: the end while following it, the\n * anchor otherwise. While the reader scrolls, it moves the rows instead of the scroll position, except for\n * `immediate` corrections, which follow structural changes and jumps.\n */\n const restore = (immediate = false) => {\n if (!viewport) return;\n if (restoring) {\n restoreAgain = true;\n return;\n }\n restoring = true;\n let target = 0;\n let top = 0;\n // Following the end shows the end of all items from now on, so later moves are judged against it.\n if (stick) appendedFrom = -1;\n try {\n for (let pass = 0; ; pass++) {\n restoreAgain = false;\n recompute();\n target = stick ? total() : offsetOf(anchor.index) - anchor.delta;\n top = writeTop(target, immediate);\n updateRange();\n setVersion((value) => value + 1);\n if (pass === MEASURE_PASSES) break;\n // Rows mounted here reach the ResizeObserver only next frame (its loop limit), so measure them now.\n const mounted = fresh.filter((node) => node.isConnected);\n fresh = [];\n if (measure(mounted.map((node) => [node, node.getBoundingClientRect().height] as const))) restoreAgain = true;\n if (!restoreAgain) break;\n }\n // A position the layout cannot reach, above its start or past its end, becomes the one the reader sees, so a\n // page that loads there later keeps it instead of moving to it.\n if (!stick && Math.abs(top - target) > 0.5) anchor = { index: anchor.index, delta: offsetOf(anchor.index) - top };\n } finally {\n restoring = false;\n }\n checkEdges();\n reportVisible();\n };\n\n /**\n * Keeps the reader's new position, reached from `from`. A row that the move reveals at the top can change size in the\n * same frame, before the feed measured it, and the reader never saw it. So the row at the top of `from` keeps its\n * place while it is still in view, and the rows the reader saw move by the reader's step alone.\n */\n const captureAnchor = (from: number) => {\n const top = logicalTop();\n setStick(reachesEnd(top));\n const seen = indexAt(from);\n anchor =\n offsetOf(seen + 1) > top && offsetOf(seen) < top + viewport.clientHeight\n ? { index: seen, delta: offsetOf(seen) - top }\n : anchorAt(top);\n };\n\n /**\n * Whether scrollTop moved since the feed last wrote or accounted for it. When a size change shortens the scroll\n * range, the engine clamps the position onto the new end; that move is the size change, not the reader.\n */\n const readerMoved = () => {\n const top = viewport.scrollTop;\n if (Math.abs(top - lastTop) <= 0.5) return false;\n const end = viewport.scrollHeight - viewport.clientHeight;\n return !(lastTop > end + 1 && Math.abs(top - end) <= 1);\n };\n\n /**\n * Takes a scroll position the feed did not make as the reader's, whatever moved it: touch, momentum, wheel, keys,\n * the scrollbar, focus, scrollIntoView, find in page, or assistive technology. Returns whether there was one.\n */\n const noteReader = () => {\n if (!readerMoved()) return false;\n lastMove = performance.now();\n if (overriding) {\n // Momentum left from before a jump of the application does not take the reader away again.\n armEnd(QUIET_MS);\n restore(true);\n return false;\n }\n armEnd();\n const from = lastTop + deferred;\n lastTop = viewport.scrollTop;\n scrolling = true;\n captureAnchor(from);\n return true;\n };\n\n const armEnd = (ms = hasScrollEnd ? END_WAIT_MS : QUIET_MS) => {\n clearTimeout(endTimer);\n endTimer = setTimeout(() => {\n endTimer = undefined;\n // A finger holds the scroll until it lifts; a move without its scroll event yet continues it.\n if (fingers.size > 0) return;\n if (readerMoved()) noteReader();\n else endScroll();\n }, ms);\n };\n\n /** The reader's scroll ended: what it held back is written in one step that moves nothing the reader sees. */\n const endScroll = () => {\n clearTimeout(endTimer);\n endTimer = undefined;\n scrolling = false;\n overriding = false;\n appendedFrom = -1;\n restore();\n };\n\n /**\n * A jump of the application ends the reader's scroll in progress: the jump lands at once, and what is left of the\n * momentum is put back until it has been still for a quiet time, or the reader touches, wheels, clicks, or presses\n * a key. A scrollend does not end this: a momentum stopped by the engine can still deliver a step in flight.\n */\n const takeOver = () => {\n appendedFrom = -1;\n if (!scrolling || fingers.size > 0) return;\n scrolling = false;\n overriding = true;\n lastMove = performance.now();\n armEnd(QUIET_MS);\n // A scroller that cannot scroll drops its momentum where the engine allows that. It scrolls again after a frame\n // in which nothing was left to put back.\n viewport.style.overflowY = \"hidden\";\n let seen = Number.NaN;\n const check = () => {\n if (disposed) return;\n if (overriding && lastMove !== seen) {\n seen = lastMove;\n requestAnimationFrame(check);\n } else viewport.style.removeProperty(\"overflow-y\");\n };\n requestAnimationFrame(check);\n };\n\n /** Lays out a window of about half the maximum around `center`. */\n const windowAround = (center: number) => {\n lo = center;\n hi = center + 1;\n let height = sizes[center]!;\n while (height < MAX_WINDOW / 2 && (lo > 0 || hi < list.length)) {\n if (lo > 0 && (center - lo <= hi - 1 - center || hi >= list.length)) height += sizes[--lo]!;\n else height += sizes[hi++]!;\n }\n dirtyFrom = 0;\n };\n\n const dropFocus = () => {\n if (focusIndex >= lo && focusIndex < hi) return;\n const focused = rows.get(keys[focusIndex] ?? \"\")?.node;\n focusIndex = -1;\n if (focused?.contains(document.activeElement)) viewport.focus({ preventScroll: true });\n };\n\n /**\n * Drops items from one side of the window, never those around the reading position, until it fits again. Returns\n * whether it dropped any.\n */\n const trimWindow = (side: \"start\" | \"end\") => {\n recompute();\n let excess = total() - MAX_WINDOW;\n if (excess <= 0) return false;\n const [from, to] = [lo, hi];\n const height = viewport.clientHeight;\n const top = stick ? total() - height : offsetOf(anchor.index) - anchor.delta;\n // While following the end the anchor is not maintained; only the visible end counts.\n const first = Math.min(indexAt(top - height - OVERSCAN), stick ? hi : anchor.index);\n const last = Math.max(indexAt(top + 2 * height + OVERSCAN), stick ? lo : anchor.index);\n if (side === \"start\") while (excess > 0 && lo < first) excess -= sizes[lo++]!;\n else while (excess > 0 && hi - 1 > last) excess -= sizes[--hi]!;\n dirtyFrom = 0;\n dropFocus();\n return lo !== from || hi !== to;\n };\n\n const loadNewest = () => {\n if (loadingOlder() || loadingNewer()) {\n newest = \"waiting\";\n return;\n }\n newest = \"loading\";\n load(\"newest\");\n };\n\n const load = (direction: \"older\" | \"newer\" | \"newest\") => {\n const setLoading = direction === \"older\" ? setLoadingOlder : setLoadingNewer;\n const callback = direction === \"older\" ? props.onLoadOlder : direction === \"newer\" ? props.onLoadNewer : props.onLoadNewest;\n if (!callback) return;\n // A load succeeded when its edge moved; other changes to `items` meanwhile do not count.\n const edge = () => (direction === \"older\" ? keys[0] : keys[keys.length - 1]);\n const before = edge();\n setLoading(true);\n let result: unknown;\n try {\n result = callback();\n } catch {\n result = undefined;\n }\n void Promise.resolve(result)\n .catch(() => undefined)\n .then(() => {\n setLoading(false);\n if (disposed) return;\n if (direction === \"newest\") newest = undefined;\n if (newest === \"waiting\") {\n if (!loadingOlder() && !loadingNewer()) loadNewest();\n return;\n }\n const arrived = edge() !== before;\n // A failed or empty load toward the end shows \"Jump to latest\" again instead of following an end that never came.\n if (direction !== \"older\" && !arrived && stick && props.hasNewer) setStick(false);\n // Keep loading while the reader still sits at the edge and the last page arrived.\n if (arrived) checkEdges();\n });\n };\n\n /** Grows the window or asks for more items when the reader nears an edge. */\n const checkEdges = () => {\n if (hi <= lo || restoring) return;\n const top = logicalTop();\n const height = viewport.clientHeight;\n // Rows measured taller than estimated can grow the window past the cap without any edge moving.\n if (total() > MAX_WINDOW && trimWindow(top + height / 2 > total() / 2 ? \"start\" : \"end\")) {\n restore(true);\n return;\n }\n const margin = Math.max(2_000, 3 * height);\n if (top < margin) {\n if (lo > 0) {\n let added = 0;\n while (lo > 0 && added < WINDOW_STEP) added += sizes[--lo]!;\n dirtyFrom = 0;\n trimWindow(\"end\");\n restore(true);\n return;\n }\n if (props.hasOlder && !loadingOlder() && !newest) load(\"older\");\n }\n if (total() - top - height < margin) {\n if (hi < list.length) {\n let added = 0;\n while (hi < list.length && added < WINDOW_STEP) added += sizes[hi++]!;\n dirtyFrom = 0;\n trimWindow(\"start\");\n restore(true);\n return;\n }\n if (props.hasNewer && !loadingNewer() && !newest) load(\"newer\");\n }\n };\n\n const queueAnnouncement = (added: readonly T[]) => {\n pendingAnnouncement = pendingAnnouncement.concat(added);\n if (announceTimer !== undefined) return;\n announceTimer = setTimeout(() => {\n announceTimer = undefined;\n const batch = pendingAnnouncement;\n pendingAnnouncement = [];\n const text = props.announce ? props.announce(batch) : feedMessages().feedNewItems({ count: batch.length });\n if (!text) return;\n const line = document.createElement(\"p\");\n line.textContent = text;\n log.append(line);\n while (log.childElementCount > 3) log.firstElementChild?.remove();\n }, ANNOUNCE_MS);\n };\n\n /** Applies a new `items` array: appends follow the end, prepends and other changes keep the anchor by key. */\n const sync = (next: readonly T[]) => {\n // The reader may have scrolled in this frame before its scroll event ran; take that position first.\n if (keys.length > 0) noteReader();\n const length = next.length;\n const nextKeys = next.map(props.getKey);\n const previous = keys.length;\n const focusKey = focusIndex >= 0 ? keys[focusIndex] : undefined;\n let added: readonly T[] = [];\n let appended = false;\n /** A new feed, or one that shares no item with the last: start at its end. */\n const reset = () => {\n sizes = Float64Array.from(next, estimate);\n focusIndex = -1;\n appendedFrom = -1;\n setStick(!props.hasNewer);\n anchor = { index: 0, delta: 0 };\n setUnseen(0);\n // Pending announcements describe the items that are gone.\n clearTimeout(announceTimer);\n announceTimer = undefined;\n pendingAnnouncement = [];\n list = next;\n if (sizes.reduce((sum, size) => sum + size, 0) <= MAX_WINDOW) {\n lo = 0;\n hi = length;\n } else windowAround(length - 1);\n };\n if (previous === 0 || length === 0) reset();\n else if (length >= previous && runsMatch(keys, nextKeys, 0)) {\n const grown = new Float64Array(length);\n grown.set(sizes);\n for (let index = previous; index < length; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n if (hi === previous) hi = length;\n appended = true;\n // Away from the end, the reader's scroll in progress still reaches the end it was heading for.\n if (!stick && deferring() && appendedFrom < 0) appendedFrom = previous;\n // Only items after the newest one the feed has known are new; older pages toward the end are history.\n const known = endKey === undefined ? -1 : nextKeys.lastIndexOf(endKey);\n if (known >= 0) added = next.slice(Math.max(previous, known + 1));\n } else if (length >= previous && runsMatch(keys, nextKeys, length - previous)) {\n const shift = length - previous;\n const grown = new Float64Array(length);\n grown.set(sizes, shift);\n for (let index = 0; index < shift; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n anchor = { index: anchor.index + shift, delta: anchor.delta };\n if (focusIndex >= 0) focusIndex += shift;\n if (appendedFrom >= 0) appendedFrom += shift;\n if (lo > 0) lo += shift;\n hi += shift;\n } else {\n const known = new Map<string, number>();\n for (let index = 0; index < previous; index++) known.set(keys[index]!, sizes[index]!);\n const position = new Map<string, number>();\n for (let index = 0; index < length; index++) position.set(nextKeys[index]!, index);\n if (!nextKeys.some((key) => known.has(key))) reset();\n else {\n sizes = new Float64Array(length);\n for (let index = 0; index < length; index++) sizes[index] = known.get(nextKeys[index]!) ?? estimate(next[index]!);\n // An item that is gone hands its role to the nearest surviving neighbor.\n const survivor = (from: number) => {\n for (let distance = 0; distance < previous; distance++) {\n const below = position.get(keys[from + distance] ?? \"\");\n if (below !== undefined) return below;\n const above = position.get(keys[from - distance] ?? \"\");\n if (above !== undefined) return above;\n }\n return length - 1;\n };\n const wasAtStart = lo === 0;\n const wasAtEnd = hi === previous;\n appendedFrom = -1;\n anchor = { index: survivor(anchor.index), delta: anchor.delta };\n focusIndex = focusKey === undefined ? -1 : (position.get(focusKey) ?? -1);\n lo = wasAtStart ? 0 : survivor(lo);\n hi = wasAtEnd ? length : survivor(hi - 1) + 1;\n if (anchor.index < lo || anchor.index >= hi) {\n list = next;\n windowAround(anchor.index);\n }\n }\n }\n list = next;\n keys = nextKeys;\n dirtyFrom = 0;\n setCount(length);\n setListVersion((value) => value + 1);\n if (!props.hasNewer) endKey = nextKeys[length - 1];\n recompute();\n const center = stick ? hi - 1 : anchor.index;\n const trimmed = total() > MAX_WINDOW && trimWindow(center - lo > hi - 1 - center ? \"start\" : \"end\");\n // Appended items wait for the reader's scroll to end like other size changes; the rows show them meanwhile.\n restore(!appended || trimmed);\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n if (added.length > 0) {\n if (!stick) setUnseen((value) => value + added.length);\n queueAnnouncement(added);\n }\n };\n\n /**\n * Follows the end. With newer items not loaded, `onLoadNewest` replaces the items, after any running load; without\n * it, following the end keeps `onLoadNewer` paging until the newest item arrives or the reader scrolls away.\n */\n const scrollToEnd = () => {\n takeOver();\n setStick(!props.hasNewer || Boolean(props.onLoadNewer || props.onLoadNewest));\n if (props.hasNewer && props.onLoadNewest) loadNewest();\n if (hi < list.length) windowAround(list.length - 1);\n restore(true);\n };\n\n const scrollToKey = (key: string, options: VirtualFeedScrollOptions = {}) => {\n const index = keys.indexOf(key);\n if (index < 0) return false;\n takeOver();\n if (index < lo || index >= hi) windowAround(index);\n recompute();\n const delta = () => (options.align === \"start\" ? 0 : Math.max(0, (viewport.clientHeight - sizes[index]!) / 2));\n setStick(false);\n anchor = { index, delta: delta() };\n restore(true);\n // The row was measured while mounting, before this frame paints; center it on its real height.\n if (anchor.index === index && anchor.delta !== delta()) {\n anchor = { index, delta: delta() };\n restore(true);\n }\n if (reachesEnd(logicalTop())) setStick(true);\n if (options.highlight) {\n clearTimeout(highlightTimer);\n setHighlighted(key);\n highlightTimer = setTimeout(() => setHighlighted(undefined), HIGHLIGHT_MS);\n }\n return true;\n };\n\n const focusRow = (target: number) => {\n if (list.length === 0) return;\n const index = Math.min(list.length - 1, Math.max(0, target));\n // An edge load during the restore may add items synchronously and shift indices; the key keeps the target.\n const key = keys[index]!;\n const outside = index < lo || index >= hi;\n if (outside) windowAround(index);\n recompute();\n focusIndex = index;\n const top = logicalTop();\n const height = viewport.clientHeight;\n const start = offsetOf(index);\n const size = sizes[index]!;\n if (index === list.length - 1 && hi === list.length && !props.hasNewer) setStick(true);\n else if (outside) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start < top) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start + size > top + height) {\n setStick(false);\n anchor = { index, delta: Math.max(0, height - size) };\n restore(true);\n // The row was measured while mounting; align its real bottom before this frame paints.\n if (anchor.index === focusIndex) anchor = { index: focusIndex, delta: Math.max(0, height - sizes[focusIndex]!) };\n }\n restore(true);\n rows.get(key)?.node.focus({ preventScroll: true });\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const row = rowOf.get(event.target as Element);\n if (!row) return;\n const index = row.index;\n if (event.key === \"ArrowUp\" || event.key === \"PageUp\") focusRow(index - 1);\n else if (event.key === \"ArrowDown\" || event.key === \"PageDown\") focusRow(index + 1);\n else if (event.key === \"Home\" && event.ctrlKey) focusRow(0);\n else if (event.key === \"End\" && event.ctrlKey) {\n scrollToEnd();\n focusRow(list.length - 1);\n } else return;\n event.preventDefault();\n };\n\n const onScroll = () => {\n // The feed checked its edges when it wrote scrollTop. Its own scroll event arrives a frame later, and checking again\n // then would retry a load that failed in between.\n const reader = noteReader();\n // Near the start, the rows no longer stand in for a held-back correction; it is written now.\n if (deferred !== 0 && !mayDefer(logicalTop())) restore(true);\n else {\n updateRange();\n if (reader) checkEdges();\n }\n };\n\n /**\n * Ends the reader's scroll if the feed stands still for the next two frames. A `scrollend` not counted as a write's\n * can still be the late one of an earlier write; movement after it means the scroll goes on.\n */\n const confirmEnd = () => {\n const seen = lastMove;\n requestAnimationFrame(() =>\n requestAnimationFrame(() => {\n if (disposed || fingers.size > 0 || !scrolling || lastMove !== seen || readerMoved()) return;\n endScroll();\n }),\n );\n };\n\n const onScrollEnd = () => {\n // The scrollend of the feed's own write, not the end of the reader's scroll.\n if (performance.now() < owedUntil) {\n owedUntil = 0;\n return;\n }\n endedAt = performance.now();\n if (fingers.size > 0 || !scrolling) return;\n confirmEnd();\n };\n\n const controller: VirtualFeedController = {\n scrollToKey,\n scrollToEnd,\n isAtEnd: () => stick,\n };\n\n // Created before the first sync below, so items that an edge load adds synchronously during it are not lost.\n createEffect(on(() => props.items, sync, { defer: true }));\n // More items can appear at an edge without new items, for example when a live update reports newer ones.\n createEffect(\n on(\n [() => props.hasOlder, () => props.hasNewer],\n () => {\n if (!props.hasNewer) endKey = keys[keys.length - 1];\n if (hi <= lo) return;\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n // Only newer pages can be followed; with just `onLoadNewest`, \"Jump to latest\" has to show.\n else if (stick && props.hasNewer && !props.onLoadNewer) setStick(false);\n checkEdges();\n },\n { defer: true },\n ),\n );\n\n onMount(() => {\n hasScrollEnd = \"onscrollend\" in window;\n lastHeight = viewport.clientHeight;\n const observer = new ResizeObserver((entries) => {\n observing = true;\n try {\n // A scroll of the reader in this frame counts first, in the geometry from before these changes.\n noteReader();\n fresh = [];\n let resized = false;\n const measured: Array<readonly [HTMLElement, number]> = [];\n for (const entry of entries) {\n if (entry.target === viewport) {\n // A shorter viewport (a growing footer or keyboard) keeps what is at its bottom in place.\n const height = viewport.clientHeight;\n if (!stick) anchor = { index: anchor.index, delta: anchor.delta + height - lastHeight };\n lastHeight = height;\n resized = true;\n } else if (entry.target.isConnected) {\n const row = entry.target as HTMLElement;\n measured.push([row, entry.borderBoxSize?.[0]?.blockSize ?? row.getBoundingClientRect().height]);\n }\n }\n if (measure(measured) || resized) restore();\n else reportVisible();\n } finally {\n observing = false;\n }\n });\n observer.observe(viewport);\n // Rows observed inside the observer's own callback miss its first notification, which raises a window error.\n // They were measured while mounting, so they are observed from the next frame on.\n let later: HTMLElement[] = [];\n let laterFrame = 0;\n observeRow = (row) => {\n if (!observing) return observer.observe(row);\n later.push(row);\n laterFrame ||= requestAnimationFrame(() => {\n laterFrame = 0;\n for (const node of later) if (node.isConnected) observer.observe(node);\n later = [];\n });\n };\n unobserveRow = (row) => observer.unobserve(row);\n const release = () => {\n for (const target of touched) {\n target.removeEventListener(\"touchend\", touchEnd);\n target.removeEventListener(\"touchcancel\", touchEnd);\n }\n touched.clear();\n };\n // Input of the reader ends a takeover by the application at once, and lets the feed scroll for that input.\n const act = () => {\n overriding = false;\n viewport.style.removeProperty(\"overflow-y\");\n };\n const touchStart = (event: TouchEvent) => {\n // A touch whose end the feed missed has left the screen by now.\n const down = new Set(Array.from(event.touches, (touch) => touch.identifier));\n for (const id of fingers) if (!down.has(id)) fingers.delete(id);\n for (const touch of Array.from(event.changedTouches)) fingers.add(touch.identifier);\n act();\n // Touch events stay with the element the touch began on, also when the feed removes its row meanwhile.\n const target = event.target;\n if (target && !touched.has(target)) {\n touched.add(target);\n target.addEventListener(\"touchend\", touchEnd, { passive: true });\n target.addEventListener(\"touchcancel\", touchEnd, { passive: true });\n }\n };\n function touchEnd(event: Event) {\n for (const touch of Array.from((event as TouchEvent).changedTouches)) fingers.delete(touch.identifier);\n if (fingers.size > 0) return;\n release();\n // The last step of a short flick can have moved scrollTop before its scroll event; it counts before anything ends.\n if (!scrolling && !noteReader()) return endScroll();\n armEnd();\n // A scroll that ended under the finger ends now, unless the release starts a momentum.\n if (endedAt >= lastMove) confirmEnd();\n }\n viewport.addEventListener(\"touchstart\", touchStart, { passive: true });\n viewport.addEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.addEventListener(type, act, { passive: true });\n onCleanup(() => {\n disposed = true;\n observer.disconnect();\n cancelAnimationFrame(laterFrame);\n viewport.removeEventListener(\"touchstart\", touchStart);\n viewport.removeEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.removeEventListener(type, act);\n release();\n clearTimeout(endTimer);\n clearTimeout(announceTimer);\n clearTimeout(highlightTimer);\n for (const row of rows.values()) row.dispose();\n rows.clear();\n });\n sync(props.items);\n props.controller?.(controller);\n });\n\n const shownCount = () => props.newCount ?? unseen();\n\n return (\n <div class={props.class ? `k2b-virtual-feed ${props.class}` : \"k2b-virtual-feed\"}>\n <div ref={viewport} class=\"k2b-virtual-feed__viewport\" tabindex=\"-1\" onScroll={onScroll}>\n <div\n ref={feed}\n class=\"k2b-virtual-feed__feed\"\n role=\"feed\"\n aria-label={props.label}\n aria-busy={props.busy || loadingOlder() || loadingNewer() ? \"true\" : \"false\"}\n onKeyDown={onKeyDown}\n onFocusIn={(event) => {\n const node = (event.target as HTMLElement).closest(\".k2b-virtual-feed__item\");\n const row = node ? rowOf.get(node) : undefined;\n if (row) {\n focusIndex = row.index;\n setTabStop(focusIndex);\n }\n }}\n onFocusOut={(event) => {\n const next = event.relatedTarget as Node | null;\n if (next && !feed.contains(next)) focusIndex = -1;\n }}\n />\n </div>\n <Show when={count() === 0 && props.empty}>\n <div class=\"k2b-virtual-feed__empty\">{props.empty}</div>\n </Show>\n <Show when={loadingOlder()}>\n <div class=\"k2b-virtual-feed__status\" aria-hidden=\"true\">\n <i class=\"ti ti-loader-2 k2b-spin\" />\n {messages().loading}\n </div>\n </Show>\n <Show when={!atEnd() && count() > 0}>\n <button\n type=\"button\"\n class=\"k2b-virtual-feed__end\"\n aria-label={shownCount() > 0 ? feedMessages().feedJumpToLatestCount({ count: shownCount() }) : undefined}\n onClick={() => {\n scrollToEnd();\n // The button disappears at the end; keep focus in the feed instead of the document.\n if (props.hasNewer) viewport.focus({ preventScroll: true });\n else focusRow(list.length - 1);\n }}\n >\n <i class={loadingNewer() ? \"ti ti-loader-2 k2b-spin\" : \"ti ti-arrow-down\"} aria-hidden=\"true\" />\n {feedMessages().feedJumpToLatest}\n <Show when={shownCount() > 0}>\n <span class=\"k2b-virtual-feed__count\" aria-hidden=\"true\">\n {shownCount()}\n </span>\n </Show>\n </button>\n </Show>\n <div ref={log} class=\"k2b-sr-only\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\" />\n </div>\n );\n}\n\nexport default VirtualFeed;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/VirtualFeed.tsx"],"sourcesContent":["import { type Accessor, createEffect, createRoot, createSignal, getOwner, type JSX, on, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { useFeedMessages } from \"./feed-messages\";\n\n/**\n * The tallest loaded window in px. Firefox renders an element taller than about 17.9 M px with a height of 0, so the\n * feed lays out at most this much and drops far items while it keeps the reading position.\n */\nconst MAX_WINDOW = 8_000_000;\n/** How much the loaded window grows at once when the reader nears one of its edges. */\nconst WINDOW_STEP = 2_000_000;\n/** Rows rendered above and below the visible part, in px. */\nconst OVERSCAN = 600;\n/** Distance from the end, in px, that still counts as being at the end. */\nconst END_TOLERANCE = 2;\n/** Part of an item, in px, that may be cut off while it still counts as fully in view: rounding, not a hidden line. */\nconst VISIBLE_TOLERANCE = 1;\n/**\n * Rows mounted during one correction reach the ResizeObserver a frame late; measure up to this many passes at once.\n * A last pass places the rows; the observer measures what that pass mounted.\n */\nconst MEASURE_PASSES = 4;\nconst ANNOUNCE_MS = 1_000;\nconst HIGHLIGHT_MS = 1_600;\n/** In engines without `scrollend`, the reader's scroll has ended after this long without moving. */\nconst QUIET_MS = 300;\n/** The longest wait for the `scrollend` of the reader's scroll after it last moved, or of a write of the feed. */\nconst END_WAIT_MS = 1_000;\n\nexport type VirtualFeedScrollOptions = {\n /** Where the item lands in the visible area. Defaults to `\"center\"`. */\n align?: \"start\" | \"center\";\n /** Tints the item briefly so the reader finds it. */\n highlight?: boolean;\n};\n\nexport type VirtualFeedController = {\n /**\n * Scrolls to a loaded item, also when the reader's scroll still coasts. Returns false when no loaded item has this\n * key, so the caller can load around it first.\n */\n scrollToKey: (key: string, options?: VirtualFeedScrollOptions) => boolean;\n /**\n * Follows the end again, also when the reader's scroll still coasts. When newer items exist but are not loaded, it\n * asks `onLoadNewest` for them first.\n */\n scrollToEnd: () => void;\n /** Whether the reader is at the end and new items keep the feed there. */\n isAtEnd: () => boolean;\n};\n\nexport type VirtualFeedProps<T> = {\n /** Loaded items, oldest first. Replace the array to add, remove, or change items. */\n items: readonly T[];\n /** Stable, unique identity of an item across updates. */\n getKey: (item: T) => string;\n /** Height in px before the item was measured. Close estimates mean fewer corrections while scrolling. */\n estimateSize: (item: T) => number;\n /** Content of one item, created once per item object as with Solid's `For`. `index` is its position in `items`. */\n children: (item: T, index: Accessor<number>) => JSX.Element;\n /** Accessible name of the feed. */\n label: string;\n /** Accessible name of one item, for example its author and time. */\n itemLabel?: (item: T) => string | undefined;\n /**\n * Label shown above an item, for example when the day changes. Return nothing for no separator. While `hasOlder` is\n * set, the first loaded item has no known predecessor and gets none.\n */\n separator?: (item: T, previous: T | undefined) => JSX.Element;\n /** Key of the first item the reader has not seen; a marker appears above it. */\n markerKey?: string | null;\n /** Text of that marker. Defaults to \"New\". */\n markerLabel?: string;\n /** Older items exist that `items` does not contain yet. */\n hasOlder?: boolean;\n /** Newer items exist that `items` does not contain yet. */\n hasNewer?: boolean;\n /** Called near the start of the loaded items while `hasOlder` is true. Prepend the next older page to `items`. */\n onLoadOlder?: () => unknown;\n /** Called near the end of the loaded items while `hasNewer` is true. Append the next newer page to `items`. */\n onLoadNewer?: () => unknown;\n /** Called by \"Jump to latest\" while `hasNewer` is true. Replace `items` with the newest page. */\n onLoadNewest?: () => unknown;\n /** Marks the feed as busy for assistive technology, for example during the first load. */\n busy?: boolean;\n /** Number of items in the whole feed when known. */\n totalCount?: number;\n /** One-based position of `items[0]` in the whole feed when known. */\n firstPosition?: number;\n /**\n * Count shown on \"Jump to latest\". Defaults to the new items added while the reader was away from the end, which\n * excludes pages of older history loaded toward the end.\n */\n newCount?: number;\n /** Text announced for new items added at the end, bundled per second. Return nothing to stay silent. */\n announce?: (added: readonly T[]) => string | undefined;\n /** Called when the reader reaches or leaves the end. */\n onEndChange?: (atEnd: boolean) => void;\n /**\n * Called when the items in view change: the first and last item whose whole height is in view. An item taller\n * than the view counts while it covers the view. `null` while no item is in view.\n */\n onVisibleChange?: (visible: { first: T; last: T } | null) => void;\n /** Receives the controller once the feed is mounted. */\n controller?: (controller: VirtualFeedController) => void;\n /** Shown while `items` is empty. */\n empty?: JSX.Element;\n class?: string;\n};\n\n/**\n * One mounted row. Rows are created and removed but never moved, so focus, media, and frames inside them survive.\n * `lead` is the measured height of the separator and marker above the content.\n */\ntype Row<T> = { item: T; node: HTMLElement; index: number; lead?: number; setIndex: (index: number) => void; dispose: () => void };\n\nconst runsMatch = (before: readonly string[], after: readonly string[], shift: number) => {\n for (let index = 0; index < before.length; index++) if (before[index] !== after[index + shift]) return false;\n return true;\n};\n\n/** Height of the separator and marker that a row shows above its content. */\nconst leadOf = (node: HTMLElement) => {\n let height = 0;\n for (const child of node.children) {\n if (!child.classList.contains(\"k2b-virtual-feed__separator\") && !child.classList.contains(\"k2b-virtual-feed__marker\")) break;\n height += child.getBoundingClientRect().height;\n }\n return height;\n};\n\n/**\n * A virtualized feed of items with variable heights that grows at both ends and keeps the reading position: it stays\n * at the end while the reader is there, and otherwise keeps the item in view where it is, whatever loads, grows, or\n * resizes around it.\n */\nexport function VirtualFeed<T>(props: VirtualFeedProps<T>): JSX.Element {\n const messages = useUiMessages();\n const feedMessages = useFeedMessages();\n let viewport!: HTMLDivElement;\n let feed!: HTMLDivElement;\n let log!: HTMLDivElement;\n\n // Layout: one size per item and prefix sums over the loaded window [lo, hi).\n let list: readonly T[] = [];\n let keys: string[] = [];\n let sizes = new Float64Array(0);\n let lo = 0;\n let hi = 0;\n let offsets = new Float64Array(1);\n let dirtyFrom = 0;\n\n // Reading position: follow the end, or keep one item (index) at a pixel distance (delta) below the visible top.\n let stick = true;\n let anchor = { index: 0, delta: 0 };\n /** Key of the last item while no newer items existed; items appended after it are new. */\n let endKey: string | undefined;\n /** The last scrollTop the feed wrote or accounted for; any other value comes from the reader. */\n let lastTop = 0;\n /** The viewport height the reading position was last applied to. */\n let lastHeight = 0;\n /**\n * While the reader scrolls, the feed does not write scrollTop, which would fight a finger, momentum, or a scroll\n * animation. It moves the rows by this much instead: the logical position minus the physical scrollTop.\n */\n let deferred = 0;\n /** Touches that began in the feed and have not ended. */\n const fingers = new Set<number>();\n /** Where those touches began. Their touchend still goes there after the feed removed the row. */\n const touched = new Set<EventTarget>();\n /** The reader's scroll runs, from its first move until its scrollend, or a quiet time where the engine has none. */\n let scrolling = false;\n /** A jump by the application ended the reader's scroll; what is left of its momentum is put back. */\n let overriding = false;\n let lastMove = 0;\n let endedAt = Number.NEGATIVE_INFINITY;\n /**\n * Until then, the next `scrollend` belongs to the feed's last write that moved the position. iOS delivers it late\n * enough to land in a later scroll of the reader, also in a pause of a slow momentum tail.\n */\n let owedUntil = 0;\n let endTimer: ReturnType<typeof setTimeout> | undefined;\n let hasScrollEnd = false;\n /** First item appended while the reader scrolls away from the end; reaching the end is judged before it. */\n let appendedFrom = -1;\n let focusIndex = -1;\n let fresh: HTMLElement[] = [];\n let restoring = false;\n let restoreVersion = 0;\n let restoreAgain = false;\n let pendingAnnouncement: T[] = [];\n let announceTimer: ReturnType<typeof setTimeout> | undefined;\n let highlightTimer: ReturnType<typeof setTimeout> | undefined;\n /** \"Jump to latest\" asked for the newest page; it waits for running loads and stops new paging until it settles. */\n let newest: \"waiting\" | \"loading\" | undefined;\n let disposed = false;\n let observeRow: (row: HTMLElement) => void = () => {};\n /** Set while the ResizeObserver callback runs. */\n let observing = false;\n let unobserveRow: (row: HTMLElement) => void = () => {};\n const owner = getOwner();\n const rows = new Map<string, Row<T>>();\n const rowOf = new WeakMap<Element, Row<T>>();\n\n const [version, setVersion] = createSignal(0);\n /** Changes with every new `items` array, so separators see a replaced predecessor. */\n const [listVersion, setListVersion] = createSignal(0);\n const [tabStop, setTabStop] = createSignal(-1);\n // Known on the server too, so the empty slot never flashes for a feed that has items.\n const [count, setCount] = createSignal(untrack(() => props.items.length));\n const [atEnd, setAtEnd] = createSignal(true);\n const [unseen, setUnseen] = createSignal(0);\n const [highlighted, setHighlighted] = createSignal<string>();\n const [loadingOlder, setLoadingOlder] = createSignal(false);\n const [loadingNewer, setLoadingNewer] = createSignal(false);\n\n const estimate = (item: T) => {\n const size = props.estimateSize(item);\n return size > 0 ? size : 1;\n };\n\n const recompute = () => {\n const length = hi - lo;\n if (offsets.length !== length + 1) {\n offsets = new Float64Array(length + 1);\n dirtyFrom = 0;\n }\n for (let j = dirtyFrom; j < length; j++) offsets[j + 1] = offsets[j]! + sizes[lo + j]!;\n dirtyFrom = length;\n };\n const total = () => offsets[hi - lo]!;\n const offsetOf = (index: number) => offsets[Math.min(hi - lo, Math.max(0, index - lo))]!;\n /** The loaded item whose bottom edge lies below `y`. */\n const indexAt = (y: number) => {\n let low = 0;\n let high = hi - lo - 1;\n while (low < high) {\n const middle = (low + high) >> 1;\n if (offsets[middle + 1]! <= y) low = middle + 1;\n else high = middle;\n }\n return lo + Math.max(0, low);\n };\n\n const anchorAt = (top: number) => {\n const index = indexAt(top);\n return { index, delta: offsetOf(index) - top };\n };\n const logicalTop = () => viewport.scrollTop + deferred;\n const setStick = (value: boolean) => {\n // The anchor is not maintained while following the end; leaving the end keeps what is visible now.\n if (stick && !value && hi > lo) anchor = anchorAt(logicalTop());\n stick = value;\n if (value) setUnseen(0);\n if (atEnd() === value) return;\n setAtEnd(value);\n props.onEndChange?.(value);\n };\n /**\n * Whether `top` shows the end. It is judged in the geometry the position was last applied to: a viewport resize\n * not yet handled, and items appended while the reader scrolls away from the end, do not count yet.\n */\n const reachesEnd = (top: number) =>\n hi === list.length && !props.hasNewer && (appendedFrom >= 0 ? offsetOf(appendedFrom) : total()) - (top + lastHeight) <= END_TOLERANCE;\n\n const deferring = () => fingers.size > 0 || scrolling;\n /**\n * Whether the rows may stand in for the logical position `top` while the reader scrolls. Near the start they may\n * not: rows moved down would show empty space above the first item, and rows moved up would put the first items\n * out of the scroll range's reach. The margin is the overscan, so the write lands before the engine draws there.\n */\n const mayDefer = (top: number, physicalTop?: number) => deferring() && Math.min(physicalTop ?? viewport.scrollTop, top) > OVERSCAN;\n /** Scrolls to `target`, within what the layout can reach, and returns the position the reader gets. */\n const writeTop = (target: number, immediate: boolean, height: number) => {\n const next = Math.min(Math.max(0, total() - height), Math.max(0, target));\n const from = viewport.scrollTop;\n if (!immediate && mayDefer(next, from)) {\n // The rows move instead; the scroll range stays the same, so the engine clamps nothing.\n lastTop = from;\n deferred = next - lastTop;\n feed.style.height = `${total() - deferred}px`;\n return next;\n }\n deferred = 0;\n feed.style.height = `${total()}px`;\n if (Math.abs(from - next) > 0.5) viewport.scrollTop = next;\n lastTop = viewport.scrollTop;\n if (Math.abs(lastTop - from) > 0.5) owedUntil = performance.now() + END_WAIT_MS;\n return next;\n };\n\n let visibleKeys: { first: string; last: string } | null | undefined;\n const reportVisible = (top?: number, height?: number) => {\n if (!props.onVisibleChange) return;\n top ??= logicalTop();\n const bottom = top + (height ?? viewport.clientHeight);\n let first = -1;\n let last = -1;\n if (bottom > top && hi > lo)\n for (let index = indexAt(top); index < hi && offsetOf(index) < bottom; index++) {\n const from = offsetOf(index);\n const to = offsetOf(index + 1);\n // Rounded scroll positions may cut a fully shown item by a fraction of a pixel.\n if ((from > top - VISIBLE_TOLERANCE && to < bottom + VISIBLE_TOLERANCE) || (from <= top && to >= bottom)) {\n if (first < 0) first = index;\n last = index;\n }\n }\n const next = first < 0 ? null : { first: keys[first]!, last: keys[last]! };\n if (visibleKeys !== undefined && next?.first === visibleKeys?.first && next?.last === visibleKeys?.last) return;\n visibleKeys = next;\n props.onVisibleChange(first < 0 ? null : { first: list[first]!, last: list[last]! });\n };\n\n const updateRange = (top = logicalTop(), height = viewport.clientHeight) => {\n const indices: number[] = [];\n if (hi > lo) {\n const start = indexAt(top - OVERSCAN);\n const end = indexAt(top + height + OVERSCAN);\n // The focused row stays mounted wherever it is, so focus never falls back to the document.\n const focused = focusIndex >= lo && focusIndex < hi;\n if (focused && focusIndex < start) indices.push(focusIndex);\n for (let index = start; index <= end; index++) indices.push(index);\n if (focused && focusIndex > end) indices.push(focusIndex);\n }\n renderRows(indices);\n setTabStop(focusIndex >= lo && focusIndex < hi ? focusIndex : hi > lo ? indexAt(top + height - 1) : -1);\n // Newly mounted rows still have estimates; report only after their heights are measured.\n if (!restoring && !fresh.some((node) => node.isConnected)) reportVisible(top, height);\n };\n\n const measure = (measured: ReadonlyArray<readonly [HTMLElement, number]>) => {\n let changed = false;\n for (const [node, size] of measured) {\n const row = rowOf.get(node);\n if (!row || row.index < lo || row.index >= hi) continue;\n const index = row.index;\n // The anchor keeps the content of its row in place: a separator or marker that appears or goes away above it\n // moves the row's top instead.\n const lead = leadOf(node);\n if (!stick && index === anchor.index && row.lead !== undefined) anchor = { index, delta: anchor.delta + row.lead - lead };\n row.lead = lead;\n if (Math.abs(sizes[index]! - size) > 0.1) {\n sizes[index] = size;\n dirtyFrom = Math.min(dirtyFrom, index - lo);\n changed = true;\n }\n }\n return changed;\n };\n\n const position = (index: number) =>\n props.firstPosition !== undefined ? props.firstPosition + index : props.hasOlder ? undefined : index + 1;\n const setSize = () => props.totalCount ?? (props.hasOlder || props.hasNewer ? -1 : count());\n\n const createRow = (item: T, key: string, at: number): Row<T> =>\n createRoot((dispose) => {\n const [index, setIndex] = createSignal(at);\n // While older items may come, the first loaded item's predecessor is unknown, so it gets no separator yet.\n const separator = () => (listVersion(), index() === 0 && props.hasOlder ? undefined : props.separator?.(item, list[index() - 1]));\n // Created once, as Solid's For does, so signals that the content reads while rendering never rebuild it.\n const content = untrack(() => props.children(item, index));\n const node = (\n <div\n class=\"k2b-virtual-feed__item\"\n role=\"article\"\n data-index={index()}\n data-key={key}\n data-highlighted={highlighted() === key ? \"\" : undefined}\n tabindex={index() === tabStop() ? 0 : -1}\n aria-label={props.itemLabel?.(item)}\n aria-posinset={position(index())}\n aria-setsize={setSize()}\n style={{ transform: `translateY(${(version(), offsetOf(index()) - deferred)}px)` }}\n >\n <Show when={separator()}>\n {(content) => (\n <div class=\"k2b-virtual-feed__separator\">\n <span>{content()}</span>\n </div>\n )}\n </Show>\n <Show when={props.markerKey === key}>\n <div class=\"k2b-virtual-feed__marker\">\n <span>{props.markerLabel ?? feedMessages().feedNewMarker}</span>\n </div>\n </Show>\n {content}\n </div>\n ) as HTMLElement;\n const row: Row<T> = {\n item,\n node,\n index: at,\n setIndex: (next) => {\n row.index = next;\n setIndex(next);\n },\n dispose,\n };\n return row;\n }, owner);\n\n /** Mounts exactly these items in this order; rows that stay keep their node in place. */\n const renderRows = (indices: readonly number[]) => {\n const wanted = new Map<string, number>();\n for (const index of indices) wanted.set(keys[index]!, index);\n const active = feed.contains(document.activeElement) ? (document.activeElement as HTMLElement) : undefined;\n let focusedKey: string | undefined;\n for (const [key, row] of rows) {\n const index = wanted.get(key);\n if (index !== undefined && list[index] === row.item) continue;\n if (active && row.node.contains(active)) focusedKey = key;\n unobserveRow(row.node);\n row.node.remove();\n row.dispose();\n rows.delete(key);\n }\n let cursor = feed.firstChild;\n for (const index of indices) {\n const key = keys[index]!;\n let row = rows.get(key);\n if (row) row.setIndex(index);\n else {\n row = createRow(list[index]!, key, index);\n rows.set(key, row);\n rowOf.set(row.node, row);\n observeRow(row.node);\n fresh.push(row.node);\n }\n if (row.node === cursor) cursor = cursor.nextSibling;\n else feed.insertBefore(row.node, cursor);\n }\n // A reordered item moves its node, which blurs it, and a replaced item gets a new row: focus stays on the item.\n // Only when the item is gone does it fall back to the scroll area.\n if (active && document.activeElement !== active) {\n const replaced = focusedKey === undefined ? undefined : rows.get(focusedKey)?.node;\n (active.isConnected ? active : (replaced ?? viewport)).focus({ preventScroll: true });\n }\n };\n\n /**\n * Puts the reading position back after sizes, items, or the viewport changed: the end while following it, the\n * anchor otherwise. While the reader scrolls, it moves the rows instead of the scroll position, except for\n * `immediate` corrections, which follow structural changes and jumps.\n */\n const restore = (immediate = false) => {\n if (!viewport) return;\n if (restoring) {\n restoreAgain = true;\n return;\n }\n restoring = true;\n const restored = ++restoreVersion;\n const height = viewport.clientHeight;\n let target = 0;\n let top = 0;\n // Following the end shows the end of all items from now on, so later moves are judged against it.\n if (stick) appendedFrom = -1;\n try {\n for (let pass = 0; ; pass++) {\n restoreAgain = false;\n recompute();\n target = stick ? total() : offsetOf(anchor.index) - anchor.delta;\n top = Math.min(Math.max(0, total() - height), Math.max(0, target));\n // Row heights do not depend on their translation or the feed's scroll position. Mount and measure the\n // logical range first; writing the final geometry once avoids a layout flush on every correction pass.\n updateRange(top, height);\n if (pass === MEASURE_PASSES) break;\n // Rows mounted here reach the ResizeObserver only next frame (its loop limit), so measure them now.\n const mounted = fresh.filter((node) => node.isConnected);\n fresh = [];\n if (measure(mounted.map((node) => [node, node.getBoundingClientRect().height] as const))) restoreAgain = true;\n if (!restoreAgain) break;\n }\n top = writeTop(target, immediate, height);\n setVersion((value) => value + 1);\n // A position the layout cannot reach, above its start or past its end, becomes the one the reader sees, so a\n // page that loads there later keeps it instead of moving to it.\n if (!stick && Math.abs(top - target) > 0.5) anchor = { index: anchor.index, delta: offsetOf(anchor.index) - top };\n } finally {\n restoring = false;\n }\n checkEdges(lastTop + deferred, height);\n // A synchronous edge load can restore another window; that restore already reports its final geometry.\n if (restored === restoreVersion) reportVisible(lastTop + deferred, height);\n };\n\n /**\n * Keeps the reader's new position, reached from `from`. A row that the move reveals at the top can change size in the\n * same frame, before the feed measured it, and the reader never saw it. So the row at the top of `from` keeps its\n * place while it is still in view, and the rows the reader saw move by the reader's step alone.\n */\n const captureAnchor = (from: number) => {\n const top = logicalTop();\n setStick(reachesEnd(top));\n const seen = indexAt(from);\n anchor =\n offsetOf(seen + 1) > top && offsetOf(seen) < top + viewport.clientHeight\n ? { index: seen, delta: offsetOf(seen) - top }\n : anchorAt(top);\n };\n\n /**\n * Whether scrollTop moved since the feed last wrote or accounted for it. When a size change shortens the scroll\n * range, the engine clamps the position onto the new end; that move is the size change, not the reader.\n */\n const readerMoved = () => {\n const top = viewport.scrollTop;\n if (Math.abs(top - lastTop) <= 0.5) return false;\n const end = viewport.scrollHeight - viewport.clientHeight;\n return !(lastTop > end + 1 && Math.abs(top - end) <= 1);\n };\n\n /**\n * Takes a scroll position the feed did not make as the reader's, whatever moved it: touch, momentum, wheel, keys,\n * the scrollbar, focus, scrollIntoView, find in page, or assistive technology. Returns whether there was one.\n */\n const noteReader = () => {\n if (!readerMoved()) return false;\n lastMove = performance.now();\n if (overriding) {\n // Momentum left from before a jump of the application does not take the reader away again.\n armEnd(QUIET_MS);\n restore(true);\n return false;\n }\n armEnd();\n const from = lastTop + deferred;\n lastTop = viewport.scrollTop;\n scrolling = true;\n captureAnchor(from);\n return true;\n };\n\n const armEnd = (ms = hasScrollEnd ? END_WAIT_MS : QUIET_MS) => {\n clearTimeout(endTimer);\n endTimer = setTimeout(() => {\n endTimer = undefined;\n // A finger holds the scroll until it lifts; a move without its scroll event yet continues it.\n if (fingers.size > 0) return;\n if (readerMoved()) noteReader();\n else endScroll();\n }, ms);\n };\n\n /** The reader's scroll ended: what it held back is written in one step that moves nothing the reader sees. */\n const endScroll = () => {\n clearTimeout(endTimer);\n endTimer = undefined;\n scrolling = false;\n overriding = false;\n appendedFrom = -1;\n restore();\n };\n\n /**\n * A jump of the application ends the reader's scroll in progress: the jump lands at once, and what is left of the\n * momentum is put back until it has been still for a quiet time, or the reader touches, wheels, clicks, or presses\n * a key. A scrollend does not end this: a momentum stopped by the engine can still deliver a step in flight.\n */\n const takeOver = () => {\n appendedFrom = -1;\n if (!scrolling || fingers.size > 0) return;\n scrolling = false;\n overriding = true;\n lastMove = performance.now();\n armEnd(QUIET_MS);\n // A scroller that cannot scroll drops its momentum where the engine allows that. It scrolls again after a frame\n // in which nothing was left to put back.\n viewport.style.overflowY = \"hidden\";\n let seen = Number.NaN;\n const check = () => {\n if (disposed) return;\n if (overriding && lastMove !== seen) {\n seen = lastMove;\n requestAnimationFrame(check);\n } else viewport.style.removeProperty(\"overflow-y\");\n };\n requestAnimationFrame(check);\n };\n\n /** Lays out a window of about half the maximum around `center`. */\n const windowAround = (center: number) => {\n lo = center;\n hi = center + 1;\n let height = sizes[center]!;\n while (height < MAX_WINDOW / 2 && (lo > 0 || hi < list.length)) {\n if (lo > 0 && (center - lo <= hi - 1 - center || hi >= list.length)) height += sizes[--lo]!;\n else height += sizes[hi++]!;\n }\n dirtyFrom = 0;\n };\n\n const dropFocus = () => {\n if (focusIndex >= lo && focusIndex < hi) return;\n const focused = rows.get(keys[focusIndex] ?? \"\")?.node;\n focusIndex = -1;\n if (focused?.contains(document.activeElement)) viewport.focus({ preventScroll: true });\n };\n\n /**\n * Drops items from one side of the window, never those around the reading position, until it fits again. Returns\n * whether it dropped any.\n */\n const trimWindow = (side: \"start\" | \"end\") => {\n recompute();\n let excess = total() - MAX_WINDOW;\n if (excess <= 0) return false;\n const [from, to] = [lo, hi];\n const height = viewport.clientHeight;\n const top = stick ? total() - height : offsetOf(anchor.index) - anchor.delta;\n // While following the end the anchor is not maintained; only the visible end counts.\n const first = Math.min(indexAt(top - height - OVERSCAN), stick ? hi : anchor.index);\n const last = Math.max(indexAt(top + 2 * height + OVERSCAN), stick ? lo : anchor.index);\n if (side === \"start\") while (excess > 0 && lo < first) excess -= sizes[lo++]!;\n else while (excess > 0 && hi - 1 > last) excess -= sizes[--hi]!;\n dirtyFrom = 0;\n dropFocus();\n return lo !== from || hi !== to;\n };\n\n const loadNewest = () => {\n if (loadingOlder() || loadingNewer()) {\n newest = \"waiting\";\n return;\n }\n newest = \"loading\";\n load(\"newest\");\n };\n\n const load = (direction: \"older\" | \"newer\" | \"newest\") => {\n const setLoading = direction === \"older\" ? setLoadingOlder : setLoadingNewer;\n const callback = direction === \"older\" ? props.onLoadOlder : direction === \"newer\" ? props.onLoadNewer : props.onLoadNewest;\n if (!callback) return;\n // A load succeeded when its edge moved; other changes to `items` meanwhile do not count.\n const edge = () => (direction === \"older\" ? keys[0] : keys[keys.length - 1]);\n const before = edge();\n setLoading(true);\n let result: unknown;\n try {\n result = callback();\n } catch {\n result = undefined;\n }\n void Promise.resolve(result)\n .catch(() => undefined)\n .then(() => {\n setLoading(false);\n if (disposed) return;\n if (direction === \"newest\") newest = undefined;\n if (newest === \"waiting\") {\n if (!loadingOlder() && !loadingNewer()) loadNewest();\n return;\n }\n const arrived = edge() !== before;\n // A failed or empty load toward the end shows \"Jump to latest\" again instead of following an end that never came.\n if (direction !== \"older\" && !arrived && stick && props.hasNewer) setStick(false);\n // Keep loading while the reader still sits at the edge and the last page arrived.\n if (arrived) checkEdges();\n });\n };\n\n /** Grows the window or asks for more items when the reader nears an edge. */\n const checkEdges = (top?: number, height?: number) => {\n if (hi <= lo || restoring) return;\n top ??= logicalTop();\n height ??= viewport.clientHeight;\n // Rows measured taller than estimated can grow the window past the cap without any edge moving.\n if (total() > MAX_WINDOW && trimWindow(top + height / 2 > total() / 2 ? \"start\" : \"end\")) {\n restore(true);\n return;\n }\n const margin = Math.max(2_000, 3 * height);\n if (top < margin) {\n if (lo > 0) {\n let added = 0;\n while (lo > 0 && added < WINDOW_STEP) added += sizes[--lo]!;\n dirtyFrom = 0;\n trimWindow(\"end\");\n restore(true);\n return;\n }\n if (props.hasOlder && !loadingOlder() && !newest) load(\"older\");\n }\n if (total() - top - height < margin) {\n if (hi < list.length) {\n let added = 0;\n while (hi < list.length && added < WINDOW_STEP) added += sizes[hi++]!;\n dirtyFrom = 0;\n trimWindow(\"start\");\n restore(true);\n return;\n }\n if (props.hasNewer && !loadingNewer() && !newest) load(\"newer\");\n }\n };\n\n const queueAnnouncement = (added: readonly T[]) => {\n pendingAnnouncement = pendingAnnouncement.concat(added);\n if (announceTimer !== undefined) return;\n announceTimer = setTimeout(() => {\n announceTimer = undefined;\n const batch = pendingAnnouncement;\n pendingAnnouncement = [];\n const text = props.announce ? props.announce(batch) : feedMessages().feedNewItems({ count: batch.length });\n if (!text) return;\n const line = document.createElement(\"p\");\n line.textContent = text;\n log.append(line);\n while (log.childElementCount > 3) log.firstElementChild?.remove();\n }, ANNOUNCE_MS);\n };\n\n /** Applies a new `items` array: appends follow the end, prepends and other changes keep the anchor by key. */\n const sync = (next: readonly T[]) => {\n // The reader may have scrolled in this frame before its scroll event ran; take that position first.\n if (keys.length > 0) noteReader();\n const length = next.length;\n const nextKeys = next.map(props.getKey);\n const previous = keys.length;\n const focusKey = focusIndex >= 0 ? keys[focusIndex] : undefined;\n let added: readonly T[] = [];\n let appended = false;\n /** A new feed, or one that shares no item with the last: start at its end. */\n const reset = () => {\n sizes = Float64Array.from(next, estimate);\n focusIndex = -1;\n appendedFrom = -1;\n setStick(!props.hasNewer);\n anchor = { index: 0, delta: 0 };\n setUnseen(0);\n // Pending announcements describe the items that are gone.\n clearTimeout(announceTimer);\n announceTimer = undefined;\n pendingAnnouncement = [];\n list = next;\n if (sizes.reduce((sum, size) => sum + size, 0) <= MAX_WINDOW) {\n lo = 0;\n hi = length;\n } else windowAround(length - 1);\n };\n if (previous === 0 || length === 0) reset();\n else if (length >= previous && runsMatch(keys, nextKeys, 0)) {\n const grown = new Float64Array(length);\n grown.set(sizes);\n for (let index = previous; index < length; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n if (hi === previous) hi = length;\n appended = true;\n // Away from the end, the reader's scroll in progress still reaches the end it was heading for.\n if (!stick && deferring() && appendedFrom < 0) appendedFrom = previous;\n // Only items after the newest one the feed has known are new; older pages toward the end are history.\n const known = endKey === undefined ? -1 : nextKeys.lastIndexOf(endKey);\n if (known >= 0) added = next.slice(Math.max(previous, known + 1));\n } else if (length >= previous && runsMatch(keys, nextKeys, length - previous)) {\n const shift = length - previous;\n const grown = new Float64Array(length);\n grown.set(sizes, shift);\n for (let index = 0; index < shift; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n anchor = { index: anchor.index + shift, delta: anchor.delta };\n if (focusIndex >= 0) focusIndex += shift;\n if (appendedFrom >= 0) appendedFrom += shift;\n if (lo > 0) lo += shift;\n hi += shift;\n } else {\n const known = new Map<string, number>();\n for (let index = 0; index < previous; index++) known.set(keys[index]!, sizes[index]!);\n const position = new Map<string, number>();\n for (let index = 0; index < length; index++) position.set(nextKeys[index]!, index);\n if (!nextKeys.some((key) => known.has(key))) reset();\n else {\n sizes = new Float64Array(length);\n for (let index = 0; index < length; index++) sizes[index] = known.get(nextKeys[index]!) ?? estimate(next[index]!);\n // An item that is gone hands its role to the nearest surviving neighbor.\n const survivor = (from: number) => {\n for (let distance = 0; distance < previous; distance++) {\n const below = position.get(keys[from + distance] ?? \"\");\n if (below !== undefined) return below;\n const above = position.get(keys[from - distance] ?? \"\");\n if (above !== undefined) return above;\n }\n return length - 1;\n };\n const wasAtStart = lo === 0;\n const wasAtEnd = hi === previous;\n appendedFrom = -1;\n anchor = { index: survivor(anchor.index), delta: anchor.delta };\n focusIndex = focusKey === undefined ? -1 : (position.get(focusKey) ?? -1);\n lo = wasAtStart ? 0 : survivor(lo);\n hi = wasAtEnd ? length : survivor(hi - 1) + 1;\n if (anchor.index < lo || anchor.index >= hi) {\n list = next;\n windowAround(anchor.index);\n }\n }\n }\n list = next;\n keys = nextKeys;\n dirtyFrom = 0;\n setCount(length);\n setListVersion((value) => value + 1);\n if (!props.hasNewer) endKey = nextKeys[length - 1];\n recompute();\n const center = stick ? hi - 1 : anchor.index;\n const trimmed = total() > MAX_WINDOW && trimWindow(center - lo > hi - 1 - center ? \"start\" : \"end\");\n // Appended items wait for the reader's scroll to end like other size changes; the rows show them meanwhile.\n restore(!appended || trimmed);\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n if (added.length > 0) {\n if (!stick) setUnseen((value) => value + added.length);\n queueAnnouncement(added);\n }\n };\n\n /**\n * Follows the end. With newer items not loaded, `onLoadNewest` replaces the items, after any running load; without\n * it, following the end keeps `onLoadNewer` paging until the newest item arrives or the reader scrolls away.\n */\n const scrollToEnd = () => {\n takeOver();\n setStick(!props.hasNewer || Boolean(props.onLoadNewer || props.onLoadNewest));\n if (props.hasNewer && props.onLoadNewest) loadNewest();\n if (hi < list.length) windowAround(list.length - 1);\n restore(true);\n };\n\n const scrollToKey = (key: string, options: VirtualFeedScrollOptions = {}) => {\n const index = keys.indexOf(key);\n if (index < 0) return false;\n takeOver();\n if (index < lo || index >= hi) windowAround(index);\n recompute();\n const delta = () => (options.align === \"start\" ? 0 : Math.max(0, (viewport.clientHeight - sizes[index]!) / 2));\n setStick(false);\n anchor = { index, delta: delta() };\n restore(true);\n // The row was measured while mounting, before this frame paints; center it on its real height.\n if (anchor.index === index && anchor.delta !== delta()) {\n anchor = { index, delta: delta() };\n restore(true);\n }\n if (reachesEnd(logicalTop())) setStick(true);\n if (options.highlight) {\n clearTimeout(highlightTimer);\n setHighlighted(key);\n highlightTimer = setTimeout(() => setHighlighted(undefined), HIGHLIGHT_MS);\n }\n return true;\n };\n\n const focusRow = (target: number) => {\n if (list.length === 0) return;\n const index = Math.min(list.length - 1, Math.max(0, target));\n // An edge load during the restore may add items synchronously and shift indices; the key keeps the target.\n const key = keys[index]!;\n const outside = index < lo || index >= hi;\n if (outside) windowAround(index);\n recompute();\n focusIndex = index;\n const top = logicalTop();\n const height = viewport.clientHeight;\n const start = offsetOf(index);\n const size = sizes[index]!;\n if (index === list.length - 1 && hi === list.length && !props.hasNewer) setStick(true);\n else if (outside) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start < top) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start + size > top + height) {\n setStick(false);\n anchor = { index, delta: Math.max(0, height - size) };\n restore(true);\n // The row was measured while mounting; align its real bottom before this frame paints.\n if (anchor.index === focusIndex) anchor = { index: focusIndex, delta: Math.max(0, height - sizes[focusIndex]!) };\n }\n restore(true);\n rows.get(key)?.node.focus({ preventScroll: true });\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const row = rowOf.get(event.target as Element);\n if (!row) return;\n const index = row.index;\n if (event.key === \"ArrowUp\" || event.key === \"PageUp\") focusRow(index - 1);\n else if (event.key === \"ArrowDown\" || event.key === \"PageDown\") focusRow(index + 1);\n else if (event.key === \"Home\" && event.ctrlKey) focusRow(0);\n else if (event.key === \"End\" && event.ctrlKey) {\n scrollToEnd();\n focusRow(list.length - 1);\n } else return;\n event.preventDefault();\n };\n\n const onScroll = () => {\n // The feed checked its edges when it wrote scrollTop. Its own scroll event arrives a frame later, and checking again\n // then would retry a load that failed in between.\n const reader = noteReader();\n // Near the start, the rows no longer stand in for a held-back correction; it is written now.\n if (deferred !== 0 && !mayDefer(logicalTop())) restore(true);\n else {\n updateRange();\n if (reader) checkEdges();\n }\n };\n\n /**\n * Ends the reader's scroll if the feed stands still for the next two frames. A `scrollend` not counted as a write's\n * can still be the late one of an earlier write; movement after it means the scroll goes on.\n */\n const confirmEnd = () => {\n const seen = lastMove;\n requestAnimationFrame(() =>\n requestAnimationFrame(() => {\n if (disposed || fingers.size > 0 || !scrolling || lastMove !== seen || readerMoved()) return;\n endScroll();\n }),\n );\n };\n\n const onScrollEnd = () => {\n // The scrollend of the feed's own write, not the end of the reader's scroll.\n if (performance.now() < owedUntil) {\n owedUntil = 0;\n return;\n }\n endedAt = performance.now();\n if (fingers.size > 0 || !scrolling) return;\n confirmEnd();\n };\n\n const controller: VirtualFeedController = {\n scrollToKey,\n scrollToEnd,\n isAtEnd: () => stick,\n };\n\n // Created before the first sync below, so items that an edge load adds synchronously during it are not lost.\n createEffect(on(() => props.items, sync, { defer: true }));\n // More items can appear at an edge without new items, for example when a live update reports newer ones.\n createEffect(\n on(\n [() => props.hasOlder, () => props.hasNewer],\n () => {\n if (!props.hasNewer) endKey = keys[keys.length - 1];\n if (hi <= lo) return;\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n // Only newer pages can be followed; with just `onLoadNewest`, \"Jump to latest\" has to show.\n else if (stick && props.hasNewer && !props.onLoadNewer) setStick(false);\n checkEdges();\n },\n { defer: true },\n ),\n );\n\n onMount(() => {\n hasScrollEnd = \"onscrollend\" in window;\n lastHeight = viewport.clientHeight;\n const observer = new ResizeObserver((entries) => {\n observing = true;\n try {\n // A scroll of the reader in this frame counts first, in the geometry from before these changes.\n noteReader();\n fresh = [];\n let resized = false;\n const measured: Array<readonly [HTMLElement, number]> = [];\n for (const entry of entries) {\n if (entry.target === viewport) {\n // A shorter viewport (a growing footer or keyboard) keeps what is at its bottom in place.\n const height = viewport.clientHeight;\n if (!stick) anchor = { index: anchor.index, delta: anchor.delta + height - lastHeight };\n lastHeight = height;\n resized = true;\n } else if (entry.target.isConnected) {\n const row = entry.target as HTMLElement;\n measured.push([row, entry.borderBoxSize?.[0]?.blockSize ?? row.getBoundingClientRect().height]);\n }\n }\n if (measure(measured) || resized) restore();\n else reportVisible();\n } finally {\n observing = false;\n }\n });\n observer.observe(viewport);\n // Rows observed inside the observer's own callback miss its first notification, which raises a window error.\n // They were measured while mounting, so they are observed from the next frame on.\n let later: HTMLElement[] = [];\n let laterFrame = 0;\n observeRow = (row) => {\n if (!observing) return observer.observe(row);\n later.push(row);\n laterFrame ||= requestAnimationFrame(() => {\n laterFrame = 0;\n for (const node of later) if (node.isConnected) observer.observe(node);\n later = [];\n });\n };\n unobserveRow = (row) => observer.unobserve(row);\n const release = () => {\n for (const target of touched) {\n target.removeEventListener(\"touchend\", touchEnd);\n target.removeEventListener(\"touchcancel\", touchEnd);\n }\n touched.clear();\n };\n // Input of the reader ends a takeover by the application at once, and lets the feed scroll for that input.\n const act = () => {\n overriding = false;\n viewport.style.removeProperty(\"overflow-y\");\n };\n const touchStart = (event: TouchEvent) => {\n // A touch whose end the feed missed has left the screen by now.\n const down = new Set(Array.from(event.touches, (touch) => touch.identifier));\n for (const id of fingers) if (!down.has(id)) fingers.delete(id);\n for (const touch of Array.from(event.changedTouches)) fingers.add(touch.identifier);\n act();\n // Touch events stay with the element the touch began on, also when the feed removes its row meanwhile.\n const target = event.target;\n if (target && !touched.has(target)) {\n touched.add(target);\n target.addEventListener(\"touchend\", touchEnd, { passive: true });\n target.addEventListener(\"touchcancel\", touchEnd, { passive: true });\n }\n };\n function touchEnd(event: Event) {\n for (const touch of Array.from((event as TouchEvent).changedTouches)) fingers.delete(touch.identifier);\n if (fingers.size > 0) return;\n release();\n // The last step of a short flick can have moved scrollTop before its scroll event; it counts before anything ends.\n if (!scrolling && !noteReader()) return endScroll();\n armEnd();\n // A scroll that ended under the finger ends now, unless the release starts a momentum.\n if (endedAt >= lastMove) confirmEnd();\n }\n viewport.addEventListener(\"touchstart\", touchStart, { passive: true });\n viewport.addEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.addEventListener(type, act, { passive: true });\n onCleanup(() => {\n disposed = true;\n observer.disconnect();\n cancelAnimationFrame(laterFrame);\n viewport.removeEventListener(\"touchstart\", touchStart);\n viewport.removeEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.removeEventListener(type, act);\n release();\n clearTimeout(endTimer);\n clearTimeout(announceTimer);\n clearTimeout(highlightTimer);\n for (const row of rows.values()) row.dispose();\n rows.clear();\n });\n sync(props.items);\n props.controller?.(controller);\n });\n\n const shownCount = () => props.newCount ?? unseen();\n\n return (\n <div class={props.class ? `k2b-virtual-feed ${props.class}` : \"k2b-virtual-feed\"}>\n <div ref={viewport} class=\"k2b-virtual-feed__viewport\" tabindex=\"-1\" onScroll={onScroll}>\n <div\n ref={feed}\n class=\"k2b-virtual-feed__feed\"\n role=\"feed\"\n aria-label={props.label}\n aria-busy={props.busy || loadingOlder() || loadingNewer() ? \"true\" : \"false\"}\n onKeyDown={onKeyDown}\n onFocusIn={(event) => {\n const node = (event.target as HTMLElement).closest(\".k2b-virtual-feed__item\");\n const row = node ? rowOf.get(node) : undefined;\n if (row) {\n focusIndex = row.index;\n setTabStop(focusIndex);\n }\n }}\n onFocusOut={(event) => {\n const next = event.relatedTarget as Node | null;\n if (next && !feed.contains(next)) focusIndex = -1;\n }}\n />\n </div>\n <Show when={count() === 0 && props.empty}>\n <div class=\"k2b-virtual-feed__empty\">{props.empty}</div>\n </Show>\n <Show when={loadingOlder()}>\n <div class=\"k2b-virtual-feed__status\" aria-hidden=\"true\">\n <i class=\"ti ti-loader-2 k2b-spin\" />\n {messages().loading}\n </div>\n </Show>\n <Show when={!atEnd() && count() > 0}>\n <button\n type=\"button\"\n class=\"k2b-virtual-feed__end\"\n aria-label={shownCount() > 0 ? feedMessages().feedJumpToLatestCount({ count: shownCount() }) : undefined}\n onClick={() => {\n scrollToEnd();\n // The button disappears at the end; keep focus in the feed instead of the document.\n if (props.hasNewer) viewport.focus({ preventScroll: true });\n else focusRow(list.length - 1);\n }}\n >\n <i class={loadingNewer() ? \"ti ti-loader-2 k2b-spin\" : \"ti ti-arrow-down\"} aria-hidden=\"true\" />\n {feedMessages().feedJumpToLatest}\n <Show when={shownCount() > 0}>\n <span class=\"k2b-virtual-feed__count\" aria-hidden=\"true\">\n {shownCount()}\n </span>\n </Show>\n </button>\n </Show>\n <div ref={log} class=\"k2b-sr-only\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\" />\n </div>\n );\n}\n\nexport default VirtualFeed;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -89,7 +89,10 @@ export function Combobox(props) {
|
|
|
89
89
|
};
|
|
90
90
|
createEffect(on(options, list => {
|
|
91
91
|
const index = props.autoHighlight;
|
|
92
|
-
if (index
|
|
92
|
+
if (index === undefined || focusedIndex() >= 0 || !popover.open() || list.length === 0) return;
|
|
93
|
+
// A result that cannot be picked is never the one Enter takes: the next one that can, or none.
|
|
94
|
+
const start = Math.min(index, list.length - 1);
|
|
95
|
+
setFocusedIndex(list[start]?.disabled ? nextEnabledChoiceIndex(list, start, 1) : start);
|
|
93
96
|
}));
|
|
94
97
|
createEffect(() => {
|
|
95
98
|
if (props.readOnly) {
|
|
@@ -99,7 +102,7 @@ export function Combobox(props) {
|
|
|
99
102
|
}
|
|
100
103
|
});
|
|
101
104
|
const select = option => {
|
|
102
|
-
if (props.disabled || props.readOnly) return;
|
|
105
|
+
if (props.disabled || props.readOnly || option.disabled) return;
|
|
103
106
|
popover.hide();
|
|
104
107
|
props.onSelect({
|
|
105
108
|
id: option.value,
|
|
@@ -316,7 +319,9 @@ export function Combobox(props) {
|
|
|
316
319
|
[_el$33, _co$7] = _$getNextMarker(_el$32.nextSibling);
|
|
317
320
|
_el$29.$$click = () => select(option());
|
|
318
321
|
_el$29.$$pointerdown = event => event.preventDefault();
|
|
319
|
-
_el$29.$$pointermove = () =>
|
|
322
|
+
_el$29.$$pointermove = () => {
|
|
323
|
+
if (!option().disabled) focus(index());
|
|
324
|
+
};
|
|
320
325
|
_$use(element => optionRefs[index()] = element, _el$29);
|
|
321
326
|
_$insert(_el$29, _$createComponent(Show, {
|
|
322
327
|
get when() {
|
|
@@ -342,15 +347,18 @@ export function Combobox(props) {
|
|
|
342
347
|
_$effect(_p$ => {
|
|
343
348
|
var _v$ = `${listboxId}-${index()}`,
|
|
344
349
|
_v$2 = index() === focusedIndex(),
|
|
345
|
-
_v$3 =
|
|
350
|
+
_v$3 = option().disabled ? "true" : undefined,
|
|
351
|
+
_v$4 = index() === focusedIndex() ? "true" : undefined;
|
|
346
352
|
_v$ !== _p$.e && _$setAttribute(_el$29, "id", _p$.e = _v$);
|
|
347
353
|
_v$2 !== _p$.t && _$setAttribute(_el$29, "aria-selected", _p$.t = _v$2);
|
|
348
|
-
_v$3 !== _p$.a && _$setAttribute(_el$29, "
|
|
354
|
+
_v$3 !== _p$.a && _$setAttribute(_el$29, "aria-disabled", _p$.a = _v$3);
|
|
355
|
+
_v$4 !== _p$.o && _$setAttribute(_el$29, "data-focused", _p$.o = _v$4);
|
|
349
356
|
return _p$;
|
|
350
357
|
}, {
|
|
351
358
|
e: undefined,
|
|
352
359
|
t: undefined,
|
|
353
|
-
a: undefined
|
|
360
|
+
a: undefined,
|
|
361
|
+
o: undefined
|
|
354
362
|
});
|
|
355
363
|
_$runHydrationEvents();
|
|
356
364
|
return _el$29;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/Combobox.tsx"],"sourcesContent":["import { createEffect, createMemo, createSignal, For, type JSX, on, Show } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type ChoiceOption, createChoiceLoader, createChoicePopover, nextEnabledChoiceIndex } from \"./choice\";\nimport type { FieldProps, MaybeAccessor } from \"./field-contract\";\nimport { resolveMaybeAccessor } from \"./field-contract\";\nimport { useSelectMessages } from \"./select-messages\";\n\nexport type ComboboxOption = { id: string; label: string; description?: string; icon?: string };\nexport type ComboboxProps = FieldProps & {\n readOnly?: boolean;\n query?: MaybeAccessor<string>;\n onQueryChange?: (query: string) => void;\n placeholder?: string;\n fetchData: (query: string, signal: AbortSignal) => Promise<ComboboxOption[]>;\n onSelect: (option: ComboboxOption) => void;\n debounceMs?: number;\n /** The query is the field's own value: picking or closing keeps the typed text, and Enter without an active option only closes the list. */\n freeText?: boolean;\n /** Below this many characters nothing loads and the list stays closed. */\n minQueryLength?: number;\n /** This result (by position) is active as soon as results arrive, so Enter takes it. */\n autoHighlight?: number;\n /** Replaces the results with a host-owned notice, such as an exhausted quota; nothing loads while it is set. */\n status?: JSX.Element;\n /** Shown instead of the default text when a search finds nothing. */\n empty?: JSX.Element;\n /** One line under the results, such as their source. */\n footer?: JSX.Element;\n};\n\nconst iconClass = (icon: string) => (icon.split(/\\s+/).includes(\"ti\") ? icon : `ti ${icon}`);\n\nexport function Combobox(props: ComboboxProps): JSX.Element {\n const messages = useUiMessages();\n const selectMessages = useSelectMessages();\n const meta = createFieldMeta(props.id);\n const listboxId = `${meta.controlId}-listbox`;\n const [localQuery, setLocalQuery] = createSignal(\"\");\n const query = () => resolveMaybeAccessor(props.query) ?? localQuery();\n const setQuery = (value: string) => {\n setLocalQuery(value);\n props.onQueryChange?.(value);\n };\n const error = () => resolveMaybeAccessor(props.error);\n const [focusedIndex, setFocusedIndex] = createSignal(-1);\n let inputRef: HTMLInputElement | undefined;\n let optionRefs: HTMLButtonElement[] = [];\n const loader = createChoiceLoader(\n () => async (value, signal) => (await props.fetchData(value, signal)).map((option) => ({ ...option, value: option.id })),\n // Cloud debounces at 200ms and then pads the response with a 200ms minimum\n // load time to stop the spinner flickering. The spinner here sits in the\n // chevron slot and stale results stay visible, so there is nothing to pad —\n // 150ms keeps typing responsive without hammering the loader.\n () => props.debounceMs ?? 150,\n );\n const popover = createChoicePopover(() => Boolean(props.disabled || props.readOnly));\n // A host notice or an error replaces the results; hidden results are never selectable.\n const options = () => (props.status || loader.error() ? [] : loader.options());\n const optionsById = createMemo(() => new Map(options().map((option) => [option.value, option])));\n const focusedOption = () => options()[focusedIndex()];\n const searchable = (value: string) => value.trim().length >= (props.minQueryLength ?? 0);\n const focus = (index: number) => {\n setFocusedIndex(index);\n optionRefs[index]?.scrollIntoView({ block: \"nearest\" });\n };\n /** `eager` loads the currently controlled query on open; typing supplies its\n * own query, so opening from `onInput` skips the duplicate request. */\n const open = (eager = true) => {\n if (props.disabled || props.readOnly || popover.open() || !searchable(query())) return;\n popover.show();\n if (eager && !props.status) loader.load(query(), true);\n focus(-1);\n };\n const reset = () => {\n loader.cancel();\n setQuery(\"\");\n focus(-1);\n };\n const close = () => {\n popover.hide();\n if (!props.freeText) return reset();\n loader.cancel();\n focus(-1);\n };\n createEffect(\n on(options, (list) => {\n const index = props.autoHighlight;\n if (index !== undefined && focusedIndex() < 0 && popover.open() && list.length > 0) setFocusedIndex(Math.min(index, list.length - 1));\n }),\n );\n createEffect(() => {\n if (props.readOnly) {\n popover.hide();\n loader.cancel();\n setFocusedIndex(-1);\n }\n });\n const select = (option: ChoiceOption<string>) => {\n if (props.disabled || props.readOnly) return;\n popover.hide();\n props.onSelect({ id: option.value, label: option.label, description: option.description, icon: option.icon });\n if (props.freeText) {\n loader.cancel();\n focus(-1);\n } else reset();\n inputRef?.focus();\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (props.disabled || props.readOnly) return;\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!popover.open()) open();\n else focus(nextEnabledChoiceIndex(options(), focusedIndex(), event.key === \"ArrowDown\" ? 1 : -1));\n } else if (event.key === \"Enter\" && popover.open()) {\n // While the results are open, Enter belongs to them: it never submits an enclosing form, even with no option active.\n event.preventDefault();\n const option = options()[focusedIndex()];\n if (option) select(option);\n else if (props.freeText) close();\n } else if ((event.key === \"Escape\" || event.key === \"Tab\") && popover.open()) {\n // Escape is only ours while the list is open; otherwise it has to reach an\n // enclosing dialog or drawer.\n if (event.key === \"Escape\") event.preventDefault();\n close();\n }\n };\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={props.disabled}\n >\n <div class=\"k2b-combobox\" data-invalid={error() ? \"true\" : undefined}>\n <div ref={popover.setTrigger} class=\"k2b-combobox__input\">\n <i class=\"ti ti-search\" aria-hidden=\"true\" />\n {/* A click, typing, or an arrow key opens the list. Focus alone (Tab, a dialog's initial focus) does not, so Escape still closes the enclosing dialog. */}\n <input\n ref={(element) => {\n inputRef = element;\n }}\n id={meta.controlId}\n type=\"text\"\n value={query()}\n placeholder={props.placeholder ?? messages().search}\n disabled={props.disabled}\n readOnly={props.readOnly}\n aria-readonly={props.readOnly ? \"true\" : undefined}\n role=\"combobox\"\n autocomplete=\"off\"\n aria-autocomplete=\"list\"\n aria-expanded={popover.open()}\n aria-controls={listboxId}\n aria-activedescendant={focusedOption() ? `${listboxId}-${focusedIndex()}` : undefined}\n {...fieldControlAria(meta, props)}\n onClick={() => open()}\n onInput={(event) => {\n if (props.disabled || props.readOnly) {\n event.currentTarget.value = query();\n return;\n }\n const value = event.currentTarget.value;\n setQuery(value);\n focus(-1);\n if (!searchable(value)) {\n popover.hide();\n loader.cancel();\n return;\n }\n open(false);\n if (!props.status) loader.load(value);\n }}\n onKeyDown={onKeyDown}\n />\n <Show when={loader.loading()} fallback={<i class=\"ti ti-chevron-down\" aria-hidden=\"true\" />}>\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n </Show>\n </div>\n <div ref={popover.setPopover} popover=\"manual\" class=\"k2b-choice-popover\">\n <div class=\"k2b-choice-options\" role=\"listbox\" id={listboxId}>\n <Show when={props.status}>{(status) => <div class=\"k2b-choice-status\">{status()}</div>}</Show>\n <Show when={!props.status && loader.error()}>\n {(message) => (\n <div class=\"k2b-choice-status\" data-tone=\"danger\">\n <span>{message()}</span>\n <button type=\"button\" onClick={loader.retry}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n {/* Keyed by option ID, not object: each fetch returns new objects, and a row replaced between press and release\n would swallow the click. */}\n <For\n each={options().map((option) => option.value)}\n fallback={\n <Show when={!props.status && !loader.error()}>\n <Show\n when={loader.loading()}\n fallback={\n <div class=\"k2b-choice-status\">\n {query().length >= 2 ? (props.empty ?? selectMessages().noResultsFound) : selectMessages().typeToSearch}\n </div>\n }\n >\n {/* The first search has nothing to keep visible yet: rows of the final size wait in its place. */}\n <div class=\"k2b-choice-loading\" role=\"status\">\n <span class=\"k2b-sr-only\">{messages().loading}</span>\n <For each={[62, 48, 55]}>\n {(width) => (\n <div class=\"k2b-choice-loading__row\" aria-hidden=\"true\">\n <span class=\"k2b-skeleton\" />\n <span class=\"k2b-skeleton\" style={{ width: `${width}%` }} />\n </div>\n )}\n </For>\n </div>\n </Show>\n </Show>\n }\n >\n {(id, index) => {\n const first = optionsById().get(id)!;\n const option = () => optionsById().get(id) ?? first;\n return (\n <button\n ref={(element) => (optionRefs[index()] = element)}\n type=\"button\"\n id={`${listboxId}-${index()}`}\n class=\"k2b-choice-option\"\n role=\"option\"\n aria-selected={index() === focusedIndex()}\n data-focused={index() === focusedIndex() ? \"true\" : undefined}\n onPointerMove={() => focus(index())}\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => select(option())}\n >\n <Show when={option().icon}>{(icon) => <i class={iconClass(icon())} aria-hidden=\"true\" />}</Show>\n <span>\n <strong>{option().label}</strong>\n <Show when={option().description}>{(description) => <small>{description()}</small>}</Show>\n </span>\n </button>\n );\n }}\n </For>\n </div>\n <Show when={props.footer}>{(footer) => <div class=\"k2b-choice-footer\">{footer()}</div>}</Show>\n </div>\n </div>\n </Field>\n );\n}\n\nexport default Combobox;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/Combobox.tsx"],"sourcesContent":["import { createEffect, createMemo, createSignal, For, type JSX, on, Show } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type ChoiceOption, createChoiceLoader, createChoicePopover, nextEnabledChoiceIndex } from \"./choice\";\nimport type { FieldProps, MaybeAccessor } from \"./field-contract\";\nimport { resolveMaybeAccessor } from \"./field-contract\";\nimport { useSelectMessages } from \"./select-messages\";\n\nexport type ComboboxOption = {\n id: string;\n label: string;\n description?: string;\n icon?: string;\n /** Shown but cannot be picked, such as someone who is already on the list; say why in `description`. */\n disabled?: boolean;\n};\nexport type ComboboxProps = FieldProps & {\n readOnly?: boolean;\n query?: MaybeAccessor<string>;\n onQueryChange?: (query: string) => void;\n placeholder?: string;\n fetchData: (query: string, signal: AbortSignal) => Promise<ComboboxOption[]>;\n onSelect: (option: ComboboxOption) => void;\n debounceMs?: number;\n /** The query is the field's own value: picking or closing keeps the typed text, and Enter without an active option only closes the list. */\n freeText?: boolean;\n /** Below this many characters nothing loads and the list stays closed. */\n minQueryLength?: number;\n /** This result (by position) is active as soon as results arrive, so Enter takes it. */\n autoHighlight?: number;\n /** Replaces the results with a host-owned notice, such as an exhausted quota; nothing loads while it is set. */\n status?: JSX.Element;\n /** Shown instead of the default text when a search finds nothing. */\n empty?: JSX.Element;\n /** One line under the results, such as their source. */\n footer?: JSX.Element;\n};\n\nconst iconClass = (icon: string) => (icon.split(/\\s+/).includes(\"ti\") ? icon : `ti ${icon}`);\n\nexport function Combobox(props: ComboboxProps): JSX.Element {\n const messages = useUiMessages();\n const selectMessages = useSelectMessages();\n const meta = createFieldMeta(props.id);\n const listboxId = `${meta.controlId}-listbox`;\n const [localQuery, setLocalQuery] = createSignal(\"\");\n const query = () => resolveMaybeAccessor(props.query) ?? localQuery();\n const setQuery = (value: string) => {\n setLocalQuery(value);\n props.onQueryChange?.(value);\n };\n const error = () => resolveMaybeAccessor(props.error);\n const [focusedIndex, setFocusedIndex] = createSignal(-1);\n let inputRef: HTMLInputElement | undefined;\n let optionRefs: HTMLButtonElement[] = [];\n const loader = createChoiceLoader(\n () => async (value, signal) => (await props.fetchData(value, signal)).map((option) => ({ ...option, value: option.id })),\n // Cloud debounces at 200ms and then pads the response with a 200ms minimum\n // load time to stop the spinner flickering. The spinner here sits in the\n // chevron slot and stale results stay visible, so there is nothing to pad —\n // 150ms keeps typing responsive without hammering the loader.\n () => props.debounceMs ?? 150,\n );\n const popover = createChoicePopover(() => Boolean(props.disabled || props.readOnly));\n // A host notice or an error replaces the results; hidden results are never selectable.\n const options = () => (props.status || loader.error() ? [] : loader.options());\n const optionsById = createMemo(() => new Map(options().map((option) => [option.value, option])));\n const focusedOption = () => options()[focusedIndex()];\n const searchable = (value: string) => value.trim().length >= (props.minQueryLength ?? 0);\n const focus = (index: number) => {\n setFocusedIndex(index);\n optionRefs[index]?.scrollIntoView({ block: \"nearest\" });\n };\n /** `eager` loads the currently controlled query on open; typing supplies its\n * own query, so opening from `onInput` skips the duplicate request. */\n const open = (eager = true) => {\n if (props.disabled || props.readOnly || popover.open() || !searchable(query())) return;\n popover.show();\n if (eager && !props.status) loader.load(query(), true);\n focus(-1);\n };\n const reset = () => {\n loader.cancel();\n setQuery(\"\");\n focus(-1);\n };\n const close = () => {\n popover.hide();\n if (!props.freeText) return reset();\n loader.cancel();\n focus(-1);\n };\n createEffect(\n on(options, (list) => {\n const index = props.autoHighlight;\n if (index === undefined || focusedIndex() >= 0 || !popover.open() || list.length === 0) return;\n // A result that cannot be picked is never the one Enter takes: the next one that can, or none.\n const start = Math.min(index, list.length - 1);\n setFocusedIndex(list[start]?.disabled ? nextEnabledChoiceIndex(list, start, 1) : start);\n }),\n );\n createEffect(() => {\n if (props.readOnly) {\n popover.hide();\n loader.cancel();\n setFocusedIndex(-1);\n }\n });\n const select = (option: ChoiceOption<string>) => {\n if (props.disabled || props.readOnly || option.disabled) return;\n popover.hide();\n props.onSelect({ id: option.value, label: option.label, description: option.description, icon: option.icon });\n if (props.freeText) {\n loader.cancel();\n focus(-1);\n } else reset();\n inputRef?.focus();\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (props.disabled || props.readOnly) return;\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!popover.open()) open();\n else focus(nextEnabledChoiceIndex(options(), focusedIndex(), event.key === \"ArrowDown\" ? 1 : -1));\n } else if (event.key === \"Enter\" && popover.open()) {\n // While the results are open, Enter belongs to them: it never submits an enclosing form, even with no option active.\n event.preventDefault();\n const option = options()[focusedIndex()];\n if (option) select(option);\n else if (props.freeText) close();\n } else if ((event.key === \"Escape\" || event.key === \"Tab\") && popover.open()) {\n // Escape is only ours while the list is open; otherwise it has to reach an\n // enclosing dialog or drawer.\n if (event.key === \"Escape\") event.preventDefault();\n close();\n }\n };\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={props.disabled}\n >\n <div class=\"k2b-combobox\" data-invalid={error() ? \"true\" : undefined}>\n <div ref={popover.setTrigger} class=\"k2b-combobox__input\">\n <i class=\"ti ti-search\" aria-hidden=\"true\" />\n {/* A click, typing, or an arrow key opens the list. Focus alone (Tab, a dialog's initial focus) does not, so Escape still closes the enclosing dialog. */}\n <input\n ref={(element) => {\n inputRef = element;\n }}\n id={meta.controlId}\n type=\"text\"\n value={query()}\n placeholder={props.placeholder ?? messages().search}\n disabled={props.disabled}\n readOnly={props.readOnly}\n aria-readonly={props.readOnly ? \"true\" : undefined}\n role=\"combobox\"\n autocomplete=\"off\"\n aria-autocomplete=\"list\"\n aria-expanded={popover.open()}\n aria-controls={listboxId}\n aria-activedescendant={focusedOption() ? `${listboxId}-${focusedIndex()}` : undefined}\n {...fieldControlAria(meta, props)}\n onClick={() => open()}\n onInput={(event) => {\n if (props.disabled || props.readOnly) {\n event.currentTarget.value = query();\n return;\n }\n const value = event.currentTarget.value;\n setQuery(value);\n focus(-1);\n if (!searchable(value)) {\n popover.hide();\n loader.cancel();\n return;\n }\n open(false);\n if (!props.status) loader.load(value);\n }}\n onKeyDown={onKeyDown}\n />\n <Show when={loader.loading()} fallback={<i class=\"ti ti-chevron-down\" aria-hidden=\"true\" />}>\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n </Show>\n </div>\n <div ref={popover.setPopover} popover=\"manual\" class=\"k2b-choice-popover\">\n <div class=\"k2b-choice-options\" role=\"listbox\" id={listboxId}>\n <Show when={props.status}>{(status) => <div class=\"k2b-choice-status\">{status()}</div>}</Show>\n <Show when={!props.status && loader.error()}>\n {(message) => (\n <div class=\"k2b-choice-status\" data-tone=\"danger\">\n <span>{message()}</span>\n <button type=\"button\" onClick={loader.retry}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n {/* Keyed by option ID, not object: each fetch returns new objects, and a row replaced between press and release\n would swallow the click. */}\n <For\n each={options().map((option) => option.value)}\n fallback={\n <Show when={!props.status && !loader.error()}>\n <Show\n when={loader.loading()}\n fallback={\n <div class=\"k2b-choice-status\">\n {query().length >= 2 ? (props.empty ?? selectMessages().noResultsFound) : selectMessages().typeToSearch}\n </div>\n }\n >\n {/* The first search has nothing to keep visible yet: rows of the final size wait in its place. */}\n <div class=\"k2b-choice-loading\" role=\"status\">\n <span class=\"k2b-sr-only\">{messages().loading}</span>\n <For each={[62, 48, 55]}>\n {(width) => (\n <div class=\"k2b-choice-loading__row\" aria-hidden=\"true\">\n <span class=\"k2b-skeleton\" />\n <span class=\"k2b-skeleton\" style={{ width: `${width}%` }} />\n </div>\n )}\n </For>\n </div>\n </Show>\n </Show>\n }\n >\n {(id, index) => {\n const first = optionsById().get(id)!;\n const option = () => optionsById().get(id) ?? first;\n return (\n <button\n ref={(element) => (optionRefs[index()] = element)}\n type=\"button\"\n id={`${listboxId}-${index()}`}\n class=\"k2b-choice-option\"\n role=\"option\"\n aria-selected={index() === focusedIndex()}\n aria-disabled={option().disabled ? \"true\" : undefined}\n data-focused={index() === focusedIndex() ? \"true\" : undefined}\n onPointerMove={() => {\n if (!option().disabled) focus(index());\n }}\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => select(option())}\n >\n <Show when={option().icon}>{(icon) => <i class={iconClass(icon())} aria-hidden=\"true\" />}</Show>\n <span>\n <strong>{option().label}</strong>\n <Show when={option().description}>{(description) => <small>{description()}</small>}</Show>\n </span>\n </button>\n );\n }}\n </For>\n </div>\n <Show when={props.footer}>{(footer) => <div class=\"k2b-choice-footer\">{footer()}</div>}</Show>\n </div>\n </div>\n </Field>\n );\n}\n\nexport default Combobox;\n"],"mappings":"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","ignoreList":[]}
|