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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
3
|
|
|
4
|
+
import { eventBelongsToPicker } from '../DomUtils/eventBelongsToPicker';
|
|
4
5
|
import {
|
|
5
6
|
allUnifiedFromEmojiElement,
|
|
6
7
|
isEmojiElement,
|
|
@@ -22,15 +23,21 @@ import {
|
|
|
22
23
|
} from '../config/useConfig';
|
|
23
24
|
import { DataEmoji } from '../dataUtils/DataTypes';
|
|
24
25
|
import {
|
|
25
|
-
|
|
26
|
+
skinToneFromEmoji,
|
|
26
27
|
emojiHasVariations,
|
|
27
28
|
emojiNames,
|
|
28
29
|
emojiUnified,
|
|
30
|
+
emojiCanonicalUnified,
|
|
29
31
|
} from '../dataUtils/emojiUtils';
|
|
30
32
|
import { parseNativeEmoji } from '../dataUtils/parseNativeEmoji';
|
|
31
33
|
import { setSuggested } from '../dataUtils/suggested';
|
|
32
34
|
import { isCustomEmoji } from '../typeRefinements/typeRefinements';
|
|
33
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
EmojiClickData,
|
|
37
|
+
EmojiStyle,
|
|
38
|
+
EmojiStyleValue,
|
|
39
|
+
SkinTones,
|
|
40
|
+
} from '../types/exposedTypes';
|
|
34
41
|
|
|
35
42
|
import { useCloseAllOpenToggles } from './useCloseAllOpenToggles';
|
|
36
43
|
import useSetVariationPicker from './useSetVariationPicker';
|
|
@@ -39,7 +46,9 @@ export function useMouseDownHandlers(
|
|
|
39
46
|
ContainerRef: React.MutableRefObject<NullableElement>,
|
|
40
47
|
mouseEventSource: MOUSE_EVENT_SOURCE,
|
|
41
48
|
) {
|
|
42
|
-
const mouseDownTimerRef = useRef<ReturnType<typeof setTimeout
|
|
49
|
+
const mouseDownTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(
|
|
50
|
+
undefined,
|
|
51
|
+
);
|
|
43
52
|
const setVariationPicker = useSetVariationPicker();
|
|
44
53
|
const disallowClickRef = useDisallowClickRef();
|
|
45
54
|
const [, setEmojiVariationPicker] = useEmojiVariationPickerState();
|
|
@@ -53,20 +62,23 @@ export function useMouseDownHandlers(
|
|
|
53
62
|
|
|
54
63
|
const onClick = React.useCallback(
|
|
55
64
|
function onClick(event: MouseEvent) {
|
|
56
|
-
if (
|
|
65
|
+
if (
|
|
66
|
+
!eventBelongsToPicker(event, ContainerRef.current) ||
|
|
67
|
+
disallowClickRef.current
|
|
68
|
+
) {
|
|
57
69
|
return;
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
closeAllOpenToggles();
|
|
61
73
|
|
|
62
|
-
const [
|
|
74
|
+
const [record, unified] = emojiFromEvent(event, emojiByUnified);
|
|
63
75
|
|
|
64
|
-
if (!
|
|
76
|
+
if (!record || !unified) {
|
|
65
77
|
return;
|
|
66
78
|
}
|
|
67
79
|
|
|
68
|
-
const
|
|
69
|
-
|
|
80
|
+
const emoji = { ...record, renderUnified: unified };
|
|
81
|
+
const skinToneToUse = skinToneFromEmoji(emoji, unified, activeSkinTone);
|
|
70
82
|
|
|
71
83
|
updateSuggested();
|
|
72
84
|
setSuggested(emoji, skinToneToUse);
|
|
@@ -76,6 +88,7 @@ export function useMouseDownHandlers(
|
|
|
76
88
|
);
|
|
77
89
|
},
|
|
78
90
|
[
|
|
91
|
+
ContainerRef,
|
|
79
92
|
activeSkinTone,
|
|
80
93
|
closeAllOpenToggles,
|
|
81
94
|
disallowClickRef,
|
|
@@ -89,6 +102,7 @@ export function useMouseDownHandlers(
|
|
|
89
102
|
|
|
90
103
|
const onMouseDown = React.useCallback(
|
|
91
104
|
function onMouseDown(event: MouseEvent) {
|
|
105
|
+
if (!eventBelongsToPicker(event, ContainerRef.current)) return;
|
|
92
106
|
if (mouseDownTimerRef.current) {
|
|
93
107
|
clearTimeout(mouseDownTimerRef.current);
|
|
94
108
|
}
|
|
@@ -99,15 +113,19 @@ export function useMouseDownHandlers(
|
|
|
99
113
|
return;
|
|
100
114
|
}
|
|
101
115
|
|
|
116
|
+
// Preserve the native target before dispatch ends. Shadow DOM events
|
|
117
|
+
// are retargeted to the host afterward, before the long-press timer.
|
|
118
|
+
const target = event.target as HTMLElement;
|
|
102
119
|
mouseDownTimerRef.current = setTimeout(() => {
|
|
103
120
|
disallowClickRef.current = true;
|
|
104
121
|
mouseDownTimerRef.current = undefined;
|
|
105
122
|
closeAllOpenToggles();
|
|
106
|
-
setVariationPicker(
|
|
123
|
+
setVariationPicker(target);
|
|
107
124
|
setEmojiVariationPicker(emoji);
|
|
108
125
|
}, 500);
|
|
109
126
|
},
|
|
110
127
|
[
|
|
128
|
+
ContainerRef,
|
|
111
129
|
disallowClickRef,
|
|
112
130
|
emojiByUnified,
|
|
113
131
|
closeAllOpenToggles,
|
|
@@ -140,6 +158,40 @@ export function useMouseDownHandlers(
|
|
|
140
158
|
return;
|
|
141
159
|
}
|
|
142
160
|
const confainerRef = ContainerRef.current;
|
|
161
|
+
let pointerStart: { x: number; y: number } | null = null;
|
|
162
|
+
const cancelPress = () => {
|
|
163
|
+
if (mouseDownTimerRef.current) clearTimeout(mouseDownTimerRef.current);
|
|
164
|
+
mouseDownTimerRef.current = undefined;
|
|
165
|
+
pointerStart = null;
|
|
166
|
+
};
|
|
167
|
+
const onPointerDown = (event: PointerEvent) => {
|
|
168
|
+
if (event.pointerType === 'mouse' || !event.isPrimary) return;
|
|
169
|
+
pointerStart = { x: event.clientX, y: event.clientY };
|
|
170
|
+
onMouseDown(event);
|
|
171
|
+
};
|
|
172
|
+
const onPointerMove = (event: PointerEvent) => {
|
|
173
|
+
if (
|
|
174
|
+
pointerStart &&
|
|
175
|
+
Math.hypot(
|
|
176
|
+
event.clientX - pointerStart.x,
|
|
177
|
+
event.clientY - pointerStart.y,
|
|
178
|
+
) > 8
|
|
179
|
+
) {
|
|
180
|
+
cancelPress();
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const onPointerUp = (event: PointerEvent) => {
|
|
184
|
+
if (event.pointerType === 'mouse') return;
|
|
185
|
+
onMouseUp();
|
|
186
|
+
pointerStart = null;
|
|
187
|
+
};
|
|
188
|
+
const onPointerCancel = () => {
|
|
189
|
+
onMouseUp();
|
|
190
|
+
cancelPress();
|
|
191
|
+
};
|
|
192
|
+
const onContextMenu = (event: Event) => {
|
|
193
|
+
if (disallowClickRef.current) event.preventDefault();
|
|
194
|
+
};
|
|
143
195
|
confainerRef.addEventListener('click', onClick, {
|
|
144
196
|
passive: true,
|
|
145
197
|
});
|
|
@@ -150,13 +202,32 @@ export function useMouseDownHandlers(
|
|
|
150
202
|
confainerRef.addEventListener('mouseup', onMouseUp, {
|
|
151
203
|
passive: true,
|
|
152
204
|
});
|
|
205
|
+
confainerRef.addEventListener('pointerdown', onPointerDown, {
|
|
206
|
+
passive: true,
|
|
207
|
+
});
|
|
208
|
+
confainerRef.addEventListener('pointermove', onPointerMove, {
|
|
209
|
+
passive: true,
|
|
210
|
+
});
|
|
211
|
+
window.addEventListener('pointerup', onPointerUp, { passive: true });
|
|
212
|
+
window.addEventListener('pointercancel', onPointerCancel, {
|
|
213
|
+
passive: true,
|
|
214
|
+
});
|
|
215
|
+
confainerRef.addEventListener('scroll', cancelPress, { passive: true });
|
|
216
|
+
confainerRef.addEventListener('contextmenu', onContextMenu);
|
|
153
217
|
|
|
154
218
|
return () => {
|
|
219
|
+
cancelPress();
|
|
155
220
|
confainerRef?.removeEventListener('click', onClick);
|
|
156
221
|
confainerRef?.removeEventListener('mousedown', onMouseDown);
|
|
157
222
|
confainerRef?.removeEventListener('mouseup', onMouseUp);
|
|
223
|
+
confainerRef.removeEventListener('pointerdown', onPointerDown);
|
|
224
|
+
confainerRef.removeEventListener('pointermove', onPointerMove);
|
|
225
|
+
window.removeEventListener('pointerup', onPointerUp);
|
|
226
|
+
window.removeEventListener('pointercancel', onPointerCancel);
|
|
227
|
+
confainerRef.removeEventListener('scroll', cancelPress);
|
|
228
|
+
confainerRef.removeEventListener('contextmenu', onContextMenu);
|
|
158
229
|
};
|
|
159
|
-
}, [ContainerRef, onClick, onMouseDown, onMouseUp]);
|
|
230
|
+
}, [ContainerRef, onClick, onMouseDown, onMouseUp, disallowClickRef]);
|
|
160
231
|
}
|
|
161
232
|
|
|
162
233
|
function emojiFromEvent(
|
|
@@ -179,13 +250,13 @@ function emojiFromEvent(
|
|
|
179
250
|
return [];
|
|
180
251
|
}
|
|
181
252
|
|
|
182
|
-
return [emoji,
|
|
253
|
+
return [emoji, resolvedUnified];
|
|
183
254
|
}
|
|
184
255
|
|
|
185
|
-
function emojiClickOutput(
|
|
256
|
+
export function emojiClickOutput(
|
|
186
257
|
emoji: DataEmoji,
|
|
187
258
|
activeSkinTone: SkinTones,
|
|
188
|
-
activeEmojiStyle:
|
|
259
|
+
activeEmojiStyle: EmojiStyleValue,
|
|
189
260
|
getEmojiUrl: GetEmojiUrl,
|
|
190
261
|
): EmojiClickData {
|
|
191
262
|
const names = emojiNames(emoji);
|
|
@@ -206,17 +277,21 @@ function emojiClickOutput(
|
|
|
206
277
|
};
|
|
207
278
|
}
|
|
208
279
|
const unified = emojiUnified(emoji, activeSkinTone);
|
|
280
|
+
const imageStyle =
|
|
281
|
+
activeEmojiStyle === EmojiStyle.NATIVE
|
|
282
|
+
? EmojiStyle.APPLE
|
|
283
|
+
: activeEmojiStyle;
|
|
209
284
|
|
|
210
285
|
return {
|
|
211
286
|
activeSkinTone,
|
|
212
287
|
emoji: parseNativeEmoji(unified),
|
|
213
|
-
getImageUrl(emojiStyle:
|
|
288
|
+
getImageUrl(emojiStyle: EmojiStyleValue = imageStyle) {
|
|
214
289
|
return getEmojiUrl(unified, emojiStyle);
|
|
215
290
|
},
|
|
216
|
-
imageUrl: getEmojiUrl(unified,
|
|
291
|
+
imageUrl: getEmojiUrl(unified, imageStyle),
|
|
217
292
|
isCustom: false,
|
|
218
293
|
names,
|
|
219
294
|
unified,
|
|
220
|
-
unifiedWithoutSkinTone:
|
|
295
|
+
unifiedWithoutSkinTone: emojiCanonicalUnified(emoji),
|
|
221
296
|
};
|
|
222
297
|
}
|
package/src/hooks/useOnFocus.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { eventBelongsToPicker } from '../DomUtils/eventBelongsToPicker';
|
|
4
|
+
import {
|
|
5
|
+
allUnifiedFromEmojiElement,
|
|
6
|
+
buttonFromTarget,
|
|
7
|
+
} from '../DomUtils/selectors';
|
|
4
8
|
import { useBodyRef } from '../components/context/ElementRefContext';
|
|
9
|
+
import { usePickerDataContext } from '../components/context/PickerDataContext';
|
|
5
10
|
import { useEmojiStyleConfig, useGetEmojiUrlConfig } from '../config/useConfig';
|
|
6
11
|
import { emojiHasVariations } from '../dataUtils/emojiUtils';
|
|
7
12
|
import { EmojiStyle } from '../types/exposedTypes';
|
|
@@ -12,6 +17,8 @@ export function useOnFocus() {
|
|
|
12
17
|
const BodyRef = useBodyRef();
|
|
13
18
|
const emojiStyle = useEmojiStyleConfig();
|
|
14
19
|
const getEmojiUrl = useGetEmojiUrlConfig();
|
|
20
|
+
// Root-scoped lookup: honors localized emojiData and custom emojis.
|
|
21
|
+
const { emojiByUnified } = usePickerDataContext();
|
|
15
22
|
|
|
16
23
|
useEffect(() => {
|
|
17
24
|
if (emojiStyle === EmojiStyle.NATIVE) {
|
|
@@ -27,13 +34,15 @@ export function useOnFocus() {
|
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
function onFocus(event: FocusEvent) {
|
|
37
|
+
if (!eventBelongsToPicker(event, bodyRef)) return;
|
|
30
38
|
const button = buttonFromTarget(event.target as HTMLElement);
|
|
31
39
|
|
|
32
40
|
if (!button) {
|
|
33
41
|
return;
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
const
|
|
44
|
+
const { unified, originalUnified } = allUnifiedFromEmojiElement(button);
|
|
45
|
+
const emoji = emojiByUnified(unified ?? originalUnified ?? undefined);
|
|
37
46
|
|
|
38
47
|
if (!emoji) {
|
|
39
48
|
return;
|
|
@@ -43,5 +52,5 @@ export function useOnFocus() {
|
|
|
43
52
|
preloadEmoji(getEmojiUrl, emoji, emojiStyle);
|
|
44
53
|
}
|
|
45
54
|
}
|
|
46
|
-
}, [BodyRef, emojiStyle, getEmojiUrl]);
|
|
55
|
+
}, [BodyRef, emojiStyle, getEmojiUrl, emojiByUnified]);
|
|
47
56
|
}
|
package/src/hooks/useOnScroll.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ElementRef } from '../components/context/ElementRefContext';
|
|
4
4
|
|
|
@@ -7,6 +7,9 @@ import { useCloseAllOpenToggles } from './useCloseAllOpenToggles';
|
|
|
7
7
|
export function useOnScroll(BodyRef: ElementRef) {
|
|
8
8
|
const closeAllOpenToggles = useCloseAllOpenToggles();
|
|
9
9
|
const [scrollTop, setScrollTop] = useState(0);
|
|
10
|
+
const latestRef = useRef(0);
|
|
11
|
+
const scheduledRef = useRef(false);
|
|
12
|
+
const frameRef = useRef(0);
|
|
10
13
|
|
|
11
14
|
useEffect(() => {
|
|
12
15
|
const bodyRef = BodyRef.current;
|
|
@@ -18,13 +21,26 @@ export function useOnScroll(BodyRef: ElementRef) {
|
|
|
18
21
|
passive: true,
|
|
19
22
|
});
|
|
20
23
|
|
|
24
|
+
// High-frequency geometry work coalesces to at most one scheduled
|
|
25
|
+
// virtualization update per animation frame.
|
|
26
|
+
// Toggle dismissal stays immediate: those setters bail out when
|
|
27
|
+
// nothing is open, so unrelated regions never rerender for it.
|
|
21
28
|
function onScroll() {
|
|
22
|
-
|
|
29
|
+
latestRef.current = bodyRef?.scrollTop ?? 0;
|
|
30
|
+
if (!scheduledRef.current) {
|
|
31
|
+
scheduledRef.current = true;
|
|
32
|
+
frameRef.current = requestAnimationFrame(() => {
|
|
33
|
+
scheduledRef.current = false;
|
|
34
|
+
setScrollTop(latestRef.current);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
23
37
|
closeAllOpenToggles();
|
|
24
38
|
}
|
|
25
39
|
|
|
26
40
|
return () => {
|
|
27
41
|
bodyRef?.removeEventListener('scroll', onScroll);
|
|
42
|
+
cancelAnimationFrame(frameRef.current);
|
|
43
|
+
scheduledRef.current = false;
|
|
28
44
|
};
|
|
29
45
|
}, [BodyRef, closeAllOpenToggles]);
|
|
30
46
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { focusElement } from '../DomUtils/focusElement';
|
|
4
|
+
import {
|
|
5
|
+
usePickerMainRef,
|
|
6
|
+
useReactionsRef,
|
|
7
|
+
useSearchInputRef,
|
|
8
|
+
} from '../components/context/ElementRefContext';
|
|
9
|
+
import {
|
|
10
|
+
useNavigationRegistry,
|
|
11
|
+
useReactionsModeState,
|
|
12
|
+
} from '../components/context/PickerContext';
|
|
13
|
+
import { useAutoFocusSearchConfig } from '../config/useConfig';
|
|
14
|
+
import { getActiveRegionsInDomOrder } from '../state/regionTraversal';
|
|
15
|
+
|
|
16
|
+
import { useFocusSearchInput } from './useFocus';
|
|
17
|
+
import { useFocusRegion } from './useKeyboardNavigation';
|
|
18
|
+
|
|
19
|
+
// Reactions ↔ full-picker focus management.
|
|
20
|
+
//
|
|
21
|
+
// - On expansion (compact → full): the managed panel activates; after its
|
|
22
|
+
// destination exists, Search is preferred when present and autofocus is
|
|
23
|
+
// enabled, otherwise the next valid focusable region takes focus. No
|
|
24
|
+
// focus transfer waits on an arbitrary animation timeout — effects run
|
|
25
|
+
// after commit, when destinations exist.
|
|
26
|
+
// - On collapse (full → compact): the panel deactivates and focus restores
|
|
27
|
+
// to the initiating control when it is still connected and outside the
|
|
28
|
+
// now-inert panel; otherwise the first valid Reactions control.
|
|
29
|
+
// - Initial mount never steals focus in either mode (autofocus, when
|
|
30
|
+
// enabled, remains the browser/input's own behavior).
|
|
31
|
+
export function useReactionsFocusManager() {
|
|
32
|
+
const PickerMainRef = usePickerMainRef();
|
|
33
|
+
const ReactionsRef = useReactionsRef();
|
|
34
|
+
const SearchInputRef = useSearchInputRef();
|
|
35
|
+
const [reactionsOpen] = useReactionsModeState();
|
|
36
|
+
const autoFocusSearch = useAutoFocusSearchConfig();
|
|
37
|
+
const focusSearchInput = useFocusSearchInput();
|
|
38
|
+
const focusRegion = useFocusRegion();
|
|
39
|
+
const registry = useNavigationRegistry();
|
|
40
|
+
const lastControlRef = React.useRef<HTMLElement | null>(null);
|
|
41
|
+
// Previous-value ref (not a first-run flag): StrictMode double-invokes
|
|
42
|
+
// this effect on mount, and a flag would treat the second run as a
|
|
43
|
+
// transition and steal focus. Comparing values keeps both runs silent.
|
|
44
|
+
const prevReactionsOpen = React.useRef(reactionsOpen);
|
|
45
|
+
|
|
46
|
+
// Remember the initiating control: the last focused element inside Root.
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
const root = PickerMainRef.current;
|
|
49
|
+
if (!root) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
function onFocusIn(event: FocusEvent) {
|
|
53
|
+
if (event.target instanceof HTMLElement) {
|
|
54
|
+
lastControlRef.current = event.target;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
root.addEventListener('focusin', onFocusIn);
|
|
58
|
+
return () => {
|
|
59
|
+
root.removeEventListener('focusin', onFocusIn);
|
|
60
|
+
};
|
|
61
|
+
}, [PickerMainRef]);
|
|
62
|
+
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (prevReactionsOpen.current === reactionsOpen) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
prevReactionsOpen.current = reactionsOpen;
|
|
68
|
+
if (!reactionsOpen) {
|
|
69
|
+
focusAfterExpansion();
|
|
70
|
+
} else {
|
|
71
|
+
focusAfterCollapse();
|
|
72
|
+
}
|
|
73
|
+
// Runs on reactions-mode transitions only.
|
|
74
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
75
|
+
}, [reactionsOpen]);
|
|
76
|
+
|
|
77
|
+
function focusAfterExpansion() {
|
|
78
|
+
if (autoFocusSearch && SearchInputRef.current) {
|
|
79
|
+
focusSearchInput();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Next valid focusable region in DOM order (Search deliberately
|
|
83
|
+
// skipped here: without autofocus it is not the preferred entry).
|
|
84
|
+
const root = PickerMainRef.current;
|
|
85
|
+
const active = getActiveRegionsInDomOrder(registry, root).filter(
|
|
86
|
+
(region) => region.kind !== 'search' && region.kind !== 'reactions',
|
|
87
|
+
);
|
|
88
|
+
focusRegion(active[0]);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function focusAfterCollapse() {
|
|
92
|
+
const last = lastControlRef.current;
|
|
93
|
+
const panel = PickerMainRef.current?.querySelector(
|
|
94
|
+
'[data-epr-part="panel"]',
|
|
95
|
+
);
|
|
96
|
+
if (
|
|
97
|
+
last &&
|
|
98
|
+
last.isConnected &&
|
|
99
|
+
!(panel && panel.contains(last)) &&
|
|
100
|
+
isFocusable(last)
|
|
101
|
+
) {
|
|
102
|
+
focusElement(last);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const firstReaction = ReactionsRef.current?.querySelector('button');
|
|
106
|
+
focusElement(firstReaction ?? null);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function isFocusable(element: HTMLElement): boolean {
|
|
110
|
+
if (element.hidden || element.getAttribute('aria-hidden') === 'true') {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (element instanceof HTMLButtonElement && element.disabled) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { usePickerMainRef } from '../components/context/ElementRefContext';
|
|
4
|
+
import { useNavigationRegistry } from '../components/context/PickerContext';
|
|
5
|
+
import {
|
|
6
|
+
NavigationRegionKind,
|
|
7
|
+
reportDuplicateRegion,
|
|
8
|
+
reportPortalRegion,
|
|
9
|
+
} from '../state/navigationRegistry';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Register a semantic focus region root with the Root-scoped navigation
|
|
13
|
+
* registry.
|
|
14
|
+
*
|
|
15
|
+
* - Registers after mount and unregisters on unmount; omitted regions
|
|
16
|
+
* (null element) stay absent from the graph — there are no placeholder
|
|
17
|
+
* or dead graph nodes.
|
|
18
|
+
* - `presenceDeps` reruns registration when presence-affecting state
|
|
19
|
+
* changes (e.g. a tab bar that unmounts below two categories).
|
|
20
|
+
* - Portal roots (outside the Root DOM element) are unsupported: dev
|
|
21
|
+
* warns and the region is excluded from traversal.
|
|
22
|
+
* - A second singleton registration throws in development and is ignored
|
|
23
|
+
* (first wins) in production.
|
|
24
|
+
*/
|
|
25
|
+
export function useRegisterRegion(
|
|
26
|
+
kind: NavigationRegionKind,
|
|
27
|
+
ref: React.RefObject<Element | null> & {
|
|
28
|
+
subscribe?: (listener: () => void) => () => void;
|
|
29
|
+
},
|
|
30
|
+
presenceDeps: readonly unknown[] = [],
|
|
31
|
+
): void {
|
|
32
|
+
const registry = useNavigationRegistry();
|
|
33
|
+
const PickerMainRef = usePickerMainRef();
|
|
34
|
+
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
if (!registry.claimSingleton(kind)) {
|
|
37
|
+
// Development throws inside; production warns once and falls
|
|
38
|
+
// through to the return below, keeping the first registration
|
|
39
|
+
// authoritative.
|
|
40
|
+
reportDuplicateRegion(kind);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let unregister: (() => void) | undefined;
|
|
45
|
+
const attach = () => {
|
|
46
|
+
unregister?.();
|
|
47
|
+
unregister = undefined;
|
|
48
|
+
const element = ref.current;
|
|
49
|
+
if (!element) return;
|
|
50
|
+
const rootElement = PickerMainRef.current;
|
|
51
|
+
if (rootElement && !rootElement.contains(element)) {
|
|
52
|
+
reportPortalRegion(kind);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// A tone control composed inside Search belongs to that region's
|
|
56
|
+
// local keyboard flow, rather than an extra region on ArrowDown.
|
|
57
|
+
if (
|
|
58
|
+
kind === 'preview-skin-tone' &&
|
|
59
|
+
element.closest('[data-epr-part="search"]')
|
|
60
|
+
)
|
|
61
|
+
return;
|
|
62
|
+
unregister = registry.register(kind, element);
|
|
63
|
+
};
|
|
64
|
+
attach();
|
|
65
|
+
const unsubscribe = ref.subscribe?.(attach);
|
|
66
|
+
return () => {
|
|
67
|
+
unsubscribe?.();
|
|
68
|
+
unregister?.();
|
|
69
|
+
registry.releaseSingleton(kind);
|
|
70
|
+
};
|
|
71
|
+
// presenceDeps reruns the effect when region presence may have changed.
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [registry, kind, ref, PickerMainRef, ...presenceDeps]);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Claim a structural singleton slot (Viewport/Preview)
|
|
78
|
+
* without registering a focus region. Same duplicate policy as regions.
|
|
79
|
+
*/
|
|
80
|
+
export function useSingletonClaim(kind: string): void {
|
|
81
|
+
const registry = useNavigationRegistry();
|
|
82
|
+
|
|
83
|
+
React.useEffect(() => {
|
|
84
|
+
if (!registry.claimSingleton(kind)) {
|
|
85
|
+
reportDuplicateRegion(kind);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
return () => {
|
|
89
|
+
registry.releaseSingleton(kind);
|
|
90
|
+
};
|
|
91
|
+
}, [registry, kind]);
|
|
92
|
+
}
|