emoji-picker-react 4.22.3 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +331 -49
- package/dist/DomUtils/categoryNameFromDom.d.ts +1 -1
- package/dist/DomUtils/classNames.d.ts +23 -23
- package/dist/DomUtils/detectEmojyPartiallyBelowFold.d.ts +2 -2
- package/dist/DomUtils/elementPositionInRow.d.ts +5 -5
- package/dist/DomUtils/eventBelongsToPicker.d.ts +2 -0
- package/dist/DomUtils/focusElement.d.ts +5 -5
- package/dist/DomUtils/getActiveElement.d.ts +2 -2
- package/dist/DomUtils/isJsdom.d.ts +1 -0
- package/dist/DomUtils/isRtl.d.ts +1 -0
- package/dist/DomUtils/keyboardNavigation.d.ts +15 -8
- package/dist/DomUtils/scrollTo.d.ts +4 -5
- package/dist/DomUtils/selectors.d.ts +31 -35
- package/dist/EmojiPickerReact.d.ts +5 -5
- package/dist/Stylesheet/DedupedStyle.d.ts +13 -0
- package/dist/Stylesheet/stylesheet.d.ts +40 -37
- package/dist/components/ErrorBoundary.d.ts +15 -15
- package/dist/components/Layout/Absolute.d.ts +8 -8
- package/dist/components/Layout/Flex.d.ts +13 -13
- package/dist/components/Layout/Relative.d.ts +8 -8
- package/dist/components/Layout/Space.d.ts +7 -7
- package/dist/components/Reactions/BtnPlus.d.ts +2 -2
- package/dist/components/Reactions/DEFAULT_REACTIONS.d.ts +1 -1
- package/dist/components/Reactions/Reactions.d.ts +3 -2
- package/dist/components/atoms/Button.d.ts +11 -6
- package/dist/components/body/EmojiCategory.d.ts +13 -12
- package/dist/components/body/EmojiList.d.ts +7 -4
- package/dist/components/body/EmojiVariationPicker.d.ts +2 -2
- package/dist/components/body/MeasureEmoji.d.ts +2 -2
- package/dist/components/body/listComponents.d.ts +47 -0
- package/dist/components/context/ElementRefContext.d.ts +18 -16
- package/dist/components/context/PickerConfigContext.d.ts +14 -9
- package/dist/components/context/PickerContext.d.ts +57 -25
- package/dist/components/context/PickerDataContext.d.ts +23 -17
- package/dist/components/emoji/BaseEmojiProps.d.ts +14 -13
- package/dist/components/emoji/ClickableEmojiButton.d.ts +23 -15
- package/dist/components/emoji/Emoji.d.ts +18 -15
- package/dist/components/emoji/EmojiImg.d.ts +11 -11
- package/dist/components/emoji/ExportedEmoji.d.ts +11 -11
- package/dist/components/emoji/NativeEmoji.d.ts +6 -6
- package/dist/components/emoji/ViewOnlyEmoji.d.ts +3 -3
- package/dist/components/emoji/emojiStyles.d.ts +6 -1
- package/dist/components/footer/Preview.d.ts +7 -7
- package/dist/components/header/Header.d.ts +2 -2
- package/dist/components/header/Search/BtnClearSearch.d.ts +2 -2
- package/dist/components/header/Search/IcnSearch.d.ts +2 -2
- package/dist/components/header/Search/Search.d.ts +11 -3
- package/dist/components/header/SkinTonePicker/BtnSkinToneVariation.d.ts +12 -12
- package/dist/components/header/SkinTonePicker/SkinTonePicker.d.ts +11 -11
- package/dist/components/icons/svgIcons.d.ts +4 -0
- package/dist/components/main/PickerMainBehaviors.d.ts +4 -0
- package/dist/components/main/defaultAppearance.d.ts +12 -0
- package/dist/components/main/labelHeight.d.ts +1 -0
- package/dist/components/navigation/CategoryButton.d.ts +12 -12
- package/dist/components/navigation/CategoryNavIcon.d.ts +4 -4
- package/dist/components/navigation/CategoryNavigation.d.ts +19 -2
- package/dist/config/categoryConfig.d.ts +34 -34
- package/dist/config/cdnUrls.d.ts +2 -2
- package/dist/config/compareConfig.d.ts +10 -2
- package/dist/config/config.d.ts +166 -64
- package/dist/config/customEmojiConfig.d.ts +14 -14
- package/dist/config/defaultPickerConfiguration.d.ts +10 -0
- package/dist/config/mutableConfig.d.ts +32 -10
- package/dist/config/useConfig.d.ts +48 -36
- package/dist/data/defaultEmojiData.d.ts +9 -0
- package/dist/data/defaultEmojiData.js +40 -0
- package/dist/data/emojis-bn.d.mts +39 -0
- package/dist/data/emojis-bn.d.ts +38 -2
- package/dist/data/emojis-bn.js +25 -2
- package/dist/data/emojis-bn.mjs +2 -0
- package/dist/data/emojis-da.d.mts +39 -0
- package/dist/data/emojis-da.d.ts +38 -2
- package/dist/data/emojis-da.js +25 -2
- package/dist/data/emojis-da.mjs +2 -0
- package/dist/data/emojis-de.d.mts +39 -0
- package/dist/data/emojis-de.d.ts +38 -2
- package/dist/data/emojis-de.js +25 -2
- package/dist/data/emojis-de.mjs +2 -0
- package/dist/data/emojis-en-gb.d.mts +39 -0
- package/dist/data/emojis-en-gb.d.ts +38 -2
- package/dist/data/emojis-en-gb.js +25 -2
- package/dist/data/emojis-en-gb.mjs +2 -0
- package/dist/data/emojis-en.d.mts +39 -0
- package/dist/data/emojis-en.d.ts +38 -2
- package/dist/data/emojis-en.js +25 -2
- package/dist/data/emojis-en.mjs +2 -0
- package/dist/data/emojis-es-mx.d.mts +39 -0
- package/dist/data/emojis-es-mx.d.ts +38 -2
- package/dist/data/emojis-es-mx.js +25 -2
- package/dist/data/emojis-es-mx.mjs +2 -0
- package/dist/data/emojis-es.d.mts +39 -0
- package/dist/data/emojis-es.d.ts +38 -2
- package/dist/data/emojis-es.js +25 -2
- package/dist/data/emojis-es.mjs +2 -0
- package/dist/data/emojis-et.d.mts +39 -0
- package/dist/data/emojis-et.d.ts +38 -2
- package/dist/data/emojis-et.js +25 -2
- package/dist/data/emojis-et.mjs +2 -0
- package/dist/data/emojis-fi.d.mts +39 -0
- package/dist/data/emojis-fi.d.ts +38 -2
- package/dist/data/emojis-fi.js +25 -2
- package/dist/data/emojis-fi.mjs +2 -0
- package/dist/data/emojis-fr.d.mts +39 -0
- package/dist/data/emojis-fr.d.ts +38 -2
- package/dist/data/emojis-fr.js +25 -2
- package/dist/data/emojis-fr.mjs +2 -0
- package/dist/data/emojis-hi.d.mts +39 -0
- package/dist/data/emojis-hi.d.ts +38 -2
- package/dist/data/emojis-hi.js +25 -2
- package/dist/data/emojis-hi.mjs +2 -0
- package/dist/data/emojis-hu.d.mts +39 -0
- package/dist/data/emojis-hu.d.ts +38 -2
- package/dist/data/emojis-hu.js +25 -2
- package/dist/data/emojis-hu.mjs +2 -0
- package/dist/data/emojis-it.d.mts +39 -0
- package/dist/data/emojis-it.d.ts +38 -2
- package/dist/data/emojis-it.js +25 -2
- package/dist/data/emojis-it.mjs +2 -0
- package/dist/data/emojis-ja.d.mts +39 -0
- package/dist/data/emojis-ja.d.ts +38 -2
- package/dist/data/emojis-ja.js +25 -2
- package/dist/data/emojis-ja.mjs +2 -0
- package/dist/data/emojis-ko.d.mts +39 -0
- package/dist/data/emojis-ko.d.ts +38 -2
- package/dist/data/emojis-ko.js +25 -2
- package/dist/data/emojis-ko.mjs +2 -0
- package/dist/data/emojis-lt.d.mts +39 -0
- package/dist/data/emojis-lt.d.ts +38 -2
- package/dist/data/emojis-lt.js +25 -2
- package/dist/data/emojis-lt.mjs +2 -0
- package/dist/data/emojis-ms.d.mts +39 -0
- package/dist/data/emojis-ms.d.ts +38 -2
- package/dist/data/emojis-ms.js +25 -2
- package/dist/data/emojis-ms.mjs +2 -0
- package/dist/data/emojis-nb.d.mts +39 -0
- package/dist/data/emojis-nb.d.ts +38 -2
- package/dist/data/emojis-nb.js +25 -2
- package/dist/data/emojis-nb.mjs +2 -0
- package/dist/data/emojis-nl.d.mts +39 -0
- package/dist/data/emojis-nl.d.ts +38 -2
- package/dist/data/emojis-nl.js +25 -2
- package/dist/data/emojis-nl.mjs +2 -0
- package/dist/data/emojis-pl.d.mts +39 -0
- package/dist/data/emojis-pl.d.ts +38 -2
- package/dist/data/emojis-pl.js +25 -2
- package/dist/data/emojis-pl.mjs +2 -0
- package/dist/data/emojis-pt.d.mts +39 -0
- package/dist/data/emojis-pt.d.ts +38 -2
- package/dist/data/emojis-pt.js +25 -2
- package/dist/data/emojis-pt.mjs +2 -0
- package/dist/data/emojis-ru.d.mts +39 -0
- package/dist/data/emojis-ru.d.ts +38 -2
- package/dist/data/emojis-ru.js +25 -2
- package/dist/data/emojis-ru.mjs +2 -0
- package/dist/data/emojis-sv.d.mts +39 -0
- package/dist/data/emojis-sv.d.ts +38 -2
- package/dist/data/emojis-sv.js +25 -2
- package/dist/data/emojis-sv.mjs +2 -0
- package/dist/data/emojis-th.d.mts +39 -0
- package/dist/data/emojis-th.d.ts +38 -2
- package/dist/data/emojis-th.js +25 -2
- package/dist/data/emojis-th.mjs +2 -0
- package/dist/data/emojis-uk.d.mts +39 -0
- package/dist/data/emojis-uk.d.ts +38 -2
- package/dist/data/emojis-uk.js +25 -2
- package/dist/data/emojis-uk.mjs +2 -0
- package/dist/data/emojis-vi.d.mts +39 -0
- package/dist/data/emojis-vi.d.ts +38 -2
- package/dist/data/emojis-vi.js +25 -2
- package/dist/data/emojis-vi.mjs +2 -0
- package/dist/data/emojis-zh-hant.d.mts +39 -0
- package/dist/data/emojis-zh-hant.d.ts +38 -2
- package/dist/data/emojis-zh-hant.js +25 -2
- package/dist/data/emojis-zh-hant.mjs +2 -0
- package/dist/data/emojis-zh.d.mts +39 -0
- package/dist/data/emojis-zh.d.ts +38 -2
- package/dist/data/emojis-zh.js +25 -2
- package/dist/data/emojis-zh.mjs +2 -0
- package/dist/data/index.js +1 -0
- package/dist/data/registerDefaultEmojiData.d.ts +1 -0
- package/dist/data/registerDefaultEmojiData.js +3 -0
- package/dist/data/skinToneVariations.js +2 -2
- package/dist/data/skinToneVariations.ts +8 -7
- package/dist/data-core/pickerData.d.ts +12 -0
- package/dist/data-core/prepare.d.ts +23 -0
- package/dist/data-core/search.d.ts +13 -0
- package/dist/data-core/types.d.ts +23 -0
- package/dist/data.d.mts +72 -0
- package/dist/data.d.ts +72 -0
- package/dist/dataUtils/DataTypes.d.ts +23 -19
- package/dist/dataUtils/emojiSelectors.d.ts +15 -16
- package/dist/dataUtils/emojiUtils.d.ts +1 -12
- package/dist/dataUtils/nativeEmojiSequenceSupport.d.ts +10 -0
- package/dist/dataUtils/nativeEmojiSupport.d.ts +40 -0
- package/dist/dataUtils/parseNativeEmoji.d.ts +1 -1
- package/dist/dataUtils/suggested.d.ts +11 -11
- package/dist/dataUtils/suggestedEmojis.d.ts +7 -0
- package/dist/esm/chunks/chunk-7ZGTUZFB.mjs +8025 -0
- package/dist/esm/chunks/chunk-ACXAQEKG.mjs +149 -0
- package/dist/esm/chunks/chunk-F2KS7DCA.mjs +6735 -0
- package/dist/esm/chunks/chunk-L5W4PFRJ.mjs +14 -0
- package/dist/esm/chunks/chunk-LO4TPPLH.mjs +33 -0
- package/dist/esm/chunks/emojis-6L3GRBAP.mjs +7 -0
- package/dist/esm/data.mjs +11 -0
- package/dist/esm/index.mjs +279 -0
- package/dist/esm/primitives/index.mjs +8 -0
- package/dist/hooks/preloadEmoji.d.ts +5 -9
- package/dist/hooks/useActiveCategoryScrollDetection.d.ts +11 -11
- package/dist/hooks/useCategoryHeight.d.ts +7 -5
- package/dist/hooks/useCloseAllOpenToggles.d.ts +2 -2
- package/dist/hooks/useDataIdentityStabilityWarning.d.ts +13 -0
- package/dist/hooks/useDebouncedState.d.ts +1 -1
- package/dist/hooks/useDisallowMouseMove.d.ts +4 -4
- package/dist/hooks/useDisallowedEmojis.d.ts +2 -3
- package/dist/hooks/useEmojiPreviewEvents.d.ts +3 -3
- package/dist/hooks/useEmojiVirtualization.d.ts +22 -17
- package/dist/hooks/useFilter.d.ts +10 -16
- package/dist/hooks/useFocus.d.ts +3 -3
- package/dist/hooks/useInitialLoad.d.ts +2 -2
- package/dist/hooks/useIsEmojiHidden.d.ts +8 -8
- package/dist/hooks/useIsMounted.d.ts +1 -1
- package/dist/hooks/useIsSearchMode.d.ts +1 -1
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
- package/dist/hooks/useKeyboardNavigation.d.ts +3 -1
- package/dist/hooks/useMouseDownHandlers.d.ts +8 -4
- package/dist/hooks/useOnFocus.d.ts +1 -1
- package/dist/hooks/useOnScroll.d.ts +2 -2
- package/dist/hooks/useReactionsFocus.d.ts +1 -0
- package/dist/hooks/useRegisterRegion.d.ts +24 -0
- package/dist/hooks/useResolvedEmojiData.d.ts +37 -0
- package/dist/hooks/useScrollCategoryIntoView.d.ts +1 -1
- package/dist/hooks/useSearchController.d.ts +17 -0
- package/dist/hooks/useSearchResults.d.ts +8 -0
- package/dist/hooks/useSetVariationPicker.d.ts +2 -2
- package/dist/hooks/useShouldHideCustomEmojis.d.ts +1 -1
- package/dist/hooks/useShouldShowSkinTonePicker.d.ts +4 -4
- package/dist/index.d.mts +376 -0
- package/dist/index.d.ts +376 -9
- package/dist/index.js +2 -8
- package/dist/primitives/CategoryNav.d.ts +4 -0
- package/dist/primitives/Empty.d.ts +6 -0
- package/dist/primitives/List.d.ts +4 -0
- package/dist/primitives/LoadError.d.ts +8 -0
- package/dist/primitives/Loading.d.ts +4 -0
- package/dist/primitives/Panel.d.ts +3 -0
- package/dist/primitives/Preview.d.ts +3 -0
- package/dist/primitives/Reactions.d.ts +2 -0
- package/dist/primitives/Root.d.ts +26 -0
- package/dist/primitives/Search.d.ts +5 -0
- package/dist/primitives/SearchInput.d.ts +3 -0
- package/dist/primitives/SkinTone.d.ts +4 -0
- package/dist/primitives/Viewport.d.ts +19 -0
- package/dist/primitives/appearance.d.ts +3 -0
- package/dist/primitives/components.d.ts +27 -0
- package/dist/primitives/hooks.d.ts +48 -0
- package/dist/primitives/index.d.mts +561 -0
- package/dist/primitives/index.d.ts +561 -0
- package/dist/primitives/index.js +2 -0
- package/dist/primitives/nativeProps.d.ts +15 -0
- package/dist/primitives/scope.d.ts +13 -0
- package/dist/primitives/structuralStyles.d.ts +16 -0
- package/dist/primitives/tokens.d.ts +18 -0
- package/dist/primitives/types.d.ts +85 -0
- package/dist/state/activeEmojiStore.d.ts +7 -0
- package/dist/state/navigationRegistry.d.ts +61 -0
- package/dist/state/regionTraversal.d.ts +20 -0
- package/dist/typeRefinements/typeRefinements.d.ts +6 -6
- package/dist/types/exposedTypes.d.ts +16 -6
- package/dist/types/exposedTypes.js +5 -0
- package/dist/virtualization/virtualizationHelpers.d.ts +22 -18
- package/llms-full.txt +3683 -0
- package/llms.txt +66 -480
- package/package.json +180 -66
- package/src/DomUtils/categoryNameFromDom.ts +1 -1
- package/src/DomUtils/classNames.ts +1 -4
- package/src/DomUtils/elementPositionInRow.ts +28 -6
- package/src/DomUtils/eventBelongsToPicker.ts +17 -0
- package/src/DomUtils/getActiveElement.ts +7 -1
- package/src/DomUtils/isJsdom.ts +12 -0
- package/src/DomUtils/isRtl.ts +5 -0
- package/src/DomUtils/keyboardNavigation.ts +164 -144
- package/src/DomUtils/scrollTo.ts +20 -18
- package/src/DomUtils/selectors.ts +30 -127
- package/src/EmojiPickerReact.tsx +155 -48
- package/src/Stylesheet/DedupedStyle.tsx +80 -0
- package/src/Stylesheet/stylesheet.tsx +128 -59
- package/src/components/Layout/Flex.tsx +12 -11
- package/src/components/Reactions/BtnPlus.tsx +61 -51
- package/src/components/Reactions/Reactions.tsx +113 -55
- package/src/components/atoms/Button.tsx +18 -15
- package/src/components/body/EmojiCategory.tsx +77 -40
- package/src/components/body/EmojiList.tsx +107 -44
- package/src/components/body/EmojiVariationPicker.tsx +113 -66
- package/src/components/body/MeasureEmoji.tsx +9 -2
- package/src/components/body/listComponents.tsx +79 -0
- package/src/components/context/ElementRefContext.tsx +46 -35
- package/src/components/context/PickerConfigContext.tsx +55 -40
- package/src/components/context/PickerContext.tsx +567 -92
- package/src/components/context/PickerDataContext.tsx +114 -99
- package/src/components/emoji/BaseEmojiProps.ts +5 -4
- package/src/components/emoji/ClickableEmojiButton.tsx +148 -63
- package/src/components/emoji/Emoji.tsx +24 -2
- package/src/components/emoji/EmojiImg.tsx +13 -12
- package/src/components/emoji/ExportedEmoji.tsx +5 -4
- package/src/components/emoji/NativeEmoji.tsx +19 -16
- package/src/components/emoji/ViewOnlyEmoji.tsx +55 -30
- package/src/components/emoji/emojiStyles.ts +12 -11
- package/src/components/footer/Preview.tsx +86 -91
- package/src/components/header/Header.tsx +21 -6
- package/src/components/header/Search/BtnClearSearch.tsx +69 -55
- package/src/components/header/Search/IcnSearch.tsx +21 -21
- package/src/components/header/Search/Search.tsx +79 -137
- package/src/components/header/SkinTonePicker/BtnSkinToneVariation.tsx +99 -62
- package/src/components/header/SkinTonePicker/SkinTonePicker.tsx +84 -46
- package/src/components/icons/svgIcons.ts +17 -0
- package/src/components/main/PickerMainBehaviors.tsx +163 -0
- package/src/components/main/defaultAppearance.tsx +189 -0
- package/src/components/main/labelHeight.ts +5 -0
- package/src/components/navigation/CategoryButton.tsx +83 -57
- package/src/components/navigation/CategoryNavIcon.tsx +73 -194
- package/src/components/navigation/CategoryNavigation.tsx +118 -46
- package/src/config/categoryConfig.ts +7 -3
- package/src/config/cdnUrls.ts +11 -21
- package/src/config/compareConfig.ts +128 -30
- package/src/config/config.ts +228 -24
- package/src/config/defaultPickerConfiguration.ts +7 -0
- package/src/config/mutableConfig.ts +44 -20
- package/src/config/useConfig.ts +130 -37
- package/src/data/defaultEmojiData.ts +49 -0
- package/src/data/registerDefaultEmojiData.ts +8 -0
- package/src/data/skinToneVariations.ts +8 -7
- package/src/data-core/pickerData.ts +171 -0
- package/src/data-core/prepare.ts +163 -0
- package/src/data-core/search.ts +122 -0
- package/src/data-core/types.ts +36 -0
- package/src/data.ts +10 -0
- package/src/dataUtils/DataTypes.ts +4 -0
- package/src/dataUtils/emojiSelectors.ts +59 -63
- package/src/dataUtils/emojiUtils.ts +17 -74
- package/src/dataUtils/nativeEmojiSequenceSupport.ts +116 -0
- package/src/dataUtils/nativeEmojiSupport.ts +160 -0
- package/src/dataUtils/parseNativeEmoji.ts +3 -4
- package/src/dataUtils/suggested.ts +8 -4
- package/src/dataUtils/suggestedEmojis.ts +92 -0
- package/src/env.d.ts +4 -0
- package/src/hooks/preloadEmoji.ts +2 -47
- package/src/hooks/useActiveCategoryScrollDetection.ts +28 -16
- package/src/hooks/useCategoryHeight.ts +116 -10
- package/src/hooks/useDataIdentityStabilityWarning.ts +86 -0
- package/src/hooks/useDebouncedState.ts +13 -1
- package/src/hooks/useDisallowedEmojis.ts +31 -42
- package/src/hooks/useEmojiPreviewEvents.ts +43 -10
- package/src/hooks/useEmojiVirtualization.tsx +112 -52
- package/src/hooks/useFilter.ts +92 -132
- package/src/hooks/useFocus.ts +14 -24
- package/src/hooks/useIsEmojiHidden.ts +22 -14
- package/src/hooks/useKeyboardNavigation.ts +412 -432
- package/src/hooks/useMouseDownHandlers.ts +91 -16
- package/src/hooks/useOnFocus.ts +12 -3
- package/src/hooks/useOnScroll.ts +18 -2
- package/src/hooks/useReactionsFocus.ts +118 -0
- package/src/hooks/useRegisterRegion.ts +92 -0
- package/src/hooks/useResolvedEmojiData.ts +200 -0
- package/src/hooks/useScrollCategoryIntoView.ts +74 -12
- package/src/hooks/useSearchController.ts +369 -0
- package/src/hooks/useSearchResults.ts +51 -0
- package/src/hooks/useSetVariationPicker.ts +4 -1
- package/src/index.tsx +67 -5
- package/src/primitives/CategoryNav.tsx +40 -0
- package/src/primitives/Empty.tsx +68 -0
- package/src/primitives/List.tsx +61 -0
- package/src/primitives/LoadError.tsx +38 -0
- package/src/primitives/Loading.tsx +60 -0
- package/src/primitives/Panel.tsx +47 -0
- package/src/primitives/Preview.tsx +38 -0
- package/src/primitives/Reactions.tsx +2 -0
- package/src/primitives/Root.tsx +398 -0
- package/src/primitives/Search.tsx +41 -0
- package/src/primitives/SearchInput.tsx +110 -0
- package/src/primitives/SkinTone.tsx +76 -0
- package/src/primitives/Viewport.tsx +204 -0
- package/src/primitives/appearance.tsx +7 -0
- package/src/primitives/components.tsx +30 -0
- package/src/primitives/hooks.ts +165 -0
- package/src/primitives/index.ts +94 -0
- package/src/primitives/nativeProps.ts +90 -0
- package/src/primitives/scope.tsx +109 -0
- package/src/primitives/structuralStyles.tsx +136 -0
- package/src/primitives/tokens.ts +150 -0
- package/src/primitives/types.ts +192 -0
- package/src/state/activeEmojiStore.ts +39 -0
- package/src/state/navigationRegistry.ts +209 -0
- package/src/state/regionTraversal.ts +116 -0
- package/src/svg.d.ts +2 -2
- package/src/types/exposedTypes.ts +28 -1
- package/src/virtualization/virtualizationHelpers.ts +29 -8
- package/dist/components/body/Body.d.ts +0 -2
- package/dist/components/main/PickerMain.d.ts +0 -7
- package/dist/dataUtils/alphaNumericEmojiIndex.d.ts +0 -5
- package/dist/emoji-picker-react.cjs.development.js +0 -31413
- package/dist/emoji-picker-react.cjs.development.js.map +0 -1
- package/dist/emoji-picker-react.cjs.production.min.js +0 -2
- package/dist/emoji-picker-react.cjs.production.min.js.map +0 -1
- package/dist/emoji-picker-react.esm.js +0 -31411
- package/dist/emoji-picker-react.esm.js.map +0 -1
- package/dist/hooks/useHideEmojisByUniocode.d.ts +0 -1
- package/src/components/body/Body.tsx +0 -43
- package/src/components/main/PickerMain.tsx +0 -249
- package/src/dataUtils/alphaNumericEmojiIndex.ts +0 -21
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* global process: readonly */
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { CustomEmoji } from '../config/customEmojiConfig';
|
|
5
|
+
import { defaultEmojiDataOrEmpty } from '../data/defaultEmojiData';
|
|
6
|
+
import type { EmojiData } from '../types/exposedTypes';
|
|
7
|
+
|
|
8
|
+
interface IdentityTracker {
|
|
9
|
+
prev: unknown;
|
|
10
|
+
consecutiveChanges: number;
|
|
11
|
+
warned: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function trackIdentity(
|
|
15
|
+
tracker: IdentityTracker,
|
|
16
|
+
value: unknown,
|
|
17
|
+
isDefault: boolean,
|
|
18
|
+
message: string,
|
|
19
|
+
): void {
|
|
20
|
+
if (isDefault) {
|
|
21
|
+
tracker.prev = value;
|
|
22
|
+
tracker.consecutiveChanges = 0;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (tracker.prev !== undefined && tracker.prev !== value) {
|
|
26
|
+
tracker.consecutiveChanges += 1;
|
|
27
|
+
} else if (tracker.prev === value) {
|
|
28
|
+
tracker.consecutiveChanges = 0;
|
|
29
|
+
}
|
|
30
|
+
tracker.prev = value;
|
|
31
|
+
if (tracker.consecutiveChanges >= 3 && !tracker.warned) {
|
|
32
|
+
tracker.warned = true;
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.warn(message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function freshTracker(): IdentityTracker {
|
|
39
|
+
return { prev: undefined, consecutiveChanges: 0, warned: false };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Dev-only diagnostic.
|
|
44
|
+
*
|
|
45
|
+
* Identity caching only helps when callers keep data props referentially
|
|
46
|
+
* stable. If a non-default `emojiData` (or `customEmojis`) changes identity
|
|
47
|
+
* on three consecutive committed renders, warn once that repeated identity
|
|
48
|
+
* churn defeats prepared-data caching. Behavior stays correct; this is
|
|
49
|
+
* diagnostic only. A single/occasional replacement (e.g. locale change)
|
|
50
|
+
* must not warn. No deep-compare or clone is performed.
|
|
51
|
+
*/
|
|
52
|
+
export const useDataIdentityStabilityWarning: (
|
|
53
|
+
emojiData: EmojiData | undefined,
|
|
54
|
+
customEmojis: CustomEmoji[] | undefined,
|
|
55
|
+
) => void =
|
|
56
|
+
// Development only: production bundles drop the trackers entirely.
|
|
57
|
+
process.env.NODE_ENV === 'production'
|
|
58
|
+
? () => undefined
|
|
59
|
+
: useIdentityChurnWarning;
|
|
60
|
+
|
|
61
|
+
function useIdentityChurnWarning(
|
|
62
|
+
emojiData: EmojiData | undefined,
|
|
63
|
+
customEmojis: CustomEmoji[] | undefined,
|
|
64
|
+
): void {
|
|
65
|
+
const emojiState = React.useRef<IdentityTracker>(freshTracker());
|
|
66
|
+
const customState = React.useRef<IdentityTracker>(freshTracker());
|
|
67
|
+
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
trackIdentity(
|
|
70
|
+
emojiState.current,
|
|
71
|
+
emojiData,
|
|
72
|
+
!emojiData || emojiData === defaultEmojiDataOrEmpty(),
|
|
73
|
+
'[emoji-picker-react] `emojiData` changed identity on three consecutive renders. ' +
|
|
74
|
+
'Memoize/reuse the dataset object so the prepared-data cache can be shared. ' +
|
|
75
|
+
'Behavior remains correct; caching is only defeated by identity churn.',
|
|
76
|
+
);
|
|
77
|
+
trackIdentity(
|
|
78
|
+
customState.current,
|
|
79
|
+
customEmojis,
|
|
80
|
+
!customEmojis || customEmojis.length === 0,
|
|
81
|
+
'[emoji-picker-react] `customEmojis` changed identity on three consecutive renders. ' +
|
|
82
|
+
'Memoize/reuse the array so custom-emoji derivation can be cached. ' +
|
|
83
|
+
'Behavior remains correct; caching is only defeated by identity churn.',
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useRef, useState } from 'react';
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
export function useDebouncedState<T>(
|
|
4
4
|
initialValue: T,
|
|
@@ -7,6 +7,18 @@ export function useDebouncedState<T>(
|
|
|
7
7
|
const [state, setState] = useState<T>(initialValue);
|
|
8
8
|
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
9
9
|
|
|
10
|
+
// A pending trailing edge must never fire after unmount (React warns
|
|
11
|
+
// about the post-unmount setState and the work is wasted).
|
|
12
|
+
useEffect(
|
|
13
|
+
() => () => {
|
|
14
|
+
if (timer.current) {
|
|
15
|
+
clearTimeout(timer.current);
|
|
16
|
+
timer.current = null;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
[],
|
|
20
|
+
);
|
|
21
|
+
|
|
10
22
|
function debouncedSetState(value: T) {
|
|
11
23
|
return new Promise<T>((resolve) => {
|
|
12
24
|
if (timer.current) {
|
|
@@ -1,52 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
useActiveSkinToneState,
|
|
5
|
+
useNativeEmojiSupport,
|
|
6
|
+
} from '../components/context/PickerContext';
|
|
7
|
+
import { useEmojiVersionConfig, useUnicodeToHide } from '../config/useConfig';
|
|
5
8
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
6
9
|
import {
|
|
7
10
|
addedIn,
|
|
8
11
|
emojiUnified,
|
|
9
12
|
unifiedWithoutSkinTone,
|
|
10
13
|
} from '../dataUtils/emojiUtils';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
export function useDisallowedEmojis() {
|
|
15
|
-
const DisallowedEmojisRef = useRef<Record<string, boolean>>({});
|
|
16
|
-
const emojiVersionConfig = useEmojiVersionConfig();
|
|
17
|
-
const { allEmojis } = usePickerDataContext();
|
|
18
|
-
|
|
19
|
-
return useMemo(() => {
|
|
20
|
-
const emojiVersion = parseFloat(`${emojiVersionConfig}`);
|
|
21
|
-
|
|
22
|
-
if (!emojiVersionConfig || Number.isNaN(emojiVersion)) {
|
|
23
|
-
return DisallowedEmojisRef.current;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return allEmojis.reduce((disallowedEmojis, emoji) => {
|
|
27
|
-
if (addedInNewerVersion(emoji, emojiVersion)) {
|
|
28
|
-
disallowedEmojis[emojiUnified(emoji)] = true;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return disallowedEmojis;
|
|
32
|
-
}, DisallowedEmojisRef.current);
|
|
33
|
-
}, [emojiVersionConfig, allEmojis]);
|
|
34
|
-
}
|
|
14
|
+
import { isNativeEmojiSupported } from '../dataUtils/nativeEmojiSupport';
|
|
15
|
+
import { isCustomEmoji } from '../typeRefinements/typeRefinements';
|
|
35
16
|
|
|
36
17
|
export function useIsEmojiDisallowed() {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
18
|
+
const configured = parseFloat(useEmojiVersionConfig() || '');
|
|
19
|
+
const nativeSupport = useNativeEmojiSupport();
|
|
20
|
+
// A configured cap restricts native support; it never overrides it.
|
|
21
|
+
const cap = Number.isNaN(configured) ? Infinity : configured;
|
|
22
|
+
const unicodeToHide = useUnicodeToHide();
|
|
23
|
+
const [activeSkinTone] = useActiveSkinToneState();
|
|
24
|
+
|
|
25
|
+
return useCallback(
|
|
26
|
+
function isEmojiDisallowed(
|
|
27
|
+
emoji: DataEmoji,
|
|
28
|
+
renderedUnified = emojiUnified(emoji, activeSkinTone),
|
|
29
|
+
) {
|
|
30
|
+
if (unicodeToHide.has(unifiedWithoutSkinTone(emojiUnified(emoji))))
|
|
31
|
+
return true;
|
|
32
|
+
if (isCustomEmoji(emoji)) return false;
|
|
33
|
+
const version = addedIn(emoji);
|
|
34
|
+
return (
|
|
35
|
+
version > cap ||
|
|
36
|
+
!isNativeEmojiSupported(nativeSupport, renderedUnified, version)
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
[activeSkinTone, unicodeToHide, cap, nativeSupport],
|
|
40
|
+
);
|
|
52
41
|
}
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
|
|
4
4
|
import { detectEmojyPartiallyBelowFold } from '../DomUtils/detectEmojyPartiallyBelowFold';
|
|
5
|
+
import { eventBelongsToPicker } from '../DomUtils/eventBelongsToPicker';
|
|
5
6
|
import { focusElement } from '../DomUtils/focusElement';
|
|
6
7
|
import {
|
|
7
8
|
allUnifiedFromEmojiElement,
|
|
@@ -11,16 +12,19 @@ import {
|
|
|
11
12
|
useBodyRef,
|
|
12
13
|
usePickerMainRef,
|
|
13
14
|
} from '../components/context/ElementRefContext';
|
|
14
|
-
import {
|
|
15
|
+
import { ActiveEmojiState } from '../components/context/PickerContext';
|
|
15
16
|
|
|
16
17
|
import {
|
|
17
18
|
useAllowMouseMove,
|
|
18
19
|
useIsMouseDisallowed,
|
|
19
20
|
} from './useDisallowMouseMove';
|
|
20
21
|
|
|
22
|
+
// Tracks the hovered/focused emoji. `focusOnHover` additionally moves
|
|
23
|
+
// focus to the hovered emoji so arrow keys continue from it (enabled
|
|
24
|
+
// together with the preview, as in v4).
|
|
21
25
|
export function useEmojiPreviewEvents(
|
|
22
|
-
|
|
23
|
-
setPreviewEmoji: React.Dispatch<React.SetStateAction<
|
|
26
|
+
focusOnHover: boolean,
|
|
27
|
+
setPreviewEmoji: React.Dispatch<React.SetStateAction<ActiveEmojiState>>,
|
|
24
28
|
) {
|
|
25
29
|
const BodyRef = useBodyRef();
|
|
26
30
|
const PickerMainRef = usePickerMainRef();
|
|
@@ -28,9 +32,6 @@ export function useEmojiPreviewEvents(
|
|
|
28
32
|
const allowMouseMove = useAllowMouseMove();
|
|
29
33
|
|
|
30
34
|
useEffect(() => {
|
|
31
|
-
if (!allow) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
35
|
const bodyRef = BodyRef.current;
|
|
35
36
|
|
|
36
37
|
bodyRef?.addEventListener('keydown', onEscape, {
|
|
@@ -39,6 +40,14 @@ export function useEmojiPreviewEvents(
|
|
|
39
40
|
|
|
40
41
|
bodyRef?.addEventListener('mouseover', onMouseOver, true);
|
|
41
42
|
|
|
43
|
+
// Mouseover precedes mousemove on a newly hovered cell. Resume hover
|
|
44
|
+
// during capture, before the body's movement listener clears the
|
|
45
|
+
// keyboard guard, so the first real pointer movement is not lost.
|
|
46
|
+
bodyRef?.addEventListener('mousemove', onMouseMove, {
|
|
47
|
+
capture: true,
|
|
48
|
+
passive: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
42
51
|
bodyRef?.addEventListener('focus', onEnter, true);
|
|
43
52
|
|
|
44
53
|
bodyRef?.addEventListener('mouseout', onLeave, {
|
|
@@ -47,6 +56,7 @@ export function useEmojiPreviewEvents(
|
|
|
47
56
|
bodyRef?.addEventListener('blur', onLeave, true);
|
|
48
57
|
|
|
49
58
|
function onEnter(e: FocusEvent) {
|
|
59
|
+
if (!eventBelongsToPicker(e, bodyRef)) return;
|
|
50
60
|
const button = buttonFromTarget(e.target as HTMLElement);
|
|
51
61
|
|
|
52
62
|
if (!button) {
|
|
@@ -65,6 +75,7 @@ export function useEmojiPreviewEvents(
|
|
|
65
75
|
});
|
|
66
76
|
}
|
|
67
77
|
function onLeave(e?: FocusEvent | MouseEvent) {
|
|
78
|
+
if (e && !eventBelongsToPicker(e, bodyRef)) return;
|
|
68
79
|
if (e) {
|
|
69
80
|
const relatedTarget = e.relatedTarget as HTMLElement;
|
|
70
81
|
|
|
@@ -76,13 +87,22 @@ export function useEmojiPreviewEvents(
|
|
|
76
87
|
setPreviewEmoji(null);
|
|
77
88
|
}
|
|
78
89
|
function onEscape(e: KeyboardEvent) {
|
|
90
|
+
if (!eventBelongsToPicker(e, bodyRef)) return;
|
|
79
91
|
if (e.key === 'Escape') {
|
|
80
92
|
setPreviewEmoji(null);
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
|
|
96
|
+
function onMouseMove(e: MouseEvent) {
|
|
97
|
+
if (!eventBelongsToPicker(e, bodyRef) || !isMouseDisallowed()) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
allowMouseMove();
|
|
101
|
+
onMouseOver(e);
|
|
102
|
+
}
|
|
103
|
+
|
|
84
104
|
function onMouseOver(e: MouseEvent) {
|
|
85
|
-
if (isMouseDisallowed()) {
|
|
105
|
+
if (!eventBelongsToPicker(e, bodyRef) || isMouseDisallowed()) {
|
|
86
106
|
return;
|
|
87
107
|
}
|
|
88
108
|
|
|
@@ -112,6 +132,7 @@ export function useEmojiPreviewEvents(
|
|
|
112
132
|
// the browser scroll them into view, yanking the scroll position
|
|
113
133
|
// while the user is browsing (see also PR #509).
|
|
114
134
|
if (
|
|
135
|
+
focusOnHover &&
|
|
115
136
|
!isExternalElementFocused() &&
|
|
116
137
|
!isPartiallyBelowFold(button, bodyRef)
|
|
117
138
|
) {
|
|
@@ -130,7 +151,11 @@ export function useEmojiPreviewEvents(
|
|
|
130
151
|
function isExternalElementFocused(): boolean {
|
|
131
152
|
const active = document.activeElement as HTMLElement | null;
|
|
132
153
|
|
|
133
|
-
if (
|
|
154
|
+
if (
|
|
155
|
+
!active ||
|
|
156
|
+
active === document.body ||
|
|
157
|
+
active === document.documentElement
|
|
158
|
+
) {
|
|
134
159
|
return false;
|
|
135
160
|
}
|
|
136
161
|
|
|
@@ -138,11 +163,19 @@ export function useEmojiPreviewEvents(
|
|
|
138
163
|
}
|
|
139
164
|
|
|
140
165
|
return () => {
|
|
141
|
-
bodyRef?.removeEventListener('mouseover', onMouseOver);
|
|
166
|
+
bodyRef?.removeEventListener('mouseover', onMouseOver, true);
|
|
167
|
+
bodyRef?.removeEventListener('mousemove', onMouseMove, true);
|
|
142
168
|
bodyRef?.removeEventListener('mouseout', onLeave);
|
|
143
169
|
bodyRef?.removeEventListener('focus', onEnter, true);
|
|
144
170
|
bodyRef?.removeEventListener('blur', onLeave, true);
|
|
145
171
|
bodyRef?.removeEventListener('keydown', onEscape);
|
|
146
172
|
};
|
|
147
|
-
}, [
|
|
173
|
+
}, [
|
|
174
|
+
BodyRef,
|
|
175
|
+
PickerMainRef,
|
|
176
|
+
focusOnHover,
|
|
177
|
+
setPreviewEmoji,
|
|
178
|
+
isMouseDisallowed,
|
|
179
|
+
allowMouseMove,
|
|
180
|
+
]);
|
|
148
181
|
}
|
|
@@ -2,7 +2,10 @@ import { ReactNode, useEffect } from 'react';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
4
|
import { useBodyRef } from '../components/context/ElementRefContext';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useActiveSkinToneState,
|
|
7
|
+
useRequestNativeProbe,
|
|
8
|
+
} from '../components/context/PickerContext';
|
|
6
9
|
import { ClickableEmoji } from '../components/emoji/Emoji';
|
|
7
10
|
import {
|
|
8
11
|
useEmojiStyleConfig,
|
|
@@ -10,17 +13,20 @@ import {
|
|
|
10
13
|
useLazyLoadEmojisConfig,
|
|
11
14
|
useSkinTonesDisabledConfig,
|
|
12
15
|
} from '../config/useConfig';
|
|
13
|
-
import { DataEmojis } from '../dataUtils/DataTypes';
|
|
16
|
+
import { DataEmoji, DataEmojis } from '../dataUtils/DataTypes';
|
|
14
17
|
import { emojiUnified } from '../dataUtils/emojiUtils';
|
|
18
|
+
import { EmojiStyle } from '../types/exposedTypes';
|
|
15
19
|
import {
|
|
16
20
|
getEmojiPositionStyle,
|
|
17
21
|
shouldVirtualize,
|
|
22
|
+
isJustBelowViewport,
|
|
18
23
|
} from '../virtualization/virtualizationHelpers';
|
|
19
24
|
|
|
20
|
-
import {
|
|
25
|
+
import { preloadEmoji } from './preloadEmoji';
|
|
21
26
|
import { useCategoryHeight } from './useCategoryHeight';
|
|
22
27
|
import { useIsEmojiDisallowed } from './useDisallowedEmojis';
|
|
23
28
|
import { useIsEmojiHidden } from './useIsEmojiHidden';
|
|
29
|
+
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
|
|
24
30
|
|
|
25
31
|
export function useEmojiVirtualization({
|
|
26
32
|
categoryEmojis,
|
|
@@ -28,12 +34,15 @@ export function useEmojiVirtualization({
|
|
|
28
34
|
onHeightReady,
|
|
29
35
|
scrollTop,
|
|
30
36
|
isCategoryVisible,
|
|
37
|
+
positioned,
|
|
31
38
|
}: {
|
|
32
39
|
categoryEmojis: DataEmojis;
|
|
33
40
|
topOffset: number;
|
|
34
41
|
onHeightReady: (height: number) => void;
|
|
35
42
|
scrollTop: number;
|
|
36
43
|
isCategoryVisible: boolean;
|
|
44
|
+
/** Whether topOffset is final; unmeasured sections above shift it. */
|
|
45
|
+
positioned: boolean;
|
|
37
46
|
}) {
|
|
38
47
|
const isEmojiHidden = useIsEmojiHidden();
|
|
39
48
|
const lazyLoadEmojis = useLazyLoadEmojisConfig();
|
|
@@ -43,25 +52,52 @@ export function useEmojiVirtualization({
|
|
|
43
52
|
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
44
53
|
const showVariations = !useSkinTonesDisabledConfig();
|
|
45
54
|
const BodyRef = useBodyRef();
|
|
55
|
+
const requestNativeProbe = useRequestNativeProbe();
|
|
56
|
+
// Native glyphs checked exactly: the cells this pass renders (visible
|
|
57
|
+
// rows plus virtualization's margin rows), nothing else.
|
|
58
|
+
const probe: string[] = [];
|
|
59
|
+
const preloads: DataEmoji[] = [];
|
|
60
|
+
const [committed, setCommitted] = React.useState(false);
|
|
46
61
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
62
|
+
// A section shows each rendered emoji once. Recents can hold the same
|
|
63
|
+
// emoji under two tones (e.g. neutral and medium); the active tone
|
|
64
|
+
// renders both as one identity, which must not be listed or keyed twice.
|
|
65
|
+
const emojisToPush = React.useMemo(() => {
|
|
66
|
+
const rendered = new Set<string>();
|
|
67
|
+
return categoryEmojis.filter((emoji) => {
|
|
68
|
+
const isDisallowed = isEmojiDisallowed(emoji);
|
|
69
|
+
const { hidden } = isEmojiHidden(emoji);
|
|
52
70
|
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
if (hidden || isDisallowed) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const unified = emojiUnified(emoji, activeSkinTone);
|
|
75
|
+
if (rendered.has(unified)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
rendered.add(unified);
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
}, [categoryEmojis, activeSkinTone, isEmojiHidden, isEmojiDisallowed]);
|
|
55
82
|
|
|
56
|
-
const dimensions = useCategoryHeight(
|
|
83
|
+
const dimensions = useCategoryHeight(
|
|
84
|
+
emojisToPush.length,
|
|
85
|
+
isCategoryVisible && positioned,
|
|
86
|
+
);
|
|
57
87
|
|
|
88
|
+
// Guarantee a render even when a hidden picker has no measurement cell.
|
|
89
|
+
// A passive update avoids flushing all observer effects before first paint.
|
|
58
90
|
useEffect(() => {
|
|
91
|
+
if (!dimensions) setCommitted(true);
|
|
92
|
+
}, [dimensions]);
|
|
93
|
+
|
|
94
|
+
useIsomorphicLayoutEffect(() => {
|
|
59
95
|
if (dimensions) {
|
|
60
96
|
onHeightReady(dimensions.categoryHeight);
|
|
61
97
|
}
|
|
62
98
|
}, [dimensions, onHeightReady, emojisToPush.length]);
|
|
63
99
|
|
|
64
|
-
const isVirtualized = (style: { top: number
|
|
100
|
+
const isVirtualized = (style: { top: number } | undefined) =>
|
|
65
101
|
dimensions &&
|
|
66
102
|
BodyRef.current &&
|
|
67
103
|
shouldVirtualize({
|
|
@@ -72,51 +108,75 @@ export function useEmojiVirtualization({
|
|
|
72
108
|
dimensions,
|
|
73
109
|
});
|
|
74
110
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
scrollTop,
|
|
85
|
-
BodyRef.current?.clientHeight ?? 0,
|
|
86
|
-
topOffset,
|
|
87
|
-
style,
|
|
88
|
-
dimensions,
|
|
89
|
-
getEmojiUrl,
|
|
90
|
-
);
|
|
91
|
-
return accumulator;
|
|
92
|
-
}
|
|
111
|
+
const needsPreload = (style: { top: number } | undefined) =>
|
|
112
|
+
emojiStyle !== EmojiStyle.NATIVE &&
|
|
113
|
+
dimensions &&
|
|
114
|
+
style &&
|
|
115
|
+
isJustBelowViewport(
|
|
116
|
+
topOffset + style.top,
|
|
117
|
+
scrollTop + (BodyRef.current?.clientHeight ?? 0),
|
|
118
|
+
dimensions.emojiSize,
|
|
119
|
+
);
|
|
93
120
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
121
|
+
const waitingForLayout =
|
|
122
|
+
(!committed && !dimensions) ||
|
|
123
|
+
((!dimensions || !positioned) && BodyRef.current?.clientWidth);
|
|
98
124
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
125
|
+
// MeasureEmoji supplies geometry before cells are built. Layout-free
|
|
126
|
+
// environments can render after the first commit without measurements.
|
|
127
|
+
const emojis = waitingForLayout
|
|
128
|
+
? []
|
|
129
|
+
: emojisToPush.reduce((accumulator, emoji, index) => {
|
|
130
|
+
const style = getEmojiPositionStyle(dimensions, index);
|
|
131
|
+
|
|
132
|
+
if (isVirtualized(style)) {
|
|
133
|
+
if (needsPreload(style)) preloads.push(emoji);
|
|
134
|
+
return accumulator;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!isCategoryVisible) {
|
|
138
|
+
return accumulator;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const unified = emojiUnified(emoji, activeSkinTone);
|
|
142
|
+
// Wait for layout: an unmeasured pass renders a whole category, and
|
|
143
|
+
// while sections above are unmeasured this one renders off-screen
|
|
144
|
+
// cells as if it were at the top.
|
|
145
|
+
if (dimensions && positioned) probe.push(unified);
|
|
146
|
+
accumulator.push(
|
|
147
|
+
<ClickableEmoji
|
|
148
|
+
showVariations={showVariations}
|
|
149
|
+
key={unified}
|
|
150
|
+
emoji={emoji}
|
|
151
|
+
unified={unified}
|
|
152
|
+
emojiStyle={emojiStyle}
|
|
153
|
+
lazyLoad={lazyLoadEmojis}
|
|
154
|
+
getEmojiUrl={getEmojiUrl}
|
|
155
|
+
style={{
|
|
156
|
+
...style,
|
|
157
|
+
position: 'absolute',
|
|
158
|
+
}}
|
|
159
|
+
index={index}
|
|
160
|
+
// Grid semantics (issue #508): each emoji is a cell of its
|
|
161
|
+
// category row; native button activation is kept.
|
|
162
|
+
role="gridcell"
|
|
163
|
+
/>,
|
|
164
|
+
);
|
|
165
|
+
return accumulator;
|
|
166
|
+
}, [] as ReactNode[]);
|
|
167
|
+
|
|
168
|
+
// Every commit: requests for already-checked glyphs are free.
|
|
169
|
+
useEffect(() => requestNativeProbe(probe));
|
|
170
|
+
// Image requests belong to committed work, never an abandoned render.
|
|
171
|
+
// The proximity and cache checks run synchronously, without per-cell timers.
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
preloads.forEach((emoji) => preloadEmoji(getEmojiUrl, emoji, emojiStyle));
|
|
174
|
+
});
|
|
116
175
|
|
|
117
176
|
return {
|
|
118
|
-
virtualizedCounter,
|
|
177
|
+
virtualizedCounter: emojisToPush.length - emojis.length,
|
|
119
178
|
emojis,
|
|
120
179
|
dimensions,
|
|
180
|
+
emojiCount: emojisToPush.length,
|
|
121
181
|
};
|
|
122
182
|
}
|