stream-chat-react-native-core 10.0.0-rc.2 → 10.0.0-rc.4

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 (527) hide show
  1. package/lib/commonjs/ai-components/README.md +50 -2
  2. package/lib/commonjs/ai-components/index.js +24 -0
  3. package/lib/commonjs/ai-components/index.js.map +1 -1
  4. package/lib/commonjs/ai-components/message-composer/ComposerView.js +4 -2
  5. package/lib/commonjs/ai-components/message-composer/ComposerView.js.map +1 -1
  6. package/lib/commonjs/ai-components/message-composer/SpeechToTextButton.js +4 -1
  7. package/lib/commonjs/ai-components/message-composer/SpeechToTextButton.js.map +1 -1
  8. package/lib/commonjs/ai-components/native/AIDictation.js +6 -0
  9. package/lib/commonjs/ai-components/native/AIDictation.js.map +1 -1
  10. package/lib/commonjs/ai-components/store/dictation/store.js +4 -2
  11. package/lib/commonjs/ai-components/store/dictation/store.js.map +1 -1
  12. package/lib/commonjs/ai-components/store/dictation/useDictationState.js +4 -2
  13. package/lib/commonjs/ai-components/store/dictation/useDictationState.js.map +1 -1
  14. package/lib/commonjs/ai-components/store/index.js +22 -0
  15. package/lib/commonjs/ai-components/store/index.js.map +1 -1
  16. package/lib/commonjs/ai-components/theme.js +3 -0
  17. package/lib/commonjs/ai-components/theme.js.map +1 -1
  18. package/lib/commonjs/ai-components/transcription/useDictation.js +7 -3
  19. package/lib/commonjs/ai-components/transcription/useDictation.js.map +1 -1
  20. package/lib/commonjs/ai-components/transcription/useDictationAudioLevel.js +32 -0
  21. package/lib/commonjs/ai-components/transcription/useDictationAudioLevel.js.map +1 -0
  22. package/lib/commonjs/ai-components/voice-visualization/VoiceGlow.js +79 -0
  23. package/lib/commonjs/ai-components/voice-visualization/VoiceGlow.js.map +1 -0
  24. package/lib/commonjs/ai-components/voice-visualization/VoiceVisualizationView.js +147 -0
  25. package/lib/commonjs/ai-components/voice-visualization/VoiceVisualizationView.js.map +1 -0
  26. package/lib/commonjs/ai-components/voice-visualization/VoiceWave.js +58 -0
  27. package/lib/commonjs/ai-components/voice-visualization/VoiceWave.js.map +1 -0
  28. package/lib/commonjs/ai-components/voice-visualization/bounce.js +60 -0
  29. package/lib/commonjs/ai-components/voice-visualization/bounce.js.map +1 -0
  30. package/lib/commonjs/ai-components/voice-visualization/driver.js +208 -0
  31. package/lib/commonjs/ai-components/voice-visualization/driver.js.map +1 -0
  32. package/lib/commonjs/ai-components/voice-visualization/glowShader.js +218 -0
  33. package/lib/commonjs/ai-components/voice-visualization/glowShader.js.map +1 -0
  34. package/lib/commonjs/ai-components/voice-visualization/index.js +18 -0
  35. package/lib/commonjs/ai-components/voice-visualization/index.js.map +1 -0
  36. package/lib/commonjs/ai-components/voice-visualization/math.js +70 -0
  37. package/lib/commonjs/ai-components/voice-visualization/math.js.map +1 -0
  38. package/lib/commonjs/ai-components/voice-visualization/palette.js +47 -0
  39. package/lib/commonjs/ai-components/voice-visualization/palette.js.map +1 -0
  40. package/lib/commonjs/ai-components/voice-visualization/simplex.js +77 -0
  41. package/lib/commonjs/ai-components/voice-visualization/simplex.js.map +1 -0
  42. package/lib/commonjs/ai-components/voice-visualization/styles.js +33 -0
  43. package/lib/commonjs/ai-components/voice-visualization/styles.js.map +1 -0
  44. package/lib/commonjs/ai-components/voice-visualization/types.js +4 -0
  45. package/lib/commonjs/ai-components/voice-visualization/types.js.map +1 -0
  46. package/lib/commonjs/ai-components/voice-visualization/useReduceMotion.js +28 -0
  47. package/lib/commonjs/ai-components/voice-visualization/useReduceMotion.js.map +1 -0
  48. package/lib/commonjs/ai-components/voice-visualization/useVoiceVisualization.js +129 -0
  49. package/lib/commonjs/ai-components/voice-visualization/useVoiceVisualization.js.map +1 -0
  50. package/lib/commonjs/ai-components/voice-visualization/waveGeometry.js +124 -0
  51. package/lib/commonjs/ai-components/voice-visualization/waveGeometry.js.map +1 -0
  52. package/lib/commonjs/components/Channel/Channel.js +1 -0
  53. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  54. package/lib/commonjs/components/Channel/ChannelShell.js +8 -1
  55. package/lib/commonjs/components/Channel/ChannelShell.js.map +1 -1
  56. package/lib/commonjs/components/Channel/hooks/useChannelLifecycle.js +2 -1
  57. package/lib/commonjs/components/Channel/hooks/useChannelLifecycle.js.map +1 -1
  58. package/lib/commonjs/components/Channel/hooks/useJumpToLatestOnOpen.js +26 -0
  59. package/lib/commonjs/components/Channel/hooks/useJumpToLatestOnOpen.js.map +1 -0
  60. package/lib/commonjs/components/ChannelDetails/components/members/ChannelMemberItem.js +1 -1
  61. package/lib/commonjs/components/ChannelDetails/components/members/ChannelMemberItem.js.map +1 -1
  62. package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsMemberStatusText.js +1 -1
  63. package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsMemberStatusText.js.map +1 -1
  64. package/lib/commonjs/components/ChannelList/ChannelListView.js +0 -2
  65. package/lib/commonjs/components/ChannelList/ChannelListView.js.map +1 -1
  66. package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js +2 -2
  67. package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
  68. package/lib/commonjs/components/ChannelPreview/ChannelDetailsBottomSheet.js +1 -1
  69. package/lib/commonjs/components/ChannelPreview/ChannelDetailsBottomSheet.js.map +1 -1
  70. package/lib/commonjs/components/ChannelPreview/ChannelLastMessagePreview.js +1 -0
  71. package/lib/commonjs/components/ChannelPreview/ChannelLastMessagePreview.js.map +1 -1
  72. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +2 -0
  73. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  74. package/lib/commonjs/components/ChannelPreview/ChannelPreviewTitle.js +1 -0
  75. package/lib/commonjs/components/ChannelPreview/ChannelPreviewTitle.js.map +1 -1
  76. package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js +1 -1
  77. package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
  78. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js +5 -5
  79. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -1
  80. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js +1 -1
  81. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js.map +1 -1
  82. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.js +1 -1
  83. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.js.map +1 -1
  84. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewPollLabel.js +4 -1
  85. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewPollLabel.js.map +1 -1
  86. package/lib/commonjs/components/Chat/hooks/useConnectionLifecycle.js +6 -2
  87. package/lib/commonjs/components/Chat/hooks/useConnectionLifecycle.js.map +1 -1
  88. package/lib/commonjs/components/Indicators/LoadingErrorIndicator.js +5 -0
  89. package/lib/commonjs/components/Indicators/LoadingErrorIndicator.js.map +1 -1
  90. package/lib/commonjs/components/Message/Message.js +1 -1
  91. package/lib/commonjs/components/Message/Message.js.map +1 -1
  92. package/lib/commonjs/components/Message/MessageItemView/MessageStatus.js +4 -0
  93. package/lib/commonjs/components/Message/MessageItemView/MessageStatus.js.map +1 -1
  94. package/lib/commonjs/components/Message/MessageItemView/MessageWrapper.js +7 -4
  95. package/lib/commonjs/components/Message/MessageItemView/MessageWrapper.js.map +1 -1
  96. package/lib/commonjs/components/Message/hooks/useCreateMessageActionHandlers.js +3 -3
  97. package/lib/commonjs/components/Message/hooks/useCreateMessageActionHandlers.js.map +1 -1
  98. package/lib/commonjs/components/Message/hooks/useProcessReactions.js +2 -2
  99. package/lib/commonjs/components/Message/hooks/useProcessReactions.js.map +1 -1
  100. package/lib/commonjs/components/Message/hooks/useUserMuteActive.js +1 -1
  101. package/lib/commonjs/components/Message/hooks/useUserMuteActive.js.map +1 -1
  102. package/lib/commonjs/components/MessageInput/MessageComposer.js +2 -1
  103. package/lib/commonjs/components/MessageInput/MessageComposer.js.map +1 -1
  104. package/lib/commonjs/components/MessageList/MessageFlashList.js +2 -2
  105. package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
  106. package/lib/commonjs/components/MessageList/MessageList.js +2 -2
  107. package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
  108. package/lib/commonjs/components/MessageList/hooks/useOwnUnreadCount.js +1 -1
  109. package/lib/commonjs/components/MessageList/hooks/useOwnUnreadCount.js.map +1 -1
  110. package/lib/commonjs/components/MessageMenu/MessageUserReactionsItem.js +1 -1
  111. package/lib/commonjs/components/MessageMenu/MessageUserReactionsItem.js.map +1 -1
  112. package/lib/commonjs/components/MessageMenu/hooks/useMessageOwnReactions.js +2 -2
  113. package/lib/commonjs/components/MessageMenu/hooks/useMessageOwnReactions.js.map +1 -1
  114. package/lib/commonjs/components/Poll/components/PollAnswersList.js +1 -1
  115. package/lib/commonjs/components/Poll/components/PollAnswersList.js.map +1 -1
  116. package/lib/commonjs/components/Poll/components/PollButtons.js +1 -1
  117. package/lib/commonjs/components/Poll/components/PollButtons.js.map +1 -1
  118. package/lib/commonjs/components/Poll/hook/useIsPollCreatedByCurrentUser.js +1 -1
  119. package/lib/commonjs/components/Poll/hook/useIsPollCreatedByCurrentUser.js.map +1 -1
  120. package/lib/commonjs/components/Thread/Thread.js +1 -1
  121. package/lib/commonjs/components/Thread/Thread.js.map +1 -1
  122. package/lib/commonjs/components/ThreadList/ThreadListItem.js +1 -1
  123. package/lib/commonjs/components/ThreadList/ThreadListItem.js.map +1 -1
  124. package/lib/commonjs/components/ThreadList/ThreadListUnreadBanner.js +9 -2
  125. package/lib/commonjs/components/ThreadList/ThreadListUnreadBanner.js.map +1 -1
  126. package/lib/commonjs/components/index.js +36 -0
  127. package/lib/commonjs/components/index.js.map +1 -1
  128. package/lib/commonjs/contexts/componentsContext/defaultComponents.js +0 -2
  129. package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
  130. package/lib/commonjs/contexts/liveLocationManagerContext/LiveLocationManagerContext.js +1 -1
  131. package/lib/commonjs/contexts/liveLocationManagerContext/LiveLocationManagerContext.js.map +1 -1
  132. package/lib/commonjs/hooks/actions/useChannelActionItems.js +1 -1
  133. package/lib/commonjs/hooks/actions/useChannelActionItems.js.map +1 -1
  134. package/lib/commonjs/hooks/actions/useChannelActions.js +2 -2
  135. package/lib/commonjs/hooks/actions/useChannelActions.js.map +1 -1
  136. package/lib/commonjs/hooks/actions/useChannelMemberActionItems.js +1 -1
  137. package/lib/commonjs/hooks/actions/useChannelMemberActionItems.js.map +1 -1
  138. package/lib/commonjs/hooks/index.js +11 -0
  139. package/lib/commonjs/hooks/index.js.map +1 -1
  140. package/lib/commonjs/hooks/messagePreview/useMessageDeliveryStatus.js +6 -6
  141. package/lib/commonjs/hooks/messagePreview/useMessageDeliveryStatus.js.map +1 -1
  142. package/lib/commonjs/hooks/useIsDirectChat.js +1 -1
  143. package/lib/commonjs/hooks/useIsDirectChat.js.map +1 -1
  144. package/lib/commonjs/i18n/runtimeDefaults.js +1 -0
  145. package/lib/commonjs/i18n/runtimeDefaults.js.map +1 -1
  146. package/lib/commonjs/store/apis/getChannelMessages.js +5 -3
  147. package/lib/commonjs/store/apis/getChannelMessages.js.map +1 -1
  148. package/lib/commonjs/store/apis/getChannels.js +6 -3
  149. package/lib/commonjs/store/apis/getChannels.js.map +1 -1
  150. package/lib/commonjs/store/apis/getChannelsForFilterSort.js +2 -1
  151. package/lib/commonjs/store/apis/getChannelsForFilterSort.js.map +1 -1
  152. package/lib/commonjs/store/apis/queries/selectMessagesForChannels.js +7 -5
  153. package/lib/commonjs/store/apis/queries/selectMessagesForChannels.js.map +1 -1
  154. package/lib/commonjs/utils/installNativeMultipartAdapter.js.map +1 -1
  155. package/lib/commonjs/utils/setupCommandUIMiddlewares.js +6 -3
  156. package/lib/commonjs/utils/setupCommandUIMiddlewares.js.map +1 -1
  157. package/lib/commonjs/version.json +1 -1
  158. package/lib/module/ai-components/README.md +50 -2
  159. package/lib/module/ai-components/index.js +24 -0
  160. package/lib/module/ai-components/index.js.map +1 -1
  161. package/lib/module/ai-components/message-composer/ComposerView.js +4 -2
  162. package/lib/module/ai-components/message-composer/ComposerView.js.map +1 -1
  163. package/lib/module/ai-components/message-composer/SpeechToTextButton.js +4 -1
  164. package/lib/module/ai-components/message-composer/SpeechToTextButton.js.map +1 -1
  165. package/lib/module/ai-components/native/AIDictation.js +6 -0
  166. package/lib/module/ai-components/native/AIDictation.js.map +1 -1
  167. package/lib/module/ai-components/store/dictation/store.js +4 -2
  168. package/lib/module/ai-components/store/dictation/store.js.map +1 -1
  169. package/lib/module/ai-components/store/dictation/useDictationState.js +4 -2
  170. package/lib/module/ai-components/store/dictation/useDictationState.js.map +1 -1
  171. package/lib/module/ai-components/store/index.js +22 -0
  172. package/lib/module/ai-components/store/index.js.map +1 -1
  173. package/lib/module/ai-components/theme.js +3 -0
  174. package/lib/module/ai-components/theme.js.map +1 -1
  175. package/lib/module/ai-components/transcription/useDictation.js +7 -3
  176. package/lib/module/ai-components/transcription/useDictation.js.map +1 -1
  177. package/lib/module/ai-components/transcription/useDictationAudioLevel.js +32 -0
  178. package/lib/module/ai-components/transcription/useDictationAudioLevel.js.map +1 -0
  179. package/lib/module/ai-components/voice-visualization/VoiceGlow.js +79 -0
  180. package/lib/module/ai-components/voice-visualization/VoiceGlow.js.map +1 -0
  181. package/lib/module/ai-components/voice-visualization/VoiceVisualizationView.js +147 -0
  182. package/lib/module/ai-components/voice-visualization/VoiceVisualizationView.js.map +1 -0
  183. package/lib/module/ai-components/voice-visualization/VoiceWave.js +58 -0
  184. package/lib/module/ai-components/voice-visualization/VoiceWave.js.map +1 -0
  185. package/lib/module/ai-components/voice-visualization/bounce.js +60 -0
  186. package/lib/module/ai-components/voice-visualization/bounce.js.map +1 -0
  187. package/lib/module/ai-components/voice-visualization/driver.js +208 -0
  188. package/lib/module/ai-components/voice-visualization/driver.js.map +1 -0
  189. package/lib/module/ai-components/voice-visualization/glowShader.js +218 -0
  190. package/lib/module/ai-components/voice-visualization/glowShader.js.map +1 -0
  191. package/lib/module/ai-components/voice-visualization/index.js +18 -0
  192. package/lib/module/ai-components/voice-visualization/index.js.map +1 -0
  193. package/lib/module/ai-components/voice-visualization/math.js +70 -0
  194. package/lib/module/ai-components/voice-visualization/math.js.map +1 -0
  195. package/lib/module/ai-components/voice-visualization/palette.js +47 -0
  196. package/lib/module/ai-components/voice-visualization/palette.js.map +1 -0
  197. package/lib/module/ai-components/voice-visualization/simplex.js +77 -0
  198. package/lib/module/ai-components/voice-visualization/simplex.js.map +1 -0
  199. package/lib/module/ai-components/voice-visualization/styles.js +33 -0
  200. package/lib/module/ai-components/voice-visualization/styles.js.map +1 -0
  201. package/lib/module/ai-components/voice-visualization/types.js +4 -0
  202. package/lib/module/ai-components/voice-visualization/types.js.map +1 -0
  203. package/lib/module/ai-components/voice-visualization/useReduceMotion.js +28 -0
  204. package/lib/module/ai-components/voice-visualization/useReduceMotion.js.map +1 -0
  205. package/lib/module/ai-components/voice-visualization/useVoiceVisualization.js +129 -0
  206. package/lib/module/ai-components/voice-visualization/useVoiceVisualization.js.map +1 -0
  207. package/lib/module/ai-components/voice-visualization/waveGeometry.js +124 -0
  208. package/lib/module/ai-components/voice-visualization/waveGeometry.js.map +1 -0
  209. package/lib/module/components/Channel/Channel.js +1 -0
  210. package/lib/module/components/Channel/Channel.js.map +1 -1
  211. package/lib/module/components/Channel/ChannelShell.js +8 -1
  212. package/lib/module/components/Channel/ChannelShell.js.map +1 -1
  213. package/lib/module/components/Channel/hooks/useChannelLifecycle.js +2 -1
  214. package/lib/module/components/Channel/hooks/useChannelLifecycle.js.map +1 -1
  215. package/lib/module/components/Channel/hooks/useJumpToLatestOnOpen.js +26 -0
  216. package/lib/module/components/Channel/hooks/useJumpToLatestOnOpen.js.map +1 -0
  217. package/lib/module/components/ChannelDetails/components/members/ChannelMemberItem.js +1 -1
  218. package/lib/module/components/ChannelDetails/components/members/ChannelMemberItem.js.map +1 -1
  219. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsMemberStatusText.js +1 -1
  220. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsMemberStatusText.js.map +1 -1
  221. package/lib/module/components/ChannelList/ChannelListView.js +0 -2
  222. package/lib/module/components/ChannelList/ChannelListView.js.map +1 -1
  223. package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js +2 -2
  224. package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
  225. package/lib/module/components/ChannelPreview/ChannelDetailsBottomSheet.js +1 -1
  226. package/lib/module/components/ChannelPreview/ChannelDetailsBottomSheet.js.map +1 -1
  227. package/lib/module/components/ChannelPreview/ChannelLastMessagePreview.js +1 -0
  228. package/lib/module/components/ChannelPreview/ChannelLastMessagePreview.js.map +1 -1
  229. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +2 -0
  230. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  231. package/lib/module/components/ChannelPreview/ChannelPreviewTitle.js +1 -0
  232. package/lib/module/components/ChannelPreview/ChannelPreviewTitle.js.map +1 -1
  233. package/lib/module/components/ChannelPreview/ChannelPreviewView.js +1 -1
  234. package/lib/module/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
  235. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js +5 -5
  236. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -1
  237. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js +1 -1
  238. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js.map +1 -1
  239. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.js +1 -1
  240. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.js.map +1 -1
  241. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewPollLabel.js +4 -1
  242. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewPollLabel.js.map +1 -1
  243. package/lib/module/components/Chat/hooks/useConnectionLifecycle.js +6 -2
  244. package/lib/module/components/Chat/hooks/useConnectionLifecycle.js.map +1 -1
  245. package/lib/module/components/Indicators/LoadingErrorIndicator.js +5 -0
  246. package/lib/module/components/Indicators/LoadingErrorIndicator.js.map +1 -1
  247. package/lib/module/components/Message/Message.js +1 -1
  248. package/lib/module/components/Message/Message.js.map +1 -1
  249. package/lib/module/components/Message/MessageItemView/MessageStatus.js +4 -0
  250. package/lib/module/components/Message/MessageItemView/MessageStatus.js.map +1 -1
  251. package/lib/module/components/Message/MessageItemView/MessageWrapper.js +7 -4
  252. package/lib/module/components/Message/MessageItemView/MessageWrapper.js.map +1 -1
  253. package/lib/module/components/Message/hooks/useCreateMessageActionHandlers.js +3 -3
  254. package/lib/module/components/Message/hooks/useCreateMessageActionHandlers.js.map +1 -1
  255. package/lib/module/components/Message/hooks/useProcessReactions.js +2 -2
  256. package/lib/module/components/Message/hooks/useProcessReactions.js.map +1 -1
  257. package/lib/module/components/Message/hooks/useUserMuteActive.js +1 -1
  258. package/lib/module/components/Message/hooks/useUserMuteActive.js.map +1 -1
  259. package/lib/module/components/MessageInput/MessageComposer.js +2 -1
  260. package/lib/module/components/MessageInput/MessageComposer.js.map +1 -1
  261. package/lib/module/components/MessageList/MessageFlashList.js +2 -2
  262. package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
  263. package/lib/module/components/MessageList/MessageList.js +2 -2
  264. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  265. package/lib/module/components/MessageList/hooks/useOwnUnreadCount.js +1 -1
  266. package/lib/module/components/MessageList/hooks/useOwnUnreadCount.js.map +1 -1
  267. package/lib/module/components/MessageMenu/MessageUserReactionsItem.js +1 -1
  268. package/lib/module/components/MessageMenu/MessageUserReactionsItem.js.map +1 -1
  269. package/lib/module/components/MessageMenu/hooks/useMessageOwnReactions.js +2 -2
  270. package/lib/module/components/MessageMenu/hooks/useMessageOwnReactions.js.map +1 -1
  271. package/lib/module/components/Poll/components/PollAnswersList.js +1 -1
  272. package/lib/module/components/Poll/components/PollAnswersList.js.map +1 -1
  273. package/lib/module/components/Poll/components/PollButtons.js +1 -1
  274. package/lib/module/components/Poll/components/PollButtons.js.map +1 -1
  275. package/lib/module/components/Poll/hook/useIsPollCreatedByCurrentUser.js +1 -1
  276. package/lib/module/components/Poll/hook/useIsPollCreatedByCurrentUser.js.map +1 -1
  277. package/lib/module/components/Thread/Thread.js +1 -1
  278. package/lib/module/components/Thread/Thread.js.map +1 -1
  279. package/lib/module/components/ThreadList/ThreadListItem.js +1 -1
  280. package/lib/module/components/ThreadList/ThreadListItem.js.map +1 -1
  281. package/lib/module/components/ThreadList/ThreadListUnreadBanner.js +9 -2
  282. package/lib/module/components/ThreadList/ThreadListUnreadBanner.js.map +1 -1
  283. package/lib/module/components/index.js +36 -0
  284. package/lib/module/components/index.js.map +1 -1
  285. package/lib/module/contexts/componentsContext/defaultComponents.js +0 -2
  286. package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
  287. package/lib/module/contexts/liveLocationManagerContext/LiveLocationManagerContext.js +1 -1
  288. package/lib/module/contexts/liveLocationManagerContext/LiveLocationManagerContext.js.map +1 -1
  289. package/lib/module/hooks/actions/useChannelActionItems.js +1 -1
  290. package/lib/module/hooks/actions/useChannelActionItems.js.map +1 -1
  291. package/lib/module/hooks/actions/useChannelActions.js +2 -2
  292. package/lib/module/hooks/actions/useChannelActions.js.map +1 -1
  293. package/lib/module/hooks/actions/useChannelMemberActionItems.js +1 -1
  294. package/lib/module/hooks/actions/useChannelMemberActionItems.js.map +1 -1
  295. package/lib/module/hooks/index.js +11 -0
  296. package/lib/module/hooks/index.js.map +1 -1
  297. package/lib/module/hooks/messagePreview/useMessageDeliveryStatus.js +6 -6
  298. package/lib/module/hooks/messagePreview/useMessageDeliveryStatus.js.map +1 -1
  299. package/lib/module/hooks/useIsDirectChat.js +1 -1
  300. package/lib/module/hooks/useIsDirectChat.js.map +1 -1
  301. package/lib/module/i18n/runtimeDefaults.js +1 -0
  302. package/lib/module/i18n/runtimeDefaults.js.map +1 -1
  303. package/lib/module/store/apis/getChannelMessages.js +5 -3
  304. package/lib/module/store/apis/getChannelMessages.js.map +1 -1
  305. package/lib/module/store/apis/getChannels.js +6 -3
  306. package/lib/module/store/apis/getChannels.js.map +1 -1
  307. package/lib/module/store/apis/getChannelsForFilterSort.js +2 -1
  308. package/lib/module/store/apis/getChannelsForFilterSort.js.map +1 -1
  309. package/lib/module/store/apis/queries/selectMessagesForChannels.js +7 -5
  310. package/lib/module/store/apis/queries/selectMessagesForChannels.js.map +1 -1
  311. package/lib/module/utils/installNativeMultipartAdapter.js.map +1 -1
  312. package/lib/module/utils/setupCommandUIMiddlewares.js +6 -3
  313. package/lib/module/utils/setupCommandUIMiddlewares.js.map +1 -1
  314. package/lib/module/version.json +1 -1
  315. package/lib/typescript/ai-components/index.d.ts +3 -1
  316. package/lib/typescript/ai-components/index.d.ts.map +1 -1
  317. package/lib/typescript/ai-components/message-composer/ComposerView.d.ts.map +1 -1
  318. package/lib/typescript/ai-components/native/AIDictation.d.ts +6 -0
  319. package/lib/typescript/ai-components/native/AIDictation.d.ts.map +1 -1
  320. package/lib/typescript/ai-components/store/dictation/store.d.ts +7 -0
  321. package/lib/typescript/ai-components/store/dictation/store.d.ts.map +1 -1
  322. package/lib/typescript/ai-components/store/dictation/useDictationState.d.ts +1 -0
  323. package/lib/typescript/ai-components/store/dictation/useDictationState.d.ts.map +1 -1
  324. package/lib/typescript/ai-components/store/index.d.ts +2 -0
  325. package/lib/typescript/ai-components/store/index.d.ts.map +1 -1
  326. package/lib/typescript/ai-components/theme.d.ts +13 -0
  327. package/lib/typescript/ai-components/theme.d.ts.map +1 -1
  328. package/lib/typescript/ai-components/transcription/useDictation.d.ts +9 -1
  329. package/lib/typescript/ai-components/transcription/useDictation.d.ts.map +1 -1
  330. package/lib/typescript/ai-components/transcription/useDictationAudioLevel.d.ts +11 -0
  331. package/lib/typescript/ai-components/transcription/useDictationAudioLevel.d.ts.map +1 -0
  332. package/lib/typescript/ai-components/voice-visualization/VoiceGlow.d.ts +13 -0
  333. package/lib/typescript/ai-components/voice-visualization/VoiceGlow.d.ts.map +1 -0
  334. package/lib/typescript/ai-components/voice-visualization/VoiceVisualizationView.d.ts +26 -0
  335. package/lib/typescript/ai-components/voice-visualization/VoiceVisualizationView.d.ts.map +1 -0
  336. package/lib/typescript/ai-components/voice-visualization/VoiceWave.d.ts +13 -0
  337. package/lib/typescript/ai-components/voice-visualization/VoiceWave.d.ts.map +1 -0
  338. package/lib/typescript/ai-components/voice-visualization/bounce.d.ts +20 -0
  339. package/lib/typescript/ai-components/voice-visualization/bounce.d.ts.map +1 -0
  340. package/lib/typescript/ai-components/voice-visualization/driver.d.ts +96 -0
  341. package/lib/typescript/ai-components/voice-visualization/driver.d.ts.map +1 -0
  342. package/lib/typescript/ai-components/voice-visualization/glowShader.d.ts +7 -0
  343. package/lib/typescript/ai-components/voice-visualization/glowShader.d.ts.map +1 -0
  344. package/lib/typescript/ai-components/voice-visualization/index.d.ts +4 -0
  345. package/lib/typescript/ai-components/voice-visualization/index.d.ts.map +1 -0
  346. package/lib/typescript/ai-components/voice-visualization/math.d.ts +26 -0
  347. package/lib/typescript/ai-components/voice-visualization/math.d.ts.map +1 -0
  348. package/lib/typescript/ai-components/voice-visualization/palette.d.ts +18 -0
  349. package/lib/typescript/ai-components/voice-visualization/palette.d.ts.map +1 -0
  350. package/lib/typescript/ai-components/voice-visualization/simplex.d.ts +11 -0
  351. package/lib/typescript/ai-components/voice-visualization/simplex.d.ts.map +1 -0
  352. package/lib/typescript/ai-components/voice-visualization/styles.d.ts +24 -0
  353. package/lib/typescript/ai-components/voice-visualization/styles.d.ts.map +1 -0
  354. package/lib/typescript/ai-components/voice-visualization/types.d.ts +45 -0
  355. package/lib/typescript/ai-components/voice-visualization/types.d.ts.map +1 -0
  356. package/lib/typescript/ai-components/voice-visualization/useReduceMotion.d.ts +10 -0
  357. package/lib/typescript/ai-components/voice-visualization/useReduceMotion.d.ts.map +1 -0
  358. package/lib/typescript/ai-components/voice-visualization/useVoiceVisualization.d.ts +18 -0
  359. package/lib/typescript/ai-components/voice-visualization/useVoiceVisualization.d.ts.map +1 -0
  360. package/lib/typescript/ai-components/voice-visualization/waveGeometry.d.ts +25 -0
  361. package/lib/typescript/ai-components/voice-visualization/waveGeometry.d.ts.map +1 -0
  362. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  363. package/lib/typescript/components/Channel/ChannelShell.d.ts +2 -0
  364. package/lib/typescript/components/Channel/ChannelShell.d.ts.map +1 -1
  365. package/lib/typescript/components/Channel/hooks/useChannelLifecycle.d.ts.map +1 -1
  366. package/lib/typescript/components/Channel/hooks/useJumpToLatestOnOpen.d.ts +15 -0
  367. package/lib/typescript/components/Channel/hooks/useJumpToLatestOnOpen.d.ts.map +1 -0
  368. package/lib/typescript/components/ChannelList/ChannelListView.d.ts +1 -1
  369. package/lib/typescript/components/ChannelList/ChannelListView.d.ts.map +1 -1
  370. package/lib/typescript/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.d.ts.map +1 -1
  371. package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts.map +1 -1
  372. package/lib/typescript/components/Chat/hooks/useConnectionLifecycle.d.ts +5 -4
  373. package/lib/typescript/components/Chat/hooks/useConnectionLifecycle.d.ts.map +1 -1
  374. package/lib/typescript/components/Indicators/LoadingErrorIndicator.d.ts +1 -1
  375. package/lib/typescript/components/Indicators/LoadingErrorIndicator.d.ts.map +1 -1
  376. package/lib/typescript/components/Message/MessageItemView/MessageStatus.d.ts.map +1 -1
  377. package/lib/typescript/components/Message/MessageItemView/MessageWrapper.d.ts.map +1 -1
  378. package/lib/typescript/components/MessageInput/MessageComposer.d.ts.map +1 -1
  379. package/lib/typescript/components/ThreadList/ThreadListUnreadBanner.d.ts.map +1 -1
  380. package/lib/typescript/components/index.d.ts +3 -0
  381. package/lib/typescript/components/index.d.ts.map +1 -1
  382. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +0 -1
  383. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
  384. package/lib/typescript/hooks/index.d.ts +1 -0
  385. package/lib/typescript/hooks/index.d.ts.map +1 -1
  386. package/lib/typescript/hooks/messagePreview/useMessageDeliveryStatus.d.ts +3 -0
  387. package/lib/typescript/hooks/messagePreview/useMessageDeliveryStatus.d.ts.map +1 -1
  388. package/lib/typescript/i18n/keys.d.ts +3 -1
  389. package/lib/typescript/i18n/keys.d.ts.map +1 -1
  390. package/lib/typescript/i18n/runtimeDefaults.d.ts +1 -0
  391. package/lib/typescript/i18n/runtimeDefaults.d.ts.map +1 -1
  392. package/lib/typescript/store/apis/getChannelMessages.d.ts +2 -1
  393. package/lib/typescript/store/apis/getChannelMessages.d.ts.map +1 -1
  394. package/lib/typescript/store/apis/getChannels.d.ts +3 -1
  395. package/lib/typescript/store/apis/getChannels.d.ts.map +1 -1
  396. package/lib/typescript/store/apis/getChannelsForFilterSort.d.ts.map +1 -1
  397. package/lib/typescript/store/apis/queries/selectMessagesForChannels.d.ts +3 -1
  398. package/lib/typescript/store/apis/queries/selectMessagesForChannels.d.ts.map +1 -1
  399. package/lib/typescript/utils/installNativeMultipartAdapter.d.ts +5 -3
  400. package/lib/typescript/utils/installNativeMultipartAdapter.d.ts.map +1 -1
  401. package/lib/typescript/utils/setupCommandUIMiddlewares.d.ts.map +1 -1
  402. package/package.json +4 -4
  403. package/src/__tests__/offline-support/offline-feature.tsx +7 -7
  404. package/src/__tests__/offline-support/optimistic-update.tsx +5 -5
  405. package/src/ai-components/README.md +50 -2
  406. package/src/ai-components/__tests__/VoiceVisualization.test.tsx +208 -0
  407. package/src/ai-components/__tests__/dictation.test.tsx +58 -1
  408. package/src/ai-components/__tests__/voiceDriver.test.ts +317 -0
  409. package/src/ai-components/__tests__/voicePalette.test.ts +124 -0
  410. package/src/ai-components/index.ts +3 -1
  411. package/src/ai-components/message-composer/ComposerView.tsx +6 -3
  412. package/src/ai-components/message-composer/SpeechToTextButton.tsx +5 -2
  413. package/src/ai-components/native/AIDictation.ts +11 -0
  414. package/src/ai-components/store/dictation/store.ts +9 -0
  415. package/src/ai-components/store/dictation/useDictationState.ts +2 -1
  416. package/src/ai-components/store/index.ts +2 -0
  417. package/src/ai-components/theme.ts +16 -0
  418. package/src/ai-components/transcription/useDictation.ts +16 -3
  419. package/src/ai-components/transcription/useDictationAudioLevel.ts +38 -0
  420. package/src/ai-components/voice-visualization/VoiceGlow.tsx +79 -0
  421. package/src/ai-components/voice-visualization/VoiceVisualizationView.tsx +179 -0
  422. package/src/ai-components/voice-visualization/VoiceWave.tsx +67 -0
  423. package/src/ai-components/voice-visualization/bounce.ts +61 -0
  424. package/src/ai-components/voice-visualization/driver.ts +240 -0
  425. package/src/ai-components/voice-visualization/glowShader.ts +227 -0
  426. package/src/ai-components/voice-visualization/index.ts +3 -0
  427. package/src/ai-components/voice-visualization/math.ts +73 -0
  428. package/src/ai-components/voice-visualization/palette.ts +59 -0
  429. package/src/ai-components/voice-visualization/simplex.ts +92 -0
  430. package/src/ai-components/voice-visualization/styles.ts +42 -0
  431. package/src/ai-components/voice-visualization/types.ts +44 -0
  432. package/src/ai-components/voice-visualization/useReduceMotion.ts +34 -0
  433. package/src/ai-components/voice-visualization/useVoiceVisualization.ts +153 -0
  434. package/src/ai-components/voice-visualization/waveGeometry.ts +137 -0
  435. package/src/components/Channel/Channel.tsx +1 -0
  436. package/src/components/Channel/ChannelShell.tsx +12 -0
  437. package/src/components/Channel/__tests__/Channel.test.tsx +146 -5
  438. package/src/components/Channel/hooks/useChannelLifecycle.ts +4 -1
  439. package/src/components/Channel/hooks/useJumpToLatestOnOpen.ts +42 -0
  440. package/src/components/ChannelDetails/__tests__/ChannelDetails.test.tsx +1 -1
  441. package/src/components/ChannelDetails/__tests__/ChannelDetailsActionsSection.test.tsx +1 -1
  442. package/src/components/ChannelDetails/__tests__/ChannelDetailsEditButton.test.tsx +1 -1
  443. package/src/components/ChannelDetails/__tests__/ChannelDetailsMemberSection.test.tsx +1 -1
  444. package/src/components/ChannelDetails/__tests__/ChannelDetailsNavHeader.test.tsx +1 -1
  445. package/src/components/ChannelDetails/__tests__/ChannelDetailsProfile.test.tsx +2 -2
  446. package/src/components/ChannelDetails/__tests__/ChannelEditDetailsForm.test.tsx +1 -1
  447. package/src/components/ChannelDetails/__tests__/ChannelEditDetailsFormContent.test.tsx +2 -2
  448. package/src/components/ChannelDetails/__tests__/ChannelEditName.test.tsx +1 -1
  449. package/src/components/ChannelDetails/__tests__/members/ChannelAddMembersForm.test.tsx +1 -1
  450. package/src/components/ChannelDetails/__tests__/members/ChannelMemberActionsSheet.test.tsx +2 -2
  451. package/src/components/ChannelDetails/__tests__/members/ChannelMemberItem.test.tsx +1 -1
  452. package/src/components/ChannelDetails/__tests__/useChannelDetailsMemberStatusText.test.tsx +1 -1
  453. package/src/components/ChannelDetails/components/members/ChannelMemberItem.tsx +1 -1
  454. package/src/components/ChannelDetails/hooks/useChannelDetailsMemberStatusText.ts +1 -1
  455. package/src/components/ChannelList/ChannelListView.tsx +1 -3
  456. package/src/components/ChannelList/__tests__/ChannelList.test.tsx +72 -0
  457. package/src/components/ChannelList/hooks/usePaginatedChannels.ts +2 -2
  458. package/src/components/ChannelPreview/ChannelDetailsBottomSheet.tsx +1 -1
  459. package/src/components/ChannelPreview/ChannelLastMessagePreview.tsx +1 -1
  460. package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx +8 -2
  461. package/src/components/ChannelPreview/ChannelPreviewTitle.tsx +1 -1
  462. package/src/components/ChannelPreview/ChannelPreviewView.tsx +1 -1
  463. package/src/components/ChannelPreview/__tests__/ChannelPreview.test.tsx +4 -4
  464. package/src/components/ChannelPreview/__tests__/ChannelPreviewView.test.tsx +40 -0
  465. package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewData.test.tsx +51 -0
  466. package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayName.test.tsx +1 -1
  467. package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayPresence.test.tsx +1 -1
  468. package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewPollLabel.test.tsx +87 -0
  469. package/src/components/ChannelPreview/hooks/useChannelPreviewData.ts +3 -4
  470. package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayName.ts +1 -1
  471. package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.ts +1 -1
  472. package/src/components/ChannelPreview/hooks/useChannelPreviewPollLabel.ts +1 -1
  473. package/src/components/Chat/__tests__/Chat.test.tsx +31 -1
  474. package/src/components/Chat/hooks/useConnectionLifecycle.ts +12 -6
  475. package/src/components/Indicators/LoadingErrorIndicator.tsx +8 -1
  476. package/src/components/Message/Message.tsx +1 -1
  477. package/src/components/Message/MessageItemView/MessageStatus.tsx +16 -2
  478. package/src/components/Message/MessageItemView/MessageWrapper.tsx +14 -4
  479. package/src/components/Message/MessageItemView/__tests__/MessageStatus.test.tsx +21 -0
  480. package/src/components/Message/hooks/__tests__/useCreateMessageActionHandlers.test.tsx +1 -1
  481. package/src/components/Message/hooks/__tests__/useUserMuteActive.test.tsx +1 -1
  482. package/src/components/Message/hooks/useCreateMessageActionHandlers.ts +3 -3
  483. package/src/components/Message/hooks/useProcessReactions.ts +2 -2
  484. package/src/components/Message/hooks/useUserMuteActive.ts +1 -1
  485. package/src/components/MessageInput/MessageComposer.tsx +4 -2
  486. package/src/components/MessageList/MessageFlashList.tsx +2 -2
  487. package/src/components/MessageList/MessageList.tsx +2 -2
  488. package/src/components/MessageList/__tests__/MessageList.test.tsx +115 -14
  489. package/src/components/MessageList/__tests__/ScrollToBottomButton.test.tsx +3 -3
  490. package/src/components/MessageList/hooks/useOwnUnreadCount.ts +1 -1
  491. package/src/components/MessageMenu/MessageUserReactionsItem.tsx +1 -1
  492. package/src/components/MessageMenu/hooks/useMessageOwnReactions.ts +2 -2
  493. package/src/components/Poll/components/PollAnswersList.tsx +1 -1
  494. package/src/components/Poll/components/PollButtons.tsx +1 -1
  495. package/src/components/Poll/hook/useIsPollCreatedByCurrentUser.ts +1 -1
  496. package/src/components/Thread/Thread.tsx +1 -1
  497. package/src/components/Thread/__tests__/Thread.test.tsx +89 -2
  498. package/src/components/ThreadList/ThreadListItem.tsx +1 -1
  499. package/src/components/ThreadList/ThreadListUnreadBanner.tsx +6 -2
  500. package/src/components/ThreadList/__tests__/ThreadList.test.tsx +21 -0
  501. package/src/components/index.ts +3 -0
  502. package/src/contexts/componentsContext/defaultComponents.ts +0 -2
  503. package/src/contexts/liveLocationManagerContext/LiveLocationManagerContext.tsx +1 -1
  504. package/src/hooks/__tests__/useChannelMuteActive.test.tsx +1 -1
  505. package/src/hooks/__tests__/useIsDirectChat.test.tsx +1 -1
  506. package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx +1 -1
  507. package/src/hooks/actions/__tests__/useChannelActions.test.tsx +1 -1
  508. package/src/hooks/actions/__tests__/useChannelMemberActionItems.test.tsx +6 -6
  509. package/src/hooks/actions/useChannelActionItems.tsx +1 -1
  510. package/src/hooks/actions/useChannelActions.ts +2 -2
  511. package/src/hooks/actions/useChannelMemberActionItems.tsx +1 -1
  512. package/src/hooks/index.ts +1 -0
  513. package/src/hooks/messagePreview/__tests__/useMessageDeliveryStatus.test.tsx +57 -32
  514. package/src/hooks/messagePreview/useMessageDeliveryStatus.ts +13 -7
  515. package/src/hooks/useIsDirectChat.ts +1 -1
  516. package/src/i18n/__tests__/catalog.fixture.json +2 -0
  517. package/src/i18n/keys.ts +3 -0
  518. package/src/i18n/runtimeDefaults.ts +1 -0
  519. package/src/store/__tests__/selectMessagesForChannels.test.ts +34 -12
  520. package/src/store/apis/getChannelMessages.ts +4 -1
  521. package/src/store/apis/getChannels.ts +5 -1
  522. package/src/store/apis/getChannelsForFilterSort.ts +1 -0
  523. package/src/store/apis/queries/selectMessagesForChannels.ts +7 -2
  524. package/src/utils/__tests__/setupCommandUIMiddlewares.test.ts +49 -0
  525. package/src/utils/installNativeMultipartAdapter.ts +5 -3
  526. package/src/utils/setupCommandUIMiddlewares.ts +3 -0
  527. package/src/version.json +1 -1
