UNPKG

@patreon/studio

Version:

Patreon Studio Design System

81 lines (80 loc) 3.38 kB
'use client'; import React from 'react'; import Measure from 'react-measure'; import styled, { css } from 'styled-components'; import { tokens } from '../../tokens'; import { convertLegacyUnitValue } from '../../utilities/legacy-units'; import { BodyText } from '../BodyText'; export const getOffset = (offsetProp, dimension) => offsetProp && dimension ? `${offsetProp - dimension}px` : undefined; // TODO (legacied react-prefer-function-component/react-prefer-function-component) // This failure is legacied in and should be updated. DO NOT COPY. // eslint-disable-next-line react-prefer-function-component/react-prefer-function-component export class Badge extends React.Component { constructor(props) { super(props); this.getMeasuredContent = this.getMeasuredContent.bind(this); } getMeasuredContent({ contentRect, measureRef }) { const { children, id, maxDigits = 2, target, xOffset, yOffset, dot, hideIfZero = false, variant = 'primary', } = this.props; const text = typeof children === 'number' ? Math.log10(children) >= maxDigits ? (Math.pow(10, maxDigits) - 1).toString() + '+' : Math.floor(children) : children; const shouldShow = !(hideIfZero && text === 0); // We only want to show an empty badge when it is a `dot`. const isEmptyAndNotDot = !dot && !!children; if (!contentRect.bounds) { return null; } const { width, height } = contentRect.bounds; const rightOffset = getOffset(xOffset, width); const topOffset = getOffset(yOffset, height); return (<Wrapper ref={measureRef}> {shouldShow ? (<StyledBadge aria-hidden badgeOnTarget={!!target} dot={dot} id={id} right={rightOffset} top={topOffset} variant={variant} isEmptyAndNotDot={isEmptyAndNotDot}> {dot ? (<Dot />) : (<TextWrapper> <BodyText color="inherit" as="div" size="sm"> {text} </BodyText> </TextWrapper>)} </StyledBadge>) : (<span />)} <div data-tag="badge-target">{target}</div> </Wrapper>); } render() { return <Measure bounds>{this.getMeasuredContent.bind(this)}</Measure>; } } const Wrapper = styled.span ` display: inline-flex; position: relative; `; const Dot = styled.div ` height: ${convertLegacyUnitValue(0.75)}; width: ${convertLegacyUnitValue(0.75)}; `; const StyledBadge = styled.span ` width: ${({ dot }) => dot && '6px'}; min-width: ${({ dot, isEmptyAndNotDot }) => !dot && isEmptyAndNotDot && '24px'}; height: ${({ dot, isEmptyAndNotDot }) => (dot ? '6px' : isEmptyAndNotDot && '24px')}; right: ${({ right }) => right}; top: ${({ top }) => top}; display: flex; justify-content: center; align-items: center; border-radius: 44px; pointer-events: none; z-index: ${tokens.global.layer.z1}; position: ${({ badgeOnTarget }) => badgeOnTarget && 'absolute'}; background-color: ${tokens.global.primary.actionBase.default}; color: ${tokens.global.primary.onActionBase.default}; ${({ variant }) => variant === 'secondary' && css ` background-color: ${tokens.global.secondary.muted.default}; color: ${tokens.global.content.muted.default}; `} `; const TextWrapper = styled.div ` margin: 0 8px; `; //# sourceMappingURL=index.jsx.map