emoji-picker-react 4.22.3 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (409) hide show
  1. package/README.md +331 -49
  2. package/dist/DomUtils/categoryNameFromDom.d.ts +1 -1
  3. package/dist/DomUtils/classNames.d.ts +23 -23
  4. package/dist/DomUtils/detectEmojyPartiallyBelowFold.d.ts +2 -2
  5. package/dist/DomUtils/elementPositionInRow.d.ts +5 -5
  6. package/dist/DomUtils/eventBelongsToPicker.d.ts +2 -0
  7. package/dist/DomUtils/focusElement.d.ts +5 -5
  8. package/dist/DomUtils/getActiveElement.d.ts +2 -2
  9. package/dist/DomUtils/isJsdom.d.ts +1 -0
  10. package/dist/DomUtils/isRtl.d.ts +1 -0
  11. package/dist/DomUtils/keyboardNavigation.d.ts +15 -8
  12. package/dist/DomUtils/scrollTo.d.ts +4 -5
  13. package/dist/DomUtils/selectors.d.ts +31 -35
  14. package/dist/EmojiPickerReact.d.ts +5 -5
  15. package/dist/Stylesheet/DedupedStyle.d.ts +13 -0
  16. package/dist/Stylesheet/stylesheet.d.ts +40 -37
  17. package/dist/components/ErrorBoundary.d.ts +15 -15
  18. package/dist/components/Layout/Absolute.d.ts +8 -8
  19. package/dist/components/Layout/Flex.d.ts +13 -13
  20. package/dist/components/Layout/Relative.d.ts +8 -8
  21. package/dist/components/Layout/Space.d.ts +7 -7
  22. package/dist/components/Reactions/BtnPlus.d.ts +2 -2
  23. package/dist/components/Reactions/DEFAULT_REACTIONS.d.ts +1 -1
  24. package/dist/components/Reactions/Reactions.d.ts +3 -2
  25. package/dist/components/atoms/Button.d.ts +11 -6
  26. package/dist/components/body/EmojiCategory.d.ts +13 -12
  27. package/dist/components/body/EmojiList.d.ts +7 -4
  28. package/dist/components/body/EmojiVariationPicker.d.ts +2 -2
  29. package/dist/components/body/MeasureEmoji.d.ts +2 -2
  30. package/dist/components/body/listComponents.d.ts +47 -0
  31. package/dist/components/context/ElementRefContext.d.ts +18 -16
  32. package/dist/components/context/PickerConfigContext.d.ts +14 -9
  33. package/dist/components/context/PickerContext.d.ts +57 -25
  34. package/dist/components/context/PickerDataContext.d.ts +23 -17
  35. package/dist/components/emoji/BaseEmojiProps.d.ts +14 -13
  36. package/dist/components/emoji/ClickableEmojiButton.d.ts +23 -15
  37. package/dist/components/emoji/Emoji.d.ts +18 -15
  38. package/dist/components/emoji/EmojiImg.d.ts +11 -11
  39. package/dist/components/emoji/ExportedEmoji.d.ts +11 -11
  40. package/dist/components/emoji/NativeEmoji.d.ts +6 -6
  41. package/dist/components/emoji/ViewOnlyEmoji.d.ts +3 -3
  42. package/dist/components/emoji/emojiStyles.d.ts +6 -1
  43. package/dist/components/footer/Preview.d.ts +7 -7
  44. package/dist/components/header/Header.d.ts +2 -2
  45. package/dist/components/header/Search/BtnClearSearch.d.ts +2 -2
  46. package/dist/components/header/Search/IcnSearch.d.ts +2 -2
  47. package/dist/components/header/Search/Search.d.ts +11 -3
  48. package/dist/components/header/SkinTonePicker/BtnSkinToneVariation.d.ts +12 -12
  49. package/dist/components/header/SkinTonePicker/SkinTonePicker.d.ts +11 -11
  50. package/dist/components/icons/svgIcons.d.ts +4 -0
  51. package/dist/components/main/PickerMainBehaviors.d.ts +4 -0
  52. package/dist/components/main/defaultAppearance.d.ts +12 -0
  53. package/dist/components/main/labelHeight.d.ts +1 -0
  54. package/dist/components/navigation/CategoryButton.d.ts +12 -12
  55. package/dist/components/navigation/CategoryNavIcon.d.ts +4 -4
  56. package/dist/components/navigation/CategoryNavigation.d.ts +19 -2
  57. package/dist/config/categoryConfig.d.ts +34 -34
  58. package/dist/config/cdnUrls.d.ts +2 -2
  59. package/dist/config/compareConfig.d.ts +10 -2
  60. package/dist/config/config.d.ts +166 -64
  61. package/dist/config/customEmojiConfig.d.ts +14 -14
  62. package/dist/config/defaultPickerConfiguration.d.ts +10 -0
  63. package/dist/config/mutableConfig.d.ts +32 -10
  64. package/dist/config/useConfig.d.ts +48 -36
  65. package/dist/data/defaultEmojiData.d.ts +9 -0
  66. package/dist/data/defaultEmojiData.js +40 -0
  67. package/dist/data/emojis-bn.d.mts +39 -0
  68. package/dist/data/emojis-bn.d.ts +38 -2
  69. package/dist/data/emojis-bn.js +25 -2
  70. package/dist/data/emojis-bn.mjs +2 -0
  71. package/dist/data/emojis-da.d.mts +39 -0
  72. package/dist/data/emojis-da.d.ts +38 -2
  73. package/dist/data/emojis-da.js +25 -2
  74. package/dist/data/emojis-da.mjs +2 -0
  75. package/dist/data/emojis-de.d.mts +39 -0
  76. package/dist/data/emojis-de.d.ts +38 -2
  77. package/dist/data/emojis-de.js +25 -2
  78. package/dist/data/emojis-de.mjs +2 -0
  79. package/dist/data/emojis-en-gb.d.mts +39 -0
  80. package/dist/data/emojis-en-gb.d.ts +38 -2
  81. package/dist/data/emojis-en-gb.js +25 -2
  82. package/dist/data/emojis-en-gb.mjs +2 -0
  83. package/dist/data/emojis-en.d.mts +39 -0
  84. package/dist/data/emojis-en.d.ts +38 -2
  85. package/dist/data/emojis-en.js +25 -2
  86. package/dist/data/emojis-en.mjs +2 -0
  87. package/dist/data/emojis-es-mx.d.mts +39 -0
  88. package/dist/data/emojis-es-mx.d.ts +38 -2
  89. package/dist/data/emojis-es-mx.js +25 -2
  90. package/dist/data/emojis-es-mx.mjs +2 -0
  91. package/dist/data/emojis-es.d.mts +39 -0
  92. package/dist/data/emojis-es.d.ts +38 -2
  93. package/dist/data/emojis-es.js +25 -2
  94. package/dist/data/emojis-es.mjs +2 -0
  95. package/dist/data/emojis-et.d.mts +39 -0
  96. package/dist/data/emojis-et.d.ts +38 -2
  97. package/dist/data/emojis-et.js +25 -2
  98. package/dist/data/emojis-et.mjs +2 -0
  99. package/dist/data/emojis-fi.d.mts +39 -0
  100. package/dist/data/emojis-fi.d.ts +38 -2
  101. package/dist/data/emojis-fi.js +25 -2
  102. package/dist/data/emojis-fi.mjs +2 -0
  103. package/dist/data/emojis-fr.d.mts +39 -0
  104. package/dist/data/emojis-fr.d.ts +38 -2
  105. package/dist/data/emojis-fr.js +25 -2
  106. package/dist/data/emojis-fr.mjs +2 -0
  107. package/dist/data/emojis-hi.d.mts +39 -0
  108. package/dist/data/emojis-hi.d.ts +38 -2
  109. package/dist/data/emojis-hi.js +25 -2
  110. package/dist/data/emojis-hi.mjs +2 -0
  111. package/dist/data/emojis-hu.d.mts +39 -0
  112. package/dist/data/emojis-hu.d.ts +38 -2
  113. package/dist/data/emojis-hu.js +25 -2
  114. package/dist/data/emojis-hu.mjs +2 -0
  115. package/dist/data/emojis-it.d.mts +39 -0
  116. package/dist/data/emojis-it.d.ts +38 -2
  117. package/dist/data/emojis-it.js +25 -2
  118. package/dist/data/emojis-it.mjs +2 -0
  119. package/dist/data/emojis-ja.d.mts +39 -0
  120. package/dist/data/emojis-ja.d.ts +38 -2
  121. package/dist/data/emojis-ja.js +25 -2
  122. package/dist/data/emojis-ja.mjs +2 -0
  123. package/dist/data/emojis-ko.d.mts +39 -0
  124. package/dist/data/emojis-ko.d.ts +38 -2
  125. package/dist/data/emojis-ko.js +25 -2
  126. package/dist/data/emojis-ko.mjs +2 -0
  127. package/dist/data/emojis-lt.d.mts +39 -0
  128. package/dist/data/emojis-lt.d.ts +38 -2
  129. package/dist/data/emojis-lt.js +25 -2
  130. package/dist/data/emojis-lt.mjs +2 -0
  131. package/dist/data/emojis-ms.d.mts +39 -0
  132. package/dist/data/emojis-ms.d.ts +38 -2
  133. package/dist/data/emojis-ms.js +25 -2
  134. package/dist/data/emojis-ms.mjs +2 -0
  135. package/dist/data/emojis-nb.d.mts +39 -0
  136. package/dist/data/emojis-nb.d.ts +38 -2
  137. package/dist/data/emojis-nb.js +25 -2
  138. package/dist/data/emojis-nb.mjs +2 -0
  139. package/dist/data/emojis-nl.d.mts +39 -0
  140. package/dist/data/emojis-nl.d.ts +38 -2
  141. package/dist/data/emojis-nl.js +25 -2
  142. package/dist/data/emojis-nl.mjs +2 -0
  143. package/dist/data/emojis-pl.d.mts +39 -0
  144. package/dist/data/emojis-pl.d.ts +38 -2
  145. package/dist/data/emojis-pl.js +25 -2
  146. package/dist/data/emojis-pl.mjs +2 -0
  147. package/dist/data/emojis-pt.d.mts +39 -0
  148. package/dist/data/emojis-pt.d.ts +38 -2
  149. package/dist/data/emojis-pt.js +25 -2
  150. package/dist/data/emojis-pt.mjs +2 -0
  151. package/dist/data/emojis-ru.d.mts +39 -0
  152. package/dist/data/emojis-ru.d.ts +38 -2
  153. package/dist/data/emojis-ru.js +25 -2
  154. package/dist/data/emojis-ru.mjs +2 -0
  155. package/dist/data/emojis-sv.d.mts +39 -0
  156. package/dist/data/emojis-sv.d.ts +38 -2
  157. package/dist/data/emojis-sv.js +25 -2
  158. package/dist/data/emojis-sv.mjs +2 -0
  159. package/dist/data/emojis-th.d.mts +39 -0
  160. package/dist/data/emojis-th.d.ts +38 -2
  161. package/dist/data/emojis-th.js +25 -2
  162. package/dist/data/emojis-th.mjs +2 -0
  163. package/dist/data/emojis-uk.d.mts +39 -0
  164. package/dist/data/emojis-uk.d.ts +38 -2
  165. package/dist/data/emojis-uk.js +25 -2
  166. package/dist/data/emojis-uk.mjs +2 -0
  167. package/dist/data/emojis-vi.d.mts +39 -0
  168. package/dist/data/emojis-vi.d.ts +38 -2
  169. package/dist/data/emojis-vi.js +25 -2
  170. package/dist/data/emojis-vi.mjs +2 -0
  171. package/dist/data/emojis-zh-hant.d.mts +39 -0
  172. package/dist/data/emojis-zh-hant.d.ts +38 -2
  173. package/dist/data/emojis-zh-hant.js +25 -2
  174. package/dist/data/emojis-zh-hant.mjs +2 -0
  175. package/dist/data/emojis-zh.d.mts +39 -0
  176. package/dist/data/emojis-zh.d.ts +38 -2
  177. package/dist/data/emojis-zh.js +25 -2
  178. package/dist/data/emojis-zh.mjs +2 -0
  179. package/dist/data/index.js +1 -0
  180. package/dist/data/registerDefaultEmojiData.d.ts +1 -0
  181. package/dist/data/registerDefaultEmojiData.js +3 -0
  182. package/dist/data/skinToneVariations.js +2 -2
  183. package/dist/data/skinToneVariations.ts +8 -7
  184. package/dist/data-core/pickerData.d.ts +12 -0
  185. package/dist/data-core/prepare.d.ts +23 -0
  186. package/dist/data-core/search.d.ts +13 -0
  187. package/dist/data-core/types.d.ts +23 -0
  188. package/dist/data.d.mts +72 -0
  189. package/dist/data.d.ts +72 -0
  190. package/dist/dataUtils/DataTypes.d.ts +23 -19
  191. package/dist/dataUtils/emojiSelectors.d.ts +15 -16
  192. package/dist/dataUtils/emojiUtils.d.ts +1 -12
  193. package/dist/dataUtils/nativeEmojiSequenceSupport.d.ts +10 -0
  194. package/dist/dataUtils/nativeEmojiSupport.d.ts +40 -0
  195. package/dist/dataUtils/parseNativeEmoji.d.ts +1 -1
  196. package/dist/dataUtils/suggested.d.ts +11 -11
  197. package/dist/dataUtils/suggestedEmojis.d.ts +7 -0
  198. package/dist/esm/chunks/chunk-7ZGTUZFB.mjs +8025 -0
  199. package/dist/esm/chunks/chunk-ACXAQEKG.mjs +149 -0
  200. package/dist/esm/chunks/chunk-F2KS7DCA.mjs +6735 -0
  201. package/dist/esm/chunks/chunk-L5W4PFRJ.mjs +14 -0
  202. package/dist/esm/chunks/chunk-LO4TPPLH.mjs +33 -0
  203. package/dist/esm/chunks/emojis-6L3GRBAP.mjs +7 -0
  204. package/dist/esm/data.mjs +11 -0
  205. package/dist/esm/index.mjs +279 -0
  206. package/dist/esm/primitives/index.mjs +8 -0
  207. package/dist/hooks/preloadEmoji.d.ts +5 -9
  208. package/dist/hooks/useActiveCategoryScrollDetection.d.ts +11 -11
  209. package/dist/hooks/useCategoryHeight.d.ts +7 -5
  210. package/dist/hooks/useCloseAllOpenToggles.d.ts +2 -2
  211. package/dist/hooks/useDataIdentityStabilityWarning.d.ts +13 -0
  212. package/dist/hooks/useDebouncedState.d.ts +1 -1
  213. package/dist/hooks/useDisallowMouseMove.d.ts +4 -4
  214. package/dist/hooks/useDisallowedEmojis.d.ts +2 -3
  215. package/dist/hooks/useEmojiPreviewEvents.d.ts +3 -3
  216. package/dist/hooks/useEmojiVirtualization.d.ts +22 -17
  217. package/dist/hooks/useFilter.d.ts +10 -16
  218. package/dist/hooks/useFocus.d.ts +3 -3
  219. package/dist/hooks/useInitialLoad.d.ts +2 -2
  220. package/dist/hooks/useIsEmojiHidden.d.ts +8 -8
  221. package/dist/hooks/useIsMounted.d.ts +1 -1
  222. package/dist/hooks/useIsSearchMode.d.ts +1 -1
  223. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
  224. package/dist/hooks/useKeyboardNavigation.d.ts +3 -1
  225. package/dist/hooks/useMouseDownHandlers.d.ts +8 -4
  226. package/dist/hooks/useOnFocus.d.ts +1 -1
  227. package/dist/hooks/useOnScroll.d.ts +2 -2
  228. package/dist/hooks/useReactionsFocus.d.ts +1 -0
  229. package/dist/hooks/useRegisterRegion.d.ts +24 -0
  230. package/dist/hooks/useResolvedEmojiData.d.ts +37 -0
  231. package/dist/hooks/useScrollCategoryIntoView.d.ts +1 -1
  232. package/dist/hooks/useSearchController.d.ts +17 -0
  233. package/dist/hooks/useSearchResults.d.ts +8 -0
  234. package/dist/hooks/useSetVariationPicker.d.ts +2 -2
  235. package/dist/hooks/useShouldHideCustomEmojis.d.ts +1 -1
  236. package/dist/hooks/useShouldShowSkinTonePicker.d.ts +4 -4
  237. package/dist/index.d.mts +376 -0
  238. package/dist/index.d.ts +376 -9
  239. package/dist/index.js +2 -8
  240. package/dist/primitives/CategoryNav.d.ts +4 -0
  241. package/dist/primitives/Empty.d.ts +6 -0
  242. package/dist/primitives/List.d.ts +4 -0
  243. package/dist/primitives/LoadError.d.ts +8 -0
  244. package/dist/primitives/Loading.d.ts +4 -0
  245. package/dist/primitives/Panel.d.ts +3 -0
  246. package/dist/primitives/Preview.d.ts +3 -0
  247. package/dist/primitives/Reactions.d.ts +2 -0
  248. package/dist/primitives/Root.d.ts +26 -0
  249. package/dist/primitives/Search.d.ts +5 -0
  250. package/dist/primitives/SearchInput.d.ts +3 -0
  251. package/dist/primitives/SkinTone.d.ts +4 -0
  252. package/dist/primitives/Viewport.d.ts +19 -0
  253. package/dist/primitives/appearance.d.ts +3 -0
  254. package/dist/primitives/components.d.ts +27 -0
  255. package/dist/primitives/hooks.d.ts +48 -0
  256. package/dist/primitives/index.d.mts +561 -0
  257. package/dist/primitives/index.d.ts +561 -0
  258. package/dist/primitives/index.js +2 -0
  259. package/dist/primitives/nativeProps.d.ts +15 -0
  260. package/dist/primitives/scope.d.ts +13 -0
  261. package/dist/primitives/structuralStyles.d.ts +16 -0
  262. package/dist/primitives/tokens.d.ts +18 -0
  263. package/dist/primitives/types.d.ts +85 -0
  264. package/dist/state/activeEmojiStore.d.ts +7 -0
  265. package/dist/state/navigationRegistry.d.ts +61 -0
  266. package/dist/state/regionTraversal.d.ts +20 -0
  267. package/dist/typeRefinements/typeRefinements.d.ts +6 -6
  268. package/dist/types/exposedTypes.d.ts +16 -6
  269. package/dist/types/exposedTypes.js +5 -0
  270. package/dist/virtualization/virtualizationHelpers.d.ts +22 -18
  271. package/llms-full.txt +3683 -0
  272. package/llms.txt +66 -480
  273. package/package.json +180 -66
  274. package/src/DomUtils/categoryNameFromDom.ts +1 -1
  275. package/src/DomUtils/classNames.ts +1 -4
  276. package/src/DomUtils/elementPositionInRow.ts +28 -6
  277. package/src/DomUtils/eventBelongsToPicker.ts +17 -0
  278. package/src/DomUtils/getActiveElement.ts +7 -1
  279. package/src/DomUtils/isJsdom.ts +12 -0
  280. package/src/DomUtils/isRtl.ts +5 -0
  281. package/src/DomUtils/keyboardNavigation.ts +164 -144
  282. package/src/DomUtils/scrollTo.ts +20 -18
  283. package/src/DomUtils/selectors.ts +30 -127
  284. package/src/EmojiPickerReact.tsx +155 -48
  285. package/src/Stylesheet/DedupedStyle.tsx +80 -0
  286. package/src/Stylesheet/stylesheet.tsx +128 -59
  287. package/src/components/Layout/Flex.tsx +12 -11
  288. package/src/components/Reactions/BtnPlus.tsx +61 -51
  289. package/src/components/Reactions/Reactions.tsx +113 -55
  290. package/src/components/atoms/Button.tsx +18 -15
  291. package/src/components/body/EmojiCategory.tsx +77 -40
  292. package/src/components/body/EmojiList.tsx +107 -44
  293. package/src/components/body/EmojiVariationPicker.tsx +113 -66
  294. package/src/components/body/MeasureEmoji.tsx +9 -2
  295. package/src/components/body/listComponents.tsx +79 -0
  296. package/src/components/context/ElementRefContext.tsx +46 -35
  297. package/src/components/context/PickerConfigContext.tsx +55 -40
  298. package/src/components/context/PickerContext.tsx +567 -92
  299. package/src/components/context/PickerDataContext.tsx +114 -99
  300. package/src/components/emoji/BaseEmojiProps.ts +5 -4
  301. package/src/components/emoji/ClickableEmojiButton.tsx +148 -63
  302. package/src/components/emoji/Emoji.tsx +24 -2
  303. package/src/components/emoji/EmojiImg.tsx +13 -12
  304. package/src/components/emoji/ExportedEmoji.tsx +5 -4
  305. package/src/components/emoji/NativeEmoji.tsx +19 -16
  306. package/src/components/emoji/ViewOnlyEmoji.tsx +55 -30
  307. package/src/components/emoji/emojiStyles.ts +12 -11
  308. package/src/components/footer/Preview.tsx +86 -91
  309. package/src/components/header/Header.tsx +21 -6
  310. package/src/components/header/Search/BtnClearSearch.tsx +69 -55
  311. package/src/components/header/Search/IcnSearch.tsx +21 -21
  312. package/src/components/header/Search/Search.tsx +79 -137
  313. package/src/components/header/SkinTonePicker/BtnSkinToneVariation.tsx +99 -62
  314. package/src/components/header/SkinTonePicker/SkinTonePicker.tsx +84 -46
  315. package/src/components/icons/svgIcons.ts +17 -0
  316. package/src/components/main/PickerMainBehaviors.tsx +163 -0
  317. package/src/components/main/defaultAppearance.tsx +189 -0
  318. package/src/components/main/labelHeight.ts +5 -0
  319. package/src/components/navigation/CategoryButton.tsx +83 -57
  320. package/src/components/navigation/CategoryNavIcon.tsx +73 -194
  321. package/src/components/navigation/CategoryNavigation.tsx +118 -46
  322. package/src/config/categoryConfig.ts +7 -3
  323. package/src/config/cdnUrls.ts +11 -21
  324. package/src/config/compareConfig.ts +128 -30
  325. package/src/config/config.ts +228 -24
  326. package/src/config/defaultPickerConfiguration.ts +7 -0
  327. package/src/config/mutableConfig.ts +44 -20
  328. package/src/config/useConfig.ts +130 -37
  329. package/src/data/defaultEmojiData.ts +49 -0
  330. package/src/data/registerDefaultEmojiData.ts +8 -0
  331. package/src/data/skinToneVariations.ts +8 -7
  332. package/src/data-core/pickerData.ts +171 -0
  333. package/src/data-core/prepare.ts +163 -0
  334. package/src/data-core/search.ts +122 -0
  335. package/src/data-core/types.ts +36 -0
  336. package/src/data.ts +10 -0
  337. package/src/dataUtils/DataTypes.ts +4 -0
  338. package/src/dataUtils/emojiSelectors.ts +59 -63
  339. package/src/dataUtils/emojiUtils.ts +17 -74
  340. package/src/dataUtils/nativeEmojiSequenceSupport.ts +116 -0
  341. package/src/dataUtils/nativeEmojiSupport.ts +160 -0
  342. package/src/dataUtils/parseNativeEmoji.ts +3 -4
  343. package/src/dataUtils/suggested.ts +8 -4
  344. package/src/dataUtils/suggestedEmojis.ts +92 -0
  345. package/src/env.d.ts +4 -0
  346. package/src/hooks/preloadEmoji.ts +2 -47
  347. package/src/hooks/useActiveCategoryScrollDetection.ts +28 -16
  348. package/src/hooks/useCategoryHeight.ts +116 -10
  349. package/src/hooks/useDataIdentityStabilityWarning.ts +86 -0
  350. package/src/hooks/useDebouncedState.ts +13 -1
  351. package/src/hooks/useDisallowedEmojis.ts +31 -42
  352. package/src/hooks/useEmojiPreviewEvents.ts +43 -10
  353. package/src/hooks/useEmojiVirtualization.tsx +112 -52
  354. package/src/hooks/useFilter.ts +92 -132
  355. package/src/hooks/useFocus.ts +14 -24
  356. package/src/hooks/useIsEmojiHidden.ts +22 -14
  357. package/src/hooks/useKeyboardNavigation.ts +412 -432
  358. package/src/hooks/useMouseDownHandlers.ts +91 -16
  359. package/src/hooks/useOnFocus.ts +12 -3
  360. package/src/hooks/useOnScroll.ts +18 -2
  361. package/src/hooks/useReactionsFocus.ts +118 -0
  362. package/src/hooks/useRegisterRegion.ts +92 -0
  363. package/src/hooks/useResolvedEmojiData.ts +200 -0
  364. package/src/hooks/useScrollCategoryIntoView.ts +74 -12
  365. package/src/hooks/useSearchController.ts +369 -0
  366. package/src/hooks/useSearchResults.ts +51 -0
  367. package/src/hooks/useSetVariationPicker.ts +4 -1
  368. package/src/index.tsx +67 -5
  369. package/src/primitives/CategoryNav.tsx +40 -0
  370. package/src/primitives/Empty.tsx +68 -0
  371. package/src/primitives/List.tsx +61 -0
  372. package/src/primitives/LoadError.tsx +38 -0
  373. package/src/primitives/Loading.tsx +60 -0
  374. package/src/primitives/Panel.tsx +47 -0
  375. package/src/primitives/Preview.tsx +38 -0
  376. package/src/primitives/Reactions.tsx +2 -0
  377. package/src/primitives/Root.tsx +398 -0
  378. package/src/primitives/Search.tsx +41 -0
  379. package/src/primitives/SearchInput.tsx +110 -0
  380. package/src/primitives/SkinTone.tsx +76 -0
  381. package/src/primitives/Viewport.tsx +204 -0
  382. package/src/primitives/appearance.tsx +7 -0
  383. package/src/primitives/components.tsx +30 -0
  384. package/src/primitives/hooks.ts +165 -0
  385. package/src/primitives/index.ts +94 -0
  386. package/src/primitives/nativeProps.ts +90 -0
  387. package/src/primitives/scope.tsx +109 -0
  388. package/src/primitives/structuralStyles.tsx +136 -0
  389. package/src/primitives/tokens.ts +150 -0
  390. package/src/primitives/types.ts +192 -0
  391. package/src/state/activeEmojiStore.ts +39 -0
  392. package/src/state/navigationRegistry.ts +209 -0
  393. package/src/state/regionTraversal.ts +116 -0
  394. package/src/svg.d.ts +2 -2
  395. package/src/types/exposedTypes.ts +28 -1
  396. package/src/virtualization/virtualizationHelpers.ts +29 -8
  397. package/dist/components/body/Body.d.ts +0 -2
  398. package/dist/components/main/PickerMain.d.ts +0 -7
  399. package/dist/dataUtils/alphaNumericEmojiIndex.d.ts +0 -5
  400. package/dist/emoji-picker-react.cjs.development.js +0 -31413
  401. package/dist/emoji-picker-react.cjs.development.js.map +0 -1
  402. package/dist/emoji-picker-react.cjs.production.min.js +0 -2
  403. package/dist/emoji-picker-react.cjs.production.min.js.map +0 -1
  404. package/dist/emoji-picker-react.esm.js +0 -31411
  405. package/dist/emoji-picker-react.esm.js.map +0 -1
  406. package/dist/hooks/useHideEmojisByUniocode.d.ts +0 -1
  407. package/src/components/body/Body.tsx +0 -43
  408. package/src/components/main/PickerMain.tsx +0 -249
  409. package/src/dataUtils/alphaNumericEmojiIndex.ts +0 -21
