ignite-parse-auth-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/CONTRIBUTING.md +0 -0
  2. package/LICENSE +21 -0
  3. package/README.md +492 -0
  4. package/app/app.tsx +116 -0
  5. package/app/components/AlertTongle.tsx +105 -0
  6. package/app/components/AutoImage.tsx +89 -0
  7. package/app/components/Button.tsx +248 -0
  8. package/app/components/Card.tsx +314 -0
  9. package/app/components/EmptyState.tsx +248 -0
  10. package/app/components/Header.tsx +332 -0
  11. package/app/components/Icon.tsx +140 -0
  12. package/app/components/ListItem.tsx +243 -0
  13. package/app/components/ListView.tsx +42 -0
  14. package/app/components/Screen.tsx +305 -0
  15. package/app/components/Text.test.tsx +23 -0
  16. package/app/components/Text.tsx +116 -0
  17. package/app/components/TextField.tsx +292 -0
  18. package/app/components/Toggle/Checkbox.tsx +123 -0
  19. package/app/components/Toggle/Radio.tsx +106 -0
  20. package/app/components/Toggle/Switch.tsx +264 -0
  21. package/app/components/Toggle/Toggle.tsx +285 -0
  22. package/app/components/index copy.ts +15 -0
  23. package/app/components/index.ts +18 -0
  24. package/app/config/config.base.ts +26 -0
  25. package/app/config/config.dev.ts +10 -0
  26. package/app/config/config.prod.ts +10 -0
  27. package/app/config/index.ts +28 -0
  28. package/app/context/AuthContext.tsx +14 -0
  29. package/app/context/EpisodeContext.tsx +136 -0
  30. package/app/context/auth/AuthProvider.tsx +340 -0
  31. package/app/context/auth/hooks.ts +29 -0
  32. package/app/context/auth/index.ts +38 -0
  33. package/app/context/auth/reducer.ts +68 -0
  34. package/app/context/auth/services.ts +394 -0
  35. package/app/context/auth/types.ts +99 -0
  36. package/app/context/auth/validation.ts +45 -0
  37. package/app/devtools/ReactotronClient.ts +9 -0
  38. package/app/devtools/ReactotronClient.web.ts +12 -0
  39. package/app/devtools/ReactotronConfig.ts +139 -0
  40. package/app/i18n/ar.ts +126 -0
  41. package/app/i18n/demo-ar.ts +464 -0
  42. package/app/i18n/demo-en.ts +462 -0
  43. package/app/i18n/demo-es.ts +469 -0
  44. package/app/i18n/demo-fr.ts +471 -0
  45. package/app/i18n/demo-hi.ts +468 -0
  46. package/app/i18n/demo-ja.ts +464 -0
  47. package/app/i18n/demo-ko.ts +457 -0
  48. package/app/i18n/en.ts +146 -0
  49. package/app/i18n/es.ts +132 -0
  50. package/app/i18n/fr.ts +132 -0
  51. package/app/i18n/hi.ts +131 -0
  52. package/app/i18n/index.ts +86 -0
  53. package/app/i18n/ja.ts +130 -0
  54. package/app/i18n/ko.ts +129 -0
  55. package/app/i18n/translate.ts +33 -0
  56. package/app/lib/Parse/index.ts +2 -0
  57. package/app/lib/Parse/parse.ts +62 -0
  58. package/app/navigators/AppNavigator.tsx +145 -0
  59. package/app/navigators/DemoNavigator.tsx +137 -0
  60. package/app/navigators/navigationUtilities.ts +208 -0
  61. package/app/screens/ChooseAuthScreen.tsx +224 -0
  62. package/app/screens/DemoCommunityScreen.tsx +141 -0
  63. package/app/screens/DemoDebugScreen.tsx +192 -0
  64. package/app/screens/DemoPodcastListScreen.tsx +387 -0
  65. package/app/screens/DemoShowroomScreen/DemoDivider.tsx +66 -0
  66. package/app/screens/DemoShowroomScreen/DemoShowroomScreen.tsx +313 -0
  67. package/app/screens/DemoShowroomScreen/DemoUseCase.tsx +52 -0
  68. package/app/screens/DemoShowroomScreen/DrawerIconButton.tsx +120 -0
  69. package/app/screens/DemoShowroomScreen/SectionListWithKeyboardAwareScrollView.tsx +59 -0
  70. package/app/screens/DemoShowroomScreen/demos/DemoAutoImage.tsx +230 -0
  71. package/app/screens/DemoShowroomScreen/demos/DemoButton.tsx +234 -0
  72. package/app/screens/DemoShowroomScreen/demos/DemoCard.tsx +181 -0
  73. package/app/screens/DemoShowroomScreen/demos/DemoEmptyState.tsx +78 -0
  74. package/app/screens/DemoShowroomScreen/demos/DemoHeader.tsx +151 -0
  75. package/app/screens/DemoShowroomScreen/demos/DemoIcon.tsx +115 -0
  76. package/app/screens/DemoShowroomScreen/demos/DemoListItem.tsx +218 -0
  77. package/app/screens/DemoShowroomScreen/demos/DemoText.tsx +144 -0
  78. package/app/screens/DemoShowroomScreen/demos/DemoTextField.tsx +233 -0
  79. package/app/screens/DemoShowroomScreen/demos/DemoToggle.tsx +354 -0
  80. package/app/screens/DemoShowroomScreen/demos/index.ts +12 -0
  81. package/app/screens/ErrorScreen/ErrorBoundary.tsx +76 -0
  82. package/app/screens/ErrorScreen/ErrorDetails.tsx +98 -0
  83. package/app/screens/ForgetPasswordScreen.tsx +180 -0
  84. package/app/screens/LoginScreen.tsx +260 -0
  85. package/app/screens/RegisterScreen.tsx +395 -0
  86. package/app/screens/WelcomeScreen.tsx +114 -0
  87. package/app/services/api/apiProblem.test.ts +73 -0
  88. package/app/services/api/apiProblem.ts +74 -0
  89. package/app/services/api/index.ts +91 -0
  90. package/app/services/api/types.ts +50 -0
  91. package/app/theme/colors.ts +85 -0
  92. package/app/theme/colorsDark.ts +50 -0
  93. package/app/theme/context.tsx +145 -0
  94. package/app/theme/context.utils.ts +25 -0
  95. package/app/theme/spacing.ts +14 -0
  96. package/app/theme/spacingDark.ts +14 -0
  97. package/app/theme/styles.ts +24 -0
  98. package/app/theme/theme.ts +23 -0
  99. package/app/theme/timing.ts +6 -0
  100. package/app/theme/types.ts +64 -0
  101. package/app/theme/typography.ts +71 -0
  102. package/app/utils/crashReporting.ts +62 -0
  103. package/app/utils/delay.ts +6 -0
  104. package/app/utils/formatDate.ts +49 -0
  105. package/app/utils/gestureHandler.native.ts +3 -0
  106. package/app/utils/gestureHandler.ts +6 -0
  107. package/app/utils/hasValidStringProp.ts +11 -0
  108. package/app/utils/openLinkInBrowser.ts +8 -0
  109. package/app/utils/storage/index.ts +82 -0
  110. package/app/utils/storage/storage.test.ts +61 -0
  111. package/app/utils/useHeader.tsx +37 -0
  112. package/app/utils/useIsMounted.ts +18 -0
  113. package/app/utils/useSafeAreaInsetsStyle.ts +46 -0
  114. package/app.config.ts +39 -0
  115. package/app.json +67 -0
  116. package/assets/icons/back.png +0 -0
  117. package/assets/icons/back@2x.png +0 -0
  118. package/assets/icons/back@3x.png +0 -0
  119. package/assets/icons/bell.png +0 -0
  120. package/assets/icons/bell@2x.png +0 -0
  121. package/assets/icons/bell@3x.png +0 -0
  122. package/assets/icons/caretLeft.png +0 -0
  123. package/assets/icons/caretLeft@2x.png +0 -0
  124. package/assets/icons/caretLeft@3x.png +0 -0
  125. package/assets/icons/caretRight.png +0 -0
  126. package/assets/icons/caretRight@2x.png +0 -0
  127. package/assets/icons/caretRight@3x.png +0 -0
  128. package/assets/icons/check.png +0 -0
  129. package/assets/icons/check@2x.png +0 -0
  130. package/assets/icons/check@3x.png +0 -0
  131. package/assets/icons/demo/clap.png +0 -0
  132. package/assets/icons/demo/clap@2x.png +0 -0
  133. package/assets/icons/demo/clap@3x.png +0 -0
  134. package/assets/icons/demo/community.png +0 -0
  135. package/assets/icons/demo/community@2x.png +0 -0
  136. package/assets/icons/demo/community@3x.png +0 -0
  137. package/assets/icons/demo/components.png +0 -0
  138. package/assets/icons/demo/components@2x.png +0 -0
  139. package/assets/icons/demo/components@3x.png +0 -0
  140. package/assets/icons/demo/debug.png +0 -0
  141. package/assets/icons/demo/debug@2x.png +0 -0
  142. package/assets/icons/demo/debug@3x.png +0 -0
  143. package/assets/icons/demo/github.png +0 -0
  144. package/assets/icons/demo/github@2x.png +0 -0
  145. package/assets/icons/demo/github@3x.png +0 -0
  146. package/assets/icons/demo/heart.png +0 -0
  147. package/assets/icons/demo/heart@2x.png +0 -0
  148. package/assets/icons/demo/heart@3x.png +0 -0
  149. package/assets/icons/demo/pin.png +0 -0
  150. package/assets/icons/demo/pin@2x.png +0 -0
  151. package/assets/icons/demo/pin@3x.png +0 -0
  152. package/assets/icons/demo/podcast.png +0 -0
  153. package/assets/icons/demo/podcast@2x.png +0 -0
  154. package/assets/icons/demo/podcast@3x.png +0 -0
  155. package/assets/icons/demo/slack.png +0 -0
  156. package/assets/icons/demo/slack@2x.png +0 -0
  157. package/assets/icons/demo/slack@3x.png +0 -0
  158. package/assets/icons/google.png +0 -0
  159. package/assets/icons/hidden.png +0 -0
  160. package/assets/icons/hidden@2x.png +0 -0
  161. package/assets/icons/hidden@3x.png +0 -0
  162. package/assets/icons/ladybug.png +0 -0
  163. package/assets/icons/ladybug@2x.png +0 -0
  164. package/assets/icons/ladybug@3x.png +0 -0
  165. package/assets/icons/lock.png +0 -0
  166. package/assets/icons/lock@2x.png +0 -0
  167. package/assets/icons/lock@3x.png +0 -0
  168. package/assets/icons/menu.png +0 -0
  169. package/assets/icons/menu@2x.png +0 -0
  170. package/assets/icons/menu@3x.png +0 -0
  171. package/assets/icons/more.png +0 -0
  172. package/assets/icons/more@2x.png +0 -0
  173. package/assets/icons/more@3x.png +0 -0
  174. package/assets/icons/settings.png +0 -0
  175. package/assets/icons/settings@2x.png +0 -0
  176. package/assets/icons/settings@3x.png +0 -0
  177. package/assets/icons/view.png +0 -0
  178. package/assets/icons/view@2x.png +0 -0
  179. package/assets/icons/view@3x.png +0 -0
  180. package/assets/icons/x.png +0 -0
  181. package/assets/icons/x@2x.png +0 -0
  182. package/assets/icons/x@3x.png +0 -0
  183. package/assets/images/app-icon-all.png +0 -0
  184. package/assets/images/app-icon-android-adaptive-background.png +0 -0
  185. package/assets/images/app-icon-android-adaptive-foreground.png +0 -0
  186. package/assets/images/app-icon-android-legacy.png +0 -0
  187. package/assets/images/app-icon-ios.png +0 -0
  188. package/assets/images/app-icon-web-favicon.png +0 -0
  189. package/assets/images/demo/cr-logo.png +0 -0
  190. package/assets/images/demo/cr-logo@2x.png +0 -0
  191. package/assets/images/demo/cr-logo@3x.png +0 -0
  192. package/assets/images/demo/rnl-logo.png +0 -0
  193. package/assets/images/demo/rnl-logo@2x.png +0 -0
  194. package/assets/images/demo/rnl-logo@3x.png +0 -0
  195. package/assets/images/demo/rnn-logo.png +0 -0
  196. package/assets/images/demo/rnn-logo@2x.png +0 -0
  197. package/assets/images/demo/rnn-logo@3x.png +0 -0
  198. package/assets/images/demo/rnr-image-1.png +0 -0
  199. package/assets/images/demo/rnr-image-1@2x.png +0 -0
  200. package/assets/images/demo/rnr-image-1@3x.png +0 -0
  201. package/assets/images/demo/rnr-image-2.png +0 -0
  202. package/assets/images/demo/rnr-image-2@2x.png +0 -0
  203. package/assets/images/demo/rnr-image-2@3x.png +0 -0
  204. package/assets/images/demo/rnr-image-3.png +0 -0
  205. package/assets/images/demo/rnr-image-3@2x.png +0 -0
  206. package/assets/images/demo/rnr-image-3@3x.png +0 -0
  207. package/assets/images/demo/rnr-logo.png +0 -0
  208. package/assets/images/demo/rnr-logo@2x.png +0 -0
  209. package/assets/images/demo/rnr-logo@3x.png +0 -0
  210. package/assets/images/logo.png +0 -0
  211. package/assets/images/logo@2x.png +0 -0
  212. package/assets/images/logo@3x.png +0 -0
  213. package/assets/images/sad-face.png +0 -0
  214. package/assets/images/sad-face@2x.png +0 -0
  215. package/assets/images/sad-face@3x.png +0 -0
  216. package/assets/images/welcome-face.png +0 -0
  217. package/assets/images/welcome-face@2x.png +0 -0
  218. package/assets/images/welcome-face@3x.png +0 -0
  219. package/babel.config.js +7 -0
  220. package/bin/cli.js +196 -0
  221. package/ignite/templates/app-icon/android-adaptive-background.png +0 -0
  222. package/ignite/templates/app-icon/android-adaptive-foreground.png +0 -0
  223. package/ignite/templates/app-icon/android-legacy.png +0 -0
  224. package/ignite/templates/app-icon/ios-universal.png +0 -0
  225. package/ignite/templates/component/NAME.tsx.ejs +39 -0
  226. package/ignite/templates/navigator/NAMENavigator.tsx.ejs +18 -0
  227. package/ignite/templates/screen/NAMEScreen.tsx.ejs +29 -0
  228. package/ignite/templates/splash-screen/logo.png +0 -0
  229. package/index.tsx +9 -0
  230. package/jest.config.js +5 -0
  231. package/metro.config.js +31 -0
  232. package/package.json +166 -0
  233. package/plugins/withSplashScreen.ts +69 -0
  234. package/src/app/_layout.tsx +58 -0
  235. package/src/app/index.tsx +5 -0
  236. package/test/i18n.test.ts +75 -0
  237. package/test/mockFile.ts +6 -0
  238. package/test/setup.ts +58 -0
  239. package/test/test-tsconfig.json +8 -0
  240. package/tsconfig.json +52 -0
  241. package/types/lib.es5.d.ts +25 -0
