emoji-picker-react 4.22.3 → 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 +331 -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 -480
- package/package.json +180 -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
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import { useCallback, useEffect,
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { eventBelongsToPicker } from '../DomUtils/eventBelongsToPicker';
|
|
4
4
|
import {
|
|
5
5
|
focusElement,
|
|
6
6
|
focusNextElementSibling,
|
|
7
7
|
focusPrevElementSibling,
|
|
8
8
|
} from '../DomUtils/focusElement';
|
|
9
9
|
import { getActiveElement } from '../DomUtils/getActiveElement';
|
|
10
|
+
import { isRtl } from '../DomUtils/isRtl';
|
|
10
11
|
import {
|
|
11
12
|
focusAndClickFirstVisibleEmoji,
|
|
12
13
|
focusFirstVisibleEmoji,
|
|
13
|
-
|
|
14
|
-
focusPrevVisibleEmoji,
|
|
15
|
-
focusVisibleEmojiOneRowDown,
|
|
16
|
-
focusVisibleEmojiOneRowUp,
|
|
14
|
+
focusAdjacentEmoji,
|
|
17
15
|
} from '../DomUtils/keyboardNavigation';
|
|
18
16
|
import { useScrollTo } from '../DomUtils/scrollTo';
|
|
19
17
|
import { buttonFromTarget } from '../DomUtils/selectors';
|
|
20
18
|
import {
|
|
19
|
+
ElementRef,
|
|
21
20
|
useBodyRef,
|
|
22
21
|
useCategoryNavigationRef,
|
|
23
22
|
usePickerMainRef,
|
|
@@ -26,358 +25,285 @@ import {
|
|
|
26
25
|
useSkinTonePickerRef,
|
|
27
26
|
} from '../components/context/ElementRefContext';
|
|
28
27
|
import {
|
|
29
|
-
|
|
28
|
+
useNavigationRegistry,
|
|
29
|
+
useSearchComposingState,
|
|
30
30
|
useSkinToneFanOpenState,
|
|
31
31
|
} from '../components/context/PickerContext';
|
|
32
32
|
import { useSearchDisabledConfig } from '../config/useConfig';
|
|
33
|
+
import {
|
|
34
|
+
NavigationRegionKind,
|
|
35
|
+
RegisteredRegion,
|
|
36
|
+
} from '../state/navigationRegistry';
|
|
37
|
+
import { getNextRegion, getPrevRegion } from '../state/regionTraversal';
|
|
33
38
|
|
|
34
39
|
import {
|
|
35
40
|
useCloseAllOpenToggles,
|
|
36
41
|
useHasOpenToggles,
|
|
37
42
|
} from './useCloseAllOpenToggles';
|
|
38
43
|
import { useDisallowMouseMove } from './useDisallowMouseMove';
|
|
39
|
-
import { useAppendSearch, useClearSearch } from './useFilter';
|
|
40
44
|
import {
|
|
41
45
|
useFocusCategoryNavigation,
|
|
42
46
|
useFocusSearchInput,
|
|
43
47
|
useFocusSkinTonePicker,
|
|
44
48
|
} from './useFocus';
|
|
45
49
|
import useIsSearchMode from './useIsSearchMode';
|
|
50
|
+
import { useClearSearchValue, useTypeToSearchKey } from './useSearchController';
|
|
46
51
|
import useSetVariationPicker from './useSetVariationPicker';
|
|
47
|
-
import {
|
|
48
|
-
useIsSkinToneInPreview,
|
|
49
|
-
useIsSkinToneInSearch,
|
|
50
|
-
} from './useShouldShowSkinTonePicker';
|
|
51
|
-
|
|
52
|
-
enum KeyboardEvents {
|
|
53
|
-
ArrowDown = 'ArrowDown',
|
|
54
|
-
ArrowUp = 'ArrowUp',
|
|
55
|
-
ArrowLeft = 'ArrowLeft',
|
|
56
|
-
ArrowRight = 'ArrowRight',
|
|
57
|
-
Escape = 'Escape',
|
|
58
|
-
Enter = 'Enter',
|
|
59
|
-
Space = ' ',
|
|
60
|
-
}
|
|
61
52
|
|
|
62
53
|
export function useKeyboardNavigation() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
useCategoryNavigationKeyboardEvents();
|
|
67
|
-
useReactionsKeyboardEvents();
|
|
68
|
-
useBodyKeyboardEvents();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function usePickerMainKeyboardEvents() {
|
|
72
|
-
const PickerMainRef = usePickerMainRef();
|
|
73
|
-
const clearSearch = useClearSearch();
|
|
54
|
+
const ref = usePickerMainRef();
|
|
55
|
+
const hasOpenToggles = useHasOpenToggles();
|
|
56
|
+
const clearSearch = useClearSearchValue();
|
|
74
57
|
const scrollTo = useScrollTo();
|
|
75
|
-
const SearchInputRef = useSearchInputRef();
|
|
76
58
|
const focusSearchInput = useFocusSearchInput();
|
|
77
|
-
const hasOpenToggles = useHasOpenToggles();
|
|
78
59
|
const disallowMouseMove = useDisallowMouseMove();
|
|
79
|
-
|
|
80
60
|
const closeAllOpenToggles = useCloseAllOpenToggles();
|
|
81
|
-
|
|
82
|
-
const onKeyDown = useMemo(
|
|
83
|
-
() =>
|
|
84
|
-
function onKeyDown(event: KeyboardEvent) {
|
|
85
|
-
const { key } = event;
|
|
86
|
-
|
|
87
|
-
disallowMouseMove();
|
|
88
|
-
switch (key) {
|
|
89
|
-
// eslint-disable-next-line no-fallthrough
|
|
90
|
-
case KeyboardEvents.Escape:
|
|
91
|
-
event.preventDefault();
|
|
92
|
-
if (hasOpenToggles()) {
|
|
93
|
-
closeAllOpenToggles();
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
clearSearch();
|
|
97
|
-
scrollTo(0);
|
|
98
|
-
focusSearchInput();
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
[
|
|
103
|
-
scrollTo,
|
|
104
|
-
clearSearch,
|
|
105
|
-
closeAllOpenToggles,
|
|
106
|
-
focusSearchInput,
|
|
107
|
-
hasOpenToggles,
|
|
108
|
-
disallowMouseMove,
|
|
109
|
-
],
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
const current = PickerMainRef.current;
|
|
114
|
-
|
|
115
|
-
if (!current) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
current.addEventListener('keydown', onKeyDown);
|
|
120
|
-
|
|
121
|
-
return () => {
|
|
122
|
-
current.removeEventListener('keydown', onKeyDown);
|
|
123
|
-
};
|
|
124
|
-
}, [PickerMainRef, SearchInputRef, scrollTo, onKeyDown]);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function useSearchInputKeyboardEvents() {
|
|
128
61
|
const focusSkinTonePicker = useFocusSkinTonePicker();
|
|
129
|
-
const PickerMainRef = usePickerMainRef();
|
|
130
62
|
const BodyRef = useBodyRef();
|
|
131
63
|
const SearchInputRef = useSearchInputRef();
|
|
132
|
-
const [, setSkinToneFanOpenState] = useSkinToneFanOpenState();
|
|
133
|
-
const goDownFromSearchInput = useGoDownFromSearchInput();
|
|
134
|
-
const isSkinToneInSearch = useIsSkinToneInSearch();
|
|
135
|
-
|
|
136
|
-
const onKeyDown = useMemo(
|
|
137
|
-
() =>
|
|
138
|
-
function onKeyDown(event: KeyboardEvent) {
|
|
139
|
-
const { key } = event;
|
|
140
|
-
|
|
141
|
-
switch (key) {
|
|
142
|
-
case KeyboardEvents.ArrowRight:
|
|
143
|
-
if (!isSkinToneInSearch) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
event.preventDefault();
|
|
147
|
-
setSkinToneFanOpenState(true);
|
|
148
|
-
focusSkinTonePicker();
|
|
149
|
-
break;
|
|
150
|
-
case KeyboardEvents.ArrowDown:
|
|
151
|
-
event.preventDefault();
|
|
152
|
-
goDownFromSearchInput();
|
|
153
|
-
break;
|
|
154
|
-
case KeyboardEvents.Enter:
|
|
155
|
-
event.preventDefault();
|
|
156
|
-
focusAndClickFirstVisibleEmoji(BodyRef.current);
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
[
|
|
161
|
-
focusSkinTonePicker,
|
|
162
|
-
goDownFromSearchInput,
|
|
163
|
-
setSkinToneFanOpenState,
|
|
164
|
-
BodyRef,
|
|
165
|
-
isSkinToneInSearch,
|
|
166
|
-
],
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
useEffect(() => {
|
|
170
|
-
const current = SearchInputRef.current;
|
|
171
|
-
|
|
172
|
-
if (!current) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
current.addEventListener('keydown', onKeyDown);
|
|
177
|
-
|
|
178
|
-
return () => {
|
|
179
|
-
current.removeEventListener('keydown', onKeyDown);
|
|
180
|
-
};
|
|
181
|
-
}, [PickerMainRef, SearchInputRef, onKeyDown]);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function useSkinTonePickerKeyboardEvents() {
|
|
185
|
-
const SkinTonePickerRef = useSkinTonePickerRef();
|
|
186
|
-
const focusSearchInput = useFocusSearchInput();
|
|
187
|
-
const SearchInputRef = useSearchInputRef();
|
|
188
|
-
const goDownFromSearchInput = useGoDownFromSearchInput();
|
|
189
64
|
const [isOpen, setIsOpen] = useSkinToneFanOpenState();
|
|
190
|
-
const
|
|
191
|
-
const
|
|
65
|
+
const focusCategoryNavigation = useFocusCategoryNavigation();
|
|
66
|
+
const focusNextRegionFromSearch = useFocusNextRegionFrom('search');
|
|
67
|
+
const isSearchMode = useIsSearchMode();
|
|
68
|
+
const SkinTonePickerRef = useSkinTonePickerRef();
|
|
69
|
+
const isSkinToneInSearch = () =>
|
|
70
|
+
!!SkinTonePickerRef.current?.closest('[data-epr-part="search"]');
|
|
192
71
|
const onType = useOnType();
|
|
72
|
+
const CategoryNavigationRef = useCategoryNavigationRef();
|
|
73
|
+
const focusPrevRegionFromCategories = useFocusPrevRegionFrom('categories');
|
|
74
|
+
const focusNextRegionFromCategories = useFocusNextRegionFrom('categories');
|
|
75
|
+
const ReactionsRef = useReactionsRef();
|
|
76
|
+
const focusPrevRegionFromGrid = useFocusPrevRegionFrom('grid');
|
|
77
|
+
const setVariationPicker = useSetVariationPicker();
|
|
78
|
+
const registry = useNavigationRegistry();
|
|
79
|
+
const goDownFromSearchInput = () => {
|
|
80
|
+
if (isSearchMode) return focusFirstVisibleEmoji(BodyRef.current);
|
|
81
|
+
focusCategoryNavigation();
|
|
82
|
+
};
|
|
83
|
+
const goUpFromBody = () => {
|
|
84
|
+
if (isSearchMode) return focusSearchInput();
|
|
85
|
+
focusPrevRegionFromGrid(focusCategoryNavigation);
|
|
86
|
+
};
|
|
87
|
+
const main = function onKeyDown(event: KeyboardEvent) {
|
|
88
|
+
const { key } = event;
|
|
193
89
|
|
|
194
|
-
|
|
195
|
-
()
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (!isOpen) {
|
|
205
|
-
return focusSearchInput();
|
|
206
|
-
}
|
|
207
|
-
focusNextSkinTone(focusSearchInput);
|
|
208
|
-
break;
|
|
209
|
-
case KeyboardEvents.ArrowRight:
|
|
210
|
-
event.preventDefault();
|
|
211
|
-
if (!isOpen) {
|
|
212
|
-
return focusSearchInput();
|
|
213
|
-
}
|
|
214
|
-
focusPrevSkinTone();
|
|
215
|
-
break;
|
|
216
|
-
case KeyboardEvents.ArrowDown:
|
|
217
|
-
event.preventDefault();
|
|
218
|
-
if (isOpen) {
|
|
219
|
-
setIsOpen(false);
|
|
220
|
-
}
|
|
221
|
-
goDownFromSearchInput();
|
|
222
|
-
break;
|
|
223
|
-
default:
|
|
224
|
-
onType(event);
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
90
|
+
disallowMouseMove();
|
|
91
|
+
switch (key) {
|
|
92
|
+
case 'Escape':
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
if (hasOpenToggles()) {
|
|
95
|
+
closeAllOpenToggles();
|
|
96
|
+
// A nested variation/tone menu consumes Escape before the
|
|
97
|
+
// host popover or autocomplete dismisses the whole picker.
|
|
98
|
+
event.stopPropagation();
|
|
99
|
+
return;
|
|
227
100
|
}
|
|
101
|
+
clearSearch();
|
|
102
|
+
scrollTo(0);
|
|
103
|
+
focusSearchInput();
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const search = function onKeyDown(event: KeyboardEvent) {
|
|
108
|
+
if (!eventInRegion(event, SearchInputRef)) return;
|
|
109
|
+
const key = logicalArrowKey(event, SearchInputRef.current);
|
|
228
110
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (!isOpen) {
|
|
234
|
-
return focusSearchInput();
|
|
235
|
-
}
|
|
236
|
-
focusNextSkinTone(focusSearchInput);
|
|
237
|
-
break;
|
|
238
|
-
case KeyboardEvents.ArrowDown:
|
|
239
|
-
event.preventDefault();
|
|
240
|
-
if (!isOpen) {
|
|
241
|
-
return focusSearchInput();
|
|
242
|
-
}
|
|
243
|
-
focusPrevSkinTone();
|
|
244
|
-
break;
|
|
245
|
-
default:
|
|
246
|
-
onType(event);
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
111
|
+
switch (key) {
|
|
112
|
+
case 'ArrowRight':
|
|
113
|
+
if (!isSkinToneInSearch()) {
|
|
114
|
+
return;
|
|
249
115
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
setIsOpen(true);
|
|
118
|
+
focusSkinTonePicker();
|
|
119
|
+
break;
|
|
120
|
+
case 'ArrowDown':
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
// The active-search Search↔Grid exception
|
|
123
|
+
// wins over generic DOM-order traversal.
|
|
124
|
+
if (isSearchMode) {
|
|
125
|
+
goDownFromSearchInput();
|
|
126
|
+
} else {
|
|
127
|
+
focusNextRegionFromSearch(goDownFromSearchInput);
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
case 'Enter':
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
focusAndClickFirstVisibleEmoji(BodyRef.current);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const tone = function onKeyDown(event: KeyboardEvent) {
|
|
137
|
+
if (!eventInRegion(event, SkinTonePickerRef)) return;
|
|
138
|
+
const key = logicalArrowKey(event, SkinTonePickerRef.current);
|
|
139
|
+
// The fan axis decides the arrow keys: the search placement and a
|
|
140
|
+
// horizontal SkinTone primitive move left/right, the preview
|
|
141
|
+
// placement and a vertical primitive move up/down.
|
|
142
|
+
const vertical =
|
|
143
|
+
SkinTonePickerRef.current?.getAttribute('data-epr-direction') ===
|
|
144
|
+
'vertical';
|
|
145
|
+
|
|
146
|
+
switch (key) {
|
|
147
|
+
case vertical ? 'ArrowUp' : 'ArrowLeft':
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
if (!isOpen) return focusSearchInput();
|
|
150
|
+
focusNextSkinTone(focusSearchInput);
|
|
151
|
+
break;
|
|
152
|
+
case vertical ? 'ArrowDown' : 'ArrowRight':
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
if (!isOpen) return focusSearchInput();
|
|
155
|
+
focusPrevElementSibling(getActiveElement());
|
|
156
|
+
break;
|
|
157
|
+
case 'ArrowDown':
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
setIsOpen(false);
|
|
160
|
+
goDownFromSearchInput();
|
|
161
|
+
break;
|
|
162
|
+
default:
|
|
163
|
+
onType(event);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const categories = function onKeyDown(event: KeyboardEvent) {
|
|
167
|
+
if (!eventInRegion(event, CategoryNavigationRef)) return;
|
|
168
|
+
// Arrows along the tab axis move between tabs; arrows across it
|
|
169
|
+
// leave for the previous/next region. A vertical tablist (e.g. a
|
|
170
|
+
// side rail) therefore uses Up/Down for tabs, per the ARIA tabs
|
|
171
|
+
// pattern, and Left/Right to leave.
|
|
172
|
+
const vertical =
|
|
173
|
+
CategoryNavigationRef.current?.getAttribute('aria-orientation') ===
|
|
174
|
+
'vertical';
|
|
175
|
+
const key = logicalArrowKey(event, CategoryNavigationRef.current);
|
|
176
|
+
const direction = reactionFocusDelta(key);
|
|
177
|
+
|
|
178
|
+
if (!direction) {
|
|
179
|
+
onType(event);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
event.preventDefault();
|
|
183
|
+
if (vertical === (key === 'ArrowUp' || key === 'ArrowDown')) {
|
|
184
|
+
const focusSibling =
|
|
185
|
+
direction > 0 ? focusNextElementSibling : focusPrevElementSibling;
|
|
186
|
+
focusSibling(getActiveElement());
|
|
187
|
+
} else if (direction < 0) {
|
|
188
|
+
focusPrevRegionFromCategories(focusSearchInput);
|
|
189
|
+
} else {
|
|
190
|
+
focusNextRegionFromCategories(() =>
|
|
191
|
+
focusFirstVisibleEmoji(BodyRef.current),
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const reactions = function onKeyDown(event: KeyboardEvent) {
|
|
196
|
+
if (!eventInRegion(event, ReactionsRef)) return;
|
|
197
|
+
const key = logicalArrowKey(event, ReactionsRef.current);
|
|
198
|
+
const current = ReactionsRef.current;
|
|
264
199
|
|
|
265
200
|
if (!current) {
|
|
266
201
|
return;
|
|
267
202
|
}
|
|
268
203
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return () => {
|
|
272
|
-
current.removeEventListener('keydown', onKeyDown);
|
|
273
|
-
};
|
|
274
|
-
}, [SkinTonePickerRef, SearchInputRef, isOpen, onKeyDown]);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function useCategoryNavigationKeyboardEvents() {
|
|
278
|
-
const focusSearchInput = useFocusSearchInput();
|
|
279
|
-
const CategoryNavigationRef = useCategoryNavigationRef();
|
|
280
|
-
const BodyRef = useBodyRef();
|
|
281
|
-
const onType = useOnType();
|
|
204
|
+
const delta = reactionFocusDelta(key);
|
|
282
205
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
206
|
+
if (delta !== 0 && focusReactionSibling(current, delta)) {
|
|
207
|
+
event.preventDefault();
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const body = function onKeyDown(event: KeyboardEvent) {
|
|
211
|
+
if (!eventInRegion(event, BodyRef)) return;
|
|
212
|
+
const key = logicalArrowKey(event, BodyRef.current);
|
|
213
|
+
|
|
214
|
+
const activeElement = buttonFromTarget(event.target as HTMLElement);
|
|
215
|
+
// Consumer controls own editing and activation; only managed emoji
|
|
216
|
+
// buttons issue grid commands.
|
|
217
|
+
if (!activeElement) return;
|
|
218
|
+
|
|
219
|
+
// Navigation-generation guard: a pending
|
|
220
|
+
// materialize/scroll/focus completion aborts when search, data,
|
|
221
|
+
// geometry, or reactions state changed underneath it.
|
|
222
|
+
const generation = registry.currentGeneration();
|
|
223
|
+
const focusGuard = () => registry.isCurrent(generation);
|
|
224
|
+
|
|
225
|
+
const direction = reactionFocusDelta(key);
|
|
226
|
+
if (direction) {
|
|
227
|
+
event.preventDefault();
|
|
228
|
+
const row = key === 'ArrowDown' || key === 'ArrowUp';
|
|
229
|
+
if (row && hasOpenToggles()) closeAllOpenToggles();
|
|
230
|
+
else
|
|
231
|
+
focusAdjacentEmoji(activeElement, direction, row, {
|
|
232
|
+
shouldFocus: focusGuard,
|
|
233
|
+
exitUp: row ? goUpFromBody : undefined,
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
switch (key) {
|
|
238
|
+
case ' ':
|
|
239
|
+
event.preventDefault();
|
|
240
|
+
setVariationPicker(event.target as HTMLElement);
|
|
241
|
+
break;
|
|
242
|
+
default:
|
|
243
|
+
onType(event);
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
const [composing] = useSearchComposingState();
|
|
248
|
+
const handler = useRef<(event: KeyboardEvent, menusOnly?: boolean) => void>(
|
|
249
|
+
() => {},
|
|
311
250
|
);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
251
|
+
// One listener owns the native lifecycle; current callbacks supply state
|
|
252
|
+
// and live region refs without reattaching on every picker render.
|
|
253
|
+
handler.current = (event, menusOnly) => {
|
|
254
|
+
if (
|
|
255
|
+
composing ||
|
|
256
|
+
event.isComposing ||
|
|
257
|
+
event.keyCode === 229 ||
|
|
258
|
+
(menusOnly && !hasOpenToggles())
|
|
259
|
+
)
|
|
317
260
|
return;
|
|
261
|
+
if (!menusOnly) {
|
|
262
|
+
search(event);
|
|
263
|
+
tone(event);
|
|
264
|
+
categories(event);
|
|
265
|
+
reactions(event);
|
|
266
|
+
body(event);
|
|
318
267
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
268
|
+
main(event);
|
|
269
|
+
};
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
// RootAside owns this native aside for its entire mounted lifetime.
|
|
272
|
+
// Descendant parts are read through live refs by the delegated handler.
|
|
273
|
+
const current = ref.current;
|
|
274
|
+
if (!current) return;
|
|
275
|
+
const scoped = (event: KeyboardEvent) => {
|
|
276
|
+
if (eventBelongsToPicker(event, current)) handler.current(event);
|
|
277
|
+
};
|
|
278
|
+
const capture = (event: KeyboardEvent) => {
|
|
279
|
+
if (event.key === 'Escape' && eventBelongsToPicker(event, current))
|
|
280
|
+
handler.current(event, true);
|
|
281
|
+
};
|
|
282
|
+
current.addEventListener('keydown', scoped);
|
|
283
|
+
window.addEventListener('keydown', capture, true);
|
|
322
284
|
return () => {
|
|
323
|
-
current.removeEventListener('keydown',
|
|
285
|
+
current.removeEventListener('keydown', scoped);
|
|
286
|
+
window.removeEventListener('keydown', capture, true);
|
|
324
287
|
};
|
|
325
|
-
}, [
|
|
288
|
+
}, [ref]);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function eventInRegion(event: KeyboardEvent, ref: ElementRef): boolean {
|
|
292
|
+
return !!ref.current?.contains(event.target as Node);
|
|
326
293
|
}
|
|
327
294
|
|
|
328
295
|
// Arrow keys move between reaction buttons (and the expand button)
|
|
329
296
|
// while the reactions bar has focus. The bar lives outside the scroll
|
|
330
297
|
// body, so the body handler never sees these events.
|
|
331
298
|
// https://github.com/ealush/emoji-picker-react/issues/411
|
|
332
|
-
function useReactionsKeyboardEvents() {
|
|
333
|
-
const ReactionsRef = useReactionsRef();
|
|
334
|
-
// The reactions bar mounts late when the user collapses the full
|
|
335
|
-
// picker, so the listener effect must rerun when it opens.
|
|
336
|
-
const [reactionsOpen] = useReactionsModeState();
|
|
337
|
-
|
|
338
|
-
const onKeyDown = useMemo(
|
|
339
|
-
() =>
|
|
340
|
-
function onKeyDown(event: KeyboardEvent) {
|
|
341
|
-
const { key } = event;
|
|
342
|
-
const current = ReactionsRef.current;
|
|
343
|
-
|
|
344
|
-
if (!current) {
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const delta = reactionFocusDelta(key);
|
|
349
|
-
|
|
350
|
-
if (delta !== 0 && focusReactionSibling(current, delta)) {
|
|
351
|
-
event.preventDefault();
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
// reactionsOpen: the bar mounts late on collapse, and the new
|
|
355
|
-
// callback identity reinstalls the listener effect below.
|
|
356
|
-
[ReactionsRef, reactionsOpen],
|
|
357
|
-
);
|
|
358
|
-
|
|
359
|
-
useEffect(() => {
|
|
360
|
-
const current = ReactionsRef.current;
|
|
361
|
-
|
|
362
|
-
if (!current) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
current.addEventListener('keydown', onKeyDown);
|
|
367
|
-
|
|
368
|
-
return () => {
|
|
369
|
-
current.removeEventListener('keydown', onKeyDown);
|
|
370
|
-
};
|
|
371
|
-
}, [ReactionsRef, onKeyDown]);
|
|
372
|
-
}
|
|
373
299
|
|
|
374
300
|
function reactionFocusDelta(key: string): number {
|
|
375
301
|
switch (key) {
|
|
376
|
-
case
|
|
377
|
-
case
|
|
302
|
+
case 'ArrowRight':
|
|
303
|
+
case 'ArrowDown':
|
|
378
304
|
return 1;
|
|
379
|
-
case
|
|
380
|
-
case
|
|
305
|
+
case 'ArrowLeft':
|
|
306
|
+
case 'ArrowUp':
|
|
381
307
|
return -1;
|
|
382
308
|
default:
|
|
383
309
|
return 0;
|
|
@@ -386,9 +312,7 @@ function reactionFocusDelta(key: string): number {
|
|
|
386
312
|
|
|
387
313
|
function focusReactionSibling(root: HTMLElement, delta: number): boolean {
|
|
388
314
|
const buttons = Array.from(root.querySelectorAll('button'));
|
|
389
|
-
const activeIndex = buttons.indexOf(
|
|
390
|
-
getActiveElement() as HTMLButtonElement,
|
|
391
|
-
);
|
|
315
|
+
const activeIndex = buttons.indexOf(getActiveElement() as HTMLButtonElement);
|
|
392
316
|
const sibling = activeIndex === -1 ? null : buttons[activeIndex + delta];
|
|
393
317
|
|
|
394
318
|
if (!sibling) {
|
|
@@ -399,141 +323,87 @@ function focusReactionSibling(root: HTMLElement, delta: number): boolean {
|
|
|
399
323
|
return true;
|
|
400
324
|
}
|
|
401
325
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
const onType = useOnType();
|
|
410
|
-
|
|
411
|
-
const onKeyDown = useMemo(
|
|
412
|
-
() =>
|
|
413
|
-
// eslint-disable-next-line complexity
|
|
414
|
-
function onKeyDown(event: KeyboardEvent) {
|
|
415
|
-
const { key } = event;
|
|
416
|
-
|
|
417
|
-
const activeElement = buttonFromTarget(getActiveElement());
|
|
418
|
-
|
|
419
|
-
switch (key) {
|
|
420
|
-
case KeyboardEvents.ArrowRight:
|
|
421
|
-
event.preventDefault();
|
|
422
|
-
focusNextVisibleEmoji(activeElement);
|
|
423
|
-
break;
|
|
424
|
-
case KeyboardEvents.ArrowLeft:
|
|
425
|
-
event.preventDefault();
|
|
426
|
-
focusPrevVisibleEmoji(activeElement);
|
|
427
|
-
break;
|
|
428
|
-
case KeyboardEvents.ArrowDown:
|
|
429
|
-
event.preventDefault();
|
|
430
|
-
if (hasOpenToggles()) {
|
|
431
|
-
closeAllOpenToggles();
|
|
432
|
-
break;
|
|
433
|
-
}
|
|
434
|
-
focusVisibleEmojiOneRowDown(activeElement);
|
|
435
|
-
break;
|
|
436
|
-
case KeyboardEvents.ArrowUp:
|
|
437
|
-
event.preventDefault();
|
|
438
|
-
if (hasOpenToggles()) {
|
|
439
|
-
closeAllOpenToggles();
|
|
440
|
-
break;
|
|
441
|
-
}
|
|
442
|
-
focusVisibleEmojiOneRowUp(activeElement, goUpFromBody);
|
|
443
|
-
break;
|
|
444
|
-
case KeyboardEvents.Space:
|
|
445
|
-
event.preventDefault();
|
|
446
|
-
setVariationPicker(event.target as HTMLElement);
|
|
447
|
-
break;
|
|
448
|
-
default:
|
|
449
|
-
onType(event);
|
|
450
|
-
break;
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
[
|
|
454
|
-
goUpFromBody,
|
|
455
|
-
onType,
|
|
456
|
-
setVariationPicker,
|
|
457
|
-
hasOpenToggles,
|
|
458
|
-
closeAllOpenToggles,
|
|
459
|
-
],
|
|
460
|
-
);
|
|
461
|
-
|
|
462
|
-
useEffect(() => {
|
|
463
|
-
const current = BodyRef.current;
|
|
464
|
-
|
|
465
|
-
if (!current) {
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
current.addEventListener('keydown', onKeyDown);
|
|
470
|
-
|
|
471
|
-
return () => {
|
|
472
|
-
current.removeEventListener('keydown', onKeyDown);
|
|
473
|
-
};
|
|
474
|
-
}, [BodyRef, onKeyDown]);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function useGoDownFromSearchInput() {
|
|
326
|
+
// Cross-region focus through the registered semantic graph. Returns true
|
|
327
|
+
// when a region handled the move; callers keep their legacy direct target
|
|
328
|
+
// as fallback so unregistered trees behave exactly as before. Exported for
|
|
329
|
+
// focus-restoration flows (reactions transitions) that target regions.
|
|
330
|
+
export function useFocusRegion() {
|
|
331
|
+
const focusSearchInput = useFocusSearchInput();
|
|
478
332
|
const focusCategoryNavigation = useFocusCategoryNavigation();
|
|
479
|
-
const
|
|
333
|
+
const focusSkinTonePicker = useFocusSkinTonePicker();
|
|
480
334
|
const BodyRef = useBodyRef();
|
|
335
|
+
const ReactionsRef = useReactionsRef();
|
|
336
|
+
const registry = useNavigationRegistry();
|
|
481
337
|
|
|
482
338
|
return useCallback(
|
|
483
|
-
function
|
|
484
|
-
if (
|
|
485
|
-
return
|
|
339
|
+
function focusRegion(region: RegisteredRegion | undefined): boolean {
|
|
340
|
+
if (!region) {
|
|
341
|
+
return false;
|
|
486
342
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
343
|
+
// Grid entry is a materialize/scroll/focus operation: capture the
|
|
344
|
+
// navigation generation so a stale completion cannot steal focus.
|
|
345
|
+
const generation = registry.currentGeneration();
|
|
346
|
+
const focusGuard = () => registry.isCurrent(generation);
|
|
347
|
+
switch (region.kind as NavigationRegionKind) {
|
|
348
|
+
case 'search':
|
|
349
|
+
focusSearchInput();
|
|
350
|
+
return true;
|
|
351
|
+
case 'categories':
|
|
352
|
+
focusCategoryNavigation();
|
|
353
|
+
return true;
|
|
354
|
+
case 'grid':
|
|
355
|
+
focusFirstVisibleEmoji(BodyRef.current, focusGuard);
|
|
356
|
+
return true;
|
|
357
|
+
case 'reactions': {
|
|
358
|
+
const firstButton = ReactionsRef.current?.querySelector('button');
|
|
359
|
+
focusElement(firstButton ?? null, focusGuard);
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
case 'preview-skin-tone':
|
|
363
|
+
focusSkinTonePicker();
|
|
364
|
+
return true;
|
|
502
365
|
}
|
|
503
|
-
return focusCategoryNavigation();
|
|
504
366
|
},
|
|
505
|
-
[
|
|
367
|
+
[
|
|
368
|
+
focusSearchInput,
|
|
369
|
+
focusCategoryNavigation,
|
|
370
|
+
focusSkinTonePicker,
|
|
371
|
+
BodyRef,
|
|
372
|
+
ReactionsRef,
|
|
373
|
+
registry,
|
|
374
|
+
],
|
|
506
375
|
);
|
|
507
376
|
}
|
|
508
377
|
|
|
509
|
-
function
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (!currentSkinTone) {
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
if (!hasNextElementSibling(currentSkinTone)) {
|
|
517
|
-
exitLeft();
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
focusNextElementSibling(currentSkinTone);
|
|
378
|
+
function useFocusNextRegionFrom(from: NavigationRegionKind) {
|
|
379
|
+
return useFocusAdjacentRegion(from, 1);
|
|
521
380
|
}
|
|
522
381
|
|
|
523
|
-
function
|
|
524
|
-
|
|
382
|
+
function useFocusPrevRegionFrom(from: NavigationRegionKind) {
|
|
383
|
+
return useFocusAdjacentRegion(from, -1);
|
|
384
|
+
}
|
|
525
385
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
386
|
+
function useFocusAdjacentRegion(from: NavigationRegionKind, direction: number) {
|
|
387
|
+
const registry = useNavigationRegistry();
|
|
388
|
+
const PickerMainRef = usePickerMainRef();
|
|
389
|
+
const focusRegion = useFocusRegion();
|
|
390
|
+
return (fallback?: () => void) => {
|
|
391
|
+
const getRegion = direction > 0 ? getNextRegion : getPrevRegion;
|
|
392
|
+
if (!focusRegion(getRegion(registry, PickerMainRef.current, from)))
|
|
393
|
+
fallback?.();
|
|
394
|
+
};
|
|
395
|
+
}
|
|
529
396
|
|
|
530
|
-
|
|
397
|
+
function focusNextSkinTone(exitLeft: () => void) {
|
|
398
|
+
const current = getActiveElement();
|
|
399
|
+
if (current && !current.nextElementSibling) exitLeft();
|
|
400
|
+
focusNextElementSibling(current);
|
|
531
401
|
}
|
|
532
402
|
|
|
533
403
|
function useOnType() {
|
|
534
|
-
const
|
|
535
|
-
const focusSearchInput = useFocusSearchInput();
|
|
404
|
+
const typeToSearch = useTypeToSearchKey();
|
|
536
405
|
const searchDisabled = useSearchDisabledConfig();
|
|
406
|
+
const SearchInputRef = useSearchInputRef();
|
|
537
407
|
const closeAllOpenToggles = useCloseAllOpenToggles();
|
|
538
408
|
|
|
539
409
|
return function onType(event: KeyboardEvent) {
|
|
@@ -543,15 +413,38 @@ function useOnType() {
|
|
|
543
413
|
return;
|
|
544
414
|
}
|
|
545
415
|
|
|
546
|
-
|
|
416
|
+
// No search input mounted (a bare Root without Search): the
|
|
417
|
+
// transition would no-op, so the key is left unclaimed — no
|
|
418
|
+
// preventDefault, no toggle closing — exactly like searchDisabled.
|
|
419
|
+
if (!SearchInputRef.current) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// One printable letter or digit in any script (not only ASCII): the
|
|
424
|
+
// localized datasets are searched in their own languages, so a Hebrew,
|
|
425
|
+
// Cyrillic or Japanese keystroke on the grid starts a search like a
|
|
426
|
+
// Latin one. Named keys ("Enter", "Tab") are longer than one code
|
|
427
|
+
// point; space and punctuation stay unclaimed for the grid's own keys.
|
|
428
|
+
if (/^[\p{L}\p{N}]$/u.test(key)) {
|
|
547
429
|
event.preventDefault();
|
|
548
430
|
closeAllOpenToggles();
|
|
549
|
-
|
|
550
|
-
appendSearch(key);
|
|
431
|
+
typeToSearch(key);
|
|
551
432
|
}
|
|
552
433
|
};
|
|
553
434
|
}
|
|
554
435
|
|
|
436
|
+
// Left/right arrows follow the visual direction: under `dir="rtl"` the
|
|
437
|
+
// grid, tabs, reactions and tone fan are mirrored, so ArrowLeft moves
|
|
438
|
+
// forward. The live region element supplies the computed direction.
|
|
439
|
+
function logicalArrowKey(event: KeyboardEvent, region: Element | null): string {
|
|
440
|
+
const { key } = event;
|
|
441
|
+
return (key === 'ArrowLeft' || key === 'ArrowRight') && isRtl(region)
|
|
442
|
+
? key === 'ArrowLeft'
|
|
443
|
+
? 'ArrowRight'
|
|
444
|
+
: 'ArrowLeft'
|
|
445
|
+
: key;
|
|
446
|
+
}
|
|
447
|
+
|
|
555
448
|
function hasModifier(event: KeyboardEvent): boolean {
|
|
556
449
|
const { metaKey, ctrlKey, altKey } = event;
|
|
557
450
|
|