@spaced-out/ui-design-system
Version:
Sense UI components library
1,061 lines (1,024 loc) • 26.8 kB
Flow
// @flow strict
import * as React from 'react';
import type {ColorTypes} from '../../types/typography';
import {TEXT_COLORS} from '../../types/typography';
import classify from '../../utils/classify';
import {escapeRegExp} from '../../utils/string';
import css from '../../styles/typography.module.css';
export type TextProps = {
color?: ColorTypes,
children?: React.Node,
className?: string,
highlightedTextClassName?: string,
highlightString?: string | string[],
caseSensitiveHighlighting?: boolean,
highlightWithBackground?: boolean,
...
};
export type HighlightTextProps = {
text: string,
highlight: string | string[],
highlightClassName?: string,
caseSensitiveHighlighting?: boolean,
highlightWithBackground?: boolean,
};
const HighlightText: React$AbstractComponent<
HighlightTextProps,
HTMLSpanElement,
> = React.forwardRef<HighlightTextProps, HTMLSpanElement>(
(
{
text,
highlight,
highlightClassName,
caseSensitiveHighlighting,
highlightWithBackground,
}: HighlightTextProps,
ref,
) => {
// Split text on highlight term, include term itself into parts, ignore case
// Convert highlight to an array if it's not already
const highlightArray = [].concat(highlight).filter((item) => item !== '');
const highlights = highlightArray.map(escapeRegExp).join('|');
const parts = text
.split(
new RegExp(`(${highlights})`, caseSensitiveHighlighting ? '' : 'gi'),
)
.filter((part) => part !== '');
return (
<span ref={ref}>
{parts.map((part, idx) => {
const isHighlighted = highlightArray.some((highlightTerm) =>
caseSensitiveHighlighting
? escapeRegExp(part).includes(escapeRegExp(highlightTerm))
: escapeRegExp(part)
.toLowerCase()
.includes(escapeRegExp(highlightTerm).toLowerCase()),
);
return isHighlighted ? (
<span
// eslint-disable-next-line react/no-array-index-key
key={idx}
className={classify(
css.highlightText,
{
[css.bgHighlighting]: highlightWithBackground,
},
highlightClassName,
)}
>
{part}
</span>
) : (
part
);
})}
</span>
);
},
);
export const JumboLarge: React$AbstractComponent<TextProps, HTMLSpanElement> =
React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.jumboLarge, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const JumboMedium: React$AbstractComponent<TextProps, HTMLSpanElement> =
React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.jumboMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const JumboSmall: React$AbstractComponent<TextProps, HTMLSpanElement> =
React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.jumboSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const TitleMedium: React$AbstractComponent<
TextProps,
HTMLHeadingElement,
> = React.forwardRef<TextProps, HTMLHeadingElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<h1
{...props}
className={classify(css.titleMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</h1>
),
);
export const SubTitleLarge: React$AbstractComponent<
TextProps,
HTMLHeadingElement,
> = React.forwardRef<TextProps, HTMLHeadingElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<h2
{...props}
className={classify(css.subTitleLarge, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</h2>
),
);
export const SubTitleMedium: React$AbstractComponent<
TextProps,
HTMLHeadingElement,
> = React.forwardRef<TextProps, HTMLHeadingElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<h3
{...props}
className={classify(css.subTitleMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</h3>
),
);
export const SubTitleSmall: React$AbstractComponent<
TextProps,
HTMLHeadingElement,
> = React.forwardRef<TextProps, HTMLHeadingElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<h4
{...props}
className={classify(css.subTitleSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</h4>
),
);
export const SubTitleExtraSmall: React$AbstractComponent<
TextProps,
HTMLHeadingElement,
> = React.forwardRef<TextProps, HTMLHeadingElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<h5
{...props}
className={classify(css.subTitleExtraSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</h5>
),
);
export const ButtonTextMedium: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.buttonTextMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const ButtonTextSmall: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.buttonTextSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const MenuTextMedium: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.menuTextMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const MenuTextSmall: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.menuTextSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const ButtonTextExtraSmall: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.buttonTextExtraSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const ButtonTextMediumUnderline: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(
css.buttonTextMedium,
css.underline,
css[color],
className,
)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const ButtonTextSmallUnderline: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(
css.buttonTextSmall,
css.underline,
css[color],
className,
)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const ButtonTextExtraSmallUnderline: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(
css.buttonTextExtraSmall,
css.underline,
css[color],
className,
)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const FormInputMedium: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.formInputMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const FormInputSmall: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.formInputSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const BodyLarge: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.bodyLarge, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const BodyMedium: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.bodyMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const BodySmall: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.bodySmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const BodyLargeBold: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.bodyLarge, css.bold, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const BodyMediumBold: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.bodyMedium, css.bold, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const BodySmallBold: React$AbstractComponent<
TextProps,
HTMLParagraphElement,
> = React.forwardRef<TextProps, HTMLParagraphElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<p
{...props}
className={classify(css.bodySmall, css.bold, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</p>
),
);
export const FormLabelMedium: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.formLabelMedium, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);
export const FormLabelSmall: React$AbstractComponent<
TextProps,
HTMLSpanElement,
> = React.forwardRef<TextProps, HTMLSpanElement>(
(
{
color = TEXT_COLORS.primary,
children,
className,
highlightedTextClassName,
highlightString,
caseSensitiveHighlighting,
highlightWithBackground,
...props
}: TextProps,
ref,
): React.Node => (
<span
{...props}
className={classify(css.formLabelSmall, css[color], className)}
ref={ref}
>
{!!highlightString?.length && typeof children === 'string' ? (
<HighlightText
text={children}
highlight={highlightString}
caseSensitiveHighlighting={caseSensitiveHighlighting}
highlightClassName={highlightedTextClassName}
highlightWithBackground={highlightWithBackground}
/>
) : (
children
)}
</span>
),
);