vibefast-cli 1.1.5 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +63 -169
  3. package/dist/__tests__/recipes.test.js +89 -85
  4. package/dist/__tests__/recipes.test.js.map +1 -1
  5. package/dist/commands/add.d.ts +1 -1
  6. package/dist/commands/add.d.ts.map +1 -1
  7. package/dist/commands/add.js +576 -588
  8. package/dist/commands/add.js.map +1 -1
  9. package/dist/commands/checklist.d.ts +1 -1
  10. package/dist/commands/checklist.d.ts.map +1 -1
  11. package/dist/commands/checklist.js +40 -39
  12. package/dist/commands/checklist.js.map +1 -1
  13. package/dist/commands/doctor.d.ts +1 -1
  14. package/dist/commands/doctor.js +22 -22
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/env.d.ts +1 -1
  17. package/dist/commands/env.d.ts.map +1 -1
  18. package/dist/commands/env.js +58 -53
  19. package/dist/commands/env.js.map +1 -1
  20. package/dist/commands/health.d.ts +1 -1
  21. package/dist/commands/health.d.ts.map +1 -1
  22. package/dist/commands/health.js +101 -93
  23. package/dist/commands/health.js.map +1 -1
  24. package/dist/commands/init.d.ts +1 -1
  25. package/dist/commands/init.d.ts.map +1 -1
  26. package/dist/commands/init.js +416 -296
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/commands/remove.d.ts +1 -1
  29. package/dist/commands/remove.d.ts.map +1 -1
  30. package/dist/commands/remove.js +77 -64
  31. package/dist/commands/remove.js.map +1 -1
  32. package/dist/commands/status.d.ts +1 -1
  33. package/dist/commands/status.d.ts.map +1 -1
  34. package/dist/commands/status.js +15 -14
  35. package/dist/commands/status.js.map +1 -1
  36. package/dist/core/__tests__/detect.test.js +68 -34
  37. package/dist/core/__tests__/detect.test.js.map +1 -1
  38. package/dist/core/ast.d.ts +14 -0
  39. package/dist/core/ast.d.ts.map +1 -0
  40. package/dist/core/ast.js +239 -0
  41. package/dist/core/ast.js.map +1 -0
  42. package/dist/core/codemod.d.ts.map +1 -1
  43. package/dist/core/codemod.js +62 -44
  44. package/dist/core/codemod.js.map +1 -1
  45. package/dist/core/config.d.ts +10 -0
  46. package/dist/core/config.d.ts.map +1 -0
  47. package/dist/core/config.js +51 -0
  48. package/dist/core/config.js.map +1 -0
  49. package/dist/core/detect.d.ts +8 -2
  50. package/dist/core/detect.d.ts.map +1 -1
  51. package/dist/core/detect.js +52 -21
  52. package/dist/core/detect.js.map +1 -1
  53. package/dist/core/errors.d.ts.map +1 -1
  54. package/dist/core/errors.js +9 -8
  55. package/dist/core/errors.js.map +1 -1
  56. package/dist/core/exec.d.ts +16 -0
  57. package/dist/core/exec.d.ts.map +1 -0
  58. package/dist/core/exec.js +48 -0
  59. package/dist/core/exec.js.map +1 -0
  60. package/dist/core/manualSteps.d.ts +7 -0
  61. package/dist/core/manualSteps.d.ts.map +1 -0
  62. package/dist/core/manualSteps.js +59 -0
  63. package/dist/core/manualSteps.js.map +1 -0
  64. package/dist/core/paths.d.ts +3 -1
  65. package/dist/core/paths.d.ts.map +1 -1
  66. package/dist/core/paths.js +14 -10
  67. package/dist/core/paths.js.map +1 -1
  68. package/dist/core/spinner.d.ts +1 -1
  69. package/dist/core/spinner.d.ts.map +1 -1
  70. package/dist/core/spinner.js +38 -8
  71. package/dist/core/spinner.js.map +1 -1
  72. package/dist/core/vosk.d.ts.map +1 -1
  73. package/dist/core/vosk.js +50 -39
  74. package/dist/core/vosk.js.map +1 -1
  75. package/docs/manual-testing.md +91 -0
  76. package/package.json +6 -3
  77. package/recipes/audio-recorder/apps/native/src/app/audio-recorder/index.tsx +5 -0
  78. package/recipes/audio-recorder/recipe.json +3 -3
  79. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
  80. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
  81. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
  82. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/index.ts +4 -0
  83. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
  84. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
  85. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
  86. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
  87. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
  88. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
  89. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
  90. package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +369 -0
  91. package/recipes/audio-recorder-supabase/packages/backend/supabase/migrations/recordings.sql +70 -0
  92. package/recipes/audio-recorder-supabase/recipe.json +52 -0
  93. package/recipes/audio-recorder-supabase@latest.zip +0 -0
  94. package/recipes/audio-recorder@latest.zip +0 -0
  95. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -3
  96. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +2 -2
  97. package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +5 -5
  98. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -3
  99. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +20 -4
  100. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +7 -6
  101. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +6 -4
  102. package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +1 -1
  103. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +5 -4
  104. package/recipes/charts/recipe.json +4 -13
  105. package/recipes/charts@latest.zip +0 -0
  106. package/recipes/chatbot/apps/native/src/app/chatbot/index.tsx +1 -0
  107. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
  108. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
  109. package/recipes/chatbot/recipe.json +26 -92
  110. package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +515 -0
  111. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/app/index.tsx +257 -0
  112. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +59 -0
  113. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-input-bar.tsx +485 -0
  114. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +575 -0
  115. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +223 -0
  116. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +161 -0
  117. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
  118. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +165 -0
  119. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/index.ts +10 -0
  120. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +129 -0
  121. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-error-boundary.tsx +78 -0
  122. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-list.tsx +170 -0
  123. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/model-selector.tsx +283 -0
  124. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/report-content-modal.tsx +188 -0
  125. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/suggested-messages.tsx +67 -0
  126. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/models.ts +20 -0
  127. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/report-reasons.ts +9 -0
  128. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +142 -0
  129. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-config.ts +458 -0
  130. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +429 -0
  131. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +89 -0
  132. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-conversation.ts +90 -0
  133. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-image-picker.ts +122 -0
  134. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +161 -0
  135. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +213 -0
  136. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/index.ts +86 -0
  137. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/models.ts +162 -0
  138. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/providers.ts +62 -0
  139. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/types.ts +40 -0
  140. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/file-uploader.ts +287 -0
  141. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/message-handler-service.ts +189 -0
  142. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/types/index.ts +70 -0
  143. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/utils/chat-telemetry.ts +91 -0
  144. package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +243 -0
  145. package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +327 -0
  146. package/recipes/chatbot-supabase/packages/backend/supabase/functions/chat-stream/index.ts +347 -0
  147. package/recipes/chatbot-supabase/packages/backend/supabase/migrations/chatbot.sql +104 -0
  148. package/recipes/chatbot-supabase/recipe.json +106 -0
  149. package/recipes/chatbot-supabase@latest.zip +0 -0
  150. package/recipes/chatbot.zip +0 -0
  151. package/recipes/chatbot@latest.zip +0 -0
  152. package/recipes/image-analysis/packages/backend/convex/imageAnalysis/index.ts +2 -2
  153. package/recipes/image-analysis/packages/backend/convex/imageAnalysis.ts +0 -1
  154. package/recipes/image-analysis/recipe.json +15 -55
  155. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
  156. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
  157. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
  158. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading-screen.tsx +214 -0
  159. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading.tsx +191 -0
  160. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
  161. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
  162. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +160 -0
  163. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
  164. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
  165. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
  166. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
  167. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
  168. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
  169. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
  170. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
  171. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
  172. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
  173. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
  174. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
  175. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
  176. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
  177. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
  178. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
  179. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
  180. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
  181. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
  182. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +38 -0
  183. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +208 -0
  184. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
  185. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
  186. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
  187. package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +132 -0
  188. package/recipes/image-analysis-supabase/packages/backend/supabase/functions/analyze-image/index.ts +312 -0
  189. package/recipes/image-analysis-supabase/packages/backend/supabase/migrations/image_analysis.sql +42 -0
  190. package/recipes/image-analysis-supabase/recipe.json +90 -0
  191. package/recipes/image-analysis-supabase@latest.zip +0 -0
  192. package/recipes/image-analysis@latest.zip +0 -0
  193. package/recipes/image-generator/apps/native/src/features/image-generator/app/index.tsx +16 -2
  194. package/recipes/image-generator/apps/native/src/features/image-generator/components/image-model-selector.tsx +11 -5
  195. package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator.ts +11 -5
  196. package/recipes/image-generator/packages/backend/convex/imageGeneration/index.ts +2 -2
  197. package/recipes/image-generator/recipe.json +16 -39
  198. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
  199. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
  200. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/index.tsx +251 -0
  201. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
  202. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
  203. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-model-selector.tsx +216 -0
  204. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
  205. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
  206. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
  207. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator.ts +103 -0
  208. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/models/models.ts +66 -0
  209. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-gallery-service.ts +96 -0
  210. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-save-service.ts +120 -0
  211. package/recipes/image-generator-supabase/packages/backend/supabase/functions/generate-image/index.ts +291 -0
  212. package/recipes/image-generator-supabase/packages/backend/supabase/migrations/image_generator.sql +71 -0
  213. package/recipes/image-generator-supabase/recipe.json +86 -0
  214. package/recipes/image-generator-supabase@latest.zip +0 -0
  215. package/recipes/image-generator@latest.zip +0 -0
  216. package/recipes/ios-widget/recipe.json +15 -24
  217. package/recipes/ios-widget@latest.zip +0 -0
  218. package/recipes/onboarding/apps/native/src/features/onboarding/analytics/index.ts +9 -0
  219. package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
  220. package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
  221. package/recipes/onboarding/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
  222. package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/app/index.tsx +42 -0
  223. package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
  224. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/app/index.tsx +43 -0
  225. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +222 -0
  226. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +133 -0
  227. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +165 -0
  228. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +199 -0
  229. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +154 -0
  230. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +156 -0
  231. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +158 -0
  232. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +139 -0
  233. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +129 -0
  234. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +138 -0
  235. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +190 -0
  236. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +98 -0
  237. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +181 -0
  238. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +110 -0
  239. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +139 -0
  240. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +217 -0
  241. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +58 -0
  242. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/constants.ts +179 -0
  243. package/recipes/onboarding/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
  244. package/recipes/onboarding/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
  245. package/recipes/onboarding/recipe.json +15 -0
  246. package/recipes/onboarding@latest.zip +0 -0
  247. package/recipes/payments/recipe.json +28 -61
  248. package/recipes/payments-supabase/apps/native/src/features/payments/README.md +200 -0
  249. package/recipes/payments-supabase/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
  250. package/recipes/payments-supabase/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
  251. package/recipes/payments-supabase/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
  252. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
  253. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
  254. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
  255. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
  256. package/recipes/payments-supabase/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
  257. package/recipes/payments-supabase/apps/native/src/features/payments/index.ts +8 -0
  258. package/recipes/payments-supabase/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
  259. package/recipes/payments-supabase/packages/backend/src/services/payments.ts +201 -0
  260. package/recipes/payments-supabase/packages/backend/supabase/migrations/payments.sql +35 -0
  261. package/recipes/payments-supabase/recipe.json +72 -0
  262. package/recipes/payments-supabase@latest.zip +0 -0
  263. package/recipes/payments@latest.zip +0 -0
  264. package/recipes/quiz/apps/native/src/features/quiz/index.tsx +1 -2
  265. package/recipes/quiz/recipe.json +6 -9
  266. package/recipes/quiz@latest.zip +0 -0
  267. package/recipes/tracker-app/apps/native/src/features/tracker-app/app/index.tsx +1 -2
  268. package/recipes/tracker-app/recipe.json +7 -10
  269. package/recipes/tracker-app@latest.zip +0 -0
  270. package/recipes/voice-bot/recipe.json +8 -68
  271. package/recipes/voice-bot.zip +0 -0
  272. package/recipes/voice-bot@latest.zip +0 -0
  273. package/recipes/wake-word/recipe.json +10 -9
  274. package/recipes/wake-word.zip +0 -0
  275. package/recipes/wake-word@latest.zip +0 -0
  276. package/recipes/charts/apps/native/src/app/(root)/(protected)/charts/index.tsx +0 -3
  277. package/recipes/chatbot/packages/backend/convex/lib/rateLimit.ts +0 -100
  278. package/recipes/chatbot/packages/backend/convex/lib/telemetry.ts +0 -29
  279. package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -0
  280. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/front.jpg +0 -0
  281. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/side.jpg +0 -0
  282. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
  283. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +0 -5
  284. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +0 -50
  285. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +0 -2
  286. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +0 -50
  287. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +0 -50
  288. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +0 -2
  289. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +0 -3
  290. package/recipes/image-analysis/packages/backend/convex/imageAnalysisFunctions.ts +0 -325
  291. package/recipes/image-analysis/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +0 -200
  292. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/index.tsx +0 -74
  293. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/local.tsx +0 -25
  294. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +0 -23
  295. package/recipes/quiz/apps/native/src/app/(root)/(protected)/quiz/index.tsx +0 -47
  296. package/recipes/tracker-app/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +0 -1
  297. package/recipes/voice-bot/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +0 -27
  298. package/recipes/voice-bot/packages/backend/convex/router.ts +0 -81
  299. /package/recipes/{chatbot/apps/native/src/app/(root)/(protected) → chatbot-supabase/apps/native/src/app}/chatbot/index.tsx +0 -0
  300. /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/gallery.tsx +0 -0
  301. /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,71 @@
