UNPKG

@metamask/design-system-react

Version:
84 lines 5.07 kB
function $importDefault(module) { if (module?.__esModule) { return module.default; } return module; } import { Slot, Slottable } from "@radix-ui/react-slot"; import $React, { forwardRef } from "react"; const React = $importDefault($React); import { ButtonBaseSize } from "../../types/index.mjs"; import { twMerge } from "../../utils/tw-merge.mjs"; import { Icon, IconName, IconSize } from "../Icon/index.mjs"; import { Text, FontWeight, TextColor } from "../Text/index.mjs"; import { TWCLASSMAP_BUTTONBASE_SIZE_DIMENSION } from "./ButtonBase.constants.mjs"; export const ButtonBase = forwardRef(({ children, className, size = ButtonBaseSize.Lg, isFullWidth, asChild, isDisabled, isLoading, loadingText, loadingIconProps, loadingTextProps, startIconName, startIconProps, startAccessory, endIconName, endIconProps, endAccessory, textProps, style, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, 'aria-describedby': ariaDescribedby, 'aria-pressed': ariaPressed, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'aria-haspopup': ariaHaspopup, ...props }, ref) => { const Component = asChild ? Slot : 'button'; const isInteractive = !(isDisabled ?? isLoading); // Calculate tabIndex based on asChild and disabled state const getTabIndex = () => { if (asChild) { return undefined; } return isDisabled ? -1 : undefined; }; const renderLoadingState = () => (React.createElement(React.Fragment, null, React.createElement("span", { className: "absolute inline-flex items-center", "aria-hidden": "true" }, React.createElement(Icon, { name: IconName.Loading, size: IconSize.Sm, className: twMerge('mr-2 animate-spin text-inherit', loadingIconProps?.className), ...loadingIconProps }), React.createElement(Text, { fontWeight: FontWeight.Medium, color: TextColor.Inherit, asChild: true, ...loadingTextProps }, React.createElement("span", null, loadingText))), React.createElement("span", { className: "invisible inline-flex items-center" }, children), React.createElement("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true" }, loadingText || 'Loading'))); const renderStartContent = () => { if (startIconName) { return (React.createElement(Icon, { name: startIconName, size: IconSize.Sm, className: twMerge('mr-2 shrink-0 text-inherit', startIconProps?.className), "aria-hidden": "true", ...startIconProps })); } if (startAccessory) { return (React.createElement("span", { className: "mr-2", "aria-hidden": "true" }, startAccessory)); } return null; }; const renderEndContent = () => { if (endIconName) { return (React.createElement(Icon, { name: endIconName, size: IconSize.Sm, className: twMerge('ml-2 shrink-0 text-inherit', endIconProps?.className), "aria-hidden": "true", ...endIconProps })); } if (endAccessory) { return (React.createElement("span", { className: "ml-2", "aria-hidden": "true" }, endAccessory)); } return null; }; const renderContent = () => { if (children && typeof children === 'string') { return (React.createElement(Text, { fontWeight: FontWeight.Medium, color: TextColor.Inherit, asChild: true, ...textProps }, React.createElement("span", null, children))); } return children; }; const mergedClassName = twMerge( // Base styles 'inline-flex items-center justify-center', 'rounded-xl px-4', 'font-medium text-default', 'bg-muted', 'min-w-20 overflow-hidden', // Add relative positioning for loading state 'relative', // Size TWCLASSMAP_BUTTONBASE_SIZE_DIMENSION[size], // Full width isFullWidth && 'w-full', // Animation classes - only applied when interactive isInteractive && [ 'transition-all', 'duration-100', 'ease-linear', 'active:scale-[0.97]', 'active:ease-[cubic-bezier(0.3,0.8,0.3,1)]', ], // Disabled state - apply to both isDisabled and isLoading (isDisabled || isLoading) && 'cursor-not-allowed', isDisabled && 'opacity-50', // Custom classes className); return (React.createElement(Component, { ref: ref, className: mergedClassName, disabled: asChild ? undefined : (isDisabled ?? isLoading), "aria-disabled": isDisabled ? 'true' : undefined, "aria-busy": isLoading ? 'true' : undefined, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, "aria-pressed": ariaPressed, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, "aria-haspopup": ariaHaspopup, role: asChild ? undefined : 'button', tabIndex: getTabIndex(), style: style, ...props }, renderStartContent(), React.createElement(Slottable, null, isLoading ? renderLoadingState() : renderContent()), renderEndContent())); }); ButtonBase.displayName = 'ButtonBase'; //# sourceMappingURL=ButtonBase.mjs.map