diff --git a/src/components/EmojiPicker/index.web.tsx b/src/components/EmojiPicker/index.web.tsx index 8d5e7788ec..41a80a5d60 100644 --- a/src/components/EmojiPicker/index.web.tsx +++ b/src/components/EmojiPicker/index.web.tsx @@ -1,5 +1,13 @@ -import {createContext, useContext, useEffect, useMemo, useRef} from 'react' -import EmojiPicker from '@emoji-mart/react' +import { + createContext, + lazy, + Suspense, + useContext, + useEffect, + useMemo, + useRef, +} from 'react' +import {View} from 'react-native' import {DropdownMenu} from 'radix-ui' import {useA11y} from '#/state/a11y' @@ -16,6 +24,24 @@ import { export * from './types' +/** + * The emoji-mart picker is code-split into its own chunk (`emoji-mart`) so its + * weight stays out of the main bundle and is only fetched when the picker + * actually mounts (i.e. when the dropdown opens). {@link useWebPreloadEmoji} + * warms the same chunk ahead of time. + */ +const EmojiPickerLazy = lazy( + () => import(/* webpackChunkName: "emoji-mart" */ '@emoji-mart/react'), +) + +/** + * Fixed-size placeholder shown while the emoji-mart chunk loads, sized to match + * emoji-mart's default picker so the dropdown doesn't visually jump when the + * real picker mounts. + */ +const PICKER_WIDTH = 352 +const PICKER_HEIGHT = 435 + const EmojiPickerContext = createContext<{ onEmojiSelect: (emoji: Emoji) => void nextFocusRef: RootProps['nextFocusRef'] @@ -124,16 +150,21 @@ export function Picker({keepOpenWhenShiftHeld = true}: PickerProps) {