vibefast-cli 1.1.5 → 1.2.1

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 (299) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +63 -169
  3. package/dist/commands/add.d.ts +1 -1
  4. package/dist/commands/add.d.ts.map +1 -1
  5. package/dist/commands/add.js +547 -589
  6. package/dist/commands/add.js.map +1 -1
  7. package/dist/commands/checklist.d.ts +1 -1
  8. package/dist/commands/checklist.d.ts.map +1 -1
  9. package/dist/commands/checklist.js +40 -39
  10. package/dist/commands/checklist.js.map +1 -1
  11. package/dist/commands/doctor.d.ts +1 -1
  12. package/dist/commands/doctor.js +22 -22
  13. package/dist/commands/doctor.js.map +1 -1
  14. package/dist/commands/env.d.ts +1 -1
  15. package/dist/commands/env.d.ts.map +1 -1
  16. package/dist/commands/env.js +58 -53
  17. package/dist/commands/env.js.map +1 -1
  18. package/dist/commands/health.d.ts +1 -1
  19. package/dist/commands/health.d.ts.map +1 -1
  20. package/dist/commands/health.js +101 -93
  21. package/dist/commands/health.js.map +1 -1
  22. package/dist/commands/init.d.ts +1 -1
  23. package/dist/commands/init.d.ts.map +1 -1
  24. package/dist/commands/init.js +416 -296
  25. package/dist/commands/init.js.map +1 -1
  26. package/dist/commands/remove.d.ts +1 -1
  27. package/dist/commands/remove.d.ts.map +1 -1
  28. package/dist/commands/remove.js +77 -64
  29. package/dist/commands/remove.js.map +1 -1
  30. package/dist/commands/status.d.ts +1 -1
  31. package/dist/commands/status.d.ts.map +1 -1
  32. package/dist/commands/status.js +15 -14
  33. package/dist/commands/status.js.map +1 -1
  34. package/dist/core/__tests__/detect.test.js +68 -34
  35. package/dist/core/__tests__/detect.test.js.map +1 -1
  36. package/dist/core/ast.d.ts +14 -0
  37. package/dist/core/ast.d.ts.map +1 -0
  38. package/dist/core/ast.js +239 -0
  39. package/dist/core/ast.js.map +1 -0
  40. package/dist/core/codemod.d.ts.map +1 -1
  41. package/dist/core/codemod.js +62 -44
  42. package/dist/core/codemod.js.map +1 -1
  43. package/dist/core/config.d.ts +10 -0
  44. package/dist/core/config.d.ts.map +1 -0
  45. package/dist/core/config.js +51 -0
  46. package/dist/core/config.js.map +1 -0
  47. package/dist/core/detect.d.ts +8 -2
  48. package/dist/core/detect.d.ts.map +1 -1
  49. package/dist/core/detect.js +52 -21
  50. package/dist/core/detect.js.map +1 -1
  51. package/dist/core/errors.d.ts.map +1 -1
  52. package/dist/core/errors.js +9 -8
  53. package/dist/core/errors.js.map +1 -1
  54. package/dist/core/exec.d.ts +16 -0
  55. package/dist/core/exec.d.ts.map +1 -0
  56. package/dist/core/exec.js +48 -0
  57. package/dist/core/exec.js.map +1 -0
  58. package/dist/core/manualSteps.d.ts +7 -0
  59. package/dist/core/manualSteps.d.ts.map +1 -0
  60. package/dist/core/manualSteps.js +59 -0
  61. package/dist/core/manualSteps.js.map +1 -0
  62. package/dist/core/paths.d.ts +3 -1
  63. package/dist/core/paths.d.ts.map +1 -1
  64. package/dist/core/paths.js +14 -10
  65. package/dist/core/paths.js.map +1 -1
  66. package/dist/core/spinner.d.ts +1 -1
  67. package/dist/core/spinner.d.ts.map +1 -1
  68. package/dist/core/spinner.js +38 -8
  69. package/dist/core/spinner.js.map +1 -1
  70. package/dist/core/vosk.d.ts.map +1 -1
  71. package/dist/core/vosk.js +50 -39
  72. package/dist/core/vosk.js.map +1 -1
  73. package/docs/manual-testing.md +91 -0
  74. package/package.json +6 -3
  75. package/recipes/audio-recorder/apps/native/src/app/audio-recorder/index.tsx +5 -0
  76. package/recipes/audio-recorder/recipe.json +3 -3
  77. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
  78. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
  79. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
  80. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/index.ts +4 -0
  81. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
  82. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
  83. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
  84. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
  85. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
  86. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
  87. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
  88. package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +369 -0
  89. package/recipes/audio-recorder-supabase/packages/backend/supabase/migrations/recordings.sql +70 -0
  90. package/recipes/audio-recorder-supabase/recipe.json +35 -0
  91. package/recipes/audio-recorder-supabase@latest.zip +0 -0
  92. package/recipes/audio-recorder@latest.zip +0 -0
  93. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -3
  94. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +2 -2
  95. package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +5 -5
  96. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -3
  97. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +20 -4
  98. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +7 -6
  99. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +6 -4
  100. package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +1 -1
  101. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +5 -4
  102. package/recipes/charts/recipe.json +4 -13
  103. package/recipes/charts@latest.zip +0 -0
  104. package/recipes/chatbot/apps/native/src/app/chatbot/index.tsx +1 -0
  105. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
  106. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
  107. package/recipes/chatbot/recipe.json +26 -92
  108. package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +515 -0
  109. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/app/index.tsx +257 -0
  110. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +59 -0
  111. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-input-bar.tsx +485 -0
  112. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +575 -0
  113. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +223 -0
  114. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +161 -0
  115. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
  116. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +165 -0
  117. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/index.ts +10 -0
  118. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +129 -0
  119. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-error-boundary.tsx +78 -0
  120. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-list.tsx +170 -0
  121. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/model-selector.tsx +283 -0
  122. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/report-content-modal.tsx +188 -0
  123. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/suggested-messages.tsx +67 -0
  124. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/models.ts +20 -0
  125. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/report-reasons.ts +9 -0
  126. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +142 -0
  127. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-config.ts +458 -0
  128. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +429 -0
  129. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +89 -0
  130. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-conversation.ts +90 -0
  131. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-image-picker.ts +122 -0
  132. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +161 -0
  133. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +213 -0
  134. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/index.ts +86 -0
  135. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/models.ts +162 -0
  136. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/providers.ts +62 -0
  137. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/types.ts +40 -0
  138. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/file-uploader.ts +287 -0
  139. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/message-handler-service.ts +189 -0
  140. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/types/index.ts +70 -0
  141. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/utils/chat-telemetry.ts +91 -0
  142. package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +243 -0
  143. package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +327 -0
  144. package/recipes/chatbot-supabase/packages/backend/supabase/functions/chat-stream/index.ts +347 -0
  145. package/recipes/chatbot-supabase/packages/backend/supabase/migrations/chatbot.sql +104 -0
  146. package/recipes/chatbot-supabase/recipe.json +79 -0
  147. package/recipes/chatbot-supabase@latest.zip +0 -0
  148. package/recipes/chatbot.zip +0 -0
  149. package/recipes/chatbot@latest.zip +0 -0
  150. package/recipes/image-analysis/packages/backend/convex/imageAnalysis/index.ts +2 -2
  151. package/recipes/image-analysis/packages/backend/convex/imageAnalysis.ts +0 -1
  152. package/recipes/image-analysis/recipe.json +15 -55
  153. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
  154. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
  155. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
  156. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading-screen.tsx +214 -0
  157. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading.tsx +191 -0
  158. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
  159. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
  160. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +160 -0
  161. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
  162. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
  163. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
  164. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
  165. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
  166. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
  167. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
  168. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
  169. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
  170. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
  171. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
  172. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
  173. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
  174. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
  175. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
  176. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
  177. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
  178. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
  179. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
  180. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +38 -0
  181. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +208 -0
  182. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
  183. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
  184. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
  185. package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +132 -0
  186. package/recipes/image-analysis-supabase/packages/backend/supabase/functions/analyze-image/index.ts +312 -0
  187. package/recipes/image-analysis-supabase/packages/backend/supabase/migrations/image_analysis.sql +42 -0
  188. package/recipes/image-analysis-supabase/recipe.json +57 -0
  189. package/recipes/image-analysis-supabase@latest.zip +0 -0
  190. package/recipes/image-analysis@latest.zip +0 -0
  191. package/recipes/image-generator/apps/native/src/features/image-generator/app/index.tsx +16 -2
  192. package/recipes/image-generator/apps/native/src/features/image-generator/components/image-model-selector.tsx +11 -5
  193. package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator.ts +11 -5
  194. package/recipes/image-generator/packages/backend/convex/imageGeneration/index.ts +2 -2
  195. package/recipes/image-generator/recipe.json +16 -39
  196. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
  197. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
  198. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/index.tsx +251 -0
  199. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
  200. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
  201. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-model-selector.tsx +216 -0
  202. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
  203. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
  204. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
  205. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator.ts +103 -0
  206. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/models/models.ts +66 -0
  207. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-gallery-service.ts +96 -0
  208. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-save-service.ts +120 -0
  209. package/recipes/image-generator-supabase/packages/backend/supabase/functions/generate-image/index.ts +291 -0
  210. package/recipes/image-generator-supabase/packages/backend/supabase/migrations/image_generator.sql +71 -0
  211. package/recipes/image-generator-supabase/recipe.json +59 -0
  212. package/recipes/image-generator-supabase@latest.zip +0 -0
  213. package/recipes/image-generator@latest.zip +0 -0
  214. package/recipes/ios-widget/recipe.json +15 -24
  215. package/recipes/ios-widget@latest.zip +0 -0
  216. package/recipes/onboarding/apps/native/src/features/onboarding/analytics/index.ts +9 -0
  217. package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
  218. package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
  219. package/recipes/onboarding/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
  220. package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/app/index.tsx +42 -0
  221. package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
  222. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/app/index.tsx +43 -0
  223. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +222 -0
  224. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +133 -0
  225. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +165 -0
  226. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +199 -0
  227. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +154 -0
  228. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +156 -0
  229. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +158 -0
  230. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +139 -0
  231. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +129 -0
  232. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +138 -0
  233. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +190 -0
  234. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +98 -0
  235. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +181 -0
  236. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +110 -0
  237. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +139 -0
  238. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +217 -0
  239. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +58 -0
  240. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/constants.ts +179 -0
  241. package/recipes/onboarding/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
  242. package/recipes/onboarding/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
  243. package/recipes/onboarding/recipe.json +15 -0
  244. package/recipes/onboarding@latest.zip +0 -0
  245. package/recipes/payments/recipe.json +28 -61
  246. package/recipes/payments-supabase/apps/native/src/features/payments/README.md +200 -0
  247. package/recipes/payments-supabase/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
  248. package/recipes/payments-supabase/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
  249. package/recipes/payments-supabase/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
  250. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
  251. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
  252. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
  253. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
  254. package/recipes/payments-supabase/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
  255. package/recipes/payments-supabase/apps/native/src/features/payments/index.ts +8 -0
  256. package/recipes/payments-supabase/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
  257. package/recipes/payments-supabase/packages/backend/src/services/payments.ts +201 -0
  258. package/recipes/payments-supabase/packages/backend/supabase/migrations/payments.sql +35 -0
  259. package/recipes/payments-supabase/recipe.json +51 -0
  260. package/recipes/payments-supabase@latest.zip +0 -0
  261. package/recipes/payments@latest.zip +0 -0
  262. package/recipes/quiz/apps/native/src/features/quiz/index.tsx +1 -2
  263. package/recipes/quiz/recipe.json +6 -9
  264. package/recipes/quiz@latest.zip +0 -0
  265. package/recipes/tracker-app/apps/native/src/features/tracker-app/app/index.tsx +1 -2
  266. package/recipes/tracker-app/recipe.json +7 -10
  267. package/recipes/tracker-app@latest.zip +0 -0
  268. package/recipes/voice-bot/recipe.json +8 -68
  269. package/recipes/voice-bot.zip +0 -0
  270. package/recipes/voice-bot@latest.zip +0 -0
  271. package/recipes/wake-word/recipe.json +10 -9
  272. package/recipes/wake-word.zip +0 -0
  273. package/recipes/wake-word@latest.zip +0 -0
  274. package/recipes/charts/apps/native/src/app/(root)/(protected)/charts/index.tsx +0 -3
  275. package/recipes/chatbot/packages/backend/convex/lib/rateLimit.ts +0 -100
  276. package/recipes/chatbot/packages/backend/convex/lib/telemetry.ts +0 -29
  277. package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -0
  278. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/front.jpg +0 -0
  279. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/side.jpg +0 -0
  280. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
  281. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +0 -5
  282. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +0 -50
  283. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +0 -2
  284. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +0 -50
  285. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +0 -50
  286. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +0 -2
  287. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +0 -3
  288. package/recipes/image-analysis/packages/backend/convex/imageAnalysisFunctions.ts +0 -325
  289. package/recipes/image-analysis/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +0 -200
  290. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/index.tsx +0 -74
  291. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/local.tsx +0 -25
  292. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +0 -23
  293. package/recipes/quiz/apps/native/src/app/(root)/(protected)/quiz/index.tsx +0 -47
  294. package/recipes/tracker-app/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +0 -1
  295. package/recipes/voice-bot/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +0 -27
  296. package/recipes/voice-bot/packages/backend/convex/router.ts +0 -81
  297. /package/recipes/{chatbot/apps/native/src/app/(root)/(protected) → chatbot-supabase/apps/native/src/app}/chatbot/index.tsx +0 -0
  298. /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/gallery.tsx +0 -0
  299. /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/index.tsx +0 -0
