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,199 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { View } from 'react-native';
3
+ import Animated, {
4
+ FadeIn,
5
+ FadeOut,
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ withSpring,
9
+ withRepeat,
10
+ withSequence,
11
+ withTiming,
12
+ } from 'react-native-reanimated';
13
+ import { LinearGradient } from 'expo-linear-gradient';
14
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
15
+ import { Text, Button } from '@/components/ui';
16
+ import { useThemeConfig } from '@/lib/use-theme-config';
17
+ import * as Haptics from 'expo-haptics';
18
+
19
+ const AIDemo = () => {
20
+ const theme = useThemeConfig();
21
+ const cursorOpacity = useSharedValue(0);
22
+ const cardScale = useSharedValue(0.8);
23
+ const cardOpacity = useSharedValue(0);
24
+ const [typedText, setTypedText] = useState('');
25
+ const [isAnalyzing, setIsAnalyzing] = useState(false);
26
+
27
+ // Complex example
28
+ const fullText = 'dinner €45 at Vapiano with team, paid in cash';
29
+
30
+ useEffect(() => {
31
+ cursorOpacity.value = withRepeat(
32
+ withSequence(
33
+ withTiming(1, { duration: 500 }),
34
+ withTiming(0, { duration: 500 }),
35
+ ),
36
+ -1,
37
+ );
38
+
39
+ let currentIndex = 0;
40
+ const typingInterval = setInterval(() => {
41
+ if (currentIndex <= fullText.length) {
42
+ setTypedText(fullText.slice(0, currentIndex));
43
+ currentIndex++;
44
+ } else {
45
+ clearInterval(typingInterval);
46
+ setIsAnalyzing(true);
47
+
48
+ // Simulate analysis delay then show result
49
+ setTimeout(() => {
50
+ setIsAnalyzing(false);
51
+ cardOpacity.value = withTiming(1, { duration: 500 });
52
+ cardScale.value = withSpring(1);
53
+ }, 1500);
54
+ }
55
+ }, 30); // Faster typing (30ms)
56
+
57
+ return () => clearInterval(typingInterval);
58
+ }, []);
59
+
60
+ const animatedCardStyle = useAnimatedStyle(() => ({
61
+ opacity: cardOpacity.value,
62
+ transform: [{ scale: cardScale.value }],
63
+ }));
64
+
65
+ return (
66
+ <View className="bg-card border border-border rounded-3xl overflow-hidden h-80 w-full max-w-sm mx-auto shadow-sm">
67
+ <LinearGradient
68
+ colors={[theme.colors.primary + '10', 'transparent']}
69
+ className="absolute inset-0"
70
+ />
71
+ <View className="p-6 flex-1 justify-center">
72
+ {/* Chat Bubble */}
73
+ <View className="bg-muted/30 self-start rounded-2xl rounded-tl-none px-3 py-4 mb-4 max-w-[95%]">
74
+ <Text className="text-base font-medium leading-5">
75
+ {typedText}
76
+ <Animated.Text style={{ opacity: cursorOpacity }}>|</Animated.Text>
77
+ </Text>
78
+ </View>
79
+
80
+ {/* Analyzing Indicator */}
81
+ {isAnalyzing && (
82
+ <Animated.View
83
+ entering={FadeIn}
84
+ exiting={FadeOut}
85
+ className="flex-row items-center gap-2 mb-4 ml-2"
86
+ >
87
+ <MaterialCommunityIcons
88
+ name="creation"
89
+ size={18}
90
+ color={theme.colors.primary}
91
+ />
92
+ <Text className="text-primary font-medium text-sm">
93
+ Analyzing context & extracting details...
94
+ </Text>
95
+ </Animated.View>
96
+ )}
97
+
98
+ {/* Result Card */}
99
+ <Animated.View
100
+ style={animatedCardStyle}
101
+ className="bg-background border border-border rounded-2xl p-4 shadow-md self-end w-full"
102
+ >
103
+ {/* Header */}
104
+ <View className="flex-row items-center justify-between mb-4 pb-3 border-b border-border/50">
105
+ <View className="flex-row items-center gap-3">
106
+ <View className="bg-orange-100 p-2.5 rounded-full">
107
+ <MaterialCommunityIcons
108
+ name="silverware-fork-knife"
109
+ size={20}
110
+ color="#F97316"
111
+ />
112
+ </View>
113
+ <View>
114
+ <Text className="font-bold text-base">Vapiano</Text>
115
+ <Text className="text-xs text-muted-foreground">
116
+ Food & Drink
117
+ </Text>
118
+ </View>
119
+ </View>
120
+ <Text className="font-bold text-xl text-primary">€45.00</Text>
121
+ </View>
122
+
123
+ {/* Details Grid */}
124
+ <View className="flex-row flex-wrap gap-2 mb-3">
125
+ <View className="bg-muted/50 px-2 py-1 rounded-md flex-row items-center">
126
+ <MaterialCommunityIcons
127
+ name="credit-card-outline"
128
+ size={14}
129
+ color={theme.colors.mutedForeground}
130
+ />
131
+ <Text className="text-xs text-muted-foreground ml-1">Amex</Text>
132
+ </View>
133
+ <View className="bg-blue-50 px-2 py-1 rounded-md flex-row items-center">
134
+ <MaterialCommunityIcons name="pound" size={14} color="#2563EB" />
135
+ <Text className="text-xs text-blue-600 ml-1">work</Text>
136
+ </View>
137
+ <View className="bg-muted/50 px-2 py-1 rounded-md flex-row items-center">
138
+ <MaterialCommunityIcons
139
+ name="text"
140
+ size={14}
141
+ color={theme.colors.mutedForeground}
142
+ />
143
+ <Text className="text-xs text-muted-foreground ml-1">
144
+ with team
145
+ </Text>
146
+ </View>
147
+ </View>
148
+ </Animated.View>
149
+ </View>
150
+ </View>
151
+ );
152
+ };
153
+
154
+ interface FeatureAIStepProps {
155
+ onNext: () => void;
156
+ }
157
+
158
+ export function FeatureAIStep({ onNext }: FeatureAIStepProps) {
159
+ return (
160
+ <Animated.View
161
+ entering={FadeIn}
162
+ exiting={FadeOut}
163
+ className="flex-1 px-6 pt-12"
164
+ >
165
+ <View className="flex-1 justify-center">
166
+ <View className="items-center mb-8">
167
+ <View className="bg-purple-100 p-4 rounded-2xl mb-4">
168
+ <MaterialCommunityIcons name="robot" size={32} color="#9333EA" />
169
+ </View>
170
+ <Text className="text-3xl font-bold text-center mb-2">
171
+ AI Smart Note
172
+ </Text>
173
+ <Text className="text-lg text-muted-foreground text-center px-4">
174
+ Write in simple english no need to fill in boring forms
175
+ </Text>
176
+ </View>
177
+
178
+ <AIDemo />
179
+
180
+ <Text className="text-center text-muted-foreground mt-6 px-4">
181
+ We extract amount, date, merchant, category, tags, and even payment
182
+ method automatically.
183
+ </Text>
184
+ </View>
185
+
186
+ <View className="pt-4 border-t border-border bg-background">
187
+ <Button
188
+ label="Next Feature"
189
+ onPress={() => {
190
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
191
+ onNext();
192
+ }}
193
+ size="lg"
194
+ className="w-full m-0"
195
+ />
196
+ </View>
197
+ </Animated.View>
198
+ );
199
+ }
@@ -0,0 +1,154 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { View } from 'react-native';
3
+ import Animated, {
4
+ FadeIn,
5
+ FadeOut,
6
+ SlideInRight,
7
+ } from 'react-native-reanimated';
8
+ import { LinearGradient } from 'expo-linear-gradient';
9
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
10
+ import { Text, Button } from '@/components/ui';
11
+ import { useThemeConfig } from '@/lib/use-theme-config';
12
+ import * as Haptics from 'expo-haptics';
13
+
14
+ const ChatbotDemo = () => {
15
+ const theme = useThemeConfig();
16
+ const [showUserMessage, setShowUserMessage] = useState(false);
17
+ const [showTyping, setShowTyping] = useState(false);
18
+ const [showBotMessage, setShowBotMessage] = useState(false);
19
+
20
+ useEffect(() => {
21
+ const sequence = async () => {
22
+ await new Promise((r) => setTimeout(r, 500));
23
+ setShowUserMessage(true);
24
+
25
+ await new Promise((r) => setTimeout(r, 1000));
26
+ setShowTyping(true);
27
+
28
+ await new Promise((r) => setTimeout(r, 1500));
29
+ setShowTyping(false);
30
+ setShowBotMessage(true);
31
+ };
32
+
33
+ sequence();
34
+ }, []);
35
+
36
+ return (
37
+ <View className="bg-card border border-border rounded-3xl overflow-hidden h-80 w-full max-w-sm mx-auto shadow-sm relative">
38
+ <LinearGradient
39
+ colors={[theme.colors.primary + '05', 'transparent']}
40
+ className="absolute inset-0"
41
+ />
42
+
43
+ <View className="p-5 flex-1 justify-center gap-4">
44
+ {/* User Message */}
45
+ {showUserMessage && (
46
+ <Animated.View
47
+ entering={SlideInRight.springify()}
48
+ className="self-end bg-primary rounded-2xl rounded-tr-sm px-4 py-3 max-w-[85%]"
49
+ >
50
+ <Text className="text-primary-foreground font-medium">
51
+ How much did I spend on food this month? 🍔
52
+ </Text>
53
+ </Animated.View>
54
+ )}
55
+
56
+ {/* Typing Indicator */}
57
+ {showTyping && (
58
+ <Animated.View
59
+ entering={FadeIn}
60
+ exiting={FadeOut}
61
+ className="self-start bg-muted rounded-2xl rounded-tl-sm px-4 py-3"
62
+ >
63
+ <View className="flex-row gap-1">
64
+ <View className="w-2 h-2 bg-muted-foreground/40 rounded-full" />
65
+ <View className="w-2 h-2 bg-muted-foreground/40 rounded-full" />
66
+ <View className="w-2 h-2 bg-muted-foreground/40 rounded-full" />
67
+ </View>
68
+ </Animated.View>
69
+ )}
70
+
71
+ {/* Bot Message */}
72
+ {showBotMessage && (
73
+ <Animated.View
74
+ entering={SlideInRight.springify()}
75
+ className="self-start bg-muted rounded-2xl rounded-tl-sm px-4 py-3 max-w-[90%] shadow-sm border border-border/50"
76
+ >
77
+ <View className="flex-row items-center gap-2 mb-2">
78
+ <View className="bg-purple-100 p-1 rounded-full">
79
+ <MaterialCommunityIcons
80
+ name="robot"
81
+ size={12}
82
+ color="#9333EA"
83
+ />
84
+ </View>
85
+ <Text className="text-xs font-bold text-purple-600">
86
+ CashPilot AI
87
+ </Text>
88
+ </View>
89
+ <Text className="text-foreground leading-5">
90
+ You spent <Text className="font-bold text-primary">$450</Text> on
91
+ food.
92
+ </Text>
93
+ <Text className="text-foreground leading-5 mt-2">
94
+ That's <Text className="text-green-600 font-bold">10% less</Text>{' '}
95
+ than last month! Great job sticking to your budget. 📉
96
+ </Text>
97
+ </Animated.View>
98
+ )}
99
+ </View>
100
+ </View>
101
+ );
102
+ };
103
+
104
+ interface FeatureChatbotStepProps {
105
+ onNext: () => void;
106
+ }
107
+
108
+ export function FeatureChatbotStep({ onNext }: FeatureChatbotStepProps) {
109
+ return (
110
+ <Animated.View
111
+ entering={FadeIn}
112
+ exiting={FadeOut}
113
+ className="flex-1 px-6 pt-12"
114
+ >
115
+ <View className="flex-1 justify-center">
116
+ <View className="items-center mb-8">
117
+ <View className="bg-indigo-100 p-4 rounded-2xl mb-4">
118
+ <MaterialCommunityIcons
119
+ name="chat-processing-outline"
120
+ size={32}
121
+ color="#4F46E5"
122
+ />
123
+ </View>
124
+ <Text className="text-3xl font-bold text-center mb-2">
125
+ AI Assistant
126
+ </Text>
127
+ <Text className="text-lg text-muted-foreground text-center px-4">
128
+ Ask questions about your spending, get insights, and personalized
129
+ tips.
130
+ </Text>
131
+ </View>
132
+
133
+ <ChatbotDemo />
134
+
135
+ <Text className="text-center text-muted-foreground mt-6 px-4">
136
+ "Where is my money going?" • "Can I afford a vacation?" • "Analyze my
137
+ habits"
138
+ </Text>
139
+ </View>
140
+
141
+ <View className="pt-4 border-t border-border bg-background">
142
+ <Button
143
+ label="Next Feature"
144
+ onPress={() => {
145
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
146
+ onNext();
147
+ }}
148
+ size="lg"
149
+ className="w-full m-0"
150
+ />
151
+ </View>
152
+ </Animated.View>
153
+ );
154
+ }
@@ -0,0 +1,156 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import Animated, {
4
+ FadeIn,
5
+ FadeOut,
6
+ SlideInRight,
7
+ } from 'react-native-reanimated';
8
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
9
+ import { Text, Button } from '@/components/ui';
10
+ import { useThemeConfig } from '@/lib/use-theme-config';
11
+ import * as Haptics from 'expo-haptics';
12
+
13
+ const ManualDemo = () => {
14
+ const theme = useThemeConfig();
15
+
16
+ return (
17
+ <View
18
+ className="bg-card border-border h-88 w-full max-w-sm mx-auto justify-center overflow-hidden rounded-3xl border p-6 shadow-sm"
19
+ style={{ backgroundColor: theme.colors.card }}
20
+ >
21
+ <View className="gap-4">
22
+ <Animated.View
23
+ entering={SlideInRight.delay(100)}
24
+ className="flex-row items-center rounded-2xl p-4"
25
+ style={{ backgroundColor: theme.colors.muted }}
26
+ >
27
+ <MaterialCommunityIcons
28
+ name="tag-outline"
29
+ size={24}
30
+ color={theme.colors.mutedForeground}
31
+ />
32
+ <View className="ml-4 gap-2">
33
+ <View
34
+ className="h-2 w-10 rounded-full"
35
+ style={{ backgroundColor: theme.colors.outline }}
36
+ />
37
+ <View
38
+ className="h-3 w-32 rounded-full"
39
+ style={{ backgroundColor: theme.colors.outline }}
40
+ />
41
+ </View>
42
+ </Animated.View>
43
+ <Animated.View
44
+ entering={SlideInRight.delay(200)}
45
+ className="flex-row items-center rounded-2xl p-4"
46
+ style={{ backgroundColor: theme.colors.muted }}
47
+ >
48
+ <MaterialCommunityIcons
49
+ name="currency-usd"
50
+ size={24}
51
+ color={theme.colors.mutedForeground}
52
+ />
53
+ <View className="ml-4 gap-2">
54
+ <View
55
+ className="h-2 w-10 rounded-full"
56
+ style={{ backgroundColor: theme.colors.outline }}
57
+ />
58
+ <View
59
+ className="h-3 w-24 rounded-full"
60
+ style={{ backgroundColor: theme.colors.outline }}
61
+ />
62
+ </View>
63
+ </Animated.View>
64
+ <Animated.View
65
+ entering={SlideInRight.delay(300)}
66
+ className="flex-row items-center rounded-2xl p-4"
67
+ style={{ backgroundColor: theme.colors.muted }}
68
+ >
69
+ <MaterialCommunityIcons
70
+ name="calendar-blank-outline"
71
+ size={24}
72
+ color={theme.colors.mutedForeground}
73
+ />
74
+ <View className="ml-4 gap-2">
75
+ <View
76
+ className="h-2 w-10 rounded-full"
77
+ style={{ backgroundColor: theme.colors.outline }}
78
+ />
79
+ <View
80
+ className="h-3 w-28 rounded-full"
81
+ style={{ backgroundColor: theme.colors.outline }}
82
+ />
83
+ </View>
84
+ </Animated.View>
85
+ <Animated.View
86
+ entering={SlideInRight.delay(400)}
87
+ className="flex-row items-center rounded-2xl p-4"
88
+ style={{ backgroundColor: theme.colors.muted }}
89
+ >
90
+ <MaterialCommunityIcons
91
+ name="shape-outline"
92
+ size={24}
93
+ color={theme.colors.mutedForeground}
94
+ />
95
+ <View className="ml-4 gap-2">
96
+ <View
97
+ className="h-2 w-10 rounded-full"
98
+ style={{ backgroundColor: theme.colors.outline }}
99
+ />
100
+ <View
101
+ className="h-3 w-32 rounded-full"
102
+ style={{ backgroundColor: theme.colors.outline }}
103
+ />
104
+ </View>
105
+ </Animated.View>
106
+ </View>
107
+ </View>
108
+ );
109
+ };
110
+
111
+ interface FeatureManualStepProps {
112
+ onNext: () => void;
113
+ }
114
+
115
+ export function FeatureManualStep({ onNext }: FeatureManualStepProps) {
116
+ const theme = useThemeConfig();
117
+
118
+ return (
119
+ <Animated.View
120
+ entering={FadeIn}
121
+ exiting={FadeOut}
122
+ className="flex-1 px-6 pt-12"
123
+ >
124
+ <View className="flex-1 justify-center">
125
+ <View className="mb-10 items-center">
126
+ <View className="mb-6 rounded-3xl bg-[#DBEAFE] p-5">
127
+ <MaterialCommunityIcons name="pencil" size={36} color="#2563EB" />
128
+ </View>
129
+ <Text className="mb-3 text-center text-3xl font-bold">
130
+ Power Entry
131
+ </Text>
132
+ <Text
133
+ className="px-4 text-center text-lg"
134
+ style={{ color: theme.colors.mutedForeground }}
135
+ >
136
+ For when you need total control over every detail.
137
+ </Text>
138
+ </View>
139
+
140
+ <ManualDemo />
141
+ </View>
142
+
143
+ <View className="border-border bg-background border-t pt-4">
144
+ <Button
145
+ label="Next"
146
+ onPress={() => {
147
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
148
+ onNext();
149
+ }}
150
+ size="lg"
151
+ className="m-0 w-full"
152
+ />
153
+ </View>
154
+ </Animated.View>
155
+ );
156
+ }
@@ -0,0 +1,158 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View } from 'react-native';
3
+ import Animated, {
4
+ FadeIn,
5
+ FadeOut,
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ withRepeat,
9
+ withSequence,
10
+ withTiming,
11
+ Easing,
12
+ } from 'react-native-reanimated';
13
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
14
+ import { Text, Button } from '@/components/ui';
15
+ import { useThemeConfig } from '@/lib/use-theme-config';
16
+ import * as Haptics from 'expo-haptics';
17
+
18
+ const ScanDemo = () => {
19
+ const theme = useThemeConfig();
20
+ const scanLineY = useSharedValue(0);
21
+ const checkmarkScale = useSharedValue(0);
22
+
23
+ useEffect(() => {
24
+ scanLineY.value = withRepeat(
25
+ withSequence(
26
+ withTiming(280, { duration: 2000, easing: Easing.linear }),
27
+ withTiming(0, { duration: 0 }),
28
+ ),
29
+ -1,
30
+ );
31
+
32
+ checkmarkScale.value = withRepeat(
33
+ withSequence(
34
+ withTiming(1.2, { duration: 500 }),
35
+ withTiming(1, { duration: 500 }),
36
+ ),
37
+ -1,
38
+ true,
39
+ );
40
+ }, []);
41
+
42
+ const animatedLineStyle = useAnimatedStyle(() => ({
43
+ transform: [{ translateY: scanLineY.value }],
44
+ }));
45
+
46
+ const animatedCheckmarkStyle = useAnimatedStyle(() => ({
47
+ transform: [{ scale: checkmarkScale.value }],
48
+ }));
49
+
50
+ return (
51
+ <View className="bg-card border border-border rounded-3xl overflow-hidden h-96 w-full max-w-sm mx-auto items-center justify-center shadow-sm relative">
52
+ <View className="relative w-56 h-80 bg-background border border-border rounded-xl shadow-sm overflow-hidden p-4">
53
+ {/* Skeleton Receipt Content */}
54
+ <View className="items-center mb-6">
55
+ <View className="w-16 h-16 bg-muted rounded-full mb-3" />
56
+ <View className="w-32 h-4 bg-muted rounded-full mb-2" />
57
+ <View className="w-24 h-3 bg-muted/50 rounded-full" />
58
+ </View>
59
+
60
+ <View className="gap-3 mb-6">
61
+ <View className="flex-row justify-between">
62
+ <View className="w-24 h-3 bg-muted/50 rounded-full" />
63
+ <View className="w-12 h-3 bg-muted/50 rounded-full" />
64
+ </View>
65
+ <View className="flex-row justify-between">
66
+ <View className="w-20 h-3 bg-muted/50 rounded-full" />
67
+ <View className="w-10 h-3 bg-muted/50 rounded-full" />
68
+ </View>
69
+ <View className="flex-row justify-between">
70
+ <View className="w-28 h-3 bg-muted/50 rounded-full" />
71
+ <View className="w-14 h-3 bg-muted/50 rounded-full" />
72
+ </View>
73
+ </View>
74
+
75
+ <View className="border-t border-dashed border-border my-2" />
76
+
77
+ <View className="flex-row justify-between mt-4">
78
+ <View className="w-16 h-4 bg-muted rounded-full" />
79
+ <View className="w-20 h-4 bg-muted rounded-full" />
80
+ </View>
81
+
82
+ {/* Scan Line Overlay */}
83
+ <Animated.View
84
+ style={[
85
+ animatedLineStyle,
86
+ {
87
+ position: 'absolute',
88
+ top: 0,
89
+ left: 0,
90
+ right: 0,
91
+ height: 4,
92
+ backgroundColor: theme.colors.primary,
93
+ shadowColor: theme.colors.primary,
94
+ shadowOpacity: 0.8,
95
+ shadowRadius: 8,
96
+ elevation: 5,
97
+ zIndex: 10,
98
+ },
99
+ ]}
100
+ />
101
+
102
+ {/* Checkmark Overlay */}
103
+ <Animated.View
104
+ style={[
105
+ animatedCheckmarkStyle,
106
+ { position: 'absolute', bottom: 15, right: 15, zIndex: 20 },
107
+ ]}
108
+ >
109
+ <View className="bg-green-500 rounded-full p-2 shadow-md">
110
+ <MaterialCommunityIcons name="check" size={20} color="white" />
111
+ </View>
112
+ </Animated.View>
113
+ </View>
114
+ </View>
115
+ );
116
+ };
117
+
118
+ interface FeatureScanStepProps {
119
+ onNext: () => void;
120
+ }
121
+
122
+ export function FeatureScanStep({ onNext }: FeatureScanStepProps) {
123
+ return (
124
+ <Animated.View
125
+ entering={FadeIn}
126
+ exiting={FadeOut}
127
+ className="flex-1 px-6 pt-12"
128
+ >
129
+ <View className="flex-1 justify-center">
130
+ <View className="items-center mb-8">
131
+ <View className="bg-green-100 p-4 rounded-2xl mb-4">
132
+ <MaterialCommunityIcons name="camera" size={32} color="#16A34A" />
133
+ </View>
134
+ <Text className="text-3xl font-bold text-center mb-2">
135
+ Insta-Scan
136
+ </Text>
137
+ <Text className="text-lg text-muted-foreground text-center px-4">
138
+ Snap a photo of any receipt. We extract the data instantly.
139
+ </Text>
140
+ </View>
141
+
142
+ <ScanDemo />
143
+ </View>
144
+
145
+ <View className="pt-4 border-t border-border bg-background">
146
+ <Button
147
+ label="Next Feature"
148
+ onPress={() => {
149
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
150
+ onNext();
151
+ }}
152
+ size="lg"
153
+ className="w-full m-0"
154
+ />
155
+ </View>
156
+ </Animated.View>
157
+ );
158
+ }