@@ -0,0 +1,313 @@
1
+ import { FC, ReactElement, useCallback, useEffect, useRef, useState } from "react"
2
+ import { Image, ImageStyle, Platform, SectionList, TextStyle, View, ViewStyle } from "react-native"
3
+ import { Link, RouteProp, useRoute } from "@react-navigation/native"
4
+ import { type ContentStyle } from "@shopify/flash-list"
5
+ import { Drawer } from "react-native-drawer-layout"
6
+
7
+ import { ListItem } from "@/components/ListItem"
8
+ import { ListView, type ListViewRef } from "@/components/ListView"
9
+ import { Screen } from "@/components/Screen"
10
+ import { Text } from "@/components/Text"
11
+ import { TxKeyPath, isRTL } from "@/i18n"
12
+ import { translate } from "@/i18n/translate"
13
+ import { DemoTabParamList, DemoTabScreenProps } from "@/navigators/DemoNavigator"
14
+ import type { Theme, ThemedStyle } from "@/theme/types"
15
+ import { useAppTheme } from "@/theme/context"
16
+ import { $styles } from "@/theme/styles"
17
+ import { hasValidStringProp } from "@/utils/hasValidStringProp"
18
+ import { useSafeAreaInsetsStyle } from "@/utils/useSafeAreaInsetsStyle"
19
+
20
+ import * as Demos from "./demos"
21
+ import { DrawerIconButton } from "./DrawerIconButton"
22
+ import SectionListWithKeyboardAwareScrollView from "./SectionListWithKeyboardAwareScrollView"
23
+
24
+ const logo = require("@assets/images/logo.png")
25
+
26
+ export interface Demo {
27
+ name: string
28
+ description: TxKeyPath
29
+ data: ({ themed, theme }: { themed: any; theme: Theme }) => ReactElement[]
30
+ }
31
+
32
+ interface DemoListItem {
33
+ item: { name: string; useCases: string[] }
34
+ sectionIndex: number
35
+ handleScroll?: (sectionIndex: number, itemIndex?: number) => void
36
+ }
37
+
38
+ const slugify = (str: string) =>
39
+ str
40
+ .toLowerCase()
41
+ .trim()
42
+ .replace(/[^\w\s-]/g, "")
43
+ .replace(/[\s_-]+/g, "-")
44
+ .replace(/^-+|-+$/g, "")
45
+
46
+ const WebListItem: FC<DemoListItem> = ({ item, sectionIndex }) => {
47
+ const sectionSlug = item.name.toLowerCase()
48
+ const { themed } = useAppTheme()
49
+ return (
50
+ <View>
51
+ <Link
52
+ screen="DemoShowroom"
53
+ params={{ queryIndex: sectionSlug }}
54
+ style={themed($menuContainer)}
55
+ >
56
+ <Text preset="bold">{item.name}</Text>
57
+ </Link>
58
+ {item.useCases.map((u) => {
59
+ const itemSlug = slugify(u)
60
+
61
+ return (
62
+ <Link
63
+ key={`section${sectionIndex}-${u}`}
64
+ screen="DemoShowroom"
65
+ params={{ queryIndex: sectionSlug, itemIndex: itemSlug }}
66
+ >
67
+ <Text>{u}</Text>
68
+ </Link>
69
+ )
70
+ })}
71
+ </View>
72
+ )
73
+ }
74
+
75
+ const NativeListItem: FC<DemoListItem> = ({ item, sectionIndex, handleScroll }) => {
76
+ const { themed } = useAppTheme()
77
+ return (
78
+ <View>
79
+ <Text
80
+ onPress={() => handleScroll?.(sectionIndex)}
81
+ preset="bold"
82
+ style={themed($menuContainer)}
83
+ >
84
+ {item.name}
85
+ </Text>
86
+ {item.useCases.map((u, index) => (
87
+ <ListItem
88
+ key={`section${sectionIndex}-${u}`}
89
+ onPress={() => handleScroll?.(sectionIndex, index)}
90
+ text={u}
91
+ rightIcon={isRTL ? "caretLeft" : "caretRight"}
92
+ />
93
+ ))}
94
+ </View>
95
+ )
96
+ }
97
+
98
+ const ShowroomListItem = Platform.select({ web: WebListItem, default: NativeListItem })
99
+ const isAndroid = Platform.OS === "android"
100
+
101
+ export const DemoShowroomScreen: FC<DemoTabScreenProps<"DemoShowroom">> =
102
+ function DemoShowroomScreen(_props) {
103
+ const [open, setOpen] = useState(false)
104
+ const timeout = useRef<ReturnType<typeof setTimeout>>(null)
105
+ const listRef = useRef<SectionList>(null)
106
+ const menuRef = useRef<ListViewRef<DemoListItem["item"]>>(null)
107
+ const route = useRoute<RouteProp<DemoTabParamList, "DemoShowroom">>()
108
+ const params = route.params
109
+
110
+ const { themed, theme } = useAppTheme()
111
+
112
+ const toggleDrawer = useCallback(() => {
113
+ if (!open) {
114
+ setOpen(true)
115
+ } else {
116
+ setOpen(false)
117
+ }
118
+ }, [open])
119
+
120
+ const handleScroll = useCallback((sectionIndex: number, itemIndex = 0) => {
121
+ try {
122
+ listRef.current?.scrollToLocation({
123
+ animated: true,
124
+ itemIndex,
125
+ sectionIndex,
126
+ viewPosition: 0.25,
127
+ })
128
+ } catch (e) {
129
+ console.error(e)
130
+ }
131
+ }, [])
132
+
133
+ // handle Web links
134
+ useEffect(() => {
135
+ if (params !== undefined && Object.keys(params).length > 0) {
136
+ const demoValues = Object.values(Demos)
137
+ const findSectionIndex = demoValues.findIndex(
138
+ (x) => x.name.toLowerCase() === params.queryIndex,
139
+ )
140
+ let findItemIndex = 0
141
+ if (params.itemIndex) {
142
+ try {
143
+ findItemIndex = demoValues[findSectionIndex].data({ themed, theme }).findIndex((u) => {
144
+ if (hasValidStringProp(u.props, "name")) {
145
+ return (
146
+ slugify(translate((u.props as { name: TxKeyPath }).name)) === params.itemIndex
147
+ )
148
+ }
149
+ return false
150
+ })
151
+ } catch (err) {
152
+ console.error(err)
153
+ }
154
+ }
155
+ handleScroll(findSectionIndex, findItemIndex)
156
+ }
157
+ }, [handleScroll, params, theme, themed])
158
+
159
+ const scrollToIndexFailed = (info: {
160
+ index: number
161
+ highestMeasuredFrameIndex: number
162
+ averageItemLength: number
163
+ }) => {
164
+ listRef.current?.getScrollResponder()?.scrollToEnd()
165
+ timeout.current = setTimeout(
166
+ () =>
167
+ listRef.current?.scrollToLocation({
168
+ animated: true,
169
+ itemIndex: info.index,
170
+ sectionIndex: 0,
171
+ }),
172
+ 50,
173
+ )
174
+ }
175
+
176
+ useEffect(() => {
177
+ return () => {
178
+ if (timeout.current) {
179
+ clearTimeout(timeout.current)
180
+ }
181
+ }
182
+ }, [])
183
+
184
+ const $drawerInsets = useSafeAreaInsetsStyle(["top"])
185
+
186
+ return (
187
+ <Drawer
188
+ open={open}
189
+ onOpen={() => setOpen(true)}
190
+ onClose={() => setOpen(false)}
191
+ drawerType="back"
192
+ drawerPosition={isRTL ? "right" : "left"}
193
+ renderDrawerContent={() => (
194
+ <View style={themed([$drawer, $drawerInsets])}>
195
+ <View style={themed($logoContainer)}>
196
+ <Image source={logo} style={$logoImage} />
197
+ </View>
198
+ <ListView<DemoListItem["item"]>
199
+ ref={menuRef}
200
+ contentContainerStyle={themed($listContentContainer)}
201
+ estimatedItemSize={250}
202
+ data={Object.values(Demos).map((d) => ({
203
+ name: d.name,
204
+ useCases: d.data({ theme, themed }).map((u) => {
205
+ if (hasValidStringProp(u.props, "name")) {
206
+ return translate((u.props as { name: TxKeyPath }).name)
207
+ }
208
+ return ""
209
+ }),
210
+ }))}
211
+ keyExtractor={(item) => item.name}
212
+ renderItem={({ item, index: sectionIndex }) => (
213
+ <ShowroomListItem {...{ item, sectionIndex, handleScroll }} />
214
+ )}
215
+ />
216
+ </View>
217
+ )}
218
+ >
219
+ <Screen
220
+ preset="fixed"
221
+ safeAreaEdges={["top"]}
222
+ contentContainerStyle={$styles.flex1}
223
+ {...(isAndroid ? { KeyboardAvoidingViewProps: { behavior: undefined } } : {})}
224
+ >
225
+ <DrawerIconButton onPress={toggleDrawer} />
226
+
227
+ <SectionListWithKeyboardAwareScrollView
228
+ ref={listRef}
229
+ contentContainerStyle={themed($sectionListContentContainer)}
230
+ stickySectionHeadersEnabled={false}
231
+ sections={Object.values(Demos).map((d) => ({
232
+ name: d.name,
233
+ description: d.description,
234
+ data: [d.data({ theme, themed })],
235
+ }))}
236
+ renderItem={({ item, index: sectionIndex }) => (
237
+ <View>
238
+ {item.map((demo: ReactElement, demoIndex: number) => (
239
+ <View key={`${sectionIndex}-${demoIndex}`}>{demo}</View>
240
+ ))}
241
+ </View>
242
+ )}
243
+ renderSectionFooter={() => <View style={themed($demoUseCasesSpacer)} />}
244
+ ListHeaderComponent={
245
+ <View style={themed($heading)}>
246
+ <Text preset="heading" tx="demoShowroomScreen:jumpStart" />
247
+ </View>
248
+ }
249
+ onScrollToIndexFailed={scrollToIndexFailed}
250
+ renderSectionHeader={({ section }) => {
251
+ return (
252
+ <View>
253
+ <Text preset="heading" style={themed($demoItemName)}>
254
+ {section.name}
255
+ </Text>
256
+ <Text style={themed($demoItemDescription)}>{translate(section.description)}</Text>
257
+ </View>
258
+ )
259
+ }}
260
+ />
261
+ </Screen>
262
+ </Drawer>
263
+ )
264
+ }
265
+
266
+ const $drawer: ThemedStyle<ViewStyle> = ({ colors }) => ({
267
+ backgroundColor: colors.background,
268
+ flex: 1,
269
+ })
270
+
271
+ const $listContentContainer: ThemedStyle<ContentStyle> = ({ spacing }) => ({
272
+ paddingHorizontal: spacing.lg,
273
+ })
274
+
275
+ const $sectionListContentContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
276
+ paddingHorizontal: spacing.lg,
277
+ })
278
+
279
+ const $heading: ThemedStyle<ViewStyle> = ({ spacing }) => ({
280
+ marginBottom: spacing.xxxl,
281
+ })
282
+
283
+ const $logoImage: ImageStyle = {
284
+ height: 42,
285
+ width: 77,
286
+ }
287
+
288
+ const $logoContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
289
+ alignSelf: "flex-start",
290
+ justifyContent: "center",
291
+ height: 56,
292
+ paddingHorizontal: spacing.lg,
293
+ })
294
+
295
+ const $menuContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
296
+ paddingBottom: spacing.xs,
297
+ paddingTop: spacing.lg,
298
+ })
299
+
300
+ const $demoItemName: ThemedStyle<TextStyle> = ({ spacing }) => ({
301
+ fontSize: 24,
302
+ marginBottom: spacing.md,
303
+ })
304
+
305
+ const $demoItemDescription: ThemedStyle<TextStyle> = ({ spacing }) => ({
306
+ marginBottom: spacing.xxl,
307
+ })
308
+
309
+ const $demoUseCasesSpacer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
310
+ paddingBottom: spacing.xxl,
311
+ })
312
+
313
+ // @demo remove-file
@@ -0,0 +1,52 @@
1
+ import { ReactNode } from "react"
2
+ import { TextStyle, View, ViewStyle } from "react-native"
3
+
4
+ import { Text } from "@/components/Text"
5
+ import type { TxKeyPath } from "@/i18n"
6
+ import { translate } from "@/i18n/translate"
7
+ import type { ThemedStyle } from "@/theme/types"
8
+ import { useAppTheme } from "@/theme/context"
9
+ import { $styles } from "@/theme/styles"
10
+
11
+ interface DemoUseCaseProps {
12
+ name: TxKeyPath
13
+ description?: TxKeyPath
14
+ layout?: "column" | "row"
15
+ itemStyle?: ViewStyle
16
+ children: ReactNode
17
+ }
18
+
19
+ /**
20
+ * @param {DemoUseCaseProps} props - The props for the `DemoUseCase` component.
21
+ * @returns {JSX.Element} The rendered `DemoUseCase` component.
22
+ */
23
+ export function DemoUseCase(props: DemoUseCaseProps) {
24
+ const { name, description, children, layout = "column", itemStyle = {} } = props
25
+ const { themed } = useAppTheme()
26
+
27
+ return (
28
+ <View>
29
+ <Text style={themed($name)}>{translate(name)}</Text>
30
+ {description && <Text style={themed($description)}>{translate(description)}</Text>}
31
+
32
+ <View style={[itemStyle, layout === "row" && $styles.row, themed($item)]}>{children}</View>
33
+ </View>
34
+ )
35
+ }
36
+
37
+ const $description: ThemedStyle<TextStyle> = ({ spacing }) => ({
38
+ marginTop: spacing.md,
39
+ })
40
+
41
+ const $item: ThemedStyle<ViewStyle> = ({ colors, spacing }) => ({
42
+ backgroundColor: colors.palette.neutral100,
43
+ borderRadius: 8,
44
+ padding: spacing.lg,
45
+ marginVertical: spacing.md,
46
+ })
47
+
48
+ const $name: ThemedStyle<TextStyle> = ({ typography }) => ({
49
+ fontFamily: typography.primary.bold,
50
+ })
51
+
52
+ // @demo remove-file
@@ -0,0 +1,120 @@
1
+ import { Pressable, PressableProps, ViewStyle, Platform } from "react-native"
2
+ import { useDrawerProgress } from "react-native-drawer-layout"
3
+ import Animated, { interpolate, interpolateColor, useAnimatedStyle } from "react-native-reanimated"
4
+
5
+ import { isRTL } from "@/i18n"
6
+ import { useAppTheme } from "@/theme/context"
7
+
8
+ interface DrawerIconButtonProps extends PressableProps {}
9
+
10
+ const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
11
+
12
+ /**
13
+ * @param {DrawerIconButtonProps} props - The props for the `DrawerIconButton` component.
14
+ * @returns {JSX.Element} The rendered `DrawerIconButton` component.
15
+ */
16
+ export function DrawerIconButton(props: DrawerIconButtonProps) {
17
+ const { ...PressableProps } = props
18
+ const progress = useDrawerProgress()
19
+ const isWeb = Platform.OS === "web"
20
+ const {
21
+ theme: { colors },
22
+ themed,
23
+ } = useAppTheme()
24
+
25
+ const animatedContainerStyles = useAnimatedStyle(() => {
26
+ const translateX = interpolate(progress.value, [0, 1], [0, isRTL ? 60 : -60])
27
+
28
+ return {
29
+ transform: [{ translateX }],
30
+ }
31
+ })
32
+
33
+ const animatedTopBarStyles = useAnimatedStyle(() => {
34
+ const backgroundColor = interpolateColor(progress.value, [0, 1], [colors.text, colors.tint])
35
+ const marginStart = interpolate(progress.value, [0, 1], [0, -11.5])
36
+ const rotate = interpolate(progress.value, [0, 1], [0, isRTL ? 45 : -45])
37
+ const marginBottom = interpolate(progress.value, [0, 1], [0, -2])
38
+ const width = interpolate(progress.value, [0, 1], [18, 12])
39
+ const marginHorizontal =
40
+ isWeb && isRTL
41
+ ? { marginRight: marginStart }
42
+ : {
43
+ marginLeft: marginStart,
44
+ }
45
+
46
+ return {
47
+ ...marginHorizontal,
48
+ backgroundColor,
49
+ marginBottom,
50
+ width,
51
+ transform: [{ rotate: `${rotate}deg` }],
52
+ }
53
+ })
54
+
55
+ const animatedMiddleBarStyles = useAnimatedStyle(() => {
56
+ const backgroundColor = interpolateColor(progress.value, [0, 1], [colors.text, colors.tint])
57
+ const width = interpolate(progress.value, [0, 1], [18, 16])
58
+
59
+ return {
60
+ backgroundColor,
61
+ width,
62
+ }
63
+ })
64
+
65
+ const animatedBottomBarStyles = useAnimatedStyle(() => {
66
+ const marginTop = interpolate(progress.value, [0, 1], [4, 2])
67
+ const backgroundColor = interpolateColor(progress.value, [0, 1], [colors.text, colors.tint])
68
+ const marginStart = interpolate(progress.value, [0, 1], [0, -11.5])
69
+ const rotate = interpolate(progress.value, [0, 1], [0, isRTL ? -45 : 45])
70
+ const width = interpolate(progress.value, [0, 1], [18, 12])
71
+ const marginHorizontal =
72
+ isWeb && isRTL
73
+ ? { marginRight: marginStart }
74
+ : {
75
+ marginLeft: marginStart,
76
+ }
77
+
78
+ return {
79
+ ...marginHorizontal,
80
+ backgroundColor,
81
+ width,
82
+ marginTop,
83
+ transform: [{ rotate: `${rotate}deg` }],
84
+ }
85
+ })
86
+
87
+ return (
88
+ <AnimatedPressable {...PressableProps} style={[$container, animatedContainerStyles]}>
89
+ <Animated.View style={[$topBar, animatedTopBarStyles]} />
90
+
91
+ <Animated.View style={[themed($middleBar), animatedMiddleBarStyles]} />
92
+
93
+ <Animated.View style={[$bottomBar, animatedBottomBarStyles]} />
94
+ </AnimatedPressable>
95
+ )
96
+ }
97
+
98
+ const barHeight = 2
99
+
100
+ const $container: ViewStyle = {
101
+ alignItems: "center",
102
+ height: 56,
103
+ justifyContent: "center",
104
+ width: 56,
105
+ }
106
+
107
+ const $topBar: ViewStyle = {
108
+ height: barHeight,
109
+ }
110
+
111
+ const $middleBar: ViewStyle = {
112
+ height: barHeight,
113
+ marginTop: 4,
114
+ }
115
+
116
+ const $bottomBar: ViewStyle = {
117
+ height: barHeight,
118
+ }
119
+
120
+ // @demo remove-file
@@ -0,0 +1,59 @@
1
+ import { forwardRef, ReactElement, ReactNode, useCallback } from "react"
2
+ import { ScrollViewProps, SectionList, SectionListProps } from "react-native"
3
+ import { KeyboardAwareScrollView } from "react-native-keyboard-controller"
4
+
5
+ import { DEFAULT_BOTTOM_OFFSET } from "@/components/Screen"
6
+
7
+ type SectionType<ItemType> = {
8
+ name: string
9
+ description: string
10
+ data: ItemType[]
11
+ }
12
+
13
+ type SectionListWithKeyboardAwareScrollViewProps<ItemType> = SectionListProps<ItemType> & {
14
+ /* Optional function to pass a custom scroll component */
15
+ renderScrollComponent?: (props: ScrollViewProps) => ReactNode
16
+ /* Optional additional offset between TextInput bottom edge and keyboard top edge. See https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-aware-scroll-view#bottomoffset */
17
+ bottomOffset?: number
18
+ /* The sections to be rendered in the list */
19
+ sections: SectionType<ItemType>[]
20
+ /* Function to render the header for each section */
21
+ renderSectionHeader: ({ section }: { section: SectionType<ItemType> }) => React.ReactNode
22
+ }
23
+
24
+ function SectionListWithKeyboardAwareScrollView<ItemType = any>(
25
+ {
26
+ renderScrollComponent,
27
+ bottomOffset = DEFAULT_BOTTOM_OFFSET,
28
+ contentContainerStyle,
29
+ ...props
30
+ }: SectionListWithKeyboardAwareScrollViewProps<ItemType>,
31
+ ref: React.Ref<SectionList<ItemType>>,
32
+ ): ReactElement {
33
+ const defaultRenderScrollComponent = useCallback(
34
+ (props: ScrollViewProps) => (
35
+ <KeyboardAwareScrollView
36
+ contentContainerStyle={contentContainerStyle}
37
+ bottomOffset={bottomOffset}
38
+ {...props}
39
+ />
40
+ ),
41
+ [contentContainerStyle, bottomOffset],
42
+ )
43
+
44
+ return (
45
+ <SectionList
46
+ {...props}
47
+ ref={ref}
48
+ renderScrollComponent={renderScrollComponent ?? defaultRenderScrollComponent}
49
+ />
50
+ )
51
+ }
52
+
53
+ export default forwardRef(SectionListWithKeyboardAwareScrollView) as <ItemType = any>(
54
+ props: SectionListWithKeyboardAwareScrollViewProps<ItemType> & {
55
+ ref?: React.Ref<SectionList<ItemType>>
56
+ },
57
+ ) => ReactElement
58
+
59
+ // @demo remove-file