create-du-app 0.1.3 → 0.1.4

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 (414) hide show
  1. package/README.md +10 -7
  2. package/package.json +6 -5
  3. package/src/index.js +8 -8
  4. package/src/prompts.js +1 -1
  5. package/templates/mobile/expo/.env.example +5 -0
  6. package/templates/mobile/expo/.eslintrc.js +7 -0
  7. package/templates/mobile/expo/.prettierrc.js +7 -0
  8. package/templates/mobile/expo/.svgrrc.js +9 -0
  9. package/templates/mobile/expo/README.md +42 -7
  10. package/templates/mobile/expo/_gitignore +20 -0
  11. package/templates/mobile/expo/_package.json +62 -1
  12. package/templates/mobile/expo/app.json +18 -0
  13. package/templates/mobile/expo/babel.config.js +21 -0
  14. package/templates/mobile/expo/index.js +5 -0
  15. package/templates/mobile/expo/metro.config.js +31 -0
  16. package/templates/mobile/expo/src/app/App.tsx +24 -0
  17. package/templates/mobile/expo/src/app/app-provider.tsx +36 -0
  18. package/templates/mobile/expo/src/app/config/translation.ts +26 -0
  19. package/templates/mobile/expo/src/app/index.ts +1 -0
  20. package/templates/mobile/expo/src/app/navigation/app-route-type.ts +27 -0
  21. package/templates/mobile/expo/src/app/navigation/bottom-tabs.tsx +34 -0
  22. package/templates/mobile/expo/src/app/navigation/index.tsx +14 -0
  23. package/templates/mobile/expo/src/app/stores/auth.store.ts +33 -0
  24. package/templates/mobile/expo/src/app/stores/common.store.ts +19 -0
  25. package/templates/mobile/expo/src/app/stores/index.ts +3 -0
  26. package/templates/mobile/expo/src/app/stores/loading.store.ts +22 -0
  27. package/templates/mobile/expo/src/assets/Images/empty-list.png +0 -0
  28. package/templates/mobile/expo/src/assets/Images/index.ts +5 -0
  29. package/templates/mobile/expo/src/assets/Images/screen-bg-gradian.png +0 -0
  30. package/templates/mobile/expo/src/assets/i18n/en.json +12 -0
  31. package/templates/mobile/expo/src/assets/i18n/fr.json +12 -0
  32. package/templates/mobile/expo/src/assets/lotties/index.ts +3 -0
  33. package/templates/mobile/expo/src/assets/lotties/loading.json +1 -0
  34. package/templates/mobile/expo/src/assets/svgs/arrow-left.svg +3 -0
  35. package/templates/mobile/expo/src/assets/svgs/arrow-right.svg +3 -0
  36. package/templates/mobile/expo/src/assets/svgs/calendar.svg +12 -0
  37. package/templates/mobile/expo/src/assets/svgs/check.svg +3 -0
  38. package/templates/mobile/expo/src/assets/svgs/close.svg +3 -0
  39. package/templates/mobile/expo/src/assets/svgs/eye-hide.svg +3 -0
  40. package/templates/mobile/expo/src/assets/svgs/eye.svg +4 -0
  41. package/templates/mobile/expo/src/assets/svgs/index.ts +29 -0
  42. package/templates/mobile/expo/src/assets/svgs/minus.svg +3 -0
  43. package/templates/mobile/expo/src/assets/svgs/plus.svg +3 -0
  44. package/templates/mobile/expo/src/assets/svgs/search.svg +3 -0
  45. package/templates/mobile/expo/src/assets/svgs/toast-error.svg +5 -0
  46. package/templates/mobile/expo/src/assets/svgs/toast-success.svg +4 -0
  47. package/templates/mobile/expo/src/core/api/endpoints.ts +8 -0
  48. package/templates/mobile/expo/src/core/api/example.api.ts +53 -0
  49. package/templates/mobile/expo/src/core/api/index.ts +4 -0
  50. package/templates/mobile/expo/src/core/components/common/index.ts +1 -0
  51. package/templates/mobile/expo/src/core/components/common/list-empty/index.ts +2 -0
  52. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.tsx +30 -0
  53. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  54. package/templates/mobile/expo/src/core/components/forms/hf-date-time.tsx +301 -0
  55. package/templates/mobile/expo/src/core/components/forms/hf-password-input.tsx +153 -0
  56. package/templates/mobile/expo/src/core/components/forms/hf-text-input.tsx +59 -0
  57. package/templates/mobile/expo/src/core/components/forms/hf-time-picker.tsx +117 -0
  58. package/templates/mobile/expo/src/core/components/forms/index.ts +4 -0
  59. package/templates/mobile/expo/src/core/components/index.ts +5 -0
  60. package/templates/mobile/expo/src/core/components/loading/index.ts +1 -0
  61. package/templates/mobile/expo/src/core/components/loading/loading-app/index.ts +1 -0
  62. package/templates/mobile/expo/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  63. package/templates/mobile/expo/src/core/components/offline/index.ts +1 -0
  64. package/templates/mobile/expo/src/core/components/offline/offline-banner.tsx +186 -0
  65. package/templates/mobile/expo/src/core/components/screen/index.ts +1 -0
  66. package/templates/mobile/expo/src/core/components/screen/screen-container/index.ts +1 -0
  67. package/templates/mobile/expo/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  68. package/templates/mobile/expo/src/core/components/splash/index.ts +1 -0
  69. package/templates/mobile/expo/src/core/components/splash/splash-overlay/index.ts +1 -0
  70. package/templates/mobile/expo/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  71. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  72. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  73. package/templates/mobile/expo/src/core/components/ui/animated-list-item/index.ts +2 -0
  74. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.tsx +104 -0
  75. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.type.ts +19 -0
  76. package/templates/mobile/expo/src/core/components/ui/app-image/index.ts +2 -0
  77. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  78. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/index.ts +1 -0
  79. package/templates/mobile/expo/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  80. package/templates/mobile/expo/src/core/components/ui/avatar-image/index.ts +1 -0
  81. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  82. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  83. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/index.ts +2 -0
  84. package/templates/mobile/expo/src/core/components/ui/button/button.style.ts +146 -0
  85. package/templates/mobile/expo/src/core/components/ui/button/button.tsx +97 -0
  86. package/templates/mobile/expo/src/core/components/ui/button/button.type.ts +47 -0
  87. package/templates/mobile/expo/src/core/components/ui/button/index.ts +4 -0
  88. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  89. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  90. package/templates/mobile/expo/src/core/components/ui/checkbox/index.ts +2 -0
  91. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  92. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  93. package/templates/mobile/expo/src/core/components/ui/collapsible-section/index.ts +2 -0
  94. package/templates/mobile/expo/src/core/components/ui/components.registry.json +313 -0
  95. package/templates/mobile/expo/src/core/components/ui/field/field-frame.tsx +62 -0
  96. package/templates/mobile/expo/src/core/components/ui/field/field.shared.ts +31 -0
  97. package/templates/mobile/expo/src/core/components/ui/header/header.tsx +196 -0
  98. package/templates/mobile/expo/src/core/components/ui/header/header.type.ts +30 -0
  99. package/templates/mobile/expo/src/core/components/ui/header/index.ts +2 -0
  100. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  101. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  102. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  103. package/templates/mobile/expo/src/core/components/ui/icon-button/index.ts +2 -0
  104. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  105. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  106. package/templates/mobile/expo/src/core/components/ui/image-slider/index.ts +2 -0
  107. package/templates/mobile/expo/src/core/components/ui/index.ts +25 -0
  108. package/templates/mobile/expo/src/core/components/ui/label/index.ts +2 -0
  109. package/templates/mobile/expo/src/core/components/ui/label/label.tsx +36 -0
  110. package/templates/mobile/expo/src/core/components/ui/label/label.type.ts +12 -0
  111. package/templates/mobile/expo/src/core/components/ui/modal/index.ts +2 -0
  112. package/templates/mobile/expo/src/core/components/ui/modal/modal.tsx +62 -0
  113. package/templates/mobile/expo/src/core/components/ui/modal/modal.type.ts +11 -0
  114. package/templates/mobile/expo/src/core/components/ui/otp-input/index.ts +2 -0
  115. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  116. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  117. package/templates/mobile/expo/src/core/components/ui/page-dots/index.ts +1 -0
  118. package/templates/mobile/expo/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  119. package/templates/mobile/expo/src/core/components/ui/radio/index.ts +2 -0
  120. package/templates/mobile/expo/src/core/components/ui/radio/radio.tsx +121 -0
  121. package/templates/mobile/expo/src/core/components/ui/radio/radio.type.ts +20 -0
  122. package/templates/mobile/expo/src/core/components/ui/screen/index.ts +1 -0
  123. package/templates/mobile/expo/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  124. package/templates/mobile/expo/src/core/components/ui/search-box/index.ts +2 -0
  125. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.tsx +162 -0
  126. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.type.ts +26 -0
  127. package/templates/mobile/expo/src/core/components/ui/segmented-control/index.ts +2 -0
  128. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  129. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  130. package/templates/mobile/expo/src/core/components/ui/skeleton/index.ts +2 -0
  131. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  132. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  133. package/templates/mobile/expo/src/core/components/ui/success-state/index.ts +1 -0
  134. package/templates/mobile/expo/src/core/components/ui/success-state/success-state.tsx +68 -0
  135. package/templates/mobile/expo/src/core/components/ui/tabs/index.ts +2 -0
  136. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.tsx +273 -0
  137. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.type.ts +21 -0
  138. package/templates/mobile/expo/src/core/components/ui/tag-input/index.ts +2 -0
  139. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  140. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  141. package/templates/mobile/expo/src/core/components/ui/text-area/index.ts +2 -0
  142. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.tsx +90 -0
  143. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.type.ts +20 -0
  144. package/templates/mobile/expo/src/core/components/ui/text-field/index.ts +2 -0
  145. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.tsx +116 -0
  146. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.type.ts +21 -0
  147. package/templates/mobile/expo/src/core/components/ui/toggle/index.ts +2 -0
  148. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.tsx +110 -0
  149. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.type.ts +19 -0
  150. package/templates/mobile/expo/src/core/constants/external-urls.constant.ts +5 -0
  151. package/templates/mobile/expo/src/core/constants/hard-data.constant.ts +0 -0
  152. package/templates/mobile/expo/src/core/constants/index.ts +2 -0
  153. package/templates/mobile/expo/src/core/constants/type.constant.ts +3 -0
  154. package/templates/mobile/expo/src/core/context/index.ts +1 -0
  155. package/templates/mobile/expo/src/core/context/shared-transition-context.tsx +35 -0
  156. package/templates/mobile/expo/src/core/hook/index.ts +8 -0
  157. package/templates/mobile/expo/src/core/hook/useActiveRouteName.ts +63 -0
  158. package/templates/mobile/expo/src/core/hook/useAppNavigation.tsx +7 -0
  159. package/templates/mobile/expo/src/core/hook/useBottomInset.tsx +26 -0
  160. package/templates/mobile/expo/src/core/hook/useDebounce.tsx +16 -0
  161. package/templates/mobile/expo/src/core/hook/useEndReached.tsx +46 -0
  162. package/templates/mobile/expo/src/core/hook/useManualRefetch.ts +56 -0
  163. package/templates/mobile/expo/src/core/hook/useNetworkStatus.ts +68 -0
  164. package/templates/mobile/expo/src/core/hook/useTimeout.tsx +30 -0
  165. package/templates/mobile/expo/src/core/index.ts +7 -0
  166. package/templates/mobile/expo/src/core/services/api.service.ts +230 -0
  167. package/templates/mobile/expo/src/core/services/device-id.service.ts +23 -0
  168. package/templates/mobile/expo/src/core/services/index.ts +3 -0
  169. package/templates/mobile/expo/src/core/services/session-end.bridge.ts +26 -0
  170. package/templates/mobile/expo/src/core/theme/dark.theme.ts +10 -0
  171. package/templates/mobile/expo/src/core/theme/index.ts +5 -0
  172. package/templates/mobile/expo/src/core/theme/light.theme.ts +44 -0
  173. package/templates/mobile/expo/src/core/theme/theme-context.tsx +82 -0
  174. package/templates/mobile/expo/src/core/theme/theme.types.ts +26 -0
  175. package/templates/mobile/expo/src/core/theme/use-themed-styles.ts +25 -0
  176. package/templates/mobile/expo/src/core/utils/color.util.tsx +198 -0
  177. package/templates/mobile/expo/src/core/utils/date.util.ts +97 -0
  178. package/templates/mobile/expo/src/core/utils/device-locale.util.ts +22 -0
  179. package/templates/mobile/expo/src/core/utils/emitter/index.ts +161 -0
  180. package/templates/mobile/expo/src/core/utils/emitter/type.ts +40 -0
  181. package/templates/mobile/expo/src/core/utils/enum.util.tsx +15 -0
  182. package/templates/mobile/expo/src/core/utils/font.util.tsx +42 -0
  183. package/templates/mobile/expo/src/core/utils/func.util.ts +48 -0
  184. package/templates/mobile/expo/src/core/utils/greeting.util.ts +20 -0
  185. package/templates/mobile/expo/src/core/utils/image-format.util.ts +117 -0
  186. package/templates/mobile/expo/src/core/utils/image-picker.util.ts +84 -0
  187. package/templates/mobile/expo/src/core/utils/index.ts +18 -0
  188. package/templates/mobile/expo/src/core/utils/linking.util.ts +16 -0
  189. package/templates/mobile/expo/src/core/utils/navigation.util.tsx +100 -0
  190. package/templates/mobile/expo/src/core/utils/number-format.ts +28 -0
  191. package/templates/mobile/expo/src/core/utils/query-client.util.ts +35 -0
  192. package/templates/mobile/expo/src/core/utils/query-persister.util.ts +36 -0
  193. package/templates/mobile/expo/src/core/utils/schema.util.tsx +2713 -0
  194. package/templates/mobile/expo/src/core/utils/size.util.tsx +74 -0
  195. package/templates/mobile/expo/src/core/utils/storage.util.tsx +53 -0
  196. package/templates/mobile/expo/src/core/utils/toast.util.tsx +151 -0
  197. package/templates/mobile/expo/src/core/utils/translator.util.tsx +23 -0
  198. package/templates/mobile/expo/src/core/utils/typography.util.tsx +69 -0
  199. package/templates/mobile/expo/src/core/utils/validate.util.tsx +13 -0
  200. package/templates/mobile/expo/src/declarations.d.ts +54 -0
  201. package/templates/mobile/expo/src/modules/home/home.screen.tsx +33 -0
  202. package/templates/mobile/expo/src/modules/profile/profile.screen.tsx +29 -0
  203. package/templates/mobile/expo/src/scripts/link-fonts.js +60 -0
  204. package/templates/mobile/expo/src/scripts/sync-images.js +56 -0
  205. package/templates/mobile/expo/src/scripts/sync-svgs.js +50 -0
  206. package/templates/mobile/expo/src/types/models.d.ts +24 -0
  207. package/templates/mobile/expo/tsconfig.json +19 -0
  208. package/templates/mobile/rn/.env.example +5 -0
  209. package/templates/mobile/rn/.eslintrc.js +7 -0
  210. package/templates/mobile/rn/.prettierrc.js +7 -0
  211. package/templates/mobile/rn/.svgrrc.js +9 -0
  212. package/templates/mobile/rn/README.md +40 -7
  213. package/templates/mobile/rn/_gitignore +24 -0
  214. package/templates/mobile/rn/_package.json +67 -1
  215. package/templates/mobile/rn/app.json +4 -0
  216. package/templates/mobile/rn/babel.config.js +18 -0
  217. package/templates/mobile/rn/index.js +8 -0
  218. package/templates/mobile/rn/metro.config.js +33 -0
  219. package/templates/mobile/rn/src/app/App.tsx +24 -0
  220. package/templates/mobile/rn/src/app/app-provider.tsx +36 -0
  221. package/templates/mobile/rn/src/app/config/translation.ts +26 -0
  222. package/templates/mobile/rn/src/app/index.ts +1 -0
  223. package/templates/mobile/rn/src/app/navigation/app-route-type.ts +27 -0
  224. package/templates/mobile/rn/src/app/navigation/bottom-tabs.tsx +34 -0
  225. package/templates/mobile/rn/src/app/navigation/index.tsx +14 -0
  226. package/templates/mobile/rn/src/app/stores/auth.store.ts +33 -0
  227. package/templates/mobile/rn/src/app/stores/common.store.ts +19 -0
  228. package/templates/mobile/rn/src/app/stores/index.ts +3 -0
  229. package/templates/mobile/rn/src/app/stores/loading.store.ts +22 -0
  230. package/templates/mobile/rn/src/assets/Images/empty-list.png +0 -0
  231. package/templates/mobile/rn/src/assets/Images/index.ts +5 -0
  232. package/templates/mobile/rn/src/assets/Images/screen-bg-gradian.png +0 -0
  233. package/templates/mobile/rn/src/assets/i18n/en.json +12 -0
  234. package/templates/mobile/rn/src/assets/i18n/fr.json +12 -0
  235. package/templates/mobile/rn/src/assets/lotties/index.ts +3 -0
  236. package/templates/mobile/rn/src/assets/lotties/loading.json +1 -0
  237. package/templates/mobile/rn/src/assets/svgs/arrow-left.svg +3 -0
  238. package/templates/mobile/rn/src/assets/svgs/arrow-right.svg +3 -0
  239. package/templates/mobile/rn/src/assets/svgs/calendar.svg +12 -0
  240. package/templates/mobile/rn/src/assets/svgs/check.svg +3 -0
  241. package/templates/mobile/rn/src/assets/svgs/close.svg +3 -0
  242. package/templates/mobile/rn/src/assets/svgs/eye-hide.svg +3 -0
  243. package/templates/mobile/rn/src/assets/svgs/eye.svg +4 -0
  244. package/templates/mobile/rn/src/assets/svgs/index.ts +29 -0
  245. package/templates/mobile/rn/src/assets/svgs/minus.svg +3 -0
  246. package/templates/mobile/rn/src/assets/svgs/plus.svg +3 -0
  247. package/templates/mobile/rn/src/assets/svgs/search.svg +3 -0
  248. package/templates/mobile/rn/src/assets/svgs/toast-error.svg +5 -0
  249. package/templates/mobile/rn/src/assets/svgs/toast-success.svg +4 -0
  250. package/templates/mobile/rn/src/core/api/endpoints.ts +8 -0
  251. package/templates/mobile/rn/src/core/api/example.api.ts +53 -0
  252. package/templates/mobile/rn/src/core/api/index.ts +4 -0
  253. package/templates/mobile/rn/src/core/components/common/index.ts +1 -0
  254. package/templates/mobile/rn/src/core/components/common/list-empty/index.ts +2 -0
  255. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.tsx +30 -0
  256. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  257. package/templates/mobile/rn/src/core/components/forms/hf-date-time.tsx +301 -0
  258. package/templates/mobile/rn/src/core/components/forms/hf-password-input.tsx +153 -0
  259. package/templates/mobile/rn/src/core/components/forms/hf-text-input.tsx +59 -0
  260. package/templates/mobile/rn/src/core/components/forms/hf-time-picker.tsx +117 -0
  261. package/templates/mobile/rn/src/core/components/forms/index.ts +4 -0
  262. package/templates/mobile/rn/src/core/components/index.ts +5 -0
  263. package/templates/mobile/rn/src/core/components/loading/index.ts +1 -0
  264. package/templates/mobile/rn/src/core/components/loading/loading-app/index.ts +1 -0
  265. package/templates/mobile/rn/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  266. package/templates/mobile/rn/src/core/components/offline/index.ts +1 -0
  267. package/templates/mobile/rn/src/core/components/offline/offline-banner.tsx +186 -0
  268. package/templates/mobile/rn/src/core/components/screen/index.ts +1 -0
  269. package/templates/mobile/rn/src/core/components/screen/screen-container/index.ts +1 -0
  270. package/templates/mobile/rn/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  271. package/templates/mobile/rn/src/core/components/splash/index.ts +1 -0
  272. package/templates/mobile/rn/src/core/components/splash/splash-overlay/index.ts +1 -0
  273. package/templates/mobile/rn/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  274. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  275. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  276. package/templates/mobile/rn/src/core/components/ui/animated-list-item/index.ts +2 -0
  277. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.tsx +104 -0
  278. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.type.ts +19 -0
  279. package/templates/mobile/rn/src/core/components/ui/app-image/index.ts +2 -0
  280. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  281. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/index.ts +1 -0
  282. package/templates/mobile/rn/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  283. package/templates/mobile/rn/src/core/components/ui/avatar-image/index.ts +1 -0
  284. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  285. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  286. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/index.ts +2 -0
  287. package/templates/mobile/rn/src/core/components/ui/button/button.style.ts +146 -0
  288. package/templates/mobile/rn/src/core/components/ui/button/button.tsx +97 -0
  289. package/templates/mobile/rn/src/core/components/ui/button/button.type.ts +47 -0
  290. package/templates/mobile/rn/src/core/components/ui/button/index.ts +4 -0
  291. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  292. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  293. package/templates/mobile/rn/src/core/components/ui/checkbox/index.ts +2 -0
  294. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  295. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  296. package/templates/mobile/rn/src/core/components/ui/collapsible-section/index.ts +2 -0
  297. package/templates/mobile/rn/src/core/components/ui/components.registry.json +313 -0
  298. package/templates/mobile/rn/src/core/components/ui/field/field-frame.tsx +62 -0
  299. package/templates/mobile/rn/src/core/components/ui/field/field.shared.ts +31 -0
  300. package/templates/mobile/rn/src/core/components/ui/header/header.tsx +196 -0
  301. package/templates/mobile/rn/src/core/components/ui/header/header.type.ts +30 -0
  302. package/templates/mobile/rn/src/core/components/ui/header/index.ts +2 -0
  303. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  304. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  305. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  306. package/templates/mobile/rn/src/core/components/ui/icon-button/index.ts +2 -0
  307. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  308. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  309. package/templates/mobile/rn/src/core/components/ui/image-slider/index.ts +2 -0
  310. package/templates/mobile/rn/src/core/components/ui/index.ts +25 -0
  311. package/templates/mobile/rn/src/core/components/ui/label/index.ts +2 -0
  312. package/templates/mobile/rn/src/core/components/ui/label/label.tsx +36 -0
  313. package/templates/mobile/rn/src/core/components/ui/label/label.type.ts +12 -0
  314. package/templates/mobile/rn/src/core/components/ui/modal/index.ts +2 -0
  315. package/templates/mobile/rn/src/core/components/ui/modal/modal.tsx +62 -0
  316. package/templates/mobile/rn/src/core/components/ui/modal/modal.type.ts +11 -0
  317. package/templates/mobile/rn/src/core/components/ui/otp-input/index.ts +2 -0
  318. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  319. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  320. package/templates/mobile/rn/src/core/components/ui/page-dots/index.ts +1 -0
  321. package/templates/mobile/rn/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  322. package/templates/mobile/rn/src/core/components/ui/radio/index.ts +2 -0
  323. package/templates/mobile/rn/src/core/components/ui/radio/radio.tsx +121 -0
  324. package/templates/mobile/rn/src/core/components/ui/radio/radio.type.ts +20 -0
  325. package/templates/mobile/rn/src/core/components/ui/screen/index.ts +1 -0
  326. package/templates/mobile/rn/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  327. package/templates/mobile/rn/src/core/components/ui/search-box/index.ts +2 -0
  328. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.tsx +162 -0
  329. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.type.ts +26 -0
  330. package/templates/mobile/rn/src/core/components/ui/segmented-control/index.ts +2 -0
  331. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  332. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  333. package/templates/mobile/rn/src/core/components/ui/skeleton/index.ts +2 -0
  334. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  335. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  336. package/templates/mobile/rn/src/core/components/ui/success-state/index.ts +1 -0
  337. package/templates/mobile/rn/src/core/components/ui/success-state/success-state.tsx +68 -0
  338. package/templates/mobile/rn/src/core/components/ui/tabs/index.ts +2 -0
  339. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.tsx +273 -0
  340. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.type.ts +21 -0
  341. package/templates/mobile/rn/src/core/components/ui/tag-input/index.ts +2 -0
  342. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  343. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  344. package/templates/mobile/rn/src/core/components/ui/text-area/index.ts +2 -0
  345. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.tsx +90 -0
  346. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.type.ts +20 -0
  347. package/templates/mobile/rn/src/core/components/ui/text-field/index.ts +2 -0
  348. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.tsx +116 -0
  349. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.type.ts +21 -0
  350. package/templates/mobile/rn/src/core/components/ui/toggle/index.ts +2 -0
  351. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.tsx +110 -0
  352. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.type.ts +19 -0
  353. package/templates/mobile/rn/src/core/constants/external-urls.constant.ts +5 -0
  354. package/templates/mobile/rn/src/core/constants/hard-data.constant.ts +0 -0
  355. package/templates/mobile/rn/src/core/constants/index.ts +2 -0
  356. package/templates/mobile/rn/src/core/constants/type.constant.ts +3 -0
  357. package/templates/mobile/rn/src/core/context/index.ts +1 -0
  358. package/templates/mobile/rn/src/core/context/shared-transition-context.tsx +35 -0
  359. package/templates/mobile/rn/src/core/hook/index.ts +8 -0
  360. package/templates/mobile/rn/src/core/hook/useActiveRouteName.ts +63 -0
  361. package/templates/mobile/rn/src/core/hook/useAppNavigation.tsx +7 -0
  362. package/templates/mobile/rn/src/core/hook/useBottomInset.tsx +26 -0
  363. package/templates/mobile/rn/src/core/hook/useDebounce.tsx +16 -0
  364. package/templates/mobile/rn/src/core/hook/useEndReached.tsx +46 -0
  365. package/templates/mobile/rn/src/core/hook/useManualRefetch.ts +56 -0
  366. package/templates/mobile/rn/src/core/hook/useNetworkStatus.ts +68 -0
  367. package/templates/mobile/rn/src/core/hook/useTimeout.tsx +30 -0
  368. package/templates/mobile/rn/src/core/index.ts +7 -0
  369. package/templates/mobile/rn/src/core/services/api.service.ts +230 -0
  370. package/templates/mobile/rn/src/core/services/device-id.service.ts +23 -0
  371. package/templates/mobile/rn/src/core/services/index.ts +3 -0
  372. package/templates/mobile/rn/src/core/services/session-end.bridge.ts +26 -0
  373. package/templates/mobile/rn/src/core/theme/dark.theme.ts +10 -0
  374. package/templates/mobile/rn/src/core/theme/index.ts +5 -0
  375. package/templates/mobile/rn/src/core/theme/light.theme.ts +44 -0
  376. package/templates/mobile/rn/src/core/theme/theme-context.tsx +82 -0
  377. package/templates/mobile/rn/src/core/theme/theme.types.ts +26 -0
  378. package/templates/mobile/rn/src/core/theme/use-themed-styles.ts +25 -0
  379. package/templates/mobile/rn/src/core/utils/color.util.tsx +198 -0
  380. package/templates/mobile/rn/src/core/utils/date.util.ts +97 -0
  381. package/templates/mobile/rn/src/core/utils/device-locale.util.ts +22 -0
  382. package/templates/mobile/rn/src/core/utils/emitter/index.ts +161 -0
  383. package/templates/mobile/rn/src/core/utils/emitter/type.ts +40 -0
  384. package/templates/mobile/rn/src/core/utils/enum.util.tsx +15 -0
  385. package/templates/mobile/rn/src/core/utils/font.util.tsx +42 -0
  386. package/templates/mobile/rn/src/core/utils/func.util.ts +48 -0
  387. package/templates/mobile/rn/src/core/utils/greeting.util.ts +20 -0
  388. package/templates/mobile/rn/src/core/utils/image-format.util.ts +117 -0
  389. package/templates/mobile/rn/src/core/utils/image-picker.util.ts +84 -0
  390. package/templates/mobile/rn/src/core/utils/index.ts +18 -0
  391. package/templates/mobile/rn/src/core/utils/linking.util.ts +16 -0
  392. package/templates/mobile/rn/src/core/utils/navigation.util.tsx +100 -0
  393. package/templates/mobile/rn/src/core/utils/number-format.ts +28 -0
  394. package/templates/mobile/rn/src/core/utils/query-client.util.ts +35 -0
  395. package/templates/mobile/rn/src/core/utils/query-persister.util.ts +36 -0
  396. package/templates/mobile/rn/src/core/utils/schema.util.tsx +2713 -0
  397. package/templates/mobile/rn/src/core/utils/size.util.tsx +74 -0
  398. package/templates/mobile/rn/src/core/utils/storage.util.tsx +53 -0
  399. package/templates/mobile/rn/src/core/utils/toast.util.tsx +151 -0
  400. package/templates/mobile/rn/src/core/utils/translator.util.tsx +23 -0
  401. package/templates/mobile/rn/src/core/utils/typography.util.tsx +69 -0
  402. package/templates/mobile/rn/src/core/utils/validate.util.tsx +13 -0
  403. package/templates/mobile/rn/src/declarations.d.ts +54 -0
  404. package/templates/mobile/rn/src/modules/home/home.screen.tsx +33 -0
  405. package/templates/mobile/rn/src/modules/profile/profile.screen.tsx +29 -0
  406. package/templates/mobile/rn/src/scripts/link-fonts.js +60 -0
  407. package/templates/mobile/rn/src/scripts/sync-images.js +56 -0
  408. package/templates/mobile/rn/src/scripts/sync-svgs.js +50 -0
  409. package/templates/mobile/rn/src/types/models.d.ts +24 -0
  410. package/templates/mobile/rn/tsconfig.json +21 -0
  411. package/templates/shared/src/api-endpoints.ts +8 -0
  412. package/templates/shared/src/enums.ts +34 -0
  413. package/templates/shared/src/external-urls.ts +5 -0
  414. package/templates/shared/src/index.ts +6 -3
