UNPKG

@navinc/base-react-components

Version:
442 lines (436 loc) 18.5 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { jsx as _jsx } from "react/jsx-runtime"; import styled from 'styled-components'; import isRebrand from './is-rebrand.js'; import Link from './link.js'; import LoadingDots from './loading-dots.js'; const sizeVariants = { 'nav-blue': { small: { padding: '0.5em 1.33em', fontSize: '12px', borderRadius: '12px', lineHeight: '1', }, medium: { padding: '0.64em 1.71em', fontSize: '14px', borderRadius: '12px', lineHeight: '1', }, large: { padding: '0.75em 2em', fontSize: '16px', borderRadius: '12px', lineHeight: '1', }, extraLarge: { padding: '0.9em 1.6em', fontSize: '20px', borderRadius: '16px', lineHeight: '1', }, cardButton: { padding: '8px', fontSize: '16px', borderRadius: '12px', lineHeight: '1', }, }, 'nav-purple': { small: { padding: '0.5em 1.33em', fontSize: '12px', borderRadius: '8px', lineHeight: '1', }, medium: { padding: '6px 16px 6px 16px', fontSize: '14px', borderRadius: '8px', lineHeight: '1', }, large: { padding: '8px 24px 8px 24px', fontSize: '16px', borderRadius: '8px', lineHeight: '1', }, extraLarge: { padding: '16px 32px 16px 32px', fontSize: '20px', borderRadius: '8px', lineHeight: '1', }, cardButton: { padding: '8px', fontSize: '16px', borderRadius: '12px', lineHeight: '1', }, }, }; const getSize = ({ size = 'medium', themeName = 'nav-blue' }) => { var _a; return (_a = sizeVariants[themeName][size]) !== null && _a !== void 0 ? _a : sizeVariants[themeName].medium; }; const getVariation = ({ variation = 'main', theme, size = 'medium', }) => { var _a, _b, _c; const lineHeightMap = { small: '18px', medium: '20px', large: '24px', extraLarge: '28px', }; const styleVariation = { main: { borderColor: 'transparent', backgroundColor: theme.navPrimary, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary700} 1%) center/15000%`, /* Despite remaining the same, the font color must be defined for both hover/focus so as to override nested link styling */ color: theme.navNeutralLight, hover: { backgroundColor: isRebrand(theme) ? theme.navPrimary500 : theme.navStatusPositive500, color: theme.navNeutralLight, }, focus: Object.assign({ backgroundColor: isRebrand(theme) ? theme.navPrimary : theme.navStatusPositive500 }, (isRebrand(theme) ? { outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, } : {})), active: Object.assign(Object.assign({}, (isRebrand(theme) ? { backgroundColor: theme.navPrimary700 } : {})), { backgroundSize: '100%', transition: 'background 0s' }), }, outline: { borderColor: theme.navPrimary, backgroundColor: theme.transparentWhite, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`, color: theme.navPrimary, hover: { backgroundColor: theme.navPrimary200, }, focus: { backgroundColor: isRebrand(theme) ? theme.transparentWhite : theme.bubbleBlue100, outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, }, active: { backgroundColor: theme.navPrimary300, /* Tied to the background property, these will create the click impression effect */ backgroundSize: '100%', transition: 'background 0s', }, }, shade: { borderColor: 'transparent', backgroundColor: theme.navPrimary200, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`, color: theme.navPrimary, hover: { backgroundColor: theme.navPrimary100, }, focus: { outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, }, active: { backgroundColor: theme.navPrimary300, /* Tied to the background property, these will create the click impression effect */ backgroundSize: '100%', transition: 'background 0s', }, }, white: { borderColor: 'transparent', backgroundColor: theme.navNeutralLight, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`, color: theme.navPrimary, hover: { backgroundColor: theme.navPrimary200, }, focus: { outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, }, active: { backgroundColor: theme.navPrimary300, /* Tied to the background property, these will create the click impression effect */ backgroundSize: '100%', transition: 'background 0s', }, }, tan: { borderColor: 'transparent', backgroundColor: theme.navSecondary, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navSecondary200} radial-gradient(circle, transparent 1%, ${theme.navSecondary300} 1%) center/15000%`, color: theme.navPrimary400, hover: { backgroundColor: theme.navSecondary100, color: theme.navPrimary500, }, focus: { outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, }, active: { backgroundColor: theme.navSecondary300, color: theme.navPrimary500, /* Tied to the background property, these will create the click impression effect */ backgroundSize: '100%', transition: 'background 0s', }, }, destructive: { borderColor: 'transparent', backgroundColor: theme.navStatusNegative, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navStatusNegative} radial-gradient(circle, transparent 1%, ${theme.navStatusNegative700} 1%) center/15000%`, color: theme.navNeutralLight, hover: { backgroundColor: theme.navStatusNegative500, }, focus: { outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, }, active: { backgroundColor: theme.navStatusNegative700, /* Tied to the background property, these will create the click impression effect */ backgroundSize: '100%', transition: 'background 0s', }, }, accent: { borderColor: 'transparent', backgroundColor: theme.navStatusPositive, /* Imposes a background radial gradient too small to detect, that upon activation will expand 100% of the container like a ripple from the click */ background: `${theme.navStatusPositive} radial-gradient(circle, transparent 1%, ${theme.navStatusPositive700} 1%) center/15000%`, color: theme.navNeutralLight, hover: { backgroundColor: theme.navStatusPositive500, }, focus: { outline: 'none', boxShadow: isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 1px ${theme.azure}`, }, active: { backgroundColor: theme.navStatusPositive700, /* Tied to the background property, these will create the click impression effect */ backgroundSize: '100%', transition: 'background 0s', }, }, buttonLink: { borderColor: 'transparent', backgroundColor: theme.transparentWhite, color: theme.navPrimary400, padding: 0, lineHeight: (_a = lineHeightMap[size]) !== null && _a !== void 0 ? _a : lineHeightMap.medium, hover: { color: isRebrand(theme) ? theme.navPrimary500 : theme.oceanBoat, }, focus: Object.assign({}, (isRebrand(theme) ? { outline: 'none', boxShadow: `0 0 0 4px ${theme.navStatusPositive500}`, borderRadius: '2px', } : { borderColor: 'transparent', color: theme.oceanBoat, })), active: { color: isRebrand(theme) ? theme.navPrimary500 : theme.oceanBoat, }, }, buttonAction: { borderColor: 'transparent', backgroundColor: theme.transparentWhite, color: theme.navNeutral400, padding: 0, lineHeight: (_b = lineHeightMap[size]) !== null && _b !== void 0 ? _b : lineHeightMap.medium, }, noOutline: { borderColor: 'transparent', backgroundColor: theme.transparentWhite, color: theme.navPrimary400, hover: Object.assign({}, (isRebrand(theme) ? { color: theme.navPrimary500 } : { borderColor: theme.navStatusPositive500 })), focus: Object.assign({ borderColor: theme.navStatusPositive500 }, (isRebrand(theme) ? { outline: 'none', boxShadow: `0 0 0 4px ${theme.navStatusPositive500}` } : {})), active: Object.assign({}, (isRebrand(theme) ? { color: theme.navPrimary500 } : { backgroundColor: theme.navPrimary300, borderColor: 'transparent' })), }, whiteOutline: { borderColor: theme.white, backgroundColor: theme.transparentWhite, color: theme.white, hover: { backgroundColor: theme.navPrimary200, color: theme.navPrimary, }, focus: { backgroundColor: theme.navPrimary200, color: theme.navPrimary, }, active: { backgroundColor: theme.navPrimary300, color: theme.navPrimary, borderColor: 'transparent', }, }, neutral: { borderColor: 'transparent', backgroundColor: theme.scuttleGray200, background: `${theme.navPrimary200} radial-gradient(circle, transparent 1%, ${theme.navPrimary300} 1%) center/15000%`, color: theme.scuttleGray600, hover: { backgroundColor: theme.bubbleBlue200, }, focus: { outline: 'none', }, active: { backgroundColor: theme.navPrimary700, backgroundSize: '100%', transition: 'background 0s', borderColor: 'transparent', }, }, }; return (_c = styleVariation[variation]) !== null && _c !== void 0 ? _c : styleVariation.main; }; const getRule = (rulePath) => ({ size, variation, theme }) => { const rules = Object.assign(Object.assign({}, getSize({ size, themeName: theme.name })), getVariation({ variation, theme, size })); const rule = rulePath.split('.').reduce((rules, pathPart) => { var _a; return (_a = rules[pathPart]) !== null && _a !== void 0 ? _a : ''; }, rules); return typeof rule === 'function' ? rule({ theme }) : rule; }; const getDisabledStyleByVariation = ({ variation, theme }) => { switch (variation) { case 'buttonLink': case 'noOutline': return ''; case 'outline': return isRebrand(theme) ? '' : `border-color: ${theme.neutral300};`; default: return `background-color: ${theme.neutral200};`; } }; export const StyledButton = styled.button.withConfig({ displayName: "brc-sc-StyledButton", componentId: "brc-sc-bkuhcf" }) ` display: inline-flex; align-items: center; box-sizing: border-box; font-family: ${({ theme }) => theme.fontPrimary}; padding: ${getRule('padding')}; border: 1px solid ${getRule('borderColor')}; border-radius: ${getRule('borderRadius')}; background: ${getRule('background')}; background-color: ${getRule('backgroundColor')}; color: ${getRule('color')}; font-size: ${getRule('fontSize')}; line-height: ${getRule('lineHeight')}; text-align: center; white-space: ${({ wrap }) => (wrap ? 'normal' : 'nowrap')}; cursor: pointer; outline: none; font-weight: 700; transition: ease-out background 0.4s; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; &:hover:not([disabled]) { background-color: ${getRule('hover.backgroundColor')}; color: ${getRule('hover.color')}; border-color: ${getRule('hover.borderColor')}; } /* Override hover styles, b/c when pressed the hover event is also active */ &:hover:active { background-color: ${getRule('active.backgroundColor')}; color: ${getRule('active.color')}; border-color: ${getRule('active.borderColor')}; } &:focus { background-color: ${getRule('focus.backgroundColor')}; color: ${getRule('focus.color')}; outline: ${getRule('focus.outline')}; box-shadow: ${getRule('focus.boxShadow')}; border-radius: ${getRule('focus.borderRadius')}; } &:focus:active { outline: none; box-shadow: none; } &[disabled] { ${({ $isLoading, variation = 'main', theme, size }) => $isLoading ? '' : ` ${getDisabledStyleByVariation({ variation, theme })} ${isRebrand(theme) ? `opacity: 38%;` : `color: ${theme.neutral400};`} ${isRebrand(theme) ? `background: ${getRule('backgroundColor')({ size, variation, theme })} !important;` : ''} cursor: not-allowed; `} } &:active { background-color: ${getRule('active.backgroundColor')}; background-size: ${getRule('active.backgroundSize')}; transition: ${getRule('active.transition')}; } `; const ButtonBase = (_a) => { var { children, $isLoading, onClick = () => { } } = _a, props = __rest(_a, ["children", "$isLoading", "onClick"]); let dotColor = 'purple'; switch (props.variation) { case 'main': case 'destructive': case 'accent': case undefined: dotColor = 'white'; break; default: break; } return (_jsx(StyledButton, Object.assign({ disabled: $isLoading, onClick: (event) => { event.persist(); onClick(event); } }, props, { children: $isLoading ? _jsx(LoadingDots, { dotColor: dotColor, "data-testid": "button-loading-dots" }) : children }))); }; ButtonBase.displayName = 'ButtonBase'; const ButtonLink = styled(StyledButton).attrs(() => ({ as: Link })) ` text-decoration: none; `; ButtonLink.displayName = 'ButtonLink'; const ButtonAnchor = styled(StyledButton).attrs(() => ({ as: 'a' })).withConfig({ displayName: "brc-sc-ButtonAnchor", componentId: "brc-sc-1uee4oc" }) ` text-decoration: none; `; ButtonAnchor.displayName = 'ButtonAnchor'; export const Button = (_a) => { var { href, asAnchor, isLoading } = _a, props = __rest(_a, ["href", "asAnchor", "isLoading"]); if (!href) { return _jsx(ButtonBase, Object.assign({ "$isLoading": isLoading }, props)); } if (asAnchor) { return _jsx(ButtonAnchor, Object.assign({ "$isLoading": isLoading, href: href }, props)); } return _jsx(ButtonLink, Object.assign({ "$isLoading": isLoading, href: href }, props)); }; Button.displayName = 'Button'; const StyledButtonExp = styled(Button).withConfig({ displayName: "brc-sc-StyledButtonExp", componentId: "brc-sc-1jq7psv" }) ``; export default StyledButtonExp; //# sourceMappingURL=button.js.map