vibefast-cli 1.2.1 → 1.3.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 (348) hide show
  1. package/README.md +30 -95
  2. package/dist/__tests__/recipes.test.js +94 -91
  3. package/dist/__tests__/recipes.test.js.map +1 -1
  4. package/dist/commands/add.d.ts.map +1 -1
  5. package/dist/commands/add.js +301 -125
  6. package/dist/commands/add.js.map +1 -1
  7. package/dist/commands/checklist.d.ts.map +1 -1
  8. package/dist/commands/checklist.js +85 -44
  9. package/dist/commands/checklist.js.map +1 -1
  10. package/dist/commands/health.d.ts.map +1 -1
  11. package/dist/commands/health.js +13 -4
  12. package/dist/commands/health.js.map +1 -1
  13. package/dist/commands/init.d.ts.map +1 -1
  14. package/dist/commands/init.js +118 -26
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/migrate.d.ts +3 -0
  17. package/dist/commands/migrate.d.ts.map +1 -0
  18. package/dist/commands/migrate.js +202 -0
  19. package/dist/commands/migrate.js.map +1 -0
  20. package/dist/commands/remove.d.ts.map +1 -1
  21. package/dist/commands/remove.js +61 -3
  22. package/dist/commands/remove.js.map +1 -1
  23. package/dist/core/auth.d.ts.map +1 -1
  24. package/dist/core/auth.js +20 -18
  25. package/dist/core/auth.js.map +1 -1
  26. package/dist/core/codemod.d.ts +33 -0
  27. package/dist/core/codemod.d.ts.map +1 -1
  28. package/dist/core/codemod.js +116 -0
  29. package/dist/core/codemod.js.map +1 -1
  30. package/dist/core/detect.d.ts.map +1 -1
  31. package/dist/core/detect.js +24 -7
  32. package/dist/core/detect.js.map +1 -1
  33. package/dist/core/journal.d.ts +1 -0
  34. package/dist/core/journal.d.ts.map +1 -1
  35. package/dist/core/journal.js.map +1 -1
  36. package/dist/core/recipes.d.ts.map +1 -1
  37. package/dist/core/recipes.js +25 -7
  38. package/dist/core/recipes.js.map +1 -1
  39. package/dist/index.js +2 -2
  40. package/dist/index.js.map +1 -1
  41. package/docs/architecture.md +50 -0
  42. package/docs/commands.md +78 -0
  43. package/docs/contributing.md +27 -0
  44. package/docs/quickstart.md +50 -0
  45. package/docs/recipes.md +57 -0
  46. package/docs/troubleshooting.md +31 -0
  47. package/package.json +2 -2
  48. package/recipes/0/apps/native/src/components/advanced-ui/timeline/demo.tsx +445 -0
  49. package/recipes/0/apps/native/src/components/advanced-ui/timeline/timeline-view.tsx +355 -0
  50. package/recipes/0/apps/native/src/components/advanced-ui/timeline/types.ts +31 -0
  51. package/recipes/0/recipe.json +18 -0
  52. package/recipes/animated-chip/apps/native/src/components/advanced-ui/chip/demo.tsx +2 -1
  53. package/recipes/animated-chip/recipe.json +5 -2
  54. package/recipes/animated-chip-native@latest.zip +0 -0
  55. package/recipes/animated-chip@latest.zip +0 -0
  56. package/recipes/animated-switch/apps/native/src/components/advanced-ui/switch/demo.tsx +1 -1
  57. package/recipes/animated-switch/recipe.json +5 -2
  58. package/recipes/animated-switch-native@latest.zip +0 -0
  59. package/recipes/animated-switch@latest.zip +0 -0
  60. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
  61. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -2
  62. package/recipes/audio-recorder/recipe.json +7 -2
  63. package/recipes/audio-recorder-native@latest.zip +0 -0
  64. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
  65. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -1
  66. package/recipes/audio-recorder-supabase/recipe.json +12 -16
  67. package/recipes/audio-recorder-supabase-native@latest.zip +0 -0
  68. package/recipes/audio-recorder-supabase@latest.zip +0 -0
  69. package/recipes/audio-recorder@latest.zip +0 -0
  70. package/recipes/charts/apps/native/src/app/charts/index.tsx +3 -0
  71. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -1
  72. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +3 -1
  73. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -1
  74. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +3 -1
  75. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +3 -1
  76. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +3 -1
  77. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +3 -1
  78. package/recipes/charts/recipe.json +13 -4
  79. package/recipes/charts-native@latest.zip +0 -0
  80. package/recipes/charts@latest.zip +0 -0
  81. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
  82. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +4 -4
  83. package/recipes/chatbot/recipe.json +3 -40
  84. package/recipes/chatbot-native@latest.zip +0 -0
  85. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +4 -1
  86. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
  87. package/recipes/chatbot-supabase/recipe.json +3 -42
  88. package/recipes/chatbot-supabase-native@latest.zip +0 -0
  89. package/recipes/chatbot-supabase@latest.zip +0 -0
  90. package/recipes/chatbot@latest.zip +0 -0
  91. package/recipes/glowing-button/recipe.json +6 -2
  92. package/recipes/glowing-button-native@latest.zip +0 -0
  93. package/recipes/glowing-button@latest.zip +0 -0
  94. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
  95. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
  96. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
  97. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/index.tsx +50 -0
  98. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
  99. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/results.tsx +2 -0
  100. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
  101. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +2 -2
  102. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/camera.tsx +72 -65
  103. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +65 -47
  104. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading-screen.tsx +43 -2
  105. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading.tsx +34 -1
  106. package/recipes/image-analysis/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +83 -2
  107. package/recipes/image-analysis/recipe.json +11 -19
  108. package/recipes/image-analysis-native@latest.zip +0 -0
  109. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
  110. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
  111. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
  112. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/index.tsx +50 -0
  113. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
  114. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/results.tsx +2 -0
  115. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
  116. package/recipes/image-analysis-supabase/recipe.json +10 -37
  117. package/recipes/image-analysis-supabase-native@latest.zip +0 -0
  118. package/recipes/image-analysis-supabase@latest.zip +0 -0
  119. package/recipes/image-analysis@latest.zip +0 -0
  120. package/recipes/image-analyzer/apps/native/src/app/(root)/(protected)/image-analyzer/index.tsx +2 -0
  121. package/recipes/image-generator/apps/native/src/app/image-generator/gallery.tsx +3 -0
  122. package/recipes/image-generator/apps/native/src/app/image-generator/index.tsx +3 -0
  123. package/recipes/image-generator/recipe.json +8 -18
  124. package/recipes/image-generator-native@latest.zip +0 -0
  125. package/recipes/image-generator-supabase/recipe.json +6 -35
  126. package/recipes/image-generator-supabase-native@latest.zip +0 -0
  127. package/recipes/image-generator-supabase@latest.zip +0 -0
  128. package/recipes/image-generator@latest.zip +0 -0
  129. package/recipes/ios-widget/recipe.json +18 -119
  130. package/recipes/ios-widget-native@latest.zip +0 -0
  131. package/recipes/ios-widget@latest.zip +0 -0
  132. package/recipes/number-stepper/apps/native/src/components/advanced-ui/stepper/demo.tsx +1 -1
  133. package/recipes/number-stepper/recipe.json +5 -2
  134. package/recipes/number-stepper-native@latest.zip +0 -0
  135. package/recipes/number-stepper@latest.zip +0 -0
  136. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +11 -18
  137. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +5 -7
  138. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +9 -7
  139. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +8 -7
  140. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +6 -5
  141. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +4 -3
  142. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +6 -5
  143. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +5 -7
  144. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +7 -6
  145. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +5 -7
  146. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +8 -7
  147. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +6 -5
  148. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +5 -6
  149. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +5 -4
  150. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +5 -7
  151. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +7 -6
  152. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +4 -3
  153. package/recipes/onboarding/recipe.json +9 -6
  154. package/recipes/onboarding-native@latest.zip +0 -0
  155. package/recipes/onboarding@latest.zip +0 -0
  156. package/recipes/payments/apps/native/src/app/paywall/index.tsx +74 -0
  157. package/recipes/payments/apps/native/src/app/paywall/local.tsx +25 -0
  158. package/recipes/payments/apps/native/src/app/paywall/remote.tsx +23 -0
  159. package/recipes/payments/packages/backend/convex/payments.ts +21 -3
  160. package/recipes/payments/recipe.json +14 -34
  161. package/recipes/payments-native@latest.zip +0 -0
  162. package/recipes/payments-supabase/apps/native/src/app/paywall/index.tsx +74 -0
  163. package/recipes/payments-supabase/apps/native/src/app/paywall/local.tsx +25 -0
  164. package/recipes/payments-supabase/apps/native/src/app/paywall/remote.tsx +23 -0
  165. package/recipes/payments-supabase/recipe.json +16 -23
  166. package/recipes/payments-supabase-native@latest.zip +0 -0
  167. package/recipes/payments-supabase@latest.zip +0 -0
  168. package/recipes/payments@latest.zip +0 -0
  169. package/recipes/posthog/apps/native/src/components/analytics/navigation-tracker.tsx +14 -0
  170. package/recipes/posthog/apps/native/src/lib/hooks/use-navigation-analytics.ts +44 -0
  171. package/recipes/posthog/apps/native/src/providers/posthog-provider.tsx +51 -0
  172. package/recipes/posthog/recipe.json +60 -0
  173. package/recipes/posthog-native@latest.zip +0 -0
  174. package/recipes/progress-circle/apps/native/src/components/advanced-ui/progress-bars/progress-circle-page.tsx +1 -1
  175. package/recipes/progress-circle/recipe.json +5 -2
  176. package/recipes/progress-circle-native@latest.zip +0 -0
  177. package/recipes/progress-circle@latest.zip +0 -0
  178. package/recipes/quiz/apps/native/src/app/quiz/index.tsx +47 -0
  179. package/recipes/quiz/recipe.json +9 -6
  180. package/recipes/quiz-native@latest.zip +0 -0
  181. package/recipes/quiz@latest.zip +0 -0
  182. package/recipes/screen-kits/apps/native/src/app/screen-kits/_layout.tsx +12 -0
  183. package/recipes/screen-kits/apps/native/src/app/screen-kits/index.tsx +114 -0
  184. package/recipes/screen-kits/apps/native/src/features/screen-kits/index.ts +1 -0
  185. package/recipes/screen-kits/apps/native/src/features/screen-kits/types.ts +28 -0
  186. package/recipes/screen-kits/recipe.json +26 -0
  187. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/_layout.tsx +12 -0
  188. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/home.tsx +5 -0
  189. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/index.tsx +5 -0
  190. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-complete.tsx +5 -0
  191. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-fail.tsx +5 -0
  192. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson.tsx +5 -0
  193. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/skill-tree.tsx +5 -0
  194. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/duo-button.tsx +174 -0
  195. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/skill-button.tsx +186 -0
  196. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/xp-header.tsx +115 -0
  197. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/constants.ts +89 -0
  198. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/index.ts +3 -0
  199. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/home-screen.tsx +225 -0
  200. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-complete-screen.tsx +485 -0
  201. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-fail-screen.tsx +105 -0
  202. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-screen.tsx +384 -0
  203. package/recipes/screen-kits-duolingo/recipe.json +58 -0
  204. package/recipes/screen-kits-duolingo-native@latest.zip +0 -0
  205. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/_layout.tsx +45 -0
  206. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/asset-detail.tsx +3 -0
  207. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/notifications.tsx +3 -0
  208. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/receive.tsx +3 -0
  209. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/send.tsx +3 -0
  210. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/swap.tsx +3 -0
  211. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/wallet.tsx +3 -0
  212. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/ActionButtons.tsx +78 -0
  213. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/AssetRow.tsx +94 -0
  214. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/BalanceCard.tsx +118 -0
  215. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/constants.ts +85 -0
  216. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/asset-detail.tsx +378 -0
  217. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/notifications.tsx +210 -0
  218. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/receive-modal.tsx +317 -0
  219. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/send-modal.tsx +420 -0
  220. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/swap-modal.tsx +363 -0
  221. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/wallet-dashboard.tsx +281 -0
  222. package/recipes/screen-kits-finance/recipe.json +46 -0
  223. package/recipes/screen-kits-finance-native@latest.zip +0 -0
  224. package/recipes/screen-kits-fitness/apps/native/assets/sounds/timer-beep.wav +0 -0
  225. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/_layout.tsx +10 -0
  226. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/index.tsx +6 -0
  227. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/timer.tsx +3 -0
  228. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/workout.tsx +3 -0
  229. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-components.tsx +500 -0
  230. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-settings-modal.tsx +352 -0
  231. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/workout-card.tsx +105 -0
  232. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/constants.ts +189 -0
  233. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/hooks/use-timer.ts +307 -0
  234. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/index.ts +1 -0
  235. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/timer-screen.tsx +278 -0
  236. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/workout-dashboard.tsx +350 -0
  237. package/recipes/screen-kits-fitness/recipe.json +63 -0
  238. package/recipes/screen-kits-fitness-native@latest.zip +0 -0
  239. package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/habits.tsx +1 -0
  240. package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/kanban.tsx +1 -0
  241. package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/routes.ts +4 -0
  242. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/AddTaskModal.tsx +246 -0
  243. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/DraggableTaskCard.tsx +92 -0
  244. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/KanbanColumn.tsx +238 -0
  245. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/TaskCard.tsx +144 -0
  246. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/add-habit-modal.tsx +271 -0
  247. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/constants.ts +295 -0
  248. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/kanban-utils.ts +62 -0
  249. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/habit-tracker.tsx +1160 -0
  250. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/kanban-board.tsx +432 -0
  251. package/recipes/screen-kits-habits/recipe.json +52 -0
  252. package/recipes/screen-kits-habits-native@latest.zip +0 -0
  253. package/recipes/screen-kits-native@latest.zip +0 -0
  254. package/recipes/sentry/apps/native/src/providers/sentry-provider.tsx +64 -0
  255. package/recipes/sentry/recipe.json +39 -0
  256. package/recipes/sentry-native@latest.zip +0 -0
  257. package/recipes/swipe-slider/apps/native/src/components/advanced-ui/sliders/swipe-slider-page.tsx +1 -1
  258. package/recipes/swipe-slider/recipe.json +5 -2
  259. package/recipes/swipe-slider-native@latest.zip +0 -0
  260. package/recipes/swipe-slider@latest.zip +0 -0
  261. package/recipes/timeline/apps/native/src/components/advanced-ui/timeline/demo.tsx +2 -1
  262. package/recipes/timeline/recipe.json +5 -2
  263. package/recipes/timeline-native@latest.zip +0 -0
  264. package/recipes/timeline@latest.zip +0 -0
  265. package/recipes/tracker-app/apps/native/src/app/tracker-app/index.tsx +1 -0
  266. package/recipes/tracker-app/recipe.json +10 -7
  267. package/recipes/tracker-app-native@latest.zip +0 -0
  268. package/recipes/tracker-app@latest.zip +0 -0
  269. package/recipes/upload-all.sh +8 -31
  270. package/recipes/voice-bot/apps/native/src/app/voice-bot/index.tsx +56 -0
  271. package/recipes/voice-bot/recipe.json +31 -7
  272. package/recipes/voice-bot-native@latest.zip +0 -0
  273. package/recipes/voice-bot@latest.zip +0 -0
  274. package/recipes/wake-word/apps/native/src/app/{(root)/(protected)/test-wake-word.tsx → test-wake-word.tsx} +43 -4
  275. package/recipes/wake-word/recipe.json +16 -26
  276. package/recipes/wake-word-native@latest.zip +0 -0
  277. package/recipes/wake-word@latest.zip +0 -0
  278. package/scripts/create-advanced-ui-recipes.sh +46 -19
  279. package/scripts/create-recipes.mjs +471 -117
  280. package/scripts/package-recipes.mjs +76 -0
  281. package/scripts/publish-all.sh +6 -2
  282. package/CHANGELOG.md +0 -198
  283. package/docs/archive/AUTO-DETECT-DEPS.md +0 -607
  284. package/docs/archive/FINAL-PACKAGE-STRATEGY.md +0 -583
  285. package/docs/archive/FINAL-SIMPLE-PLAN.md +0 -487
  286. package/docs/archive/FINAL-STATUS.md +0 -144
  287. package/docs/archive/FLOW-DIAGRAM.md +0 -1629
  288. package/docs/archive/GOTCHAS-AND-RISKS.md +0 -801
  289. package/docs/archive/IMPLEMENTATION-PLAN.md +0 -1360
  290. package/docs/archive/PLAN.md +0 -453
  291. package/docs/archive/PRODUCTION-READINESS.md +0 -684
  292. package/docs/archive/PRODUCTION-TEST-RESULTS.md +0 -465
  293. package/docs/archive/SIMPLIFIED-PLAN.md +0 -578
  294. package/docs/archive/STATUS.md +0 -199
  295. package/docs/archive/SUCCESS.md +0 -259
  296. package/docs/archive/TEST-SUMMARY.md +0 -261
  297. package/docs/archive/TESTING-CHECKLIST.md +0 -450
  298. package/docs/archive/USER-MODIFICATIONS.md +0 -448
  299. package/docs/decisions.md +0 -55
  300. package/docs/manual-testing.md +0 -91
  301. package/docs/next-steps.md +0 -12
  302. package/recipes/README.md +0 -156
  303. package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +0 -369
  304. package/recipes/chatbot/apps/native/src/api-client/chatbot.ts +0 -83
  305. package/recipes/chatbot/packages/backend/convex/agents.ts +0 -115
  306. package/recipes/chatbot/packages/backend/convex/tools/index.ts +0 -18
  307. package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +0 -97
  308. package/recipes/chatbot/packages/backend/convex/tools/tavilySearch.ts +0 -83
  309. package/recipes/chatbot/packages/backend/convex/tools/userProfile.ts +0 -72
  310. package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +0 -515
  311. package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +0 -243
  312. package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +0 -327
  313. package/recipes/image-analysis/apps/native/src/api-client/image-analyzer.ts +0 -62
  314. package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +0 -132
  315. package/recipes/image-generator/apps/native/src/api-client/image-generator.ts +0 -34
  316. package/recipes/payments/apps/native/src/api-client/payments.ts +0 -44
  317. package/recipes/payments-supabase/packages/backend/src/services/payments.ts +0 -201
  318. package/recipes/posthog.json +0 -47
  319. package/recipes/revenuecat.json +0 -43
  320. package/recipes/sentry.json +0 -47
  321. package/recipes/wake-word/apps/native/assets/vosk-model/README.md +0 -103
  322. package/recipes/wake-word/apps/native/scripts/download-vosk-model.mjs +0 -127
  323. /package/recipes/{audio-recorder/apps/native/src/app/(root)/(protected) → audio-recorder-supabase/apps/native/src/app}/audio-recorder/index.tsx +0 -0
  324. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/AppIntent.swift +0 -0
  325. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png +0 -0
  326. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png +0 -0
  327. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png +0 -0
  328. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png +0 -0
  329. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png +0 -0
  330. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png +0 -0
  331. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png +0 -0
  332. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png +0 -0
  333. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png +0 -0
  334. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png +0 -0
  335. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png +0 -0
  336. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png +0 -0
  337. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png +0 -0
  338. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png +0 -0
  339. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  340. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png +0 -0
  341. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/CalorieTrackerWidget.swift +0 -0
  342. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/HabitTrackerWidget.swift +0 -0
  343. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Info.plist +0 -0
  344. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/WidgetLiveActivity.swift +0 -0
  345. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/expo-target.config.js +0 -0
  346. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/generated.entitlements +0 -0
  347. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/index.swift +0 -0
  348. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/widgets.swift +0 -0
