@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
87 lines (86 loc) • 3.41 kB
JavaScript
import { isChrome as isChromeFn } from '@ui5/webcomponents-react-base/Device';
import { useSyncRef } from '@ui5/webcomponents-react-base/internal/hooks';
import { debounce } from '@ui5/webcomponents-react-base/internal/utils/debounce';
import { clsx } from 'clsx';
import { forwardRef, useEffect, useRef, useState } from 'react';
import { FlexBoxDirection } from '../../../enums/FlexBoxDirection.js';
import { FlexBox } from '../../FlexBox/index.js';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const isChrome = isChromeFn();
export const VerticalScrollbar = /*#__PURE__*/forwardRef((props, ref) => {
const {
internalRowHeight,
tableRef,
tableBodyHeight,
scrollContainerRef,
classNames
} = props;
const [hasHorizontalScrollbar, setHasHorizontalScrollbar] = useState(false);
const [componentRef, scrollbarRef] = useSyncRef(ref);
const contentRef = useRef(null);
useEffect(() => {
const tableElement = tableRef?.current;
if (!tableElement) return;
const debouncedCheckScrollbar = debounce(() => {
requestAnimationFrame(() => {
const hasScrollbar = tableElement.offsetWidth !== tableElement.scrollWidth;
setHasHorizontalScrollbar(hasScrollbar);
});
}, 100);
const resizeObserver = new ResizeObserver(debouncedCheckScrollbar);
resizeObserver.observe(tableElement);
debouncedCheckScrollbar();
return () => {
debouncedCheckScrollbar.cancel();
resizeObserver.disconnect();
};
}, [tableRef]);
// Force style recalculation to fix Chrome scrollbar-color bug (track height not updating correctly)
useEffect(() => {
if (!isChrome) {
return;
}
if (scrollbarRef.current && contentRef.current) {
const scrollbarElement = scrollbarRef.current;
const forceScrollbarUpdate = () => {
const originalHeight = scrollbarElement.style.height;
scrollbarElement.style.height = `${tableBodyHeight + 1}px`;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
scrollbarElement.offsetHeight; // Force reflow
scrollbarElement.style.height = originalHeight ?? `${tableBodyHeight}px`;
};
requestAnimationFrame(forceScrollbarUpdate);
}
}, [tableBodyHeight, scrollContainerRef, scrollbarRef]);
return /*#__PURE__*/_jsxs(FlexBox, {
direction: FlexBoxDirection.Column,
className: classNames.verticalScrollbarContainer,
"data-component-name": "AnalyticalTableVerticalScrollbarContainer",
children: [/*#__PURE__*/_jsx("div", {
style: {
height: `${internalRowHeight}px`
},
className: classNames.headerSection
}), /*#__PURE__*/_jsx("div", {
ref: componentRef,
style: {
height: `${tableBodyHeight}px`
},
className: clsx(classNames.scrollbar),
"data-component-name": "AnalyticalTableVerticalScrollbar",
tabIndex: -1,
children: /*#__PURE__*/_jsx("div", {
ref: node => {
contentRef.current = node;
if (node && scrollContainerRef.current?.scrollHeight) {
node.style.height = `${scrollContainerRef.current?.scrollHeight}px`;
}
},
className: classNames.verticalScroller
})
}), /*#__PURE__*/_jsx("div", {
className: clsx(hasHorizontalScrollbar && classNames.bottomSection)
})]
});
});
VerticalScrollbar.displayName = 'VerticalScrollbar';