1
+ -- Image Generator Feature Migration
2
+ -- Creates tables for AI-generated images
3
+ -- Run this migration when adding the image-generator feature via CLI
4
+
5
+ -- ============================================================================
6
+ -- GENERATED_IMAGES TABLE
7
+ -- Stores AI-generated images metadata
8
+ -- ============================================================================
9
+ CREATE TABLE IF NOT EXISTS generated_images (
10
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
11
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
12
+ prompt TEXT NOT NULL,
13
+ image_url TEXT,
14
+ storage_id TEXT,
15
+ mime_type TEXT,
16
+ provider TEXT NOT NULL,
17
+ model TEXT NOT NULL,
18
+ created_at TIMESTAMPTZ DEFAULT now()
19
+ );
20
+
21
+ -- ============================================================================
22
+ -- INDEXES
23
+ -- ============================================================================
24
+ CREATE INDEX IF NOT EXISTS idx_generated_images_user_id ON generated_images(user_id);
25
+
26
+ -- ============================================================================
27
+ -- RLS POLICIES
28
+ -- ============================================================================
29
+ ALTER TABLE generated_images ENABLE ROW LEVEL SECURITY;
30
+
31
+ CREATE POLICY "generated_images_select_own" ON generated_images
32
+ FOR SELECT USING (auth.uid() = user_id);
33
+
34
+ CREATE POLICY "generated_images_insert_own" ON generated_images
35
+ FOR INSERT WITH CHECK (auth.uid() = user_id);
36
+
37
+ CREATE POLICY "generated_images_update_own" ON generated_images
38
+ FOR UPDATE USING (auth.uid() = user_id);
39
+
40
+ CREATE POLICY "generated_images_delete_own" ON generated_images
41
+ FOR DELETE USING (auth.uid() = user_id);
42
+
43
+ -- ============================================================================
44
+ -- STORAGE BUCKET - generated-images
45
+ -- ============================================================================
46
+ INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
47
+ VALUES (
48
+ 'generated-images',
49
+ 'generated-images',
50
+ false,
51
+ 10485760, -- 10MB limit
52
+ ARRAY['image/jpeg', 'image/png', 'image/webp']
53
+ ) ON CONFLICT (id) DO NOTHING;
54
+
55
+ -- Storage RLS for generated-images
56
+ CREATE POLICY "Users can view their own generated images"
57
+ ON storage.objects FOR SELECT TO authenticated
58
+ USING (bucket_id = 'generated-images' AND (storage.foldername(name))[1] = auth.uid()::text);
59
+
60
+ CREATE POLICY "Users can upload their own generated images"
61
+ ON storage.objects FOR INSERT TO authenticated
62
+ WITH CHECK (bucket_id = 'generated-images' AND (storage.foldername(name))[1] = auth.uid()::text);
63
+
64
+ CREATE POLICY "Users can update their own generated images"
65
+ ON storage.objects FOR UPDATE TO authenticated
66
+ USING (bucket_id = 'generated-images' AND (storage.foldername(name))[1] = auth.uid()::text)
67
+ WITH CHECK (bucket_id = 'generated-images' AND (storage.foldername(name))[1] = auth.uid()::text);
68
+
69
+ CREATE POLICY "Users can delete their own generated images"
70
+ ON storage.objects FOR DELETE TO authenticated
71
+ USING (bucket_id = 'generated-images' AND (storage.foldername(name))[1] = auth.uid()::text);
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "image-generator",
3
+ "version": "1.0.0",
4
+ "description": "AI-powered image generation with Supabase backend",
5
+ "copy": [
6
+ {
7
+ "from": "apps/native/src/app/image-generator",
8
+ "to": "apps/native/src/app/(root)/(protected)/image-generator"
9
+ },
10
+ {
11
+ "from": "apps/native/src/features/image-generator",
12
+ "to": "apps/native/src/features/image-generator"
13
+ },
14
+ {
15
+ "from": "apps/native/src/api-client/supabase/image-generator.ts",
16
+ "to": "apps/native/src/api-client/supabase/image-generator.ts"
17
+ },
18
+ {
19
+ "from": "apps/native/src/api-client/supabase/reporting.ts",
20
+ "to": "apps/native/src/api-client/supabase/reporting.ts"
21
+ },
22
+ {
23
+ "from": "apps/native/src/api-client/supabase/shared.ts",
24
+ "to": "apps/native/src/api-client/supabase/shared.ts"
25
+ },
26
+ {
27
+ "from": "apps/native/src/api-client/reporting.ts",
28
+ "to": "apps/native/src/api-client/reporting.ts"
29
+ },
30
+ {
31
+ "from": "apps/native/src/api-client/shared.ts",
32
+ "to": "apps/native/src/api-client/shared.ts"
33
+ },
34
+ {
35
+ "from": "packages/backend/supabase/functions/generate-image",
36
+ "to": "packages/backend/supabase/functions/generate-image"
37
+ },
38
+ {
39
+ "from": "packages/backend/supabase/migrations/image_generator.sql",
40
+ "to": "packages/backend/supabase/migrations/image_generator.sql"
41
+ }
42
+ ],
43
+ "nav": {
44
+ "href": "/(root)/(protected)/image-generator",
45
+ "label": "Image Generator",
46
+ "icon": "🎨",
47
+ "color": "#8B5CF6"
48
+ },
49
+ "target": "native",
50
+ "configuration": {
51
+ "apiClient": {
52
+ "exports": [
53
+ "export { type SupabaseImageGeneratorApi as ImageGeneratorApi, supabaseImageGeneratorApi as imageGeneratorApi } from './supabase/image-generator';"
54
+ ]
55
+ }
56
+ },
57
+ "dependencies": {
58
+ "expo": [
59
+ "@supabase/supabase-js",
60
+ "@tanstack/react-query",
61
+ "expo-file-system",
62
+ "expo-media-library",
63
+ "expo-sharing"
64
+ ]
65
+ },
66
+ "env": [
67
+ {
68
+ "key": "OPENAI_API_KEY",
69
+ "description": "OpenAI API key for DALL-E image generation",
70
+ "example": "sk-...",
71
+ "link": "https://platform.openai.com/api-keys",
72
+ "file": "packages/backend/supabase/.env",
73
+ "required": true
74
+ }
75
+ ],
76
+ "manualSteps": [
77
+ {
78
+ "title": "Apply Supabase migration",
79
+ "description": "Run: cd packages/backend && supabase db push"
80
+ },
81
+ {
82
+ "title": "Deploy Edge Function",
83
+ "description": "Run: cd packages/backend && supabase functions deploy generate-image"
84
+ }
85
+ ]
86
+ }
Binary file
@@ -96,44 +96,35 @@
96
96
  "dependencies": {
97
97
  "expo": ["@bacons/apple-targets"]
98
98
  },