package/README.md CHANGED
@@ -44,16 +44,13 @@ npx create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs
44
44
 
45
45
  ## Install globally (optional)
46
46
 
47
- Scaffold often? Install once and use the shorter `create-app` command:
47
+ Scaffold often? Install once so you don't re-download it each time:
48
48
 
49
49
  ```bash
50
50
  npm install -g create-du-app # or: pnpm add -g create-du-app
51
- create-app # same as npx create-du-app
51
+ create-du-app # same as npx create-du-app
52
52
  ```
53
53
 
54
- > The **package** is `create-du-app`; the installed **command** is `create-app`
55
- > (same pattern as `create-next-app`).
56
-
57
54
  ## Available stacks
58
55
 
59
56
  | Group | Technologies | Output folder |
@@ -62,7 +59,9 @@ create-app # same as npx create-du-app
62
59
  | Frontend | Next.js · ReactJS | `apps/web` |
63
60
  | Backend | Node.js · NestJS · PHP | `apps/backend` |
64
61
 
65
- `packages/shared` (shared types + api client) is added automatically when you pick **≥ 2** JS/TS stacks.
62
+ `packages/shared` (`@repo/shared` shared data contracts, built with tsup) is added
63
+ automatically when you pick **≥ 2** JS/TS stacks, and every JS/TS app is wired to it
64
+ as a `workspace:*` dependency.
66
65
 
