emoji-picker-react 5.1.0 → 5.1.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.
- package/README.md +29 -1
- package/dist/DomUtils/classNames.d.ts +0 -1
- package/dist/DomUtils/keyboardNavigation.d.ts +5 -1
- package/dist/DomUtils/selectors.d.ts +2 -2
- package/dist/config/defaultPickerConfiguration.d.ts +1 -1
- package/dist/data/index.js +1 -1
- package/dist/data/skinToneVariations.js +2 -2
- package/dist/esm/chunks/chunk-6LOWV5AK.mjs +144 -0
- package/dist/esm/chunks/chunk-DDDACPJK.mjs +6825 -0
- package/dist/esm/chunks/chunk-G75AG4FD.mjs +6 -0
- package/dist/esm/chunks/chunk-ZOAKI5M6.mjs +8025 -18
- package/dist/esm/chunks/deferredPicker-A6MWDDKH.mjs +113 -0
- package/dist/esm/chunks/emojis-VTEL5M5C.mjs +3 -6
- package/dist/esm/data.mjs +6 -9
- package/dist/esm/index.mjs +226 -333
- package/dist/esm/primitives/index.mjs +5 -65
- package/dist/hooks/preloadEmoji.d.ts +0 -4
- package/dist/hooks/searchHighlight.d.ts +3 -5
- package/dist/hooks/useCategoryHeight.d.ts +2 -1
- package/dist/hooks/useEmojiVirtualization.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/primitives/Root.d.ts +2 -2
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.d.ts +2 -2
- package/dist/primitives/index.js +1 -1
- package/dist/virtualization/virtualizationHelpers.d.ts +2 -0
- package/llms-full.txt +181 -21
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/dist/esm/chunks/chunk-3NQHPTFV.mjs +0 -9
- package/dist/esm/chunks/chunk-FJVAS6PR.mjs +0 -214
- package/dist/esm/chunks/chunk-L4H5QY3X.mjs +0 -9509
- package/dist/esm/chunks/searchHighlight-7NH7OJ5Q.mjs +0 -134
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare const OVERSCAN_ROWS = 2;
|
|
2
|
+
export declare function isJustBelowViewport(top: number, bottom: number, size: number): boolean;
|
|
1
3
|
export declare function shouldVirtualize({ scrollTop, clientHeight, topOffset, style, dimensions, }: {
|
|
2
4
|
scrollTop: number;
|
|
3
5
|
clientHeight: number;
|
package/llms-full.txt
CHANGED
|
@@ -53,23 +53,24 @@ Contents:
|
|
|
53
53
|
1. Agent integration guide (docs/v5/AGENT_GUIDE.md): installed-version discovery, batteries included/BYOD, typed input/cell contracts, localization and verification
|
|
54
54
|
2. Copyable integration prompts (docs/v5/PROMPTS.md): setup, brand styling, design-library composition, recipe adoption and v4-to-v5 migration
|
|
55
55
|
3. README (README.md): overview, quick start, choosing a path, styling with any solution, common tasks
|
|
56
|
-
4.
|
|
57
|
-
5.
|
|
58
|
-
6.
|
|
59
|
-
7.
|
|
60
|
-
8.
|
|
61
|
-
9.
|
|
62
|
-
10.
|
|
63
|
-
11.
|
|
64
|
-
12. Styling
|
|
65
|
-
13.
|
|
66
|
-
14.
|
|
67
|
-
15. Migrating from
|
|
68
|
-
16.
|
|
69
|
-
17.
|
|
70
|
-
18.
|
|
71
|
-
19.
|
|
72
|
-
20.
|
|
56
|
+
4. Emoji picker comparison (docs/v5/COMPARISON.md): v5 versus Emoji Mart, Frimousse and emoji-picker-element: capabilities, v5 APIs and audited sources
|
|
57
|
+
5. Props reference (PROPS.md): every prop of the default <EmojiPicker />
|
|
58
|
+
6. CSS variables (CSS_VARIABLES.md): every --epr-* design token
|
|
59
|
+
7. Customization (CUSTOMIZATION.md): custom emojis and groups, category icons, preview, CSP nonce
|
|
60
|
+
8. Internationalization (INTERNATIONALIZATION.md): locale datasets and labels
|
|
61
|
+
9. Adoption (docs/v5/ADOPTION.md): native input, loading recovery, registry installation and source downloads
|
|
62
|
+
10. v5 API (docs/v5/API.md): all v5 additions with examples
|
|
63
|
+
11. Primitives (docs/v5/PRIMITIVES.md): composable parts, hooks, custom cells, grammar
|
|
64
|
+
12. Styling (docs/v5/STYLING.md): tokens, parts, cascade, structural rules
|
|
65
|
+
13. Styling recipes by library (docs/v5/STYLING_RECIPES.md): theme, unstyled and composed snippets for plain CSS, CSS Modules, Tailwind, shadcn/ui, Emotion, styled-components and MUI
|
|
66
|
+
14. Data API (docs/v5/DATA_API.md): framework-free search and lookup
|
|
67
|
+
15. Migrating from v4 (docs/v5/MIGRATION.md): what changed and how to upgrade
|
|
68
|
+
16. Migrating from emoji-mart (docs/v5/MIGRATING_FROM_EMOJI_MART.md): prop and payload mapping, size comparison, CSP
|
|
69
|
+
17. Website examples (website/README.md): typed customization, locale loading and composition
|
|
70
|
+
18. Design recipes (stories/recipes/README.md): 25 designs, each in seven styling stacks
|
|
71
|
+
19. Styling integrations (stories/integrations/README.md): shadcn/ui, Tailwind, Emotion, styled-components, CSS Modules, CSS, MUI
|
|
72
|
+
20. Example app (example/README.md): Vite + React 19 app running the batteries-included, unstyled, composed and data-API paths
|
|
73
|
+
21. Worked example: team chat picker composition (stories/recipes/team-chat/picker.tsx; picker only, demo app chrome excluded)
|
|
73
74
|
|
|
74
75
|
<!-- source: docs/v5/AGENT_GUIDE.md -->
|
|
75
76
|
|
|
@@ -463,7 +464,7 @@ One emoji-picker engine, with two ways to build your UI: use the complete picker
|
|
|
463
464
|
|
|
464
465
|
[](https://www.npmjs.com/package/emoji-picker-react)
|
|
465
466
|
|
|
466
|
-
**[Live demo](https://ealush.com/emoji-picker-react)** · **[Quick start](#quick-start)** · **[Props](PROPS.md)** · **[BYOD](#byod-bring-your-own-design)** · **[Common tasks](#common-tasks)** · **[For AI assistants](#for-ai-assistants)** · **[Report a bug](https://github.com/ealush/emoji-picker-react/issues)** · **[Sponsor](https://github.com/sponsors/ealush)**
|
|
467
|
+
**[Live demo](https://ealush.com/emoji-picker-react)** · **[Quick start](#quick-start)** · **[Props](PROPS.md)** · **[Compare pickers](#compare-emoji-pickers)** · **[BYOD](#byod-bring-your-own-design)** · **[Common tasks](#common-tasks)** · **[For AI assistants](#for-ai-assistants)** · **[Report a bug](https://github.com/ealush/emoji-picker-react/issues)** · **[Sponsor](https://github.com/sponsors/ealush)**
|
|
467
468
|
|
|
468
469
|

|
|
469
470
|
|
|
@@ -524,6 +525,34 @@ See [PROPS.md](PROPS.md) for every prop.
|
|
|
524
525
|
|
|
525
526
|
> **Upgrading from v4?** Most code works unchanged; the default emoji style is now native, and markup, styling and package boundaries have changed. See [Migrating from v4](docs/v5/MIGRATION.md). The APIs on this page need `emoji-picker-react@5` or later.
|
|
526
527
|
|
|
528
|
+
## Compare emoji pickers
|
|
529
|
+
|
|
530
|
+
v5 supports both a complete styled picker and unstyled React composition,
|
|
531
|
+
with custom image emoji, recents, category navigation and reactions built in.
|
|
532
|
+
|
|
533
|
+
| Capability | emoji-picker-react v5 | Emoji Mart + React wrapper | Frimousse | emoji-picker-element |
|
|
534
|
+
| --- | --- | --- | --- | --- |
|
|
535
|
+
| Complete styled picker | Built in | Built in | Compose/style parts or use shadcn starter | Built in |
|
|
536
|
+
| Unstyled React primitives | Built in | No React primitives API | Built in | Web component |
|
|
537
|
+
| Keyboard navigation, search and skin tones | Built in | Built in | Built in | Built in |
|
|
538
|
+
| Localized search and UI | Built in | Built in | Built in | Built in |
|
|
539
|
+
| Native glyph support filtering | Built in | Built in | Built in for default data resolver | Built in |
|
|
540
|
+
| Custom image emoji and named groups | Built in | Built in | Custom data and cell rendering | Built in |
|
|
541
|
+
| Recent/frequent emoji | Built in | Built in | App-owned | Built-in favorites |
|
|
542
|
+
| Category navigation controls | Built in | Built in | App-owned | Built in |
|
|
543
|
+
| Compact reactions bar with expansion | Built in | App-owned | App-owned | App-owned |
|
|
544
|
+
| Standalone emoji search API | Framework-free `/data` entry | `SearchIndex` | Metadata lookup only | Browser `Database` API |
|
|
545
|
+
| Persistent dataset cache | Remote cache policy is app-owned | Remote cache policy is app-owned | Built-in localStorage cache | Built-in IndexedDB cache |
|
|
546
|
+
|
|
547
|
+
“App-owned” means the application implements the feature. Custom renderers and
|
|
548
|
+
data resolvers can extend the supplied behavior. Bundled data in
|
|
549
|
+
emoji-picker-react and Emoji Mart can be used offline without a remote cache.
|
|
550
|
+
|
|
551
|
+
Audited October 20, 2026 against Emoji Mart 5.6.0 / React wrapper 1.1.1,
|
|
552
|
+
Frimousse 0.4.0 and emoji-picker-element 1.29.1. See the
|
|
553
|
+
[full comparison and sources](docs/v5/COMPARISON.md) for API details,
|
|
554
|
+
v5 capabilities, native-detection limits and data-loading APIs.
|
|
555
|
+
|
|
527
556
|
## Copyable integration prompts
|
|
528
557
|
|
|
529
558
|
Use the [setup, customization, recipe adoption and v5 migration prompts](docs/v5/PROMPTS.md)
|
|
@@ -878,6 +907,132 @@ Contributions are welcome — see the [Contributing Guide](https://github.com/ea
|
|
|
878
907
|
|
|
879
908
|
Design inspiration by [Pavel Bolo](https://pavelbolo.com).
|
|
880
909
|
|
|
910
|
+
<!-- source: docs/v5/COMPARISON.md -->
|
|
911
|
+
|
|
912
|
+
<!-- Emoji picker comparison -->
|
|
913
|
+
|
|
914
|
+
# Comparing emoji pickers
|
|
915
|
+
|
|
916
|
+
**Audited October 20, 2026.** This comparison covers **emoji-picker-react v5**
|
|
917
|
+
in this repository, Emoji Mart (`emoji-mart` 5.6.0 with `@emoji-mart/react`
|
|
918
|
+
1.1.1), Frimousse 0.4.0 and emoji-picker-element 1.29.1. Competitor sources
|
|
919
|
+
below are pinned to their published release commits. Earlier comparisons of
|
|
920
|
+
emoji-picker-react v4 do not describe v5's unstyled mode, primitives, custom
|
|
921
|
+
components, controlled state or data loaders.
|
|
922
|
+
|
|
923
|
+
Emoji Mart is an established complete picker with a React wrapper; Frimousse
|
|
924
|
+
is a direct comparison for unstyled React composition; emoji-picker-element
|
|
925
|
+
provides a framework-independent web-component alternative. PicMo is excluded
|
|
926
|
+
from the table because its [repository was archived in September 2023](https://github.com/joeattardi/picmo).
|
|
927
|
+
|
|
928
|
+
## Capability comparison
|
|
929
|
+
|
|
930
|
+
**Built in** means a supported public API. **App-owned** means the application
|
|
931
|
+
supplies that feature; it is not a built-in picker API in the audited version.
|
|
932
|
+
Custom renderers and data resolvers can extend a library beyond its defaults.
|
|
933
|
+
The table compares capabilities, not identical prop names or component trees.
|
|
934
|
+
|
|
935
|
+
| Capability | emoji-picker-react v5 | [Emoji Mart][mart-readme] + React wrapper | [Frimousse][frimousse-api] | [emoji-picker-element][element-readme] |
|
|
936
|
+
| --- | --- | --- | --- | --- |
|
|
937
|
+
| Complete styled picker | Built in: `<EmojiPicker />`, no CSS import | Built in | Compose and style parts; shadcn starter available | Built in: `<emoji-picker>` |
|
|
938
|
+
| Unstyled React primitives and custom layout | Built in: `/primitives`; `unstyled` also keeps the supplied layout | No React primitives API; configurable web component | Built in | No React primitives API; web component |
|
|
939
|
+
| Custom input, emoji cells and category headers | `SearchInput as`, `components`, `List components` | Configurable icons and appearance; no React input/cell slots | Native Search props; List component replacements | CSS/custom shadow styles; no React input/cell slots |
|
|
940
|
+
| Styling with Tailwind, CSS Modules or CSS-in-JS | Classes, styles, parts, tokens, optional cascade layer | CSS variables and shadow-root styles | Classes, styles and part attributes | CSS variables and shadow-root styles |
|
|
941
|
+
| Keyboard navigation and accessible semantics | Built in | Built in | Built in | Built in |
|
|
942
|
+
| List rendering strategy | Virtualized rows | Visibility-based row rendering | Virtualized rows | Category panels; custom-category rendering containment |
|
|
943
|
+
| Controlled search from application state | `searchValue` / `onSearchChange`; search actions hook | No documented controlled-search prop | Controlled Search `value` / `onChange` | No documented controlled-search prop |
|
|
944
|
+
| Hovered/focused emoji preview | `Preview` or `useActiveEmoji()` | Built-in preview with position options | `ActiveEmoji` or `useActiveEmoji()` | App-owned preview |
|
|
945
|
+
| Skin tones and custom tone controls | `SkinTone`, controlled state, `useSkinTone()` | Built-in selector and `skin` option | `SkinToneSelector`, `SkinTone`, `useSkinTone()` | Built-in selector, change event and database preference API |
|
|
946
|
+
| Localized emoji search and UI | 28 packaged datasets; `labels` and category/preview configuration | `locale`, `i18n` and supplied data | 28 default locales; native props, custom content and data resolver | `locale`, `i18n` and localized `dataSource` |
|
|
947
|
+
| Hide unsupported native glyphs | Version/flag probes plus checks of visible sequences and variants | Native version/flag detection | Default resolver detects version/flag support | Native support detection, including ZWJ checks |
|
|
948
|
+
| Category navigation controls | `CategoryNav`, custom buttons, navigation hook | Built-in navigation and icon options | App-owned; no built-in category navigation API | Built-in category tabs |
|
|
949
|
+
| Recent/frequent emoji | Built in; also accepts supplied suggestions | Built-in frequent category | App-owned | Built-in favorites |
|
|
950
|
+
| Custom image emoji and named groups | Built in: `customEmojis` | Built in: `custom` categories | Custom data/cell rendering; no built-in image-emoji API | Built in: `customEmoji` categories |
|
|
951
|
+
| Native and vendor image sets | Native, Apple, Google, Facebook, Twitter; URL override | Native, Apple, Google, Facebook, Twitter; spritesheet override | Native; other rendering through custom cells | Native/custom font; custom image emoji |
|
|
952
|
+
| Compact reactions bar that expands to the picker | Built in; also composable with `Reactions` / `Panel` | App-owned | App-owned | App-owned |
|
|
953
|
+
| Bundled or self-hosted data | Packaged datasets, object input or async loader | Separate data package, object input or async loader | Default CDN; alternate URL or sync/async resolver | Fetch from configurable `dataSource` |
|
|
954
|
+
| Custom loading and empty states | `Loading`, `Empty` | App-owned loading UI; configurable no-results appearance | `Loading`, `Empty` | Built-in loading/error messages via `i18n` |
|
|
955
|
+
| Recoverable data-error UI | `LoadError`, retry hook, abortable loader | App-owned | App-owned | Built-in error message; no documented retry control |
|
|
956
|
+
| Persistent emoji-dataset cache | Bundled data works offline; remote cache policy is app-owned | Bundled data works offline; remote cache policy is app-owned | Built-in localStorage cache/revalidation; `createEmojiDataCache` for custom data | Built-in IndexedDB cache/revalidation; IndexedDB required |
|
|
957
|
+
| Search/metadata outside the picker | Framework-free `/data`: search and unified-code lookup | `SearchIndex` and native-emoji lookup after `init` | `getEmojiDetails` / `useEmojiDetails`; no standalone search API | Separate browser `Database`: search and lookup |
|
|
958
|
+
| React compatibility | React 16.8–19 | Wrapper declares React 16.8, 17 and 18 | React 18 and 19 | Framework-independent; integrate as a custom element |
|
|
959
|
+
| License | MIT | MIT | MIT | Apache-2.0 |
|
|
960
|
+
|
|
961
|
+
All four provide keyboard behavior and accessibility support. This audit
|
|
962
|
+
reviews APIs and source; it does not rank screen-reader quality or certify
|
|
963
|
+
accessibility. v5's [browser accessibility tests](../../playwright/a11y-reactions-focus.spec.ts)
|
|
964
|
+
exercise keyboard focus and axe checks.
|
|
965
|
+
Native-glyph detection is heuristic in every picker; see v5's
|
|
966
|
+
[detection limits](./API.md#5c-native-emoji-support-detection).
|
|
967
|
+
|
|
968
|
+
## Capabilities in v5
|
|
969
|
+
|
|
970
|
+
v5 provides a complete styled picker and composable primitives backed by the
|
|
971
|
+
same engine. Choose the supplied layout, remove its appearance with `unstyled`,
|
|
972
|
+
or compose your own controls and layout. Search, virtualization, keyboard
|
|
973
|
+
navigation and localization stay built in across these paths.
|
|
974
|
+
|
|
975
|
+
| Capability | emoji-picker-react v5 API |
|
|
976
|
+
| --- | --- |
|
|
977
|
+
| Complete styled picker | Render `<EmojiPicker />`; theme it with `colorScheme` and `--epr-*` tokens |
|
|
978
|
+
| Custom layout | Compose `Root`, `SearchInput` (or `Search`), `Viewport` and `List` from `/primitives` |
|
|
979
|
+
| Design-system styling | Use classes, styles and `[data-epr-part]` selectors, or install the [shadcn registry component](./ADOPTION.md#shadcn-registry) |
|
|
980
|
+
| Custom input, emoji cells and headers | Use `SearchInput as={Input}`, Root `components` or `List components`; preserve managed props, refs and geometry |
|
|
981
|
+
| Controlled search | Use Root's `searchValue` / `onSearchChange`, or `useSearchActions()` for custom controls |
|
|
982
|
+
| Active-emoji previews | Compose `Preview` or build a custom preview with `useActiveEmoji()` |
|
|
983
|
+
| Skin-tone controls | Compose `SkinTone`, control `skinTone` / `onSkinToneChange`, or use `useSkinTone()` |
|
|
984
|
+
| Localized and asynchronous data | Supply an `emojiData` object or abortable loader; translate remaining strings through `labels` |
|
|
985
|
+
| Loading, empty and error states | Compose `Loading`, `Empty` and `LoadError`; access loading state and retry through `useEmojiDataState()` |
|
|
986
|
+
| Custom image emoji and groups | Supply `customEmojis` with image URLs and optional named groups |
|
|
987
|
+
| Recent/frequent emoji and supplied suggestions | Configure `suggestedEmojisMode`, or supply `suggestedEmojis` |
|
|
988
|
+
| Category navigation | Compose `CategoryNav` or build controls with `useCategoryNavigation()` |
|
|
989
|
+
| Compact reactions with expansion | Use reactions mode on `<EmojiPicker />`, or compose `Reactions` and `Panel` with `usePickerMode()` |
|
|
990
|
+
| Search and metadata outside React | Use `searchEmojis` and `getEmojiByUnified` from `/data`, passing a localized dataset when needed |
|
|
991
|
+
|
|
992
|
+
See the [primitives contract](./PRIMITIVES.md), [input adapters and data
|
|
993
|
+
recovery](./ADOPTION.md), [styling recipes](./STYLING_RECIPES.md) and
|
|
994
|
+
[data API](./DATA_API.md) for implementation patterns.
|
|
995
|
+
|
|
996
|
+
## Audit sources and maintenance
|
|
997
|
+
|
|
998
|
+
The emoji-picker-react column was checked against this checkout's
|
|
999
|
+
[public props](../../PROPS.md), [primitive types](../../src/primitives/types.ts),
|
|
1000
|
+
[component replacement types](../../src/primitives/components.tsx),
|
|
1001
|
+
[data API](./DATA_API.md) and [localization guide](../../INTERNATIONALIZATION.md).
|
|
1002
|
+
Competitor versions were verified against npm's `latest` metadata on the audit
|
|
1003
|
+
date, then their release sources were inspected:
|
|
1004
|
+
|
|
1005
|
+
- **Emoji Mart:** [5.6.0 README][mart-readme], [actual picker options][mart-props],
|
|
1006
|
+
[row rendering][mart-rendering], [native filtering][mart-native] and
|
|
1007
|
+
[React wrapper 1.1.1 peer dependencies][mart-react]. The separate
|
|
1008
|
+
`@emoji-mart/data` package was 1.2.1. Where the README and runtime defaults
|
|
1009
|
+
differ, the table follows the source.
|
|
1010
|
+
- **Frimousse:** [0.4.0 README][frimousse-readme], [public types][frimousse-api],
|
|
1011
|
+
[exports][frimousse-exports], [data resolver][frimousse-data],
|
|
1012
|
+
[persistent cache][frimousse-cache] and [metadata lookup][frimousse-details].
|
|
1013
|
+
- **emoji-picker-element:** [1.29.1 README and database API][element-readme],
|
|
1014
|
+
[picker behavior][element-picker] and [rendering styles][element-styles].
|
|
1015
|
+
|
|
1016
|
+
Recheck these versions and public contracts when updating the table. A missing
|
|
1017
|
+
first-class API is not evidence that a capability is impossible to implement.
|
|
1018
|
+
No competitor browser benchmark or manual assistive-technology comparison was
|
|
1019
|
+
performed for this documentation audit.
|
|
1020
|
+
|
|
1021
|
+
[mart-readme]: https://github.com/missive/emoji-mart/blob/8af68308851a0585c5224fb16f574ca92f4f578c/README.md
|
|
1022
|
+
[mart-props]: https://github.com/missive/emoji-mart/blob/8af68308851a0585c5224fb16f574ca92f4f578c/packages/emoji-mart/src/components/Picker/PickerProps.ts
|
|
1023
|
+
[mart-rendering]: https://github.com/missive/emoji-mart/blob/8af68308851a0585c5224fb16f574ca92f4f578c/packages/emoji-mart/src/components/Picker/Picker.tsx
|
|
1024
|
+
[mart-native]: https://github.com/missive/emoji-mart/blob/8af68308851a0585c5224fb16f574ca92f4f578c/packages/emoji-mart/src/helpers/native-support.ts
|
|
1025
|
+
[mart-react]: https://github.com/missive/emoji-mart/blob/465eec076b23d55b6606b6a81fe3a4fd7b2375a4/packages/emoji-mart-react/package.json
|
|
1026
|
+
[frimousse-readme]: https://github.com/liveblocks/frimousse/blob/868aebea0b441be44005e67c90ab6e082756a906/README.md
|
|
1027
|
+
[frimousse-api]: https://github.com/liveblocks/frimousse/blob/868aebea0b441be44005e67c90ab6e082756a906/src/types.ts
|
|
1028
|
+
[frimousse-exports]: https://github.com/liveblocks/frimousse/blob/868aebea0b441be44005e67c90ab6e082756a906/src/index.ts
|
|
1029
|
+
[frimousse-data]: https://github.com/liveblocks/frimousse/blob/868aebea0b441be44005e67c90ab6e082756a906/src/data/emoji.ts
|
|
1030
|
+
[frimousse-cache]: https://github.com/liveblocks/frimousse/blob/868aebea0b441be44005e67c90ab6e082756a906/src/data/emoji-data-cache.ts
|
|
1031
|
+
[frimousse-details]: https://github.com/liveblocks/frimousse/blob/868aebea0b441be44005e67c90ab6e082756a906/src/data/get-emoji-details.ts
|
|
1032
|
+
[element-readme]: https://github.com/nolanlawson/emoji-picker-element/blob/ded142e5c820c3fe6803ae372dd2b77ed7fbcf9d/README.md
|
|
1033
|
+
[element-picker]: https://github.com/nolanlawson/emoji-picker-element/blob/ded142e5c820c3fe6803ae372dd2b77ed7fbcf9d/src/picker/components/Picker/Picker.js
|
|
1034
|
+
[element-styles]: https://github.com/nolanlawson/emoji-picker-element/blob/ded142e5c820c3fe6803ae372dd2b77ed7fbcf9d/src/picker/styles/picker.scss
|
|
1035
|
+
|
|
881
1036
|
<!-- source: PROPS.md -->
|
|
882
1037
|
|
|
883
1038
|
<!-- Props reference -->
|
|
@@ -1570,12 +1725,14 @@ By default, the arrow key toward the grid moves focus from the search input into
|
|
|
1570
1725
|
```
|
|
1571
1726
|
|
|
1572
1727
|
- The arrow toward the grid highlights the first emoji in view (the first result while searching): ArrowDown when the grid is below the input, ArrowUp when it is above, and Left or Right when it is beside the input (with the caret at that end of the text). The arrow keys then move the highlight through the grid, including rows that are not rendered yet. Otherwise Left and Right edit the text until an emoji is highlighted; from then on they move the highlight, and Escape gives them back to the text. With Shift, Ctrl, Alt or Meta, arrows always stay with the input (selecting text, moving by word), with or without a highlight. Left and Right follow the reading direction in RTL.
|
|
1573
|
-
- Enter selects the highlighted emoji, or the first result when nothing is highlighted, even if the results are scrolled. Focus stays in the input.
|
|
1574
|
-
- Once started, the highlight follows the results: when the search changes, it moves to the first result.
|
|
1728
|
+
- Enter selects the highlighted emoji, or the first result when nothing is highlighted, even if the results are scrolled. Focus stays in the input. While filtering is pending, Enter queues one selection for the matching results after they commit. Editing the query, pressing another key, or leaving the input cancels that queued selection.
|
|
1729
|
+
- Once started, the highlight follows the results: when the applied search, dataset or `suggestedEmojis` changes, it moves to the first result and updates Preview.
|
|
1575
1730
|
- Moving past the grid edge that faces the input (ArrowUp from the first row when the input is above, Left from the first column when it is on the left), Escape, or leaving the input removes the highlight, and cancels a move that has not landed yet. Escape ends only the highlight, even one whose emoji is scrolled out and unmounted; with nothing highlighted, it clears the search as usual.
|
|
1576
1731
|
- Hovering an emoji previews it without taking focus from the input (true in both modes: hover never takes focus from the search input). The highlight stays where it is, and Enter still selects it; once the pointer leaves the emoji, the preview shows the highlighted one again.
|
|
1577
1732
|
- Space types a space, so it does not open skin tone variations in this mode.
|
|
1578
1733
|
|
|
1734
|
+
An Escape consumed by the picker stops propagation in window capture, before document-capture and bubbling host dismissal handlers. With nothing left to undo, Escape is left untouched for the host.
|
|
1735
|
+
|
|
1579
1736
|
The input becomes an ARIA combobox with a grid popup: `aria-controls` names the grid while both are mounted, and `aria-activedescendant` names the highlighted cell (it is empty while virtualization has the highlighted cell scrolled out). That cell carries `data-epr-highlighted` and is the active emoji for Preview, `useActiveEmoji()` and `emoji.isActive`. The default appearance styles it like keyboard focus; with `unstyled` or custom cells, style `[data-epr-highlighted]` as well.
|
|
1580
1737
|
|
|
1581
1738
|
Primitive compositions pass the same prop to `Root`.
|
|
@@ -1686,7 +1843,7 @@ For standard emoji IDs:
|
|
|
1686
1843
|
- a valid variation remains that exact variation for rendering rather than collapsing to the neutral base emoji;
|
|
1687
1844
|
- duplicates are removed by canonical normalized ID, first occurrence wins.
|
|
1688
1845
|
|
|
1689
|
-
Custom emoji IDs use the same case-insensitive rule
|
|
1846
|
+
Custom emoji IDs use the same case-insensitive rule: IDs are lowercased when indexed. Custom display names retain the supplied capitalization; search still matches them case-insensitively.
|
|
1690
1847
|
|
|
1691
1848
|
Entries may be unified IDs, custom emoji IDs, or the emoji characters themselves (`'🧠'`, `'❤️'`), so recents stored as inserted text can be passed through unchanged; unknown entries are ignored.
|
|
1692
1849
|
|
|
@@ -1978,6 +2135,8 @@ Styling is opt-in in both directions:
|
|
|
1978
2135
|
|
|
1979
2136
|
`columns` sets the emojis per row on EmojiPicker and Root. The picker's width then fits those columns plus a stable scrollbar gutter, unless the consumer sets a width (`width`, `style` or any class). A container narrower than the columns renders fewer columns instead of clipping. Without `columns`, the width decides the column count, as in v4.
|
|
1980
2137
|
|
|
2138
|
+
The intrinsic grid width remains present during an empty search, data loading or a load error.
|
|
2139
|
+
|
|
1981
2140
|
## 12. Data API
|
|
1982
2141
|
|
|
1983
2142
|
The data entry point is defined in [DATA_API.md](./DATA_API.md):
|
|
@@ -2451,6 +2610,7 @@ The following variables are already documented public customization surface and
|
|
|
2451
2610
|
- `--epr-preview-text-color`
|
|
2452
2611
|
|
|
2453
2612
|
### Native emoji font
|
|
2613
|
+
- `--epr-font-family` — font for picker text (`sans-serif` by default). Set it to `inherit` on the picker to use the surrounding application's font. Native emoji glyphs keep their separate font stack.
|
|
2454
2614
|
- `--epr-emoji-font-family` (v5) — font stack for native emojis, e.g. a country-flag polyfill font; native support detection measures this same font.
|
|
2455
2615
|
|
|
2456
2616
|
### Skin tone
|
package/llms.txt
CHANGED
|
@@ -51,6 +51,7 @@ searchEmojis('party'); getEmojiByUnified('1f389'); // { emoji: '🎉', name: 'pa
|
|
|
51
51
|
- [Agent integration guide](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/docs/v5/AGENT_GUIDE.md): installed-version discovery, batteries included/BYOD, typed input/cell contracts, localization and verification
|
|
52
52
|
- [Copyable integration prompts](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/docs/v5/PROMPTS.md): setup, brand styling, design-library composition, recipe adoption and v4-to-v5 migration
|
|
53
53
|
- [README](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/README.md): overview, quick start, choosing a path, styling with any solution, common tasks
|
|
54
|
+
- [Emoji picker comparison](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/docs/v5/COMPARISON.md): v5 versus Emoji Mart, Frimousse and emoji-picker-element: capabilities, v5 APIs and audited sources
|
|
54
55
|
- [Props reference](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/PROPS.md): every prop of the default <EmojiPicker />
|
|
55
56
|
- [CSS variables](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/CSS_VARIABLES.md): every --epr-* design token
|
|
56
57
|
- [Customization](https://raw.githubusercontent.com/ealush/emoji-picker-react/master/CUSTOMIZATION.md): custom emojis and groups, category icons, preview, CSP nonce
|
package/package.json
CHANGED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
// src/data/defaultEmojiData.ts
|
|
2
|
-
var registered = null;
|
|
3
|
-
function registerDefaultEmojiData(data) {
|
|
4
|
-
registered = data;
|
|
5
|
-
}
|
|
6
|
-
function getRegisteredDefaultEmojiData() {
|
|
7
|
-
return registered;
|
|
8
|
-
}
|
|
9
|
-
var EMPTY_EMOJI_DATA = Object.freeze({
|
|
10
|
-
categories: {},
|
|
11
|
-
emojis: {}
|
|
12
|
-
});
|
|
13
|
-
function defaultEmojiDataOrEmpty() {
|
|
14
|
-
return registered ?? EMPTY_EMOJI_DATA;
|
|
15
|
-
}
|
|
16
|
-
var pending = null;
|
|
17
|
-
function loadDefaultEmojiData() {
|
|
18
|
-
if (registered) {
|
|
19
|
-
return Promise.resolve(registered);
|
|
20
|
-
}
|
|
21
|
-
if (!pending) {
|
|
22
|
-
pending = import("./emojis-VTEL5M5C.mjs").then((module) => {
|
|
23
|
-
const data = module.default ?? module;
|
|
24
|
-
registered = registered ?? data;
|
|
25
|
-
return registered;
|
|
26
|
-
}).catch((error) => {
|
|
27
|
-
pending = null;
|
|
28
|
-
throw error;
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
return pending;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// src/dataUtils/parseNativeEmoji.ts
|
|
35
|
-
function parseNativeEmoji(unified) {
|
|
36
|
-
return unified.split("-").map((hex) => String.fromCodePoint(parseInt(hex, 16))).join("");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// src/data-core/prepare.ts
|
|
40
|
-
var coreCache = /* @__PURE__ */ new WeakMap();
|
|
41
|
-
var prepareCount = 0;
|
|
42
|
-
function normalizeUnified(input) {
|
|
43
|
-
return input.trim().toLowerCase();
|
|
44
|
-
}
|
|
45
|
-
function normalizeQuery(input) {
|
|
46
|
-
if (!input || typeof input !== "string") {
|
|
47
|
-
return "";
|
|
48
|
-
}
|
|
49
|
-
return input.trim().toLowerCase();
|
|
50
|
-
}
|
|
51
|
-
function toEmojiInfo(unified, names, variations, addedIn) {
|
|
52
|
-
return Object.freeze({
|
|
53
|
-
unified,
|
|
54
|
-
emoji: parseNativeEmoji(unified),
|
|
55
|
-
name: names[names.length - 1] || "",
|
|
56
|
-
names: Object.freeze([...names]),
|
|
57
|
-
variations: Object.freeze([...variations ?? []]),
|
|
58
|
-
addedIn
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
function readStringArray(raw) {
|
|
62
|
-
if (!Array.isArray(raw)) {
|
|
63
|
-
return [];
|
|
64
|
-
}
|
|
65
|
-
return raw.filter((n) => typeof n === "string").map(
|
|
66
|
-
(n) => n.toLowerCase()
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
function appendEntry(byUnified, byCharMutable, records, entry) {
|
|
70
|
-
const rawUnified = entry.u;
|
|
71
|
-
if (typeof rawUnified !== "string" || rawUnified.length === 0) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const unified = rawUnified.toLowerCase();
|
|
75
|
-
if (byUnified.has(unified)) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const names = readStringArray(entry.n);
|
|
79
|
-
const variations = readStringArray(entry.v);
|
|
80
|
-
const rawAddedIn = entry.a;
|
|
81
|
-
const addedIn = typeof rawAddedIn === "string" ? rawAddedIn : String(rawAddedIn ?? "");
|
|
82
|
-
const info = toEmojiInfo(unified, names, variations, addedIn);
|
|
83
|
-
records.push(info);
|
|
84
|
-
byUnified.set(unified, info);
|
|
85
|
-
for (const variation of info.variations) {
|
|
86
|
-
if (!byUnified.has(variation)) {
|
|
87
|
-
byUnified.set(variation, info);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
indexCharBucket(byCharMutable, names, info);
|
|
91
|
-
}
|
|
92
|
-
function indexCharBucket(byCharMutable, names, info) {
|
|
93
|
-
const distinctChars = Array.from(new Set(names.join("")));
|
|
94
|
-
for (const char of distinctChars) {
|
|
95
|
-
const bucket = byCharMutable.get(char);
|
|
96
|
-
if (bucket) {
|
|
97
|
-
bucket.push(info);
|
|
98
|
-
} else {
|
|
99
|
-
byCharMutable.set(char, [info]);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function getPreparedCore(emojiData) {
|
|
104
|
-
const source = emojiData ?? defaultEmojiDataOrEmpty();
|
|
105
|
-
const cached = coreCache.get(source);
|
|
106
|
-
if (cached) {
|
|
107
|
-
return cached;
|
|
108
|
-
}
|
|
109
|
-
prepareCount += 1;
|
|
110
|
-
const byUnified = /* @__PURE__ */ new Map();
|
|
111
|
-
const byCharMutable = /* @__PURE__ */ new Map();
|
|
112
|
-
const records = [];
|
|
113
|
-
const groups = source.emojis ?? {};
|
|
114
|
-
for (const key of Object.keys(groups)) {
|
|
115
|
-
const list = groups[key] ?? [];
|
|
116
|
-
for (const entry of list) {
|
|
117
|
-
appendEntry(byUnified, byCharMutable, records, entry);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const byChar = /* @__PURE__ */ new Map();
|
|
121
|
-
byCharMutable.forEach((bucket, char) => {
|
|
122
|
-
byChar.set(char, Object.freeze(bucket));
|
|
123
|
-
});
|
|
124
|
-
const core = {
|
|
125
|
-
records,
|
|
126
|
-
byUnified,
|
|
127
|
-
byChar,
|
|
128
|
-
queryMemo: /* @__PURE__ */ new Map()
|
|
129
|
-
};
|
|
130
|
-
coreCache.set(source, core);
|
|
131
|
-
return core;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// src/data-core/search.ts
|
|
135
|
-
var EMPTY_RESULTS = Object.freeze([]);
|
|
136
|
-
var MAX_QUERY_MEMO_SIZE = 500;
|
|
137
|
-
function memoizeQuery(core, normalized, results) {
|
|
138
|
-
const memo = core.queryMemo;
|
|
139
|
-
if (memo.has(normalized)) {
|
|
140
|
-
memo.delete(normalized);
|
|
141
|
-
} else if (memo.size >= MAX_QUERY_MEMO_SIZE) {
|
|
142
|
-
const oldest = memo.keys().next();
|
|
143
|
-
if (!oldest.done) {
|
|
144
|
-
memo.delete(oldest.value);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
memo.set(normalized, results);
|
|
148
|
-
}
|
|
149
|
-
function smallestCandidateBucket(core, normalized) {
|
|
150
|
-
let smallest = core.records;
|
|
151
|
-
for (const char of Array.from(normalized)) {
|
|
152
|
-
const bucket = core.byChar.get(char);
|
|
153
|
-
if (!bucket) {
|
|
154
|
-
return EMPTY_RESULTS;
|
|
155
|
-
}
|
|
156
|
-
if (bucket.length < smallest.length) {
|
|
157
|
-
smallest = bucket;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return smallest;
|
|
161
|
-
}
|
|
162
|
-
function getEmojiByUnified(unified, options) {
|
|
163
|
-
if (!unified || typeof unified !== "string") {
|
|
164
|
-
return void 0;
|
|
165
|
-
}
|
|
166
|
-
const normalized = normalizeUnified(unified);
|
|
167
|
-
if (!normalized) {
|
|
168
|
-
return void 0;
|
|
169
|
-
}
|
|
170
|
-
const core = getPreparedCore(options?.emojiData);
|
|
171
|
-
return core.byUnified.get(normalized);
|
|
172
|
-
}
|
|
173
|
-
function searchEmojis(query, options) {
|
|
174
|
-
const normalized = normalizeQuery(query);
|
|
175
|
-
if (!normalized) {
|
|
176
|
-
return EMPTY_RESULTS;
|
|
177
|
-
}
|
|
178
|
-
const core = getPreparedCore(options?.emojiData);
|
|
179
|
-
const memoized = core.queryMemo.get(normalized);
|
|
180
|
-
if (memoized) {
|
|
181
|
-
memoizeQuery(core, normalized, memoized);
|
|
182
|
-
return Object.freeze([...memoized]);
|
|
183
|
-
}
|
|
184
|
-
if (normalized.length === 1) {
|
|
185
|
-
const bucket = core.byChar.get(normalized) ?? EMPTY_RESULTS;
|
|
186
|
-
memoizeQuery(core, normalized, bucket);
|
|
187
|
-
return Object.freeze([...bucket]);
|
|
188
|
-
}
|
|
189
|
-
const matches = [];
|
|
190
|
-
for (const record of smallestCandidateBucket(core, normalized)) {
|
|
191
|
-
const names = record.names;
|
|
192
|
-
for (let i = 0; i < names.length; i += 1) {
|
|
193
|
-
if (names[i].includes(normalized)) {
|
|
194
|
-
matches.push(record);
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
memoizeQuery(core, normalized, matches);
|
|
200
|
-
return Object.freeze([...matches]);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export {
|
|
204
|
-
registerDefaultEmojiData,
|
|
205
|
-
getRegisteredDefaultEmojiData,
|
|
206
|
-
EMPTY_EMOJI_DATA,
|
|
207
|
-
defaultEmojiDataOrEmpty,
|
|
208
|
-
loadDefaultEmojiData,
|
|
209
|
-
parseNativeEmoji,
|
|
210
|
-
normalizeQuery,
|
|
211
|
-
getPreparedCore,
|
|
212
|
-
getEmojiByUnified,
|
|
213
|
-
searchEmojis
|
|
214
|
-
};
|