@@ -0,0 +1,432 @@
1
+ import { Ionicons } from '@expo/vector-icons';
2
+ import * as Haptics from 'expo-haptics';
3
+ import { Stack } from 'expo-router';
4
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
5
+ import type { LayoutRectangle, ViewStyle } from 'react-native';
6
+ import { ScrollView, View } from 'react-native';
7
+ import { useColorScheme } from 'react-native-css-interop';
8
+ import Animated, {
9
+ useAnimatedStyle,
10
+ useSharedValue,
11
+ withSpring,
12
+ } from 'react-native-reanimated';
13
+
14
+ import { FocusAwareStatusBar, Pressable, Text } from '@/components/ui';
15
+
16
+ import type { AddTaskModalRef } from '../components/AddTaskModal';
17
+ import { AddTaskModal } from '../components/AddTaskModal';
18
+ import type { DragSharedValues } from '../components/DraggableTaskCard';
19
+ import { KanbanColumn } from '../components/KanbanColumn';
20
+ import { TaskCard } from '../components/TaskCard';
21
+ import type { KanbanColumns, KanbanStatus, KanbanTask, Priority } from '../constants';
22
+ import {
23
+ KANBAN_COLUMNS,
24
+ MOCK_TASKS,
25
+ PRIORITY_CONFIG,
26
+ PRIORITY_LEVELS,
27
+ PRODUCTIVITY_COLORS,
28
+ } from '../constants';
29
+ import { buildKanbanColumns, moveKanbanTask } from '../kanban-utils';
30
+
31
+ type LayoutMap = Record<KanbanStatus, LayoutRectangle | null>;
32
+ type ScrollOffsetMap = Record<KanbanStatus, number>;
33
+ type DragCardSize = { width: number; height: number };
34
+ type FilterPriority = Priority | 'all';
35
+
36
+ const COLUMN_WIDTH = 288;
37
+ const COLUMN_GAP = 16;
38
+
39
+ export default function KanbanBoard(): React.ReactElement {
40
+ const { colorScheme } = useColorScheme();
41
+ const isDark = colorScheme === 'dark';
42
+ const colors = isDark ? PRODUCTIVITY_COLORS.dark : PRODUCTIVITY_COLORS.light;
43
+
44
+ const [columns, setColumns] = useState<KanbanColumns>(() =>
45
+ buildKanbanColumns(MOCK_TASKS),
46
+ );
47
+ const [columnTitles, setColumnTitles] = useState<Record<KanbanStatus, string>>({
48
+ todo: 'To Do',
49
+ doing: 'In Progress',
50
+ done: 'Done',
51
+ });
52
+ const [activeTask, setActiveTask] = useState<KanbanTask | null>(null);
53
+ const [dragCardSize, setDragCardSize] = useState<DragCardSize | null>(null);
54
+ const [priorityFilter, setPriorityFilter] = useState<FilterPriority>('all');
55
+
56
+ const addTaskModalRef = useRef<AddTaskModalRef>(null);
57
+ const columnLayouts = useRef<LayoutMap>({ todo: null, doing: null, done: null });
58
+ const listLayouts = useRef<LayoutMap>({ todo: null, doing: null, done: null });
59
+ const scrollOffsets = useRef<ScrollOffsetMap>({ todo: 0, doing: 0, done: 0 });
60
+ const cardLayouts = useRef<Record<string, LayoutRectangle>>({});
61
+
62
+ const dragX = useSharedValue(0);
63
+ const dragY = useSharedValue(0);
64
+ const dragOffsetX = useSharedValue(0);
65
+ const dragOffsetY = useSharedValue(0);
66
+ const dragOpacity = useSharedValue(0);
67
+ const dragScale = useSharedValue(1);
68
+ const dragRotation = useSharedValue(0);
69
+
70
+ const dragValues: DragSharedValues = useMemo(
71
+ () => ({ dragX, dragY, dragOffsetX, dragOffsetY }),
72
+ [dragOffsetX, dragOffsetY, dragX, dragY],
73
+ );
74
+
75
+ const isDragging = activeTask !== null;
76
+
77
+ // Filter tasks by priority
78
+ const filteredColumns = useMemo<KanbanColumns>(() => {
79
+ if (priorityFilter === 'all') return columns;
80
+ return {
81
+ todo: columns.todo.filter((t) => t.priority === priorityFilter),
82
+ doing: columns.doing.filter((t) => t.priority === priorityFilter),
83
+ done: columns.done.filter((t) => t.priority === priorityFilter),
84
+ };
85
+ }, [columns, priorityFilter]);
86
+
87
+ // Total task count for display
88
+ const totalTasks = useMemo(() => {
89
+ return columns.todo.length + columns.doing.length + columns.done.length;
90
+ }, [columns]);
91
+
92
+ const handleColumnLayout = useCallback(
93
+ (status: KanbanStatus, layout: LayoutRectangle) => {
94
+ columnLayouts.current[status] = layout;
95
+ },
96
+ [],
97
+ );
98
+
99
+ const handleListLayout = useCallback(
100
+ (status: KanbanStatus, layout: LayoutRectangle) => {
101
+ listLayouts.current[status] = layout;
102
+ },
103
+ [],
104
+ );
105
+
106
+ const handleTaskLayout = useCallback(
107
+ (taskId: string, layout: LayoutRectangle) => {
108
+ cardLayouts.current[taskId] = layout;
109
+ },
110
+ [],
111
+ );
112
+
113
+ const handleScrollOffset = useCallback(
114
+ (status: KanbanStatus, offsetY: number) => {
115
+ scrollOffsets.current[status] = offsetY;
116
+ },
117
+ [],
118
+ );
119
+
120
+ const getDropStatus = useCallback(
121
+ (absoluteX: number, absoluteY: number): KanbanStatus | null => {
122
+ const match = KANBAN_COLUMNS.find(({ status }) => {
123
+ const layout = columnLayouts.current[status];
124
+ if (!layout) return false;
125
+ return (
126
+ absoluteX >= layout.x &&
127
+ absoluteX <= layout.x + layout.width &&
128
+ absoluteY >= layout.y &&
129
+ absoluteY <= layout.y + layout.height
130
+ );
131
+ });
132
+ return match?.status ?? null;
133
+ },
134
+ [],
135
+ );
136
+
137
+ const getDropIndex = useCallback(
138
+ (status: KanbanStatus, taskId: string, absoluteY: number): number => {
139
+ const listLayout = listLayouts.current[status];
140
+ if (!listLayout) return columns[status].length;
141
+
142
+ const scrollOffset = scrollOffsets.current[status] ?? 0;
143
+ const cardTopY = absoluteY - dragOffsetY.value;
144
+ const relativeY = cardTopY - listLayout.y + scrollOffset;
145
+ const relativeCenterY = relativeY + (dragCardSize?.height ?? 0) / 2;
146
+ const targetTasks = columns[status].filter((task) => task.id !== taskId);
147
+
148
+ if (targetTasks.length === 0) return 0;
149
+
150
+ const targetIndex = targetTasks.findIndex((task) => {
151
+ const layout = cardLayouts.current[task.id];
152
+ if (!layout) return false;
153
+ const midpoint = layout.y + layout.height / 2;
154
+ return relativeCenterY < midpoint;
155
+ });
156
+
157
+ return targetIndex === -1 ? targetTasks.length : targetIndex;
158
+ },
159
+ [columns, dragCardSize?.height, dragOffsetY],
160
+ );
161
+
162
+ const handleDragStart = useCallback(
163
+ (task: KanbanTask, absoluteX: number, absoluteY: number) => {
164
+ const listLayout = listLayouts.current[task.status];
165
+ const cardLayout = cardLayouts.current[task.id];
166
+
167
+ if (!listLayout || !cardLayout) return;
168
+
169
+ // Haptic feedback on drag start
170
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
171
+
172
+ const scrollOffset = scrollOffsets.current[task.status] ?? 0;
173
+ const cardAbsoluteX = listLayout.x + cardLayout.x;
174
+ const cardAbsoluteY = listLayout.y + cardLayout.y - scrollOffset;
175
+
176
+ dragOffsetX.value = absoluteX - cardAbsoluteX;
177
+ dragOffsetY.value = absoluteY - cardAbsoluteY;
178
+ dragX.value = cardAbsoluteX;
179
+ dragY.value = cardAbsoluteY;
180
+ dragOpacity.value = 1;
181
+ dragScale.value = withSpring(1.05, { damping: 15, stiffness: 300 });
182
+ dragRotation.value = withSpring(2, { damping: 20, stiffness: 200 });
183
+
184
+ setDragCardSize({ width: cardLayout.width, height: cardLayout.height });
185
+ setActiveTask(task);
186
+ },
187
+ [dragOffsetX, dragOffsetY, dragOpacity, dragScale, dragX, dragY, dragRotation],
188
+ );
189
+
190
+ const handleDragEnd = useCallback(
191
+ (
192
+ task: KanbanTask,
193
+ absoluteX: number,
194
+ absoluteY: number,
195
+ success: boolean,
196
+ ) => {
197
+ if (success) {
198
+ const dropStatus = getDropStatus(absoluteX, absoluteY);
199
+ if (dropStatus) {
200
+ // Haptic feedback on successful drop
201
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
202
+ const dropIndex = getDropIndex(dropStatus, task.id, absoluteY);
203
+ setColumns((prev) => moveKanbanTask(prev, task.id, dropStatus, dropIndex));
204
+ }
205
+ }
206
+
207
+ dragOpacity.value = 0;
208
+ dragScale.value = withSpring(1, { damping: 18, stiffness: 220 });
209
+ dragRotation.value = withSpring(0, { damping: 20, stiffness: 200 });
210
+ setActiveTask(null);
211
+ setDragCardSize(null);
212
+ },
213
+ [getDropIndex, getDropStatus, dragOpacity, dragScale, dragRotation],
214
+ );
215
+
216
+ const handleAddTask = useCallback((status?: KanbanStatus) => {
217
+ addTaskModalRef.current?.open(status);
218
+ }, []);
219
+
220
+ const handleAddTaskSubmit = useCallback(
221
+ (task: Omit<KanbanTask, 'id'>) => {
222
+ const newTask: KanbanTask = {
223
+ ...task,
224
+ id: `t${Date.now()}`,
225
+ };
226
+ setColumns((prev) => ({
227
+ ...prev,
228
+ [task.status]: [...prev[task.status], newTask],
229
+ }));
230
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
231
+ },
232
+ [],
233
+ );
234
+
235
+ const handleTitleChange = useCallback((status: KanbanStatus, newTitle: string) => {
236
+ setColumnTitles((prev) => ({ ...prev, [status]: newTitle }));
237
+ }, []);
238
+
239
+ const dragOverlayStyle = useAnimatedStyle<ViewStyle>(() => {
240
+ return {
241
+ opacity: dragOpacity.value,
242
+ transform: [
243
+ { translateX: dragX.value },
244
+ { translateY: dragY.value },
245
+ { scale: dragScale.value },
246
+ { rotate: `${dragRotation.value}deg` },
247
+ ] as ViewStyle['transform'],
248
+ };
249
+ });
250
+
251
+ const renderFilterButton = (priority: FilterPriority) => {
252
+ const isActive = priorityFilter === priority;
253
+ const config = priority !== 'all' ? PRIORITY_CONFIG[priority] : null;
254
+ const bg = isActive
255
+ ? priority === 'all'
256
+ ? colors.accent
257
+ : isDark
258
+ ? config!.bgDark
259
+ : config!.bgLight
260
+ : 'transparent';
261
+ const textColor = isActive
262
+ ? priority === 'all'
263
+ ? '#fff'
264
+ : isDark
265
+ ? config!.textDark
266
+ : config!.textLight
267
+ : colors.textMuted;
268
+
269
+ return (
270
+ <Pressable
271
+ key={priority}
272
+ onPress={() => setPriorityFilter(priority)}
273
+ className="px-3 py-1.5 rounded-full flex-row items-center gap-1"
274
+ style={{
275
+ backgroundColor: bg,
276
+ borderWidth: 1,
277
+ borderColor: isActive ? textColor : colors.columnBorder,
278
+ }}
279
+ >
280
+ {priority === 'high' && (
281
+ <Ionicons name="arrow-up" size={12} color={textColor} />
282
+ )}
283
+ {priority === 'low' && (
284
+ <Ionicons name="arrow-down" size={12} color={textColor} />
285
+ )}
286
+ <Text className="text-xs font-semibold" style={{ color: textColor }}>
287
+ {priority === 'all' ? 'All' : config!.label}
288
+ </Text>
289
+ </Pressable>
290
+ );
291
+ };
292
+
293
+ return (
294
+ <View className="flex-1" style={{ backgroundColor: colors.background }}>
295
+ <FocusAwareStatusBar />
296
+ <Stack.Screen options={{ headerShown: false }} />
297
+
298
+ {/* Header */}
299
+ <View
300
+ className="px-6 pt-14 pb-4 border-b"
301
+ style={{ borderBottomColor: colors.columnBorder }}
302
+ >
303
+ <View className="flex-row justify-between items-center mb-4">
304
+ <View>
305
+ <Text
306
+ className="text-2xl font-black tracking-tight"
307
+ style={{ color: colors.text }}
308
+ >
309
+ Task Flow
310
+ </Text>
311
+ <Text className="font-medium" style={{ color: colors.textMuted }}>
312
+ {totalTasks} tasks • Mobile App Redesign
313
+ </Text>
314
+ </View>
315
+ <View className="flex-row -space-x-3">
316
+ {[1, 2, 3].map((i) => (
317
+ <View
318
+ key={i}
319
+ className="w-10 h-10 rounded-full items-center justify-center"
320
+ style={{
321
+ borderWidth: 2,
322
+ borderColor: colors.background,
323
+ backgroundColor: isDark ? '#374151' : '#e5e7eb',
324
+ }}
325
+ >
326
+ <Ionicons name="person" size={16} color={colors.textMuted} />
327
+ </View>
328
+ ))}
329
+ <View
330
+ className="w-10 h-10 rounded-full items-center justify-center"
331
+ style={{
332
+ borderWidth: 2,
333
+ borderColor: colors.background,
334
+ backgroundColor: colors.accent,
335
+ }}
336
+ >
337
+ <Text className="font-bold text-xs text-white">+2</Text>
338
+ </View>
339
+ </View>
340
+ </View>
341
+
342
+ {/* Filter Bar */}
343
+ <View className="flex-row items-center gap-2">
344
+ <Ionicons name="filter-outline" size={16} color={colors.textMuted} />
345
+ <ScrollView
346
+ horizontal
347
+ showsHorizontalScrollIndicator={false}
348
+ contentContainerStyle={{ gap: 8 }}
349
+ >
350
+ {renderFilterButton('all')}
351
+ {Object.values(PRIORITY_LEVELS).map((p) => renderFilterButton(p))}
352
+ </ScrollView>
353
+ </View>
354
+ </View>
355
+
356
+ {/* Board */}
357
+ <ScrollView
358
+ horizontal
359
+ pagingEnabled
360
+ snapToInterval={COLUMN_WIDTH + COLUMN_GAP}
361
+ decelerationRate="fast"
362
+ showsHorizontalScrollIndicator={false}
363
+ contentContainerStyle={{ paddingHorizontal: 16, paddingTop: 16, paddingBottom: 100 }}
364
+ className="flex-1"
365
+ scrollEnabled={!isDragging}
366
+ >
367
+ {KANBAN_COLUMNS.map((column) => (
368
+ <KanbanColumn
369
+ key={column.status}
370
+ title={columnTitles[column.status]}
371
+ status={column.status}
372
+ icon={column.icon}
373
+ tasks={filteredColumns[column.status]}
374
+ activeTaskId={activeTask?.id ?? null}
375
+ dragValues={dragValues}
376
+ isDragging={isDragging}
377
+ onDragStart={handleDragStart}
378
+ onDragEnd={handleDragEnd}
379
+ onColumnLayout={handleColumnLayout}
380
+ onListLayout={handleListLayout}
381
+ onTaskLayout={handleTaskLayout}
382
+ onScrollOffset={handleScrollOffset}
383
+ onAddTask={() => handleAddTask(column.status)}
384
+ onTitleChange={handleTitleChange}
385
+ />
386
+ ))}
387
+ </ScrollView>
388
+
389
+ {/* Drag Overlay */}
390
+ {activeTask ? (
391
+ <Animated.View
392
+ pointerEvents="none"
393
+ style={[
394
+ dragOverlayStyle,
395
+ {
396
+ position: 'absolute',
397
+ left: 0,
398
+ top: 0,
399
+ zIndex: 50,
400
+ elevation: 12,
401
+ width: dragCardSize?.width,
402
+ height: dragCardSize?.height,
403
+ },
404
+ ]}
405
+ >
406
+ <TaskCard task={activeTask} style={{ marginBottom: 0 }} isDragging />
407
+ </Animated.View>
408
+ ) : null}
409
+
410
+ {/* FAB */}
411
+ <Pressable
412
+ onPress={() => handleAddTask()}
413
+ className="absolute bottom-8 right-6 w-14 h-14 rounded-full items-center justify-center"
414
+ style={{
415
+ backgroundColor: colors.accent,
416
+ shadowColor: colors.accent,
417
+ shadowOffset: { width: 0, height: 4 },
418
+ shadowOpacity: 0.4,
419
+ shadowRadius: 12,
420
+ elevation: 8,
421
+ }}
422
+ accessibilityRole="button"
423
+ accessibilityLabel="Add task"
424
+ >
425
+ <Ionicons name="add" size={32} color="white" />
426
+ </Pressable>
427
+
428
+ {/* Add Task Modal */}
429
+ <AddTaskModal ref={addTaskModalRef} onAddTask={handleAddTaskSubmit} />
430
+ </View>
431
+ );
432
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "screen-kits-habits",
3
+ "version": "1.0.0",
4
+ "description": "Screen kit: Task Flow (productivity & habits)",
5
+ "copy": [
6
+ {
7
+ "from": "apps/native/src/app/screen-kits/productivity",
8
+ "to": "apps/native/src/app/(root)/(protected)/screen-kits/productivity"
9
+ },
10
+ {
11
+ "from": "apps/native/src/features/screen-kits/productivity",
12
+ "to": "apps/native/src/features/screen-kits/productivity"
13
+ }
14
+ ],
15
+ "screenKit": {
16
+ "id": "habits",
17
+ "title": "Task Flow",
18
+ "description": "Zen productivity suite",
19
+ "icon": "🧘",
20
+ "color": "#18181b",
21
+ "screens": [
22
+ {
23
+ "id": "kanban",
24
+ "name": "Kanban Board",
25
+ "description": "Drag & drop project management",
26
+ "route": "/screen-kits/productivity/kanban"
27
+ },
28
+ {
29
+ "id": "habits",
30
+ "name": "Habit Tracker",
31
+ "description": "Daily consistency grid",
32
+ "route": "/screen-kits/productivity/habits"
33
+ }
34
+ ]
35
+ },
36
+ "target": "native",
37
+ "dependencies": {
38
+ "expo": [
39
+ "@expo/vector-icons",
40
+ "@gorhom/bottom-sheet",
41
+ "expo-blur",
42
+ "expo-haptics",
43
+ "expo-linear-gradient",
44
+ "lottie-react-native",
45
+ "react-native-css-interop",
46
+ "react-native-gesture-handler",
47
+ "react-native-reanimated",
48
+ "react-native-safe-area-context",
49
+ "react-native-svg"
50
+ ]
51
+ }
52
+ }
@@ -0,0 +1,64 @@
1
+ import { Env } from '@env';
2
+ import * as Sentry from '@sentry/react-native';
3
+ import { type ReactNode, useEffect } from 'react';
4
+
5
+ // Initialize Sentry once at module level (only if DSN is provided)
6
+ if (Env.SENTRY_DSN) {
7
+ Sentry.init({
8
+ dsn: Env.SENTRY_DSN,
9
+ // Configure Session Replay
10
+ replaysSessionSampleRate: 1.0,
11
+ replaysOnErrorSampleRate: 1.0,
12
+ integrations: [
13
+ Sentry.mobileReplayIntegration(),
14
+ // Completely disable React Navigation integration for Expo Router compatibility
15
+ ],
16
+ // Disable automatic route change tracking for Expo Router compatibility
17
+ // enableAutoRouteTracking: false, // This option doesn't exist in current Sentry version
18
+
19
+ // Filter out getCurrentRoute errors
20
+ beforeSend(event) {
21
+ // Ignore getCurrentRoute errors from navigation integration
22
+ if (event.exception?.values?.[0]?.value?.includes('getCurrentRoute')) {
23
+ return null; // Don't send this error to Sentry
24
+ }
25
+ return event;
26
+ },
27
+
28
+ // uncomment the line below to enable Spotlight (https://spotlightjs.com)
29
+ // spotlight: __DEV__,
30
+ });
31
+ }
32
+
33
+ interface SentryProviderProps {
34
+ children: ReactNode;
35
+ }
36
+
37
+ /**
38
+ * Sentry provider that handles error tracking and performance monitoring
39
+ * Sentry.init() is called at module level to avoid re-initialization on Fast Refresh
40
+ */
41
+ export function SentryProvider({ children }: SentryProviderProps) {
42
+ useEffect(() => {
43
+ const originalError = console.error;
44
+ const patchedError = (...args: any[]) => {
45
+ const message = args[0];
46
+ if (
47
+ typeof message === 'string' &&
48
+ message.includes('getCurrentRoute error')
49
+ ) {
50
+ return;
51
+ }
52
+ originalError.apply(console, args);
53
+ };
54
+
55
+ console.error = patchedError;
56
+
57
+ return () => {
58
+ console.error = originalError;
59
+ };
60
+ }, []);
61
+
62
+ // Sentry init is handled at module level, so this component just passes through children
63
+ return <>{children}</>;
64
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "sentry",
3
+ "version": "1.0.0",
4
+ "description": "Error tracking with Sentry",
5
+ "copy": [
6
+ {
7
+ "from": "apps/native/src/providers/sentry-provider.tsx",
8
+ "to": "apps/native/src/providers/sentry-provider.tsx"
9
+ }
10
+ ],
11
+ "target": "native",
12
+ "dependencies": {
13
+ "expo": [
14
+ "@sentry/react-native"
15
+ ]
16
+ },
17
+ "configuration": {
18
+ "env": {
19
+ "client": {
20
+ "schema": [
21
+ " SENTRY_DSN: z.string().optional(),"
22
+ ],
23
+ "env": [
24
+ " SENTRY_DSN: process.env.SENTRY_DSN,"
25
+ ]
26
+ }
27
+ }
28
+ },
29
+ "manualSteps": [
30
+ {
31
+ "title": "Add Sentry DSN",
32
+ "description": "Add SENTRY_DSN to your .env files.",
33
+ "file": "apps/native/.env.local"
34
+ }
35
+ ],
36
+ "postInstall": {
37
+ "message": "✅ Sentry files added. Update env files and re-run the app."
38
+ }
39
+ }
Binary file
@@ -9,8 +9,8 @@ import {
9
9
  Text,
10
10
  View,
11
11
  } from 'react-native';