99
+ "plugins": [
100
+ {
101
+ "name": "@bacons/apple-targets",
102
+ "config": "{\n targets: [\n {\n name: 'VibeFastWidget',\n type: 'widget',\n bundleIdentifier: `${Env.BUNDLE_ID}.widget`,\n entitlements: {\n 'com.apple.security.application-groups': [\n `group.${Env.BUNDLE_ID}.shared`,\n ],\n },\n },\n ],\n }"
103
+ }
104
+ ],
105
+ "iosConfig": {
106
+ "appleTeamId": "Env.APPLE_TEAM_ID",
107
+ "entitlements": "{\n 'com.apple.security.application-groups': [`group.${Env.BUNDLE_ID}.shared`],\n }"
108
+ },
99
109
  "env": [
100
110
  {
101
111
  "key": "APPLE_TEAM_ID",
102
112
  "description": "Apple Developer Team ID (used to sign widgets).",
103
113
  "example": "ABCDE12345",
104
114
  "link": "https://developer.apple.com/account/#/membership",
105
- "file": "apps/native/.env.local"
115
+ "file": "apps/native/env.js"
106
116
  }
107
117
  ],
108
118
  "configuration": {
109
119
  "env": {
110
- "constants": [
111
- "const APPLE_TEAM_ID = 'replace_me';"
112
- ],
120
+ "constants": ["const APPLE_TEAM_ID = 'replace_me';"],
113
121
  "buildTime": {
114
- "schema": [
115
- " APPLE_TEAM_ID: z.string(),"
116
- ],
117
- "env": [
118
- " APPLE_TEAM_ID: process.env.APPLE_TEAM_ID,"
119
- ]
122
+ "schema": [" APPLE_TEAM_ID: z.string(),"],
123
+ "env": [" APPLE_TEAM_ID,"]
120
124
  }
121
125
  }
122
126
  },
