@wonderflow/react-components
Version:
UI components from Wonderflow's Wanda design system
93 lines (92 loc) • 4.32 kB
JavaScript
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';