vibefast-cli 0.1.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 (250) hide show
  1. package/FINAL-STATUS.md +144 -0
  2. package/HOW-IT-WORKS.md +559 -0
  3. package/PLAN.md +453 -0
  4. package/README.md +129 -0
  5. package/RECIPES-READY.md +172 -0
  6. package/STATUS.md +199 -0
  7. package/SUCCESS.md +259 -0
  8. package/TESTING-CHECKLIST.md +450 -0
  9. package/cloudflare-worker/.wrangler/state/v3/kv/64907821e2634080acce34618d2f3d4c/blobs/11f2769953c717e188062bc644da97c1fd1e4d6d0813a226ce7567dba759afab0000019a736fb8d4 +1 -0
  10. package/cloudflare-worker/.wrangler/state/v3/kv/miniflare-KVNamespaceObject/0b03767237c0408301af51ca35d4b09470cbc479c7e5f23cc9de774749d23c59.sqlite +0 -0
  11. package/cloudflare-worker/.wrangler/state/v3/kv/miniflare-KVNamespaceObject/0b03767237c0408301af51ca35d4b09470cbc479c7e5f23cc9de774749d23c59.sqlite-shm +0 -0
  12. package/cloudflare-worker/.wrangler/state/v3/kv/miniflare-KVNamespaceObject/0b03767237c0408301af51ca35d4b09470cbc479c7e5f23cc9de774749d23c59.sqlite-wal +0 -0
  13. package/cloudflare-worker/.wrangler/state/v3/r2/miniflare-R2BucketObject/d1cc388a1a0ef44dd5669fd1a165d168b61362136c8b5fa50aefd96c72688e54.sqlite +0 -0
  14. package/cloudflare-worker/.wrangler/state/v3/r2/miniflare-R2BucketObject/d1cc388a1a0ef44dd5669fd1a165d168b61362136c8b5fa50aefd96c72688e54.sqlite-shm +0 -0
  15. package/cloudflare-worker/.wrangler/state/v3/r2/miniflare-R2BucketObject/d1cc388a1a0ef44dd5669fd1a165d168b61362136c8b5fa50aefd96c72688e54.sqlite-wal +0 -0
  16. package/cloudflare-worker/.wrangler/state/v3/r2/vibefast-recipes/blobs/620e8cf7c35d9806da25dee237e1d7e8b2432bd98f755b60e2c7f08a48d2c7b90000019a73736484 +0 -0
  17. package/cloudflare-worker/MIGRATION.md +160 -0
  18. package/cloudflare-worker/QUICKSTART.md +200 -0
  19. package/cloudflare-worker/README.md +242 -0
  20. package/cloudflare-worker/generate-token.js +32 -0
  21. package/cloudflare-worker/mini-native@latest.zip +0 -0
  22. package/cloudflare-worker/setup.sh +143 -0
  23. package/cloudflare-worker/test-recipe/apps/native/src/app/mini/index.tsx +15 -0
  24. package/cloudflare-worker/test-recipe/recipe.json +16 -0
  25. package/cloudflare-worker/worker.js +308 -0
  26. package/cloudflare-worker/wrangler.toml +13 -0
  27. package/dist/commands/add.d.ts +3 -0
  28. package/dist/commands/add.d.ts.map +1 -0
  29. package/dist/commands/add.js +149 -0
  30. package/dist/commands/add.js.map +1 -0
  31. package/dist/commands/devices.d.ts +3 -0
  32. package/dist/commands/devices.d.ts.map +1 -0
  33. package/dist/commands/devices.js +35 -0
  34. package/dist/commands/devices.js.map +1 -0
  35. package/dist/commands/doctor.d.ts +3 -0
  36. package/dist/commands/doctor.d.ts.map +1 -0
  37. package/dist/commands/doctor.js +67 -0
  38. package/dist/commands/doctor.js.map +1 -0
  39. package/dist/commands/list.d.ts +3 -0
  40. package/dist/commands/list.d.ts.map +1 -0
  41. package/dist/commands/list.js +40 -0
  42. package/dist/commands/list.js.map +1 -0
  43. package/dist/commands/login.d.ts +3 -0
  44. package/dist/commands/login.d.ts.map +1 -0
  45. package/dist/commands/login.js +23 -0
  46. package/dist/commands/login.js.map +1 -0
  47. package/dist/commands/logout.d.ts +3 -0
  48. package/dist/commands/logout.d.ts.map +1 -0
  49. package/dist/commands/logout.js +16 -0
  50. package/dist/commands/logout.js.map +1 -0
  51. package/dist/commands/remove.d.ts +3 -0
  52. package/dist/commands/remove.d.ts.map +1 -0
  53. package/dist/commands/remove.js +67 -0
  54. package/dist/commands/remove.js.map +1 -0
  55. package/dist/core/__tests__/journal.test.d.ts +2 -0
  56. package/dist/core/__tests__/journal.test.d.ts.map +1 -0
  57. package/dist/core/__tests__/journal.test.js +101 -0
  58. package/dist/core/__tests__/journal.test.js.map +1 -0
  59. package/dist/core/__tests__/validate.test.d.ts +2 -0
  60. package/dist/core/__tests__/validate.test.d.ts.map +1 -0
  61. package/dist/core/__tests__/validate.test.js +53 -0
  62. package/dist/core/__tests__/validate.test.js.map +1 -0
  63. package/dist/core/archive.d.ts +2 -0
  64. package/dist/core/archive.d.ts.map +1 -0
  65. package/dist/core/archive.js +59 -0
  66. package/dist/core/archive.js.map +1 -0
  67. package/dist/core/auth.d.ts +15 -0
  68. package/dist/core/auth.d.ts.map +1 -0
  69. package/dist/core/auth.js +76 -0
  70. package/dist/core/auth.js.map +1 -0
  71. package/dist/core/codemod.d.ts +20 -0
  72. package/dist/core/codemod.d.ts.map +1 -0
  73. package/dist/core/codemod.js +150 -0
  74. package/dist/core/codemod.js.map +1 -0
  75. package/dist/core/fsx.d.ts +12 -0
  76. package/dist/core/fsx.d.ts.map +1 -0
  77. package/dist/core/fsx.js +70 -0
  78. package/dist/core/fsx.js.map +1 -0
  79. package/dist/core/http.d.ts +30 -0
  80. package/dist/core/http.d.ts.map +1 -0
  81. package/dist/core/http.js +95 -0
  82. package/dist/core/http.js.map +1 -0
  83. package/dist/core/journal.d.ts +18 -0
  84. package/dist/core/journal.d.ts.map +1 -0
  85. package/dist/core/journal.js +34 -0
  86. package/dist/core/journal.js.map +1 -0
  87. package/dist/core/log.d.ts +8 -0
  88. package/dist/core/log.d.ts.map +1 -0
  89. package/dist/core/log.js +9 -0
  90. package/dist/core/log.js.map +1 -0
  91. package/dist/core/pathGuard.d.ts +3 -0
  92. package/dist/core/pathGuard.d.ts.map +1 -0
  93. package/dist/core/pathGuard.js +18 -0
  94. package/dist/core/pathGuard.js.map +1 -0
  95. package/dist/core/paths.d.ts +11 -0
  96. package/dist/core/paths.d.ts.map +1 -0
  97. package/dist/core/paths.js +22 -0
  98. package/dist/core/paths.js.map +1 -0
  99. package/dist/core/validate.d.ts +8 -0
  100. package/dist/core/validate.d.ts.map +1 -0
  101. package/dist/core/validate.js +27 -0
  102. package/dist/core/validate.js.map +1 -0
  103. package/dist/index.d.ts +3 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +23 -0
  106. package/dist/index.js.map +1 -0
  107. package/docs/decisions.md +55 -0
  108. package/package.json +39 -0
  109. package/recipes/audio-recorder/apps/native/src/app/audio-recorder/index.tsx +5 -0
  110. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
  111. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
  112. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
  113. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/index.ts +4 -0
  114. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
  115. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
  116. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
  117. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
  118. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
  119. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
  120. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
  121. package/recipes/audio-recorder/recipe.json +22 -0
  122. package/recipes/audio-recorder@latest.zip +0 -0
  123. package/recipes/charts/apps/native/src/app/charts/index.tsx +3 -0
  124. package/recipes/charts/apps/native/src/features/charts/README.md +185 -0
  125. package/recipes/charts/apps/native/src/features/charts/app/preview.tsx +223 -0
  126. package/recipes/charts/apps/native/src/features/charts/components/area-chart.tsx +40 -0
  127. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +143 -0
  128. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +196 -0
  129. package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +65 -0
  130. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +143 -0
  131. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +246 -0
  132. package/recipes/charts/apps/native/src/features/charts/components/index.ts +10 -0
  133. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +308 -0
  134. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +180 -0
  135. package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +188 -0
  136. package/recipes/charts/apps/native/src/features/charts/components/stacked-area-chart.tsx +265 -0
  137. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +322 -0
  138. package/recipes/charts/apps/native/src/features/charts/data/mock-data.ts +183 -0
  139. package/recipes/charts/apps/native/src/features/charts/types/index.ts +66 -0
  140. package/recipes/charts/recipe.json +22 -0
  141. package/recipes/charts@latest.zip +0 -0
  142. package/recipes/chatbot/apps/native/src/app/chatbot/index.tsx +1 -0
  143. package/recipes/chatbot/apps/native/src/features/chatbot/app/index.tsx +302 -0
  144. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +59 -0
  145. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-input-bar.tsx +469 -0
  146. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +575 -0
  147. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +246 -0
  148. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +161 -0
  149. package/recipes/chatbot/apps/native/src/features/chatbot/components/image-preview-list.tsx +115 -0
  150. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +165 -0
  151. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/index.ts +10 -0
  152. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +129 -0
  153. package/recipes/chatbot/apps/native/src/features/chatbot/components/message-error-boundary.tsx +78 -0
  154. package/recipes/chatbot/apps/native/src/features/chatbot/components/message-list.tsx +173 -0
  155. package/recipes/chatbot/apps/native/src/features/chatbot/components/model-selector.tsx +283 -0
  156. package/recipes/chatbot/apps/native/src/features/chatbot/components/report-content-modal.tsx +188 -0
  157. package/recipes/chatbot/apps/native/src/features/chatbot/components/suggested-messages.tsx +67 -0
  158. package/recipes/chatbot/apps/native/src/features/chatbot/constants/models.ts +20 -0
  159. package/recipes/chatbot/apps/native/src/features/chatbot/constants/report-reasons.ts +9 -0
  160. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +143 -0
  161. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chat-config.ts +664 -0
  162. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +359 -0
  163. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +89 -0
  164. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-conversation.ts +79 -0
  165. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-image-picker.ts +122 -0
  166. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +161 -0
  167. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +207 -0
  168. package/recipes/chatbot/apps/native/src/features/chatbot/models/index.ts +86 -0
  169. package/recipes/chatbot/apps/native/src/features/chatbot/models/models.ts +162 -0
  170. package/recipes/chatbot/apps/native/src/features/chatbot/models/providers.ts +62 -0
  171. package/recipes/chatbot/apps/native/src/features/chatbot/models/types.ts +40 -0
  172. package/recipes/chatbot/apps/native/src/features/chatbot/services/file-uploader.ts +238 -0
  173. package/recipes/chatbot/apps/native/src/features/chatbot/services/message-handler-service.ts +180 -0
  174. package/recipes/chatbot/apps/native/src/features/chatbot/types/index.ts +60 -0
  175. package/recipes/chatbot/apps/native/src/features/chatbot/utils/chat-telemetry.ts +91 -0
  176. package/recipes/chatbot/recipe.json +22 -0
  177. package/recipes/chatbot@latest.zip +0 -0
  178. package/recipes/image-generator/apps/native/src/app/image-generator/gallery.tsx +3 -0
  179. package/recipes/image-generator/apps/native/src/app/image-generator/index.tsx +3 -0
  180. package/recipes/image-generator/apps/native/src/features/image-generator/app/_layout.tsx +25 -0
  181. package/recipes/image-generator/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
  182. package/recipes/image-generator/apps/native/src/features/image-generator/app/index.tsx +237 -0
  183. package/recipes/image-generator/apps/native/src/features/image-generator/components/gallery-image.tsx +26 -0
  184. package/recipes/image-generator/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
  185. package/recipes/image-generator/apps/native/src/features/image-generator/components/image-model-selector.tsx +210 -0
  186. package/recipes/image-generator/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
  187. package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
  188. package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
  189. package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator.ts +93 -0
  190. package/recipes/image-generator/apps/native/src/features/image-generator/models/models.ts +66 -0
  191. package/recipes/image-generator/apps/native/src/features/image-generator/services/image-gallery-service.ts +98 -0
  192. package/recipes/image-generator/apps/native/src/features/image-generator/services/image-save-service.ts +121 -0
  193. package/recipes/image-generator/recipe.json +22 -0
  194. package/recipes/image-generator@latest.zip +0 -0
  195. package/recipes/quiz/apps/native/src/app/quiz/index.tsx +47 -0
  196. package/recipes/quiz/apps/native/src/features/quiz/components/question.tsx +67 -0
  197. package/recipes/quiz/apps/native/src/features/quiz/config.ts +11 -0
  198. package/recipes/quiz/apps/native/src/features/quiz/index.tsx +133 -0
  199. package/recipes/quiz/recipe.json +22 -0
  200. package/recipes/quiz@latest.zip +0 -0
  201. package/recipes/tracker-app/apps/native/src/app/tracker-app/index.tsx +1 -0
  202. package/recipes/tracker-app/apps/native/src/features/tracker-app/app/index.tsx +108 -0
  203. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/animated-number.tsx +102 -0
  204. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/calorie-card.tsx +66 -0
  205. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/circular-progress.tsx +97 -0
  206. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/floating-add-button.tsx +27 -0
  207. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/macro-card.tsx +80 -0
  208. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/promo-banner.tsx +98 -0
  209. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/recently-logged.tsx +64 -0
  210. package/recipes/tracker-app/apps/native/src/features/tracker-app/components/week-calendar.tsx +68 -0
  211. package/recipes/tracker-app/recipe.json +22 -0
  212. package/recipes/tracker-app@latest.zip +0 -0
  213. package/recipes/upload-all.sh +32 -0
  214. package/recipes/voice-bot/apps/native/src/app/voice-bot/index.tsx +27 -0
  215. package/recipes/voice-bot/apps/native/src/features/voice-bot/README.md +185 -0
  216. package/recipes/voice-bot/apps/native/src/features/voice-bot/components/conversation-status.tsx +76 -0
  217. package/recipes/voice-bot/apps/native/src/features/voice-bot/components/index.ts +4 -0
  218. package/recipes/voice-bot/apps/native/src/features/voice-bot/components/message-input.tsx +98 -0
  219. package/recipes/voice-bot/apps/native/src/features/voice-bot/components/voice-bot-screen.tsx +173 -0
  220. package/recipes/voice-bot/apps/native/src/features/voice-bot/components/voice-controls.tsx +73 -0
  221. package/recipes/voice-bot/apps/native/src/features/voice-bot/index.ts +3 -0
  222. package/recipes/voice-bot/apps/native/src/features/voice-bot/services/index.ts +1 -0
  223. package/recipes/voice-bot/apps/native/src/features/voice-bot/services/use-voice-bot.ts +161 -0
  224. package/recipes/voice-bot/apps/native/src/features/voice-bot/types.ts +29 -0
  225. package/recipes/voice-bot/recipe.json +22 -0
  226. package/recipes/voice-bot@latest.zip +0 -0
  227. package/scripts/create-recipes.mjs +189 -0
  228. package/src/commands/add.ts +183 -0
  229. package/src/commands/devices.ts +38 -0
  230. package/src/commands/doctor.ts +67 -0
  231. package/src/commands/list.ts +45 -0
  232. package/src/commands/login.ts +24 -0
  233. package/src/commands/logout.ts +15 -0
  234. package/src/commands/remove.ts +78 -0
  235. package/src/core/__tests__/journal.test.ts +119 -0
  236. package/src/core/__tests__/validate.test.ts +64 -0
  237. package/src/core/archive.ts +69 -0
  238. package/src/core/auth.ts +103 -0
  239. package/src/core/codemod.ts +211 -0
  240. package/src/core/fsx.ts +80 -0
  241. package/src/core/http.ts +136 -0
  242. package/src/core/journal.ts +64 -0
  243. package/src/core/log.ts +9 -0
  244. package/src/core/pathGuard.ts +22 -0
  245. package/src/core/paths.ts +33 -0
  246. package/src/core/validate.ts +44 -0
  247. package/src/index.ts +27 -0
  248. package/test-critical-cases.mjs +258 -0
  249. package/tsconfig.json +21 -0
  250. package/vitest.config.mts +12 -0
@@ -0,0 +1,89 @@
1
+ import { Alert, View } from 'react-native';
2
+
3
+ import { Button, Icon, List, Text } from '@/components/ui';
4
+
5
+ import { AudioPlayer } from './audio-player';
6
+
7
+ export interface Recording {
8
+ uri: string;
9
+ name: string;
10
+ date: string;
11
+ }
12
+
13
+ export interface RecordingListProps {
14
+ recordings: Recording[];
15
+ onDeleteRecording: (uri: string) => void;
16
+ }
17
+
18
+ export function RecordingList({
19
+ recordings,
20
+ onDeleteRecording,
21
+ }: RecordingListProps) {
22
+ const handleDelete = (uri: string) => {
23
+ Alert.alert(
24
+ 'Delete Recording',
25
+ 'Are you sure you want to delete this recording?',
26
+ [
27
+ { text: 'Cancel', style: 'cancel' },
28
+ {
29
+ text: 'Delete',
30
+ style: 'destructive',
31
+ onPress: () => onDeleteRecording(uri),
32
+ },
33
+ ],
34
+ );
35
+ };
36
+
37
+ const renderItem = ({ item }: { item: Recording }) => (
38
+ <View className="my-1 rounded-lg border border-neutral-300 p-3 dark:border-neutral-800">
39
+ <View className="mb-2 flex-row items-center justify-between">
40
+ <View className="flex-1">
41
+ <Text className="pr-2 text-base font-semibold">{item.name}</Text>
42
+ <Text className="text-xs text-muted">{item.date}</Text>
43
+ </View>
44
+ <Button
45
+ variant="ghost"
46
+ size="icon"
47
+ onPress={() => handleDelete(item.uri)}
48
+ className="size-8"
49
+ >
50
+ <Icon name="trash" size={18} />
51
+ </Button>
52
+ </View>
53
+ <AudioPlayer
54
+ source={{ uri: item.uri }}
55
+ shrinked={true}
56
+ showWaveform={true}
57
+ showTimer={true}
58
+ showProgressBar={false}
59
+ showControls={true}
60
+ style={{ className: 'm-0 p-0 bg-transparent' }}
61
+ // Only shrink waveform, keep normal button sizes
62
+ waveformHeight={50}
63
+ waveformBarCount={45}
64
+ waveformBarWidth={2.5}
65
+ waveformBarGap={1}
66
+ controlButtonSize={20}
67
+ playButtonSize={24}
68
+ />
69
+ </View>
70
+ );
71
+
72
+ return (
73
+ <View className="flex-1">
74
+ <List
75
+ data={recordings}
76
+ renderItem={renderItem}
77
+ keyExtractor={(item) => item.uri}
78
+ ListEmptyComponent={
79
+ <View className="items-center p-4">
80
+ <Text>No recordings saved.</Text>
81
+ </View>
82
+ }
83
+ contentContainerStyle={{ paddingHorizontal: 8, flexGrow: 1 }}
84
+ showsVerticalScrollIndicator={false}
85
+ nestedScrollEnabled={true}
86
+ />
87
+ </View>
88
+ );
89
+ }
@@ -0,0 +1,66 @@
1
+ import React, { useState } from 'react';
2
+ import { Switch, View } from 'react-native';
3
+
4
+ import { Text } from '@/components/ui';
5
+
6
+ import { AudioPlayer } from '../components';
7
+
8
+ export function AudioPlayerDemo() {
9
+ const [showControls, setShowControls] = useState(true);
10
+ const [showWaveform, setShowWaveform] = useState(true);
11
+ const [showTimer, setShowTimer] = useState(true);
12
+ const [showProgressBar, setShowProgressBar] = useState(true);
13
+
14
+ const remoteAudioSource = {
15
+ uri: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',
16
+ };
17
+
18
+ const renderToggle = (
19
+ label: string,
20
+ value: boolean,
21
+ onValueChange: (value: boolean) => void,
22
+ ) => (
23
+ <View
24
+ style={{
25
+ flexDirection: 'row',
26
+ alignItems: 'center',
27
+ justifyContent: 'space-between',
28
+ paddingVertical: 8,
29
+ }}
30
+ >
31
+ <Text>{label}</Text>
32
+ <Switch value={value} onValueChange={onValueChange} />
33
+ </View>
34
+ );
35
+
36
+ return (
37
+ <View style={{ width: '100%', gap: 16 }}>
38
+ <Text className="text-center text-lg font-bold">Audio Player Demo</Text>
39
+ <AudioPlayer
40
+ source={remoteAudioSource}
41
+ showControls={showControls}
42
+ showWaveform={showWaveform}
43
+ showTimer={showTimer}
44
+ showProgressBar={showProgressBar}
45
+ autoPlay={false}
46
+ onPlaybackStatusUpdate={(status) =>
47
+ console.log('Playback status:', status)
48
+ }
49
+ />
50
+ <View
51
+ style={{
52
+ padding: 16,
53
+ marginTop: 16,
54
+ backgroundColor: '#f0f0f0',
55
+ borderRadius: 8,
56
+ }}
57
+ >
58
+ <Text className="text-md mb-2 font-bold">Player Options</Text>
59
+ {renderToggle('Show Controls', showControls, setShowControls)}
60
+ {renderToggle('Show Waveform', showWaveform, setShowWaveform)}
61
+ {renderToggle('Show Timer', showTimer, setShowTimer)}
62
+ {renderToggle('Show Progress Bar', showProgressBar, setShowProgressBar)}
63
+ </View>
64
+ </View>
65
+ );
66
+ }
@@ -0,0 +1,68 @@
1
+ import React, { useState } from 'react';
2
+ import { ActivityIndicator, View } from 'react-native';
3
+
4
+ import { Text } from '@/components/ui';
5
+
6
+ import { AudioRecorder } from '../components/audio-recorder';
7
+
8
+ export function AudioRecorderCloud() {
9
+ const [uploading, setUploading] = useState(false);
10
+ const [uploadProgress, setUploadProgress] = useState(0);
11
+
12
+ const simulateCloudUpload = async (uri: string): Promise<string> => {
13
+ return new Promise((resolve) => {
14
+ setUploading(true);
15
+ setUploadProgress(0);
16
+
17
+ const interval = setInterval(() => {
18
+ setUploadProgress((prev) => {
19
+ if (prev >= 100) {
20
+ clearInterval(interval);
21
+ setUploading(false);
22
+ resolve(
23
+ `https://cloud-storage.example.com/audio/${Date.now()}.m4a`,
24
+ );
25
+ return 100;
26
+ }
27
+ return prev + 10;
28
+ });
29
+ }, 200);
30
+ });
31
+ };
32
+
33
+ const handleRecordingComplete = async (uri: string) => {
34
+ try {
35
+ const cloudUrl = await simulateCloudUpload(uri);
36
+
37
+ console.log(`Recording uploaded to cloud storage!\n\nURL: ${cloudUrl}`);
38
+
39
+ setUploadProgress(0);
40
+ } catch (error) {
41
+ console.log('Failed to upload recording to cloud storage:', error);
42
+
43
+ setUploading(false);
44
+ setUploadProgress(0);
45
+ }
46
+ };
47
+
48
+ return (
49
+ <View style={{ width: '100%' }}>
50
+ <AudioRecorder
51
+ quality="high"
52
+ showWaveform={true}
53
+ showTimer={true}
54
+ maxDuration={600} // 10 minutes
55
+ onRecordingComplete={handleRecordingComplete}
56
+ />
57
+
58
+ {uploading && (
59
+ <View style={{ marginTop: 16, alignItems: 'center' }}>
60
+ <ActivityIndicator size="small" />
61
+ <Text className="text-sm" style={{ marginTop: 8 }}>
62
+ Uploading... {uploadProgress}%
63
+ </Text>
64
+ </View>
65
+ )}
66
+ </View>
67
+ );
68
+ }
@@ -0,0 +1,102 @@
1
+ import { RecordingPresets } from 'expo-audio';
2
+ import React, { useState } from 'react';
3
+ import { Alert, StyleSheet, View } from 'react-native';
4
+
5
+ import { Text } from '@/components/ui';
6
+
7
+ import { AudioRecorder } from '../components/audio-recorder';
8
+
9
+ export function AudioRecorderInterview() {
10
+ const [interviewTitle, setInterviewTitle] = useState('');
11
+ const [isRecording, setIsRecording] = useState(false);
12
+
13
+ const handleRecordingStart = () => {
14
+ setIsRecording(true);
15
+ const title = `Interview ${new Date().toLocaleDateString()}`;
16
+ setInterviewTitle(title);
17
+ };
18
+
19
+ const handleRecordingStop = () => {
20
+ setIsRecording(false);
21
+ };
22
+
23
+ const handleRecordingComplete = (uri: string) => {
24
+ Alert.alert(
25
+ '🎤 Interview Complete',
26
+ `"${interviewTitle}" has been recorded and saved.\n\nDuration: Available in file metadata\nQuality: High (48kHz, Stereo)`,
27
+ [{ text: 'Save & Exit' }],
28
+ );
29
+ };
30
+
31
+ return (
32
+ <View style={{ width: '100%' }}>
33
+ <View style={styles.interviewHeader}>
34
+ <Text
35
+ className="mt-4 text-xl font-medium"
36
+ style={styles.interviewTitle}
37
+ >
38
+ {interviewTitle || 'Ready for Interview'}
39
+ </Text>
40
+
41
+ <View
42
+ style={[styles.statusBadge, isRecording && styles.recordingBadge]}
43
+ >
44
+ <Text
45
+ style={[styles.statusText, isRecording && styles.recordingText]}
46
+ >
47
+ {isRecording ? '🔴 LIVE' : '⏸️ READY'}
48
+ </Text>
49
+ </View>
50
+ </View>
51
+
52
+ <AudioRecorder
53
+ quality="high"
54
+ showWaveform={true}
55
+ showTimer={true}
56
+ maxDuration={7200} // 2 hours for long interviews
57
+ customRecordingOptions={{
58
+ ...RecordingPresets.HIGH_QUALITY,
59
+ sampleRate: 48000,
60
+ bitRate: 128000,
61
+ numberOfChannels: 2,
62
+ isMeteringEnabled: true,
63
+ }}
64
+ onRecordingStart={handleRecordingStart}
65
+ onRecordingStop={handleRecordingStop}
66
+ onRecordingComplete={handleRecordingComplete}
67
+ />
68
+
69
+ <Text className="text-sm" style={{ marginTop: 12, textAlign: 'center' }}>
70
+ Maximum duration: 2 hours • High quality stereo recording
71
+ </Text>
72
+ </View>
73
+ );
74
+ }
75
+
76
+ const styles = StyleSheet.create({
77
+ interviewHeader: {
78
+ marginBottom: 16,
79
+ alignItems: 'center',
80
+ },
81
+ interviewTitle: {
82
+ marginBottom: 8,
83
+ textAlign: 'center',
84
+ },
85
+ statusBadge: {
86
+ paddingHorizontal: 12,
87
+ paddingVertical: 4,
88
+ borderRadius: 12,
89
+ backgroundColor: '#f3f4f6',
90
+ },
91
+ recordingBadge: {
92
+ backgroundColor: '#fef2f2',
93
+ },
94
+ statusText: {
95
+ fontSize: 12,
96
+ fontWeight: '600',
97
+ color: '#6b7280',
98
+ },
99
+ recordingText: {
100
+ color: '#dc2626',
101
+ },
102
+ });
@@ -0,0 +1,27 @@
1
+ import { AudioRecorder } from '../components/audio-recorder';
2
+
3
+ export function AudioRecorderDemo() {
4
+ const handleRecordingComplete = (uri: string) => {
5
+ console.log('Recording saved to:', uri);
6
+ };
7
+
8
+ const handleRecordingStart = () => {
9
+ console.log('Recording started');
10
+ };
11
+
12
+ const handleRecordingStop = () => {
13
+ console.log('Recording stopped');
14
+ };
15
+
16
+ return (
17
+ <AudioRecorder
18
+ quality="high"
19
+ showWaveform={true}
20
+ showTimer={true}
21
+ maxDuration={300} // 5 minutes
22
+ onRecordingComplete={handleRecordingComplete}
23
+ onRecordingStart={handleRecordingStart}
24
+ onRecordingStop={handleRecordingStop}
25
+ />
26
+ );
27
+ }
@@ -0,0 +1,5 @@
1
+ export * from './audio-player-demo';
2
+ export * from './audio-recorder-cloud';
3
+ export * from './audio-recorder-interview';
4
+ export * from './basic';
5
+ export * from './with-recording-list-demo';
@@ -0,0 +1,82 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { ActivityIndicator, View } from 'react-native';
3
+ import { MMKV } from 'react-native-mmkv';
4
+
5
+ import { AudioRecorder, type Recording, RecordingList } from '../components';
6
+
7
+ const RECORDINGS_STORAGE_KEY = 'audio_recordings';
8
+ const storage = new MMKV();
9
+
10
+ export function RecordingListDemo() {
11
+ const [recordings, setRecordings] = useState<Recording[]>([]);
12
+ const [isLoading, setIsLoading] = useState(true);
13
+
14
+ // Load recordings from storage on component mount
15
+ useEffect(() => {
16
+ loadRecordings();
17
+ }, []);
18
+
19
+ const loadRecordings = () => {
20
+ try {
21
+ const storedRecordings = storage.getString(RECORDINGS_STORAGE_KEY);
22
+ if (storedRecordings) {
23
+ const parsedRecordings = JSON.parse(storedRecordings);
24
+ setRecordings(parsedRecordings);
25
+ }
26
+ } catch (error) {
27
+ console.error('Failed to load recordings:', error);
28
+ } finally {
29
+ setIsLoading(false);
30
+ }
31
+ };
32
+
33
+ const saveRecordings = (newRecordings: Recording[]) => {
34
+ try {
35
+ storage.set(RECORDINGS_STORAGE_KEY, JSON.stringify(newRecordings));
36
+ } catch (error) {
37
+ console.error('Failed to save recordings:', error);
38
+ }
39
+ };
40
+
41
+ const handleRecordingComplete = (uri: string) => {
42
+ const newRecording: Recording = {
43
+ uri,
44
+ name: `Recording ${recordings.length + 1}`,
45
+ date: new Date().toLocaleString(),
46
+ };
47
+ const updatedRecordings = [...recordings, newRecording];
48
+ setRecordings(updatedRecordings);
49
+ saveRecordings(updatedRecordings);
50
+ };
51
+
52
+ const handleDeleteRecording = (uri: string) => {
53
+ const updatedRecordings = recordings.filter((rec) => rec.uri !== uri);
54
+ setRecordings(updatedRecordings);
55
+ saveRecordings(updatedRecordings);
56
+ };
57
+
58
+ if (isLoading) {
59
+ return (
60
+ <View
61
+ style={{
62
+ flex: 1,
63
+ width: '100%',
64
+ justifyContent: 'center',
65
+ alignItems: 'center',
66
+ }}
67
+ >
68
+ <ActivityIndicator size="large" />
69
+ </View>
70
+ );
71
+ }
72
+
73
+ return (
74
+ <View style={{ flex: 1, width: '100%', gap: 16 }}>
75
+ <AudioRecorder onRecordingComplete={handleRecordingComplete} />
76
+ <RecordingList
77
+ recordings={recordings}
78
+ onDeleteRecording={handleDeleteRecording}
79
+ />
80
+ </View>
81
+ );
82
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "audio-recorder",
3
+ "version": "1.0.0",
4
+ "description": "Record and manage voice notes",
5
+ "copy": [
6
+ {
7
+ "from": "apps/native/src/app/audio-recorder",
8
+ "to": "apps/native/src/app/(root)/(protected)/audio-recorder"
9
+ },
10
+ {
11
+ "from": "apps/native/src/features/audio-recorder",
12
+ "to": "apps/native/src/features/audio-recorder"
13
+ }
14
+ ],
15
+ "nav": {
16
+ "href": "/(root)/(protected)/audio-recorder",
17
+ "label": "Voice Notes",
18
+ "icon": "🎤",
19
+ "color": "#EF4444"
20
+ },
21
+ "target": "native"
22
+ }
@@ -0,0 +1,3 @@
1
+ import ChartPreviewScreen from '@/features/charts/app/preview';
2
+
3
+ export default ChartPreviewScreen;
@@ -0,0 +1,185 @@
1
+ # Chart Components
2
+
3
+ A collection of beautiful, animated chart components built with React Native SVG, d3-shape, and React Native Reanimated.
4
+
5
+ ## 🚀 Features
6
+
7
+ - **Fully Animated**: Smooth entrance animations with staggered effects
8
+ - **Theme-Aware**: Automatically adapts to light/dark themes using `useThemeConfig`
9
+ - **Responsive**: Horizontal scrolling support for charts that exceed screen width
10
+ - **Accessible**: Proper contrast ratios and accessibility labels
11
+ - **TypeScript**: Fully typed with comprehensive prop interfaces
12
+ - **Customizable**: Extensive styling and behavior options
13
+
14
+ ## 📊 Available Charts
15
+
16
+ ### BarChart
17
+
18
+ Animated bar charts with horizontal scrolling support.
19
+
20
+ **Features:**
21
+
22
+ - Staggered bar growth animations
23
+ - Grid lines with proper contrast
24
+ - Value labels above bars
25
+ - Category labels below bars
26
+ - Horizontal scrolling for wide datasets
27
+ - Haptic feedback on press
28
+
29
+ **Props:**
30
+
31
+ - `data`: Array of chart data objects with `id`, `label`, `value`, and optional `color`
32
+ - `height`: Chart height (default: 250)
33
+ - `showValues`: Display values above bars (default: true)
34
+ - `showLabels`: Display labels below bars (default: true)
35
+ - `showGrid`: Show grid lines (default: true)
36
+ - `valueFormatter`: Function to format displayed values
37
+ - `barRadius`: Border radius of bars (default: 8)
38
+ - `gap`: Space between bars (default: 12)
39
+
40
+ ### LineChart
41
+
42
+ Smooth animated line charts with area fills and data points.
43
+
44
+ **Features:**
45
+
46
+ - Animated path drawing with stroke-dash effects
47
+ - Curved or linear line styles
48
+ - Optional area fills
49
+ - Animated data points
50
+ - Grid overlay support
51
+
52
+ **Props:**
53
+
54
+ - `data`: Array of numeric values
55
+ - `labels`: Array of string labels for x-axis
56
+ - `height`: Chart height (default: 200)
57
+ - `curved`: Use curved lines (default: true)
58
+ - `showArea`: Show area fill (default: true)
59
+ - `showDots`: Show data points (default: true)
60
+ - `valueFormatter`: Function to format displayed values
61
+
62
+ ### PieChart
63
+
64
+ Animated pie charts with detailed legends.
65
+
66
+ **Features:**
67
+
68
+ - Slice-by-slice animation with staggered timing
69
+ - Interactive legend with slide-in effects
70
+ - Support for custom colors
71
+ - Touch interactions with haptic feedback
72
+
73
+ **Props:**
74
+
75
+ - `data`: Array of chart data objects
76
+ - `height`: Chart height (default: 300)
77
+ - `radius`: Chart radius (auto-calculated if not provided)
78
+ - `showLegend`: Display legend (default: true)
79
+ - `valueFormatter`: Function to format displayed values
80
+
81
+ ### DonutChart
82
+
83
+ Specialized donut charts with center labels.
84
+
85
+ **Features:**
86
+
87
+ - All PieChart features
88
+ - Customizable inner radius ratio
89
+ - Center total display for donut charts
90
+ - Enhanced visual hierarchy
91
+
92
+ **Props:**
93
+
94
+ - All PieChart props except `innerRadius`
95
+ - `innerRadiusRatio`: Inner radius as percentage of outer radius (default: 0.6)
96
+
97
+ ## 🎨 Theme Integration
98
+
99
+ All charts use the `useThemeConfig` hook for consistent theming:
100
+
101
+ ```typescript
102
+ // Text colors
103
+ theme.colors.foreground; // Primary text
104
+ theme.colors.mutedForeground; // Secondary text
105
+
106
+ // Background colors
107
+ theme.colors.background; // Chart background
108
+ theme.colors.card; // Card backgrounds
109
+ theme.colors.muted; // Legend item backgrounds
110
+
111
+ // Border colors
112
+ theme.colors.outline; // Grid lines and borders
113
+ ```
114
+
115
+ ## 🔧 Usage Examples
116
+
117
+ ### Bar Chart with Horizontal Scrolling
118
+
119
+ ```tsx
120
+ <BarChart
121
+ data={salesData}
122
+ height={350}
123
+ showValues={true}
124
+ showGrid={true}
125
+ showLabels={true}
126
+ valueFormatter={(value) => `$${value.toLocaleString()}`}
127
+ />
128
+ ```
129
+
130
+ ### Animated Line Chart
131
+
132
+ ```tsx
133
+ <LineChart
134
+ data={monthlyActiveUsers}
135
+ labels={monthLabels}
136
+ height={250}
137
+ curved={true}
138
+ showArea={true}
139
+ showDots={true}
140
+ valueFormatter={(value) => value.toLocaleString()}
141
+ />
142
+ ```
143
+
144
+ ### Donut Chart with Custom Styling
145
+
146
+ ```tsx
147
+ <DonutChart
148
+ data={expensesData}
149
+ height={450}
150
+ radius={130}
151
+ innerRadiusRatio={0.65}
152
+ showLegend={true}
153
+ valueFormatter={(value) => `$${value}k`}
154
+ />
155
+ ```
156
+
157
+ ## 🎭 Animation Details
158
+
159
+ - **Bar Charts**: Staggered bar growth with 100ms delays between bars
160
+ - **Line Charts**: Stroke-dash animation followed by area fill and dot appearance
161
+ - **Pie Charts**: Radial growth animation with 150ms delays between slices
162
+ - **Legends**: Slide-in animations with opacity transitions
163
+
164
+ ## 📱 Responsive Design
165
+
166
+ Charts automatically adapt to different screen sizes:
167
+
168
+ - Bar charts enable horizontal scrolling when content exceeds screen width
169
+ - Minimum bar widths ensure readability on all devices
170
+ - Dynamic font sizing based on chart dimensions
171
+ - Proper padding and margins for touch interactions
172
+
173
+ ## 🔄 Performance Optimizations
174
+
175
+ - React Native Reanimated for smooth 60fps animations
176
+ - Efficient re-renders using `useCallback` and `useMemo`
177
+ - SVG path caching for complex shapes
178
+ - Minimal re-animations on data updates
179
+
180
+ ## 🎯 Accessibility
181
+
182
+ - High contrast color schemes for both light and dark themes
183
+ - Proper accessibility labels and roles
184
+ - Touch target sizes meet accessibility guidelines
185
+ - Screen reader friendly value announcements