@botiverse/raft-ui 0.10.6 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { cn } from "./cn.mjs";
2
2
  import { A as buttonVariants, C as DialogNav, D as DialogTitle, E as DialogSurface, F as resolveThemeScopeProps, I as useThemeScopeProps, L as useTheme, M as defaultNativeButton, N as useParentOverlayKind, O as DialogTrigger, P as withOverlayLayer, R as ThemeStateContext, S as DialogHeader, T as DialogPortal, _ as DialogBody, a as DrawerContent, b as DialogDescription, c as DrawerHeader, d as DrawerTitle, f as DrawerTrigger, g as Dialog, h as panelHeader, i as DrawerClose, j as Spinner, k as Button, l as DrawerOverlay, m as panelHeadEdges, n as DrawerActions, o as DrawerDescription, p as panelHeadActions, r as DrawerBody, s as DrawerFooter, t as Drawer, u as DrawerPortal, v as DialogClose, w as DialogOverlay, x as DialogFooter, y as DialogContent, z as tv } from "./drawer-yZD16Ybl.mjs";
3
3
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
4
4
  import { AlertTriangle, Bell, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, FileText, Image, Info, Minus, Upload, X, Zap } from "lucide-react";
5
- import { Children, Fragment, cloneElement, createContext, isValidElement, use, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
+ import { Children, Fragment, cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { Button as Button$1 } from "@base-ui/react/button";
8
8
  import { mergeProps } from "@base-ui/react/merge-props";
@@ -34,6 +34,7 @@ import { Toast } from "@base-ui/react/toast";
34
34
  import { Tabs as Tabs$1 } from "@base-ui/react/tabs";
35
35
  import { Separator as Separator$1 } from "@base-ui/react/separator";
36
36
  import { Group, Panel as Panel$1, Separator as Separator$2 } from "react-resizable-panels";
37
+ import { flushSync } from "react-dom";
37
38
  //#region src/components/alert-dialog/alert-dialog.tsx
38
39
  const alertDialog = tv({
39
40
  slots: {
@@ -7755,7 +7756,7 @@ const messageActionCardContent = tv({ slots: {
7755
7756
  properties: [
7756
7757
  "m-0 grid",
7757
7758
  "max-sm:grid-cols-1 max-sm:gap-y-0.5",
7758
- "grid-cols-[minmax(88px,max-content)_minmax(0,1fr)] items-center gap-x-4 gap-y-0.5"
7759
+ "grid-cols-[minmax(88px,max-content)_minmax(0,1fr)] items-baseline gap-x-4 gap-y-0.5"
7759
7760
  ],
7760
7761
  property: ["contents"],
7761
7762
  propertyLabel: ["max-w-40 min-w-0 wrap-break-word", "text-footnote font-medium text-foreground-hint"],
@@ -14872,6 +14873,2144 @@ function TaskSectionEmpty({ className, render, ...props }) {
14872
14873
  });
14873
14874
  }
14874
14875
  //#endregion
14876
+ //#region src/components/virtual-list/utils/constants.ts
14877
+ /**
14878
+ * Written on the root element of every measured item: maps the DOM to item keys (kept selections,
14879
+ * and what other code uses to find an item).
14880
+ */
14881
+ const ITEM_KEY_ATTR = "data-virtual-list-item-key";
14882
+ /** The default of the `columns` and `items` props, and the empty kept-item lists. */
14883
+ const EMPTY_ARRAY = [];
14884
+ /**
14885
+ * The visible-items element lays the rows out in normal block flow, so their margins collapse as the
14886
+ * consumer's CSS says (between adjacent rows, and a row's children's through the row). It is a block
14887
+ * formatting context (`flow-root`), so the first row's top margin and the last row's bottom margin stay
14888
+ * inside it instead of collapsing through it (into the spacer, or with the footer), and it is the rows'
14889
+ * offsetParent (`position: relative`): the list measures where each row starts from layout
14890
+ * (`measureRowSpans`).
14891
+ */
14892
+ const VIRTUAL_VISIBLE_ITEMS_STYLE = {
14893
+ position: "relative",
14894
+ display: "flow-root"
14895
+ };
14896
+ /**
14897
+ * With virtualization off, the visible-items element still carries the CSS variables, so sticky
14898
+ * children that use `calc(var(--virtual-list-transform-y))` keep working.
14899
+ */
14900
+ const NON_VIRTUAL_VISIBLE_ITEMS_STYLE = {
14901
+ "--virtual-list-transform-y": "0px",
14902
+ "--virtual-list-ios-compensation-y": "0px",
14903
+ transform: "translateY(0px)",
14904
+ position: "relative",
14905
+ display: "flow-root"
14906
+ };
14907
+ /** ... within this window (ms). */
14908
+ const RENDER_THRASHING_WINDOW_MS = 1e3;
14909
+ //#endregion
14910
+ //#region src/components/virtual-list/utils/fenwick-tree.ts
14911
+ /**
14912
+ * Sizes of `l` items, each `estimated` plus a delta stored in the tree: `sum(i)` (the offset of item
14913
+ * `i`) is `i * estimated` plus the prefix sum of the deltas, in O(log n); `getBound(offset)` maps an
14914
+ * offset to an item index by a binary search over `sum()` (O(log² n)).
14915
+ */
14916
+ var FenwickTree = class {
14917
+ l;
14918
+ estimated;
14919
+ ft;
14920
+ constructor(length, estimated) {
14921
+ this.l = length;
14922
+ this.estimated = estimated;
14923
+ const ft = Array(length + 1);
14924
+ for (let i = 0; i < length + 1; ++i) ft[i] = 0;
14925
+ this.ft = ft;
14926
+ }
14927
+ /** Adds `delta` to the size of item `index`. */
14928
+ add(index, delta) {
14929
+ if (delta === 0) return;
14930
+ const { l, ft } = this;
14931
+ index += 1;
14932
+ while (index <= l) {
14933
+ ft[index] += delta;
14934
+ index += index & -index;
14935
+ }
14936
+ }
14937
+ /** The size of item `index`. */
14938
+ get(index) {
14939
+ return this.sum(index + 1) - this.sum(index);
14940
+ }
14941
+ /** The total size of the first `count` items (all of them by default). */
14942
+ sum(count = this.l) {
14943
+ if (count <= 0) return 0;
14944
+ const { ft, estimated, l } = this;
14945
+ if (count > l) throw new Error("[FenwickTree.sum]: `i` is larger than length.");
14946
+ let sum = count * estimated;
14947
+ while (count > 0) {
14948
+ sum += ft[count];
14949
+ count -= count & -count;
14950
+ }
14951
+ return sum;
14952
+ }
14953
+ /** The largest count `c` with `sum(c) <= threshold`: the index of the item that contains `threshold`. */
14954
+ getBound(threshold) {
14955
+ let lo = 0;
14956
+ let hi = this.l;
14957
+ while (hi > lo) {
14958
+ const mid = Math.floor((lo + hi) / 2);
14959
+ const midSum = this.sum(mid);
14960
+ if (midSum > threshold) {
14961
+ hi = mid;
14962
+ continue;
14963
+ }
14964
+ if (!(midSum < threshold)) return mid;
14965
+ if (lo === mid) {
14966
+ if (this.sum(lo + 1) <= threshold) return lo + 1;
14967
+ return mid;
14968
+ }
14969
+ lo = mid;
14970
+ }
14971
+ return lo;
14972
+ }
14973
+ };
14974
+ //#endregion
14975
+ //#region src/components/virtual-list/utils/items-anchor.ts
14976
+ /**
14977
+ * Finds the row at `top` (the view's top, in item coordinates: `scrollTop + compensation - paddingTop`)
14978
+ * in the previous items and returns it with where it is now. If that row is gone, the first row after
14979
+ * it that is still there is kept instead, at the distance from the view's top it had; `null` when no row
14980
+ * from the one at the top onwards is left (or there is nothing to anchor to). Rows `canAnchor` rejects are
14981
+ * passed over the same way (edge rows such as a list's leading boundary, which new rows go below).
14982
+ */
14983
+ function findItemsAnchor({ prevItems, prevTree, prevPrependIndexes, nextItems, getKey, canAnchor, top }) {
14984
+ if (prevItems.length === 0 || nextItems.length === 0) return null;
14985
+ const nextIndexOfKey = /* @__PURE__ */ new Map();
14986
+ nextItems.forEach((item, index) => {
14987
+ nextIndexOfKey.set(getKey(item), index);
14988
+ });
14989
+ const topIndex = Math.min(Math.max(prevTree.getBound(top), 0), prevItems.length - 1);
14990
+ for (let index = topIndex; index < prevItems.length; ++index) {
14991
+ const item = prevItems[index];
14992
+ if (canAnchor !== void 0 && !canAnchor(item)) continue;
14993
+ const key = getKey(item);
14994
+ const nextIndex = nextIndexOfKey.get(key);
14995
+ if (nextIndex === void 0) continue;
14996
+ const prependIndexes = [];
14997
+ for (const prevIndex of prevPrependIndexes) {
14998
+ const item = prevItems[prevIndex];
14999
+ const moved = item === void 0 ? void 0 : nextIndexOfKey.get(getKey(item));
15000
+ if (moved !== void 0) prependIndexes.push(moved);
15001
+ }
15002
+ return {
15003
+ key,
15004
+ delta: top - prevTree.sum(index),
15005
+ index: nextIndex,
15006
+ prependIndexes
15007
+ };
15008
+ }
15009
+ return null;
15010
+ }
15011
+ /**
15012
+ * The range to render with the new items: from the anchor row, as many rows as `start..end` held (none if
15013
+ * it was empty), clamped to `itemCount` items. It starts at the anchor row, not at the new index of the old
15014
+ * start: the rows above the anchor are not mounted in this render. When the view's top is above the anchor
15015
+ * row (the row at the top was removed), the range update that follows mounts the rows above as rows
15016
+ * entering above the range, so their first measurement is compensated like when scrolling up.
15017
+ */
15018
+ function getAnchoredRange(start, end, anchorIndex, itemCount) {
15019
+ if (end < start) return [anchorIndex, anchorIndex - 1];
15020
+ return [anchorIndex, Math.min(anchorIndex + (end - start), itemCount - 1)];
15021
+ }
15022
+ //#endregion
15023
+ //#region src/components/virtual-list/hooks/use-event-callback.ts
15024
+ /** A stable function that calls the `fn` of the latest render. */
15025
+ function useEventCallback(fn) {
15026
+ const fnRef = useRef(fn);
15027
+ fnRef.current = fn;
15028
+ return useCallback((...args) => fnRef.current(...args), []);
15029
+ }
15030
+ //#endregion
15031
+ //#region src/components/virtual-list/hooks/use-latest-ref.ts
15032
+ /** A ref whose `current` is the value of the latest render. */
15033
+ function useLatestRef(value) {
15034
+ const ref = useRef(value);
15035
+ ref.current = value;
15036
+ return ref;
15037
+ }
15038
+ //#endregion
15039
+ //#region src/components/virtual-list/hooks/use-layout-effect-with-previous.ts
15040
+ /**
15041
+ * `useLayoutEffect(() => fn(previousDeps), deps)`: the layout-effect form of useMemoWithPrevious;
15042
+ * `fn` may return a cleanup.
15043
+ */
15044
+ function useLayoutEffectWithPrevious(fn, deps) {
15045
+ const previousRef = useRef(void 0);
15046
+ useLayoutEffect(() => {
15047
+ const cleanup = fn(previousRef.current);
15048
+ previousRef.current = deps;
15049
+ return cleanup;
15050
+ }, deps);
15051
+ }
15052
+ //#endregion
15053
+ //#region src/components/virtual-list/hooks/use-memo-with-previous.ts
15054
+ /**
15055
+ * `useMemo(() => fn(previousDeps), deps)`: runs `fn` while rendering whenever `deps` change, with the
15056
+ * deps of the last committed render (`undefined` before the first commit).
15057
+ *
15058
+ * The previous deps are recorded at commit, not inside the memo: React may call a memo's function
15059
+ * more than once for one render (StrictMode does on purpose) or throw a render away, and either
15060
+ * would otherwise pass this render's own deps as `previous`.
15061
+ */
15062
+ function useMemoWithPrevious(fn, deps) {
15063
+ const previousRef = useRef(void 0);
15064
+ const previous = previousRef.current;
15065
+ useMemo(() => {
15066
+ fn(previous);
15067
+ }, deps);
15068
+ useLayoutEffect(() => {
15069
+ previousRef.current = deps;
15070
+ });
15071
+ }
15072
+ //#endregion
15073
+ //#region src/components/virtual-list/hooks/use-merged-ref.ts
15074
+ /**
15075
+ * Merges refs into one setter. Returns `[setRef, getRef]`: `setRef(el)` stores `el` and passes it to
15076
+ * every ref; `getRef()` reads the stored element. When a ref changes between renders (checked while
15077
+ * rendering), the old one is cleared and the new one gets the stored element at once. The setter
15078
+ * calls ref callbacks itself, so what they return is ignored.
15079
+ */
15080
+ function useMergedRef(...refs) {
15081
+ const entries = useMemo(() => [], []);
15082
+ const elementRef = useRef(null);
15083
+ const getRef = useCallback(() => elementRef.current, []);
15084
+ const clearEntry = useCallback((entry) => {
15085
+ if (entry != null) {
15086
+ if (entry.type === "RefCallback") entry.ref(null);
15087
+ else entry.ref.current = null;
15088
+ }
15089
+ }, []);
15090
+ const applyStoredElement = useCallback((ref) => {
15091
+ if (typeof ref == "function") ref(getRef());
15092
+ else ref.current = getRef();
15093
+ }, [getRef]);
15094
+ const setRef = useCallback((el) => {
15095
+ elementRef.current = el;
15096
+ for (const entry of entries) if (entry == null) continue;
15097
+ else if (entry.type === "RefObject") entry.ref.current = el;
15098
+ else entry.ref(el);
15099
+ }, [entries]);
15100
+ for (let i = 0; i < refs.length; i++) {
15101
+ const ref = refs[i];
15102
+ const entry = entries[i];
15103
+ if (ref == null) {
15104
+ clearEntry(entry);
15105
+ entries[i] = null;
15106
+ } else {
15107
+ if (entry && entry.ref === ref) continue;
15108
+ if (typeof ref == "function") {
15109
+ if (entry != null) clearEntry(entry);
15110
+ entries[i] = {
15111
+ type: "RefCallback",
15112
+ ref
15113
+ };
15114
+ } else {
15115
+ if (entry != null) clearEntry(entry);
15116
+ entries[i] = {
15117
+ type: "RefObject",
15118
+ ref
15119
+ };
15120
+ }
15121
+ applyStoredElement(ref);
15122
+ }
15123
+ }
15124
+ for (let i = refs.length; i < entries.length; i++) {
15125
+ clearEntry(entries[i]);
15126
+ entries[i] = null;
15127
+ }
15128
+ return [setRef, getRef];
15129
+ }
15130
+ //#endregion
15131
+ //#region src/components/virtual-list/hooks/use-non-passive-wheel.ts
15132
+ /**
15133
+ * Adds a non-passive `wheel` listener (so it may call `preventDefault`) to the element `getTarget`
15134
+ * returns, in a layout effect, only while `enabled` (a non-passive listener can hold up scrolling, so
15135
+ * none is added when it would not be used).
15136
+ */
15137
+ function useNonPassiveWheel(getTarget, listener, enabled) {
15138
+ useLayoutEffect(() => {
15139
+ if (!enabled) return;
15140
+ const target = getTarget();
15141
+ if (target != null) target.addEventListener("wheel", listener, { passive: false });
15142
+ return () => {
15143
+ if (target != null) target.removeEventListener("wheel", listener);
15144
+ };
15145
+ }, [
15146
+ getTarget,
15147
+ listener,
15148
+ enabled
15149
+ ]);
15150
+ }
15151
+ //#endregion
15152
+ //#region src/components/virtual-list/ItemColumns.tsx
15153
+ const ColumnsContext = createContext(null);
15154
+ /**
15155
+ * Renders the item's columns in the current column range: `renderItemWithCols` once, else
15156
+ * `renderCol` for each column.
15157
+ */
15158
+ function ItemColumns(props) {
15159
+ const { index, item } = props;
15160
+ const context = useContext(ColumnsContext);
15161
+ if (!context) return null;
15162
+ const { startIndex, endIndex, columns, renderCol, renderItemWithCols, getLeft } = context;
15163
+ if (renderItemWithCols != null) return renderItemWithCols({
15164
+ itemIndex: index,
15165
+ startColIndex: startIndex,
15166
+ endColIndex: endIndex,
15167
+ allColumns: columns,
15168
+ item,
15169
+ getLeft
15170
+ });
15171
+ if (renderCol != null) {
15172
+ const cols = [];
15173
+ for (let i = startIndex; i <= endIndex; ++i) {
15174
+ const column = columns[i];
15175
+ cols.push(renderCol({
15176
+ column,
15177
+ left: getLeft(i),
15178
+ item,
15179
+ key: i
15180
+ }));
15181
+ }
15182
+ return cols;
15183
+ }
15184
+ return null;
15185
+ }
15186
+ /**
15187
+ * An iPhone, iPad or iPod, or an iPad that reports itself as a Mac with touch points
15188
+ * (`navigator.platform` is deprecated, but it still tells iPadOS from macOS here).
15189
+ */
15190
+ const isIOS = !!(typeof document !== "undefined" && typeof window !== "undefined") && (/iPad|iPhone|iPod/.test(navigator.platform) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) && !window.MSStream;
15191
+ let coarsePointerCache;
15192
+ let devicePixelRatioCache;
15193
+ /** Whether the primary pointer is coarse (a touch screen); read once. */
15194
+ function isCoarsePointer() {
15195
+ if (coarsePointerCache === void 0) coarsePointerCache = "matchMedia" in window && window.matchMedia("(pointer:coarse)").matches;
15196
+ return coarsePointerCache;
15197
+ }
15198
+ /**
15199
+ * What wheel deltas are divided by: `devicePixelRatio` in Chromium (`"chrome" in window`), else 1;
15200
+ * read once.
15201
+ */
15202
+ function getWheelDeltaScale() {
15203
+ if (typeof document === "undefined") return 1;
15204
+ if (devicePixelRatioCache === void 0) devicePixelRatioCache = "chrome" in window ? window.devicePixelRatio : 1;
15205
+ return devicePixelRatioCache;
15206
+ }
15207
+ /**
15208
+ * Makes a runner that runs a callback in the next animation frame. Each runner requests one frame at
15209
+ * a time: a callback given before it fires replaces the previous one. One per list, so lists never
15210
+ * replace each other's callbacks.
15211
+ */
15212
+ function createLatestInNextFrame() {
15213
+ let nextFrameCallback;
15214
+ let nextFrameHandle;
15215
+ return (callback) => {
15216
+ nextFrameCallback = callback;
15217
+ if (nextFrameHandle === void 0) nextFrameHandle = requestAnimationFrame(() => {
15218
+ nextFrameHandle = void 0;
15219
+ nextFrameCallback?.();
15220
+ });
15221
+ };
15222
+ }
15223
+ //#endregion
15224
+ //#region src/components/virtual-list/utils/align.ts
15225
+ /**
15226
+ * The `scrollTop` that puts an item (its top `itemTop` in the list's content, its height `itemSize`) at
15227
+ * `align` in a view `viewportHeight` high, inside the margins: its top `scrollMarginTop` below the view's
15228
+ * top (`"start"`), its bottom `scrollMarginBottom` above the view's bottom (`"end"`), or its middle in the
15229
+ * middle of the area between them (`"center"`). Clamped to `0 .. maxScrollTop`.
15230
+ */
15231
+ function getAlignedScrollTop({ itemTop, itemSize, viewportHeight, align, scrollMarginTop, scrollMarginBottom, maxScrollTop }) {
15232
+ let top;
15233
+ if (align === "start") top = itemTop - scrollMarginTop;
15234
+ else if (align === "end") top = itemTop + itemSize - viewportHeight + scrollMarginBottom;
15235
+ else {
15236
+ const area = viewportHeight - scrollMarginTop - scrollMarginBottom;
15237
+ top = itemTop + itemSize / 2 - scrollMarginTop - area / 2;
15238
+ }
15239
+ return Math.max(0, Math.min(top, Math.max(0, maxScrollTop)));
15240
+ }
15241
+ //#endregion
15242
+ //#region src/components/virtual-list/utils/measure.ts
15243
+ /**
15244
+ * Where each in-flow row starts in the visible-items element `container`, and where the rows end: in one
15245
+ * pass of reads, no writes, so the browser lays out at most once.
15246
+ *
15247
+ * `starts[i]` is the top of the border box of `rows[i]` (in document order), relative to the container's
15248
+ * padding edge; `end` is the container's inner height. The container is a block formatting context
15249
+ * (`display: flow-root`, see `constants.ts`) and `position: relative`, so it is the rows' offsetParent, the
15250
+ * first row's top margin and the last row's bottom margin stay inside it, and between two rows sits their
15251
+ * collapsed margin, whatever the consumer's CSS (a child's margins collapsing through a row included).
15252
+ *
15253
+ * Read from the boxes' rects (sub-pixel, so a span does not change with the rounding of its position), but
15254
+ * checked against the layout's own `offsetTop` / `clientHeight` (whole pixels, and blind to transforms):
15255
+ * where they disagree by more than a pixel, a transform is at work (the row's own, say an entrance
15256
+ * animation, or a scale on an ancestor, say a dialog zooming in) and the layout's value is used, since
15257
+ * the rows are laid out, and measured again on resize, without it.
15258
+ *
15259
+ * A row that is not laid out (`display: none`, so no offsetParent) takes no space: it starts where the
15260
+ * next one does.
15261
+ */
15262
+ function measureRowStarts(container, rows) {
15263
+ const frame = readFrame(container);
15264
+ const starts = rows.map((row) => readRowStart(frame, row));
15265
+ let next = frame.end;
15266
+ for (let i = starts.length - 1; i >= 0; --i) next = starts[i] ??= next;
15267
+ return {
15268
+ starts,
15269
+ end: frame.end
15270
+ };
15271
+ }
15272
+ /** Where `row` starts in `container` (see `measureRowStarts`); 0 when it is not laid out. */
15273
+ function measureRowStart(container, row) {
15274
+ return readRowStart(readFrame(container), row) ?? 0;
15275
+ }
15276
+ function readFrame(container) {
15277
+ const rect = container.getBoundingClientRect();
15278
+ const layoutHeight = container.offsetHeight;
15279
+ const scaled = Math.abs(rect.height - layoutHeight) > 1;
15280
+ const borderY = layoutHeight - container.clientHeight;
15281
+ return {
15282
+ container,
15283
+ scaled,
15284
+ innerTop: rect.top + container.clientTop,
15285
+ end: scaled ? container.clientHeight : toLayoutUnit(rect.height - borderY)
15286
+ };
15287
+ }
15288
+ function readRowStart({ container, scaled, innerTop }, row) {
15289
+ if (row.offsetParent !== container) return null;
15290
+ const layoutTop = row.offsetTop;
15291
+ if (scaled) return layoutTop;
15292
+ const rectTop = toLayoutUnit(row.getBoundingClientRect().top - innerTop);
15293
+ return Math.abs(rectTop - layoutTop) > 1 ? layoutTop : rectTop;
15294
+ }
15295
+ /**
15296
+ * The space each of `rows` takes: from where it starts to where the next one starts, the last one to the
15297
+ * end of the rows (see `measureRowStarts`). So the collapsed margin between two rows belongs to the upper
15298
+ * one, and the spans add up to the rows' laid-out height from the first row's border box on. `firstStart`
15299
+ * is where the first row starts (its top margin, plus the margins of its first children that collapse
15300
+ * through it): space before the rows that no span holds (the list keeps it apart, see VirtualList's
15301
+ * `leadingMarginRef` and `applyLayoutStyles`).
15302
+ */
15303
+ function measureRowSpans(container, rows) {
15304
+ const { starts, end } = measureRowStarts(container, rows);
15305
+ return {
15306
+ spans: starts.map((start, i) => (i + 1 < starts.length ? starts[i + 1] : end) - start),
15307
+ firstStart: starts[0] ?? 0
15308
+ };
15309
+ }
15310
+ /**
15311
+ * Rounded to 1/64px, the unit browsers lay out in: rect differences carry floating-point noise (with page
15312
+ * zoom), and a size that differs from the cached one by noise alone would count as a resize.
15313
+ */
15314
+ function toLayoutUnit(value) {
15315
+ return Math.round(value * 64) / 64;
15316
+ }
15317
+ //#endregion
15318
+ //#region src/components/virtual-list/utils/range.ts
15319
+ /**
15320
+ * The items to render: from the item at `scrollTop - paddingTop` through as many items as fit in
15321
+ * `listHeight` at their minimum size, plus one (no overscan). Empty (`0..-1`) before the list has been
15322
+ * measured or when there are no items.
15323
+ */
15324
+ function getVerticalRange({ fenwickTree, scrollTop, listHeight, itemMinSize, itemCount, paddingTop }) {
15325
+ if (listHeight === void 0 || itemCount === 0) return {
15326
+ startIndex: 0,
15327
+ endIndex: -1
15328
+ };
15329
+ const startIndex = Math.max(fenwickTree.getBound(scrollTop - paddingTop), 0);
15330
+ return {
15331
+ startIndex,
15332
+ endIndex: Math.min(startIndex + Math.ceil(listHeight / itemMinSize + 1), itemCount - 1)
15333
+ };
15334
+ }
15335
+ /** The columns to render: the ones in `scrollLeft .. scrollLeft + listWidth`, plus one on each side. */
15336
+ function getHorizontalRange({ xFenwickTree, scrollLeft, listWidth, columnCount }) {
15337
+ if (xFenwickTree === null || columnCount === 0) return {
15338
+ startIndex: 0,
15339
+ endIndex: 0
15340
+ };
15341
+ else return {
15342
+ startIndex: Math.max(xFenwickTree.getBound(scrollLeft) - 1, 0),
15343
+ endIndex: Math.min(xFenwickTree.getBound(scrollLeft + listWidth) + 1, columnCount - 1)
15344
+ };
15345
+ }
15346
+ /** Whether `a` and `b` have the same length and every key of `a` is in `b`. */
15347
+ function haveSameKeys(a, b) {
15348
+ if (a.length !== b.length) return false;
15349
+ for (const key of a) if (!b.includes(key)) return false;
15350
+ return true;
15351
+ }
15352
+ /** Whether `el` or one of its ancestors is hidden with an inline `display: none`. */
15353
+ function isHiddenByDisplayNone(el) {
15354
+ let current = el;
15355
+ while (current !== null) {
15356
+ if (current.style.display === "none") return true;
15357
+ current = current.parentElement;
15358
+ }
15359
+ return false;
15360
+ }
15361
+ function px(value) {
15362
+ if (value !== void 0) return `${value}px`;
15363
+ }
15364
+ //#endregion
15365
+ //#region src/components/virtual-list/resize-observer/resize-observer-delegate.ts
15366
+ /**
15367
+ * Observes elements with one ResizeObserver, created on the first `observe()`, and calls each
15368
+ * element's own callback. Entries whose target is detached (no `parentElement`) are ignored.
15369
+ * `runAfterEntries(fn)` (from an element's callback) runs `fn` once after every entry of the current
15370
+ * notification has been delivered: VirtualList measures all of a list's rows once per notification,
15371
+ * not once per row.
15372
+ */
15373
+ var ResizeObserverDelegate = class {
15374
+ observer = void 0;
15375
+ callbacksMap = /* @__PURE__ */ new Map();
15376
+ observedDomSet = /* @__PURE__ */ new WeakSet();
15377
+ afterEntries = /* @__PURE__ */ new Set();
15378
+ /** The shared observer, created on first use; `null` without a native ResizeObserver. */
15379
+ ensureObserver() {
15380
+ if (this.observer === void 0) this.observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(this.callback.bind(this));
15381
+ return this.observer;
15382
+ }
15383
+ callback(entries) {
15384
+ for (const entry of entries) {
15385
+ if (!entry.target.parentElement) continue;
15386
+ const callback = this.callbacksMap.get(entry.target);
15387
+ if (callback) callback(entry);
15388
+ }
15389
+ const afterEntries = [...this.afterEntries];
15390
+ this.afterEntries.clear();
15391
+ for (const fn of afterEntries) fn();
15392
+ }
15393
+ runAfterEntries(fn) {
15394
+ this.afterEntries.add(fn);
15395
+ }
15396
+ observe(el, callback) {
15397
+ this.callbacksMap.set(el, callback);
15398
+ if (!this.observedDomSet.has(el)) {
15399
+ this.ensureObserver()?.observe(el);
15400
+ this.observedDomSet.add(el);
15401
+ }
15402
+ }
15403
+ unobserve(el) {
15404
+ this.callbacksMap.delete(el);
15405
+ if (this.observedDomSet.has(el)) {
15406
+ this.ensureObserver()?.unobserve(el);
15407
+ this.observedDomSet.delete(el);
15408
+ }
15409
+ }
15410
+ };
15411
+ let resizeObserverDelegate;
15412
+ /** The shared delegate, created on first use. */
15413
+ function getResizeObserverDelegate() {
15414
+ resizeObserverDelegate ||= new ResizeObserverDelegate();
15415
+ return resizeObserverDelegate;
15416
+ }
15417
+ //#endregion
15418
+ //#region src/components/virtual-list/resize-observer/ResizeObserverWrapper.tsx
15419
+ /**
15420
+ * Calls `children({ ref })` and observes the element `ref` receives. `onRefUpdate` runs synchronously
15421
+ * whenever the ref is set (VirtualList measures a new item there, before paint), and again in a
15422
+ * layout effect when `simulateRefUpdateTrigger` differs from its first value; `onResize` runs from the
15423
+ * ResizeObserver, with `isFirst` for its first call (again after re-enabling). `disabled` stops
15424
+ * observing; `onUnmounted` runs in a layout-effect cleanup.
15425
+ */
15426
+ function ResizeObserverWrapper(props) {
15427
+ const { disabled, onResize, children, onRefUpdate, forwardedRef, simulateRefUpdateTrigger, onUnmounted } = props;
15428
+ const [setRef, getRef] = useMergedRef(forwardedRef);
15429
+ const isFirstResizeRef = useRef(true);
15430
+ const prevSimulateTriggerRef = useRef(simulateRefUpdateTrigger);
15431
+ const emitRefUpdate = useEventCallback(() => {
15432
+ onRefUpdate?.(getRef());
15433
+ });
15434
+ useLayoutEffect(() => {
15435
+ if (prevSimulateTriggerRef.current !== simulateRefUpdateTrigger) emitRefUpdate();
15436
+ }, [simulateRefUpdateTrigger, emitRefUpdate]);
15437
+ const handleResize = useEventCallback((entry) => {
15438
+ if (!disabled) onResize({
15439
+ entry,
15440
+ isFirst: isFirstResizeRef.current
15441
+ });
15442
+ isFirstResizeRef.current = false;
15443
+ });
15444
+ useLayoutEffect(() => {
15445
+ const el = getRef();
15446
+ if (el != null) {
15447
+ if (disabled) {
15448
+ getResizeObserverDelegate().unobserve(el);
15449
+ isFirstResizeRef.current = true;
15450
+ } else {
15451
+ getResizeObserverDelegate().observe(el, handleResize);
15452
+ return () => {
15453
+ getResizeObserverDelegate().unobserve(el);
15454
+ };
15455
+ }
15456
+ }
15457
+ }, [
15458
+ disabled,
15459
+ getRef,
15460
+ handleResize
15461
+ ]);
15462
+ const emitUnmounted = useEventCallback(() => {
15463
+ onUnmounted?.();
15464
+ });
15465
+ useLayoutEffect(() => () => {
15466
+ emitUnmounted();
15467
+ }, [emitUnmounted]);
15468
+ return children({ ref: useEventCallback((el) => {
15469
+ const previous = getRef();
15470
+ setRef(el);
15471
+ onRefUpdate?.(el);
15472
+ if (disabled) {
15473
+ if (previous != null) getResizeObserverDelegate().unobserve(previous);
15474
+ } else if (el === null) {
15475
+ if (previous !== null) getResizeObserverDelegate().unobserve(previous);
15476
+ } else {
15477
+ if (previous !== null && previous !== el) getResizeObserverDelegate().unobserve(previous);
15478
+ getResizeObserverDelegate().observe(el, handleResize);
15479
+ }
15480
+ }) });
15481
+ }
15482
+ //#endregion
15483
+ //#region src/components/virtual-list/hooks/use-ios-momentum-compensation.ts
15484
+ /**
15485
+ * On iOS, writing `scrollTop` during momentum scrolling stops the fling. So while a touch scroll is
15486
+ * active, size changes above the view are accumulated and applied as `translateY(-compensation)` on
15487
+ * the items element; they are written to `scrollTop` (flushed) one second after the finger lifted, at
15488
+ * the top or bottom edge, or on the next touchstart.
15489
+ */
15490
+ function useIosMomentumCompensation({ enabled, listElRef, itemsElRef, syncViewport, compensationYRef: iosCompYRef }) {
15491
+ const touchSessionActiveRef = useRef(false);
15492
+ const idleTimerRef = useRef(null);
15493
+ const scrollSuppressTimerRef = useRef(null);
15494
+ const forcedScrollTopRef = useRef(null);
15495
+ const touchEndedRef = useRef(true);
15496
+ const applyCompensationTransform = useEventCallback(() => {
15497
+ const itemsEl = itemsElRef.current;
15498
+ if (itemsEl) {
15499
+ const compensation = iosCompYRef.current;
15500
+ if (compensation === 0) itemsEl.style.transform = "";
15501
+ else itemsEl.style.transform = `translateY(${-compensation}px)`;
15502
+ }
15503
+ });
15504
+ const clearIdleTimer = useEventCallback(() => {
15505
+ if (idleTimerRef.current !== null) {
15506
+ clearTimeout(idleTimerRef.current);
15507
+ idleTimerRef.current = null;
15508
+ }
15509
+ });
15510
+ const startScrollSuppression = useEventCallback(() => {
15511
+ if (scrollSuppressTimerRef.current !== null) clearTimeout(scrollSuppressTimerRef.current);
15512
+ scrollSuppressTimerRef.current = setTimeout(() => {
15513
+ scrollSuppressTimerRef.current = null;
15514
+ forcedScrollTopRef.current = null;
15515
+ syncViewport();
15516
+ }, 200);
15517
+ });
15518
+ const flushCompensation = useEventCallback((reason) => {
15519
+ clearIdleTimer();
15520
+ const compensation = iosCompYRef.current;
15521
+ iosCompYRef.current = 0;
15522
+ touchSessionActiveRef.current = false;
15523
+ applyCompensationTransform();
15524
+ const listEl = listElRef.current;
15525
+ if (listEl && compensation !== 0) {
15526
+ const scrollTop = listEl.scrollTop + compensation;
15527
+ listEl.scrollTop = scrollTop;
15528
+ if (reason == "touchStart") {
15529
+ forcedScrollTopRef.current = scrollTop;
15530
+ startScrollSuppression();
15531
+ }
15532
+ }
15533
+ });
15534
+ const scheduleIdleFlush = useEventCallback(() => {
15535
+ clearIdleTimer();
15536
+ idleTimerRef.current = setTimeout(() => {
15537
+ idleTimerRef.current = null;
15538
+ if (touchEndedRef.current) flushCompensation("idleTimer");
15539
+ else scheduleIdleFlush();
15540
+ }, 1e3);
15541
+ });
15542
+ const handleTouchStart = useEventCallback(() => {
15543
+ touchEndedRef.current = false;
15544
+ if (touchSessionActiveRef.current) flushCompensation("touchStart");
15545
+ touchSessionActiveRef.current = true;
15546
+ scheduleIdleFlush();
15547
+ });
15548
+ const handleTouchEnd = useEventCallback(() => {
15549
+ touchEndedRef.current = true;
15550
+ });
15551
+ const handleScrollDuringTouch = useEventCallback(() => {
15552
+ if (touchSessionActiveRef.current) scheduleIdleFlush();
15553
+ });
15554
+ const clampCompensation = useEventCallback(() => {
15555
+ const listEl = listElRef.current;
15556
+ if (!listEl) return;
15557
+ const maxScrollTop = listEl.scrollHeight - listEl.clientHeight;
15558
+ iosCompYRef.current = Math.max(-listEl.scrollTop, Math.min(maxScrollTop - listEl.scrollTop, iosCompYRef.current));
15559
+ });
15560
+ const addCompensation = useEventCallback((deltaY) => {
15561
+ if (!enabled || !touchSessionActiveRef.current) return false;
15562
+ iosCompYRef.current += deltaY;
15563
+ clampCompensation();
15564
+ const listEl = listElRef.current;
15565
+ if (listEl) {
15566
+ if (listEl.scrollTop <= 0) {
15567
+ if (touchEndedRef.current) flushCompensation("scrollToTop");
15568
+ return true;
15569
+ }
15570
+ if (iosCompYRef.current > 0) {
15571
+ const maxScrollTop = listEl.scrollHeight - listEl.clientHeight;
15572
+ if (listEl.scrollTop + iosCompYRef.current >= maxScrollTop) {
15573
+ flushCompensation("overBottom");
15574
+ return true;
15575
+ }
15576
+ }
15577
+ }
15578
+ applyCompensationTransform();
15579
+ return true;
15580
+ });
15581
+ useLayoutEffect(() => {
15582
+ if (!enabled) return;
15583
+ const listEl = listElRef.current;
15584
+ if (!listEl) return;
15585
+ const itemsEl = itemsElRef.current;
15586
+ listEl.addEventListener("touchstart", handleTouchStart, { passive: true });
15587
+ listEl.addEventListener("touchend", handleTouchEnd, { passive: true });
15588
+ listEl.addEventListener("touchcancel", handleTouchEnd, { passive: true });
15589
+ listEl.addEventListener("scroll", handleScrollDuringTouch, { passive: true });
15590
+ return () => {
15591
+ listEl.removeEventListener("touchstart", handleTouchStart);
15592
+ listEl.removeEventListener("touchend", handleTouchEnd);
15593
+ listEl.removeEventListener("touchcancel", handleTouchEnd);
15594
+ listEl.removeEventListener("scroll", handleScrollDuringTouch);
15595
+ clearIdleTimer();
15596
+ if (scrollSuppressTimerRef.current !== null) {
15597
+ clearTimeout(scrollSuppressTimerRef.current);
15598
+ scrollSuppressTimerRef.current = null;
15599
+ forcedScrollTopRef.current = null;
15600
+ }
15601
+ if (iosCompYRef.current !== 0) {
15602
+ if (itemsEl) itemsEl.style.transform = "";
15603
+ listEl.scrollTop += iosCompYRef.current;
15604
+ iosCompYRef.current = 0;
15605
+ }
15606
+ touchSessionActiveRef.current = false;
15607
+ };
15608
+ }, [
15609
+ enabled,
15610
+ listElRef,
15611
+ itemsElRef,
15612
+ handleTouchStart,
15613
+ handleTouchEnd,
15614
+ handleScrollDuringTouch,
15615
+ clearIdleTimer,
15616
+ iosCompYRef
15617
+ ]);
15618
+ return {
15619
+ addCompensation,
15620
+ isScrollSuppressedWithForceRestore: useEventCallback((scrollTop) => {
15621
+ const suppressed = scrollSuppressTimerRef.current !== null;
15622
+ if (suppressed && listElRef.current && forcedScrollTopRef.current !== null && scrollTop === 0) listElRef.current.scrollTop = forcedScrollTopRef.current;
15623
+ return suppressed;
15624
+ })
15625
+ };
15626
+ }
15627
+ //#endregion
15628
+ //#region src/components/virtual-list/hooks/use-keyboard-scroll.ts
15629
+ /**
15630
+ * PageUp / PageDown / Space (Shift+Space up) scroll by the list's height minus `pageBottomOcclusion`
15631
+ * (what covers the bottom of the list, e.g. an input box) minus 32 px; Home / End and Cmd+Up / Cmd+Down
15632
+ * call `scrollTo({ position: "top" | "bottom" })`. Only keys pressed on the list itself (the scroll
15633
+ * container has focus) scroll it: a key pressed in a row (a button, a checkbox, a text field, a segmented
15634
+ * control) is left to that control, and so is a key a handler has already taken (`defaultPrevented`).
15635
+ */
15636
+ function useKeyboardScroll(scrollTo, { pageBottomOcclusion = 0 } = {}) {
15637
+ const occlusionRef = useRef(0);
15638
+ occlusionRef.current = pageBottomOcclusion;
15639
+ return { onKeyDown: useCallback((event) => {
15640
+ if (event.defaultPrevented || event.target !== event.currentTarget) return;
15641
+ if (event.key === "PageDown" || event.key === "PageUp" || event.key === " " || event.key === "Spacebar") {
15642
+ const page = Math.max(event.currentTarget.clientHeight - occlusionRef.current - 32, 0);
15643
+ if (page <= 0) return;
15644
+ event.preventDefault();
15645
+ event.currentTarget.scrollTop += event.key === "PageUp" || (event.key === " " || event.key === "Spacebar") && event.shiftKey ? -page : page;
15646
+ return;
15647
+ }
15648
+ let position = null;
15649
+ switch (event.key) {
15650
+ case "Home":
15651
+ position = "top";
15652
+ break;
15653
+ case "ArrowUp":
15654
+ if (event.metaKey) position = "top";
15655
+ break;
15656
+ case "End":
15657
+ position = "bottom";
15658
+ break;
15659
+ case "ArrowDown": if (event.metaKey) position = "bottom";
15660
+ }
15661
+ if (position) {
15662
+ event.preventDefault();
15663
+ scrollTo({ position });
15664
+ }
15665
+ }, [scrollTo]) };
15666
+ }
15667
+ //#endregion
15668
+ //#region src/components/virtual-list/hooks/use-non-virtual-content-resize.ts
15669
+ /**
15670
+ * While `nonVirtual`, observes the items element and calls `onContentResize` when it resizes (with
15671
+ * virtualization on, the list calls it from its own measurements).
15672
+ */
15673
+ function useNonVirtualContentResize(itemsElRef, onContentResize, nonVirtual) {
15674
+ const notifyContentResize = useEventCallback(() => {
15675
+ onContentResize?.();
15676
+ });
15677
+ useLayoutEffect(() => {
15678
+ const itemsEl = itemsElRef.current;
15679
+ if (itemsEl && nonVirtual) {
15680
+ getResizeObserverDelegate().observe(itemsEl, notifyContentResize);
15681
+ return () => {
15682
+ getResizeObserverDelegate().unobserve(itemsEl);
15683
+ };
15684
+ }
15685
+ }, [
15686
+ itemsElRef,
15687
+ notifyContentResize,
15688
+ nonVirtual
15689
+ ]);
15690
+ }
15691
+ //#endregion
15692
+ //#region src/components/virtual-list/hooks/use-scroll-anchor.ts
15693
+ /**
15694
+ * Finds the first child of `container` whose box crosses the top of `scroller` (a binary search over
15695
+ * `getBoundingClientRect()`) and saves it with its top in `anchorRef`, or null when there is none.
15696
+ */
15697
+ function snapshotAnchorElementStateAndSaveToRef(anchorRef, scroller, container) {
15698
+ const children = Array.from(container.children);
15699
+ const scrollerTop = scroller.getBoundingClientRect().top;
15700
+ let lo = 0;
15701
+ let hi = children.length - 1;
15702
+ let found = -1;
15703
+ let foundTop = 0;
15704
+ while (lo <= hi) {
15705
+ const mid = Math.floor((lo + hi) / 2);
15706
+ const rect = children[mid].getBoundingClientRect();
15707
+ if (rect.top <= scrollerTop && rect.bottom > scrollerTop) {
15708
+ found = mid;
15709
+ hi = mid - 1;
15710
+ foundTop = rect.top;
15711
+ } else lo = mid + 1;
15712
+ }
15713
+ if (found < 0) anchorRef.current = null;
15714
+ else {
15715
+ const element = children[found];
15716
+ if (element) anchorRef.current = {
15717
+ element,
15718
+ top: foundTop
15719
+ };
15720
+ else anchorRef.current = null;
15721
+ }
15722
+ }
15723
+ /**
15724
+ * `snapshotAnchorElementStateAndSaveToRef()` remembers the item at the top of the list;
15725
+ * `restoreScrollStateFromAnchor()` scrolls by how far it moved since; `clearAnchor()` forgets it.
15726
+ */
15727
+ function useScrollAnchor(listElRef, getVisibleItemsEl) {
15728
+ const anchorRef = useRef(null);
15729
+ return {
15730
+ snapshotAnchorElementStateAndSaveToRef: useCallback(() => {
15731
+ const visibleItemsEl = getVisibleItemsEl();
15732
+ if (listElRef.current && visibleItemsEl) snapshotAnchorElementStateAndSaveToRef(anchorRef, listElRef.current, visibleItemsEl);
15733
+ }, [listElRef, getVisibleItemsEl]),
15734
+ restoreScrollStateFromAnchor: useCallback(() => {
15735
+ if (!anchorRef.current) return;
15736
+ const moved = anchorRef.current.element.getBoundingClientRect().top - anchorRef.current.top;
15737
+ listElRef.current?.scrollBy(0, moved);
15738
+ }, [listElRef]),
15739
+ clearAnchor: useCallback(() => {
15740
+ anchorRef.current = null;
15741
+ }, [])
15742
+ };
15743
+ }
15744
+ //#endregion
15745
+ //#region src/components/virtual-list/VirtualListContext.ts
15746
+ const VirtualListContext = createContext(null);
15747
+ //#endregion
15748
+ //#region src/components/virtual-list/VirtualList.tsx
15749
+ /**
15750
+ * The most range updates one aligned jump goes through before it stops (each one mounts and measures the
15751
+ * rows the previous position brought into view; it is usually stable after 2-3).
15752
+ */
15753
+ const MAX_ALIGN_STEPS = 10;
15754
+ function VirtualList(props) {
15755
+ const { virtual = true, sessionId, showScrollbar = false, columns = EMPTY_ARRAY, renderCol, renderItemWithCols, items = EMPTY_ARRAY, itemMinSize, itemEstimatedSize, itemResizable = false, itemsStyle, visibleItemsTag = "div", visibleItemsProps, ignoreItemResize = false, onScroll, onWheel, onResize, defaultScrollKey, defaultScrollIndex, getKey, paddingTop = 0, paddingBottom = 0, children: renderItemChild, ItemComponent, empty, emptyAlign = "start", className, style, itemsClassName, footer, footerAfterBottomPadding, header, domRef, ref: _ref, onContentResize, onTransformChange, componentRef, printable, catchWheel = false, onRenderAnomaly, keyboardPageBottomOcclusion = 0, focusable = true, keepAnchorOnItemsChange = false, canAnchorItem, onKeyDown: onNativeKeyDown, ...nativeProps } = props;
15756
+ const listElRef = useRef(null);
15757
+ const [mergedListRefSetter] = useMergedRef(domRef, listElRef);
15758
+ const itemsElRef = useRef(null);
15759
+ const getVisibleItemsEl = useCallback(() => itemsElRef.current?.children[0] || null, []);
15760
+ const [[renderReason, renderCallback, renderVersion], setRenderState] = useState([
15761
+ null,
15762
+ null,
15763
+ 0
15764
+ ]);
15765
+ const viewportRef = useRef({
15766
+ listHeight: void 0,
15767
+ scrollTop: 0,
15768
+ scrollLeft: 0,
15769
+ listWidth: 0
15770
+ });
15771
+ const rangeRef = useRef({
15772
+ prependIndexes: [],
15773
+ verticalStartIndex: 0,
15774
+ verticalEndIndex: -1,
15775
+ horizontalStartIndex: 0,
15776
+ horizontalEndIndex: -1
15777
+ });
15778
+ /**
15779
+ * The rows kept mounted outside the range (absolutely positioned at their offsets): the rows holding
15780
+ * the text selection and the row holding focus (`focusedKeyRef`).
15781
+ */
15782
+ const keptKeysRef = useRef([]);
15783
+ /** The key of the row that holds focus (`document.activeElement` is in it), tracked by focusin / focusout. */
15784
+ const focusedKeyRef = useRef(null);
15785
+ const keyToHeightOffsetRef = useRef(/* @__PURE__ */ new Map());
15786
+ const leadingMarginRef = useRef(0);
15787
+ /**
15788
+ * Where the first mounted row in flow starts in the visible-items element (its top margin there,
15789
+ * since nothing above it is mounted), as last written by `applyLayoutStyles`.
15790
+ */
15791
+ const firstRowStartRef = useRef(0);
15792
+ const pendingScrollTaskRef = useRef(null);
15793
+ const pendingScrollTaskTimeoutRef = useRef(null);
15794
+ const pendingScrollTaskRafRef = useRef(null);
15795
+ const wheelScrollingRef = useRef(false);
15796
+ /** Clears `wheelScrollingRef` in the next frame; this list's own, so other lists cannot replace it. */
15797
+ const [runLatestInNextFrame] = useState(createLatestInNextFrame);
15798
+ /** The wheel is only taken over (catchWheel) where the pointer is not coarse. */
15799
+ const mayUseWheelRef = useRef(typeof document === "undefined" || !isCoarsePointer());
15800
+ const reportRenderAnomaly = useEventCallback((anomaly) => {
15801
+ onRenderAnomaly?.(anomaly);
15802
+ });
15803
+ const forcedRenderTimesRef = useRef([]);
15804
+ /**
15805
+ * The offset applied by the iOS compensation, created here (not in its hook) because
15806
+ * `keepAnchorOnItemsChange` reads it while rendering, before the hook is called.
15807
+ */
15808
+ const compensationYRef = useRef(0);
15809
+ /** The items, Fenwick tree and session of the last commit (the tree is updated in place by measurements). */
15810
+ const committedLayoutRef = useRef(null);
15811
+ const itemsAnchor = useMemo(() => {
15812
+ const committed = committedLayoutRef.current;
15813
+ const listEl = listElRef.current;
15814
+ if (!keepAnchorOnItemsChange || !virtual || committed === null || listEl === null || committed.items === items || committed.sessionId !== sessionId) return null;
15815
+ return findItemsAnchor({
15816
+ prevItems: committed.items,
15817
+ prevTree: committed.tree,
15818
+ prevPrependIndexes: rangeRef.current.prependIndexes,
15819
+ nextItems: items,
15820
+ getKey,
15821
+ canAnchor: canAnchorItem,
15822
+ top: listEl.scrollTop + compensationYRef.current - paddingTop - leadingMarginRef.current
15823
+ });
15824
+ }, [items]);
15825
+ /** The anchor whose range has been committed to `rangeRef` (so it is applied once). */
15826
+ const appliedItemsAnchorRef = useRef(null);
15827
+ const pendingItemsAnchor = itemsAnchor !== null && itemsAnchor !== appliedItemsAnchorRef.current ? itemsAnchor : null;
15828
+ let renderedRange = rangeRef.current;
15829
+ if (pendingItemsAnchor !== null) {
15830
+ const [verticalStartIndex, verticalEndIndex] = getAnchoredRange(renderedRange.verticalStartIndex, renderedRange.verticalEndIndex, pendingItemsAnchor.index, items.length);
15831
+ renderedRange = {
15832
+ ...renderedRange,
15833
+ prependIndexes: pendingItemsAnchor.prependIndexes,
15834
+ verticalStartIndex,
15835
+ verticalEndIndex
15836
+ };
15837
+ }
15838
+ const { prependIndexes, verticalStartIndex: startIndex, verticalEndIndex: endIndex, horizontalStartIndex: colStartIndex, horizontalEndIndex: colEndIndex } = renderedRange;
15839
+ const keyToIndexRef = useRef(void 0);
15840
+ const prevSessionIdRef = useRef(sessionId);
15841
+ const sessionChangedRef = useRef(false);
15842
+ const lastTransformSignatureRef = useRef(null);
15843
+ const clearPendingScrollTask = useCallback(() => {
15844
+ if (pendingScrollTaskTimeoutRef.current !== null) {
15845
+ window.clearTimeout(pendingScrollTaskTimeoutRef.current);
15846
+ pendingScrollTaskTimeoutRef.current = null;
15847
+ }
15848
+ if (pendingScrollTaskRafRef.current != null) {
15849
+ window.cancelAnimationFrame(pendingScrollTaskRafRef.current);
15850
+ pendingScrollTaskRafRef.current = null;
15851
+ }
15852
+ pendingScrollTaskRef.current = null;
15853
+ }, []);
15854
+ useMemo(() => {
15855
+ if (prevSessionIdRef.current === sessionId) return;
15856
+ prevSessionIdRef.current = sessionId;
15857
+ sessionChangedRef.current = true;
15858
+ clearPendingScrollTask();
15859
+ wheelScrollingRef.current = false;
15860
+ keptKeysRef.current = [];
15861
+ focusedKeyRef.current = null;
15862
+ keyToHeightOffsetRef.current.clear();
15863
+ leadingMarginRef.current = 0;
15864
+ keyToIndexRef.current = /* @__PURE__ */ new Map();
15865
+ rangeRef.current = {
15866
+ prependIndexes: [],
15867
+ verticalStartIndex: 0,
15868
+ verticalEndIndex: -1,
15869
+ horizontalStartIndex: 0,
15870
+ horizontalEndIndex: -1
15871
+ };
15872
+ const viewport = viewportRef.current;
15873
+ viewport.scrollTop = 0;
15874
+ viewport.scrollLeft = 0;
15875
+ const listEl = listElRef.current;
15876
+ if (listEl != null) {
15877
+ listEl.scrollTop = 0;
15878
+ listEl.scrollLeft = 0;
15879
+ }
15880
+ }, [sessionId, clearPendingScrollTask]);
15881
+ useMemo(() => {
15882
+ lastTransformSignatureRef.current = null;
15883
+ }, [sessionId]);
15884
+ useMemo(() => {
15885
+ const keyToIndex = /* @__PURE__ */ new Map();
15886
+ items.forEach((item, index) => {
15887
+ keyToIndex.set(getKey(item), index);
15888
+ });
15889
+ keyToIndexRef.current = keyToIndex;
15890
+ const keptKeys = [];
15891
+ keptKeysRef.current.forEach((key) => {
15892
+ if (keyToIndexRef.current.has(key)) keptKeys.push(key);
15893
+ });
15894
+ keptKeysRef.current = keptKeys;
15895
+ }, [
15896
+ sessionId,
15897
+ items,
15898
+ getKey
15899
+ ]);
15900
+ const totalColumnsWidth = useMemo(() => {
15901
+ if (renderCol == null && renderItemWithCols == null || columns.length === 0) return;
15902
+ let width = 0;
15903
+ columns.forEach((column) => {
15904
+ width += column.width;
15905
+ });
15906
+ return width;
15907
+ }, [
15908
+ sessionId,
15909
+ renderCol,
15910
+ renderItemWithCols,
15911
+ columns
15912
+ ]);
15913
+ /**
15914
+ * Rebuilt whenever the items or the session change: `itemEstimatedSize` for every item plus the
15915
+ * measured offsets cached by key, so measurements survive re-renders and reordering.
15916
+ */
15917
+ const fenwickTree = useMemo(() => {
15918
+ if (!virtual) return new FenwickTree(0, 0);
15919
+ const tree = new FenwickTree(items.length, itemEstimatedSize);
15920
+ const heightOffsets = keyToHeightOffsetRef.current;
15921
+ items.forEach((item, index) => {
15922
+ const key = getKey(item);
15923
+ const offset = heightOffsets.get(key);
15924
+ if (offset !== void 0) tree.add(index, offset);
15925
+ });
15926
+ return tree;
15927
+ }, [
15928
+ sessionId,
15929
+ items,
15930
+ itemEstimatedSize,
15931
+ getKey,
15932
+ virtual
15933
+ ]);
15934
+ const visibleItems = useMemo(() => {
15935
+ if (!virtual) return items;
15936
+ if (endIndex < startIndex) return [];
15937
+ const visible = [];
15938
+ const lastIndex = Math.min(endIndex, items.length - 1);
15939
+ for (let i = startIndex; i <= lastIndex; ++i) visible.push(items[i]);
15940
+ return visible;
15941
+ }, [
15942
+ sessionId,
15943
+ startIndex,
15944
+ endIndex,
15945
+ items,
15946
+ virtual
15947
+ ]);
15948
+ const xFenwickTree = useMemo(() => {
15949
+ if (columns.length === 0) return null;
15950
+ const tree = new FenwickTree(columns.length, 0);
15951
+ columns.forEach((column, index) => {
15952
+ tree.add(index, column.width);
15953
+ });
15954
+ return tree;
15955
+ }, [sessionId, columns]);
15956
+ const getColumnLeft = useEventCallback((index) => xFenwickTree !== null ? xFenwickTree.sum(index) : 0);
15957
+ const columnsContextValue = useMemo(() => ({
15958
+ startIndex: colStartIndex,
15959
+ endIndex: colEndIndex,
15960
+ columns,
15961
+ renderCol,
15962
+ renderItemWithCols,
15963
+ getLeft: getColumnLeft
15964
+ }), [
15965
+ colStartIndex,
15966
+ colEndIndex,
15967
+ columns,
15968
+ renderCol,
15969
+ renderItemWithCols,
15970
+ getColumnLeft
15971
+ ]);
15972
+ /** Where the rows start in the spacer's content: `paddingTop` plus the first row's top margin. */
15973
+ const getRowsTop = useEventCallback(() => paddingTop + leadingMarginRef.current);
15974
+ /**
15975
+ * The mounted rows in flow, in order: the measured elements of the rendered range. Kept rows (outside
15976
+ * the range, absolutely positioned) are left out: they take no space in the flow.
15977
+ */
15978
+ const getFlowRows = useEventCallback(() => {
15979
+ const rows = [];
15980
+ const visibleItemsEl = getVisibleItemsEl();
15981
+ if (visibleItemsEl === null) return rows;
15982
+ for (const el of Array.from(visibleItemsEl.children)) {
15983
+ const key = el.getAttribute(ITEM_KEY_ATTR);
15984
+ const index = key === null ? void 0 : keyToIndexRef.current.get(key);
15985
+ if (key !== null && index !== void 0 && index >= startIndex && index <= endIndex && el instanceof HTMLElement) rows.push({
15986
+ el,
15987
+ key,
15988
+ index
15989
+ });
15990
+ }
15991
+ return rows;
15992
+ });
15993
+ /**
15994
+ * Writes the layout without a render: the spacer height (the total size plus the first row's top
15995
+ * margin; a min-height with itemResizable, so the real content may exceed it) and the visible items'
15996
+ * translateY, with the CSS variables sticky children read (`--virtual-list-transform-y`,
15997
+ * `--virtual-list-ios-compensation-y`).
15998
+ *
15999
+ * Unlike the reference implementation (DeepSeek web): the translateY puts the border box of the first
16000
+ * mounted row at its offset (`firstIndex`, or the first row in the DOM), not the element's top. The visible-items element is a
16001
+ * block formatting context, so the first mounted row's top margin is inside it, above the row, and
16002
+ * does not collapse with the row before it (not mounted): the element starts that margin higher. The
16003
+ * collapsed gap above that row is already in the size of the row before it (see `leadingMarginRef`),
16004
+ * so the rows sit exactly where the tree has them whichever row is first, and moving the window's top
16005
+ * edge moves no row. Read before anything is written, so it forces no extra layout.
16006
+ */
16007
+ const applyLayoutStyles = useEventCallback((firstIndex) => {
16008
+ if (!virtual) return;
16009
+ let index = Math.min(firstIndex, items.length);
16010
+ let firstRowStart = 0;
16011
+ const itemsEl = itemsElRef.current;
16012
+ const visibleItemsEl = itemsEl?.children[0];
16013
+ const firstRow = itemResizable ? getFlowRows()[0] : void 0;
16014
+ if (firstRow !== void 0 && visibleItemsEl instanceof HTMLElement) {
16015
+ index = firstRow.index;
16016
+ firstRowStart = measureRowStart(visibleItemsEl, firstRow.el);
16017
+ }
16018
+ firstRowStartRef.current = firstRowStart;
16019
+ const leadingMargin = leadingMarginRef.current;
16020
+ if (itemsEl) {
16021
+ const height = px(fenwickTree.sum() + leadingMargin) || "";
16022
+ if (itemResizable) {
16023
+ itemsEl.style.height = "";
16024
+ itemsEl.style.minHeight = height;
16025
+ } else {
16026
+ const changed = itemsEl.style.height !== height || itemsEl.style.minHeight !== "";
16027
+ itemsEl.style.height = height;
16028
+ itemsEl.style.minHeight = "";
16029
+ if (changed) onContentResize?.();
16030
+ }
16031
+ }
16032
+ if (visibleItemsEl instanceof HTMLElement) {
16033
+ const offset = px(leadingMargin + fenwickTree.sum(index) - firstRowStart);
16034
+ visibleItemsEl.style.transform = `translateY(${offset})`;
16035
+ visibleItemsEl.style.setProperty("--virtual-list-transform-y", offset);
16036
+ const compensation = px(compensationYRef.current);
16037
+ visibleItemsEl.style.setProperty("--virtual-list-ios-compensation-y", compensation);
16038
+ const signature = `${index}|${offset}`;
16039
+ if (lastTransformSignatureRef.current !== signature) {
16040
+ lastTransformSignatureRef.current = signature;
16041
+ onTransformChange?.();
16042
+ }
16043
+ }
16044
+ });
16045
+ useLayoutEffect(() => {
16046
+ if (!virtual) {
16047
+ const itemsEl = itemsElRef.current;
16048
+ if (itemsEl) {
16049
+ itemsEl.style.height = "";
16050
+ itemsEl.style.minHeight = "";
16051
+ }
16052
+ }
16053
+ }, [virtual]);
16054
+ /**
16055
+ * The viewport sync. The range starts at the item at `scrollTop + compensation - paddingTop` and
16056
+ * holds as many items as fit at `itemMinSize`, plus one. Items holding the text selection, and the item
16057
+ * holding focus, stay
16058
+ * mounted ("kept"). When the new range is inside the old one, only the layout styles are written;
16059
+ * otherwise the items entering above the old start are recorded (`prependIndexes`) and the range is
16060
+ * rendered with flushSync, now or in a microtask (`deferRenderToMicrotask`). At 120 forced renders
16061
+ * within a second a "renderThrashing" anomaly is reported. `afterRender` runs after the layout styles
16062
+ * of the new range are applied.
16063
+ */
16064
+ const updateRange = useEventCallback((reason, deferRenderToMicrotask, afterRender) => {
16065
+ if (!virtual) return;
16066
+ const listEl = listElRef.current;
16067
+ if (listEl == null) return;
16068
+ const viewport = viewportRef.current;
16069
+ if (viewport.listHeight === void 0) {
16070
+ applyLayoutStyles(startIndex);
16071
+ afterRender?.();
16072
+ return;
16073
+ }
16074
+ const scrollTop = listEl.scrollTop;
16075
+ const effectiveScrollTop = scrollTop + compensationYRef.current;
16076
+ const scrollLeft = listEl.scrollLeft;
16077
+ const range = rangeRef.current;
16078
+ const prevRange = {
16079
+ startIndex: range.verticalStartIndex,
16080
+ endIndex: range.verticalEndIndex
16081
+ };
16082
+ const nextRange = getVerticalRange({
16083
+ fenwickTree,
16084
+ scrollTop: effectiveScrollTop,
16085
+ listHeight: viewport.listHeight,
16086
+ itemMinSize,
16087
+ itemCount: items.length,
16088
+ paddingTop: getRowsTop()
16089
+ });
16090
+ const rangeChanged = prevRange.startIndex !== nextRange.startIndex || prevRange.endIndex !== nextRange.endIndex;
16091
+ const nextInsidePrev = nextRange.startIndex >= prevRange.startIndex && prevRange.endIndex >= nextRange.endIndex;
16092
+ const prevColRange = {
16093
+ startIndex: range.horizontalStartIndex,
16094
+ endIndex: range.horizontalEndIndex
16095
+ };
16096
+ const nextColRange = getHorizontalRange({
16097
+ xFenwickTree,
16098
+ scrollLeft,
16099
+ listWidth: viewport.listWidth,
16100
+ columnCount: columns.length
16101
+ });
16102
+ const colRangeChanged = prevColRange.startIndex !== nextColRange.startIndex || prevColRange.endIndex !== nextColRange.endIndex;
16103
+ viewport.scrollTop = scrollTop;
16104
+ viewport.scrollLeft = scrollLeft;
16105
+ let keptKeysChanged = false;
16106
+ if (typeof window !== "undefined" && reason !== "sessionChanged") {
16107
+ const { startIndex: nextStart, endIndex: nextEnd } = nextRange;
16108
+ const keptKeys = [];
16109
+ const keep = (key) => {
16110
+ const index = keyToIndexRef.current.get(key);
16111
+ if (index !== void 0 && (!(index >= nextStart) || !(index <= nextEnd)) && !keptKeys.includes(key)) keptKeys.push(key);
16112
+ };
16113
+ const focusedKey = focusedKeyRef.current;
16114
+ if (focusedKey !== null) {
16115
+ const active = document.activeElement;
16116
+ if (active !== null && listEl.contains(active)) keep(focusedKey);
16117
+ else focusedKeyRef.current = null;
16118
+ }
16119
+ const selection = window.getSelection();
16120
+ if (selection != null && !selection.isCollapsed && selection.rangeCount > 0) listEl.querySelectorAll(`[${ITEM_KEY_ATTR}]`).forEach((itemEl) => {
16121
+ if (!selection.containsNode(itemEl, true) && itemEl.getElementsByTagName("input").length !== 0) return;
16122
+ const key = itemEl.getAttribute(ITEM_KEY_ATTR);
16123
+ if (key !== null) keep(key);
16124
+ });
16125
+ if (!haveSameKeys(keptKeys, keptKeysRef.current)) {
16126
+ keptKeysRef.current = keptKeys;
16127
+ keptKeysChanged = true;
16128
+ }
16129
+ }
16130
+ if (reason !== "sessionChanged" && !keptKeysChanged && (!rangeChanged || nextInsidePrev) && !colRangeChanged) {
16131
+ if (nextInsidePrev) applyLayoutStyles(prevRange.startIndex);
16132
+ else applyLayoutStyles(nextRange.startIndex);
16133
+ afterRender?.();
16134
+ return;
16135
+ }
16136
+ if (reason !== "sessionChanged") {
16137
+ const entering = [];
16138
+ if (pendingScrollTaskRef.current?.type === void 0 && nextRange.endIndex >= prevRange.startIndex) for (let i = nextRange.startIndex; i < prevRange.startIndex; ++i) entering.push(i);
16139
+ range.prependIndexes = entering;
16140
+ } else range.prependIndexes = [];
16141
+ range.verticalStartIndex = nextRange.startIndex;
16142
+ range.verticalEndIndex = nextRange.endIndex;
16143
+ range.horizontalStartIndex = nextColRange.startIndex;
16144
+ range.horizontalEndIndex = nextColRange.endIndex;
16145
+ const now = Date.now();
16146
+ const renderTimes = forcedRenderTimesRef.current;
16147
+ renderTimes.push(now);
16148
+ const windowStart = now - RENDER_THRASHING_WINDOW_MS;
16149
+ while (renderTimes.length > 0 && renderTimes[0] < windowStart) renderTimes.shift();
16150
+ if (renderTimes.length >= 120) {
16151
+ reportRenderAnomaly({
16152
+ type: "renderThrashing",
16153
+ message: `${renderTimes.length} forced renders within ${RENDER_THRASHING_WINDOW_MS}ms`,
16154
+ payload: {
16155
+ renderCount: renderTimes.length,
16156
+ windowMs: RENDER_THRASHING_WINDOW_MS,
16157
+ triggerReason: reason,
16158
+ itemCount: items.length
16159
+ }
16160
+ });
16161
+ renderTimes.length = 0;
16162
+ }
16163
+ if (deferRenderToMicrotask) Promise.resolve().then(() => {
16164
+ flushSync(() => {
16165
+ setRenderState((state) => [
16166
+ reason,
16167
+ afterRender,
16168
+ state[2] + 1
16169
+ ]);
16170
+ });
16171
+ });
16172
+ else flushSync(() => {
16173
+ setRenderState((state) => [
16174
+ reason,
16175
+ afterRender,
16176
+ state[2] + 1
16177
+ ]);
16178
+ });
16179
+ });
16180
+ /**
16181
+ * A pending scroll task (to the top, the bottom, an index, or a custom task) stays armed for one
16182
+ * animation frame plus one task, so that item sizes measured right after the jump replay it instead
16183
+ * of being compensated.
16184
+ */
16185
+ const schedulePendingScrollTaskExpiry = useCallback(() => {
16186
+ pendingScrollTaskRafRef.current = requestAnimationFrame(() => {
16187
+ pendingScrollTaskRafRef.current = null;
16188
+ pendingScrollTaskTimeoutRef.current = window.setTimeout(() => {
16189
+ pendingScrollTaskRef.current = null;
16190
+ pendingScrollTaskTimeoutRef.current = null;
16191
+ });
16192
+ });
16193
+ }, []);
16194
+ const scrollToPosition = useEventCallback((left, top, behavior) => {
16195
+ listElRef.current?.scrollTo({
16196
+ left,
16197
+ top,
16198
+ behavior
16199
+ });
16200
+ });
16201
+ /**
16202
+ * Scrolls to the offset of `index` in the Fenwick tree (an estimate for items not measured yet);
16203
+ * an "instant" jump is armed as the pending task, to be replayed after measurements. `ensureVisibleOnly`
16204
+ * (the `debounce` option) scrolls only as far as needed to show the item. With virtualization off the
16205
+ * offset is read from the DOM (`getBoundingClientRect` of the index-th child).
16206
+ */
16207
+ const scrollToIndex = useEventCallback((index, behavior, ensureVisibleOnly, isReplay, scrollMarginTop = 0, scrollMarginBottom = 0) => {
16208
+ if (!virtual) {
16209
+ const listEl = listElRef.current;
16210
+ const itemsEl = itemsElRef.current;
16211
+ if (!itemsEl || !listEl) return;
16212
+ const visibleItemsEl = itemsEl.firstElementChild;
16213
+ if (!visibleItemsEl) return;
16214
+ const itemEl = visibleItemsEl.children.item(index);
16215
+ if (!(itemEl instanceof HTMLElement)) return;
16216
+ const listRect = listEl.getBoundingClientRect();
16217
+ const itemRect = itemEl.getBoundingClientRect();
16218
+ const itemTop = itemRect.top - listRect.top + listEl.scrollTop;
16219
+ if (ensureVisibleOnly) {
16220
+ const { scrollTop, offsetHeight } = listEl;
16221
+ const itemHeight = itemRect.height;
16222
+ if (itemTop > scrollTop) {
16223
+ if (!(itemTop + itemHeight <= scrollTop + offsetHeight)) listEl.scrollTo({
16224
+ left: 0,
16225
+ top: itemTop + itemHeight - offsetHeight + scrollMarginBottom,
16226
+ behavior
16227
+ });
16228
+ } else listEl.scrollTo({
16229
+ left: 0,
16230
+ top: itemTop - scrollMarginTop,
16231
+ behavior
16232
+ });
16233
+ } else listEl.scrollTo({
16234
+ left: 0,
16235
+ top: itemTop,
16236
+ behavior
16237
+ });
16238
+ return;
16239
+ }
16240
+ const targetTop = fenwickTree.sum(index) + getRowsTop();
16241
+ if (!isReplay) {
16242
+ clearPendingScrollTask();
16243
+ if (behavior === "instant") {
16244
+ pendingScrollTaskRef.current = {
16245
+ type: "index",
16246
+ index,
16247
+ debounce: ensureVisibleOnly
16248
+ };
16249
+ schedulePendingScrollTaskExpiry();
16250
+ }
16251
+ }
16252
+ if (ensureVisibleOnly) {
16253
+ const listEl = listElRef.current;
16254
+ if (listEl) {
16255
+ const { scrollTop, offsetHeight } = listEl;
16256
+ if (targetTop > scrollTop) {
16257
+ const itemSize = fenwickTree.get(index);
16258
+ if (!(targetTop + itemSize <= scrollTop + offsetHeight)) {
16259
+ listEl.scrollTo({
16260
+ left: 0,
16261
+ top: targetTop + itemSize - offsetHeight + scrollMarginBottom,
16262
+ behavior
16263
+ });
16264
+ updateRange("listScroll", true, null);
16265
+ }
16266
+ } else {
16267
+ listEl.scrollTo({
16268
+ left: 0,
16269
+ top: targetTop - scrollMarginTop,
16270
+ behavior
16271
+ });
16272
+ updateRange("listScroll", true, null);
16273
+ }
16274
+ }
16275
+ } else {
16276
+ listElRef.current?.scrollTo({
16277
+ left: 0,
16278
+ top: targetTop,
16279
+ behavior
16280
+ });
16281
+ updateRange("listScroll", true, null);
16282
+ }
16283
+ });
16284
+ /**
16285
+ * Measures the mounted rows in flow from layout, synchronously, and writes the sizes that changed into
16286
+ * the Fenwick tree and the key -> offset cache, and the first row's top margin when the first row is
16287
+ * mounted (`leadingMarginRef`). Reads everything first (`measureRowSpans`), then writes: no layout is
16288
+ * forced in between. O(mounted rows).
16289
+ *
16290
+ * Unlike the reference implementation (DeepSeek web): it measured each row's own `offsetHeight`,
16291
+ * which in block flow misses the margins between rows and a child's margins that collapse through a row, so the rows drifted from
16292
+ * their offsets. A row's size here is the space it takes in the flow: from where its border box starts
16293
+ * to where the next row's starts (the last mounted row: to the end of the rows), so collapsed margins
16294
+ * are counted once, in the row above them, and the sizes add up to the laid-out height. A row's size
16295
+ * depends on the next row's top margin, so every measurement measures the whole run, not the row that
16296
+ * resized. The last mounted row's bottom margin does not collapse with the next row (not mounted): its
16297
+ * size is provisional until the next row mounts, which corrects it without moving any mounted row
16298
+ * (they are laid out by the browser, positioned by the first row's offset alone). Kept rows are not
16299
+ * measured: absolutely positioned, they take no space in the flow, and keep the size they were
16300
+ * measured at in it.
16301
+ */
16302
+ const measureFlowRun = useEventCallback(() => {
16303
+ const resizes = [];
16304
+ const visibleItemsEl = getVisibleItemsEl();
16305
+ if (!virtual || ignoreItemResize || !itemResizable || !(visibleItemsEl instanceof HTMLElement)) return {
16306
+ resizes,
16307
+ leadingMarginDelta: 0
16308
+ };
16309
+ const rows = getFlowRows();
16310
+ if (rows.length === 0) return {
16311
+ resizes,
16312
+ leadingMarginDelta: 0
16313
+ };
16314
+ const { spans, firstStart } = measureRowSpans(visibleItemsEl, rows.map((row) => row.el));
16315
+ let leadingMarginDelta = 0;
16316
+ if (rows[0].index === 0 && firstStart !== leadingMarginRef.current) {
16317
+ leadingMarginDelta = firstStart - leadingMarginRef.current;
16318
+ leadingMarginRef.current = firstStart;
16319
+ }
16320
+ rows.forEach(({ key, index }, i) => {
16321
+ const size = spans[i];
16322
+ const previousSize = fenwickTree.get(index);
16323
+ if (size === previousSize) return;
16324
+ if (size - itemEstimatedSize === 0) keyToHeightOffsetRef.current.delete(key);
16325
+ else keyToHeightOffsetRef.current.set(key, size - itemEstimatedSize);
16326
+ fenwickTree.add(index, size - previousSize);
16327
+ resizes.push({
16328
+ index,
16329
+ key,
16330
+ delta: size - previousSize
16331
+ });
16332
+ });
16333
+ return {
16334
+ resizes,
16335
+ leadingMarginDelta
16336
+ };
16337
+ });
16338
+ /**
16339
+ * Measures the mounted rows now (`measureFlowRun`) and applies the layout; returns whether any size
16340
+ * changed. Used by the aligned jump, which cannot wait for the batch (a microtask) or the
16341
+ * ResizeObserver (after layout, possibly a frame later) to learn the sizes.
16342
+ */
16343
+ const measureMountedItems = useEventCallback(() => {
16344
+ const { resizes, leadingMarginDelta } = measureFlowRun();
16345
+ const changed = resizes.length !== 0 || leadingMarginDelta !== 0;
16346
+ if (changed) {
16347
+ applyLayoutStyles(startIndex);
16348
+ onContentResize?.();
16349
+ }
16350
+ return changed;
16351
+ });
16352
+ /**
16353
+ * Where item `index` is, in the list's scroll coordinates: read from the DOM when
16354
+ * it is mounted (exact), else its offset in the Fenwick tree (estimates for unmeasured items).
16355
+ */
16356
+ const getItemExtent = useEventCallback((index) => {
16357
+ const listEl = listElRef.current;
16358
+ const item = items[index];
16359
+ const visibleItemsEl = getVisibleItemsEl();
16360
+ if (listEl && item !== void 0 && visibleItemsEl && itemResizable) {
16361
+ const key = getKey(item);
16362
+ for (const itemEl of Array.from(visibleItemsEl.children)) if (itemEl.getAttribute("data-virtual-list-item-key") === key) {
16363
+ const rect = itemEl.getBoundingClientRect();
16364
+ const listTop = listEl.getBoundingClientRect().top + listEl.clientTop;
16365
+ return {
16366
+ top: rect.top - listTop + listEl.scrollTop,
16367
+ size: rect.height,
16368
+ measured: true
16369
+ };
16370
+ }
16371
+ }
16372
+ return {
16373
+ top: fenwickTree.sum(index) + getRowsTop(),
16374
+ size: fenwickTree.get(index),
16375
+ measured: !itemResizable
16376
+ };
16377
+ });
16378
+ /** Bumped by every aligned jump: a chain of steps stops when a newer jump has started. */
16379
+ const alignRunRef = useRef(0);
16380
+ /**
16381
+ * One step of an aligned jump: measure the mounted items, work out the exact
16382
+ * `scrollTop` for the item from the DOM, set it, and update the range. If the range changes, the rows it
16383
+ * brings into view are rendered (in a microtask, still before the browser paints) and the next step runs
16384
+ * from the render callback (a layout effect) to measure them; the jump is done when a step finds the item
16385
+ * mounted, no size changed and `scrollTop` already right. Bounded by `MAX_ALIGN_STEPS`.
16386
+ */
16387
+ const alignStep = useEventCallback((run, index, align, scrollMarginTop, scrollMarginBottom, remaining) => {
16388
+ const listEl = listElRef.current;
16389
+ if (listEl == null || run !== alignRunRef.current || index >= items.length) return;
16390
+ const sizesChanged = measureMountedItems();
16391
+ const { top: itemTop, size: itemSize, measured } = getItemExtent(index);
16392
+ const viewportHeight = listEl.clientHeight;
16393
+ const target = Math.round(getAlignedScrollTop({
16394
+ itemTop,
16395
+ itemSize,
16396
+ viewportHeight,
16397
+ align,
16398
+ scrollMarginTop,
16399
+ scrollMarginBottom,
16400
+ maxScrollTop: listEl.scrollHeight - viewportHeight
16401
+ }));
16402
+ const moved = Math.abs(listEl.scrollTop - target) >= .5;
16403
+ if (moved) listEl.scrollTo({
16404
+ left: listEl.scrollLeft,
16405
+ top: target,
16406
+ behavior: "instant"
16407
+ });
16408
+ viewportRef.current.scrollTop = listEl.scrollTop;
16409
+ if (!moved && !sizesChanged && measured || remaining <= 0) return;
16410
+ updateRange("listScroll", true, () => {
16411
+ alignStep(run, index, align, scrollMarginTop, scrollMarginBottom, remaining - 1);
16412
+ });
16413
+ });
16414
+ /**
16415
+ * `scrollTo({ index | key, align })`. Instant (or "auto"): the aligned steps above, armed as the pending
16416
+ * task like the other instant jumps (item sizes reported after the jump replay it, for one frame plus one
16417
+ * task). Smooth: one scroll to the position worked out from the current layout (estimates for rows not
16418
+ * measured yet), like the smooth index jump. Virtualization off: read from the DOM.
16419
+ */
16420
+ const scrollToAligned = useEventCallback((index, align, behavior, isReplay, scrollMarginTop, scrollMarginBottom) => {
16421
+ const listEl = listElRef.current;
16422
+ if (listEl == null) return;
16423
+ if (!virtual) {
16424
+ const itemEl = getVisibleItemsEl()?.children.item(index);
16425
+ if (!itemEl) return;
16426
+ const rect = itemEl.getBoundingClientRect();
16427
+ const listTop = listEl.getBoundingClientRect().top + listEl.clientTop;
16428
+ const top = getAlignedScrollTop({
16429
+ itemTop: rect.top - listTop + listEl.scrollTop,
16430
+ itemSize: rect.height,
16431
+ viewportHeight: listEl.clientHeight,
16432
+ align,
16433
+ scrollMarginTop,
16434
+ scrollMarginBottom,
16435
+ maxScrollTop: listEl.scrollHeight - listEl.clientHeight
16436
+ });
16437
+ listEl.scrollTo({
16438
+ left: 0,
16439
+ top: Math.round(top),
16440
+ behavior
16441
+ });
16442
+ return;
16443
+ }
16444
+ const smooth = behavior === "smooth";
16445
+ if (!isReplay) {
16446
+ clearPendingScrollTask();
16447
+ if (!smooth) {
16448
+ pendingScrollTaskRef.current = {
16449
+ type: "align",
16450
+ index,
16451
+ align,
16452
+ scrollMarginTop,
16453
+ scrollMarginBottom
16454
+ };
16455
+ schedulePendingScrollTaskExpiry();
16456
+ }
16457
+ }
16458
+ const run = ++alignRunRef.current;
16459
+ if (smooth) {
16460
+ const { top: itemTop, size: itemSize } = getItemExtent(index);
16461
+ const top = getAlignedScrollTop({
16462
+ itemTop,
16463
+ itemSize,
16464
+ viewportHeight: listEl.clientHeight,
16465
+ align,
16466
+ scrollMarginTop,
16467
+ scrollMarginBottom,
16468
+ maxScrollTop: listEl.scrollHeight - listEl.clientHeight
16469
+ });
16470
+ listEl.scrollTo({
16471
+ left: 0,
16472
+ top: Math.round(top),
16473
+ behavior
16474
+ });
16475
+ updateRange("listScroll", true, null);
16476
+ return;
16477
+ }
16478
+ alignStep(run, index, align, scrollMarginTop, scrollMarginBottom, MAX_ALIGN_STEPS);
16479
+ });
16480
+ const scrollTo = useEventCallback((options, topIfNumber) => {
16481
+ if (typeof options == "number") {
16482
+ scrollToPosition(options, topIfNumber, "instant");
16483
+ return;
16484
+ }
16485
+ const { left, top, index, key, position, behavior = "instant", debounce = true, scrollMarginTop = 0, scrollMarginBottom = 0, align } = options;
16486
+ if (left !== void 0 || top !== void 0) scrollToPosition(left, top, behavior);
16487
+ else if (align !== void 0 && (index !== void 0 || key !== void 0)) {
16488
+ const alignIndex = index ?? keyToIndexRef.current.get(key);
16489
+ if (alignIndex !== void 0) scrollToAligned(alignIndex, align, behavior, false, scrollMarginTop, scrollMarginBottom);
16490
+ } else if (index !== void 0) scrollToIndex(index, behavior, debounce, false, scrollMarginTop, scrollMarginBottom);
16491
+ else if (key !== void 0) {
16492
+ const keyIndex = keyToIndexRef.current.get(key);
16493
+ if (keyIndex !== void 0) scrollToIndex(keyIndex, behavior, debounce, false, scrollMarginTop, scrollMarginBottom);
16494
+ } else if (position) {
16495
+ if (virtual) {
16496
+ clearPendingScrollTask();
16497
+ if (behavior === "instant") {
16498
+ pendingScrollTaskRef.current = { type: position };
16499
+ schedulePendingScrollTaskExpiry();
16500
+ }
16501
+ }
16502
+ if (position === "bottom") {
16503
+ scrollToPosition(0, listElRef.current?.scrollHeight || 2e9, behavior);
16504
+ if (virtual) updateRange("listScroll", true, null);
16505
+ } else if (position === "top") scrollToPosition(0, 0, behavior);
16506
+ }
16507
+ });
16508
+ const replayPendingScrollTask = useEventCallback(() => {
16509
+ const task = pendingScrollTaskRef.current;
16510
+ if (task) {
16511
+ if (task.type === "top") scrollToPosition(0, 0, "instant");
16512
+ else if (task.type === "bottom") scrollToPosition(0, listElRef.current?.scrollHeight || 2e9, "instant");
16513
+ else if (task.type === "index") scrollToIndex(task.index, "instant", task.debounce, true);
16514
+ else if (task.type === "align") scrollToAligned(task.index, task.align, "instant", true, task.scrollMarginTop, task.scrollMarginBottom);
16515
+ else if (task.type === "custom") task.task();
16516
+ }
16517
+ });
16518
+ /**
16519
+ * Runs `task` now (after a range update) and again after every batch of item resizes while it is
16520
+ * armed (one frame plus one task).
16521
+ */
16522
+ const submitScrollAdjustingTask = useCallback((task) => {
16523
+ clearPendingScrollTask();
16524
+ pendingScrollTaskRef.current = {
16525
+ type: "custom",
16526
+ task
16527
+ };
16528
+ schedulePendingScrollTaskExpiry();
16529
+ updateRange("listScroll", true, replayPendingScrollTask);
16530
+ }, [
16531
+ replayPendingScrollTask,
16532
+ clearPendingScrollTask,
16533
+ schedulePendingScrollTaskExpiry,
16534
+ updateRange
16535
+ ]);
16536
+ const syncViewport = useCallback(() => {
16537
+ updateRange("listScroll", false, null);
16538
+ }, [updateRange]);
16539
+ const restoreItemsAnchor = useEventCallback((anchor) => {
16540
+ appliedItemsAnchorRef.current = anchor;
16541
+ rangeRef.current = renderedRange;
16542
+ const listEl = listElRef.current;
16543
+ const index = keyToIndexRef.current.get(anchor.key);
16544
+ if (listEl == null || index === void 0 || pendingScrollTaskRef.current?.type !== void 0) return;
16545
+ applyLayoutStyles(startIndex);
16546
+ const diff = fenwickTree.sum(index) + anchor.delta + getRowsTop() - (listEl.scrollTop + compensationYRef.current);
16547
+ if (diff !== 0 && !addCompensation(diff)) listEl.scrollBy(0, diff);
16548
+ viewportRef.current.scrollTop = listEl.scrollTop;
16549
+ });
16550
+ useLayoutEffect(() => {
16551
+ if (pendingItemsAnchor !== null && !sessionChangedRef.current) restoreItemsAnchor(pendingItemsAnchor);
16552
+ if (sessionChangedRef.current) {
16553
+ updateRange("sessionChanged", true, replayPendingScrollTask);
16554
+ sessionChangedRef.current = false;
16555
+ } else if (itemResizable) {
16556
+ const heightBefore = listElRef.current?.offsetHeight;
16557
+ applyLayoutStyles(startIndex);
16558
+ if (heightBefore === listElRef.current?.offsetHeight) updateRange("itemsChanged", true, replayPendingScrollTask);
16559
+ } else updateRange("itemsChanged", true, replayPendingScrollTask);
16560
+ }, [
16561
+ sessionId,
16562
+ items,
16563
+ replayPendingScrollTask,
16564
+ updateRange,
16565
+ itemResizable,
16566
+ applyLayoutStyles
16567
+ ]);
16568
+ useLayoutEffect(() => {
16569
+ committedLayoutRef.current = {
16570
+ items,
16571
+ tree: fenwickTree,
16572
+ sessionId
16573
+ };
16574
+ });
16575
+ useLayoutEffect(() => {
16576
+ applyLayoutStyles(startIndex);
16577
+ renderCallback?.();
16578
+ }, [
16579
+ renderReason,
16580
+ renderCallback,
16581
+ renderVersion,
16582
+ applyLayoutStyles
16583
+ ]);
16584
+ const getOffsetTopOfKey = useEventCallback((key) => {
16585
+ const index = keyToIndexRef.current.get(key);
16586
+ if (index !== void 0) return fenwickTree.sum(index) + getRowsTop();
16587
+ });
16588
+ const refreshListWidth = useCallback(() => {
16589
+ const listEl = listElRef.current;
16590
+ if (listEl) listEl.style.setProperty("--virtual-list-width", `${listEl.offsetWidth}px`);
16591
+ }, [listElRef]);
16592
+ const imperativeApi = useMemo(() => ({
16593
+ listElRef,
16594
+ itemsElRef,
16595
+ scrollTo,
16596
+ syncViewport,
16597
+ getOffsetTopOfKey,
16598
+ submitScrollAdjustingTask,
16599
+ refreshListWidth
16600
+ }), [
16601
+ getOffsetTopOfKey,
16602
+ scrollTo,
16603
+ syncViewport,
16604
+ submitScrollAdjustingTask,
16605
+ refreshListWidth
16606
+ ]);
16607
+ useImperativeHandle(componentRef, () => imperativeApi, [imperativeApi]);
16608
+ const itemResizeQueueRef = useRef([]);
16609
+ const enqueueItemResize = useEventCallback((entry) => {
16610
+ itemResizeQueueRef.current.push(entry);
16611
+ });
16612
+ const clearItemResizeQueue = useEventCallback(() => {
16613
+ itemResizeQueueRef.current = [];
16614
+ });
16615
+ const batchResizeScheduledRef = useRef(false);
16616
+ /**
16617
+ * Applies the queued item measurements (in place of the browser's scroll anchoring): the mounted rows
16618
+ * are measured (`measureFlowRun`: all of them, since a row's size depends on its neighbour) and each
16619
+ * size change goes into the Fenwick tree and the key -> offset cache. With no pending scroll task,
16620
+ * the size changes of items measured for the FIRST time among those that entered above the old start
16621
+ * of the range (`prependIndexes`), and of rows above the view, are scrolled away (`scrollBy`, or
16622
+ * through the iOS compensation during a touch scroll); with a pending task, the task is replayed.
16623
+ */
16624
+ const handleItemBatchResize = useEventCallback(() => {
16625
+ if (!virtual) return;
16626
+ const queue = itemResizeQueueRef.current;
16627
+ if (ignoreItemResize) return;
16628
+ const listElBefore = listElRef.current;
16629
+ const viewTop = listElBefore == null ? 0 : listElBefore.scrollTop + compensationYRef.current - getRowsTop();
16630
+ const viewTopIndex = listElBefore == null ? 0 : fenwickTree.getBound(viewTop);
16631
+ const isFirstOfKey = /* @__PURE__ */ new Map();
16632
+ for (const { key, isFirst } of queue) if (!isFirstOfKey.has(key)) isFirstOfKey.set(key, isFirst);
16633
+ const { resizes, leadingMarginDelta } = measureFlowRun();
16634
+ applyLayoutStyles(startIndex);
16635
+ onContentResize?.();
16636
+ const listEl = listElRef.current;
16637
+ if (listEl != null) {
16638
+ if (pendingScrollTaskRef.current?.type === void 0) {
16639
+ const compensates = (index, key) => key !== void 0 && isFirstOfKey.get(key) === true && prependIndexes.includes(index) || index < viewTopIndex;
16640
+ let compensation = 0;
16641
+ for (const { index, key, delta } of resizes) if (compensates(index, key)) compensation += delta;
16642
+ const firstItem = items[0];
16643
+ if (leadingMarginDelta !== 0 && (viewTop > 0 || compensates(0, firstItem === void 0 ? void 0 : getKey(firstItem)))) compensation += leadingMarginDelta;
16644
+ if (compensation !== 0 && !addCompensation(compensation)) listEl.scrollBy(0, compensation);
16645
+ } else replayPendingScrollTask();
16646
+ const viewport = viewportRef.current;
16647
+ viewport.scrollTop = listEl.scrollTop;
16648
+ viewport.scrollLeft = listEl.scrollLeft;
16649
+ }
16650
+ clearItemResizeQueue();
16651
+ updateRange("batchItemResize", false, null);
16652
+ });
16653
+ /** Measurements of items that just mounted are applied together, in one microtask. */
16654
+ const scheduleItemBatchResize = useEventCallback(() => {
16655
+ if (!batchResizeScheduledRef.current) {
16656
+ Promise.resolve().then(() => {
16657
+ handleItemBatchResize();
16658
+ batchResizeScheduledRef.current = false;
16659
+ });
16660
+ batchResizeScheduledRef.current = true;
16661
+ }
16662
+ });
16663
+ /**
16664
+ * Ignores scroll events while a flush of the iOS compensation suppresses them; otherwise updates
16665
+ * the range (replaying a pending task) and calls `onScroll`.
16666
+ */
16667
+ const handleListScroll = useEventCallback((event) => {
16668
+ const scrollTop = event.target.scrollTop;
16669
+ if (!isScrollSuppressedWithForceRestore(scrollTop)) {
16670
+ if (!wheelScrollingRef.current) updateRange("listScroll", false, pendingScrollTaskRef.current ? replayPendingScrollTask : null);
16671
+ onScroll?.(event.nativeEvent);
16672
+ }
16673
+ });
16674
+ /**
16675
+ * With `catchWheel` (and a fine pointer): scrolls by the wheel itself (`preventDefault`, then
16676
+ * `scrollTop +=`) and updates the range at once, so the rows are rendered in the same frame.
16677
+ */
16678
+ const handleWheel = useEventCallback((wheelEvent) => {
16679
+ if (catchWheel) {
16680
+ if (mayUseWheelRef.current) {
16681
+ const listEl = listElRef.current;
16682
+ if (listEl != null) {
16683
+ const scale = getWheelDeltaScale();
16684
+ const deltaX = wheelEvent.deltaX / scale;
16685
+ const deltaY = wheelEvent.deltaY / scale;
16686
+ if (deltaX === 0 && (listEl.scrollTop === 0 && deltaY <= 0 || listEl.scrollTop + listEl.offsetHeight >= listEl.scrollHeight && deltaY >= 0)) return;
16687
+ wheelEvent.preventDefault();
16688
+ listEl.scrollTop += deltaY;
16689
+ listEl.scrollLeft += deltaX;
16690
+ syncViewport();
16691
+ wheelScrollingRef.current = true;
16692
+ runLatestInNextFrame(() => {
16693
+ wheelScrollingRef.current = false;
16694
+ });
16695
+ }
16696
+ }
16697
+ onWheel?.(wheelEvent);
16698
+ }
16699
+ });
16700
+ useNonPassiveWheel(useCallback(() => listElRef.current, []), handleWheel, catchWheel);
16701
+ const iosCompensationEnabled = isIOS && virtual;
16702
+ const { addCompensation, isScrollSuppressedWithForceRestore } = useIosMomentumCompensation({
16703
+ enabled: iosCompensationEnabled,
16704
+ listElRef,
16705
+ itemsElRef,
16706
+ syncViewport,
16707
+ compensationYRef
16708
+ });
16709
+ /**
16710
+ * The list's own resize: stores its height and width, sets `--virtual-list-width` and updates
16711
+ * the range. Skipped while the list is hidden with `display: none`.
16712
+ */
16713
+ const handleListResize = useEventCallback((listEl, deferRender) => {
16714
+ if (isHiddenByDisplayNone(listEl)) return;
16715
+ const height = listEl.offsetHeight;
16716
+ const width = listEl.offsetWidth;
16717
+ const viewport = viewportRef.current;
16718
+ if (listElRef.current) listElRef.current.style.setProperty("--virtual-list-width", `${width}px`);
16719
+ if (renderCol == null && renderItemWithCols == null) {
16720
+ if (height === viewport.listHeight) return;
16721
+ } else if (height === viewport.listHeight && width === viewport.listWidth) return;
16722
+ viewport.listHeight = height;
16723
+ viewport.listWidth = width;
16724
+ updateRange("listResize", deferRender, replayPendingScrollTask);
16725
+ });
16726
+ const onListResizeObserved = useEventCallback(({ entry }) => {
16727
+ handleListResize(entry.target, false);
16728
+ onResize?.(entry);
16729
+ });
16730
+ const onListRefUpdated = useEventCallback((el) => {
16731
+ if (el) handleListResize(el, true);
16732
+ });
16733
+ /**
16734
+ * Tracks the row holding focus: focusin finds the row the target is in (the visible-items element's
16735
+ * child it is inside); focusout to outside the list releases it, and the range is updated so the row
16736
+ * unmounts if it is out of the range.
16737
+ */
16738
+ const handleFocusIn = useEventCallback((event) => {
16739
+ const visibleItemsEl = getVisibleItemsEl();
16740
+ let el = event.target instanceof Element ? event.target : null;
16741
+ while (el !== null && el.parentElement !== visibleItemsEl) el = el.parentElement;
16742
+ focusedKeyRef.current = el?.getAttribute("data-virtual-list-item-key") ?? null;
16743
+ });
16744
+ const handleFocusOut = useEventCallback((event) => {
16745
+ const listEl = listElRef.current;
16746
+ const next = event.relatedTarget;
16747
+ if (listEl === null || next instanceof Node && listEl.contains(next)) return;
16748
+ if (focusedKeyRef.current !== null) {
16749
+ focusedKeyRef.current = null;
16750
+ updateRange("listScroll", true, null);
16751
+ }
16752
+ });
16753
+ useLayoutEffect(() => {
16754
+ const listEl = listElRef.current;
16755
+ if (listEl === null) return;
16756
+ listEl.addEventListener("focusin", handleFocusIn);
16757
+ listEl.addEventListener("focusout", handleFocusOut);
16758
+ return () => {
16759
+ listEl.removeEventListener("focusin", handleFocusIn);
16760
+ listEl.removeEventListener("focusout", handleFocusOut);
16761
+ };
16762
+ }, [handleFocusIn, handleFocusOut]);
16763
+ useLayoutEffect(() => {
16764
+ if (defaultScrollIndex != null) scrollTo({ index: defaultScrollIndex });
16765
+ else if (defaultScrollKey != null) scrollTo({ key: defaultScrollKey });
16766
+ }, [sessionId]);
16767
+ const itemsContainerStyle = useMemo(() => ({
16768
+ boxSizing: "content-box",
16769
+ width: px(totalColumnsWidth) ?? void 0,
16770
+ paddingTop: px(paddingTop) ?? void 0,
16771
+ ...typeof itemsStyle == "object" ? itemsStyle : {}
16772
+ }), [
16773
+ totalColumnsWidth,
16774
+ paddingTop,
16775
+ itemsStyle
16776
+ ]);
16777
+ const [keptItemsBefore, keptItemsAfter] = useMemo(() => {
16778
+ if (!virtual) return [EMPTY_ARRAY, EMPTY_ARRAY];
16779
+ const before = [];
16780
+ const after = [];
16781
+ keptKeysRef.current.forEach((key) => {
16782
+ const index = keyToIndexRef.current.get(key);
16783
+ if (index === void 0) return;
16784
+ const item = items[index];
16785
+ if (item !== void 0) {
16786
+ if (index < startIndex) before.push(item);
16787
+ else if (index > endIndex) after.push(item);
16788
+ }
16789
+ });
16790
+ return [before, after];
16791
+ }, [
16792
+ virtual,
16793
+ keptKeysRef.current,
16794
+ items,
16795
+ startIndex,
16796
+ endIndex
16797
+ ]);
16798
+ /**
16799
+ * Renders one item. With `itemResizable` it is wrapped in a ResizeObserverWrapper: when the ref is
16800
+ * set the item gets `data-virtual-list-item-key` and is measured in the next microtask batch
16801
+ * (`isFirst`); later sizes come from the ResizeObserver. The React key is `sessionId:key`, so a new
16802
+ * session remounts every item.
16803
+ */
16804
+ const renderItem = useCallback((item, absolute) => {
16805
+ const key = getKey(item);
16806
+ const index = keyToIndexRef.current.get(key);
16807
+ const reactKey = sessionId !== void 0 ? `${sessionId}:${key}` : key;
16808
+ const absoluteStyle = absolute ? {
16809
+ position: "absolute",
16810
+ top: px(fenwickTree.sum(index) - fenwickTree.sum(startIndex) + firstRowStartRef.current),
16811
+ left: 0,
16812
+ right: 0
16813
+ } : void 0;
16814
+ const colsNode = renderCol != null ? /* @__PURE__ */ jsx(ItemColumns, {
16815
+ index,
16816
+ item
16817
+ }) : void 0;
16818
+ const itemWithColsNode = renderItemWithCols != null ? /* @__PURE__ */ jsx(ItemColumns, {
16819
+ index,
16820
+ item
16821
+ }) : void 0;
16822
+ if (itemResizable) return /* @__PURE__ */ jsx(ResizeObserverWrapper, {
16823
+ simulateRefUpdateTrigger: sessionId,
16824
+ disabled: !virtual,
16825
+ onRefUpdate: (el) => {
16826
+ if (el) {
16827
+ el.setAttribute(ITEM_KEY_ATTR, key);
16828
+ if (!ignoreItemResize && virtual) {
16829
+ enqueueItemResize({
16830
+ key,
16831
+ target: el,
16832
+ isFirst: true
16833
+ });
16834
+ scheduleItemBatchResize();
16835
+ }
16836
+ }
16837
+ },
16838
+ onResize: ({ entry, isFirst }) => {
16839
+ if (!ignoreItemResize) {
16840
+ enqueueItemResize({
16841
+ key,
16842
+ target: entry.target,
16843
+ isFirst
16844
+ });
16845
+ getResizeObserverDelegate().runAfterEntries(handleItemBatchResize);
16846
+ }
16847
+ },
16848
+ children: ({ ref }) => {
16849
+ if (ItemComponent) return /* @__PURE__ */ jsx(ItemComponent, {
16850
+ domRef: ref,
16851
+ item,
16852
+ index,
16853
+ renderedCols: colsNode,
16854
+ renderedItemWithCols: itemWithColsNode,
16855
+ style: absoluteStyle
16856
+ });
16857
+ else if (renderItemChild == null) return;
16858
+ else return renderItemChild({
16859
+ key: void 0,
16860
+ domRef: ref,
16861
+ item,
16862
+ index,
16863
+ renderedCols: colsNode,
16864
+ renderedItemWithCols: itemWithColsNode,
16865
+ style: absoluteStyle
16866
+ });
16867
+ }
16868
+ }, reactKey);
16869
+ else if (ItemComponent) return /* @__PURE__ */ jsx(ItemComponent, {
16870
+ domRef: null,
16871
+ item,
16872
+ index,
16873
+ renderedCols: colsNode,
16874
+ renderedItemWithCols: itemWithColsNode,
16875
+ style: absoluteStyle
16876
+ }, reactKey);
16877
+ else if (renderItemChild == null) return;
16878
+ else return renderItemChild({
16879
+ key: reactKey,
16880
+ domRef: null,
16881
+ item,
16882
+ index,
16883
+ renderedCols: colsNode,
16884
+ renderedItemWithCols: itemWithColsNode,
16885
+ style: absoluteStyle
16886
+ });
16887
+ }, [
16888
+ virtual,
16889
+ getKey,
16890
+ fenwickTree,
16891
+ startIndex,
16892
+ renderCol,
16893
+ renderItemWithCols,
16894
+ itemResizable,
16895
+ sessionId,
16896
+ ignoreItemResize,
16897
+ enqueueItemResize,
16898
+ scheduleItemBatchResize,
16899
+ handleItemBatchResize,
16900
+ ItemComponent,
16901
+ renderItemChild
16902
+ ]);
16903
+ const renderedVisibleItems = useMemo(() => visibleItems.map((item) => renderItem(item, false)), [renderItem, visibleItems]);
16904
+ const renderedKeptBefore = useMemo(() => keptItemsBefore.map((item) => renderItem(item, true)), [renderItem, keptItemsBefore]);
16905
+ const renderedKeptAfter = useMemo(() => keptItemsAfter.map((item) => renderItem(item, true)), [renderItem, keptItemsAfter]);
16906
+ useNonVirtualContentResize(itemsElRef, onContentResize, !virtual);
16907
+ const onContentResizeRef = useLatestRef(onContentResize);
16908
+ const hasItems = items.length !== 0;
16909
+ const footerNode = useMemo(() => typeof footer != "function" ? footer : /* @__PURE__ */ jsx(ResizeObserverWrapper, {
16910
+ onResize: () => {
16911
+ onContentResizeRef.current?.();
16912
+ },
16913
+ onUnmounted: () => {
16914
+ onContentResizeRef.current?.();
16915
+ },
16916
+ children: ({ ref }) => footer({ domRef: ref })
16917
+ }), [footer, onContentResizeRef]);
16918
+ const emptyNode = useMemo(() => typeof empty != "function" ? empty : /* @__PURE__ */ jsx(ResizeObserverWrapper, {
16919
+ onResize: () => {
16920
+ onContentResizeRef.current?.();
16921
+ },
16922
+ onUnmounted: () => {
16923
+ onContentResizeRef.current?.();
16924
+ },
16925
+ children: ({ ref }) => empty({ domRef: ref })
16926
+ }), [empty, onContentResizeRef]);
16927
+ const { snapshotAnchorElementStateAndSaveToRef, restoreScrollStateFromAnchor, clearAnchor } = useScrollAnchor(listElRef, getVisibleItemsEl);
16928
+ useMemoWithPrevious((previous) => {
16929
+ if (!previous || !itemResizable) return;
16930
+ const [wasVirtual, previousSessionId] = previous;
16931
+ if (previousSessionId === sessionId) {
16932
+ if (wasVirtual && !virtual) snapshotAnchorElementStateAndSaveToRef();
16933
+ else {
16934
+ const visibleItemsEl = getVisibleItemsEl();
16935
+ if (!(visibleItemsEl instanceof HTMLElement)) return;
16936
+ const rows = [];
16937
+ for (const el of Array.from(visibleItemsEl.children)) {
16938
+ const key = el.getAttribute(ITEM_KEY_ATTR);
16939
+ if (key !== null && el instanceof HTMLElement) rows.push({
16940
+ el,
16941
+ key
16942
+ });
16943
+ }
16944
+ const { spans, firstStart } = measureRowSpans(visibleItemsEl, rows.map((row) => row.el));
16945
+ if (rows[0] !== void 0 && keyToIndexRef.current.get(rows[0].key) === 0) leadingMarginRef.current = firstStart;
16946
+ rows.forEach(({ key }, i) => {
16947
+ const offset = spans[i] - itemEstimatedSize;
16948
+ if (offset === 0) keyToHeightOffsetRef.current.delete(key);
16949
+ else keyToHeightOffsetRef.current.set(key, offset);
16950
+ });
16951
+ }
16952
+ }
16953
+ }, [virtual, sessionId]);
16954
+ useLayoutEffectWithPrevious((previous) => {
16955
+ if (!itemResizable || !previous) return;
16956
+ const [wasVirtual, previousSessionId] = previous;
16957
+ if (previousSessionId === sessionId && wasVirtual && !virtual) {
16958
+ restoreScrollStateFromAnchor();
16959
+ clearAnchor();
16960
+ }
16961
+ }, [virtual, sessionId]);
16962
+ const { onKeyDown: onKeyboardScroll } = useKeyboardScroll(scrollTo, { pageBottomOcclusion: keyboardPageBottomOcclusion });
16963
+ /** The consumer's `onKeyDown` first: a key it takes (`preventDefault`) does not scroll the list. */
16964
+ const onKeyDown = useCallback((event) => {
16965
+ onNativeKeyDown?.(event);
16966
+ onKeyboardScroll(event);
16967
+ }, [onNativeKeyDown, onKeyboardScroll]);
16968
+ const emptyCentered = items.length === 0 && emptyAlign === "center";
16969
+ const rootClassName = cn("r-virtual-list", columns.length !== 0 && "r-virtual-list--x-scrollable", showScrollbar && "r-virtual-list--show-scrollbar", printable === true && "r-virtual-list--printable", emptyCentered && "r-virtual-list--empty-centered", iosCompensationEnabled && "r-virtual-list--ios-compensation-enabled", className);
16970
+ return /* @__PURE__ */ jsx(ResizeObserverWrapper, {
16971
+ forwardedRef: mergedListRefSetter,
16972
+ onRefUpdate: onListRefUpdated,
16973
+ onResize: onListResizeObserved,
16974
+ children: ({ ref }) => /* @__PURE__ */ jsxs("div", {
16975
+ ...nativeProps,
16976
+ "data-slot": "virtual-list",
16977
+ className: rootClassName,
16978
+ style,
16979
+ onScroll: handleListScroll,
16980
+ ref,
16981
+ onKeyDown,
16982
+ tabIndex: focusable ? 0 : -1,
16983
+ children: [
16984
+ header,
16985
+ hasItems ? /* @__PURE__ */ jsx("div", {
16986
+ "data-slot": "virtual-list-items",
16987
+ ref: itemsElRef,
16988
+ className: itemsClassName,
16989
+ style: itemsContainerStyle,
16990
+ children: /* @__PURE__ */ jsx(VirtualListContext.Provider, {
16991
+ value: imperativeApi,
16992
+ children: /* @__PURE__ */ jsx(ColumnsContext.Provider, {
16993
+ value: columnsContextValue,
16994
+ children: createElement(visibleItemsTag, {
16995
+ "data-slot": "virtual-list-visible-items",
16996
+ style: virtual ? VIRTUAL_VISIBLE_ITEMS_STYLE : NON_VIRTUAL_VISIBLE_ITEMS_STYLE,
16997
+ ...visibleItemsProps
16998
+ }, ...renderedKeptBefore, ...renderedVisibleItems, ...renderedKeptAfter)
16999
+ })
17000
+ })
17001
+ }, "items") : /* @__PURE__ */ jsx("div", {
17002
+ "data-slot": "virtual-list-empty",
17003
+ className: cn("r-virtual-list__empty", emptyCentered && "r-virtual-list__empty--center"),
17004
+ children: emptyNode
17005
+ }, "empty"),
17006
+ footerNode,
17007
+ paddingBottom ? /* @__PURE__ */ jsx("div", { style: { paddingBottom } }) : null,
17008
+ footerAfterBottomPadding
17009
+ ]
17010
+ })
17011
+ });
17012
+ }
17013
+ //#endregion
14875
17014
  //#region src/components/tasks/tasks-panel.recipe.ts
14876
17015
  const tasksPanel = tv({ slots: {
14877
17016
  root: ["flex min-h-0 min-w-0 flex-1 flex-col", "bg-layer-canvas text-foreground"],
@@ -16688,4 +18827,4 @@ function ThemeProvider({ mode, defaultMode = "light", onModeChange, storageKey,
16688
18827
  });
16689
18828
  }
16690
18829
  //#endregion
16691
- export { ActivityInboxControls, ActivityInboxLoadingMore, ActivityInboxPanel, ActivityInboxSelectionCount, ActivityInboxSelectionToolbar, ActivityInboxSidebar, ActivityInboxViewport, AlertDialog, AlertDialogAction, AlertDialogBody, AlertDialogCancel, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AppRailFooter, AppRailHeader, AppRailItem, AppRailItemAttention, AppRailItemBadge, AppRailItemIcon, AppRailItemIndicator, AppRailItemLabel, AppRailNav, AppRailRoot, AppShellMainSlot, AppShellOverlaySlot, AppShellPanelSlot, AppShellRailSlot, AppShellRoot, AppShellSidebarSlot, AppShellSidebarTrigger, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Banner, BannerAction, BannerDescription, BannerTitle, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardLeading, CardTitle, CardTrailing, ChatIcon, Checkbox, CheckboxIndicator, CodeBlock, CodeBlockAction, CodeBlockActions, CodeBlockBody, CodeBlockHeader, CodeBlockTitle, Combobox, ComboboxChip, ComboboxChipRemove, ComboboxChips, ComboboxClear, ComboboxCollection, ComboboxContent, ComboboxControl, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxHeader, ComboboxInput, ComboboxInputGroup, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxList, ComboboxPopup, ComboboxPortal, ComboboxRow, ComboboxSeparator, ComboboxTrigger, ComboboxTriggerCount, ComboboxTriggerIndicator, ComboboxValue, Composer, ComposerActions, ComposerAttachment, ComposerAttachmentBody, ComposerAttachmentFailedOverlay, ComposerAttachmentFile, ComposerAttachmentImage, ComposerAttachmentMeta, ComposerAttachmentRemove, ComposerAttachmentTitle, ComposerAttachmentUploadProgressBar, ComposerAttachmentUploadingOverlay, ComposerAttachments, ComposerAttachmentsScrollArea, ComposerDropOverlay, ComposerDropOverlayLabel, ComposerDropOverlayPrompt, ComposerIconButton, ComposerInput, ComposerMeta, ComposerRoot, ComposerSubmit, ComposerSuggestionAside, ComposerSuggestionContent, ComposerSuggestionGroup, ComposerSuggestionGroupLabel, ComposerSuggestionIcon, ComposerSuggestionList, ComposerSuggestionMeta, ComposerSuggestionOption, ComposerSuggestionTitle, ComposerToolbar, ComposerToolbarLabel, ContextMenu, ContextMenuCheckboxItem, ContextMenuCheckboxItemIndicator, ContextMenuContent, ContextMenuFooter, ContextMenuItem, ContextMenuItemLabel, ContextMenuLabel, ContextMenuPopup, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuRadioItemIndicator, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSubmenu, ContextMenuSubmenuTrigger, ContextMenuTrigger, ConversationPanelBody, ConversationPanelContent, ConversationPanelEmptyState, ConversationPanelEmptyStateBrand, ConversationPanelEmptyStateBrandMark, ConversationPanelFooter, ConversationPanelRoot, ConversationPanelTabs, CopyableCode, CopyableCodeAction, CopyableCodeRoot, DescriptionDetails, DescriptionItem, DescriptionList, DescriptionTerm, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogNav, DialogOverlay, DialogPortal, DialogSurface, DialogTitle, DialogTrigger, DirectMessageIcon, Drawer, DrawerActions, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuCheckboxItemIndicator, DropdownMenuContent, DropdownMenuFooter, DropdownMenuItem, DropdownMenuItemCount, DropdownMenuItemLabel, DropdownMenuLabel, DropdownMenuPopup, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuRadioItemIndicator, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSubmenu, DropdownMenuSubmenuTrigger, DropdownMenuTrigger, EmptyState, EmptyStateActions, EmptyStateContent, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, FileAction, FileActions, FileContent, FileImage, FileMeta, FileMetaItem, FileName, FilePreview, FilePreviewBadge, FilePreviewCode, FilePreviewDocument, FilePreviewFile, FilePreviewMedia, FileRow, FileRowOpen, FileThumbnail, FilesList, FilesPanel, FilesViewport, FloatButton, FloatButtonGroup, FormSection, IconTile, InboxItem, InboxItemActions, InboxItemBody, InboxItemContent, InboxItemContext, InboxItemHeading, InboxItemHoverTarget, InboxItemLeading, InboxItemMarks, InboxItemMessage, InboxItemMetadata, InboxItemSelection, InboxItemSender, InboxItemSubtitle, InboxItemTimestamp, InboxItemTitle, InboxItemTrailing, InboxItemTrigger, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupInput, Kbd, KbdGroup, Label, LabelAsterisk, LabelOptional, LabelSub, LegacyTaskPanelActions, LegacyTaskPanelBody, LegacyTaskPanelField, LegacyTaskPanelFieldLabel, LegacyTaskPanelFieldText, LegacyTaskPanelFieldTitle, LegacyTaskPanelHeader, LegacyTaskPanelIcon, LegacyTaskPanelMeta, LegacyTaskPanelMetaLabel, LegacyTaskPanelMetaRow, LegacyTaskPanelMetaValue, LegacyTaskPanelRoot, LegacyTaskPanelSection, LegacyTaskPanelStatus, LegacyTaskPanelTitle, LegacyTaskPanelTitleMeta, Lightbox, LightboxActions, LightboxClose, LightboxContent, LightboxHeader, LightboxHeaderLabel, LightboxHeaderMeta, LightboxInfoActions, LightboxInfoBar, LightboxInfoDock, LightboxInfoTitle, LightboxMedia, LightboxNavigationButton, LightboxPortal, LightboxStage, LightboxThumbnail, LightboxThumbnailStrip, LightboxTitle, LightboxToolbar, LightboxTrigger, ListRow, ListRowBody, ListRowBottom, ListRowChevron, ListRowDescription, ListRowGroup, ListRowIcon, ListRowMeta, ListRowTitle, ListRowTop, ListRowValue, LiveAgentActivityBar, LiveAgentActivityBarAvatar, LiveAgentActivityBarContent, LiveAgentActivityBarRow, LiveAgentActivityBarStatus, LiveAgentActivityBarText, MarkdownBlockquote, MarkdownCell, MarkdownCheckbox, MarkdownHeaderCell, MarkdownHeading, MarkdownImage, MarkdownInlineCode, MarkdownLink, MarkdownList, MarkdownListItem, MarkdownMark, MarkdownOrderedList, MarkdownParagraph, MarkdownRule, MarkdownTable, MarkdownTableRow, MarkdownTableScroll, MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, MessageActionCardCollapseTrigger, MessageActionCardCompletion, MessageActionCardContent, MessageActionCardHeader, MessageActionCardHeaderDescription, MessageActionCardHeaderIcon, MessageActionCardHeaderStatus, MessageActionCardHeaderTitle, MessageActionCardHint, MessageActionCardHintLabel, MessageActionCardNotice, MessageActionCardProperties, MessageActionCardProperty, MessageActionCardPropertyLabel, MessageActionCardPropertyValue, MessageActionCardScope, MessageActionCardScopeDescription, MessageActionCardScopeList, MessageActionCardScopeListLabel, MessageActionCardScopeListViewport, MessageActionCardScopeName, MessageActionCardStatus, MessageAttachmentAction, MessageAttachmentCard, MessageAttachmentCommentSummary, MessageAttachmentDiffAddition, MessageAttachmentDiffDeletion, MessageAttachmentDiffSummary, MessageAttachmentGroup, MessageAttachmentMeta, MessageAttachmentMetaEnd, MessageAttachmentMetaStart, MessageAttachmentSummary, MessageAttachmentTitle, MessageEmbed, MessageEmbedContent, MessageEmbedFooter, MessageEmbedHeader, MessageForwardedBundle, MessageForwardedBundleAttachment, MessageForwardedBundleAttachmentMeta, MessageForwardedBundleAttachmentName, MessageForwardedBundleAttachments, MessageForwardedBundleFooter, MessageForwardedBundleFooterAction, MessageForwardedBundleGallery, MessageForwardedBundleGalleryTile, MessageForwardedBundleHeader, MessageForwardedBundleHeaderContent, MessageForwardedBundleHeaderCount, MessageForwardedBundleHeaderLabel, MessageForwardedBundleItem, MessageForwardedBundleItemAuthor, MessageForwardedBundleItemContent, MessageForwardedBundleItemMeta, MessageForwardedBundleItems, MessageForwardedBundleSource, MessageForwardedBundleSourceLabel, MessageIcon, MessageImageGallery, MessageImageGalleryAction, MessageImageGalleryItem, MessageImageGalleryMedia, MessageImageGalleryOverlay, MessageImageGalleryPreview, MessageImageGalleryRow, MessageItem, MessageItemAttachments, MessageItemAvatarSlot, MessageItemBadge, MessageItemBadgeSeparator, MessageItemBody, MessageItemContent, MessageItemContinuationTime, MessageItemEdited, MessageItemEmbedded, MessageItemFooter, MessageItemGutter, MessageItemHeader, MessageItemInlineStatus, MessageItemMeta, MessageItemReadReceipt, MessageItemSavedIndicator, MessageItemSearchMatch, MessageItemSender, MessageItemSenderBadges, MessageItemSenderButton, MessageItemSenderGroup, MessageItemTime, MessageItemToolbar, MessageItemToolbarButton, MessageItemTranslationAction, MessageItemTranslationFailedStatus, MessageItemTranslationOriginal, MessageItemTranslationOriginalLabel, MessageItemTranslationProgressTrack, MessageItemTranslationRetryAction, MessageItemTranslationStatus, MessageList, MessageListDateDivider, MessageListHistoryLimited, MessageListNotice, MessageMultiSelect, MessageMultiSelectCheckbox, MessageMultiSelectToolbar, MessageQuotedPreview, MessageQuotedPreviewAttachment, MessageQuotedPreviewAttachments, MessageQuotedPreviewAuthor, MessageQuotedPreviewAuthorMeta, MessageQuotedPreviewAuthorName, MessageQuotedPreviewChannel, MessageQuotedPreviewContent, MessageQuotedPreviewHeader, MessageQuotedPreviewLoading, MessageQuotedPreviewText, MessageQuotedPreviewThread, MessageQuotedPreviewTimestamp, MessageQuotedPreviewUnavailable, MessageReactionAddButton, MessageReactionChip, MessageReactionCount, MessageReactionErrorIndicator, MessageReactionGlyph, MessageReactionPickerContent, MessageReactionPickerStatic, MessageReactionQuickButton, MessageReactionQuickRow, MessageReactionTooltipContent, MessageReactionTooltipMeta, MessageReactionTooltipName, MessageReactionTooltipNameText, MessageReactionTooltipNames, MessageReactionTooltipSeparator, MessageReferenceChip, MessageReferenceIndicator, MessageReferenceLabel, MessageReferencePending, MessageReferenceText, MessageReferenceUnavailable, MessageReplies, MessageRepliesItem, MessageRepliesItemContent, MessageRepliesItemSender, MessageRepliesItemTime, MessageRepliesSummary, MessageRepliesSummaryItem, MessageTextSelectionToolbar, MessageTextSelectionToolbarButton, MessageTextSelectionToolbarSeparator, MessageVideoPreview, MessageVideoPreviewAction, MessageVideoPreviewFailureAction, MessageVideoPreviewFailureContent, MessageVideoPreviewFailureIcon, MessageVideoPreviewFailureTitle, MessageVideoPreviewFallback, MessageVideoPreviewMedia, MobileNavItem, MobileNavLabel, MobileNavRoot, NotificationCenter, NotificationCenterActionButton, NotificationCenterCount, NotificationCenterEmptyState, NotificationCenterHeader, NotificationCenterItem, NotificationCenterItemActions, NotificationCenterItemBody, NotificationCenterItemContent, NotificationCenterItemIcon, NotificationCenterItemRow, NotificationCenterItemTitle, NotificationCenterList, NotificationCenterPopup, NotificationCenterScroller, NotificationCenterTitle, NotificationCenterTrigger, OtterIndicator, Panel, PanelAction, PanelActions, PanelActivity, PanelBody, PanelFooter, PanelHeader, PanelHeaderContent, PanelHeaderIcon, PanelHeaderRoot, PanelHeading, PanelMeta, PanelNotice, PanelNoticeActions, PanelNoticeContent, PanelScrollContent, PanelScrollViewport, PanelSection, PanelSectionHeader, PanelStatus, PanelTitle, PanelToggleAction, PickerTriggerButton, Popover, PopoverArrow, PopoverBackdrop, PopoverClose, PopoverContent, PopoverDescription, PopoverHeader, PopoverPopup, PopoverPortal, PopoverSeparator, PopoverTitle, PopoverTrigger, PopoverViewport, PreviewCard, PreviewCardArrow, PreviewCardContent, PreviewCardDescription, PreviewCardHeader, PreviewCardPopup, PreviewCardPortal, PreviewCardSeparator, PreviewCardTitle, PreviewCardTrigger, ProfilePanel, ProfilePanelBody, ProfilePanelHeader, ProfilePanelHeaderContent, ProfilePanelSection, Progress, ProgressHeader, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, RadioGroup, RadioGroupIndicator, RadioGroupItem, RaftLogo, RaftLogoLockup, RaftWordmark, ResizableGroup, ResizableHandle, ResizablePanel, SINGLE_IMAGE_MAX_HEIGHT, SINGLE_IMAGE_MAX_WIDTH, ScrollArea, ScrollAreaContent, ScrollAreaCorner, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport, SearchEntityResult, SearchEntityResultActivity, SearchEntityResultContent, SearchEntityResultDescription, SearchEntityResultHeader, SearchEntityResultIcon, SearchEntityResultLeading, SearchEntityResultTitle, SearchMessageResult, SearchMessageResultBody, SearchMessageResultHeader, SearchMessageResultMatch, SearchMessageResultMeta, SearchMessageResultSender, SearchMessageResultThreadMeta, SearchMessageResultTimestamp, SearchResultsList, SearchResultsSection, SearchResultsSectionHeading, SearchResultsSummary, SearchShellFilters, SearchShellRoot, SearchShellViewport, SearchThreadMessageResult, SearchThreadResult, SearchThreadResultHeader, SearchThreadResultMessages, SearchThreadResultMeta, SearchThreadResultTimestamp, SearchThreadResultTitle, SearchTrigger, SearchTriggerLabel, SearchTriggerShortcut, SegmentedControl, SegmentedControlCount, SegmentedControlItem, SegmentedControlLabel, Select, SelectArrow, SelectContent, SelectGroup, SelectGroupLabel, SelectIcon, SelectItem, SelectItemDescription, SelectItemIndicator, SelectItemLeading, SelectItemText, SelectLabel, SelectList, SelectPopup, SelectPortal, SelectScrollDownArrow, SelectScrollUpArrow, SelectSeparator, SelectTrigger, SelectValue, Separator, SidebarBody, SidebarContent, SidebarControl, SidebarGroupLabel, SidebarHeader, SidebarHeaderTitle, SidebarItem, SidebarItemAside, SidebarItemChannelIcon, SidebarItemContent, SidebarItemCount, SidebarItemCountSeparator, SidebarItemIcon, SidebarItemIndicator, SidebarItemMeta, SidebarItemMetaIcon, SidebarItemStatus, SidebarItemSubtitle, SidebarItemThreadCount, SidebarItemTitle, SidebarList, SidebarLiveActivity, SidebarMenu, SidebarMenuAside, SidebarMenuCount, SidebarMenuIcon, SidebarMenuTitle, SidebarRoot, SidebarSection, SidebarSectionAttention, SidebarSectionChevron, SidebarSectionControl, SidebarSectionControls, SidebarSectionCount, SidebarSectionDisclosure, SidebarSectionEmpty, SidebarSectionHeader, SidebarSectionTitle, SidebarSectionTrailing, Skeleton, SortableComposerAttachment, SortableComposerAttachments, SortableComposerAttachmentsScroll, SortableTabsList, SortableTabsTab, Spinner, Status, Step, Steps, Switch, SwitchThumb, SystemMessage, SystemMessageContent, SystemMessageGroup, SystemMessageGroupChevron, SystemMessageGroupDisclosure, SystemMessageGroupHeader, SystemMessageGroupPanel, SystemMessageGroupSummary, SystemMessageTime, TASK_STATUS_IDS, Table, TableBody, TableCaption, TableCell, TableColgroup, TableColumn, TableHead, TableHeader, TableRow, Tabs, TabsLabel, TabsList, TabsPanel, TabsTab, TaskBoardColumn, TaskBoardColumnBadge, TaskBoardColumnChevron, TaskBoardColumnCount, TaskBoardColumnEmpty, TaskBoardColumnEmptyAllowed, TaskBoardColumnEmptyBlocked, TaskBoardColumnEmptyIdle, TaskBoardColumnHeading, TaskBoardColumnItems, TaskBoardColumnPanel, TaskBoardColumnTrigger, TaskBoardRoot, TaskCard, TaskCardBody, TaskCardChannel, TaskCardDescription, TaskCardLegacy, TaskCardMeta, TaskCardNumber, TaskCardRow, TaskCardStatus, TaskCardTitle, TaskChip, TaskClosedIcon, TaskDndProvider, TaskDoneIcon, TaskDragOverlay, TaskDraggable, TaskDropPlaceholder, TaskDropZone, TaskInProgressIcon, TaskInReviewIcon, TaskListRoot, TaskLoadingList, TaskLoadingRow, TaskSection, TaskSectionBadge, TaskSectionChevron, TaskSectionCount, TaskSectionEmpty, TaskSectionHeading, TaskSectionItems, TaskSectionPanel, TaskSectionTrigger, TaskStatusBadge, TaskStatusIcon, TaskTodoIcon, TasksPanelEmpty, TasksPanelRoot, TasksPanelToolbar, TasksPanelToolbarFilters, TasksPanelToolbarGroup, TasksPanelToolbarLabel, TasksPanelToolbarNewTask, TasksPanelToolbarView, TasksPanelViewport, Text, TextHeading, TextLink, TextMono, TextSans, Textarea, TextareaCounter, TextareaGroup, ThemeProvider, ThreadIcon, ThreadPanelActions, ThreadPanelBody, ThreadPanelContent, ThreadPanelFooter, ThreadPanelHeader, ThreadPanelOriginalMessage, ThreadPanelReplyCount, ThreadPanelReplySummary, ThreadPanelRoot, ThreadPanelSearch, ThreadPanelSearchCount, ThreadPanelSearchTrailing, ThreadPanelTitle, ThreadPanelTitleMeta, Timeline, TimelineContent, TimelineItem, TimelineTime, TimelineTitle, ToastAction, ToastActions, ToastArrow, ToastBody, ToastClose, ToastContent, ToastDescription, ToastIcon, ToastPortal, ToastPositioner, ToastProgress, ToastProvider, ToastRoot, ToastTitle, ToastViewport, ToggleGroup, ToggleGroupItem, ToggleGroupLabel, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, buildMessageImageGalleryRows, buttonVariants, classifyMessageImageAspect, cn, createMessageTextSelectionAnchor, createToastManager, getTextSelectionFocusRect, installInputModality, taskStatusSoft, taskStatusStrong, textLinkVariants, toast, useComposerSuggestions, useOrderedTabs, useTheme, useToastManager };
18830
+ export { ActivityInboxControls, ActivityInboxLoadingMore, ActivityInboxPanel, ActivityInboxSelectionCount, ActivityInboxSelectionToolbar, ActivityInboxSidebar, ActivityInboxViewport, AlertDialog, AlertDialogAction, AlertDialogBody, AlertDialogCancel, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AppRailFooter, AppRailHeader, AppRailItem, AppRailItemAttention, AppRailItemBadge, AppRailItemIcon, AppRailItemIndicator, AppRailItemLabel, AppRailNav, AppRailRoot, AppShellMainSlot, AppShellOverlaySlot, AppShellPanelSlot, AppShellRailSlot, AppShellRoot, AppShellSidebarSlot, AppShellSidebarTrigger, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Banner, BannerAction, BannerDescription, BannerTitle, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardLeading, CardTitle, CardTrailing, ChatIcon, Checkbox, CheckboxIndicator, CodeBlock, CodeBlockAction, CodeBlockActions, CodeBlockBody, CodeBlockHeader, CodeBlockTitle, Combobox, ComboboxChip, ComboboxChipRemove, ComboboxChips, ComboboxClear, ComboboxCollection, ComboboxContent, ComboboxControl, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxHeader, ComboboxInput, ComboboxInputGroup, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxList, ComboboxPopup, ComboboxPortal, ComboboxRow, ComboboxSeparator, ComboboxTrigger, ComboboxTriggerCount, ComboboxTriggerIndicator, ComboboxValue, Composer, ComposerActions, ComposerAttachment, ComposerAttachmentBody, ComposerAttachmentFailedOverlay, ComposerAttachmentFile, ComposerAttachmentImage, ComposerAttachmentMeta, ComposerAttachmentRemove, ComposerAttachmentTitle, ComposerAttachmentUploadProgressBar, ComposerAttachmentUploadingOverlay, ComposerAttachments, ComposerAttachmentsScrollArea, ComposerDropOverlay, ComposerDropOverlayLabel, ComposerDropOverlayPrompt, ComposerIconButton, ComposerInput, ComposerMeta, ComposerRoot, ComposerSubmit, ComposerSuggestionAside, ComposerSuggestionContent, ComposerSuggestionGroup, ComposerSuggestionGroupLabel, ComposerSuggestionIcon, ComposerSuggestionList, ComposerSuggestionMeta, ComposerSuggestionOption, ComposerSuggestionTitle, ComposerToolbar, ComposerToolbarLabel, ContextMenu, ContextMenuCheckboxItem, ContextMenuCheckboxItemIndicator, ContextMenuContent, ContextMenuFooter, ContextMenuItem, ContextMenuItemLabel, ContextMenuLabel, ContextMenuPopup, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuRadioItemIndicator, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSubmenu, ContextMenuSubmenuTrigger, ContextMenuTrigger, ConversationPanelBody, ConversationPanelContent, ConversationPanelEmptyState, ConversationPanelEmptyStateBrand, ConversationPanelEmptyStateBrandMark, ConversationPanelFooter, ConversationPanelRoot, ConversationPanelTabs, CopyableCode, CopyableCodeAction, CopyableCodeRoot, DescriptionDetails, DescriptionItem, DescriptionList, DescriptionTerm, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogNav, DialogOverlay, DialogPortal, DialogSurface, DialogTitle, DialogTrigger, DirectMessageIcon, Drawer, DrawerActions, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuCheckboxItemIndicator, DropdownMenuContent, DropdownMenuFooter, DropdownMenuItem, DropdownMenuItemCount, DropdownMenuItemLabel, DropdownMenuLabel, DropdownMenuPopup, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuRadioItemIndicator, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSubmenu, DropdownMenuSubmenuTrigger, DropdownMenuTrigger, EmptyState, EmptyStateActions, EmptyStateContent, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, FileAction, FileActions, FileContent, FileImage, FileMeta, FileMetaItem, FileName, FilePreview, FilePreviewBadge, FilePreviewCode, FilePreviewDocument, FilePreviewFile, FilePreviewMedia, FileRow, FileRowOpen, FileThumbnail, FilesList, FilesPanel, FilesViewport, FloatButton, FloatButtonGroup, FormSection, IconTile, InboxItem, InboxItemActions, InboxItemBody, InboxItemContent, InboxItemContext, InboxItemHeading, InboxItemHoverTarget, InboxItemLeading, InboxItemMarks, InboxItemMessage, InboxItemMetadata, InboxItemSelection, InboxItemSender, InboxItemSubtitle, InboxItemTimestamp, InboxItemTitle, InboxItemTrailing, InboxItemTrigger, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupInput, Kbd, KbdGroup, Label, LabelAsterisk, LabelOptional, LabelSub, LegacyTaskPanelActions, LegacyTaskPanelBody, LegacyTaskPanelField, LegacyTaskPanelFieldLabel, LegacyTaskPanelFieldText, LegacyTaskPanelFieldTitle, LegacyTaskPanelHeader, LegacyTaskPanelIcon, LegacyTaskPanelMeta, LegacyTaskPanelMetaLabel, LegacyTaskPanelMetaRow, LegacyTaskPanelMetaValue, LegacyTaskPanelRoot, LegacyTaskPanelSection, LegacyTaskPanelStatus, LegacyTaskPanelTitle, LegacyTaskPanelTitleMeta, Lightbox, LightboxActions, LightboxClose, LightboxContent, LightboxHeader, LightboxHeaderLabel, LightboxHeaderMeta, LightboxInfoActions, LightboxInfoBar, LightboxInfoDock, LightboxInfoTitle, LightboxMedia, LightboxNavigationButton, LightboxPortal, LightboxStage, LightboxThumbnail, LightboxThumbnailStrip, LightboxTitle, LightboxToolbar, LightboxTrigger, ListRow, ListRowBody, ListRowBottom, ListRowChevron, ListRowDescription, ListRowGroup, ListRowIcon, ListRowMeta, ListRowTitle, ListRowTop, ListRowValue, LiveAgentActivityBar, LiveAgentActivityBarAvatar, LiveAgentActivityBarContent, LiveAgentActivityBarRow, LiveAgentActivityBarStatus, LiveAgentActivityBarText, MarkdownBlockquote, MarkdownCell, MarkdownCheckbox, MarkdownHeaderCell, MarkdownHeading, MarkdownImage, MarkdownInlineCode, MarkdownLink, MarkdownList, MarkdownListItem, MarkdownMark, MarkdownOrderedList, MarkdownParagraph, MarkdownRule, MarkdownTable, MarkdownTableRow, MarkdownTableScroll, MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, MessageActionCardCollapseTrigger, MessageActionCardCompletion, MessageActionCardContent, MessageActionCardHeader, MessageActionCardHeaderDescription, MessageActionCardHeaderIcon, MessageActionCardHeaderStatus, MessageActionCardHeaderTitle, MessageActionCardHint, MessageActionCardHintLabel, MessageActionCardNotice, MessageActionCardProperties, MessageActionCardProperty, MessageActionCardPropertyLabel, MessageActionCardPropertyValue, MessageActionCardScope, MessageActionCardScopeDescription, MessageActionCardScopeList, MessageActionCardScopeListLabel, MessageActionCardScopeListViewport, MessageActionCardScopeName, MessageActionCardStatus, MessageAttachmentAction, MessageAttachmentCard, MessageAttachmentCommentSummary, MessageAttachmentDiffAddition, MessageAttachmentDiffDeletion, MessageAttachmentDiffSummary, MessageAttachmentGroup, MessageAttachmentMeta, MessageAttachmentMetaEnd, MessageAttachmentMetaStart, MessageAttachmentSummary, MessageAttachmentTitle, MessageEmbed, MessageEmbedContent, MessageEmbedFooter, MessageEmbedHeader, MessageForwardedBundle, MessageForwardedBundleAttachment, MessageForwardedBundleAttachmentMeta, MessageForwardedBundleAttachmentName, MessageForwardedBundleAttachments, MessageForwardedBundleFooter, MessageForwardedBundleFooterAction, MessageForwardedBundleGallery, MessageForwardedBundleGalleryTile, MessageForwardedBundleHeader, MessageForwardedBundleHeaderContent, MessageForwardedBundleHeaderCount, MessageForwardedBundleHeaderLabel, MessageForwardedBundleItem, MessageForwardedBundleItemAuthor, MessageForwardedBundleItemContent, MessageForwardedBundleItemMeta, MessageForwardedBundleItems, MessageForwardedBundleSource, MessageForwardedBundleSourceLabel, MessageIcon, MessageImageGallery, MessageImageGalleryAction, MessageImageGalleryItem, MessageImageGalleryMedia, MessageImageGalleryOverlay, MessageImageGalleryPreview, MessageImageGalleryRow, MessageItem, MessageItemAttachments, MessageItemAvatarSlot, MessageItemBadge, MessageItemBadgeSeparator, MessageItemBody, MessageItemContent, MessageItemContinuationTime, MessageItemEdited, MessageItemEmbedded, MessageItemFooter, MessageItemGutter, MessageItemHeader, MessageItemInlineStatus, MessageItemMeta, MessageItemReadReceipt, MessageItemSavedIndicator, MessageItemSearchMatch, MessageItemSender, MessageItemSenderBadges, MessageItemSenderButton, MessageItemSenderGroup, MessageItemTime, MessageItemToolbar, MessageItemToolbarButton, MessageItemTranslationAction, MessageItemTranslationFailedStatus, MessageItemTranslationOriginal, MessageItemTranslationOriginalLabel, MessageItemTranslationProgressTrack, MessageItemTranslationRetryAction, MessageItemTranslationStatus, MessageList, MessageListDateDivider, MessageListHistoryLimited, MessageListNotice, MessageMultiSelect, MessageMultiSelectCheckbox, MessageMultiSelectToolbar, MessageQuotedPreview, MessageQuotedPreviewAttachment, MessageQuotedPreviewAttachments, MessageQuotedPreviewAuthor, MessageQuotedPreviewAuthorMeta, MessageQuotedPreviewAuthorName, MessageQuotedPreviewChannel, MessageQuotedPreviewContent, MessageQuotedPreviewHeader, MessageQuotedPreviewLoading, MessageQuotedPreviewText, MessageQuotedPreviewThread, MessageQuotedPreviewTimestamp, MessageQuotedPreviewUnavailable, MessageReactionAddButton, MessageReactionChip, MessageReactionCount, MessageReactionErrorIndicator, MessageReactionGlyph, MessageReactionPickerContent, MessageReactionPickerStatic, MessageReactionQuickButton, MessageReactionQuickRow, MessageReactionTooltipContent, MessageReactionTooltipMeta, MessageReactionTooltipName, MessageReactionTooltipNameText, MessageReactionTooltipNames, MessageReactionTooltipSeparator, MessageReferenceChip, MessageReferenceIndicator, MessageReferenceLabel, MessageReferencePending, MessageReferenceText, MessageReferenceUnavailable, MessageReplies, MessageRepliesItem, MessageRepliesItemContent, MessageRepliesItemSender, MessageRepliesItemTime, MessageRepliesSummary, MessageRepliesSummaryItem, MessageTextSelectionToolbar, MessageTextSelectionToolbarButton, MessageTextSelectionToolbarSeparator, MessageVideoPreview, MessageVideoPreviewAction, MessageVideoPreviewFailureAction, MessageVideoPreviewFailureContent, MessageVideoPreviewFailureIcon, MessageVideoPreviewFailureTitle, MessageVideoPreviewFallback, MessageVideoPreviewMedia, MobileNavItem, MobileNavLabel, MobileNavRoot, NotificationCenter, NotificationCenterActionButton, NotificationCenterCount, NotificationCenterEmptyState, NotificationCenterHeader, NotificationCenterItem, NotificationCenterItemActions, NotificationCenterItemBody, NotificationCenterItemContent, NotificationCenterItemIcon, NotificationCenterItemRow, NotificationCenterItemTitle, NotificationCenterList, NotificationCenterPopup, NotificationCenterScroller, NotificationCenterTitle, NotificationCenterTrigger, OtterIndicator, Panel, PanelAction, PanelActions, PanelActivity, PanelBody, PanelFooter, PanelHeader, PanelHeaderContent, PanelHeaderIcon, PanelHeaderRoot, PanelHeading, PanelMeta, PanelNotice, PanelNoticeActions, PanelNoticeContent, PanelScrollContent, PanelScrollViewport, PanelSection, PanelSectionHeader, PanelStatus, PanelTitle, PanelToggleAction, PickerTriggerButton, Popover, PopoverArrow, PopoverBackdrop, PopoverClose, PopoverContent, PopoverDescription, PopoverHeader, PopoverPopup, PopoverPortal, PopoverSeparator, PopoverTitle, PopoverTrigger, PopoverViewport, PreviewCard, PreviewCardArrow, PreviewCardContent, PreviewCardDescription, PreviewCardHeader, PreviewCardPopup, PreviewCardPortal, PreviewCardSeparator, PreviewCardTitle, PreviewCardTrigger, ProfilePanel, ProfilePanelBody, ProfilePanelHeader, ProfilePanelHeaderContent, ProfilePanelSection, Progress, ProgressHeader, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, RadioGroup, RadioGroupIndicator, RadioGroupItem, RaftLogo, RaftLogoLockup, RaftWordmark, ResizableGroup, ResizableHandle, ResizablePanel, SINGLE_IMAGE_MAX_HEIGHT, SINGLE_IMAGE_MAX_WIDTH, ScrollArea, ScrollAreaContent, ScrollAreaCorner, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport, SearchEntityResult, SearchEntityResultActivity, SearchEntityResultContent, SearchEntityResultDescription, SearchEntityResultHeader, SearchEntityResultIcon, SearchEntityResultLeading, SearchEntityResultTitle, SearchMessageResult, SearchMessageResultBody, SearchMessageResultHeader, SearchMessageResultMatch, SearchMessageResultMeta, SearchMessageResultSender, SearchMessageResultThreadMeta, SearchMessageResultTimestamp, SearchResultsList, SearchResultsSection, SearchResultsSectionHeading, SearchResultsSummary, SearchShellFilters, SearchShellRoot, SearchShellViewport, SearchThreadMessageResult, SearchThreadResult, SearchThreadResultHeader, SearchThreadResultMessages, SearchThreadResultMeta, SearchThreadResultTimestamp, SearchThreadResultTitle, SearchTrigger, SearchTriggerLabel, SearchTriggerShortcut, SegmentedControl, SegmentedControlCount, SegmentedControlItem, SegmentedControlLabel, Select, SelectArrow, SelectContent, SelectGroup, SelectGroupLabel, SelectIcon, SelectItem, SelectItemDescription, SelectItemIndicator, SelectItemLeading, SelectItemText, SelectLabel, SelectList, SelectPopup, SelectPortal, SelectScrollDownArrow, SelectScrollUpArrow, SelectSeparator, SelectTrigger, SelectValue, Separator, SidebarBody, SidebarContent, SidebarControl, SidebarGroupLabel, SidebarHeader, SidebarHeaderTitle, SidebarItem, SidebarItemAside, SidebarItemChannelIcon, SidebarItemContent, SidebarItemCount, SidebarItemCountSeparator, SidebarItemIcon, SidebarItemIndicator, SidebarItemMeta, SidebarItemMetaIcon, SidebarItemStatus, SidebarItemSubtitle, SidebarItemThreadCount, SidebarItemTitle, SidebarList, SidebarLiveActivity, SidebarMenu, SidebarMenuAside, SidebarMenuCount, SidebarMenuIcon, SidebarMenuTitle, SidebarRoot, SidebarSection, SidebarSectionAttention, SidebarSectionChevron, SidebarSectionControl, SidebarSectionControls, SidebarSectionCount, SidebarSectionDisclosure, SidebarSectionEmpty, SidebarSectionHeader, SidebarSectionTitle, SidebarSectionTrailing, Skeleton, SortableComposerAttachment, SortableComposerAttachments, SortableComposerAttachmentsScroll, SortableTabsList, SortableTabsTab, Spinner, Status, Step, Steps, Switch, SwitchThumb, SystemMessage, SystemMessageContent, SystemMessageGroup, SystemMessageGroupChevron, SystemMessageGroupDisclosure, SystemMessageGroupHeader, SystemMessageGroupPanel, SystemMessageGroupSummary, SystemMessageTime, TASK_STATUS_IDS, Table, TableBody, TableCaption, TableCell, TableColgroup, TableColumn, TableHead, TableHeader, TableRow, Tabs, TabsLabel, TabsList, TabsPanel, TabsTab, TaskBoardColumn, TaskBoardColumnBadge, TaskBoardColumnChevron, TaskBoardColumnCount, TaskBoardColumnEmpty, TaskBoardColumnEmptyAllowed, TaskBoardColumnEmptyBlocked, TaskBoardColumnEmptyIdle, TaskBoardColumnHeading, TaskBoardColumnItems, TaskBoardColumnPanel, TaskBoardColumnTrigger, TaskBoardRoot, TaskCard, TaskCardBody, TaskCardChannel, TaskCardDescription, TaskCardLegacy, TaskCardMeta, TaskCardNumber, TaskCardRow, TaskCardStatus, TaskCardTitle, TaskChip, TaskClosedIcon, TaskDndProvider, TaskDoneIcon, TaskDragOverlay, TaskDraggable, TaskDropPlaceholder, TaskDropZone, TaskInProgressIcon, TaskInReviewIcon, TaskListRoot, TaskLoadingList, TaskLoadingRow, TaskSection, TaskSectionBadge, TaskSectionChevron, TaskSectionCount, TaskSectionEmpty, TaskSectionHeading, TaskSectionItems, TaskSectionPanel, TaskSectionTrigger, TaskStatusBadge, TaskStatusIcon, TaskTodoIcon, TasksPanelEmpty, TasksPanelRoot, TasksPanelToolbar, TasksPanelToolbarFilters, TasksPanelToolbarGroup, TasksPanelToolbarLabel, TasksPanelToolbarNewTask, TasksPanelToolbarView, TasksPanelViewport, Text, TextHeading, TextLink, TextMono, TextSans, Textarea, TextareaCounter, TextareaGroup, ThemeProvider, ThreadIcon, ThreadPanelActions, ThreadPanelBody, ThreadPanelContent, ThreadPanelFooter, ThreadPanelHeader, ThreadPanelOriginalMessage, ThreadPanelReplyCount, ThreadPanelReplySummary, ThreadPanelRoot, ThreadPanelSearch, ThreadPanelSearchCount, ThreadPanelSearchTrailing, ThreadPanelTitle, ThreadPanelTitleMeta, Timeline, TimelineContent, TimelineItem, TimelineTime, TimelineTitle, ToastAction, ToastActions, ToastArrow, ToastBody, ToastClose, ToastContent, ToastDescription, ToastIcon, ToastPortal, ToastPositioner, ToastProgress, ToastProvider, ToastRoot, ToastTitle, ToastViewport, ToggleGroup, ToggleGroupItem, ToggleGroupLabel, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, VirtualList, buildMessageImageGalleryRows, buttonVariants, classifyMessageImageAspect, cn, createMessageTextSelectionAnchor, createToastManager, getTextSelectionFocusRect, installInputModality, taskStatusSoft, taskStatusStrong, textLinkVariants, toast, useComposerSuggestions, useOrderedTabs, useTheme, useToastManager };