UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

87 lines (86 loc) 3.41 kB
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';