Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 116 lines 3.2 kB view raw
1import {logger} from '#/logger' 2import {UITextView} from '#/platform/ui-text-view' 3import {atoms as a, type TextStyleProp, useAlf, useTheme, web} from '#/alf' 4import { 5 childHasEmoji, 6 normalizeTextStyles, 7 renderChildrenWithEmoji, 8 type TextProps, 9} from '#/alf/typography' 10 11export type {TextProps} 12export {Text as Span} from 'react-native' 13 14/** 15 * Our main text component. Use this most of the time. 16 */ 17export function Text({ 18 children, 19 emoji, 20 style, 21 selectable, 22 title, 23 dataSet, 24 numberOfLines, 25 ...rest 26}: TextProps) { 27 const {fonts, flags} = useAlf() 28 const t = useTheme() 29 const s = normalizeTextStyles( 30 [ 31 a.text_sm, 32 t.atoms.text, 33 web(numberOfLines === 1 && numberOfLinesClippingFix), 34 style, 35 ], 36 { 37 fontScale: fonts.scaleMultiplier, 38 fontFamily: fonts.family, 39 flags, 40 }, 41 ) 42 43 if (__DEV__) { 44 if (!emoji && childHasEmoji(children)) { 45 logger.warn( 46 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-base-to-string 47 `Text: emoji detected but emoji not enabled: "${children}"\n\nPlease add <Text emoji />'`, 48 ) 49 } 50 } 51 52 const shared = { 53 uiTextView: true, 54 selectable, 55 numberOfLines, 56 style: s, 57 dataSet: Object.assign({tooltip: title}, dataSet || {}), 58 ...rest, 59 } 60 61 return ( 62 <UITextView {...shared}> 63 {renderChildrenWithEmoji(children, shared, emoji ?? false)} 64 </UITextView> 65 ) 66} 67 68function createHeadingElement({level}: {level: number}) { 69 return function HeadingElement({style, ...rest}: TextProps) { 70 const attr = 71 web({ 72 role: 'heading', 73 'aria-level': level, 74 }) || {} 75 return <Text {...attr} {...rest} style={style} /> 76 } 77} 78 79/* 80 * Use semantic components when it's beneficial to the user or to a web scraper 81 */ 82export const H1 = createHeadingElement({level: 1}) 83export const H2 = createHeadingElement({level: 2}) 84export const H3 = createHeadingElement({level: 3}) 85export const H4 = createHeadingElement({level: 4}) 86export const H5 = createHeadingElement({level: 5}) 87export const H6 = createHeadingElement({level: 6}) 88export function P({style, ...rest}: TextProps) { 89 const attr = 90 web({ 91 role: 'paragraph', 92 }) || {} 93 return ( 94 <Text {...attr} {...rest} style={[a.text_md, a.leading_relaxed, style]} /> 95 ) 96} 97 98/** 99 * HACKFIX: React Native Web applies `overflow: hidden` to 100 * text when using the `numberOfLines` prop, which causes it to clip 101 * ascenders/descenders. It only needs to be doing this for the X axis, 102 * so override the style with `overflowX: 'hidden'`. 103 * Note this only works for `numberOfLines={1}` -sfn 104 * 105 * @see https://github.com/necolas/react-native-web/pull/2836 106 */ 107const numberOfLinesClippingFix = { 108 overflowY: 'visible', 109 overflowX: 'clip', 110 // mimic browser default behavior of `min-width: 0` on `overflow: hidden` 111 // elements to allow text to shrink smaller than its intrinsic width when 112 // necessary 113 minWidth: 0, 114 // this is neater and supports vertical writing modes, but it's only baseline newly available 115 // overflowInline: 'clip', 116} satisfies React.CSSProperties as TextStyleProp