Skip to content

feat(ai-components): add VoiceWave and VoiceGlow voice-agent visualizations - #3339

Merged
oliverlaz merged 8 commits into
release-v14from
feat/ai-voice-visualizations
Oct 22, 2026
Merged

oliverlaz merged 8 commits into
release-v14from
feat/ai-voice-visualizations

Conversation

@oliverlaz

@oliverlaz oliverlaz commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Goal

Android (GetStream/stream-chat-android#6848, GetStream/stream-chat-android#6849, GetStream/stream-chat-android#6851) and iOS (GetStream/stream-chat-swift#4338) added two visualizations of a voice agent to their AI components. This brings them to stream-chat-react/ai-components on v14, with the same motion, so the three platforms look and move alike, and shows them in a new voice mode in the ai-chatbot sample.

Implementation details

Public API, all from stream-chat-react/ai-components:

  • VoiceWave: a single string carrying a wave packet that erupts with speech, its colors flowing along it.
  • VoiceGlow: a soft globe whose color masses orbit inside it and swell with speech. rendering?: 'auto' | 'css' (default auto).
  • useAudioLevel(stream): a stable getter for the live level of a MediaStream (a microphone or a remote track), for the audioLevel prop.
  • Types: VoiceAgentState, VoiceGlowRendering, VoiceVisualizationProps, VoiceWaveProps, VoiceGlowProps.

Both components take state (idle | connecting | listening | thinking | speaking), colors (one to five CSS colors, defaulting to the theme accent), expressivity (0 to 2) and audioLevel (a getter read once a frame, so a changing level re-renders nothing; null animates speech on its own). Any other div prop goes to the root.

Shared motion. A port of Android's driver: the per-state motion table, frame-rate-independent easing, reduced motion slowing time to 0.07x, the tap bounce and the HSV palette. The speech envelope runs the shader's simplex noise in float32, so the CPU-drawn wave and the GPU glow speak with the same rhythm as iOS.

VoiceWave is a Canvas2D port of Android's WaveDrawing. Its line is 0.6% of the shorter side with Android's 1.5 device-pixel floor, drawn at the screen's density up to 3x as on iOS. In speech it is smoothed on the web: the crests spread out rather than steepen past a slope of 6, and the height rises quickly and settles slowly. While idle, connecting or thinking it is exactly the native wave, and it matches Android's Paparazzi snapshots down to antialiasing.

VoiceGlow draws with a GLSL ES 1.00 port of the AGSL shader, at 1x (it is all soft gradients). Every glow on a page draws with one shared offscreen WebGL context, as iOS shares one renderer, and copies its frame onto its own 2D canvas. The shader compiles once, and a page with many glows stays under the browser's limit on live contexts. If the context is lost, every glow falls back to CSS and the next glow to mount starts a fresh context; the last glow to unmount releases it.

rendering='css', also the fallback where WebGL is unavailable or lost, is one CSS composition of the shader's glow: a color field seen through a mask riding the first mass's orbit, without the shader's fine marbling or its second, fainter riding mass. Its gradients are painted once and only transform and opacity animate, so the browser's compositor runs the motion and it keeps moving while the main thread is busy. Off screen, its animations pause and its theme and audio reads stop. With GPU acceleration disabled, it holds 60 fps at about 18 to 22% CPU at 300px in headless Chrome.

Behavior shared with iOS:

  • Only the shape takes the pointer (the globe or the string); clicks elsewhere in the box pass through. A tap bounces it and a hovering pointer ripples it, and the root's or a parent's onClick still fires.
  • It fades in once its first frame is drawn and pauses while off screen, both the canvas renderers and the CSS glow.
  • The canvas follows a change of pixel ratio, as on a move to another monitor.
  • It follows the theme through --str-chat__ai-voice-color and --str-chat__ai-voice-backdrop, re-read about once a second.
  • The root is role="img" with a name such as "Voice agent: Speaking", translated in all 12 locales.
  • It is SSR-safe.

useAudioLevel measures RMS on demand over the last 2048 samples (about 43 ms), so the level holds steady through a vowel. The audio graph is torn down when the stream changes and on unmount.

Sample app. ai-chatbot gets a voice mode: a full-panel overlay with the glow for the agent and the wave for the user's microphone. It uses useSpeechToText for dictation and speechSynthesis to read replies aloud, and returns to listening hands-free. A turn the agent is never seen working on ends after 20 seconds, with its answer if one came in. The send path moved into a shared useSendAIMessage. The sample's README and implementation.md describe it.

Known differences from native:

  • The glow is drawn at 1x where iOS uses 2x.
  • The CSS glow leaves out the shader's second riding mass and its marbling; a tap sends out a ring instead of a ripple.
  • The wave's smoothing in speech exists only on the web; it could be proposed to Android and iOS.

Tests:

  • Android's driver tests, ported.
  • Palette and color parsing, and the simplex noise against values read back from the shader on a GPU.
  • The wave renderer: native in calm states, the steepness cap, and attack and release.
  • The shared WebGL context: one compile for many glows, losing it, and releasing it.
  • The CSS glow, including resting off screen, and useAudioLevel.
  • Rejected colors under a browser-like canvas, and the canvas following a pixel-ratio change.
  • SSR, hydration, axe, class names, i18n and the style-token rules, extended to the new components.

UI Changes

Screenshots and a recording of voice mode are to be added. In the meantime, the sample's voice mode shows both components: run yarn build, then yarn start:ai-chatbot, and start voice mode from the composer. Microphone access needs Chrome, Edge or Safari.

…ations

Port the voice agent visualizations from stream-chat-android
(GetStream/stream-chat-android#6848, #6849, #6851) to the
ai-components entry point, with the same motion maths.

- VoiceWave: a string carrying a wave packet, drawn on a 2D canvas.
- VoiceGlow: a soft globe drawn by a WebGL shader, with a 2D canvas
  fallback chosen by `rendering`.
- useAudioLevel: a pull-based level getter for a MediaStream, for the
  `audioLevel` prop.
- Both follow the theme through the voice-color and voice-backdrop
  tokens, honour prefers-reduced-motion, pause off screen and are
  labelled for assistive technology in all 12 locales.

The ai-chatbot example gains a hands-free voice mode built on them,
and its send path moves into a shared useSendAIMessage hook.
…ow to the globe

The glow is all soft gradients, so a 2x backing store filled four times
the pixels for no visible difference; it now draws at no more than 1x,
while the wave keeps up to 2x for a crisp line. The Canvas glow clips its
color masses to the globe instead of painting past it and masking the
excess away, and computes the orbit angles once a frame.
`rendering='css'` composes the glow the way the shader does, as CSS:
an opaque color field (a base and the masses mixed over it in order,
with the shader's smoothstep falloffs, diffuse shade and fresnel rim)
seen through an alpha that only the first two masses carry, a faint
static body plus one mask riding each of their orbits, with inverse
turns inside each mask keeping the colors still.

Every gradient is painted once and only transform and opacity animate,
so the compositor runs the motion: it keeps moving while the main
thread is busy, needs no canvas or WebGL, and runs no script per frame
unless an audio level is given. The palette is computed with the
shader's color math and follows the theme; each state sets playback
rates, so state changes ease instead of jumping. WebGL stays the
default for `auto`.
…h, speech rhythm and fade-in

- Only the shape takes the pointer: the root lets events through to
  whatever is behind it, and a hit area the size of the globe or the
  string takes them and hands them to the root's handlers.
- The wave and the Canvas glow animate speech with the shader's simplex
  envelope, ported in float32, instead of a 1-D CPU noise, so every
  renderer and iOS share the same rhythm.
- The visualizations fade in over 0.3s once their first frame is drawn
  (the CSS glow once its palette is set), instantly with reduced motion.
…ghter CSS glow

`rendering` is now 'auto' | 'webgl' | 'css'. Where WebGL cannot start or
loses its context, VoiceGlow falls back to the CSS renderer instead of a
Canvas2D drawing: closer to the shader in look, and it keeps moving while
the main thread is busy.

Standing in for WebGL, the GPU is likely off and the compositor blends
every layer on the CPU, so the fallback draws a lighter CSS glow: the
still body and the body riding the first orbit, without the stretches,
shade and rim. With GPU acceleration off it holds 60 fps at about half
the CPU of the full CSS glow, close to the old Canvas2D cost, while
leaving the main thread nearly idle. An explicit rendering='css' keeps
the full look. Both skip masses the palette leaves empty.

The Canvas2D renderer and the 1-D noise only it used are removed.
…t at up to 3x

Stroke the wave at 0.6% of the shorter side with Android's 1.5 device-pixel floor, instead of a
1.5 CSS-pixel floor that made it heavier in boxes under 250px, and draw it at the screen's own
density up to 3x, as iOS does. Each visualization now sets its own pixel-ratio cap.

Give the ai-chatbot voice mode's wave a square box, since the wave is sized from the shorter side.
In loud speech the wave's crests rose into near-vertical spikes and its height swung sharply
with every syllable. The crests now spread out instead of steepening past a slope of 6, with the
cap on their spacing eased so it breathes, and the speech height rises quickly and settles
slowly, with shallower syllables. While idle, connecting or thinking the wave is still exactly
the Android and iOS wave.

useAudioLevel now measures over 2048 samples (about 43 ms) instead of 256, a few pitch periods of
a voice, so the level holds steady through a vowel. Renderers get the time since the last frame
so the smoothing runs at the same speed at any frame rate.

The voice-mode demo uses the default expressivity, and the CSS glow stylesheet uses list.nth in
place of the deprecated global nth.
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Size Change: +49.1 kB (+4.34%)

Total Size: 1.18 MB

📦 View Changed
Filename Size Change
dist/cjs/ai-components.js 25.7 kB +19.5 kB (+314.29%) 🆘
dist/cjs/index.js 251 kB +624 B (+0.25%)
dist/cjs/useMessageTextStreaming.js 0 B -852 B (removed) 🏆
dist/cjs/useReducedMotionPreference.js 1.2 kB +1.2 kB (new file) 🆕
dist/css/ai-components.css 4.58 kB +1.59 kB (+53.11%) 🆘
dist/es/ai-components.mjs 283 B +62 B (+28.05%) 🚨
dist/es/i18n/de.mjs 12.1 kB +109 B (+0.91%)
dist/es/i18n/en.mjs 8.92 kB +86 B (+0.97%)
dist/es/i18n/es.mjs 12.3 kB +110 B (+0.91%)
dist/es/i18n/fr.mjs 12.5 kB +123 B (+0.99%)
dist/es/i18n/hi.mjs 13.4 kB +120 B (+0.9%)
dist/es/i18n/it.mjs 12.2 kB +113 B (+0.94%)
dist/es/i18n/ja.mjs 12.7 kB +140 B (+1.12%)
dist/es/i18n/ko.mjs 12.4 kB +122 B (+1%)
dist/es/i18n/nl.mjs 11.8 kB +117 B (+1%)
dist/es/i18n/pt.mjs 12.2 kB +107 B (+0.89%)
dist/es/i18n/ru.mjs 14.5 kB +133 B (+0.93%)
dist/es/i18n/tr.mjs 11.9 kB +113 B (+0.96%)
dist/es/plugins/AIComponents/VoiceVisualization/bounce.mjs 804 B +804 B (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/cssGlow.mjs 2.27 kB +2.27 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/driver.mjs 1.99 kB +1.99 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/hitArea.mjs 496 B +496 B (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/math.mjs 1.15 kB +1.15 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/palette.mjs 1.59 kB +1.59 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/renderers/glowWebGLRenderer.mjs 4.75 kB +4.75 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/renderers/types.mjs 216 B +216 B (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/renderers/waveRenderer.mjs 2.26 kB +2.26 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/simplex.mjs 1.26 kB +1.26 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/useAudioLevel.mjs 1.26 kB +1.26 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/useVoiceStateLabel.mjs 356 B +356 B (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/VoiceGlow.mjs 771 B +771 B (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/VoiceGlowCss.mjs 3.39 kB +3.39 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/VoiceVisualizationView.mjs 2.38 kB +2.38 kB (new file) 🆕
dist/es/plugins/AIComponents/VoiceVisualization/VoiceWave.mjs 628 B +628 B (new file) 🆕
ℹ️ View Unchanged
Filename Size
dist/cjs/audioProcessing.js 1.74 kB
dist/cjs/channel-detail.js 23.2 kB
dist/cjs/Chart.js 1.09 kB
dist/cjs/chartTypes.js 584 B
dist/cjs/emojis.js 2.69 kB
dist/cjs/mp3-encoder.js 814 B
dist/cjs/NotificationList.js 67 kB
dist/cjs/ReactPlayerWrapper.js 547 B
dist/cjs/useChannelHeaderOnlineStatus.js 8.82 kB
dist/cjs/useInertWhenHidden.js 57.3 kB
dist/cjs/useStableCallback.js 902 B
dist/cjs/useStableId.js 24.7 kB
dist/css/channel-detail.css 2.84 kB
dist/css/emoji-picker.css 178 B
dist/css/emoji-replacement.css 456 B
dist/css/index.css 42.1 kB
dist/es/_virtual/_rolldown/runtime.mjs 252 B
dist/es/a11y/a11yUtils.mjs 630 B
dist/es/a11y/accessibleLabel.mjs 721 B
dist/es/a11y/hooks/useAriaIdentifiers.mjs 540 B
dist/es/a11y/hooks/useListboxKeyboardNavigation.mjs 1.52 kB
dist/es/a11y/hooks/useResolvedModalAriaProps.mjs 497 B
dist/es/a11y/hooks/useVirtualizedListboxKeyboardNavigation.mjs 1.39 kB
dist/es/channel-detail.mjs 802 B
dist/es/components/Accessibility/AriaLiveAnnouncerProvider.mjs 1.65 kB
dist/es/components/Accessibility/AriaLiveOutlet.mjs 964 B
dist/es/components/Accessibility/AriaLiveOutletContext.mjs 194 B
dist/es/components/Accessibility/hooks/useAudioPlaybackChangeAnnouncements.mjs 425 B
dist/es/components/Accessibility/hooks/useFocusReturn.mjs 916 B
dist/es/components/Accessibility/hooks/useIncomingMessageAnnouncements.mjs 1.19 kB
dist/es/components/Accessibility/hooks/useInertWhenHidden.mjs 1.62 kB
dist/es/components/Accessibility/hooks/useInteractionAnnouncements.mjs 3.02 kB
dist/es/components/Accessibility/NotificationAnnouncer.mjs 1.4 kB
dist/es/components/Accessibility/scheduling/useAnnouncementQueue.mjs 793 B
dist/es/components/Accessibility/scheduling/useDebouncedAnnounce.mjs 1.68 kB
dist/es/components/Accessibility/scheduling/useSettledAnnouncement.mjs 1.84 kB
dist/es/components/Accessibility/useAriaLiveAnnouncer.mjs 300 B
dist/es/components/AIStateIndicator/AIStateIndicator.mjs 458 B
dist/es/components/AIStateIndicator/hooks/useAIState.mjs 616 B
dist/es/components/Attachment/attachment-sizing.mjs 1.05 kB
dist/es/components/Attachment/Attachment.mjs 971 B
dist/es/components/Attachment/AttachmentActions.mjs 1.59 kB
dist/es/components/Attachment/AttachmentContainer.mjs 2.47 kB
dist/es/components/Attachment/Audio.mjs 1.48 kB
dist/es/components/Attachment/audioSampling.mjs 1.29 kB
dist/es/components/Attachment/components/AttachmentUploadProgressIndicator.mjs 825 B
dist/es/components/Attachment/components/DownloadButton.mjs 669 B
dist/es/components/Attachment/components/FileSizeIndicator.mjs 436 B
dist/es/components/Attachment/FileAttachment.mjs 644 B
dist/es/components/Attachment/Geolocation.mjs 1.07 kB
dist/es/components/Attachment/Giphy.mjs 1.03 kB
dist/es/components/Attachment/giphyAccessibility.mjs 481 B
dist/es/components/Attachment/hooks/useAttachmentUploadState.mjs 2.31 kB
dist/es/components/Attachment/hooks/useLocalVideoDimensions.mjs 1.43 kB
dist/es/components/Attachment/icons.mjs 411 B
dist/es/components/Attachment/Image.mjs 346 B
dist/es/components/Attachment/LinkPreview/Card.mjs 1.03 kB
dist/es/components/Attachment/LinkPreview/UnableToRenderCard.mjs 402 B
dist/es/components/Attachment/ModalGallery.mjs 1.87 kB
dist/es/components/Attachment/UnsupportedAttachment.mjs 403 B
dist/es/components/Attachment/utils.mjs 740 B
dist/es/components/Attachment/VideoAttachment.mjs 936 B
dist/es/components/Attachment/VisibilityDisclaimer.mjs 354 B
dist/es/components/Attachment/VoiceRecording.mjs 1.75 kB
dist/es/components/AudioPlayback/AudioPlayer.mjs 3.58 kB
dist/es/components/AudioPlayback/AudioPlayerPool.mjs 1.01 kB
dist/es/components/AudioPlayback/components/DurationDisplay.mjs 596 B
dist/es/components/AudioPlayback/components/formatTime.mjs 339 B
dist/es/components/AudioPlayback/components/keyboardSeek.mjs 524 B
dist/es/components/AudioPlayback/components/PlaybackRateButton.mjs 300 B
dist/es/components/AudioPlayback/components/ProgressBar.mjs 819 B
dist/es/components/AudioPlayback/components/progressBarA11y.mjs 460 B
dist/es/components/AudioPlayback/components/useInteractiveProgressBar.mjs 1.07 kB
dist/es/components/AudioPlayback/components/WaveProgressBar.mjs 1.72 kB
dist/es/components/AudioPlayback/plugins/AudioPlayerNotificationsPlugin.mjs 613 B
dist/es/components/AudioPlayback/WithAudioPlayback.mjs 1 kB
dist/es/components/Avatar/Avatar.mjs 1.02 kB
dist/es/components/Avatar/AvatarStack.mjs 669 B
dist/es/components/Avatar/ChannelAvatar.mjs 344 B
dist/es/components/Avatar/GroupAvatar.mjs 868 B
dist/es/components/Avatar/utils.mjs 183 B
dist/es/components/Badge/Badge.mjs 509 B
dist/es/components/Badge/MediaBadge.mjs 426 B
dist/es/components/BaseImage/BaseImage.mjs 682 B
dist/es/components/BaseImage/ImagePlaceholder.mjs 397 B
dist/es/components/BaseImage/toBaseImageDescriptors.mjs 547 B
dist/es/components/Button/Button.mjs 529 B
dist/es/components/Button/PlayButton.mjs 475 B
dist/es/components/Channel/Channel.mjs 7.14 kB
dist/es/components/Channel/channelState.mjs 978 B
dist/es/components/Channel/constants.mjs 156 B
dist/es/components/Channel/hooks/useChannelContainerClasses.mjs 391 B
dist/es/components/Channel/hooks/useCreateChannelStateContext.mjs 1.1 kB
dist/es/components/Channel/hooks/useCreateTypingContext.mjs 229 B
dist/es/components/Channel/hooks/useEditMessageHandler.mjs 297 B
dist/es/components/Channel/hooks/useIsMounted.mjs 235 B
dist/es/components/Channel/hooks/useMentionsHandlers.mjs 448 B
dist/es/components/Channel/utils.mjs 2.12 kB
dist/es/components/ChannelHeader/ChannelHeader.mjs 927 B
dist/es/components/ChannelHeader/hooks/useChannelHasMembersOnline.mjs 651 B
dist/es/components/ChannelHeader/hooks/useChannelHeaderOnlineStatus.mjs 599 B
dist/es/components/ChannelList/ChannelList.mjs 2.29 kB
dist/es/components/ChannelList/ChannelListHeader.mjs 380 B
dist/es/components/ChannelList/ChannelListUI.mjs 607 B
dist/es/components/ChannelList/hooks/useChannelListKeyboardNavigation.mjs 1.25 kB
dist/es/components/ChannelList/hooks/useChannelListShape.mjs 2.14 kB
dist/es/components/ChannelList/hooks/useChannelMembershipState.mjs 262 B
dist/es/components/ChannelList/hooks/useChannelMembersState.mjs 300 B
dist/es/components/ChannelList/hooks/useConnectionRecoveredListener.mjs 306 B
dist/es/components/ChannelList/hooks/usePaginatedChannels.mjs 1.59 kB
dist/es/components/ChannelList/hooks/useSelectedChannelState.mjs 403 B
dist/es/components/ChannelList/utils.mjs 1.05 kB
dist/es/components/ChannelListItem/ChannelListItem.mjs 1.3 kB
dist/es/components/ChannelListItem/ChannelListItemActionButtons.mjs 2.46 kB
dist/es/components/ChannelListItem/ChannelListItemTimestamp.mjs 505 B
dist/es/components/ChannelListItem/ChannelListItemUI.mjs 1.51 kB
dist/es/components/ChannelListItem/hooks/useChannelDisplayName.mjs 817 B
dist/es/components/ChannelListItem/hooks/useChannelPreviewInfo.mjs 624 B
dist/es/components/ChannelListItem/hooks/useIsChannelMuted.mjs 671 B
dist/es/components/ChannelListItem/hooks/useIsUserMuted.mjs 269 B
dist/es/components/ChannelListItem/hooks/useMessageDeliveryStatus.mjs 830 B
dist/es/components/ChannelListItem/utils.a11y.mjs 2.37 kB
dist/es/components/ChannelListItem/utils.mjs 2.59 kB
dist/es/components/Chat/Chat.mjs 1.25 kB
dist/es/components/Chat/hooks/useChannelsQueryState.mjs 250 B
dist/es/components/Chat/hooks/useChat.mjs 1.05 kB
dist/es/components/Chat/hooks/useCreateChatClient.mjs 533 B
dist/es/components/Chat/hooks/useCreateChatContext.mjs 539 B
dist/es/components/Chat/hooks/useReportLostConnectionSystemNotification.mjs 677 B
dist/es/components/Chat/hooks/useSplitActionSet.mjs 319 B
dist/es/components/ChatView/a11y.utility.mjs 291 B
dist/es/components/ChatView/mjs 2.24 kB
dist/es/components/DateSeparator/DateSeparator.mjs 575 B
dist/es/components/Dialog/components/Alert.mjs 647 B
dist/es/components/Dialog/components/Callout.mjs 819 B
dist/es/components/Dialog/components/ContextMenu.mjs 5.49 kB
dist/es/components/Dialog/components/Prompt.mjs 1.07 kB
dist/es/components/Dialog/components/Viewer.mjs 963 B
dist/es/components/Dialog/hooks/useDialog.mjs 688 B
dist/es/components/Dialog/hooks/usePopoverPosition.mjs 839 B
dist/es/components/Dialog/service/DialogAnchor.mjs 2.06 kB
dist/es/components/Dialog/service/DialogManager.mjs 1.29 kB
dist/es/components/Dialog/service/DialogPortal.mjs 1.02 kB
dist/es/components/DragAndDrop/DragAndDropContainer.mjs 1.16 kB
dist/es/components/EmptyStateIndicator/EmptyStateIndicator.mjs 547 B
dist/es/components/EventComponent/EventComponent.mjs 462 B
dist/es/components/FileIcon/FileIconSet.mjs 6.71 kB
dist/es/components/FileIcon/iconMap.mjs 512 B
dist/es/components/FileIcon/mimeTypes.mjs 1.73 kB
dist/es/components/FileIcon/mjs 599 B
dist/es/components/Form/FieldError.mjs 261 B
dist/es/components/Form/hooks/useFormState.mjs 550 B
dist/es/components/Form/mjs 1.55 kB
dist/es/components/Form/NumericInput.mjs 1.33 kB
dist/es/components/Form/SwitchField.mjs 1.53 kB
dist/es/components/Form/TextInput.mjs 1.3 kB
dist/es/components/Form/TextInputFieldSet.mjs 376 B
dist/es/components/Gallery/Gallery.mjs 654 B
dist/es/components/Gallery/GalleryContext.mjs 422 B
dist/es/components/Gallery/GalleryHeader.mjs 939 B
dist/es/components/Gallery/GalleryUI.mjs 2.02 kB
dist/es/components/Icons/createIcon.mjs 429 B
dist/es/components/Icons/icons.mjs 19.3 kB
dist/es/components/Icons/mjs 378 B
dist/es/components/InfiniteScrollPaginator/hooks/useCursorPaginator.mjs 591 B
dist/es/components/InfiniteScrollPaginator/InfiniteScroll.mjs 1.34 kB
dist/es/components/InfiniteScrollPaginator/InfiniteScrollPaginator.mjs 1.03 kB
dist/es/components/ListItemLayout/ListItemLayout.mjs 707 B
dist/es/components/Loading/AttachmentUploadedSizeIndicator.mjs 634 B
dist/es/components/Loading/LoadingChannel.mjs 639 B
dist/es/components/Loading/LoadingChannels.mjs 377 B
dist/es/components/Loading/LoadingErrorIndicator.mjs 395 B
dist/es/components/Loading/LoadingIndicator.mjs 286 B
dist/es/components/Loading/progress-indicators.mjs 714 B
dist/es/components/Loading/UploadedSizeIndicator.mjs 413 B
dist/es/components/Loading/UploadProgressIndicator.mjs 366 B
dist/es/components/LoadMore/LoadMoreButton.mjs 492 B
dist/es/components/LoadMore/LoadMorePaginator.mjs 378 B
dist/es/components/Location/hooks/useLiveLocationSharingManager.mjs 631 B
dist/es/components/Location/ShareLocationDialog.mjs 2.2 kB
dist/es/components/MediaRecorder/AudioRecorder/AudioRecorder.mjs 621 B
dist/es/components/MediaRecorder/AudioRecorder/AudioRecorderRecordingControls.mjs 1 kB
dist/es/components/MediaRecorder/AudioRecorder/AudioRecordingButtonWithNotification.mjs 1.04 kB
dist/es/components/MediaRecorder/AudioRecorder/AudioRecordingPlayback.mjs 989 B
dist/es/components/MediaRecorder/AudioRecorder/AudioRecordingPreview.mjs 909 B
dist/es/components/MediaRecorder/AudioRecorder/hooks/useTimeElapsed.mjs 434 B
dist/es/components/MediaRecorder/AudioRecorder/recordingStateIdentity.mjs 227 B
dist/es/components/MediaRecorder/AudioRecorder/RecordingTimer.mjs 322 B
dist/es/components/MediaRecorder/classes/AmplitudeRecorder.mjs 1.05 kB
dist/es/components/MediaRecorder/classes/BrowserPermission.mjs 749 B
dist/es/components/MediaRecorder/classes/MediaRecorderController.mjs 2.53 kB
dist/es/components/MediaRecorder/hooks/useMediaRecorder.mjs 962 B
dist/es/components/MediaRecorder/observable/BehaviorSubject.mjs 353 B
dist/es/components/MediaRecorder/observable/mjs 186 B
dist/es/components/MediaRecorder/observable/Observable.mjs 310 B
dist/es/components/MediaRecorder/observable/Subject.mjs 548 B
dist/es/components/MediaRecorder/observable/Subscription.mjs 206 B
dist/es/components/MediaRecorder/RecordingPermissionDeniedNotification.mjs 481 B
dist/es/components/MediaRecorder/transcode/audioProcessing.mjs 758 B
dist/es/components/MediaRecorder/transcode/index.mjs 351 B
dist/es/components/MediaRecorder/transcode/wav.mjs 1.33 kB
dist/es/components/Message/emojiRegex.mjs 450 B
dist/es/components/Message/hooks/useActionHandler.mjs 596 B
dist/es/components/Message/hooks/useDeleteHandler.mjs 363 B
dist/es/components/Message/hooks/useFlagHandler.mjs 382 B
dist/es/components/Message/hooks/useMarkUnreadHandler.mjs 324 B
dist/es/components/Message/hooks/useMentionsHandler.mjs 455 B
dist/es/components/Message/hooks/useMessageReminder.mjs 300 B
dist/es/components/Message/hooks/useMessageTextStreaming.mjs 783 B
dist/es/components/Message/hooks/useMuteHandler.mjs 433 B
dist/es/components/Message/hooks/useOpenThreadHandler.mjs 333 B
dist/es/components/Message/hooks/usePinHandler.mjs 476 B
dist/es/components/Message/hooks/useReactionHandler.mjs 1.36 kB
dist/es/components/Message/hooks/useReactionsFetcher.mjs 492 B
dist/es/components/Message/hooks/useRetryHandler.mjs 266 B
dist/es/components/Message/hooks/useUserHandler.mjs 255 B
dist/es/components/Message/hooks/useUserRole.mjs 718 B
dist/es/components/Message/Message.mjs 1.81 kB
dist/es/components/Message/MessageAlsoSentInChannelIndicator.mjs 1.1 kB
dist/es/components/Message/MessageBlocked.mjs 444 B
dist/es/components/Message/MessageBubble.mjs 246 B
dist/es/components/Message/MessageDeletedBubble.mjs 399 B
dist/es/components/Message/MessageEditedIndicator.mjs 692 B
dist/es/components/Message/MessageRepliesCountButton.mjs 744 B
dist/es/components/Message/MessageStatus.mjs 1.25 kB
dist/es/components/Message/MessageText.mjs 1.62 kB
dist/es/components/Message/MessageTimestamp.mjs 361 B
dist/es/components/Message/MessageTranslationIndicator.mjs 866 B
dist/es/components/Message/MessageUI.mjs 2.77 kB
dist/es/components/Message/PinIndicator.mjs 610 B
dist/es/components/Message/QuotedMessage.mjs 424 B
dist/es/components/Message/ReminderNotification.mjs 947 B
dist/es/components/Message/renderText/componentRenderers/Anchor.mjs 406 B
dist/es/components/Message/renderText/componentRenderers/Emoji.mjs 246 B
dist/es/components/Message/renderText/componentRenderers/Mention.mjs 307 B
dist/es/components/Message/renderText/regex.mjs 440 B
dist/es/components/Message/renderText/rehypePlugins/emojiMarkdownPlugin.mjs 338 B
dist/es/components/Message/renderText/rehypePlugins/mentionsMarkdownPlugin.mjs 1.47 kB
dist/es/components/Message/renderText/remarkPlugins/htmlToTextPlugin.mjs 243 B
dist/es/components/Message/renderText/remarkPlugins/imageToLink.mjs 591 B
dist/es/components/Message/renderText/remarkPlugins/keepLineBreaksPlugin.mjs 824 B
dist/es/components/Message/renderText/remarkPlugins/plusPlusToEmphasis.mjs 962 B
dist/es/components/Message/renderText/remarkPlugins/remarkIgnoreMarkdown.mjs 337 B
dist/es/components/Message/renderText/renderText.mjs 1.58 kB
dist/es/components/Message/StreamedMessageText.mjs 484 B
dist/es/components/Message/Timestamp.mjs 517 B
dist/es/components/Message/utils.mjs 2.65 kB
dist/es/components/MessageActions/DeleteMessageAlert.mjs 581 B
dist/es/components/MessageActions/DownloadSubmenu.mjs 812 B
dist/es/components/MessageActions/downloadUtils.mjs 980 B
dist/es/components/MessageActions/hooks/useBaseMessageActionSetFilter.mjs 1.23 kB
dist/es/components/MessageActions/MessageActions.mjs 3.9 kB
dist/es/components/MessageActions/QuickMessageActionButton.mjs 359 B
dist/es/components/MessageActions/RemindMeSubmenu.mjs 997 B
dist/es/components/MessageBounce/MessageBounceModal.mjs 348 B
dist/es/components/MessageBounce/MessageBouncePrompt.mjs 772 B
dist/es/components/MessageComposer/AttachmentPreviewList/AttachmentPreviewList.mjs 1.19 kB
dist/es/components/MessageComposer/AttachmentPreviewList/AudioAttachmentPreview.mjs 1.75 kB
dist/es/components/MessageComposer/AttachmentPreviewList/FileAttachmentPreview.mjs 1.05 kB
dist/es/components/MessageComposer/AttachmentPreviewList/GeolocationPreview.mjs 715 B
dist/es/components/MessageComposer/AttachmentPreviewList/MediaAttachmentPreview.mjs 1.33 kB
dist/es/components/MessageComposer/AttachmentPreviewList/UnsupportedAttachmentPreview.mjs 529 B
dist/es/components/MessageComposer/AttachmentPreviewList/utils/AttachmentPreviewRoot.mjs 884 B
dist/es/components/MessageComposer/AttachmentPreviewList/VoiceRecordingPreviewSlot.mjs 548 B
dist/es/components/MessageComposer/AttachmentSelector/AttachmentSelector.mjs 3.23 kB
dist/es/components/MessageComposer/AttachmentSelector/CommandsMenu.mjs 1.29 kB
dist/es/components/MessageComposer/CommandChip.mjs 550 B
dist/es/components/MessageComposer/CooldownTimer.mjs 294 B
dist/es/components/MessageComposer/EditedMessagePreview.mjs 318 B
dist/es/components/MessageComposer/hooks/useAttachmentManagerState.mjs 405 B
dist/es/components/MessageComposer/hooks/useAttachmentsForPreview.mjs 362 B
dist/es/components/MessageComposer/hooks/useCanCreatePoll.mjs 285 B
dist/es/components/MessageComposer/hooks/useCooldownRemaining.mjs 449 B
dist/es/components/MessageComposer/hooks/useCreateMessageComposerContext.mjs 429 B
dist/es/components/MessageComposer/hooks/useIsCooldownActive.mjs 294 B
dist/es/components/MessageComposer/hooks/useMessageComposerBindings.mjs 374 B
dist/es/components/MessageComposer/hooks/useMessageComposerCommands.mjs 414 B
dist/es/components/MessageComposer/hooks/useMessageComposerController.mjs 680 B
dist/es/components/MessageComposer/hooks/useMessageComposerHasSendableData.mjs 274 B
dist/es/components/MessageComposer/hooks/useMessageContentIsEmpty.mjs 274 B
dist/es/components/MessageComposer/hooks/usePasteHandler.mjs 577 B
dist/es/components/MessageComposer/hooks/useSubmitHandler.mjs 1.49 kB
dist/es/components/MessageComposer/hooks/useTextareaRef.mjs 269 B
dist/es/components/MessageComposer/hooks/utils.mjs 339 B
dist/es/components/MessageComposer/icons.mjs 1.26 kB
dist/es/components/MessageComposer/LinkPreviewList.mjs 1.07 kB
dist/es/components/MessageComposer/MessageComposer.mjs 1.01 kB
dist/es/components/MessageComposer/MessageComposerActions.mjs 1.31 kB
dist/es/components/MessageComposer/MessageComposerUI.mjs 1.41 kB
dist/es/components/MessageComposer/preEditSnapshot.mjs 627 B
dist/es/components/MessageComposer/QuotedMessageIndicator.mjs 263 B
dist/es/components/MessageComposer/QuotedMessagePreview.mjs 2.93 kB
dist/es/components/MessageComposer/RemoveAttachmentPreviewButton.mjs 586 B
dist/es/components/MessageComposer/SendButton.mjs 483 B
dist/es/components/MessageComposer/SendToChannelCheckbox.mjs 748 B
dist/es/components/MessageComposer/StopAIGenerationButton.mjs 354 B
dist/es/components/MessageComposer/WithDragAndDropUpload.mjs 1.59 kB
dist/es/components/MessageList/FloatingDateSeparator.mjs 687 B
dist/es/components/MessageList/GiphyPreviewMessage.mjs 278 B
dist/es/components/MessageList/hooks/MessageList/useEnrichedMessages.mjs 648 B
dist/es/components/MessageList/hooks/MessageList/useFloatingDateSeparatorMessageList.mjs 933 B
dist/es/components/MessageList/hooks/MessageList/useMessageListElements.mjs 571 B
dist/es/components/MessageList/hooks/MessageList/useMessageListScrollManager.mjs 1.68 kB
dist/es/components/MessageList/hooks/MessageList/useScrollLocationLogic.mjs 3.14 kB
dist/es/components/MessageList/hooks/MessageList/useUnreadMessagesNotification.mjs 1.12 kB
dist/es/components/MessageList/hooks/useLastDeliveredData.mjs 539 B
dist/es/components/MessageList/hooks/useLastOwnMessage.mjs 249 B
dist/es/components/MessageList/hooks/useLastReadData.mjs 397 B
dist/es/components/MessageList/hooks/useMarkRead.mjs 1.18 kB
dist/es/components/MessageList/hooks/useReducedMotionPreference.mjs 475 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useFloatingDateSeparator.mjs 955 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useGiphyPreview.mjs 427 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useMessageSetKey.mjs 396 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useNewMessageNotification.mjs 533 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/usePrependMessagesCount.mjs 647 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useScrollerViewport.mjs 1.12 kB
dist/es/components/MessageList/hooks/VirtualizedMessageList/useScrollToBottomOnNewMessage.mjs 499 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useShouldForceScrollToBottom.mjs 422 B
dist/es/components/MessageList/hooks/VirtualizedMessageList/useUnreadMessagesNotificationVirtualized.mjs 721 B
dist/es/components/MessageList/MessageList.mjs 3.87 kB
dist/es/components/MessageList/MessageListMainPanel.mjs 284 B
dist/es/components/MessageList/NewMessageNotification.mjs 519 B
dist/es/components/MessageList/renderMessages.mjs 1.13 kB
dist/es/components/MessageList/ScrollToLatestMessageButton.mjs 1.09 kB
dist/es/components/MessageList/UnreadMessagesNotification.mjs 616 B
dist/es/components/MessageList/UnreadMessagesSeparator.mjs 601 B
dist/es/components/MessageList/utils.mjs 2.19 kB
dist/es/components/MessageList/VirtualizedMessageList.mjs 4.35 kB
dist/es/components/MessageList/VirtualizedMessageListComponents.mjs 1.66 kB
dist/es/components/Modal/GlobalModal.mjs 1.81 kB
dist/es/components/Notifications/hooks/useNotificationApi.mjs 1.27 kB
dist/es/components/Notifications/hooks/useNotifications.mjs 569 B
dist/es/components/Notifications/hooks/useNotificationTarget.mjs 422 B
dist/es/components/Notifications/hooks/useSystemNotifications.mjs 458 B
dist/es/components/Notifications/Notification.mjs 1.22 kB
dist/es/components/Notifications/NotificationConfigurationContext.mjs 386 B
dist/es/components/Notifications/NotificationList.mjs 3.17 kB
dist/es/components/Notifications/notificationTarget.mjs 636 B
dist/es/components/Poll/hooks/useManagePollVotesRealtime.mjs 686 B
dist/es/components/Poll/hooks/usePollAnswerPagination.mjs 566 B
dist/es/components/Poll/hooks/usePollOptionVotesPagination.mjs 572 B
dist/es/components/Poll/mjs 872 B
dist/es/components/Poll/Poll.mjs 302 B
dist/es/components/Poll/PollActions/AddCommentPrompt.mjs 1.25 kB
dist/es/components/Poll/PollActions/EndPollAlert.mjs 764 B
dist/es/components/Poll/PollActions/PollAction.mjs 492 B
dist/es/components/Poll/PollActions/PollActions.mjs 1.26 kB
dist/es/components/Poll/PollActions/PollAnswerList.mjs 1.01 kB
dist/es/components/Poll/PollActions/PollOptionsFullList.mjs 561 B
dist/es/components/Poll/PollActions/PollQuestion.mjs 335 B
dist/es/components/Poll/PollActions/PollResults/PollOptionWithVotes.mjs 815 B
dist/es/components/Poll/PollActions/PollResults/PollOptionWithVotesHeader.mjs 684 B
dist/es/components/Poll/PollActions/PollResults/PollOptionWithVotesList.mjs 615 B
dist/es/components/Poll/PollActions/PollResults/PollResults.mjs 1.03 kB
dist/es/components/Poll/PollActions/SuggestPollOptionPrompt.mjs 1.23 kB
dist/es/components/Poll/PollContent.mjs 488 B
dist/es/components/Poll/PollCreationDialog/MultipleAnswersField.mjs 1.24 kB
dist/es/components/Poll/PollCreationDialog/NameField.mjs 677 B
dist/es/components/Poll/PollCreationDialog/OptionFieldSet.mjs 2.24 kB
dist/es/components/Poll/PollCreationDialog/PollCreationDialog.mjs 1.02 kB
dist/es/components/Poll/PollCreationDialog/PollCreationDialogControls.mjs 820 B
dist/es/components/Poll/PollCreationDialog/PollOptionReorderHandle.mjs 982 B
dist/es/components/Poll/PollHeader.mjs 635 B
dist/es/components/Poll/PollOptionList.mjs 814 B
dist/es/components/Poll/PollOptionSelector.mjs 1.47 kB
dist/es/components/Portal/Portal.mjs 300 B
dist/es/components/ReactFileUtilities/UploadButton.mjs 803 B
dist/es/components/ReactFileUtilities/utils.mjs 1.06 kB
dist/es/components/Reactions/hooks/useFetchReactions.mjs 701 B
dist/es/components/Reactions/hooks/useProcessReactions.mjs 1.23 kB
dist/es/components/Reactions/MessageReactions.mjs 2.07 kB
dist/es/components/Reactions/MessageReactionsDetail.mjs 1.89 kB
dist/es/components/Reactions/reactionOptions.mjs 1.11 kB
dist/es/components/Reactions/ReactionSelector.mjs 1.58 kB
dist/es/components/Reactions/ReactionSelectorWithButton.mjs 910 B
dist/es/components/Reactions/SpriteImage.mjs 727 B
dist/es/components/Reactions/utils/utils.mjs 284 B
dist/es/components/SafeAnchor/SafeAnchor.mjs 336 B
dist/es/components/Search/hooks/useAnnounceSearchResultCount.mjs 1.31 kB
dist/es/components/Search/hooks/useSearchFocusedMessage.mjs 296 B
dist/es/components/Search/hooks/useSearchQueriesInProgress.mjs 450 B
dist/es/components/Search/hooks/useSearchResultsKeyboardNavigation.mjs 721 B
dist/es/components/Search/Search.mjs 643 B
dist/es/components/Search/SearchBar/SearchBar.mjs 1.32 kB
dist/es/components/Search/SearchContext.mjs 306 B
dist/es/components/Search/SearchResults/SearchResultItem.mjs 1.27 kB
dist/es/components/Search/SearchResults/SearchResults.mjs 711 B
dist/es/components/Search/SearchResults/SearchResultsHeader.mjs 856 B
dist/es/components/Search/SearchResults/SearchResultsPresearch.mjs 305 B
dist/es/components/Search/SearchResults/SearchSourceResultList.mjs 649 B
dist/es/components/Search/SearchResults/SearchSourceResultListFooter.mjs 547 B
dist/es/components/Search/SearchResults/SearchSourceResults.mjs 562 B
dist/es/components/Search/SearchResults/SearchSourceResultsEmpty.mjs 308 B
dist/es/components/Search/SearchResults/SearchSourceResultsHeader.mjs 148 B
dist/es/components/Search/SearchResults/SearchSourceResultsLoadingIndicator.mjs 375 B
dist/es/components/Search/SearchSourceResultsContext.mjs 316 B
dist/es/components/SkipNavigation/SkipNavigation.mjs 1.01 kB
dist/es/components/SummarizedMessagePreview/hooks/useLatestMessagePreview.mjs 1.36 kB
dist/es/components/SummarizedMessagePreview/SummarizedMessagePreview.mjs 821 B
dist/es/components/TextareaComposer/hooks/useTextareaPlaceholder.mjs 600 B
dist/es/components/TextareaComposer/SuggestionList/CommandItem.mjs 481 B
dist/es/components/TextareaComposer/SuggestionList/EmoticonItem.mjs 508 B
dist/es/components/TextareaComposer/SuggestionList/MentionItem/BroadcastMentionItem.mjs 614 B
dist/es/components/TextareaComposer/SuggestionList/MentionItem/MentionItem.mjs 439 B
dist/es/components/TextareaComposer/SuggestionList/MentionItem/MentionSuggestionTitle.mjs 236 B
dist/es/components/TextareaComposer/SuggestionList/MentionItem/mjs 775 B
dist/es/components/TextareaComposer/SuggestionList/MentionItem/SpecialMentionItem.mjs 161 B
dist/es/components/TextareaComposer/SuggestionList/MentionItem/UserGroupItem.mjs 590 B
dist/es/components/TextareaComposer/SuggestionList/SuggestionList.mjs 2.39 kB
dist/es/components/TextareaComposer/SuggestionList/SuggestionListItem.mjs 648 B
dist/es/components/TextareaComposer/SuggestionList/TokenizedSuggestionParts.mjs 608 B
dist/es/components/TextareaComposer/TextareaComposer.mjs 3.78 kB
dist/es/components/Thread/LegacyThreadContext.mjs 198 B
dist/es/components/Thread/Thread.mjs 1.39 kB
dist/es/components/Thread/ThreadHead.mjs 416 B
dist/es/components/Thread/ThreadHeader.mjs 1.34 kB
dist/es/components/Thread/ThreadStart.mjs 461 B
dist/es/components/Threads/ThreadContext.mjs 305 B
dist/es/components/Threads/ThreadList/ThreadList.mjs 1.52 kB
dist/es/components/Threads/ThreadList/ThreadListEmptyPlaceholder.mjs 390 B
dist/es/components/Threads/ThreadList/ThreadListHeader.mjs 395 B
dist/es/components/Threads/ThreadList/ThreadListItem.mjs 351 B
dist/es/components/Threads/ThreadList/ThreadListItemUI.mjs 1.72 kB
dist/es/components/Threads/ThreadList/ThreadListLoadingIndicator.mjs 441 B
dist/es/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.mjs 625 B
dist/es/components/Threads/ThreadList/utils.a11y.mjs 1.74 kB
dist/es/components/Threads/UnreadCountBadge.mjs 332 B
dist/es/components/Tooltip/hooks/useEnterLeaveHandlers.mjs 296 B
dist/es/components/Tooltip/Tooltip.mjs 556 B
dist/es/components/TypingIndicator/hooks/useDebouncedTypingActive.mjs 974 B
dist/es/components/TypingIndicator/TypingIndicator.mjs 1.22 kB
dist/es/components/TypingIndicator/TypingIndicatorDots.mjs 411 B
dist/es/components/TypingIndicator/TypingIndicatorHeader.mjs 838 B
dist/es/components/TypingIndicator/utils/getTypingStatusMessage.mjs 384 B
dist/es/components/UtilityComponents/ErrorBoundary.mjs 313 B
dist/es/components/UtilityComponents/hooks/useMutationObserver.mjs 798 B
dist/es/components/UtilityComponents/NullComponent.mjs 138 B
dist/es/components/UtilityComponents/useStableId.mjs 455 B
dist/es/components/VideoPlayer/ReactPlayerWrapper.mjs 481 B
dist/es/components/VideoPlayer/VideoPlayer.mjs 466 B
dist/es/components/VideoPlayer/VideoThumbnail.mjs 550 B
dist/es/components/VisuallyHidden/VisuallyHidden.mjs 397 B
dist/es/components/Window/Window.mjs 406 B
dist/es/constants/messageTypes.mjs 173 B
dist/es/context/AttachmentSelectorContext.mjs 272 B
dist/es/context/ChannelActionContext.mjs 412 B
dist/es/context/ChannelListContext.mjs 334 B
dist/es/context/ChannelStateContext.mjs 453 B
dist/es/context/ChatContext.mjs 402 B
dist/es/context/ComponentContext.mjs 263 B
dist/es/context/DialogManagerContext.mjs 1.38 kB
dist/es/context/MessageBounceContext.mjs 739 B
dist/es/context/MessageComposerContext.mjs 306 B
dist/es/context/MessageContext.mjs 305 B
dist/es/context/MessageListContext.mjs 434 B
dist/es/context/MessageTranslationViewContext.mjs 1.55 kB
dist/es/context/ModalContext.mjs 385 B
dist/es/context/PollContext.mjs 278 B
dist/es/context/TranslationContext.mjs 544 B
dist/es/context/TypingContext.mjs 408 B
dist/es/context/useComponentContextIcons.mjs 564 B
dist/es/context/VirtualizedMessageListContext.mjs 310 B
dist/es/context/WithComponents.mjs 308 B
dist/es/emojis.mjs 126 B
dist/es/i18n/Streami18n.mjs 5.08 kB
dist/es/i18n/TranslationBuilder/notifications/NotificationTranslationTopic.mjs 588 B
dist/es/i18n/TranslationBuilder/notifications/translators.mjs 668 B
dist/es/i18n/TranslationBuilder/notifications/translatorsByNotificationType.mjs 592 B
dist/es/i18n/TranslationBuilder/TranslationBuilder.mjs 741 B
dist/es/i18n/utils.mjs 2.04 kB
dist/es/index.mjs 8.57 kB
dist/es/mp3-encoder.mjs 778 B
dist/es/plugins/AIComponents/AIMarkdown/AIMarkdown.mjs 1.19 kB
dist/es/plugins/AIComponents/AIMarkdown/tools/charts/Chart.mjs 796 B
dist/es/plugins/AIComponents/AIMarkdown/tools/charts/chartJsSchema.mjs 425 B
dist/es/plugins/AIComponents/AIMarkdown/tools/charts/chartTypes.mjs 517 B
dist/es/plugins/AIComponents/AIMarkdown/tools/charts/JsonChart.mjs 424 B
dist/es/plugins/AIComponents/AIMarkdown/tools/charts/SuspendedChart.mjs 715 B
dist/es/plugins/AIComponents/AIMessageComposer/AIMessageComposer.mjs 2.7 kB
dist/es/plugins/AIComponents/AIMessageComposer/AttachmentPreview.mjs 973 B
dist/es/plugins/AIComponents/AIMessageComposer/hooks/useSpeechToText.mjs 1.12 kB
dist/es/plugins/AIComponents/AIStateIndicator/AIStateIndicator.mjs 656 B
dist/es/plugins/AIComponents/StreamingMessage/StreamingMessage.mjs 456 B
dist/es/plugins/ChannelDetail/AvatarWithChannelDetail.mjs 703 B
dist/es/plugins/ChannelDetail/ChannelDetail.mjs 944 B
dist/es/plugins/ChannelDetail/ChannelDetailContext.mjs 373 B
dist/es/plugins/ChannelDetail/ChannelDetailEmptyList.mjs 337 B
dist/es/plugins/ChannelDetail/ChannelDetailListLoadingIndicator.mjs 419 B
dist/es/plugins/ChannelDetail/ChannelDetailNavButton.mjs 505 B
dist/es/plugins/ChannelDetail/ChannelDetailSearchInput.mjs 567 B
dist/es/plugins/ChannelDetail/SectionNavigator/SectionNavigator.mjs 1.79 kB
dist/es/plugins/ChannelDetail/SectionNavigator/SectionNavigatorHeader.mjs 832 B
dist/es/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesEmptyList.mjs 445 B
dist/es/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesView.mjs 1.48 kB
dist/es/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesView.utils.mjs 1.1 kB
dist/es/plugins/ChannelDetail/Views/ChannelFilesView/useChannelFilesSearch.mjs 726 B
dist/es/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementActions.mjs 3.67 kB
dist/es/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementView.mjs 3.54 kB
dist/es/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaEmptyList.mjs 454 B
dist/es/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.mjs 2.29 kB
dist/es/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.utils.mjs 665 B
dist/es/plugins/ChannelDetail/Views/ChannelMediaView/useChannelMediaSearch.mjs 723 B
dist/es/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberActions.mjs 3.26 kB
dist/es/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberDetail.mjs 1 kB
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersAddView.mjs 2.21 kB
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersBrowseView.mjs 1.56 kB
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersHeaderActions.mjs 1.61 kB
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersView.mjs 1.25 kB
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersView.utils.mjs 361 B
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMemberCount.mjs 408 B
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMemberIds.mjs 430 B
dist/es/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMembersSearch.mjs 744 B
dist/es/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesEmptyList.mjs 447 B
dist/es/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesView.mjs 1.66 kB
dist/es/plugins/ChannelDetail/Views/PinnedMessagesView/usePinnedMessagesCount.mjs 447 B
dist/es/plugins/ChannelDetail/Views/PinnedMessagesView/usePinnedMessagesSearch.mjs 881 B
dist/es/plugins/ChannelDetail/VirtualizedList/VirtualizedList.mjs 670 B
dist/es/plugins/Emojis/EmojiPicker.mjs 1.3 kB
dist/es/plugins/Emojis/middleware/textComposerEmojiMiddleware.mjs 1.37 kB
dist/es/plugins/Emojis/Picker.mjs 324 B
dist/es/store/hooks/useStateStore.mjs 516 B
dist/es/utils/findReverse.mjs 188 B
dist/es/utils/getChannel.mjs 690 B
dist/es/utils/getChannelConfig.mjs 266 B
dist/es/utils/getTextareaCaretRect.mjs 856 B
dist/es/utils/getWholeChar.mjs 368 B
dist/es/utils/isDmChannel.mjs 247 B
dist/es/utils/mergeDeep.mjs 197 B
dist/es/utils/useStableCallback.mjs 831 B

compressed-size-action

@codecov

codecov Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.07944% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.45%. Comparing base (b753243) to head (e2cbdeb).
⚠️ Report is 3 commits behind head on release-v14.

Files with missing lines Patch % Lines
...ents/VoiceVisualization/VoiceVisualizationView.tsx 87.60% 15 Missing ⚠️
.../VoiceVisualization/renderers/glowWebGLRenderer.ts 97.08% 3 Missing ⚠️
...nents/VoiceVisualization/renderers/waveRenderer.ts 96.73% 3 Missing ⚠️
...s/AIComponents/VoiceVisualization/VoiceGlowCss.tsx 99.22% 1 Missing ⚠️
.../plugins/AIComponents/VoiceVisualization/bounce.ts 96.87% 1 Missing ⚠️
...plugins/AIComponents/VoiceVisualization/palette.ts 98.38% 1 Missing ⚠️
...s/AIComponents/VoiceVisualization/useAudioLevel.ts 97.36% 1 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff               @@
##           release-v14    #3339      +/-   ##
===============================================
+ Coverage        85.89%   86.45%   +0.55%     
===============================================
  Files              524      540      +16     
  Lines            16649    17516     +867     
  Branches          5229     5401     +172     
===============================================
+ Hits             14301    15143     +842     
- Misses            2348     2373      +25     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 578a7cc9-b18c-475a-b837-805eea8df031

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ow and fix review findings

- Every WebGL glow now draws with one shared offscreen context and copies its frame onto its own
  2D canvas, so the shader compiles once and many glows stay under the browser's context limit.
  A lost context drops every glow to CSS; the last glow to unmount releases it.
- The CSS glow has one composition, the former fallback: no stretches, shade, rim or second
  riding mass. Off screen its animations pause and its theme and audio reads stop.
- `rendering` is `'auto' | 'css'`; `'webgl'` behaved exactly like `'auto'`.
- Colors the browser rejects are skipped instead of read as black, and an unreadable backdrop is
  no longer taken for dark.
- Both glows share the theme reading, the pointer conversion and the driver's easing constants.
- The driver computes its color slots once per palette and eases its own copies in place.
- The canvas follows a change of pixel ratio alone, as on a move to another monitor.
- Ripple timers are dropped once they fire.
- The voice-mode demo ends a turn the agent is never seen working on after 20 seconds.
@oliverlaz
oliverlaz merged commit da6f72f into release-v14 Oct 22, 2026
11 checks passed
@oliverlaz
oliverlaz deleted the feat/ai-voice-visualizations branch October 22, 2026 13:50
oliverlaz added a commit that referenced this pull request Oct 22, 2026
Resolve the ai-components README conflict with #3339 (VoiceWave and
VoiceGlow): keep both sides' exports in the component, hook, context and
type lists, and both hook sections (useHeardText and useAudioLevel).
github-actions Bot pushed a commit that referenced this pull request Oct 22, 2026
@stream-ci-bot

Copy link
Copy Markdown

🎉 This PR is included in version 14.14.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

oliverlaz added a commit that referenced this pull request Oct 22, 2026
…ardText hook (#3344)

### 🎯 Goal

`stream-chat-react/ai-components` must work standalone, without the core
SDK. `SpokenMessageText` (added in #3343) rendered through the core
`Message` components (`MessageText`, the `StreamedMessageText` fallback,
and the message and channel contexts), so it doesn't belong in the
plugin. This keeps only the utility hook. The drop-in component becomes
a recipe in the docs (GetStream/getstream.io#761).

This is the last commit of #3343 (`57e84ca2e`), which was pushed just
before the PR was merged and didn't make it in.

> ⚠️ **14.14.0 already shipped `SpokenMessageText`,
`SpokenTextProvider`, `SpokenTextContext` and `useSpokenTextContext`**
(with the message-based `useHeardText`) from
`stream-chat-react/ai-components`. This PR removes those exports and
changes `useHeardText`'s signature, and ships as a fix (14.14.1): they
were released minutes ago without docs, so it is treated as correcting a
mistaken release rather than a major change.

### 🛠 Implementation details

- **Removed:** `SpokenMessageText`, `SpokenTextProvider`,
`SpokenTextContext`, `useSpokenTextContext`, their types and their
tests.
- **`useHeardText`** now lives in
`src/plugins/AIComponents/hooks/useHeardText.ts`. Its only import is
`react`; I checked this in the source, the built ESM and the CJS bundle.
- `useHeardText({ text, heard, subscribe?, generating?, live? }) => {
heardText, isPaced, skip }`.
- `heard(now)` returns `{ chars, done } | undefined`, where `chars`
counts Unicode code points.
- `heard` and `subscribe` are read through refs, so new function
identities on each render don't restart pacing.
- Types: `HeardTextProgress`, `HeardTextFunction`, `HeardTextSubscribe`,
`UseHeardTextParams`, `UseHeardTextResult`.
- **Behaviour:**
- Reveals the first `floor(chars)` code points and never goes backwards;
surrogate pairs are never split.
  - Ticks on `requestAnimationFrame` only while paced and not done.
- The full text appears once `done && !generating`, when `live` is
false, or after `skip()`.
  - Falls back to the full text when unpaced.
- **README:** documents the hook with a plain-element example and points
to the docs for the drop-in. The VoiceWave/VoiceGlow docs from #3339 are
untouched.
- **Checks:** 21 `renderHook` tests. Full suite 3175/3175 passes, as do
`yarn types`, `yarn lint`, `yarn build` and `validate-cjs` /
`validate-esm` / `validate-entry-isolation`. In the built output,
`ai-components` exports `useHeardText` and nothing `Spoken*`, and the
main entry exports neither.
- **Verified** end to end in a Next.js app against a local Stream Agents
router, using the docs' `SpokenMessageText` recipe on this hook: each
voice reply is revealed as its audio plays.

### 🎨 UI Changes

None.
github-actions Bot pushed a commit that referenced this pull request Oct 22, 2026
## [14.14.1](v14.14.0...v14.14.1) (2026-10-22)

### Bug Fixes

* **ai-components:** replace SpokenMessageText with a standalone useHeardText hook ([#3344](#3344)) ([ad16506](ad16506)), closes [#3343](#3343) [GetStream/getstream.io#761](https://github.com/GetStream/getstream.io/issues/761) [#3343](#3343) [#3339](#3339)
oliverlaz added a commit that referenced this pull request Oct 26, 2026
…ations

Port of #3339 from the v14 line: VoiceWave, VoiceGlow and useAudioLevel in
stream-chat-react/ai-components, with v15 namespaced i18n keys
(aiComponents.voiceVisualization.*), and a voice mode in the ai-chatbot
example built on v15's channel and composer APIs.
oliverlaz added a commit that referenced this pull request Oct 26, 2026
…ations (#3347)

### Goal

Port the voice-agent visualizations from the v14 line
(#3339, released in v14.14.0) to v15, so
`stream-chat-react/ai-components` on `master` ships `VoiceWave`,
`VoiceGlow` and `useAudioLevel` with the same API, motion and theming as
v14, and the `ai-chatbot` example gets the voice mode.

### Implementation details

The components, hook, styles and tests come over from #3339 unchanged:
`VoiceWave`, `VoiceGlow` (`rendering?: 'auto' | 'css'`),
`useAudioLevel(stream)`, the types `VoiceAgentState`,
`VoiceGlowRendering`, `VoiceVisualizationProps`, `VoiceWaveProps` and
`VoiceGlowProps`, `voice-visualization.scss`, `voice-glow-css.scss` and
the new `_tokens.scss` entries. See #3339 for how they work.

Adapted to v15:

- **i18n.** The accessible name now uses namespaced keys with inline
English defaults:
`aiComponents.voiceVisualization.{connecting,listening,ready,speaking,thinking}.text`
and `aiComponents.voiceVisualization.voiceAgent.ariaLabel` (`Voice
agent: {{ state }}`). `keys.ts` and the catalog fixture are regenerated.
The v14 locale JSON changes are dropped, as v15 bundles English only.
- **Migration docs.** The six v14 keys (`Connecting`, `Listening`,
`Ready`, `Speaking`, `Thinking`, `aria/Voice agent: {{ state }}`) are
added to the key table in the AI components README and to
`ai-docs/i18n-v15-key-map.json`.
- **Tests.** The voice tests use the default translator and `mockT`
instead of v14's `en.json`. `i18n.test.tsx` checks both the requested
keys and the English defaults.
- **ai-chatbot example.** `useSendAIMessage` is the send path shared by
the composer and voice mode, rebuilt on master's flow: `useChannel()`,
`channel.ensureWatched()` for a new conversation, `composer.send()`, and
the summary in `data.custom.summary`, now written in the background so
it never delays or fails a send. `ChatContainer` wraps master's
`<Channel channel={channel}>` in `VoiceModeProvider`.
- **Voice mode fixes over v14.** Spoken turns send through an
unregistered `MessageComposer` of their own (drafts off), so they no
longer replace the typed draft or send its attachments. A failed send
stops voice mode with an error instead of waiting out the answer
timeout. The agent's answer is read from
`channel.messagePaginator.latestMessage`, which does not depend on the
window the list shows. Opening or closing voice mode refreshes the
composer's rate-limit banner.

The port adds API and breaks nothing.

### UI Changes

The same visuals as #3339. In the `ai-chatbot` example, a waveform
button in the composer opens voice mode, which needs a browser with
`SpeechRecognition` (Chrome, Edge or Safari) and microphone access.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **New Features**
* Added `VoiceWave` and `VoiceGlow` visualizations that respond to
voice-agent states and audio levels, with theme-aware colors and
accessible state labels.
* Added a CSS rendering option for the glow, including fallback when
WebGL is unavailable and support for reduced-motion preferences.
* The AI chatbot example now includes hands-free voice conversations
with pause, resume, and end controls. Voice mode requires browser speech
recognition and microphone access.
* **Documentation**
  * Added guidance on voice mode and voice visualization options.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
oliverlaz added a commit that referenced this pull request Oct 26, 2026
### Goal

Port #3343 and
#3344 from `release-v14` to v15. Together
they add `useHeardText` to `stream-chat-react/ai-components`: a
standalone hook (React only, no chat SDK imports) that reveals a text at
the pace a voice AI agent speaks it.

Neither PR was ported to `master`. #3344 removes the `SpokenMessageText`
/ `SpokenTextProvider` / `SpokenTextContext` exports that #3343 added,
so `master` never had them, and the port is the net result: the hook,
its tests, the export and the README section. A review of the port found
issues in the hook itself (shared with v14), which the second commit
fixes.

### Implementation details

**Commit 1, the port** (`feat(ai-components): add useHeardText for
voice-paced text`)

- `src/plugins/AIComponents/hooks/useHeardText.ts` and
`__tests__/useHeardText.test.ts` are byte-identical to `release-v14`.
- `src/plugins/AIComponents/index.ts` exports the hook and its types
(`HeardTextProgress`, `HeardTextFunction`, `HeardTextSubscribe`,
`UseHeardTextParams`, `UseHeardTextResult`).
- README: the `useHeardText` section matches v14; the intro sentence and
the export lists mention the hook. The VoiceWave / VoiceGlow /
`useAudioLevel` entries that sit next to it on v14 are left to the open
port of #3339 (#3347), which edits the same
README lines, so whichever lands second has a small conflict there.

**Commit 2, fixes from the review** (`fix(ai-components): restart
useHeardText for a new text and treat Infinity as fully heard`)

- A component that renders the next reply with the same hook instance
(for example the README's `SpokenReply` without a `key`) carried over
the length already shown, `skip()` and `live`, so the new reply appeared
partly or fully revealed before any audio. The reveal now starts over
when `text` is replaced by a different text. Growing or truncating the
text keeps the reveal, capped at the new length, so a regrowth after a
cut does not reuse the old length. The reset happens during render, so
the new text never renders with the previous reveal.
- `chars: Infinity` revealed nothing, contrary to the type doc ("a value
at or above the text's code point length reveals the whole text"). It
now reveals the whole text; `NaN`, negative and non-numeric counts still
mean nothing heard.
- Docs (JSDoc and README): `heard` should return `undefined` only for a
text that is not spoken. The old wording also suggested it for a text
"not known to the voice source yet", which shows the full text and then
never paces it, because the reveal does not move backwards. Also
documented: `subscribe` is bound once (remount to switch speech sources)
and is the only wake-up for a settled hook, and `heard` is called during
render, so it must be free of side effects.
- Left as is: re-subscribing on a new `subscribe` identity (it would
churn every frame with inline arrows, which the hook explicitly
supports), and polling unpaced texts (every non-spoken message would
tick forever). Rebuilding the code-point offsets per streamed chunk
costs about 20 ms over a whole 4k-character reply in 1k chunks, so it
was not optimized.

`release-v14` still has the issues fixed in commit 2; they should be
ported back.

Checks: `yarn test src/plugins/AIComponents` (101 tests, 27 for the
hook, 6 of them new), eslint `--max-warnings 0`, prettier, `tsc -p
tsconfig.lib.json --noEmit`, `yarn build`, `validate-cjs`,
`validate-esm` and `validate-entry-isolation`. The built `useHeardText`
module imports only `react`, and the main entry does not include it.

### UI Changes

None.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **New Features**
* Added a hook that reveals text in sync with speech progress, with
support for skipping the reveal and handling Unicode text. Text is shown
immediately when pacing is unavailable and fully revealed when speech or
generation is complete.
* **Documentation**
* Added usage guidance covering the hook’s inputs, results, pacing
behavior, and an example.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
oliverlaz added a commit to GetStream/stream-chat-react-native that referenced this pull request Oct 28, 2026
…ations (#3895)

Ticket: https://linear.app/stream/issue/RN-468

## 🎯 Goal

Android (GetStream/stream-chat-android#6848,
GetStream/stream-chat-android#6849, GetStream/stream-chat-android#6851),
iOS (GetStream/stream-chat-swift#4338) and web
(GetStream/stream-chat-react#3339) added two voice-agent visualizations
to their AI components. This brings them to
`stream-chat-react-native/ai-components` (and
`stream-chat-expo/ai-components`) with the same motion, so the platforms
look and move alike, and shows them in a new voice mode in
`ExpoChatGPTSample`.

## 🛠 Implementation details

**Public API** (from the `ai-components` entry point):

- `VoiceWave`: a single string carrying a wave packet that erupts with
speech, its colors flowing along it.
- `VoiceGlow`: a soft globe whose color masses orbit inside it and swell
with speech.
- `useDictationAudioLevel()`: the microphone's live level while
dictation listens, as a Reanimated `SharedValue<number | null>`.
- Types `VoiceAgentState`, `VoiceVisualizationProps`, `VoiceWaveProps`,
`VoiceGlowProps`, `DictationLevel`; `useDictationState` and
`useDictationTranscript` are now exported too.
- An optional `voiceVisualization` theme key: `colors` (default palette,
the accent color) and `backdropColor` (light or dark look; the system
color scheme when unset).

Both components take `state` (`idle | connecting | listening | thinking
| speaking`), `colors` (one to five colors), `expressivity` (0 to 2) and
`audioLevel` (a `SharedValue`, read once a frame on the UI thread;
`null` animates speech on its own). Other `View` props go to the root.

**How it's built:**

- One motion driver, ported from Android's `VoiceVisualizationDriver`
(per-state motion table, frame-rate-independent easing, reduced motion
at 0.07x, tap bounce, HSV palette, and the `Steady`/`Smooth` level
responses for glow and wave). It's plain objects and worklets, advanced
in a Reanimated `useFrameCallback`, so the motion runs on the UI thread
and keeps going while JS is busy streaming a reply.
- `VoiceGlow` is a Skia `RuntimeEffect`: Android's AGSL shader is SkSL,
so it's ported nearly verbatim and runs on every Android version. Every
glow shares one compiled effect. There is no Canvas/CSS fallback and no
`rendering` prop.
- `VoiceWave` is a Skia path with a 13-stop gradient, as Android draws
it; its speech envelope uses the shader's float32 simplex noise (as on
iOS and the web).
- Drawn at most 2x for the glow and 3x for the wave, as on iOS.
- Touches are only observed on a hit area the size of the shape, so a
parent `Pressable` still fires and touches beside the shape pass
through. Hover ripples with a mouse or pen.
- Accessibility follows native: "Voice agent" as the label and the state
as the value; Reduce Motion is honoured.
- Where native and web differ, this follows native (e.g. no web-only
wave smoothing).

**Native dictation:**

- New `AIDictationOnLevel` event (no codegen spec change; it goes
through the existing `NativeEventEmitter`). Android maps the
recognizer's `onRmsChanged`; iOS measures the audio tap in dBFS,
throttled to ~30 Hz, tuned on an iPhone for `.measurement` mode (-60 to
-35 dBFS).
- Fix: iOS dictation now remembers the `AVAudioSession` configuration it
found and restores it when dictation ends. It used to leave the session
in the `.record` category, which muted all playback in the app after the
first dictation and kept other apps' audio ducked.

**Sample:** `ExpoChatGPTSample` gets a full-screen voice mode
(`VoiceGlow` for the agent, `VoiceWave` on the microphone level). It
listens with dictation, sends the transcript, follows the agent's AI
state, reads the reply aloud with `expo-speech` and listens again. The
send path moved into a shared `useSendAIMessage`, and the demo backend
is now called with `platform: 'openai'`, as in the React example (its
Anthropic key currently fails `/summarize`).

**Entry isolation:** everything lives under `src/ai-components`;
`validate-entry-isolation` passes.

## 🎨 UI Changes

Voice mode in `ExpoChatGPTSample`, on a physical iPhone 15 Pro Max and
the iOS simulator. Screenshots and a recording to be added.

## 🧪 Testing

- Unit tests: Android's 22 driver tests and the bounce tests ported;
palette, input clamping, simplex noise against GPU readback values, hit
areas, wave geometry, rendering, accessibility label and value, theme
fallbacks, reduced motion, and the dictation level hook. `yarn
test:unit`, `yarn lint`, `yarn typecheck` and `yarn build` pass.
- The SkSL shader compiles and renders under CanvasKit, matching
Android's Paparazzi snapshot.
- iOS simulator: both visualizations render and animate, and the
voice-mode loop runs (listening, thinking, speaking, back to listening).
Speech recognition itself fails on iOS 27 simulators ("Failed to
initialize recognizer"), so transcription was faked there.
- Physical iPhone: dictation, the mic level driving the wave, the spoken
reply and the full voice loop work.
- Not yet tested: Android on a device (the Android level mapping is
untuned), SampleApp.

## ☑️ Checklist

- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [x] PR targets the `develop` branch
- [x] Documentation is updated (AI components README; the React Native
v9 AI integration docs are in a separate getstream.io PR)
- [ ] New code is tested in main example apps, including all possible
scenarios
  - [ ] SampleApp iOS and Android
  - [ ] Expo iOS and Android (iOS done, Android pending)
github-actions Bot pushed a commit that referenced this pull request Oct 28, 2026
## [15.0.0-rc.3](v15.0.0-rc.2...v15.0.0-rc.3) (2026-10-28)

### ⚠ BREAKING CHANGES

* channel.watch() resolves with the channel instance to use (the channel, or the instance that superseded it), not the server response: read channel.data, channel.state and channel.messagePaginator instead.
- channel.watch() sends no query for a channel already watched and loaded unless it asks for options the current watch was not sent with, so it no longer refreshes one: refresh with channel.reload(), load other messages through channel.messagePaginator.
- A channel.watch() while another with the same options is in flight joins it instead of sending a request.
* **MessageList:** useMessageListScrollManager no longer takes onScrollToTop. Loading older messages keeps the message the reader was looking at in place, also when loading starts at the very top, instead of pinning the newly loaded page to the top.
- InfiniteScrollPaginator's loadNextDebounceMs now rate-limits the edge check while scrolling (the first check runs at once, then at most once per loadNextDebounceMs) instead of waiting until scrolling stops for that long. Older and newer pages start loading before the reader reaches the edge.
- MessageList and VirtualizedMessageList pass showNotification to NewMessageNotification only when a message from someone else arrives while the list is scrolled up. Being on an older message set no longer shows it; ScrollToLatestMessageButton signals that.
- In a channel, ScrollToLatestMessageButton shows the current user's unread count from the channel's read state instead of counting message.new events, so messages a reconnect brought in are included. In a thread it counts new replies from 0.
* marker: the removals are v14 API, so the branch has a
`fix!:` commit with a `BREAKING CHANGE:` footer, per the AGENTS.md
convention. The footer to keep in the squash commit:
* `MessageList` no longer accepts `messages`, `hasMore`,
`jumpToLatestMessage`, `loadingMoreNewer` or `messageLimit`, and
`VirtualizedMessageList` no longer accepts `messages`; the lists render
and paginate the message paginator. `CustomClasses.chatContainer` and
the `ComponentContext.LoadingErrorIndicator` slot are removed. Inside
`ChatView` the channel list no longer renders its own `str-chat <theme>`
scope. See ai-docs/v15-breaking-changes.md (BC-019, BC-046, BC-047,
BC-073, BC-074).

Verification: `yarn lint`, `tsc -p tsconfig.lib.json --noEmit`, `yarn
types:scripts`, `yarn validate-translations` and `yarn test` (281 files,
3090 tests) pass. `yarn build`, `validate-cjs`, `validate-esm`,
`validate-entry-isolation`, and the tutorial and vite example builds
passed before the rebase onto the guides branch, which brought in only
docs and the api-surface script. The ai-chatbot example build was not
verified: it hung locally in a sandboxed environment. The theme-scope
change was not checked visually in a browser.

### UI Changes

No intended visual change inside `ChatView`. Outside `ChatView`, the
channel list picks up the design tokens again, as in v14. The
`MessageList` loading indicator now appears while older messages load.
No screenshots: the examples need Stream credentials to run.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Gallery items can display message-specific timestamp overrides.
* Reply-count buttons honor a message’s custom thread-opening behavior.
* Standalone channel lists now inherit the chat theme, and
channel-detail actions use workspace navigation.
* `useMessagePaginator` and `useIsCooldownActive` are available from the
package entry point.
* Message timestamps can render with an explicit message outside a
message context.

* **Bug Fixes**
* Message-list loading indicators and pagination behavior now reflect
active page loads more accurately.
* Workspace navigation warns when navigation actions are used without a
provider.

* **Breaking Changes**
* Removed legacy message-list props and the `LoadingErrorIndicator`
component override slot.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

### Bug Fixes

* correct issues found during the comment cleanup ([#3334](#3334)) ([7f87026](7f87026))
* **examples:** translate the voice visualization keys in the vite example ([#3352](#3352)) ([c88ab33](c88ab33)), closes [#3347](#3347)
* **MediaRecorder:** stop the recording timer when the preview unmounts ([#3351](#3351)) ([3c8b30a](3c8b30a))
* **MessageList:** keep the reader's place on older pages and count only arrived messages as new ([#3342](#3342)) ([ab00d67](ab00d67))
* remove dead v15 surface and restore v14 behaviors found by the API audit ([#3328](#3328)) ([d721f40](d721f40)), closes [#3327](#3327) [#3305](#3305) [#3237](#3237)

### Features

* **ai-components:** add useHeardText for voice-paced text ([#3348](#3348)) ([ec7c956](ec7c956)), closes [#3343](#3343) [#3344](#3344) [#3344](#3344) [#3343](#3343) [#3339](#3339) [#3347](#3347)
* **ai-components:** add VoiceWave and VoiceGlow voice-agent visualizations ([#3347](#3347)) ([216d00d](216d00d)), closes [#3339](#3339) [#3339](#3339) [#3339](#3339)

### Refactors

* call Channel.watch(), which replaces ensureWatched() in stream-chat ([#3346](#3346)) ([0100d98](0100d98))
github-actions Bot pushed a commit that referenced this pull request Nov 6, 2026
## [15.0.0](https://github.com/GetStream/stream-chat-react/compare/v14.12.0...v15.0.0) (2026-11-06)

### ⚠ BREAKING CHANGES

* props and ComponentContext keys that had no effect are removed, nine slots are typed without props, and overrides of several slots render in more places.

- `additionalMessageComposerProps` is removed from `Message`, `MessageList`, `VirtualizedMessageList` and `VirtuosoContext`. It did nothing in v14; delete it. If the props were meant for the composer, pass them to the `MessageComposer` you render.
- `MessageReactions.reverse`, `MessageReactionsDetail.sort` and `MessageReactionsDetail.dialogId` are removed, and `MessageUI` no longer passes `reverse` to a `MessageReactions` override. Order reaction types with `sortReactions` and reacting users with `reactionDetailsSort`; the detail's dialog id is `MessageReactionsDetail.getDialogId({ messageId })`.
- `MessageComposer` no longer takes `emojiSearchIndex` or `parent`, the `emojiSearchIndex` override key is removed, and `useMessageComposerContext()` no longer returns `emojiSearchIndex`, `parent` or `audioRecordingConfig`. For emoji autocomplete, register `createTextComposerEmojiMiddleware(SearchIndex)` from `stream-chat-react/emojis` in a `client.config.setSetupFunction('messageComposer', ...)`.
- `WithDragAndDropUpload.acceptedFiles` is removed. Set the accepted types on the composer config, `attachments.acceptedFiles`.
- `ChannelListItem.activeChannel` is removed. A custom `ChannelListItemUI` reads `active`, or compares the app's own selected channel with its `channel`.
- `ChatView.entityInferrers`, the `ChatViewEntityInferer` type and `useChatViewContext().entityInferers` are removed.
- The `AttachmentPreviewList`, `MessageComposerUI`, `MessageEditedIndicator`, `MessageStatus`, `NotificationAnnouncer`, `QuotedMessagePreview`, `SearchSourceResultList`, `TextareaComposer` and `VoiceRecordingPreviewSlot` slots are typed `React.ComponentType` without props, because the SDK renders them without props. Rendering one from `useComponentContext()` with props, or an override with required props, no longer compiles; render the exported component with its props inside the override.
- Overrides of `FileDragAndDropContent`, `BaseImage`, `LoadingIndicator`, `Timestamp`, `Avatar`, `DateSeparator`, `Gallery` and `FileSizeIndicator` now also render where the SDK rendered the default directly: link previews, video thumbnails, galleries, quoted messages, load-more buttons, poll vote lists, thread list items, user search results, the thread's parent message, composer previews and channel detail lists. To keep the default in one place, wrap it in `WithComponents` with the exported default.

See ai-docs/v15-breaking-changes.md (BC-105 to BC-109, BC-033) and ai-docs/ai-migration-v14-v15.md.
* **ChannelListHeader:** ComponentContext.HeaderEndContent is removed. Pass the content
as EndContent to ChannelListHeader / ThreadListHeader instead, by registering a
component that renders the header with it under the ChannelListHeader or
ThreadListHeader key. One component no longer fills both headers.
* **ChannelListHeader:** list-header content renders whenever it is set. HeaderEndContent
showed only while a channel (channel list) or a thread (thread list) was open;
content that should keep that behavior returns null while
useWorkspaceNavigation().openChannels / openThreads is empty. See BC-099 in
ai-docs/v15-breaking-changes.md and "List headers: HeaderEndContent becomes an
EndContent prop" in ai-docs/ai-migration-v14-v15.md.
* **ChannelDetail:** ChannelMembersHeaderActionItem.component is renamed to
Component, matching the message and channel-list action sets.
* **ChannelDetail:** the 'menu' placement of a channel members header action is
renamed to 'dropdown'. A 'menu' item is no longer rendered.
* **ChannelDetail:** the HeaderActionsMenuTrigger prop (on ChannelMembersView and
ChannelMembersHeaderActionsProps), DefaultHeaderActionsMenuTrigger and
ChannelMembersHeaderActionsMenuTriggerProps are removed. The menu trigger is a
{ Component, placement: 'quick-dropdown-toggle' } item in headerActionSet: a
forwardRef button that receives the ref the menu anchors to, aria-expanded and
onClick, and spreads them. defaultChannelMembersHeaderActionSet starts with
DefaultChannelMembersHeaderActions.QuickDropdownToggle; a set without a toggle
item renders no dropdown menu.
* **ChannelDetail:** dropdown header actions no longer receive a closeMenu prop.
They read closeMenu from useContextMenuContext().
* **ChannelDetail:** a header action's filter is renamed to isVisible, typed with
ChannelMembersHeaderActionVisibilityFilterParams and called with { channel }, as
on message actions. A leftover filter is ignored, so the action it hid shows to
every user.
* **ChannelDetail:** ChannelMembersHeaderActionItem is a union whose
quick-dropdown-toggle member has no type or isVisible, and
ChannelMembersHeaderActionPlacement includes 'quick-dropdown-toggle'. Narrow an
item (e.g. 'type' in item) before reading type.
* **ChannelDetail:** a custom HeaderActions renders the set's quick-dropdown-toggle
item itself and filters the set with useBaseChannelMembersHeaderActionSetFilter.
It renders the dropdown items in a ContextMenu opened with
useDialogOnNearestManager, using an id unique to the component instance. See
BC-098 in ai-docs/v15-breaking-changes.md and "The channel members header action
set uses the shared action names" in ai-docs/ai-migration-v14-v15.md.
* **TypingIndicator:** translations of `typing.twoUsers` must use
`{{ firstUser }}` and `{{ secondUser }}` instead of `{{ typing }}`, for example
'{{ firstUser }} und {{ secondUser }} schreiben'. A translation that keeps
`{{ typing }}` still compiles but shows the literal text `{{ typing }}`.
See BC-100 in ai-docs/v15-breaking-changes.md and "Keys whose values changed"
in ai-docs/i18n-v15-migration.md.
* unused exports and the transliterate dependency are removed, and stream-chat-react now types channel custom data for apps.

- `Root` and `Header` are no longer exported from the package root. They are the parts of `Alert`; use `Alert.Root` and `Alert.Header`.
- `UploadIcon`, `BinIcon`, `PauseIcon` and `PlayIcon` are removed. Copy the SVG into the app, or use `IconPlus` / `IconAttachment`, `IconDelete`, `IconPauseFill` and `IconPlayFill` from the v15 icon set.
- `@stream-io/transliterate` is no longer an optional dependency. Apps that import it must add it to their own dependencies. For mention search, pass a `transliterate` function to stream-chat's mentions middleware.
- Importing `stream-chat-react` now types `channel.data.custom.name` and `.image` (`string | undefined`). Delete the app's own `name` / `image` declarations on `CustomChannelData`; a declaration with another type overrides the SDK's under `skipLibCheck` and fails with TS2430 without it.
- `DefaultChannelData` no longer has `subtitle` or `team`. Declare them on `CustomChannelData` if the app stores them under `custom`; read the channel's team from `channel.data.team`.
- The translation key `messageComposer.icons.attachFiles.text` is removed.

See ai-docs/v15-breaking-changes.md (BC-101) and ai-docs/ai-migration-v14-v15.md.
* **Message:** Removed the initialMessage property from message props and context. Use the new hook to identify thread-parent messages.
* **ChannelDetail:** outside a modal, the ChannelDetail views render no close
button unless ChannelDetail or ChannelDetailProvider gets onClose. They used to
render a close button that did nothing.
* **ChannelDetail:** ChannelDetail calls onLayoutChange on every layout change. It
used to ignore the prop.
* **AttachmentSelector:** SimpleAttachmentSelector, and the plain upload button AttachmentSelector renders when File is its only action, follow the composer's File rule instead of the upload-file capability alone. They appear without upload-file when attachments.customCdn is set, are hidden when attachments are disabled (the channel type's uploads flag is off without customCdn, or the client sets attachments.enabled: false), and are disabled once the message holds maxNumberOfFilesPerMessage files. At that limit the menu's File item also stays, disabled, where v14 hid it. See BC-065 in ai-docs/v15-breaking-changes.md and "Attachment and poll availability" in ai-docs/ai-migration-v14-v15.md.
* deprecated message, mention and list APIs are removed.

- `renderText(text, mentionedUsers, options)` is now `renderText(text, options)`, and `RenderTextFunction` is `(text, options)`. Pass mentions as `options.messageMentionEntities`, built with `getRenderTextMentionEntities(message)`.
- Custom mention renderers get `node.mentionedEntity` instead of `node.mentionedUser`.
- `onMentionsClick` / `onMentionsHover` are called with `(event, message)`; the `mentioned_users` argument and the `MentionedUserEventHandler` type are removed (use `CustomMentionHandler`). Read the clicked mention from the target's `data-user-id` / `data-mention-id`.
- `MessageContextValue.onMentionsClickMessage` / `onMentionsHoverMessage` and the handlers from `useMentionsHandler` are `undefined` unless `onMentionsClick` / `onMentionsHover` is passed. Mentions are interactive only when a click handler is set.
- `mentionsMarkdownPlugin` and `createMentionPluginAndDisplayTextSet` take mention entities only, not `UserResponse[]`.
- `useUserRole` is renamed `useMessagePermissions(message)`, and it no longer returns `isAdmin`, `isModerator` or `isOwner`; gate on the `can*` flags or `useChannelCapabilities()`.
- `disableQuotedMessages` is removed from `MessageList`, `Message` and `useMessagePermissions`. To hide quoting, pass a `messageActionSet` without the `quote` item through the `MessageActions` slot.
- `VirtualizedMessageList` drops `defaultItemHeight`, `overscan` and `scrollSeekPlaceHolder`; pass them through `additionalVirtuosoProps`.
- `PinEnabledUserRoles` and `PinPermissions` are removed; use `useMessagePermissions(message).canPin`.

See ai-docs/v15-breaking-changes.md (BC-087 to BC-095) and ai-docs/ai-migration-v14-v15.md.
* message context and grouping API changes.
- MessageProps.threadList and MessageContextValue.threadList are removed. Detect a thread
  with `!!useThreadContext()`.
- ReactionSelector.getDialogId takes only `{ messageId }`; the reaction selector dialog id
  no longer has a `-thread` part. Each message list has its own dialog manager.
- MessageContextValue.endOfGroup, firstOfGroup and groupedByUser are removed. Read
  `useMessageContext().groupStyles[0]` (`top`, `middle`, `bottom` or `single`).
- The str-chat__virtual-message__wrapper--end, --first and --group classes are no longer
  applied. Target the list item's .str-chat__li--top / --middle / --bottom / --single.
- MessageList.noGroupByUser and VirtualizedMessageList.shouldGroupByUser are replaced by
  groupByUser (defaults: true and false). VirtuosoContext.shouldGroupByUser is groupByUser.
- The groupStyles function prop of both lists is renamed getGroupStyles and is called with
  one GetGroupStylesParams object: { groupByUser, maxTimeBetweenGroupedMessages, message,
  nextMessage, previousMessage }. The exported getGroupStyles takes the same object, and
  useEnrichedMessages takes getGroupStyles and groupByUser instead of groupStyles and
  noGroupByUser.
See BC-048, BC-085 and BC-086 in ai-docs/v15-breaking-changes.md.
* **MessageComposer:** useUserRole(message).canEdit is now the update permission alone
(update-any-message, or update-own-message on the user's own message). It no
longer excludes poll messages and giphies. A custom UI that gated an edit button
on it and wants that rule adds `!message.poll_id && message.command !== 'giphy'`.
* **MessageComposer:** the edit, copyMessageText and download rules about the message
moved from useBaseMessageActionSetFilter onto the items of
defaultMessageActionSet as isVisible. A hand-written edit, copyMessageText or
download item without isVisible now shows wherever the base filter allows it,
e.g. edit on a poll message the user may update. Copy the default item's
isVisible to keep the rule. Item isVisible rules also apply when
disableBaseMessageActionSetFilter is set, which previously returned the set
unfiltered, and to failed messages: a poll message or giphy that failed to send
for a network reason no longer offers Edit.
* **MessageComposer:** a message with a poll renders its text and attachments too, and
the quoted message now renders above the poll instead of below it. Such a
message gets str-chat__message--has-poll and no longer gets
str-chat__message--has-single-attachment.
* **MessageComposer:** custom AttachmentPreviewList, VoiceRecordingPreviewSlot and
LinkPreviewList components mount only while their item in
defaultMessageComposerPreviewSet is visible: attachments while the composer holds
an attachment other than a voice recording, voiceRecording while it holds a voice
recording, linkPreviews while a link preview is loading or loaded. Previously they
mounted whenever the preview area showed. A custom component that also renders
something else (a location, a poll, an empty or upload state) replaces its item
with one whose isVisible covers it.
* channel.watch() resolves with the channel instance to use (the channel, or the instance that superseded it), not the server response: read channel.data, channel.state and channel.messagePaginator instead.
- channel.watch() sends no query for a channel already watched and loaded unless it asks for options the current watch was not sent with, so it no longer refreshes one: refresh with channel.reload(), load other messages through channel.messagePaginator.
- A channel.watch() while another with the same options is in flight joins it instead of sending a request.
* **MessageList:** useMessageListScrollManager no longer takes onScrollToTop. Loading older messages keeps the message the reader was looking at in place, also when loading starts at the very top, instead of pinning the newly loaded page to the top.
- InfiniteScrollPaginator's loadNextDebounceMs now rate-limits the edge check while scrolling (the first check runs at once, then at most once per loadNextDebounceMs) instead of waiting until scrolling stops for that long. Older and newer pages start loading before the reader reaches the edge.
- MessageList and VirtualizedMessageList pass showNotification to NewMessageNotification only when a message from someone else arrives while the list is scrolled up. Being on an older message set no longer shows it; ScrollToLatestMessageButton signals that.
- In a channel, ScrollToLatestMessageButton shows the current user's unread count from the channel's read state instead of counting message.new events, so messages a reconnect brought in are included. In a thread it counts new replies from 0.
* marker: the removals are v14 API, so the branch has a
`fix!:` commit with a `BREAKING CHANGE:` footer, per the AGENTS.md
convention. The footer to keep in the squash commit:
* `MessageList` no longer accepts `messages`, `hasMore`,
`jumpToLatestMessage`, `loadingMoreNewer` or `messageLimit`, and
`VirtualizedMessageList` no longer accepts `messages`; the lists render
and paginate the message paginator. `CustomClasses.chatContainer` and
the `ComponentContext.LoadingErrorIndicator` slot are removed. Inside
`ChatView` the channel list no longer renders its own `str-chat <theme>`
scope. See ai-docs/v15-breaking-changes.md (BC-019, BC-046, BC-047,
BC-073, BC-074).

Verification: `yarn lint`, `tsc -p tsconfig.lib.json --noEmit`, `yarn
types:scripts`, `yarn validate-translations` and `yarn test` (281 files,
3090 tests) pass. `yarn build`, `validate-cjs`, `validate-esm`,
`validate-entry-isolation`, and the tutorial and vite example builds
passed before the rebase onto the guides branch, which brought in only
docs and the api-surface script. The ai-chatbot example build was not
verified: it hung locally in a sandboxed environment. The theme-scope
change was not checked visually in a browser.

### UI Changes

No intended visual change inside `ChatView`. Outside `ChatView`, the
channel list picks up the design tokens again, as in v14. The
`MessageList` loading indicator now appears while older messages load.
No screenshots: the examples need Stream credentials to run.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Gallery items can display message-specific timestamp overrides.
* Reply-count buttons honor a message’s custom thread-opening behavior.
* Standalone channel lists now inherit the chat theme, and
channel-detail actions use workspace navigation.
* `useMessagePaginator` and `useIsCooldownActive` are available from the
package entry point.
* Message timestamps can render with an explicit message outside a
message context.

* **Bug Fixes**
* Message-list loading indicators and pagination behavior now reflect
active page loads more accurately.
* Workspace navigation warns when navigation actions are used without a
provider.

* **Breaking Changes**
* Removed legacy message-list props and the `LoadingErrorIndicator`
component override slot.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
* the `options` prop of `useCreateChatClient` is renamed to
`config`, and its type changes from `StreamChatOptions` to the `stream-chat`
configuration tree (`DeepPartial<InstanceConfigTree>`). Options that were
passed at the top level now go under the `client` key, for example
`options={{ baseURL, axiosRequestConfig }}` becomes
`config={{ client: { baseURL, axiosRequestConfig } }}`. Requires a
* requires stream-chat 10.0.0-rc.20 or later; client.activeChannels, client.getChannelById() and client.getChannelByMembers() are gone, use client.channelManager.get(cid), values() and client.channel() / client.channelManager.ensure({ type, id, data }); the thread list is client.threads.paginator, and threads come from client.threads.ensure() / get().
* getChannel() is removed; get the channel from client.channelManager.ensure() and call channel.ensureWatched(options).
* channel search results, and the channels message search fetches for its results, are no longer watched; a custom search result component watches the channel when it is opened (channel.ensureWatched(), or jumpToMessage(id, { watchChannel: true }) for a message).
* port the tutorial alignment (#3251) to v15, with panel-aware workspace navigation (#3301)
* **MessageComposer:** the `preventClearingOnUnmount` prop is removed from
`MessageComposer`. Drop it. If you relied on unmounting to clear a
composer supplied through `MessageComposerControllerProvider`, call
`clear()` on it yourself when your UI is done with it.
* `ChannelListItemProps.channelUpdateCount` is removed.
The unread badge now updates without it.
* `ChannelListItemProps.key` is removed. React's own
`key` prop is unaffected.
* `ChannelListItemProps.watchers` is removed. It had no
effect in v15.
* adopt stream-chat's branded TimestampNS (#3297)
* **Attachment:** `useSendMessageFn` and `useUpdateMessageFn` are removed. Call
`messageComposer.send()` and `messageComposer.update()` instead. They resolve
`'sent' | 'nothing-to-send' | 'failed'` rather than a boolean, so a truthiness
check on the result now passes for every outcome — compare against `'sent'`.
* **Attachment:** the two message submission failure notifications changed key.
`messageComposer.sendMessageFn.sendMessageRequestFailed.text` is now
`notification.messageSendFailed`, and
`messageComposer.updateMessageFn.editMessageRequestFailed.text` is now
`notification.messageUpdateFailed`. A typed custom translation dictionary fails
to compile until both are renamed.
* **Attachment:** `RetryHandler` takes `Omit<OperationParams<'retry'>, 'message'>`
instead of `RetrySendMessageWithLocalUpdateParams`, which stream-chat removed in
GetStream/stream-chat-js#1882. Code that names the old type must be updated.
* the `stream-chat` peer range moves to `^10.0.0-rc.12`. That release removes
`connection.changed`, changes `client.wsConnection` from the socket itself to a wrapper, and moves
the socket's settings into configuration. See GetStream/stream-chat-js PR 1859 for the full list;
an application on an earlier `stream-chat` will not typecheck against this version.
* connectivity is read from state stores rather than events. Code that listened for
`connection.changed` — to render its own banner, to refetch on reconnect — must subscribe to
`client.wsConnection.state` or `client.networkConnection.state` instead, or use the new
`useWSConnectionState` / `useNetworkConnectionState` hooks. Nothing in this package dispatches or
forwards the old event. Note the two stores name their fields differently: the socket's `isHealthy`
is always a boolean, while the network's `isOnline` is `boolean | undefined`, where `undefined`
means no platform reporter has reported yet and must be tested with `=== false`.
* `Channel` no longer reloads its channel on `connection.recovered`. The client
reloads every active channel itself and dispatches the event afterwards, so handling it here
reloaded each open channel twice per reconnect. Anything relying on the component to refresh a
channel after a reconnect should rely on the client instead.
* a socket drop on a working network now renders "Reconnecting…" rather than
"Waiting for network…", from the new `chat.reportLostConnection.reconnecting.text` key. Tests and
dictionaries keyed on the old copy for that case need updating; the `waitingNetwork` key is
unchanged and still used when the device network is down. The delay before either banner appears
now comes from `client.wsConnection.config.offlineNotificationDisplayDelayMs` (5s default) rather
than from a fixed hold inside the client, so changing that config changes when the banner shows.
The `system:network:connection:lost` notification type is unchanged.
* `Thread` requires a `thread` prop and renders `children`.
`additionalMessageComposerProps`, `additionalMessageListProps`,
`additionalParentMessageProps`, `additionalVirtualizedMessageListProps`, `autoFocus` and
`virtualized` are removed — pass those props to the children you render. `Thread`
provides the thread itself, so it no longer needs to be wrapped in `ThreadProvider`. The
`str-chat__thread--virtualized` class is gone; `Thread` cannot know which list you chose.
* `Thread.enableDateSeparator` is removed with nothing in its place. A
`MessageList` in a thread now follows its own default and shows date separators unless
you pass `withDateSeparator={false}`.
* `disableDateSeparator` is renamed to `withDateSeparator` on
`MessageList` (default `true`, was `disableDateSeparator={false}`) and
`VirtualizedMessageList` (default `false`, was `disableDateSeparator={true}`). The rename
also reaches `processMessages`, `useEnrichedMessages`, `FloatingDateSeparator`,
`useFloatingDateSeparator` and `useFloatingDateSeparatorMessageList`.
* the `head` prop is removed from `MessageList` and
`VirtualizedMessageList`. Both render the thread's parent message from context; override
it with a `ThreadHead` component on `ComponentContext`.
* `ThreadHeaderProps` is down to `overrideTitle`. `thread` comes from the
thread in context, and `closeThread` goes through workspace navigation — customize it
centrally via `ChatView`'s `deriveWorkspaceNavigation`, or call the new `useCloseThread()`
hook from a header of your own. `ComponentContext.ThreadHeader` is removed; compose the
header you want.
* `ThreadSlot` wraps its children in `<Thread>` instead of letting them
replace the whole panel, mirroring `ChannelSlot`. Markup that must sit outside the thread
container moves outside `ThreadSlot`; anything needing thread context must sit inside.
* `Thread` no longer rebuilds its subtree when the thread changes. A
custom component rendered inside `Thread` that relied on being remounted per thread — to
reset local state, or to re-run a mount effect — must depend on the thread instead. The
SDK's own message list does this by keying on the thread; `WithAudioPlayback` by taking
`playbackScope`.
* `LegacyThreadContext` and its `legacyThread` value are removed. The
thread composer resolves its composition context from the `Thread` instance in
`ThreadContext`.
* **MessageActions:** the `messageActions` prop is removed from `Channel`,
`MessageList`, `VirtualizedMessageList`, `Thread` and `Message`. Filter
`defaultMessageActionSet` and pass the result as `messageActionSet`
instead.
* **MessageActions:** `MESSAGE_ACTIONS`, `OPTIONAL_MESSAGE_ACTIONS`,
`getMessageActions()`, and the `MessageActionsArray` and `Capabilities`
types are no longer exported. Use the new `DefaultMessageActionType`
union for the action types the SDK ships.
* **MessageActions:** `MessageContext` no longer carries `getMessageActions`
or `actionsEnabled`. The rendered action set is decided by
`messageActionSet` and each item's own `isVisible` predicate.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* **AudioPlayback:** `ChannelProps.allowConcurrentAudioPlayback`,
`ThreadProps.allowConcurrentAudioPlayback` and
`WithAudioPlaybackProps.allowConcurrentPlayback`
are removed, with no replacement. If you passed `true`, delete it:
starting a player now pauses
whichever was playing and takes the shared element over. If you passed
`false` or nothing, the
only change is that playback is exclusive across surfaces rather than
within one.
* **AudioPlayback:** `useActiveAudioPlayer()` now reports the app-wide
active player rather than the
calling surface's.
* **Channel:** `ChannelProps.channel` is now required and
`EmptyPlaceholder` is removed.
Render the exported `ChannelPlaceholder` to fill the same
`.str-chat__channel` layout slot
while no channel is selected.
* **Channel:** `Channel` no longer queries the channel;
`initializeOnMount` and
`channelQueryOptions` are removed. Whoever supplies the channel
initializes it — use the
exported `getChannel({ channel, client })`, which watches and
de-duplicates concurrent calls.
Channels from `ChannelList` or any `queryChannels` call arrive watched
already. `Channel` no
longer renders `LoadingIndicator` or `LoadingErrorIndicator` for a query
it does not make, and
an uninitialized channel renders as an empty channel with no error.
* **Channel:** `Channel` no longer writes `document.title`, and
`activeUnreadHandler` is
removed. See `examples/vite/src/DocumentTitleManager` for a working
replacement in application
code.
* **Channel:** the `channel.channelMissing.text` translation key is
removed. This is a
compile error (TS2353) for any dictionary typed with the exact
`TranslationDictionary` —
delete the entry from custom locale files.
* **Channel:** `ChatContext.latestMessageDatesByChannels` is removed.
Slow-mode cooldown now
lives on `channel.cooldownTimer` (`useCooldownRemaining` /
`useIsCooldownActive`), and the
channel's latest message on
`channel.messagePaginator.aggregateState.lastMessage`.
* **Channel:** `Channel` no longer jumps to a message focused from
search. Selecting a search
result calls `channel.messagePaginator.jumpToMessage(id)` directly, and
the highlight is read
from `channel.messagePaginator.messageFocusSignal`. A custom message
list that relied on
`Channel` performing the jump must call `jumpToMessage` itself.
* **i18n:** consume the shared runtime from @stream-io/i18n (#3284)
* move to timestamps in response models (#3278)
* request-handler props are removed from `Channel` and
`Thread`.
`doSendMessageRequest`, `doUpdateMessageRequest`,
`doDeleteMessageRequest` and
`doMarkReadRequest` are gone, along with `useChannelRequestHandlers`,
`useThreadRequestHandlers` and `useEditMessageHandler`. Register once on
the client:

```
  // v14
  <Channel channel={channel} doSendMessageRequest={mySend}>

  // v15
  client.config.set({
    channel: {
      requestHandlers: {
        sendMessageRequest: async ({ localMessage, message, options }) => ({
          message: await mySend(message, options),
        }),
      },
    },
  });
```

Three differences: handlers take a single params object and return `{
message }`; thread
flows register under the `thread` key; and registration is per CLIENT,
not per mounted
subtree — the one thing the props could do that this cannot. Per-channel
behaviour now
needs a branch inside one handler on the `cid` it receives.
* `useChannelConfig` returns the channel's RESOLVED
configuration instead
of the channel type's raw server config, so field names change:

channelConfig?.typing_events → channelConfig?.typingEvents.enabled
channelConfig?.read_events → channelConfig?.readEvents.enabled
channelConfig?.replies → channelConfig?.replies.enabled
channelConfig?.user_message_reminders →
channelConfig?.userMessageReminders.enabled
channelConfig?.commands → channelConfig?.availableCommands

Every gate is now the server flag ANDed with what is registered through
`client.config`,
which is what the client actually enforces. The hook also subscribes:
these were getters,
so a `client.config.set()` previously never reached the screen. No
component reads
`channel.serverConfig` any more.
* `useAttachmentManagerState` replaces
`hasCustomDoUploadRequest` with
`customCdn`, and gains `attachmentsEnabled`, `locationEnabled` and
`pollsEnabled`.
* the per-domain stores on `channel.state` are removed —
`readStore`,
`typingStore`, `membersStore`, `watcherStore`, `ownCapabilitiesStore`,
`mutedUsersStore`.
Subscribe to `channel.state` itself; the selector is unchanged, because
`ChannelStateData`
is flat and keeps the same top-level keys:

useStateStore(channel.state.ownCapabilitiesStore, sel) →
useStateStore(channel.state, sel)

`WatcherState` is renamed `ChannelWatchState`, and
`channel.disconnected` is renamed
`channel.pendingDisposal` (removed outright — no deprecated alias).
* `AIStates` is no longer exported from
`stream-chat-react` — import it
from `stream-chat`. The values are unchanged, but it is now
literal-typed, so an inferred
array of its members no longer accepts the wide `AIState`:

const STOPPABLE: readonly AIState[] = [AIStates.Thinking,
AIStates.Generating];
* `<Channel>` marks its channel active while mounted and
reloads it on
`connection.recovered`. The client skips re-seeding an active channel's
message list on
hydration and reconnect, so the consumer owns that window. A custom
channel surface that
does not render `<Channel>` must call `channel.activate()` /
`deactivate()` and
`channel.reload()` itself, or its list goes stale after a reconnect.
* **i18n:** adopt the shared i18n layer from stream-chat/i18n (#3271)
* **context:** - **Context hooks no longer accept a `componentName` argument.**
`useChatContext('X')` and friends stop type-checking; drop the argument.
- **Required contexts throw when used outside their provider**, instead
of logging a warning and returning `{}`. Affects the 14 hooks listed
above. Components must be rendered within the provider they read from —
e.g. anything calling `useChatContext` needs a `<Chat>` ancestor.
- **`useChannelInstanceContext` returns
`Partial<ChannelInstanceContextValue>`** — `channel` is now typed as
possibly `undefined`.
- **`ChatViewContext` has no default value** (typed `| undefined`), so
`useContext(ChatViewContext)` may return `undefined`.
- **`MessageComposerContext` is typed as `MessageComposerContextValue |
undefined`**, correcting a narrower declaration that was papered over
with casts.
- **The gallery header no longer uses the
`ComponentContext.MessageTimestamp` override**; it renders the item's
own timestamp.

### 🛠 Implementation details

Parameter removed from all 7 hooks and their 138 call sites.

Missing-provider behaviour also normalized, since `src/` had three
competing conventions (warn + `{} as T`, throw, silent cast). The `{} as
T` fallback deferred failures to a downstream `Cannot read properties of
undefined` several frames away. Everything now goes through
`requireContext` (`src/context/requireContext.ts`):

- **Required → throw**, naming hook and provider: `useChatContext`,
`useMessageContext`, `useMessageComposerContext`,
`useMessageListContext`, `useVirtualizedMessageListContext`,
`useMessageBounceContext`, `usePollContext`, `useDialogManager`,
`useSearchContext`, `useSearchSourceResultsContext`,
`useContextMenuContext`, `useChannelListItemContext`,
`useGalleryContext`, `useChatViewContext`
- **Optional by design → keep default, honest type**:
`useTranslationContext`, `useComponentContext`,
`useChannelInstanceContext` (now `Partial`), `useModalContext`,
`useAriaLiveAnnouncer`, `useMessageTranslationViewContext`
- **Renders both inside and outside a provider → read the raw context**:
`Audio`, `VoiceRecording`, `CardAudio`, `Timestamp`,
`MessageRepliesCountButton`, `MessageComposerUI`, `ModalGallery`

Two changes were needed before their hooks could throw:

- `WithDragAndDropUpload` detected the composer via
`Object.keys(ctx).length > 0`; now uses a
`useIsWithinMessageComposerContext()` predicate. Adds the test file this
component lacked.
- `GalleryHeader` read message context while rendering outside any
`MessageProvider`. `GalleryItem` now carries `user` and `createdAt` —
wrapping the call sites would be wrong, since `ChannelMediaView`
flattens many messages into one list. Adds a
`timestamp.GalleryTimestamp` key.

`ChatViewContext` also loses its module-level `LayoutController`
default, which let unrelated subtrees write to one shared instance.

`src/context/__tests__/missingProviderContract.test.tsx` pins the
required/optional split.

### 🎨 UI Changes

The channel-media gallery header now shows a per-item sender and
timestamp, which it previously couldn't display at all.

No screenshots: the demo users on the shared environment have no
channels, and seeding one would write test data others would see.
Covered by unit tests in `GalleryUI.test.tsx` — worth a manual look.
* the <Chat> prop and the ChatContext field channelPaginatorsOrchestrator are renamed to channelManager, and the types ChannelPaginatorsOrchestrator / ChannelPaginatorsOrchestratorState are now ChannelManager / ChannelManagerState. Every useChatContext() consumer reading the old field, and any test that builds a partial ChatContext value, has to be updated. No deprecated prop or type aliases are exported.
* requires stream-chat v10.
* Removed `ChannelStateContext` and `ChannelActionContext` along with
  `useChannelStateContext()`, `useChannelActionContext()`,
  `useCreateChannelStateContext()` and `useCreateChannelActionContext()`.
  Read the channel via `useChannel()` and message state via
  `useMessagePaginator()`; both are backed by LLC `StateStore`s.
* `ChatContext` no longer exposes the active channel or `setActiveChannel()`.
  Channel/thread routing is slot-driven — use `useChatViewNavigation()` from
  `stream-chat-react/slot-layout` (`openChannel`, `openThread`, `closeThread`).
* The `TypingContext` provider path was removed from the `Channel` runtime.
  `TypingIndicator` now derives its state from LLC stores and takes
  `isMessageListScrolledToBottom` and `scrollToBottom` props.
* Context mutation/pagination helpers were replaced by paginator methods:
  `updateMessage`/`removeMessage` -> `ingestItem`/`removeItem`;
  `loadMore`/`loadMoreNewer` -> `toTail()`/`toHead()`;
  `jumpToMessage`/`jumpToFirstUnreadMessage` -> `messagePaginator.jumpToMessage()`/
  `jumpToTheFirstUnreadMessage()`. Messages are no longer in `channel.state`.
* Custom send/update/delete/markRead overrides move from ChannelActionContext
  callbacks to `channel.configState.requestHandlers` /
  `thread.configState.requestHandlers`.
* `ChatView` is a navigation landmark, not a WAI-ARIA Tabs widget: the selector
  is `role="navigation"` with `aria-current` on the active button. There is no
  `role="tab"`/`"tablist"`/`"tabpanel"`. `activeChatView` renamed to `activeView`.
* `ChannelList` renders a `role="listbox"` whose items are `role="option"`.
* v10 data shapes: channel name/image read from `channel.data.custom.name`/
  `.custom.image`; user custom fields from `user.custom` (e.g. `username`);
  attachment `duration`/`file_size`/`mime_type`/`waveform_data` from
  `attachment.custom`. Message moderation uses `message.moderation`
  (`moderation_details` is gone).

### Bug Fixes

* adapt to removed stream-chat-js hand-written types ([#3274](https://github.com/GetStream/stream-chat-react/issues/3274)) ([ccccce5](https://github.com/GetStream/stream-chat-react/commit/ccccce5e4bbb55340118315b2244df0f37e260d3))
* **ai-components:** fromStreamMessage takes a LocalMessage, loadOlderMessages a toTail ([#3390](https://github.com/GetStream/stream-chat-react/issues/3390)) ([20a488f](https://github.com/GetStream/stream-chat-react/commit/20a488f94128cc9c2fff6999f3afb3aa68af53aa)), closes [#3389](https://github.com/GetStream/stream-chat-react/issues/3389)
* **ai-components:** theme generated UI from AI tokens alone, add showsUI and approval arguments ([#3412](https://github.com/GetStream/stream-chat-react/issues/3412)) ([49f859c](https://github.com/GetStream/stream-chat-react/commit/49f859c800eee8f39018825804c82cc8e2281383)), closes [#3399](https://github.com/GetStream/stream-chat-react/issues/3399) [#3399](https://github.com/GetStream/stream-chat-react/issues/3399) [#3399](https://github.com/GetStream/stream-chat-react/issues/3399) [#3394](https://github.com/GetStream/stream-chat-react/issues/3394) [#3395](https://github.com/GetStream/stream-chat-react/issues/3395) [#3393](https://github.com/GetStream/stream-chat-react/issues/3393) [#3399](https://github.com/GetStream/stream-chat-react/issues/3399) [#3399](https://github.com/GetStream/stream-chat-react/issues/3399)
* **Attachment:** render giphy attachments in their own group with uni… ([#3322](https://github.com/GetStream/stream-chat-react/issues/3322)) ([08b8c0e](https://github.com/GetStream/stream-chat-react/commit/08b8c0ea75a20d19b0d66042bb521e3b6f463567)), closes [#2934](https://github.com/GetStream/stream-chat-react/issues/2934)
* **Attachment:** render giphy attachments in their own group with unique keys ([8967e37](https://github.com/GetStream/stream-chat-react/commit/8967e37bc8ef1224ffa4d31239de4e6bf02d9803))
* **AttachmentSelector:** offer file uploads with customCdn and add StandaloneButton ([#3397](https://github.com/GetStream/stream-chat-react/issues/3397)) ([3e5af96](https://github.com/GetStream/stream-chat-react/commit/3e5af961049050f23258e2071f0e67fc50fca895))
* bubble-aware colors for quotes, location, polls and the AI stop button ([#3411](https://github.com/GetStream/stream-chat-react/issues/3411)) ([b2a8ded](https://github.com/GetStream/stream-chat-react/commit/b2a8ded2c901c8e254704a77f4e3a798edafa32d))
* **ChannelDetail:** call onLayoutChange and close through onClose outside a modal ([#3396](https://github.com/GetStream/stream-chat-react/issues/3396)) ([03796b0](https://github.com/GetStream/stream-chat-react/commit/03796b03dad983d096268784301d26d208a9a037))
* **ChannelDetail:** give the channel members header action set the shared action-set shape ([#3405](https://github.com/GetStream/stream-chat-react/issues/3405)) ([e7af1aa](https://github.com/GetStream/stream-chat-react/commit/e7af1aa3302f24159bc8a54fd29950f33bf26e54))
* **ChannelListHeader:** list headers take StartContent / EndContent props ([#3406](https://github.com/GetStream/stream-chat-react/issues/3406)) ([d60e737](https://github.com/GetStream/stream-chat-react/commit/d60e7372ace041eaccc8471767e26a2eddd741f8))
* **ChannelList:** strip markdown from the last-message preview and add listboxProps ([#3410](https://github.com/GetStream/stream-chat-react/issues/3410)) ([e614648](https://github.com/GetStream/stream-chat-react/commit/e614648afaf160bf80bd23a9bdd869f91b657e39))
* correct issues found during the comment cleanup ([#3334](https://github.com/GetStream/stream-chat-react/issues/3334)) ([7f87026](https://github.com/GetStream/stream-chat-react/commit/7f870262d8946abb1b27122227d65f3697f5a236))
* **deps:** bump [@stream-io](https://github.com/stream-io) toolkit packages to the .mjs/.cjs builds ([#3368](https://github.com/GetStream/stream-chat-react/issues/3368)) ([c22f3f8](https://github.com/GetStream/stream-chat-react/commit/c22f3f8bb4b2314c28ecb19e7fd57473afb926a8)), closes [GetStream/js-toolkit#58](https://github.com/GetStream/js-toolkit/issues/58)
* **deps:** bump stream-chat to 10.0.0-rc.28 ([#3369](https://github.com/GetStream/stream-chat-react/issues/3369)) ([bca4ce2](https://github.com/GetStream/stream-chat-react/commit/bca4ce24484cf2245f487126de449c6c4bf712dc))
* drop unset MessageContext fields and unify message grouping props ([#3386](https://github.com/GetStream/stream-chat-react/issues/3386)) ([097b474](https://github.com/GetStream/stream-chat-react/commit/097b4742a2533896b4051984af935d5c23436cd4))
* **EmojiPicker:** drop @emoji-mart/react peer dependency on v15 ([#3300](https://github.com/GetStream/stream-chat-react/issues/3300)) ([e7ce32f](https://github.com/GetStream/stream-chat-react/commit/e7ce32fa7840c54e91e8648929353f838628ef03))
* **examples:** translate the voice visualization keys in the vite example ([#3352](https://github.com/GetStream/stream-chat-react/issues/3352)) ([c88ab33](https://github.com/GetStream/stream-chat-react/commit/c88ab339f3dbd89817edb5d2251b62126f5f6520)), closes [#3347](https://github.com/GetStream/stream-chat-react/issues/3347)
* **Gallery:** play videos without a thumbnail and load the selected Giphy version ([#3407](https://github.com/GetStream/stream-chat-react/issues/3407)) ([506cb9d](https://github.com/GetStream/stream-chat-react/commit/506cb9dfacc41d719445f11aaca569a6ea97d3a2))
* **InfiniteScrollPaginator:** check the edges on resize in the next frame ([#3357](https://github.com/GetStream/stream-chat-react/issues/3357)) ([dd40f58](https://github.com/GetStream/stream-chat-react/commit/dd40f582daaa9810dcb4faa00e4a2a41b61e520c)), closes [GetStream/website-react-examples#138](https://github.com/GetStream/website-react-examples/issues/138) [#3342](https://github.com/GetStream/stream-chat-react/issues/3342)
* **LinkPreviewList:** take the preview thumbnail from image_url or thumb_url ([#3392](https://github.com/GetStream/stream-chat-react/issues/3392)) ([8b6bbd9](https://github.com/GetStream/stream-chat-react/commit/8b6bbd96bfee84748028290d72b561488a3ad191))
* **MediaRecorder:** build the voice recording with a pending upload state ([#3400](https://github.com/GetStream/stream-chat-react/issues/3400)) ([6285e3d](https://github.com/GetStream/stream-chat-react/commit/6285e3dd03d153e957de355001c96dfa49d2e0fe))
* **MediaRecorder:** stop the recording timer when the preview unmounts ([#3351](https://github.com/GetStream/stream-chat-react/issues/3351)) ([3c8b30a](https://github.com/GetStream/stream-chat-react/commit/3c8b30aa8c37cdc939cf3846f8f616bce8eaa9c6))
* **MessageActions:** show Pin only with the pin-message capability ([#3382](https://github.com/GetStream/stream-chat-react/issues/3382)) ([f31ab7a](https://github.com/GetStream/stream-chat-react/commit/f31ab7a4211af432c9cd137c86cdead5cc0fdaee))
* **MessageList:** keep the reader's place on older pages and count only arrived messages as new ([#3342](https://github.com/GetStream/stream-chat-react/issues/3342)) ([ab00d67](https://github.com/GetStream/stream-chat-react/commit/ab00d67111cd945714d5689d7cef163d0bf55f9f))
* **MessageList:** keep the viewport still when a jumped-to window reaches the live head ([#3290](https://github.com/GetStream/stream-chat-react/issues/3290)) ([351d69d](https://github.com/GetStream/stream-chat-react/commit/351d69dc71a59b6254b4c03f32d63127d67e721b)), closes [#3027](https://github.com/GetStream/stream-chat-react/issues/3027)
* **MessageList:** restore the older-page anchor on iOS WebKit ([#3316](https://github.com/GetStream/stream-chat-react/issues/3316)) ([e3247e1](https://github.com/GetStream/stream-chat-react/commit/e3247e10ac97a49c509c41da0af23b5b21acff22))
* **MessageList:** show delivery and read state on every message that has it ([#3296](https://github.com/GetStream/stream-chat-react/issues/3296)) ([e74c57a](https://github.com/GetStream/stream-chat-react/commit/e74c57acf9215421cbcb860489a4685c2d9b0474))
* **MessageList:** stop the floating date separator from stacking on the inline one ([#3370](https://github.com/GetStream/stream-chat-react/issues/3370)) ([ec1413d](https://github.com/GetStream/stream-chat-react/commit/ec1413d20c7db9e70abde78a3f730a7e0ea9e448))
* **Message:** send default reactions through messageOperations ([#3379](https://github.com/GetStream/stream-chat-react/issues/3379)) ([53f497d](https://github.com/GetStream/stream-chat-react/commit/53f497dc115dce6c4d6d4eaea00797bc647385bd))
* **Message:** show error notification when pin, mute or delete fails ([#3360](https://github.com/GetStream/stream-chat-react/issues/3360)) ([d88dbf0](https://github.com/GetStream/stream-chat-react/commit/d88dbf02a7d021a75c5a5d179875b66571c5804d)), closes [#3359](https://github.com/GetStream/stream-chat-react/issues/3359)
* **Message:** throw when a message handler is missing a parameter ([#3362](https://github.com/GetStream/stream-chat-react/issues/3362)) ([290d2db](https://github.com/GetStream/stream-chat-react/commit/290d2dbaf931a5f19e12b022d542dc8b93c389c6)), closes [#3360](https://github.com/GetStream/stream-chat-react/issues/3360) [#3360](https://github.com/GetStream/stream-chat-react/issues/3360)
* **Poll:** port the poll vote debounce removal ([#3308](https://github.com/GetStream/stream-chat-react/issues/3308)) to v15 ([#3309](https://github.com/GetStream/stream-chat-react/issues/3309)) ([1af035e](https://github.com/GetStream/stream-chat-react/commit/1af035eaf14f1579a3179ed551baff576f6bc3f7)), closes [#1904](https://github.com/GetStream/stream-chat-react/issues/1904)
* prevent eager requests on Thread component mount ([#3282](https://github.com/GetStream/stream-chat-react/issues/3282)) ([6b7dd6c](https://github.com/GetStream/stream-chat-react/commit/6b7dd6cacde3cd3a5d450dc638ae4999070c863f))
* remove dead v15 surface and restore v14 behaviors found by the API audit ([#3328](https://github.com/GetStream/stream-chat-react/issues/3328)) ([d721f40](https://github.com/GetStream/stream-chat-react/commit/d721f406675c327ada97ce1089525f05d180d20b)), closes [GetStream/stream-chat-react#3327](https://github.com/GetStream/stream-chat-react/issues/3327) [#3305](https://github.com/GetStream/stream-chat-react/issues/3305) [#3237](https://github.com/GetStream/stream-chat-react/issues/3237)
* remove props and override keys that have no effect, wire up the rest ([#3408](https://github.com/GetStream/stream-chat-react/issues/3408)) ([91b2c68](https://github.com/GetStream/stream-chat-react/commit/91b2c688536a8309db0ba6136e8922589c825c35))
* render stable notification host for Channel and Thread ([#3291](https://github.com/GetStream/stream-chat-react/issues/3291)) ([ce59094](https://github.com/GetStream/stream-chat-react/commit/ce59094bcd2347357628107b8841851cc4af8ee0))
* **renderText:** stop markdown tables from rendering an empty row under the header ([#3385](https://github.com/GetStream/stream-chat-react/issues/3385)) ([6a4f93d](https://github.com/GetStream/stream-chat-react/commit/6a4f93d99b88e54190a6baf53fcfc60e9b981c2c))
* retry attachment uploads through AttachmentManager.uploadFile ([#3384](https://github.com/GetStream/stream-chat-react/issues/3384)) ([2359ae8](https://github.com/GetStream/stream-chat-react/commit/2359ae839ed5ef354e017870be38b46808519530))
* **ShareLocationDialog:** keep one position watch and give the first fix 10 s ([#3409](https://github.com/GetStream/stream-chat-react/issues/3409)) ([37a4be3](https://github.com/GetStream/stream-chat-react/commit/37a4be336efe5816ca3933fe344e5d4b82579fe9))
* ship the CustomChannelData typing and remove dead exports and the transliterate dependency ([#3403](https://github.com/GetStream/stream-chat-react/issues/3403)) ([85d5b4e](https://github.com/GetStream/stream-chat-react/commit/85d5b4e5dadc07385c177cea89a6309a08bd0b4b))
* show list query errors with a retry in ChannelList and ThreadList ([#3381](https://github.com/GetStream/stream-chat-react/issues/3381)) ([bb1b874](https://github.com/GetStream/stream-chat-react/commit/bb1b874c263b14962f8199f46a1ea2b56b920864))
* **store:** provide getServerSnapshot to useStateStore so server rendering works ([0ccf60d](https://github.com/GetStream/stream-chat-react/commit/0ccf60db7011866068a5ae2ab025f529a1ec2581))
* system message row class, thread list slide, composer error icons, addNotification id ([#3398](https://github.com/GetStream/stream-chat-react/issues/3398)) ([a5daf2a](https://github.com/GetStream/stream-chat-react/commit/a5daf2a6a887edf2481c6c7d3ff4fa4af570d530))
* **types:** remove DefaultCommandData and the CustomCommandData augmentation ([#3380](https://github.com/GetStream/stream-chat-react/issues/3380)) ([10e2b66](https://github.com/GetStream/stream-chat-react/commit/10e2b6651cf53b36b809bfc877158df158d798e4))
* **TypingIndicator:** pass the two typing names to typing.twoUsers as separate values ([#3404](https://github.com/GetStream/stream-chat-react/issues/3404)) ([7021ab9](https://github.com/GetStream/stream-chat-react/commit/7021ab95f337d45a6b2a91aec9535c9135268adb))
* v15 regressions found in side-by-side QA ([#3364](https://github.com/GetStream/stream-chat-react/issues/3364)) ([534c503](https://github.com/GetStream/stream-chat-react/commit/534c5039c44eedd51622fa5404eec649dad0e4ea))
* **VirtualizedMessageList:** keep the last message fully visible in short lists ([#3318](https://github.com/GetStream/stream-chat-react/issues/3318)) ([ef5c384](https://github.com/GetStream/stream-chat-react/commit/ef5c384dd2d3fa0641744fb4168e4459a79bc3f9))
* **VirtualizedMessageList:** pass mention and user handlers and unsafeHTML to messages ([#3402](https://github.com/GetStream/stream-chat-react/issues/3402)) ([059f939](https://github.com/GetStream/stream-chat-react/commit/059f9392d283151143ade44e2ec9009a27a4d100))

### Features

* add icons to ComponentContext adapted to stream-chat-react@15 ([#3294](https://github.com/GetStream/stream-chat-react/issues/3294)) ([baf4b62](https://github.com/GetStream/stream-chat-react/commit/baf4b62f6e43681af1a4712be0f8e0b02609a9d0))
* adopt stream-chat's branded TimestampNS ([#3297](https://github.com/GetStream/stream-chat-react/issues/3297)) ([aaa7fa3](https://github.com/GetStream/stream-chat-react/commit/aaa7fa31e54fed4f7ac1b6d7ee6cf436a4c3234c)), closes [GetStream/stream-chat-js#1884](https://github.com/GetStream/stream-chat-js/issues/1884) [GetStream/stream-chat-js#1884](https://github.com/GetStream/stream-chat-js/issues/1884) [#3295](https://github.com/GetStream/stream-chat-react/issues/3295)
* **ai-components:** add stream-chat-react/ai-components entry point ([50fe88e](https://github.com/GetStream/stream-chat-react/commit/50fe88e27a80a9db805fe747d6d0a9e1b776afe6))
* **ai-components:** add useHeardText for voice-paced text ([#3348](https://github.com/GetStream/stream-chat-react/issues/3348)) ([ec7c956](https://github.com/GetStream/stream-chat-react/commit/ec7c956b88ff35798cd3aad89a90935ce4be6b2c)), closes [GetStream/stream-chat-react#3343](https://github.com/GetStream/stream-chat-react/issues/3343) [GetStream/stream-chat-react#3344](https://github.com/GetStream/stream-chat-react/issues/3344) [#3344](https://github.com/GetStream/stream-chat-react/issues/3344) [#3343](https://github.com/GetStream/stream-chat-react/issues/3343) [#3339](https://github.com/GetStream/stream-chat-react/issues/3339) [GetStream/stream-chat-react#3347](https://github.com/GetStream/stream-chat-react/issues/3347)
* **ai-components:** add VoiceWave and VoiceGlow voice-agent visualizations ([#3347](https://github.com/GetStream/stream-chat-react/issues/3347)) ([216d00d](https://github.com/GetStream/stream-chat-react/commit/216d00dd7aadd45d1e3a4933483f46e35db6c94c)), closes [GetStream/stream-chat-react#3339](https://github.com/GetStream/stream-chat-react/issues/3339) [#3339](https://github.com/GetStream/stream-chat-react/issues/3339) [#3339](https://github.com/GetStream/stream-chat-react/issues/3339)
* **ai-components:** agent conversations, reply steps, approvals and sign-in ([#3389](https://github.com/GetStream/stream-chat-react/issues/3389)) ([6ac68dd](https://github.com/GetStream/stream-chat-react/commit/6ac68dd2826176a5e4c581a3b56eef44764fe767)), closes [#3376](https://github.com/GetStream/stream-chat-react/issues/3376) [#3376](https://github.com/GetStream/stream-chat-react/issues/3376)
* **ai-components:** generated UI, with A2UI and OpenUI renderers ([#3393](https://github.com/GetStream/stream-chat-react/issues/3393)) ([3e808cc](https://github.com/GetStream/stream-chat-react/commit/3e808cc8a9b16216ff728850d18f54cc6eda3f38)), closes [GetStream/stream-chat-react#3388](https://github.com/GetStream/stream-chat-react/issues/3388) [#3388](https://github.com/GetStream/stream-chat-react/issues/3388) [GetStream/stream-chat-react#3394](https://github.com/GetStream/stream-chat-react/issues/3394) [#3394](https://github.com/GetStream/stream-chat-react/issues/3394) [#3394](https://github.com/GetStream/stream-chat-react/issues/3394)
* **ai-components:** port the ai-components entry point ([#3314](https://github.com/GetStream/stream-chat-react/issues/3314)) to v15 ([#3315](https://github.com/GetStream/stream-chat-react/issues/3315)) ([9d1eacb](https://github.com/GetStream/stream-chat-react/commit/9d1eacbd288865898647ef92c24052608b1444a2))
* **Attachment:** render live upload progress on messages being sent ([#3295](https://github.com/GetStream/stream-chat-react/issues/3295)) ([4f1459e](https://github.com/GetStream/stream-chat-react/commit/4f1459e54ee37980c0c0418e69ae927eee60e16a))
* **AudioPlayback:** play one voice message at a time, across the whole app ([#3287](https://github.com/GetStream/stream-chat-react/issues/3287)) ([68999a7](https://github.com/GetStream/stream-chat-react/commit/68999a7b387c05b77d25bcecd3af77c87f2cd02c))
* **Channel:** depend on the Channel instance, not its cid, and narrow its responsibilities ([#3286](https://github.com/GetStream/stream-chat-react/issues/3286)) ([088c795](https://github.com/GetStream/stream-chat-react/commit/088c795c1628da6290f3a6ae5a57aaa058013095))
* **ChannelHeader:** add a Title slot and export the default subtitle ([#3367](https://github.com/GetStream/stream-chat-react/issues/3367)) ([766a71f](https://github.com/GetStream/stream-chat-react/commit/766a71f89d1ba76b53abf2a194e8674aa5e33913))
* **context:** consolidate message UI overrides on the MessageUI slot ([#3268](https://github.com/GetStream/stream-chat-react/issues/3268)) ([0766489](https://github.com/GetStream/stream-chat-react/commit/07664893efe5da053a7430aa6f985ceb91ff2901)), closes [#3267](https://github.com/GetStream/stream-chat-react/issues/3267)
* **context:** drop componentName param from context consumer hooks ([#3267](https://github.com/GetStream/stream-chat-react/issues/3267)) ([9194215](https://github.com/GetStream/stream-chat-react/commit/9194215f01029e79f3ed573991e99686449a84cb))
* **i18n:** english-only bundle with namespaced, type-checked translation keys ([#3261](https://github.com/GetStream/stream-chat-react/issues/3261)) ([17c91bc](https://github.com/GetStream/stream-chat-react/commit/17c91bc70c4af2621870475bf62f15e0341d1ac9))
* **MessageComposer:** let integrators supply the composer MessageComposer edits ([#3299](https://github.com/GetStream/stream-chat-react/issues/3299)) ([14e5860](https://github.com/GetStream/stream-chat-react/commit/14e58601fe7b4d0e9f424468e260e03247dc5f10))
* **MessageComposer:** make composer previews a configurable set ([#3365](https://github.com/GetStream/stream-chat-react/issues/3365)) ([1c02ba0](https://github.com/GetStream/stream-chat-react/commit/1c02ba07fd4bc7a94f23fc5848c70c8405086731))
* migrate components from ChannelActionContext, ChannelStateContext to StateStore instances ([#3237](https://github.com/GetStream/stream-chat-react/issues/3237)) ([99cbe67](https://github.com/GetStream/stream-chat-react/commit/99cbe67049d45d5a0f5f3c4463989a6824f739b6))
* move to new upload API ([#3272](https://github.com/GetStream/stream-chat-react/issues/3272)) ([04a31b1](https://github.com/GetStream/stream-chat-react/commit/04a31b18eff73492e6b305dd751f315bc9637a2b))
* move to timestamps in response models ([#3278](https://github.com/GetStream/stream-chat-react/issues/3278)) ([cb472c3](https://github.com/GetStream/stream-chat-react/commit/cb472c35f0bfe940b360a8564c535b3e9c0e6b53))
* pass the stream-chat configuration tree through useCreateChatClient ([#3321](https://github.com/GetStream/stream-chat-react/issues/3321)) ([557ffcb](https://github.com/GetStream/stream-chat-react/commit/557ffcb3cface45aa152474238c85aefbd0eff53)), closes [GetStream/stream-chat-js#1911](https://github.com/GetStream/stream-chat-js/issues/1911)
* port the tutorial alignment ([#3251](https://github.com/GetStream/stream-chat-react/issues/3251)) to v15, with panel-aware workspace navigation ([#3301](https://github.com/GetStream/stream-chat-react/issues/3301)) ([66557d6](https://github.com/GetStream/stream-chat-react/commit/66557d63b9a6eb08f6cfa8b0cb74418ec2451386))
* release v15 under the latest npm tag ([#3418](https://github.com/GetStream/stream-chat-react/issues/3418)) ([4ff3c97](https://github.com/GetStream/stream-chat-react/commit/4ff3c9745f364d9b34602f080a454afb641d3a09))
* rename ChannelPaginatorsOrchestrator to ChannelManager ([#3258](https://github.com/GetStream/stream-chat-react/issues/3258)) ([be2c8e1](https://github.com/GetStream/stream-chat-react/commit/be2c8e1e7bc486495ac5c9399728f58e78a23398))
* replace StreamChat.activeChannels with entity item index for loaded channels ([#3310](https://github.com/GetStream/stream-chat-react/issues/3310)) ([a41eed5](https://github.com/GetStream/stream-chat-react/commit/a41eed56fb5d471474768a3e989e50bbd9ba62c0))
* support local unread count on v15 ([#3298](https://github.com/GetStream/stream-chat-react/issues/3298)) ([a42c3cf](https://github.com/GetStream/stream-chat-react/commit/a42c3cf9729c107f95516001942aca864eb7f7f9))
* use configuration service API as a single source of truth ([#3273](https://github.com/GetStream/stream-chat-react/issues/3273)) ([f66597a](https://github.com/GetStream/stream-chat-react/commit/f66597a131c8ea2cd7758c78b95fa1479b3d4b3e))
* use network and WS connection observer services from LLC ([#3281](https://github.com/GetStream/stream-chat-react/issues/3281)) ([3098a90](https://github.com/GetStream/stream-chat-react/commit/3098a90a658b6ba49f9831aba27ce6b6720c9c82))

### Refactors

* align Thread with Channel - instance prop, provider, children ([#3289](https://github.com/GetStream/stream-chat-react/issues/3289)) ([c2136f3](https://github.com/GetStream/stream-chat-react/commit/c2136f307021b6007f2015659eb801aed2adfc9e))
* call Channel.watch(), which replaces ensureWatched() in stream-chat ([#3346](https://github.com/GetStream/stream-chat-react/issues/3346)) ([0100d98](https://github.com/GetStream/stream-chat-react/commit/0100d98ce0cac448238afaba2d4f8ec197b04d49))
* **i18n:** adopt the shared i18n layer from stream-chat/i18n ([#3271](https://github.com/GetStream/stream-chat-react/issues/3271)) ([f68cad3](https://github.com/GetStream/stream-chat-react/commit/f68cad3322e5c9fb3e9a20f415bc26cf28c9a701)), closes [GetStream/stream-chat-js#1830](https://github.com/GetStream/stream-chat-js/issues/1830)
* **i18n:** consume the shared runtime from @stream-io/i18n ([#3284](https://github.com/GetStream/stream-chat-react/issues/3284)) ([eb3ae7a](https://github.com/GetStream/stream-chat-react/commit/eb3ae7a5d44d39f86a69476514884ae3e5d4f823))
* **MessageActions:** remove the messageActions prop in from message lists ([#3288](https://github.com/GetStream/stream-chat-react/issues/3288)) ([b541c45](https://github.com/GetStream/stream-chat-react/commit/b541c45f92e448f8f29425beeb13f15bcd262252))
* **MessageList:** render thread messages from the thread unread snapshot ([#3324](https://github.com/GetStream/stream-chat-react/issues/3324)) ([ec6ce33](https://github.com/GetStream/stream-chat-react/commit/ec6ce3397b1e9af006ade622e138bc3cb4e4c007))
* **Message:** replace initialMessage with useIsRenderedAsThreadParent ([#3401](https://github.com/GetStream/stream-chat-react/issues/3401)) ([3b616f9](https://github.com/GetStream/stream-chat-react/commit/3b616f9761a3523c4a78fcbe35a7bc139c8c01f3))
* remove deprecated message APIs before v15 GA ([#3387](https://github.com/GetStream/stream-chat-react/issues/3387)) ([80ca72d](https://github.com/GetStream/stream-chat-react/commit/80ca72d85f4845af04d8627bdae0f8cbe85061cd))

### Performance Improvements

* **build:** emit ESM per source module so consumers can tree-shake ([#3269](https://github.com/GetStream/stream-chat-react/issues/3269)) ([55e76dc](https://github.com/GetStream/stream-chat-react/commit/55e76dca1f9e8a11c3f2ccdc88cc0686d9cf3ccc))

This branch was successfully deployed

2 active deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants