UNPKG

@grafana/ui

Version:
363 lines (356 loc) • 10.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var jsxRuntime = require('react/jsx-runtime'); var css = require('@emotion/css'); var React = require('react'); var data = require('@grafana/data'); var ThemeContext = require('../../themes/ThemeContext.cjs'); var mixins = require('../../themes/mixins.cjs'); var commonStyles = require('../Forms/commonStyles.cjs'); var Icon = require('../Icon/Icon.cjs'); var Tooltip = require('../Tooltip/Tooltip.cjs'); function _interopNamespaceCompat(e) { if (e && typeof e === 'object' && 'default' in e) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespaceCompat(React); "use strict"; const allButtonVariants = ["primary", "secondary", "accent", "destructive", "success"]; const allButtonFills = ["solid", "outline", "text"]; const Button = React__namespace.forwardRef( ({ "aria-label": ariaLabel, size = "md", fill = "solid", variant = fill === "text" ? "accent" : "primary", icon, fullWidth, children, className, type = "button", tooltip, disabled, tooltipPlacement, iconPlacement = "left", onClick, ...otherProps }, ref) => { const theme = ThemeContext.useTheme2(); const styles = getButtonStyles({ theme, size, variant, fill, fullWidth, iconOnly: !children }); const buttonStyles = css.cx( styles.button, { [styles.disabled]: disabled }, className ); const hasTooltip = Boolean(tooltip); const iconComponent = icon && /* @__PURE__ */ jsxRuntime.jsx(IconRenderer, { icon, size, className: styles.icon }); const button = /* @__PURE__ */ jsxRuntime.jsxs( "button", { className: buttonStyles, type, onClick: disabled ? void 0 : onClick, ...otherProps, "aria-disabled": hasTooltip && disabled, disabled: !hasTooltip && disabled, ref: tooltip ? void 0 : ref, "aria-label": ariaLabel != null ? ariaLabel : !children && typeof tooltip === "string" ? tooltip : void 0, children: [ iconPlacement === "left" && iconComponent, children && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.content, children }), iconPlacement === "right" && iconComponent ] } ); if (tooltip) { return /* @__PURE__ */ jsxRuntime.jsx(Tooltip.Tooltip, { ref, content: tooltip, placement: tooltipPlacement, children: button }); } return button; } ); Button.displayName = "Button"; const LinkButton = React__namespace.forwardRef( ({ "aria-label": ariaLabel, variant = "primary", size = "md", fill = "solid", icon, iconPlacement = "left", fullWidth, children, className, onBlur, onFocus, disabled, tooltip, tooltipPlacement, href, ...otherProps }, ref) => { const sanitizedHref = href ? data.textUtil.sanitizeUrl(href) : href; const theme = ThemeContext.useTheme2(); const styles = getButtonStyles({ theme, fullWidth, size, variant, fill, iconOnly: !children }); const linkButtonStyles = css.cx( styles.button, { [css.css(styles.disabled, { pointerEvents: "none" })]: disabled }, className ); const iconComponent = icon && /* @__PURE__ */ jsxRuntime.jsx(IconRenderer, { icon, size, className: styles.icon }); const button = /* @__PURE__ */ jsxRuntime.jsxs( "a", { className: linkButtonStyles, ...otherProps, href: sanitizedHref, tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, ref: tooltip ? void 0 : ref, "aria-label": ariaLabel != null ? ariaLabel : !children && typeof tooltip === "string" ? tooltip : void 0, children: [ iconPlacement === "left" && iconComponent, children && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.content, children }), iconPlacement === "right" && iconComponent ] } ); if (tooltip) { return /* @__PURE__ */ jsxRuntime.jsx(Tooltip.Tooltip, { ref, content: tooltip, placement: tooltipPlacement, children: button }); } return button; } ); LinkButton.displayName = "LinkButton"; const IconRenderer = ({ icon, size, className, iconType }) => { if (!icon) { return null; } if (React__namespace.isValidElement(icon)) { return React__namespace.cloneElement(icon, { className, size }); } return /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { name: icon, size, className, type: iconType }); }; const getButtonStyles = (props) => { const { theme, variant, fill = "solid", size, iconOnly, fullWidth } = props; const { height, padding, fontSize } = commonStyles.getPropertiesForButtonSize(size, theme); const variantStyles = getPropertiesForVariant(theme, variant, fill); const disabledStyles = getPropertiesForDisabled(theme, variant, fill); const focusStyle = mixins.getButtonFocusStyles(theme); const paddingMinusBorder = theme.spacing.gridSize * padding - 1; return { button: css.css({ label: "button", display: "inline-flex", alignItems: "center", gap: theme.spacing(1), fontSize, fontWeight: theme.typography.fontWeightMedium, fontFamily: theme.typography.fontFamily, padding: `0 ${paddingMinusBorder}px`, height: theme.spacing(height), // Deduct border from line-height for perfect vertical centering on windows and linux lineHeight: `${theme.spacing.gridSize * height - 2}px`, verticalAlign: "middle", cursor: "pointer", borderRadius: theme.shape.radius.default, "&:focus": focusStyle, "&:focus-visible": focusStyle, "&:focus:not(:focus-visible)": mixins.getMouseFocusStyles(theme), ...fullWidth && { flexGrow: 1, justifyContent: "center" }, ...variantStyles, ":disabled": disabledStyles, "&[disabled]": disabledStyles, [theme.transitions.handleMotion("no-preference", "reduce")]: { transition: theme.transitions.create(["background-color", "border-color", "color"], { duration: theme.transitions.duration.short }) } }), disabled: css.css(disabledStyles, { "&:hover": css.css(disabledStyles), "&:focus": css.css(disabledStyles), "&:focus-visible": css.css(disabledStyles) }), img: css.css({ width: "16px", height: "16px", margin: theme.spacing(0, 1, 0, 0.5) }), icon: iconOnly ? css.css({ // Important not to set margin bottom here as it would override internal icon bottom margin marginRight: theme.spacing(-padding / 2), marginLeft: theme.spacing(-padding / 2) }) : void 0, content: css.css({ display: "flex", flexDirection: "row", alignItems: "center", whiteSpace: "nowrap", overflow: "hidden", height: "100%" }) }; }; function getActiveButtonStyles(color, fill) { return { background: fill === "solid" ? color.main : "transparent" }; } function getButtonVariantStyles(theme, color, fill) { let outlineBorderColor = color.border; let borderColor = "transparent"; let hoverBorderColor = "transparent"; if (color.name === "secondary") { borderColor = color.border; hoverBorderColor = theme.colors.emphasize(color.border, 0.25); outlineBorderColor = theme.colors.border.strong; } if (fill === "outline") { return { background: "transparent", color: color.text, border: `1px solid ${outlineBorderColor}`, "&:hover, &:focus": { background: color.transparent, borderColor: theme.colors.emphasize(outlineBorderColor, 0.25), color: color.text }, "&:active": { ...getActiveButtonStyles(color, fill) } }; } if (fill === "text") { return { background: "transparent", color: color.text, border: "1px solid transparent", "&:hover, &:focus": { background: color.transparent, textDecoration: "none", outline: "none" }, "&:active": { ...getActiveButtonStyles(color, fill) } }; } return { background: color.main, color: color.contrastText, border: `1px solid ${borderColor}`, "&:hover": { background: color.shade, color: color.contrastText, boxShadow: theme.shadows.z1, borderColor: hoverBorderColor }, "&:focus": { background: color.shade, color: color.contrastText }, "&:active": { ...getActiveButtonStyles(color, fill) } }; } function getPropertiesForDisabled(theme, variant, fill) { const disabledStyles = { cursor: "not-allowed", boxShadow: "none", color: theme.colors.text.disabled, transition: "none", background: theme.colors.action.disabledBackground }; if (fill === "text") { return { ...disabledStyles, background: "transparent", border: `1px solid transparent` }; } if (fill === "outline") { return { ...disabledStyles, background: "transparent", border: `1px solid ${theme.colors.border.weak}` }; } return { ...disabledStyles, background: theme.colors.action.disabledBackground, border: `1px solid transparent` }; } function getPropertiesForVariant(theme, variant, fill) { switch (variant) { case "secondary": return getButtonVariantStyles(theme, theme.colors.secondary, fill); case "destructive": return getButtonVariantStyles(theme, theme.colors.error, fill); case "success": return getButtonVariantStyles(theme, theme.colors.success, fill); case "accent": return getButtonVariantStyles(theme, theme.colors.accent, fill); case "primary": default: return getButtonVariantStyles(theme, theme.colors.primary, fill); } } const clearButtonStyles = (theme) => { return css.css({ background: "transparent", color: theme.colors.text.primary, border: "none", padding: 0 }); }; exports.Button = Button; exports.IconRenderer = IconRenderer; exports.LinkButton = LinkButton; exports.allButtonFills = allButtonFills; exports.allButtonVariants = allButtonVariants; exports.clearButtonStyles = clearButtonStyles; exports.getActiveButtonStyles = getActiveButtonStyles; exports.getButtonStyles = getButtonStyles; exports.getPropertiesForVariant = getPropertiesForVariant; //# sourceMappingURL=Button.cjs.map