UNPKG

@grafana/ui

Version:
1 lines 10.5 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\n/**\n * A container for multiple ToolbarButtons. Provides automatic overflow behaviour when the buttons no longer fit in the container.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/navigation-toolbarbuttonrow--docs\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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"}