emoji-picker-react 4.22.2 → 5.0.0
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 +335 -49
- package/dist/DomUtils/categoryNameFromDom.d.ts +1 -1
- package/dist/DomUtils/classNames.d.ts +24 -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 +7 -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-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-46BUDQLE.mjs +228 -0
- package/dist/esm/chunks/chunk-7ZGTUZFB.mjs +16 -0
- package/dist/esm/chunks/chunk-FQIJ4HBW.mjs +25 -0
- package/dist/esm/chunks/chunk-KQPOIRSC.mjs +9305 -0
- package/dist/esm/chunks/chunk-LO4TPPLH.mjs +43 -0
- package/dist/esm/chunks/emojis-6L3GRBAP.mjs +9 -0
- package/dist/esm/data.mjs +18 -0
- package/dist/esm/index.mjs +389 -0
- package/dist/esm/primitives/index.mjs +67 -0
- package/dist/hooks/preloadEmoji.d.ts +9 -9
- package/dist/hooks/useActiveCategoryScrollDetection.d.ts +11 -11
- package/dist/hooks/useCategoryHeight.d.ts +6 -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 +21 -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 +20 -18
- package/llms-full.txt +3680 -0
- package/llms.txt +66 -476
- package/package.json +204 -66
- package/src/DomUtils/categoryNameFromDom.ts +1 -1
- package/src/DomUtils/classNames.ts +1 -0
- package/src/DomUtils/elementPositionInRow.ts +26 -4
- 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 +105 -149
- package/src/DomUtils/scrollTo.ts +18 -16
- package/src/DomUtils/selectors.ts +20 -111
- 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 +55 -23
- 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 +110 -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 +77 -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 +188 -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-core/pickerData.ts +173 -0
- package/src/data-core/prepare.ts +178 -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 +58 -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/suggested.ts +8 -4
- package/src/dataUtils/suggestedEmojis.ts +92 -0
- package/src/env.d.ts +4 -0
- package/src/hooks/preloadEmoji.ts +3 -3
- package/src/hooks/useActiveCategoryScrollDetection.ts +10 -1
- package/src/hooks/useCategoryHeight.ts +82 -8
- package/src/hooks/useDataIdentityStabilityWarning.ts +86 -0
- package/src/hooks/useDebouncedState.ts +13 -1
- package/src/hooks/useDisallowedEmojis.ts +26 -42
- package/src/hooks/useEmojiPreviewEvents.ts +43 -10
- package/src/hooks/useEmojiVirtualization.tsx +38 -4
- package/src/hooks/useFilter.ts +85 -127
- package/src/hooks/useFocus.ts +14 -24
- package/src/hooks/useIsEmojiHidden.ts +10 -6
- package/src/hooks/useKeyboardNavigation.ts +322 -429
- 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 +133 -0
- package/src/primitives/tokens.ts +149 -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 +20 -6
- 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
|
@@ -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,
|
|
@@ -28,12 +31,15 @@ export function useEmojiVirtualization({
|
|
|
28
31
|
onHeightReady,
|
|
29
32
|
scrollTop,
|
|
30
33
|
isCategoryVisible,
|
|
34
|
+
positioned,
|
|
31
35
|
}: {
|
|
32
36
|
categoryEmojis: DataEmojis;
|
|
33
37
|
topOffset: number;
|
|
34
38
|
onHeightReady: (height: number) => void;
|
|
35
39
|
scrollTop: number;
|
|
36
40
|
isCategoryVisible: boolean;
|
|
41
|
+
/** Whether topOffset is final; unmeasured sections above shift it. */
|
|
42
|
+
positioned: boolean;
|
|
37
43
|
}) {
|
|
38
44
|
const isEmojiHidden = useIsEmojiHidden();
|
|
39
45
|
const lazyLoadEmojis = useLazyLoadEmojisConfig();
|
|
@@ -43,14 +49,30 @@ export function useEmojiVirtualization({
|
|
|
43
49
|
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
44
50
|
const showVariations = !useSkinTonesDisabledConfig();
|
|
45
51
|
const BodyRef = useBodyRef();
|
|
52
|
+
const requestNativeProbe = useRequestNativeProbe();
|
|
53
|
+
// Native glyphs checked exactly: the cells this pass renders (visible
|
|
54
|
+
// rows plus virtualization's margin rows), nothing else.
|
|
55
|
+
const probe: string[] = [];
|
|
46
56
|
|
|
47
57
|
let virtualizedCounter = 0;
|
|
48
58
|
|
|
59
|
+
// A section shows each rendered emoji once. Recents can hold the same
|
|
60
|
+
// emoji under two tones (e.g. neutral and medium); the active tone
|
|
61
|
+
// renders both as one identity, which must not be listed or keyed twice.
|
|
62
|
+
const rendered = new Set<string>();
|
|
49
63
|
const emojisToPush = categoryEmojis.filter((emoji) => {
|
|
50
64
|
const isDisallowed = isEmojiDisallowed(emoji);
|
|
51
|
-
const {
|
|
65
|
+
const { hidden } = isEmojiHidden(emoji);
|
|
52
66
|
|
|
53
|
-
|
|
67
|
+
if (hidden || isDisallowed) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const unified = emojiUnified(emoji, activeSkinTone);
|
|
71
|
+
if (rendered.has(unified)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
rendered.add(unified);
|
|
75
|
+
return true;
|
|
54
76
|
});
|
|
55
77
|
|
|
56
78
|
const dimensions = useCategoryHeight(emojisToPush.length);
|
|
@@ -61,7 +83,7 @@ export function useEmojiVirtualization({
|
|
|
61
83
|
}
|
|
62
84
|
}, [dimensions, onHeightReady, emojisToPush.length]);
|
|
63
85
|
|
|
64
|
-
const isVirtualized = (style: { top: number
|
|
86
|
+
const isVirtualized = (style: { top: number } | undefined) =>
|
|
65
87
|
dimensions &&
|
|
66
88
|
BodyRef.current &&
|
|
67
89
|
shouldVirtualize({
|
|
@@ -96,6 +118,10 @@ export function useEmojiVirtualization({
|
|
|
96
118
|
return accumulator;
|
|
97
119
|
}
|
|
98
120
|
|
|
121
|
+
// Wait for layout: an unmeasured pass renders a whole category, and
|
|
122
|
+
// while sections above are unmeasured this one renders off-screen
|
|
123
|
+
// cells as if it were at the top.
|
|
124
|
+
if (dimensions && positioned) probe.push(unified);
|
|
99
125
|
accumulator.push(
|
|
100
126
|
<ClickableEmoji
|
|
101
127
|
showVariations={showVariations}
|
|
@@ -109,14 +135,22 @@ export function useEmojiVirtualization({
|
|
|
109
135
|
...style,
|
|
110
136
|
position: 'absolute',
|
|
111
137
|
}}
|
|
138
|
+
index={index}
|
|
139
|
+
// Grid semantics (issue #508): each emoji is a cell of its
|
|
140
|
+
// category row; native button activation is kept.
|
|
141
|
+
role="gridcell"
|
|
112
142
|
/>,
|
|
113
143
|
);
|
|
114
144
|
return accumulator;
|
|
115
145
|
}, [] as ReactNode[]);
|
|
116
146
|
|
|
147
|
+
// Every commit: requests for already-checked glyphs are free.
|
|
148
|
+
useEffect(() => requestNativeProbe(probe));
|
|
149
|
+
|
|
117
150
|
return {
|
|
118
151
|
virtualizedCounter,
|
|
119
152
|
emojis,
|
|
120
153
|
dimensions,
|
|
154
|
+
emojiCount: emojisToPush.length,
|
|
121
155
|
};
|
|
122
156
|
}
|
package/src/hooks/useFilter.ts
CHANGED
|
@@ -1,143 +1,116 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
1
3
|
import { scrollTo } from '../DomUtils/scrollTo';
|
|
2
|
-
import {
|
|
3
|
-
usePickerMainRef,
|
|
4
|
-
useSearchInputRef,
|
|
5
|
-
} from '../components/context/ElementRefContext';
|
|
4
|
+
import { usePickerMainRef } from '../components/context/ElementRefContext';
|
|
6
5
|
import {
|
|
7
6
|
FilterState,
|
|
7
|
+
useFilterQueryOrderRef,
|
|
8
8
|
useFilterRef,
|
|
9
|
+
useNavigationRegistry,
|
|
9
10
|
useSearchTermState,
|
|
10
11
|
} from '../components/context/PickerContext';
|
|
11
|
-
import {
|
|
12
|
+
import { usePickerDataContext } from '../components/context/PickerDataContext';
|
|
13
|
+
import { normalizeQuery } from '../data-core/prepare';
|
|
12
14
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
13
15
|
import { emojiNames } from '../dataUtils/emojiUtils';
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Bound on cached per-query filter dicts per Root. Dicts are cheaply
|
|
19
|
+
* rebuilt from the shared memoized core, so a long typing session keeps
|
|
20
|
+
* only a recent window instead of growing without bound.
|
|
21
|
+
*/
|
|
22
|
+
const MAX_FILTER_QUERIES = 50;
|
|
16
23
|
|
|
17
24
|
function useSetFilterRef() {
|
|
18
25
|
const filterRef = useFilterRef();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
const orderRef = useFilterQueryOrderRef();
|
|
27
|
+
|
|
28
|
+
return function setFilter(nextValue: string, dict: FilterDict): void {
|
|
29
|
+
// Copy-on-write into a fresh object: the ref never aliases shared
|
|
30
|
+
// snapshot state, and spread defines own properties (no prototype
|
|
31
|
+
// mutation for adversarial queries such as "__proto__").
|
|
32
|
+
const next: FilterState = { ...filterRef.current, [nextValue]: dict };
|
|
33
|
+
const order = orderRef.current;
|
|
34
|
+
if (!order.includes(nextValue)) {
|
|
35
|
+
order.push(nextValue);
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function useClearSearch() {
|
|
32
|
-
const applySearch = useApplySearch();
|
|
33
|
-
const SearchInputRef = useSearchInputRef();
|
|
34
|
-
const focusSearchInput = useFocusSearchInput();
|
|
35
|
-
|
|
36
|
-
return function clearSearch() {
|
|
37
|
-
if (SearchInputRef.current) {
|
|
38
|
-
SearchInputRef.current.value = '';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
applySearch('');
|
|
42
|
-
focusSearchInput();
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function useAppendSearch() {
|
|
47
|
-
const SearchInputRef = useSearchInputRef();
|
|
48
|
-
const applySearch = useApplySearch();
|
|
49
|
-
|
|
50
|
-
return function appendSearch(str: string) {
|
|
51
|
-
if (SearchInputRef.current) {
|
|
52
|
-
SearchInputRef.current.value = `${SearchInputRef.current.value}${str}`;
|
|
53
|
-
applySearch(getNormalizedSearchTerm(SearchInputRef.current.value));
|
|
54
|
-
} else {
|
|
55
|
-
applySearch(getNormalizedSearchTerm(str));
|
|
37
|
+
while (order.length > MAX_FILTER_QUERIES) {
|
|
38
|
+
const oldest = order.shift() as string;
|
|
39
|
+
delete next[oldest];
|
|
56
40
|
}
|
|
41
|
+
filterRef.current = next;
|
|
57
42
|
};
|
|
58
43
|
}
|
|
59
44
|
|
|
60
45
|
export function useFilter() {
|
|
61
|
-
const SearchInputRef = useSearchInputRef();
|
|
62
46
|
const filterRef = useFilterRef();
|
|
63
47
|
const setFilterRef = useSetFilterRef();
|
|
64
48
|
const applySearch = useApplySearch();
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
filterRef.current,
|
|
69
|
-
searchTerm,
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
onChange,
|
|
74
|
-
searchTerm,
|
|
75
|
-
SearchInputRef,
|
|
76
|
-
statusSearchResults,
|
|
77
|
-
};
|
|
49
|
+
const { queryFilterDict } = usePickerDataContext();
|
|
50
|
+
// Managed SearchInput owns announcements; this hook only applies filters.
|
|
51
|
+
return { onChange };
|
|
78
52
|
|
|
79
53
|
function onChange(inputValue: string) {
|
|
80
54
|
const filter = filterRef.current;
|
|
81
55
|
|
|
82
|
-
|
|
56
|
+
// Normalized derived query: the visible/callback value
|
|
57
|
+
// stays raw, filtering folds case and trims surrounding whitespace.
|
|
58
|
+
// Matching itself runs in the single shared prepared core.
|
|
59
|
+
const nextValue = normalizeQuery(inputValue);
|
|
83
60
|
|
|
84
|
-
if (
|
|
61
|
+
if (!nextValue) {
|
|
85
62
|
return applySearch(nextValue);
|
|
86
63
|
}
|
|
87
|
-
|
|
88
|
-
const longestMatch = findLongestMatch(nextValue, filter);
|
|
89
|
-
|
|
90
|
-
if (!longestMatch) {
|
|
91
|
-
// Can we even get here?
|
|
92
|
-
// If so, we need to search among all emojis
|
|
64
|
+
if (hasOwnQuery(filter, nextValue)) {
|
|
93
65
|
return applySearch(nextValue);
|
|
94
66
|
}
|
|
95
67
|
|
|
96
|
-
setFilterRef((
|
|
97
|
-
Object.assign(current, {
|
|
98
|
-
[nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue),
|
|
99
|
-
}),
|
|
100
|
-
);
|
|
68
|
+
setFilterRef(nextValue, queryFilterDict(nextValue));
|
|
101
69
|
applySearch(nextValue);
|
|
102
70
|
}
|
|
103
71
|
}
|
|
104
72
|
|
|
73
|
+
function hasOwnQuery(filter: FilterState, query: string): boolean {
|
|
74
|
+
return Object.prototype.hasOwnProperty.call(filter, query);
|
|
75
|
+
}
|
|
76
|
+
|
|
105
77
|
function useApplySearch() {
|
|
106
78
|
const [, setSearchTerm] = useSearchTermState();
|
|
107
79
|
const PickerMainRef = usePickerMainRef();
|
|
80
|
+
const registry = useNavigationRegistry();
|
|
81
|
+
// A search frame pending at unmount must not schedule post-unmount
|
|
82
|
+
// debounce work (the debounced state also clears its own timer, so
|
|
83
|
+
// both stages of the pipeline die with the Root).
|
|
84
|
+
const mountedRef = React.useRef(true);
|
|
85
|
+
React.useEffect(() => {
|
|
86
|
+
mountedRef.current = true;
|
|
87
|
+
return () => {
|
|
88
|
+
mountedRef.current = false;
|
|
89
|
+
};
|
|
90
|
+
}, []);
|
|
108
91
|
|
|
109
92
|
return function applySearch(searchTerm: string) {
|
|
93
|
+
// A new accepted filter obsoletes pending grid materialize/focus work.
|
|
94
|
+
registry.invalidate();
|
|
95
|
+
// The scroll back to the top lands after the debounce; navigation in
|
|
96
|
+
// the meantime (e.g. a category tab clicked right after clearing the
|
|
97
|
+
// search) supersedes it instead of being yanked back to the top.
|
|
98
|
+
const token = registry.currentGeneration();
|
|
110
99
|
requestAnimationFrame(() => {
|
|
100
|
+
if (!mountedRef.current) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
111
103
|
setSearchTerm(searchTerm ? searchTerm?.toLowerCase() : searchTerm).then(
|
|
112
104
|
() => {
|
|
113
|
-
|
|
105
|
+
if (registry.isCurrent(token)) {
|
|
106
|
+
scrollTo(PickerMainRef.current, 0, () => registry.isCurrent(token));
|
|
107
|
+
}
|
|
114
108
|
},
|
|
115
109
|
);
|
|
116
110
|
});
|
|
117
111
|
};
|
|
118
112
|
}
|
|
119
113
|
|
|
120
|
-
export function filterEmojiObjectByKeyword(
|
|
121
|
-
emojis: FilterDict,
|
|
122
|
-
keyword: string,
|
|
123
|
-
): FilterDict {
|
|
124
|
-
const filtered: FilterDict = {};
|
|
125
|
-
|
|
126
|
-
for (const unified in emojis) {
|
|
127
|
-
const emoji = emojis[unified];
|
|
128
|
-
|
|
129
|
-
if (hasMatch(emoji, keyword)) {
|
|
130
|
-
filtered[unified] = emoji;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return filtered;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function hasMatch(emoji: DataEmoji, keyword: string): boolean {
|
|
138
|
-
return emojiNames(emoji).some((name) => name.includes(keyword));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
114
|
export function useIsEmojiFiltered(): (unified: string) => boolean {
|
|
142
115
|
const { current: filter } = useFilterRef();
|
|
143
116
|
const [searchTerm] = useSearchTermState();
|
|
@@ -159,45 +132,30 @@ export function isEmojiFilteredBySearchTerm(
|
|
|
159
132
|
|
|
160
133
|
export type FilterDict = Record<string, DataEmoji>;
|
|
161
134
|
|
|
135
|
+
export function filterEmojiObjectByKeyword(
|
|
136
|
+
emojis: FilterDict,
|
|
137
|
+
keyword: string,
|
|
138
|
+
): FilterDict {
|
|
139
|
+
const filtered: FilterDict = {};
|
|
140
|
+
Object.keys(emojis).forEach((unified) => {
|
|
141
|
+
const emoji = emojis[unified];
|
|
142
|
+
if (
|
|
143
|
+
emojiNames(emoji).some((name) => name.toLowerCase().includes(keyword))
|
|
144
|
+
) {
|
|
145
|
+
filtered[unified] = emoji;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return filtered;
|
|
149
|
+
}
|
|
150
|
+
|
|
162
151
|
export function findLongestMatch(
|
|
163
152
|
keyword: string,
|
|
164
153
|
dict: Record<string, FilterDict> | null,
|
|
165
154
|
): FilterDict | null {
|
|
166
|
-
if (!dict)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (dict[keyword]) {
|
|
171
|
-
return dict[keyword];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const longestMatchingKey = Object.keys(dict)
|
|
175
|
-
.sort((a, b) => b.length - a.length)
|
|
155
|
+
if (!dict) return null;
|
|
156
|
+
if (dict[keyword]) return dict[keyword];
|
|
157
|
+
const longest = Object.keys(dict)
|
|
158
|
+
.sort((left, right) => right.length - left.length)
|
|
176
159
|
.find((key) => keyword.includes(key));
|
|
177
|
-
|
|
178
|
-
if (longestMatchingKey) {
|
|
179
|
-
return dict[longestMatchingKey];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export function getNormalizedSearchTerm(str: string): string {
|
|
186
|
-
if (!str || typeof str !== 'string') {
|
|
187
|
-
return '';
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return str.trim().toLowerCase();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function getStatusSearchResults(
|
|
194
|
-
filterState: FilterState,
|
|
195
|
-
searchTerm: string,
|
|
196
|
-
): string {
|
|
197
|
-
if (!filterState?.[searchTerm]) return '';
|
|
198
|
-
|
|
199
|
-
const searchResultsCount =
|
|
200
|
-
Object.entries(filterState?.[searchTerm])?.length || 0;
|
|
201
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
202
|
-
return useSearchResultsConfig(searchResultsCount);
|
|
160
|
+
return longest ? dict[longest] : null;
|
|
203
161
|
}
|
package/src/hooks/useFocus.ts
CHANGED
|
@@ -1,40 +1,30 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
|
|
3
|
-
import { focusElement
|
|
3
|
+
import { focusElement } from '../DomUtils/focusElement';
|
|
4
|
+
import { NullableElement } from '../DomUtils/selectors';
|
|
4
5
|
import {
|
|
6
|
+
ElementRef,
|
|
5
7
|
useCategoryNavigationRef,
|
|
6
8
|
useSearchInputRef,
|
|
7
9
|
useSkinTonePickerRef,
|
|
8
10
|
} from '../components/context/ElementRefContext';
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
const SearchInputRef = useSearchInputRef();
|
|
12
|
-
|
|
12
|
+
function useFocusRef(ref: ElementRef, child = false) {
|
|
13
13
|
return useCallback(() => {
|
|
14
|
-
focusElement(
|
|
15
|
-
|
|
14
|
+
focusElement(
|
|
15
|
+
(child ? ref.current?.firstElementChild : ref.current) as NullableElement,
|
|
16
|
+
);
|
|
17
|
+
}, [ref, child]);
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
export function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return useCallback(() => {
|
|
22
|
-
if (!SkinTonePickerRef.current) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
20
|
+
export function useFocusSearchInput() {
|
|
21
|
+
return useFocusRef(useSearchInputRef());
|
|
22
|
+
}
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
export function useFocusSkinTonePicker() {
|
|
25
|
+
return useFocusRef(useSkinTonePickerRef(), true);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
export function useFocusCategoryNavigation() {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return useCallback(() => {
|
|
34
|
-
if (!CategoryNavigationRef.current) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
focusFirstElementChild(CategoryNavigationRef.current);
|
|
39
|
-
}, [CategoryNavigationRef]);
|
|
29
|
+
return useFocusRef(useCategoryNavigationRef(), true);
|
|
40
30
|
}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useActiveSkinToneState,
|
|
3
|
+
useEmojisThatFailedToLoadState,
|
|
4
|
+
} from '../components/context/PickerContext';
|
|
2
5
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
3
|
-
import { emojiUnified } from '../dataUtils/emojiUtils';
|
|
6
|
+
import { emojiUnified, emojiCanonicalUnified } from '../dataUtils/emojiUtils';
|
|
4
7
|
|
|
5
8
|
import { useIsEmojiFiltered } from './useFilter';
|
|
6
9
|
|
|
7
10
|
export function useIsEmojiHidden(): (emoji: DataEmoji) => IsHiddenReturn {
|
|
11
|
+
const [activeSkinTone] = useActiveSkinToneState();
|
|
8
12
|
const [emojisThatFailedToLoad] = useEmojisThatFailedToLoadState();
|
|
9
13
|
const isEmojiFiltered = useIsEmojiFiltered();
|
|
10
14
|
|
|
11
15
|
return (emoji: DataEmoji): IsHiddenReturn => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const filteredOut = isEmojiFiltered(
|
|
16
|
+
const failedToLoad = emojisThatFailedToLoad.has(
|
|
17
|
+
emojiUnified(emoji, activeSkinTone),
|
|
18
|
+
);
|
|
19
|
+
const filteredOut = isEmojiFiltered(emojiCanonicalUnified(emoji));
|
|
16
20
|
|
|
17
21
|
return {
|
|
18
22
|
failedToLoad,
|