An ATproto social media client -- with an independent Appview.
1import {UITextView} from 'react-native-uitextview'
2
3import {logger} from '#/logger'
4import {atoms, flatten, useAlf, useTheme, web} from '#/alf'
5import {
6 childHasEmoji,
7 normalizeTextStyles,
8 renderChildrenWithEmoji,
9 type TextProps,
10} from '#/alf/typography'
11
12export type {TextProps}
13export {Text as Span} from 'react-native'
14
15/**
16 * Our main text component. Use this most of the time.
17 */
18export function Text({
19 children,
20 emoji,
21 style,
22 selectable,
23 title,
24 dataSet,
25 ...rest
26}: TextProps) {
27 const {fonts, flags} = useAlf()
28 const t = useTheme()
29 const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, flatten(style)], {
30 fontScale: fonts.scaleMultiplier,
31 fontFamily: fonts.family,
32 flags,
33 })
34
35 if (__DEV__) {
36 if (!emoji && childHasEmoji(children)) {
37 logger.warn(
38 `Text: emoji detected but emoji not enabled: "${children}"\n\nPlease add <Text emoji />'`,
39 )
40 }
41 }
42
43 const shared = {
44 uiTextView: true,
45 selectable,
46 style: s,
47 dataSet: Object.assign({tooltip: title}, dataSet || {}),
48 ...rest,
49 }
50
51 return (
52 <UITextView {...shared}>
53 {renderChildrenWithEmoji(children, shared, emoji ?? false)}
54 </UITextView>
55 )
56}
57
58function createHeadingElement({level}: {level: number}) {
59 return function HeadingElement({style, ...rest}: TextProps) {
60 const attr =
61 web({
62 role: 'heading',
63 'aria-level': level,
64 }) || {}
65 return <Text {...attr} {...rest} style={style} />
66 }
67}
68
69/*
70 * Use semantic components when it's beneficial to the user or to a web scraper
71 */
72export const H1 = createHeadingElement({level: 1})
73export const H2 = createHeadingElement({level: 2})
74export const H3 = createHeadingElement({level: 3})
75export const H4 = createHeadingElement({level: 4})
76export const H5 = createHeadingElement({level: 5})
77export const H6 = createHeadingElement({level: 6})
78export function P({style, ...rest}: TextProps) {
79 const attr =
80 web({
81 role: 'paragraph',
82 }) || {}
83 return (
84 <Text
85 {...attr}
86 {...rest}
87 style={[atoms.text_md, atoms.leading_normal, flatten(style)]}
88 />
89 )
90}