67
66
  ---
68
67
 
@@ -76,6 +75,10 @@ Working on the CLI source or the templates? See the
76
75
  | `src/index.js` | Entry point. Parses flags, runs interactive or non-interactive, then generates. |
77
76
  | `src/registry.js` | **Data declaration** of groups, technologies, `templatePath`, and `lang`. Edit this to add/remove a stack. |
78
77
  | `src/prompts.js` | Interactive prompts (`@clack/prompts`). |
79
- | `src/generate.js` | Copies templates, renames `_package.json` → `package.json`, emits the root `package.json` + `pnpm-workspace.yaml`, substitutes `{{PROJECT_NAME}}`. |
78
+ | `src/generate.js` | Copies templates, renames `_package.json` → `package.json`, substitutes `{{PROJECT_NAME}}`, emits the root config (`package.json`, `pnpm-workspace.yaml`, `turbo.json`, `tsconfig.base.json`, `.gitignore`, `.npmrc`, `scripts/bootstrap.mjs`), and wires JS/TS apps to `@repo/shared`. |
79
+ | `scripts/validate-templates.mjs` | Validates every registered template (gates `prepack`/publish). Run with `pnpm validate`. |
80
+
81
+ Before publishing, `prepack` runs template validation automatically. Run the full
82
+ check (validate + generate smoke test) from the repo root with `pnpm test`.
80
83
 
