@patreon/studio
Version:
Patreon Studio Design System
81 lines (80 loc) • 3.38 kB
JSX
'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