mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import * as React from 'react'
2import {StyleSheet, View} from 'react-native'
3import {usePalette} from 'lib/hooks/usePalette'
4import {useTheme} from 'lib/ThemeContext'
5import {Text} from './text/Text'
6import {TextLink} from './Link'
7import {
8 H1 as ExpoH1,
9 H2 as ExpoH2,
10 H3 as ExpoH3,
11 H4 as ExpoH4,
12} from '@expo/html-elements'
13import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
14
15/**
16 * These utilities are used to define long documents in an html-like
17 * DSL. See for instance /locale/en/privacy-policy.tsx
18 */
19
20interface IsChildProps {
21 isChild?: boolean
22}
23
24// type ReactNodeWithIsChildProp =
25// | React.ReactElement<IsChildProps>
26// | React.ReactElement<IsChildProps>[]
27// | React.ReactNode
28
29export function H1({children}: React.PropsWithChildren<{}>) {
30 const styles = useStyles()
31 const pal = usePalette('default')
32 const typography = useTheme().typography['title-xl']
33 // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf
34 return <ExpoH1 style={[typography, pal.text, styles.h1]}>{children}</ExpoH1>
35}
36
37export function H2({children}: React.PropsWithChildren<{}>) {
38 const styles = useStyles()
39 const pal = usePalette('default')
40 const typography = useTheme().typography['title-lg']
41 // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf
42 return <ExpoH2 style={[typography, pal.text, styles.h2]}>{children}</ExpoH2>
43}
44
45export function H3({children}: React.PropsWithChildren<{}>) {
46 const styles = useStyles()
47 const pal = usePalette('default')
48 const typography = useTheme().typography.title
49 // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf
50 return <ExpoH3 style={[typography, pal.text, styles.h3]}>{children}</ExpoH3>
51}
52
53export function H4({children}: React.PropsWithChildren<{}>) {
54 const styles = useStyles()
55 const pal = usePalette('default')
56 const typography = useTheme().typography['title-sm']
57 // @ts-ignore Expo's TextStyle definition seems to have gotten away from RN's -prf
58 return <ExpoH4 style={[typography, pal.text, styles.h4]}>{children}</ExpoH4>
59}
60
61export function P({children}: React.PropsWithChildren<{}>) {
62 const styles = useStyles()
63 const pal = usePalette('default')
64 return (
65 <Text type="md" style={[pal.text, styles.p]}>
66 {children}
67 </Text>
68 )
69}
70
71export function UL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
72 const styles = useStyles()
73 return (
74 <View style={[styles.ul, isChild && styles.ulChild]}>
75 {markChildProps(children)}
76 </View>
77 )
78}
79
80export function OL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
81 const styles = useStyles()
82 return (
83 <View style={[styles.ol, isChild && styles.olChild]}>
84 {markChildProps(children)}
85 </View>
86 )
87}
88
89export function LI({
90 children,
91 value,
92}: React.PropsWithChildren<{value?: string}>) {
93 const styles = useStyles()
94 const pal = usePalette('default')
95 return (
96 <View style={styles.li}>
97 <Text style={[pal.text, styles.liBullet]}>{value || <>•</>}</Text>
98 <Text type="md" style={[pal.text, styles.liText]}>
99 {markChildProps(children)}
100 </Text>
101 </View>
102 )
103}
104
105export function A({children, href}: React.PropsWithChildren<{href: string}>) {
106 const styles = useStyles()
107 const pal = usePalette('default')
108 return (
109 <TextLink
110 type="md"
111 style={[pal.link, styles.a]}
112 text={children}
113 href={href}
114 />
115 )
116}
117
118export function STRONG({children}: React.PropsWithChildren<{}>) {
119 const pal = usePalette('default')
120 return (
121 <Text type="md-medium" style={[pal.text]}>
122 {children}
123 </Text>
124 )
125}
126
127export function EM({children}: React.PropsWithChildren<{}>) {
128 const styles = useStyles()
129 const pal = usePalette('default')
130 return (
131 <Text type="md" style={[pal.text, styles.em]}>
132 {children}
133 </Text>
134 )
135}
136
137function markChildProps(children: React.ReactNode) {
138 return React.Children.map(children, child => {
139 if (React.isValidElement(child)) {
140 return React.cloneElement<IsChildProps>(
141 child as React.ReactElement<IsChildProps>,
142 {isChild: true},
143 )
144 }
145 return child
146 })
147}
148
149const useStyles = () => {
150 const {isDesktop} = useWebMediaQueries()
151 return StyleSheet.create({
152 h1: {
153 marginTop: 20,
154 marginBottom: 10,
155 letterSpacing: 0.8,
156 },
157 h2: {
158 marginTop: 20,
159 marginBottom: 10,
160 letterSpacing: 0.8,
161 },
162 h3: {
163 marginTop: 0,
164 marginBottom: 10,
165 },
166 h4: {
167 marginTop: 0,
168 marginBottom: 10,
169 fontWeight: 'bold',
170 },
171 p: {
172 marginBottom: 10,
173 },
174 ul: {
175 marginBottom: 10,
176 paddingLeft: isDesktop ? 18 : 4,
177 },
178 ulChild: {
179 paddingTop: 10,
180 marginBottom: 0,
181 },
182 ol: {
183 marginBottom: 10,
184 paddingLeft: isDesktop ? 18 : 4,
185 },
186 olChild: {
187 paddingTop: 10,
188 marginBottom: 0,
189 },
190 li: {
191 flexDirection: 'row',
192 paddingRight: 20,
193 marginBottom: 10,
194 },
195 liBullet: {
196 paddingRight: 10,
197 },
198 liText: {},
199 a: {
200 marginBottom: 10,
201 },
202 em: {
203 fontStyle: 'italic',
204 },
205 })
206}