UNPKG

@kadconsulting/dry

Version:
129 lines 9.11 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useState, useEffect, useMemo } from 'react'; import { Icon } from '../Icons/Icon'; import { GoogleColor, Google, Facebook, FacebookBrand, FacebookColor, Apple, AppleBrand, AppleColor, Twitter, TwitterBrand, TwitterColor, FigmaColor, FigmaGrey, Dribbble, DribbbleBrand, DribbbleColor, ArrowUp, ArrowDown, } from '../Icons/paths'; import { IconSizes } from '../Icons/Icon/IconTypes'; import classnames from 'classnames'; import LoadingSpinner from '../LoadingSpinner/LoadingSpinner'; // import * as Utils from "./Button.utils.js"; /** * Determines if a given background color is light. * @param {string} bgColor - The CSS color value in rgb() or rgba() format. * @returns {boolean} True if the background color is considered light; otherwise, false. */ function isBackgroundLight(bgColor) { // Extract RGB components from bgColor, assuming it's in the format rgb(r, g, b) or rgba(r, g, b, a) const rgb = bgColor?.match(/\d+/g)?.map(Number); if (!rgb) { return false; } // Convert RGB to luminance const luminance = (0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]) / 255; return luminance > 0.5; } import './Button.scss'; const Button = forwardRef(({ id, passProps, text = '', iconSrc = '', onClick, isLoading = false, isError = false, disabled = false, buttonType = 'primary', size = 'medium', icon = null, fullWidth = false, submit = false, blink = false, pulse = false, animated = false, tooltip = '', children, closeButton = false, className = '', iconLeft = false, iconRight = false, note, wrapperClassName = 'dry-button__content-wrapper', width, adornmentLeft, adornmentRight, social = undefined, socialText = false, socialVariant = 'brand', destructive = false, textColor, dropdownButton = false, ...rest }, ref) => { const [loading, setLoading] = useState(isLoading); const [isOpen, setIsOpen] = useState(false); const [error, setError] = useState(isError); const [dynamicTextColor, setDynamicTextColor] = useState(''); const icons = { google: { color: _jsx(Icon, { Path: Google, size: IconSizes.SMALL }), brand: _jsx(Icon, { Path: GoogleColor, size: IconSizes.SMALL }), colorWithBrand: _jsx(Icon, { Path: GoogleColor, size: IconSizes.SMALL }), }, facebook: { color: _jsx(Icon, { Path: FacebookColor, size: IconSizes.SMALL }), brand: _jsx(Icon, { Path: Facebook, size: IconSizes.SMALL }), colorWithBrand: _jsx(Icon, { Path: FacebookBrand, size: IconSizes.SMALL }), }, apple: { brand: _jsx(Icon, { Path: Apple, size: IconSizes.SMALL }), colorWithBrand: _jsx(Icon, { Path: AppleBrand, size: IconSizes.SMALL }), color: _jsx(Icon, { Path: AppleColor, size: IconSizes.SMALL }), }, twitter: { brand: _jsx(Icon, { Path: Twitter, size: IconSizes.SMALL }), colorWithBrand: _jsx(Icon, { Path: TwitterBrand, size: IconSizes.SMALL }), color: _jsx(Icon, { Path: TwitterColor, size: IconSizes.SMALL }), }, figma: { brand: _jsx(Icon, { Path: FigmaColor, size: IconSizes.SMALL }), colorWithBrand: _jsx(Icon, { Path: FigmaColor, size: IconSizes.SMALL }), color: _jsx(Icon, { Path: FigmaGrey, size: IconSizes.SMALL }), }, dribbble: { brand: _jsx(Icon, { Path: Dribbble, size: IconSizes.SMALL }), colorWithBrand: _jsx(Icon, { Path: DribbbleBrand, size: IconSizes.SMALL }), color: _jsx(Icon, { Path: DribbbleColor, size: IconSizes.SMALL }), }, }; // Update loading and error state when props change useEffect(() => { setLoading(isLoading); setError(isError); }, [isLoading, isError]); useEffect(() => { setLoading(isLoading); setError(isError); }, [isLoading, isError, ref]); // Conditional loading and error states const loadingState = _jsx(LoadingSpinner, {}); const errorState = _jsx("span", { children: "Error" }); // Compute the button content with adornments if provided const ButtonContent = useMemo(() => (_jsxs(_Fragment, { children: [adornmentLeft && (_jsx("span", { className: 'button-adornment-left', children: adornmentLeft })), children && (_jsx("span", { className: 'dry-button__button-content', children: children })), adornmentRight && (_jsx("span", { className: 'button-adornment-right', children: adornmentRight }))] })), [children, adornmentLeft, adornmentRight]); // Compute class names for the button const buttonClasses = useMemo(() => classnames('dry-button', `dry-button--${buttonType}`, `dry-button--${size}`, { 'dry-button--full-width': fullWidth }, { 'dry-button--submit': submit }, { 'dry-button--blink': blink }, { 'dry-button--pulse': pulse }, { 'dry-button--animated': animated }, { 'dry-button--loading': loading }, { 'dry-button--error': error }, { 'dry-button--disabled': disabled }, { 'dry-button--icon-left': iconLeft }, { 'dry-button--icon-right': iconRight }, destructive ? `dry-button--${buttonType}-destructive` : '', className), [ buttonType, size, fullWidth, submit, blink, pulse, animated, loading, error, disabled, iconLeft, iconRight, className, ]); // TODO-dry: we could add this as a utility function to DRY const genStyle = () => { const baseStyle = width ? { width: `${width}px`, } : { width: 'auto', }; // const textStyle = { // color: dynamicTextColor, // }; const overLayStyle = textColor ? { color: textColor, } : {}; return { ...baseStyle, ...overLayStyle }; // return { ...baseStyle, ...overLayStyle, ...textStyle }; }; // Conditional rendering for the close button if (closeButton) { return (_jsx("button", { className: classnames('dry-button', 'dry-button--close', `dry-button--${size}`, { 'dry-button--full-width': fullWidth }, { 'dry-button--loading': loading }, { 'dry-button--error': error }, { 'dry-button--disabled': disabled }, { 'dry-button--icon-left': iconLeft }, { 'dry-button--icon-right': iconRight }, destructive ? `dry-button--${buttonType}-destructive` : '', className), onClick: onClick, disabled: disabled, title: tooltip, type: 'button', ...rest, children: "X" })); } if (dropdownButton) { return (_jsxs("div", { id: id, ref: ref, className: classnames(className, 'dry-button', 'dry-button-container', 'dry-button-dropdown'), style: { width: width ? `${width}` : '100%' }, children: [note && _jsx("div", { className: 'dry-button__note', children: note }), _jsxs("button", { id: id, className: 'dry-button dry-button--dropdown', style: genStyle(), onClick: () => { setIsOpen(!isOpen); onClick && onClick(); }, disabled: disabled || loading || error, title: tooltip, type: submit ? 'submit' : 'button', ...rest, children: [iconSrc && (_jsx("img", { className: 'dry-button__icon', alt: '', src: iconSrc })), icon && _jsx("span", { className: 'dry-button__icon', children: icon }), loading ? (loadingState) : error ? (errorState) : (_jsxs("span", { className: wrapperClassName, children: [ButtonContent, text && _jsx("span", { className: 'dry-button__text', children: text })] })), isOpen && _jsx(Icon, { Path: ArrowUp, size: IconSizes.SMALL }), !isOpen && _jsx(Icon, { Path: ArrowDown, size: IconSizes.SMALL })] })] })); } if (social) { return (_jsx("div", { id: id, ref: ref, className: classnames(className, 'dry-button', 'dry-button-container'), children: _jsxs("button", { className: ` dry-button dry-button-social--${social} dry-button-socialVariant--${socialVariant}`, onClick: onClick, disabled: disabled, title: tooltip, type: 'button', ...rest, children: [icons[social][socialVariant], socialText ? `Sign in with ${social}` : ''] }) })); } // Main button rendering return (_jsxs("div", { id: id, ref: ref, className: classnames(className, 'dry-button', 'dry-button-container'), style: { width: width ? `${width}` : '100%' }, children: [note && _jsx("div", { className: 'dry-button__note', children: note }), _jsxs("button", { id: id, className: buttonClasses, style: genStyle(), onClick: onClick, disabled: disabled || loading || error, title: tooltip, type: submit ? 'submit' : 'button', ...rest, children: [iconSrc && _jsx("img", { className: 'dry-button__icon', alt: '', src: iconSrc }), icon && _jsx("span", { className: 'dry-button__icon', children: icon }), loading ? (loadingState) : error ? (errorState) : (_jsxs("span", { className: wrapperClassName, children: [ButtonContent, text && _jsx("span", { className: 'dry-button__text', children: text })] }))] })] })); }); export default Button; //# sourceMappingURL=Button.js.map