UNPKG

@spark-web/text

Version:

--- title: Text storybookPath: typography-text--default isExperimentalPackage: false ---

252 lines (229 loc) 7.58 kB
import { useContext, createContext, useMemo } from 'react'; import { jsx } from 'react/jsx-runtime'; import { css } from '@emotion/css'; import { useTheme } from '@spark-web/theme'; import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2'; import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties'; import { useBackgroundLightness, Box } from '@spark-web/box'; import { forwardRefWithAs } from '@spark-web/utils/ts'; var TextContext = /*#__PURE__*/createContext(undefined); function useTextContext() { return useContext(TextContext); } var DefaultTextPropsContext = /*#__PURE__*/createContext({ size: undefined, tone: undefined, weight: undefined }); function DefaultTextPropsProvider(_ref) { var children = _ref.children, size = _ref.size, tone = _ref.tone, weight = _ref.weight; var defaultTextProps = useMemo(function () { return { size: size, tone: tone, weight: weight }; }, [size, tone, weight]); return /*#__PURE__*/jsx(DefaultTextPropsContext.Provider, { value: defaultTextProps, children: children }); } var useDefaultTextProps = function useDefaultTextProps(_ref2) { var _ref3, _ref4, _ref5; var sizeProp = _ref2.size, toneProp = _ref2.tone, weightProp = _ref2.weight; var _useContext = useContext(DefaultTextPropsContext), size = _useContext.size, tone = _useContext.tone, weight = _useContext.weight; return { size: (_ref3 = sizeProp !== null && sizeProp !== void 0 ? sizeProp : size) !== null && _ref3 !== void 0 ? _ref3 : 'standard', tone: (_ref4 = toneProp !== null && toneProp !== void 0 ? toneProp : tone) !== null && _ref4 !== void 0 ? _ref4 : 'neutral', weight: (_ref5 = weightProp !== null && weightProp !== void 0 ? weightProp : weight) !== null && _ref5 !== void 0 ? _ref5 : 'regular' }; }; var Strong = function Strong(_ref) { var children = _ref.children; var theme = useTheme(); var styles = { fontWeight: theme.typography.fontWeight.semibold }; return /*#__PURE__*/jsx("strong", { className: css(styles), children: children }); }; var strategyMap = { truncate: { display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, nowrap: { whiteSpace: 'nowrap' }, // https://css-tricks.com/better-line-breaks-for-long-urls/ breakword: { display: 'block', overflowWrap: 'break-word', wordBreak: 'break-word', wordWrap: 'break-word' } }; function useOverflowStrategy(strategy) { if (!strategy) { return null; } return strategyMap[strategy]; } var invertableTones = { neutral: { dark: 'neutralInverted', light: 'neutral' }, muted: { dark: 'mutedInverted', light: 'muted' }, link: { dark: 'neutralInverted', light: 'link' } }; function useForegroundTone(tone) { var theme = useTheme(); var backgroundLightness = useBackgroundLightness(); if (tone in invertableTones) { return theme.color.foreground[invertableTones[tone][backgroundLightness]]; } return theme.color.foreground[tone]; } function useText(_ref) { var _ref$baseline = _ref.baseline, baseline = _ref$baseline === void 0 ? true : _ref$baseline, size = _ref.size, tone = _ref.tone, weight = _ref.weight; var theme = useTheme(); var color = useForegroundTone(tone); var _theme$typography$tex = theme.typography.text[size], mobile = _theme$typography$tex.mobile, tablet = _theme$typography$tex.tablet; var responsiveStyles = theme.utils.responsiveStyles({ mobile: createTextStyles(mobile, { includeTrims: baseline }), tablet: createTextStyles(tablet, { includeTrims: baseline }) }); var styles = [{ color: color, fontFamily: theme.typography.fontFamily.sans.name, fontWeight: theme.typography.fontWeight[weight] }, responsiveStyles]; return styles; } function createTextStyles(_ref2) { var fontSize = _ref2.fontSize, lineHeight = _ref2.lineHeight, trims = _ref2.trims; var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref3$includeTrims = _ref3.includeTrims, includeTrims = _ref3$includeTrims === void 0 ? true : _ref3$includeTrims; var pseudo = { content: '" "', display: 'table' }; var leadingTrim = includeTrims ? { '::before': _objectSpread(_objectSpread({}, pseudo), {}, { marginBottom: trims.capHeightTrim }), '::after': _objectSpread(_objectSpread({}, pseudo), {}, { marginTop: trims.baselineTrim }) } : null; return _objectSpread({ fontSize: fontSize, lineHeight: lineHeight }, leadingTrim); } var _excluded = ["as", "children", "data", "id", "align", "baseline", "inline", "overflowStrategy", "size", "tabularNumbers", "tone", "transform", "weight"]; var Text = forwardRefWithAs(function (_ref, forwardedRef) { var as = _ref.as, children = _ref.children, data = _ref.data, id = _ref.id, align = _ref.align, baselineProp = _ref.baseline, inline = _ref.inline, overflowStrategy = _ref.overflowStrategy, sizeProp = _ref.size, tabularNumbers = _ref.tabularNumbers, toneProp = _ref.tone, transform = _ref.transform, weightProp = _ref.weight, consumerProps = _objectWithoutProperties(_ref, _excluded); var overflowStyles = useOverflowStrategy(overflowStrategy); var textContext = useTextContext(); var _useDefaultTextProps = useDefaultTextProps({ size: sizeProp !== null && sizeProp !== void 0 ? sizeProp : textContext === null || textContext === void 0 ? void 0 : textContext.size, tone: toneProp !== null && toneProp !== void 0 ? toneProp : textContext === null || textContext === void 0 ? void 0 : textContext.tone, weight: weightProp !== null && weightProp !== void 0 ? weightProp : textContext === null || textContext === void 0 ? void 0 : textContext.weight }), size = _useDefaultTextProps.size, tone = _useDefaultTextProps.tone, weight = _useDefaultTextProps.weight; var baseline = !inline && baselineProp; var textStyles = useText({ baseline: baseline, size: size, tone: tone, weight: weight }); var styles = [textStyles, { display: inline ? 'inline' : 'block', fontVariantNumeric: tabularNumbers ? 'tabular-nums' : undefined, textAlign: align, textTransform: transform }]; // early exit for inline variant if (inline) { return /*#__PURE__*/jsx(Box, _objectSpread(_objectSpread({}, consumerProps), {}, { as: as !== null && as !== void 0 ? as : 'span', data: data, ref: forwardedRef, id: id, className: css(styles), children: children })); } // prepare block variant var content = overflowStrategy ? /*#__PURE__*/jsx("span", { className: css(overflowStyles), children: children }) : children; var textContextValue = useMemo(function () { return { size: size, tone: tone, weight: weight }; }, [size, tone, weight]); return /*#__PURE__*/jsx(TextContext.Provider, { value: textContextValue, children: /*#__PURE__*/jsx(Box, _objectSpread(_objectSpread({}, consumerProps), {}, { as: as, data: data, ref: forwardedRef, id: id, className: css(styles), children: content })) }); }); export { DefaultTextPropsProvider, Strong, Text, createTextStyles, useDefaultTextProps, useForegroundTone, useOverflowStrategy, useText, useTextContext };