UNPKG

@grafana/ui

Version:
1 lines 12.9 kB
{"version":3,"file":"CustomScrollbar.mjs","sources":["../../../../src/components/CustomScrollbar/CustomScrollbar.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { RefCallback, useCallback, useEffect, useRef } from 'react';\nimport * as React from 'react';\nimport Scrollbars, { positionValues } from 'react-custom-scrollbars-2';\n\nimport { GrafanaTheme2 } from '@grafana/data';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\n\nimport { ScrollIndicators } from './ScrollIndicators';\n\nexport type ScrollbarPosition = positionValues;\n\ninterface Props {\n className?: string;\n testId?: string;\n autoHide?: boolean;\n autoHideTimeout?: number;\n autoHeightMax?: string;\n hideTracksWhenNotNeeded?: boolean;\n hideHorizontalTrack?: boolean;\n hideVerticalTrack?: boolean;\n scrollRefCallback?: RefCallback<HTMLDivElement>;\n scrollTop?: number;\n setScrollTop?: (position: ScrollbarPosition) => void;\n showScrollIndicators?: boolean;\n autoHeightMin?: number | string;\n updateAfterMountMs?: number;\n onScroll?: React.UIEventHandler;\n divId?: string;\n}\n\n/**\n * Wraps component into <Scrollbars> component from `react-custom-scrollbars`\n * @deprecated Use `ScrollContainer` from `@grafana/ui` instead. It uses native scrollbars and has a simpler API.\n */\nexport const CustomScrollbar = ({\n autoHide = false,\n autoHideTimeout = 200,\n setScrollTop,\n className,\n testId,\n autoHeightMin = '0',\n autoHeightMax = '100%',\n hideTracksWhenNotNeeded = false,\n hideHorizontalTrack,\n hideVerticalTrack,\n scrollRefCallback,\n showScrollIndicators = false,\n updateAfterMountMs,\n scrollTop,\n onScroll,\n children,\n divId,\n}: React.PropsWithChildren<Props>) => {\n const ref = useRef<Scrollbars & { view: HTMLDivElement; update: () => void }>(null);\n const styles = useStyles2(getStyles);\n\n useEffect(() => {\n if (ref.current && scrollRefCallback) {\n scrollRefCallback(ref.current.view);\n }\n }, [ref, scrollRefCallback]);\n\n useScrollTop(ref.current, scrollTop);\n\n /**\n * Special logic for doing a update a few milliseconds after mount to check for\n * updated height due to dynamic content\n */\n useEffect(() => {\n if (!updateAfterMountMs) {\n return;\n }\n setTimeout(() => {\n const scrollbar = ref.current;\n if (scrollbar?.update) {\n scrollbar.update();\n }\n }, updateAfterMountMs);\n }, [updateAfterMountMs]);\n\n function renderTrack(className: string, hideTrack: boolean | undefined, passedProps: JSX.IntrinsicElements['div']) {\n if (passedProps.style && hideTrack) {\n passedProps.style.display = 'none';\n }\n\n return <div {...passedProps} className={className} />;\n }\n\n const renderTrackHorizontal = useCallback(\n (passedProps: JSX.IntrinsicElements['div']) => {\n return renderTrack('track-horizontal', hideHorizontalTrack, passedProps);\n },\n [hideHorizontalTrack]\n );\n\n const renderTrackVertical = useCallback(\n (passedProps: JSX.IntrinsicElements['div']) => {\n return renderTrack('track-vertical', hideVerticalTrack, passedProps);\n },\n [hideVerticalTrack]\n );\n\n const renderThumbHorizontal = useCallback((passedProps: JSX.IntrinsicElements['div']) => {\n return <div {...passedProps} className=\"thumb-horizontal\" />;\n }, []);\n\n const renderThumbVertical = useCallback((passedProps: JSX.IntrinsicElements['div']) => {\n return <div {...passedProps} className=\"thumb-vertical\" />;\n }, []);\n\n const renderView = useCallback(\n (passedProps: JSX.IntrinsicElements['div']) => {\n // fixes issues of visibility on safari and ios devices\n if (passedProps.style && passedProps.style['WebkitOverflowScrolling'] === 'touch') {\n passedProps.style['WebkitOverflowScrolling'] = 'auto';\n }\n\n return <div {...passedProps} className=\"scrollbar-view\" id={divId} />;\n },\n [divId]\n );\n\n const onScrollStop = useCallback(() => {\n ref.current && setScrollTop && setScrollTop(ref.current.getValues());\n }, [setScrollTop]);\n\n return (\n <Scrollbars\n data-testid={testId}\n ref={ref}\n className={cx(styles.customScrollbar, className, {\n [styles.scrollbarWithScrollIndicators]: showScrollIndicators,\n })}\n onScrollStop={onScrollStop}\n autoHeight={true}\n autoHide={autoHide}\n autoHideTimeout={autoHideTimeout}\n hideTracksWhenNotNeeded={hideTracksWhenNotNeeded}\n // These autoHeightMin & autoHeightMax options affect firefox and chrome differently.\n // Before these where set to inherit but that caused problems with cut of legends in firefox\n autoHeightMax={autoHeightMax}\n autoHeightMin={autoHeightMin}\n renderTrackHorizontal={renderTrackHorizontal}\n renderTrackVertical={renderTrackVertical}\n renderThumbHorizontal={renderThumbHorizontal}\n renderThumbVertical={renderThumbVertical}\n renderView={renderView}\n onScroll={onScroll}\n >\n {showScrollIndicators ? <ScrollIndicators>{children}</ScrollIndicators> : children}\n </Scrollbars>\n );\n};\n\nexport default CustomScrollbar;\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n customScrollbar: css({\n // Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to\n // make scroll working it should fit outer container size (scroll appears only when inner container size is\n // greater than outer one).\n display: 'flex',\n flexGrow: 1,\n '.scrollbar-view': {\n display: 'flex',\n flexGrow: 1,\n flexDirection: 'column',\n },\n '.track-vertical': {\n borderRadius: theme.shape.borderRadius(2),\n width: `${theme.spacing(1)} !important`,\n right: 0,\n bottom: theme.spacing(0.25),\n top: theme.spacing(0.25),\n },\n '.track-horizontal': {\n borderRadius: theme.shape.borderRadius(2),\n height: `${theme.spacing(1)} !important`,\n right: theme.spacing(0.25),\n bottom: theme.spacing(0.25),\n left: theme.spacing(0.25),\n },\n '.thumb-vertical': {\n background: theme.colors.action.focus,\n borderRadius: theme.shape.borderRadius(2),\n opacity: 0,\n },\n '.thumb-horizontal': {\n background: theme.colors.action.focus,\n borderRadius: theme.shape.borderRadius(2),\n opacity: 0,\n },\n '&:hover': {\n '.thumb-vertical, .thumb-horizontal': {\n opacity: 1,\n [theme.transitions.handleMotion('no-preference', 'reduce')]: {\n transition: 'opacity 0.3s ease-in-out',\n },\n },\n },\n }),\n // override the scroll container position so that the scroll indicators\n // are positioned at the top and bottom correctly.\n // react-custom-scrollbars doesn't provide any way for us to hook in nicely,\n // so we have to override with !important. feelsbad.\n scrollbarWithScrollIndicators: css({\n '.scrollbar-view': {\n // Need type assertion here due to the use of !important\n // see https://github.com/frenic/csstype/issues/114#issuecomment-697201978\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n position: 'static !important' as 'static',\n },\n }),\n };\n};\n\n/**\n * Calling scrollTop on a scrollbar ref in a useEffect can race with internal state in react-custom-scrollbars-2, causing scrollTop to get called on a stale reference, which prevents the element from scrolling as desired.\n * Adding the reference to the useEffect dependency array not notify react that the reference has changed (and is an eslint violation), so we create a custom hook so updates to the reference trigger another render, fixing the race condition bug.\n *\n * @param scrollBar\n * @param scrollTop\n */\nfunction useScrollTop(\n scrollBar: (Scrollbars & { view: HTMLDivElement; update: () => void }) | null,\n scrollTop?: number\n) {\n useEffect(() => {\n if (scrollBar && scrollTop != null) {\n scrollBar.scrollTop(scrollTop);\n }\n }, [scrollTop, scrollBar]);\n}\n"],"names":["className"],"mappings":"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"}