UNPKG

@wonderflow/react-components

Version:

UI components from Wonderflow's Wanda design system

93 lines (92 loc) 4.32 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import clsx from 'clsx'; import { Children, cloneElement, forwardRef, isValidElement, useCallback, useMemo, } from 'react'; import slugify from 'slugify'; import { Symbol, } from '../..'; import * as styles from './text.module.css'; const decoratorSizeConfig = { 'body-1': { chip: { small: 'small', medium: 'regular', big: 'big', }, icon: { small: 16, medium: 16, big: 18, }, }, 'body-2': { chip: { small: 'small', medium: 'regular', big: 'big', }, icon: { small: 12, medium: 16, big: 18, }, }, 'body-3': { chip: { small: 'small', medium: 'small', big: 'small', }, icon: { small: 12, medium: 12, big: 12, }, }, }; export const Text = forwardRef(({ children, className, variant = 'body-1', color, textAlign = 'start', as: Wrapper = 'p', preventResponsive = false, truncate = false, maxWidth, preventBreakWord = false, decoratorStart, decoratorEnd, decoratorSize = 'small', anchor = false, style, id, ...otherProps }, forwardedRef) => { const dynamicStyle = { '--t-align': textAlign, '--max-width': maxWidth, }; const isBody = useMemo(() => variant.includes('body'), [variant]); const isTitle = useMemo(() => variant.includes('display') || variant.includes('heading'), [variant]); const isDisplay = useMemo(() => variant.includes('display'), [variant]); const hasStart = useMemo(() => !!(isBody && decoratorStart), [decoratorStart, isBody]); const hasEnd = useMemo(() => !!(isBody && decoratorEnd), [decoratorEnd, isBody]); const isDecoratorAnIcon = (d) => Object.prototype.hasOwnProperty.call(d?.props, 'source'); const isDecoratorStartAnIcon = useMemo(() => (hasStart && isDecoratorAnIcon(decoratorStart)), [hasStart, decoratorStart]); const isDecoratorEndAnIcon = useMemo(() => (hasEnd && isDecoratorAnIcon(decoratorEnd)), [hasEnd, decoratorEnd]); const getDecoratorSize = (w) => { if (w === 'start') { return isDecoratorStartAnIcon ? decoratorSizeConfig[variant].icon[decoratorSize] : decoratorSizeConfig[variant].chip[decoratorSize]; } return isDecoratorEndAnIcon ? decoratorSizeConfig[variant].icon[decoratorSize] : decoratorSizeConfig[variant].chip[decoratorSize]; }; const decoratorStartDimension = hasStart ? getDecoratorSize('start') : decoratorSize; const decoratorEndDimension = hasEnd ? getDecoratorSize('end') : decoratorSize; const getTextFromChildren = useCallback(() => { let label = ''; Children.map(children, (child) => { if (typeof child === 'string') { label += child; } }); return label; }, [children]); const generatedID = slugify(String(id ?? getTextFromChildren()), { lower: true, replacement: '_' }); return (_jsxs(Wrapper, { ref: forwardedRef, "data-text-variant": variant, "data-text-color": color, "data-text-prevent-responsive": preventResponsive, "data-text-truncate": truncate, "data-text-decorator": hasStart || hasEnd, "data-text-prevent-break-word": preventBreakWord, className: clsx(styles.Text, className), style: { ...dynamicStyle, ...style }, id: id || (isTitle && anchor) ? generatedID : undefined, ...otherProps, children: [hasStart && isValidElement(decoratorStart) && cloneElement(decoratorStart, { ...decoratorStart.props, dimension: decoratorStartDimension, }), children, (anchor && isTitle) && (_jsx("a", { href: `#${generatedID}`, className: styles.Anchor, rel: "noreferrer", children: _jsx(Symbol, { source: "link", weight: "duotone", dimension: isDisplay ? 24 : 16 }) })), hasEnd && isValidElement(decoratorEnd) && cloneElement(decoratorEnd, { ...decoratorEnd.props, dimension: decoratorEndDimension, })] })); }); Text.displayName = 'Text';