123
- "manualSteps": [
124
- {
125
- "title": "Verify widget plugin",
126
- "description": "The CLI adds the @bacons/apple-targets plugin automatically. Confirm it exists in app.config.ts.",
127
- "file": "apps/native/app.config.ts",
128
- "content": "[\n '@bacons/apple-targets',\n {\n targets: [\n {\n name: 'VibeFastWidget',\n type: 'widget',\n bundleIdentifier: `${Env.BUNDLE_ID}.widget`,\n entitlements: {\n 'com.apple.security.application-groups': [\n 'group.com.vibefast.vibefast',\n ],\n },\n },\n ],\n },\n]"
129
- },
130
- {
131
- "title": "Configure App Groups",
132
- "description": "Ensure your main app has App Groups entitlements in app.config.ts",
133
- "file": "apps/native/app.config.ts",
134
- "content": "ios: {\n entitlements: {\n 'com.apple.security.application-groups': ['group.com.vibefast.shared'],\n },\n}"
135
- }
136
- ],
127
+ "manualSteps": [],
137
128
  "postInstall": {
138
129
  "instructions": [
139
130
  "Widget target files have been added",
Binary file
@@ -0,0 +1,9 @@
1
+ // Export analytics service and types
2
+
3
+ // Export enhanced components
4
+ export * from '../components/onboarding-with-analytics';
5
+ // Export configuration
6
+ export * from '../config/onboarding-flow-config';
7
+ // Export React hooks
8
+ export * from '../hooks/use-onboarding-analytics';
9
+ export * from '../services/onboarding-analytics';
@@ -0,0 +1,141 @@
1
+ import React, { useCallback, useEffect } from 'react';
2
+
3
+ import { MAIN_ONBOARDING_FLOW } from '../config/onboarding-flow-config';
4
+ import { useOnboardingAnalytics } from '../hooks/use-onboarding-analytics';
5
+ import { Onboarding } from './onboarding';
6
+
7
+ /**
8
+ * Props for the analytics-enabled onboarding component
9
+ */
10
+ export type OnboardingWithAnalyticsProps = {
11
+ userType?: 'new' | 'returning' | 'migrated';
12
+ variant?: 'control' | 'experimental';
13
+ onComplete?: () => void;
14
+ onSkip?: () => void;
15
+ };
16
+
17
+ /**
18
+ * Enhanced onboarding component that automatically tracks user progress
19
+ * and behavior through the onboarding flow with PostHog analytics.
20
+ *
21
+ * This component wraps your existing Onboarding component and adds:
22
+ * - Automatic step tracking
23
+ * - Flow completion analytics
24
+ * - User abandonment detection
25
+ * - A/B test variant tracking
26
+ *
27
+ * Usage:
28
+ * ```tsx
29
+ * <OnboardingWithAnalytics
30
+ * userType="new"
31
+ * variant="experimental"
32
+ * onComplete={() => router.push('/home')}
33
+ * />
34
+ * ```
35
+ */
36
+ export function OnboardingWithAnalytics({
37
+ userType = 'new',
38
+ variant,
39
+ onComplete,
40
+ onSkip,
41
+ }: OnboardingWithAnalyticsProps) {
42
+ // Get the appropriate flow configuration
43
+ const flowConfig = variant
44
+ ? { ...MAIN_ONBOARDING_FLOW, variant }
45
+ : MAIN_ONBOARDING_FLOW;
46
+
47
+ // Initialize onboarding analytics
48
+ const analytics = useOnboardingAnalytics({
49
+ flowConfig,
50
+ userType,
51
+ autoStart: true, // Automatically start tracking when component mounts
52
+ });
53
+
54
+ // Track when component mounts (onboarding starts)
55
+ useEffect(() => {
56
+ // Analytics are auto-started, but we can add additional properties
57
+ analytics.startFlow().then((sessionId) => {
58
+ console.log(`Onboarding session started: ${sessionId}`);
59
+ });
60
+ }, [analytics]);
61
+
62
+ // Enhanced completion handler with analytics
63
+ const handleComplete = useCallback(async () => {
64
+ await analytics.completeFlow();
65
+ onComplete?.();
66
+ }, [analytics, onComplete]);
67
+
68
+ // Enhanced skip handler with analytics (unused but kept for future use)
69
+ // const handleSkip = useCallback(async () => {
70
+ // await analytics.abandonFlow('user_skipped');
71
+ // onSkip?.();
72
+ // }, [analytics, onSkip]);
73
+
74
+ // Example handlers for step-level tracking (unused but kept for future use)
75
+ // const handleStepTransition = useCallback(
76
+ // async (stepId: string, action: 'viewed' | 'completed') => {
77
+ // if (action === 'viewed') {
78
+ // await analytics.trackStepViewed(stepId, {
79
+ // timestamp: new Date().toISOString(),
80
+ // user_type: userType,
81
+ // variant: variant || 'default',
82
+ // });
83
+ // } else if (action === 'completed') {
84
+ // await analytics.trackStepCompleted(stepId, {
85
+ // timestamp: new Date().toISOString(),
86
+ // interaction_method: 'button', // Could be 'swipe', 'tap', etc.
87
+ // });
88
+ // }
89
+ // },
90
+ // [analytics, userType, variant]
91
+ // );
92
+
93
+ // Pass enhanced handlers to your existing Onboarding component
94
+ // Note: You'll need to provide the actual onboarding data
95
+ return (
96
+ <Onboarding
97
+ data={
98
+ [
99
+ // Add your actual onboarding data here
100
+ // This is just a placeholder structure
101
+ ]
102
+ }
103
+ onComplete={handleComplete}
104
+ testID="onboarding-with-analytics"
105
+ />
106
+ );
107
+ }
108
+
109
+ /**
110
+ * Example of how to integrate with your demo screens:
111
+ * You can enhance your existing demo-one.tsx and demo-two.tsx files
112
+ * to include step tracking like this:
113
+ */
114
+
115
+ /*
116
+ // In your demo-one.tsx file:
117
+ export default function DemoOneScreen() {
118
+ const { trackStepViewed, trackStepCompleted } = useContext(OnboardingAnalyticsContext);
119
+
120
+ useEffect(() => {
121
+ trackStepViewed('demo_one');
122
+ }, []);
123
+
124
+ const handleContinue = () => {
125
+ trackStepCompleted('demo_one', {
126
+ interaction_method: 'button',
127
+ time_spent_seconds: Math.floor((Date.now() - startTime) / 1000)
128
+ });
129
+ // Navigate to next step
130
+ };
131
+
132
+ const handleSkip = () => {
133
+ trackStepSkipped('demo_one', 'user_choice');
134
+ // Skip to end or next step
135
+ };
136
+
137
+ return (
138
+ // Your existing UI
139
+ );
140
+ }
141
+ */
@@ -0,0 +1,173 @@
1
+ import LottieView from 'lottie-react-native';
2
+ import React, { useRef, useState } from 'react';
3
+ import { Dimensions, View, type ViewToken } from 'react-native';
4
+ import Animated, {
5
+ useAnimatedScrollHandler,
6
+ useSharedValue,
7
+ } from 'react-native-reanimated';
8
+
9
+ import { Button, Text } from '@/components/ui';
10
+ import ScrollingPaginationDots from '@/components/ui/core/pagination-dots';
11
+ import { translate } from '@/lib';
12
+ import { useThemeConfig } from '@/lib/use-theme-config';
13
+
14
+ const { width: SCREEN_WIDTH } = Dimensions.get('window');
15
+
16
+ export type OnboardingItem = {
17
+ id: string;
18
+ title: string;
19
+ description: string;
20
+ lottieAnim: any; // Lottie animation source
21
+ };
22
+
23
+ export type OnboardingProps = {
24
+ data: OnboardingItem[];
25
+ onComplete: () => void;
26
+ testID?: string;
27
+ };
28
+
29
+ /**
30
+ * Reusable Onboarding component with horizontal swipeable screens,
31
+ * Lottie animations, and progress dots
32
+ */
33
+ export function Onboarding({ data, onComplete, testID }: OnboardingProps) {
34
+ const theme = useThemeConfig();
35
+ const scrollX = useSharedValue(0);
36
+ const flatListRef = useRef<Animated.FlatList<OnboardingItem>>(null);
37
+ const [currentIndex, setCurrentIndex] = useState(0);
38
+
39
+ const handleScroll = useAnimatedScrollHandler((event) => {
40
+ scrollX.value = event.contentOffset.x;
41
+ });
42
+
43
+ const onViewableItemsChanged = ({
44
+ viewableItems,
45
+ }: {
46
+ viewableItems: ViewToken[];
47
+ }) => {
48
+ if (viewableItems.length > 0) {
49
+ const index = viewableItems[0].index || 0;
50
+ setCurrentIndex(index);
51
+ }
52
+ };
53
+
54
+ const handleNext = () => {
55
+ if (currentIndex < data.length - 1) {
56
+ flatListRef.current?.scrollToIndex({
57
+ index: currentIndex + 1,
58
+ animated: true,
59
+ });
60
+ } else {
61
+ onComplete();
62
+ }
63
+ };
64
+
65
+ const handleSkip = () => {
66
+ onComplete();
67
+ };
68
+
69
+ const renderItem = ({ item }: { item: OnboardingItem }) => (
70
+ <View
71
+ style={{ width: SCREEN_WIDTH }}
72
+ className="flex-1 items-center justify-center px-8"
73
+ >
74
+ {/* Lottie Animation */}
75
+ <View className="h-80 w-full items-center justify-center">
76
+ <LottieView
77
+ source={item.lottieAnim}
78
+ autoPlay
79
+ loop
80
+ style={{
81
+ width: 250,
82
+ height: 250,
83
+ }}
84
+ testID={`${testID}-lottie-${item.id}`}
85
+ />
86
+ </View>
87
+
88
+ {/* Title */}
89
+ <Text
90
+ className="my-4 text-center text-4xl font-bold"
91
+ testID={`${testID}-title-${item.id}`}
92
+ >
93
+ {item.title}
94
+ </Text>
95
+
96
+ {/* Description */}
97
+ <Text
98
+ className="text-center text-lg leading-6"
99
+ style={{ color: theme.colors.mutedForeground }}
100
+ testID={`${testID}-description-${item.id}`}
101
+ >
102
+ {item.description}
103
+ </Text>
104
+ </View>
105
+ );
106
+
107
+ const isLastSlide = currentIndex === data.length - 1;
108
+
109
+ return (
110
+ <View className="flex-1" testID={testID}>
111
+ {/* Main Content */}
112
+ <View className="flex-1">
113
+ <Animated.FlatList
114
+ ref={flatListRef}
115
+ data={data}
116
+ keyExtractor={(item) => item.id}
117
+ renderItem={renderItem}
118
+ horizontal
119
+ pagingEnabled
120
+ showsHorizontalScrollIndicator={false}
121
+ onScroll={handleScroll}
122
+ onViewableItemsChanged={onViewableItemsChanged}
123
+ viewabilityConfig={{
124
+ itemVisiblePercentThreshold: 50,
125
+ }}
126
+ scrollEventThrottle={16}
127
+ testID={`${testID}-flatlist`}
128
+ />
129
+ </View>
130
+
131
+ {/* Progress Dots */}
132
+ <View className="items-center py-6">
133
+ <ScrollingPaginationDots
134
+ count={data.length}
135
+ scrollX={scrollX}
136
+ slideWidth={SCREEN_WIDTH}
137
+ dotColor={theme.colors.primary}
138
+ inactiveDotColor={theme.colors.mutedForeground}
139
+ dotSize={10}
140
+ spacing={12}
141
+ inactiveDotOpacity={0.3}
142
+ maxVisibleDots={5}
143
+ />
144
+ </View>
145
+
146
+ {/* Action Buttons */}
147
+ <View className="flex-row items-center justify-between px-8 pb-8">
148
+ <Button
149
+ variant="ghost"
150
+ label={translate('onboarding.skip')}
151
+ onPress={handleSkip}
152
+ testID={`${testID}-skip-button`}
153
+ className="flex-1"
154
+ />
155
+
156
+ <View className="w-4" />
157
+
158
+ <Button
159
+ label={
160
+ isLastSlide
161
+ ? translate('onboarding.get_started')
162
+ : translate('onboarding.next')
163
+ }
164
+ onPress={handleNext}
165
+ testID={`${testID}-${isLastSlide ? 'complete' : 'next'}-button`}
166
+ className="flex-1"
167
+ />
168
+ </View>
169
+ </View>
170
+ );
171
+ }
172
+
173
+ export default Onboarding;