@kadconsulting/dry
Version:
KAD Reusable Component Library
129 lines • 9.11 kB
JavaScript
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