{"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import {\n createLazyMeasurementsView,\n getMeasurementKey,\n} from './lazy-measurements'\nimport { approxEqual, debounce, memo, notUndefined } from './utils'\nimport {\n classifyScrollEvent,\n externalRetiresCommand,\n flingCaught,\n flingSpedUp,\n} from './scroll-classifier'\nimport {\n IosGesture,\n iosMomentumOverridesWrites,\n isIOSWebKit,\n} from './ios-gesture'\nimport type { ScrollPhase, ScrollSample } from './scroll-classifier'\n\nexport { _resetIOSDetectionForTests } from './ios-gesture'\nexport { approxEqual, debounce, memo, notUndefined } from './utils'\nexport type { NoInfer, PartialKeys } from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth' | 'instant'\n\ntype ScrollAnchor = 'start' | 'end'\n\ntype FollowOnAppend = boolean | ScrollBehavior\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\ntype ScrollToEndOptions = Pick\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n /**\n * Lane count of the virtualizer. When greater than 1, `overscan` counts\n * rows of `lanes` items rather than single items.\n */\n lanes?: number\n}\n\ntype Key = number | string | bigint\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n}\n\nexport interface Rect {\n width: number\n height: number\n}\n\n//\n\nconst getRect = (element: HTMLElement): Rect => {\n const { clientWidth, clientHeight } = element\n return { width: clientWidth, height: clientHeight }\n}\n\n// Animation frames for `useAnimationFrameWithResizeObserver`, requested from\n// the scroll element's own window rather than the global one.\nconst createFrameQueue = (targetWindow: Window) => {\n const ids = new Set()\n return {\n schedule: (fn: () => void) => {\n const id = targetWindow.requestAnimationFrame(() => {\n ids.delete(id)\n fn()\n })\n ids.add(id)\n },\n cancel: () => {\n ids.forEach((id) => targetWindow.cancelAnimationFrame(id))\n ids.clear()\n },\n }\n}\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n // With lanes, the visible range is already aligned to whole rows; overscan\n // by whole rows too, so every lane gets the same number of items rendered\n // (and measured). Overscanning single items leaves partial rows, letting one\n // lane collect more measured sizes than the others and drift (#1036).\n const overscan = range.overscan * Math.max(range.lanes ?? 1, 1)\n const start = Math.max(range.startIndex - overscan, 0)\n const end = Math.min(range.endIndex + overscan, range.count - 1)\n const len = end - start + 1\n\n const arr = new Array(len)\n for (let i = 0; i < len; i++) {\n arr[i] = start + i\n }\n return arr\n}\n\nexport const observeElementRect = (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(getRect(element as unknown as HTMLElement))\n\n if (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const frames = createFrameQueue(targetWindow)\n const observer = new targetWindow.ResizeObserver(() => {\n const run = () => {\n handler(getRect(element as unknown as HTMLElement))\n }\n\n instance.options.useAnimationFrameWithResizeObserver\n ? frames.schedule(run)\n : run()\n })\n\n observer.observe(element, { box: 'content-box' })\n\n return () => {\n observer.unobserve(element)\n frames.cancel()\n }\n}\n\nconst addEventListenerOptions = {\n passive: true,\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nconst supportsScrollend =\n typeof window == 'undefined' ? true : 'onscrollend' in window\n\ntype ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void\n\n// Shared core: both element and window variants attach scroll/scrollend\n// listeners with the same lifecycle; they only differ in how to read the\n// current offset from the scroll target.\nconst observeOffset = (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n readOffset: (target: T) => number,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n\n let offset = 0\n const fallback = registerScrollendEvent\n ? null\n : debounce(\n targetWindow,\n () => cb(readOffset(element), false),\n instance.options.isScrollingResetDelay,\n )\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = readOffset(element)\n fallback?.()\n cb(offset, isScrolling)\n }\n const handler = createHandler(true)\n const endHandler = createHandler(false)\n\n element.addEventListener('scroll', handler, addEventListenerOptions)\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\n // Removing the listener doesn't retract a reset already queued by the\n // last scroll, and that call would land on a virtualizer that has been\n // torn down — in React, a dispatch into an unmounted tree.\n fallback?.cancel()\n }\n}\n\nexport const observeElementOffset = (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n) =>\n observeOffset(instance, cb, (el) => {\n const { horizontal, isRtl } = instance.options\n return horizontal ? el.scrollLeft * ((isRtl && -1) || 1) : el.scrollTop\n })\n\nexport const observeWindowOffset = (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n) =>\n observeOffset(instance, cb, (win) =>\n instance.options.horizontal ? win.scrollX : win.scrollY,\n )\n\nexport const measureElement = (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer,\n) => {\n // When useCachedMeasurements is enabled, return the cached size\n // (or estimateSize as fallback) instead of measuring the DOM.\n if (instance.options.useCachedMeasurements) {\n const index = instance.indexFromElement(element)\n const key = instance.options.getItemKey(index)\n return (\n instance.itemSizeCache.get(key) ?? instance.options.estimateSize(index)\n )\n }\n\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\n }\n\n // When called without a ResizeObserverEntry (sync measurement path),\n // return the previously measured size if available. This avoids a\n // synchronous layout read (offsetWidth/offsetHeight) on re-renders.\n // The ResizeObserver is already observing the element and will deliver\n // the accurate size asynchronously if it changed.\n // Users who need synchronous DOM reads can provide a custom measureElement.\n if (!entry) {\n const index = instance.indexFromElement(element)\n const key = instance.options.getItemKey(index)\n const cachedSize = instance.itemSizeCache.get(key)\n if (cachedSize !== undefined) {\n return cachedSize\n }\n }\n\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\n ]\n}\n\nconst scrollWithAdjustments = (\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => {\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: offset + adjustments,\n behavior,\n })\n}\n\nexport const windowScroll: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => void = scrollWithAdjustments\n\nexport const elementScroll: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => void = scrollWithAdjustments\n\ntype LaneAssignmentMode = 'estimate' | 'measured'\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n ) => void\n observeElementRect: (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer,\n cb: ObserveOffsetCallBack,\n ) => void | (() => void)\n // Optional\n debug?: boolean\n initialRect?: Rect\n onChange?: (\n instance: Virtualizer,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number | (() => number)\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => Array\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array\n lanes?: number\n anchorTo?: ScrollAnchor\n followOnAppend?: FollowOnAppend\n scrollEndThreshold?: number\n isScrollingResetDelay?: number\n useScrollendEvent?: boolean\n enabled?: boolean\n isRtl?: boolean\n useAnimationFrameWithResizeObserver?: boolean\n laneAssignmentMode?: LaneAssignmentMode\n useCachedMeasurements?: boolean\n}\n\ntype ScrollState = {\n // what we want\n index: number | null\n align: ScrollAlignment\n // scrollToEnd: track the DOM max scroll offset instead of the item's offset\n toEnd?: boolean\n\n // lifecycle\n startedAt: number\n // how the command was asked to scroll; a queued command writes with it\n behavior: ScrollBehavior\n\n // target tracking\n lastTargetOffset: number\n\n // settling\n stableFrames: number\n phase: ScrollPhase\n\n // A `queued` command's view of the fling it waits for: the scroll events\n // since it was queued, at most the last 200ms (`flingSpedUp`,\n // `flingCaught`). Read only while `queued`.\n samples?: Array\n}\n\nconst initialScrollPhase = (\n behavior: ScrollBehavior,\n atTarget: boolean,\n): ScrollPhase =>\n behavior === 'smooth' ? (atTarget ? 'smoothLanded' : 'smooth') : 'instant'\n\n// A smooth scroll owns the position: size compensation, the prepend anchor\n// sync and far measurements hold off until it switches to instant writes.\nconst isSmoothScroll = (state: ScrollState | null): state is ScrollState =>\n state?.phase === 'smooth' || state?.phase === 'smoothLanded'\n\n// What `setOptions` decided about the scroll position for `_willUpdate` to\n// carry out once the consumer has rendered: keep the reading anchor in place\n// after a prepend (`scrollOffset` already moved by `delta`, the element has\n// not), or follow an append to the end. A prepend that qualifies for both\n// only follows.\ntype PendingScrollAnchor =\n | { kind: 'anchor'; delta: number }\n | { kind: 'follow'; behavior: ScrollBehavior }\n\nfunction isAppendWithTrim(\n prevCount: number,\n nextCount: number,\n getPreviousKey: (index: number) => Key,\n getNextKey: (index: number) => Key,\n): boolean {\n if (nextCount === 0) return false\n\n const firstKey = getNextKey(0)\n const removedKeys = new Set()\n let removedCount = 0\n while (removedCount < prevCount) {\n const key = getPreviousKey(removedCount)\n if (key === firstKey) break\n removedKeys.add(key)\n removedCount++\n }\n\n const retainedCount = prevCount - removedCount\n if (retainedCount === 0 || retainedCount >= nextCount) return false\n\n for (let i = 0; i < retainedCount; i++) {\n if (getNextKey(i) !== getPreviousKey(removedCount + i)) return false\n }\n for (let i = retainedCount; i < nextCount; i++) {\n if (removedKeys.has(getNextKey(i))) return false\n }\n return true\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array void)> = []\n options!: Required>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollState: ScrollState | null = null\n measurementsCache: Array = []\n // Keys belong to the layout build, even when VirtualItems are read later.\n // The flat [start, size, ...] buffer is reused across builds.\n private _singleLaneMeasurements: {\n flat: Float64Array\n items: Array\n } | null = null\n itemSizeCache = new Map()\n private itemSizeCacheVersion = 0\n private laneAssignments = new Map() // index → lane cache\n // Earliest index dirtied since last getMeasurements() rebuild, or null.\n private pendingMin: number | null = null\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\n private pendingScrollAnchor: PendingScrollAnchor | null = null\n scrollRect: Rect | null = null\n /**\n * The scroll position in the list's layout, consistent with\n * `getOffsetForIndex`, `scrollToOffset` and `initialOffset`. While a\n * correction is held (`_holdOffset`), `getVirtualItems()` and\n * `getTotalSize()` describe what is rendered, shifted by the held amount;\n * this stays the layout position.\n */\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n /**\n * @deprecated Always 0: a scroll correction is folded into `scrollOffset`\n * at once, so there is never an outstanding adjustment to add to it. Read\n * `scrollOffset` alone.\n */\n get scrollAdjustments() {\n return 0\n }\n // Scroll corrections (a prepend's anchor delta, size changes above the\n // viewport) that could not be written to the element because a write was\n // impossible at the time (see `_canWriteScroll`): the difference between\n // `scrollOffset`, which always carries the corrected layout position, and\n // where the element is. While it is non-zero the rows and the total size\n // are exposed shifted by `-_holdOffset`, so every adapter renders the\n // reader's row where it was, writes subtract it (`_scrollToOffset`) and\n // scroll events add it back (the handler in `_willUpdate`). Released by\n // `_flushHoldIfReady`: the rows re-render in layout coordinates and the\n // element moves by the same amount in one paint.\n private _holdOffset = 0\n // Whether the element's last scroll event reported a position past either\n // edge (the rubber-band bounce). Judged at report time against the\n // element's own max, with a 1px tolerance for a fractional scrollTop: a\n // sizer that shrinks after the report (a trim) is not a bounce, and\n // `scrollOffset` is no judge either, since an eager bump past the max while\n // the sizer has not grown yet (#1258) is not one.\n //\n // Stored rather than read from the element when a write is decided. The\n // two differ once a write has landed but not been reported back, and in\n // that window the element reads in bounds while `scrollOffset` is still\n // the pre-write value. With the anchor sync now skipped in that window\n // (`_awaitingCommandReadBack`), the remaining difference is the trim: a\n // list that shrank under the position reads past the element's max until\n // the browser clamps it, which is where the anchor's write has to go\n // (`followOnAppend does not follow 'trim only'`; reading the element at\n // write time still moves 49 of 1080 snapshot seeds).\n private _reportedOverscroll = false\n // The touch gesture in progress (see `IosGesture`). Its tail closing on\n // its own makes a write possible again: the last momentum frame may have\n // come before the timer. The hold is released first, so a command that\n // waited for the tail is written over rows already back in layout\n // coordinates.\n private _iosGesture = new IosGesture({\n getWindow: () => this.targetWindow,\n now: () => this.now(),\n // The end of a fling can move less than a pixel per scroll event, so\n // events can stop for 150ms while the fling is still running (seen on\n // an iPhone, 27.0.1). A command waiting for it would then be written\n // into the fling and overridden. The element having moved since the\n // last event means it has not ended: wait again. Not while our own\n // write has yet to report: that moved it.\n tailStillMoving: () => {\n const state = this.scrollState\n if (state?.phase !== 'queued' || this.pendingWrite !== null) {\n return false\n }\n const now = this._readElementOffset()\n if (\n now === null ||\n this._lastElementOffset === null ||\n Math.abs(now - this._lastElementOffset) < 1\n ) {\n return false\n }\n this._lastElementOffset = now\n // It moved with no event: a sample, so the speed `flingCaught` reads\n // when it stops is not the one from before the silence.\n state.samples = [...(state.samples ?? []), { t: this.now(), offset: now }]\n return true\n },\n onTailClosed: () => {\n // A fling that stopped at speed was caught by a finger that is still\n // down, with no touch events: the user has taken over, as with a\n // drag, and iOS would undo the write anyway.\n const state = this.scrollState\n if (state?.phase === 'queued' && flingCaught(state.samples ?? [])) {\n this.scrollState = null\n }\n this._flushHoldIfReady(true)\n this._writeAwaitingCommand()\n },\n })\n // The last position the scroll handler was given, in the element's own\n // coordinates. The tail compares it with the element (`tailStillMoving`\n // above).\n private _lastElementOffset: number | null = null\n // Our last write to the element, from `_scrollToOffset` until the next\n // scroll event reports it (the only place it is cleared). Until then\n // `scrollOffset` may still hold the old position.\n //\n // - `target`: where the write puts the element (offset + the adjustment\n // passed to `scrollToFn`).\n // Safari (and Chrome/Firefox under certain DPRs) round writes to whole\n // pixels: wrote 12345.5, read back 12346. A read-back within 1.5px of\n // `target` is taken as our own and adopts the exact value, so reconcile\n // does not see a moved target and write again; a user scroll has moved\n // further by the time it reports.\n // - `smooth`: the write animates, so until it lands the element is\n // somewhere between the old offset and `target`.\n // - `lowMaxes`: for a command's instant write, each scroll max below\n // `target` the element had since the write. A command's target is\n // clamped to the max at the write, but the sizer can shrink under it\n // before the report (rows measured smaller, a count change) and grow\n // back, so the read-back is the max the browser clamped to then rather\n // than the element's current one. Read wherever the sizer can have\n // been committed (`_noteClampMax`).\n private pendingWrite: {\n target: number\n smooth: boolean\n lowMaxes?: Array\n } | null = null\n // A compensation write from `applyScrollAdjustment` whose target exceeded\n // the element's scroll max at the moment of the write. The browser clamps\n // such a write because the consumer's sizer has not grown yet: an\n // end-anchored item growing at the bottom only extends `scrollHeight` to\n // its own end, so with `paddingEnd > 0` the clamp lands exactly\n // `paddingEnd` short of the target (#1258). `_willUpdate` re-issues the\n // write once the sizer has caught up; the clamped read-back keeps it\n // pending, any other scroll event (a real gesture) cancels it.\n private _clampedAdjustment: { target: number; maxAtWrite: number } | null =\n null\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\n delta: number,\n instance: Virtualizer,\n ) => boolean)\n elementsCache = new Map()\n // Set while a ResizeObserver callback measures its entries; `resizeItem`\n // records the pending notify here instead of firing it per entry.\n private _resizeBatch: { sync: boolean; notify?: boolean } | null = null\n private now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n let _frames: ReturnType | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n }\n\n const targetWindow = this.targetWindow\n if (!targetWindow || !targetWindow.ResizeObserver) {\n return null\n }\n\n const frames = (_frames = createFrameQueue(targetWindow))\n return (_ro = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\n // Measure every entry before notifying. A notify that adjusted\n // scroll re-renders synchronously, and that render can unmount\n // nodes whose entries are still queued here, leaving them\n // unmeasured. With lanes, a half-measured row lets one lane drift\n // away from the others (#1036).\n const batch: { sync: boolean; notify?: boolean } = { sync: false }\n this._resizeBatch = batch\n try {\n entries.forEach(measureEntry)\n } finally {\n this._resizeBatch = null\n if (batch.notify) {\n this.notify(batch.sync)\n this._noteClampMax()\n this._flushHoldIfReady(true)\n this._retryClampedAdjustment()\n }\n }\n }\n this.options.useAnimationFrameWithResizeObserver\n ? frames.schedule(run)\n : run()\n }))\n }\n\n const measureEntry = (entry: ResizeObserverEntry) => {\n const node = entry.target as TItemElement\n const index = this.indexFromElement(node)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n // Find the cache entry pointing to this exact node and remove\n // it. We can't call getItemKey(index) here because items may\n // have been removed since this node was rendered — the index\n // could be stale and out-of-bounds in the user's data array\n // (regression test in e2e/.../stale-index.spec.ts, fix #1148).\n // The === comparison naturally handles the React-replaced-\n // a-node-for-the-same-key case: that entry now points to a\n // different node, so this loop won't match.\n for (const [cacheKey, cachedNode] of this.elementsCache) {\n if (cachedNode === node) {\n this.elementsCache.delete(cacheKey)\n break\n }\n }\n return\n }\n\n if (!this.isIndexInRange(index)) return\n\n if (this.shouldMeasureDuringScroll(index)) {\n this.resizeItem(index, this.options.measureElement(node, entry, this))\n }\n }\n\n return {\n disconnect: () => {\n get()?.disconnect()\n _frames?.cancel()\n _ro = null\n _frames = null\n },\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } | null = null\n\n constructor(opts: VirtualizerOptions) {\n this.setOptions(opts)\n }\n\n setOptions = (opts: VirtualizerOptions) => {\n // Skip `{...defaults, ...opts}` because explicit `undefined` values in\n // opts would override defaults with `undefined`.\n const merged = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n gap: 0,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n anchorTo: 'start',\n followOnAppend: false,\n scrollEndThreshold: 1,\n isScrollingResetDelay: 150,\n enabled: true,\n isRtl: false,\n useScrollendEvent: false,\n useAnimationFrameWithResizeObserver: false,\n laneAssignmentMode: 'estimate',\n useCachedMeasurements: false,\n } as unknown as Required>\n\n for (const key in opts) {\n const v = (opts as any)[key]\n if (v !== undefined) (merged as any)[key] = v\n }\n\n const prevOptions = this.options as\n | Required>\n | undefined\n let anchor: [Key, number] | null = null\n let followOnAppend: ScrollBehavior | null = null\n let edgeKeysChanged = false\n\n if (\n prevOptions !== undefined &&\n prevOptions.enabled &&\n merged.enabled &&\n merged.anchorTo === 'end' &&\n this.scrollElement !== null\n ) {\n const prevCount = prevOptions.count\n const nextCount = merged.count\n const measurements = this.getMeasurements()\n const previousItems = this._singleLaneMeasurements?.items ?? measurements\n const getPreviousKey = (index: number) =>\n getMeasurementKey(previousItems[index]!)\n const prevFirstKey = prevCount > 0 ? getPreviousKey(0) : null\n const prevLastKey = prevCount > 0 ? getPreviousKey(prevCount - 1) : null\n const didCountChange = nextCount !== prevCount\n const didEdgeKeysChange =\n didCountChange ||\n (prevCount > 0 &&\n nextCount > 0 &&\n (merged.getItemKey(0) !== prevFirstKey ||\n merged.getItemKey(nextCount - 1) !== prevLastKey))\n\n if (didEdgeKeysChange) {\n edgeKeysChanged = true\n const item =\n prevCount > 0\n ? (this.getVirtualItemForOffset(this.getScrollOffset()) ??\n measurements[0])\n : null\n\n if (item) {\n anchor = [item.key, this.getScrollOffset() - item.start]\n }\n\n const behavior =\n merged.followOnAppend === true\n ? 'auto'\n : merged.followOnAppend || null\n\n if (\n behavior &&\n nextCount > 0 &&\n this.isAtEnd(prevOptions.scrollEndThreshold) &&\n (prevCount === 0 || merged.getItemKey(nextCount - 1) !== prevLastKey)\n ) {\n if (\n nextCount > prevCount ||\n isAppendWithTrim(\n prevCount,\n nextCount,\n getPreviousKey,\n merged.getItemKey,\n )\n ) {\n followOnAppend = behavior\n }\n }\n }\n }\n\n this.options = merged\n\n // When edge keys changed (prepend, trim, reorder, etc.) the key→index\n // mapping has shifted. Force a full measurement rebuild so the anchor\n // resolution below reads positions from the new layout, not the stale\n // memoised cache. Without this, a stable `getItemKey` reference +\n // unchanged `count` would let getMeasurements() return the old layout.\n if (edgeKeysChanged) {\n this.pendingMin = 0\n this.itemSizeCacheVersion++\n }\n\n // Eagerly adjust scrollOffset so the virtualizer computes the correct\n // visible range during the current render pass — before _willUpdate\n // syncs the DOM scroll position in a layout effect. Without this,\n // the virtualizer would render the wrong items for one frame (the\n // estimate-based positions are stale) and then correct in the next\n // frame, producing a visible \"jump\" on prepend with dynamic sizes.\n // Not before a scroll command's write has been read back: `scrollOffset`\n // is still the pre-command position, so the anchor would be resolved\n // against rows that are no longer where the command put the element, and\n // the sync would write that stale offset over the command. Reconcile\n // retargets an index or end command from the new layout; an offset\n // command lands where it was written (#1307, step 5).\n let anchorDelta: number | null = null\n if (\n anchor &&\n this.scrollOffset !== null &&\n !this._awaitingCommandReadBack()\n ) {\n const [anchorKey, anchorOffset] = anchor\n const newMeasurements = this.getMeasurements()\n const { count, getItemKey } = this.options\n let idx = 0\n while (idx < count && getItemKey(idx) !== anchorKey) {\n idx++\n }\n if (idx < count) {\n const anchorItem = newMeasurements[idx]\n if (anchorItem) {\n // Clamp to the reachable range's lower bound — anchorOffset may\n // have been derived from a transiently negative scrollOffset\n // (rubber-band), and a negative tracked offset never self-heals\n // when the element cannot scroll (#1229).\n const newOffset = Math.max(0, anchorItem.start + anchorOffset)\n // A no-op end scroll emits no event to correct a reading-anchor offset.\n if (!followOnAppend && newOffset !== this.scrollOffset) {\n anchorDelta = newOffset - this.scrollOffset\n this.scrollOffset = newOffset\n }\n }\n }\n }\n\n if (followOnAppend) {\n this.pendingScrollAnchor = { kind: 'follow', behavior: followOnAppend }\n } else if (anchorDelta !== null) {\n if (this._canWriteScroll()) {\n this.pendingScrollAnchor = { kind: 'anchor', delta: anchorDelta }\n } else {\n // The element cannot take the write (a touch owns it on iOS, or it is\n // overscrolled). Hold the delta instead: this render already exposes\n // the rows and the total shifted back by it, so the reader's row\n // stays put, and the flush writes it once a write is possible.\n this._holdOffset += anchorDelta\n this._followOffsetTarget(anchorDelta)\n }\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n // Returns `true` when it performed a synchronous `scrollTop` write this\n // tick, `false` when the delta was zero or the write was deferred (iOS).\n // `resizeItem` uses that to decide whether the follow-up `notify` must be\n // synchronous so the grown transforms commit in the same paint (#1227).\n private applyScrollAdjustment(\n delta: number,\n behavior?: ScrollBehavior,\n ): boolean {\n if (delta === 0) return false\n\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n // The correction moves the content the viewport is on; an offset target\n // moves with it, or reconcile would wait for a position it can never see.\n this._followOffsetTarget(delta)\n\n if (!this._canWriteScroll()) {\n // Hold the correction: `scrollOffset` takes it as if written, the rows\n // are exposed shifted back by it. The notify must be synchronous like\n // a write's, so the shifted rows commit in the same paint as the\n // content change that caused the correction.\n this._holdOffset += delta\n if (this.scrollOffset !== null) this.scrollOffset += delta\n return true\n } else {\n const offset = this.getScrollOffset()\n this._clampedAdjustment = this._clampedBy(offset + delta)\n const write = this._scrollToOffset(offset, {\n adjustments: delta,\n behavior,\n })\n // Eagerly carry the intended target in `scrollOffset` so callers that\n // read it before the next scroll event — notably the next `resizeItem`\n // tick's `getVirtualDistanceFromEnd()` / `wasAtEnd` check — see the\n // post-adjustment position even when the DOM `scrollTop` write was\n // clamped because the consumer hasn't grown the sizer yet (`notify()`\n // runs after this in `resizeItem`). Same idea as the eager\n // `scrollOffset` adjustment for prepend in `setOptions` (#1176). A\n // `scrollToFn` that reports the write synchronously has already set\n // `scrollOffset` to the read-back (and cleared `pendingWrite`).\n if (this.scrollOffset !== null) {\n if (this.pendingWrite === write) this.scrollOffset += delta\n // Clamp only the lower bound: a negative offset is unreachable, and\n // on an unscrollable element (content fits the viewport) no scroll\n // event ever fires to correct it, permanently skewing\n // getDistanceFromEnd() and wedging the hold flush (#1229).\n // Upper-bound overflow stays untouched — it is transiently\n // legitimate mid-prepend while the consumer's sizer catches up.\n if (this.scrollOffset < 0) this.scrollOffset = 0\n }\n return true\n }\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.observer.disconnect()\n if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\n // The element is let go of: give it back its overflow now. A stop the\n // next element needs starts afresh.\n this._momentumStop?.restore()\n this._momentumStop = null\n // The debounce cancelled above is the only thing that writes `isScrolling`\n // back to false, so a cleanup inside the reset window would strand it, and\n // the direction derived from it, as true. That matters because `cleanup`\n // also runs when the scroll element changes or `enabled` goes false, where\n // the instance lives on.\n this.isScrolling = false\n this.scrollDirection = null\n // The iOS gesture/deferral state is scoped to the current scroll\n // element: the touch listeners that maintain it were just removed, and\n // an in-flight touch keeps targeting the old element (implicit touch\n // capture), so the new element never reports it. Carrying the state\n // over would replay a stale deferred delta on the new element's first\n // flush, and a cleanup that lands mid-touch or inside the post-touchend\n // grace window would strand the gesture (the listeners that end it were\n // just removed), deferring every adjustment on the new element until\n // its next touch cycle.\n this._holdOffset = 0\n this._reportedOverscroll = false\n // (The gesture was ended with its listeners, in the unsubs above.)\n this._clampedAdjustment = null\n // A write to the old element will never be read back.\n this.pendingWrite = null\n this.scrollElement = null\n this.targetWindow = null\n }\n\n _didMount = () => {\n return () => {\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.enabled\n ? this.options.getScrollElement()\n : null\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n if (!scrollElement) {\n this.maybeNotify()\n return\n }\n\n this.scrollElement = scrollElement\n\n if (this.scrollElement && 'ownerDocument' in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView\n } else {\n this.targetWindow = this.scrollElement?.window ?? null\n }\n\n this.elementsCache.forEach((cached) => {\n this.observer.observe(cached)\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.maybeNotify()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset, isScrolling) => {\n // Past the top is never a resting position. Past the bottom is\n // judged only while scrolling: at rest the element has clamped,\n // and a stale sizer makes no bounce.\n const elementMax = isScrolling ? this._elementMaxScrollOffset() : null\n const wasOverscrolled = this._reportedOverscroll\n this._reportedOverscroll =\n offset < 0 || (elementMax !== null && offset > elementMax + 1)\n const elementOffset = offset\n this._lastElementOffset = elementOffset\n // Everything below works in layout coordinates.\n offset = this._toLayoutOffset(offset)\n\n const kind = this._classifyScrollEvent(\n offset,\n isScrolling,\n elementMax,\n )\n if (kind === 'spurious') return\n\n if (kind === 'readBack') {\n // Adopt the exact target over the browser's rounded value (see\n // `pendingWrite`).\n offset = this.pendingWrite!.target\n } else if (\n kind === 'clampedReadBack' &&\n this.scrollState?.index != null &&\n // Not `elementMax`: an adapter can report the read-back at rest.\n offset < this.getMaxScrollOffset() - 1.5\n ) {\n // Our write, clamped at a max the sizer has since grown back\n // from: reconcile writes the target again, even when the layout\n // came back to the same end.\n this.scrollState.lastTargetOffset = offset\n } else if (\n externalRetiresCommand({\n kind,\n offset,\n command: this.scrollState,\n target: () => this.getScrollStateTarget(this.scrollState!),\n })\n ) {\n this.scrollState = null\n }\n this.pendingWrite = null\n\n // A pending clamped compensation write (#1258) survives only its\n // own read-back, which the browser reports at the scroll max we\n // saw at write time. Anything else is a real gesture (or the write\n // landing after all), so drop it rather than yank the user later.\n // Not `kind !== 'clampedEcho'`: the classifier ranks `readBack` and\n // `clampedReadBack` first, and either can also sit at that max, so\n // the record must survive them too.\n if (\n this._clampedAdjustment !== null &&\n Math.abs(offset - this._clampedAdjustment.maxAtWrite) >= 1.5\n ) {\n this._clampedAdjustment = null\n }\n\n // If the offset hasn't moved, this is the echo of our own\n // adjustment write — `applyScrollAdjustment` already folded it\n // into `scrollOffset`. There's no direction to infer, so leave\n // it alone; a real gesture always moves the offset.\n const prevOffset = this.getScrollOffset()\n const prevDirection = this.scrollDirection\n this.scrollDirection = isScrolling\n ? prevOffset === offset\n ? this.scrollDirection\n : prevOffset < offset\n ? 'forward'\n : 'backward'\n : null\n this.scrollOffset = offset\n this.isScrolling = isScrolling\n\n // A finger that lands on a fling fires no touch events (#1307), so\n // while a command waits for the fling, the scroll events are all\n // that show the user taking over: the scroll turns back, or speeds\n // up (`flingSpedUp`). Momentum does neither inside the scroll\n // range; a bounce does both, so no part of one counts.\n const queued = this.scrollState\n if (\n queued?.phase === 'queued' &&\n kind === 'external' &&\n isScrolling\n ) {\n if (wasOverscrolled || this._reportedOverscroll) {\n queued.samples = []\n } else {\n const t = this.now()\n queued.samples = [\n ...(queued.samples ?? []).filter(\n (sample) => t - sample.t <= 200,\n ),\n { t, offset: elementOffset },\n ]\n if (\n (prevDirection !== null &&\n this.scrollDirection !== prevDirection) ||\n flingSpedUp(queued.samples)\n ) {\n this.scrollState = null\n }\n }\n }\n if (\n this._iosGesture.onScroll({\n isScrolling,\n ownReadBack: kind === 'readBack',\n moved: offset !== prevOffset,\n // Neither our write's read-back nor a frame of our smooth\n // animation: the user or a fling moved it.\n external:\n kind === 'external' &&\n this.scrollState?.phase !== 'smooth' &&\n this.scrollState?.phase !== 'smoothFinishing',\n }) &&\n // The user scrolls: a command still waiting for the tail is\n // theirs to override, like a written one would be.\n this.scrollState?.phase === 'queued'\n ) {\n this.scrollState = null\n }\n\n // A held correction is written once a write is possible.\n this._flushHoldIfReady(true)\n\n if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n // Touch event listeners (iOS-aware deferral).\n if ('addEventListener' in this.scrollElement) {\n this.unsubs.push(\n this._iosGesture.listen(this.scrollElement as unknown as EventTarget),\n )\n }\n\n this._scrollToOffset(this.getScrollOffset())\n }\n\n // The consumer has committed the sizer.\n this._noteClampMax()\n\n const anchor = this.pendingScrollAnchor\n this.pendingScrollAnchor = null\n\n if (anchor && this.scrollElement && this.options.enabled) {\n if (anchor.kind === 'anchor') {\n // scrollOffset was eagerly adjusted in setOptions so the\n // virtualizer already computed the correct range during render.\n // Now sync the browser's actual scroll position to match.\n //\n // `setOptions` found the element writable; a scroll event between\n // it and this commit (a concurrent render) can have changed that.\n // Hold the delta after all and have the rows re-rendered shifted;\n // an update scheduled from a layout effect commits before paint.\n if (!this._canWriteScroll()) {\n this._holdOffset += anchor.delta\n this._followOffsetTarget(anchor.delta)\n this.notify(false)\n } else if (\n isSmoothScroll(this.scrollState) &&\n !approxEqual(\n this.getScrollOffset() - anchor.delta,\n this.scrollState.lastTargetOffset,\n )\n ) {\n // A smooth programmatic scroll is still travelling. Writing scrollTop\n // here would cancel the browser's animation, and Chromium drops a\n // smooth request re-issued in the frame right after that cancel, so\n // the journey would be stranded. The target is index-based and\n // recomputes against the new layout in reconcileScroll, so let the\n // animation run; the next scroll event re-syncs the tracked offset.\n // A smooth scroll that has already landed (offset at its target,\n // reconcile not yet retired it) still gets the anchor sync.\n } else {\n this._followOffsetTarget(anchor.delta)\n this._scrollToOffset(this.getScrollOffset())\n }\n } else {\n this.scrollToEnd({ behavior: anchor.behavior })\n }\n }\n\n // A hold whose cause has passed without a scroll event (the sizer caught\n // up with a position that read as overscrolled) is written here. An\n // update scheduled from a layout effect commits before paint, so the\n // notify need not be synchronous.\n this._flushHoldIfReady(false)\n // The consumer has committed the new total size by now, so a clamped\n // compensation write may have room (#1258).\n this._retryClampedAdjustment()\n }\n\n // Classify a scroll event (see `ScrollEventKind`) from the state as it was\n // before the event. `offset` is the reported position in layout\n // coordinates; `elementMax` is the element's own max, read only while\n // scrolling (null otherwise).\n private _classifyScrollEvent = (\n offset: number,\n isScrolling: boolean,\n elementMax: number | null,\n ) =>\n classifyScrollEvent({\n offset,\n isScrolling,\n elementMax,\n holdOffset: this._holdOffset,\n scrollOffset: this.scrollOffset,\n pendingWrite: this.pendingWrite,\n clampedMaxAtWrite: this._clampedAdjustment?.maxAtWrite ?? null,\n })\n\n // Re-issue a compensation write the browser clamped because the sizer had\n // not grown yet (#1258, #1266). Called after `notify` in `resizeItem`,\n // which covers consumers that size the container synchronously inside\n // `onChange` (direct DOM updates, flushSync renders — where no re-render\n // may follow at all), and from `_willUpdate` for consumers that size it\n // during an asynchronous render. Both the clamped read-back and the\n // absence of one leave `_clampedAdjustment` set, so timing does not matter.\n private _retryClampedAdjustment = () => {\n if (\n this._clampedAdjustment === null ||\n !this.scrollElement ||\n !this.options.enabled\n ) {\n return\n }\n const { target, maxAtWrite } = this._clampedAdjustment\n const max = this.getMaxScrollOffset()\n if (max > maxAtWrite + 0.5) {\n // Still short (the sizer grew only partially): stay pending against\n // the new max so the next opportunity retries.\n this._clampedAdjustment =\n target > max + 0.5 ? { target, maxAtWrite: max } : null\n this._scrollToOffset(target)\n }\n }\n\n // Write the command that `_startScroll` left waiting for the momentum\n // tail, against the layout as it is now (rows measured during the fling\n // have moved an index target).\n private _writeAwaitingCommand = () => {\n const state = this.scrollState\n if (state === null || state.phase !== 'queued') return\n const { behavior } = state\n this.getMeasurements()\n const offset = this.getScrollStateTarget(state)\n state.lastTargetOffset = offset\n // The hold flushed just before can leave a clamp retry (#1258); it\n // would write its old target over this command.\n this._clampedAdjustment = null\n state.phase = initialScrollPhase(\n behavior,\n state.index != null && approxEqual(offset, this.getScrollOffset()),\n )\n this._scrollToOffset(offset, { behavior })\n this.scheduleScrollReconcile()\n }\n\n // The element's position as the offset observers report it, or null for a\n // scroll element that is neither an element nor a window.\n private _readElementOffset = (): number | null => {\n const el = this.scrollElement as unknown as Partial<\n Element & Pick\n > | null\n if (el == null) return null\n const { horizontal, isRtl } = this.options\n if (typeof el.scrollTop === 'number') {\n return horizontal ? el.scrollLeft! * ((isRtl && -1) || 1) : el.scrollTop\n }\n if (typeof el.scrollY === 'number') {\n return horizontal ? el.scrollX! : el.scrollY\n }\n return null\n }\n\n // Whether a scrollTop write made now would reach the element and stay:\n // - not on iOS while a touch gesture owns the scroll (`IosGesture`): a\n // dragging finger ignores the write, momentum is cancelled by it on\n // iOS 26 and earlier and overrides it within a frame on 27 (#884,\n // #1307), so a correction is held through the tail on every version;\n // - not while the element is overscrolled past either edge (the\n // rubber-band bounce): WebKit discards the write and the bounce can\n // stall where it was (#1287).\n // A write that is unwanted for another reason (a travelling smooth scroll\n // owns the position) is a separate check at the call sites.\n private _canWriteScroll = () =>\n !(isIOSWebKit() && this._iosGesture.inMotion()) && !this._reportedOverscroll\n\n // Write a held correction once a write is possible, from the scroll\n // handler, the touch tail timer, `_willUpdate` and a resize notify. The\n // rows go back to layout coordinates and the total grows by the hold in a\n // notify issued before the write, so the sizer can take the position and\n // both commit in the paint the write lands in. `sync` is false only where\n // the caller already runs inside the consumer's commit (`_willUpdate`),\n // where an update it schedules commits before paint anyway.\n private _flushHoldIfReady = (sync: boolean) => {\n if (this._holdOffset === 0) return\n if (!this.scrollElement || !this.options.enabled) return\n if (!this._canWriteScroll()) return\n // Let a travelling smooth scroll land first (see `_willUpdate`).\n if (this.scrollState?.phase === 'smooth') return\n this._holdOffset = 0\n // A held shrink can leave the layout position above the top; the\n // element clamps that to 0 without an event to say so (#1229).\n if (this.scrollOffset !== null && this.scrollOffset < 0) {\n this.scrollOffset = 0\n }\n this.notify(sync)\n // A command whose write has not been reported back yet owns the target:\n // `scrollOffset` is still the pre-command position until its read-back,\n // and a command that closes the touch tail makes a write possible with\n // no scroll event in between, so this flush can run first.\n const target = this.getCommandWrittenOffset() ?? this.getScrollOffset()\n // A consumer that sizes the container after this write gets the retry\n // (#1258).\n this._clampedAdjustment = this._clampedBy(target)\n this._scrollToOffset(target)\n }\n\n private rafId: number | null = null\n private scheduleScrollReconcile() {\n if (!this.targetWindow) {\n this.scrollState = null\n return\n }\n if (this.rafId != null) return\n this.rafId = this.targetWindow.requestAnimationFrame(() => {\n this.rafId = null\n this.reconcileScroll()\n })\n }\n private getScrollStateTarget(state: ScrollState) {\n const offsetInfo = state.toEnd\n ? ([Math.max(this.getMaxScrollOffset(), 0)] as const)\n : state.index != null\n ? this.getOffsetForIndex(state.index, state.align)\n : undefined\n return offsetInfo ? offsetInfo[0] : state.lastTargetOffset\n }\n private reconcileScroll() {\n if (!this.scrollState) return\n\n const el = this.scrollElement\n if (!el) return\n\n // Safety valve: bail out if reconciliation has been running too long\n const MAX_RECONCILE_MS = 5000\n if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {\n this.scrollState = null\n return\n }\n\n // Nothing to reconcile until the tail closes and the command is written;\n // only the safety valve above applies.\n if (this.scrollState.phase === 'queued') {\n this.scheduleScrollReconcile()\n return\n }\n\n // A resize since the last render leaves measurementsCache stale until\n // something reads getMeasurements(); rebuild it (memoized) so an index\n // target reflects it even when no render ran in between.\n this.getMeasurements()\n const targetOffset = this.getScrollStateTarget(this.scrollState)\n\n // Index targets can still depend on cached sizes during the first rAF,\n // which runs before ResizeObserver delivers pending measurements. Wait\n // another frame (two when measurements are themselves deferred to rAF)\n // before retiring an index scroll. Absolute offsets don't need this wait.\n const STABLE_FRAMES =\n this.scrollState.index == null\n ? 1\n : this.options.useAnimationFrameWithResizeObserver\n ? 3\n : 2\n\n const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n // At the target: a travelling smooth scroll has landed, and a\n // finishing one is now an instant scroll.\n if (this.scrollState.phase === 'smooth') {\n this.scrollState.phase = 'smoothLanded'\n } else if (this.scrollState.phase === 'smoothFinishing') {\n this.scrollState.phase = 'instant'\n }\n this.scrollState.stableFrames++\n if (this.scrollState.stableFrames >= STABLE_FRAMES) {\n // Final-pass exact landing. The reconcile-stable check uses a 1.01px\n // tolerance (approxEqual) so we don't fight subpixel browser rounding\n // during the converging phase. Once we're definitively settled,\n // commit the exact target so consumers calling scrollToIndex(N)\n // end up at the EXACT computed position of item N — matching\n // virtuoso's 0px landing accuracy rather than our prior 0.5-1px.\n if (this.getScrollOffset() !== targetOffset) {\n this._scrollToOffset(targetOffset, { behavior: 'auto' })\n }\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n // When the target moves during smooth scroll (because items came into\n // view and got measured, shifting positions), the original logic was\n // to immediately snap to 'auto' — visibly jarring on long\n // scroll-to-index calls. Now: keep smooth while we're still far\n // (more than a viewport) from the new target. Only fall back to\n // 'auto' for the final approach, so the user sees one continuous\n // motion that smoothly adjusts its endpoint as measurements arrive.\n const viewport = this.getSize() || 600\n const distance = Math.abs(targetOffset - this.getScrollOffset())\n const keepSmooth =\n isSmoothScroll(this.scrollState) && distance > viewport\n\n this.scrollState.lastTargetOffset = targetOffset\n if (keepSmooth) {\n // A smooth retarget travels again, so its intermediate scroll\n // events must not read as an external scroll away from the target.\n this.scrollState.phase = 'smooth'\n } else if (this.scrollState.phase === 'smooth') {\n // The final approach is instant, but the animation can still report.\n this.scrollState.phase = 'smoothFinishing'\n } else if (this.scrollState.phase === 'smoothLanded') {\n this.scrollState.phase = 'instant'\n }\n // 'smoothFinishing' stays as it is (its animation may still report)\n // until reconcile sees it at the target; 'instant' stays instant.\n\n this._scrollToOffset(targetOffset, {\n behavior: keepSmooth ? 'smooth' : 'auto',\n })\n }\n }\n\n // Always reschedule while scrollState is active to guarantee\n // the safety valve timeout runs even if no scroll events fire\n // (e.g. no-op scrollToFn, detached element)\n this.scheduleScrollReconcile()\n }\n\n private getSize = () => {\n if (!this.options.enabled) {\n this.scrollRect = null\n return 0\n }\n\n this.scrollRect = this.scrollRect ?? this.options.initialRect\n\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null\n return 0\n }\n\n this.scrollOffset =\n this.scrollOffset ??\n (typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset)\n\n return this.scrollOffset\n }\n\n private getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n this.options.lanes,\n this.options.laneAssignmentMode,\n this.options.gap,\n ],\n (\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n gap,\n ) => {\n const lanesChanged =\n this.prevLanes !== undefined && this.prevLanes !== lanes\n\n if (lanesChanged) {\n // Set flag for getMeasurements to handle\n this.lanesChangedFlag = true\n }\n\n this.prevLanes = lanes\n this.pendingMin = null\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n gap,\n }\n },\n {\n key: false,\n },\n )\n\n private isIndexInRange = (index: number): boolean =>\n index >= 0 && index < this.options.count\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCacheVersion],\n (\n {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n gap,\n },\n _itemSizeCacheVersion,\n ) => {\n const itemSizeCache = this.itemSizeCache\n if (!enabled) {\n this.measurementsCache = []\n this._singleLaneMeasurements = null\n this.itemSizeCache.clear()\n this.laneAssignments.clear()\n return []\n }\n\n // Clean up stale lane cache entries when count decreases\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index)\n }\n }\n }\n\n // ✅ Force complete recalculation when lanes change\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false // Reset immediately\n this.lanesSettling = true // Start settling period\n this.measurementsCache = []\n this._singleLaneMeasurements = null\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for new lane count\n // Force min = 0 on the rebuild\n this.pendingMin = null\n }\n\n // Don't restore from initialMeasurementsCache during lane changes\n // as it contains stale lane assignments from the previous lane count\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\n // During lanes settling, ignore pendingMin to prevent repositioning\n const min = this.lanesSettling ? 0 : (this.pendingMin ?? 0)\n this.pendingMin = null\n\n // ✅ End settling period when cache is fully built\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false\n }\n\n // ─── Fast path: single-lane lazy materialization ────────────────────\n // For lanes === 1 (the default and most common case), skip the\n // per-item VirtualItem object allocation. We write start/size pairs\n // into a Float64Array and return a Proxy that builds VirtualItem\n // objects on demand (only the indices a consumer actually reads).\n if (lanes === 1) {\n // Reuse flat backing if large enough; else grow (preserving data\n // before `min` to mirror the slice-and-rebuild contract).\n const need = count * 2\n let flat = this._singleLaneMeasurements?.flat\n if (!flat || flat.length < need) {\n const next = new Float64Array(need)\n if (flat && min > 0) next.set(flat.subarray(0, min * 2))\n flat = next\n }\n\n const items: Array =\n min === 0\n ? new Array(count)\n : this._singleLaneMeasurements!.items.slice()\n\n let runningStart: number\n if (min === 0) {\n runningStart = paddingStart + scrollMargin\n } else {\n // Continue from where we left off\n const prevIdx = min - 1\n runningStart = flat[prevIdx * 2]! + flat[prevIdx * 2 + 1]! + gap\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n items[i] = key\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n flat[i * 2] = runningStart\n flat[i * 2 + 1] = size\n runningStart += size + gap\n }\n\n this._singleLaneMeasurements = { flat, items }\n const view = createLazyMeasurementsView(items, flat)\n this.measurementsCache = view\n return view\n }\n\n const measurements = this.measurementsCache.slice(0, min)\n\n // ✅ Performance: Track last item index per lane for O(1) lookup\n const laneLastIndex: Array = new Array(lanes).fill(\n undefined,\n )\n // Running end position of each lane's last item, so the shortest lane\n // can be found with an O(lanes) argmin instead of the old backward walk\n // through `measurements` (getFurthestMeasurement). `filledLanes` tracks\n // how many lanes have at least one item, mirroring the previous\n // \"all lanes seen → shortest lane, else i % lanes\" branch.\n const laneEnds = new Float64Array(lanes)\n let filledLanes = 0\n\n // Initialize from existing measurements (before min)\n for (let m = 0; m < min; m++) {\n const item = measurements[m]\n if (item) {\n if (laneLastIndex[item.lane] === undefined) filledLanes++\n laneLastIndex[item.lane] = m\n laneEnds[item.lane] = item.end\n }\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n // Check for cached lane assignment\n const cachedLane = this.laneAssignments.get(i)\n let lane: number\n let start: number\n\n const shouldCacheLane =\n laneAssignmentMode === 'estimate' || itemSizeCache.has(key)\n\n if (cachedLane !== undefined && this.options.lanes > 1) {\n // Use cached lane - O(1) lookup for previous item in same lane\n lane = cachedLane\n const prevIndex = laneLastIndex[lane]\n const prevInLane =\n prevIndex !== undefined ? measurements[prevIndex] : undefined\n start = prevInLane\n ? prevInLane.end + gap\n : paddingStart + scrollMargin\n } else if (filledLanes === lanes) {\n // No cache, every lane seeded: place in the shortest lane.\n // Read the running per-lane ends (O(lanes) argmin) instead of the\n // old backward scan. Tie-break on the lane's last-item index to\n // preserve the previous sort-by-(end, index) placement exactly.\n let bestLane = 0\n let bestEnd = laneEnds[0]!\n let bestIdx = laneLastIndex[0]!\n for (let l = 1; l < lanes; l++) {\n const e = laneEnds[l]!\n if (e < bestEnd || (e === bestEnd && laneLastIndex[l]! < bestIdx)) {\n bestLane = l\n bestEnd = e\n bestIdx = laneLastIndex[l]!\n }\n }\n lane = bestLane\n start = bestEnd + gap\n\n if (shouldCacheLane) {\n this.laneAssignments.set(i, lane)\n }\n } else {\n // No cache and not every lane seeded yet — seed lanes in order,\n // matching the previous `i % lanes` fallback for the first row.\n lane = i % this.options.lanes\n start = paddingStart + scrollMargin\n\n if (shouldCacheLane) {\n this.laneAssignments.set(i, lane)\n }\n }\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n\n // ✅ Performance: Update lane's last item index + running end\n if (laneLastIndex[lane] === undefined) filledLanes++\n laneLastIndex[lane] = i\n laneEnds[lane] = end\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes,\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n if (measurements.length === 0 || outerSize === 0) {\n this.range = null\n return null\n }\n this.range = calculateRangeImpl(\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n // Pass the typed array so binary search + forward-walk can read\n // start/end directly from Float64Array, skipping the Proxy traps.\n lanes === 1 && this._singleLaneMeasurements !== null\n ? this._singleLaneMeasurements.flat\n : null,\n )\n return this.range\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualIndexes = memo(\n () => {\n let startIndex: number | null = null\n let endIndex: number | null = null\n const range = this.calculateRange()\n if (range) {\n startIndex = range.startIndex\n endIndex = range.endIndex\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex,\n this.options.lanes,\n ]\n },\n (rangeExtractor, overscan, count, startIndex, endIndex, lanes) => {\n return startIndex === null || endIndex === null\n ? []\n : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count,\n lanes,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n /**\n * Determines if an item at the given index should be measured during smooth scroll.\n * During smooth scroll, only items within a buffer range around the target are measured\n * to prevent items far from the target from pushing it away.\n */\n private shouldMeasureDuringScroll = (index: number): boolean => {\n // No scroll state or not smooth scroll - always allow measurements\n if (!isSmoothScroll(this.scrollState)) {\n return true\n }\n\n const scrollIndex =\n this.scrollState.index ??\n this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index\n\n if (scrollIndex !== undefined && this.range) {\n // Allow measurements within a buffer range around the scroll target\n const bufferSize = Math.max(\n this.options.overscan,\n Math.ceil((this.range.endIndex - this.range.startIndex) / 2),\n )\n const minIndex = Math.max(0, scrollIndex - bufferSize)\n const maxIndex = Math.min(\n this.options.count - 1,\n scrollIndex + bufferSize,\n )\n return index >= minIndex && index <= maxIndex\n }\n\n return true\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached)\n this.elementsCache.delete(key)\n }\n })\n return\n }\n\n const index = this.indexFromElement(node)\n if (!this.isIndexInRange(index)) return\n\n const key = this.options.getItemKey(index)\n const prevNode = this.elementsCache.get(key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.elementsCache.set(key, node)\n }\n\n // Sync-measure when idle (initial render) or during programmatic scrolling\n // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.\n // During normal user scrolling, skip sync measurement — the RO callback handles it async.\n // Skip nodes that aren't attached yet: they have no layout and would be\n // cached as 0. Vue calls function refs during patch, before the parent is\n // inserted. The node is observed above, so the RO reports its size once\n // it's connected.\n if (\n node.isConnected &&\n (!this.isScrolling || this.scrollState) &&\n this.shouldMeasureDuringScroll(index)\n ) {\n this.resizeItem(index, this.options.measureElement(node, undefined, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n if (!this.isIndexInRange(index)) return\n\n // An earlier entry in this ResizeObserver batch moved `scrollOffset`.\n // Outside a batch its sync notify would have re-rendered and rebuilt the\n // caches read below; rebuild them here so the anchoring check compares\n // this item's current start, not a stale one, against the adjusted\n // offset (#1218). Without a scroll move, the caches are exactly as stale\n // as they were before batching, so skip the rebuild.\n if (this._resizeBatch?.sync) this.getMeasurements()\n\n // Fast field reads. For lanes===1 we read raw start/size from the flat\n // typed array, avoiding a Proxy.get + VirtualItem allocation per call.\n // For lanes>1 we fall back to the cached VirtualItem array.\n let cachedSize: number\n let itemStart: number\n let key: Key\n const flat = this._singleLaneMeasurements?.flat\n if (this.options.lanes === 1 && flat != null) {\n key = this.options.getItemKey(index)\n itemStart = flat[index * 2]!\n cachedSize = flat[index * 2 + 1]!\n } else {\n const item = this.measurementsCache[index]\n if (!item) return\n key = item.key\n itemStart = item.start\n cachedSize = item.size\n }\n\n const itemSize = this.itemSizeCache.get(key) ?? cachedSize\n const delta = size - itemSize\n\n if (delta !== 0) {\n const wasAtEnd =\n this.options.anchorTo === 'end' &&\n !isSmoothScroll(this.scrollState) &&\n this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold\n const prevTotalSize = wasAtEnd ? this._getLayoutTotalSize() : 0\n // Default anchoring predicate (used unless the consumer supplies a\n // custom shouldAdjustScrollPositionOnItemSizeChange).\n const scrollOffset = this.getScrollOffset()\n const isFirstMeasure = !this.itemSizeCache.has(key)\n const defaultShouldAdjust = isFirstMeasure\n ? // First measurement: compensate any item whose top sits above the\n // fold — the estimate→actual delta must be corrected regardless of\n // scroll direction, since the whole estimated block was above it.\n itemStart < scrollOffset\n : // Re-measurement: only compensate an item that is ENTIRELY above the\n // fold. An item that merely *spans* the fold (top above, bottom\n // below — e.g. a streaming chat message growing at its bottom)\n // changes size *below* the anchor point, so shifting scrollTop by the\n // delta would drag the viewport downward on every growth (#1218).\n // Also skip during backward scroll to avoid the \"items jump while\n // scrolling up\" cascade.\n itemStart + itemSize <= scrollOffset &&\n this.scrollDirection !== 'backward'\n const shouldAdjustScroll =\n !isSmoothScroll(this.scrollState) &&\n (this.shouldAdjustScrollPositionOnItemSizeChange !== undefined\n ? this.shouldAdjustScrollPositionOnItemSizeChange(\n // The callback expects a VirtualItem; build one lazily only\n // when the consumer actually supplied a custom predicate.\n this.measurementsCache[index] ?? {\n index,\n key,\n start: itemStart,\n size: cachedSize,\n end: itemStart + cachedSize,\n lane: 0,\n },\n delta,\n this,\n )\n : defaultShouldAdjust)\n\n if (this.pendingMin === null || index < this.pendingMin) {\n this.pendingMin = index\n }\n this.itemSizeCache.set(key, size)\n this.itemSizeCacheVersion++\n\n // Before a command's read-back, an index or end target is retargeted\n // from fresh measurements by reconcileScroll next frame; an offset\n // target lands where it was written and the delta is not applied.\n let adjustedSync = false\n if (!this._awaitingCommandReadBack()) {\n if (wasAtEnd) {\n adjustedSync = this.applyScrollAdjustment(\n this._getLayoutTotalSize() - prevTotalSize,\n )\n } else if (shouldAdjustScroll) {\n adjustedSync = this.applyScrollAdjustment(delta)\n }\n }\n\n // When we just moved `scrollTop` to compensate for an above-viewport\n // resize, the grown item transforms must commit in the SAME frame as\n // that write. `applyScrollAdjustment` writes `scrollTop` synchronously\n // inside this ResizeObserver callback, but an async `notify` schedules\n // the transform render for a later commit — so the browser can paint\n // one frame with the new `scrollTop` and the old positions, and the\n // viewport visibly jumps by `delta` before snapping back (#1227). A\n // synchronous notify flushes the render in this same callback, so both\n // land in one paint. When nothing moved (or the write was deferred on\n // iOS), keep the cheaper async notify.\n if (this._resizeBatch) {\n // Inside a ResizeObserver callback: notify once after every entry\n // is measured, synchronously if any of them moved `scrollTop`.\n this._resizeBatch.notify = true\n this._resizeBatch.sync ||= adjustedSync\n return\n }\n this.notify(adjustedSync)\n this._noteClampMax()\n // A consumer that grows the sizer synchronously inside `onChange`\n // (direct DOM updates) may never re-render when the range is\n // unchanged, so retry a clamped write here rather than only in\n // `_willUpdate` (#1266).\n this._flushHoldIfReady(true)\n this._retryClampedAdjustment()\n }\n }\n\n getVirtualItems = memo(\n () => [this.getVirtualIndexes(), this.getMeasurements(), this._holdOffset],\n (indexes, measurements, hold) => {\n const virtualItems: Array = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n // A held correction is exposed as a shift of every row (see\n // `_holdOffset`); the layout itself is untouched.\n virtualItems.push(\n hold === 0\n ? measurement\n : {\n ...measurement,\n start: measurement.start - hold,\n end: measurement.end - hold,\n },\n )\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualItems',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n if (measurements.length === 0) {\n return undefined\n }\n // Same fast-path as calculateRange: read start values directly from the\n // typed array during binary search to skip the Proxy.get materialization\n // per probe.\n const flat = this._singleLaneMeasurements?.flat\n const useFlat = this.options.lanes === 1 && flat != null\n const idx = findNearestBinarySearch(\n 0,\n measurements.length - 1,\n useFlat\n ? (i: number) => flat[i * 2]!\n : (i: number) => notUndefined(measurements[i]).start,\n offset,\n )\n return notUndefined(measurements[idx])\n }\n\n // Record the element's max, in layout coordinates, as one a command's\n // pending instant write may be clamped to (see `lowMaxes` on\n // `pendingWrite`). Called where the sizer can have been committed: after\n // a notify, for a consumer that sizes it in `onChange`, and in\n // `_willUpdate`. The element cannot clamp below its own 0, which is the\n // hold in layout coordinates.\n private _noteClampMax = () => {\n if (!this._awaitingCommandReadBack()) return\n const elementMax = this._elementMaxScrollOffset()\n if (elementMax === null) return\n const write = this.pendingWrite!\n const max = Math.max(elementMax, 0) + this._holdOffset\n if (max >= write.target) return\n const lowMaxes = (write.lowMaxes ??= [])\n if (lowMaxes[lowMaxes.length - 1] !== max) lowMaxes.push(max)\n }\n\n // The element's scroll range in layout coordinates: while a correction is\n // held the sizer is short by the hold, so the element's own max is too.\n private getMaxScrollOffset = () =>\n (this._elementMaxScrollOffset() ?? 0) + this._holdOffset\n\n // An element position in layout coordinates: how far the layout position\n // is ahead of the element. The element is `_holdOffset` behind while a\n // correction is held, and a prepend's anchor delta behind from\n // `setOptions` (which moved `scrollOffset` by it) until `_willUpdate`\n // writes or holds it. Writes (`_scrollToOffset`) and the clamp record\n // (`_clampedBy`) deliberately subtract the hold alone, not this whole\n // lead: by the time they run, the anchor delta is already in\n // `scrollOffset`, and writing that layout position is what closes it.\n private _toLayoutOffset = (elementOffset: number) => {\n let offset = elementOffset + this._holdOffset\n if (this.pendingScrollAnchor?.kind === 'anchor') {\n offset += this.pendingScrollAnchor.delta\n }\n return offset\n }\n\n // The element's own scroll range, or null where it cannot be read (no\n // element, or a bare test double without `scrollHeight` / `document`).\n private _elementMaxScrollOffset = (): number | null => {\n const el = this.scrollElement\n if (el === null) return null\n if ('scrollHeight' in el) {\n return this.options.horizontal\n ? el.scrollWidth - el.clientWidth\n : el.scrollHeight - el.clientHeight\n }\n if ('document' in el) {\n const doc = el.document.documentElement\n return this.options.horizontal\n ? doc.scrollWidth - el.innerWidth\n : doc.scrollHeight - el.innerHeight\n }\n return null\n }\n\n // Stop a running iOS fling, then call `done`: the momentum does not\n // survive the element losing its overflow for a frame. Hidden and\n // restored within one task, iOS never sees the change and the fling\n // carries on (27.0.1 iPhone); hidden for two frames, it stops at once.\n // Nothing moves on screen. A second call while one is in progress waits\n // for the same frames. The app's inline value comes back, unless the app\n // set a new one meanwhile; `done` is then not called.\n private _momentumStop: { restore: () => boolean; done: () => void } | null =\n null\n private _stopMomentum = (done: () => void) => {\n const el = this.scrollElement\n const win = this.targetWindow\n if (el === null || win === null) return\n const scroller = (\n 'document' in el ? el.document.scrollingElement : el\n ) as HTMLElement | null\n // A test double may have no style to change.\n if (!scroller?.style) return\n if (this._momentumStop) {\n this._momentumStop.done = done\n return\n }\n const { style } = scroller\n const property = this.options.horizontal ? 'overflow-x' : 'overflow-y'\n const value = style.getPropertyValue(property)\n const priority = style.getPropertyPriority(property)\n style.setProperty(property, 'hidden', 'important')\n const stop = {\n // False when the app replaced the hidden value: the fling may not\n // have stopped.\n restore: () => {\n if (\n style.getPropertyValue(property) !== 'hidden' ||\n style.getPropertyPriority(property) !== 'important'\n ) {\n return false\n }\n style.setProperty(property, value, priority)\n return true\n },\n done,\n }\n this._momentumStop = stop\n win.requestAnimationFrame(() =>\n win.requestAnimationFrame(() => {\n // Already restored by `cleanup`, which also drops its command.\n if (this._momentumStop !== stop) return\n this._momentumStop = null\n // The command waits for the tail, as without the stop.\n if (stop.restore()) stop.done()\n }),\n )\n }\n\n // A compensation write past the element's current max (the sizer has not\n // grown yet) is clamped by the browser; record it for the retry (#1258).\n private _clampedBy = (target: number) => {\n const elementMax = this._elementMaxScrollOffset()\n if (elementMax === null) return null\n const maxAtWrite = elementMax + this._holdOffset\n return target > maxAtWrite + 0.5 ? { target, maxAtWrite } : null\n }\n\n private getVirtualDistanceFromEnd = () => {\n return Math.max(\n this._getLayoutTotalSize() - this.getSize() - this.getScrollOffset(),\n 0,\n )\n }\n\n getDistanceFromEnd = () => {\n return Math.max(this.getMaxScrollOffset() - this.getScrollOffset(), 0)\n }\n\n isAtEnd = (threshold = this.options.scrollEndThreshold) => {\n return this.getDistanceFromEnd() <= threshold\n }\n\n getOffsetForAlignment = (\n toOffset: number,\n align: ScrollAlignment,\n itemSize = 0,\n ) => {\n if (!this.scrollElement) return 0\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n align = toOffset >= scrollOffset + size ? 'end' : 'start'\n }\n\n if (align === 'center') {\n // When aligning to a particular item (e.g. with scrollToIndex),\n // adjust offset by the size of the item to center on the item\n toOffset += (itemSize - size) / 2\n } else if (align === 'end') {\n toOffset -= size\n }\n\n const maxOffset = this.getMaxScrollOffset()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n const item = this.measurementsCache[index]\n if (!item) return\n\n if (align === 'auto') {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = 'start'\n } else {\n return [scrollOffset, align] as const\n }\n }\n\n // For the last item with 'end' alignment, use browser's actual max scroll\n // to account for borders/padding that aren't in our measurements (#1001),\n // but swap paddingEnd for scrollPaddingEnd so the last item lands where\n // any other end-aligned item would instead of overshooting past it (#1257).\n if (align === 'end' && index === this.options.count - 1) {\n const maxOffset = this.getMaxScrollOffset()\n const toOffset =\n maxOffset - this.options.paddingEnd + this.options.scrollPaddingEnd\n return [Math.max(Math.min(toOffset, maxOffset), 0), align] as const\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align,\n ] as const\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n this._startScroll(\n { index: null, align },\n this.getOffsetForAlignment(toOffset, align),\n behavior,\n 'absolute',\n )\n }\n\n scrollToIndex = (\n index: number,\n {\n align: initialAlign = 'auto',\n behavior = 'auto',\n }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const offsetInfo = this.getOffsetForIndex(index, initialAlign)\n // No target (an empty list), so nothing is written.\n if (!offsetInfo) return\n const [offset, align] = offsetInfo\n\n this._startScroll({ index, align }, offset, behavior, 'absolute')\n }\n\n scrollBy = (\n delta: number,\n { behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n // Build on a position we just wrote even before its scroll event arrives.\n // Clamp: a write past either edge that leaves the element where it was\n // fires no scroll event, so nothing would clear an unreachable offset.\n const offset = this.getOffsetForAlignment(\n (this.getCommandWrittenOffset() ?? this.getScrollOffset()) + delta,\n 'start',\n )\n\n this._startScroll(\n { index: null, align: 'start' },\n offset,\n behavior,\n 'relative',\n )\n }\n\n scrollToEnd = ({ behavior = 'auto' }: ScrollToEndOptions = {}) => {\n if (this.options.count > 0) {\n // Target the browser's max scroll rather than the last item's end-align\n // offset, so paddingEnd is included and isAtEnd() holds afterwards.\n this._startScroll(\n { index: this.options.count - 1, align: 'end', toEnd: true },\n Math.max(this.getMaxScrollOffset(), 0),\n behavior,\n 'absolute',\n )\n return\n }\n\n this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {\n behavior,\n })\n }\n\n // Every scroll command starts here: it becomes the in-flight command,\n // writes its first target and leaves reconcile to retarget and retire it.\n //\n // Targets are layout offsets. A held correction is not dropped by a\n // command: the write lands the element `_holdOffset` short of the target,\n // under the rows exposed shifted by the same amount, and the flush moves\n // both together once a write is possible.\n //\n // An index or end target that is already at its offset starts a smooth\n // scroll as landed; an offset target never does, so its first scroll\n // event is read as the user's (see the scroll handler in `_willUpdate`).\n private _startScroll(\n target: Pick,\n offset: number,\n behavior: ScrollBehavior,\n kind: 'absolute' | 'relative',\n ) {\n const tail = this._iosGesture.tail()\n if (kind === 'absolute' && tail !== null) {\n if (tail === 'fling' && iosMomentumOverridesWrites()) {\n // iOS 27: a write now shows for one frame and the fling carries on\n // along its own path, so the command would be lost (#1307, step 3).\n // Stop the fling and write two frames later. Otherwise (no style to\n // change, a finger down, a bounce) the tail stays open and\n // the command is written when it closes, ~150ms after the last\n // fling frame. The user taking over before the write (a drag, a\n // second flick, a finger stopping the fling) cancels the command\n // (see the scroll handler and `onTailClosed`). A relative command\n // (`scrollBy`) is not postponed: its target is taken from the\n // position at the call, which the fling leaves behind either way.\n this._stopMomentum(() => {\n const state = this.scrollState\n if (\n state?.phase !== 'queued' ||\n // A finger came down: it owns the scroll until it lifts.\n this._iosGesture.tail() !== 'fling' ||\n // In a bounce WebKit can drop the write (#1287): the tail\n // decides, as without the stop. (Not `flingCaught`: our stop\n // also ends the fling at speed, so a slow frame would read as\n // a catch and the tail would drop the command.)\n this._reportedOverscroll\n ) {\n return\n }\n this._iosGesture.end()\n this._flushHoldIfReady(true)\n this._writeAwaitingCommand()\n })\n this.scrollState = {\n ...target,\n startedAt: this.now(),\n lastTargetOffset: offset,\n stableFrames: 0,\n phase: 'queued',\n behavior,\n samples: [],\n }\n this.scheduleScrollReconcile()\n return\n }\n // The command takes over the scroll, so close the tail: the landing's\n // corrections then apply before paint, even for a command issued from\n // a tap handler inside the tail (#1250). On iOS 26 and earlier the\n // write stops the momentum. With a finger down the user owns the\n // scroll: leave it.\n this._iosGesture.end()\n }\n this.scrollState = {\n ...target,\n startedAt: this.now(),\n lastTargetOffset: offset,\n stableFrames: 0,\n behavior,\n phase: initialScrollPhase(\n behavior,\n target.index != null && approxEqual(offset, this.getScrollOffset()),\n ),\n }\n this._scrollToOffset(offset, { behavior })\n this.scheduleScrollReconcile()\n }\n\n // Drops the target of an in-flight scrollToIndex / scrollToOffset /\n // scrollBy / scrollToEnd so a user gesture can take over the viewport.\n // The scroll position is left untouched: writing it would stop iOS\n // momentum, and a real gesture already interrupts a native smooth scroll.\n cancelScroll = () => {\n if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\n }\n\n // The size the consumer gives the container: the layout's total, short by\n // a held correction so the rows exposed shifted by it still fill it (see\n // `_holdOffset`).\n getTotalSize = () =>\n Math.max(this._getLayoutTotalSize() - this._holdOffset, 0)\n\n private _getLayoutTotalSize = () => {\n const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n // If there is only one lane, use the last measurement's end\n // Otherwise find the maximum end value among all measurements\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else if (this.options.lanes === 1) {\n // Fast path: read last item's end directly from the flat typed array\n // when available; avoids a Proxy.get + VirtualItem materialization\n // just to call getTotalSize (which React renders trigger every commit).\n const lastIdx = measurements.length - 1\n const flat = this._singleLaneMeasurements?.flat\n if (flat != null) {\n end = flat[lastIdx * 2]! + flat[lastIdx * 2 + 1]!\n } else {\n end = measurements[lastIdx]?.end ?? 0\n }\n } else {\n const endByLane = Array(this.options.lanes).fill(null)\n let endIndex = measurements.length - 1\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex]!\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end\n }\n\n endIndex--\n }\n\n end = Math.max(...endByLane.filter((val): val is number => val !== null))\n }\n\n return Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0,\n )\n }\n\n /**\n * Returns a snapshot of currently-measured items suitable for round-\n * tripping through state storage (sessionStorage, history, etc.) and\n * passing back as `initialMeasurementsCache` on remount. Pair with the\n * current `scrollOffset` to restore exact scroll position after navigation.\n *\n * Only items the consumer has actually rendered (and thus measured) appear\n * in the snapshot; unmeasured items will fall back to `estimateSize` on\n * restore. Returns an empty array if no items have been measured.\n */\n takeSnapshot = (): Array => {\n const snapshot: Array = []\n if (this.itemSizeCache.size === 0) return snapshot\n // Iterate measurementsCache only for indices whose key is in itemSizeCache\n // (i.e., have been measured). We build VirtualItem objects with the\n // current start/size/end so they can be persisted as plain data.\n const m = this.getMeasurements()\n for (const item of m) {\n if (item && this.itemSizeCache.has(item.key)) {\n // Force materialization (lazy path) and copy plain fields.\n snapshot.push({\n index: item.index,\n key: item.key,\n start: item.start,\n size: item.size,\n end: item.end,\n lane: item.lane,\n })\n }\n }\n return snapshot\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior } = {},\n ) => {\n const write = {\n target: offset + (adjustments ?? 0),\n smooth: behavior === 'smooth',\n }\n this.pendingWrite = write\n // The element sits `_holdOffset` behind the layout while a correction\n // is held; `target` and the read-back stay in layout coordinates.\n this.options.scrollToFn(\n offset - this._holdOffset,\n { behavior, adjustments },\n this,\n )\n return write\n }\n\n // Where the in-flight command's last instant write put the element, until\n // its scroll event arrives; the rows on screen are still the ones rendered\n // for the old `scrollOffset`. Null after a smooth write (the element is\n // somewhere on the way) and without a command, so a write the browser\n // ignored (no read-back) does not outlive its command.\n private getCommandWrittenOffset = () =>\n this.scrollState !== null &&\n this.pendingWrite !== null &&\n !this.pendingWrite.smooth\n ? this.pendingWrite.target\n : null\n\n // A scroll command (or reconcile) wrote a new position that neither a\n // scroll event nor an eager update has reflected in `scrollOffset` yet.\n // The rows on screen were rendered for the old position, so \"above the\n // viewport\" means nothing against either offset: a correction decided now\n // would be written over the command. Compensation writes and the prepend\n // anchor sync update `scrollOffset` eagerly, and the hold's flush writes\n // exactly `scrollOffset`, so none of them count. Under a dragging finger\n // iOS ignores the write, so no read-back will come and the hold takes the\n // correction instead.\n private _awaitingCommandReadBack = () => {\n const writtenOffset = this.getCommandWrittenOffset()\n return (\n !(isIOSWebKit() && this._iosGesture.dragging()) &&\n writtenOffset !== null &&\n !approxEqual(writtenOffset, this.getScrollOffset())\n )\n }\n\n // An offset target (scrollToOffset, scrollBy) is a layout position. A\n // correction for content above the viewport moves the viewport's layout\n // position by `delta`, and the target moves with it, so reconcile sees the\n // command reached rather than waiting for a position it can never see\n // (#1307, step 5). Index and end targets are recomputed from the layout.\n private _followOffsetTarget = (delta: number) => {\n if (this.scrollState !== null && this.scrollState.index == null) {\n this.scrollState.lastTargetOffset += delta\n }\n }\n\n measure = () => {\n // Reset pendingMin so the next getMeasurements rebuilds from index 0.\n // Without this, a prior resizeItem() that left pendingMin > 0 would\n // cause the rebuild to preserve stale items before that index.\n this.pendingMin = null\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for full re-layout\n this.itemSizeCacheVersion++\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\n// Monomorphic Float64Array variant — reads start values directly at stride\n// 2 instead of through a getter closure. JITs the inner load to a typed-\n// array bounds-check + load with no indirect call.\nfunction findNearestBinarySearchFlat(\n flat: Float64Array,\n high: number,\n value: number,\n) {\n let low = 0\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = flat[middle * 2]!\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n return low > 0 ? low - 1 : 0\n}\n\nfunction calculateRangeImpl(\n measurements: Array,\n outerSize: number,\n scrollOffset: number,\n lanes: number,\n flat: Float64Array | null,\n) {\n const lastIndex = measurements.length - 1\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return { startIndex: 0, endIndex: lastIndex }\n }\n\n if (lanes === 1 && flat !== null) {\n // Hot single-lane path: typed-array reads, no closures, no Proxy traps.\n const startIndex = findNearestBinarySearchFlat(\n flat,\n lastIndex,\n scrollOffset,\n )\n let endIndex = startIndex\n const limit = scrollOffset + outerSize\n while (\n endIndex < lastIndex &&\n flat[endIndex * 2]! + flat[endIndex * 2 + 1]! < limit\n ) {\n endIndex++\n }\n return { startIndex, endIndex }\n }\n\n // Fallback (lanes > 1 or no flat array): closure-based reads.\n const getStart = (index: number) => measurements[index]!.start\n let startIndex = findNearestBinarySearch(0, lastIndex, getStart, scrollOffset)\n let endIndex = startIndex\n\n if (lanes === 1) {\n while (\n endIndex < lastIndex &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n } else if (lanes > 1) {\n // Expand forward until we include the visible items from all lanes\n // which are closer to the end of the virtualizer window\n const endPerLane = Array(lanes).fill(0)\n while (\n endIndex < lastIndex &&\n endPerLane.some((pos) => pos < scrollOffset + outerSize)\n ) {\n const item = measurements[endIndex]!\n endPerLane[item.lane] = item.end\n endIndex++\n }\n\n // Expand backward until we include all lanes' visible items\n // closer to the top\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize)\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex]!\n startPerLane[item.lane] = item.start\n startIndex--\n }\n\n // Align startIndex to the beginning of its lane\n startIndex = Math.max(0, startIndex - (startIndex % lanes))\n // Align endIndex to the end of its lane\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))\n }\n\n return { startIndex, endIndex }\n}\n"],"names":["debounce","IosGesture","flingCaught","opts","getMeasurementKey","memo","_a","externalRetiresCommand","flingSpedUp","approxEqual","classifyScrollEvent","isIOSWebKit","createLazyMeasurementsView","key","notUndefined","toOffset","iosMomentumOverridesWrites","startIndex","endIndex"],"mappings":";;;;;;AA2EA,MAAM,UAAU,CAAC,YAA+B;AAC9C,QAAM,EAAE,aAAa,aAAA,IAAiB;AACtC,SAAO,EAAE,OAAO,aAAa,QAAQ,aAAA;AACvC;AAIA,MAAM,mBAAmB,CAAC,iBAAyB;AACjD,QAAM,0BAAU,IAAA;AAChB,SAAO;AAAA,IACL,UAAU,CAAC,OAAmB;AAC5B,YAAM,KAAK,aAAa,sBAAsB,MAAM;AAClD,YAAI,OAAO,EAAE;AACb,WAAA;AAAA,MACF,CAAC;AACD,UAAI,IAAI,EAAE;AAAA,IACZ;AAAA,IACA,QAAQ,MAAM;AACZ,UAAI,QAAQ,CAAC,OAAO,aAAa,qBAAqB,EAAE,CAAC;AACzD,UAAI,MAAA;AAAA,IACN;AAAA,EAAA;AAEJ;AAEO,MAAM,sBAAsB,CAAC,UAAkB;AAE/C,MAAM,wBAAwB,CAAC,UAAiB;AAKrD,QAAM,WAAW,MAAM,WAAW,KAAK,IAAI,MAAM,SAAS,GAAG,CAAC;AAC9D,QAAM,QAAQ,KAAK,IAAI,MAAM,aAAa,UAAU,CAAC;AACrD,QAAM,MAAM,KAAK,IAAI,MAAM,WAAW,UAAU,MAAM,QAAQ,CAAC;AAC/D,QAAM,MAAM,MAAM,QAAQ;AAE1B,QAAM,MAAM,IAAI,MAAc,GAAG;AACjC,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,QAAI,CAAC,IAAI,QAAQ;AAAA,EACnB;AACA,SAAO;AACT;AAEO,MAAM,qBAAqB,CAChC,UACA,OACG;AACH,QAAM,UAAU,SAAS;AACzB,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AACA,QAAM,eAAe,SAAS;AAC9B,MAAI,CAAC,cAAc;AACjB;AAAA,EACF;AAEA,QAAM,UAAU,CAAC,SAAe;AAC9B,UAAM,EAAE,OAAO,OAAA,IAAW;AAC1B,OAAG,EAAE,OAAO,KAAK,MAAM,KAAK,GAAG,QAAQ,KAAK,MAAM,MAAM,EAAA,CAAG;AAAA,EAC7D;AAEA,UAAQ,QAAQ,OAAiC,CAAC;AAElD,MAAI,CAAC,aAAa,gBAAgB;AAChC,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,QAAM,SAAS,iBAAiB,YAAY;AAC5C,QAAM,WAAW,IAAI,aAAa,eAAe,MAAM;AACrD,UAAM,MAAM,MAAM;AAChB,cAAQ,QAAQ,OAAiC,CAAC;AAAA,IACpD;AAEA,aAAS,QAAQ,sCACb,OAAO,SAAS,GAAG,IACnB,IAAA;AAAA,EACN,CAAC;AAED,WAAS,QAAQ,SAAS,EAAE,KAAK,eAAe;AAEhD,SAAO,MAAM;AACX,aAAS,UAAU,OAAO;AAC1B,WAAO,OAAA;AAAA,EACT;AACF;AAEA,MAAM,0BAA0B;AAAA,EAC9B,SAAS;AACX;AAEO,MAAM,oBAAoB,CAC/B,UACA,OACG;AACH,QAAM,UAAU,SAAS;AACzB,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AAEA,QAAM,UAAU,MAAM;AACpB,OAAG,EAAE,OAAO,QAAQ,YAAY,QAAQ,QAAQ,aAAa;AAAA,EAC/D;AACA,UAAA;AAEA,UAAQ,iBAAiB,UAAU,SAAS,uBAAuB;AAEnE,SAAO,MAAM;AACX,YAAQ,oBAAoB,UAAU,OAAO;AAAA,EAC/C;AACF;AAEA,MAAM,oBACJ,OAAO,UAAU,cAAc,OAAO,iBAAiB;AAOzD,MAAM,gBAAgB,CACpB,UACA,IACA,eACG;AACH,QAAM,UAAU,SAAS;AACzB,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AACA,QAAM,eAAe,SAAS;AAC9B,MAAI,CAAC,cAAc;AACjB;AAAA,EACF;AAEA,QAAM,yBACJ,SAAS,QAAQ,qBAAqB;AAExC,MAAI,SAAS;AACb,QAAM,WAAW,yBACb,OACAA,MAAAA;AAAAA,IACE;AAAA,IACA,MAAM,GAAG,WAAW,OAAO,GAAG,KAAK;AAAA,IACnC,SAAS,QAAQ;AAAA,EAAA;AAGvB,QAAM,gBAAgB,CAAC,gBAAyB,MAAM;AACpD,aAAS,WAAW,OAAO;AAC3B;AACA,OAAG,QAAQ,WAAW;AAAA,EACxB;AACA,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,aAAa,cAAc,KAAK;AAEtC,UAAQ,iBAAiB,UAAU,SAAS,uBAAuB;AACnE,MAAI,wBAAwB;AAC1B,YAAQ,iBAAiB,aAAa,YAAY,uBAAuB;AAAA,EAC3E;AACA,SAAO,MAAM;AACX,YAAQ,oBAAoB,UAAU,OAAO;AAC7C,QAAI,wBAAwB;AAC1B,cAAQ,oBAAoB,aAAa,UAAU;AAAA,IACrD;AAIA,yCAAU;AAAA,EACZ;AACF;AAEO,MAAM,uBAAuB,CAClC,UACA,OAEA,cAAc,UAAU,IAAI,CAAC,OAAO;AAClC,QAAM,EAAE,YAAY,MAAA,IAAU,SAAS;AACvC,SAAO,aAAa,GAAG,cAAe,SAAS,MAAO,KAAK,GAAG;AAChE,CAAC;AAEI,MAAM,sBAAsB,CACjC,UACA,OAEA;AAAA,EAAc;AAAA,EAAU;AAAA,EAAI,CAAC,QAC3B,SAAS,QAAQ,aAAa,IAAI,UAAU,IAAI;AAClD;AAEK,MAAM,iBAAiB,CAC5B,SACA,OACA,aACG;AAGH,MAAI,SAAS,QAAQ,uBAAuB;AAC1C,UAAM,QAAQ,SAAS,iBAAiB,OAAO;AAC/C,UAAM,MAAM,SAAS,QAAQ,WAAW,KAAK;AAC7C,WACE,SAAS,cAAc,IAAI,GAAG,KAAK,SAAS,QAAQ,aAAa,KAAK;AAAA,EAE1E;AAEA,MAAI,+BAAO,eAAe;AACxB,UAAM,MAAM,MAAM,cAAc,CAAC;AACjC,QAAI,KAAK;AACP,YAAM,OAAO,KAAK;AAAA,QAChB,IAAI,SAAS,QAAQ,aAAa,eAAe,WAAW;AAAA,MAAA;AAE9D,aAAO;AAAA,IACT;AAAA,EACF;AAQA,MAAI,CAAC,OAAO;AACV,UAAM,QAAQ,SAAS,iBAAiB,OAAO;AAC/C,UAAM,MAAM,SAAS,QAAQ,WAAW,KAAK;AAC7C,UAAM,aAAa,SAAS,cAAc,IAAI,GAAG;AACjD,QAAI,eAAe,QAAW;AAC5B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAQ,QACN,SAAS,QAAQ,aAAa,gBAAgB,cAChD;AACF;AAEA,MAAM,wBAAwB,CAC5B,QACA;AAAA,EACE,cAAc;AAAA,EACd;AACF,GACA,aACG;;AACH,uBAAS,kBAAT,mBAAwB,aAAxB,4BAAmC;AAAA,IACjC,CAAC,SAAS,QAAQ,aAAa,SAAS,KAAK,GAAG,SAAS;AAAA,IACzD;AAAA,EAAA;AAEJ;AAEO,MAAM,eAID;AAEL,MAAM,gBAID;AA0FZ,MAAM,qBAAqB,CACzB,UACA,aAEA,aAAa,WAAY,WAAW,iBAAiB,WAAY;AAInE,MAAM,iBAAiB,CAAC,WACtB,+BAAO,WAAU,aAAY,+BAAO,WAAU;AAWhD,SAAS,iBACP,WACA,WACA,gBACA,YACS;AACT,MAAI,cAAc,EAAG,QAAO;AAE5B,QAAM,WAAW,WAAW,CAAC;AAC7B,QAAM,kCAAkB,IAAA;AACxB,MAAI,eAAe;AACnB,SAAO,eAAe,WAAW;AAC/B,UAAM,MAAM,eAAe,YAAY;AACvC,QAAI,QAAQ,SAAU;AACtB,gBAAY,IAAI,GAAG;AACnB;AAAA,EACF;AAEA,QAAM,gBAAgB,YAAY;AAClC,MAAI,kBAAkB,KAAK,iBAAiB,UAAW,QAAO;AAE9D,WAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,QAAI,WAAW,CAAC,MAAM,eAAe,eAAe,CAAC,EAAG,QAAO;AAAA,EACjE;AACA,WAAS,IAAI,eAAe,IAAI,WAAW,KAAK;AAC9C,QAAI,YAAY,IAAI,WAAW,CAAC,CAAC,EAAG,QAAO;AAAA,EAC7C;AACA,SAAO;AACT;AAEO,MAAM,YAGX;AAAA,EA2PA,YAAY,MAAwD;AA1PpE,SAAQ,SAAqC,CAAA;AAE7C,SAAA,gBAAuC;AACvC,SAAA,eAAoD;AACpD,SAAA,cAAc;AACd,SAAQ,cAAkC;AAC1C,SAAA,oBAAwC,CAAA;AAGxC,SAAQ,0BAGG;AACX,SAAA,oCAAoB,IAAA;AACpB,SAAQ,uBAAuB;AAC/B,SAAQ,sCAAsB,IAAA;AAE9B,SAAQ,aAA4B;AACpC,SAAQ,YAAgC;AACxC,SAAQ,mBAAmB;AAC3B,SAAQ,gBAAgB;AACxB,SAAQ,sBAAkD;AAC1D,SAAA,aAA0B;AAQ1B,SAAA,eAA8B;AAC9B,SAAA,kBAA0C;AAmB1C,SAAQ,cAAc;AAiBtB,SAAQ,sBAAsB;AAM9B,SAAQ,cAAc,IAAIC,sBAAW;AAAA,MACnC,WAAW,MAAM,KAAK;AAAA,MACtB,KAAK,MAAM,KAAK,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOhB,iBAAiB,MAAM;AACrB,cAAM,QAAQ,KAAK;AACnB,aAAI,+BAAO,WAAU,YAAY,KAAK,iBAAiB,MAAM;AAC3D,iBAAO;AAAA,QACT;AACA,cAAM,MAAM,KAAK,mBAAA;AACjB,YACE,QAAQ,QACR,KAAK,uBAAuB,QAC5B,KAAK,IAAI,MAAM,KAAK,kBAAkB,IAAI,GAC1C;AACA,iBAAO;AAAA,QACT;AACA,aAAK,qBAAqB;AAG1B,cAAM,UAAU,CAAC,GAAI,MAAM,WAAW,CAAA,GAAK,EAAE,GAAG,KAAK,IAAA,GAAO,QAAQ,KAAK;AACzE,eAAO;AAAA,MACT;AAAA,MACA,cAAc,MAAM;AAIlB,cAAM,QAAQ,KAAK;AACnB,aAAI,+BAAO,WAAU,YAAYC,iBAAAA,YAAY,MAAM,WAAW,CAAA,CAAE,GAAG;AACjE,eAAK,cAAc;AAAA,QACrB;AACA,aAAK,kBAAkB,IAAI;AAC3B,aAAK,sBAAA;AAAA,MACP;AAAA,IAAA,CACD;AAID,SAAQ,qBAAoC;AAqB5C,SAAQ,eAIG;AASX,SAAQ,qBACN;AAQF,SAAA,oCAAoB,IAAA;AAGpB,SAAQ,eAA2D;AACnE,SAAQ,MAAM,MAAA;;AAAM,qCAAK,iBAAL,mBAAmB,gBAAnB,mBAAgC,QAAhC,gCAA2C,KAAK,IAAA;AAAA;AACpE,SAAQ,WAAY,uBAAM;AACxB,UAAI,MAA6B;AACjC,UAAI,UAAsD;AAE1D,YAAM,MAAM,MAAM;AAChB,YAAI,KAAK;AACP,iBAAO;AAAA,QACT;AAEA,cAAM,eAAe,KAAK;AAC1B,YAAI,CAAC,gBAAgB,CAAC,aAAa,gBAAgB;AACjD,iBAAO;AAAA,QACT;AAEA,cAAM,SAAU,UAAU,iBAAiB,YAAY;AACvD,eAAQ,MAAM,IAAI,aAAa,eAAe,CAAC,YAAY;AACzD,gBAAM,MAAM,MAAM;AAMhB,kBAAM,QAA6C,EAAE,MAAM,MAAA;AAC3D,iBAAK,eAAe;AACpB,gBAAI;AACF,sBAAQ,QAAQ,YAAY;AAAA,YAC9B,UAAA;AACE,mBAAK,eAAe;AACpB,kBAAI,MAAM,QAAQ;AAChB,qBAAK,OAAO,MAAM,IAAI;AACtB,qBAAK,cAAA;AACL,qBAAK,kBAAkB,IAAI;AAC3B,qBAAK,wBAAA;AAAA,cACP;AAAA,YACF;AAAA,UACF;AACA,eAAK,QAAQ,sCACT,OAAO,SAAS,GAAG,IACnB,IAAA;AAAA,QACN,CAAC;AAAA,MACH;AAEA,YAAM,eAAe,CAAC,UAA+B;AACnD,cAAM,OAAO,MAAM;AACnB,cAAM,QAAQ,KAAK,iBAAiB,IAAI;AAExC,YAAI,CAAC,KAAK,aAAa;AACrB,eAAK,SAAS,UAAU,IAAI;AAS5B,qBAAW,CAAC,UAAU,UAAU,KAAK,KAAK,eAAe;AACvD,gBAAI,eAAe,MAAM;AACvB,mBAAK,cAAc,OAAO,QAAQ;AAClC;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AAEA,YAAI,CAAC,KAAK,eAAe,KAAK,EAAG;AAEjC,YAAI,KAAK,0BAA0B,KAAK,GAAG;AACzC,eAAK,WAAW,OAAO,KAAK,QAAQ,eAAe,MAAM,OAAO,IAAI,CAAC;AAAA,QACvE;AAAA,MACF;AAEA,aAAO;AAAA,QACL,YAAY,MAAM;;AAChB,oBAAA,MAAA,mBAAO;AACP,6CAAS;AACT,gBAAM;AACN,oBAAU;AAAA,QACZ;AAAA,QACA,SAAS,CAAC,WAAA;;AACR,2BAAA,MAAA,mBAAO,QAAQ,QAAQ,EAAE,KAAK;;QAChC,WAAW,CAAC,WAAA;;AAAoB,2BAAA,MAAA,mBAAO,UAAU;AAAA;AAAA,MAAM;AAAA,IAE3D,GAAA;AACA,SAAA,QAAyD;AAMzD,SAAA,aAAa,CAACC,UAA2D;;AAGvE,YAAM,SAAS;AAAA,QACb,OAAO;AAAA,QACP,eAAe;AAAA,QACf,UAAU;AAAA,QACV,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,oBAAoB;AAAA,QACpB,kBAAkB;AAAA,QAClB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,UAAU,MAAM;AAAA,QAAC;AAAA,QACjB;AAAA,QACA,aAAa,EAAE,OAAO,GAAG,QAAQ,EAAA;AAAA,QACjC,cAAc;AAAA,QACd,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,0BAA0B,CAAA;AAAA,QAC1B,OAAO;AAAA,QACP,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,oBAAoB;AAAA,QACpB,uBAAuB;AAAA,QACvB,SAAS;AAAA,QACT,OAAO;AAAA,QACP,mBAAmB;AAAA,QACnB,qCAAqC;AAAA,QACrC,oBAAoB;AAAA,QACpB,uBAAuB;AAAA,MAAA;AAGzB,iBAAW,OAAOA,OAAM;AACtB,cAAM,IAAKA,MAAa,GAAG;AAC3B,YAAI,MAAM,OAAY,QAAe,GAAG,IAAI;AAAA,MAC9C;AAEA,YAAM,cAAc,KAAK;AAGzB,UAAI,SAA+B;AACnC,UAAI,iBAAwC;AAC5C,UAAI,kBAAkB;AAEtB,UACE,gBAAgB,UAChB,YAAY,WACZ,OAAO,WACP,OAAO,aAAa,SACpB,KAAK,kBAAkB,MACvB;AACA,cAAM,YAAY,YAAY;AAC9B,cAAM,YAAY,OAAO;AACzB,cAAM,eAAe,KAAK,gBAAA;AAC1B,cAAM,kBAAgB,UAAK,4BAAL,mBAA8B,UAAS;AAC7D,cAAM,iBAAiB,CAAC,UACtBC,iBAAAA,kBAAkB,cAAc,KAAK,CAAE;AACzC,cAAM,eAAe,YAAY,IAAI,eAAe,CAAC,IAAI;AACzD,cAAM,cAAc,YAAY,IAAI,eAAe,YAAY,CAAC,IAAI;AACpE,cAAM,iBAAiB,cAAc;AACrC,cAAM,oBACJ,kBACC,YAAY,KACX,YAAY,MACX,OAAO,WAAW,CAAC,MAAM,gBACxB,OAAO,WAAW,YAAY,CAAC,MAAM;AAE3C,YAAI,mBAAmB;AACrB,4BAAkB;AAClB,gBAAM,OACJ,YAAY,IACP,KAAK,wBAAwB,KAAK,iBAAiB,KACpD,aAAa,CAAC,IACd;AAEN,cAAI,MAAM;AACR,qBAAS,CAAC,KAAK,KAAK,KAAK,gBAAA,IAAoB,KAAK,KAAK;AAAA,UACzD;AAEA,gBAAM,WACJ,OAAO,mBAAmB,OACtB,SACA,OAAO,kBAAkB;AAE/B,cACE,YACA,YAAY,KACZ,KAAK,QAAQ,YAAY,kBAAkB,MAC1C,cAAc,KAAK,OAAO,WAAW,YAAY,CAAC,MAAM,cACzD;AACA,gBACE,YAAY,aACZ;AAAA,cACE;AAAA,cACA;AAAA,cACA;AAAA,cACA,OAAO;AAAA,YAAA,GAET;AACA,+BAAiB;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,WAAK,UAAU;AAOf,UAAI,iBAAiB;AACnB,aAAK,aAAa;AAClB,aAAK;AAAA,MACP;AAcA,UAAI,cAA6B;AACjC,UACE,UACA,KAAK,iBAAiB,QACtB,CAAC,KAAK,4BACN;AACA,cAAM,CAAC,WAAW,YAAY,IAAI;AAClC,cAAM,kBAAkB,KAAK,gBAAA;AAC7B,cAAM,EAAE,OAAO,WAAA,IAAe,KAAK;AACnC,YAAI,MAAM;AACV,eAAO,MAAM,SAAS,WAAW,GAAG,MAAM,WAAW;AACnD;AAAA,QACF;AACA,YAAI,MAAM,OAAO;AACf,gBAAM,aAAa,gBAAgB,GAAG;AACtC,cAAI,YAAY;AAKd,kBAAM,YAAY,KAAK,IAAI,GAAG,WAAW,QAAQ,YAAY;AAE7D,gBAAI,CAAC,kBAAkB,cAAc,KAAK,cAAc;AACtD,4BAAc,YAAY,KAAK;AAC/B,mBAAK,eAAe;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,gBAAgB;AAClB,aAAK,sBAAsB,EAAE,MAAM,UAAU,UAAU,eAAA;AAAA,MACzD,WAAW,gBAAgB,MAAM;AAC/B,YAAI,KAAK,mBAAmB;AAC1B,eAAK,sBAAsB,EAAE,MAAM,UAAU,OAAO,YAAA;AAAA,QACtD,OAAO;AAKL,eAAK,eAAe;AACpB,eAAK,oBAAoB,WAAW;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,SAAQ,SAAS,CAAC,SAAkB;;AAClC,uBAAK,SAAQ,aAAb,4BAAwB,MAAM;AAAA,IAChC;AA0DA,SAAQ,cAAcC,MAAAA;AAAAA,MACpB,MAAM;AACJ,aAAK,eAAA;AAEL,eAAO;AAAA,UACL,KAAK;AAAA,UACL,KAAK,QAAQ,KAAK,MAAM,aAAa;AAAA,UACrC,KAAK,QAAQ,KAAK,MAAM,WAAW;AAAA,QAAA;AAAA,MAEvC;AAAA,MACA,CAAC,gBAAgB;AACf,aAAK,OAAO,WAAW;AAAA,MACzB;AAAA,MACA;AAAA,QACE,KAAK,QAAQ,IAAI,aAAa,gBAAgB;AAAA,QAC9C,OAAO,MAAM,KAAK,QAAQ;AAAA,QAC1B,aAAa;AAAA,UACX,KAAK;AAAA,UACL,KAAK,QAAQ,KAAK,MAAM,aAAa;AAAA,UACrC,KAAK,QAAQ,KAAK,MAAM,WAAW;AAAA,QAAA;AAAA,MACrC;AAAA,IACF;AAGF,SAAQ,UAAU,MAAM;;AACtB,WAAK,OAAO,OAAO,OAAO,EAAE,QAAQ,CAAC,MAAM,GAAI;AAC/C,WAAK,SAAS,CAAA;AACd,WAAK,SAAS,WAAA;AACd,UAAI,KAAK,SAAS,QAAQ,KAAK,cAAc;AAC3C,aAAK,aAAa,qBAAqB,KAAK,KAAK;AACjD,aAAK,QAAQ;AAAA,MACf;AACA,WAAK,cAAc;AAGnB,iBAAK,kBAAL,mBAAoB;AACpB,WAAK,gBAAgB;AAMrB,WAAK,cAAc;AACnB,WAAK,kBAAkB;AAUvB,WAAK,cAAc;AACnB,WAAK,sBAAsB;AAE3B,WAAK,qBAAqB;AAE1B,WAAK,eAAe;AACpB,WAAK,gBAAgB;AACrB,WAAK,eAAe;AAAA,IACtB;AAEA,SAAA,YAAY,MAAM;AAChB,aAAO,MAAM;AACX,aAAK,QAAA;AAAA,MACP;AAAA,IACF;AAEA,SAAA,cAAc,MAAM;;AAClB,YAAM,gBAAgB,KAAK,QAAQ,UAC/B,KAAK,QAAQ,qBACb;AAEJ,UAAI,KAAK,kBAAkB,eAAe;AACxC,aAAK,QAAA;AAEL,YAAI,CAAC,eAAe;AAClB,eAAK,YAAA;AACL;AAAA,QACF;AAEA,aAAK,gBAAgB;AAErB,YAAI,KAAK,iBAAiB,mBAAmB,KAAK,eAAe;AAC/D,eAAK,eAAe,KAAK,cAAc,cAAc;AAAA,QACvD,OAAO;AACL,eAAK,iBAAe,UAAK,kBAAL,mBAAoB,WAAU;AAAA,QACpD;AAEA,aAAK,cAAc,QAAQ,CAAC,WAAW;AACrC,eAAK,SAAS,QAAQ,MAAM;AAAA,QAC9B,CAAC;AAED,aAAK,OAAO;AAAA,UACV,KAAK,QAAQ,mBAAmB,MAAM,CAAC,SAAS;AAC9C,iBAAK,aAAa;AAClB,iBAAK,YAAA;AAAA,UACP,CAAC;AAAA,QAAA;AAGH,aAAK,OAAO;AAAA,UACV,KAAK,QAAQ,qBAAqB,MAAM,CAAC,QAAQ,gBAAgB;;AAI/D,kBAAM,aAAa,cAAc,KAAK,wBAAA,IAA4B;AAClE,kBAAM,kBAAkB,KAAK;AAC7B,iBAAK,sBACH,SAAS,KAAM,eAAe,QAAQ,SAAS,aAAa;AAC9D,kBAAM,gBAAgB;AACtB,iBAAK,qBAAqB;AAE1B,qBAAS,KAAK,gBAAgB,MAAM;AAEpC,kBAAM,OAAO,KAAK;AAAA,cAChB;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAEF,gBAAI,SAAS,WAAY;AAEzB,gBAAI,SAAS,YAAY;AAGvB,uBAAS,KAAK,aAAc;AAAA,YAC9B,WACE,SAAS,uBACTC,MAAA,KAAK,gBAAL,gBAAAA,IAAkB,UAAS;AAAA,YAE3B,SAAS,KAAK,mBAAA,IAAuB,KACrC;AAIA,mBAAK,YAAY,mBAAmB;AAAA,YACtC,WACEC,iBAAAA,uBAAuB;AAAA,cACrB;AAAA,cACA;AAAA,cACA,SAAS,KAAK;AAAA,cACd,QAAQ,MAAM,KAAK,qBAAqB,KAAK,WAAY;AAAA,YAAA,CAC1D,GACD;AACA,mBAAK,cAAc;AAAA,YACrB;AACA,iBAAK,eAAe;AASpB,gBACE,KAAK,uBAAuB,QAC5B,KAAK,IAAI,SAAS,KAAK,mBAAmB,UAAU,KAAK,KACzD;AACA,mBAAK,qBAAqB;AAAA,YAC5B;AAMA,kBAAM,aAAa,KAAK,gBAAA;AACxB,kBAAM,gBAAgB,KAAK;AAC3B,iBAAK,kBAAkB,cACnB,eAAe,SACb,KAAK,kBACL,aAAa,SACX,YACA,aACJ;AACJ,iBAAK,eAAe;AACpB,iBAAK,cAAc;AAOnB,kBAAM,SAAS,KAAK;AACpB,iBACE,iCAAQ,WAAU,YAClB,SAAS,cACT,aACA;AACA,kBAAI,mBAAmB,KAAK,qBAAqB;AAC/C,uBAAO,UAAU,CAAA;AAAA,cACnB,OAAO;AACL,sBAAM,IAAI,KAAK,IAAA;AACf,uBAAO,UAAU;AAAA,kBACf,IAAI,OAAO,WAAW,CAAA,GAAI;AAAA,oBACxB,CAAC,WAAW,IAAI,OAAO,KAAK;AAAA,kBAAA;AAAA,kBAE9B,EAAE,GAAG,QAAQ,cAAA;AAAA,gBAAc;AAE7B,oBACG,kBAAkB,QACjB,KAAK,oBAAoB,iBAC3BC,iBAAAA,YAAY,OAAO,OAAO,GAC1B;AACA,uBAAK,cAAc;AAAA,gBACrB;AAAA,cACF;AAAA,YACF;AACA,gBACE,KAAK,YAAY,SAAS;AAAA,cACxB;AAAA,cACA,aAAa,SAAS;AAAA,cACtB,OAAO,WAAW;AAAA;AAAA;AAAA,cAGlB,UACE,SAAS,gBACT,UAAK,gBAAL,mBAAkB,WAAU,cAC5B,UAAK,gBAAL,mBAAkB,WAAU;AAAA,YAAA,CAC/B;AAAA;AAAA,cAGD,UAAK,gBAAL,mBAAkB,WAAU,UAC5B;AACA,mBAAK,cAAc;AAAA,YACrB;AAGA,iBAAK,kBAAkB,IAAI;AAE3B,gBAAI,KAAK,aAAa;AACpB,mBAAK,wBAAA;AAAA,YACP;AACA,iBAAK,YAAA;AAAA,UACP,CAAC;AAAA,QAAA;AAIH,YAAI,sBAAsB,KAAK,eAAe;AAC5C,eAAK,OAAO;AAAA,YACV,KAAK,YAAY,OAAO,KAAK,aAAuC;AAAA,UAAA;AAAA,QAExE;AAEA,aAAK,gBAAgB,KAAK,iBAAiB;AAAA,MAC7C;AAGA,WAAK,cAAA;AAEL,YAAM,SAAS,KAAK;AACpB,WAAK,sBAAsB;AAE3B,UAAI,UAAU,KAAK,iBAAiB,KAAK,QAAQ,SAAS;AACxD,YAAI,OAAO,SAAS,UAAU;AAS5B,cAAI,CAAC,KAAK,mBAAmB;AAC3B,iBAAK,eAAe,OAAO;AAC3B,iBAAK,oBAAoB,OAAO,KAAK;AACrC,iBAAK,OAAO,KAAK;AAAA,UACnB,WACE,eAAe,KAAK,WAAW,KAC/B,CAACC,MAAAA;AAAAA,YACC,KAAK,oBAAoB,OAAO;AAAA,YAChC,KAAK,YAAY;AAAA,UAAA,EAEnB;AAAA,eASK;AACL,iBAAK,oBAAoB,OAAO,KAAK;AACrC,iBAAK,gBAAgB,KAAK,iBAAiB;AAAA,UAC7C;AAAA,QACF,OAAO;AACL,eAAK,YAAY,EAAE,UAAU,OAAO,UAAU;AAAA,QAChD;AAAA,MACF;AAMA,WAAK,kBAAkB,KAAK;AAG5B,WAAK,wBAAA;AAAA,IACP;AAMA,SAAQ,uBAAuB,CAC7B,QACA,aACA;;AAEAC,8BAAAA,oBAAoB;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,cAAc,KAAK;AAAA,QACnB,cAAc,KAAK;AAAA,QACnB,qBAAmB,UAAK,uBAAL,mBAAyB,eAAc;AAAA,MAAA,CAC3D;AAAA;AASH,SAAQ,0BAA0B,MAAM;AACtC,UACE,KAAK,uBAAuB,QAC5B,CAAC,KAAK,iBACN,CAAC,KAAK,QAAQ,SACd;AACA;AAAA,MACF;AACA,YAAM,EAAE,QAAQ,WAAA,IAAe,KAAK;AACpC,YAAM,MAAM,KAAK,mBAAA;AACjB,UAAI,MAAM,aAAa,KAAK;AAG1B,aAAK,qBACH,SAAS,MAAM,MAAM,EAAE,QAAQ,YAAY,QAAQ;AACrD,aAAK,gBAAgB,MAAM;AAAA,MAC7B;AAAA,IACF;AAKA,SAAQ,wBAAwB,MAAM;AACpC,YAAM,QAAQ,KAAK;AACnB,UAAI,UAAU,QAAQ,MAAM,UAAU,SAAU;AAChD,YAAM,EAAE,aAAa;AACrB,WAAK,gBAAA;AACL,YAAM,SAAS,KAAK,qBAAqB,KAAK;AAC9C,YAAM,mBAAmB;AAGzB,WAAK,qBAAqB;AAC1B,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA,MAAM,SAAS,QAAQD,MAAAA,YAAY,QAAQ,KAAK,iBAAiB;AAAA,MAAA;AAEnE,WAAK,gBAAgB,QAAQ,EAAE,SAAA,CAAU;AACzC,WAAK,wBAAA;AAAA,IACP;AAIA,SAAQ,qBAAqB,MAAqB;AAChD,YAAM,KAAK,KAAK;AAGhB,UAAI,MAAM,KAAM,QAAO;AACvB,YAAM,EAAE,YAAY,MAAA,IAAU,KAAK;AACnC,UAAI,OAAO,GAAG,cAAc,UAAU;AACpC,eAAO,aAAa,GAAG,cAAgB,SAAS,MAAO,KAAK,GAAG;AAAA,MACjE;AACA,UAAI,OAAO,GAAG,YAAY,UAAU;AAClC,eAAO,aAAa,GAAG,UAAW,GAAG;AAAA,MACvC;AACA,aAAO;AAAA,IACT;AAYA,SAAQ,kBAAkB,MACxB,EAAEE,WAAAA,iBAAiB,KAAK,YAAY,SAAA,MAAe,CAAC,KAAK;AAS3D,SAAQ,oBAAoB,CAAC,SAAkB;;AAC7C,UAAI,KAAK,gBAAgB,EAAG;AAC5B,UAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,QAAQ,QAAS;AAClD,UAAI,CAAC,KAAK,kBAAmB;AAE7B,YAAI,UAAK,gBAAL,mBAAkB,WAAU,SAAU;AAC1C,WAAK,cAAc;AAGnB,UAAI,KAAK,iBAAiB,QAAQ,KAAK,eAAe,GAAG;AACvD,aAAK,eAAe;AAAA,MACtB;AACA,WAAK,OAAO,IAAI;AAKhB,YAAM,SAAS,KAAK,wBAAA,KAA6B,KAAK,gBAAA;AAGtD,WAAK,qBAAqB,KAAK,WAAW,MAAM;AAChD,WAAK,gBAAgB,MAAM;AAAA,IAC7B;AAEA,SAAQ,QAAuB;AA2H/B,SAAQ,UAAU,MAAM;AACtB,UAAI,CAAC,KAAK,QAAQ,SAAS;AACzB,aAAK,aAAa;AAClB,eAAO;AAAA,MACT;AAEA,WAAK,aAAa,KAAK,cAAc,KAAK,QAAQ;AAElD,aAAO,KAAK,WAAW,KAAK,QAAQ,aAAa,UAAU,QAAQ;AAAA,IACrE;AAEA,SAAQ,kBAAkB,MAAM;AAC9B,UAAI,CAAC,KAAK,QAAQ,SAAS;AACzB,aAAK,eAAe;AACpB,eAAO;AAAA,MACT;AAEA,WAAK,eACH,KAAK,iBACJ,OAAO,KAAK,QAAQ,kBAAkB,aACnC,KAAK,QAAQ,cAAA,IACb,KAAK,QAAQ;AAEnB,aAAO,KAAK;AAAA,IACd;AAEA,SAAQ,wBAAwBN,MAAAA;AAAAA,MAC9B,MAAM;AAAA,QACJ,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,MAAA;AAAA,MAEf,CACE,OACA,cACA,cACA,YACA,SACA,OACA,oBACA,QACG;AACH,cAAM,eACJ,KAAK,cAAc,UAAa,KAAK,cAAc;AAErD,YAAI,cAAc;AAEhB,eAAK,mBAAmB;AAAA,QAC1B;AAEA,aAAK,YAAY;AACjB,aAAK,aAAa;AAElB,eAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,MAAA;AAAA,IACP;AAGF,SAAQ,iBAAiB,CAAC,UACxB,SAAS,KAAK,QAAQ,KAAK,QAAQ;AAErC,SAAQ,kBAAkBA,MAAAA;AAAAA,MACxB,MAAM,CAAC,KAAK,yBAAyB,KAAK,oBAAoB;AAAA,MAC9D,CACE;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,GAEF,0BACG;;AACH,cAAM,gBAAgB,KAAK;AAC3B,YAAI,CAAC,SAAS;AACZ,eAAK,oBAAoB,CAAA;AACzB,eAAK,0BAA0B;AAC/B,eAAK,cAAc,MAAA;AACnB,eAAK,gBAAgB,MAAA;AACrB,iBAAO,CAAA;AAAA,QACT;AAGA,YAAI,KAAK,gBAAgB,OAAO,OAAO;AACrC,qBAAW,SAAS,KAAK,gBAAgB,KAAA,GAAQ;AAC/C,gBAAI,SAAS,OAAO;AAClB,mBAAK,gBAAgB,OAAO,KAAK;AAAA,YACnC;AAAA,UACF;AAAA,QACF;AAGA,YAAI,KAAK,kBAAkB;AACzB,eAAK,mBAAmB;AACxB,eAAK,gBAAgB;AACrB,eAAK,oBAAoB,CAAA;AACzB,eAAK,0BAA0B;AAC/B,eAAK,cAAc,MAAA;AACnB,eAAK,gBAAgB,MAAA;AAErB,eAAK,aAAa;AAAA,QACpB;AAIA,YAAI,KAAK,kBAAkB,WAAW,KAAK,CAAC,KAAK,eAAe;AAC9D,eAAK,oBAAoB,KAAK,QAAQ;AACtC,eAAK,kBAAkB,QAAQ,CAAC,SAAS;AACvC,iBAAK,cAAc,IAAI,KAAK,KAAK,KAAK,IAAI;AAAA,UAC5C,CAAC;AAAA,QACH;AAGA,cAAM,MAAM,KAAK,gBAAgB,IAAK,KAAK,cAAc;AACzD,aAAK,aAAa;AAGlB,YAAI,KAAK,iBAAiB,KAAK,kBAAkB,WAAW,OAAO;AACjE,eAAK,gBAAgB;AAAA,QACvB;AAOA,YAAI,UAAU,GAAG;AAGf,gBAAM,OAAO,QAAQ;AACrB,cAAI,QAAO,UAAK,4BAAL,mBAA8B;AACzC,cAAI,CAAC,QAAQ,KAAK,SAAS,MAAM;AAC/B,kBAAM,OAAO,IAAI,aAAa,IAAI;AAClC,gBAAI,QAAQ,MAAM,EAAG,MAAK,IAAI,KAAK,SAAS,GAAG,MAAM,CAAC,CAAC;AACvD,mBAAO;AAAA,UACT;AAEA,gBAAM,QACJ,QAAQ,IACJ,IAAI,MAAM,KAAK,IACf,KAAK,wBAAyB,MAAM,MAAA;AAE1C,cAAI;AACJ,cAAI,QAAQ,GAAG;AACb,2BAAe,eAAe;AAAA,UAChC,OAAO;AAEL,kBAAM,UAAU,MAAM;AACtB,2BAAe,KAAK,UAAU,CAAC,IAAK,KAAK,UAAU,IAAI,CAAC,IAAK;AAAA,UAC/D;AAEA,mBAAS,IAAI,KAAK,IAAI,OAAO,KAAK;AAChC,kBAAM,MAAM,WAAW,CAAC;AACxB,kBAAM,CAAC,IAAI;AACX,kBAAM,eAAe,cAAc,IAAI,GAAG;AAC1C,kBAAM,OACJ,OAAO,iBAAiB,WACpB,eACA,KAAK,QAAQ,aAAa,CAAC;AACjC,iBAAK,IAAI,CAAC,IAAI;AACd,iBAAK,IAAI,IAAI,CAAC,IAAI;AAClB,4BAAgB,OAAO;AAAA,UACzB;AAEA,eAAK,0BAA0B,EAAE,MAAM,MAAA;AACvC,gBAAM,OAAOO,iBAAAA,2BAA2B,OAAO,IAAI;AACnD,eAAK,oBAAoB;AACzB,iBAAO;AAAA,QACT;AAEA,cAAM,eAAe,KAAK,kBAAkB,MAAM,GAAG,GAAG;AAGxD,cAAM,gBAA2C,IAAI,MAAM,KAAK,EAAE;AAAA,UAChE;AAAA,QAAA;AAOF,cAAM,WAAW,IAAI,aAAa,KAAK;AACvC,YAAI,cAAc;AAGlB,iBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,gBAAM,OAAO,aAAa,CAAC;AAC3B,cAAI,MAAM;AACR,gBAAI,cAAc,KAAK,IAAI,MAAM,OAAW;AAC5C,0BAAc,KAAK,IAAI,IAAI;AAC3B,qBAAS,KAAK,IAAI,IAAI,KAAK;AAAA,UAC7B;AAAA,QACF;AAEA,iBAAS,IAAI,KAAK,IAAI,OAAO,KAAK;AAChC,gBAAM,MAAM,WAAW,CAAC;AAGxB,gBAAM,aAAa,KAAK,gBAAgB,IAAI,CAAC;AAC7C,cAAI;AACJ,cAAI;AAEJ,gBAAM,kBACJ,uBAAuB,cAAc,cAAc,IAAI,GAAG;AAE5D,cAAI,eAAe,UAAa,KAAK,QAAQ,QAAQ,GAAG;AAEtD,mBAAO;AACP,kBAAM,YAAY,cAAc,IAAI;AACpC,kBAAM,aACJ,cAAc,SAAY,aAAa,SAAS,IAAI;AACtD,oBAAQ,aACJ,WAAW,MAAM,MACjB,eAAe;AAAA,UACrB,WAAW,gBAAgB,OAAO;AAKhC,gBAAI,WAAW;AACf,gBAAI,UAAU,SAAS,CAAC;AACxB,gBAAI,UAAU,cAAc,CAAC;AAC7B,qBAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,oBAAM,IAAI,SAAS,CAAC;AACpB,kBAAI,IAAI,WAAY,MAAM,WAAW,cAAc,CAAC,IAAK,SAAU;AACjE,2BAAW;AACX,0BAAU;AACV,0BAAU,cAAc,CAAC;AAAA,cAC3B;AAAA,YACF;AACA,mBAAO;AACP,oBAAQ,UAAU;AAElB,gBAAI,iBAAiB;AACnB,mBAAK,gBAAgB,IAAI,GAAG,IAAI;AAAA,YAClC;AAAA,UACF,OAAO;AAGL,mBAAO,IAAI,KAAK,QAAQ;AACxB,oBAAQ,eAAe;AAEvB,gBAAI,iBAAiB;AACnB,mBAAK,gBAAgB,IAAI,GAAG,IAAI;AAAA,YAClC;AAAA,UACF;AAEA,gBAAM,eAAe,cAAc,IAAI,GAAG;AAC1C,gBAAM,OACJ,OAAO,iBAAiB,WACpB,eACA,KAAK,QAAQ,aAAa,CAAC;AAEjC,gBAAM,MAAM,QAAQ;AAEpB,uBAAa,CAAC,IAAI;AAAA,YAChB,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAIF,cAAI,cAAc,IAAI,MAAM,OAAW;AACvC,wBAAc,IAAI,IAAI;AACtB,mBAAS,IAAI,IAAI;AAAA,QACnB;AAEA,aAAK,oBAAoB;AAEzB,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,KAAK,QAAQ,IAAI,aAAa,gBAAgB;AAAA,QAC9C,OAAO,MAAM,KAAK,QAAQ;AAAA,MAAA;AAAA,IAC5B;AAGF,SAAA,iBAAiBP,MAAAA;AAAAA,MACf,MAAM;AAAA,QACJ,KAAK,gBAAA;AAAA,QACL,KAAK,QAAA;AAAA,QACL,KAAK,gBAAA;AAAA,QACL,KAAK,QAAQ;AAAA,MAAA;AAAA,MAEf,CAAC,cAAc,WAAW,cAAc,UAAU;AAChD,YAAI,aAAa,WAAW,KAAK,cAAc,GAAG;AAChD,eAAK,QAAQ;AACb,iBAAO;AAAA,QACT;AACA,aAAK,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA;AAAA,UAGA,UAAU,KAAK,KAAK,4BAA4B,OAC5C,KAAK,wBAAwB,OAC7B;AAAA,QAAA;AAEN,eAAO,KAAK;AAAA,MACd;AAAA,MACA;AAAA,QACE,KAAK,QAAQ,IAAI,aAAa,gBAAgB;AAAA,QAC9C,OAAO,MAAM,KAAK,QAAQ;AAAA,MAAA;AAAA,IAC5B;AAGF,SAAA,oBAAoBA,MAAAA;AAAAA,MAClB,MAAM;AACJ,YAAI,aAA4B;AAChC,YAAI,WAA0B;AAC9B,cAAM,QAAQ,KAAK,eAAA;AACnB,YAAI,OAAO;AACT,uBAAa,MAAM;AACnB,qBAAW,MAAM;AAAA,QACnB;AACA,aAAK,YAAY,WAAW,CAAC,KAAK,aAAa,YAAY,QAAQ,CAAC;AACpE,eAAO;AAAA,UACL,KAAK,QAAQ;AAAA,UACb,KAAK,QAAQ;AAAA,UACb,KAAK,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,UACA,KAAK,QAAQ;AAAA,QAAA;AAAA,MAEjB;AAAA,MACA,CAAC,gBAAgB,UAAU,OAAO,YAAY,UAAU,UAAU;AAChE,eAAO,eAAe,QAAQ,aAAa,OACvC,CAAA,IACA,eAAe;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAAA,MACP;AAAA,MACA;AAAA,QACE,KAAK,QAAQ,IAAI,aAAa,gBAAgB;AAAA,QAC9C,OAAO,MAAM,KAAK,QAAQ;AAAA,MAAA;AAAA,IAC5B;AAGF,SAAA,mBAAmB,CAAC,SAAuB;AACzC,YAAM,gBAAgB,KAAK,QAAQ;AACnC,YAAM,WAAW,KAAK,aAAa,aAAa;AAEhD,UAAI,CAAC,UAAU;AACb,gBAAQ;AAAA,UACN,2BAA2B,aAAa;AAAA,QAAA;AAE1C,eAAO;AAAA,MACT;AAEA,aAAO,SAAS,UAAU,EAAE;AAAA,IAC9B;AAOA,SAAQ,4BAA4B,CAAC,UAA2B;;AAE9D,UAAI,CAAC,eAAe,KAAK,WAAW,GAAG;AACrC,eAAO;AAAA,MACT;AAEA,YAAM,cACJ,KAAK,YAAY,WACjB,UAAK,wBAAwB,KAAK,YAAY,gBAAgB,MAA9D,mBAAiE;AAEnE,UAAI,gBAAgB,UAAa,KAAK,OAAO;AAE3C,cAAM,aAAa,KAAK;AAAA,UACtB,KAAK,QAAQ;AAAA,UACb,KAAK,MAAM,KAAK,MAAM,WAAW,KAAK,MAAM,cAAc,CAAC;AAAA,QAAA;AAE7D,cAAM,WAAW,KAAK,IAAI,GAAG,cAAc,UAAU;AACrD,cAAM,WAAW,KAAK;AAAA,UACpB,KAAK,QAAQ,QAAQ;AAAA,UACrB,cAAc;AAAA,QAAA;AAEhB,eAAO,SAAS,YAAY,SAAS;AAAA,MACvC;AAEA,aAAO;AAAA,IACT;AAEA,SAAA,iBAAiB,CAAC,SAA8B;AAC9C,UAAI,CAAC,MAAM;AACT,aAAK,cAAc,QAAQ,CAAC,QAAQQ,SAAQ;AAC1C,cAAI,CAAC,OAAO,aAAa;AACvB,iBAAK,SAAS,UAAU,MAAM;AAC9B,iBAAK,cAAc,OAAOA,IAAG;AAAA,UAC/B;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK,iBAAiB,IAAI;AACxC,UAAI,CAAC,KAAK,eAAe,KAAK,EAAG;AAEjC,YAAM,MAAM,KAAK,QAAQ,WAAW,KAAK;AACzC,YAAM,WAAW,KAAK,cAAc,IAAI,GAAG;AAE3C,UAAI,aAAa,MAAM;AACrB,YAAI,UAAU;AACZ,eAAK,SAAS,UAAU,QAAQ;AAAA,QAClC;AACA,aAAK,SAAS,QAAQ,IAAI;AAC1B,aAAK,cAAc,IAAI,KAAK,IAAI;AAAA,MAClC;AASA,UACE,KAAK,gBACJ,CAAC,KAAK,eAAe,KAAK,gBAC3B,KAAK,0BAA0B,KAAK,GACpC;AACA,aAAK,WAAW,OAAO,KAAK,QAAQ,eAAe,MAAM,QAAW,IAAI,CAAC;AAAA,MAC3E;AAAA,IACF;AAEA,SAAA,aAAa,CAAC,OAAe,SAAiB;;AAC5C,UAAI,CAAC,KAAK,eAAe,KAAK,EAAG;AAQjC,WAAI,UAAK,iBAAL,mBAAmB,KAAM,MAAK,gBAAA;AAKlC,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,YAAM,QAAO,UAAK,4BAAL,mBAA8B;AAC3C,UAAI,KAAK,QAAQ,UAAU,KAAK,QAAQ,MAAM;AAC5C,cAAM,KAAK,QAAQ,WAAW,KAAK;AACnC,oBAAY,KAAK,QAAQ,CAAC;AAC1B,qBAAa,KAAK,QAAQ,IAAI,CAAC;AAAA,MACjC,OAAO;AACL,cAAM,OAAO,KAAK,kBAAkB,KAAK;AACzC,YAAI,CAAC,KAAM;AACX,cAAM,KAAK;AACX,oBAAY,KAAK;AACjB,qBAAa,KAAK;AAAA,MACpB;AAEA,YAAM,WAAW,KAAK,cAAc,IAAI,GAAG,KAAK;AAChD,YAAM,QAAQ,OAAO;AAErB,UAAI,UAAU,GAAG;AACf,cAAM,WACJ,KAAK,QAAQ,aAAa,SAC1B,CAAC,eAAe,KAAK,WAAW,KAChC,KAAK,0BAAA,KAA+B,KAAK,QAAQ;AACnD,cAAM,gBAAgB,WAAW,KAAK,oBAAA,IAAwB;AAG9D,cAAM,eAAe,KAAK,gBAAA;AAC1B,cAAM,iBAAiB,CAAC,KAAK,cAAc,IAAI,GAAG;AAClD,cAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA,UAIxB,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAQZ,YAAY,YAAY,gBACxB,KAAK,oBAAoB;AAAA;AAC7B,cAAM,qBACJ,CAAC,eAAe,KAAK,WAAW,MAC/B,KAAK,+CAA+C,SACjD,KAAK;AAAA;AAAA;AAAA,UAGH,KAAK,kBAAkB,KAAK,KAAK;AAAA,YAC/B;AAAA,YACA;AAAA,YACA,OAAO;AAAA,YACP,MAAM;AAAA,YACN,KAAK,YAAY;AAAA,YACjB,MAAM;AAAA,UAAA;AAAA,UAER;AAAA,UACA;AAAA,QAAA,IAEF;AAEN,YAAI,KAAK,eAAe,QAAQ,QAAQ,KAAK,YAAY;AACvD,eAAK,aAAa;AAAA,QACpB;AACA,aAAK,cAAc,IAAI,KAAK,IAAI;AAChC,aAAK;AAKL,YAAI,eAAe;AACnB,YAAI,CAAC,KAAK,4BAA4B;AACpC,cAAI,UAAU;AACZ,2BAAe,KAAK;AAAA,cAClB,KAAK,wBAAwB;AAAA,YAAA;AAAA,UAEjC,WAAW,oBAAoB;AAC7B,2BAAe,KAAK,sBAAsB,KAAK;AAAA,UACjD;AAAA,QACF;AAYA,YAAI,KAAK,cAAc;AAGrB,eAAK,aAAa,SAAS;AAC3B,qBAAK,cAAa,SAAlB,GAAkB,OAAS;AAC3B;AAAA,QACF;AACA,aAAK,OAAO,YAAY;AACxB,aAAK,cAAA;AAKL,aAAK,kBAAkB,IAAI;AAC3B,aAAK,wBAAA;AAAA,MACP;AAAA,IACF;AAEA,SAAA,kBAAkBR,MAAAA;AAAAA,MAChB,MAAM,CAAC,KAAK,kBAAA,GAAqB,KAAK,gBAAA,GAAmB,KAAK,WAAW;AAAA,MACzE,CAAC,SAAS,cAAc,SAAS;AAC/B,cAAM,eAAmC,CAAA;AAEzC,iBAAS,IAAI,GAAG,MAAM,QAAQ,QAAQ,IAAI,KAAK,KAAK;AAClD,gBAAM,IAAI,QAAQ,CAAC;AACnB,gBAAM,cAAc,aAAa,CAAC;AAIlC,uBAAa;AAAA,YACX,SAAS,IACL,cACA;AAAA,cACE,GAAG;AAAA,cACH,OAAO,YAAY,QAAQ;AAAA,cAC3B,KAAK,YAAY,MAAM;AAAA,YAAA;AAAA,UACzB;AAAA,QAER;AAEA,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,KAAK,QAAQ,IAAI,aAAa,gBAAgB;AAAA,QAC9C,OAAO,MAAM,KAAK,QAAQ;AAAA,MAAA;AAAA,IAC5B;AAGF,SAAA,0BAA0B,CAAC,WAAmB;;AAC5C,YAAM,eAAe,KAAK,gBAAA;AAC1B,UAAI,aAAa,WAAW,GAAG;AAC7B,eAAO;AAAA,MACT;AAIA,YAAM,QAAO,UAAK,4BAAL,mBAA8B;AAC3C,YAAM,UAAU,KAAK,QAAQ,UAAU,KAAK,QAAQ;AACpD,YAAM,MAAM;AAAA,QACV;AAAA,QACA,aAAa,SAAS;AAAA,QACtB,UACI,CAAC,MAAc,KAAK,IAAI,CAAC,IACzB,CAAC,MAAcS,MAAAA,aAAa,aAAa,CAAC,CAAC,EAAE;AAAA,QACjD;AAAA,MAAA;AAEF,aAAOA,MAAAA,aAAa,aAAa,GAAG,CAAC;AAAA,IACvC;AAQA,SAAQ,gBAAgB,MAAM;AAC5B,UAAI,CAAC,KAAK,2BAA4B;AACtC,YAAM,aAAa,KAAK,wBAAA;AACxB,UAAI,eAAe,KAAM;AACzB,YAAM,QAAQ,KAAK;AACnB,YAAM,MAAM,KAAK,IAAI,YAAY,CAAC,IAAI,KAAK;AAC3C,UAAI,OAAO,MAAM,OAAQ;AACzB,YAAM,WAAY,MAAM,aAAN,MAAM,WAAa,CAAA;AACrC,UAAI,SAAS,SAAS,SAAS,CAAC,MAAM,IAAK,UAAS,KAAK,GAAG;AAAA,IAC9D;AAIA,SAAQ,qBAAqB,OAC1B,KAAK,6BAA6B,KAAK,KAAK;AAU/C,SAAQ,kBAAkB,CAAC,kBAA0B;;AACnD,UAAI,SAAS,gBAAgB,KAAK;AAClC,YAAI,UAAK,wBAAL,mBAA0B,UAAS,UAAU;AAC/C,kBAAU,KAAK,oBAAoB;AAAA,MACrC;AACA,aAAO;AAAA,IACT;AAIA,SAAQ,0BAA0B,MAAqB;AACrD,YAAM,KAAK,KAAK;AAChB,UAAI,OAAO,KAAM,QAAO;AACxB,UAAI,kBAAkB,IAAI;AACxB,eAAO,KAAK,QAAQ,aAChB,GAAG,cAAc,GAAG,cACpB,GAAG,eAAe,GAAG;AAAA,MAC3B;AACA,UAAI,cAAc,IAAI;AACpB,cAAM,MAAM,GAAG,SAAS;AACxB,eAAO,KAAK,QAAQ,aAChB,IAAI,cAAc,GAAG,aACrB,IAAI,eAAe,GAAG;AAAA,MAC5B;AACA,aAAO;AAAA,IACT;AASA,SAAQ,gBACN;AACF,SAAQ,gBAAgB,CAAC,SAAqB;AAC5C,YAAM,KAAK,KAAK;AAChB,YAAM,MAAM,KAAK;AACjB,UAAI,OAAO,QAAQ,QAAQ,KAAM;AACjC,YAAM,WACJ,cAAc,KAAK,GAAG,SAAS,mBAAmB;AAGpD,UAAI,EAAC,qCAAU,OAAO;AACtB,UAAI,KAAK,eAAe;AACtB,aAAK,cAAc,OAAO;AAC1B;AAAA,MACF;AACA,YAAM,EAAE,UAAU;AAClB,YAAM,WAAW,KAAK,QAAQ,aAAa,eAAe;AAC1D,YAAM,QAAQ,MAAM,iBAAiB,QAAQ;AAC7C,YAAM,WAAW,MAAM,oBAAoB,QAAQ;AACnD,YAAM,YAAY,UAAU,UAAU,WAAW;AACjD,YAAM,OAAO;AAAA;AAAA;AAAA,QAGX,SAAS,MAAM;AACb,cACE,MAAM,iBAAiB,QAAQ,MAAM,YACrC,MAAM,oBAAoB,QAAQ,MAAM,aACxC;AACA,mBAAO;AAAA,UACT;AACA,gBAAM,YAAY,UAAU,OAAO,QAAQ;AAC3C,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAEF,WAAK,gBAAgB;AACrB,UAAI;AAAA,QAAsB,MACxB,IAAI,sBAAsB,MAAM;AAE9B,cAAI,KAAK,kBAAkB,KAAM;AACjC,eAAK,gBAAgB;AAErB,cAAI,KAAK,UAAW,MAAK,KAAA;AAAA,QAC3B,CAAC;AAAA,MAAA;AAAA,IAEL;AAIA,SAAQ,aAAa,CAAC,WAAmB;AACvC,YAAM,aAAa,KAAK,wBAAA;AACxB,UAAI,eAAe,KAAM,QAAO;AAChC,YAAM,aAAa,aAAa,KAAK;AACrC,aAAO,SAAS,aAAa,MAAM,EAAE,QAAQ,eAAe;AAAA,IAC9D;AAEA,SAAQ,4BAA4B,MAAM;AACxC,aAAO,KAAK;AAAA,QACV,KAAK,oBAAA,IAAwB,KAAK,QAAA,IAAY,KAAK,gBAAA;AAAA,QACnD;AAAA,MAAA;AAAA,IAEJ;AAEA,SAAA,qBAAqB,MAAM;AACzB,aAAO,KAAK,IAAI,KAAK,mBAAA,IAAuB,KAAK,gBAAA,GAAmB,CAAC;AAAA,IACvE;AAEA,SAAA,UAAU,CAAC,YAAY,KAAK,QAAQ,uBAAuB;AACzD,aAAO,KAAK,wBAAwB;AAAA,IACtC;AAEA,SAAA,wBAAwB,CACtB,UACA,OACA,WAAW,MACR;AACH,UAAI,CAAC,KAAK,cAAe,QAAO;AAEhC,YAAM,OAAO,KAAK,QAAA;AAClB,YAAM,eAAe,KAAK,gBAAA;AAE1B,UAAI,UAAU,QAAQ;AACpB,gBAAQ,YAAY,eAAe,OAAO,QAAQ;AAAA,MACpD;AAEA,UAAI,UAAU,UAAU;AAGtB,qBAAa,WAAW,QAAQ;AAAA,MAClC,WAAW,UAAU,OAAO;AAC1B,oBAAY;AAAA,MACd;AAEA,YAAM,YAAY,KAAK,mBAAA;AAEvB,aAAO,KAAK,IAAI,KAAK,IAAI,WAAW,QAAQ,GAAG,CAAC;AAAA,IAClD;AAEA,SAAA,oBAAoB,CAAC,OAAe,QAAyB,WAAW;AACtE,cAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,KAAK,QAAQ,QAAQ,CAAC,CAAC;AAE3D,YAAM,OAAO,KAAK,QAAA;AAClB,YAAM,eAAe,KAAK,gBAAA;AAE1B,YAAM,OAAO,KAAK,kBAAkB,KAAK;AACzC,UAAI,CAAC,KAAM;AAEX,UAAI,UAAU,QAAQ;AACpB,YAAI,KAAK,OAAO,eAAe,OAAO,KAAK,QAAQ,kBAAkB;AACnE,kBAAQ;AAAA,QACV,WAAW,KAAK,SAAS,eAAe,KAAK,QAAQ,oBAAoB;AACvE,kBAAQ;AAAA,QACV,OAAO;AACL,iBAAO,CAAC,cAAc,KAAK;AAAA,QAC7B;AAAA,MACF;AAMA,UAAI,UAAU,SAAS,UAAU,KAAK,QAAQ,QAAQ,GAAG;AACvD,cAAM,YAAY,KAAK,mBAAA;AACvB,cAAMC,YACJ,YAAY,KAAK,QAAQ,aAAa,KAAK,QAAQ;AACrD,eAAO,CAAC,KAAK,IAAI,KAAK,IAAIA,WAAU,SAAS,GAAG,CAAC,GAAG,KAAK;AAAA,MAC3D;AAEA,YAAM,WACJ,UAAU,QACN,KAAK,MAAM,KAAK,QAAQ,mBACxB,KAAK,QAAQ,KAAK,QAAQ;AAEhC,aAAO;AAAA,QACL,KAAK,sBAAsB,UAAU,OAAO,KAAK,IAAI;AAAA,QACrD;AAAA,MAAA;AAAA,IAEJ;AAEA,SAAA,iBAAiB,CACf,UACA,EAAE,QAAQ,SAAS,WAAW,OAAA,IAAkC,OAC7D;AACH,WAAK;AAAA,QACH,EAAE,OAAO,MAAM,MAAA;AAAA,QACf,KAAK,sBAAsB,UAAU,KAAK;AAAA,QAC1C;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAEA,SAAA,gBAAgB,CACd,OACA;AAAA,MACE,OAAO,eAAe;AAAA,MACtB,WAAW;AAAA,IAAA,IACa,OACvB;AACH,cAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,KAAK,QAAQ,QAAQ,CAAC,CAAC;AAE3D,YAAM,aAAa,KAAK,kBAAkB,OAAO,YAAY;AAE7D,UAAI,CAAC,WAAY;AACjB,YAAM,CAAC,QAAQ,KAAK,IAAI;AAExB,WAAK,aAAa,EAAE,OAAO,SAAS,QAAQ,UAAU,UAAU;AAAA,IAClE;AAEA,SAAA,WAAW,CACT,OACA,EAAE,WAAW,OAAA,IAAkC,OAC5C;AAIH,YAAM,SAAS,KAAK;AAAA,SACjB,KAAK,wBAAA,KAA6B,KAAK,qBAAqB;AAAA,QAC7D;AAAA,MAAA;AAGF,WAAK;AAAA,QACH,EAAE,OAAO,MAAM,OAAO,QAAA;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAEA,SAAA,cAAc,CAAC,EAAE,WAAW,OAAA,IAA+B,CAAA,MAAO;AAChE,UAAI,KAAK,QAAQ,QAAQ,GAAG;AAG1B,aAAK;AAAA,UACH,EAAE,OAAO,KAAK,QAAQ,QAAQ,GAAG,OAAO,OAAO,OAAO,KAAA;AAAA,UACtD,KAAK,IAAI,KAAK,mBAAA,GAAsB,CAAC;AAAA,UACrC;AAAA,UACA;AAAA,QAAA;AAEF;AAAA,MACF;AAEA,WAAK,eAAe,KAAK,IAAI,KAAK,aAAA,IAAiB,KAAK,WAAW,CAAC,GAAG;AAAA,QACrE;AAAA,MAAA,CACD;AAAA,IACH;AAwFA,SAAA,eAAe,MAAM;AACnB,UAAI,KAAK,SAAS,QAAQ,KAAK,cAAc;AAC3C,aAAK,aAAa,qBAAqB,KAAK,KAAK;AACjD,aAAK,QAAQ;AAAA,MACf;AACA,WAAK,cAAc;AAAA,IACrB;AAKA,SAAA,eAAe,MACb,KAAK,IAAI,KAAK,wBAAwB,KAAK,aAAa,CAAC;AAE3D,SAAQ,sBAAsB,MAAM;;AAClC,YAAM,eAAe,KAAK,gBAAA;AAE1B,UAAI;AAIJ,UAAI,aAAa,WAAW,GAAG;AAC7B,cAAM,KAAK,QAAQ;AAAA,MACrB,WAAW,KAAK,QAAQ,UAAU,GAAG;AAInC,cAAM,UAAU,aAAa,SAAS;AACtC,cAAM,QAAO,UAAK,4BAAL,mBAA8B;AAC3C,YAAI,QAAQ,MAAM;AAChB,gBAAM,KAAK,UAAU,CAAC,IAAK,KAAK,UAAU,IAAI,CAAC;AAAA,QACjD,OAAO;AACL,kBAAM,kBAAa,OAAO,MAApB,mBAAuB,QAAO;AAAA,QACtC;AAAA,MACF,OAAO;AACL,cAAM,YAAY,MAAqB,KAAK,QAAQ,KAAK,EAAE,KAAK,IAAI;AACpE,YAAI,WAAW,aAAa,SAAS;AACrC,eAAO,YAAY,KAAK,UAAU,KAAK,CAAC,QAAQ,QAAQ,IAAI,GAAG;AAC7D,gBAAM,OAAO,aAAa,QAAQ;AAClC,cAAI,UAAU,KAAK,IAAI,MAAM,MAAM;AACjC,sBAAU,KAAK,IAAI,IAAI,KAAK;AAAA,UAC9B;AAEA;AAAA,QACF;AAEA,cAAM,KAAK,IAAI,GAAG,UAAU,OAAO,CAAC,QAAuB,QAAQ,IAAI,CAAC;AAAA,MAC1E;AAEA,aAAO,KAAK;AAAA,QACV,MAAM,KAAK,QAAQ,eAAe,KAAK,QAAQ;AAAA,QAC/C;AAAA,MAAA;AAAA,IAEJ;AAYA,SAAA,eAAe,MAA0B;AACvC,YAAM,WAA+B,CAAA;AACrC,UAAI,KAAK,cAAc,SAAS,EAAG,QAAO;AAI1C,YAAM,IAAI,KAAK,gBAAA;AACf,iBAAW,QAAQ,GAAG;AACpB,YAAI,QAAQ,KAAK,cAAc,IAAI,KAAK,GAAG,GAAG;AAE5C,mBAAS,KAAK;AAAA,YACZ,OAAO,KAAK;AAAA,YACZ,KAAK,KAAK;AAAA,YACV,OAAO,KAAK;AAAA,YACZ,MAAM,KAAK;AAAA,YACX,KAAK,KAAK;AAAA,YACV,MAAM,KAAK;AAAA,UAAA,CACZ;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,SAAQ,kBAAkB,CACxB,QACA;AAAA,MACE;AAAA,MACA;AAAA,IAAA,IACuD,OACtD;AACH,YAAM,QAAQ;AAAA,QACZ,QAAQ,UAAU,eAAe;AAAA,QACjC,QAAQ,aAAa;AAAA,MAAA;AAEvB,WAAK,eAAe;AAGpB,WAAK,QAAQ;AAAA,QACX,SAAS,KAAK;AAAA,QACd,EAAE,UAAU,YAAA;AAAA,QACZ;AAAA,MAAA;AAEF,aAAO;AAAA,IACT;AAOA,SAAQ,0BAA0B,MAChC,KAAK,gBAAgB,QACrB,KAAK,iBAAiB,QACtB,CAAC,KAAK,aAAa,SACf,KAAK,aAAa,SAClB;AAWN,SAAQ,2BAA2B,MAAM;AACvC,YAAM,gBAAgB,KAAK,wBAAA;AAC3B,aACE,EAAEJ,WAAAA,YAAA,KAAiB,KAAK,YAAY,SAAA,MACpC,kBAAkB,QAClB,CAACF,MAAAA,YAAY,eAAe,KAAK,iBAAiB;AAAA,IAEtD;AAOA,SAAQ,sBAAsB,CAAC,UAAkB;AAC/C,UAAI,KAAK,gBAAgB,QAAQ,KAAK,YAAY,SAAS,MAAM;AAC/D,aAAK,YAAY,oBAAoB;AAAA,MACvC;AAAA,IACF;AAEA,SAAA,UAAU,MAAM;AAId,WAAK,aAAa;AAClB,WAAK,cAAc,MAAA;AACnB,WAAK,gBAAgB,MAAA;AACrB,WAAK;AACL,WAAK,OAAO,KAAK;AAAA,IACnB;AA/4DE,SAAK,WAAW,IAAI;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAvNA,IAAI,oBAAoB;AACtB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAgZQ,sBACN,OACA,UACS;AACT,QAAI,UAAU,EAAG,QAAO;AAExB,QAAI,QAAQ,IAAI,aAAa,gBAAgB,KAAK,QAAQ,OAAO;AAC/D,cAAQ,KAAK,cAAc,KAAK;AAAA,IAClC;AAIA,SAAK,oBAAoB,KAAK;AAE9B,QAAI,CAAC,KAAK,mBAAmB;AAK3B,WAAK,eAAe;AACpB,UAAI,KAAK,iBAAiB,KAAM,MAAK,gBAAgB;AACrD,aAAO;AAAA,IACT,OAAO;AACL,YAAM,SAAS,KAAK,gBAAA;AACpB,WAAK,qBAAqB,KAAK,WAAW,SAAS,KAAK;AACxD,YAAM,QAAQ,KAAK,gBAAgB,QAAQ;AAAA,QACzC,aAAa;AAAA,QACb;AAAA,MAAA,CACD;AAUD,UAAI,KAAK,iBAAiB,MAAM;AAC9B,YAAI,KAAK,iBAAiB,MAAO,MAAK,gBAAgB;AAOtD,YAAI,KAAK,eAAe,EAAG,MAAK,eAAe;AAAA,MACjD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EA+aQ,0BAA0B;AAChC,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,cAAc;AACnB;AAAA,IACF;AACA,QAAI,KAAK,SAAS,KAAM;AACxB,SAAK,QAAQ,KAAK,aAAa,sBAAsB,MAAM;AACzD,WAAK,QAAQ;AACb,WAAK,gBAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EACQ,qBAAqB,OAAoB;AAC/C,UAAM,aAAa,MAAM,QACpB,CAAC,KAAK,IAAI,KAAK,sBAAsB,CAAC,CAAC,IACxC,MAAM,SAAS,OACb,KAAK,kBAAkB,MAAM,OAAO,MAAM,KAAK,IAC/C;AACN,WAAO,aAAa,WAAW,CAAC,IAAI,MAAM;AAAA,EAC5C;AAAA,EACQ,kBAAkB;AACxB,QAAI,CAAC,KAAK,YAAa;AAEvB,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC,GAAI;AAGT,UAAM,mBAAmB;AACzB,QAAI,KAAK,IAAA,IAAQ,KAAK,YAAY,YAAY,kBAAkB;AAC9D,WAAK,cAAc;AACnB;AAAA,IACF;AAIA,QAAI,KAAK,YAAY,UAAU,UAAU;AACvC,WAAK,wBAAA;AACL;AAAA,IACF;AAKA,SAAK,gBAAA;AACL,UAAM,eAAe,KAAK,qBAAqB,KAAK,WAAW;AAM/D,UAAM,gBACJ,KAAK,YAAY,SAAS,OACtB,IACA,KAAK,QAAQ,sCACX,IACA;AAER,UAAM,gBAAgB,iBAAiB,KAAK,YAAY;AAExD,QAAI,CAAC,iBAAiBA,MAAAA,YAAY,cAAc,KAAK,gBAAA,CAAiB,GAAG;AAGvE,UAAI,KAAK,YAAY,UAAU,UAAU;AACvC,aAAK,YAAY,QAAQ;AAAA,MAC3B,WAAW,KAAK,YAAY,UAAU,mBAAmB;AACvD,aAAK,YAAY,QAAQ;AAAA,MAC3B;AACA,WAAK,YAAY;AACjB,UAAI,KAAK,YAAY,gBAAgB,eAAe;AAOlD,YAAI,KAAK,gBAAA,MAAsB,cAAc;AAC3C,eAAK,gBAAgB,cAAc,EAAE,UAAU,QAAQ;AAAA,QACzD;AACA,aAAK,cAAc;AACnB;AAAA,MACF;AAAA,IACF,OAAO;AACL,WAAK,YAAY,eAAe;AAEhC,UAAI,eAAe;AAQjB,cAAM,WAAW,KAAK,QAAA,KAAa;AACnC,cAAM,WAAW,KAAK,IAAI,eAAe,KAAK,iBAAiB;AAC/D,cAAM,aACJ,eAAe,KAAK,WAAW,KAAK,WAAW;AAEjD,aAAK,YAAY,mBAAmB;AACpC,YAAI,YAAY;AAGd,eAAK,YAAY,QAAQ;AAAA,QAC3B,WAAW,KAAK,YAAY,UAAU,UAAU;AAE9C,eAAK,YAAY,QAAQ;AAAA,QAC3B,WAAW,KAAK,YAAY,UAAU,gBAAgB;AACpD,eAAK,YAAY,QAAQ;AAAA,QAC3B;AAIA,aAAK,gBAAgB,cAAc;AAAA,UACjC,UAAU,aAAa,WAAW;AAAA,QAAA,CACnC;AAAA,MACH;AAAA,IACF;AAKA,SAAK,wBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+4BQ,aACN,QACA,QACA,UACA,MACA;AACA,UAAM,OAAO,KAAK,YAAY,KAAA;AAC9B,QAAI,SAAS,cAAc,SAAS,MAAM;AACxC,UAAI,SAAS,WAAWO,WAAAA,8BAA8B;AAWpD,aAAK,cAAc,MAAM;AACvB,gBAAM,QAAQ,KAAK;AACnB,eACE,+BAAO,WAAU;AAAA,UAEjB,KAAK,YAAY,KAAA,MAAW;AAAA;AAAA;AAAA;AAAA,UAK5B,KAAK,qBACL;AACA;AAAA,UACF;AACA,eAAK,YAAY,IAAA;AACjB,eAAK,kBAAkB,IAAI;AAC3B,eAAK,sBAAA;AAAA,QACP,CAAC;AACD,aAAK,cAAc;AAAA,UACjB,GAAG;AAAA,UACH,WAAW,KAAK,IAAA;AAAA,UAChB,kBAAkB;AAAA,UAClB,cAAc;AAAA,UACd,OAAO;AAAA,UACP;AAAA,UACA,SAAS,CAAA;AAAA,QAAC;AAEZ,aAAK,wBAAA;AACL;AAAA,MACF;AAMA,WAAK,YAAY,IAAA;AAAA,IACnB;AACA,SAAK,cAAc;AAAA,MACjB,GAAG;AAAA,MACH,WAAW,KAAK,IAAA;AAAA,MAChB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACL;AAAA,QACA,OAAO,SAAS,QAAQP,MAAAA,YAAY,QAAQ,KAAK,iBAAiB;AAAA,MAAA;AAAA,IACpE;AAEF,SAAK,gBAAgB,QAAQ,EAAE,SAAA,CAAU;AACzC,SAAK,wBAAA;AAAA,EACP;AAuKF;AAEA,MAAM,0BAA0B,CAC9B,KACA,MACA,iBACA,UACG;AACH,SAAO,OAAO,MAAM;AAClB,UAAM,UAAW,MAAM,QAAQ,IAAK;AACpC,UAAM,eAAe,gBAAgB,MAAM;AAE3C,QAAI,eAAe,OAAO;AACxB,YAAM,SAAS;AAAA,IACjB,WAAW,eAAe,OAAO;AAC/B,aAAO,SAAS;AAAA,IAClB,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,MAAM,GAAG;AACX,WAAO,MAAM;AAAA,EACf,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAKA,SAAS,4BACP,MACA,MACA,OACA;AACA,MAAI,MAAM;AACV,SAAO,OAAO,MAAM;AAClB,UAAM,UAAW,MAAM,QAAQ,IAAK;AACpC,UAAM,eAAe,KAAK,SAAS,CAAC;AAEpC,QAAI,eAAe,OAAO;AACxB,YAAM,SAAS;AAAA,IACjB,WAAW,eAAe,OAAO;AAC/B,aAAO,SAAS;AAAA,IAClB,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,MAAM,IAAI,MAAM,IAAI;AAC7B;AAEA,SAAS,mBACP,cACA,WACA,cACA,OACA,MACA;AACA,QAAM,YAAY,aAAa,SAAS;AAGxC,MAAI,aAAa,UAAU,OAAO;AAChC,WAAO,EAAE,YAAY,GAAG,UAAU,UAAA;AAAA,EACpC;AAEA,MAAI,UAAU,KAAK,SAAS,MAAM;AAEhC,UAAMQ,cAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,QAAIC,YAAWD;AACf,UAAM,QAAQ,eAAe;AAC7B,WACEC,YAAW,aACX,KAAKA,YAAW,CAAC,IAAK,KAAKA,YAAW,IAAI,CAAC,IAAK,OAChD;AACAA;AAAAA,IACF;AACA,WAAO,EAAE,YAAAD,aAAY,UAAAC,UAAAA;AAAAA,EACvB;AAGA,QAAM,WAAW,CAAC,UAAkB,aAAa,KAAK,EAAG;AACzD,MAAI,aAAa,wBAAwB,GAAG,WAAW,UAAU,YAAY;AAC7E,MAAI,WAAW;AAEf,MAAI,UAAU,GAAG;AACf,WACE,WAAW,aACX,aAAa,QAAQ,EAAG,MAAM,eAAe,WAC7C;AACA;AAAA,IACF;AAAA,EACF,WAAW,QAAQ,GAAG;AAGpB,UAAM,aAAa,MAAM,KAAK,EAAE,KAAK,CAAC;AACtC,WACE,WAAW,aACX,WAAW,KAAK,CAAC,QAAQ,MAAM,eAAe,SAAS,GACvD;AACA,YAAM,OAAO,aAAa,QAAQ;AAClC,iBAAW,KAAK,IAAI,IAAI,KAAK;AAC7B;AAAA,IACF;AAIA,UAAM,eAAe,MAAM,KAAK,EAAE,KAAK,eAAe,SAAS;AAC/D,WAAO,cAAc,KAAK,aAAa,KAAK,CAAC,QAAQ,OAAO,YAAY,GAAG;AACzE,YAAM,OAAO,aAAa,UAAU;AACpC,mBAAa,KAAK,IAAI,IAAI,KAAK;AAC/B;AAAA,IACF;AAGA,iBAAa,KAAK,IAAI,GAAG,aAAc,aAAa,KAAM;AAE1D,eAAW,KAAK,IAAI,WAAW,YAAY,QAAQ,IAAK,WAAW,MAAO;AAAA,EAC5E;AAEA,SAAO,EAAE,YAAY,SAAA;AACvB;;;;;;;;;;;;;;;;"}