UNPKG

@grafana/ui

Version:
120 lines (117 loc) 3.67 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { css, cx } from '@emotion/css'; import { uniqueId } from 'lodash'; import { useState, useRef } from 'react'; import { useStyles2 } from '../../themes/ThemeContext.mjs'; import { getFocusStyles } from '../../themes/mixins.mjs'; import { Icon } from '../Icon/Icon.mjs'; import { Spinner } from '../Spinner/Spinner.mjs'; "use strict"; const CollapsableSection = ({ label, isOpen, onToggle, className, contentClassName, children, labelId, loading = false, headerDataTestId, contentDataTestId, unmountContentWhenClosed = true }) => { const [internalOpenState, toggleInternalOpenState] = useState(isOpen); const styles = useStyles2(collapsableSectionStyles); const isControlled = isOpen !== void 0 && onToggle !== void 0; const isSectionOpen = isControlled ? isOpen : internalOpenState; const onClick = (e) => { if (e.target instanceof HTMLElement && e.target.tagName === "A") { return; } e.preventDefault(); e.stopPropagation(); onToggle == null ? void 0 : onToggle(!isOpen); if (!isControlled) { toggleInternalOpenState(!internalOpenState); } }; const { current: id } = useRef(uniqueId()); const buttonLabelId = labelId != null ? labelId : `collapse-label-${id}`; const content = /* @__PURE__ */ jsx( "div", { id: `collapse-content-${id}`, className: cx(styles.content, contentClassName, { [styles.contentHidden]: !unmountContentWhenClosed && !isSectionOpen }), "data-testid": contentDataTestId, children } ); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs("div", { onClick, className: cx(styles.header, className), children: [ /* @__PURE__ */ jsx( "button", { type: "button", id: `collapse-button-${id}`, className: styles.button, onClick, "aria-expanded": isSectionOpen && !loading, "aria-controls": `collapse-content-${id}`, "aria-labelledby": buttonLabelId, children: loading ? /* @__PURE__ */ jsx(Spinner, { className: styles.spinner }) : /* @__PURE__ */ jsx(Icon, { name: isSectionOpen ? "angle-down" : "angle-right", className: styles.icon }) } ), /* @__PURE__ */ jsx("div", { className: styles.label, id: `collapse-label-${id}`, "data-testid": headerDataTestId, children: label }) ] }), unmountContentWhenClosed ? isSectionOpen && content : content ] }); }; const collapsableSectionStyles = (theme) => ({ header: css({ display: "flex", alignItems: "center", cursor: "pointer", boxSizing: "border-box", position: "relative", justifyContent: "flex-start", fontSize: theme.typography.size.lg, padding: `${theme.spacing(0.5)} 0`, "&:focus-within": getFocusStyles(theme) }), button: css({ all: "unset", marginRight: theme.spacing(1), "&:focus-visible": { outline: "none", outlineOffset: "unset", [theme.transitions.handleMotion("no-preference", "reduce")]: { transition: "none" }, boxShadow: "none" } }), icon: css({ color: theme.colors.text.secondary }), content: css({ padding: `${theme.spacing(2)} 0` }), contentHidden: css({ display: "none" }), spinner: css({ display: "flex", alignItems: "center", width: theme.spacing(2) }), label: css({ display: "flex", flex: "1 1 auto", fontWeight: theme.typography.fontWeightMedium, color: theme.colors.text.maxContrast }) }); export { CollapsableSection }; //# sourceMappingURL=CollapsableSection.mjs.map