react-emoji-text 1.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +408 -0
- package/dist/adapters/emoji-mart.cjs +9 -0
- package/dist/adapters/emoji-mart.d.cts +7 -0
- package/dist/adapters/emoji-mart.d.cts.map +1 -0
- package/dist/adapters/emoji-mart.d.mts +7 -0
- package/dist/adapters/emoji-mart.d.mts.map +1 -0
- package/dist/adapters/emoji-mart.mjs +10 -0
- package/dist/adapters/emoji-mart.mjs.map +1 -0
- package/dist/adapters/emojibase.cjs +71 -0
- package/dist/adapters/emojibase.d.cts +38 -0
- package/dist/adapters/emojibase.d.cts.map +1 -0
- package/dist/adapters/emojibase.d.mts +38 -0
- package/dist/adapters/emojibase.d.mts.map +1 -0
- package/dist/adapters/emojibase.mjs +72 -0
- package/dist/adapters/emojibase.mjs.map +1 -0
- package/dist/compat/index.cjs +93 -0
- package/dist/compat/index.d.cts +32 -0
- package/dist/compat/index.d.cts.map +1 -0
- package/dist/compat/index.d.mts +32 -0
- package/dist/compat/index.d.mts.map +1 -0
- package/dist/compat/index.mjs +90 -0
- package/dist/compat/index.mjs.map +1 -0
- package/dist/core.cjs +10 -0
- package/dist/core.d.cts +4 -0
- package/dist/core.d.mts +4 -0
- package/dist/core.mjs +2 -0
- package/dist/index-B39vk6JI.d.mts +23 -0
- package/dist/index-B39vk6JI.d.mts.map +1 -0
- package/dist/index-DPd10zCJ.d.cts +23 -0
- package/dist/index-DPd10zCJ.d.cts.map +1 -0
- package/dist/index-DXKnU6tZ.d.cts +398 -0
- package/dist/index-DXKnU6tZ.d.cts.map +1 -0
- package/dist/index-UT6qWHp1.d.mts +398 -0
- package/dist/index-UT6qWHp1.d.mts.map +1 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +5 -0
- package/dist/indexes-3fK5ySH8.d.cts +20 -0
- package/dist/indexes-3fK5ySH8.d.cts.map +1 -0
- package/dist/indexes-BMCSN-X0.d.mts +20 -0
- package/dist/indexes-BMCSN-X0.d.mts.map +1 -0
- package/dist/react/index.cjs +8 -0
- package/dist/react/index.d.cts +2 -0
- package/dist/react/index.d.mts +2 -0
- package/dist/react/index.mjs +3 -0
- package/dist/react-9EdWn0Gg.mjs +196 -0
- package/dist/react-9EdWn0Gg.mjs.map +1 -0
- package/dist/react-C8xGkPhi.cjs +211 -0
- package/dist/render-C7VPZ7if.cjs +140 -0
- package/dist/render-DzloPAWX.mjs +119 -0
- package/dist/render-DzloPAWX.mjs.map +1 -0
- package/dist/tokenize-BUKMZ9Yg.mjs +313 -0
- package/dist/tokenize-BUKMZ9Yg.mjs.map +1 -0
- package/dist/tokenize-CyKMb3O9.cjs +364 -0
- package/dist/types-Dyzdpq-R.d.cts +92 -0
- package/dist/types-Dyzdpq-R.d.cts.map +1 -0
- package/dist/types-o0mRO30y.d.mts +92 -0
- package/dist/types-o0mRO30y.d.mts.map +1 -0
- package/package.json +108 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 drenther
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# react-emoji-text
|
|
2
|
+
|
|
3
|
+
A modern React 19 renderer that converts plain text into rendered emojis, backed by `@emoji-mart/data`.
|
|
4
|
+
|
|
5
|
+
## Entry Points
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { EmojiProvider, EmojiText } from 'react-emoji-text/react';
|
|
9
|
+
import { tokenize } from 'react-emoji-text/core';
|
|
10
|
+
import Emoji, { toArray } from 'react-emoji-text/compat';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The root entry (`react-emoji-text`) re-exports the core and React APIs. Use the subpath entries when you want the smallest import surface.
|
|
14
|
+
|
|
15
|
+
## React Usage
|
|
16
|
+
|
|
17
|
+
Wrap your app (or subtree) with `EmojiProvider` and use `EmojiText` to render emoji-enriched text.
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import data from '@emoji-mart/data';
|
|
21
|
+
import { EmojiProvider, EmojiText } from 'react-emoji-text/react';
|
|
22
|
+
|
|
23
|
+
export function Message() {
|
|
24
|
+
return (
|
|
25
|
+
<EmojiProvider data={data}>
|
|
26
|
+
<EmojiText>hello :wave:</EmojiText>
|
|
27
|
+
</EmojiProvider>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`EmojiText` accepts content as a `children` string or via the `text` prop. Use `text` when `children` contains slots (see [Custom Rendering](#custom-rendering)).
|
|
33
|
+
|
|
34
|
+
### EmojiProvider Props
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Default | Description |
|
|
37
|
+
| ------------------ | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------------- |
|
|
38
|
+
| `data` | `EmojiData` | _required_ | Emoji dataset (e.g. `@emoji-mart/data`) |
|
|
39
|
+
| `set` | `"native" \| "apple" \| "google" \| "twitter" \| "facebook"` | `"native"` | Emoji image set |
|
|
40
|
+
| `defaultSkin` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | — | Default skin tone applied to all emojis |
|
|
41
|
+
| `ascii` | `boolean` | `true` | Match ASCII emoticons like `:)` and `<3` |
|
|
42
|
+
| `customEmojis` | `CustomEmojiCategory[]` | — | Custom emoji categories (see [Custom Emojis](#custom-emojis)) |
|
|
43
|
+
| `extraAliases` | `Record<string, string>` | — | Additional shortcode mappings (see [Extra Aliases](#extra-aliases)) |
|
|
44
|
+
| `getImageUrl` | `(emoji, context) => string` | — | Custom image URL resolver |
|
|
45
|
+
| `imageUrlTemplate` | `string` | — | URL template with `{set}`, `{unified}`, `{skin}` placeholders |
|
|
46
|
+
| `sprite` | `SpriteConfig` | — | Sprite sheet configuration |
|
|
47
|
+
|
|
48
|
+
### EmojiText Props
|
|
49
|
+
|
|
50
|
+
All `EmojiProvider` props except `data` can be overridden per-instance on `EmojiText`.
|
|
51
|
+
|
|
52
|
+
| Prop | Type | Default | Description |
|
|
53
|
+
| -------------------- | ----------------------------- | -------- | -------------------------------------------------------------- |
|
|
54
|
+
| `children` | `string` | — | Source text (mutually exclusive with `text`) |
|
|
55
|
+
| `text` | `string` | — | Source text (use when `children` contains slots) |
|
|
56
|
+
| `as` | `keyof HTMLElementTagNameMap` | `"span"` | Wrapper element tag |
|
|
57
|
+
| `className` | `string` | — | Class on the wrapper element |
|
|
58
|
+
| `emojiClassName` | `string` | — | Class applied to individual emoji images |
|
|
59
|
+
| `onlyEmojiClassName` | `string` | — | Class applied to the wrapper when content contains only emojis |
|
|
60
|
+
| `ref` | `Ref<HTMLElement>` | — | Forwarded ref to the wrapper element |
|
|
61
|
+
|
|
62
|
+
Any additional HTML attributes are forwarded to the wrapper element.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<EmojiText as="p" className="message" data-testid="msg" title="Greeting">
|
|
66
|
+
hello :wave:
|
|
67
|
+
</EmojiText>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Custom Rendering
|
|
71
|
+
|
|
72
|
+
Customize token rendering with compound slots. Use `text` for the source string when `children` contains slots.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<EmojiText text="hello :wave: :missing:">
|
|
76
|
+
<EmojiText.Emoji>
|
|
77
|
+
{(token) => <strong title={token.shortcode}>{token.native}</strong>}
|
|
78
|
+
</EmojiText.Emoji>
|
|
79
|
+
<EmojiText.Unknown>{(token) => <code>{token.match}</code>}</EmojiText.Unknown>
|
|
80
|
+
</EmojiText>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The `EmojiText.Emoji` slot receives an `EmojiToken` with fields: `emoji`, `native`, `skin`, `shortcode`, `match`, and `source`. The `EmojiText.Unknown` slot receives an `UnknownToken` with `shortcode` and `match`.
|
|
84
|
+
|
|
85
|
+
For full control over every token type, compose the `useTokens` hook with `renderTokenDefault`:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { useTokens, renderTokenDefault } from 'react-emoji-text/react';
|
|
89
|
+
|
|
90
|
+
function CustomRenderer({ text }: { text: string }) {
|
|
91
|
+
const tokens = useTokens(text);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<span>
|
|
95
|
+
{tokens.map((token, index) => {
|
|
96
|
+
if (token.type === 'emoji') {
|
|
97
|
+
return (
|
|
98
|
+
<span key={index} className="emoji">
|
|
99
|
+
{token.native}
|
|
100
|
+
</span>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return renderTokenDefault(token, { set: 'native' });
|
|
104
|
+
})}
|
|
105
|
+
</span>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Image Rendering
|
|
111
|
+
|
|
112
|
+
By default, emojis render as native Unicode characters. To render image-based emojis, configure one of the image resolution strategies on the provider or per-instance.
|
|
113
|
+
|
|
114
|
+
### Image URL Template
|
|
115
|
+
|
|
116
|
+
Use `{set}`, `{unified}`, and `{skin}` placeholders:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
<EmojiProvider data={data} set="apple" imageUrlTemplate="/emoji/{set}/{unified}.png">
|
|
120
|
+
<EmojiText>:wave:</EmojiText>
|
|
121
|
+
</EmojiProvider>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Custom Image URL Function
|
|
125
|
+
|
|
126
|
+
For full control, provide a `getImageUrl` function:
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
<EmojiProvider
|
|
130
|
+
data={data}
|
|
131
|
+
set="apple"
|
|
132
|
+
getImageUrl={(emoji, context) => `/cdn/${context.set}/${context.unified}.svg`}
|
|
133
|
+
>
|
|
134
|
+
<EmojiText>:wave:</EmojiText>
|
|
135
|
+
</EmojiProvider>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Sprite Sheets
|
|
139
|
+
|
|
140
|
+
Render emojis from a sprite sheet by providing a `sprite` config:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<EmojiText
|
|
144
|
+
set="apple"
|
|
145
|
+
sprite={{
|
|
146
|
+
src: '/emoji-sheet.png',
|
|
147
|
+
size: 20,
|
|
148
|
+
columns: 4,
|
|
149
|
+
sheet: { '1F44B': { x: 1, y: 2 } },
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
:wave:
|
|
153
|
+
</EmojiText>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Sprite coordinates are matched case-insensitively. Emojis without coordinates fall back to native rendering.
|
|
157
|
+
|
|
158
|
+
### Resolution Priority
|
|
159
|
+
|
|
160
|
+
When multiple image strategies are configured, they resolve in this order:
|
|
161
|
+
|
|
162
|
+
1. `getImageUrl` (highest priority)
|
|
163
|
+
2. `sprite`
|
|
164
|
+
3. `imageUrlTemplate`
|
|
165
|
+
4. Native Unicode (fallback)
|
|
166
|
+
|
|
167
|
+
The `emojiClassName` prop is applied to rendered `<img>` and sprite `<span>` elements.
|
|
168
|
+
|
|
169
|
+
## Skin Tones
|
|
170
|
+
|
|
171
|
+
### Default Skin Tone
|
|
172
|
+
|
|
173
|
+
Set a default skin tone on the provider or per-instance. Values range from `1` (default yellow) to `6`.
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<EmojiProvider data={data} defaultSkin={3}>
|
|
177
|
+
<EmojiText>:wave:</EmojiText> {/* renders 👋🏼 */}
|
|
178
|
+
</EmojiProvider>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Shortcode Skin Tone Suffix
|
|
182
|
+
|
|
183
|
+
Append `:skin-tone-N:` to a shortcode to override the skin tone for that emoji:
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
<EmojiText>:wave::skin-tone-5:</EmojiText> {/* renders 👋🏾 */}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Unicode skin tone modifiers embedded in the source text are always preserved.
|
|
190
|
+
|
|
191
|
+
## ASCII Emoticons
|
|
192
|
+
|
|
193
|
+
ASCII emoticons like `:)`, `<3`, `:D`, and `;)` are matched by default. They require whitespace or string boundaries on both sides to avoid false positives inside words.
|
|
194
|
+
|
|
195
|
+
Disable ASCII matching on the provider or per-instance:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
<EmojiProvider data={data} ascii={false}>
|
|
199
|
+
<EmojiText>hello :)</EmojiText> {/* renders as plain text */}
|
|
200
|
+
</EmojiProvider>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Only-Emoji Detection
|
|
204
|
+
|
|
205
|
+
When the rendered content contains only emoji tokens (and optional whitespace), the `onlyEmojiClassName` is applied to the wrapper element. This is useful for styling messages that contain only emojis differently (e.g., rendering them larger).
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
<EmojiText className="message" onlyEmojiClassName="jumbo">
|
|
209
|
+
:wave:
|
|
210
|
+
</EmojiText>;
|
|
211
|
+
{
|
|
212
|
+
/* wrapper gets class="message jumbo" */
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
<EmojiText className="message" onlyEmojiClassName="jumbo">
|
|
216
|
+
hello :wave:
|
|
217
|
+
</EmojiText>;
|
|
218
|
+
{
|
|
219
|
+
/* wrapper gets class="message" */
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Empty content does not receive `onlyEmojiClassName`.
|
|
224
|
+
|
|
225
|
+
## Custom Emojis
|
|
226
|
+
|
|
227
|
+
Register custom emojis via the provider or per-instance. Each category contains an array of emojis with image sources.
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
<EmojiProvider
|
|
231
|
+
data={data}
|
|
232
|
+
customEmojis={[
|
|
233
|
+
{
|
|
234
|
+
id: 'custom',
|
|
235
|
+
name: 'Custom',
|
|
236
|
+
emojis: [
|
|
237
|
+
{
|
|
238
|
+
id: 'partyparrot',
|
|
239
|
+
name: 'Party Parrot',
|
|
240
|
+
keywords: ['party', 'parrot'],
|
|
241
|
+
skins: [{ src: '/emojis/partyparrot.gif' }],
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
},
|
|
245
|
+
]}
|
|
246
|
+
>
|
|
247
|
+
<EmojiText>:partyparrot:</EmojiText>
|
|
248
|
+
</EmojiProvider>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Custom emojis render as `<img>` elements. If a custom emoji shares the same ID as a built-in emoji, the custom emoji takes precedence.
|
|
252
|
+
|
|
253
|
+
## Extra Aliases
|
|
254
|
+
|
|
255
|
+
Map additional shortcodes to existing emoji IDs via `extraAliases`. Values can reference built-in emoji IDs, built-in shortcodes, or custom emoji IDs.
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
<EmojiProvider data={data}>
|
|
259
|
+
<EmojiText extraAliases={{ hi: 'wave', dance: 'partyparrot' }}>:hi: :dance:</EmojiText>
|
|
260
|
+
</EmojiProvider>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Shortcode Resolution Priority
|
|
264
|
+
|
|
265
|
+
When multiple sources define the same shortcode, the last writer wins. Resolution runs in this order, where later entries overwrite earlier ones:
|
|
266
|
+
|
|
267
|
+
1. Built-in emoji IDs and their aliases
|
|
268
|
+
2. Data-level aliases (`data.aliases`)
|
|
269
|
+
3. Custom emoji IDs
|
|
270
|
+
4. Extra aliases
|
|
271
|
+
|
|
272
|
+
This means an `extraAliases` entry with the same key as a custom emoji ID will override that custom emoji's shortcode. This is intentional — `extraAliases` acts as the highest-priority override.
|
|
273
|
+
|
|
274
|
+
## Core API
|
|
275
|
+
|
|
276
|
+
The `tokenize` function is framework-agnostic and can be used without React.
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
import { tokenize } from 'react-emoji-text/core';
|
|
280
|
+
import data from '@emoji-mart/data';
|
|
281
|
+
|
|
282
|
+
const tokens = tokenize('hello :wave: world', { data });
|
|
283
|
+
// [
|
|
284
|
+
// { type: "text", value: "hello " },
|
|
285
|
+
// { type: "emoji", emoji: {...}, native: "👋", source: "shortcode", ... },
|
|
286
|
+
// { type: "text", value: " world" },
|
|
287
|
+
// ]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### TokenizeOptions
|
|
291
|
+
|
|
292
|
+
| Option | Type | Default | Description |
|
|
293
|
+
| -------------- | ------------------------ | ---------- | ----------------------------- |
|
|
294
|
+
| `data` | `EmojiData` | _required_ | Emoji dataset |
|
|
295
|
+
| `customEmojis` | `CustomEmojiCategory[]` | — | Custom emoji categories |
|
|
296
|
+
| `ascii` | `boolean` | `true` | Match ASCII emoticons |
|
|
297
|
+
| `defaultSkin` | `SkinTone` | — | Default skin tone |
|
|
298
|
+
| `extraAliases` | `Record<string, string>` | — | Additional shortcode mappings |
|
|
299
|
+
|
|
300
|
+
### Token Types
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
type Token = TextToken | EmojiToken | UnknownToken;
|
|
304
|
+
|
|
305
|
+
type TextToken = { type: 'text'; value: string };
|
|
306
|
+
|
|
307
|
+
type EmojiToken = {
|
|
308
|
+
type: 'emoji';
|
|
309
|
+
emoji: EmojiEntry;
|
|
310
|
+
native: string;
|
|
311
|
+
skin?: SkinTone;
|
|
312
|
+
shortcode?: string;
|
|
313
|
+
match: string;
|
|
314
|
+
source: 'unicode' | 'shortcode' | 'ascii' | 'custom';
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
type UnknownToken = {
|
|
318
|
+
type: 'unknown';
|
|
319
|
+
shortcode: string;
|
|
320
|
+
match: string;
|
|
321
|
+
};
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Compat API
|
|
325
|
+
|
|
326
|
+
A drop-in replacement for `react-emoji-render`. Pass adapted emoji data directly via `options` — no provider needed. Works with both `@emoji-mart/data` and `emojibase-data`.
|
|
327
|
+
|
|
328
|
+
### Emoji Component
|
|
329
|
+
|
|
330
|
+
#### With @emoji-mart/data
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
import emojiMartData from '@emoji-mart/data';
|
|
334
|
+
import { fromEmojiMart } from 'react-emoji-text/adapters/emoji-mart';
|
|
335
|
+
import Emoji from 'react-emoji-text/compat';
|
|
336
|
+
|
|
337
|
+
const data = fromEmojiMart(emojiMartData);
|
|
338
|
+
|
|
339
|
+
<Emoji text="hello :wave:" options={{ data }} />
|
|
340
|
+
<Emoji text=":wave:" onlyEmojiClassName="jumbo" options={{ data }} />
|
|
341
|
+
<Emoji text=":wave:" svg options={{ data, imageUrlTemplate: "/emoji/{set}/{unified}.png" }} />
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### With emojibase
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
import emojis from 'emojibase-data/en/data.json';
|
|
348
|
+
import shortcodes from 'emojibase-data/en/shortcodes/emojibase.json';
|
|
349
|
+
import { fromEmojibase } from 'react-emoji-text/adapters/emojibase';
|
|
350
|
+
import Emoji from 'react-emoji-text/compat';
|
|
351
|
+
|
|
352
|
+
const data = fromEmojibase(emojis, { shortcodes });
|
|
353
|
+
|
|
354
|
+
<Emoji text="hello :wave:" options={{ data }} />;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
| Prop | Type | Default | Description |
|
|
358
|
+
| -------------------- | ---------------------- | ---------- | ----------------------------------------- |
|
|
359
|
+
| `text` | `string` | _required_ | Source text |
|
|
360
|
+
| `onlyEmojiClassName` | `string` | — | Class when content is only emojis |
|
|
361
|
+
| `svg` | `boolean` | — | When `true`, uses the `"apple"` image set |
|
|
362
|
+
| `options` | `CompatOptions` | _required_ | Tokenize and render options |
|
|
363
|
+
| `ref` | `Ref<HTMLSpanElement>` | — | Forwarded ref |
|
|
364
|
+
|
|
365
|
+
All additional HTML attributes are forwarded to the wrapper `<span>`.
|
|
366
|
+
|
|
367
|
+
### toArray
|
|
368
|
+
|
|
369
|
+
Returns an array of strings and React elements for manual rendering:
|
|
370
|
+
|
|
371
|
+
```ts
|
|
372
|
+
import { toArray } from 'react-emoji-text/compat';
|
|
373
|
+
|
|
374
|
+
const elements = toArray('hello :wave:', { data });
|
|
375
|
+
// ["hello ", <span title="wave">👋</span>]
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Accepts the same `CompatOptions` as the `Emoji` component's `options` prop.
|
|
379
|
+
|
|
380
|
+
### Wrapper Pattern
|
|
381
|
+
|
|
382
|
+
Create a thin wrapper to pre-configure the data source, then use it everywhere without repeating the adapter setup:
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
// emoji.tsx
|
|
386
|
+
import emojiMartData from '@emoji-mart/data';
|
|
387
|
+
import { fromEmojiMart } from 'react-emoji-text/adapters/emoji-mart';
|
|
388
|
+
import BaseEmoji, { toArray as baseToArray } from 'react-emoji-text/compat';
|
|
389
|
+
import type { EmojiProps } from 'react-emoji-text/compat';
|
|
390
|
+
|
|
391
|
+
const data = fromEmojiMart(emojiMartData);
|
|
392
|
+
|
|
393
|
+
export default function Emoji(props: Omit<EmojiProps, 'options'>) {
|
|
394
|
+
return <BaseEmoji {...props} options={{ data }} />;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export function toArray(text: string) {
|
|
398
|
+
return baseToArray(text, { data });
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
// usage
|
|
404
|
+
import Emoji, { toArray } from './emoji';
|
|
405
|
+
|
|
406
|
+
<Emoji text="hello :wave:" />;
|
|
407
|
+
toArray('hello :wave:');
|
|
408
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/adapters/emoji-mart.ts
|
|
3
|
+
function fromEmojiMart(data) {
|
|
4
|
+
const record = data;
|
|
5
|
+
if (!record.emojis || !record.aliases || !record.categories) throw new Error("Invalid @emoji-mart/data: expected \"emojis\", \"aliases\", and \"categories\" fields");
|
|
6
|
+
return data;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
exports.fromEmojiMart = fromEmojiMart;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-mart.d.cts","names":[],"sources":["../../src/adapters/emoji-mart.ts"],"mappings":";;;iBAEgB,aAAA,CAAc,IAAA,YAAgB,SAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-mart.d.mts","names":[],"sources":["../../src/adapters/emoji-mart.ts"],"mappings":";;;iBAEgB,aAAA,CAAc,IAAA,YAAgB,SAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/adapters/emoji-mart.ts
|
|
2
|
+
function fromEmojiMart(data) {
|
|
3
|
+
const record = data;
|
|
4
|
+
if (!record.emojis || !record.aliases || !record.categories) throw new Error("Invalid @emoji-mart/data: expected \"emojis\", \"aliases\", and \"categories\" fields");
|
|
5
|
+
return data;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { fromEmojiMart };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=emoji-mart.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-mart.mjs","names":[],"sources":["../../src/adapters/emoji-mart.ts"],"sourcesContent":["import type { EmojiData } from '../core/types';\n\nexport function fromEmojiMart(data: unknown): EmojiData {\n const record = data as Record<string, unknown>;\n if (!record.emojis || !record.aliases || !record.categories) {\n throw new Error(\n 'Invalid @emoji-mart/data: expected \"emojis\", \"aliases\", and \"categories\" fields',\n );\n }\n return data as EmojiData;\n}\n"],"mappings":";AAEA,SAAgB,cAAc,MAA0B;CACtD,MAAM,SAAS;AACf,KAAI,CAAC,OAAO,UAAU,CAAC,OAAO,WAAW,CAAC,OAAO,WAC/C,OAAM,IAAI,MACR,wFACD;AAEH,QAAO"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/adapters/emojibase.ts
|
|
3
|
+
const GROUP_NAMES = {
|
|
4
|
+
0: "smileys-emotion",
|
|
5
|
+
1: "people-body",
|
|
6
|
+
2: "component",
|
|
7
|
+
3: "animals-nature",
|
|
8
|
+
4: "food-drink",
|
|
9
|
+
5: "travel-places",
|
|
10
|
+
6: "activities",
|
|
11
|
+
7: "objects",
|
|
12
|
+
8: "symbols",
|
|
13
|
+
9: "flags"
|
|
14
|
+
};
|
|
15
|
+
function getNative(entry) {
|
|
16
|
+
return "emoji" in entry ? entry.emoji : entry.unicode;
|
|
17
|
+
}
|
|
18
|
+
function resolveShortcodes(hexcode, shortcodesMap) {
|
|
19
|
+
if (!shortcodesMap) return [];
|
|
20
|
+
const value = shortcodesMap[hexcode];
|
|
21
|
+
if (!value) return [];
|
|
22
|
+
return Array.isArray(value) ? value : [value];
|
|
23
|
+
}
|
|
24
|
+
function toSkin(entry) {
|
|
25
|
+
return {
|
|
26
|
+
unified: entry.hexcode,
|
|
27
|
+
native: getNative(entry)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function fromEmojibase(emojis, options) {
|
|
31
|
+
const shortcodesMap = options?.shortcodes;
|
|
32
|
+
const emojiRecord = {};
|
|
33
|
+
const aliases = {};
|
|
34
|
+
const categoryBuckets = /* @__PURE__ */ new Map();
|
|
35
|
+
for (const raw of emojis) {
|
|
36
|
+
const codes = resolveShortcodes(raw.hexcode, shortcodesMap);
|
|
37
|
+
const emojiId = codes[0] ?? raw.hexcode;
|
|
38
|
+
const skins = [toSkin(raw)];
|
|
39
|
+
if (raw.skins) for (const skinVariant of raw.skins) skins.push(toSkin(skinVariant));
|
|
40
|
+
const entryAliases = codes.length > 1 ? codes.slice(1) : void 0;
|
|
41
|
+
emojiRecord[emojiId] = {
|
|
42
|
+
id: emojiId,
|
|
43
|
+
name: raw.label,
|
|
44
|
+
keywords: raw.tags ?? [],
|
|
45
|
+
skins,
|
|
46
|
+
aliases: entryAliases
|
|
47
|
+
};
|
|
48
|
+
if (entryAliases) for (const alias of entryAliases) aliases[alias] = emojiId;
|
|
49
|
+
const emoticons = raw.emoticon ? Array.isArray(raw.emoticon) ? raw.emoticon : [raw.emoticon] : [];
|
|
50
|
+
for (const emoticon of emoticons) aliases[emoticon] = emojiId;
|
|
51
|
+
if (raw.group !== void 0) {
|
|
52
|
+
const categoryName = GROUP_NAMES[raw.group] ?? `group-${String(raw.group)}`;
|
|
53
|
+
let bucket = categoryBuckets.get(categoryName);
|
|
54
|
+
if (!bucket) {
|
|
55
|
+
bucket = [];
|
|
56
|
+
categoryBuckets.set(categoryName, bucket);
|
|
57
|
+
}
|
|
58
|
+
bucket.push(emojiId);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
emojis: emojiRecord,
|
|
63
|
+
aliases,
|
|
64
|
+
categories: Array.from(categoryBuckets, ([id, emojiIds]) => ({
|
|
65
|
+
id,
|
|
66
|
+
emojis: emojiIds
|
|
67
|
+
}))
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
exports.fromEmojibase = fromEmojibase;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { i as EmojiData } from "../types-Dyzdpq-R.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/types.d.ts
|
|
4
|
+
interface EmojibaseEmoji {
|
|
5
|
+
label: string;
|
|
6
|
+
hexcode: string;
|
|
7
|
+
emoji: string;
|
|
8
|
+
text: string;
|
|
9
|
+
type: number;
|
|
10
|
+
order?: number;
|
|
11
|
+
group?: number;
|
|
12
|
+
subgroup?: number;
|
|
13
|
+
version: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
emoticon?: string | string[];
|
|
16
|
+
skins?: EmojibaseEmoji[];
|
|
17
|
+
tone?: number | number[];
|
|
18
|
+
}
|
|
19
|
+
interface EmojibaseCompactEmoji {
|
|
20
|
+
label: string;
|
|
21
|
+
hexcode: string;
|
|
22
|
+
unicode: string;
|
|
23
|
+
order?: number;
|
|
24
|
+
group?: number;
|
|
25
|
+
tags?: string[];
|
|
26
|
+
emoticon?: string | string[];
|
|
27
|
+
skins?: EmojibaseCompactEmoji[];
|
|
28
|
+
}
|
|
29
|
+
type EmojibaseShortcodes = Record<string, string | string[]>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/adapters/emojibase.d.ts
|
|
32
|
+
interface FromEmojibaseOptions {
|
|
33
|
+
shortcodes?: EmojibaseShortcodes;
|
|
34
|
+
}
|
|
35
|
+
declare function fromEmojibase(emojis: EmojibaseEmoji[] | EmojibaseCompactEmoji[], options?: FromEmojibaseOptions): EmojiData;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { fromEmojibase };
|
|
38
|
+
//# sourceMappingURL=emojibase.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emojibase.d.cts","names":[],"sources":["../../src/adapters/types.ts","../../src/adapters/emojibase.ts"],"mappings":";;;UAAiB,cAAA;EACf,KAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA;EACA,IAAA;EACA,KAAA;EACA,KAAA;EACA,QAAA;EACA,OAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,GAAQ,cAAA;EACR,IAAA;AAAA;AAAA,UAGe,qBAAA;EACf,KAAA;EACA,OAAA;EACA,OAAA;EACA,KAAA;EACA,KAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,GAAQ,qBAAA;AAAA;AAAA,KAGE,mBAAA,GAAsB,MAAA;;;UCXxB,oBAAA;EACR,UAAA,GAAa,mBAAA;AAAA;AAAA,iBAwBC,aAAA,CACd,MAAA,EAAQ,cAAA,KAAmB,qBAAA,IAC3B,OAAA,GAAU,oBAAA,GACT,SAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { i as EmojiData } from "../types-o0mRO30y.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/types.d.ts
|
|
4
|
+
interface EmojibaseEmoji {
|
|
5
|
+
label: string;
|
|
6
|
+
hexcode: string;
|
|
7
|
+
emoji: string;
|
|
8
|
+
text: string;
|
|
9
|
+
type: number;
|
|
10
|
+
order?: number;
|
|
11
|
+
group?: number;
|
|
12
|
+
subgroup?: number;
|
|
13
|
+
version: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
emoticon?: string | string[];
|
|
16
|
+
skins?: EmojibaseEmoji[];
|
|
17
|
+
tone?: number | number[];
|
|
18
|
+
}
|
|
19
|
+
interface EmojibaseCompactEmoji {
|
|
20
|
+
label: string;
|
|
21
|
+
hexcode: string;
|
|
22
|
+
unicode: string;
|
|
23
|
+
order?: number;
|
|
24
|
+
group?: number;
|
|
25
|
+
tags?: string[];
|
|
26
|
+
emoticon?: string | string[];
|
|
27
|
+
skins?: EmojibaseCompactEmoji[];
|
|
28
|
+
}
|
|
29
|
+
type EmojibaseShortcodes = Record<string, string | string[]>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/adapters/emojibase.d.ts
|
|
32
|
+
interface FromEmojibaseOptions {
|
|
33
|
+
shortcodes?: EmojibaseShortcodes;
|
|
34
|
+
}
|
|
35
|
+
declare function fromEmojibase(emojis: EmojibaseEmoji[] | EmojibaseCompactEmoji[], options?: FromEmojibaseOptions): EmojiData;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { fromEmojibase };
|
|
38
|
+
//# sourceMappingURL=emojibase.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emojibase.d.mts","names":[],"sources":["../../src/adapters/types.ts","../../src/adapters/emojibase.ts"],"mappings":";;;UAAiB,cAAA;EACf,KAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA;EACA,IAAA;EACA,KAAA;EACA,KAAA;EACA,QAAA;EACA,OAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,GAAQ,cAAA;EACR,IAAA;AAAA;AAAA,UAGe,qBAAA;EACf,KAAA;EACA,OAAA;EACA,OAAA;EACA,KAAA;EACA,KAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,GAAQ,qBAAA;AAAA;AAAA,KAGE,mBAAA,GAAsB,MAAA;;;UCXxB,oBAAA;EACR,UAAA,GAAa,mBAAA;AAAA;AAAA,iBAwBC,aAAA,CACd,MAAA,EAAQ,cAAA,KAAmB,qBAAA,IAC3B,OAAA,GAAU,oBAAA,GACT,SAAA"}
|