wip
This commit is contained in:
@@ -1,26 +1,4 @@
|
|||||||
import { NativeModulesProxy, EventEmitter, Subscription } from 'expo-modules-core';
|
import ExpoSelectableTextView from './src/ExpoSelectableTextView'
|
||||||
|
import {ExpoProTextViewProps} from './src/ExpoSelectableText.types'
|
||||||
|
|
||||||
// Import the native module. On web, it will be resolved to ExpoSelectableText.web.ts
|
export {ExpoSelectableTextView as SelectableText, type ExpoProTextViewProps}
|
||||||
// and on native platforms to ExpoSelectableText.ts
|
|
||||||
import ExpoSelectableTextModule from './src/ExpoSelectableTextModule';
|
|
||||||
import ExpoSelectableTextView from './src/ExpoSelectableTextView';
|
|
||||||
import { ChangeEventPayload, ExpoSelectableTextViewProps } from './src/ExpoSelectableText.types';
|
|
||||||
|
|
||||||
// Get the native constant value.
|
|
||||||
export const PI = ExpoSelectableTextModule.PI;
|
|
||||||
|
|
||||||
export function hello(): string {
|
|
||||||
return ExpoSelectableTextModule.hello();
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setValueAsync(value: string) {
|
|
||||||
return await ExpoSelectableTextModule.setValueAsync(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emitter = new EventEmitter(ExpoSelectableTextModule ?? NativeModulesProxy.ExpoSelectableText);
|
|
||||||
|
|
||||||
export function addChangeListener(listener: (event: ChangeEventPayload) => void): Subscription {
|
|
||||||
return emitter.addListener<ChangeEventPayload>('onChange', listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { ExpoSelectableTextView, ExpoSelectableTextViewProps, ChangeEventPayload };
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import ExpoModulesCore
|
|
||||||
|
|
||||||
public class ExpoProTextModule: Module {
|
|
||||||
public func definition() -> ModuleDefinition {
|
|
||||||
Name("ExpoProText")
|
|
||||||
|
|
||||||
View(ExpoProTextView.self) {
|
|
||||||
Events("onTextPress", "onTextLongPress")
|
|
||||||
|
|
||||||
Prop("segments") { (view: ExpoProTextView, prop: String) in
|
|
||||||
// Convert the JSON to segments
|
|
||||||
if let data = prop.data(using: .utf8) {
|
|
||||||
print("yes")
|
|
||||||
if let segments = try? JSONDecoder().decode(TextSegments.self, from: data) {
|
|
||||||
print("yes2")
|
|
||||||
view.segments = segments.segments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Prop("selectable") { (view: ExpoProTextView, prop: Bool) in
|
|
||||||
view.textView.isSelectable = prop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'ExpoProText'
|
s.name = 'ExpoSelectableText'
|
||||||
s.version = '1.0.0'
|
s.version = '1.0.0'
|
||||||
s.summary = 'A sample project summary'
|
s.summary = 'A sample project summary'
|
||||||
s.description = 'A sample project description'
|
s.description = 'A sample project description'
|
||||||
@@ -16,6 +16,6 @@ Pod::Spec.new do |s|
|
|||||||
'DEFINES_MODULE' => 'YES',
|
'DEFINES_MODULE' => 'YES',
|
||||||
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
||||||
}
|
}
|
||||||
|
|
||||||
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
||||||
end
|
end
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import ExpoModulesCore
|
||||||
|
|
||||||
|
public class ExpoSelectableTextModule: Module {
|
||||||
|
public func definition() -> ModuleDefinition {
|
||||||
|
Name("ExpoSelectableText")
|
||||||
|
|
||||||
|
View(ExpoSelectableTextView.self) {
|
||||||
|
Events("onTextPress", "onTextLongPress", "onTextLayout")
|
||||||
|
|
||||||
|
Prop("segments") { (view: ExpoSelectableTextView, prop: String) in
|
||||||
|
// Convert the JSON to segments
|
||||||
|
if let data = prop.data(using: .utf8) {
|
||||||
|
if let segments = try? JSONDecoder().decode(TextSegments.self, from: data) {
|
||||||
|
view.segments = segments.segments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Prop("selectable") { (view: ExpoSelectableTextView, prop: Bool) in
|
||||||
|
view.textView.isSelectable = prop
|
||||||
|
}
|
||||||
|
|
||||||
|
Prop("rootStyle") { (view: ExpoSelectableTextView, prop: String) in
|
||||||
|
if let data = prop.data(using: .utf8) {
|
||||||
|
if let style = try? JSONDecoder().decode(TextStyle.self, from: data) {
|
||||||
|
view.style = style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
public class ExpoProTextUtil {
|
public class ExpoSelectableTextUtil {
|
||||||
public static func hexToUIColor(hex: String?) -> UIColor {
|
public static func hexToUIColor(hex: String?) -> UIColor {
|
||||||
guard let hex else {
|
guard let hex else {
|
||||||
return UIColor.black
|
return UIColor.black
|
||||||
+12
-4
@@ -1,13 +1,18 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ExpoModulesCore
|
import ExpoModulesCore
|
||||||
|
|
||||||
class ExpoProTextView: ExpoView {
|
class ExpoSelectableTextView: ExpoView {
|
||||||
let textView: UITextView = UITextView()
|
let textView: UITextView = UITextView()
|
||||||
var segments: Array<TextSegment> = [] {
|
var segments: Array<TextSegment> = [] {
|
||||||
didSet {
|
didSet {
|
||||||
setText()
|
setText()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var style: TextStyle? {
|
||||||
|
didSet {
|
||||||
|
self.setNeedsLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let onTextPress = EventDispatcher()
|
let onTextPress = EventDispatcher()
|
||||||
let onTextLongPress = EventDispatcher()
|
let onTextLongPress = EventDispatcher()
|
||||||
@@ -22,6 +27,8 @@ class ExpoProTextView: ExpoView {
|
|||||||
textView.isScrollEnabled = false
|
textView.isScrollEnabled = false
|
||||||
textView.backgroundColor = .clear
|
textView.backgroundColor = .clear
|
||||||
|
|
||||||
|
clipsToBounds = true
|
||||||
|
|
||||||
// Add the text view to the root view
|
// Add the text view to the root view
|
||||||
addSubview(textView)
|
addSubview(textView)
|
||||||
|
|
||||||
@@ -71,8 +78,8 @@ class ExpoProTextView: ExpoView {
|
|||||||
segments.forEach { segment in
|
segments.forEach { segment in
|
||||||
// Set some generic attributes that don't need ranges
|
// Set some generic attributes that don't need ranges
|
||||||
let attributes: [NSAttributedString.Key:Any] = [
|
let attributes: [NSAttributedString.Key:Any] = [
|
||||||
.font: UIFont.systemFont(ofSize: segment.style?.fontSize ?? 12.0, weight: segment.style?.fontWeight?.toFontWeight() ?? .regular),
|
.font: UIFont.systemFont(ofSize: segment.style?.fontSize ?? self.style?.fontSize ?? 12.0, weight: segment.style?.fontWeight?.toFontWeight() ?? self.style?.fontWeight?.toFontWeight() ?? .regular),
|
||||||
.foregroundColor: ExpoProTextUtil.hexToUIColor(hex: segment.style?.color),
|
.foregroundColor: ExpoSelectableTextUtil.hexToUIColor(hex: segment.style?.color),
|
||||||
]
|
]
|
||||||
|
|
||||||
// Create the attributed string with the generic attributes
|
// Create the attributed string with the generic attributes
|
||||||
@@ -81,7 +88,8 @@ class ExpoProTextView: ExpoView {
|
|||||||
// Set the paragraph style attributes if necessary
|
// Set the paragraph style attributes if necessary
|
||||||
if let lineHeight = segment.style?.lineHeight {
|
if let lineHeight = segment.style?.lineHeight {
|
||||||
let paragraphStyle = NSMutableParagraphStyle()
|
let paragraphStyle = NSMutableParagraphStyle()
|
||||||
paragraphStyle.lineSpacing = lineHeight
|
paragraphStyle.minimumLineHeight = lineHeight
|
||||||
|
paragraphStyle.maximumLineHeight = lineHeight
|
||||||
string.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, string.length))
|
string.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, string.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7,11 +7,21 @@ struct TextStyle: Decodable {
|
|||||||
var textAlign: String? = "auto"
|
var textAlign: String? = "auto"
|
||||||
var lineHeight: Double?
|
var lineHeight: Double?
|
||||||
var textDecorationLine: TextDecorationLine?
|
var textDecorationLine: TextDecorationLine?
|
||||||
|
var flex: Int?
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FontWeight: String, Decodable {
|
enum FontWeight: String, Decodable {
|
||||||
case bold
|
case bold
|
||||||
case normal
|
case normal
|
||||||
|
case one = "100"
|
||||||
|
case two = "200"
|
||||||
|
case three = "300"
|
||||||
|
case four = "400"
|
||||||
|
case five = "500"
|
||||||
|
case six = "600"
|
||||||
|
case seven = "700"
|
||||||
|
case eight = "800"
|
||||||
|
case nine = "900"
|
||||||
|
|
||||||
func toFontWeight() -> UIFont.Weight {
|
func toFontWeight() -> UIFont.Weight {
|
||||||
switch self {
|
switch self {
|
||||||
@@ -19,6 +29,24 @@ enum FontWeight: String, Decodable {
|
|||||||
return .bold
|
return .bold
|
||||||
case .normal:
|
case .normal:
|
||||||
return .regular
|
return .regular
|
||||||
|
case .one:
|
||||||
|
return .ultraLight
|
||||||
|
case .two:
|
||||||
|
return .ultraLight
|
||||||
|
case .three:
|
||||||
|
return .light
|
||||||
|
case .four:
|
||||||
|
return .regular
|
||||||
|
case .five:
|
||||||
|
return .medium
|
||||||
|
case .six:
|
||||||
|
return .semibold
|
||||||
|
case .seven:
|
||||||
|
return .semibold
|
||||||
|
case .eight:
|
||||||
|
return .bold
|
||||||
|
case .nine:
|
||||||
|
return .heavy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,5 +55,6 @@ enum TextDecorationLine: String, Decodable {
|
|||||||
case underline
|
case underline
|
||||||
case lineThrough = "line-through"
|
case lineThrough = "line-through"
|
||||||
case underlineLineThrough = "underline line-through"
|
case underlineLineThrough = "underline line-through"
|
||||||
|
|
||||||
case normal
|
case normal
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ColorValue } from 'react-native'
|
import {ColorValue, TextStyle, ViewStyle} from 'react-native'
|
||||||
|
|
||||||
interface ExpoProTextViewCommonProps {
|
interface ExpoProTextViewCommonProps {
|
||||||
selectable?: boolean
|
selectable?: boolean
|
||||||
@@ -7,7 +7,7 @@ interface ExpoProTextViewCommonProps {
|
|||||||
|
|
||||||
export interface ExpoProTextViewProps extends ExpoProTextViewCommonProps {
|
export interface ExpoProTextViewProps extends ExpoProTextViewCommonProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
style?: ExpoProTextStyle
|
style?: TextStyle
|
||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
onLongPress?: () => void
|
onLongPress?: () => void
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,8 @@ export interface ExpoProTextNativeViewProps extends ExpoProTextViewCommonProps {
|
|||||||
onTextLongPress?: (event: ExpoProTextPressEvent) => void
|
onTextLongPress?: (event: ExpoProTextPressEvent) => void
|
||||||
onTextLayout?: (event: ExpoProTextLayoutEvent) => void
|
onTextLayout?: (event: ExpoProTextLayoutEvent) => void
|
||||||
disableLongPress: boolean
|
disableLongPress: boolean
|
||||||
|
style: ViewStyle
|
||||||
|
rootStyle?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExpoProTextStyle {
|
interface ExpoProTextStyle {
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
|
||||||
import { ExpoProTextViewProps } from './ExpoProText.types'
|
import {ExpoProTextViewProps} from './ExpoSelectableText.types'
|
||||||
|
|
||||||
export default function ExpoProTextView(props: ExpoProTextViewProps) {
|
export default function ExpoProTextView(props: ExpoProTextViewProps) {
|
||||||
return (
|
return (
|
||||||
+19
-15
@@ -1,4 +1,4 @@
|
|||||||
import { requireNativeViewManager } from 'expo-modules-core'
|
import {requireNativeViewManager} from 'expo-modules-core'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -7,37 +7,37 @@ import {
|
|||||||
ExpoProTextPressEvent,
|
ExpoProTextPressEvent,
|
||||||
ExpoProTextSegment,
|
ExpoProTextSegment,
|
||||||
ExpoProTextViewProps,
|
ExpoProTextViewProps,
|
||||||
} from './ExpoProText.types'
|
} from './ExpoSelectableText.types'
|
||||||
import { Text, View } from 'react-native'
|
import {StyleSheet, Text, View} from 'react-native'
|
||||||
|
|
||||||
const NativeView: React.ComponentType<ExpoProTextNativeViewProps> =
|
const NativeView: React.ComponentType<ExpoProTextNativeViewProps> =
|
||||||
requireNativeViewManager('ExpoProText')
|
requireNativeViewManager('ExpoSelectableText')
|
||||||
|
|
||||||
export default function ExpoProTextView({
|
export default function ExpoSelectableTextView({
|
||||||
style,
|
style,
|
||||||
children,
|
children,
|
||||||
selectable = false,
|
selectable = false,
|
||||||
onPress,
|
onPress,
|
||||||
onLongPress,
|
onLongPress,
|
||||||
}: ExpoProTextViewProps) {
|
}: ExpoProTextViewProps) {
|
||||||
const [dims, setDims] = React.useState({ height: 0 })
|
const [dims, setDims] = React.useState({height: 0})
|
||||||
const segmentPressCallbacks = React.useRef<
|
const segmentPressCallbacks = React.useRef<
|
||||||
Array<{ index: number; onPress: () => void }>
|
Array<{index: number; onPress: () => void}>
|
||||||
>([])
|
>([])
|
||||||
const segmentLongPressCallbacks = React.useRef<
|
const segmentLongPressCallbacks = React.useRef<
|
||||||
Array<{ index: number, onLongPress: () => void, }>
|
Array<{index: number; onLongPress: () => void}>
|
||||||
>([])
|
>([])
|
||||||
|
|
||||||
const onTextLayout = React.useCallback((e: ExpoProTextLayoutEvent) => {
|
const onTextLayout = React.useCallback((e: ExpoProTextLayoutEvent) => {
|
||||||
|
console.log('layout')
|
||||||
setDims({
|
setDims({
|
||||||
height: e.nativeEvent.height,
|
height: e.nativeEvent.height,
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const onTextPress = React.useCallback((e: ExpoProTextPressEvent) => {
|
const onTextPress = React.useCallback((e: ExpoProTextPressEvent) => {
|
||||||
console.log(e.nativeEvent)
|
|
||||||
const onPressSegment = segmentPressCallbacks.current.find(
|
const onPressSegment = segmentPressCallbacks.current.find(
|
||||||
(s) => s.index === e.nativeEvent.index,
|
s => s.index === e.nativeEvent.index,
|
||||||
)
|
)
|
||||||
onPressSegment?.onPress()
|
onPressSegment?.onPress()
|
||||||
}, [])
|
}, [])
|
||||||
@@ -58,7 +58,7 @@ export default function ExpoProTextView({
|
|||||||
React.isValidElement(child) &&
|
React.isValidElement(child) &&
|
||||||
(child as React.ReactElement<any>).type === Text
|
(child as React.ReactElement<any>).type === Text
|
||||||
) {
|
) {
|
||||||
const { onPress, onLongPress, children, style } = child.props
|
const {onPress, onLongPress, children, style} = child.props
|
||||||
|
|
||||||
segments.push({
|
segments.push({
|
||||||
index,
|
index,
|
||||||
@@ -88,21 +88,25 @@ export default function ExpoProTextView({
|
|||||||
}, [children])
|
}, [children])
|
||||||
|
|
||||||
const segmentsJson = React.useMemo(() => {
|
const segmentsJson = React.useMemo(() => {
|
||||||
const json = JSON.stringify({ segments: textSegments })
|
const json = JSON.stringify({segments: textSegments})
|
||||||
console.log(json)
|
|
||||||
return json
|
return json
|
||||||
}, [textSegments])
|
}, [textSegments])
|
||||||
|
|
||||||
|
const rootStyle = React.useMemo(() => {
|
||||||
|
return style ? JSON.stringify(style) : undefined
|
||||||
|
}, [style])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={dims}>
|
<View style={[dims, {width: '100%'}]}>
|
||||||
<NativeView
|
<NativeView
|
||||||
textStyle={style}
|
|
||||||
segments={segmentsJson}
|
segments={segmentsJson}
|
||||||
selectable={selectable}
|
selectable={selectable}
|
||||||
onTextPress={onTextPress}
|
onTextPress={onTextPress}
|
||||||
onTextLongPress={onLongPress}
|
onTextLongPress={onLongPress}
|
||||||
onTextLayout={onTextLayout}
|
onTextLayout={onTextLayout}
|
||||||
disableLongPress={onLongPress !== undefined}
|
disableLongPress={onLongPress !== undefined}
|
||||||
|
style={{flex: 1}}
|
||||||
|
rootStyle={rootStyle}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -369,6 +369,7 @@ let PostThreadItemLoaded = ({
|
|||||||
richText={richText}
|
richText={richText}
|
||||||
lineHeight={1.3}
|
lineHeight={1.3}
|
||||||
style={s.flex1}
|
style={s.flex1}
|
||||||
|
selectable
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export function RichText({
|
|||||||
lineHeight = 1.2,
|
lineHeight = 1.2,
|
||||||
style,
|
style,
|
||||||
numberOfLines,
|
numberOfLines,
|
||||||
|
selectable,
|
||||||
}: {
|
}: {
|
||||||
testID?: string
|
testID?: string
|
||||||
type?: TypographyVariant
|
type?: TypographyVariant
|
||||||
@@ -24,6 +25,7 @@ export function RichText({
|
|||||||
lineHeight?: number
|
lineHeight?: number
|
||||||
style?: StyleProp<TextStyle>
|
style?: StyleProp<TextStyle>
|
||||||
numberOfLines?: number
|
numberOfLines?: number
|
||||||
|
selectable?: boolean
|
||||||
}) {
|
}) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
@@ -54,7 +56,8 @@ export function RichText({
|
|||||||
style={[style, pal.text, lineHeightStyle]}
|
style={[style, pal.text, lineHeightStyle]}
|
||||||
numberOfLines={numberOfLines}
|
numberOfLines={numberOfLines}
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
dataSet={WORD_WRAP}>
|
dataSet={WORD_WRAP}
|
||||||
|
selectable={selectable}>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Text as RNText, TextProps} from 'react-native'
|
import {StyleSheet, Text as RNText, TextProps} from 'react-native'
|
||||||
import {s, lh} from 'lib/styles'
|
import {s, lh} from 'lib/styles'
|
||||||
import {useTheme, TypographyVariant} from 'lib/ThemeContext'
|
import {useTheme, TypographyVariant} from 'lib/ThemeContext'
|
||||||
|
import {SelectableText} from '../../../../../modules/expo-selectable-text'
|
||||||
|
import {isIOS} from 'platform/detection'
|
||||||
|
import {fontSize} from '#/alf/tokens'
|
||||||
|
|
||||||
export type CustomTextProps = TextProps & {
|
export type CustomTextProps = TextProps & {
|
||||||
type?: TypographyVariant
|
type?: TypographyVariant
|
||||||
lineHeight?: number
|
lineHeight?: number
|
||||||
title?: string
|
title?: string
|
||||||
dataSet?: Record<string, string | number>
|
dataSet?: Record<string, string | number>
|
||||||
|
selectable?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Text({
|
export function Text({
|
||||||
@@ -17,11 +21,30 @@ export function Text({
|
|||||||
style,
|
style,
|
||||||
title,
|
title,
|
||||||
dataSet,
|
dataSet,
|
||||||
|
selectable,
|
||||||
...props
|
...props
|
||||||
}: React.PropsWithChildren<CustomTextProps>) {
|
}: React.PropsWithChildren<CustomTextProps>) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const typography = theme.typography[type]
|
const typography = theme.typography[type]
|
||||||
const lineHeightStyle = lineHeight ? lh(theme, type, lineHeight) : undefined
|
const lineHeightStyle = lineHeight ? lh(theme, type, lineHeight) : undefined
|
||||||
|
|
||||||
|
// {"color":"#000000","fontSize":20,"letterSpacing":0.2,"fontWeight":"400","flex":1,"lineHeight":26}
|
||||||
|
|
||||||
|
if (selectable && isIOS) {
|
||||||
|
return (
|
||||||
|
<SelectableText
|
||||||
|
selectable
|
||||||
|
style={StyleSheet.flatten([
|
||||||
|
s.black,
|
||||||
|
typography,
|
||||||
|
lineHeightStyle,
|
||||||
|
style,
|
||||||
|
])}>
|
||||||
|
{children}
|
||||||
|
</SelectableText>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RNText
|
<RNText
|
||||||
style={[s.black, typography, lineHeightStyle, style]}
|
style={[s.black, typography, lineHeightStyle, style]}
|
||||||
|
|||||||
Reference in New Issue
Block a user