@@ -0,0 +1,38 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { type SharedValue, useSharedValue } from 'react-native-reanimated';
4
+
5
+ import { AIDictation } from '../native/AIDictation';
6
+
7
+ /**
8
+ * The microphone's live level while dictation listens, from 0 to 1, for the `audioLevel` of
9
+ * `VoiceWave` and `VoiceGlow`. It is `null` while dictation is not listening, which lets a
10
+ * visualization animate speech on its own.
11
+ *
12
+ * The level is a shared value rather than state, so a level changing many times a second
13
+ * re-renders nothing: the visualizations read it once a frame on the UI thread.
14
+ */
15
+ export const useDictationAudioLevel = (): SharedValue<number | null> => {
16
+ const level = useSharedValue<number | null>(null);
17
+
18
+ useEffect(() => {
19
+ const unsubscribeLevel = AIDictation.addLevelListener((payload) => {
20
+ level.value = typeof payload?.level === 'number' ? payload.level : null;
21
+ });
22
+ const unsubscribeState = AIDictation.addStateListener(({ state }) => {
23
+ if (state !== 'listening' && state !== 'starting') level.value = null;
24
+ });
25
+ const unsubscribeError = AIDictation.addErrorListener(() => {
26
+ level.value = null;
27
+ });
28
+
29
+ return () => {
30
+ unsubscribeLevel();
31
+ unsubscribeState();
32
+ unsubscribeError();
33
+ level.value = null;
34
+ };
35
+ }, [level]);
36
+
37
+ return level;
38
+ };
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+
3
+ import { useDerivedValue } from 'react-native-reanimated';
4
+
5
+ import { Canvas, Fill, Shader } from '@shopify/react-native-skia';
6
+
7
+ import { driverReact, driverScale } from './driver';
8
+ import { getGlowEffect } from './glowShader';
9
+ import { GLOW_STYLE } from './styles';
10
+ import type { VoiceVisualizationProps } from './types';
11
+ import type { VoiceVisualization } from './useVoiceVisualization';
12
+ import { type VoiceCanvasSize, VoiceVisualizationView } from './VoiceVisualizationView';
13
+
14
+ export type VoiceGlowProps = VoiceVisualizationProps;
15
+
16
+ const GlowCanvas = ({
17
+ size: { height, width },
18
+ visualization: { dark, driver },
19
+ }: {
20
+ size: VoiceCanvasSize;
21
+ visualization: VoiceVisualization;
22
+ }) => {
23
+ const effect = getGlowEffect();
24
+ const uniforms = useDerivedValue(() => {
25
+ const d = driver.value;
26
+ const color = (i: number) => [d.colors[i].hue, d.colors[i].saturation, d.colors[i].value, 0];
27
+ return {
28
+ bright: d.bright,
29
+ col0: color(0),
30
+ col1: color(1),
31
+ col2: color(2),
32
+ col3: color(3),
33
+ col4: color(4),
34
+ count: d.count,
35
+ dark: dark.value,
36
+ flow: d.flow,
37
+ flowSpin: d.flowSpin,
38
+ hover: [d.hoverX, d.hoverY],
39
+ hoverAmt: d.hoverAmount,
40
+ load: d.load,
41
+ mic: d.mic,
42
+ orbSpin: d.orbSpin,
43
+ react: driverReact(d),
44
+ resolution: [width, height],
45
+ sat: d.sat,
46
+ scale: driverScale(d),
47
+ tap: [d.tapX, d.tapY],
48
+ tapTime: d.tapAge,
49
+ time: d.time,
50
+ voice: d.voice,
51
+ };
52
+ });
53
+
54
+ if (!effect) return null;
55
+
56
+ return (
57
+ <Canvas style={{ height, width }}>
58
+ <Fill>
59
+ <Shader source={effect} uniforms={uniforms} />
60
+ </Fill>
61
+ </Canvas>
62
+ );
63
+ };
64
+
65
+ const renderGlow = (visualization: VoiceVisualization, size: VoiceCanvasSize) => (
66
+ <GlowCanvas size={size} visualization={visualization} />
67
+ );
68
+
69
+ /**
70
+ * A voice agent as a soft, airy globe: color masses orbit inside it and swell with speech, and the
71
+ * gaps between them let the background show through. Tapping the globe bounces it and ripples it
72
+ * from the touch, and so does a hovering mouse or pen.
73
+ *
74
+ * It has no size of its own and draws in the middle of the view it is given, about half as wide
75
+ * as its shorter side, so give it a square.
76
+ */
77
+ export const VoiceGlow = (props: VoiceGlowProps) => (
78
+ <VoiceVisualizationView {...props} renderCanvas={renderGlow} visualStyle={GLOW_STYLE} />
79
+ );
@@ -0,0 +1,179 @@
1
+ import React, { type ReactNode, useCallback, useMemo, useState } from 'react';
2
+ import {
3
+ type GestureResponderEvent,
4
+ type LayoutChangeEvent,
5
+ PixelRatio,
6
+ type PointerEvent,
7
+ StyleSheet,
8
+ View,
9
+ } from 'react-native';
10
+
11
+ import Animated from 'react-native-reanimated';
12
+
13
+ import type { VoiceVisualizationStyle } from './styles';
14
+ import type { VoiceAgentState, VoiceVisualizationProps } from './types';
15
+ import { useVoiceVisualization, type VoiceVisualization } from './useVoiceVisualization';
16
+
17
+ /** What the renderer draws in: the canvas size, in its own units, and the screen's pixels per unit. */
18
+ export type VoiceCanvasSize = { height: number; pixelRatio: number; width: number };
19
+
20
+ type ViewProps = VoiceVisualizationProps & {
21
+ /** Draws the visualization into a canvas of the given size. */
22
+ renderCanvas: (visualization: VoiceVisualization, size: VoiceCanvasSize) => ReactNode;
23
+ visualStyle: VoiceVisualizationStyle;
24
+ };
25
+
26
+ const DEFAULT_STATE_LABELS: Record<VoiceAgentState, string> = {
27
+ connecting: 'Connecting',
28
+ idle: 'Ready',
29
+ listening: 'Listening',
30
+ speaking: 'Speaking',
31
+ thinking: 'Thinking',
32
+ };
33
+
34
+ /**
35
+ * What VoiceWave and VoiceGlow share: the motion, the canvas kept at the view's size and at most
36
+ * the style's density, reduced motion, taps and hover, and accessibility.
37
+ *
38
+ * It names itself "Voice agent" with its state as the value, as on iOS and Android. Touches are
39
+ * only watched, never claimed, so a press handler on the view or a parent still gets them, and
40
+ * only the shape takes them: around it they reach whatever is behind.
41
+ */
42
+ export const VoiceVisualizationView = ({
43
+ accessibilityLabel = 'Voice agent',
44
+ accessibilityValue,
45
+ audioLevel,
46
+ colors,
47
+ expressivity,
48
+ onLayout,
49
+ pointerEvents = 'box-none',
50
+ renderCanvas,
51
+ state,
52
+ stateLabels,
53
+ style,
54
+ visualStyle,
55
+ ...restProps
56
+ }: ViewProps) => {
57
+ const visualization = useVoiceVisualization(
58
+ { audioLevel, colors, expressivity, state },
59
+ visualStyle,
60
+ );
61
+ const { hover, opacity, tap } = visualization;
62
+ const [layout, setLayout] = useState({ height: 0, width: 0 });
63
+
64
+ const handleLayout = useCallback(
65
+ (event: LayoutChangeEvent) => {
66
+ onLayout?.(event);
67
+ const { height, width } = event.nativeEvent.layout;
68
+ setLayout((current) =>
69
+ current.width === width && current.height === height ? current : { height, width },
70
+ );
71
+ },
72
+ [onLayout],
73
+ );
74
+
75
+ const side = Math.min(layout.width, layout.height);
76
+ const pixelRatio = PixelRatio.get();
77
+ // Drawn at no more than the style's density, then scaled up to the view: the glow's soft
78
+ // gradients look the same at 2x with fewer pixels to fill, while the wave's line needs 3x.
79
+ const density = Math.min(1, visualStyle.maxScale / pixelRatio);
80
+ const canvasSize = useMemo<VoiceCanvasSize>(
81
+ () => ({
82
+ height: layout.height * density,
83
+ pixelRatio: pixelRatio * density,
84
+ width: layout.width * density,
85
+ }),
86
+ [density, layout.height, layout.width, pixelRatio],
87
+ );
88
+ const hitWidth = visualStyle.hitArea.width * side;
89
+ const hitHeight = visualStyle.hitArea.height * side;
90
+
91
+ /** A touch on the hit area, centred on the view and normalized to its shorter side, y up. */
92
+ const toLocalPoint = useCallback(
93
+ (locationX: number, locationY: number) => ({
94
+ x: (locationX - hitWidth / 2) / (side || 1),
95
+ y: (hitHeight / 2 - locationY) / (side || 1),
96
+ }),
97
+ [hitHeight, hitWidth, side],
98
+ );
99
+
100
+ const handleTouchEnd = useCallback(
101
+ (event: GestureResponderEvent) => {
102
+ const { x, y } = toLocalPoint(event.nativeEvent.locationX, event.nativeEvent.locationY);
103
+ if (visualStyle.contains(x, y)) tap(x, y);
104
+ },
105
+ [tap, toLocalPoint, visualStyle],
106
+ );
107
+
108
+ const handlePointerMove = useCallback(
109
+ (event: PointerEvent) => {
110
+ // Only a hovering mouse or pen ripples it; a finger has no hover.
111
+ const { buttons, offsetX, offsetY, pointerType } = event.nativeEvent;
112
+ if (pointerType === 'touch') return;
113
+ const { x, y } = toLocalPoint(offsetX, offsetY);
114
+ const hovering = buttons === 0 && visualStyle.contains(x, y);
115
+ hover(hovering ? x : null, hovering ? y : null);
116
+ },
117
+ [hover, toLocalPoint, visualStyle],
118
+ );
119
+
120
+ const handlePointerLeave = useCallback(() => hover(null, null), [hover]);
121
+
122
+ return (
123
+ <View
124
+ accessibilityLabel={accessibilityLabel}
125
+ accessibilityRole='image'
126
+ accessibilityValue={
127
+ accessibilityValue ?? { text: stateLabels?.[state] ?? DEFAULT_STATE_LABELS[state] }
128
+ }
129
+ accessible
130
+ onLayout={handleLayout}
131
+ pointerEvents={pointerEvents}
132
+ style={style}
133
+ {...restProps}
134
+ >
135
+ {side > 0 ? (
136
+ <>
137
+ <Animated.View
138
+ pointerEvents='none'
139
+ style={[
140
+ styles.canvas,
141
+ {
142
+ height: canvasSize.height,
143
+ left: (layout.width - canvasSize.width) / 2,
144
+ opacity,
145
+ top: (layout.height - canvasSize.height) / 2,
146
+ transform: [{ scale: 1 / density }],
147
+ width: canvasSize.width,
148
+ },
149
+ ]}
150
+ >
151
+ {renderCanvas(visualization, canvasSize)}
152
+ </Animated.View>
153
+ <View
154
+ // A transparent view with only handlers could be flattened away, leaving no target.
155
+ collapsable={false}
156
+ onPointerLeave={handlePointerLeave}
157
+ onPointerMove={handlePointerMove}
158
+ onTouchEnd={handleTouchEnd}
159
+ style={[
160
+ styles.hitArea,
161
+ {
162
+ height: hitHeight,
163
+ left: (layout.width - hitWidth) / 2,
164
+ top: (layout.height - hitHeight) / 2,
165
+ width: hitWidth,
166
+ },
167
+ ]}
168
+ testID='voice-visualization-hit-area'
169
+ />
170
+ </>
171
+ ) : null}
172
+ </View>
173
+ );
174
+ };
175
+
176
+ const styles = StyleSheet.create({
177
+ canvas: { position: 'absolute' },
178
+ hitArea: { position: 'absolute' },
179
+ });
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+
3
+ import { useDerivedValue } from 'react-native-reanimated';
4
+
5
+ import { Canvas, LinearGradient, Path, vec } from '@shopify/react-native-skia';
6
+
7
+ import { WAVE_STYLE } from './styles';
8
+ import type { VoiceVisualizationProps } from './types';
9
+ import type { VoiceVisualization } from './useVoiceVisualization';
10
+ import { type VoiceCanvasSize, VoiceVisualizationView } from './VoiceVisualizationView';
11
+ import {
12
+ WAVE_END,
13
+ WAVE_POSITIONS,
14
+ WAVE_START,
15
+ waveColors,
16
+ wavePath,
17
+ waveStrokeWidth,
18
+ } from './waveGeometry';
19
+
20
+ export type VoiceWaveProps = VoiceVisualizationProps;
21
+
22
+ const WaveCanvas = ({
23
+ size: { height, pixelRatio, width },
24
+ visualization: { dark, driver },
25
+ }: {
26
+ size: VoiceCanvasSize;
27
+ visualization: VoiceVisualization;
28
+ }) => {
29
+ const path = useDerivedValue(() => wavePath(driver.value, width, height));
30
+ const colors = useDerivedValue(() => waveColors(driver.value, dark.value));
31
+ const m = Math.min(width, height);
32
+
33
+ return (
34
+ <Canvas style={{ height, width }}>
35
+ <Path
36
+ path={path}
37
+ strokeCap='round'
38
+ strokeJoin='round'
39
+ strokeWidth={waveStrokeWidth(width, height, pixelRatio)}
40
+ style='stroke'
41
+ >
42
+ <LinearGradient
43
+ colors={colors}
44
+ end={vec(width / 2 + WAVE_END * m, 0)}
45
+ positions={WAVE_POSITIONS}
46
+ start={vec(width / 2 + WAVE_START * m, 0)}
47
+ />
48
+ </Path>
49
+ </Canvas>
50
+ );
51
+ };
52
+
53
+ const renderWave = (visualization: VoiceVisualization, size: VoiceCanvasSize) => (
54
+ <WaveCanvas size={size} visualization={visualization} />
55
+ );
56
+
57
+ /**
58
+ * A voice agent as a single string, flat at its ends, carrying a wave packet that erupts with
59
+ * speech while its colors flow along it. Tapping the string ripples it from the touch, and so does
60
+ * a hovering mouse or pen.
61
+ *
62
+ * It has no size of its own and draws in the middle of the view it is given, about 80% as wide as
63
+ * its shorter side, so give it a square or a wide box.
64
+ */
65
+ export const VoiceWave = (props: VoiceWaveProps) => (
66
+ <VoiceVisualizationView {...props} renderCanvas={renderWave} visualStyle={WAVE_STYLE} />
67
+ );
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The bounce of a tap: a dip to 93% and an overshoot to 103% before settling, over 340 ms.
3
+ *
4
+ * These are authored keyframes rather than a spring: the ease-out curve times the whole run and
5
+ * the keyframes are linear between their stops.
6
+ */
7
+ export const BOUNCE_DURATION = 0.34;
8
+
9
+ const OFFSETS = [0, 0.3, 0.62, 1];
10
+ const SCALES = [1, 0.93, 1.03, 1];
11
+
12
+ /** How long ago the last bounce started, in seconds; infinite before the first. */
13
+ export type BounceState = { age: number };
14
+
15
+ export const createBounce = (): BounceState => ({ age: Number.POSITIVE_INFINITY });
16
+
17
+ export const startBounce = (bounce: BounceState) => {
18
+ 'worklet';
19
+ bounce.age = 0;
20
+ };
21
+
22
+ export const advanceBounce = (bounce: BounceState, seconds: number) => {
23
+ 'worklet';
24
+ bounce.age += seconds;
25
+ };
26
+
27
+ /** CSS `ease-out`, `cubic-bezier(0, 0, 0.58, 1)`. */
28
+ export const easeOut = (x: number) => {
29
+ 'worklet';
30
+ const bx = 3 * 0.58;
31
+ const ax = 1 - bx;
32
+ const by = 3;
33
+ const ay = 1 - by;
34
+ let low = 0;
35
+ let high = 1;
36
+ for (let i = 0; i < 24; i++) {
37
+ const middle = (low + high) / 2;
38
+ if ((ax * middle + bx) * middle * middle < x) low = middle;
39
+ else high = middle;
40
+ }
41
+ const t = (low + high) / 2;
42
+ return (ay * t + by) * t * t;
43
+ };
44
+
45
+ /** The keyframed scale at `progress`, from 0 to 1. */
46
+ export const scaleAt = (progress: number) => {
47
+ 'worklet';
48
+ for (let i = 1; i < OFFSETS.length; i++) {
49
+ if (progress <= OFFSETS[i]) {
50
+ const fraction = (progress - OFFSETS[i - 1]) / (OFFSETS[i] - OFFSETS[i - 1]);
51
+ return SCALES[i - 1] + (SCALES[i] - SCALES[i - 1]) * fraction;
52
+ }
53
+ }
54
+ return 1;
55
+ };
56
+
57
+ export const bounceScale = (bounce: BounceState) => {
58
+ 'worklet';
59
+ if (bounce.age >= BOUNCE_DURATION) return 1;
60
+ return scaleAt(easeOut(Math.max(bounce.age, 0) / BOUNCE_DURATION));
61
+ };
@@ -0,0 +1,240 @@
1
+ import { advanceBounce, type BounceState, bounceScale, createBounce, startBounce } from './bounce';
2
+ import { MAXIMUM_COLORS } from './palette';
3
+ import type { Hsv, VoiceAgentState } from './types';
4
+
5
+ /**
6
+ * The share of the way the live level moves each frame at 60 Hz, toward a louder or a quieter
7
+ * level.
8
+ */
9
+ export type LevelResponse = { rise: number; fall: number };
10
+
11
+ export const LEVEL_RESPONSE = {
12
+ /** Follows the level closely, both ways. The glow's. */
13
+ steady: { fall: 0.35, rise: 0.35 },
14
+ /**
15
+ * Follows the level like a VU meter: about 0.1 s up to a louder reading, about 0.3 s down from
16
+ * it, so a meter's per-syllable jumps swell with the phrase instead. The wave's.
17
+ */
18
+ smooth: { fall: 0.05, rise: 0.16 },
19
+ } satisfies Record<string, LevelResponse>;
20
+
21
+ export type VoiceDriverInput = {
22
+ state: VoiceAgentState;
23
+ /** One to five colors. */
24
+ colors: Hsv[];
25
+ /** From 0 to 2. */
26
+ expressivity: number;
27
+ /** From 0 to 1, or null when no live audio drives the motion. */
28
+ audioLevel: number | null;
29
+ reduceMotion: boolean;
30
+ };
31
+
32
+ /**
33
+ * The motion of a voice visualization: where it is in time, how it moves, and its colors. A plain
34
+ * object rather than a class, so it can live in a shared value and be advanced on the UI thread.
35
+ */
36
+ export type VoiceDriverState = {
37
+ speed: number;
38
+ bright: number;
39
+ sat: number;
40
+ load: number;
41
+ flow: number;
42
+ baseReact: number;
43
+ expressivity: number;
44
+ time: number;
45
+ flowSpin: number;
46
+ orbSpin: number;
47
+ count: number;
48
+ tapX: number;
49
+ tapY: number;
50
+ tapAge: number;
51
+ hoverX: number;
52
+ hoverY: number;
53
+ hoverAmount: number;
54
+ isHovering: boolean;
55
+ mic: number;
56
+ voice: number;
57
+ /** The colors drawn, eased in place toward the input's color slots. */
58
+ colors: Hsv[];
59
+ bounce: BounceState;
60
+ levelResponse: LevelResponse;
61
+ };
62
+
63
+ /**
64
+ * How a state moves. `load`, `flow` and `react` each select a motion pattern, one per state, so
65
+ * easing between states crossfades the patterns.
66
+ */
67
+ type VoiceMotion = {
68
+ bright: number;
69
+ flow: number;
70
+ load: number;
71
+ react: number;
72
+ sat: number;
73
+ speed: number;
74
+ };
75
+
76
+ const MOTIONS: Record<VoiceAgentState, VoiceMotion> = {
77
+ connecting: { bright: 1, flow: 0, load: 1, react: 0, sat: 1, speed: 1 },
78
+ idle: { bright: 1, flow: 0, load: 0, react: 0.12, sat: 1, speed: 0.4 },
79
+ listening: { bright: 1, flow: 0, load: 0, react: 0.45, sat: 1, speed: 0.9 },
80
+ speaking: { bright: 1, flow: 0, load: 0, react: 1, sat: 1, speed: 1.25 },
81
+ thinking: { bright: 1, flow: 1, load: 0, react: 0, sat: 1, speed: 1.25 },
82
+ };
83
+
84
+ export const NO_TAP = 100;
85
+ const MAX_FRAME = 0.05;
86
+ /** How fast time runs under reduced motion. */
87
+ export const REDUCED = 0.07;
88
+ const DRIVERS = 0.08;
89
+ const GENTLE = 0.12;
90
+ const VOICE = 0.1;
91
+
92
+ /** Expressivity scales amplitude and speed, each with a floor so the motion breathes at 0. */
93
+ export const scales = (expressivity: number) => {
94
+ 'worklet';
95
+ return { amplitude: 0.15 + 0.85 * expressivity, speed: 0.6 + 0.4 * expressivity };
96
+ };
97
+
98
+ /**
99
+ * The share of the way a value moves in `dt` seconds when it moves `perFrame` of the way each
100
+ * frame at 60 Hz.
101
+ */
102
+ export const ease = (perFrame: number, dt: number) => {
103
+ 'worklet';
104
+ return 1 - Math.pow(1 - perFrame, dt * 60);
105
+ };
106
+
107
+ const rem = (x: number, m: number) => {
108
+ 'worklet';
109
+ return ((x % m) + m) % m;
110
+ };
111
+
112
+ /** Eases an HSV color in place, its hue taking the shorter way round the wheel. */
113
+ const easeHsv = (color: Hsv, target: Hsv, fraction: number) => {
114
+ 'worklet';
115
+ const hueStep = (rem(target.hue - color.hue + 1.5, 1) - 0.5) * fraction;
116
+ color.hue = rem(color.hue + hueStep + 1, 1);
117
+ color.saturation += (target.saturation - color.saturation) * fraction;
118
+ color.value += (target.value - color.value) * fraction;
119
+ };
120
+
121
+ /** The five color slots the renderers read; past the palette they repeat its first color. */
122
+ export const slots = (colors: Hsv[]): Hsv[] => {
123
+ 'worklet';
124
+ const first = colors[0] ?? { hue: 0, saturation: 0, value: 0 };
125
+ const result: Hsv[] = [];
126
+ for (let i = 0; i < MAXIMUM_COLORS; i++) result.push(colors[i] ?? first);
127
+ return result;
128
+ };
129
+
130
+ /** A driver settled on `input`, so the first frame shows it rather than easing into it. */
131
+ export const createDriverState = (
132
+ input: VoiceDriverInput,
133
+ levelResponse: LevelResponse = LEVEL_RESPONSE.steady,
134
+ ): VoiceDriverState => {
135
+ const m = MOTIONS[input.state];
136
+ const s = scales(input.expressivity);
137
+ return {
138
+ baseReact: m.react * s.amplitude,
139
+ bounce: createBounce(),
140
+ bright: m.bright,
141
+ // Copies, as they are eased in place and the palette belongs to the caller.
142
+ colors: slots(input.colors).map((color) => ({ ...color })),
143
+ count: input.colors.length,
144
+ expressivity: input.expressivity,
145
+ flow: m.flow * s.amplitude,
146
+ flowSpin: 0,
147
+ hoverAmount: 0,
148
+ hoverX: 0,
149
+ hoverY: 0,
150
+ isHovering: false,
151
+ levelResponse,
152
+ load: m.load * s.amplitude,
153
+ mic: 0,
154
+ orbSpin: 0,
155
+ sat: m.sat,
156
+ speed: m.speed * s.speed,
157
+ tapAge: NO_TAP,
158
+ tapX: 0,
159
+ tapY: 0,
160
+ time: 0,
161
+ voice: 0,
162
+ };
163
+ };
164
+
165
+ /** Live audio lifts the motion to its level, whatever the state. */
166
+ export const driverReact = (d: VoiceDriverState) => {
167
+ 'worklet';
168
+ return d.baseReact + (Math.max(d.baseReact, d.mic) - d.baseReact) * d.voice;
169
+ };
170
+
171
+ /** The scale of a tap's bounce. */
172
+ export const driverScale = (d: VoiceDriverState) => {
173
+ 'worklet';
174
+ return bounceScale(d.bounce);
175
+ };
176
+
177
+ /** A tap at (x, y), centred and normalized to the shorter side with y up. */
178
+ export const tapDriver = (d: VoiceDriverState, input: VoiceDriverInput, x: number, y: number) => {
179
+ 'worklet';
180
+ if (input.reduceMotion) return;
181
+ d.tapX = x;
182
+ d.tapY = y;
183
+ d.tapAge = 0;
184
+ startBounce(d.bounce);
185
+ };
186
+
187
+ /** Where a pointer hovers, or null once it has left. */
188
+ export const hoverDriver = (
189
+ d: VoiceDriverState,
190
+ input: VoiceDriverInput,
191
+ x: number | null,
192
+ y: number | null,
193
+ ) => {
194
+ 'worklet';
195
+ if (x === null || y === null || input.reduceMotion) {
196
+ d.isHovering = false;
197
+ return;
198
+ }
199
+ d.hoverX = x;
200
+ d.hoverY = y;
201
+ d.isHovering = true;
202
+ };
203
+
204
+ /**
205
+ * Advances the motion by `seconds`, easing each value toward the input's motion by a fixed share
206
+ * per frame at 60 Hz, converted to time, so it moves the same at any refresh rate.
207
+ */
208
+ export const advanceDriver = (d: VoiceDriverState, input: VoiceDriverInput, seconds: number) => {
209
+ 'worklet';
210
+ // Clamped so a frame after a stall cannot leap the motion.
211
+ const dt = Math.min(Math.max(seconds, 0), MAX_FRAME);
212
+ if (input.reduceMotion) d.isHovering = false;
213
+ const m = MOTIONS[input.state];
214
+ const s = scales(input.expressivity);
215
+ const drivers = ease(DRIVERS, dt);
216
+ d.speed += (m.speed * s.speed - d.speed) * drivers;
217
+ d.bright += (m.bright - d.bright) * drivers;
218
+ d.sat += (m.sat - d.sat) * drivers;
219
+ d.load += (m.load * s.amplitude - d.load) * drivers;
220
+ d.flow += (m.flow * s.amplitude - d.flow) * drivers;
221
+ d.baseReact += (m.react * s.amplitude - d.baseReact) * drivers;
222
+ d.expressivity += (input.expressivity - d.expressivity) * drivers;
223
+ // Integrated rather than computed as time times a weight, so a change of state eases the turns
224
+ // instead of jumping their angles.
225
+ const step = dt * (input.reduceMotion ? REDUCED : 1) * d.speed;
226
+ d.time += step;
227
+ d.flowSpin += step * d.flow;
228
+ d.orbSpin += step * (1 + 0.5 * d.flow + 0.1 * d.baseReact);
229
+ d.tapAge += dt;
230
+ advanceBounce(d.bounce, dt);
231
+ const gentle = ease(GENTLE, dt);
232
+ d.hoverAmount += ((d.isHovering ? 1 : 0) - d.hoverAmount) * gentle;
233
+ d.voice += ((input.audioLevel === null ? 0 : 1) - d.voice) * ease(VOICE, dt);
234
+ const level = input.audioLevel ?? 0;
235
+ const response = level > d.mic ? d.levelResponse.rise : d.levelResponse.fall;
236
+ d.mic += (level - d.mic) * ease(response, dt);
237
+ const targets = slots(input.colors);
238
+ for (let i = 0; i < d.colors.length; i++) easeHsv(d.colors[i], targets[i], gentle);
239
+ d.count += (input.colors.length - d.count) * gentle;
240
+ };