81
84
  Release a new version: `pnpm release` (see [scripts/release.mjs](scripts/release.mjs)).
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-du-app",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "CLI generator: pick templates (Mobile/FE/BE) and scaffold a product monorepo",
5
5
  "type": "module",
6
6
  "bin": {
7
- "create-app": "src/index.js"
7
+ "create-du-app": "src/index.js"
8
8
  },
9
9
  "files": [
10
10
  "src",
@@ -12,14 +12,15 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "start": "node src/index.js",
15
+ "validate": "node scripts/validate-templates.mjs",
15
16
  "release": "node scripts/release.mjs",
16
- "prepack": "node scripts/bundle-templates.mjs",
17
+ "prepack": "node scripts/validate-templates.mjs && node scripts/bundle-templates.mjs",
17
18
  "postpack": "node scripts/bundle-templates.mjs --clean"
18
19
  },
19
20
  "engines": {
20
- "node": ">=18"
21
+ "node": ">=20"
21
22
  },
22
- "packageManager": "pnpm@9.0.0",
23
+ "packageManager": "pnpm@9.12.0",
23
24
  "dependencies": {
24
25
  "@clack/prompts": "^0.7.0",
25
26
  "fs-extra": "^11.2.0"
package/src/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
  // index.js — entry point. Parse args + run prompts (TTY) or generate directly (flags).
3
3
  //
4
4
  // Usage:
5
- // create-app interactive (requires a real terminal)
6
- // create-app --name my-shop --be nestjs non-interactive (runs anywhere)
5
+ // create-du-app interactive (requires a real terminal)
6
+ // create-du-app --name my-shop --be nestjs non-interactive (runs anywhere)
7
7
  // node src/index.js
8
8
  //
9
9
  // Flags:
@@ -56,11 +56,11 @@ async function readVersion() {
56
56
 
57
57
  function printHelp() {
58
58
  console.log(`
59
- create-app — scaffold a product monorepo from company templates
59
+ create-du-app — scaffold a product monorepo from company templates
60
60
 
61
61
  Usage:
62
- create-app interactive (requires a real terminal)
63
- create-app --name my-shop --be nestjs non-interactive (runs anywhere)
62
+ create-du-app interactive (requires a real terminal)
63
+ create-du-app --name my-shop --be nestjs non-interactive (runs anywhere)
64
64
  node src/index.js equivalent (when not linked)
65
65
 
66
66
  Options:
@@ -73,7 +73,7 @@ Options:
73
73
  -y, --yes generate without prompting (needs --name + >=1 group)
74
74
 
75
75
  Example:
76
- create-app --name my-shop --mobile expo --fe nextjs --be nestjs
76
+ create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs
77
77
 
78
78
  Add/remove templates: edit packages/cli/src/registry.js
79
79
  `);
@@ -93,7 +93,7 @@ function parseArgs(argv) {
93
93
  case '--fe': out.fe = argv[++i]; break;
94
94
  case '--be': out.be = argv[++i]; break;
95
95
  default:
96
- throw new Error(`Invalid argument: ${a}. See: create-app --help`);
96
+ throw new Error(`Invalid argument: ${a}. See: create-du-app --help`);
97
97
  }
98
98
  }
99
99
  return out;
@@ -155,7 +155,7 @@ async function main() {
155
155
  throw new Error(
156
156
  'This terminal does not support interactive mode (stdin is not a TTY).\n' +
157
157
  ' → Run it in Terminal.app/iTerm, OR use flags:\n' +
158
- ' create-app --name my-shop --mobile expo --fe nextjs --be nestjs',
158
+ ' create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs',
159
159
  );
160
160
  } else {
161
161
  plan = await runPrompts();
package/src/prompts.js CHANGED
@@ -24,7 +24,7 @@ function ensureNotCancelled(value) {
24
24
  }
25
25
 
26
26
  export async function runPrompts() {
27
- intro('create-app — scaffold a product monorepo from company templates');
27
+ intro('create-du-app — scaffold a product monorepo from company templates');
28
28
 
29
29
  // 1) Project name
30
30
  const projectName = ensureNotCancelled(
@@ -0,0 +1,5 @@
1
+ # Copy to .env and fill in. Read at build time by react-native-config.
2
+ # NEVER commit the real .env — only this example.
3
+
4
+ # Base URL of your API (include trailing slash).
5
+ BASE_URL=https://api.example.com/
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: '@react-native',
4
+ rules: {
5
+ semi: 0,
6
+ },
7
+ };
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ arrowParens: 'avoid',
3
+ bracketSameLine: true,
4
+ bracketSpacing: true,
5
+ singleQuote: true,
6
+ trailingComma: 'all',
7
+ };
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ replaceAttrValues: {
3
+ '{currentColor}': '{props.color || "#0D1F2D"}',
4
+ '{292929}': '{props.color || "#292929"}',
5
+ '{D4D4FF}': '{props.color || "#D4D4FF"}',
6
+ '{7C7C7C}': '{props.color || "#7C7C7C"}',
7
+ '{D97706}': '{props.color || "#D97706"}',
8
+ },
9
+ }
@@ -1,11 +1,46 @@
1
- # Placeholder: Expo (mobile/expo)
1
+ # {{PROJECT_NAME}} Mobile (Expo)
2
2
 
3
- This is a **placeholder** for the **Expo** template.
3
+ An Expo + React Native starter built from the company's production core. The
4
+ reusable infrastructure (`src/core`) is ported as-is; only product-specific
5
+ features (audio/player, real-estate, IAP, maps, blur) were removed. Build your
6
+ features under `src/modules/`.
4
7
 
5
- Drop the standard Expo source here. Conventions:
8
+ ## Architecture
6
9
 
7
- - Name the template's `package.json` as **`_package.json`** (the CLI renames it on generate).
8
- - Name `.gitignore` as **`_gitignore`**, `.npmrc` as **`_npmrc`** if present.
9
- - Wherever you need the project name, write `{{PROJECT_NAME}}` — the CLI replaces it with the real name.
10
+ ```
11
+ src/
12
+ ├── app/ composition: providers, navigation, global stores (auth/loading/common), i18n
13
+ ├── core/ reusable infrastructure (see below)
14
+ ├── modules/ your features (home/profile examples included)
15
+ └── assets/ i18n, svgs (sync-generated barrel), images, lotties
16
+ ```
10
17
 
11
- `lang: js` this app counts toward the condition for creating `packages/shared`.
18
+ ### `src/core` the reusable kit
19
+ | Area | Where |
20
+ |------|-------|
21
+ | API | `services/api.service.ts` (axios + auth header + device-id + 401 session handling), `api/example.api.ts` (React Query pattern) |
22
+ | Data | `utils/query-client.util.ts`, `utils/query-persister.util.ts` (MMKV offline cache) |
23
+ | Theme | `theme/` — context + `Colors` design tokens (`useTheme`, `useThemedStyles`) |
24
+ | UI kit | `components/ui/*` — button, text-field/area, checkbox, radio, toggle, modal, bottom-sheet, header, tabs, otp-input, search-box, skeleton, app-image, image-slider… |
25
+ | Forms | `components/forms/*` — react-hook-form bindings over the DS fields |
26
+ | Hooks | `hook/*` — useDebounce, useTimeout, useNetworkStatus, useEndReached, useAppNavigation… |
27
+ | Utils | `utils/*` — storage, translator (i18n), validate/schema (yup), date/number format, enum, toast, size/typography… |
28
+
29
+ ### Shared contracts
30
+ The core imports domain contracts (`ApiEndpoints`, `ExternalUrls`, enums) from
31
+ **`@repo/shared`** — generate this app alongside another JS/TS stack so that
32
+ package exists; the CLI wires `"@repo/shared": "workspace:*"` automatically.
33
+
34
+ ## Getting started
35
+
36
+ ```bash
37
+ pnpm bootstrap # install + build @repo/shared
38
+ pnpm --filter {{PROJECT_NAME}}-mobile typecheck # verify
39
+ pnpm --filter {{PROJECT_NAME}}-mobile start # expo dev server
40
+ ```
41
+
42
+ Add an icon: drop `name.svg` in `src/assets/svgs/` then `pnpm --filter {{PROJECT_NAME}}-mobile sync-svgs`.
43
+
44
+ Native folders (`ios/`, `android/`) are git-ignored — run `expo prebuild` to generate them.
45
+
46
+ > Before shipping: set `name`, `slug`, `scheme`, and the iOS/Android bundle ids in `app.json`.
@@ -0,0 +1,20 @@
1
+ # Native build artifacts (regenerated by `expo prebuild`)
2
+ /ios
3
+ /android
4
+ .expo/
5
+ web-build/
6
+
7
+ # Dependencies
8
+ node_modules/
9
+
10
+ # Metro
11
+ .metro-health-check*
12
+
13
+ # Env (keep .env.example)
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+
18
+ # Logs / OS
19
+ *.log
20
+ .DS_Store
@@ -2,5 +2,66 @@
2
2
  "name": "{{PROJECT_NAME}}-mobile",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
- "description": "Placeholder Expo app for {{PROJECT_NAME}}"
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "expo start",
8
+ "android": "expo run:android",
9
+ "ios": "expo run:ios",
10
+ "prebuild": "expo prebuild",
11
+ "lint": "eslint . --ext .ts,.tsx",
12
+ "typecheck": "tsc --noEmit",
13
+ "sync-svgs": "node src/scripts/sync-svgs.js",
14
+ "sync-images": "node src/scripts/sync-images.js"
15
+ },
16
+ "dependencies": {
17
+ "@hookform/error-message": "2.0.0",
18
+ "@react-native-async-storage/async-storage": "^2.1.2",
19
+ "@react-native-community/netinfo": "^12.0.1",
20
+ "@react-navigation/bottom-tabs": "^7.12.0",
21
+ "@react-navigation/native": "^7.0.13",
22
+ "@react-navigation/native-stack": "^7.1.14",
23
+ "@tanstack/react-query": "^5.101.0",
24
+ "@tanstack/react-query-persist-client": "^5.101.0",
25
+ "axios": "^1.7.9",
26
+ "expo": "~56.0.6",
27
+ "i18next": "^21.5.4",
28
+ "lodash": "^4.17.21",
29
+ "lottie-react-native": "^7.3.4",
30
+ "qs": "^6.10.1",
31
+ "react": "19.2.3",
32
+ "react-hook-form": "^7.53.2",
33
+ "react-i18next": "^11.14.3",
34
+ "react-native": "0.85.3",
35
+ "react-native-config": "^1.6.1",
36
+ "react-native-date-picker": "5.0.12",
37
+ "react-native-device-info": "^15.0.2",
38
+ "react-native-fast-image": "^8.6.3",
39
+ "react-native-gesture-handler": "~2.31.1",
40
+ "react-native-image-picker": "^8.2.1",
41
+ "react-native-keyboard-controller": "^1.21.6",
42
+ "react-native-linear-gradient": "^2.8.3",
43
+ "react-native-localize": "^3.7.0",
44
+ "react-native-mmkv": "^4.3.1",
45
+ "react-native-nitro-modules": "^0.35.9",
46
+ "react-native-reanimated": "4.3.1",
47
+ "react-native-safe-area-context": "^5.7.0",
48
+ "react-native-screens": "4.25.2",
49
+ "react-native-svg": "^15.15.4",
50
+ "react-native-toast-message": "^2.2.1",
51
+ "react-native-worklets": "0.8.3",
52
+ "yup": "^0.32.11",
53
+ "zustand": "^5.0.7"
54
+ },
55
+ "devDependencies": {
56
+ "@babel/core": "^7.25.2",
57
+ "@react-native/eslint-config": "0.85.3",
58
+ "@types/lodash": "^4.14.176",
59
+ "@types/qs": "^6.9.7",
60
+ "@types/react": "^19.1.1",
61
+ "babel-plugin-module-resolver": "^4.1.0",
62
+ "eslint": "^8.19.0",
63
+ "prettier": "2.8.8",
64
+ "react-native-svg-transformer": "^1.5.0",
65
+ "typescript": "~5.8.3"
66
+ }
6
67
  }
