@legendapp/list
Version:
Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.
1,499 lines (1,467 loc) • 270 kB
JavaScript
'use strict';
var React3 = require('react');
var shim = require('use-sync-external-store/shim');
var ReactDOM = require('react-dom');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
// src/components/LegendList.tsx
React3.forwardRef(function AnimatedView2(props, ref) {
return /* @__PURE__ */ React3__namespace.createElement("div", { ref, ...props });
});
var View = React3.forwardRef(function View2(props, ref) {
return /* @__PURE__ */ React3__namespace.createElement("div", { ref, ...props });
});
var Text = View;
// src/platform/Platform.ts
var Platform = {
// Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
OS: "web"
};
// src/utils/rtl.ts
function clampHorizontalOffset(offset, maxOffset) {
if (maxOffset === void 0) {
return offset;
}
return Math.max(0, Math.min(maxOffset, offset));
}
function getHorizontalMaxOffset(state, contentWidth) {
if (contentWidth === void 0 || !Number.isFinite(contentWidth) || !Number.isFinite(state.scrollLength) || contentWidth <= state.scrollLength) {
return contentWidth !== void 0 && Number.isFinite(contentWidth) && Number.isFinite(state.scrollLength) ? 0 : void 0;
}
return Math.max(0, contentWidth - state.scrollLength);
}
function getDefaultHorizontalRTLScrollType() {
return "normal" ;
}
function getNativeHorizontalRTLScrollType(state) {
var _a3;
return (_a3 = state == null ? void 0 : state.horizontalRTLScrollType) != null ? _a3 : getDefaultHorizontalRTLScrollType();
}
function isRTLProps(props) {
var _a3;
return (_a3 = props == null ? void 0 : props.rtl) != null ? _a3 : false;
}
function isHorizontalRTL(state) {
return isHorizontalRTLProps(state == null ? void 0 : state.props);
}
function isHorizontalRTLProps(props) {
return !!(props == null ? void 0 : props.horizontal) && isRTLProps(props);
}
function getLogicalHorizontalMaxOffset(state, contentWidth) {
var _a3;
return (_a3 = getHorizontalMaxOffset(state, contentWidth)) != null ? _a3 : 0;
}
function getHorizontalInsetEnd(state, inset) {
if (!inset) {
return 0;
}
return (isHorizontalRTL(state) ? inset.left : inset.right) || 0;
}
function toPhysicalHorizontalItemPosition(state, logicalPosition, itemSize, listSize) {
if (!isHorizontalRTL(state) || listSize === void 0 || !Number.isFinite(listSize)) {
return logicalPosition;
}
return Math.max(0, listSize - logicalPosition - itemSize);
}
function toNativeHorizontalOffset(state, logicalOffset, contentWidth) {
if (!state || !isHorizontalRTL(state)) {
return logicalOffset;
}
const maxOffset = getHorizontalMaxOffset(state, contentWidth);
const clampedLogicalOffset = clampHorizontalOffset(logicalOffset, maxOffset);
const mode = getNativeHorizontalRTLScrollType(state);
if (mode === "negative") {
return clampedLogicalOffset === 0 ? 0 : -clampedLogicalOffset;
}
if (mode === "inverted") {
if (maxOffset === void 0) {
return clampedLogicalOffset;
}
return clampHorizontalOffset(maxOffset - clampedLogicalOffset, maxOffset);
}
return clampedLogicalOffset;
}
function toLogicalHorizontalOffset(state, rawOffset, contentWidth) {
if (!isHorizontalRTL(state)) {
state.horizontalRTLScrollType = void 0;
return rawOffset;
}
const maxOffset = getHorizontalMaxOffset(state, contentWidth);
if (rawOffset < 0) {
state.horizontalRTLScrollType = "negative";
return clampHorizontalOffset(-rawOffset, maxOffset);
}
if (maxOffset === void 0) {
return rawOffset;
}
const normalOffset = rawOffset;
const invertedOffset = maxOffset - rawOffset;
if (!Number.isFinite(invertedOffset)) {
state.horizontalRTLScrollType = "normal";
return normalOffset;
}
const previousMode = state.horizontalRTLScrollType;
if (previousMode === "inverted") {
return clampHorizontalOffset(invertedOffset, maxOffset);
}
if (previousMode === "normal") {
return clampHorizontalOffset(normalOffset, maxOffset);
}
if (!state.hasScrolled) {
const defaultMode = getDefaultHorizontalRTLScrollType();
state.horizontalRTLScrollType = defaultMode;
return clampHorizontalOffset(normalOffset, maxOffset);
}
const referenceScroll = state.scroll;
const distanceNormal = Math.abs(normalOffset - referenceScroll);
const distanceInverted = Math.abs(invertedOffset - referenceScroll);
const useInverted = distanceInverted + 0.5 < distanceNormal;
state.horizontalRTLScrollType = useInverted ? "inverted" : "normal";
return clampHorizontalOffset(useInverted ? invertedOffset : normalOffset, maxOffset);
}
// src/platform/Animated.tsx
var createAnimatedValue = (value) => value;
// src/state/state.tsx
var ContextState = React3__namespace.createContext(null);
var contextNum = 0;
function StateProvider({ children }) {
const [value] = React3__namespace.useState(() => ({
animatedScrollY: createAnimatedValue(0),
columnWrapperStyle: void 0,
contextNum: contextNum++,
listeners: /* @__PURE__ */ new Map(),
mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
mapViewabilityValues: /* @__PURE__ */ new Map(),
positionListeners: /* @__PURE__ */ new Map(),
state: void 0,
values: /* @__PURE__ */ new Map([
["stylePaddingTop", 0],
["headerSize", 0],
["numContainers", 0],
["activeStickyIndex", -1],
["isAtEnd", false],
["isAtStart", false],
["isNearEnd", false],
["isNearStart", false],
["isWithinMaintainScrollAtEndThreshold", false],
["totalSize", 0],
["scrollAdjustPending", 0]
]),
viewRefs: /* @__PURE__ */ new Map()
}));
return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
}
function useStateContext() {
return React3__namespace.useContext(ContextState);
}
function createSelectorFunctionsArr(ctx, signalNames) {
let lastValues = [];
let lastSignalValues = [];
return {
get: () => {
const currentValues = [];
let hasChanged = false;
for (let i = 0; i < signalNames.length; i++) {
const value = peek$(ctx, signalNames[i]);
currentValues.push(value);
if (value !== lastSignalValues[i]) {
hasChanged = true;
}
}
lastSignalValues = currentValues;
if (hasChanged) {
lastValues = currentValues;
}
return lastValues;
},
subscribe: (cb) => {
const listeners = [];
for (const signalName of signalNames) {
listeners.push(listen$(ctx, signalName, cb));
}
return () => {
for (const listener of listeners) {
listener();
}
};
}
};
}
function listen$(ctx, signalName, cb) {
const { listeners } = ctx;
let setListeners = listeners.get(signalName);
if (!setListeners) {
setListeners = /* @__PURE__ */ new Set();
listeners.set(signalName, setListeners);
}
setListeners.add(cb);
return () => setListeners.delete(cb);
}
function peek$(ctx, signalName) {
const { values } = ctx;
return values.get(signalName);
}
function set$(ctx, signalName, value) {
const { listeners, values } = ctx;
if (values.get(signalName) !== value) {
values.set(signalName, value);
const setListeners = listeners.get(signalName);
if (setListeners) {
for (const listener of setListeners) {
listener(value);
}
}
}
}
function listenPosition$(ctx, key, cb) {
const { positionListeners } = ctx;
let setListeners = positionListeners.get(key);
if (!setListeners) {
setListeners = /* @__PURE__ */ new Set();
positionListeners.set(key, setListeners);
}
setListeners.add(cb);
return () => setListeners.delete(cb);
}
function notifyPosition$(ctx, key, value) {
const { positionListeners } = ctx;
const setListeners = positionListeners.get(key);
if (setListeners) {
for (const listener of setListeners) {
listener(value);
}
}
}
function useArr$(signalNames) {
const ctx = React3__namespace.useContext(ContextState);
const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
const value = shim.useSyncExternalStore(subscribe, get, get);
return value;
}
function useSelector$(signalName, selector) {
const ctx = React3__namespace.useContext(ContextState);
const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
const getSelectedValue = React3__namespace.useCallback(() => selector(get()[0]), [get, selector]);
const value = shim.useSyncExternalStore(subscribe, getSelectedValue, getSelectedValue);
return value;
}
// src/state/getContentInsetEnd.ts
function getContentInsetEndAdjustmentEnd(adjustment) {
return Math.max(0, adjustment != null ? adjustment : 0);
}
function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
var _a3, _b;
const state = ctx.state;
const { props } = state;
const horizontal = props.horizontal;
const contentInset = props.contentInset;
const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
const baseEndInset = (horizontal ? getHorizontalInsetEnd(state, baseInset) : baseInset == null ? void 0 : baseInset.bottom) || 0;
const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd(
contentInsetEndAdjustmentOverride != null ? contentInsetEndAdjustmentOverride : props.contentInsetEndAdjustment
);
const anchoredEndSpaceSize = peek$(ctx, "anchoredEndSpaceSize");
const anchoredEndInset = ((_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
const adjustedBaseEndInset = baseEndInset + contentInsetEndAdjustment;
if (overrideInset) {
const mergedInset = { bottom: 0, left: 0, right: 0, ...baseInset, ...overrideInset };
return Math.max(
((horizontal ? getHorizontalInsetEnd(state, mergedInset) : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
anchoredEndInset
);
}
return Math.max(adjustedBaseEndInset, anchoredEndInset);
}
// src/state/getContentSize.ts
function getContentSize(ctx) {
var _a3;
const { values, state } = ctx;
const stylePaddingTop = values.get("stylePaddingTop") || 0;
const stylePaddingBottom = state.props.stylePaddingBottom || 0;
const headerSize = values.get("headerSize") || 0;
const footerSize = values.get("footerSize") || 0;
const contentInsetBottom = getContentInsetEnd(ctx);
const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
}
// src/components/DebugView.tsx
var DebugRow = ({ children }) => {
return /* @__PURE__ */ React3__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
};
React3__namespace.memo(function DebugView2() {
const ctx = useStateContext();
const [
totalSize = 0,
scrollAdjust = 0,
rawScroll = 0,
scroll = 0,
_numContainers = 0,
_numContainersPooled = 0,
isAtEnd = false
] = useArr$([
"totalSize",
"scrollAdjust",
"debugRawScroll",
"debugComputedScroll",
"numContainers",
"numContainersPooled",
"isAtEnd"
]);
const contentSize = getContentSize(ctx);
const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
useInterval(() => {
forceUpdate();
}, 100);
return /* @__PURE__ */ React3__namespace.createElement(
View,
{
pointerEvents: "none",
style: {
// height: 100,
backgroundColor: "#FFFFFFCC",
borderRadius: 4,
padding: 4,
paddingBottom: 4,
paddingLeft: 4,
position: "absolute",
right: 0,
top: 0
}
},
/* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, totalSize.toFixed(2))),
/* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, contentSize.toFixed(2))),
/* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, String(isAtEnd))),
/* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
/* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, rawScroll.toFixed(2))),
/* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, scroll.toFixed(2)))
);
});
function useInterval(callback, delay) {
React3.useEffect(() => {
const interval = setInterval(callback, delay);
return () => clearInterval(interval);
}, [delay]);
}
// src/utils/devEnvironment.ts
var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
var _a;
var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
var _a2;
var IS_DEV = (_a2 = processDev != null ? processDev : metroDev) != null ? _a2 : false;
// src/constants.ts
var POSITION_OUT_OF_VIEW = -1e7;
var EDGE_POSITION_EPSILON = 1;
var ENABLE_DEVMODE = IS_DEV && false;
var ENABLE_DEBUG_VIEW = IS_DEV && false;
var typedForwardRef = React3__namespace.forwardRef;
var typedMemo = React3__namespace.memo;
var getComponent = (Component) => {
if (React3__namespace.isValidElement(Component)) {
return Component;
}
if (Component) {
return /* @__PURE__ */ React3__namespace.createElement(Component, null);
}
return null;
};
// src/utils/helpers.ts
function isFunction(obj) {
return typeof obj === "function";
}
function isArray(obj) {
return Array.isArray(obj);
}
var warned = /* @__PURE__ */ new Set();
function warnDevOnce(id, text) {
if (IS_DEV && !warned.has(id)) {
warned.add(id);
console.warn(`[legend-list] ${text}`);
}
}
function roundSize(size) {
return Math.floor(size * 8) / 8;
}
function isNullOrUndefined(value) {
return value === null || value === void 0;
}
function comparatorDefault(a, b) {
return a - b;
}
function getPadding(s, type) {
var _a3, _b, _c;
const axisPadding = type === "Left" || type === "Right" ? s.paddingHorizontal : s.paddingVertical;
return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : axisPadding) != null ? _b : s.padding) != null ? _c : 0;
}
function extractPadding(style, contentContainerStyle, type) {
return getPadding(style, type) + getPadding(contentContainerStyle, type);
}
function findContainerId(ctx, key) {
var _a3, _b;
const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
if (directMatch !== void 0) {
return directMatch;
}
const numContainers = peek$(ctx, "numContainers");
for (let i = 0; i < numContainers; i++) {
const itemKey = peek$(ctx, `containerItemKey${i}`);
if (itemKey === key) {
return i;
}
}
return -1;
}
// src/components/PositionView.tsx
var isRNWeb = typeof document !== "undefined" && !!document.getElementById("react-native-stylesheet");
var baseCss = {
contain: "paint layout style",
...isRNWeb ? {
display: "flex",
flexDirection: "column"
} : {}
};
var PositionViewState = typedMemo(function PositionViewState2({
id,
horizontal,
style,
refView,
...props
}) {
const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
const composed = isArray(style) ? Object.assign({}, ...style) : style;
const combinedStyle = horizontal ? { ...baseCss, ...composed, left: position } : { ...baseCss, ...composed, top: position };
const {
animatedScrollY: _animatedScrollY,
index,
onLayout: _onLayout,
onLayoutChange: _onLayoutChange,
stickyHeaderConfig: _stickyHeaderConfig,
...webProps
} = props;
return /* @__PURE__ */ React3__namespace.createElement("div", { "data-index": index, ref: refView, ...webProps, style: combinedStyle });
});
var PositionViewSticky = typedMemo(function PositionViewSticky2({
id,
horizontal,
style,
refView,
index,
animatedScrollY: _animatedScrollY,
stickyHeaderConfig,
onLayout: _onLayout,
onLayoutChange: _onLayoutChange,
children,
...webProps
}) {
const [position = POSITION_OUT_OF_VIEW, activeStickyIndex] = useArr$([
`containerPosition${id}`,
"activeStickyIndex"
]);
const composed = React3__namespace.useMemo(
() => {
var _a3;
return (_a3 = isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
},
[style]
);
const viewStyle = React3__namespace.useMemo(() => {
var _a3;
const styleBase = { ...baseCss, ...composed };
delete styleBase.transform;
const offset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
const isActive = activeStickyIndex === index;
styleBase.position = isActive ? "sticky" : "absolute";
styleBase.zIndex = index + 1e3;
if (horizontal) {
styleBase.left = isActive ? offset : position;
} else {
styleBase.top = isActive ? offset : position;
}
return styleBase;
}, [composed, horizontal, position, index, activeStickyIndex, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
const renderStickyHeaderBackdrop = React3__namespace.useMemo(
() => (stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent) ? /* @__PURE__ */ React3__namespace.createElement(
"div",
{
style: {
inset: 0,
pointerEvents: "none",
position: "absolute"
}
},
getComponent(stickyHeaderConfig.backdropComponent)
) : null,
[stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent]
);
return /* @__PURE__ */ React3__namespace.createElement(
"div",
{
"data-index": index,
ref: refView,
style: viewStyle,
...webProps
},
renderStickyHeaderBackdrop,
children
);
});
var PositionView = PositionViewState;
// src/constants-platform.ts
var IsNewArchitecture = true;
function useInit(cb) {
React3.useState(() => cb());
}
// src/state/ContextContainer.ts
var ContextContainer = React3.createContext(null);
function useContextContainer() {
return React3.useContext(ContextContainer);
}
function useViewability(callback, configId) {
const ctx = useStateContext();
const containerContext = useContextContainer();
useInit(() => {
if (!containerContext) {
return;
}
const { containerId } = containerContext;
const key = containerId + (configId != null ? configId : "");
const value = ctx.mapViewabilityValues.get(key);
if (value) {
callback(value);
}
});
React3.useEffect(() => {
if (!containerContext) {
return;
}
const { containerId } = containerContext;
const key = containerId + (configId != null ? configId : "");
ctx.mapViewabilityCallbacks.set(key, callback);
return () => {
ctx.mapViewabilityCallbacks.delete(key);
};
}, [ctx, callback, configId, containerContext]);
}
function useViewabilityAmount(callback) {
const ctx = useStateContext();
const containerContext = useContextContainer();
useInit(() => {
if (!containerContext) {
return;
}
const { containerId } = containerContext;
const value = ctx.mapViewabilityAmountValues.get(containerId);
if (value) {
callback(value);
}
});
React3.useEffect(() => {
if (!containerContext) {
return;
}
const { containerId } = containerContext;
ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
return () => {
ctx.mapViewabilityAmountCallbacks.delete(containerId);
};
}, [ctx, callback, containerContext]);
}
function useRecyclingEffect(effect) {
const containerContext = useContextContainer();
const prevValues = React3.useRef({
prevIndex: void 0,
prevItem: void 0
});
React3.useEffect(() => {
if (!containerContext) {
return;
}
const { index, value } = containerContext;
let ret;
if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
ret = effect({
index,
item: value,
prevIndex: prevValues.current.prevIndex,
prevItem: prevValues.current.prevItem
});
}
prevValues.current = {
prevIndex: index,
prevItem: value
};
return ret;
}, [effect, containerContext]);
}
function useRecyclingState(valueOrFun) {
var _a3, _b;
const containerContext = useContextContainer();
const computeValue = (ctx) => {
if (isFunction(valueOrFun)) {
const initializer = valueOrFun;
return ctx ? initializer({
index: ctx.index,
item: ctx.value,
prevIndex: void 0,
prevItem: void 0
}) : initializer();
}
return valueOrFun;
};
const [stateValue, setStateValue] = React3.useState(() => {
return computeValue(containerContext);
});
const prevItemKeyRef = React3.useRef((_a3 = containerContext == null ? void 0 : containerContext.itemKey) != null ? _a3 : null);
const currentItemKey = (_b = containerContext == null ? void 0 : containerContext.itemKey) != null ? _b : null;
if (currentItemKey !== null && prevItemKeyRef.current !== currentItemKey) {
prevItemKeyRef.current = currentItemKey;
setStateValue(computeValue(containerContext));
}
const triggerLayout = containerContext == null ? void 0 : containerContext.triggerLayout;
const setState = React3.useCallback(
(newState) => {
if (!triggerLayout) {
return;
}
setStateValue((prevValue) => {
return isFunction(newState) ? newState(prevValue) : newState;
});
triggerLayout();
},
[triggerLayout]
);
return [stateValue, setState];
}
function useIsLastItem() {
const containerContext = useContextContainer();
const isLast = useSelector$("lastItemKeys", (lastItemKeys) => {
if (containerContext) {
const { itemKey } = containerContext;
if (!isNullOrUndefined(itemKey)) {
return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
}
}
return false;
});
return isLast;
}
function useListScrollSize() {
const [scrollSize] = useArr$(["scrollSize"]);
return scrollSize;
}
var noop = () => {
};
function useSyncLayout() {
const containerContext = useContextContainer();
if (containerContext) {
const { triggerLayout: syncLayout } = containerContext;
return syncLayout;
} else {
return noop;
}
}
// src/components/Separator.tsx
function Separator({ ItemSeparatorComponent, leadingItem }) {
const isLastItem = useIsLastItem();
return isLastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
}
// src/hooks/createResizeObserver.ts
var globalResizeObserver = null;
function getGlobalResizeObserver() {
if (!globalResizeObserver) {
globalResizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const callbacks = callbackMap.get(entry.target);
if (callbacks) {
for (const callback of callbacks) {
callback(entry);
}
}
}
});
}
return globalResizeObserver;
}
var callbackMap = /* @__PURE__ */ new WeakMap();
function createResizeObserver(element, callback) {
if (typeof ResizeObserver === "undefined") {
return () => {
};
}
if (!element) {
return () => {
};
}
const observer = getGlobalResizeObserver();
let callbacks = callbackMap.get(element);
if (!callbacks) {
callbacks = /* @__PURE__ */ new Set();
callbackMap.set(element, callbacks);
observer.observe(element);
}
callbacks.add(callback);
return () => {
if (callbacks) {
callbacks.delete(callback);
if (callbacks.size === 0) {
callbackMap.delete(element);
observer.unobserve(element);
}
}
};
}
// src/hooks/useOnLayoutSync.tsx
function useOnLayoutSync({
ref,
onLayoutProp,
onLayoutChange,
webLayoutResync
}, deps) {
React3.useLayoutEffect(() => {
var _a3, _b;
const current = ref.current;
const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
const element = scrollableNode || current;
if (!element) {
return;
}
const emit = (layout, fromLayoutEffect) => {
if (layout.height === 0 && layout.width === 0) {
return;
}
onLayoutChange(layout, fromLayoutEffect);
onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
};
const rect = element.getBoundingClientRect();
emit(toLayout(rect), true);
let prevRect = rect;
return createResizeObserver(element, (entry) => {
var _a4;
const target = entry.target instanceof HTMLElement ? entry.target : void 0;
const rectObserved = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
const didSizeChange = rectObserved.width !== prevRect.width || rectObserved.height !== prevRect.height;
const shouldResyncLayout = !!(webLayoutResync == null ? void 0 : webLayoutResync());
if (didSizeChange || shouldResyncLayout) {
prevRect = rectObserved;
emit(toLayout(rectObserved), false);
}
});
}, deps || []);
return {};
}
function toLayout(rect) {
if (!rect) {
return { height: 0, width: 0, x: 0, y: 0 };
}
return {
height: rect.height,
width: rect.width,
x: rect.left,
y: rect.top
};
}
// src/utils/hasActiveMVCPAnchorLock.ts
function hasActiveMVCPAnchorLock(state) {
const lock = state.mvcpAnchorLock;
if (!lock) {
return false;
}
if (Date.now() > lock.expiresAt) {
state.mvcpAnchorLock = void 0;
return false;
}
return true;
}
// src/utils/isInMVCPActiveMode.ts
function isInMVCPActiveMode(state) {
return state.dataChangeNeedsScrollUpdate || hasActiveMVCPAnchorLock(state);
}
// src/components/Container.tsx
function getContainerPositionStyle({
columnWrapperStyle,
horizontal,
hasItemSeparator,
isHorizontalRTLList,
numColumns,
otherAxisPos,
otherAxisSize
}) {
let paddingStyles;
if (columnWrapperStyle) {
const { columnGap, rowGap, gap } = columnWrapperStyle;
if (horizontal) {
paddingStyles = {
paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
paddingRight: columnGap || gap || void 0,
paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
};
} else {
paddingStyles = {
paddingBottom: rowGap || gap || void 0,
paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
};
}
}
return horizontal ? {
boxSizing: paddingStyles ? "border-box" : void 0,
direction: isHorizontalRTLList && Platform.OS === "web" ? "ltr" : void 0,
flexDirection: hasItemSeparator ? "row" : void 0,
height: otherAxisSize,
left: 0,
position: "absolute",
top: otherAxisPos,
...paddingStyles || {}
} : {
boxSizing: paddingStyles ? "border-box" : void 0,
left: otherAxisPos,
position: "absolute",
right: numColumns > 1 ? null : 0,
top: 0,
width: otherAxisSize,
...paddingStyles || {}
};
}
var Container = typedMemo(function Container2({
id,
itemKey,
recycleItems,
horizontal,
getRenderedItem: getRenderedItem2,
updateItemSize: updateItemSize2,
ItemSeparatorComponent,
stickyHeaderConfig
}) {
const ctx = useStateContext();
const { columnWrapperStyle, animatedScrollY } = ctx;
const isHorizontalRTLList = isHorizontalRTL(ctx.state);
const positionComponentInternal = ctx.state.props.positionComponentInternal;
const stickyPositionComponentInternal = ctx.state.props.stickyPositionComponentInternal;
const [column = 0, span = 1, data, numColumns = 1, extraData, isSticky] = useArr$([
`containerColumn${id}`,
`containerSpan${id}`,
`containerItemData${id}`,
"numColumns",
"extraData",
`containerSticky${id}`
]);
const itemLayoutRef = React3.useRef({
didLayout: false,
horizontal,
itemKey,
pendingShrinkToken: 0,
updateItemSize: updateItemSize2
});
itemLayoutRef.current.horizontal = horizontal;
itemLayoutRef.current.itemKey = itemKey;
itemLayoutRef.current.updateItemSize = updateItemSize2;
const ref = React3.useRef(null);
const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
const resolvedColumn = column > 0 ? column : 1;
const resolvedSpan = Math.min(Math.max(span || 1, 1), numColumns);
const otherAxisPos = numColumns > 1 ? `${(resolvedColumn - 1) / numColumns * 100}%` : 0;
const otherAxisSize = numColumns > 1 ? `${resolvedSpan / numColumns * 100}%` : void 0;
const style = React3.useMemo(
() => getContainerPositionStyle({
columnWrapperStyle,
hasItemSeparator: !!ItemSeparatorComponent,
horizontal,
isHorizontalRTLList,
numColumns,
otherAxisPos,
otherAxisSize
}),
[
horizontal,
isHorizontalRTLList,
otherAxisPos,
otherAxisSize,
columnWrapperStyle,
numColumns,
ItemSeparatorComponent
]
);
const renderedItemInfo = React3.useMemo(
() => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
[itemKey, data, extraData]
);
const { index, renderedItem } = renderedItemInfo || {};
const contextValue = React3.useMemo(() => {
ctx.viewRefs.set(id, ref);
return {
containerId: id,
index,
itemKey,
triggerLayout: () => {
forceLayoutRender((v) => v + 1);
},
value: data
};
}, [id, itemKey, index, data]);
const onLayoutChange = React3.useCallback((rectangle) => {
const {
horizontal: currentHorizontal,
itemKey: currentItemKey,
updateItemSize: updateItemSizeFn,
lastSize,
pendingShrinkToken
} = itemLayoutRef.current;
if (isNullOrUndefined(currentItemKey)) {
return;
}
itemLayoutRef.current.didLayout = true;
let layout = rectangle;
const axis = currentHorizontal ? "width" : "height";
const size = roundSize(rectangle[axis]);
const prevSize = lastSize ? roundSize(lastSize[axis]) : void 0;
const doUpdate = () => {
itemLayoutRef.current.lastSize = layout;
updateItemSizeFn(currentItemKey, layout);
itemLayoutRef.current.didLayout = true;
};
const shouldDeferWebShrinkLayoutUpdate = !isInMVCPActiveMode(ctx.state) && prevSize !== void 0 && size + 1 < prevSize;
if (shouldDeferWebShrinkLayoutUpdate) {
const token = pendingShrinkToken + 1;
itemLayoutRef.current.pendingShrinkToken = token;
requestAnimationFrame(() => {
var _a4;
if (itemLayoutRef.current.pendingShrinkToken !== token) {
return;
}
const element = ref.current;
const rect = (_a4 = element == null ? void 0 : element.getBoundingClientRect) == null ? void 0 : _a4.call(element);
if (rect) {
layout = { height: rect.height, width: rect.width };
}
doUpdate();
});
return;
}
{
doUpdate();
}
}, []);
const { onLayout } = useOnLayoutSync(
{
onLayoutChange,
ref,
webLayoutResync: () => isInMVCPActiveMode(ctx.state)
},
[itemKey, layoutRenderCount]
);
const PositionComponent = isSticky ? stickyPositionComponentInternal ? stickyPositionComponentInternal : PositionViewSticky : positionComponentInternal ? positionComponentInternal : PositionView;
return /* @__PURE__ */ React3__namespace.createElement(
PositionComponent,
{
animatedScrollY: isSticky ? animatedScrollY : void 0,
horizontal,
id,
index,
key: recycleItems ? void 0 : itemKey,
onLayout,
refView: ref,
stickyHeaderConfig,
style
},
/* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
);
});
// src/components/ContainerSlot.tsx
function ContainerSlotBase({
id,
horizontal,
recycleItems,
ItemSeparatorComponent,
updateItemSize: updateItemSize2,
getRenderedItem: getRenderedItem2,
stickyHeaderConfig,
ContainerComponent = Container
}) {
const [itemKey] = useArr$([`containerItemKey${id}`]);
if (itemKey === void 0) {
return null;
}
return /* @__PURE__ */ React3__namespace.createElement(
ContainerComponent,
{
getRenderedItem: getRenderedItem2,
horizontal,
ItemSeparatorComponent,
id,
itemKey,
recycleItems,
stickyHeaderConfig,
updateItemSize: updateItemSize2
}
);
}
var ContainerSlot = typedMemo(function ContainerSlot2(props) {
return /* @__PURE__ */ React3__namespace.createElement(ContainerSlotBase, { ...props });
});
// src/utils/reordering.ts
var mapFn = (element) => {
const indexStr = element.getAttribute("data-index");
if (indexStr === null) {
return [element, null];
}
const index = Number.parseInt(indexStr, 10);
return [element, Number.isNaN(index) ? null : index];
};
function sortDOMElements(container) {
const elements = Array.from(container.children);
if (elements.length <= 1) return elements;
const items = elements.map(mapFn);
items.sort((a, b) => {
const aKey = a[1];
const bKey = b[1];
if (aKey === null) {
return 1;
}
if (bKey === null) {
return -1;
}
return aKey - bKey;
});
const targetPositions = /* @__PURE__ */ new Map();
items.forEach((item, index) => {
targetPositions.set(item[0], index);
});
const currentPositions = elements.map((el) => targetPositions.get(el));
const lis = findLIS(currentPositions);
const stableIndices = new Set(lis);
for (let targetPos = 0; targetPos < items.length; targetPos++) {
const element = items[targetPos][0];
const currentPos = elements.indexOf(element);
if (!stableIndices.has(currentPos)) {
let nextStableElement = null;
for (let i = targetPos + 1; i < items.length; i++) {
const nextEl = items[i][0];
const nextCurrentPos = elements.indexOf(nextEl);
if (stableIndices.has(nextCurrentPos)) {
nextStableElement = nextEl;
break;
}
}
if (nextStableElement) {
container.insertBefore(element, nextStableElement);
} else {
container.appendChild(element);
}
}
}
}
function findLIS(arr) {
const n = arr.length;
const tails = [];
const predecessors = new Array(n).fill(-1);
const indices = [];
for (let i = 0; i < n; i++) {
const num = arr[i];
let left = 0, right = tails.length;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (arr[indices[mid]] < num) {
left = mid + 1;
} else {
right = mid;
}
}
if (left === tails.length) {
tails.push(num);
indices.push(i);
} else {
tails[left] = num;
indices[left] = i;
}
if (left > 0) {
predecessors[i] = indices[left - 1];
}
}
const result = [];
let k = indices[indices.length - 1];
while (k !== -1) {
result.unshift(k);
k = predecessors[k];
}
return result;
}
// src/hooks/useDOMOrder.ts
function useDOMOrder(ref) {
const ctx = useStateContext();
const debounceRef = React3.useRef(void 0);
React3.useEffect(() => {
const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
if (debounceRef.current !== void 0) {
clearTimeout(debounceRef.current);
}
debounceRef.current = setTimeout(() => {
const parent = ref.current;
if (parent) {
sortDOMElements(parent);
}
debounceRef.current = void 0;
}, 500);
});
return () => {
unsubscribe();
if (debounceRef.current !== void 0) {
clearTimeout(debounceRef.current);
}
};
}, [ctx]);
}
// src/components/Containers.tsx
var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
const ref = React3.useRef(null);
const ctx = useStateContext();
const columnWrapperStyle = ctx.columnWrapperStyle;
const isHorizontalRTLList = isHorizontalRTL(ctx.state);
const [otherAxisSize, readyToRender, totalSize] = useArr$(["otherAxisSize", "readyToRender", "totalSize"]);
useDOMOrder(ref);
const style = horizontal ? {
direction: isHorizontalRTLList ? "ltr" : void 0,
minHeight: otherAxisSize,
opacity: readyToRender ? 1 : 0,
position: "relative",
width: totalSize
} : { height: totalSize, minWidth: otherAxisSize, opacity: readyToRender ? 1 : 0, position: "relative" };
if (!readyToRender) {
style.pointerEvents = "none";
}
if (columnWrapperStyle && numColumns > 1) {
const { columnGap, rowGap, gap } = columnWrapperStyle;
const gapX = columnGap || gap || 0;
const gapY = rowGap || gap || 0;
if (horizontal) {
if (gapY) {
style.marginTop = style.marginBottom = -gapY / 2;
}
if (gapX) {
style.marginRight = -gapX;
}
} else {
if (gapY) {
style.marginBottom = -gapY;
}
}
}
return /* @__PURE__ */ React3__namespace.createElement("div", { ref, style }, children);
});
var Containers = typedMemo(function Containers2({
horizontal,
recycleItems,
ItemSeparatorComponent,
updateItemSize: updateItemSize2,
getRenderedItem: getRenderedItem2,
stickyHeaderConfig
}) {
const [numContainersPooled, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
const containers = [];
for (let i = 0; i < numContainersPooled; i++) {
containers.push(
/* @__PURE__ */ React3__namespace.createElement(
ContainerSlot,
{
getRenderedItem: getRenderedItem2,
horizontal,
ItemSeparatorComponent,
id: i,
key: i,
recycleItems,
stickyHeaderConfig,
updateItemSize: updateItemSize2
}
)
);
}
return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns }, containers);
});
// src/platform/StyleSheet.tsx
function flattenStyles(styles) {
if (isArray(styles)) {
return Object.assign({}, ...styles.filter(Boolean));
}
return styles;
}
var StyleSheet = {
create: (styles) => styles,
flatten: (style) => flattenStyles(style)
};
function useLatestRef(value) {
const ref = React3__namespace.useRef(value);
ref.current = value;
return ref;
}
// src/utils/useRafCoalescer.ts
function useRafCoalescer(callback) {
const callbackRef = useLatestRef(callback);
const rafIdRef = React3.useRef(void 0);
const coalescer = React3.useMemo(
() => ({
cancel() {
if (rafIdRef.current !== void 0) {
cancelAnimationFrame(rafIdRef.current);
rafIdRef.current = void 0;
}
},
flush() {
coalescer.cancel();
callbackRef.current();
},
schedule() {
if (rafIdRef.current !== void 0) {
return false;
}
const rafId = requestAnimationFrame(() => {
if (rafIdRef.current !== rafId) {
return;
}
rafIdRef.current = void 0;
callbackRef.current();
});
rafIdRef.current = rafId;
return true;
}
}),
[]
);
React3.useEffect(
() => () => {
coalescer.cancel();
},
[coalescer]
);
return coalescer;
}
// src/components/webConstants.ts
var LEGEND_LIST_CONTENT_CONTAINER_CLASS = "legend-list-content-container";
var LEGEND_LIST_SCROLLBAR_X_HIDDEN_CLASS = "legend-list-scrollbar-x-hidden";
var LEGEND_LIST_SCROLLBAR_Y_HIDDEN_CLASS = "legend-list-scrollbar-y-hidden";
// src/components/webScrollUtils.ts
function getDocumentScrollerNode() {
if (typeof document === "undefined") {
return null;
}
return document.scrollingElement || document.documentElement || document.body;
}
function getWindowScrollPosition() {
var _a3, _b, _c, _d;
if (typeof window === "undefined") {
return { x: 0, y: 0 };
}
return {
x: (_b = (_a3 = window.scrollX) != null ? _a3 : window.pageXOffset) != null ? _b : 0,
y: (_d = (_c = window.scrollY) != null ? _c : window.pageYOffset) != null ? _d : 0
};
}
function getElementDocumentPosition(element, scroll) {
var _a3, _b;
const rect = element == null ? void 0 : element.getBoundingClientRect();
return {
left: ((_a3 = rect == null ? void 0 : rect.left) != null ? _a3 : 0) + scroll.x,
top: ((_b = rect == null ? void 0 : rect.top) != null ? _b : 0) + scroll.y
};
}
function getContentSize2(content) {
var _a3, _b;
return {
height: (_a3 = content == null ? void 0 : content.scrollHeight) != null ? _a3 : 0,
width: (_b = content == null ? void 0 : content.scrollWidth) != null ? _b : 0
};
}
function getScrollContentSize(scrollElement, contentElement, isWindowScroll) {
return getContentSize2(isWindowScroll ? contentElement : scrollElement);
}
function getLayoutMeasurement(scrollElement, isWindowScroll, horizontal) {
var _a3, _b, _c, _d, _e, _f;
if (isWindowScroll && typeof window !== "undefined") {
const rect = scrollElement == null ? void 0 : scrollElement.getBoundingClientRect();
return {
// In window-scroll mode, use viewport size on the scroll axis.
height: horizontal ? (_b = (_a3 = rect == null ? void 0 : rect.height) != null ? _a3 : scrollElement == null ? void 0 : scrollElement.clientHeight) != null ? _b : window.innerHeight : window.innerHeight,
// Keep the cross-axis size list-relative to avoid inflating container measurements.
width: horizontal ? window.innerWidth : (_d = (_c = rect == null ? void 0 : rect.width) != null ? _c : scrollElement == null ? void 0 : scrollElement.clientWidth) != null ? _d : window.innerWidth
};
}
return {
height: (_e = scrollElement == null ? void 0 : scrollElement.clientHeight) != null ? _e : 0,
width: (_f = scrollElement == null ? void 0 : scrollElement.clientWidth) != null ? _f : 0
};
}
function clampOffset(offset, maxOffset) {
return Math.max(0, Math.min(offset, maxOffset));
}
function getAxisSize(size, horizontal) {
return horizontal ? size.width : size.height;
}
function getMaxOffset(contentSize, layoutMeasurement, horizontal) {
return Math.max(0, getAxisSize(contentSize, horizontal) - getAxisSize(layoutMeasurement, horizontal));
}
function resolveScrollableNode(scrollElement, isWindowScroll) {
return isWindowScroll ? getDocumentScrollerNode() || scrollElement : scrollElement;
}
function resolveScrollEventTarget(scrollElement, isWindowScroll) {
return isWindowScroll && typeof window !== "undefined" ? window : scrollElement;
}
function getLayoutRectangle(element, isWindowScroll, horizontal) {
const rect = element.getBoundingClientRect();
const scroll = getWindowScrollPosition();
return {
height: isWindowScroll && typeof window !== "undefined" && !horizontal ? window.innerHeight : rect.height,
width: isWindowScroll && typeof window !== "undefined" && horizontal ? window.innerWidth : rect.width,
x: isWindowScroll ? rect.left + scroll.x : rect.left,
y: isWindowScroll ? rect.top + scroll.y : rect.top
};
}
function resolveWindowScrollTarget({ clampedOffset, horizontal, listPos, scroll }) {
return {
left: horizontal ? listPos.left + clampedOffset : scroll.x,
top: horizontal ? scroll.y : listPos.top + clampedOffset
};
}
// src/components/ListComponentScrollView.tsx
var SCROLLBAR_HIDDEN_STYLE_ID = "legend-list-scrollbar-axis-hidden-style";
var SCROLLBAR_HIDDEN_STYLE = `.${LEGEND_LIST_SCROLLBAR_Y_HIDDEN_CLASS}::-webkit-scrollbar:vertical{width:0;display:none;}.${LEGEND_LIST_SCROLLBAR_X_HIDDEN_CLASS}::-webkit-scrollbar:horizontal{height:0;display:none;}`;
function ensureScrollbarHiddenStyle() {
if (typeof document === "undefined" || document.getElementById(SCROLLBAR_HIDDEN_STYLE_ID)) {
return;
}
const styleElement = document.createElement("style");
styleElement.id = SCROLLBAR_HIDDEN_STYLE_ID;
styleElement.textContent = SCROLLBAR_HIDDEN_STYLE;
document.head.appendChild(styleElement);
}
function getContentInsetEndAdjustmentEnd2(ctx) {
var _a3, _b;
const adjustment = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.props) == null ? void 0 : _b.contentInsetEndAdjustment;
return Math.max(0, adjustment != null ? adjustment : 0);
}
function getFiniteSnapOffsets(snapToOffsets) {
if (!(snapToOffsets == null ? void 0 : snapToOffsets.length)) {
return [];
}
const snapOffsets = [];
const seen = /* @__PURE__ */ new Set();
for (const offset of snapToOffsets) {
if (Number.isFinite(offset) && !seen.has(offset)) {
seen.add(offset);
snapOffsets.push(offset);
}
}
return snapOffsets;
}
function getSnapAnchorStyle(offset, horizontal) {
return {
height: horizontal ? "100%" : 1,
left: horizontal ? offset : 0,
pointerEvents: "none",
position: "absolute",
scrollSnapAlign: "start",
top: horizontal ? 0 : offset,
width: horizontal ? 1 : "100%"
};
}
var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView2({
children,
style,
contentContainerClassName,
contentContainerStyle,
horizontal = false,
contentOffset,
maintainVisibleContentPosition,
onScroll: onScroll2,
onMomentumScrollEnd: _onMomentumScrollEnd,
showsHorizontalScrollIndicator = true,
showsVerticalScrollIndicator = true,
refreshControl,
useWindowScroll = false,
onLayout,
...props
}, ref) {
var _a3, _b, _c, _d;
const ctx = useStateContext();
const [anchoredEndSpaceSize] = useArr$(["anchoredEndSpaceSize"]);
const scrollRef = React3.useRef(null);
const contentRef = React3.useRef(null);
const isWindowScroll = useWindowScroll;
const getScrollTarget = React3.useCallback(
() => resolveScrollEventTarget(scrollRef.current, isWindowScroll),
[isWindowScroll]
);
const getMaxScrollOffset = React3.useCallback(() => {
const scrollElement = scrollRef.current;
const contentSize = getScrollContentSize(scrollElement, contentRef.current, isWindowScroll);
const layoutMeasurement = getLayoutMeasurement(scrollElement, isWindowScroll, horizontal);
return getMaxOffset(contentSize, layoutMeasurement, horizontal);
}, [horizontal, isWindowScroll]);
const getCurrentScrollOffset = React3.useCallback(() => {
const scrollElement = scrollRef.current;
if (isWindowScroll) {
const maxOffset = getMaxScrollOffset();
const scroll = getWindowScrollPosition();
const listPos = getElementDocumentPosition(scrollElement, scroll);
const rawOffset = horizontal ? scroll.x - listPos.left : scroll.y - listPos.top;
return clampOffset(rawOffset, maxOffset);
}
if (!scrollElement) {
return 0;
}
return horizontal ? scrollElement.scrollLeft : scrollElement.scrollTop;
}, [getMaxScrollOffset, horizontal, isWindowScroll]);
const scrollToLocalOffset = React3.useCallback(
(offset, animated) => {
const scrollElement = scrollRef.current;
const target = getScrollTarget();
if (!target || typeof target.scrollTo !== "function") {
return;
}
const maxOffset = getMaxScrollOffset();
const clampedOffset = clampOffset(offset, maxOffset);
const behavior = animated ? "smooth" : "auto";
const options = { behavior };
if (isWindowScroll) {
const scroll = getWindowScrollPosition();
const listPos = getElementDocumentPosition(scrollElement, scroll);
const { left, top } = resolveWindowScrollTarget({
clampedOffset,
horizontal,
listPos,
scroll
});
options.left = left;
options.top = top;
} else if (horizontal) {
options.left = clampedOffset;
} else {
options.top = clampedOffset;
}
target.scrollTo(options);
},
[getMaxScrollOffset, getScrollTarget, horizontal, isWindowScroll]
);
React3.useImperativeHandle(ref, () => {
const api = {
getBoundingClientRect: () => {
var _a4;
return (_a4 = scrollRef.current) == null ? void 0 : _a4.ge