@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
82 lines (80 loc) • 2.64 kB
JavaScript
"use client";
import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from "../ScrollArea/atoms.mjs";
import { Children, cloneElement, useCallback, useEffect, useRef } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { createStaticStyles, cx } from "antd-style";
import { useMergeRefs } from "react-merge-refs";
import { Virtualizer } from "virtua";
//#region src/base-ui/virtual/VirtualScrollArea.tsx
const styles = createStaticStyles(({ css }) => ({
root: css`
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
margin-inline: calc(-1 * var(--lobe-virtual-scroll-inset, 0px));
`,
viewport: css`
flex: 1;
height: auto;
min-height: 0;
padding-inline: var(--lobe-virtual-scroll-inset, 0);
`
}));
const INITIAL_ROW_COUNT = 20;
const VirtualScrollArea = ({ children, className, itemSize, keepMounted, viewport, viewportProps, virtualizerRef, ...rest }) => {
const viewportRef = useRef(null);
const mergedViewportRef = useMergeRefs([viewportRef, viewportProps?.ref]);
const list = /* @__PURE__ */ jsx(Virtualizer, {
itemSize,
keepMounted,
ref: virtualizerRef,
scrollRef: viewportRef,
ssrCount: Math.min(INITIAL_ROW_COUNT, Children.count(children)),
children
});
const viewportElement = /* @__PURE__ */ jsx(ScrollAreaViewport, {
tabIndex: -1,
...viewportProps,
className: cx(styles.viewport, viewportProps?.className),
ref: mergedViewportRef
});
return /* @__PURE__ */ jsxs(ScrollAreaRoot, {
"data-virtual": "",
...rest,
className: cx(styles.root, className),
children: [cloneElement(viewport ?? viewportElement, {
children: list,
...viewport && { render: viewportElement }
}), /* @__PURE__ */ jsx(ScrollAreaScrollbar, { children: /* @__PURE__ */ jsx(ScrollAreaThumb, {}) })]
});
};
VirtualScrollArea.displayName = "VirtualScrollArea";
function usePointerScrollGuard() {
const pointerScrollRef = useRef(false);
const timeoutRef = useRef(null);
const markPointerScroll = useCallback(() => {
pointerScrollRef.current = true;
if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(() => {
pointerScrollRef.current = false;
}, 120);
}, []);
useEffect(() => {
return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
};
}, []);
return {
markPointerScroll,
pointerScrollRef,
scrollGuardProps: {
onPointerDown: markPointerScroll,
onTouchMove: markPointerScroll,
onWheel: markPointerScroll
}
};
}
//#endregion
export { VirtualScrollArea, usePointerScrollGuard };
//# sourceMappingURL=VirtualScrollArea.mjs.map