@@ -0,0 +1,204 @@
1
+ import * as React from 'react';
2
+ import { cx } from 'shipstyles';
3
+
4
+ import { ClassNames } from '../DomUtils/classNames';
5
+ import { stylesheet } from '../Stylesheet/stylesheet';
6
+ import { EmojiVariationPicker } from '../components/body/EmojiVariationPicker';
7
+ import { useBodyRef } from '../components/context/ElementRefContext';
8
+ import {
9
+ useActiveEmojiState,
10
+ useNavigationRegistry,
11
+ useVisibleCategoriesState,
12
+ } from '../components/context/PickerContext';
13
+ import { useActiveCategory } from '../components/navigation/CategoryNavigation';
14
+ import { MOUSE_EVENT_SOURCE, useCategoriesConfig } from '../config/useConfig';
15
+ import { useActiveCategoryScrollDetection } from '../hooks/useActiveCategoryScrollDetection';
16
+ import { useOnMouseMove } from '../hooks/useDisallowMouseMove';
17
+ import { useEmojiPreviewEvents } from '../hooks/useEmojiPreviewEvents';
18
+ import { useMouseDownHandlers } from '../hooks/useMouseDownHandlers';
19
+ import { useOnScroll } from '../hooks/useOnScroll';
20
+ import { useSingletonClaim } from '../hooks/useRegisterRegion';
21
+
22
+ import { filterPrimitiveProps, useMergedRefs } from './nativeProps';
23
+ import {
24
+ useRootScope,
25
+ ViewportScopeProvider,
26
+ ViewportScrollContext,
27
+ __resetPrimitiveWarningsForTest,
28
+ } from './scope';
29
+
30
+ // Re-exported for tests.
31
+ export { __resetPrimitiveWarningsForTest };
32
+
33
+ /* global process: readonly */
34
+
35
+ export type ViewportProps = Omit<
36
+ React.HTMLAttributes<HTMLDivElement>,
37
+ 'role' | 'children' | 'dangerouslySetInnerHTML'
38
+ > & {
39
+ /**
40
+ * The scrolled content: one `<List>` (it may be wrapped, e.g. by a
41
+ * styling library), optionally with `<Empty>` and `<Loading>`.
42
+ */
43
+ children: React.ReactNode;
44
+ };
45
+
46
+ const warnedViewportChildren = new Set<string>();
47
+
48
+ // Composition is validated by behavior, not element identity: List
49
+ // enforces being inside a Viewport (context) and being unique (grid
50
+ // region singleton). Matching `child.type === List` broke under anything
51
+ // that wraps elements — Emotion's css prop, styled(List), memo/HOCs.
52
+ // What remains is a development hint when a Viewport mounts without a
53
+ // List.
54
+ const useWarnWithoutList =
55
+ process.env.NODE_ENV === 'production'
56
+ ? () => undefined
57
+ : useDevWarnWithoutList;
58
+
59
+ function useDevWarnWithoutList(): void {
60
+ const registry = useNavigationRegistry();
61
+ React.useEffect(() => {
62
+ if (
63
+ process.env.NODE_ENV !== 'production' &&
64
+ registry.getRegionsByKind('grid').length === 0 &&
65
+ !warnedViewportChildren.has('missing-list')
66
+ ) {
67
+ warnedViewportChildren.add('missing-list');
68
+ // eslint-disable-next-line no-console
69
+ console.warn(
70
+ '[emoji-picker-react] <Viewport> mounted without a <List>; it ' +
71
+ 'renders no emoji grid. See docs/v5/PRIMITIVES.md.',
72
+ );
73
+ }
74
+ }, [registry]);
75
+ }
76
+
77
+ // A Viewport without a height constraint grows to the whole dataset:
78
+ // nothing scrolls, so virtualization renders every emoji (~1,900 buttons).
79
+ // A bare Root has no default height, so this is an easy first mistake.
80
+ const useWarnUnboundedViewport: (
81
+ BodyRef: React.MutableRefObject<HTMLElement | null>,
82
+ ) => void =
83
+ process.env.NODE_ENV === 'production'
84
+ ? () => undefined
85
+ : useDevWarnUnboundedViewport;
86
+
87
+ function useDevWarnUnboundedViewport(
88
+ BodyRef: React.MutableRefObject<HTMLElement | null>,
89
+ ): void {
90
+ React.useEffect(() => {
91
+ const viewport = BodyRef.current;
92
+ if (
93
+ process.env.NODE_ENV === 'production' ||
94
+ !viewport ||
95
+ typeof ResizeObserver === 'undefined' ||
96
+ warnedViewportChildren.has('unbounded')
97
+ ) {
98
+ return;
99
+ }
100
+ const observer = new ResizeObserver(() => {
101
+ const unbounded =
102
+ viewport.clientHeight > window.innerHeight * 2 &&
103
+ viewport.scrollHeight <= viewport.clientHeight + 1;
104
+ if (!unbounded || warnedViewportChildren.has('unbounded')) return;
105
+ warnedViewportChildren.add('unbounded');
106
+ observer.disconnect();
107
+ // eslint-disable-next-line no-console
108
+ console.warn(
109
+ '[emoji-picker-react] <Viewport> has no height limit, so every ' +
110
+ 'emoji renders at once. Give Root a height.',
111
+ );
112
+ });
113
+ observer.observe(viewport);
114
+ return () => observer.disconnect();
115
+ }, [BodyRef]);
116
+ }
117
+
118
+ /** Test-only: reset warn-once sets between cases. */
119
+ export function __resetViewportWarningsForTest(): void {
120
+ warnedViewportChildren.clear();
121
+ }
122
+
123
+ // Public Viewport primitive.
124
+ //
125
+ // Scroll/measurement container: owns the scroll position, dismissal of
126
+ // transient toggles on scroll, and the managed variation-picker overlay.
127
+ // At most one Viewport is supported per Root. The single List child owns
128
+ // the grid; no consumer children are accepted anywhere else.
129
+ export const Viewport = /* @__PURE__ */ React.forwardRef<
130
+ HTMLDivElement,
131
+ ViewportProps
132
+ >(function Viewport(props, forwardedRef) {
133
+ const inScope = useRootScope('Viewport');
134
+ useSingletonClaim('viewport');
135
+ const { children, ...rest } = props;
136
+ const nativeProps = filterPrimitiveProps(rest as Record<string, unknown>, [
137
+ 'role',
138
+ ]);
139
+ useWarnWithoutList();
140
+
141
+ const BodyRef = useBodyRef();
142
+ const mergedRef = useMergedRefs(forwardedRef, BodyRef);
143
+ const scrollTop = useOnScroll(BodyRef);
144
+ useWarnUnboundedViewport(BodyRef);
145
+ useMouseDownHandlers(BodyRef, MOUSE_EVENT_SOURCE.PICKER);
146
+ useOnMouseMove();
147
+
148
+ const { className, style, ...restNative } =
149
+ nativeProps as React.HTMLAttributes<HTMLDivElement>;
150
+
151
+ if (!inScope) {
152
+ return null;
153
+ }
154
+
155
+ return (
156
+ <div
157
+ {...restNative}
158
+ ref={mergedRef}
159
+ data-epr-part="viewport"
160
+ className={cx(styles.viewport, className)}
161
+ style={style}
162
+ >
163
+ <ViewportScrollContext.Provider value={scrollTop}>
164
+ <ViewportScopeProvider>
165
+ <ViewportObservers />
166
+ <EmojiVariationPicker />
167
+ {children}
168
+ </ViewportScopeProvider>
169
+ </ViewportScrollContext.Provider>
170
+ </div>
171
+ );
172
+ });
173
+
174
+ function ViewportObservers() {
175
+ // Section observation lives with the scroll container, not the tab bar:
176
+ // tracking must continue when CategoryNav unmounts (single tab) or is
177
+ // omitted from a composition entirely.
178
+ const { setActiveCategory } = useActiveCategory();
179
+ const [, setActiveEmoji] = useActiveEmojiState();
180
+ // Hover/focus tracking for Preview and useActiveEmoji lives with the
181
+ // scroll container too, so it works whether or not Preview is rendered.
182
+ useEmojiPreviewEvents(true, setActiveEmoji);
183
+ const [, setVisibleCategories] = useVisibleCategoriesState();
184
+ const categoriesConfig = useCategoriesConfig();
185
+ // The observer re-subscribes when the merged categories reference
186
+ // changes (sections added/removed); the reference is stable otherwise.
187
+ useActiveCategoryScrollDetection({
188
+ setActiveCategory,
189
+ setVisibleCategories,
190
+ categories: categoriesConfig,
191
+ });
192
+ return null;
193
+ }
194
+
195
+ const styles = /* @__PURE__ */ (() =>
196
+ stylesheet.create({
197
+ viewport: {
198
+ '.': ClassNames.scrollBody,
199
+ flex: '1',
200
+ overflowY: 'scroll',
201
+ overflowX: 'hidden',
202
+ position: 'relative',
203
+ },
204
+ }))();
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+
3
+ // Every Root resets appearance ownership, including nested Roots.
4
+ export const AppearanceContext = /* @__PURE__ */ React.createContext(false);
5
+ export function useDefaultAppearance(): boolean {
6
+ return React.useContext(AppearanceContext);
7
+ }
@@ -0,0 +1,30 @@
1
+ import * as React from 'react';
2
+
3
+ import type { ListComponents } from '../components/body/listComponents';
4
+ import type { SkinTones } from '../types/exposedTypes';
5
+
6
+ /** Spread the managed props onto one native button. Render children or your own content. */
7
+ export type CategoryButtonRenderProps =
8
+ React.ButtonHTMLAttributes<HTMLButtonElement> & {
9
+ category: { id: string; name: string; isActive: boolean };
10
+ };
11
+ export type SkinToneButtonRenderProps =
12
+ React.ButtonHTMLAttributes<HTMLButtonElement> & {
13
+ tone: { skinTone: SkinTones; isActive: boolean; isOpen: boolean };
14
+ };
15
+ export type PickerComponents = ListComponents & {
16
+ CategoryButton?: React.ComponentType<CategoryButtonRenderProps>;
17
+ SkinToneButton?: React.ComponentType<SkinToneButtonRenderProps>;
18
+ ExpandButton?: React.ComponentType<
19
+ React.ButtonHTMLAttributes<HTMLButtonElement>
20
+ >;
21
+ ClearButton?: React.ComponentType<
22
+ React.ButtonHTMLAttributes<HTMLButtonElement>
23
+ >;
24
+ };
25
+ export const EMPTY_COMPONENTS: PickerComponents = {};
26
+ export const PickerComponentsContext =
27
+ /* @__PURE__ */ React.createContext<PickerComponents>(EMPTY_COMPONENTS);
28
+ export function usePickerComponents(): PickerComponents {
29
+ return React.useContext(PickerComponentsContext);
30
+ }
@@ -0,0 +1,165 @@
1
+ import * as React from 'react';
2
+
3
+ import {
4
+ useActiveEmojiState,
5
+ useActiveSkinToneState,
6
+ useReactionsModeState,
7
+ } from '../components/context/PickerContext';
8
+ import { usePickerDataContext } from '../components/context/PickerDataContext';
9
+ import {
10
+ useActiveCategory,
11
+ useJumpToCategory,
12
+ useVisibleCategoryConfigs,
13
+ } from '../components/navigation/CategoryNavigation';
14
+ import {
15
+ categoryIdFromCategoryConfig,
16
+ categoryNameFromCategoryConfig,
17
+ } from '../config/categoryConfig';
18
+ import { useMutableConfig } from '../config/mutableConfig';
19
+ import {
20
+ useEmojiStyleConfig,
21
+ useGetEmojiUrlConfig,
22
+ useAllowExpandReactions,
23
+ } from '../config/useConfig';
24
+ import { skinToneFromEmoji } from '../dataUtils/emojiUtils';
25
+ import { emojiClickOutput } from '../hooks/useMouseDownHandlers';
26
+ import {
27
+ useEmojiDataState as useDataState,
28
+ EmojiDataState,
29
+ } from '../hooks/useResolvedEmojiData';
30
+ import {
31
+ useAcceptedSearchValue,
32
+ useSetSearchValue,
33
+ useClearSearchValue,
34
+ } from '../hooks/useSearchController';
35
+ import { useVisibleSearchResultCount } from '../hooks/useSearchResults';
36
+ import { EmojiClickData, SkinTones } from '../types/exposedTypes';
37
+
38
+ import { useRootScope } from './scope';
39
+
40
+ // Public state hooks for custom compositions. Each must be called inside
41
+ // <Root>; they read the same Root-scoped state the managed parts use, so a
42
+ // hand-built preview, skin tone control or empty state stays in sync with
43
+ // the grid, keyboard navigation and callbacks.
44
+
45
+ /**
46
+ * The emoji currently hovered or keyboard-focused in the grid, in the same
47
+ * shape `onEmojiClick` receives, or null. Use it to build a custom preview.
48
+ */
49
+ export function useActiveEmoji(): EmojiClickData | null {
50
+ useRootScope('useActiveEmoji');
51
+ const [activeEmoji] = useActiveEmojiState();
52
+ const [activeSkinTone] = useActiveSkinToneState();
53
+ const { emojiByUnified } = usePickerDataContext();
54
+ const emojiStyle = useEmojiStyleConfig();
55
+ const getEmojiUrl = useGetEmojiUrlConfig();
56
+
57
+ return React.useMemo(() => {
58
+ if (!activeEmoji) {
59
+ return null;
60
+ }
61
+ const emoji = emojiByUnified(
62
+ activeEmoji.unified ?? activeEmoji.originalUnified,
63
+ );
64
+ if (!emoji) {
65
+ return null;
66
+ }
67
+ const skinTone = skinToneFromEmoji(
68
+ emoji,
69
+ activeEmoji.unified,
70
+ activeSkinTone,
71
+ );
72
+ return emojiClickOutput(
73
+ { ...emoji, renderUnified: activeEmoji.unified },
74
+ skinTone,
75
+ emojiStyle,
76
+ getEmojiUrl,
77
+ );
78
+ }, [activeEmoji, activeSkinTone, emojiByUnified, emojiStyle, getEmojiUrl]);
79
+ }
80
+
81
+ /**
82
+ * The active skin tone and a setter that behaves exactly like choosing a
83
+ * tone in the built-in control: it updates the grid and calls
84
+ * `onSkinToneChange` (when `skinTone` is controlled, only the callback
85
+ * fires and the parent decides).
86
+ */
87
+ export function useSkinTone(): [SkinTones, (skinTone: SkinTones) => void] {
88
+ const inScope = useRootScope('useSkinTone');
89
+ const [skinTone, setActiveSkinTone] = useActiveSkinToneState();
90
+ // The mutable config ref is stable and read at call time, so the setter
91
+ // keeps a stable identity and always reaches the latest callback.
92
+ const { current: callbacks } = useMutableConfig();
93
+ const setSkinTone = React.useCallback(
94
+ (next: SkinTones) => {
95
+ if (!inScope) return;
96
+ setActiveSkinTone(next);
97
+ callbacks.onSkinToneChange?.(next);
98
+ },
99
+ [setActiveSkinTone, callbacks, inScope],
100
+ );
101
+ return [skinTone, setSkinTone];
102
+ }
103
+
104
+ export type SearchState = {
105
+ /** Accepted raw search text (controlled value or last committed edit). */
106
+ search: string;
107
+ /**
108
+ * Emojis the list shows for the applied search, or null while no search
109
+ * is applied. Debounced like the list itself.
110
+ */
111
+ resultCount: number | null;
112
+ };
113
+
114
+ /** Read-only search state, e.g. for a custom status line or empty state. */
115
+ export function useSearchState(): SearchState {
116
+ useRootScope('useSearchState');
117
+ const search = useAcceptedSearchValue();
118
+ const resultCount = useVisibleSearchResultCount();
119
+ return React.useMemo(() => ({ search, resultCount }), [search, resultCount]);
120
+ }
121
+
122
+ /** Dataset loading, recoverable failure and retry for this Root. */
123
+ export function useEmojiDataState(): EmojiDataState {
124
+ useRootScope('useEmojiDataState');
125
+ return useDataState();
126
+ }
127
+
128
+ /** Propose/commit raw text. Clear also restores focus to a mounted SearchInput. */
129
+ export function useSearchActions() {
130
+ useRootScope('useSearchActions');
131
+ const setValue = useSetSearchValue();
132
+ const clear = useClearSearchValue();
133
+ return React.useMemo(() => ({ setValue, clear }), [setValue, clear]);
134
+ }
135
+
136
+ /** Public section identities and the same deferred jump used by CategoryNav. */
137
+ export function useCategoryNavigation() {
138
+ useRootScope('useCategoryNavigation');
139
+ const { activeCategory } = useActiveCategory();
140
+ const configs = useVisibleCategoryConfigs();
141
+ const jumpToCategory = useJumpToCategory();
142
+ const categories = configs.map((config) => ({
143
+ id: categoryIdFromCategoryConfig(config),
144
+ name: categoryNameFromCategoryConfig(config),
145
+ }));
146
+ return { categories, activeCategory, jumpToCategory };
147
+ }
148
+
149
+ /** Expansion respects allowExpandReactions; collapse activates the reactions bar. */
150
+ export function usePickerMode() {
151
+ useRootScope('usePickerMode');
152
+ const [reactionsOpen, setReactionsOpen] = useReactionsModeState();
153
+ const canExpand = useAllowExpandReactions();
154
+ const expand = React.useCallback(() => {
155
+ if (canExpand) setReactionsOpen(false);
156
+ }, [canExpand, setReactionsOpen]);
157
+ const collapse = React.useCallback(
158
+ () => setReactionsOpen(true),
159
+ [setReactionsOpen],
160
+ );
161
+ return React.useMemo(
162
+ () => ({ reactionsOpen, canExpand, expand, collapse }),
163
+ [reactionsOpen, canExpand, expand, collapse],
164
+ );
165
+ }
@@ -0,0 +1,94 @@
1
+ export { Root } from './Root';
2
+ export { Panel } from './Panel';
3
+ export type { PanelProps } from './Panel';
4
+ export { Reactions } from './Reactions';
5
+ export type { ReactionsProps } from './Reactions';
6
+ export type {
7
+ PickerComponents,
8
+ CategoryButtonRenderProps,
9
+ SkinToneButtonRenderProps,
10
+ } from './components';
11
+ // Runtime configuration values must stay on this data-free entry: importing
12
+ // them from the main entry also registers its synchronous English dataset.
13
+ export {
14
+ Categories,
15
+ EmojiStyle,
16
+ SkinTones,
17
+ SkinTonePickerLocation,
18
+ SuggestionMode,
19
+ Theme,
20
+ } from '../types/exposedTypes';
21
+ export type {
22
+ CategoryConfig,
23
+ CategoryIcons,
24
+ EmojiClickData,
25
+ EmojiData,
26
+ EmojiStyleValue,
27
+ SkinTonesValue,
28
+ SuggestionModeValue,
29
+ ThemeValue,
30
+ } from '../types/exposedTypes';
31
+ export type {
32
+ PickerLabels,
33
+ PreviewConfig,
34
+ EmojiClickHandler,
35
+ SkinToneChangeHandler,
36
+ OnEmojiClickApi,
37
+ } from '../config/config';
38
+ export type { CustomEmoji } from '../config/customEmojiConfig';
39
+ export {
40
+ defaultPickerTokens,
41
+ structuralPickerTokens,
42
+ lightPickerTokens,
43
+ darkPickerTokens,
44
+ } from './tokens';
45
+ export { Empty } from './Empty';
46
+ export { Loading } from './Loading';
47
+ export { LoadError } from './LoadError';
48
+ export { useEmojiDataState } from './hooks';
49
+ export { SkinTone } from './SkinTone';
50
+ export {
51
+ useActiveEmoji,
52
+ useSkinTone,
53
+ useSearchState,
54
+ useSearchActions,
55
+ useCategoryNavigation,
56
+ usePickerMode,
57
+ } from './hooks';
58
+ export type { SearchState } from './hooks';
59
+ export { Search } from './Search';
60
+ export { SearchInput } from './SearchInput';
61
+ export { CategoryNav } from './CategoryNav';
62
+ export { Viewport } from './Viewport';
63
+ export type { ViewportProps } from './Viewport';
64
+ export { List } from './List';
65
+ export { Preview } from './Preview';
66
+ export type {
67
+ CategoryNavProps,
68
+ EmptyProps,
69
+ LoadingProps,
70
+ LoadErrorProps,
71
+ SkinToneProps,
72
+ ListProps,
73
+ PickerAppearanceProps,
74
+ PickerCompositionProps,
75
+ PreviewProps,
76
+ RootBehaviorProps,
77
+ RootProps,
78
+ SearchProps,
79
+ SearchInputProps,
80
+ SearchInputElement,
81
+ SearchInputComponent,
82
+ } from './types';
83
+ export type {
84
+ CategoryHeaderRenderProps,
85
+ EmojiRenderProps,
86
+ ListComponents,
87
+ ListEmoji,
88
+ } from '../components/body/listComponents';
89
+ export type {
90
+ EmojiDataInput,
91
+ EmojiDataLoader,
92
+ EmojiDataLoaderOptions,
93
+ EmojiDataState,
94
+ } from '../hooks/useResolvedEmojiData';
@@ -0,0 +1,90 @@
1
+ import * as React from 'react';
2
+
3
+ // Native prop forwarding for public primitives.
4
+ //
5
+ // Every primitive forwards ordinary native props valid for its root
6
+ // element (id, non-reserved aria-*, non-reserved data-*, title, className,
7
+ // style, ordinary event handlers). The library owns `role` on every
8
+ // primitive and reserves `data-epr-*`, internal focus-management
9
+ // attributes, and required hidden/inert state.
10
+
11
+ /** Keys never forwarded to the DOM (in addition to `data-epr-*`). */
12
+ export function filterPrimitiveProps(
13
+ props: object,
14
+ reserved: readonly string[],
15
+ ): Record<string, unknown> {
16
+ const forwarded: Record<string, unknown> = {};
17
+ const values = props as Record<string, unknown>;
18
+ for (const key of Object.keys(values)) {
19
+ if (
20
+ reserved.includes(key) ||
21
+ key === 'dangerouslySetInnerHTML' ||
22
+ key === 'children'
23
+ ) {
24
+ continue;
25
+ }
26
+ if (key.startsWith('data-epr-')) {
27
+ continue;
28
+ }
29
+ forwarded[key] = values[key];
30
+ }
31
+ return forwarded;
32
+ }
33
+
34
+ /**
35
+ * Handler composition: the library behavioral handler
36
+ * runs first, the consumer handler second with the same event. Consumer
37
+ * `preventDefault()` is not a supported way to disable required behavior.
38
+ * Event-handler exceptions propagate per normal React/browser behavior;
39
+ * primitives never catch them and no ErrorBoundary is installed.
40
+ */
41
+ export function composeHandlers<E>(
42
+ libraryHandler: ((event: E) => void) | undefined,
43
+ consumerHandler: ((event: E) => void) | undefined,
44
+ ): ((event: E) => void) | undefined {
45
+ if (!libraryHandler) {
46
+ return consumerHandler;
47
+ }
48
+ if (!consumerHandler) {
49
+ return libraryHandler;
50
+ }
51
+ return (event: E) => {
52
+ libraryHandler(event);
53
+ consumerHandler(event);
54
+ };
55
+ }
56
+
57
+ /** Merge any number of refs (context ref + forwarded ref) onto one node. */
58
+ export function mergeRefs<T>(
59
+ ...refs: Array<React.Ref<T> | undefined>
60
+ ): React.RefCallback<T> {
61
+ const cleanups = new Map<React.Ref<T>, () => void>();
62
+ return (node: T | null) => {
63
+ for (const ref of refs) {
64
+ if (!ref) {
65
+ continue;
66
+ }
67
+ if (typeof ref === 'function') {
68
+ const cleanup = cleanups.get(ref);
69
+ if (node === null && cleanup) {
70
+ cleanups.delete(ref);
71
+ cleanup();
72
+ } else {
73
+ const result = (ref as (node: T | null) => unknown)(node);
74
+ if (typeof result === 'function')
75
+ cleanups.set(ref, result as () => void);
76
+ }
77
+ } else {
78
+ (ref as React.MutableRefObject<T | null>).current = node;
79
+ }
80
+ }
81
+ };
82
+ }
83
+
84
+ /** Keep callback refs attached while the refs themselves are unchanged. */
85
+ export function useMergedRefs<T>(
86
+ first: React.Ref<T> | undefined,
87
+ second: React.Ref<T> | undefined,
88
+ ): React.RefCallback<T> {
89
+ return React.useMemo(() => mergeRefs(first, second), [first, second]);
90
+ }
@@ -0,0 +1,109 @@
1
+ import * as React from 'react';
2
+
3
+ /* global process: readonly */
4
+
5
+ // Primitive scope validation.
6
+ //
7
+ // Render-time context validation fails immediately in development:
8
+ // - any primitive outside Root;
9
+ // - List outside Viewport.
10
+ // In production the validators warn once and report out-of-scope so the
11
+ // primitive renders null: production avoids the hard crash, and a null is
12
+ // diagnosable whereas continuing would die later with a confusing
13
+ // TypeError deep inside provider-dependent behavior.
14
+ // Registration-time singleton validation lives in the navigation registry.
15
+ // Server rendering performs only render-time context validation; there is
16
+ // no post-mount validation during SSR. Exact development error text is not
17
+ // semver API.
18
+
19
+ interface RootScope {
20
+ readonly root: true;
21
+ }
22
+
23
+ const RootScopeContext = /* @__PURE__ */ React.createContext<RootScope | null>(
24
+ null,
25
+ );
26
+
27
+ export function RootScopeProvider({ children }: { children: React.ReactNode }) {
28
+ const value = React.useMemo<RootScope>(() => ({ root: true }), []);
29
+ return (
30
+ <RootScopeContext.Provider value={value}>
31
+ {children}
32
+ </RootScopeContext.Provider>
33
+ );
34
+ }
35
+
36
+ const warnedOutsideRoot = new Set<string>();
37
+
38
+ export function useRootScope(primitive: string): boolean {
39
+ const scope = React.useContext(RootScopeContext);
40
+ if (scope) {
41
+ return true;
42
+ }
43
+ if (process.env.NODE_ENV === 'production') {
44
+ if (!warnedOutsideRoot.has(primitive)) {
45
+ warnedOutsideRoot.add(primitive);
46
+ // eslint-disable-next-line no-console
47
+ console.warn(
48
+ `[emoji-picker-react] <${primitive}> rendered outside <Root>.`,
49
+ );
50
+ }
51
+ return false;
52
+ }
53
+ throw new Error(
54
+ (primitive.startsWith('use')
55
+ ? `[emoji-picker-react] ${primitive}() must be called inside <Root>. `
56
+ : `[emoji-picker-react] <${primitive}> must be rendered inside <Root>. `) +
57
+ `See docs/v5/PRIMITIVES.md composition grammar.`,
58
+ );
59
+ }
60
+
61
+ const ViewportScopeContext =
62
+ /* @__PURE__ */ React.createContext<boolean>(false);
63
+
64
+ export const ViewportScrollContext =
65
+ /* @__PURE__ */ React.createContext<number>(0);
66
+
67
+ export function useViewportScrollTop(): number {
68
+ return React.useContext(ViewportScrollContext);
69
+ }
70
+ export function ViewportScopeProvider({
71
+ children,
72
+ }: {
73
+ children: React.ReactNode;
74
+ }) {
75
+ return (
76
+ <ViewportScopeContext.Provider value={true}>
77
+ {children}
78
+ </ViewportScopeContext.Provider>
79
+ );
80
+ }
81
+
82
+ const warnedOutsideViewport = new Set<string>();
83
+
84
+ export function useViewportScope(primitive: string): boolean {
85
+ const inside = React.useContext(ViewportScopeContext);
86
+ if (inside) {
87
+ return true;
88
+ }
89
+ if (process.env.NODE_ENV === 'production') {
90
+ if (!warnedOutsideViewport.has(primitive)) {
91
+ warnedOutsideViewport.add(primitive);
92
+ // eslint-disable-next-line no-console
93
+ console.warn(
94
+ `[emoji-picker-react] <${primitive}> must be inside <Viewport>.`,
95
+ );
96
+ }
97
+ return false;
98
+ }
99
+ throw new Error(
100
+ `[emoji-picker-react] <${primitive}> must be rendered inside ` +
101
+ `<Viewport>. See docs/v5/PRIMITIVES.md composition grammar.`,
102
+ );
103
+ }
104
+
105
+ /** Test-only: reset warn-once sets between cases. */
106
+ export function __resetPrimitiveWarningsForTest(): void {
107
+ warnedOutsideRoot.clear();
108
+ warnedOutsideViewport.clear();
109
+ }