UNPKG

@grafana/ui

Version:
1 lines 10.2 kB
{"version":3,"file":"ToolbarButtonRow.mjs","sources":["../../../../src/components/ToolbarButton/ToolbarButtonRow.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { useDialog } from '@react-aria/dialog';\nimport { FocusScope } from '@react-aria/focus';\nimport { useOverlay } from '@react-aria/overlays';\nimport { Children, forwardRef, HTMLAttributes, useState, useRef, useLayoutEffect, createRef } from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { t } from '@grafana/i18n';\n\nimport { useTheme2 } from '../../themes/ThemeContext';\nimport { getPortalContainer } from '../Portal/Portal';\n\nimport { ToolbarButton } from './ToolbarButton';\nexport interface Props extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n /** Determine flex-alignment of child buttons. Needed for overflow behaviour. */\n alignment?: 'left' | 'right';\n}\n\nexport const ToolbarButtonRow = forwardRef<HTMLDivElement, Props>(\n ({ alignment = 'left', className, children, ...rest }, ref) => {\n // null/undefined are valid react children so we need to filter them out to prevent unnecessary padding\n const childrenWithoutNull = Children.toArray(children).filter((child) => child != null);\n const [childVisibility, setChildVisibility] = useState<boolean[]>(Array(childrenWithoutNull.length).fill(false));\n const containerRef = useRef<HTMLDivElement>(null);\n const [showOverflowItems, setShowOverflowItems] = useState(false);\n const overflowRef = useRef<HTMLDivElement>(null);\n const overflowItemsRef = createRef<HTMLDivElement>();\n const { overlayProps } = useOverlay(\n {\n onClose: () => setShowOverflowItems(false),\n isDismissable: true,\n isOpen: showOverflowItems,\n shouldCloseOnInteractOutside: (element: Element) => {\n const portalContainer = getPortalContainer();\n return !overflowRef.current?.contains(element) && !portalContainer.contains(element);\n },\n },\n overflowItemsRef\n );\n const { dialogProps } = useDialog({}, overflowItemsRef);\n const theme = useTheme2();\n const overflowButtonOrder = alignment === 'left' ? childVisibility.indexOf(false) - 1 : childVisibility.length;\n const styles = getStyles(theme, overflowButtonOrder, alignment);\n\n useLayoutEffect(() => {\n const intersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.target instanceof HTMLElement && entry.target.parentNode) {\n const index = Array.prototype.indexOf.call(entry.target.parentNode.children, entry.target);\n setChildVisibility((prev) => {\n const newVisibility = [...prev];\n newVisibility[index] = entry.isIntersecting;\n return newVisibility;\n });\n }\n });\n },\n {\n threshold: 1,\n root: containerRef.current,\n }\n );\n if (containerRef.current) {\n Array.from(containerRef.current.children).forEach((item) => {\n // don't observe the overflow button\n if (item instanceof HTMLElement && item !== overflowRef.current) {\n intersectionObserver.observe(item);\n }\n });\n }\n return () => intersectionObserver.disconnect();\n }, [children]);\n\n return (\n <div ref={containerRef} className={cx(styles.container, className)} {...rest}>\n {childrenWithoutNull.map((child, index) => (\n <div\n key={index}\n style={{ order: index, visibility: childVisibility[index] ? 'visible' : 'hidden' }}\n className={styles.childWrapper}\n >\n {child}\n </div>\n ))}\n {childVisibility.includes(false) && (\n <div ref={overflowRef} className={styles.overflowButton}>\n <ToolbarButton\n variant={showOverflowItems ? 'active' : 'default'}\n tooltip={t('grafana-ui.toolbar-button-row.show-more', 'Show more items')}\n onClick={() => setShowOverflowItems(!showOverflowItems)}\n icon=\"ellipsis-v\"\n iconOnly\n narrow\n />\n {showOverflowItems && (\n <FocusScope contain autoFocus>\n <div className={styles.overflowItems} ref={overflowItemsRef} {...overlayProps} {...dialogProps}>\n {childrenWithoutNull.map((child, index) => !childVisibility[index] && child)}\n </div>\n </FocusScope>\n )}\n </div>\n )}\n </div>\n );\n }\n);\n\nToolbarButtonRow.displayName = 'ToolbarButtonRow';\n\nconst getStyles = (theme: GrafanaTheme2, overflowButtonOrder: number, alignment: Props['alignment']) => ({\n overflowButton: css({\n order: overflowButtonOrder,\n }),\n overflowItems: css({\n alignItems: 'center',\n backgroundColor: theme.colors.background.primary,\n borderRadius: theme.shape.radius.default,\n boxShadow: theme.shadows.z2,\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(1),\n marginTop: theme.spacing(1),\n maxWidth: '80vw',\n padding: theme.spacing(0.5, 1),\n position: 'absolute',\n right: 0,\n top: '100%',\n width: 'max-content',\n zIndex: theme.zIndex.dropdown,\n }),\n container: css({\n alignItems: 'center',\n display: 'flex',\n gap: theme.spacing(1),\n justifyContent: alignment === 'left' ? 'flex-start' : 'flex-end',\n minWidth: 0,\n position: 'relative',\n }),\n childWrapper: css({\n alignItems: 'center',\n display: 'flex',\n gap: theme.spacing(1),\n }),\n});\n"],"names":[],"mappings":"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"}