UNPKG

@atlaskit/primitives

Version:

Primitives are token-backed low-level building blocks.

116 lines (113 loc) 3.57 kB
/** * @jsxRuntime classic * @jsx jsx */ import { forwardRef } from 'react'; // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766 import { css, jsx } from '@emotion/react'; import invariant from 'tiny-invariant'; import { HasTextAncestorProvider, useHasTextAncestor } from '../utils/has-text-ancestor-context'; import { useSurface } from '../utils/surface-provider'; import { inverseColorMap, textColorStylesMap, textSizeStylesMap, textWeightStylesMap } from '../xcss/style-maps.partial'; const asAllowlist = ['span', 'p', 'strong', 'em']; // We're doing this because our CSS reset can add top margins to elements such as `p` which is totally insane. // Long term we should remove those instances from the reset - it should be a reset to 0. // For now, at least we know <Text> will be unaffected by this. const resetStyles = css({ margin: 0, overflowWrap: 'anywhere' }); const strongStyles = css({ fontWeight: "var(--ds-font-weight-bold, 700)" }); const emStyles = css({ fontStyle: 'italic' }); const textAlignMap = { center: css({ textAlign: 'center' }), end: css({ textAlign: 'end' }), start: css({ textAlign: 'start' }) }; const truncationStyles = css({ display: '-webkit-box', overflow: 'hidden', WebkitBoxOrient: 'vertical' }); const wordBreakMap = { breakAll: css({ wordBreak: 'break-all' }) }; /** * Custom hook designed to abstract the parsing of the color props and make it clearer in the future how color is reconciled between themes and tokens. */ const useColor = (colorProp, hasTextAncestor) => { const surface = useSurface(); if (colorProp === 'inherit') { return undefined; } if (colorProp) { return colorProp; } if (hasTextAncestor) { return undefined; } if (inverseColorMap.hasOwnProperty(surface)) { return inverseColorMap[surface]; } return 'color.text'; }; /** * __Text__ * * Text is a primitive component that has the Atlassian Design System's design guidelines baked in. * This includes considerations for text attributes such as color, font size, font weight, and line height. * It renders a `span` by default. * * @internal */ const Text = /*#__PURE__*/forwardRef(({ as: Component = 'span', color: colorProp, align, testId, id, size, weight, maxLines, children }, ref) => { invariant(asAllowlist.includes(Component), `@atlaskit/primitives: Text received an invalid "as" value of "${Component}"`); const hasTextAncestor = useHasTextAncestor(); const color = useColor(colorProp, hasTextAncestor); if (!size && !hasTextAncestor) { size = 'medium'; } const component = jsx(Component, { ref: ref, css: [resetStyles, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values size && textSizeStylesMap[size], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values color && textColorStylesMap[color], maxLines && truncationStyles, maxLines === 1 && wordBreakMap.breakAll, align && textAlignMap[align], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values weight && textWeightStylesMap[weight], Component === 'em' && emStyles, Component === 'strong' && strongStyles], style: { WebkitLineClamp: maxLines }, "data-testid": testId, id: id }, children); return hasTextAncestor ? // no need to re-apply context if the text is already wrapped component : jsx(HasTextAncestorProvider, { value: true }, component); }); export default Text;