fix(EmojiPicker): drop @emoji-mart/react peer dependency - #3255
Conversation
@emoji-mart/react declares react as ^16.8 || ^17 || ^18, omitting React 19, so integrators on React 19 hit peer-dependency errors and have to add package.json overrides even though the package works fine there. Vendor its ~20-line wrapper around the emoji-mart Picker custom element instead (MIT, from missive/emoji-mart) and remove the dependency from peerDependencies, peerDependenciesMeta and devDependencies. emoji-mart and @emoji-mart/data remain optional peer dependencies. This also lets us drop the CJS default-unwrapping workaround from #3199, which existed because @emoji-mart/react ships CJS with the component on exports.default and broke under strict ESM interop. Not a breaking change: @emoji-mart/react was an optional peer dependency and nothing in the SDK imports it any more.
π WalkthroughWalkthroughChangesThe PR adds a local React Emoji picker integration
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: π₯ Pre-merge checks | β 5β Passed checks (5 passed)
β¨ Finishing Touchesπ Generate docstrings
π§ͺ Generate unit tests (beta)
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. Comment |
|
Size Change: +154 B (+0.02%) Total Size: 884 kB π¦ View Changed
βΉοΈ View Unchanged
|
There was a problem hiding this comment.
π§Ή Nitpick comments (1)
src/plugins/Emojis/Picker.tsx (1)
28-29: π Maintainability & Code Quality | π΅ Trivial | β‘ Quick winDocument the ESLint exception.
Add a reason before the suppression. The effect must create the picker once. Prop changes use
instance.current.update(props).Proposed change
+ // Create the picker once. Prop changes use instance.current.update(props) above. // eslint-disable-next-line react-hooks/exhaustive-deps }, []);As per coding guidelines, βDo not suppress ESLint/Prettier rules broadly; justify and scope exceptions when necessary.β
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/Emojis/Picker.tsx` around lines 28 - 29, Add a concise justification for the react-hooks/exhaustive-deps suppression next to the disable directive in the effect that creates the picker, stating that it intentionally runs once and subsequent prop changes are handled through instance.current.update(props).Source: Coding guidelines
π€ Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/plugins/Emojis/Picker.tsx`:
- Around line 28-29: Add a concise justification for the
react-hooks/exhaustive-deps suppression next to the disable directive in the
effect that creates the picker, stating that it intentionally runs once and
subsequent prop changes are handled through instance.current.update(props).
βΉοΈ Review info
βοΈ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 029e94ed-44e4-4386-ad63-81f110204be5
β Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
π Files selected for processing (4)
package.jsonsrc/plugins/Emojis/EmojiPicker.tsxsrc/plugins/Emojis/Picker.tsxsrc/plugins/Emojis/__tests__/Picker.test.tsx
π€ Files with no reviewable changes (1)
- package.json
Codecov Reportβ
All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3255 +/- ##
==========================================
+ Coverage 85.18% 85.19% +0.01%
==========================================
Files 507 508 +1
Lines 15949 15958 +9
Branches 5025 5025
==========================================
+ Hits 13586 13596 +10
+ Misses 2363 2362 -1 β View full report in Codecov by Harness. π New features to boost your workflow:
|
### π― Goal Agent-facing documentation in this repo was spread across three files that nothing verified, and all three had drifted. **`AI.md`** was a hand-maintained integration guide for AI assistants, shipped in the npm tarball. It duplicates what the official docs and tutorial already cover. Every item below is wrong on `master` today: | Claim in `AI.md` | Reality | | --- | --- | | `import 'stream-chat-react/dist/css/v2/index.css'` β **6 occurrences** | `build-styling` emits `dist/css/index.css`; there is no `dist/css/v2/`, so this import cannot resolve | | `examples/tutorial/src/4-custom-ui-components/` | `6-custom-ui-components` | | `examples/tutorial/src/7-livestream/` | `optional-livestream` | | `examples/tutorial/src/6-emoji-picker/` | `7-emoji-picker` | | `examples/vite/src/stream-imports-theme.scss` | does not exist (`examples/vite/src/index.scss`) | | `stream-chat`: `^9.27.2` | `^9.50.2` | | install `@emoji-mart/react`, add React 19 overrides | no longer a dependency (#3255) | An AI-facing guide that hands out a CSS import path which doesn't exist is worse than no guide β it produces confidently broken integrations. We now publish maintained [agent skills](https://getstream.io/agent-skills/docs/installation/) that cover integration properly and stay in sync across SDKs. **`CLAUDE.md` and `AGENTS.md`** covered overlapping ground with no shared source, so each drifted independently β `CLAUDE.md` still documented Jest, a Playwright e2e suite, and a `MessageInput` component, none of which exist. Two files describing one repo is the reason they were both wrong. **`yarn types`** silently checked nothing (details below), so the type errors a contributor expected it to catch went unreported. ### π Implementation details #### 1. Deleted `AI.md` 423 lines, and removed from the `files` array in `package.json` β it was being published to npm, so this drops a file from the package tarball, not just from the repo. **Added a `Build with AI Agents` section to `README.md`**, directly after *React Chat Tutorial*. The tutorial is presented as the best way to get started, so the agent-driven path belongs beside it rather than buried further down. It documents the install (`curl -fsSL https://getstream.io/cli.sh | bash` + `getstream init`), links [`/stream-react`](https://getstream.io/agent-skills/docs/skills/stream-react/), and shows example invocations. Three entry points, so it's discoverable however someone scans the README: a `Quick Links` bullet at the top, the section itself, and a cross-reference from the existing "Using AI assistants" block at the bottom β that block points at `AGENTS.md`, which is about *contributing to this repo*, a different audience from someone integrating the SDK. Content came from the live docs pages rather than memory, so the install command, the four skill capabilities (scaffold / enhance / audit / migrate, including Sendbird β Stream Chat) and the supported-agent list match what the docs actually say. #### 2. `AGENTS.md` is now the single source; `CLAUDE.md` imports it `CLAUDE.md` is reduced to a pointer ending in `@AGENTS.md`, which Claude Code expands inline. `AGENTS.md` absorbed the architecture content and keeps its own contribution rules, so there is one file to maintain for every agent that reads this repo β and `AGENTS.md` is already the filename Copilot, Cursor, Codex and Aider read. An import rather than a symlink: git symlinks degrade to a plain text file on Windows checkouts with `core.symlinks=false`, which would leave Claude Code with no guidance at all. Every claim in the merged file was re-derived from source rather than carried over. Corrections: | Was documented | Reality in `src` | | --- | --- | | "Run Jest tests", `yarn e2e`, `yarn e2e-fixtures` | Vitest only; no Jest, no Playwright suite in this repo | | `<MessageInput>` + `MessageInput/hooks/` | Directory no longer exists β it's `MessageComposer`, backed by `stream-chat`'s `MessageComposer` class | | `<Channel Message={CustomMessage} />` | `ChannelProps` carries no component slots; overrides go through `<WithComponents overrides={{ β¦ }}>` | | `useStateStore(chatClient.state.channelsArray)` | A selector is required; shallow-compares selected keys | | 3 bundle entry points | 4 β `channel-detail` was added; `build-styling` emits 4 stylesheets | | `css-reset β stream-new β β¦` layers | `modern-normalize, stream-new, stream-new-plugins, stream-overrides, stream-app-overrides` | | `_global-theme-variables.scss` | `variable-tokens.scss` + `light.scss`/`dark.scss` | | Yarn binary pinned to `yarn-4.14.1.cjs` | Now unpinned by filename (it's 4.15.0 and moves) | | "Never commit directly to `main`" | Default branch is `master` | | Styling / Build / i18n sections duplicated verbatim | Deduplicated | Added, because it isn't discoverable without reading several files: composer state ownership and the `client.messageComposerCache` resolution order; the Vite 8 / Rolldown constraints in `vite.config.ts` and why they must not be "simplified" (hardcoded `es`/`cjs` output dirs, regex externals for subpath imports); the `npmMinimalAgeGate: 1d` / `enableScripts: false` dependency gates; the Vitest setup contract and `mock-builders` inventory; `src/a11y` primitives; i18n `keySeparator: false` (keys legitimately contain `/`); and the CI job list. The architectural sections that still held were each re-verified against source before being kept: the 500ms/200ms/500ms-leading/2000ms throttles in `Channel.tsx`, `PREPEND_OFFSET = 10 ** 7`, the `processMessages` ordering, the string-serialization memoization FIXME in `useCreateChannelStateContext`, `areMessageUIPropsEqual`'s cheap-prop ordering, and the `react-compat` ESLint block. #### 3. `yarn types` now type-checks `src` ```diff - "types": "tsc --emitDeclarationOnly false --noEmit", + "types": "tsc --project tsconfig.lib.json --noEmit", ``` Without `--project`, `tsc` resolves the root `tsconfig.json` β a solution-style config with `"files": []` and project references only. It therefore checked **no files**, exited in under a second and always passed. `--emitDeclarationOnly false` is dropped: it only existed to dodge the old TS5053 error when `--noEmit` met `emitDeclarationOnly`, and under this repo's TypeScript 6 the output is byte-identical without it (diffed both forms). `yarn types:tests` is left alone but is now documented honestly: it is **not run by CI** and is currently red repo-wide (~1300 errors), so `AGENTS.md` frames it as advisory against a baseline rather than a green gate. Worth a follow-up; out of scope here. ### β Verification - `yarn lint` β exit 0 (prettier covers Markdown in this repo) - **`yarn types` was verified to actually check, not merely to run**: injected `const __typecheck_probe: number = "not a number"` into `src/utils/getChannel.ts`, confirmed it was reported as `TS2322`, then reverted. Before this change the same probe produced no output. - Nothing in CI invokes `yarn types`, so enabling it cannot turn CI red. The same `tsconfig.lib.json` is already compiled by `yarn build` in CI with `noEmitOnError`, so `src` type errors were failing CI before this change too β this only makes the check runnable locally under a memorable name. - `require()` of `package.json` to confirm the earlier `files` edit kept it valid; no remaining references to `AI.md` anywhere in the repo. ### π¨ UI Changes None β documentation and one script definition. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added an βAI Agent Skillsβ quick link and guidance for building, upgrading, integrating, auditing, and migrating Stream Chat React applications with AI agents. * Replaced outdated repository guidance with expanded documentation covering development workflows, architecture, testing, accessibility, styling, troubleshooting, and contribution practices. * Removed the obsolete AI integration guide and related references. * Updated published package contents to reflect the documentation changes. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## [14.11.0](v14.10.0...v14.11.0) (2026-08-07) ### Bug Fixes * **Channel:** guard render-phase channel.getConfig() against disconnected channels ([#3257](#3257)) ([f60273f](f60273f)), closes [#3254](#3254) [#2393](#2393) [#3249](#3249) * **EmojiPicker:** drop @emoji-mart/react peer dependency ([#3255](#3255)) ([0820e4c](0820e4c)) ### Features * add icons to ComponentContext ([#3246](#3246)) ([972b68c](972b68c)) * localized unread count ([#3250](#3250)) ([1b8fa34](1b8fa34)), closes [GetStream/stream-chat-react-native#3679](GetStream/stream-chat-react-native#3679) * **MessageComposer:** introduce context for custom composers ([#3249](#3249)) ([5776c16](5776c16)), closes [#3248](#3248)
|
π This PR is included in version 14.11.0 π The release is available on: Your semantic-release bot π¦π |
π― Goal
@emoji-mart/reactdeclaresreactas^16.8 || ^17 || ^18in itspeerDependenciesβ React 19 is missing. Integrators on React 19 therefore hit peer-dependency resolution errors on install and have to addpackage.jsonoverrides to get past them, even though the package works fine on React 19 in practice.The wrapper that package provides is ~20 lines of glue around the
emoji-martPickercustom element. Rather than asking every React 19 integrator to carry an override, we vendor it and drop the dependency.π Implementation details
Vendored the wrapper - new
src/plugins/Emojis/Picker.tsx, taken from@emoji-mart/react(MIT, Copyright (c) Missive). Behaviour is identical to upstream;