@q9labsai/chalk-react-native 4.1.17 → 5.0.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 (544) hide show
  1. package/README.md +134 -29
  2. package/android/build.gradle +35 -0
  3. package/android/compatibility/ModuleApiCompatibility.java +215 -0
  4. package/android/src/main/AndroidManifest.xml +2 -1
  5. package/android/src/main/java/ai/q9labs/chalk/reactnative/ChalkSpaceForegroundService.java +105 -31
  6. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkAndroidConnectionServicePackage.kt +2 -0
  7. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkAudioRouteModule.kt +137 -0
  8. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkCallServiceModule.kt +32 -0
  9. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/CommunicationDeviceListener.kt +23 -0
  10. package/android/src/test/kotlin/ai/q9labs/chalk/compatibility/UnsafeSignatures.kt +29 -0
  11. package/dist/android/call-service.d.ts +4 -0
  12. package/dist/android/call-service.d.ts.map +1 -0
  13. package/dist/avatar/FaceAvatar.d.ts +19 -0
  14. package/dist/avatar/FaceAvatar.d.ts.map +1 -0
  15. package/dist/avatar/tile-avatar-size.d.ts +3 -0
  16. package/dist/avatar/tile-avatar-size.d.ts.map +1 -0
  17. package/dist/chunk-GYVZSOGQ.js +30 -0
  18. package/dist/chunk-IHE6EA3T.js +25 -0
  19. package/dist/chunk-OIBT2FNM.js +1479 -0
  20. package/dist/client.d.ts +1 -5
  21. package/dist/client.d.ts.map +1 -1
  22. package/dist/client.js +185 -2
  23. package/dist/components/EmbeddedWhiteboard.d.ts.map +1 -1
  24. package/dist/components/native-media-visibility.d.ts +3 -2
  25. package/dist/components/native-media-visibility.d.ts.map +1 -1
  26. package/dist/components/useAndroidCallService.d.ts +8 -0
  27. package/dist/components/useAndroidCallService.d.ts.map +1 -0
  28. package/dist/dev.d.ts +10 -0
  29. package/dist/dev.d.ts.map +1 -0
  30. package/dist/dev.js +10 -0
  31. package/dist/dock/Dock.d.ts +23 -0
  32. package/dist/dock/Dock.d.ts.map +1 -0
  33. package/dist/dock/LeaveMenu.d.ts +12 -0
  34. package/dist/dock/LeaveMenu.d.ts.map +1 -0
  35. package/dist/dock/MoreSheet.d.ts +17 -0
  36. package/dist/dock/MoreSheet.d.ts.map +1 -0
  37. package/dist/dock/ReactionBurst.d.ts +8 -0
  38. package/dist/dock/ReactionBurst.d.ts.map +1 -0
  39. package/dist/dock/RoutePicker.d.ts +16 -0
  40. package/dist/dock/RoutePicker.d.ts.map +1 -0
  41. package/dist/dock/audio-route.d.ts +25 -0
  42. package/dist/dock/audio-route.d.ts.map +1 -0
  43. package/dist/error-YOPTEH5N.wav +0 -0
  44. package/dist/frame/CallFrame.d.ts +17 -0
  45. package/dist/frame/CallFrame.d.ts.map +1 -0
  46. package/dist/frame/Chalk.d.ts +40 -0
  47. package/dist/frame/Chalk.d.ts.map +1 -0
  48. package/dist/frame/back-handler.d.ts +6 -0
  49. package/dist/frame/back-handler.d.ts.map +1 -0
  50. package/dist/frame/dev-scenario.d.ts +28 -0
  51. package/dist/frame/dev-scenario.d.ts.map +1 -0
  52. package/dist/frame/device-layout.d.ts +16 -0
  53. package/dist/frame/device-layout.d.ts.map +1 -0
  54. package/dist/frame/measurement.d.ts +28 -0
  55. package/dist/frame/measurement.d.ts.map +1 -0
  56. package/dist/frame/portal.d.ts +24 -0
  57. package/dist/frame/portal.d.ts.map +1 -0
  58. package/dist/frame/preferences.d.ts +21 -0
  59. package/dist/frame/preferences.d.ts.map +1 -0
  60. package/dist/frame/regions.d.ts +25 -0
  61. package/dist/frame/regions.d.ts.map +1 -0
  62. package/dist/hand-DFWVXPH2.wav +0 -0
  63. package/dist/haptics/haptics.d.ts +12 -0
  64. package/dist/haptics/haptics.d.ts.map +1 -0
  65. package/dist/header/CallDetailsSheet.d.ts +18 -0
  66. package/dist/header/CallDetailsSheet.d.ts.map +1 -0
  67. package/dist/header/Header.d.ts +17 -0
  68. package/dist/header/Header.d.ts.map +1 -0
  69. package/dist/header/QrCode.d.ts +6 -0
  70. package/dist/header/QrCode.d.ts.map +1 -0
  71. package/dist/icons/Icon.d.ts +12 -0
  72. package/dist/icons/Icon.d.ts.map +1 -0
  73. package/dist/icons/icon-element.d.ts +24 -0
  74. package/dist/icons/icon-element.d.ts.map +1 -0
  75. package/dist/icons/icon-paths.d.ts +530 -0
  76. package/dist/icons/icon-paths.d.ts.map +1 -0
  77. package/dist/index.d.ts +6 -9
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +2956 -38
  80. package/dist/join-Z6RL5AHE.wav +0 -0
  81. package/dist/knock-4VBQSHK4.wav +0 -0
  82. package/dist/leave-MQLZOWQD.wav +0 -0
  83. package/dist/limbo/Limbo.d.ts +25 -0
  84. package/dist/limbo/Limbo.d.ts.map +1 -0
  85. package/dist/limbo/Veil.d.ts +10 -0
  86. package/dist/limbo/Veil.d.ts.map +1 -0
  87. package/dist/media/native-capture-error.d.ts +7 -0
  88. package/dist/media/native-capture-error.d.ts.map +1 -0
  89. package/dist/message-6Y6WJGTB.wav +0 -0
  90. package/dist/motion/MovingFrame.d.ts +36 -0
  91. package/dist/motion/MovingFrame.d.ts.map +1 -0
  92. package/dist/motion/motion.d.ts +82 -0
  93. package/dist/motion/motion.d.ts.map +1 -0
  94. package/dist/motion/presence.d.ts +6 -0
  95. package/dist/motion/presence.d.ts.map +1 -0
  96. package/dist/motion/press.d.ts +15 -0
  97. package/dist/motion/press.d.ts.map +1 -0
  98. package/dist/mute-H5SJFXVI.wav +0 -0
  99. package/dist/primitives/BottomSheet.d.ts +36 -0
  100. package/dist/primitives/BottomSheet.d.ts.map +1 -0
  101. package/dist/primitives/ChalkText.d.ts +13 -0
  102. package/dist/primitives/ChalkText.d.ts.map +1 -0
  103. package/dist/primitives/CopyButton.d.ts +11 -0
  104. package/dist/primitives/CopyButton.d.ts.map +1 -0
  105. package/dist/primitives/IconButton.d.ts +26 -0
  106. package/dist/primitives/IconButton.d.ts.map +1 -0
  107. package/dist/primitives/Menu.d.ts +39 -0
  108. package/dist/primitives/Menu.d.ts.map +1 -0
  109. package/dist/primitives/NameTag.d.ts +19 -0
  110. package/dist/primitives/NameTag.d.ts.map +1 -0
  111. package/dist/primitives/PillButton.d.ts +19 -0
  112. package/dist/primitives/PillButton.d.ts.map +1 -0
  113. package/dist/primitives/SegmentedControl.d.ts +17 -0
  114. package/dist/primitives/SegmentedControl.d.ts.map +1 -0
  115. package/dist/primitives/SheetGroup.d.ts +24 -0
  116. package/dist/primitives/SheetGroup.d.ts.map +1 -0
  117. package/dist/primitives/Switch.d.ts +9 -0
  118. package/dist/primitives/Switch.d.ts.map +1 -0
  119. package/dist/primitives/TileShell.d.ts +18 -0
  120. package/dist/primitives/TileShell.d.ts.map +1 -0
  121. package/dist/primitives/announce.d.ts +3 -0
  122. package/dist/primitives/announce.d.ts.map +1 -0
  123. package/dist/primitives/menu-placement.d.ts +32 -0
  124. package/dist/primitives/menu-placement.d.ts.map +1 -0
  125. package/dist/primitives/toast/Toast.d.ts +8 -0
  126. package/dist/primitives/toast/Toast.d.ts.map +1 -0
  127. package/dist/primitives/toast/ToastStack.d.ts +18 -0
  128. package/dist/primitives/toast/ToastStack.d.ts.map +1 -0
  129. package/dist/primitives/toast/toast-store.d.ts +39 -0
  130. package/dist/primitives/toast/toast-store.d.ts.map +1 -0
  131. package/dist/recording-Q4GB77Y4.wav +0 -0
  132. package/dist/sheets/people-chat/ChatNotices.d.ts +14 -0
  133. package/dist/sheets/people-chat/ChatNotices.d.ts.map +1 -0
  134. package/dist/sheets/people-chat/ChatTab.d.ts +6 -0
  135. package/dist/sheets/people-chat/ChatTab.d.ts.map +1 -0
  136. package/dist/sheets/people-chat/Composer.d.ts +7 -0
  137. package/dist/sheets/people-chat/Composer.d.ts.map +1 -0
  138. package/dist/sheets/people-chat/PeopleChatSheet.d.ts +17 -0
  139. package/dist/sheets/people-chat/PeopleChatSheet.d.ts.map +1 -0
  140. package/dist/sheets/people-chat/PeopleTab.d.ts +3 -0
  141. package/dist/sheets/people-chat/PeopleTab.d.ts.map +1 -0
  142. package/dist/sheets/people-chat/PhotoViewer.d.ts +19 -0
  143. package/dist/sheets/people-chat/PhotoViewer.d.ts.map +1 -0
  144. package/dist/sheets/people-chat/TextField.d.ts +4 -0
  145. package/dist/sheets/people-chat/TextField.d.ts.map +1 -0
  146. package/dist/sheets/people-chat/attachments.d.ts +33 -0
  147. package/dist/sheets/people-chat/attachments.d.ts.map +1 -0
  148. package/dist/sheets/people-chat/chat-model.d.ts +64 -0
  149. package/dist/sheets/people-chat/chat-model.d.ts.map +1 -0
  150. package/dist/sheets/people-chat/people-model.d.ts +43 -0
  151. package/dist/sheets/people-chat/people-model.d.ts.map +1 -0
  152. package/dist/sounds/sounds.d.ts +33 -0
  153. package/dist/sounds/sounds.d.ts.map +1 -0
  154. package/dist/space-client/create-native-space-client.d.ts +0 -4
  155. package/dist/space-client/create-native-space-client.d.ts.map +1 -1
  156. package/dist/space-client/random-uuid.d.ts +7 -0
  157. package/dist/space-client/random-uuid.d.ts.map +1 -0
  158. package/dist/stage/ContentTile.d.ts +18 -0
  159. package/dist/stage/ContentTile.d.ts.map +1 -0
  160. package/dist/stage/ParticipantTile.d.ts +18 -0
  161. package/dist/stage/ParticipantTile.d.ts.map +1 -0
  162. package/dist/stage/Stage.d.ts +14 -0
  163. package/dist/stage/Stage.d.ts.map +1 -0
  164. package/dist/stage/TileSheet.d.ts +12 -0
  165. package/dist/stage/TileSheet.d.ts.map +1 -0
  166. package/dist/stage/camera.d.ts +7 -0
  167. package/dist/stage/camera.d.ts.map +1 -0
  168. package/dist/stage/layout.d.ts +57 -0
  169. package/dist/stage/layout.d.ts.map +1 -0
  170. package/dist/stage/space-selector.d.ts +10 -0
  171. package/dist/stage/space-selector.d.ts.map +1 -0
  172. package/dist/stage/stage-view.d.ts +23 -0
  173. package/dist/stage/stage-view.d.ts.map +1 -0
  174. package/dist/status/CallOverlays.d.ts +17 -0
  175. package/dist/status/CallOverlays.d.ts.map +1 -0
  176. package/dist/status/ChalkArrival.d.ts +24 -0
  177. package/dist/status/ChalkArrival.d.ts.map +1 -0
  178. package/dist/status/StatusPage.d.ts +14 -0
  179. package/dist/status/StatusPage.d.ts.map +1 -0
  180. package/dist/status/call-screen.d.ts +20 -0
  181. package/dist/status/call-screen.d.ts.map +1 -0
  182. package/dist/test-VD2KAM4D.wav +0 -0
  183. package/dist/theme/theme.d.ts +15 -0
  184. package/dist/theme/theme.d.ts.map +1 -0
  185. package/dist/theme/tokens.d.ts +248 -0
  186. package/dist/theme/tokens.d.ts.map +1 -0
  187. package/dist/toasts/CallEventToasts.d.ts +21 -0
  188. package/dist/toasts/CallEventToasts.d.ts.map +1 -0
  189. package/dist/toasts/notices.d.ts +34 -0
  190. package/dist/toasts/notices.d.ts.map +1 -0
  191. package/dist/ui/ChalkUI.d.ts +12 -0
  192. package/dist/ui/ChalkUI.d.ts.map +1 -0
  193. package/dist/ui.d.ts +25 -0
  194. package/dist/ui.d.ts.map +1 -0
  195. package/dist/ui.js +77 -0
  196. package/dist/unmute-2XR2LICU.wav +0 -0
  197. package/embedded/chalk-whiteboard/asset-manifest.json +2 -2
  198. package/embedded/chalk-whiteboard/renderer.js +510 -510
  199. package/ios/ChalkAudioRouteModule.swift +93 -0
  200. package/ios/ChalkAudioRouteModuleBridge.m +9 -0
  201. package/package.json +46 -76
  202. package/src/android/call-service.ts +19 -0
  203. package/src/avatar/FaceAvatar.tsx +145 -0
  204. package/src/avatar/tile-avatar-size.ts +4 -0
  205. package/src/client.ts +1 -5
  206. package/src/components/EmbeddedWhiteboard.tsx +14 -71
  207. package/src/components/native-media-visibility.ts +1 -2
  208. package/src/components/useAndroidCallService.ts +41 -0
  209. package/src/dev.ts +9 -0
  210. package/src/dock/Dock.tsx +95 -0
  211. package/src/dock/LeaveMenu.tsx +21 -0
  212. package/src/dock/MoreSheet.tsx +233 -0
  213. package/src/dock/ReactionBurst.tsx +55 -0
  214. package/src/dock/RoutePicker.tsx +42 -0
  215. package/src/dock/audio-route.ts +69 -0
  216. package/src/frame/CallFrame.tsx +209 -0
  217. package/src/frame/Chalk.tsx +83 -0
  218. package/src/frame/back-handler.ts +19 -0
  219. package/src/frame/dev-scenario.ts +48 -0
  220. package/src/frame/device-layout.tsx +31 -0
  221. package/src/frame/measurement.ts +44 -0
  222. package/src/frame/portal.tsx +107 -0
  223. package/src/frame/preferences.tsx +48 -0
  224. package/src/frame/regions.test.ts +38 -0
  225. package/src/frame/regions.ts +60 -0
  226. package/src/haptics/haptics.ts +19 -0
  227. package/src/header/CallDetailsSheet.tsx +139 -0
  228. package/src/header/Header.tsx +107 -0
  229. package/src/header/QrCode.tsx +34 -0
  230. package/src/icons/Icon.tsx +35 -0
  231. package/src/icons/icon-element.ts +11 -0
  232. package/src/icons/icon-paths.ts +199 -0
  233. package/src/index.ts +6 -9
  234. package/src/limbo/Limbo.tsx +159 -0
  235. package/src/limbo/Veil.tsx +36 -0
  236. package/src/media/native-capture-error.test.ts +19 -0
  237. package/src/media/native-capture-error.ts +13 -0
  238. package/src/motion/MovingFrame.tsx +101 -0
  239. package/src/motion/motion.ts +33 -0
  240. package/src/motion/presence.ts +20 -0
  241. package/src/motion/press.ts +35 -0
  242. package/src/primitives/BottomSheet.tsx +211 -0
  243. package/src/primitives/ChalkText.tsx +23 -0
  244. package/src/primitives/CopyButton.tsx +78 -0
  245. package/src/primitives/IconButton.tsx +90 -0
  246. package/src/primitives/Menu.tsx +212 -0
  247. package/src/primitives/NameTag.tsx +68 -0
  248. package/src/primitives/PillButton.tsx +56 -0
  249. package/src/primitives/SegmentedControl.tsx +55 -0
  250. package/src/primitives/SheetGroup.tsx +72 -0
  251. package/src/primitives/Switch.tsx +39 -0
  252. package/src/primitives/TileShell.tsx +53 -0
  253. package/src/primitives/announce.ts +7 -0
  254. package/src/primitives/menu-placement.test.ts +50 -0
  255. package/src/primitives/menu-placement.ts +43 -0
  256. package/src/primitives/toast/Toast.tsx +50 -0
  257. package/src/primitives/toast/ToastStack.tsx +89 -0
  258. package/src/primitives/toast/toast-store.ts +86 -0
  259. package/src/sheets/people-chat/ChatNotices.tsx +69 -0
  260. package/src/sheets/people-chat/ChatTab.tsx +186 -0
  261. package/src/sheets/people-chat/Composer.tsx +182 -0
  262. package/src/sheets/people-chat/PeopleChatSheet.tsx +100 -0
  263. package/src/sheets/people-chat/PeopleTab.tsx +326 -0
  264. package/src/sheets/people-chat/PhotoViewer.tsx +132 -0
  265. package/src/sheets/people-chat/TextField.tsx +14 -0
  266. package/src/sheets/people-chat/attachments.tsx +183 -0
  267. package/src/sheets/people-chat/chat-model.ts +157 -0
  268. package/src/sheets/people-chat/people-chat-model.test.ts +98 -0
  269. package/src/sheets/people-chat/people-model.ts +68 -0
  270. package/src/sounds/assets/error.wav +0 -0
  271. package/src/sounds/assets/hand.wav +0 -0
  272. package/src/sounds/assets/join.wav +0 -0
  273. package/src/sounds/assets/knock.wav +0 -0
  274. package/src/sounds/assets/leave.wav +0 -0
  275. package/src/sounds/assets/message.wav +0 -0
  276. package/src/sounds/assets/mute.wav +0 -0
  277. package/src/sounds/assets/recording.wav +0 -0
  278. package/src/sounds/assets/test.wav +0 -0
  279. package/src/sounds/assets/unmute.wav +0 -0
  280. package/src/sounds/assets.d.ts +5 -0
  281. package/src/sounds/sounds.ts +50 -0
  282. package/src/space-client/create-native-space-client.ts +20 -181
  283. package/src/space-client/random-uuid.ts +17 -0
  284. package/src/space-client/whiteboard-watchdog.test.ts +23 -0
  285. package/src/stage/ContentTile.tsx +100 -0
  286. package/src/stage/ParticipantTile.tsx +140 -0
  287. package/src/stage/Stage.tsx +152 -0
  288. package/src/stage/TileSheet.tsx +116 -0
  289. package/src/stage/camera.ts +20 -0
  290. package/src/stage/layout.test.ts +77 -0
  291. package/src/stage/layout.ts +226 -0
  292. package/src/stage/space-selector.ts +31 -0
  293. package/src/stage/stage-view.tsx +68 -0
  294. package/src/status/CallOverlays.tsx +47 -0
  295. package/src/status/ChalkArrival.tsx +53 -0
  296. package/src/status/StatusPage.tsx +123 -0
  297. package/src/status/call-screen.test.ts +42 -0
  298. package/src/status/call-screen.ts +29 -0
  299. package/src/theme/theme.tsx +28 -0
  300. package/src/theme/tokens.ts +247 -0
  301. package/src/toasts/CallEventToasts.tsx +192 -0
  302. package/src/toasts/notices.test.ts +92 -0
  303. package/src/toasts/notices.ts +62 -0
  304. package/src/ui/ChalkUI.tsx +49 -0
  305. package/src/ui.ts +24 -0
  306. package/dist/android.d.ts +0 -2
  307. package/dist/android.d.ts.map +0 -1
  308. package/dist/android.js +0 -62
  309. package/dist/chunk-2OS7SSXE.js +0 -552
  310. package/dist/chunk-5DQ4KBRH.js +0 -690
  311. package/dist/chunk-ITLUHTVS.js +0 -5271
  312. package/dist/chunk-JB4LNWVP.js +0 -247
  313. package/dist/components/Chalk.d.ts +0 -79
  314. package/dist/components/Chalk.d.ts.map +0 -1
  315. package/dist/components/ChatMessageList.d.ts +0 -11
  316. package/dist/components/ChatMessageList.d.ts.map +0 -1
  317. package/dist/components/Entrance.d.ts +0 -22
  318. package/dist/components/Entrance.d.ts.map +0 -1
  319. package/dist/components/EntranceView.android.d.ts +0 -4
  320. package/dist/components/EntranceView.android.d.ts.map +0 -1
  321. package/dist/components/EntranceView.d.ts +0 -18
  322. package/dist/components/EntranceView.d.ts.map +0 -1
  323. package/dist/components/EntranceView.ios-pad.d.ts +0 -3
  324. package/dist/components/EntranceView.ios-pad.d.ts.map +0 -1
  325. package/dist/components/EntranceView.ios-phone.d.ts +0 -3
  326. package/dist/components/EntranceView.ios-phone.d.ts.map +0 -1
  327. package/dist/components/EntranceView.macos.d.ts +0 -4
  328. package/dist/components/EntranceView.macos.d.ts.map +0 -1
  329. package/dist/components/FaceAvatar.d.ts +0 -16
  330. package/dist/components/FaceAvatar.d.ts.map +0 -1
  331. package/dist/components/GradientSurface.d.ts +0 -14
  332. package/dist/components/GradientSurface.d.ts.map +0 -1
  333. package/dist/components/MediaView.d.ts +0 -14
  334. package/dist/components/MediaView.d.ts.map +0 -1
  335. package/dist/components/ReactionPicker.d.ts +0 -10
  336. package/dist/components/ReactionPicker.d.ts.map +0 -1
  337. package/dist/components/SpaceView.android.d.ts +0 -2
  338. package/dist/components/SpaceView.android.d.ts.map +0 -1
  339. package/dist/components/SpaceView.d.ts +0 -33
  340. package/dist/components/SpaceView.d.ts.map +0 -1
  341. package/dist/components/SpaceView.ios-pad.d.ts +0 -2
  342. package/dist/components/SpaceView.ios-pad.d.ts.map +0 -1
  343. package/dist/components/SpaceView.ios-phone.d.ts +0 -2
  344. package/dist/components/SpaceView.ios-phone.d.ts.map +0 -1
  345. package/dist/components/SpaceView.macos.d.ts +0 -2
  346. package/dist/components/SpaceView.macos.d.ts.map +0 -1
  347. package/dist/components/SpaceView.shared.d.ts +0 -3
  348. package/dist/components/SpaceView.shared.d.ts.map +0 -1
  349. package/dist/components/episode-diagnostic-render-observer.d.ts +0 -2
  350. package/dist/components/episode-diagnostic-render-observer.d.ts.map +0 -1
  351. package/dist/components/logo/Logo.d.ts +0 -11
  352. package/dist/components/logo/Logo.d.ts.map +0 -1
  353. package/dist/components/native-animation-controller.d.ts +0 -7
  354. package/dist/components/native-animation-controller.d.ts.map +0 -1
  355. package/dist/components/native-chat.d.ts +0 -8
  356. package/dist/components/native-chat.d.ts.map +0 -1
  357. package/dist/components/native-entrance/entrance-controller-store.d.ts +0 -34
  358. package/dist/components/native-entrance/entrance-controller-store.d.ts.map +0 -1
  359. package/dist/components/native-entrance/useEntranceController.d.ts +0 -19
  360. package/dist/components/native-entrance/useEntranceController.d.ts.map +0 -1
  361. package/dist/components/native-joining-loading-animation.d.ts +0 -9
  362. package/dist/components/native-joining-loading-animation.d.ts.map +0 -1
  363. package/dist/components/native-space-view/AppearanceSettings.d.ts +0 -2
  364. package/dist/components/native-space-view/AppearanceSettings.d.ts.map +0 -1
  365. package/dist/components/native-space-view/FeedbackSheet.d.ts +0 -12
  366. package/dist/components/native-space-view/FeedbackSheet.d.ts.map +0 -1
  367. package/dist/components/native-space-view/ParticipantActionSheet.d.ts +0 -9
  368. package/dist/components/native-space-view/ParticipantActionSheet.d.ts.map +0 -1
  369. package/dist/components/native-space-view/SettingsSheet.d.ts +0 -7
  370. package/dist/components/native-space-view/SettingsSheet.d.ts.map +0 -1
  371. package/dist/components/native-space-view/SpaceActionMenu.d.ts +0 -10
  372. package/dist/components/native-space-view/SpaceActionMenu.d.ts.map +0 -1
  373. package/dist/components/native-space-view/SpaceBottomDock.android.d.ts +0 -4
  374. package/dist/components/native-space-view/SpaceBottomDock.android.d.ts.map +0 -1
  375. package/dist/components/native-space-view/SpaceChatAttachment.d.ts +0 -8
  376. package/dist/components/native-space-view/SpaceChatAttachment.d.ts.map +0 -1
  377. package/dist/components/native-space-view/SpaceChatSheet.d.ts +0 -5
  378. package/dist/components/native-space-view/SpaceChatSheet.d.ts.map +0 -1
  379. package/dist/components/native-space-view/SpaceGrid.android.d.ts +0 -8
  380. package/dist/components/native-space-view/SpaceGrid.android.d.ts.map +0 -1
  381. package/dist/components/native-space-view/SpaceMoreSheet.d.ts +0 -7
  382. package/dist/components/native-space-view/SpaceMoreSheet.d.ts.map +0 -1
  383. package/dist/components/native-space-view/SpacePanelSheet.d.ts +0 -5
  384. package/dist/components/native-space-view/SpacePanelSheet.d.ts.map +0 -1
  385. package/dist/components/native-space-view/SpacePeopleSheet.d.ts +0 -5
  386. package/dist/components/native-space-view/SpacePeopleSheet.d.ts.map +0 -1
  387. package/dist/components/native-space-view/SpaceStage.android.d.ts +0 -29
  388. package/dist/components/native-space-view/SpaceStage.android.d.ts.map +0 -1
  389. package/dist/components/native-space-view/SpaceSurfacePrimitives.d.ts +0 -30
  390. package/dist/components/native-space-view/SpaceSurfacePrimitives.d.ts.map +0 -1
  391. package/dist/components/native-space-view/SpaceTopBar.android.d.ts +0 -11
  392. package/dist/components/native-space-view/SpaceTopBar.android.d.ts.map +0 -1
  393. package/dist/components/native-space-view/SpaceWhiteboardSurface.d.ts +0 -15
  394. package/dist/components/native-space-view/SpaceWhiteboardSurface.d.ts.map +0 -1
  395. package/dist/components/native-space-view/diagnostics.d.ts +0 -48
  396. package/dist/components/native-space-view/diagnostics.d.ts.map +0 -1
  397. package/dist/components/native-space-view/format-space-duration.d.ts +0 -2
  398. package/dist/components/native-space-view/format-space-duration.d.ts.map +0 -1
  399. package/dist/components/native-space-view/native-space-grid-keys.d.ts +0 -3
  400. package/dist/components/native-space-view/native-space-grid-keys.d.ts.map +0 -1
  401. package/dist/components/native-space-view/native-space-page-store.d.ts +0 -8
  402. package/dist/components/native-space-view/native-space-page-store.d.ts.map +0 -1
  403. package/dist/components/native-space-view/space-chat-attachments.d.ts +0 -15
  404. package/dist/components/native-space-view/space-chat-attachments.d.ts.map +0 -1
  405. package/dist/components/native-space-view/space-panel-layout.d.ts +0 -10
  406. package/dist/components/native-space-view/space-panel-layout.d.ts.map +0 -1
  407. package/dist/components/native-space-view/space-progressive-surface-helpers.d.ts +0 -16
  408. package/dist/components/native-space-view/space-progressive-surface-helpers.d.ts.map +0 -1
  409. package/dist/components/native-space-view/space-progressive-surface-types.d.ts +0 -3
  410. package/dist/components/native-space-view/space-progressive-surface-types.d.ts.map +0 -1
  411. package/dist/components/native-space-view/types.d.ts +0 -24
  412. package/dist/components/native-space-view/types.d.ts.map +0 -1
  413. package/dist/components/native-space-view/useSpaceViewController.contract.d.ts +0 -41
  414. package/dist/components/native-space-view/useSpaceViewController.contract.d.ts.map +0 -1
  415. package/dist/components/native-space-view/useSpaceViewController.d.ts +0 -156
  416. package/dist/components/native-space-view/useSpaceViewController.d.ts.map +0 -1
  417. package/dist/components/native-space-view/useSpaceViewDerived.d.ts +0 -12
  418. package/dist/components/native-space-view/useSpaceViewDerived.d.ts.map +0 -1
  419. package/dist/components/native-space-view/useSpaceViewPanels.d.ts +0 -70
  420. package/dist/components/native-space-view/useSpaceViewPanels.d.ts.map +0 -1
  421. package/dist/feedback/native-capture.d.ts +0 -9
  422. package/dist/feedback/native-capture.d.ts.map +0 -1
  423. package/dist/feedback/native-evidence.d.ts +0 -3
  424. package/dist/feedback/native-evidence.d.ts.map +0 -1
  425. package/dist/hooks/entrance-preview-store.d.ts +0 -16
  426. package/dist/hooks/entrance-preview-store.d.ts.map +0 -1
  427. package/dist/hooks/useEntrancePreview.d.ts +0 -7
  428. package/dist/hooks/useEntrancePreview.d.ts.map +0 -1
  429. package/dist/hooks/useLayout.d.ts +0 -16
  430. package/dist/hooks/useLayout.d.ts.map +0 -1
  431. package/dist/hooks/usePanels.d.ts +0 -12
  432. package/dist/hooks/usePanels.d.ts.map +0 -1
  433. package/dist/ios-pad.d.ts +0 -2
  434. package/dist/ios-pad.d.ts.map +0 -1
  435. package/dist/ios-pad.js +0 -62
  436. package/dist/ios-phone.d.ts +0 -2
  437. package/dist/ios-phone.d.ts.map +0 -1
  438. package/dist/ios-phone.js +0 -62
  439. package/dist/ios.d.ts +0 -2
  440. package/dist/ios.d.ts.map +0 -1
  441. package/dist/ios.js +0 -62
  442. package/dist/macos.d.ts +0 -2
  443. package/dist/macos.d.ts.map +0 -1
  444. package/dist/macos.js +0 -62
  445. package/dist/space-client/cloudflare-rtk-native.d.ts +0 -3
  446. package/dist/space-client/cloudflare-rtk-native.d.ts.map +0 -1
  447. package/dist/telemetry.d.ts +0 -63
  448. package/dist/telemetry.d.ts.map +0 -1
  449. package/dist/ui/appearance.d.ts +0 -246
  450. package/dist/ui/appearance.d.ts.map +0 -1
  451. package/dist/ui/appearance.js +0 -14
  452. package/dist/ui/native-appearance-context.d.ts +0 -15
  453. package/dist/ui/native-appearance-context.d.ts.map +0 -1
  454. package/dist/ui/native-theme.d.ts +0 -17
  455. package/dist/ui/native-theme.d.ts.map +0 -1
  456. package/dist/ui/native-types.d.ts +0 -38
  457. package/dist/ui/native-types.d.ts.map +0 -1
  458. package/dist/ui/participant-avatar.d.ts +0 -21
  459. package/dist/ui/participant-avatar.d.ts.map +0 -1
  460. package/dist/ui/theme-tokens.d.ts +0 -25
  461. package/dist/ui/theme-tokens.d.ts.map +0 -1
  462. package/dist/ui/theme.d.ts +0 -404
  463. package/dist/ui/theme.d.ts.map +0 -1
  464. package/dist/ui/theme.js +0 -8
  465. package/dist/utils/native-space-layout.d.ts +0 -42
  466. package/dist/utils/native-space-layout.d.ts.map +0 -1
  467. package/src/android.ts +0 -1
  468. package/src/components/Chalk.tsx +0 -363
  469. package/src/components/ChatMessageList.tsx +0 -209
  470. package/src/components/Entrance.tsx +0 -42
  471. package/src/components/EntranceView.android.tsx +0 -274
  472. package/src/components/EntranceView.ios-pad.tsx +0 -326
  473. package/src/components/EntranceView.ios-phone.tsx +0 -271
  474. package/src/components/EntranceView.macos.tsx +0 -278
  475. package/src/components/EntranceView.tsx +0 -38
  476. package/src/components/FaceAvatar.tsx +0 -120
  477. package/src/components/GradientSurface.tsx +0 -23
  478. package/src/components/MediaView.tsx +0 -76
  479. package/src/components/ReactionPicker.tsx +0 -98
  480. package/src/components/SpaceView.android.tsx +0 -1
  481. package/src/components/SpaceView.ios-pad.tsx +0 -1
  482. package/src/components/SpaceView.ios-phone.tsx +0 -1
  483. package/src/components/SpaceView.macos.tsx +0 -1
  484. package/src/components/SpaceView.shared.tsx +0 -98
  485. package/src/components/SpaceView.tsx +0 -54
  486. package/src/components/episode-diagnostic-render-observer.ts +0 -12
  487. package/src/components/logo/Logo.tsx +0 -309
  488. package/src/components/native-animation-controller.ts +0 -36
  489. package/src/components/native-chat.ts +0 -23
  490. package/src/components/native-entrance/entrance-controller-store.ts +0 -112
  491. package/src/components/native-entrance/useEntranceController.ts +0 -60
  492. package/src/components/native-joining-loading-animation.ts +0 -26
  493. package/src/components/native-space-view/AppearanceSettings.tsx +0 -114
  494. package/src/components/native-space-view/FeedbackSheet.tsx +0 -296
  495. package/src/components/native-space-view/ParticipantActionSheet.tsx +0 -99
  496. package/src/components/native-space-view/SettingsSheet.tsx +0 -164
  497. package/src/components/native-space-view/SpaceActionMenu.tsx +0 -109
  498. package/src/components/native-space-view/SpaceBottomDock.android.tsx +0 -115
  499. package/src/components/native-space-view/SpaceChatAttachment.tsx +0 -105
  500. package/src/components/native-space-view/SpaceChatSheet.tsx +0 -184
  501. package/src/components/native-space-view/SpaceGrid.android.tsx +0 -323
  502. package/src/components/native-space-view/SpaceMoreSheet.tsx +0 -190
  503. package/src/components/native-space-view/SpacePanelSheet.tsx +0 -45
  504. package/src/components/native-space-view/SpacePeopleSheet.tsx +0 -116
  505. package/src/components/native-space-view/SpaceStage.android.tsx +0 -372
  506. package/src/components/native-space-view/SpaceSurfacePrimitives.tsx +0 -75
  507. package/src/components/native-space-view/SpaceTopBar.android.tsx +0 -113
  508. package/src/components/native-space-view/SpaceWhiteboardSurface.tsx +0 -69
  509. package/src/components/native-space-view/diagnostics.ts +0 -84
  510. package/src/components/native-space-view/format-space-duration.ts +0 -3
  511. package/src/components/native-space-view/native-space-grid-keys.ts +0 -6
  512. package/src/components/native-space-view/native-space-page-store.ts +0 -41
  513. package/src/components/native-space-view/space-chat-attachments.test.ts +0 -26
  514. package/src/components/native-space-view/space-chat-attachments.ts +0 -37
  515. package/src/components/native-space-view/space-panel-layout.ts +0 -10
  516. package/src/components/native-space-view/space-progressive-surface-helpers.ts +0 -33
  517. package/src/components/native-space-view/space-progressive-surface-types.ts +0 -3
  518. package/src/components/native-space-view/types.ts +0 -25
  519. package/src/components/native-space-view/useSpaceViewController.contract.ts +0 -34
  520. package/src/components/native-space-view/useSpaceViewController.ts +0 -416
  521. package/src/components/native-space-view/useSpaceViewDerived.ts +0 -29
  522. package/src/components/native-space-view/useSpaceViewPanels.ts +0 -170
  523. package/src/feedback/native-capture.ts +0 -62
  524. package/src/feedback/native-evidence.ts +0 -37
  525. package/src/hooks/entrance-preview-store.ts +0 -99
  526. package/src/hooks/useEntrancePreview.ts +0 -26
  527. package/src/hooks/useLayout.ts +0 -37
  528. package/src/hooks/usePanels.ts +0 -30
  529. package/src/ios-pad.ts +0 -1
  530. package/src/ios-phone.ts +0 -1
  531. package/src/ios.ts +0 -1
  532. package/src/macos.ts +0 -1
  533. package/src/space-client/cloudflare-rtk-native.ts +0 -104
  534. package/src/telemetry.ts +0 -234
  535. package/src/types/hugeicons-direct.d.ts +0 -4
  536. package/src/types/react-native-safe-area-context.d.ts +0 -8
  537. package/src/ui/appearance.ts +0 -808
  538. package/src/ui/native-appearance-context.tsx +0 -74
  539. package/src/ui/native-theme.tsx +0 -54
  540. package/src/ui/native-types.ts +0 -40
  541. package/src/ui/participant-avatar.ts +0 -47
  542. package/src/ui/theme-tokens.ts +0 -41
  543. package/src/ui/theme.ts +0 -214
  544. package/src/utils/native-space-layout.ts +0 -135
