UNPKG

@grafana/ui

Version:
262 lines (259 loc) • 8.18 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { cx, css } from '@emotion/css'; import * as React from 'react'; import { useMemo, useContext, memo, cloneElement } from 'react'; import { t } from '@grafana/i18n'; import { useStyles2 } from '../../themes/ThemeContext.mjs'; import { getFocusStyles } from '../../themes/mixins.mjs'; import { getCardContainerStyles, CardContainer } from './CardContainer.mjs'; "use strict"; const CardContext = React.createContext(null); const Card = ({ disabled, href, onClick, children, isSelected, isCompact, className, noMargin, ...htmlProps }) => { const hasHeadingComponent = useMemo( () => React.Children.toArray(children).some((c) => React.isValidElement(c) && c.type === Heading), [children] ); const disableHover = disabled || !onClick && !href; const onCardClick = onClick && !disabled ? onClick : void 0; const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected, isCompact, noMargin); return /* @__PURE__ */ jsx( CardContainer, { disableEvents: disabled, disableHover, isSelected, className: cx(styles.container, className), noMargin, ...htmlProps, children: /* @__PURE__ */ jsxs(CardContext.Provider, { value: { href, onClick: onCardClick, disabled, isSelected }, children: [ !hasHeadingComponent && /* @__PURE__ */ jsx(Heading, {}), children ] }) } ); }; Card.displayName = "Card"; const Heading = ({ children, className, "aria-label": ariaLabel }) => { const context = useContext(CardContext); const styles = useStyles2(getHeadingStyles); const { href, onClick, isSelected } = context != null ? context : { href: void 0, onClick: void 0, isSelected: void 0 }; const optionLabel = t("grafana-ui.card.option", "option"); return /* @__PURE__ */ jsxs("h2", { className: cx(styles.heading, className), children: [ href ? /* @__PURE__ */ jsx("a", { href, className: styles.linkHack, "aria-label": ariaLabel, onClick, children }) : onClick ? /* @__PURE__ */ jsx("button", { onClick, className: styles.linkHack, "aria-label": ariaLabel, type: "button", children }) : /* @__PURE__ */ jsx(Fragment, { children }), isSelected !== void 0 && /* @__PURE__ */ jsx("input", { "aria-label": optionLabel, type: "radio", checked: isSelected, readOnly: true }) ] }); }; Heading.displayName = "Heading"; const getHeadingStyles = (theme) => ({ heading: css({ gridArea: "Heading", justifySelf: "start", display: "flex", justifyContent: "space-between", alignItems: "center", width: "100%", marginBottom: 0, fontSize: theme.typography.size.md, letterSpacing: "inherit", lineHeight: theme.typography.body.lineHeight, color: theme.colors.text.primary, fontWeight: theme.typography.fontWeightMedium, "& input[readonly]": { cursor: "inherit" } }), linkHack: css({ all: "unset", "&::after": { position: "absolute", content: '""', top: 0, bottom: 0, left: 0, right: 0, borderRadius: theme.shape.radius.default }, "&:focus-visible": { outline: "none", outlineOffset: 0, boxShadow: "none", "&::after": { ...getFocusStyles(theme), zIndex: 1 } } }) }); const Tags = ({ children, className }) => { const styles = useStyles2(getTagStyles); return /* @__PURE__ */ jsx("div", { className: cx(styles.tagList, className), children }); }; Tags.displayName = "Tags"; const getTagStyles = (theme) => ({ tagList: css({ position: "relative", gridArea: "Tags", alignSelf: "center" }) }); const Description = ({ children, className }) => { const styles = useStyles2(getDescriptionStyles); const Element = typeof children === "string" ? "p" : "div"; return /* @__PURE__ */ jsx(Element, { className: cx(styles.description, className), children }); }; Description.displayName = "Description"; const getDescriptionStyles = (theme) => ({ description: css({ width: "100%", gridArea: "Description", margin: theme.spacing(1, 0, 0), color: theme.colors.text.secondary, lineHeight: theme.typography.body.lineHeight }) }); const Figure = ({ children, align = "start", className }) => { const styles = useStyles2(getFigureStyles); return /* @__PURE__ */ jsx( "div", { className: cx( styles.media, className, css({ alignSelf: align }) ), children } ); }; Figure.displayName = "Figure"; const getFigureStyles = (theme) => ({ media: css({ position: "relative", gridArea: "Figure", marginRight: theme.spacing(2), width: "40px", "> img": { width: "100%" }, "&:empty": { display: "none" } }) }); const Meta = memo(({ children, className, separator = "|" }) => { const styles = useStyles2(getMetaStyles); let meta = children; const filtered = React.Children.toArray(children).filter(Boolean); if (!filtered.length) { return null; } meta = filtered.map((element, i) => /* @__PURE__ */ jsx("div", { className: styles.metadataItem, children: element }, `element_${i}`)); if (filtered.length > 1 && separator) { meta = filtered.reduce((prev, curr, i) => [ prev, /* @__PURE__ */ jsx("span", { className: styles.separator, children: separator }, `separator_${i}`), curr ]); } return /* @__PURE__ */ jsx("div", { className: cx(styles.metadata, className), children: meta }); }); Meta.displayName = "Meta"; const getMetaStyles = (theme) => ({ metadata: css({ gridArea: "Meta", display: "flex", alignItems: "center", width: "100%", fontSize: theme.typography.size.sm, color: theme.colors.text.secondary, margin: theme.spacing(0.5, 0, 0), lineHeight: theme.typography.bodySmall.lineHeight, overflowWrap: "anywhere" }), metadataItem: css({ // Needed to allow for clickable children in metadata zIndex: 0 }), separator: css({ margin: `0 ${theme.spacing(1)}` }) }); const BaseActions = ({ children, disabled, variant, className }) => { const styles = useStyles2(getActionStyles); const context = useContext(CardContext); const isDisabled = (context == null ? void 0 : context.disabled) || disabled; const css2 = variant === "primary" ? styles.actions : styles.secondaryActions; return /* @__PURE__ */ jsx("div", { className: cx(css2, className), children: React.Children.map(children, (child) => { return React.isValidElement(child) ? cloneElement(child, { disabled: isDisabled, ...child.props }) : null; }) }); }; const getActionStyles = (theme) => ({ actions: css({ display: "flex", flexDirection: "row", flexWrap: "wrap", gap: theme.spacing(1), gridArea: "Actions", marginTop: theme.spacing(2) }), secondaryActions: css({ alignSelf: "center", color: theme.colors.text.secondary, display: "flex", flexDirection: "row", flexWrap: "wrap", gap: theme.spacing(1), gridArea: "Secondary", marginTop: theme.spacing(2) }) }); const Actions = ({ children, disabled, className }) => { return /* @__PURE__ */ jsx(BaseActions, { variant: "primary", disabled, className, children }); }; Actions.displayName = "Actions"; const SecondaryActions = ({ children, disabled, className }) => { return /* @__PURE__ */ jsx(BaseActions, { variant: "secondary", disabled, className, children }); }; SecondaryActions.displayName = "SecondaryActions"; const getCardStyles = (theme) => { return { inner: css({ display: "flex", justifyContent: "space-between", alignItems: "center", width: "100%", flexWrap: "wrap" }), ...getHeadingStyles(theme), ...getMetaStyles(theme), ...getDescriptionStyles(theme), ...getFigureStyles(theme), ...getActionStyles(theme), ...getTagStyles(theme) }; }; Card.Heading = Heading; Card.Tags = Tags; Card.Figure = Figure; Card.Meta = Meta; Card.Actions = Actions; Card.SecondaryActions = SecondaryActions; Card.Description = Description; export { Card, getCardStyles }; //# sourceMappingURL=Card.mjs.map