diff options
author | dan <dan.abramov@gmail.com> | 2024-11-21 20:44:40 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-21 20:44:40 +0000 |
commit | cc60566cde880deeea1e50774a2108af8f7766f8 (patch) | |
tree | 5b6c925bf4331907fe57a094e30d6a23615debf4 /src/components/Typography.tsx | |
parent | ff23ddb556be4b2a9c4029dce6f857df34fc0b6b (diff) | |
download | voidsky-cc60566cde880deeea1e50774a2108af8f7766f8.tar.zst |
Fix Fast Refresh in <Text> files (#6609)
* Separate non-components from components * Mark old Text as deprecated * Move emoji utilities to non-React file * Fix type * Fix import
Diffstat (limited to 'src/components/Typography.tsx')
-rw-r--r-- | src/components/Typography.tsx | 145 |
1 files changed, 11 insertions, 134 deletions
diff --git a/src/components/Typography.tsx b/src/components/Typography.tsx index 69e073271..4bcbf9f09 100644 --- a/src/components/Typography.tsx +++ b/src/components/Typography.tsx @@ -1,140 +1,17 @@ -import React from 'react' -import {StyleProp, TextProps as RNTextProps, TextStyle} from 'react-native' import {UITextView} from 'react-native-uitextview' -import createEmojiRegex from 'emoji-regex' import {logger} from '#/logger' -import {isIOS, isNative} from '#/platform/detection' -import {Alf, applyFonts, atoms, flatten, useAlf, useTheme, web} from '#/alf' +import {isIOS} from '#/platform/detection' +import {atoms, flatten, useAlf, useTheme, web} from '#/alf' +import { + childHasEmoji, + childIsString, + normalizeTextStyles, + renderChildrenWithEmoji, + TextProps, +} from '#/alf/typography' import {IS_DEV} from '#/env' - -export type StringChild = string | (string | null)[] - -export type TextProps = Omit<RNTextProps, 'children'> & { - /** - * Lets the user select text, to use the native copy and paste functionality. - */ - selectable?: boolean - /** - * Provides `data-*` attributes to the underlying `UITextView` component on - * web only. - */ - dataSet?: Record<string, string | number | undefined> - /** - * Appears as a small tooltip on web hover. - */ - title?: string -} & ( - | { - emoji?: true - children: StringChild - } - | { - emoji?: false - children: RNTextProps['children'] - } - ) - -const EMOJI = createEmojiRegex() - -export function childHasEmoji(children: React.ReactNode) { - return (Array.isArray(children) ? children : [children]).some( - child => typeof child === 'string' && createEmojiRegex().test(child), - ) -} - -export function childIsString( - children: React.ReactNode, -): children is StringChild { - return ( - typeof children === 'string' || - (Array.isArray(children) && - children.every(child => typeof child === 'string' || child === null)) - ) -} - -export function renderChildrenWithEmoji( - children: StringChild, - props: Omit<TextProps, 'children'> = {}, -) { - const normalized = Array.isArray(children) ? children : [children] - - return ( - <UITextView {...props}> - {normalized.map(child => { - if (typeof child !== 'string') return child - - const emojis = child.match(EMOJI) - - if (emojis === null) { - return child - } - - return child.split(EMOJI).map((stringPart, index) => ( - <UITextView key={index} {...props}> - {stringPart} - {emojis[index] ? ( - <UITextView - {...props} - style={[props?.style, {color: 'black', fontFamily: 'System'}]}> - {emojis[index]} - </UITextView> - ) : null} - </UITextView> - )) - })} - </UITextView> - ) -} - -/** - * Util to calculate lineHeight from a text size atom and a leading atom - * - * Example: - * `leading(atoms.text_md, atoms.leading_normal)` // => 24 - */ -export function leading< - Size extends {fontSize?: number}, - Leading extends {lineHeight?: number}, ->(textSize: Size, leading: Leading) { - const size = textSize?.fontSize || atoms.text_md.fontSize - const lineHeight = leading?.lineHeight || atoms.leading_normal.lineHeight - return Math.round(size * lineHeight) -} - -/** - * Ensures that `lineHeight` defaults to a relative value of `1`, or applies - * other relative leading atoms. - * - * If the `lineHeight` value is > 2, we assume it's an absolute value and - * returns it as-is. - */ -export function normalizeTextStyles( - styles: StyleProp<TextStyle>, - { - fontScale, - fontFamily, - }: { - fontScale: number - fontFamily: Alf['fonts']['family'] - } & Pick<Alf, 'flags'>, -) { - const s = flatten(styles) - // should always be defined on these components - s.fontSize = (s.fontSize || atoms.text_md.fontSize) * fontScale - - if (s?.lineHeight) { - if (s.lineHeight !== 0 && s.lineHeight <= 2) { - s.lineHeight = Math.round(s.fontSize * s.lineHeight) - } - } else if (!isNative) { - s.lineHeight = s.fontSize - } - - applyFonts(s, fontFamily) - - return s -} +export type {TextProps} /** * Our main text component. Use this most of the time. @@ -183,7 +60,7 @@ export function Text({ ) } -export function createHeadingElement({level}: {level: number}) { +function createHeadingElement({level}: {level: number}) { return function HeadingElement({style, ...rest}: TextProps) { const attr = web({ |