@@ -0,0 +1,181 @@
1
+ import React, { useState } from 'react';
2
+ import { View, ScrollView } from 'react-native';
3
+ import Animated, { FadeInDown, FadeIn, FadeOut } from 'react-native-reanimated';
4
+ import { Text, Button, Pressable } from '@/components/ui';
5
+ import { useThemeConfig } from '@/lib/use-theme-config';
6
+ import { DateTimePickerComponent } from '@/components/ui/date-time-picker';
7
+ import * as Haptics from 'expo-haptics';
8
+
9
+ interface ReminderStepProps {
10
+ selectedFrequency: string | null;
11
+ selectedTime: string;
12
+ onSelectFrequency: (freq: string) => void;
13
+ onSelectTime: (time: string) => void;
14
+ onNext: () => void;
15
+ }
16
+
17
+ const FREQUENCIES = [
18
+ { id: 'daily', label: 'Once a day (evening recap)' },
19
+ { id: 'purchase', label: 'After each purchase (if possible)' },
20
+ { id: 'weekly', label: 'Only weekly summary' },
21
+ { id: 'none', label: "No reminders, I'll do it myself" },
22
+ ];
23
+
24
+ const TIMES = ['6 PM', '7 PM', '8 PM'];
25
+
26
+ export function ReminderStep({
27
+ selectedFrequency,
28
+ selectedTime,
29
+ onSelectFrequency,
30
+ onSelectTime,
31
+ onNext,
32
+ }: ReminderStepProps) {
33
+ const theme = useThemeConfig();
34
+ const showTimePicker =
35
+ selectedFrequency === 'daily' || selectedFrequency === 'purchase';
36
+ const [customDate, setCustomDate] = useState(new Date());
37
+ const [isCustomTime, setIsCustomTime] = useState(false);
38
+
39
+ const handleCustomTimeChange = (date: Date) => {
40
+ setCustomDate(date);
41
+ const timeString = date.toLocaleTimeString([], {
42
+ hour: 'numeric',
43
+ minute: '2-digit',
44
+ });
45
+ onSelectTime(timeString);
46
+ };
47
+
48
+ return (
49
+ <Animated.View
50
+ entering={FadeIn}
51
+ exiting={FadeOut}
52
+ className="flex-1 px-6 pt-4"
53
+ >
54
+ <Text className="text-3xl font-bold mb-3">Reminder Style</Text>
55
+ <Text className="text-lg text-muted-foreground mb-8">
56
+ Consistency is key.
57
+ </Text>
58
+
59
+ <ScrollView className="flex-1" showsVerticalScrollIndicator={false}>
60
+ <View className="gap-3 mb-8">
61
+ {FREQUENCIES.map((item, index) => (
62
+ <Animated.View
63
+ entering={FadeInDown.delay(index * 100).duration(400)}
64
+ key={item.id}
65
+ >
66
+ <Pressable
67
+ onPress={() => onSelectFrequency(item.id)}
68
+ className={`flex-row items-center p-4 rounded-2xl border ${
69
+ selectedFrequency === item.id
70
+ ? 'border-primary bg-primary/5'
71
+ : 'border-border bg-card'
72
+ }`}
73
+ >
74
+ <View
75
+ className={`w-6 h-6 rounded-full border-2 items-center justify-center mr-4 ${
76
+ selectedFrequency === item.id
77
+ ? 'border-primary'
78
+ : 'border-muted-foreground'
79
+ }`}
80
+ >
81
+ {selectedFrequency === item.id && (
82
+ <View className="w-3 h-3 rounded-full bg-primary" />
83
+ )}
84
+ </View>
85
+ <Text
86
+ className={`flex-1 font-medium text-base ${
87
+ selectedFrequency === item.id
88
+ ? 'text-primary'
89
+ : 'text-foreground'
90
+ }`}
91
+ >
92
+ {item.label}
93
+ </Text>
94
+ </Pressable>
95
+ </Animated.View>
96
+ ))}
97
+ </View>
98
+
99
+ {showTimePicker && (
100
+ <Animated.View entering={FadeIn} className="mb-8">
101
+ <Text className="text-lg font-semibold mb-4">
102
+ Preferred Check-in Time
103
+ </Text>
104
+ <ScrollView
105
+ horizontal
106
+ showsHorizontalScrollIndicator={false}
107
+ className="gap-3 flex-1 w-full"
108
+ >
109
+ {TIMES.map((time) => (
110
+ <Pressable
111
+ key={time}
112
+ onPress={() => {
113
+ setIsCustomTime(false);
114
+ onSelectTime(time);
115
+ }}
116
+ className={`flex-1 px-5 py-3 rounded-xl border mr-3 ${
117
+ selectedTime === time && !isCustomTime
118
+ ? 'bg-primary border-primary'
119
+ : 'bg-card border-border'
120
+ }`}
121
+ >
122
+ <Text
123
+ className={`font-medium ${
124
+ selectedTime === time && !isCustomTime
125
+ ? 'text-primary-foreground'
126
+ : 'text-foreground'
127
+ }`}
128
+ >
129
+ {time}
130
+ </Text>
131
+ </Pressable>
132
+ ))}
133
+
134
+ <Pressable
135
+ onPress={() => setIsCustomTime(true)}
136
+ className={`px-5 py-3 rounded-xl border mr-3 ${
137
+ isCustomTime
138
+ ? 'bg-primary border-primary'
139
+ : 'bg-card border-border'
140
+ }`}
141
+ >
142
+ <Text
143
+ className={`font-medium ${
144
+ isCustomTime ? 'text-primary-foreground' : 'text-foreground'
145
+ }`}
146
+ >
147
+ Custom
148
+ </Text>
149
+ </Pressable>
150
+ </ScrollView>
151
+
152
+ {isCustomTime && (
153
+ <Animated.View entering={FadeIn} className="mt-4">
154
+ <DateTimePickerComponent
155
+ mode="time"
156
+ value={customDate}
157
+ onChange={handleCustomTimeChange}
158
+ label="Select Time"
159
+ timeFormat="12"
160
+ />
161
+ </Animated.View>
162
+ )}
163
+ </Animated.View>
164
+ )}
165
+ </ScrollView>
166
+
167
+ <View className="pt-4 border-t border-border bg-background">
168
+ <Button
169
+ label="Continue"
170
+ onPress={() => {
171
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
172
+ onNext();
173
+ }}
174
+ disabled={!selectedFrequency}
175
+ size="lg"
176
+ className="w-full m-0"
177
+ />
178
+ </View>
179
+ </Animated.View>
180
+ );
181
+ }
@@ -0,0 +1,110 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import Animated, { ZoomIn, FadeIn, FadeOut } from 'react-native-reanimated';
4
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
5
+ import { Text, Button } from '@/components/ui';
6
+ import { useThemeConfig } from '@/lib/use-theme-config';
7
+ import * as Haptics from 'expo-haptics';
8
+
9
+ interface SafetyStepProps {
10
+ onComplete: () => void;
11
+ }
12
+
13
+ export function SafetyStep({ onComplete }: SafetyStepProps) {
14
+ const theme = useThemeConfig();
15
+
16
+ return (
17
+ <Animated.View
18
+ entering={FadeIn}
19
+ exiting={FadeOut}
20
+ className="flex-1 px-6 pt-12 justify-between"
21
+ >
22
+ <View>
23
+ <Text className="text-3xl font-bold mb-3">Safe & Secure</Text>
24
+ <Text className="text-lg text-muted-foreground mb-12">
25
+ Your privacy is our priority.
26
+ </Text>
27
+
28
+ <View className="items-center mb-12">
29
+ <Animated.View
30
+ entering={ZoomIn.springify()}
31
+ className="bg-primary/5 p-10 rounded-full border-4 border-primary/20 mb-8 relative"
32
+ >
33
+ <MaterialCommunityIcons
34
+ name="shield-check"
35
+ size={80}
36
+ color={theme.colors.primary}
37
+ />
38
+ <View className="absolute -right-2 -top-2 bg-background rounded-full p-2 shadow-sm border border-border">
39
+ <MaterialCommunityIcons
40
+ name="lock"
41
+ size={24}
42
+ color={theme.colors.primary}
43
+ />
44
+ </View>
45
+ </Animated.View>
46
+
47
+ <View className="bg-card p-6 rounded-2xl border border-border w-full">
48
+ <View className="flex-row items-start mb-4">
49
+ <MaterialCommunityIcons
50
+ name="check-decagram"
51
+ size={20}
52
+ color={theme.colors.primary}
53
+ />
54
+ <View className="ml-3 flex-1">
55
+ <Text className="font-semibold text-foreground">
56
+ Cloud Backup (Secure)
57
+ </Text>
58
+ <Text className="text-muted-foreground text-sm mt-1">
59
+ We securely backup your data so you never lose it.
60
+ </Text>
61
+ </View>
62
+ </View>
63
+ <View className="flex-row items-start mb-4">
64
+ <MaterialCommunityIcons
65
+ name="eye-off"
66
+ size={20}
67
+ color={theme.colors.primary}
68
+ />
69
+ <View className="ml-3 flex-1">
70
+ <Text className="font-semibold text-foreground">
71
+ No Snooping
72
+ </Text>
73
+ <Text className="text-muted-foreground text-sm mt-1">
74
+ We don't store receipt images or view your personal docs.
75
+ </Text>
76
+ </View>
77
+ </View>
78
+ <View className="flex-row items-start">
79
+ <MaterialCommunityIcons
80
+ name="message-lock"
81
+ size={20}
82
+ color={theme.colors.primary}
83
+ />
84
+ <View className="ml-3 flex-1">
85
+ <Text className="font-semibold text-foreground">
86
+ Private Chats
87
+ </Text>
88
+ <Text className="text-muted-foreground text-sm mt-1">
89
+ Your conversations with AI are private and secure.
90
+ </Text>
91
+ </View>
92
+ </View>
93
+ </View>
94
+ </View>
95
+ </View>
96
+
97
+ <View className="pt-4 border-t border-border bg-background">
98
+ <Button
99
+ label="Get Started"
100
+ onPress={() => {
101
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
102
+ onComplete();
103
+ }}
104
+ size="lg"
105
+ className="w-full m-0"
106
+ />
107
+ </View>
108
+ </Animated.View>
109
+ );
110
+ }
@@ -0,0 +1,139 @@
1
+ import React from 'react';
2
+ import { View, ScrollView } from 'react-native';
3
+ import Animated, { FadeIn, FadeOut, FadeInDown } from 'react-native-reanimated';
4
+ import { Text, Button, Pressable } from '@/components/ui';
5
+ import { useThemeConfig } from '@/lib/use-theme-config';
6
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
7
+ import * as Haptics from 'expo-haptics';
8
+
9
+ interface StruggleStepProps {
10
+ selectedStruggle: string | null;
11
+ onSelectStruggle: (struggle: string) => void;
12
+ onNext: () => void;
13
+ }
14
+
15
+ const STRUGGLES = [
16
+ {
17
+ id: 'food',
18
+ label: 'I spend too much on food / delivery',
19
+ icon: 'food',
20
+ color: '#EF4444',
21
+ },
22
+ {
23
+ id: 'impulse',
24
+ label: 'Impulse buys / random shopping',
25
+ icon: 'shopping',
26
+ color: '#F59E0B',
27
+ },
28
+ {
29
+ id: 'mindless',
30
+ label: "I swipe my card and don't think",
31
+ icon: 'credit-card-remove-outline',
32
+ color: '#8B5CF6',
33
+ },
34
+ {
35
+ id: 'clueless',
36
+ label: 'I have no idea where my money goes',
37
+ icon: 'help-circle-outline',
38
+ color: '#6366F1',
39
+ },
40
+ {
41
+ id: 'inconsistent',
42
+ label: "I'm inconsistent: some months I'm great, some months I'm a mess",
43
+ icon: 'chart-bell-curve-cumulative',
44
+ color: '#10B981',
45
+ },
46
+ ];
47
+
48
+ export function StruggleStep({
49
+ selectedStruggle,
50
+ onSelectStruggle,
51
+ onNext,
52
+ }: StruggleStepProps) {
53
+ const theme = useThemeConfig();
54
+
55
+ return (
56
+ <Animated.View
57
+ entering={FadeIn}
58
+ exiting={FadeOut}
59
+ className="flex-1 px-6 pt-4"
60
+ >
61
+ <Text className="text-3xl font-bold mb-3">
62
+ What do you struggle with the most?
63
+ </Text>
64
+ <Text className="text-lg text-muted-foreground mb-8">
65
+ Be honest, we won't judge!
66
+ </Text>
67
+
68
+ <ScrollView className="flex-1" showsVerticalScrollIndicator={false}>
69
+ <View className="gap-3 pb-8">
70
+ {STRUGGLES.map((item, index) => (
71
+ <Animated.View
72
+ entering={FadeInDown.delay(index * 100).duration(400)}
73
+ key={item.id}
74
+ >
75
+ <Pressable
76
+ onPress={() => onSelectStruggle(item.id)}
77
+ className={`flex-row items-center p-4 rounded-2xl border relative overflow-hidden ${
78
+ selectedStruggle === item.id
79
+ ? 'border-transparent'
80
+ : 'border-border bg-card'
81
+ }`}
82
+ style={
83
+ selectedStruggle === item.id
84
+ ? { borderColor: item.color, borderWidth: 1 }
85
+ : {}
86
+ }
87
+ >
88
+ {selectedStruggle === item.id && (
89
+ <View
90
+ className="absolute inset-0 opacity-10"
91
+ style={{ backgroundColor: item.color }}
92
+ />
93
+ )}
94
+
95
+ <View
96
+ className="p-3 rounded-full mr-4"
97
+ style={{ backgroundColor: item.color + '20' }}
98
+ >
99
+ <MaterialCommunityIcons
100
+ name={item.icon as any}
101
+ size={24}
102
+ color={item.color}
103
+ />
104
+ </View>
105
+
106
+ <Text
107
+ className={`ml-4 flex-1 font-medium text-base text-foreground`}
108
+ >
109
+ {item.label}
110
+ </Text>
111
+
112
+ {selectedStruggle === item.id && (
113
+ <MaterialCommunityIcons
114
+ name="check-circle"
115
+ size={24}
116
+ color={item.color}
117
+ />
118
+ )}
119
+ </Pressable>
120
+ </Animated.View>
121
+ ))}
122
+ </View>
123
+ </ScrollView>
124
+
125
+ <View className="pt-4 border-t border-border bg-background">
126
+ <Button
127
+ label="Continue"
128
+ onPress={() => {
129
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
130
+ onNext();
131
+ }}
132
+ disabled={!selectedStruggle}
133
+ size="lg"
134
+ className="w-full m-0"
135
+ />
136
+ </View>
137
+ </Animated.View>
138
+ );
139
+ }
@@ -0,0 +1,217 @@
1
+ import React, { useState } from 'react';
2
+ import { View, ScrollView, TouchableOpacity } from 'react-native';
3
+ import Animated, { FadeIn, FadeOut, ZoomIn } from 'react-native-reanimated';
4
+ import { LinearGradient } from 'expo-linear-gradient';
5
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
6
+ import { Text, Button, Pressable } from '@/components/ui';
7
+ import { useThemeConfig } from '@/lib/use-theme-config';
8
+ import * as Haptics from 'expo-haptics';
9
+ import * as Clipboard from 'expo-clipboard';
10
+
11
+ /**
12
+ * Recommended theme colors for this onboarding (from CashPilot/Expense Tracker app)
13
+ * Update your `src/lib/use-theme-config.tsx` with these colors for the best experience.
14
+ */
15
+ const RECOMMENDED_COLORS = [
16
+ {
17
+ name: 'primary',
18
+ hex: '#B47B44',
19
+ description: 'Earthy Brown - Main actions & highlights',
20
+ },
21
+ {
22
+ name: 'background',
23
+ hex: '#FFF9F0',
24
+ description: 'Warm Cream - Page background',
25
+ },
26
+ {
27
+ name: 'foreground',
28
+ hex: '#4A3B32',
29
+ description: 'Dark Brown - Primary text',
30
+ },
31
+ { name: 'card', hex: '#FFFFFF', description: 'White - Card backgrounds' },
32
+ {
33
+ name: 'border',
34
+ hex: '#EBE0D0',
35
+ description: 'Light Tan - Borders & dividers',
36
+ },
37
+ {
38
+ name: 'muted',
39
+ hex: '#FAF2E6',
40
+ description: 'Soft Cream - Muted backgrounds',
41
+ },
42
+ {
43
+ name: 'mutedForeground',
44
+ hex: '#8C7A6B',
45
+ description: 'Warm Gray - Secondary text',
46
+ },
47
+ {
48
+ name: 'secondary',
49
+ hex: '#86A778',
50
+ description: 'Sage Green - Secondary actions',
51
+ },
52
+ {
53
+ name: 'warning',
54
+ hex: '#F4C430',
55
+ description: 'Gold - Warnings & highlights',
56
+ },
57
+ ];
58
+
59
+ interface WelcomeStepProps {
60
+ onNext: () => void;
61
+ onSignIn: () => void;
62
+ }
63
+
64
+ export function WelcomeStep({ onNext, onSignIn }: WelcomeStepProps) {
65
+ const theme = useThemeConfig();
66
+ const [showPalette, setShowPalette] = useState(false);
67
+ const [copiedColor, setCopiedColor] = useState<string | null>(null);
68
+
69
+ const copyToClipboard = async (hex: string) => {
70
+ await Clipboard.setStringAsync(hex);
71
+ setCopiedColor(hex);
72
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
73
+ setTimeout(() => setCopiedColor(null), 1500);
74
+ };
75
+
76
+ return (
77
+ <Animated.View
78
+ entering={FadeIn}
79
+ exiting={FadeOut}
80
+ className="flex-1 px-6 items-center"
81
+ >
82
+ <LinearGradient
83
+ colors={[theme.colors.primary + '20', 'transparent']}
84
+ style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
85
+ />
86
+
87
+ <ScrollView
88
+ className="flex-1 w-full"
89
+ showsVerticalScrollIndicator={false}
90
+ contentContainerStyle={{ flexGrow: 1 }}
91
+ >
92
+ <View className="flex-1 w-full md:max-w-4xl mx-auto">
93
+ <View className="flex-1 justify-center items-center py-8">
94
+ <Animated.View
95
+ entering={ZoomIn.duration(1000).springify()}
96
+ className="bg-primary/10 p-10 rounded-full mb-10 border-4 border-primary/5"
97
+ >
98
+ <MaterialCommunityIcons
99
+ name="wallet-outline"
100
+ size={80}
101
+ color={theme.colors.primary}
102
+ />
103
+ </Animated.View>
104
+ <Text className="text-5xl font-bold text-center mb-4 tracking-tight">
105
+ CashPilot
106
+ </Text>
107
+ <Text className="text-xl text-muted-foreground text-center mb-8 px-4 leading-8">
108
+ Your co-pilot for smarter financial decisions.
109
+ </Text>
110
+
111
+ {/* Color Palette Toggle */}
112
+ <TouchableOpacity
113
+ onPress={() => {
114
+ setShowPalette(!showPalette);
115
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
116
+ }}
117
+ className="flex-row items-center gap-2 bg-muted/50 px-4 py-2 rounded-full mb-4"
118
+ >
119
+ <MaterialCommunityIcons
120
+ name="palette"
121
+ size={18}
122
+ color={theme.colors.mutedForeground}
123
+ />
124
+ <Text className="text-sm text-muted-foreground font-medium">
125
+ {showPalette ? 'Hide' : 'View'} Recommended Theme Colors
126
+ </Text>
127
+ <MaterialCommunityIcons
128
+ name={showPalette ? 'chevron-up' : 'chevron-down'}
129
+ size={18}
130
+ color={theme.colors.mutedForeground}
131
+ />
132
+ </TouchableOpacity>
133
+
134
+ {/* Color Palette Section */}
135
+ {showPalette && (
136
+ <Animated.View
137
+ entering={FadeIn.duration(300)}
138
+ exiting={FadeOut.duration(200)}
139
+ className="w-full bg-card border border-border rounded-2xl p-4 mb-4"
140
+ >
141
+ <Text className="text-sm font-bold mb-2 text-center">
142
+ 🎨 CashPilot Theme Colors
143
+ </Text>
144
+ <Text className="text-xs text-muted-foreground text-center mb-4">
145
+ Update{' '}
146
+ <Text className="font-mono">
147
+ src/lib/use-theme-config.tsx
148
+ </Text>{' '}
149
+ for best experience
150
+ </Text>
151
+
152
+ <View className="gap-2">
153
+ {RECOMMENDED_COLORS.map((color) => (
154
+ <TouchableOpacity
155
+ key={color.name}
156
+ onPress={() => copyToClipboard(color.hex)}
157
+ className="flex-row items-center gap-3 p-2 rounded-xl bg-muted/30 active:bg-muted/50"
158
+ >
159
+ <View
160
+ className="w-8 h-8 rounded-lg border border-border shadow-sm"
161
+ style={{ backgroundColor: color.hex }}
162
+ />
163
+ <View className="flex-1">
164
+ <View className="flex-row items-center gap-2">
165
+ <Text className="text-sm font-semibold">
166
+ {color.name}
167
+ </Text>
168
+ <Text className="text-xs font-mono text-muted-foreground">
169
+ {color.hex}
170
+ </Text>
171
+ {copiedColor === color.hex && (
172
+ <Text className="text-xs text-primary font-medium">
173
+ Copied!
174
+ </Text>
175
+ )}
176
+ </View>
177
+ <Text
178
+ className="text-xs text-muted-foreground"
179
+ numberOfLines={1}
180
+ >
181
+ {color.description}
182
+ </Text>
183
+ </View>
184
+ <MaterialCommunityIcons
185
+ name="content-copy"
186
+ size={16}
187
+ color={theme.colors.mutedForeground}
188
+ />
189
+ </TouchableOpacity>
190
+ ))}
191
+ </View>
192
+ </Animated.View>
193
+ )}
194
+ </View>
195
+
196
+ <View className="pt-4 border-t border-border bg-background pb-8">
197
+ <Button
198
+ label="Start Your Journey"
199
+ onPress={() => {
200
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
201
+ onNext();
202
+ }}
203
+ size="lg"
204
+ className="w-full m-0 shadow-lg shadow-primary/20"
205
+ />
206
+ <Pressable onPress={onSignIn} className="mt-6 items-center">
207
+ <Text className="text-muted-foreground text-base">
208
+ Already have an account?{' '}
209
+ <Text className="text-primary font-bold">Sign in</Text>
210
+ </Text>
211
+ </Pressable>
212
+ </View>
213
+ </View>
214
+ </ScrollView>
215
+ </Animated.View>
216
+ );
217
+ }