@@ -0,0 +1,18 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{PROJECT_NAME}}",
4
+ "slug": "{{PROJECT_NAME}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "userInterfaceStyle": "automatic",
8
+ "newArchEnabled": true,
9
+ "scheme": "myapp",
10
+ "ios": {
11
+ "supportsTablet": true,
12
+ "bundleIdentifier": "com.company.myapp"
13
+ },
14
+ "android": {
15
+ "package": "com.company.myapp"
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,21 @@
1
+ module.exports = function (api) {
2
+ api.cache(true);
3
+ return {
4
+ presets: ['babel-preset-expo'],
5
+ plugins: [
6
+ [
7
+ 'module-resolver',
8
+ {
9
+ root: ['.'],
10
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json', '.svg'],
11
+ alias: {
12
+ '@src': './src',
13
+ '@modules': './src/modules',
14
+ },
15
+ },
16
+ ],
17
+ // Must be last.
18
+ 'react-native-reanimated/plugin',
19
+ ],
20
+ };
21
+ };
@@ -0,0 +1,5 @@
1
+ import { registerRootComponent } from 'expo';
2
+ import AppProvider from './src/app/app-provider';
3
+
4
+ // Expo registers the root component under the fixed native module name "main".
5
+ registerRootComponent(AppProvider);
@@ -0,0 +1,31 @@
1
+ const path = require('path');
2
+ const { getDefaultConfig } = require('expo/metro-config');
3
+ const { wrapWithReanimatedMetroConfig } = require('react-native-reanimated/metro-config');
4
+
5
+ // --- Monorepo paths ---
6
+ const projectRoot = __dirname;
7
+ const monorepoRoot = path.resolve(projectRoot, '../..');
8
+
9
+ /**
10
+ * Metro configuration (Expo + monorepo-aware, with SVG support)
11
+ * https://docs.expo.dev/guides/monorepos/
12
+ *
13
+ * @type {import('expo/metro-config').MetroConfig}
14
+ */
15
+ const config = getDefaultConfig(projectRoot);
16
+
17
+ // Watch the whole monorepo so edits in packages/* trigger reloads.
18
+ config.watchFolders = [monorepoRoot];
19
+
20
+ // Resolve from the app first, then the hoisted monorepo root node_modules.
21
+ config.resolver.nodeModulesPaths = [
22
+ path.resolve(projectRoot, 'node_modules'),
23
+ path.resolve(monorepoRoot, 'node_modules'),
24
+ ];
25
+
26
+ // SVG-as-component support (react-native-svg-transformer).
27
+ config.transformer.babelTransformerPath = require.resolve('react-native-svg-transformer/expo');
28
+ config.resolver.assetExts = config.resolver.assetExts.filter(ext => ext !== 'svg');
29
+ config.resolver.sourceExts = [...config.resolver.sourceExts, 'svg'];
30
+
31
+ module.exports = wrapWithReanimatedMetroConfig(config);
@@ -0,0 +1,24 @@
1
+ import React, { useEffect } from 'react';
2
+ import { StatusBar } from 'react-native';
3
+ import { useTheme } from '@src/core/theme';
4
+ import { RootNavigator } from './navigation';
5
+ import { useAuthStore } from './stores';
6
+ import { bootstrapLanguage } from './config/translation';
7
+
8
+ // Root UI component. Restores the persisted session + language, then mounts navigation.
9
+ export function App() {
10
+ const { resolved } = useTheme();
11
+ const hydrate = useAuthStore(s => s.hydrate);
12
+
13
+ useEffect(() => {
14
+ void bootstrapLanguage();
15
+ void hydrate();
16
+ }, [hydrate]);
17
+
18
+ return (
19
+ <>
20
+ <StatusBar barStyle={resolved === 'dark' ? 'light-content' : 'dark-content'} />
21
+ <RootNavigator />
22
+ </>
23
+ );
24
+ }
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
3
+ import { SafeAreaProvider } from 'react-native-safe-area-context';
4
+ import { I18nextProvider } from 'react-i18next';
5
+ import { onlineManager } from '@tanstack/react-query';
6
+ import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
7
+ import NetInfo from '@react-native-community/netinfo';
8
+ import { queryClient, mmkvQueryPersister } from '@src/core/utils';
9
+ import { ThemeProvider } from '@src/core/theme';
10
+ import { i18n } from './config/translation';
11
+ import { App } from './App';
12
+
13
+ // Pause/resume React Query based on connectivity (offline-first).
14
+ onlineManager.setEventListener(setOnline =>
15
+ NetInfo.addEventListener(state => setOnline(Boolean(state.isConnected))),
16
+ );
17
+
18
+ // The provider tree. Order: gesture root → persisted query cache → i18n →
19
+ // safe-area → theme → app UI.
20
+ export default function AppProvider() {
21
+ return (
22
+ <GestureHandlerRootView style={{ flex: 1 }}>
23
+ <PersistQueryClientProvider
24
+ client={queryClient}
25
+ persistOptions={{ persister: mmkvQueryPersister }}>
26
+ <I18nextProvider i18n={i18n}>
27
+ <SafeAreaProvider>
28
+ <ThemeProvider>
29
+ <App />
30
+ </ThemeProvider>
31
+ </SafeAreaProvider>
32
+ </I18nextProvider>
33
+ </PersistQueryClientProvider>
34
+ </GestureHandlerRootView>
35
+ );
36
+ }
@@ -0,0 +1,26 @@
1
+ import { findBestLanguageTag } from 'react-native-localize';
2
+ import { Translator } from '@src/core/utils';
3
+ import en from '@src/assets/i18n/en.json';
4
+ import fr from '@src/assets/i18n/fr.json';
5
+
6
+ const resources = {
7
+ en: { translation: en },
8
+ fr: { translation: fr },
9
+ };
10
+
11
+ const fallbackLng = 'en';
12
+ const best = findBestLanguageTag(Object.keys(resources));
13
+
14
+ // Initialize i18next once and expose the instance. The provider mounts it in
15
+ // app-provider.tsx; the active language can be changed via Translator.changeLanguages.
16
+ export const i18n = Translator.setup({
17
+ resources,
18
+ lng: best?.languageTag?.split('-')[0] ?? fallbackLng,
19
+ fallbackLng,
20
+ interpolation: { escapeValue: false },
21
+ });
22
+
23
+ // Hook persisted-language restore here if you store a user preference.
24
+ export async function bootstrapLanguage(): Promise<void> {
25
+ // no-op for the starter; wire AppStorageUtil + Translator.changeLanguages here.
26
+ }
@@ -0,0 +1 @@
1
+ export * from './stores';
@@ -0,0 +1,27 @@
1
+ // Central screen registry + typed param list. Add a screen here and every
2
+ // navigation call to it (via NavigationUtil / useNavigation) is type-checked.
3
+ export enum Screen {
4
+ Home = 'Home',
5
+ Profile = 'Profile',
6
+ // Auth / feature screens the core references (e.g. session-expired reset).
7
+ // Wire real screens for these as you build the app.
8
+ SignIn = 'SignIn',
9
+ OtpVerification = 'OtpVerification',
10
+ PlayerFull = 'PlayerFull',
11
+ LibraryMain = 'LibraryMain',
12
+ }
13
+
14
+ export type NavigatorParamList = {
15
+ [Screen.Home]: undefined;
16
+ [Screen.Profile]: undefined;
17
+ [Screen.SignIn]: undefined;
18
+ [Screen.OtpVerification]: undefined;
19
+ [Screen.PlayerFull]: undefined;
20
+ [Screen.LibraryMain]: undefined;
21
+ };
22
+
23
+ declare global {
24
+ namespace ReactNavigation {
25
+ interface RootParamList extends NavigatorParamList {}
26
+ }
27
+ }
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { useTheme } from '@src/core/theme';
5
+ import { Screen } from './app-route-type';
6
+ import { HomeScreen } from '@src/modules/home/home.screen';
7
+ import { ProfileScreen } from '@src/modules/profile/profile.screen';
8
+
9
+ const Tab = createBottomTabNavigator();
10
+
11
+ export function BottomTabs() {
12
+ const { t } = useTranslation();
13
+ const { colors } = useTheme();
14
+ return (
15
+ <Tab.Navigator
16
+ screenOptions={{
17
+ headerStyle: { backgroundColor: colors.bg_elevation_level_1_normal },
18
+ headerTintColor: colors.fg_neutral_normal,
19
+ tabBarStyle: {
20
+ backgroundColor: colors.bg_elevation_level_1_normal,
21
+ borderTopColor: colors.bd_neutral_faded,
22
+ },
23
+ tabBarActiveTintColor: colors.fg_primary_normal,
24
+ tabBarInactiveTintColor: colors.fg_neutral_faded,
25
+ }}>
26
+ <Tab.Screen name={Screen.Home} component={HomeScreen} options={{ title: t('home.title') }} />
27
+ <Tab.Screen
28
+ name={Screen.Profile}
29
+ component={ProfileScreen}
30
+ options={{ title: t('profile.title') }}
31
+ />
32
+ </Tab.Navigator>
33
+ );
34
+ }
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { NavigationContainer } from '@react-navigation/native';
3
+ import { navigationRef } from '@src/core/utils';
4
+ import { BottomTabs } from './bottom-tabs';
5
+
6
+ // Mounts the navigation tree and wires the global navigationRef so the API
7
+ // layer (and any non-component code) can navigate / reset on session expiry.
8
+ export function RootNavigator() {
9
+ return (
10
+ <NavigationContainer ref={navigationRef}>
11
+ <BottomTabs />
12
+ </NavigationContainer>
13
+ );
14
+ }
@@ -0,0 +1,33 @@
1
+ import { create } from 'zustand';
2
+ import { AppStorageUtil, StorageKeys } from '@src/core/utils';
3
+
4
+ interface AuthState {
5
+ token: string | null;
6
+ isAuthenticated: boolean;
7
+ setToken: (token: string | null) => void;
8
+ clearTokens: () => void;
9
+ hydrate: () => Promise<void>;
10
+ }
11
+
12
+ // Global auth store (Zustand). The API layer reads `token` for the auth header
13
+ // and calls `clearTokens()` on a 401 (see core/services/api.service.ts).
14
+ export const useAuthStore = create<AuthState>()(set => ({
15
+ token: null,
16
+ isAuthenticated: false,
17
+ setToken: token => {
18
+ if (token) {
19
+ AppStorageUtil.setItem(StorageKeys.APP_ACCESS_TOKEN, token);
20
+ } else {
21
+ AppStorageUtil.removeItem(StorageKeys.APP_ACCESS_TOKEN);
22
+ }
23
+ set({ token, isAuthenticated: Boolean(token) });
24
+ },
25
+ clearTokens: () => {
26
+ AppStorageUtil.removeItem(StorageKeys.APP_ACCESS_TOKEN);
27
+ set({ token: null, isAuthenticated: false });
28
+ },
29
+ hydrate: async () => {
30
+ const token = (await AppStorageUtil.getItem(StorageKeys.APP_ACCESS_TOKEN)) as string | null;
31
+ set({ token: token ?? null, isAuthenticated: Boolean(token) });
32
+ },
33
+ }));
@@ -0,0 +1,19 @@
1
+ import { create } from 'zustand';
2
+
3
+ export interface EnumValue {
4
+ key: string;
5
+ value: string;
6
+ label?: string;
7
+ }
8
+
9
+ interface CommonState {
10
+ /** Server-provided enum/lookup values (seeded after login/bootstrap). */
11
+ enumValues: EnumValue[];
12
+ setEnumValues: (values: EnumValue[]) => void;
13
+ }
14
+
15
+ // App-wide misc state (enum lookups, etc.). Used by core/utils/func.util.
16
+ export const useCommonStore = create<CommonState>()(set => ({
17
+ enumValues: [],
18
+ setEnumValues: enumValues => set({ enumValues }),
19
+ }));
@@ -0,0 +1,3 @@
1
+ export * from './auth.store';
2
+ export * from './loading.store';
3
+ export * from './common.store';
@@ -0,0 +1,22 @@
1
+ import { create } from 'zustand';
2
+
3
+ interface LoadingState {
4
+ /** True while at least one non-silent request is in flight. */
5
+ isLoading: boolean;
6
+ count: number;
7
+ showLoading: () => void;
8
+ hideLoading: () => void;
9
+ }
10
+
11
+ // Ref-counted global loading flag. The API layer toggles it around non-silent
12
+ // requests; <LoadingApp> renders the overlay when `isLoading` is true.
13
+ export const useLoadingStore = create<LoadingState>()(set => ({
14
+ isLoading: false,
15
+ count: 0,
16
+ showLoading: () => set(s => ({ count: s.count + 1, isLoading: true })),
17
+ hideLoading: () =>
18
+ set(s => {
19
+ const count = Math.max(0, s.count - 1);
20
+ return { count, isLoading: count > 0 };
21
+ }),
22
+ }));