@@ -0,0 +1,93 @@
1
+ import AVFoundation
2
+ import Foundation
3
+ import React
4
+ import UIKit
5
+
6
+ /// Lists the call's audio outputs (earpiece, speaker, wired and Bluetooth headsets) and switches
7
+ /// between them on the shared play-and-record session that WebRTC owns.
8
+ @objc(ChalkAudioRouteModule)
9
+ final class ChalkAudioRouteModule: RCTEventEmitter {
10
+ private let eventName = "ChalkAudioRouteChanged"
11
+ private var observer: NSObjectProtocol?
12
+
13
+ override class func requiresMainQueueSetup() -> Bool {
14
+ false
15
+ }
16
+
17
+ override func constantsToExport() -> [AnyHashable: Any]! {
18
+ ["eventName": eventName]
19
+ }
20
+
21
+ override func supportedEvents() -> [String]! {
22
+ [eventName]
23
+ }
24
+
25
+ override func startObserving() {
26
+ observer = NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification, object: nil, queue: .main) { [weak self] _ in
27
+ guard let self else { return }
28
+ self.sendEvent(withName: self.eventName, body: self.snapshot())
29
+ }
30
+ }
31
+
32
+ override func stopObserving() {
33
+ if let observer { NotificationCenter.default.removeObserver(observer) }
34
+ observer = nil
35
+ }
36
+
37
+ @objc(getRoutes:rejecter:)
38
+ func getRoutes(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
39
+ resolve(snapshot())
40
+ }
41
+
42
+ @objc(selectRoute:resolver:rejecter:)
43
+ func selectRoute(_ id: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
44
+ let session = AVAudioSession.sharedInstance()
45
+ do {
46
+ if id == "speaker" {
47
+ try session.overrideOutputAudioPort(.speaker)
48
+ } else {
49
+ try session.overrideOutputAudioPort(.none)
50
+ let port = session.availableInputs?.first { input in
51
+ id == "earpiece" ? input.portType == .builtInMic : input.uid == id
52
+ }
53
+ if let port { try session.setPreferredInput(port) }
54
+ }
55
+ resolve(snapshot())
56
+ } catch {
57
+ reject("audio_route_failed", "Couldn't switch the audio output to \(id).", error)
58
+ }
59
+ }
60
+
61
+ private func snapshot() -> [String: Any] {
62
+ let session = AVAudioSession.sharedInstance()
63
+ let isPhone = UIDevice.current.userInterfaceIdiom == .phone
64
+ var routes: [[String: String]] = []
65
+ if isPhone { routes.append(["id": "earpiece", "kind": "earpiece", "name": ""]) }
66
+ routes.append(["id": "speaker", "kind": "speaker", "name": ""])
67
+ for input in session.availableInputs ?? [] {
68
+ guard let kind = Self.headsetKind(input.portType) else { continue }
69
+ routes.append(["id": input.uid, "kind": kind, "name": input.portName])
70
+ }
71
+ return ["routes": routes, "selected": selectedId(session, routes: routes)]
72
+ }
73
+
74
+ private func selectedId(_ session: AVAudioSession, routes: [[String: String]]) -> String {
75
+ guard let output = session.currentRoute.outputs.first else { return "speaker" }
76
+ switch output.portType {
77
+ case .builtInSpeaker: return "speaker"
78
+ case .builtInReceiver: return "earpiece"
79
+ default:
80
+ // Headsets report the same port as input and output, so the input's id names the route.
81
+ let input = session.currentRoute.inputs.first { Self.headsetKind($0.portType) != nil }
82
+ return input?.uid ?? routes.first { $0["name"] == output.portName }?["id"] ?? "speaker"
83
+ }
84
+ }
85
+
86
+ private static func headsetKind(_ port: AVAudioSession.Port) -> String? {
87
+ switch port {
88
+ case .bluetoothHFP, .bluetoothLE, .bluetoothA2DP: return "bluetooth"
89
+ case .headsetMic, .usbAudio: return "wired"
90
+ default: return nil
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,9 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTEventEmitter.h>
3
+
4
+ @interface RCT_EXTERN_MODULE(ChalkAudioRouteModule, RCTEventEmitter)
5
+
6
+ RCT_EXTERN_METHOD(getRoutes:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
7
+ RCT_EXTERN_METHOD(selectRoute:(NSString *)id resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
8
+
9
+ @end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q9labsai/chalk-react-native",
3
- "version": "4.1.17",
3
+ "version": "5.0.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,21 +22,6 @@
22
22
  "types": "./dist/index.d.ts",
23
23
  "typesVersions": {
24
24
  "*": {
25
- "android": [
26
- "./dist/android.d.ts"
27
- ],
28
- "ios": [
29
- "./dist/ios.d.ts"
30
- ],
31
- "ios-phone": [
32
- "./dist/ios-phone.d.ts"
33
- ],
34
- "ios-pad": [
35
- "./dist/ios-pad.d.ts"
36
- ],
37
- "macos": [
38
- "./dist/macos.d.ts"
39
- ],
40
25
  "runtime": [
41
26
  "./dist/runtime.d.ts"
42
27
  ],
@@ -49,11 +34,8 @@
49
34
  "invites": [
50
35
  "./dist/invites.d.ts"
51
36
  ],
52
- "theme": [
53
- "./dist/ui/theme.d.ts"
54
- ],
55
- "appearance": [
56
- "./dist/ui/appearance.d.ts"
37
+ "ui": [
38
+ "./dist/ui.d.ts"
57
39
  ],
58
40
  "client": [
59
41
  "./dist/client.d.ts"
@@ -72,36 +54,6 @@
72
54
  "require": "./dist/index.js",
73
55
  "default": "./dist/index.js"
74
56
  },
75
- "./android": {
76
- "types": "./dist/android.d.ts",
77
- "react-native": "./dist/android.js",
78
- "import": "./dist/android.js",
79
- "default": "./dist/android.js"
80
- },
81
- "./ios": {
82
- "types": "./dist/ios.d.ts",
83
- "react-native": "./dist/ios.js",
84
- "import": "./dist/ios.js",
85
- "default": "./dist/ios.js"
86
- },
87
- "./ios-phone": {
88
- "types": "./dist/ios-phone.d.ts",
89
- "react-native": "./dist/ios-phone.js",
90
- "import": "./dist/ios-phone.js",
91
- "default": "./dist/ios-phone.js"
92
- },
93
- "./ios-pad": {
94
- "types": "./dist/ios-pad.d.ts",
95
- "react-native": "./dist/ios-pad.js",
96
- "import": "./dist/ios-pad.js",
97
- "default": "./dist/ios-pad.js"
98
- },
99
- "./macos": {
100
- "types": "./dist/macos.d.ts",
101
- "react-native": "./dist/macos.js",
102
- "import": "./dist/macos.js",
103
- "default": "./dist/macos.js"
104
- },
105
57
  "./runtime": {
106
58
  "types": "./dist/runtime.d.ts",
107
59
  "react-native": "./dist/runtime.js",
@@ -120,24 +72,24 @@
120
72
  "import": "./dist/diagnostics.js",
121
73
  "default": "./dist/diagnostics.js"
122
74
  },
75
+ "./dev": {
76
+ "types": "./dist/dev.d.ts",
77
+ "react-native": "./dist/dev.js",
78
+ "import": "./dist/dev.js",
79
+ "default": "./dist/dev.js"
80
+ },
81
+ "./ui": {
82
+ "types": "./dist/ui.d.ts",
83
+ "react-native": "./dist/ui.js",
84
+ "import": "./dist/ui.js",
85
+ "default": "./dist/ui.js"
86
+ },
123
87
  "./invites": {
124
88
  "types": "./dist/invites.d.ts",
125
89
  "react-native": "./dist/invites.js",
126
90
  "import": "./dist/invites.js",
127
91
  "default": "./dist/invites.js"
128
92
  },
129
- "./theme": {
130
- "types": "./dist/ui/theme.d.ts",
131
- "react-native": "./dist/ui/theme.js",
132
- "import": "./dist/ui/theme.js",
133
- "default": "./dist/ui/theme.js"
134
- },
135
- "./appearance": {
136
- "types": "./dist/ui/appearance.d.ts",
137
- "react-native": "./dist/ui/appearance.js",
138
- "import": "./dist/ui/appearance.js",
139
- "default": "./dist/ui/appearance.js"
140
- },
141
93
  "./client": {
142
94
  "types": "./dist/client.d.ts",
143
95
  "react-native": "./dist/client.js",
@@ -150,38 +102,56 @@
150
102
  "registry": "https://registry.npmjs.org/"
151
103
  },
152
104
  "dependencies": {
153
- "@q9labsai/chalk-client": "^4.1.17",
154
- "@q9labsai/chalk-whiteboard": "^4.1.17",
155
- "@q9labsai/facehash": "^4.1.17"
105
+ "@q9labsai/chalk-client": "^5.0.1",
106
+ "@q9labsai/chalk-whiteboard": "^5.0.1",
107
+ "@q9labsai/facehash": "^5.0.1",
108
+ "uqr": "^0.1.3"
156
109
  },
157
110
  "devDependencies": {
158
111
  "@types/node": "^26.2.0",
159
112
  "@types/react": "^19.2.18",
160
- "react-native-view-shot": "4.0.3",
113
+ "expo-audio": "~55.0.18",
114
+ "expo-clipboard": "~55.0.9",
115
+ "expo-crypto": "~55.0.19",
116
+ "expo-document-picker": "~55.0.15",
117
+ "expo-file-system": "~55.0.24",
118
+ "expo-haptics": "~55.0.18",
119
+ "react-native-gesture-handler": "~2.30.1",
120
+ "react-native-reanimated": "4.2.1",
121
+ "react-native-safe-area-context": "~5.6.2",
122
+ "react-native-svg": "^15.15.3",
161
123
  "react-native-webview": "13.16.1",
124
+ "react-native-worklets": "0.7.2",
162
125
  "typescript": "^6.0.3"
163
126
  },
164
127
  "peerDependencies": {
165
128
  "@cloudflare/react-native-webrtc": "~125.0.1 || ~125.0.3",
166
- "@cloudflare/realtimekit-react-native": "1.1.0",
167
- "@hugeicons/core-free-icons": "^4.0.0",
168
- "@hugeicons/react-native": "^1.0.13",
129
+ "expo-audio": "~55.0.18",
130
+ "expo-clipboard": "~55.0.9",
131
+ "expo-crypto": "~55.0.19",
132
+ "expo-document-picker": "~55.0.15",
133
+ "expo-file-system": "~55.0.24",
134
+ "expo-haptics": "~55.0.18",
169
135
  "react": "^18.0.0 || ^19.0.0",
170
136
  "react-native": ">=0.77",
137
+ "react-native-gesture-handler": "~2.30.1",
138
+ "react-native-reanimated": "4.2.1",
139
+ "react-native-safe-area-context": "~5.6.2",
171
140
  "react-native-svg": "^15.15.3",
172
- "react-native-view-shot": "^4.0.3",
173
- "react-native-webview": "^13.16.1"
141
+ "react-native-webview": "^13.16.1",
142
+ "react-native-worklets": "0.7.2"
174
143
  },
175
144
  "scripts": {
176
- "build": "rm -rf ./dist && tsup ./src/index.ts ./src/client.ts ./src/android.ts ./src/ios.ts ./src/ios-phone.ts ./src/ios-pad.ts ./src/macos.ts ./src/runtime.ts ./src/clipboard.ts ./src/diagnostics.ts ./src/invites.ts ./src/ui/theme.ts ./src/ui/appearance.ts --format esm --out-dir ./dist --platform browser --external react --external react-native --external react-native-webview --external react-native-view-shot --external @q9labsai/chalk-whiteboard --external @cloudflare/react-native-webrtc --external @cloudflare/realtimekit-react-native && pnpm run build:types && pnpm run sync:whiteboard-assets",
145
+ "build": "rm -rf ./dist && tsup ./src/index.ts ./src/client.ts ./src/runtime.ts ./src/clipboard.ts ./src/diagnostics.ts ./src/dev.ts ./src/invites.ts ./src/ui.ts --format esm --out-dir ./dist --platform browser --external react --external react-native --external react-native-webview --external @q9labsai/chalk-whiteboard --external @cloudflare/react-native-webrtc --external expo-audio --external expo-clipboard --external expo-crypto --external expo-document-picker --external expo-file-system --external expo-haptics --external react-native-gesture-handler --external react-native-reanimated --external react-native-safe-area-context --external react-native-svg --loader .wav=copy && pnpm run build:types && pnpm run sync:whiteboard-assets",
177
146
  "build:types": "rm -f tsconfig.tsbuildinfo && tsc --build tsconfig.json",
178
- "dev": "tsup ./src/index.ts ./src/client.ts ./src/android.ts ./src/ios.ts ./src/ios-phone.ts ./src/ios-pad.ts ./src/macos.ts ./src/runtime.ts ./src/clipboard.ts ./src/diagnostics.ts ./src/invites.ts ./src/ui/theme.ts ./src/ui/appearance.ts --format esm --out-dir ./dist --platform browser --external react --external react-native --external react-native-webview --external react-native-view-shot --external @q9labsai/chalk-whiteboard --external @cloudflare/react-native-webrtc --external @cloudflare/realtimekit-react-native --watch",
147
+ "dev": "tsup ./src/index.ts ./src/client.ts ./src/runtime.ts ./src/clipboard.ts ./src/diagnostics.ts ./src/dev.ts ./src/invites.ts ./src/ui.ts --format esm --out-dir ./dist --platform browser --external react --external react-native --external react-native-webview --external @q9labsai/chalk-whiteboard --external @cloudflare/react-native-webrtc --external expo-audio --external expo-clipboard --external expo-crypto --external expo-document-picker --external expo-file-system --external expo-haptics --external react-native-gesture-handler --external react-native-reanimated --external react-native-safe-area-context --external react-native-svg --loader .wav=copy --watch",
179
148
  "sync:whiteboard-assets": "node ./scripts/sync-whiteboard-assets.mjs",
180
149
  "test": "pnpm exec vitest run",
181
- "check-types": "tsc --project tsconfig.check-types.json --noEmit",
150
+ "check-types": "tsc-rs --project tsconfig.check-types.json --noEmit",
182
151
  "check:tokens": "node ./scripts/check-tokenized-styles.mjs",
152
+ "check:worklets": "node ./scripts/check-worklet-directives.mjs",
183
153
  "check:client-package": "node ./scripts/check-client-package.mjs",
184
- "lint": "pnpm run check:tokens && pnpm exec oxfmt --check . && tsc --project tsconfig.check-types.json --noEmit",
154
+ "lint": "pnpm run check:tokens && pnpm run check:worklets && pnpm exec oxfmt --check . && tsc --project tsconfig.check-types.json --noEmit",
185
155
  "clean": "rm -rf dist"
186
156
  }
187
157
  }
@@ -0,0 +1,19 @@
1
+ import { NativeModules, Platform } from "react-native";
2
+
3
+ type NativeCallServiceModule = {
4
+ readonly start: () => Promise<boolean>;
5
+ readonly stop: () => Promise<void>;
6
+ };
7
+
8
+ const nativeModule: NativeCallServiceModule | undefined = NativeModules.ChalkCallService;
9
+
10
+ /** Starts the Android foreground service for the call. Resolves false when there's nothing to keep running (no microphone or camera permission) or Android refused the start. */
11
+ export async function startAndroidCallService(): Promise<boolean> {
12
+ if (Platform.OS !== "android" || !nativeModule) return false;
13
+ return nativeModule.start();
14
+ }
15
+
16
+ export async function stopAndroidCallService(): Promise<void> {
17
+ if (Platform.OS !== "android" || !nativeModule) return;
18
+ await nativeModule.stop();
19
+ }
@@ -0,0 +1,145 @@
1
+ import { createFacehashScene, getColor, getForegroundColor, type Intensity3D } from "@q9labsai/facehash";
2
+ import { memo, useCallback, useEffect, useMemo } from "react";
3
+ import { Platform, StyleSheet, View } from "react-native";
4
+ import Animated, { cancelAnimation, useAnimatedStyle, useReducedMotion, useSharedValue, withDelay, withRepeat, withSequence, withTiming, type SharedValue } from "react-native-reanimated";
5
+ import Svg, { G, Path, Text as SvgText } from "react-native-svg";
6
+ import { timings } from "../motion/motion";
7
+ import { easings, identityColors } from "../theme/tokens";
8
+
9
+ export type FaceAvatarProps = {
10
+ readonly name: string;
11
+ readonly size: number;
12
+ /** `bold` is the 3D style for tiles; `subtle` is for rows, pills, chat and toasts. */
13
+ readonly style?: "bold" | "subtle";
14
+ /** Live speaking level from 0 to 1. While it moves, the face bobs and the mouth opens. */
15
+ readonly level?: SharedValue<number>;
16
+ /** Eyes drift on their own every 1.8 s, as on the mockup's touch devices. Off for small avatars. */
17
+ readonly lookAround?: boolean;
18
+ readonly testID?: string;
19
+ };
20
+
21
+ const INTENSITY: Readonly<Record<"bold" | "subtle", Intensity3D>> = { bold: "dramatic", subtle: "subtle" };
22
+ const MONO = Platform.select({ ios: "Menlo", default: "monospace" });
23
+ const FRONT_HOLD_MS = 1400;
24
+ const LOOK_INTERVAL_MS = 1800;
25
+ const LOOK_MS = 700;
26
+ const BOB = 5;
27
+ const MOUTH = 0.55;
28
+ const CLOSED = 0.05;
29
+
30
+ /**
31
+ * A Facehash avatar drawn natively. The face blinks on its own rhythm, reacts to the speaking
32
+ * level, and turns to the front for a moment when touched. All motion runs on the UI thread and
33
+ * stops with reduced motion. Decorative: the parent names the person.
34
+ */
35
+ export const FaceAvatar = memo(function FaceAvatar({ name, size, style = "subtle", level, lookAround = false, testID }: FaceAvatarProps): React.JSX.Element {
36
+ const reduceMotion = useReducedMotion();
37
+ const scene = useMemo(() => createFacehashScene({ name, colorsLength: identityColors.length, intensity3d: INTENSITY[style] }), [name, style]);
38
+ const background = getColor(identityColors, scene.data.colorIndex);
39
+ const foreground = getForegroundColor(background);
40
+ const geometry = scene.faceGeometry;
41
+ const box = scene.faceBox;
42
+ const eyeCenter = box.y + geometry.leftEyeAnchor.y * (box.height / geometry.viewBox.height);
43
+ const unit = size / 100;
44
+ const projection = scene.projection;
45
+
46
+ const turned = useSharedValue(1);
47
+ const blink = useSharedValue(1);
48
+ const lookX = useSharedValue(0);
49
+ const lookY = useSharedValue(0);
50
+
51
+ useEffect(() => {
52
+ if (reduceMotion) {
53
+ blink.value = 1;
54
+ return;
55
+ }
56
+ const { delay, duration } = scene.data.blinkTimings.left;
57
+ const total = duration * 1000;
58
+ const close = { duration: total * 0.04, easing: easings.standard };
59
+ blink.value = withDelay(delay * 1000, withRepeat(withSequence(withDelay(total * 0.92, withTiming(CLOSED, close)), withTiming(1, close)), -1));
60
+ return () => cancelAnimation(blink);
61
+ }, [blink, reduceMotion, scene]);
62
+
63
+ useEffect(() => {
64
+ if (!lookAround || reduceMotion) return;
65
+ const timer = setInterval(() => {
66
+ if (Math.random() < 0.5 || turned.value < 1) return;
67
+ lookX.value = withTiming((Math.random() * 2 - 1) * 6, { duration: LOOK_MS, easing: easings.standard });
68
+ lookY.value = withTiming((Math.random() * 2 - 1) * 4, { duration: LOOK_MS, easing: easings.standard });
69
+ }, LOOK_INTERVAL_MS);
70
+ return () => clearInterval(timer);
71
+ }, [lookAround, lookX, lookY, reduceMotion, turned]);
72
+
73
+ const turnToFront = useCallback(() => {
74
+ if (reduceMotion) return;
75
+ turned.value = withSequence(withTiming(0, timings.avatarTurn), withDelay(FRONT_HOLD_MS, withTiming(1, timings.avatarTurn)));
76
+ lookX.value = withTiming(0, { duration: 250, easing: easings.standard });
77
+ lookY.value = withTiming(0, { duration: 250, easing: easings.standard });
78
+ blink.value = withSequence(withTiming(CLOSED, { duration: 150, easing: easings.standard }), withTiming(1, { duration: 150, easing: easings.standard }));
79
+ }, [blink, lookX, lookY, reduceMotion, turned]);
80
+
81
+ const bobStyle = useAnimatedStyle(() => {
82
+ "worklet";
83
+ return { transform: [{ translateY: level ? -level.value * BOB * unit : 0 }] };
84
+ });
85
+ const poseStyle = useAnimatedStyle(() => {
86
+ "worklet";
87
+ const t = turned.value;
88
+ return {
89
+ transform: [{ translateX: projection.translateX * unit * t }, { translateY: projection.translateY * unit * t }, { skewX: `${projection.skewX * t}deg` }, { skewY: `${projection.skewY * t}deg` }, { scaleX: 1 + (projection.scaleX - 1) * t }, { scaleY: 1 + (projection.scaleY - 1) * t }],
90
+ };
91
+ });
92
+ const eyesLookStyle = useAnimatedStyle(() => {
93
+ "worklet";
94
+ return { transform: [{ translateX: lookX.value * unit }, { translateY: lookY.value * unit }] };
95
+ });
96
+ const mouthLookStyle = useAnimatedStyle(() => {
97
+ "worklet";
98
+ return { transform: [{ translateX: (lookX.value / 2) * unit }, { translateY: (lookY.value / 2) * unit }] };
99
+ });
100
+ const blinkStyle = useAnimatedStyle(() => {
101
+ "worklet";
102
+ return { transform: [{ scaleY: blink.value }] };
103
+ });
104
+ const mouthStyle = useAnimatedStyle(() => {
105
+ "worklet";
106
+ return { transform: [{ scaleY: 1 + (level ? level.value : 0) * MOUTH }] };
107
+ });
108
+
109
+ const faceTransform = `translate(${box.x} ${box.y}) scale(${box.width / geometry.viewBox.width} ${box.height / geometry.viewBox.height})`;
110
+
111
+ return (
112
+ <View onTouchStart={turnToFront} style={[styles.circle, { width: size, height: size, borderRadius: size / 2, backgroundColor: background }]} testID={testID}>
113
+ <Animated.View style={[StyleSheet.absoluteFill, bobStyle]}>
114
+ <Animated.View style={[StyleSheet.absoluteFill, poseStyle]}>
115
+ <Animated.View style={[StyleSheet.absoluteFill, eyesLookStyle]}>
116
+ <Animated.View style={[StyleSheet.absoluteFill, { transformOrigin: `50% ${eyeCenter}%` }, blinkStyle]}>
117
+ <Svg height={size} viewBox="0 0 100 100" width={size}>
118
+ <G transform={faceTransform}>
119
+ {[...geometry.leftEyePaths, ...geometry.rightEyePaths].map((d) => (
120
+ <Path d={d} fill={foreground} key={d} />
121
+ ))}
122
+ </G>
123
+ </Svg>
124
+ </Animated.View>
125
+ </Animated.View>
126
+ <Animated.View style={[StyleSheet.absoluteFill, mouthLookStyle]}>
127
+ <Animated.View style={[StyleSheet.absoluteFill, styles.mouthOrigin, mouthStyle]}>
128
+ <Svg height={size} viewBox="0 0 100 100" width={size}>
129
+ <SvgText alignmentBaseline="middle" fill={foreground} fontFamily={MONO} fontSize={scene.initialLayout.fontSize} fontWeight="700" textAnchor="middle" x={scene.initialLayout.x} y={scene.initialLayout.y}>
130
+ {scene.data.initial}
131
+ </SvgText>
132
+ </Svg>
133
+ </Animated.View>
134
+ </Animated.View>
135
+ </Animated.View>
136
+ </Animated.View>
137
+ </View>
138
+ );
139
+ });
140
+
141
+ const styles = StyleSheet.create({
142
+ circle: { overflow: "hidden" },
143
+ // The initial sits on y = 70 with a 26-unit font, so its baseline is near y = 79.
144
+ mouthOrigin: { transformOrigin: "50% 79%" },
145
+ });
@@ -0,0 +1,4 @@
1
+ /** A camera-off tile's avatar is 42 % of the tile's shorter side, between 32 and 150 pt. */
2
+ export function tileAvatarSize(width: number, height: number): number {
3
+ return Math.round(Math.min(150, Math.max(32, Math.min(width, height) * 0.42)));
4
+ }
package/src/client.ts CHANGED
@@ -1,7 +1,3 @@
1
- /**
2
- * Native implementation seam for advanced construction. The turnkey root
3
- * remains `Chalk`; applications that need direct lifecycle ownership can
4
- * create the React Native SpaceClient through this explicit subpath.
5
- */
1
+ /** Native client construction for applications that own the call lifecycle. */
6
2
  export { createNativeSpaceClient } from "./space-client/create-native-space-client";
7
3
  export type { NativeSpaceClientOptions } from "./space-client/create-native-space-client";
@@ -1,9 +1,8 @@
1
1
  import { ChalkWhiteboardController, type ChalkEmbeddedWhiteboardTransport, type ChalkEmbeddedWhiteboardViewport } from "@q9labsai/chalk-whiteboard/embedded";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- import { ActivityIndicator, Pressable, StyleSheet, Text, useWindowDimensions, View, type LayoutChangeEvent, type StyleProp, type ViewStyle } from "react-native";
3
+ import { ActivityIndicator, Pressable, Text, useWindowDimensions, View, type LayoutChangeEvent, type StyleProp, type ViewStyle } from "react-native";
4
4
  import WebView, { type WebViewMessageEvent, type WebViewNavigation } from "react-native-webview";
5
5
 
6
- import { useNativeTheme } from "../ui/native-theme";
7
6
  import { isEmbeddedWhiteboardNavigationAllowed, rendererURLWithContext, resolveEmbeddedWhiteboardRendererURL } from "../whiteboard/embedded-whiteboard-assets";
8
7
  import { createEmbeddedWhiteboardViewport } from "../whiteboard/embedded-whiteboard-viewport";
9
8
 
@@ -39,8 +38,7 @@ export const embeddedWhiteboardWebViewSecurityPolicy = Object.freeze({
39
38
  });
40
39
 
41
40
  export function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, canDraw, canClear, theme: themeOverride, localParticipantColor, rendererURL: rendererURLOverride, style, testID, onMetric, onError, onUserExport }: EmbeddedWhiteboardProps): React.JSX.Element {
42
- const nativeTheme = useNativeTheme();
43
- const theme = themeOverride ?? nativeTheme.colorScheme;
41
+ const theme = themeOverride ?? "light";
44
42
  const webViewRef = useRef<WebView>(null);
45
43
  const controllerRef = useRef<ChalkWhiteboardController | null>(null);
46
44
  const listenersRef = useRef(new Set<(message: string) => void>());
@@ -158,26 +156,26 @@ export function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracesta
158
156
 
159
157
  if (loadError) {
160
158
  return (
161
- <View style={[styles.status, { backgroundColor: nativeTheme.colors.lightSurface }, style]} testID={testID}>
162
- <Text style={[styles.errorTitle, { color: nativeTheme.colors.lightText }]}>Whiteboard unavailable</Text>
163
- <Text style={[styles.errorMessage, { color: nativeTheme.colors.lightSubtleText }]}>{loadError}</Text>
164
- <Pressable accessibilityRole="button" onPress={retryRenderer} style={({ pressed }) => [styles.retryButton, { backgroundColor: nativeTheme.colors.info }, pressed && styles.retryButtonPressed]}>
165
- <Text style={[styles.retryButtonText, { color: nativeTheme.colors.onDark }]}>Retry</Text>
159
+ <View style={[{ flex: 1 }, style]} testID={testID}>
160
+ <Text>Whiteboard unavailable</Text>
161
+ <Text>{loadError}</Text>
162
+ <Pressable accessibilityRole="button" onPress={retryRenderer}>
163
+ <Text>Retry</Text>
166
164
  </Pressable>
167
165
  </View>
168
166
  );
169
167
  }
170
168
  if (!sourceURL || !rendererURL) {
171
169
  return (
172
- <View style={[styles.status, { backgroundColor: nativeTheme.colors.lightSurface }, style]} testID={testID}>
173
- <ActivityIndicator color={nativeTheme.colors.info} />
174
- <Text style={[styles.loadingMessage, { color: nativeTheme.colors.lightMutedText }]}>Loading whiteboard…</Text>
170
+ <View style={[{ flex: 1 }, style]} testID={testID}>
171
+ <ActivityIndicator />
172
+ <Text>Loading whiteboard…</Text>
175
173
  </View>
176
174
  );
177
175
  }
178
176
 
179
177
  return (
180
- <View onLayout={handleLayout} style={[styles.container, style]} testID={testID}>
178
+ <View onLayout={handleLayout} style={[{ flex: 1 }, style]} testID={testID}>
181
179
  <WebView
182
180
  key={rendererGeneration}
183
181
  ref={webViewRef}
@@ -197,12 +195,12 @@ export function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracesta
197
195
  pullToRefreshEnabled={false}
198
196
  scrollEnabled={false}
199
197
  source={{ uri: sourceURL }}
200
- style={[styles.webView, { backgroundColor: nativeTheme.colors.lightSurface }]}
198
+ style={{ flex: 1 }}
201
199
  webviewDebuggingEnabled={typeof __DEV__ !== "undefined" && __DEV__}
202
200
  />
203
201
  {compatibilityNotice ? (
204
- <View pointerEvents="none" style={[styles.compatibilityNotice, { backgroundColor: nativeTheme.colors.dangerSurfaceOverlay94 }]}>
205
- <Text style={[styles.compatibilityNoticeText, { color: nativeTheme.colors.onDark }]}>{compatibilityNotice}</Text>
202
+ <View pointerEvents="none">
203
+ <Text>{compatibilityNotice}</Text>
206
204
  </View>
207
205
  ) : null}
208
206
  </View>
@@ -212,58 +210,3 @@ export function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracesta
212
210
  function createRendererGeneration(): string {
213
211
  return globalThis.crypto?.randomUUID?.() ?? `whiteboard-${Date.now()}-${Math.random().toString(36).slice(2)}`;
214
212
  }
215
-
216
- const styles = StyleSheet.create({
217
- container: {
218
- flex: 1,
219
- overflow: "hidden",
220
- },
221
- webView: {
222
- flex: 1,
223
- },
224
- compatibilityNotice: {
225
- position: "absolute",
226
- top: 12,
227
- left: 12,
228
- right: 12,
229
- borderRadius: 10,
230
- paddingHorizontal: 12,
231
- paddingVertical: 10,
232
- },
233
- compatibilityNoticeText: {
234
- fontSize: 13,
235
- fontWeight: "700",
236
- textAlign: "center",
237
- },
238
- status: {
239
- flex: 1,
240
- alignItems: "center",
241
- justifyContent: "center",
242
- gap: 10,
243
- padding: 24,
244
- },
245
- loadingMessage: {
246
- fontSize: 14,
247
- fontWeight: "600",
248
- },
249
- errorTitle: {
250
- fontSize: 17,
251
- fontWeight: "700",
252
- },
253
- errorMessage: {
254
- fontSize: 13,
255
- textAlign: "center",
256
- },
257
- retryButton: {
258
- borderRadius: 8,
259
- paddingHorizontal: 16,
260
- paddingVertical: 10,
261
- },
262
- retryButtonPressed: {
263
- opacity: 0.75,
264
- },
265
- retryButtonText: {
266
- fontSize: 14,
267
- fontWeight: "700",
268
- },
269
- });
@@ -1,7 +1,6 @@
1
- import type { NativeParticipant as Participant } from "../ui/native-types";
2
1
  import type { NativeMediaStreamTrack } from "../media/native-webrtc";
3
2
 
4
- export function shouldRenderNativeMediaTrack({ participant, track, mediaKind = "camera" }: { participant: Participant | null; track: MediaStreamTrack | NativeMediaStreamTrack | null | undefined; mediaKind?: "camera" | "screen-share" }): boolean {
3
+ export function shouldRenderNativeMediaTrack({ participant, track, mediaKind = "camera" }: { participant: { readonly videoEnabled: boolean } | null; track: MediaStreamTrack | NativeMediaStreamTrack | null | undefined; mediaKind?: "camera" | "screen-share" }): boolean {
5
4
  if (!track) {
6
5
  return false;
7
6
  }
@@ -0,0 +1,41 @@
1
+ import { useEffect } from "react";
2
+ import { AppState } from "react-native";
3
+ import { startAndroidCallService, stopAndroidCallService } from "../android/call-service";
4
+ import { useConnection, useMedia } from "../hooks/space-hooks";
5
+
6
+ /**
7
+ * Runs the Android foreground service for as long as the person is in the call, so the microphone
8
+ * and camera keep working in the background. It starts again when the microphone or camera turns on,
9
+ * because that's when the person has granted the permission the service declares, and on every return
10
+ * to the foreground, because Android can refuse a start made while the app is in the background.
11
+ */
12
+ export function useAndroidCallService(): void {
13
+ const connection = useConnection();
14
+ const media = useMedia();
15
+ const inCall = connection.status === "live" || connection.status === "reconnecting";
16
+ const microphoneOn = media.local.microphone.state === "enabled";
17
+ const cameraOn = media.local.camera.state === "enabled";
18
+
19
+ useEffect(() => {
20
+ if (!inCall) return;
21
+ const start = () => {
22
+ startAndroidCallService().catch((error: unknown) => {
23
+ console.warn("Failed to start the Android call service", error);
24
+ });
25
+ };
26
+ start();
27
+ const subscription = AppState.addEventListener("change", (state) => {
28
+ if (state === "active") start();
29
+ });
30
+ return () => subscription.remove();
31
+ }, [inCall, microphoneOn, cameraOn]);
32
+
33
+ useEffect(() => {
34
+ if (!inCall) return;
35
+ return () => {
36
+ stopAndroidCallService().catch((error: unknown) => {
37
+ console.warn("Failed to stop the Android call service", error);
38
+ });
39
+ };
40
+ }, [inCall]);
41
+ }