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,354 @@
1
+ /* eslint-disable react/jsx-key, react-native/no-inline-styles */
2
+ import { useState } from "react"
3
+ import { TextStyle, View, ViewStyle } from "react-native"
4
+
5
+ import { Text } from "@/components/Text"
6
+ import { Checkbox, CheckboxToggleProps } from "@/components/Toggle/Checkbox"
7
+ import { Radio, RadioToggleProps } from "@/components/Toggle/Radio"
8
+ import { Switch, SwitchToggleProps } from "@/components/Toggle/Switch"
9
+ import { translate } from "@/i18n/translate"
10
+ import type { ThemedStyle } from "@/theme/types"
11
+ import { $styles } from "@/theme/styles"
12
+
13
+ import { DemoDivider } from "../DemoDivider"
14
+ import { Demo } from "../DemoShowroomScreen"
15
+ import { DemoUseCase } from "../DemoUseCase"
16
+
17
+ function ControlledCheckbox(props: CheckboxToggleProps) {
18
+ const [value, setValue] = useState(props.value || false)
19
+ return <Checkbox {...props} value={value} onPress={() => setValue(!value)} />
20
+ }
21
+
22
+ function ControlledRadio(props: RadioToggleProps) {
23
+ const [value, setValue] = useState(props.value || false)
24
+ return <Radio {...props} value={value} onPress={() => setValue(!value)} />
25
+ }
26
+
27
+ function ControlledSwitch(props: SwitchToggleProps) {
28
+ const [value, setValue] = useState(props.value || false)
29
+ return <Switch {...props} value={value} onPress={() => setValue(!value)} />
30
+ }
31
+
32
+ const $centeredOneThirdCol: ViewStyle = {
33
+ width: "33.33333%",
34
+ alignItems: "center",
35
+ justifyContent: "center",
36
+ }
37
+ const $centeredText: ThemedStyle<TextStyle> = ({ spacing }) => ({
38
+ textAlign: "center",
39
+ width: "100%",
40
+ marginTop: spacing.xs,
41
+ })
42
+
43
+ export const DemoToggle: Demo = {
44
+ name: "Toggle",
45
+ description: "demoToggle:description",
46
+ data: ({ theme, themed }) => [
47
+ <DemoUseCase
48
+ name="demoToggle:useCase.variants.name"
49
+ description="demoToggle:useCase.variants.description"
50
+ >
51
+ <ControlledCheckbox
52
+ labelTx="demoToggle:useCase.variants.checkbox.label"
53
+ helperTx="demoToggle:useCase.variants.checkbox.helper"
54
+ />
55
+ <DemoDivider size={24} />
56
+ <ControlledRadio
57
+ labelTx="demoToggle:useCase.variants.radio.label"
58
+ helperTx="demoToggle:useCase.variants.radio.helper"
59
+ />
60
+ <DemoDivider size={24} />
61
+ <ControlledSwitch
62
+ labelTx="demoToggle:useCase.variants.switch.label"
63
+ helperTx="demoToggle:useCase.variants.switch.helper"
64
+ />
65
+ </DemoUseCase>,
66
+
67
+ <DemoUseCase
68
+ name="demoToggle:useCase.statuses.name"
69
+ description="demoToggle:useCase.statuses.description"
70
+ layout="row"
71
+ itemStyle={$styles.flexWrap}
72
+ >
73
+ <ControlledCheckbox containerStyle={$centeredOneThirdCol} />
74
+ <ControlledRadio containerStyle={$centeredOneThirdCol} />
75
+ <ControlledSwitch containerStyle={$centeredOneThirdCol} />
76
+ <DemoDivider style={{ width: "100%" }} />
77
+ <ControlledCheckbox value containerStyle={$centeredOneThirdCol} />
78
+ <ControlledRadio value containerStyle={$centeredOneThirdCol} />
79
+ <ControlledSwitch value containerStyle={$centeredOneThirdCol} />
80
+ <Text preset="formHelper" style={themed($centeredText)}>
81
+ {translate("demoToggle:useCase.statuses.noStatus")}
82
+ </Text>
83
+
84
+ <DemoDivider size={24} style={{ width: "100%" }} />
85
+
86
+ <ControlledCheckbox status="error" containerStyle={$centeredOneThirdCol} />
87
+ <ControlledRadio status="error" containerStyle={$centeredOneThirdCol} />
88
+ <ControlledSwitch status="error" containerStyle={$centeredOneThirdCol} />
89
+ <DemoDivider style={{ width: "100%" }} />
90
+ <ControlledCheckbox value status="error" containerStyle={$centeredOneThirdCol} />
91
+ <ControlledRadio value status="error" containerStyle={$centeredOneThirdCol} />
92
+ <ControlledSwitch value status="error" containerStyle={$centeredOneThirdCol} />
93
+ <Text preset="formHelper" style={themed($centeredText)}>
94
+ {translate("demoToggle:useCase.statuses.errorStatus")}
95
+ </Text>
96
+
97
+ <DemoDivider size={24} style={{ width: "100%" }} />
98
+
99
+ <ControlledCheckbox status="disabled" containerStyle={$centeredOneThirdCol} />
100
+ <ControlledRadio status="disabled" containerStyle={$centeredOneThirdCol} />
101
+ <ControlledSwitch status="disabled" containerStyle={$centeredOneThirdCol} />
102
+ <DemoDivider style={{ width: "100%" }} />
103
+ <ControlledCheckbox value status="disabled" containerStyle={$centeredOneThirdCol} />
104
+ <ControlledRadio value status="disabled" containerStyle={$centeredOneThirdCol} />
105
+ <ControlledSwitch value status="disabled" containerStyle={$centeredOneThirdCol} />
106
+ <Text preset="formHelper" style={themed($centeredText)}>
107
+ {translate("demoToggle:useCase.statuses.disabledStatus")}
108
+ </Text>
109
+ </DemoUseCase>,
110
+
111
+ <DemoUseCase
112
+ name="demoToggle:useCase.passingContent.name"
113
+ description="demoToggle:useCase.passingContent.description"
114
+ >
115
+ <ControlledCheckbox
116
+ value
117
+ labelTx="demoToggle:useCase.passingContent.useCase.checkBox.label"
118
+ helperTx="demoToggle:useCase.passingContent.useCase.checkBox.helper"
119
+ />
120
+ <DemoDivider size={24} />
121
+ <ControlledRadio
122
+ value
123
+ labelTx="demoShowroomScreen:demoViaSpecifiedTxProp"
124
+ labelTxOptions={{ prop: "label" }}
125
+ helperTx="demoShowroomScreen:demoViaSpecifiedTxProp"
126
+ helperTxOptions={{ prop: "helper" }}
127
+ />
128
+ <DemoDivider size={24} />
129
+ <ControlledCheckbox
130
+ value
131
+ labelTx="demoToggle:useCase.passingContent.useCase.checkBoxMultiLine.helper"
132
+ editable={false}
133
+ />
134
+ <DemoDivider size={24} />
135
+ <ControlledRadio
136
+ value
137
+ labelTx="demoToggle:useCase.passingContent.useCase.radioChangeSides.helper"
138
+ labelPosition="left"
139
+ />
140
+ <DemoDivider size={24} />
141
+ <ControlledCheckbox
142
+ value
143
+ status="error"
144
+ icon="ladybug"
145
+ labelTx="demoToggle:useCase.passingContent.useCase.customCheckBox.label"
146
+ />
147
+ <DemoDivider size={24} />
148
+ <ControlledSwitch
149
+ value
150
+ accessibilityMode="text"
151
+ labelTx="demoToggle:useCase.passingContent.useCase.switch.label"
152
+ status="error"
153
+ helperTx="demoToggle:useCase.passingContent.useCase.switch.helper"
154
+ />
155
+ <DemoDivider size={24} />
156
+ <ControlledSwitch
157
+ value
158
+ labelPosition="left"
159
+ accessibilityMode="icon"
160
+ labelTx="demoToggle:useCase.passingContent.useCase.switchAid.label"
161
+ />
162
+ </DemoUseCase>,
163
+
164
+ <DemoUseCase
165
+ name="demoToggle:useCase.styling.name"
166
+ description="demoToggle:useCase.styling.description"
167
+ layout="row"
168
+ itemStyle={$styles.flexWrap}
169
+ >
170
+ <ControlledCheckbox
171
+ containerStyle={$centeredOneThirdCol}
172
+ inputOuterStyle={{
173
+ width: 50,
174
+ height: 50,
175
+ backgroundColor: theme.colors.palette.accent300,
176
+ borderColor: theme.colors.palette.accent500,
177
+ }}
178
+ />
179
+ <ControlledRadio
180
+ containerStyle={$centeredOneThirdCol}
181
+ inputOuterStyle={{
182
+ width: 50,
183
+ height: 50,
184
+ borderRadius: 25,
185
+ backgroundColor: theme.colors.palette.accent300,
186
+ borderColor: theme.colors.palette.accent500,
187
+ }}
188
+ />
189
+ <ControlledSwitch
190
+ containerStyle={$centeredOneThirdCol}
191
+ inputOuterStyle={{
192
+ width: 70,
193
+ height: 50,
194
+ borderRadius: 25,
195
+ backgroundColor: theme.colors.palette.accent300,
196
+ borderColor: theme.colors.palette.accent500,
197
+ }}
198
+ />
199
+ <Text preset="formHelper" style={themed($centeredText)}>
200
+ {translate("demoToggle:useCase.styling.outerWrapper")}
201
+ </Text>
202
+
203
+ <DemoDivider style={{ width: "100%" }} />
204
+
205
+ <ControlledCheckbox
206
+ value
207
+ containerStyle={$centeredOneThirdCol}
208
+ inputOuterStyle={{
209
+ width: 50,
210
+ height: 50,
211
+ backgroundColor: theme.colors.palette.accent300,
212
+ borderColor: theme.colors.palette.accent500,
213
+ }}
214
+ inputInnerStyle={{
215
+ backgroundColor: theme.colors.palette.accent500,
216
+ }}
217
+ />
218
+ <ControlledRadio
219
+ value
220
+ containerStyle={$centeredOneThirdCol}
221
+ inputOuterStyle={{
222
+ width: 50,
223
+ height: 50,
224
+ borderRadius: 25,
225
+ backgroundColor: theme.colors.palette.accent300,
226
+ borderColor: theme.colors.palette.accent500,
227
+ }}
228
+ inputInnerStyle={{
229
+ backgroundColor: theme.colors.palette.accent500,
230
+ }}
231
+ />
232
+ <ControlledSwitch
233
+ value
234
+ containerStyle={$centeredOneThirdCol}
235
+ inputOuterStyle={{
236
+ width: 70,
237
+ height: 50,
238
+ borderRadius: 25,
239
+ backgroundColor: theme.colors.palette.accent300,
240
+ borderColor: theme.colors.palette.accent500,
241
+ }}
242
+ inputInnerStyle={{
243
+ backgroundColor: theme.colors.palette.accent500,
244
+ paddingLeft: 10,
245
+ paddingRight: 10,
246
+ }}
247
+ />
248
+ <Text preset="formHelper" style={themed($centeredText)}>
249
+ {translate("demoToggle:useCase.styling.innerWrapper")}
250
+ </Text>
251
+
252
+ <DemoDivider style={{ width: "100%" }} />
253
+
254
+ <ControlledCheckbox
255
+ value
256
+ icon="ladybug"
257
+ containerStyle={$centeredOneThirdCol}
258
+ inputOuterStyle={{
259
+ width: 50,
260
+ height: 50,
261
+ backgroundColor: theme.colors.palette.accent300,
262
+ borderColor: theme.colors.palette.accent500,
263
+ }}
264
+ inputInnerStyle={{
265
+ backgroundColor: theme.colors.palette.accent500,
266
+ }}
267
+ inputDetailStyle={{
268
+ tintColor: theme.colors.tint,
269
+ height: 35,
270
+ width: 35,
271
+ }}
272
+ />
273
+ <ControlledRadio
274
+ value
275
+ containerStyle={$centeredOneThirdCol}
276
+ inputOuterStyle={{
277
+ width: 50,
278
+ height: 50,
279
+ borderRadius: 25,
280
+ backgroundColor: theme.colors.palette.accent300,
281
+ borderColor: theme.colors.palette.accent500,
282
+ }}
283
+ inputInnerStyle={{
284
+ backgroundColor: theme.colors.palette.accent500,
285
+ }}
286
+ inputDetailStyle={{
287
+ backgroundColor: theme.colors.tint,
288
+ height: 36,
289
+ width: 36,
290
+ borderRadius: 18,
291
+ }}
292
+ />
293
+
294
+ <ControlledSwitch
295
+ value
296
+ containerStyle={$centeredOneThirdCol}
297
+ inputOuterStyle={{
298
+ width: 70,
299
+ height: 50,
300
+ borderRadius: 25,
301
+ backgroundColor: theme.colors.palette.accent300,
302
+ borderColor: theme.colors.palette.accent500,
303
+ }}
304
+ inputInnerStyle={{
305
+ backgroundColor: theme.colors.tint,
306
+ paddingLeft: 10,
307
+ paddingRight: 10,
308
+ }}
309
+ inputDetailStyle={{
310
+ backgroundColor: theme.colors.palette.accent300,
311
+ height: 36,
312
+ width: 18,
313
+ borderRadius: 36,
314
+ }}
315
+ accessibilityMode="icon"
316
+ />
317
+
318
+ <Text preset="formHelper" style={themed($centeredText)}>
319
+ {translate("demoToggle:useCase.styling.inputDetail")}
320
+ </Text>
321
+
322
+ <DemoDivider size={32} style={{ width: "100%" }} />
323
+
324
+ <View style={{ width: "100%" }}>
325
+ <ControlledRadio
326
+ value
327
+ labelTx="demoToggle:useCase.styling.labelTx"
328
+ LabelTextProps={{ size: "xs", weight: "bold" }}
329
+ status="error"
330
+ labelStyle={{
331
+ backgroundColor: theme.colors.error,
332
+ color: theme.colors.palette.neutral100,
333
+ paddingHorizontal: 5,
334
+ }}
335
+ />
336
+ </View>
337
+
338
+ <DemoDivider size={24} style={{ width: "100%" }} />
339
+
340
+ <View style={{ width: "100%" }}>
341
+ <ControlledRadio
342
+ value
343
+ labelPosition="left"
344
+ containerStyle={{ padding: 10, backgroundColor: theme.colors.error }}
345
+ labelTx="demoToggle:useCase.styling.styleContainer"
346
+ status="error"
347
+ labelStyle={{ color: theme.colors.palette.neutral100 }}
348
+ />
349
+ </View>
350
+ </DemoUseCase>,
351
+ ],
352
+ }
353
+
354
+ // @demo remove-file
@@ -0,0 +1,12 @@
1
+ export * from "./DemoIcon"
2
+ export * from "./DemoTextField"
3
+ export * from "./DemoToggle"
4
+ export * from "./DemoButton"
5
+ export * from "./DemoListItem"
6
+ export * from "./DemoCard"
7
+ export * from "./DemoAutoImage"
8
+ export * from "./DemoText"
9
+ export * from "./DemoHeader"
10
+ export * from "./DemoEmptyState"
11
+
12
+ // @demo remove-file
@@ -0,0 +1,76 @@
1
+ import { Component, ErrorInfo, ReactNode } from "react"
2
+
3
+ import { ErrorDetails } from "./ErrorDetails"
4
+
5
+ interface Props {
6
+ children: ReactNode
7
+ catchErrors: "always" | "dev" | "prod" | "never"
8
+ }
9
+
10
+ interface State {
11
+ error: Error | null
12
+ errorInfo: ErrorInfo | null
13
+ }
14
+
15
+ /**
16
+ * This component handles whenever the user encounters a JS error in the
17
+ * app. It follows the "error boundary" pattern in React. We're using a
18
+ * class component because according to the documentation, only class
19
+ * components can be error boundaries.
20
+ * @see [Documentation and Examples]{@link https://docs.infinite.red/ignite-cli/concept/Error-Boundary/}
21
+ * @see [React Error Boundaries]{@link https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary}
22
+ * @param {Props} props - The props for the `ErrorBoundary` component.
23
+ * @returns {JSX.Element} The rendered `ErrorBoundary` component.
24
+ */
25
+ export class ErrorBoundary extends Component<Props, State> {
26
+ state = { error: null, errorInfo: null }
27
+
28
+ // If an error in a child is encountered, this will run
29
+ componentDidCatch(error: Error, errorInfo: ErrorInfo) {
30
+ // Only set errors if enabled
31
+ if (!this.isEnabled()) {
32
+ return
33
+ }
34
+ // Catch errors in any components below and re-render with error message
35
+ this.setState({
36
+ error,
37
+ errorInfo,
38
+ })
39
+
40
+ // You can also log error messages to an error reporting service here
41
+ // This is a great place to put BugSnag, Sentry, crashlytics, etc:
42
+ // reportCrash(error)
43
+ }
44
+
45
+ // Reset the error back to null
46
+ resetError = () => {
47
+ this.setState({ error: null, errorInfo: null })
48
+ }
49
+
50
+ // To avoid unnecessary re-renders
51
+ shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>): boolean {
52
+ return nextState.error !== this.state.error
53
+ }
54
+
55
+ // Only enable if we're catching errors in the right environment
56
+ isEnabled(): boolean {
57
+ return (
58
+ this.props.catchErrors === "always" ||
59
+ (this.props.catchErrors === "dev" && __DEV__) ||
60
+ (this.props.catchErrors === "prod" && !__DEV__)
61
+ )
62
+ }
63
+
64
+ // Render an error UI if there's an error; otherwise, render children
65
+ render() {
66
+ return this.isEnabled() && this.state.error ? (
67
+ <ErrorDetails
68
+ onReset={this.resetError}
69
+ error={this.state.error}
70
+ errorInfo={this.state.errorInfo}
71
+ />
72
+ ) : (
73
+ this.props.children
74
+ )
75
+ }
76
+ }
@@ -0,0 +1,98 @@
1
+ import { ErrorInfo } from "react"
2
+ import { ScrollView, TextStyle, View, ViewStyle } from "react-native"
3
+
4
+ import { Button } from "@/components/Button"
5
+ import { Icon } from "@/components/Icon"
6
+ import { Screen } from "@/components/Screen"
7
+ import { Text } from "@/components/Text"
8
+ import type { ThemedStyle } from "@/theme/types"
9
+ import { useAppTheme } from "@/theme/context"
10
+
11
+ export interface ErrorDetailsProps {
12
+ error: Error
13
+ errorInfo: ErrorInfo | null
14
+ onReset(): void
15
+ }
16
+
17
+ /**
18
+ * Renders the error details screen.
19
+ * @param {ErrorDetailsProps} props - The props for the `ErrorDetails` component.
20
+ * @returns {JSX.Element} The rendered `ErrorDetails` component.
21
+ */
22
+ export function ErrorDetails(props: ErrorDetailsProps) {
23
+ const { themed } = useAppTheme()
24
+ return (
25
+ <Screen
26
+ preset="fixed"
27
+ safeAreaEdges={["top", "bottom"]}
28
+ contentContainerStyle={themed($contentContainer)}
29
+ >
30
+ <View style={$topSection}>
31
+ <Icon icon="ladybug" size={64} />
32
+ <Text style={themed($heading)} preset="subheading" tx="errorScreen:title" />
33
+ <Text tx="errorScreen:friendlySubtitle" />
34
+ </View>
35
+
36
+ <ScrollView
37
+ style={themed($errorSection)}
38
+ contentContainerStyle={themed($errorSectionContentContainer)}
39
+ >
40
+ <Text style={themed($errorContent)} weight="bold" text={`${props.error}`.trim()} />
41
+ <Text
42
+ selectable
43
+ style={themed($errorBacktrace)}
44
+ text={`${props.errorInfo?.componentStack ?? ""}`.trim()}
45
+ />
46
+ </ScrollView>
47
+
48
+ <Button
49
+ preset="reversed"
50
+ style={themed($resetButton)}
51
+ onPress={props.onReset}
52
+ tx="errorScreen:reset"
53
+ />
54
+ </Screen>
55
+ )
56
+ }
57
+
58
+ const $contentContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
59
+ alignItems: "center",
60
+ paddingHorizontal: spacing.lg,
61
+ paddingTop: spacing.xl,
62
+ flex: 1,
63
+ })
64
+
65
+ const $topSection: ViewStyle = {
66
+ flex: 1,
67
+ alignItems: "center",
68
+ }
69
+
70
+ const $heading: ThemedStyle<TextStyle> = ({ colors, spacing }) => ({
71
+ color: colors.error,
72
+ marginBottom: spacing.md,
73
+ })
74
+
75
+ const $errorSection: ThemedStyle<ViewStyle> = ({ colors, spacing }) => ({
76
+ flex: 2,
77
+ backgroundColor: colors.separator,
78
+ marginVertical: spacing.md,
79
+ borderRadius: 6,
80
+ })
81
+
82
+ const $errorSectionContentContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
83
+ padding: spacing.md,
84
+ })
85
+
86
+ const $errorContent: ThemedStyle<TextStyle> = ({ colors }) => ({
87
+ color: colors.error,
88
+ })
89
+
90
+ const $errorBacktrace: ThemedStyle<TextStyle> = ({ colors, spacing }) => ({
91
+ marginTop: spacing.md,
92
+ color: colors.textDim,
93
+ })
94
+
95
+ const $resetButton: ThemedStyle<ViewStyle> = ({ colors, spacing }) => ({
96
+ backgroundColor: colors.error,
97
+ paddingHorizontal: spacing.xxl,
98
+ })