Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

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

at a876aae44ea07494ebea9727350aa060b81f317b 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