12
- import { SafeAreaView } from 'react-native-safe-area-context';
13
12
 
13
+ import { SafeAreaView } from '@/components/ui';
14
14
  import { useThemeConfig } from '@/lib/use-theme-config';
15
15
 
16
16
  import SwipeSlider from './swipe-slider';
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "swipe-slider",
3
3
  "version": "1.0.0",
4
- "description": "Swipeable slider component with gesture controls",
4
+ "description": "Advanced UI component: swipe-slider",
5
5
  "target": "native",
6
6
  "copy": [
7
7
  {
@@ -10,6 +10,9 @@
10
10
  }
11
11
  ],
12
12
  "dependencies": {
13
- "expo": ["react-native-reanimated", "react-native-gesture-handler"]
13
+ "expo": [
14
+ "react-native-reanimated",
15
+ "react-native-gesture-handler"
16
+ ]
14
17
  }
15
18
  }
Binary file
@@ -1,6 +1,7 @@
1
1
  import { MaterialIcons } from '@expo/vector-icons';
2
2
  import { ScrollView, StyleSheet, Text, View } from 'react-native';
3
- import { SafeAreaView } from 'react-native-safe-area-context';
3
+
4
+ import { SafeAreaView } from '@/components/ui';
4
5
 
5
6
  import { useThemeConfig } from '../../../lib/use-theme-config';
6
7
  import { Timeline } from './timeline-view';
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "timeline",
3
3
  "version": "1.0.0",
4
- "description": "Vertical timeline view component",
4
+ "description": "Advanced UI component: timeline",
5
5
  "target": "native",
6
6
  "copy": [
7
7
  {
@@ -10,6 +10,9 @@
10
10
  }
11
11
  ],
12
12
  "dependencies": {
13
- "expo": []
13
+ "expo": [
14
+ "react-native-reanimated",
15
+ "react-native-gesture-handler"
16
+ ]
14
17
  }
15
18
  }
Binary file
@@ -0,0 +1 @@
1
+ export { default } from '@/features/tracker-app/app';