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.
Files changed (405) hide show
  1. package/README.md +331 -49
  2. package/dist/DomUtils/categoryNameFromDom.d.ts +1 -1
  3. package/dist/DomUtils/classNames.d.ts +24 -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 +7 -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-core/pickerData.d.ts +12 -0
  183. package/dist/data-core/prepare.d.ts +23 -0
  184. package/dist/data-core/search.d.ts +13 -0
  185. package/dist/data-core/types.d.ts +23 -0
  186. package/dist/data.d.mts +72 -0
  187. package/dist/data.d.ts +72 -0
  188. package/dist/dataUtils/DataTypes.d.ts +23 -19
  189. package/dist/dataUtils/emojiSelectors.d.ts +15 -16
  190. package/dist/dataUtils/emojiUtils.d.ts +1 -12
  191. package/dist/dataUtils/nativeEmojiSequenceSupport.d.ts +10 -0
  192. package/dist/dataUtils/nativeEmojiSupport.d.ts +40 -0
  193. package/dist/dataUtils/parseNativeEmoji.d.ts +1 -1
  194. package/dist/dataUtils/suggested.d.ts +11 -11
  195. package/dist/dataUtils/suggestedEmojis.d.ts +7 -0
  196. package/dist/esm/chunks/chunk-46BUDQLE.mjs +228 -0
  197. package/dist/esm/chunks/chunk-7ZGTUZFB.mjs +16 -0
  198. package/dist/esm/chunks/chunk-FQIJ4HBW.mjs +25 -0
  199. package/dist/esm/chunks/chunk-KQPOIRSC.mjs +9305 -0
  200. package/dist/esm/chunks/chunk-LO4TPPLH.mjs +43 -0
  201. package/dist/esm/chunks/emojis-6L3GRBAP.mjs +9 -0
  202. package/dist/esm/data.mjs +18 -0
  203. package/dist/esm/index.mjs +389 -0
  204. package/dist/esm/primitives/index.mjs +67 -0
  205. package/dist/hooks/preloadEmoji.d.ts +9 -9
  206. package/dist/hooks/useActiveCategoryScrollDetection.d.ts +11 -11
  207. package/dist/hooks/useCategoryHeight.d.ts +6 -5
  208. package/dist/hooks/useCloseAllOpenToggles.d.ts +2 -2
  209. package/dist/hooks/useDataIdentityStabilityWarning.d.ts +13 -0
  210. package/dist/hooks/useDebouncedState.d.ts +1 -1
  211. package/dist/hooks/useDisallowMouseMove.d.ts +4 -4
  212. package/dist/hooks/useDisallowedEmojis.d.ts +2 -3
  213. package/dist/hooks/useEmojiPreviewEvents.d.ts +3 -3
  214. package/dist/hooks/useEmojiVirtualization.d.ts +21 -17
  215. package/dist/hooks/useFilter.d.ts +10 -16
  216. package/dist/hooks/useFocus.d.ts +3 -3
  217. package/dist/hooks/useInitialLoad.d.ts +2 -2
  218. package/dist/hooks/useIsEmojiHidden.d.ts +8 -8
  219. package/dist/hooks/useIsMounted.d.ts +1 -1
  220. package/dist/hooks/useIsSearchMode.d.ts +1 -1
  221. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
  222. package/dist/hooks/useKeyboardNavigation.d.ts +3 -1
  223. package/dist/hooks/useMouseDownHandlers.d.ts +8 -4
  224. package/dist/hooks/useOnFocus.d.ts +1 -1
  225. package/dist/hooks/useOnScroll.d.ts +2 -2
  226. package/dist/hooks/useReactionsFocus.d.ts +1 -0
  227. package/dist/hooks/useRegisterRegion.d.ts +24 -0
  228. package/dist/hooks/useResolvedEmojiData.d.ts +37 -0
  229. package/dist/hooks/useScrollCategoryIntoView.d.ts +1 -1
  230. package/dist/hooks/useSearchController.d.ts +17 -0
  231. package/dist/hooks/useSearchResults.d.ts +8 -0
  232. package/dist/hooks/useSetVariationPicker.d.ts +2 -2
  233. package/dist/hooks/useShouldHideCustomEmojis.d.ts +1 -1
  234. package/dist/hooks/useShouldShowSkinTonePicker.d.ts +4 -4
  235. package/dist/index.d.mts +376 -0
  236. package/dist/index.d.ts +376 -9
  237. package/dist/index.js +2 -8
  238. package/dist/primitives/CategoryNav.d.ts +4 -0
  239. package/dist/primitives/Empty.d.ts +6 -0
  240. package/dist/primitives/List.d.ts +4 -0
  241. package/dist/primitives/LoadError.d.ts +8 -0
  242. package/dist/primitives/Loading.d.ts +4 -0
  243. package/dist/primitives/Panel.d.ts +3 -0
  244. package/dist/primitives/Preview.d.ts +3 -0
  245. package/dist/primitives/Reactions.d.ts +2 -0
  246. package/dist/primitives/Root.d.ts +26 -0
  247. package/dist/primitives/Search.d.ts +5 -0
  248. package/dist/primitives/SearchInput.d.ts +3 -0
  249. package/dist/primitives/SkinTone.d.ts +4 -0
  250. package/dist/primitives/Viewport.d.ts +19 -0
  251. package/dist/primitives/appearance.d.ts +3 -0
  252. package/dist/primitives/components.d.ts +27 -0
  253. package/dist/primitives/hooks.d.ts +48 -0
  254. package/dist/primitives/index.d.mts +561 -0
  255. package/dist/primitives/index.d.ts +561 -0
  256. package/dist/primitives/index.js +2 -0
  257. package/dist/primitives/nativeProps.d.ts +15 -0
  258. package/dist/primitives/scope.d.ts +13 -0
  259. package/dist/primitives/structuralStyles.d.ts +16 -0
  260. package/dist/primitives/tokens.d.ts +18 -0
  261. package/dist/primitives/types.d.ts +85 -0
  262. package/dist/state/activeEmojiStore.d.ts +7 -0
  263. package/dist/state/navigationRegistry.d.ts +61 -0
  264. package/dist/state/regionTraversal.d.ts +20 -0
  265. package/dist/typeRefinements/typeRefinements.d.ts +6 -6
  266. package/dist/types/exposedTypes.d.ts +16 -6
  267. package/dist/types/exposedTypes.js +5 -0
  268. package/dist/virtualization/virtualizationHelpers.d.ts +20 -18
  269. package/llms-full.txt +3680 -0
  270. package/llms.txt +66 -480
  271. package/package.json +180 -66
  272. package/src/DomUtils/categoryNameFromDom.ts +1 -1
  273. package/src/DomUtils/classNames.ts +1 -0
  274. package/src/DomUtils/elementPositionInRow.ts +26 -4
  275. package/src/DomUtils/eventBelongsToPicker.ts +17 -0
  276. package/src/DomUtils/getActiveElement.ts +7 -1
  277. package/src/DomUtils/isJsdom.ts +12 -0
  278. package/src/DomUtils/isRtl.ts +5 -0
  279. package/src/DomUtils/keyboardNavigation.ts +105 -149
  280. package/src/DomUtils/scrollTo.ts +18 -16
  281. package/src/DomUtils/selectors.ts +20 -111
  282. package/src/EmojiPickerReact.tsx +155 -48
  283. package/src/Stylesheet/DedupedStyle.tsx +80 -0
  284. package/src/Stylesheet/stylesheet.tsx +128 -59
  285. package/src/components/Layout/Flex.tsx +12 -11
  286. package/src/components/Reactions/BtnPlus.tsx +61 -51
  287. package/src/components/Reactions/Reactions.tsx +113 -55
  288. package/src/components/atoms/Button.tsx +18 -15
  289. package/src/components/body/EmojiCategory.tsx +77 -40
  290. package/src/components/body/EmojiList.tsx +55 -23
  291. package/src/components/body/EmojiVariationPicker.tsx +113 -66
  292. package/src/components/body/MeasureEmoji.tsx +9 -2
  293. package/src/components/body/listComponents.tsx +79 -0
  294. package/src/components/context/ElementRefContext.tsx +46 -35
  295. package/src/components/context/PickerConfigContext.tsx +55 -40
  296. package/src/components/context/PickerContext.tsx +567 -92
  297. package/src/components/context/PickerDataContext.tsx +110 -99
  298. package/src/components/emoji/BaseEmojiProps.ts +5 -4
  299. package/src/components/emoji/ClickableEmojiButton.tsx +148 -63
  300. package/src/components/emoji/Emoji.tsx +24 -2
  301. package/src/components/emoji/EmojiImg.tsx +13 -12
  302. package/src/components/emoji/ExportedEmoji.tsx +5 -4
  303. package/src/components/emoji/NativeEmoji.tsx +19 -16
  304. package/src/components/emoji/ViewOnlyEmoji.tsx +55 -30
  305. package/src/components/emoji/emojiStyles.ts +12 -11
  306. package/src/components/footer/Preview.tsx +86 -91
  307. package/src/components/header/Header.tsx +21 -6
  308. package/src/components/header/Search/BtnClearSearch.tsx +69 -55
  309. package/src/components/header/Search/IcnSearch.tsx +21 -21
  310. package/src/components/header/Search/Search.tsx +77 -137
  311. package/src/components/header/SkinTonePicker/BtnSkinToneVariation.tsx +99 -62
  312. package/src/components/header/SkinTonePicker/SkinTonePicker.tsx +84 -46
  313. package/src/components/icons/svgIcons.ts +17 -0
  314. package/src/components/main/PickerMainBehaviors.tsx +163 -0
  315. package/src/components/main/defaultAppearance.tsx +188 -0
  316. package/src/components/main/labelHeight.ts +5 -0
  317. package/src/components/navigation/CategoryButton.tsx +83 -57
  318. package/src/components/navigation/CategoryNavIcon.tsx +73 -194
  319. package/src/components/navigation/CategoryNavigation.tsx +118 -46
  320. package/src/config/categoryConfig.ts +7 -3
  321. package/src/config/cdnUrls.ts +11 -21
  322. package/src/config/compareConfig.ts +128 -30
  323. package/src/config/config.ts +228 -24
  324. package/src/config/defaultPickerConfiguration.ts +7 -0
  325. package/src/config/mutableConfig.ts +44 -20
  326. package/src/config/useConfig.ts +130 -37
  327. package/src/data/defaultEmojiData.ts +49 -0
  328. package/src/data/registerDefaultEmojiData.ts +8 -0
  329. package/src/data-core/pickerData.ts +173 -0
  330. package/src/data-core/prepare.ts +178 -0
  331. package/src/data-core/search.ts +122 -0
  332. package/src/data-core/types.ts +36 -0
  333. package/src/data.ts +10 -0
  334. package/src/dataUtils/DataTypes.ts +4 -0
  335. package/src/dataUtils/emojiSelectors.ts +58 -63
  336. package/src/dataUtils/emojiUtils.ts +17 -74
  337. package/src/dataUtils/nativeEmojiSequenceSupport.ts +116 -0
  338. package/src/dataUtils/nativeEmojiSupport.ts +160 -0
  339. package/src/dataUtils/suggested.ts +8 -4
  340. package/src/dataUtils/suggestedEmojis.ts +92 -0
  341. package/src/env.d.ts +4 -0
  342. package/src/hooks/preloadEmoji.ts +3 -3
  343. package/src/hooks/useActiveCategoryScrollDetection.ts +10 -1
  344. package/src/hooks/useCategoryHeight.ts +82 -8
  345. package/src/hooks/useDataIdentityStabilityWarning.ts +86 -0
  346. package/src/hooks/useDebouncedState.ts +13 -1
  347. package/src/hooks/useDisallowedEmojis.ts +26 -42
  348. package/src/hooks/useEmojiPreviewEvents.ts +43 -10
  349. package/src/hooks/useEmojiVirtualization.tsx +38 -4
  350. package/src/hooks/useFilter.ts +85 -127
  351. package/src/hooks/useFocus.ts +14 -24
  352. package/src/hooks/useIsEmojiHidden.ts +10 -6
  353. package/src/hooks/useKeyboardNavigation.ts +322 -429
  354. package/src/hooks/useMouseDownHandlers.ts +91 -16
  355. package/src/hooks/useOnFocus.ts +12 -3
  356. package/src/hooks/useOnScroll.ts +18 -2
  357. package/src/hooks/useReactionsFocus.ts +118 -0
  358. package/src/hooks/useRegisterRegion.ts +92 -0
  359. package/src/hooks/useResolvedEmojiData.ts +200 -0
  360. package/src/hooks/useScrollCategoryIntoView.ts +74 -12
  361. package/src/hooks/useSearchController.ts +369 -0
  362. package/src/hooks/useSearchResults.ts +51 -0
  363. package/src/hooks/useSetVariationPicker.ts +4 -1
  364. package/src/index.tsx +67 -5
  365. package/src/primitives/CategoryNav.tsx +40 -0
  366. package/src/primitives/Empty.tsx +68 -0
  367. package/src/primitives/List.tsx +61 -0
  368. package/src/primitives/LoadError.tsx +38 -0
  369. package/src/primitives/Loading.tsx +60 -0
  370. package/src/primitives/Panel.tsx +47 -0
  371. package/src/primitives/Preview.tsx +38 -0
  372. package/src/primitives/Reactions.tsx +2 -0
  373. package/src/primitives/Root.tsx +398 -0
  374. package/src/primitives/Search.tsx +41 -0
  375. package/src/primitives/SearchInput.tsx +110 -0
  376. package/src/primitives/SkinTone.tsx +76 -0
  377. package/src/primitives/Viewport.tsx +204 -0
  378. package/src/primitives/appearance.tsx +7 -0
  379. package/src/primitives/components.tsx +30 -0
  380. package/src/primitives/hooks.ts +165 -0
  381. package/src/primitives/index.ts +94 -0
  382. package/src/primitives/nativeProps.ts +90 -0
  383. package/src/primitives/scope.tsx +109 -0
  384. package/src/primitives/structuralStyles.tsx +133 -0
  385. package/src/primitives/tokens.ts +149 -0
  386. package/src/primitives/types.ts +192 -0
  387. package/src/state/activeEmojiStore.ts +39 -0
  388. package/src/state/navigationRegistry.ts +209 -0
  389. package/src/state/regionTraversal.ts +116 -0
  390. package/src/svg.d.ts +2 -2
  391. package/src/types/exposedTypes.ts +28 -1
  392. package/src/virtualization/virtualizationHelpers.ts +20 -6
  393. package/dist/components/body/Body.d.ts +0 -2
  394. package/dist/components/main/PickerMain.d.ts +0 -7
  395. package/dist/dataUtils/alphaNumericEmojiIndex.d.ts +0 -5
  396. package/dist/emoji-picker-react.cjs.development.js +0 -31413
  397. package/dist/emoji-picker-react.cjs.development.js.map +0 -1
  398. package/dist/emoji-picker-react.cjs.production.min.js +0 -2
  399. package/dist/emoji-picker-react.cjs.production.min.js.map +0 -1
  400. package/dist/emoji-picker-react.esm.js +0 -31411
  401. package/dist/emoji-picker-react.esm.js.map +0 -1
  402. package/dist/hooks/useHideEmojisByUniocode.d.ts +0 -1
  403. package/src/components/body/Body.tsx +0 -43
  404. package/src/components/main/PickerMain.tsx +0 -249
  405. package/src/dataUtils/alphaNumericEmojiIndex.ts +0 -21
@@ -0,0 +1,122 @@
1
+ // Pure v5 data operations shared by the picker and `emoji-picker-react/data`.
2
+ // No React / ShipStyles imports allowed in this module graph.
3
+
4
+ import { getPreparedCore, normalizeQuery, normalizeUnified } from './prepare';
5
+ import type { EmojiDataOptions, EmojiInfo } from './types';
6
+
7
+ export type { EmojiDataOptions, EmojiInfo };
8
+
9
+ const EMPTY_RESULTS: readonly EmojiInfo[] = Object.freeze([]);
10
+
11
+ /**
12
+ * Bound on distinct memoized queries per prepared core. The memo is shared
13
+ * process-wide per dataset identity (including server use), so unbounded
14
+ * growth is a leak: evict the least recently used entry past this size.
15
+ * 500 distinct recent queries is generous for interactive sessions while
16
+ * keeping worst-case memory proportional to one result window.
17
+ */
18
+ const MAX_QUERY_MEMO_SIZE = 500;
19
+
20
+ function memoizeQuery(
21
+ core: ReturnType<typeof getPreparedCore>,
22
+ normalized: string,
23
+ results: readonly EmojiInfo[],
24
+ ): void {
25
+ const memo = core.queryMemo;
26
+ if (memo.has(normalized)) {
27
+ memo.delete(normalized);
28
+ } else if (memo.size >= MAX_QUERY_MEMO_SIZE) {
29
+ const oldest = memo.keys().next();
30
+ if (!oldest.done) {
31
+ memo.delete(oldest.value);
32
+ }
33
+ }
34
+ memo.set(normalized, results);
35
+ }
36
+
37
+ /**
38
+ * A record whose names contain the query contains every query character,
39
+ * so it sits in each of those characters' buckets. Scanning the smallest
40
+ * one (buckets keep record order) yields exactly the full-scan matches in
41
+ * the same order, for a fraction of the records.
42
+ */
43
+ function smallestCandidateBucket(
44
+ core: ReturnType<typeof getPreparedCore>,
45
+ normalized: string,
46
+ ): readonly EmojiInfo[] {
47
+ let smallest: readonly EmojiInfo[] = core.records;
48
+ // Code points, matching how buckets are keyed (astral chars stay whole).
49
+ for (const char of Array.from(normalized)) {
50
+ const bucket = core.byChar.get(char);
51
+ if (!bucket) {
52
+ return EMPTY_RESULTS;
53
+ }
54
+ if (bucket.length < smallest.length) {
55
+ smallest = bucket;
56
+ }
57
+ }
58
+ return smallest;
59
+ }
60
+
61
+ /**
62
+ * Lookup by base or variation unified code.
63
+ * Trims/lowercases input, returns the canonical base record or undefined.
64
+ */
65
+ export function getEmojiByUnified(
66
+ unified: string,
67
+ options?: EmojiDataOptions,
68
+ ): EmojiInfo | undefined {
69
+ if (!unified || typeof unified !== 'string') {
70
+ return undefined;
71
+ }
72
+ const normalized = normalizeUnified(unified);
73
+ if (!normalized) {
74
+ return undefined;
75
+ }
76
+ const core = getPreparedCore(options?.emojiData);
77
+ return core.byUnified.get(normalized);
78
+ }
79
+
80
+ /**
81
+ * Dataset search (not a snapshot of one picker instance's visible results).
82
+ * Picker-only layers such as emojiVersion/hiddenEmojis/customEmojis are
83
+ * intentionally not applied here; they remain Root-local filters.
84
+ */
85
+ export function searchEmojis(
86
+ query: string,
87
+ options?: EmojiDataOptions,
88
+ ): readonly EmojiInfo[] {
89
+ const normalized = normalizeQuery(query);
90
+ if (!normalized) {
91
+ return EMPTY_RESULTS;
92
+ }
93
+
94
+ const core = getPreparedCore(options?.emojiData);
95
+ const memoized = core.queryMemo.get(normalized);
96
+ if (memoized) {
97
+ memoizeQuery(core, normalized, memoized);
98
+ return Object.freeze([...memoized]) as readonly EmojiInfo[];
99
+ }
100
+
101
+ // Single-character queries hit the prepared bucket (same membership as
102
+ // a full scan: joined names contain the char iff some name includes it).
103
+ if (normalized.length === 1) {
104
+ const bucket = core.byChar.get(normalized) ?? EMPTY_RESULTS;
105
+ memoizeQuery(core, normalized, bucket);
106
+ return Object.freeze([...bucket]) as readonly EmojiInfo[];
107
+ }
108
+
109
+ const matches: EmojiInfo[] = [];
110
+ for (const record of smallestCandidateBucket(core, normalized)) {
111
+ const names = record.names;
112
+ for (let i = 0; i < names.length; i += 1) {
113
+ if (names[i].includes(normalized)) {
114
+ matches.push(record);
115
+ break;
116
+ }
117
+ }
118
+ }
119
+
120
+ memoizeQuery(core, normalized, matches);
121
+ return Object.freeze([...matches]) as readonly EmojiInfo[];
122
+ }
@@ -0,0 +1,36 @@
1
+ // v5 pure shared data core types.
2
+ //
3
+ // This module is intentionally free of React and ShipStyles imports so the
4
+ // `emoji-picker-react/data` entry can share it without pulling UI runtime.
5
+
6
+ import type { EmojiData } from '../types/exposedTypes';
7
+
8
+ export type { EmojiData };
9
+
10
+ export type EmojiInfo = Readonly<{
11
+ /** Canonical/base lowercase unified code. */
12
+ unified: string;
13
+
14
+ /** The native emoji text for `unified`, ready to insert or render. */
15
+ emoji: string;
16
+
17
+ /** Display name: the dataset's full name (the last of `names`). */
18
+ name: string;
19
+
20
+ /** Search/display names in dataset order. */
21
+ names: readonly string[];
22
+
23
+ /** Lowercase unified codes for supported variations. */
24
+ variations: readonly string[];
25
+
26
+ /** Unicode/emoji version from the dataset. */
27
+ addedIn: string;
28
+ }>;
29
+
30
+ export type EmojiDataOptions = Readonly<{
31
+ /**
32
+ * Optional dataset in the same shape accepted by the picker's emojiData prop.
33
+ * Omit for the packaged default English dataset.
34
+ */
35
+ emojiData?: EmojiData;
36
+ }>;
package/src/data.ts ADDED
@@ -0,0 +1,10 @@
1
+ // Public v5 data entry point: `emoji-picker-react/data`.
2
+ //
3
+ // Additive to the existing top-level `emojiByUnified` export. Presents a
4
+ // normalized, documented shape and shares the pure data core with the picker.
5
+ // Must not import React or ShipStyles (enforced by npm run check:package).
6
+
7
+ import './data/registerDefaultEmojiData';
8
+
9
+ export { getEmojiByUnified, searchEmojis } from './data-core/search';
10
+ export type { EmojiData, EmojiDataOptions, EmojiInfo } from './data-core/types';
@@ -9,6 +9,10 @@ export enum EmojiProperties {
9
9
  }
10
10
 
11
11
  export interface DataEmoji extends WithName {
12
+ /** Exact rendered identity; canonical unified remains the search identity. */
13
+ renderUnified?: string;
14
+ /** Stored recent identity when the active tone has no matching variation. */
15
+ fallbackUnified?: string;
12
16
  [EmojiProperties.unified]: string;
13
17
  [EmojiProperties.variations]?: string[];
14
18
  [EmojiProperties.added_in]: string;
@@ -2,24 +2,21 @@
2
2
  // imports no React components, hooks, or context providers so it can never
3
3
  // form an import cycle with them. Context-aware lookups live in
4
4
  // components/context/PickerDataContext instead.
5
- import { Categories } from '../config/categoryConfig';
6
5
  import { cdnUrl } from '../config/cdnUrls';
7
- import { CustomEmoji } from '../config/customEmojiConfig';
8
- import emojis from '../data/emojis';
6
+ import { getRegisteredDefaultEmojiData } from '../data/defaultEmojiData';
9
7
  import skinToneVariations, {
10
8
  skinTonesMapped,
11
9
  } from '../data/skinToneVariations';
12
- import { EmojiStyle, SkinTones } from '../types/exposedTypes';
10
+ import { EmojiData, EmojiStyleValue, SkinTones } from '../types/exposedTypes';
13
11
 
14
- import { DataEmoji, DataEmojis, EmojiProperties, WithName } from './DataTypes';
15
- import { indexEmoji } from './alphaNumericEmojiIndex';
12
+ import { DataEmoji, EmojiProperties, WithName } from './DataTypes';
16
13
 
17
14
  export function emojiNames(emoji: WithName): string[] {
18
15
  return emoji[EmojiProperties.name] ?? [];
19
16
  }
20
17
 
21
18
  export function addedIn(emoji: DataEmoji): number {
22
- return parseFloat(emoji[EmojiProperties.added_in]);
19
+ return parseFloat(emoji[EmojiProperties.added_in] || '0');
23
20
  }
24
21
 
25
22
  export function emojiName(emoji?: WithName): string {
@@ -42,20 +39,23 @@ export function unifiedWithoutSkinTone(unified: string): string {
42
39
  return unified;
43
40
  }
44
41
 
45
- export function emojiUnified(emoji: DataEmoji, skinTone?: string): string {
46
- const unified = emoji[EmojiProperties.unified];
47
-
48
- if (!skinTone || !emojiHasVariations(emoji)) {
49
- return unified;
50
- }
42
+ export function emojiCanonicalUnified(emoji: DataEmoji): string {
43
+ return emoji[EmojiProperties.unified];
44
+ }
51
45
 
52
- return emojiVariationUnified(emoji, skinTone) ?? unified;
46
+ export function emojiUnified(emoji: DataEmoji, skinTone?: string): string {
47
+ return (
48
+ emoji.renderUnified ??
49
+ (skinTone ? emojiVariationUnified(emoji, skinTone) : undefined) ??
50
+ emoji.fallbackUnified ??
51
+ emojiCanonicalUnified(emoji)
52
+ );
53
53
  }
54
54
 
55
55
  // WARNING: DO NOT USE DIRECTLY
56
56
  export function emojiUrlByUnified(
57
57
  unified: string,
58
- emojiStyle: EmojiStyle,
58
+ emojiStyle: EmojiStyleValue,
59
59
  ): string {
60
60
  return `${cdnUrl(emojiStyle)}${unified}.png`;
61
61
  }
@@ -77,67 +77,62 @@ export function emojiVariationUnified(
77
77
  : emojiUnified(emoji);
78
78
  }
79
79
 
80
+ // Legacy global lookup (the public top-level `emojiByUnified` export) over
81
+ // the registered default dataset. Indexed lazily on first use and again
82
+ // only if the registered dataset changes, so importing this module costs
83
+ // nothing and does not pull the dataset into a bundle.
84
+ let indexedSource: EmojiData | null = null;
85
+ let allEmojisByUnified: Record<string, DataEmoji> = Object.create(null);
86
+
87
+ function registryIndex(): Record<string, DataEmoji> {
88
+ const source = getRegisteredDefaultEmojiData();
89
+ if (source === indexedSource) {
90
+ return allEmojisByUnified;
91
+ }
92
+ indexedSource = source;
93
+ allEmojisByUnified = Object.create(null);
94
+ const groups = source?.emojis ?? {};
95
+ for (const group of Object.keys(groups)) {
96
+ for (const emoji of groups[group]) {
97
+ allEmojisByUnified[emojiUnified(emoji)] = emoji;
98
+ emojiVariations(emoji).forEach((variation) => {
99
+ allEmojisByUnified[variation] = emoji;
100
+ });
101
+ }
102
+ }
103
+ return allEmojisByUnified;
104
+ }
105
+
80
106
  export function emojiByUnified(unified?: string): DataEmoji | undefined {
81
107
  if (!unified) {
82
108
  return;
83
109
  }
84
110
 
85
- if (allEmojisByUnified[unified]) {
86
- return allEmojisByUnified[unified];
111
+ const index = registryIndex();
112
+ if (index[unified]) {
113
+ return index[unified];
87
114
  }
88
115
 
89
116
  const withoutSkinTone = unifiedWithoutSkinTone(unified);
90
- return allEmojisByUnified[withoutSkinTone];
117
+ return index[withoutSkinTone];
91
118
  }
92
119
 
93
- export const allEmojis: DataEmojis = Object.values(emojis.emojis).flat();
94
-
95
- export function setCustomEmojis(customEmojis: CustomEmoji[]): void {
96
- emojis.emojis[Categories.CUSTOM].length = 0;
97
-
98
- customEmojis.forEach((emoji) => {
99
- const emojiData = customToRegularEmoji(emoji);
100
-
101
- emojis.emojis[Categories.CUSTOM].push(emojiData as never);
102
-
103
- if (allEmojisByUnified[emojiData[EmojiProperties.unified]]) {
104
- return;
105
- }
106
-
107
- allEmojis.push(emojiData);
108
- allEmojisByUnified[emojiData[EmojiProperties.unified]] = emojiData;
109
- indexEmoji(emojiData);
110
- });
111
- }
112
-
113
- function customToRegularEmoji(emoji: CustomEmoji): DataEmoji {
114
- return {
115
- [EmojiProperties.name]: emoji.names.map((name) => name.toLowerCase()),
116
- [EmojiProperties.unified]: emoji.id.toLowerCase(),
117
- [EmojiProperties.added_in]: '0',
118
- [EmojiProperties.imgUrl]: emoji.imgUrl,
119
- };
120
- }
121
-
122
- const allEmojisByUnified: {
123
- [unified: string]: DataEmoji;
124
- } = {};
125
-
126
- allEmojis.reduce((allEmojis, Emoji) => {
127
- allEmojis[emojiUnified(Emoji)] = Emoji;
128
-
129
- if (emojiHasVariations(Emoji)) {
130
- emojiVariations(Emoji).forEach((variation) => {
131
- allEmojis[variation] = Emoji;
132
- });
133
- }
134
-
135
- return allEmojis;
136
- }, allEmojisByUnified);
137
-
138
120
  export function activeVariationFromUnified(unified: string): SkinTones | null {
139
121
  const [, suspectedSkinTone] = unified.split('-') as [string, SkinTones];
140
122
  return skinToneVariations.includes(suspectedSkinTone)
141
123
  ? suspectedSkinTone
142
124
  : null;
143
125
  }
126
+
127
+ // A button's exact identity is authoritative, including an explicit neutral
128
+ // variation. Preview metadata and selection share this resolution.
129
+ export function skinToneFromEmoji(
130
+ emoji: DataEmoji,
131
+ unified: string,
132
+ activeTone: SkinTones,
133
+ ): SkinTones {
134
+ return (
135
+ activeVariationFromUnified(unified) ??
136
+ (emojiHasVariations(emoji) ? SkinTones.NEUTRAL : activeTone)
137
+ );
138
+ }
@@ -1,74 +1,17 @@
1
- import { cdnUrl } from '../config/cdnUrls';
2
- import { skinTonesMapped } from '../data/skinToneVariations';
3
- import { EmojiStyle, SkinTones } from '../types/exposedTypes';
4
-
5
- import { DataEmoji, EmojiProperties, WithName } from './DataTypes';
6
-
7
- export function emojiNames(emoji: WithName): string[] {
8
- return emoji[EmojiProperties.name] ?? [];
9
- }
10
-
11
- export function addedIn(emoji: DataEmoji): number {
12
- return parseFloat(emoji[EmojiProperties.added_in] || '0');
13
- }
14
-
15
- export function emojiName(emoji?: WithName): string {
16
- if (!emoji) {
17
- return '';
18
- }
19
-
20
- const names = emojiNames(emoji);
21
- return names[names.length - 1];
22
- }
23
-
24
- export function unifiedWithoutSkinTone(unified: string): string {
25
- const splat = unified.split('-');
26
- const [skinTone] = splat.splice(1, 1);
27
-
28
- if (skinTonesMapped[skinTone]) {
29
- return splat.join('-');
30
- }
31
-
32
- return unified;
33
- }
34
-
35
- export function emojiUnified(emoji: DataEmoji, skinTone?: string): string {
36
- const unified = emoji[EmojiProperties.unified];
37
-
38
- if (!skinTone || !emojiHasVariations(emoji)) {
39
- return unified;
40
- }
41
-
42
- return emojiVariationUnified(emoji, skinTone) ?? unified;
43
- }
44
-
45
- export function emojiUrlByUnified(
46
- unified: string,
47
- emojiStyle: EmojiStyle,
48
- ): string {
49
- return `${cdnUrl(emojiStyle)}${unified}.png`;
50
- }
51
-
52
- export function emojiVariations(emoji: DataEmoji): string[] {
53
- return emoji[EmojiProperties.variations] ?? [];
54
- }
55
-
56
- export function emojiHasVariations(emoji: DataEmoji): boolean {
57
- return emojiVariations(emoji).length > 0;
58
- }
59
-
60
- export function emojiVariationUnified(
61
- emoji: DataEmoji,
62
- skinTone?: string,
63
- ): string | undefined {
64
- return skinTone
65
- ? emojiVariations(emoji).find((variation) => variation.includes(skinTone))
66
- : emojiUnified(emoji);
67
- }
68
-
69
- export function activeVariationFromUnified(unified: string): SkinTones | null {
70
- const [, suspectedSkinTone] = unified.split('-') as [string, SkinTones];
71
- return Object.keys(skinTonesMapped).includes(suspectedSkinTone)
72
- ? suspectedSkinTone
73
- : null;
74
- }
1
+ // Compatibility surface for the pure emoji helpers. The implementation lives
2
+ // in ./emojiSelectors (one copy in the bundle); this module only re-exports
3
+ // it so the many existing import sites keep working.
4
+ export {
5
+ activeVariationFromUnified,
6
+ skinToneFromEmoji,
7
+ addedIn,
8
+ emojiHasVariations,
9
+ emojiName,
10
+ emojiNames,
11
+ emojiUnified,
12
+ emojiCanonicalUnified,
13
+ emojiUrlByUnified,
14
+ emojiVariations,
15
+ emojiVariationUnified,
16
+ unifiedWithoutSkinTone,
17
+ } from './emojiSelectors';
@@ -0,0 +1,116 @@
1
+ import { parseNativeEmoji } from './parseNativeEmoji';
2
+
3
+ const CELL = 32;
4
+ export const NATIVE_PROBE_BATCH = 64;
5
+ type Candidate = [unified: string, text: string, comparison: string];
6
+
7
+ /** One reusable canvas and result cache per detected document/font. */
8
+ export function createNativeEmojiSequenceSupport(
9
+ ctx: CanvasRenderingContext2D,
10
+ baselineWidth: number,
11
+ ) {
12
+ const results = new Map<string, boolean | null>();
13
+ const font = ctx.font;
14
+
15
+ function prime(ids: Iterable<string>): void {
16
+ const candidates: Candidate[] = [];
17
+ for (const unified of ids) {
18
+ if (results.has(unified)) continue;
19
+ // Also deduplicates identities queued in this synchronous batch.
20
+ results.set(unified, null);
21
+ try {
22
+ const text = parseNativeEmoji(unified);
23
+ const width = ctx.measureText(text).width;
24
+ // Uncombined joins, modifiers and flags occupy multiple advances.
25
+ if (width <= 0 || width >= baselineWidth * 1.5) {
26
+ results.set(unified, false);
27
+ } else {
28
+ candidates.push([
29
+ unified,
30
+ text,
31
+ text.replace(/[\u{e0020}-\u{e007f}]/gu, ''),
32
+ ]);
33
+ }
34
+ } catch {
35
+ // Invalid identities/restricted rendering stay inconclusive.
36
+ }
37
+ }
38
+ for (
39
+ let offset = 0;
40
+ offset < candidates.length;
41
+ offset += NATIVE_PROBE_BATCH
42
+ ) {
43
+ probe(candidates.slice(offset, offset + NATIVE_PROBE_BATCH));
44
+ }
45
+ }
46
+
47
+ function draw(text: string, y: number, ink: string): void {
48
+ // Glyph overhang must not contaminate a neighboring cell's pixels.
49
+ ctx.save();
50
+ ctx.beginPath();
51
+ ctx.rect(0, y, CELL, CELL);
52
+ ctx.clip();
53
+ ctx.fillStyle = ink;
54
+ ctx.fillText(text, 0, y);
55
+ ctx.restore();
56
+ }
57
+
58
+ function probe(candidates: Candidate[]): void {
59
+ try {
60
+ const height = candidates.length * CELL;
61
+ ctx.canvas.width = CELL;
62
+ ctx.canvas.height = height * 2;
63
+ ctx.font = font;
64
+ ctx.textBaseline = 'top';
65
+ candidates.forEach(([, text, comparison], index) => {
66
+ const y = index * CELL;
67
+ draw(text, y, '#000');
68
+ draw(comparison, y + height, text === comparison ? '#f00' : '#000');
69
+ });
70
+ // One readback per bounded atlas instead of one per sequence.
71
+ const pixels = ctx.getImageData(0, 0, CELL, height * 2).data;
72
+ const artwork = new Uint32Array(
73
+ pixels.buffer,
74
+ pixels.byteOffset,
75
+ pixels.length / 4,
76
+ );
77
+ candidates.forEach(([unified, text, comparison], index) => {
78
+ const start = index * CELL * CELL;
79
+ let alpha = 0;
80
+ let difference = 0;
81
+ for (let pixel = start; pixel < start + CELL * CELL; pixel++) {
82
+ alpha |= pixels[pixel * 4 + 3];
83
+ difference |= artwork[pixel] ^ artwork[pixel + CELL * height];
84
+ }
85
+ // Ordinary emoji artwork must ignore text ink (including grayscale
86
+ // artwork). A subdivision flag must differ from its tagless black
87
+ // flag fallback; unsupported tag sequences silently draw that flag.
88
+ results.set(
89
+ unified,
90
+ alpha !== 0 &&
91
+ (text === comparison ? difference === 0 : difference !== 0),
92
+ );
93
+ });
94
+ } catch {
95
+ // A blocked/unavailable readback must not empty the picker.
96
+ for (const [unified] of candidates) results.set(unified, null);
97
+ }
98
+ }
99
+
100
+ return {
101
+ prime,
102
+ supports(unified: string): boolean | null {
103
+ // Direct callers get an answer for any identity. Pickers read
104
+ // snapshots instead, so rendering never draws on the canvas.
105
+ if (!results.has(unified)) prime([unified]);
106
+ return results.get(unified) as boolean | null;
107
+ },
108
+ /** Whether an identity was probed (results may still be null). */
109
+ has: (unified: string): boolean => results.has(unified),
110
+ /** Frozen results so far. Unprobed identities read as undefined. */
111
+ snapshot(): (unified: string) => boolean | null | undefined {
112
+ const frozen = new Map(results);
113
+ return (unified) => frozen.get(unified);
114
+ },
115
+ };
116
+ }