Full Code of missive/emoji-mart for AI

main 16978d04a766 cached
164 files
25.6 MB
6.7M tokens
102 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (26,920K chars total). Download the full file to get everything.
Repository: missive/emoji-mart
Branch: main
Commit: 16978d04a766
Files: 164
Total size: 25.6 MB

Directory structure:
gitextract_eixd0uz8/

├── .editorconfig
├── .github/
│   └── workflows/
│       └── test.yml
├── .gitignore
├── .node-version
├── .npmignore
├── .prettierignore
├── LICENSE
├── README.md
├── jest/
│   └── esm-transformer.js
├── jest.config.js
├── package.json
├── packages/
│   ├── emoji-mart/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── package.json
│   │   └── src/
│   │       ├── __tests__/
│   │       │   ├── config.test.js
│   │       │   └── utils.test.js
│   │       ├── browser.js
│   │       ├── components/
│   │       │   ├── Emoji/
│   │       │   │   ├── Emoji.tsx
│   │       │   │   ├── EmojiElement.jsx
│   │       │   │   ├── EmojiProps.ts
│   │       │   │   └── index.ts
│   │       │   ├── HOCs/
│   │       │   │   ├── PureInlineComponent.ts
│   │       │   │   └── index.ts
│   │       │   ├── HTMLElement/
│   │       │   │   ├── HTMLElement.ts
│   │       │   │   ├── ShadowElement.ts
│   │       │   │   └── index.ts
│   │       │   ├── Navigation/
│   │       │   │   ├── Navigation.tsx
│   │       │   │   └── index.ts
│   │       │   └── Picker/
│   │       │       ├── Picker.tsx
│   │       │       ├── PickerElement.tsx
│   │       │       ├── PickerProps.ts
│   │       │       ├── PickerStyles.scss
│   │       │       └── index.ts
│   │       ├── config.ts
│   │       ├── declaration.d.ts
│   │       ├── helpers/
│   │       │   ├── __tests__/
│   │       │   │   ├── frequently-used.test.js
│   │       │   │   ├── native-support.test.js
│   │       │   │   ├── search-index.test.js
│   │       │   │   └── store.test.js
│   │       │   ├── frequently-used.ts
│   │       │   ├── index.ts
│   │       │   ├── native-support.ts
│   │       │   ├── search-index.ts
│   │       │   └── store.ts
│   │       ├── icons.tsx
│   │       ├── index.ts
│   │       └── utils.ts
│   ├── emoji-mart-data/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── build.js
│   │   ├── i18n/
│   │   │   ├── ar.json
│   │   │   ├── be.json
│   │   │   ├── cs.json
│   │   │   ├── de.json
│   │   │   ├── en.json
│   │   │   ├── es.json
│   │   │   ├── fa.json
│   │   │   ├── fi.json
│   │   │   ├── fr.json
│   │   │   ├── hi.json
│   │   │   ├── it.json
│   │   │   ├── ja.json
│   │   │   ├── ko.json
│   │   │   ├── nl.json
│   │   │   ├── pl.json
│   │   │   ├── pt.json
│   │   │   ├── ru.json
│   │   │   ├── sa.json
│   │   │   ├── tr.json
│   │   │   ├── uk.json
│   │   │   ├── vi.json
│   │   │   └── zh.json
│   │   ├── index.d.ts
│   │   ├── package.json
│   │   └── sets/
│   │       ├── 1/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 11/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 12/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 12.1/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 13/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 13.1/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 14/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 15/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 2/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 3/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 4/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       └── 5/
│   │           ├── all.json
│   │           ├── apple.json
│   │           ├── facebook.json
│   │           ├── google.json
│   │           ├── native.json
│   │           └── twitter.json
│   ├── emoji-mart-react/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── package.json
│   │   └── react.tsx
│   └── emoji-mart-website/
│       ├── .posthtmlrc
│       ├── example-categories.html
│       ├── example-custom-font.html
│       ├── example-custom-styles.html
│       ├── example-dynamic-width.html
│       ├── example-emoji-component.html
│       ├── example-headless-search.html
│       ├── example-slack-colors.html
│       ├── examples.html
│       ├── index.html
│       ├── layout.html
│       ├── package.json
│       └── styles.scss
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
[*]
indent_size = 2


================================================
FILE: .github/workflows/test.yml
================================================
name: EmojiMart Tests

on:
  push:
    branches:
      - main
  pull_request:
    types: [opened, synchronize, reopened]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  integrity:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: nodenv/actions/node-version@v2.0.10
        id: nodenv

      - uses: actions/setup-node@v3
        with:
          node-version: '${{ steps.nodenv.outputs.node-version }}'
          cache: 'yarn'

      - run: yarn install
      - run: yarn prettier
      - run: yarn check:types

  tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: nodenv/actions/node-version@v2.0.10
        id: nodenv

      - uses: actions/setup-node@v3
        with:
          node-version: '${{ steps.nodenv.outputs.node-version }}'
          cache: 'yarn'

      - run: yarn install
      - run: yarn test


================================================
FILE: .gitignore
================================================
.parcel-cache
coverage
node_modules
dist


================================================
FILE: .node-version
================================================
16.13.0


================================================
FILE: .npmignore
================================================
.*
*.config.js
*.lock

src/
docs/
scripts/


================================================
FILE: .prettierignore
================================================
*.md
*.css
*.scss
**/dist
**/sets


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) Missive.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<div align="center">
  <br><b>Emoji Mart</b> is a customizable<br>emoji picker HTML component for the web
  <br><a href="https://missiveapp.com/open/emoji-mart">Demo</a>
  <br><br><a href="https://missiveapp.com/open/emoji-mart"><img width="639" alt="EmojiMart" src="https://user-images.githubusercontent.com/436043/163686169-766ef715-89b5-4ada-88d7-672623713bc0.png"></a>
  <br><br><a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com"><img width="34" alt="Missive | Team email, team chat, team tasks, one app" src="https://user-images.githubusercontent.com/436043/163655413-df22f8cc-99a7-4d8d-a5c1-105c435910d7.png"></a>
  <br>Brought to you by the <a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com">Missive</a> team
</div>

## 📖 Table of Contents
- [💾 Data](#-data)
- [🏪 Picker](#-picker)
- [🙃 Emoji component](#-emoji-component)
- [🕵️‍♀️ Headless search](#%EF%B8%8F%EF%B8%8F-headless-search)
- [🔬 Get emoji data from native](#-get-emoji-data-from-native)
- [🗺 Internationalization](#-internationalization)
- [📚 Examples](#-examples)
- [🤓 Built for modern browsers](#-built-for-modern-browsers)
- [🛠 Development](#-development)

## 💾 Data

Data required for the picker to work has been completely decoupled from the library. That gives developers the flexibility to better control their app bundle size and let them choose how and when this data is loaded. Data can be:

### Bundled directly into your codebase
- **Pros:** Picker renders instantly, data is available offline
- **Cons:** Slower initial page load (bigger file to load)

```sh
yarn add @emoji-mart/data
```

```js
import data from '@emoji-mart/data'
import { Picker } from 'emoji-mart'

new Picker({ data })
```

### Fetched remotely
- **Pros:** Data fetched only when needed, does not affect your app bundle size
- **Cons:** Network latency, doesn’t work offline (unless you configure a ServiceWorker)

```js
import { Picker } from 'emoji-mart'
new Picker({
  data: async () => {
    const response = await fetch(
      'https://cdn.jsdelivr.net/npm/@emoji-mart/data',
    )

    return response.json()
  }
})
```

In this example data is fetched from a content delivery network, but it could also be fetched from your own domain if you want to host the data.

## 🏪 Picker
### React
```sh
npm install --save emoji-mart @emoji-mart/data @emoji-mart/react
```

```js
import data from '@emoji-mart/data'
import Picker from '@emoji-mart/react'

function App() {
  return (
    <Picker data={data} onEmojiSelect={console.log} />
  )
}
```

### Browser
```html
<script src="https://cdn.jsdelivr.net/npm/emoji-mart@latest/dist/browser.js"></script>
<script>
  const pickerOptions = { onEmojiSelect: console.log }
  const picker = new EmojiMart.Picker(pickerOptions)

  document.body.appendChild(picker)
</script>
```

### Options / Props
| Option | Default | Choices | Description |
| ------ | ------- | ------- | ----------- |
| **data** | `{}` | | Data to use for the picker |
| **i18n** | `{}` | | Localization data to use for the picker |
| **categories** | `[]` | `frequent`, `people`, `nature`, `foods`, `activity`, `places`, `objects`, `symbols`, `flags` | Categories to show in the picker. Order is respected.  |
| **custom** | `[]` | | [Custom emojis](#custom-emojis) |
| **onEmojiSelect** | `null` | | Callback when an emoji is selected |
| **onClickOutside** | `null` | | Callback when a click outside of the picker happens |
| **onAddCustomEmoji** | `null` | | Callback when the *Add custom emoji* button is clicked. The button will only be displayed if this callback is provided. It is displayed when search returns no results. |
| **autoFocus** | `false` | | Whether the picker should automatically focus on the search input |
| **categoryIcons** | `{}` | | [Custom category icons](#custom-category-icons) |
| **dynamicWidth** | `false` | | Whether the picker should calculate `perLine` dynamically based on the width of `<em-emoji-picker>`. When enabled, `perLine` is ignored |
| **emojiButtonColors** | `[]` | i.e. `#f00`, `pink`, `rgba(155,223,88,.7)` | An array of color that affects the hover background color |
| **emojiButtonRadius** | `100%` | i.e. `6px`, `1em`, `100%` | The radius of the emoji buttons |
| **emojiButtonSize** | `36` | | The size of the emoji buttons |
| **emojiSize** | `24` | | The size of the emojis (inside the buttons) |
| **emojiVersion** | `14` | `1`, `2`, `3`, `4`, `5`, `11`, `12`, `12.1`, `13`, `13.1`, `14` | The version of the emoji data to use. Latest version supported in `@emoji-mart/data` is currently [14](https://emojipedia.org/emoji-14.0) |
| **exceptEmojis** | `[]` | | List of emoji IDs that will be excluded from the picker |
| **icons** | `auto` | `auto`, `outline`, `solid` | The type of icons to use for the picker. `outline` with light theme and `solid` with dark theme. |
| **locale** | `en` | `en`, `ar`, `be`, `cs`, `de`, `es`, `fa`, `fi`, `fr`, `hi`, `it`, `ja`, `ko`, `nl`, `pl`, `pt`, `ru`, `sa`, `tr`, `uk`, `vi`, `zh` | The locale to use for the picker |
| **maxFrequentRows** | `4` | | The maximum number of frequent rows to show. `0` will disable frequent category |
| **navPosition** | `top` | `top`, `bottom`, `none` | The position of the navigation bar |
| **noCountryFlags** | `false` | | Whether to show country flags or not. If not provided, tbhis is handled automatically (Windows doesn’t support country flags) |
| **noResultsEmoji** | `cry` | | The id of the emoji to use for the no results emoji |
| **perLine** | `9` | | The number of emojis to show per line |
| **previewEmoji** | `point_up` | | The id of the emoji to use for the preview when not hovering any emoji. `point_up` when preview position is bottom and `point_down` when preview position is top. |
| **previewPosition** | `bottom` | `top`, `bottom`, `none` | The position of the preview |
| **searchPosition** | `sticky` | `sticky`, `static`, `none` | The position of the search input |
| **set** | `native` | `native`, `apple`, `facebook`, `google`, `twitter` | The set of emojis to use for the picker. `native` being the most performant, others rely on spritesheets. |
| **skin** | `1` | `1`, `2`, `3`, `4`, `5`, `6` | The emojis skin tone |
| **skinTonePosition** | `preview` | `preview`, `search`, `none` | The position of the skin tone selector |
| **theme** | `auto` | `auto`, `light`, `dark` | The color theme of the picker |
| **getSpritesheetURL** | `null` | | A function that returns the URL of the spritesheet to use for the picker. It should be compatible with the data provided. |

### Custom emojis
You can use custom emojis by providing an array of categories and their emojis. Emojis also support multiple skin tones and can be GIFs or SVGs.

```js
import data from '@emoji-mart/data'
import Picker from '@emoji-mart/react'

const custom = [
  {
    id: 'github',
    name: 'GitHub',
    emojis: [
      {
        id: 'octocat',
        name: 'Octocat',
        keywords: ['github'],
        skins: [{ src: './octocat.png' }],
      },
      {
        id: 'shipit',
        name: 'Squirrel',
        keywords: ['github'],
        skins: [
          { src: './shipit-1.png' }, { src: './shipit-2.png' }, { src: './shipit-3.png' },
          { src: './shipit-4.png' }, { src: './shipit-5.png' }, { src: './shipit-6.png' },
        ],
      },
    ],
  },
  {
    id: 'gifs',
    name: 'GIFs',
    emojis: [
      {
        id: 'party_parrot',
        name: 'Party Parrot',
        keywords: ['dance', 'dancing'],
        skins: [{ src: './party_parrot.gif' }],
      },
    ],
  },
]

function App() {
  return (
    <Picker data={data} custom={custom} />
  )
}
```

### Custom category icons
You can use custom category icons by providing an object with the category name as key and the icon as value. Currently supported formats are `svg` string and `src`. See [example](https://missiveapp.com/open/emoji-mart/example-categories.html).

```js
const customCategoryIcons = {
  categoryIcons: {
    activity: {
      svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M57.89 397.2c-6.262-8.616-16.02-13.19-25.92-13.19c-23.33 0-31.98 20.68-31.98 32.03c0 6.522 1.987 13.1 6.115 18.78l46.52 64C58.89 507.4 68.64 512 78.55 512c23.29 0 31.97-20.66 31.97-32.03c0-6.522-1.988-13.1-6.115-18.78L57.89 397.2zM496.1 352c-44.13 0-79.72 35.75-79.72 80s35.59 80 79.72 80s79.91-35.75 79.91-80S540.2 352 496.1 352zM640 99.38c0-13.61-4.133-27.34-12.72-39.2l-23.63-32.5c-13.44-18.5-33.77-27.68-54.12-27.68c-13.89 0-27.79 4.281-39.51 12.8L307.8 159.7C262.2 192.8 220.4 230.9 183.4 273.4c-24.22 27.88-59.18 63.99-103.5 99.63l56.34 77.52c53.79-35.39 99.15-55.3 127.1-67.27c51.88-22 101.3-49.87 146.9-82.1l202.3-146.7C630.5 140.4 640 120 640 99.38z"/></svg>',
    },
    people: {
      src: './people.png',
    },
  },
}
```

## 🙃 Emoji component
The emoji web component usage is the same no matter what library you use.

First, you need to make sure data has been initialized. You need to call this only once per page load. Note that if you call `init` like this, you don’t necessarily need to include data in your Picker props. It doesn’t hurt either, it will noop.

```js
import data from '@emoji-mart/data'
import { init } from 'emoji-mart'

init({ data })
```

Then you can use the emoji component in your HTML / JSX.

```html
<em-emoji id="+1" size="2em"></em-emoji>
<em-emoji id="+1" skin="2"></em-emoji>
<em-emoji shortcodes=":+1::skin-tone-1:"></em-emoji>
<em-emoji shortcodes=":+1::skin-tone-2:"></em-emoji>
```

### Attributes / Props
| Attribute | Example | Description |
| --------- | ------- | ----------- |
| **id** | `+1` | An emoji ID |
| **shortcodes** | `:+1::skin-tone-2:` | An emoji shortcode |
| **native** | `👍` | A native emoji |
| **size** | `2em` | The inline element size |
| **fallback** | `:shrug:` | A string to be rendered in case the emoji can’t be found |
| **set** | `native` | The emoji set: `native`, `apple`, `facebook`, `google`, `twitter` |
| **skin** | `1` | The emoji skin tone: `1`, `2`, `3`, `4`, `5`, `6` |

## 🕵️‍♀️ Headless search
You can search without the Picker. Just like the emoji component, `data` needs to be initialized first in order to use the search index.

```js
import data from '@emoji-mart/data'
import { init, SearchIndex } from 'emoji-mart'

init({ data })

async function search(value) {
  const emojis = await SearchIndex.search(value)
  const results = emojis.map((emoji) => {
    return emoji.skins[0].native
  })

  console.log(results)
}

search('christmas') // => ['🎄', '🇨🇽', '🧑‍🎄', '🔔', '🤶', '🎁', '☃️', '❄️', '🎅', '⛄']
```

## 🔬 Get emoji data from native
You can get emoji data from a native emoji. This is useful if you want to get the emoji ID from a native emoji. Just like the emoji component, `data` needs to be initialized first in order to retrieve the emoji data.

```js
import data from '@emoji-mart/data'
import { init, getEmojiDataFromNative } from 'emoji-mart'

init({ data })

getEmojiDataFromNative('🤞🏿').then(console.log)
/* {
  aliases: ['hand_with_index_and_middle_fingers_crossed'],
  id: 'crossed_fingers',
  keywords: ['hand', 'with', 'index', 'and', 'middle', 'good', 'lucky'],
  name: 'Crossed Fingers',
  native: '🤞🏿',
  shortcodes: ':crossed_fingers::skin-tone-6:',
  skin: 6,
  unified: '1f91e-1f3ff',
} */
```

## 🗺 Internationalization
EmojiMart UI supports [multiple languages](https://github.com/missive/emoji-mart/tree/main/packages/emoji-mart-data/i18n), feel free to open a PR if yours is missing.

```js
import i18n from '@emoji-mart/data/i18n/fr.json'
i18n.search_no_results_1 = 'Aucun emoji'

new Picker({ i18n })
```

Given the small file size, English is built-in and doesn’t need to be provided.

## 📚 Examples

- [Categories](https://missiveapp.com/open/emoji-mart/example-categories.html)
- [Custom emoji font](https://missiveapp.com/open/emoji-mart/example-custom-font.html)
- [Custom styles](https://missiveapp.com/open/emoji-mart/example-custom-styles.html)
- [Emoji component](https://missiveapp.com/open/emoji-mart/example-emoji-component.html)
- [Headless search](https://missiveapp.com/open/emoji-mart/example-headless-search.html)
- [Slack colors](https://missiveapp.com/open/emoji-mart/example-slack-colors.html)

## 🤓 Built for modern browsers
EmojiMart relies on these APIs, you may need to include polyfills if you need to support older browsers:
- [Shadow DOM](https://caniuse.com/shadowdomv1) ([MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM))
- [Custom elements](https://caniuse.com/custom-elementsv1) ([MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements))
- [IntersectionObserver](https://caniuse.com/intersectionobserver) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API))
- [Async/Await](https://caniuse.com/async-functions) ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))

## 🛠 Development
```sh
yarn install
yarn dev
```


================================================
FILE: jest/esm-transformer.js
================================================
const babel = require('@babel/core')

module.exports = {
  process(src) {
    const transform = babel.transform(src, {
      babelrc: false,
      compact: false,
      plugins: [require.resolve('@babel/plugin-transform-modules-commonjs')],
    })

    return transform
  },
}


================================================
FILE: jest.config.js
================================================
/*
 * For a detailed explanation regarding each configuration property, visit:
 * https://jestjs.io/docs/configuration
 */

module.exports = {
  // All imported modules in your tests should be mocked automatically
  // automock: false,

  // Stop running tests after `n` failures
  // bail: 0,

  // The directory where Jest should store its cached dependency information
  // cacheDirectory: "/private/var/folders/vs/4cfg6_bd3vgcx3l_r272_m9m0000gn/T/jest_dx",

  // Automatically clear mock calls, instances, contexts and results before every test
  clearMocks: true,

  // Indicates whether the coverage information should be collected while executing the test
  collectCoverage: true,

  // An array of glob patterns indicating a set of files for which coverage information should be collected
  // collectCoverageFrom: undefined,

  // The directory where Jest should output its coverage files
  coverageDirectory: 'coverage',

  // An array of regexp pattern strings used to skip coverage collection
  // coveragePathIgnorePatterns: [
  //   "/node_modules/"
  // ],

  // Indicates which provider should be used to instrument code for coverage
  coverageProvider: 'v8',

  // A list of reporter names that Jest uses when writing coverage reports
  // coverageReporters: [
  //   "json",
  //   "text",
  //   "lcov",
  //   "clover"
  // ],

  // An object that configures minimum threshold enforcement for coverage results
  // coverageThreshold: undefined,

  // A path to a custom dependency extractor
  // dependencyExtractor: undefined,

  // Make calling deprecated APIs throw helpful error messages
  // errorOnDeprecated: false,

  // The default configuration for fake timers
  // fakeTimers: {
  //   "enableGlobally": false
  // },

  // Force coverage collection from ignored files using an array of glob patterns
  // forceCoverageMatch: [],

  // A path to a module which exports an async function that is triggered once before all test suites
  // globalSetup: undefined,

  // A path to a module which exports an async function that is triggered once after all test suites
  // globalTeardown: undefined,

  // A set of global variables that need to be available in all test environments
  // globals: {},

  // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
  // maxWorkers: "50%",

  // An array of directory names to be searched recursively up from the requiring module's location
  // moduleDirectories: [
  //   "node_modules"
  // ],

  // An array of file extensions your modules use
  // moduleFileExtensions: [
  //   "js",
  //   "mjs",
  //   "cjs",
  //   "jsx",
  //   "ts",
  //   "tsx",
  //   "json",
  //   "node"
  // ],

  // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
  // moduleNameMapper: {},

  // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
  // modulePathIgnorePatterns: [],

  // Activates notifications for test results
  // notify: false,

  // An enum that specifies notification mode. Requires { notify: true }
  // notifyMode: "failure-change",

  // A preset that is used as a base for Jest's configuration
  // preset: undefined,

  // Run tests from one or more projects
  // projects: undefined,

  // Use this configuration option to add custom reporters to Jest
  // reporters: undefined,

  // Automatically reset mock state before every test
  // resetMocks: false,

  // Reset the module registry before running each individual test
  // resetModules: false,

  // A path to a custom resolver
  // resolver: undefined,

  // Automatically restore mock state and implementation before every test
  // restoreMocks: false,

  // The root directory that Jest should scan for tests and modules within
  // rootDir: undefined,

  // A list of paths to directories that Jest should use to search for files in
  // roots: [
  //   "<rootDir>"
  // ],

  // Allows you to use a custom runner instead of Jest's default test runner
  // runner: "jest-runner",

  // The paths to modules that run some code to configure or set up the testing environment before each test
  // setupFiles: [],

  // A list of paths to modules that run some code to configure or set up the testing framework before each test
  // setupFilesAfterEnv: [],

  // The number of seconds after which a test is considered as slow and reported as such in the results.
  // slowTestThreshold: 5,

  // A list of paths to snapshot serializer modules Jest should use for snapshot testing
  // snapshotSerializers: [],

  // The test environment that will be used for testing
  testEnvironment: 'jest-environment-jsdom',

  // Options that will be passed to the testEnvironment
  // testEnvironmentOptions: {},

  // Adds a location field to test results
  // testLocationInResults: false,

  // The glob patterns Jest uses to detect test files
  // testMatch: [
  //   "**/__tests__/**/*.[jt]s?(x)",
  //   "**/?(*.)+(spec|test).[tj]s?(x)"
  // ],

  // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
  // testPathIgnorePatterns: [
  //   "/node_modules/"
  // ],

  // The regexp pattern or array of patterns that Jest uses to detect test files
  // testRegex: [],

  // This option allows the use of a custom results processor
  // testResultsProcessor: undefined,

  // This option allows use of a custom test runner
  // testRunner: "jest-circus/runner",

  // A map from regular expressions to paths to transformers
  transform: {
    '.js$': './jest/esm-transformer.js',
    '\\.tsx?$': 'ts-jest',
  },

  // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
  // transformIgnorePatterns: [
  //   "/node_modules/",
  //   "\\.pnp\\.[^\\/]+$"
  // ],

  // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
  // unmockedModulePathPatterns: undefined,

  // Indicates whether each individual test should be reported during the run
  // verbose: undefined,

  // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
  // watchPathIgnorePatterns: [],

  // Whether to use watchman for file crawling
  // watchman: true,
}


================================================
FILE: package.json
================================================
{
  "name": "@emoji-mart/monorepo",
  "version": "1.0.0",
  "private": true,
  "workspaces": [
    "packages/*"
  ],
  "scripts": {
    "dev": "yarn workspace @emoji-mart/website dev",
    "build": "yarn workspace emoji-mart build",
    "build:data": "yarn workspace @emoji-mart/data build",
    "build:react": "yarn workspace @emoji-mart/react build",
    "build:website": "yarn workspace @emoji-mart/website build",
    "check:types": "tsc",
    "prettier": "prettier --check .",
    "prettier:fix": "prettier --write .",
    "test": "jest"
  },
  "devDependencies": {
    "@babel/core": "7.18.9",
    "@babel/plugin-transform-modules-commonjs": "7.18.6",
    "@parcel/packager-ts": "2.6.2",
    "@parcel/transformer-inline-string": "2.6.2",
    "@parcel/transformer-sass": "2.6.2",
    "@parcel/transformer-typescript-types": "2.6.2",
    "jest-environment-jsdom": "28.0.0",
    "jest": "^28.1.3",
    "parcel": "2.6.2",
    "prettier": "2.5.1",
    "ts-jest": "^28.0.7",
    "typescript": "4.6.4"
  },
  "prettier": {
    "semi": false,
    "singleQuote": true,
    "trailingComma": "all",
    "arrowParens": "always"
  },
  "engines": {
    "yarn": ">=1"
  }
}


================================================
FILE: packages/emoji-mart/LICENSE
================================================
MIT License

Copyright (c) Missive.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: packages/emoji-mart/README.md
================================================
<div align="center">
  <br><b>Emoji Mart</b> is a customizable<br>emoji picker HTML component for the web
  <br><a href="https://missiveapp.com/open/emoji-mart">Demo</a>
  <br><br><a href="https://missiveapp.com/open/emoji-mart"><img width="639" alt="EmojiMart" src="https://user-images.githubusercontent.com/436043/163686169-766ef715-89b5-4ada-88d7-672623713bc0.png"></a>
  <br><br><a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com"><img width="34" alt="Missive | Team email, team chat, team tasks, one app" src="https://user-images.githubusercontent.com/436043/163655413-df22f8cc-99a7-4d8d-a5c1-105c435910d7.png"></a>
  <br>Brought to you by the <a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com">Missive</a> team
</div>

## 📖 Table of Contents
- [💾 Data](#-data)
- [🏪 Picker](#-picker)
- [🙃 Emoji component](#-emoji-component)
- [🕵️‍♀️ Headless search](#%EF%B8%8F%EF%B8%8F-headless-search)
- [🔬 Get emoji data from native](#-get-emoji-data-from-native)
- [🗺 Internationalization](#-internationalization)
- [📚 Examples](#-examples)
- [🤓 Built for modern browsers](#-built-for-modern-browsers)
- [🛠 Development](#-development)

## 💾 Data

Data required for the picker to work has been completely decoupled from the library. That gives developers the flexibility to better control their app bundle size and let them choose how and when this data is loaded. Data can be:

### Bundled directly into your codebase
- **Pros:** Picker renders instantly, data is available offline
- **Cons:** Slower initial page load (bigger file to load)

```sh
yarn add @emoji-mart/data
```

```js
import data from '@emoji-mart/data'
import { Picker } from 'emoji-mart'

new Picker({ data })
```

### Fetched remotely
- **Pros:** Data fetched only when needed, does not affect your app bundle size
- **Cons:** Network latency, doesn’t work offline (unless you configure a ServiceWorker)

```js
import { Picker } from 'emoji-mart'
new Picker({
  data: async () => {
    const response = await fetch(
      'https://cdn.jsdelivr.net/npm/@emoji-mart/data',
    )

    return response.json()
  }
})
```

In this example data is fetched from a content delivery network, but it could also be fetched from your own domain if you want to host the data.

## 🏪 Picker
### React
```sh
npm install --save emoji-mart @emoji-mart/data @emoji-mart/react
```

```js
import data from '@emoji-mart/data'
import Picker from '@emoji-mart/react'

function App() {
  return (
    <Picker data={data} onEmojiSelect={console.log} />
  )
}
```

### Browser
```html
<script src="https://cdn.jsdelivr.net/npm/emoji-mart@latest/dist/browser.js"></script>
<script>
  const pickerOptions = { onEmojiSelect: console.log }
  const picker = new EmojiMart.Picker(pickerOptions)

  document.body.appendChild(picker)
</script>
```

### Options / Props
| Option | Default | Choices | Description |
| ------ | ------- | ------- | ----------- |
| **data** | `{}` | | Data to use for the picker |
| **i18n** | `{}` | | Localization data to use for the picker |
| **categories** | `[]` | `frequent`, `people`, `nature`, `foods`, `activity`, `places`, `objects`, `symbols`, `flags` | Categories to show in the picker. Order is respected.  |
| **custom** | `[]` | | [Custom emojis](#custom-emojis) |
| **onEmojiSelect** | `null` | | Callback when an emoji is selected |
| **onClickOutside** | `null` | | Callback when a click outside of the picker happens |
| **onAddCustomEmoji** | `null` | | Callback when the *Add custom emoji* button is clicked. The button will only be displayed if this callback is provided. It is displayed when search returns no results. |
| **autoFocus** | `false` | | Whether the picker should automatically focus on the search input |
| **categoryIcons** | `{}` | | [Custom category icons](#custom-category-icons) |
| **dynamicWidth** | `false` | | Whether the picker should calculate `perLine` dynamically based on the width of `<em-emoji-picker>`. When enabled, `perLine` is ignored |
| **emojiButtonColors** | `[]` | i.e. `#f00`, `pink`, `rgba(155,223,88,.7)` | An array of color that affects the hover background color |
| **emojiButtonRadius** | `100%` | i.e. `6px`, `1em`, `100%` | The radius of the emoji buttons |
| **emojiButtonSize** | `36` | | The size of the emoji buttons |
| **emojiSize** | `24` | | The size of the emojis (inside the buttons) |
| **emojiVersion** | `14` | `1`, `2`, `3`, `4`, `5`, `11`, `12`, `12.1`, `13`, `13.1`, `14` | The version of the emoji data to use. Latest version supported in `@emoji-mart/data` is currently [14](https://emojipedia.org/emoji-14.0) |
| **exceptEmojis** | `[]` | | List of emoji IDs that will be excluded from the picker |
| **icons** | `auto` | `auto`, `outline`, `solid` | The type of icons to use for the picker. `outline` with light theme and `solid` with dark theme. |
| **locale** | `en` | `en`, `ar`, `be`, `cs`, `de`, `es`, `fa`, `fi`, `fr`, `hi`, `it`, `ja`, `ko`, `nl`, `pl`, `pt`, `ru`, `sa`, `tr`, `uk`, `vi`, `zh` | The locale to use for the picker |
| **maxFrequentRows** | `4` | | The maximum number of frequent rows to show. `0` will disable frequent category |
| **navPosition** | `top` | `top`, `bottom`, `none` | The position of the navigation bar |
| **noCountryFlags** | `false` | | Whether to show country flags or not. If not provided, tbhis is handled automatically (Windows doesn’t support country flags) |
| **noResultsEmoji** | `cry` | | The id of the emoji to use for the no results emoji |
| **perLine** | `9` | | The number of emojis to show per line |
| **previewEmoji** | `point_up` | | The id of the emoji to use for the preview when not hovering any emoji. `point_up` when preview position is bottom and `point_down` when preview position is top. |
| **previewPosition** | `bottom` | `top`, `bottom`, `none` | The position of the preview |
| **searchPosition** | `sticky` | `sticky`, `static`, `none` | The position of the search input |
| **set** | `native` | `native`, `apple`, `facebook`, `google`, `twitter` | The set of emojis to use for the picker. `native` being the most performant, others rely on spritesheets. |
| **skin** | `1` | `1`, `2`, `3`, `4`, `5`, `6` | The emojis skin tone |
| **skinTonePosition** | `preview` | `preview`, `search`, `none` | The position of the skin tone selector |
| **theme** | `auto` | `auto`, `light`, `dark` | The color theme of the picker |
| **getSpritesheetURL** | `null` | | A function that returns the URL of the spritesheet to use for the picker. It should be compatible with the data provided. |

### Custom emojis
You can use custom emojis by providing an array of categories and their emojis. Emojis also support multiple skin tones and can be GIFs or SVGs.

```js
import data from '@emoji-mart/data'
import Picker from '@emoji-mart/react'

const custom = [
  {
    id: 'github',
    name: 'GitHub',
    emojis: [
      {
        id: 'octocat',
        name: 'Octocat',
        keywords: ['github'],
        skins: [{ src: './octocat.png' }],
      },
      {
        id: 'shipit',
        name: 'Squirrel',
        keywords: ['github'],
        skins: [
          { src: './shipit-1.png' }, { src: './shipit-2.png' }, { src: './shipit-3.png' },
          { src: './shipit-4.png' }, { src: './shipit-5.png' }, { src: './shipit-6.png' },
        ],
      },
    ],
  },
  {
    id: 'gifs',
    name: 'GIFs',
    emojis: [
      {
        id: 'party_parrot',
        name: 'Party Parrot',
        keywords: ['dance', 'dancing'],
        skins: [{ src: './party_parrot.gif' }],
      },
    ],
  },
]

function App() {
  return (
    <Picker data={data} custom={custom} />
  )
}
```

### Custom category icons
You can use custom category icons by providing an object with the category name as key and the icon as value. Currently supported formats are `svg` string and `src`. See [example](https://missiveapp.com/open/emoji-mart/example-categories.html).

```js
const customCategoryIcons = {
  categoryIcons: {
    activity: {
      svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M57.89 397.2c-6.262-8.616-16.02-13.19-25.92-13.19c-23.33 0-31.98 20.68-31.98 32.03c0 6.522 1.987 13.1 6.115 18.78l46.52 64C58.89 507.4 68.64 512 78.55 512c23.29 0 31.97-20.66 31.97-32.03c0-6.522-1.988-13.1-6.115-18.78L57.89 397.2zM496.1 352c-44.13 0-79.72 35.75-79.72 80s35.59 80 79.72 80s79.91-35.75 79.91-80S540.2 352 496.1 352zM640 99.38c0-13.61-4.133-27.34-12.72-39.2l-23.63-32.5c-13.44-18.5-33.77-27.68-54.12-27.68c-13.89 0-27.79 4.281-39.51 12.8L307.8 159.7C262.2 192.8 220.4 230.9 183.4 273.4c-24.22 27.88-59.18 63.99-103.5 99.63l56.34 77.52c53.79-35.39 99.15-55.3 127.1-67.27c51.88-22 101.3-49.87 146.9-82.1l202.3-146.7C630.5 140.4 640 120 640 99.38z"/></svg>',
    },
    people: {
      src: './people.png',
    },
  },
}
```

## 🙃 Emoji component
The emoji web component usage is the same no matter what library you use.

First, you need to make sure data has been initialized. You need to call this only once per page load. Note that if you call `init` like this, you don’t necessarily need to include data in your Picker props. It doesn’t hurt either, it will noop.

```js
import data from '@emoji-mart/data'
import { init } from 'emoji-mart'

init({ data })
```

Then you can use the emoji component in your HTML / JSX.

```html
<em-emoji id="+1" size="2em"></em-emoji>
<em-emoji id="+1" skin="2"></em-emoji>
<em-emoji shortcodes=":+1::skin-tone-1:"></em-emoji>
<em-emoji shortcodes=":+1::skin-tone-2:"></em-emoji>
```

### Attributes / Props
| Attribute | Example | Description |
| --------- | ------- | ----------- |
| **id** | `+1` | An emoji ID |
| **shortcodes** | `:+1::skin-tone-2:` | An emoji shortcode |
| **native** | `👍` | A native emoji |
| **size** | `2em` | The inline element size |
| **fallback** | `:shrug:` | A string to be rendered in case the emoji can’t be found |
| **set** | `native` | The emoji set: `native`, `apple`, `facebook`, `google`, `twitter` |
| **skin** | `1` | The emoji skin tone: `1`, `2`, `3`, `4`, `5`, `6` |

## 🕵️‍♀️ Headless search
You can search without the Picker. Just like the emoji component, `data` needs to be initialized first in order to use the search index.

```js
import data from '@emoji-mart/data'
import { init, SearchIndex } from 'emoji-mart'

init({ data })

async function search(value) {
  const emojis = await SearchIndex.search(value)
  const results = emojis.map((emoji) => {
    return emoji.skins[0].native
  })

  console.log(results)
}

search('christmas') // => ['🎄', '🇨🇽', '🧑‍🎄', '🔔', '🤶', '🎁', '☃️', '❄️', '🎅', '⛄']
```

## 🔬 Get emoji data from native
You can get emoji data from a native emoji. This is useful if you want to get the emoji ID from a native emoji. Just like the emoji component, `data` needs to be initialized first in order to retrieve the emoji data.

```js
import data from '@emoji-mart/data'
import { init, getEmojiDataFromNative } from 'emoji-mart'

init({ data })

getEmojiDataFromNative('🤞🏿').then(console.log)
/* {
  aliases: ['hand_with_index_and_middle_fingers_crossed'],
  id: 'crossed_fingers',
  keywords: ['hand', 'with', 'index', 'and', 'middle', 'good', 'lucky'],
  name: 'Crossed Fingers',
  native: '🤞🏿',
  shortcodes: ':crossed_fingers::skin-tone-6:',
  skin: 6,
  unified: '1f91e-1f3ff',
} */
```

## 🗺 Internationalization
EmojiMart UI supports [multiple languages](https://github.com/missive/emoji-mart/tree/main/packages/emoji-mart-data/i18n), feel free to open a PR if yours is missing.

```js
import i18n from '@emoji-mart/data/i18n/fr.json'
i18n.search_no_results_1 = 'Aucun emoji'

new Picker({ i18n })
```

Given the small file size, English is built-in and doesn’t need to be provided.

## 📚 Examples

- [Categories](https://missiveapp.com/open/emoji-mart/example-categories.html)
- [Custom emoji font](https://missiveapp.com/open/emoji-mart/example-custom-font.html)
- [Custom styles](https://missiveapp.com/open/emoji-mart/example-custom-styles.html)
- [Emoji component](https://missiveapp.com/open/emoji-mart/example-emoji-component.html)
- [Headless search](https://missiveapp.com/open/emoji-mart/example-headless-search.html)
- [Slack colors](https://missiveapp.com/open/emoji-mart/example-slack-colors.html)

## 🤓 Built for modern browsers
EmojiMart relies on these APIs, you may need to include polyfills if you need to support older browsers:
- [Shadow DOM](https://caniuse.com/shadowdomv1) ([MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM))
- [Custom elements](https://caniuse.com/custom-elementsv1) ([MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements))
- [IntersectionObserver](https://caniuse.com/intersectionobserver) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API))
- [Async/Await](https://caniuse.com/async-functions) ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))

## 🛠 Development
```sh
yarn install
yarn dev
```


================================================
FILE: packages/emoji-mart/package.json
================================================
{
  "name": "emoji-mart",
  "version": "5.6.0",
  "description": "Emoji picker for the web",
  "license": "MIT",
  "homepage": "https://missiveapp.com/open/emoji-mart",
  "repository": {
    "type": "git",
    "url": "https://github.com/missive/emoji-mart",
    "directory": "packages/emoji-mart"
  },
  "source": "src/index.ts",
  "types": "dist/index.d.ts",
  "main": "dist/main.js",
  "module": "dist/module.js",
  "global": "dist/browser.js",
  "browserslist": "defaults",
  "targets": {
    "main": {
      "includeNodeModules": true
    },
    "module": {
      "includeNodeModules": true
    },
    "global": {
      "source": "src/browser.js",
      "includeNodeModules": true
    }
  },
  "keywords": [
    "emoji",
    "emoticons",
    "emoji-picker",
    "web-component",
    "twemoji"
  ],
  "scripts": {
    "build": "parcel build --no-autoinstall",
    "prepublishOnly": "yarn build"
  },
  "devDependencies": {
    "preact": "10.6.4"
  },
  "alias": {
    "react": "preact/compat",
    "react-dom/test-utils": "preact/test-utils",
    "react-dom": "preact/compat",
    "react/jsx-runtime": "preact/jsx-runtime",
    "preact/jsx-dev-runtime": "preact/jsx-runtime"
  },
  "files": [
    "/dist",
    "LICENSE"
  ]
}


================================================
FILE: packages/emoji-mart/src/__tests__/config.test.js
================================================
import { init } from '../config'

describe('init', () => {
  test.skip('', () => {})
})


================================================
FILE: packages/emoji-mart/src/__tests__/utils.test.js
================================================
import { jest } from '@jest/globals'
import { deepEqual, sleep } from '../utils'

describe('deepEqual', () => {
  test('validates deep equality', () => {
    expect(deepEqual([], [])).toBe(true)
    expect(deepEqual([0, 0], [0, 0])).toBe(true)
    expect(deepEqual([0, 1], [1, 0])).toBe(false)
  })
})

describe('sleep', () => {
  beforeEach(() => {
    jest.spyOn(window, 'requestAnimationFrame')
  })

  afterEach(() => {
    window.requestAnimationFrame.mockRestore()
  })

  test('sleep', async () => {
    expect(window.requestAnimationFrame).toHaveBeenCalledTimes(0)
    await sleep(1)
    expect(window.requestAnimationFrame).toHaveBeenCalledTimes(1)
    await sleep(2)
    expect(window.requestAnimationFrame).toHaveBeenCalledTimes(3)
  })
})


================================================
FILE: packages/emoji-mart/src/browser.js
================================================
import * as EmojiMart from './index'
window.EmojiMart = EmojiMart


================================================
FILE: packages/emoji-mart/src/components/Emoji/Emoji.tsx
================================================
import { Data } from '../../config'
import { SearchIndex } from '../../helpers'

export default function Emoji(props) {
  let { id, skin, emoji } = props

  if (props.shortcodes) {
    const matches = props.shortcodes.match(SearchIndex.SHORTCODES_REGEX)

    if (matches) {
      id = matches[1]

      if (matches[2]) {
        skin = matches[2]
      }
    }
  }

  emoji || (emoji = SearchIndex.get(id || props.native))
  if (!emoji) return props.fallback

  const emojiSkin = emoji.skins[skin - 1] || emoji.skins[0]

  const imageSrc =
    emojiSkin.src ||
    (props.set != 'native' && !props.spritesheet
      ? typeof props.getImageURL === 'function'
        ? props.getImageURL(props.set, emojiSkin.unified)
        : `https://cdn.jsdelivr.net/npm/emoji-datasource-${props.set}@15.0.1/img/${props.set}/64/${emojiSkin.unified}.png`
      : undefined)

  const spritesheetSrc =
    typeof props.getSpritesheetURL === 'function'
      ? props.getSpritesheetURL(props.set)
      : `https://cdn.jsdelivr.net/npm/emoji-datasource-${props.set}@15.0.1/img/${props.set}/sheets-256/64.png`

  return (
    <span class="emoji-mart-emoji" data-emoji-set={props.set}>
      {imageSrc ? (
        <img
          style={{
            maxWidth: props.size || '1em',
            maxHeight: props.size || '1em',
            display: 'inline-block',
          }}
          alt={emojiSkin.native || emojiSkin.shortcodes}
          src={imageSrc}
        />
      ) : props.set == 'native' ? (
        <span
          style={{
            fontSize: props.size,
            fontFamily:
              '"EmojiMart", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji"',
          }}
        >
          {emojiSkin.native}
        </span>
      ) : (
        <span
          style={{
            display: 'block',
            width: props.size,
            height: props.size,
            backgroundImage: `url(${spritesheetSrc})`,
            backgroundSize: `${100 * Data.sheet.cols}% ${
              100 * Data.sheet.rows
            }%`,
            backgroundPosition: `${
              (100 / (Data.sheet.cols - 1)) * emojiSkin.x
            }% ${(100 / (Data.sheet.rows - 1)) * emojiSkin.y}%`,
          }}
        ></span>
      )}
    </span>
  )
}


================================================
FILE: packages/emoji-mart/src/components/Emoji/EmojiElement.jsx
================================================
import { render } from 'preact'

import { init, getProps } from '../../config'
import { HTMLElement } from '../HTMLElement'
import { Emoji } from '.'
import EmojiProps from './EmojiProps'

export default class EmojiElement extends HTMLElement {
  static Props = EmojiProps

  constructor(props) {
    super(props)
  }

  async connectedCallback() {
    const props = getProps(this.props, EmojiProps, this)
    props.element = this
    props.ref = (component) => {
      this.component = component
    }

    await init()
    if (this.disconnected) return

    render(<Emoji {...props} />, this)
  }
}

if (typeof customElements !== 'undefined' && !customElements.get('em-emoji')) {
  customElements.define('em-emoji', EmojiElement)
}


================================================
FILE: packages/emoji-mart/src/components/Emoji/EmojiProps.ts
================================================
import PickerProps from '../Picker/PickerProps'

export default {
  fallback: '',
  id: '',
  native: '',
  shortcodes: '',
  size: {
    value: '',
    transform: (value) => {
      // If the value is a number, then we assume it’s a pixel value.
      if (!/\D/.test(value)) {
        return `${value}px`
      }

      return value
    },
  },

  // Shared
  set: PickerProps.set,
  skin: PickerProps.skin,
}


================================================
FILE: packages/emoji-mart/src/components/Emoji/index.ts
================================================
export { default as Emoji } from './Emoji'
export { default as EmojiElement } from './EmojiElement'


================================================
FILE: packages/emoji-mart/src/components/HOCs/PureInlineComponent.ts
================================================
import { PureComponent } from 'preact/compat'

export default class PureInlineComponent extends PureComponent {
  shouldComponentUpdate(nextProps) {
    for (let k in nextProps) {
      if (k == 'children') continue

      if (nextProps[k] != this.props[k]) {
        return true
      }
    }

    return false
  }

  render() {
    return this.props.children
  }
}


================================================
FILE: packages/emoji-mart/src/components/HOCs/index.ts
================================================
export { default as PureInlineComponent } from './PureInlineComponent'


================================================
FILE: packages/emoji-mart/src/components/HTMLElement/HTMLElement.ts
================================================
// @ts-nocheck
import { getProp } from '../../config'

const WindowHTMLElement =
  typeof window !== 'undefined' && window.HTMLElement
    ? window.HTMLElement
    : Object

export default class HTMLElement extends WindowHTMLElement {
  static get observedAttributes() {
    return Object.keys(this.Props)
  }

  constructor(props = {}) {
    super()
    this.props = props

    if (props.parent || props.ref) {
      let ref = null
      const parent = props.parent || (ref = props.ref && props.ref.current)

      if (ref) ref.innerHTML = ''
      if (parent) parent.appendChild(this)
    }
  }

  update(props = {}) {
    for (let k in props) {
      this.attributeChangedCallback(k, null, props[k])
    }
  }

  attributeChangedCallback(attr, _, newValue) {
    if (!this.component) return

    const value = getProp(
      attr,
      { [attr]: newValue },
      this.constructor.Props,
      this,
    )

    if (this.component.componentWillReceiveProps) {
      this.component.componentWillReceiveProps({ [attr]: value })
    } else {
      this.component.props[attr] = value
      this.component.forceUpdate()
    }
  }

  disconnectedCallback() {
    this.disconnected = true

    if (this.component && this.component.unregister) {
      this.component.unregister()
    }
  }
}


================================================
FILE: packages/emoji-mart/src/components/HTMLElement/ShadowElement.ts
================================================
// @ts-nocheck
import { HTMLElement } from '.'

export default class ShadowElement extends HTMLElement {
  constructor(props, { styles } = {}) {
    super(props)

    this.setShadow()
    this.injectStyles(styles)
  }

  setShadow() {
    this.attachShadow({ mode: 'open' })
  }

  injectStyles(styles) {
    if (!styles) return

    const style = document.createElement('style')
    style.textContent = styles

    this.shadowRoot.insertBefore(style, this.shadowRoot.firstChild)
  }
}


================================================
FILE: packages/emoji-mart/src/components/HTMLElement/index.ts
================================================
export { default as HTMLElement } from './HTMLElement'
export { default as ShadowElement } from './ShadowElement'


================================================
FILE: packages/emoji-mart/src/components/Navigation/Navigation.tsx
================================================
// @ts-nocheck
import { PureComponent } from 'preact/compat'
import { Data, I18n } from '../../config'
import Icons from '../../icons'

const THEME_ICONS = {
  light: 'outline',
  dark: 'solid',
}

export default class Navigation extends PureComponent {
  constructor() {
    super()

    this.categories = Data.categories.filter((category) => {
      return !category.target
    })

    this.state = {
      categoryId: this.categories[0].id,
    }
  }

  renderIcon(category) {
    const { icon } = category

    if (icon) {
      if (icon.svg) {
        return (
          <span
            class="flex"
            dangerouslySetInnerHTML={{ __html: icon.svg }}
          ></span>
        )
      }

      if (icon.src) {
        return <img src={icon.src} />
      }
    }

    const categoryIcons =
      Icons.categories[category.id] || Icons.categories.custom

    const style =
      this.props.icons == 'auto'
        ? THEME_ICONS[this.props.theme]
        : this.props.icons

    return categoryIcons[style] || categoryIcons
  }

  render() {
    let selectedCategoryIndex = null

    return (
      <nav
        id="nav"
        class="padding"
        data-position={this.props.position}
        dir={this.props.dir}
      >
        <div class="flex relative">
          {this.categories.map((category, i) => {
            const title = category.name || I18n.categories[category.id]
            const selected =
              !this.props.unfocused && category.id == this.state.categoryId

            if (selected) {
              selectedCategoryIndex = i
            }

            return (
              <button
                aria-label={title}
                aria-selected={selected || undefined}
                title={title}
                type="button"
                class="flex flex-grow flex-center"
                onMouseDown={(e) => e.preventDefault()}
                onClick={() => {
                  this.props.onClick({ category, i })
                }}
              >
                {this.renderIcon(category)}
              </button>
            )
          })}

          <div
            class="bar"
            style={{
              width: `${100 / this.categories.length}%`,
              opacity: selectedCategoryIndex == null ? 0 : 1,
              transform:
                this.props.dir === 'rtl'
                  ? `scaleX(-1) translateX(${selectedCategoryIndex * 100}%)`
                  : `translateX(${selectedCategoryIndex * 100}%)`,
            }}
          ></div>
        </div>
      </nav>
    )
  }
}


================================================
FILE: packages/emoji-mart/src/components/Navigation/index.ts
================================================
export { default as Navigation } from './Navigation'


================================================
FILE: packages/emoji-mart/src/components/Picker/Picker.tsx
================================================
// @ts-nocheck
import { Component, createRef } from 'preact'

import { deepEqual, sleep, getEmojiData } from '../../utils'
import { Data, I18n, init } from '../../config'
import { SearchIndex, Store, FrequentlyUsed } from '../../helpers'
import Icons from '../../icons'

import { Emoji } from '../Emoji'
import { Navigation } from '../Navigation'
import { PureInlineComponent } from '../HOCs'

const Performance = {
  rowsPerRender: 10,
}

export default class Picker extends Component {
  constructor(props) {
    super()

    this.observers = []

    this.state = {
      pos: [-1, -1],
      perLine: this.initDynamicPerLine(props),
      visibleRows: { 0: true },
      ...this.getInitialState(props),
    }
  }

  getInitialState(props = this.props) {
    return {
      skin: Store.get('skin') || props.skin,
      theme: this.initTheme(props.theme),
    }
  }

  componentWillMount() {
    this.dir = I18n.rtl ? 'rtl' : 'ltr'
    this.refs = {
      menu: createRef(),
      navigation: createRef(),
      scroll: createRef(),
      search: createRef(),
      searchInput: createRef(),
      skinToneButton: createRef(),
      skinToneRadio: createRef(),
    }

    this.initGrid()

    if (
      this.props.stickySearch == false &&
      this.props.searchPosition == 'sticky'
    ) {
      console.warn(
        '[EmojiMart] Deprecation warning: `stickySearch` has been renamed `searchPosition`.',
      )

      this.props.searchPosition = 'static'
    }
  }

  componentDidMount() {
    this.register()

    this.shadowRoot = this.base.parentNode

    if (this.props.autoFocus) {
      const { searchInput } = this.refs
      if (searchInput.current) {
        searchInput.current.focus()
      }
    }
  }

  componentWillReceiveProps(nextProps) {
    this.nextState || (this.nextState = {})

    for (const k in nextProps) {
      this.nextState[k] = nextProps[k]
    }

    clearTimeout(this.nextStateTimer)
    this.nextStateTimer = setTimeout(() => {
      let requiresGridReset = false

      for (const k in this.nextState) {
        this.props[k] = this.nextState[k]

        if (k === 'custom' || k === 'categories') {
          requiresGridReset = true
        }
      }

      delete this.nextState
      const nextState = this.getInitialState()

      if (requiresGridReset) {
        return this.reset(nextState)
      }

      this.setState(nextState)
    })
  }

  componentWillUnmount() {
    this.unregister()
  }

  async reset(nextState = {}) {
    await init(this.props)

    this.initGrid()
    this.unobserve()

    this.setState(nextState, () => {
      this.observeCategories()
      this.observeRows()
    })
  }

  register() {
    document.addEventListener('click', this.handleClickOutside)
    this.observe()
  }

  unregister() {
    document.removeEventListener('click', this.handleClickOutside)
    this.darkMedia?.removeEventListener('change', this.darkMediaCallback)
    this.unobserve()
  }

  observe() {
    this.observeCategories()
    this.observeRows()
  }

  unobserve({ except = [] } = {}) {
    if (!Array.isArray(except)) {
      except = [except]
    }

    for (const observer of this.observers) {
      if (except.includes(observer)) continue
      observer.disconnect()
    }

    this.observers = [].concat(except)
  }

  initGrid() {
    const { categories } = Data

    this.refs.categories = new Map()

    const navKey = Data.categories.map((category) => category.id).join(',')
    if (this.navKey && this.navKey != navKey) {
      this.refs.scroll.current && (this.refs.scroll.current.scrollTop = 0)
    }
    this.navKey = navKey

    this.grid = []
    this.grid.setsize = 0

    const addRow = (rows, category) => {
      const row = []
      row.__categoryId = category.id
      row.__index = rows.length
      this.grid.push(row)

      const rowIndex = this.grid.length - 1
      const rowRef = rowIndex % Performance.rowsPerRender ? {} : createRef()
      rowRef.index = rowIndex
      rowRef.posinset = this.grid.setsize + 1
      rows.push(rowRef)

      return row
    }

    for (let category of categories) {
      const rows = []
      let row = addRow(rows, category)

      for (let emoji of category.emojis) {
        if (row.length == this.getPerLine()) {
          row = addRow(rows, category)
        }

        this.grid.setsize += 1
        row.push(emoji)
      }

      this.refs.categories.set(category.id, { root: createRef(), rows })
    }
  }

  darkMediaCallback = () => {
    if (this.props.theme != 'auto') return
    this.setState({ theme: this.darkMedia.matches ? 'dark' : 'light' })
  }

  initTheme(theme) {
    if (theme != 'auto') return theme

    if (!this.darkMedia) {
      this.darkMedia = matchMedia('(prefers-color-scheme: dark)')
      if (this.darkMedia.media.match(/^not/)) return 'light'

      this.darkMedia.addEventListener('change', this.darkMediaCallback)
    }

    return this.darkMedia.matches ? 'dark' : 'light'
  }

  handleClickOutside = (e) => {
    const { element } = this.props

    if (e.target != element) {
      if (this.state.showSkins) {
        this.closeSkins()
      }

      if (this.props.onClickOutside) {
        this.props.onClickOutside(e)
      }
    }
  }

  handleBaseClick = (e) => {
    if (!this.state.showSkins) return
    if (!e.target.closest('.menu')) {
      e.preventDefault()
      e.stopImmediatePropagation()

      this.closeSkins()
    }
  }

  handleBaseKeydown = (e) => {
    if (!this.state.showSkins) return
    if (e.key == 'Escape') {
      e.preventDefault()
      e.stopImmediatePropagation()

      this.closeSkins()
    }
  }

  initDynamicPerLine(props = this.props) {
    if (!props.dynamicWidth) return
    const { element, emojiButtonSize } = props

    const calculatePerLine = () => {
      const { width } = element.getBoundingClientRect()
      return Math.floor(width / emojiButtonSize)
    }

    const observer = new ResizeObserver(() => {
      this.unobserve({ except: observer })
      this.setState({ perLine: calculatePerLine() }, () => {
        this.initGrid()
        this.forceUpdate(() => {
          this.observeCategories()
          this.observeRows()
        })
      })
    })

    observer.observe(element)
    this.observers.push(observer)

    return calculatePerLine()
  }

  getPerLine() {
    return this.state.perLine || this.props.perLine
  }

  getEmojiByPos([p1, p2]) {
    const grid = this.state.searchResults || this.grid
    const emoji = grid[p1] && grid[p1][p2]

    if (!emoji) return
    return SearchIndex.get(emoji)
  }

  observeCategories() {
    const navigation = this.refs.navigation.current
    if (!navigation) return

    const visibleCategories = new Map()
    const setFocusedCategory = (categoryId) => {
      if (categoryId != navigation.state.categoryId) {
        navigation.setState({ categoryId })
      }
    }

    const observerOptions = {
      root: this.refs.scroll.current,
      threshold: [0.0, 1.0],
    }

    const observer = new IntersectionObserver((entries) => {
      for (const entry of entries) {
        const id = entry.target.dataset.id
        visibleCategories.set(id, entry.intersectionRatio)
      }

      const ratios = [...visibleCategories]
      for (const [id, ratio] of ratios) {
        if (ratio) {
          setFocusedCategory(id)
          break
        }
      }
    }, observerOptions)

    for (const { root } of this.refs.categories.values()) {
      observer.observe(root.current)
    }

    this.observers.push(observer)
  }

  observeRows() {
    const visibleRows = { ...this.state.visibleRows }

    const observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          const index = parseInt(entry.target.dataset.index)

          if (entry.isIntersecting) {
            visibleRows[index] = true
          } else {
            delete visibleRows[index]
          }
        }

        this.setState({ visibleRows })
      },
      {
        root: this.refs.scroll.current,
        rootMargin: `${
          this.props.emojiButtonSize * (Performance.rowsPerRender + 5)
        }px 0px ${this.props.emojiButtonSize * Performance.rowsPerRender}px`,
      },
    )

    for (const { rows } of this.refs.categories.values()) {
      for (const row of rows) {
        if (row.current) {
          observer.observe(row.current)
        }
      }
    }

    this.observers.push(observer)
  }

  preventDefault(e) {
    e.preventDefault()
  }

  handleSearchClick = () => {
    const emoji = this.getEmojiByPos(this.state.pos)
    if (!emoji) return

    this.setState({ pos: [-1, -1] })
  }

  handleSearchInput = async () => {
    const input = this.refs.searchInput.current
    if (!input) return

    const { value } = input
    const searchResults = await SearchIndex.search(value)
    const afterRender = () => {
      if (!this.refs.scroll.current) return
      this.refs.scroll.current.scrollTop = 0
    }

    if (!searchResults) {
      return this.setState({ searchResults, pos: [-1, -1] }, afterRender)
    }

    const pos = input.selectionStart == input.value.length ? [0, 0] : [-1, -1]
    const grid = []
    grid.setsize = searchResults.length
    let row = null

    for (let emoji of searchResults) {
      if (!grid.length || row.length == this.getPerLine()) {
        row = []
        row.__categoryId = 'search'
        row.__index = grid.length
        grid.push(row)
      }

      row.push(emoji)
    }

    this.ignoreMouse()
    this.setState({ searchResults: grid, pos }, afterRender)
  }

  handleSearchKeyDown = (e) => {
    // const specialKey = e.altKey || e.ctrlKey || e.metaKey
    const input = e.currentTarget
    e.stopImmediatePropagation()

    switch (e.key) {
      case 'ArrowLeft':
        // if (specialKey) return
        // e.preventDefault()
        this.navigate({ e, input, left: true })
        break

      case 'ArrowRight':
        // if (specialKey) return
        // e.preventDefault()
        this.navigate({ e, input, right: true })
        break

      case 'ArrowUp':
        // if (specialKey) return
        // e.preventDefault()
        this.navigate({ e, input, up: true })
        break

      case 'ArrowDown':
        // if (specialKey) return
        // e.preventDefault()
        this.navigate({ e, input, down: true })
        break

      case 'Enter':
        e.preventDefault()
        this.handleEmojiClick({ e, pos: this.state.pos })
        break

      case 'Escape':
        e.preventDefault()
        if (this.state.searchResults) {
          this.clearSearch()
        } else {
          this.unfocusSearch()
        }
        break

      default:
        break
    }
  }

  clearSearch = () => {
    const input = this.refs.searchInput.current
    if (!input) return

    input.value = ''
    input.focus()

    this.handleSearchInput()
  }

  unfocusSearch() {
    const input = this.refs.searchInput.current
    if (!input) return

    input.blur()
  }

  navigate({ e, input, left, right, up, down }) {
    const grid = this.state.searchResults || this.grid
    if (!grid.length) return

    let [p1, p2] = this.state.pos

    const pos = (() => {
      if (p1 == 0) {
        if (p2 == 0 && !e.repeat && (left || up)) {
          return null
        }
      }

      if (p1 == -1) {
        if (
          !e.repeat &&
          (right || down) &&
          input.selectionStart == input.value.length
        ) {
          return [0, 0]
        }

        return null
      }

      if (left || right) {
        let row = grid[p1]
        const increment = left ? -1 : 1

        p2 += increment
        if (!row[p2]) {
          p1 += increment
          row = grid[p1]

          if (!row) {
            p1 = left ? 0 : grid.length - 1
            p2 = left ? 0 : grid[p1].length - 1

            return [p1, p2]
          }

          p2 = left ? row.length - 1 : 0
        }

        return [p1, p2]
      }

      if (up || down) {
        p1 += up ? -1 : 1
        const row = grid[p1]

        if (!row) {
          p1 = up ? 0 : grid.length - 1
          p2 = up ? 0 : grid[p1].length - 1

          return [p1, p2]
        }

        if (!row[p2]) {
          p2 = row.length - 1
        }

        return [p1, p2]
      }
    })()

    if (pos) {
      e.preventDefault()
    } else {
      if (this.state.pos[0] > -1) {
        this.setState({ pos: [-1, -1] })
      }

      return
    }

    this.setState({ pos, keyboard: true }, () => {
      this.scrollTo({ row: pos[0] })
    })
  }

  scrollTo({ categoryId, row }) {
    const grid = this.state.searchResults || this.grid
    if (!grid.length) return

    const scroll = this.refs.scroll.current
    const scrollRect = scroll.getBoundingClientRect()

    let scrollTop = 0

    if (row >= 0) {
      categoryId = grid[row].__categoryId
    }

    if (categoryId) {
      const ref =
        this.refs[categoryId] || this.refs.categories.get(categoryId).root
      const categoryRect = ref.current.getBoundingClientRect()

      scrollTop = categoryRect.top - (scrollRect.top - scroll.scrollTop) + 1
    }

    if (row >= 0) {
      if (!row) {
        scrollTop = 0
      } else {
        const rowIndex = grid[row].__index
        const rowTop = scrollTop + rowIndex * this.props.emojiButtonSize
        const rowBot =
          rowTop +
          this.props.emojiButtonSize +
          this.props.emojiButtonSize * 0.88

        if (rowTop < scroll.scrollTop) {
          scrollTop = rowTop
        } else if (rowBot > scroll.scrollTop + scrollRect.height) {
          scrollTop = rowBot - scrollRect.height
        } else {
          return
        }
      }
    }

    this.ignoreMouse()
    scroll.scrollTop = scrollTop
  }

  ignoreMouse() {
    this.mouseIsIgnored = true
    clearTimeout(this.ignoreMouseTimer)
    this.ignoreMouseTimer = setTimeout(() => {
      delete this.mouseIsIgnored
    }, 100)
  }

  handleCategoryClick = ({ category, i }) => {
    this.scrollTo(i == 0 ? { row: -1 } : { categoryId: category.id })
  }

  handleEmojiOver(pos) {
    if (this.mouseIsIgnored || this.state.showSkins) return
    this.setState({ pos: pos || [-1, -1], keyboard: false })
  }

  handleEmojiClick({ e, emoji, pos }) {
    if (!this.props.onEmojiSelect) return

    if (!emoji && pos) {
      emoji = this.getEmojiByPos(pos)
    }

    if (emoji) {
      const emojiData = getEmojiData(emoji, { skinIndex: this.state.skin - 1 })

      if (this.props.maxFrequentRows) {
        FrequentlyUsed.add(emojiData, this.props)
      }

      this.props.onEmojiSelect(emojiData, e)
    }
  }

  openSkins = (e) => {
    const { currentTarget } = e
    const rect = currentTarget.getBoundingClientRect()

    this.setState({ showSkins: rect }, async () => {
      // Firefox requires 2 frames for the transition to consistenly work
      await sleep(2)

      const menu = this.refs.menu.current
      if (!menu) return

      menu.classList.remove('hidden')
      this.refs.skinToneRadio.current.focus()

      this.base.addEventListener('click', this.handleBaseClick, true)
      this.base.addEventListener('keydown', this.handleBaseKeydown, true)
    })
  }

  closeSkins() {
    if (!this.state.showSkins) return
    this.setState({ showSkins: null, tempSkin: null })

    this.base.removeEventListener('click', this.handleBaseClick)
    this.base.removeEventListener('keydown', this.handleBaseKeydown)
  }

  handleSkinMouseOver(tempSkin) {
    this.setState({ tempSkin })
  }

  handleSkinClick(skin) {
    this.ignoreMouse()
    this.closeSkins()

    this.setState({ skin, tempSkin: null })
    Store.set('skin', skin)
  }

  renderNav() {
    return (
      <Navigation
        key={this.navKey}
        ref={this.refs.navigation}
        icons={this.props.icons}
        theme={this.state.theme}
        dir={this.dir}
        unfocused={!!this.state.searchResults}
        position={this.props.navPosition}
        onClick={this.handleCategoryClick}
      />
    )
  }

  renderPreview() {
    const emoji = this.getEmojiByPos(this.state.pos)
    const noSearchResults =
      this.state.searchResults && !this.state.searchResults.length

    return (
      <div
        id="preview"
        class="flex flex-middle"
        dir={this.dir}
        data-position={this.props.previewPosition}
      >
        <div class="flex flex-middle flex-grow">
          <div
            class="flex flex-auto flex-middle flex-center"
            style={{
              height: this.props.emojiButtonSize,
              fontSize: this.props.emojiButtonSize,
            }}
          >
            <Emoji
              emoji={emoji}
              id={
                noSearchResults
                  ? this.props.noResultsEmoji || 'cry'
                  : this.props.previewEmoji ||
                    (this.props.previewPosition == 'top'
                      ? 'point_down'
                      : 'point_up')
              }
              set={this.props.set}
              size={this.props.emojiButtonSize}
              skin={this.state.tempSkin || this.state.skin}
              spritesheet={true}
              getSpritesheetURL={this.props.getSpritesheetURL}
            />
          </div>

          <div class={`margin-${this.dir[0]}`}>
            {emoji || noSearchResults ? (
              <div class={`padding-${this.dir[2]} align-${this.dir[0]}`}>
                <div class="preview-title ellipsis">
                  {emoji ? emoji.name : I18n.search_no_results_1}
                </div>
                <div class="preview-subtitle ellipsis color-c">
                  {emoji ? emoji.skins[0].shortcodes : I18n.search_no_results_2}
                </div>
              </div>
            ) : (
              <div class="preview-placeholder color-c">{I18n.pick}</div>
            )}
          </div>
        </div>

        {!emoji &&
          this.props.skinTonePosition == 'preview' &&
          this.renderSkinToneButton()}
      </div>
    )
  }

  renderEmojiButton(emoji, { pos, posinset, grid }) {
    const size = this.props.emojiButtonSize
    const skin = this.state.tempSkin || this.state.skin
    const emojiSkin = emoji.skins[skin - 1] || emoji.skins[0]
    const native = emojiSkin.native
    const selected = deepEqual(this.state.pos, pos)
    const key = pos.concat(emoji.id).join('')

    return (
      <PureInlineComponent key={key} {...{ selected, skin, size }}>
        <button
          aria-label={native}
          aria-selected={selected || undefined}
          aria-posinset={posinset}
          aria-setsize={grid.setsize}
          data-keyboard={this.state.keyboard}
          title={this.props.previewPosition == 'none' ? emoji.name : undefined}
          type="button"
          class="flex flex-center flex-middle"
          tabindex="-1"
          onClick={(e) => this.handleEmojiClick({ e, emoji })}
          onMouseEnter={() => this.handleEmojiOver(pos)}
          onMouseLeave={() => this.handleEmojiOver()}
          style={{
            width: this.props.emojiButtonSize,
            height: this.props.emojiButtonSize,
            fontSize: this.props.emojiSize,
            lineHeight: 0,
          }}
        >
          <div
            aria-hidden="true"
            class="background"
            style={{
              borderRadius: this.props.emojiButtonRadius,
              backgroundColor: this.props.emojiButtonColors
                ? this.props.emojiButtonColors[
                    (posinset - 1) % this.props.emojiButtonColors.length
                  ]
                : undefined,
            }}
          ></div>
          <Emoji
            emoji={emoji}
            set={this.props.set}
            size={this.props.emojiSize}
            skin={skin}
            spritesheet={true}
            getSpritesheetURL={this.props.getSpritesheetURL}
          />
        </button>
      </PureInlineComponent>
    )
  }

  renderSearch() {
    const renderSkinTone =
      this.props.previewPosition == 'none' ||
      this.props.skinTonePosition == 'search'

    return (
      <div>
        <div class="spacer"></div>
        <div class="flex flex-middle">
          <div class="search relative flex-grow">
            <input
              type="search"
              ref={this.refs.searchInput}
              placeholder={I18n.search}
              onClick={this.handleSearchClick}
              onInput={this.handleSearchInput}
              onKeyDown={this.handleSearchKeyDown}
              autoComplete="off"
            ></input>
            <span class="icon loupe flex">{Icons.search.loupe}</span>
            {this.state.searchResults && (
              <button
                title="Clear"
                aria-label="Clear"
                type="button"
                class="icon delete flex"
                onClick={this.clearSearch}
                onMouseDown={this.preventDefault}
              >
                {Icons.search.delete}
              </button>
            )}
          </div>

          {renderSkinTone && this.renderSkinToneButton()}
        </div>
      </div>
    )
  }

  renderSearchResults() {
    const { searchResults } = this.state
    if (!searchResults) return null

    return (
      <div class="category" ref={this.refs.search}>
        <div class={`sticky padding-small align-${this.dir[0]}`}>
          {I18n.categories.search}
        </div>
        <div>
          {!searchResults.length ? (
            <div class={`padding-small align-${this.dir[0]}`}>
              {this.props.onAddCustomEmoji && (
                <a onClick={this.props.onAddCustomEmoji}>{I18n.add_custom}</a>
              )}
            </div>
          ) : (
            searchResults.map((row, i) => {
              return (
                <div class="flex">
                  {row.map((emoji, ii) => {
                    return this.renderEmojiButton(emoji, {
                      pos: [i, ii],
                      posinset: i * this.props.perLine + ii + 1,
                      grid: searchResults,
                    })
                  })}
                </div>
              )
            })
          )}
        </div>
      </div>
    )
  }

  renderCategories() {
    const { categories } = Data
    const hidden = !!this.state.searchResults
    const perLine = this.getPerLine()

    return (
      <div
        style={{
          visibility: hidden ? 'hidden' : undefined,
          display: hidden ? 'none' : undefined,
          height: '100%',
        }}
      >
        {categories.map((category) => {
          const { root, rows } = this.refs.categories.get(category.id)

          return (
            <div
              data-id={category.target ? category.target.id : category.id}
              class="category"
              ref={root}
            >
              <div class={`sticky padding-small align-${this.dir[0]}`}>
                {category.name || I18n.categories[category.id]}
              </div>
              <div
                class="relative"
                style={{
                  height: rows.length * this.props.emojiButtonSize,
                }}
              >
                {rows.map((row, i) => {
                  const targetRow =
                    row.index - (row.index % Performance.rowsPerRender)
                  const visible = this.state.visibleRows[targetRow]
                  const ref = 'current' in row ? row : undefined

                  if (!visible && !ref) {
                    return null
                  }

                  const start = i * perLine
                  const end = start + perLine
                  const emojiIds = category.emojis.slice(start, end)

                  if (emojiIds.length < perLine) {
                    emojiIds.push(...new Array(perLine - emojiIds.length))
                  }

                  return (
                    <div
                      key={row.index}
                      data-index={row.index}
                      ref={ref}
                      class="flex row"
                      style={{ top: i * this.props.emojiButtonSize }}
                    >
                      {visible &&
                        emojiIds.map((emojiId, ii) => {
                          if (!emojiId) {
                            return (
                              <div
                                style={{
                                  width: this.props.emojiButtonSize,
                                  height: this.props.emojiButtonSize,
                                }}
                              ></div>
                            )
                          }

                          const emoji = SearchIndex.get(emojiId)

                          return this.renderEmojiButton(emoji, {
                            pos: [row.index, ii],
                            posinset: row.posinset + ii,
                            grid: this.grid,
                          })
                        })}
                    </div>
                  )
                })}
              </div>
            </div>
          )
        })}
      </div>
    )
  }

  renderSkinToneButton() {
    if (this.props.skinTonePosition == 'none') {
      return null
    }

    return (
      <div
        class="flex flex-auto flex-center flex-middle"
        style={{
          position: 'relative',
          width: this.props.emojiButtonSize,
          height: this.props.emojiButtonSize,
        }}
      >
        <button
          type="button"
          ref={this.refs.skinToneButton}
          class="skin-tone-button flex flex-auto flex-center flex-middle"
          aria-selected={this.state.showSkins ? '' : undefined}
          aria-label={I18n.skins.choose}
          title={I18n.skins.choose}
          onClick={this.openSkins}
          style={{
            width: this.props.emojiSize,
            height: this.props.emojiSize,
          }}
        >
          <span class={`skin-tone skin-tone-${this.state.skin}`}></span>
        </button>
      </div>
    )
  }

  renderLiveRegion() {
    const emoji = this.getEmojiByPos(this.state.pos)
    const contents = emoji ? emoji.name : ''

    return (
      <div aria-live="polite" class="sr-only">
        {contents}
      </div>
    )
  }

  renderSkins() {
    const skinToneButton = this.refs.skinToneButton.current
    const skinToneButtonRect = skinToneButton.getBoundingClientRect()
    const baseRect = this.base.getBoundingClientRect()

    const position = {}

    if (this.dir == 'ltr') {
      position.right = baseRect.right - skinToneButtonRect.right - 3
    } else {
      position.left = skinToneButtonRect.left - baseRect.left - 3
    }

    if (
      this.props.previewPosition == 'bottom' &&
      this.props.skinTonePosition == 'preview'
    ) {
      position.bottom = baseRect.bottom - skinToneButtonRect.top + 6
    } else {
      position.top = skinToneButtonRect.bottom - baseRect.top + 3
      position.bottom = 'auto'
    }

    return (
      <div
        ref={this.refs.menu}
        role="radiogroup"
        dir={this.dir}
        aria-label={I18n.skins.choose}
        class="menu hidden"
        data-position={position.top ? 'top' : 'bottom'}
        style={position}
      >
        {[...Array(6).keys()].map((i) => {
          const skin = i + 1
          const checked = this.state.skin == skin

          return (
            <div>
              <input
                type="radio"
                name="skin-tone"
                value={skin}
                aria-label={I18n.skins[skin]}
                ref={checked ? this.refs.skinToneRadio : null}
                defaultChecked={checked}
                onChange={() => this.handleSkinMouseOver(skin)}
                onKeyDown={(e) => {
                  if (
                    e.code == 'Enter' ||
                    e.code == 'Space' ||
                    e.code == 'Tab'
                  ) {
                    e.preventDefault()
                    this.handleSkinClick(skin)
                  }
                }}
              ></input>

              <button
                aria-hidden="true"
                tabindex="-1"
                onClick={() => this.handleSkinClick(skin)}
                onMouseEnter={() => this.handleSkinMouseOver(skin)}
                onMouseLeave={() => this.handleSkinMouseOver()}
                class="option flex flex-grow flex-middle"
              >
                <span class={`skin-tone skin-tone-${skin}`}></span>
                <span class="margin-small-lr">{I18n.skins[skin]}</span>
              </button>
            </div>
          )
        })}
      </div>
    )
  }

  render() {
    const lineWidth = this.props.perLine * this.props.emojiButtonSize

    return (
      <section
        id="root"
        class="flex flex-column"
        dir={this.dir}
        style={{
          width: this.props.dynamicWidth
            ? '100%'
            : `calc(${lineWidth}px + (var(--padding) + var(--sidebar-width)))`,
        }}
        data-emoji-set={this.props.set}
        data-theme={this.state.theme}
        data-menu={this.state.showSkins ? '' : undefined}
      >
        {this.props.previewPosition == 'top' && this.renderPreview()}
        {this.props.navPosition == 'top' && this.renderNav()}
        {this.props.searchPosition == 'sticky' && (
          <div class="padding-lr">{this.renderSearch()}</div>
        )}

        <div ref={this.refs.scroll} class="scroll flex-grow padding-lr">
          <div
            style={{
              width: this.props.dynamicWidth ? '100%' : lineWidth,
              height: '100%',
            }}
          >
            {this.props.searchPosition == 'static' && this.renderSearch()}
            {this.renderSearchResults()}
            {this.renderCategories()}
          </div>
        </div>

        {this.props.navPosition == 'bottom' && this.renderNav()}
        {this.props.previewPosition == 'bottom' && this.renderPreview()}
        {this.state.showSkins && this.renderSkins()}
        {this.renderLiveRegion()}
      </section>
    )
  }
}


================================================
FILE: packages/emoji-mart/src/components/Picker/PickerElement.tsx
================================================
// @ts-nocheck
import { render } from 'preact'

import { init, getProps } from '../../config'
import { ShadowElement } from '../HTMLElement'
import { Picker, PickerStyles } from '.'
import PickerProps from './PickerProps'

export default class PickerElement extends ShadowElement {
  static Props = PickerProps

  constructor(props) {
    super(props, { styles: PickerStyles })
  }

  async connectedCallback() {
    const props = getProps(this.props, PickerProps, this)
    props.element = this
    props.ref = (component) => {
      this.component = component
    }

    await init(props)
    if (this.disconnected) return

    render(<Picker {...props} />, this.shadowRoot)
  }
}

if (
  typeof customElements !== 'undefined' &&
  !customElements.get('em-emoji-picker')
) {
  customElements.define('em-emoji-picker', PickerElement)
}


================================================
FILE: packages/emoji-mart/src/components/Picker/PickerProps.ts
================================================
export default {
  autoFocus: {
    value: false,
  },
  dynamicWidth: {
    value: false,
  },
  emojiButtonColors: {
    value: null,
  },
  emojiButtonRadius: {
    value: '100%',
  },
  emojiButtonSize: {
    value: 36,
  },
  emojiSize: {
    value: 24,
  },
  emojiVersion: {
    value: 15,
    choices: [1, 2, 3, 4, 5, 11, 12, 12.1, 13, 13.1, 14, 15],
  },
  exceptEmojis: {
    value: [],
  },
  icons: {
    value: 'auto',
    choices: ['auto', 'outline', 'solid'],
  },
  locale: {
    value: 'en',
    choices: [
      'en',
      'ar',
      'be',
      'cs',
      'de',
      'es',
      'fa',
      'fi',
      'fr',
      'hi',
      'it',
      'ja',
      'ko',
      'nl',
      'pl',
      'pt',
      'ru',
      'sa',
      'tr',
      'uk',
      'vi',
      'zh',
    ],
  },
  maxFrequentRows: {
    value: 4,
  },
  navPosition: {
    value: 'top',
    choices: ['top', 'bottom', 'none'],
  },
  noCountryFlags: {
    value: false,
  },
  noResultsEmoji: {
    value: null,
  },
  perLine: {
    value: 9,
  },
  previewEmoji: {
    value: null,
  },
  previewPosition: {
    value: 'bottom',
    choices: ['top', 'bottom', 'none'],
  },
  searchPosition: {
    value: 'sticky',
    choices: ['sticky', 'static', 'none'],
  },
  set: {
    value: 'native',
    choices: ['native', 'apple', 'facebook', 'google', 'twitter'],
  },
  skin: {
    value: 1,
    choices: [1, 2, 3, 4, 5, 6],
  },
  skinTonePosition: {
    value: 'preview',
    choices: ['preview', 'search', 'none'],
  },
  theme: {
    value: 'auto',
    choices: ['auto', 'light', 'dark'],
  },

  // Data
  categories: null,
  categoryIcons: null,
  custom: null,
  data: null,
  i18n: null,

  // Callbacks
  getImageURL: null,
  getSpritesheetURL: null,
  onAddCustomEmoji: null,
  onClickOutside: null,
  onEmojiSelect: null,

  // Deprecated
  stickySearch: {
    deprecated: true,
    value: true,
  },
}


================================================
FILE: packages/emoji-mart/src/components/Picker/PickerStyles.scss
================================================
:host {
  display: flex;
  width: min-content;
  height: 435px;
  min-height: 230px;
  border-radius: var(--border-radius);
  box-shadow: var(--shadow);

  --border-radius: 10px;
  --category-icon-size: 18px;
  --font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  --font-size: 15px;

  --preview-placeholder-size: 21px;
  --preview-title-size: 1.1em;
  --preview-subtitle-size: .9em;

  --shadow-color: 0deg 0% 0%;
  --shadow:
    0.3px 0.5px 2.7px hsl(var(--shadow-color) / 0.14),
    0.4px 0.8px 1px -3.2px hsl(var(--shadow-color) / 0.14),
    1px 2px 2.5px -4.5px hsl(var(--shadow-color) / 0.14);
}

[data-theme="light"] {
  --em-rgb-color: var(--rgb-color, 34, 36, 39);
  --em-rgb-accent: var(--rgb-accent, 34, 102, 237);
  --em-rgb-background: var(--rgb-background, 255, 255, 255);
  --em-rgb-input: var(--rgb-input, 255, 255, 255);
  --em-color-border: var(--color-border, rgba(0, 0, 0, .05));
  --em-color-border-over: var(--color-border-over, rgba(0, 0, 0, .1));
}

[data-theme="dark"] {
  --em-rgb-color: var(--rgb-color, 222, 222, 221);
  --em-rgb-accent: var(--rgb-accent, 58, 130, 247);
  --em-rgb-background: var(--rgb-background, 21, 22, 23);
  --em-rgb-input: var(--rgb-input, 0, 0, 0);
  --em-color-border: var(--color-border, rgba(255, 255, 255, .1));
  --em-color-border-over: var(--color-border-over, rgba(255, 255, 255, .2));
}

#root {
  --color-a: rgb(var(--em-rgb-color));
  --color-b: rgba(var(--em-rgb-color), .65);
  --color-c: rgba(var(--em-rgb-color), .45);

  --padding: 12px;
  --padding-small: calc(var(--padding) / 2);

  --sidebar-width: 16px;

  --duration: 225ms;
  --duration-fast: 125ms;
  --duration-instant: 50ms;
  --easing: cubic-bezier(.4, .0, .2, 1);

  @media (prefers-reduced-motion) {
    --duration: 0;
    --duration-fast: 0;
    --duration-instant: 0;
  }

  position: relative;
  width: 100%;
  text-align: left;
  border-radius: var(--border-radius);
  background-color: rgb(var(--em-rgb-background));

  &[data-menu] {
    button { cursor: auto }
    .menu button { cursor: pointer }
  }
}

:host, #root, input, button {
  color: rgb(var(--em-rgb-color));
  font-family: var(--font-family);
  font-size: var(--font-size);
  line-height: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

*, *:before, *:after {
  margin: 0; padding: 0;
  box-sizing: border-box;
  min-width: 0;
}

.relative { position: relative }

.flex { display: flex }
.flex-auto { flex: 0 0 auto }
.flex-center { justify-content: center; }
.flex-column { flex-direction: column }
.flex-grow { flex: 1 1 auto }
.flex-middle { align-items: center }
.flex-wrap { flex-wrap: wrap }

.padding { padding: var(--padding) }
.padding-t { padding-top: var(--padding) }
.padding-lr { padding-left: var(--padding); padding-right: var(--padding) }
.padding-r { padding-right: var(--padding) }
.padding-small { padding: var(--padding-small) }
.padding-small-b { padding-bottom: var(--padding-small)}
.padding-small-lr { padding-left: var(--padding-small); padding-right: var(--padding-small)}
.margin { margin: var(--padding) }
.margin-r { margin-right: var(--padding) }
.margin-l { margin-left: var(--padding) }
.margin-small-l { margin-left: var(--padding-small) }
.margin-small-lr { margin-left: var(--padding-small); margin-right: var(--padding-small); }

.align-l { text-align: left }
.align-r { text-align: right }

.color-a { color: var(--color-a) }
.color-b { color: var(--color-b) }
.color-c { color: var(--color-c) }

.ellipsis {
  white-space: nowrap;
  max-width: 100%;
  width: auto;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sr-only {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

a {
  cursor: pointer;
  color: rgb(var(--em-rgb-accent));

  &:hover { text-decoration: underline }
}

.spacer { height: 10px }

[dir="rtl"] .scroll {
  padding-left: 0;
  padding-right: var(--padding);
}

.scroll {
  overflow: auto;
  overflow-x: hidden;
  padding-right: 0;

  &::-webkit-scrollbar {
    width: var(--sidebar-width);
    height: var(--sidebar-width);
  }

  &::-webkit-scrollbar-track {
    border: 0;
  }

  &::-webkit-scrollbar-button {
    width: 0; height: 0;
    display: none;
  }

  &::-webkit-scrollbar-corner {
    background-color: transparent;
  }

  &::-webkit-scrollbar-thumb {
    min-height: 20%;
    min-height: 65px;
    border: 4px solid rgb(var(--em-rgb-background));
    border-radius: 8px;

    &:hover {
      background-color: var(--em-color-border-over) !important;
    }
  }

  &:hover {
    &::-webkit-scrollbar-thumb {
      background-color: var(--em-color-border);
    }
  }
}

.sticky {
  position: sticky;
  z-index: 1;
  top: -1px;
  font-weight: 500;
  background-color: rgba(var(--em-rgb-background), .9);
  backdrop-filter: blur(4px);
}

[dir="rtl"] .search {
  input[type="search"] {
    padding: 10px 2.2em 10px 2em;
  }

  .loupe {
    right: .7em;
    left: auto;
  }

  .delete {
    left: .7em;
    right: auto;
  }
}

.search {
  z-index: 2;
  position: relative;

  input, button {
    font-size: calc(var(--font-size) - 1px);
  }

  input[type="search"] {
    display: block;
    border: 0;
    outline: 0;
    width: 100%;
    padding: 10px 2em 10px 2.2em;
    border-radius: 10px;
    background-color: var(--em-color-border);
    transition-duration: var(--duration);
    transition-property: background-color, box-shadow;
    transition-timing-function: var(--easing);

    &::placeholder {
      color: inherit;
      opacity: .6;
    }

    &,
    &::-webkit-search-decoration,
    &::-webkit-search-cancel-button,
    &::-webkit-search-results-button,
    &::-webkit-search-results-decoration {
      appearance: none;
    }

    &:focus {
      background-color: rgb(var(--em-rgb-input));
      box-shadow: inset 0 0 0 1px rgb(var(--em-rgb-accent)),
                  0 1px 3px rgba(65,69,73,.2);
    }
  }

  .icon {
    z-index: 1;
    position: absolute;
    top: 50%;
    color: rgba(var(--em-rgb-color), .7);
    transform: translateY(-50%);
  }

  .loupe { left: .7em; pointer-events: none; }
  .delete { right: .7em }
}

svg {
  fill: currentColor;
  width: 1em; height: 1em;
}

button {
  appearance: none;
  cursor: pointer;
  color: currentColor;
  border: 0;
  background-color: transparent;
}

#nav {
  z-index: 2;
  position: relative;
  padding-top: 12px; padding-bottom: 12px;
  padding-right: var(--sidebar-width);

  button {
    color: var(--color-b);
    transition: color var(--duration) var(--easing);

    &:hover { color: var(--color-a) }
  }

  svg, img {
    width: var(--category-icon-size);
    height: var(--category-icon-size);
  }

  &[dir="rtl"] .bar {
    right: 0;
    left: auto;
  }

  .bar {
    position: absolute;
    bottom: -12px; left: 0;
    width: 100%; height: 3px;
    background-color: rgb(var(--em-rgb-accent));
    border-radius: 3px 3px 0 0;
    transition: transform var(--duration) var(--easing);
  }

  button[aria-selected] {
    color: rgb(var(--em-rgb-accent));
  }
}

#preview {
  z-index: 2;
  position: relative;
  padding: calc(var(--padding) + 4px) var(--padding);
  padding-right: var(--sidebar-width);

  .preview-placeholder { font-size: var(--preview-placeholder-size) }
  .preview-title { font-size: var(--preview-title-size) }
  .preview-subtitle { font-size: var(--preview-subtitle-size) }
}

#nav, #preview {
  &:before {
    content: "";
    position: absolute;
    left: 0; right: 0;
    height: 2px;
  }

  &[data-position="top"] {
    &:before {
      top: 100%;
      background: linear-gradient(to bottom, var(--em-color-border), transparent);
    }
  }

  &[data-position="bottom"] {
    &:before {
      bottom: 100%;
      background: linear-gradient(to top, var(--em-color-border), transparent);
    }
  }
}

.category {
  &:last-child {
    min-height: calc(100% + 1px);
  }

  button {
    position: relative;
    font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;

    & > * { position: relative }

    .background {
      position: absolute;
      inset: 0;
      opacity: 0;
      background-color: var(--em-color-border);
      transition: opacity var(--duration-fast) var(--easing) var(--duration-instant);
    }

    &:hover .background {
      transition-duration: var(--duration-instant);
      transition-delay: 0ms;
    }

    &[aria-selected] .background { opacity: 1 }
    &[data-keyboard] .background { transition: none }
  }
}

.row {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
}

.skin-tone-button {
  border-radius: 100%;
  border: 1px solid transparent;

  &:hover { border-color: var(--em-color-border) }

  &:active { .skin-tone { transform: scale(.85) !important } }
             .skin-tone { transition: transform var(--duration) var(--easing) }

  &[aria-selected] {
    border-left-width: 0;
    border-right-width: 0;
    border-top-color: rgba(0,0,0, .05);
    border-bottom-color: transparent;
    background-color: var(--em-color-border);

    .skin-tone { transform: scale(.9) }
  }
}

.menu {
  z-index: 2;
  position: absolute;
  white-space: nowrap;
  padding: 4px;
  border: 1px solid var(--em-color-border);
  background-color: rgba(var(--em-rgb-background), .9);
  backdrop-filter: blur(4px);
  border-radius: 10px;
  box-shadow: 1px 1px 5px rgba(0,0,0, .05);
  transition-property: opacity, transform;
  transition-duration: var(--duration);
  transition-timing-function: var(--easing);

  &.hidden { opacity: 0 }

  &[data-position="bottom"] {
    transform-origin: bottom right;
    &.hidden { transform: scale(.9) rotate(-3deg) translateY(5%) }
  }

  &[data-position="top"] {
    transform-origin: top right;
    &.hidden { transform: scale(.9) rotate(3deg) translateY(-5%) }
  }


  input[type="radio"] {
    position: absolute;
    overflow: hidden;
    clip: rect(0 0 0 0);
    width: 1px; height: 1px;
    padding: 0; margin: 0;
    border: 0;

    &:checked + .option {
      box-shadow: 0 0 0 2px rgb(var(--em-rgb-accent));
    }
  }
}

.option {
  width: 100%;
  padding: 4px 6px;
  border-radius: 6px;

  &:hover {
    color: #fff;
    background-color: rgb(var(--em-rgb-accent));
  }
}

.skin-tone {
  position: relative;
  display: inline-block;
  width: 16px; height: 16px;
  border-radius: 100%;
  overflow: hidden;

  &:after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 100%;
    border: 1px solid rgba(0,0,0, .8);
    mix-blend-mode: overlay;
    box-shadow: inset 0 -2px 3px #000,
                inset 0 1px 2px #fff;
    background: linear-gradient(to bottom, rgba(255,255,255, .2), transparent);
  }
}

.skin-tone-1 { background-color: #ffc93a }
.skin-tone-2 { background-color: #ffdab7 }
.skin-tone-3 { background-color: #e7b98f }
.skin-tone-4 { background-color: #c88c61 }
.skin-tone-5 { background-color: #a46134 }
.skin-tone-6 { background-color: #5d4437 }

[data-index] {
  justify-content: space-between;
}

[data-emoji-set="twitter"] {
  .skin-tone:after {
    border-color: rgba(0,0,0, .5);
    box-shadow: none;
  }

  .skin-tone-1 { background-color: #FADE72 }
  .skin-tone-2 { background-color: #F3DFD0 }
  .skin-tone-3 { background-color: #EED3A8 }
  .skin-tone-4 { background-color: #CFAD8D }
  .skin-tone-5 { background-color: #A8805D }
  .skin-tone-6 { background-color: #765542 }
}

[data-emoji-set="google"] {
  .skin-tone:after {
    box-shadow: inset 0 0 2px 2px rgba(0,0,0, .4);
  }

  .skin-tone-1 { background-color: #F5C748 }
  .skin-tone-2 { background-color: #F1D5AA }
  .skin-tone-3 { background-color: #D4B48D }
  .skin-tone-4 { background-color: #AA876B }
  .skin-tone-5 { background-color: #916544 }
  .skin-tone-6 { background-color: #61493F }
}

[data-emoji-set="facebook"] {
  .skin-tone:after {
    border-color: rgba(0,0,0, .4);
    box-shadow: inset 0 -2px 3px #000,
                inset 0 1px 4px #fff;
  }

  .skin-tone-1 { background-color: #F5C748 }
  .skin-tone-2 { background-color: #F1D5AA }
  .skin-tone-3 { background-color: #D4B48D }
  .skin-tone-4 { background-color: #AA876B }
  .skin-tone-5 { background-color: #916544 }
  .skin-tone-6 { background-color: #61493F }
}


================================================
FILE: packages/emoji-mart/src/components/Picker/index.ts
================================================
// @ts-nocheck
export { default as Picker } from './Picker'
export { default as PickerElement } from './PickerElement'
export { default as PickerStyles } from 'bundle-text:./PickerStyles.scss'


================================================
FILE: packages/emoji-mart/src/config.ts
================================================
// @ts-nocheck
import i18n_en from '@emoji-mart/data/i18n/en.json'
import PickerProps from './components/Picker/PickerProps'
import {
  FrequentlyUsed,
  NativeSupport,
  SafeFlags,
  SearchIndex,
} from './helpers'

export let I18n = null
export let Data = null

const fetchCache = {}
async function fetchJSON(src) {
  if (fetchCache[src]) {
    return fetchCache[src]
  }

  const response = await fetch(src)
  const json = await response.json()

  fetchCache[src] = json
  return json
}

let promise: Promise<void> | null = null
let initiated = false
let initCallback = null
let initialized = false

export function init(options, { caller } = {}) {
  promise ||
    (promise = new Promise((resolve) => {
      initCallback = resolve
    }))

  if (options) {
    _init(options)
  } else if (caller && !initialized) {
    console.warn(
      `\`${caller}\` requires data to be initialized first. Promise will be pending until \`init\` is called.`,
    )
  }

  return promise
}

async function _init(props) {
  initialized = true

  let { emojiVersion, set, locale } = props
  emojiVersion || (emojiVersion = PickerProps.emojiVersion.value)
  set || (set = PickerProps.set.value)
  locale || (locale = PickerProps.locale.value)

  if (!Data) {
    Data =
      (typeof props.data === 'function' ? await props.data() : props.data) ||
      (await fetchJSON(
        `https://cdn.jsdelivr.net/npm/@emoji-mart/data@latest/sets/${emojiVersion}/${set}.json`,
      ))

    Data.emoticons = {}
    Data.natives = {}

    Data.categories.unshift({
      id: 'frequent',
      emojis: [],
    })

    for (const alias in Data.aliases) {
      const emojiId = Data.aliases[alias]
      const emoji = Data.emojis[emojiId]
      if (!emoji) continue

      emoji.aliases || (emoji.aliases = [])
      emoji.aliases.push(alias)
    }

    Data.originalCategories = Data.categories
  } else {
    Data.categories = Data.categories.filter((c) => {
      const isCustom = !!c.name
      if (!isCustom) return true

      return false
    })
  }

  I18n =
    (typeof props.i18n === 'function' ? await props.i18n() : props.i18n) ||
    (locale == 'en'
      ? i18n_en
      : await fetchJSON(
          `https://cdn.jsdelivr.net/npm/@emoji-mart/data@latest/i18n/${locale}.json`,
        ))

  if (props.custom) {
    for (let i in props.custom) {
      i = parseInt(i)
      const category = props.custom[i]
      const prevCategory = props.custom[i - 1]

      if (!category.emojis || !category.emojis.length) continue

      category.id || (category.id = `custom_${i + 1}`)
      category.name || (category.name = I18n.categories.custom)

      if (prevCategory && !category.icon) {
        category.target = prevCategory.target || prevCategory
      }

      Data.categories.push(category)

      for (const emoji of category.emojis) {
        Data.emojis[emoji.id] = emoji
      }
    }
  }

  if (props.categories) {
    Data.categories = Data.originalCategories
      .filter((c) => {
        return props.categories.indexOf(c.id) != -1
      })
      .sort((c1, c2) => {
        const i1 = props.categories.indexOf(c1.id)
        const i2 = props.categories.indexOf(c2.id)

        return i1 - i2
      })
  }

  let latestVersionSupport = null
  let noCountryFlags = null
  if (set == 'native') {
    latestVersionSupport = NativeSupport.latestVersion()
    noCountryFlags = props.noCountryFlags || NativeSupport.noCountryFlags()
  }

  let categoryIndex = Data.categories.length
  let resetSearchIndex = false
  while (categoryIndex--) {
    const category = Data.categories[categoryIndex]

    if (category.id == 'frequent') {
      let { maxFrequentRows, perLine } = props

      maxFrequentRows =
        maxFrequentRows >= 0
          ? maxFrequentRows
          : PickerProps.maxFrequentRows.value
      perLine || (perLine = PickerProps.perLine.value)

      category.emojis = FrequentlyUsed.get({ maxFrequentRows, perLine })
    }

    if (!category.emojis || !category.emojis.length) {
      Data.categories.splice(categoryIndex, 1)
      continue
    }

    const { categoryIcons } = props
    if (categoryIcons) {
      const icon = categoryIcons[category.id]
      if (icon && !category.icon) {
        category.icon = icon
      }
    }

    let emojiIndex = category.emojis.length
    while (emojiIndex--) {
      const emojiId = category.emojis[emojiIndex]
      const emoji = emojiId.id ? emojiId : Data.emojis[emojiId]

      const ignore = () => {
        category.emojis.splice(emojiIndex, 1)
      }

      if (
        !emoji ||
        (props.exceptEmojis && props.exceptEmojis.includes(emoji.id))
      ) {
        ignore()
        continue
      }

      if (latestVersionSupport && emoji.version > latestVersionSupport) {
        ignore()
        continue
      }

      if (noCountryFlags && category.id == 'flags') {
        if (!SafeFlags.includes(emoji.id)) {
          ignore()
          continue
        }
      }

      if (!emoji.search) {
        resetSearchIndex = true
        emoji.search =
          ',' +
          [
            [emoji.id, false],
            [emoji.name, true],
            [emoji.keywords, false],
            [emoji.emoticons, false],
          ]
            .map(([strings, split]) => {
              if (!strings) return
              return (Array.isArray(strings) ? strings : [strings])
                .map((string) => {
                  return (split ? string.split(/[-|_|\s]+/) : [string]).map(
                    (s) => s.toLowerCase(),
                  )
                })
                .flat()
            })
            .flat()
            .filter((a) => a && a.trim())
            .join(',')

        if (emoji.emoticons) {
          for (const emoticon of emoji.emoticons) {
            if (Data.emoticons[emoticon]) continue
            Data.emoticons[emoticon] = emoji.id
          }
        }

        let skinIndex = 0
        for (const skin of emoji.skins) {
          if (!skin) continue
          skinIndex++

          const { native } = skin
          if (native) {
            Data.natives[native] = emoji.id
            emoji.search += `,${native}`
          }

          const skinShortcodes =
            skinIndex == 1 ? '' : `:skin-tone-${skinIndex}:`
          skin.shortcodes = `:${emoji.id}:${skinShortcodes}`
        }
      }
    }
  }

  if (resetSearchIndex) {
    SearchIndex.reset()
  }

  initCallback()
}

export function getProps(props, defaultProps, element) {
  props || (props = {})

  const _props = {}
  for (let k in defaultProps) {
    _props[k] = getProp(k, props, defaultProps, element)
  }

  return _props
}

export function getProp(propName, props, defaultProps, element) {
  const defaults = defaultProps[propName]
  let value =
    (element && element.getAttribute(propName)) ||
    (props[propName] != null && props[propName] != undefined
      ? props[propName]
      : null)

  if (!defaults) {
    return value
  }

  if (
    value != null &&
    defaults.value &&
    typeof defaults.value != typeof value
  ) {
    if (typeof defaults.value == 'boolean') {
      value = value == 'false' ? false : true
    } else {
      value = defaults.value.constructor(value)
    }
  }

  if (defaults.transform && value) {
    value = defaults.transform(value)
  }

  if (
    value == null ||
    (defaults.choices && defaults.choices.indexOf(value) == -1)
  ) {
    value = defaults.value
  }

  return value
}


================================================
FILE: packages/emoji-mart/src/declaration.d.ts
================================================
declare module '*.scss'


================================================
FILE: packages/emoji-mart/src/helpers/__tests__/frequently-used.test.js
================================================
import FrequentlyUsed from '../frequently-used'

describe('FrequentlyUsed', () => {
  test.skip('', () => {})
})


================================================
FILE: packages/emoji-mart/src/helpers/__tests__/native-support.test.js
================================================
import NativeSupport from '../native-support'

describe('NativeSupport', () => {
  test.skip('', () => {})
})


================================================
FILE: packages/emoji-mart/src/helpers/__tests__/search-index.test.js
================================================
import SearchIndex from '../search-index'

describe('SearchIndex', () => {
  test.skip('', () => {})
})


================================================
FILE: packages/emoji-mart/src/helpers/__tests__/store.test.js
================================================
import Store from '../store'

describe('Store', () => {
  test.skip('', () => {})
})


================================================
FILE: packages/emoji-mart/src/helpers/frequently-used.ts
================================================
// @ts-nocheck
import { Store } from '../helpers'

const DEFAULTS = [
  '+1',
  'grinning',
  'kissing_heart',
  'heart_eyes',
  'laughing',
  'stuck_out_tongue_winking_eye',
  'sweat_smile',
  'joy',
  'scream',
  'disappointed',
  'unamused',
  'weary',
  'sob',
  'sunglasses',
  'heart',
]

let Index: any | null = null

function add(emoji: { id: string }) {
  Index || (Index = Store.get('frequently') || {})

  const emojiId = emoji.id || emoji
  if (!emojiId) return

  Index[emojiId] || (Index[emojiId] = 0)
  Index[emojiId] += 1

  Store.set('last', emojiId)
  Store.set('frequently', Index)
}

function get({ maxFrequentRows, perLine }) {
  if (!maxFrequentRows) return []

  Index || (Index = Store.get('frequently'))
  let emojiIds = []

  if (!Index) {
    Index = {}

    for (let i in DEFAULTS.slice(0, perLine)) {
      const emojiId = DEFAULTS[i]

      Index[emojiId] = perLine - i
      emojiIds.push(emojiId)
    }

    return emojiIds
  }

  const max = maxFrequentRows * perLine
  const last = Store.get('last')

  for (let emojiId in Index) {
    emojiIds.push(emojiId)
  }

  emojiIds.sort((a, b) => {
    const aScore = Index[b]
    const bScore = Index[a]

    if (aScore == bScore) {
      return a.localeCompare(b)
    }

    return aScore - bScore
  })

  if (emojiIds.length > max) {
    const removedIds = emojiIds.slice(max)
    emojiIds = emojiIds.slice(0, max)

    for (let removedId of removedIds) {
      if (removedId == last) continue
      delete Index[removedId]
    }

    if (last && emojiIds.indexOf(last) == -1) {
      delete Index[emojiIds[emojiIds.length - 1]]
      emojiIds.splice(-1, 1, last)
    }

    Store.set('frequently', Index)
  }

  return emojiIds
}

export default { add, get, DEFAULTS }


================================================
FILE: packages/emoji-mart/src/helpers/index.ts
================================================
export { default as Store } from './store'

export { default as NativeSupport } from './native-support'
export { default as FrequentlyUsed } from './frequently-used'
export { default as SearchIndex } from './search-index'

export const SafeFlags = [
  'checkered_flag',
  'crossed_flags',
  'pirate_flag',
  'rainbow-flag',
  'transgender_flag',
  'triangular_flag_on_post',
  'waving_black_flag',
  'waving_white_flag',
]


================================================
FILE: packages/emoji-mart/src/helpers/native-support.ts
================================================
const CACHE = new Map()
const VERSIONS = [
  { v: 15, emoji: '🫨' },
  { v: 14, emoji: '🫠' },
  { v: 13.1, emoji: '😶‍🌫️' },
  { v: 13, emoji: '🥸' },
  { v: 12.1, emoji: '🧑‍🦰' },
  { v: 12, emoji: '🥱' },
  { v: 11, emoji: '🥰' },
  { v: 5, emoji: '🤩' },
  { v: 4, emoji: '👱‍♀️' },
  { v: 3, emoji: '🤣' },
  { v: 2, emoji: '👋🏻' },
  { v: 1, emoji: '🙃' },
]

function latestVersion() {
  for (const { v, emoji } of VERSIONS) {
    if (isSupported(emoji)) {
      return v
    }
  }
}

function noCountryFlags() {
  if (isSupported('🇨🇦')) {
    return false
  }

  return true
}

function isSupported(emoji) {
  if (CACHE.has(emoji)) {
    return CACHE.get(emoji)
  }

  const supported = isEmojiSupported(emoji)
  CACHE.set(emoji, supported)

  return supported
}

// https://github.com/koala-interactive/is-emoji-supported
const isEmojiSupported = (() => {
  let ctx = null
  try {
    if (!navigator.userAgent.includes('jsdom')) {
      ctx = document
        .createElement('canvas')
        .getContext('2d', { willReadFrequently: true })
    }
  } catch {}

  // Not in browser env
  if (!ctx) {
    return () => false
  }

  const CANVAS_HEIGHT = 25
  const CANVAS_WIDTH = 20
  const textSize = Math.floor(CANVAS_HEIGHT / 2)

  // Initialize convas context
  ctx.font = textSize + 'px Arial, Sans-Serif'
  ctx.textBaseline = 'top'
  ctx.canvas.width = CANVAS_WIDTH * 2
  ctx.canvas.height = CANVAS_HEIGHT

  return (unicode) => {
    ctx.clearRect(0, 0, CANVAS_WIDTH * 2, CANVAS_HEIGHT)

    // Draw in red on the left
    ctx.fillStyle = '#FF0000'
    ctx.fillText(unicode, 0, 22)

    // Draw in blue on right
    ctx.fillStyle = '#0000FF'
    ctx.fillText(unicode, CANVAS_WIDTH, 22)

    const a = ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT).data
    const count = a.length
    let i = 0

    // Search the first visible pixel
    for (; i < count && !a[i + 3]; i += 4);

    // No visible pixel
    if (i >= count) {
      return false
    }

    // Emoji has immutable color, so we check the color of the emoji in two different colors
    // the result show be the same.
    const x = CANVAS_WIDTH + ((i / 4) % CANVAS_WIDTH)
    const y = Math.floor(i / 4 / CANVAS_WIDTH)
    const b = ctx.getImageData(x, y, 1, 1).data

    if (a[i] !== b[0] || a[i + 2] !== b[2]) {
      return false
    }

    // Some emojis are a contraction of different ones, so if it's not
    // supported, it will show multiple characters
    if (ctx.measureText(unicode).width >= CANVAS_WIDTH) {
      return false
    }

    // Supported
    return true
  }
})()

export default { latestVersion, noCountryFlags }


================================================
FILE: packages/emoji-mart/src/helpers/search-index.ts
================================================
// @ts-nocheck
import { init, Data } from '../config'

const SHORTCODES_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/
let Pool = null

function get(emojiId) {
  if (emojiId.id) {
    return emojiId
  }

  return (
    Data.emojis[emojiId] ||
    Data.emojis[Data.aliases[emojiId]] ||
    Data.emojis[Data.natives[emojiId]]
  )
}

function reset() {
  Pool = null
}

async function search(value, { maxResults, caller } = {}) {
  if (!value || !value.trim().length) return null
  maxResults || (maxResults = 90)

  await init(null, { caller: caller || 'SearchIndex.search' })

  const values = value
    .toLowerCase()
    .replace(/(\w)-/, '$1 ')
    .split(/[\s|,]+/)
    .filter((word, i, words) => {
      return word.trim() && words.indexOf(word) == i
    })

  if (!values.length) return

  let pool = Pool || (Pool = Object.values(Data.emojis))
  let results, scores

  for (const value of values) {
    if (!pool.length) break

    results = []
    scores = {}

    for (const emoji of pool) {
      if (!emoji.search) continue
      const score = emoji.search.indexOf(`,${value}`)
      if (score == -1) continue

      results.push(emoji)
      scores[emoji.id] || (scores[emoji.id] = 0)
      scores[emoji.id] += emoji.id == value ? 0 : score + 1
    }

    pool = results
  }

  if (results.length < 2) {
    return results
  }

  results.sort((a, b) => {
    const aScore = scores[a.id]
    const bScore = scores[b.id]

    if (aScore == bScore) {
      return a.id.localeCompare(b.id)
    }

    return aScore - bScore
  })

  if (results.length > maxResults) {
    results = results.slice(0, maxResults)
  }

  return results
}

export default { search, get, reset, SHORTCODES_REGEX }


================================================
FILE: packages/emoji-mart/src/helpers/store.ts
================================================
function set(key: string, value: string) {
  try {
    window.localStorage[`emoji-mart.${key}`] = JSON.stringify(value)
  } catch (error) {}
}

function get(key: string): any {
  try {
    const value = window.localStorage[`emoji-mart.${key}`]

    if (value) {
      return JSON.parse(value)
    }
  } catch (error) {}
}

export default { set, get }


================================================
FILE: packages/emoji-mart/src/icons.tsx
================================================
const categories = {
  activity: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M12 0C5.373 0 0 5.372 0 12c0 6.627 5.373 12 12 12 6.628 0 12-5.373 12-12 0-6.628-5.372-12-12-12m9.949 11H17.05c.224-2.527 1.232-4.773 1.968-6.113A9.966 9.966 0 0 1 21.949 11M13 11V2.051a9.945 9.945 0 0 1 4.432 1.564c-.858 1.491-2.156 4.22-2.392 7.385H13zm-2 0H8.961c-.238-3.165-1.536-5.894-2.393-7.385A9.95 9.95 0 0 1 11 2.051V11zm0 2v8.949a9.937 9.937 0 0 1-4.432-1.564c.857-1.492 2.155-4.221 2.393-7.385H11zm4.04 0c.236 3.164 1.534 5.893 2.392 7.385A9.92 9.92 0 0 1 13 21.949V13h2.04zM4.982 4.887C5.718 6.227 6.726 8.473 6.951 11h-4.9a9.977 9.977 0 0 1 2.931-6.113M2.051 13h4.9c-.226 2.527-1.233 4.771-1.969 6.113A9.972 9.972 0 0 1 2.051 13m16.967 6.113c-.735-1.342-1.744-3.586-1.968-6.113h4.899a9.961 9.961 0 0 1-2.931 6.113" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M16.17 337.5c0 44.98 7.565 83.54 13.98 107.9C35.22 464.3 50.46 496 174.9 496c9.566 0 19.59-.4707 29.84-1.271L17.33 307.3C16.53 317.6 16.17 327.7 16.17 337.5zM495.8 174.5c0-44.98-7.565-83.53-13.98-107.9c-4.688-17.54-18.34-31.23-36.04-35.95C435.5 27.91 392.9 16 337 16c-9.564 0-19.59 .4707-29.84 1.271l187.5 187.5C495.5 194.4 495.8 184.3 495.8 174.5zM26.77 248.8l236.3 236.3c142-36.1 203.9-150.4 222.2-221.1L248.9 26.87C106.9 62.96 45.07 177.2 26.77 248.8zM256 335.1c0 9.141-7.474 16-16 16c-4.094 0-8.188-1.564-11.31-4.689L164.7 283.3C161.6 280.2 160 276.1 160 271.1c0-8.529 6.865-16 16-16c4.095 0 8.189 1.562 11.31 4.688l64.01 64C254.4 327.8 256 331.9 256 335.1zM304 287.1c0 9.141-7.474 16-16 16c-4.094 0-8.188-1.564-11.31-4.689L212.7 235.3C209.6 232.2 208 228.1 208 223.1c0-9.141 7.473-16 16-16c4.094 0 8.188 1.562 11.31 4.688l64.01 64.01C302.5 279.8 304 283.9 304 287.1zM256 175.1c0-9.141 7.473-16 16-16c4.094 0 8.188 1.562 11.31 4.688l64.01 64.01c3.125 3.125 4.688 7.219 4.688 11.31c0 9.133-7.468 16-16 16c-4.094 0-8.189-1.562-11.31-4.688l-64.01-64.01C257.6 184.2 256 180.1 256 175.1z" />
      </svg>
    ),
  },

  custom: (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
      <path d="M417.1 368c-5.937 10.27-16.69 16-27.75 16c-5.422 0-10.92-1.375-15.97-4.281L256 311.4V448c0 17.67-14.33 32-31.1 32S192 465.7 192 448V311.4l-118.3 68.29C68.67 382.6 63.17 384 57.75 384c-11.06 0-21.81-5.734-27.75-16c-8.828-15.31-3.594-34.88 11.72-43.72L159.1 256L41.72 187.7C26.41 178.9 21.17 159.3 29.1 144C36.63 132.5 49.26 126.7 61.65 128.2C65.78 128.7 69.88 130.1 73.72 132.3L192 200.6V64c0-17.67 14.33-32 32-32S256 46.33 256 64v136.6l118.3-68.29c3.838-2.213 7.939-3.539 12.07-4.051C398.7 126.7 411.4 132.5 417.1 144c8.828 15.31 3.594 34.88-11.72 43.72L288 256l118.3 68.28C421.6 333.1 426.8 352.7 417.1 368z" />
    </svg>
  ),

  flags: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M0 0l6.084 24H8L1.916 0zM21 5h-4l-1-4H4l3 12h3l1 4h13L21 5zM6.563 3h7.875l2 8H8.563l-2-8zm8.832 10l-2.856 1.904L12.063 13h3.332zM19 13l-1.5-6h1.938l2 8H16l3-2z" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M64 496C64 504.8 56.75 512 48 512h-32C7.25 512 0 504.8 0 496V32c0-17.75 14.25-32 32-32s32 14.25 32 32V496zM476.3 0c-6.365 0-13.01 1.35-19.34 4.233c-45.69 20.86-79.56 27.94-107.8 27.94c-59.96 0-94.81-31.86-163.9-31.87C160.9 .3055 131.6 4.867 96 15.75v350.5c32-9.984 59.87-14.1 84.85-14.1c73.63 0 124.9 31.78 198.6 31.78c31.91 0 68.02-5.971 111.1-23.09C504.1 355.9 512 344.4 512 332.1V30.73C512 11.1 495.3 0 476.3 0z" />
      </svg>
    ),
  },

  foods: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M17 4.978c-1.838 0-2.876.396-3.68.934.513-1.172 1.768-2.934 4.68-2.934a1 1 0 0 0 0-2c-2.921 0-4.629 1.365-5.547 2.512-.064.078-.119.162-.18.244C11.73 1.838 10.798.023 9.207.023 8.579.022 7.85.306 7 .978 5.027 2.54 5.329 3.902 6.492 4.999 3.609 5.222 0 7.352 0 12.969c0 4.582 4.961 11.009 9 11.009 1.975 0 2.371-.486 3-1 .629.514 1.025 1 3 1 4.039 0 9-6.418 9-11 0-5.953-4.055-8-7-8M8.242 2.546c.641-.508.943-.523.965-.523.426.169.975 1.405 1.357 3.055-1.527-.629-2.741-1.352-2.98-1.846.059-.112.241-.356.658-.686M15 21.978c-1.08 0-1.21-.109-1.559-.402l-.176-.146c-.367-.302-.816-.452-1.266-.452s-.898.15-1.266.452l-.176.146c-.347.292-.477.402-1.557.402-2.813 0-7-5.389-7-9.009 0-5.823 4.488-5.991 5-5.991 1.939 0 2.484.471 3.387 1.251l.323.276a1.995 1.995 0 0 0 2.58 0l.323-.276c.902-.78 1.447-1.251 3.387-1.251.512 0 5 .168 5 6 0 3.617-4.187 9-7 9" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M481.9 270.1C490.9 279.1 496 291.3 496 304C496 316.7 490.9 328.9 481.9 337.9C472.9 346.9 460.7 352 448 352H64C51.27 352 39.06 346.9 30.06 337.9C21.06 328.9 16 316.7 16 304C16 291.3 21.06 279.1 30.06 270.1C39.06 261.1 51.27 256 64 256H448C460.7 256 472.9 261.1 481.9 270.1zM475.3 388.7C478.3 391.7 480 395.8 480 400V416C480 432.1 473.3 449.3 461.3 461.3C449.3 473.3 432.1 480 416 480H96C79.03 480 62.75 473.3 50.75 461.3C38.74 449.3 32 432.1 32 416V400C32 395.8 33.69 391.7 36.69 388.7C39.69 385.7 43.76 384 48 384H464C468.2 384 472.3 385.7 475.3 388.7zM50.39 220.8C45.93 218.6 42.03 215.5 38.97 211.6C35.91 207.7 33.79 203.2 32.75 198.4C31.71 193.5 31.8 188.5 32.99 183.7C54.98 97.02 146.5 32 256 32C365.5 32 457 97.02 479 183.7C480.2 188.5 480.3 193.5 479.2 198.4C478.2 203.2 476.1 207.7 473 211.6C469.1 215.5 466.1 218.6 461.6 220.8C457.2 222.9 452.3 224 447.3 224H64.67C59.73 224 54.84 222.9 50.39 220.8zM372.7 116.7C369.7 119.7 368 123.8 368 128C368 131.2 368.9 134.3 370.7 136.9C372.5 139.5 374.1 141.6 377.9 142.8C380.8 143.1 384 144.3 387.1 143.7C390.2 143.1 393.1 141.6 395.3 139.3C397.6 137.1 399.1 134.2 399.7 131.1C400.3 128 399.1 124.8 398.8 121.9C397.6 118.1 395.5 116.5 392.9 114.7C390.3 112.9 387.2 111.1 384 111.1C379.8 111.1 375.7 113.7 372.7 116.7V116.7zM244.7 84.69C241.7 87.69 240 91.76 240 96C240 99.16 240.9 102.3 242.7 104.9C244.5 107.5 246.1 109.6 249.9 110.8C252.8 111.1 256 112.3 259.1 111.7C262.2 111.1 265.1 109.6 267.3 107.3C269.6 105.1 271.1 102.2 271.7 99.12C272.3 96.02 271.1 92.8 270.8 89.88C269.6 86.95 267.5 84.45 264.9 82.7C262.3 80.94 259.2 79.1 256 79.1C251.8 79.1 247.7 81.69 244.7 84.69V84.69zM116.7 116.7C113.7 119.7 112 123.8 112 128C112 131.2 112.9 134.3 114.7 136.9C116.5 139.5 118.1 141.6 121.9 142.8C124.8 143.1 128 144.3 131.1 143.7C134.2 143.1 137.1 141.6 139.3 139.3C141.6 137.1 143.1 134.2 143.7 131.1C144.3 128 143.1 124.8 142.8 121.9C141.6 118.1 139.5 116.5 136.9 114.7C134.3 112.9 131.2 111.1 128 111.1C123.8 111.1 119.7 113.7 116.7 116.7L116.7 116.7z" />
      </svg>
    ),
  },

  frequent: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M13 4h-2l-.001 7H9v2h2v2h2v-2h4v-2h-4z" />
        <path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0m0 22C6.486 22 2 17.514 2 12S6.486 2 12 2s10 4.486 10 10-4.486 10-10 10" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M256 512C114.6 512 0 397.4 0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512zM232 256C232 264 236 271.5 242.7 275.1L338.7 339.1C349.7 347.3 364.6 344.3 371.1 333.3C379.3 322.3 376.3 307.4 365.3 300L280 243.2V120C280 106.7 269.3 96 255.1 96C242.7 96 231.1 106.7 231.1 120L232 256z" />
      </svg>
    ),
  },

  nature: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M15.5 8a1.5 1.5 0 1 0 .001 3.001A1.5 1.5 0 0 0 15.5 8M8.5 8a1.5 1.5 0 1 0 .001 3.001A1.5 1.5 0 0 0 8.5 8" />
        <path d="M18.933 0h-.027c-.97 0-2.138.787-3.018 1.497-1.274-.374-2.612-.51-3.887-.51-1.285 0-2.616.133-3.874.517C7.245.79 6.069 0 5.093 0h-.027C3.352 0 .07 2.67.002 7.026c-.039 2.479.276 4.238 1.04 5.013.254.258.882.677 1.295.882.191 3.177.922 5.238 2.536 6.38.897.637 2.187.949 3.2 1.102C8.04 20.6 8 20.795 8 21c0 1.773 2.35 3 4 3 1.648 0 4-1.227 4-3 0-.201-.038-.393-.072-.586 2.573-.385 5.435-1.877 5.925-7.587.396-.22.887-.568 1.104-.788.763-.774 1.079-2.534 1.04-5.013C23.929 2.67 20.646 0 18.933 0M3.223 9.135c-.237.281-.837 1.155-.884 1.238-.15-.41-.368-1.349-.337-3.291.051-3.281 2.478-4.972 3.091-5.031.256.015.731.27 1.265.646-1.11 1.171-2.275 2.915-2.352 5.125-.133.546-.398.858-.783 1.313M12 22c-.901 0-1.954-.693-2-1 0-.654.475-1.236 1-1.602V20a1 1 0 1 0 2 0v-.602c.524.365 1 .947 1 1.602-.046.307-1.099 1-2 1m3-3.48v.02a4.752 4.752 0 0 0-1.262-1.02c1.092-.516 2.239-1.334 2.239-2.217 0-1.842-1.781-2.195-3.977-2.195-2.196 0-3.978.354-3.978 2.195 0 .883 1.148 1.701 2.238 2.217A4.8 4.8 0 0 0 9 18.539v-.025c-1-.076-2.182-.281-2.973-.842-1.301-.92-1.838-3.045-1.853-6.478l.023-.041c.496-.826 1.49-1.45 1.804-3.102 0-2.047 1.357-3.631 2.362-4.522C9.37 3.178 10.555 3 11.948 3c1.447 0 2.685.192 3.733.57 1 .9 2.316 2.465 2.316 4.48.313 1.651 1.307 2.275 1.803 3.102.035.058.068.117.102.178-.059 5.967-1.949 7.01-4.902 7.19m6.628-8.202c-.037-.065-.074-.13-.113-.195a7.587 7.587 0 0 0-.739-.987c-.385-.455-.648-.768-.782-1.313-.076-2.209-1.241-3.954-2.353-5.124.531-.376 1.004-.63 1.261-.647.636.071 3.044 1.764 3.096 5.031.027 1.81-.347 3.218-.37 3.235" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
        <path d="M332.7 19.85C334.6 8.395 344.5 0 356.1 0C363.6 0 370.6 3.52 375.1 9.502L392 32H444.1C456.8 32 469.1 37.06 478.1 46.06L496 64H552C565.3 64 576 74.75 576 88V112C576 156.2 540.2 192 496 192H426.7L421.6 222.5L309.6 158.5L332.7 19.85zM448 64C439.2 64 432 71.16 432 80C432 88.84 439.2 96 448 96C456.8 96 464 88.84 464 80C464 71.16 456.8 64 448 64zM416 256.1V480C416 497.7 401.7 512 384 512H352C334.3 512 320 497.7 320 480V364.8C295.1 377.1 268.8 384 240 384C211.2 384 184 377.1 160 364.8V480C160 497.7 145.7 512 128 512H96C78.33 512 64 497.7 64 480V249.8C35.23 238.9 12.64 214.5 4.836 183.3L.9558 167.8C-3.331 150.6 7.094 133.2 24.24 128.1C41.38 124.7 58.76 135.1 63.05 152.2L66.93 167.8C70.49 182 83.29 191.1 97.97 191.1H303.8L416 256.1z" />
      </svg>
    ),
  },

  objects: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M12 0a9 9 0 0 0-5 16.482V21s2.035 3 5 3 5-3 5-3v-4.518A9 9 0 0 0 12 0zm0 2c3.86 0 7 3.141 7 7s-3.14 7-7 7-7-3.141-7-7 3.14-7 7-7zM9 17.477c.94.332 1.946.523 3 .523s2.06-.19 3-.523v.834c-.91.436-1.925.689-3 .689a6.924 6.924 0 0 1-3-.69v-.833zm.236 3.07A8.854 8.854 0 0 0 12 21c.965 0 1.888-.167 2.758-.451C14.155 21.173 13.153 22 12 22c-1.102 0-2.117-.789-2.764-1.453z" />
        <path d="M14.745 12.449h-.004c-.852-.024-1.188-.858-1.577-1.824-.421-1.061-.703-1.561-1.182-1.566h-.009c-.481 0-.783.497-1.235 1.537-.436.982-.801 1.811-1.636 1.791l-.276-.043c-.565-.171-.853-.691-1.284-1.794-.125-.313-.202-.632-.27-.913-.051-.213-.127-.53-.195-.634C7.067 9.004 7.039 9 6.99 9A1 1 0 0 1 7 7h.01c1.662.017 2.015 1.373 2.198 2.134.486-.981 1.304-2.058 2.797-2.075 1.531.018 2.28 1.153 2.731 2.141l.002-.008C14.944 8.424 15.327 7 16.979 7h.032A1 1 0 1 1 17 9h-.011c-.149.076-.256.474-.319.709a6.484 6.484 0 0 1-.311.951c-.429.973-.79 1.789-1.614 1.789" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
        <path d="M112.1 454.3c0 6.297 1.816 12.44 5.284 17.69l17.14 25.69c5.25 7.875 17.17 14.28 26.64 14.28h61.67c9.438 0 21.36-6.401 26.61-14.28l17.08-25.68c2.938-4.438 5.348-12.37 5.348-17.7L272 415.1h-160L112.1 454.3zM191.4 .0132C89.44 .3257 16 82.97 16 175.1c0 44.38 16.44 84.84 43.56 115.8c16.53 18.84 42.34 58.23 52.22 91.45c.0313 .25 .0938 .5166 .125 .7823h160.2c.0313-.2656 .0938-.5166 .125-.7823c9.875-33.22 35.69-72.61 52.22-91.45C351.6 260.8 368 220.4 368 175.1C368 78.61 288.9-.2837 191.4 .0132zM192 96.01c-44.13 0-80 35.89-80 79.1C112 184.8 104.8 192 96 192S80 184.8 80 176c0-61.76 50.25-111.1 112-111.1c8.844 0 16 7.159 16 16S200.8 96.01 192 96.01z" />
      </svg>
    ),
  },

  people: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0m0 22C6.486 22 2 17.514 2 12S6.486 2 12 2s10 4.486 10 10-4.486 10-10 10" />
        <path d="M8 7a2 2 0 1 0-.001 3.999A2 2 0 0 0 8 7M16 7a2 2 0 1 0-.001 3.999A2 2 0 0 0 16 7M15.232 15c-.693 1.195-1.87 2-3.349 2-1.477 0-2.655-.805-3.347-2H15m3-2H6a6 6 0 1 0 12 0" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512C114.6 512 0 397.4 0 256zM256 432C332.1 432 396.2 382 415.2 314.1C419.1 300.4 407.8 288 393.6 288H118.4C104.2 288 92.92 300.4 96.76 314.1C115.8 382 179.9 432 256 432V432zM176.4 160C158.7 160 144.4 174.3 144.4 192C144.4 209.7 158.7 224 176.4 224C194 224 208.4 209.7 208.4 192C208.4 174.3 194 160 176.4 160zM336.4 224C354 224 368.4 209.7 368.4 192C368.4 174.3 354 160 336.4 160C318.7 160 304.4 174.3 304.4 192C304.4 209.7 318.7 224 336.4 224z" />
      </svg>
    ),
  },

  places: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M6.5 12C5.122 12 4 13.121 4 14.5S5.122 17 6.5 17 9 15.879 9 14.5 7.878 12 6.5 12m0 3c-.275 0-.5-.225-.5-.5s.225-.5.5-.5.5.225.5.5-.225.5-.5.5M17.5 12c-1.378 0-2.5 1.121-2.5 2.5s1.122 2.5 2.5 2.5 2.5-1.121 2.5-2.5-1.122-2.5-2.5-2.5m0 3c-.275 0-.5-.225-.5-.5s.225-.5.5-.5.5.225.5.5-.225.5-.5.5" />
        <path d="M22.482 9.494l-1.039-.346L21.4 9h.6c.552 0 1-.439 1-.992 0-.006-.003-.008-.003-.008H23c0-1-.889-2-1.984-2h-.642l-.731-1.717C19.262 3.012 18.091 2 16.764 2H7.236C5.909 2 4.738 3.012 4.357 4.283L3.626 6h-.642C1.889 6 1 7 1 8h.003S1 8.002 1 8.008C1 8.561 1.448 9 2 9h.6l-.043.148-1.039.346a2.001 2.001 0 0 0-1.359 2.097l.751 7.508a1 1 0 0 0 .994.901H3v1c0 1.103.896 2 2 2h2c1.104 0 2-.897 2-2v-1h6v1c0 1.103.896 2 2 2h2c1.104 0 2-.897 2-2v-1h1.096a.999.999 0 0 0 .994-.901l.751-7.508a2.001 2.001 0 0 0-1.359-2.097M6.273 4.857C6.402 4.43 6.788 4 7.236 4h9.527c.448 0 .834.43.963.857L19.313 9H4.688l1.585-4.143zM7 21H5v-1h2v1zm12 0h-2v-1h2v1zm2.189-3H2.811l-.662-6.607L3 11h18l.852.393L21.189 18z" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M39.61 196.8L74.8 96.29C88.27 57.78 124.6 32 165.4 32H346.6C387.4 32 423.7 57.78 437.2 96.29L472.4 196.8C495.6 206.4 512 229.3 512 256V448C512 465.7 497.7 480 480 480H448C430.3 480 416 465.7 416 448V400H96V448C96 465.7 81.67 480 64 480H32C14.33 480 0 465.7 0 448V256C0 229.3 16.36 206.4 39.61 196.8V196.8zM109.1 192H402.9L376.8 117.4C372.3 104.6 360.2 96 346.6 96H165.4C151.8 96 139.7 104.6 135.2 117.4L109.1 192zM96 256C78.33 256 64 270.3 64 288C64 305.7 78.33 320 96 320C113.7 320 128 305.7 128 288C128 270.3 113.7 256 96 256zM416 320C433.7 320 448 305.7 448 288C448 270.3 433.7 256 416 256C398.3 256 384 270.3 384 288C384 305.7 398.3 320 416 320z" />
      </svg>
    ),
  },

  symbols: {
    outline: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M0 0h11v2H0zM4 11h3V6h4V4H0v2h4zM15.5 17c1.381 0 2.5-1.116 2.5-2.493s-1.119-2.493-2.5-2.493S13 13.13 13 14.507 14.119 17 15.5 17m0-2.986c.276 0 .5.222.5.493 0 .272-.224.493-.5.493s-.5-.221-.5-.493.224-.493.5-.493M21.5 19.014c-1.381 0-2.5 1.116-2.5 2.493S20.119 24 21.5 24s2.5-1.116 2.5-2.493-1.119-2.493-2.5-2.493m0 2.986a.497.497 0 0 1-.5-.493c0-.271.224-.493.5-.493s.5.222.5.493a.497.497 0 0 1-.5.493M22 13l-9 9 1.513 1.5 8.99-9.009zM17 11c2.209 0 4-1.119 4-2.5V2s.985-.161 1.498.949C23.01 4.055 23 6 23 6s1-1.119 1-3.135C24-.02 21 0 21 0h-2v6.347A5.853 5.853 0 0 0 17 6c-2.209 0-4 1.119-4 2.5s1.791 2.5 4 2.5M10.297 20.482l-1.475-1.585a47.54 47.54 0 0 1-1.442 1.129c-.307-.288-.989-1.016-2.045-2.183.902-.836 1.479-1.466 1.729-1.892s.376-.871.376-1.336c0-.592-.273-1.178-.818-1.759-.546-.581-1.329-.871-2.349-.871-1.008 0-1.79.293-2.344.879-.556.587-.832 1.181-.832 1.784 0 .813.419 1.748 1.256 2.805-.847.614-1.444 1.208-1.794 1.784a3.465 3.465 0 0 0-.523 1.833c0 .857.308 1.56.924 2.107.616.549 1.423.823 2.42.823 1.173 0 2.444-.379 3.813-1.137L8.235 24h2.819l-2.09-2.383 1.333-1.135zm-6.736-6.389a1.02 1.02 0 0 1 .73-.286c.31 0 .559.085.747.254a.849.849 0 0 1 .283.659c0 .518-.419 1.112-1.257 1.784-.536-.651-.805-1.231-.805-1.742a.901.901 0 0 1 .302-.669M3.74 22c-.427 0-.778-.116-1.057-.349-.279-.232-.418-.487-.418-.766 0-.594.509-1.288 1.527-2.083.968 1.134 1.717 1.946 2.248 2.438-.921.507-1.686.76-2.3.76" />
      </svg>
    ),
    solid: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M500.3 7.251C507.7 13.33 512 22.41 512 31.1V175.1C512 202.5 483.3 223.1 447.1 223.1C412.7 223.1 383.1 202.5 383.1 175.1C383.1 149.5 412.7 127.1 447.1 127.1V71.03L351.1 90.23V207.1C351.1 234.5 323.3 255.1 287.1 255.1C252.7 255.1 223.1 234.5 223.1 207.1C223.1 181.5 252.7 159.1 287.1 159.1V63.1C287.1 48.74 298.8 35.61 313.7 32.62L473.7 .6198C483.1-1.261 492.9 1.173 500.3 7.251H500.3zM74.66 303.1L86.5 286.2C92.43 277.3 102.4 271.1 113.1 271.1H174.9C185.6 271.1 195.6 277.3 201.5 286.2L213.3 303.1H239.1C266.5 303.1 287.1 325.5 287.1 351.1V463.1C287.1 490.5 266.5 511.1 239.1 511.1H47.1C21.49 511.1-.0019 490.5-.0019 463.1V351.1C-.0019 325.5 21.49 303.1 47.1 303.1H74.66zM143.1 359.1C117.5 359.1 95.1 381.5 95.1 407.1C95.1 434.5 117.5 455.1 143.1 455.1C170.5 455.1 191.1 434.5 191.1 407.1C191.1 381.5 170.5 359.1 143.1 359.1zM440.3 367.1H496C502.7 367.1 508.6 372.1 510.1 378.4C513.3 384.6 511.6 391.7 506.5 396L378.5 508C372.9 512.1 364.6 513.3 358.6 508.9C352.6 504.6 350.3 496.6 353.3 489.7L391.7 399.1H336C329.3 399.1 323.4 395.9 321 389.6C318.7 383.4 320.4 376.3 325.5 371.1L453.5 259.1C459.1 255 467.4 254.7 473.4 259.1C479.4 263.4 481.6 271.4 478.7 278.3L440.3 367.1zM116.7 219.1L19.85 119.2C-8.112 90.26-6.614 42.31 24.85 15.34C51.82-8.137 93.26-3.642 118.2 21.83L128.2 32.32L137.7 21.83C162.7-3.642 203.6-8.137 231.6 15.34C262.6 42.31 264.1 90.26 236.1 119.2L139.7 219.1C133.2 225.6 122.7 225.6 116.7 219.1H116.7z" />
      </svg>
    ),
  },
}

const search = {
  loupe: (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
      <path d="M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z" />
    </svg>
  ),

  delete: (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
      <path d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z" />
    </svg>
  ),
}

export default { categories, search }


================================================
FILE: packages/emoji-mart/src/index.ts
================================================
export { PickerElement as Picker } from './components/Picker'
export { EmojiElement as Emoji } from './components/Emoji'

export { FrequentlyUsed, SafeFlags, SearchIndex, Store } from './helpers'

export { init, Data, I18n } from './config'

export { getEmojiDataFromNative } from './utils'


================================================
FILE: packages/emoji-mart/src/utils.ts
================================================
import { SearchIndex } from './helpers'

export function deepEqual(a: any, b: any): boolean {
  return (
    Array.isArray(a) &&
    Array.isArray(b) &&
    a.length === b.length &&
    a.every((val, index) => val == b[index])
  )
}

export async function sleep(frames = 1) {
  for (let _ in [...Array(frames).keys()]) {
    await new Promise(requestAnimationFrame)
  }
}

export function getEmojiData(emoji, { skinIndex = 0 } = {}) {
  const skin =
    emoji.skins[skinIndex] ||
    (() => {
      skinIndex = 0
      return emoji.skins[skinIndex]
    })()

  const emojiData: any = {
    id: emoji.id,
    name: emoji.name,
    native: skin.native,
    unified: skin.unified,
    keywords: emoji.keywords,
    shortcodes: skin.shortcodes || emoji.shortcodes,
  }

  if (emoji.skins.length > 1) {
    emojiData.skin = skinIndex + 1
  }

  if (skin.src) {
    emojiData.src = skin.src
  }

  if (emoji.aliases && emoji.aliases.length) {
    emojiData.aliases = emoji.aliases
  }

  if (emoji.emoticons && emoji.emoticons.length) {
    emojiData.emoticons = emoji.emoticons
  }

  return emojiData
}

export async function getEmojiDataFromNative(nativeString) {
  const results = await SearchIndex.search(nativeString, {
    maxResults: 1,
    caller: 'getEmojiDataFromNative',
  })
  if (!results || !results.length) return null

  const emoji = results[0]
  let skinIndex = 0

  for (let skin of emoji.skins) {
    if (skin.native == nativeString) {
      break
    }

    skinIndex++
  }

  return getEmojiData(emoji, { skinIndex })
}


================================================
FILE: packages/emoji-mart-data/LICENSE
================================================
MIT License

Copyright (c) Missive.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: packages/emoji-mart-data/README.md
================================================
# `@emoji-mart/data`

This package contains the data used by [EmojiMart](https://missiveapp.com/open/emoji-mart).


================================================
FILE: packages/emoji-mart-data/build.js
================================================
const { mkdir, writeFile, rmSync } = require('fs')

const inflection = require('inflection')
const emojiLib = require('emojilib')
const emojiData = require('emoji-datasource')
const unicodeEmoji = require('unicode-emoji-json')

const DRY_RUN = process.argv.indexOf('--dry') != -1

const VERSIONS = [1, 2, 3, 4, 5, 11, 12, 12.1, 13, 13.1, 14, 15]
const SKINS = ['1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']
const SETS = ['native', 'apple', 'facebook', 'google', 'twitter']
const CATEGORIES = [
  ['Smileys & Emotion', 'smileys'],
  ['People & Body', 'people'],
  ['Animals & Nature', 'nature'],
  ['Food & Drink', 'foods'],
  ['Activities', 'activity'],
  ['Travel & Places', 'places'],
  ['Objects', 'objects'],
  ['Symbols', 'symbols'],
  ['Flags', 'flags'],
]

const KEYWORD_SUBSTITUTES = {
  highfive: 'highfive high-five',
}

function unifiedToNative(unified) {
  let unicodes = unified.split('-')
  let codePoints = unicodes.map((u) => `0x${u}`)

  return String.fromCodePoint(...codePoints)
}

function buildData({ set, version } = {}) {
  const categoriesIndex = {}
  const nativeSet = set == 'native'
  const data = {
    categories: [],
    emojis: {},
    aliases: {},
    sheet: { cols: 61, rows: 61 },
  }

  CATEGORIES.forEach((category, i) => {
    let [name, id] = category
    data.categories[i] = { id: id, emojis: [] }
    categoriesIndex[name] = i
  })

  emojiData.sort((a, b) => {
    let aTest = a.sort_order || a.short_name
    let bTest = b.sort_order || b.short_name

    return aTest - bTest
  })

  emojiData.forEach((datum) => {
    if (set && !nativeSet) {
      if (!datum[`has_img_${set}`]) {
        return
      }
    }

    if (!datum.category) {
      throw new Error(`“${datum.short_name}” doesn’t have a category`)
    }

    let unified = datum.unified.toLowerCase()
    let native = unifiedToNative(unified)

    let name = inflection.titleize(
      datum.name || datum.short_name.replace(/\-/g, ' ') || '',
    )

    let unicodeEmojiName = inflection.titleize(unicodeEmoji[native]?.name || '')
    if (
      name.indexOf(':') == -1 &&
      unicodeEmojiName.length &&
      unicodeEmojiName.length < name.length
    ) {
      name = unicodeEmojiName
    }

    if (!name) {
      throw new Error(`“${datum.short_name}” doesn’t have a name`)
    }

    let ids = datum.short_names || []
    if (ids.indexOf(datum.short_name) == -1) {
      ids.unshift(datum.short_name)
    }

    for (let id of ids) {
      if (id == ids[0]) continue
      data.aliases[id] = ids[0]
    }

    let id = ids[0]

    let emoticons = datum.texts || []
    if (datum.text && emoticons.indexOf(datum.text) == -1) {
      emoticons.unshift(datum.text)
    }

    if (id == 'expressionless') {
      if (emoticons.indexOf('-_-') == -1) {
        emoticons.push('-_-')
      }
    }

    let keywords = ids
      .concat(emojiLib[native] || [])
      .map((word) => {
        word = KEYWORD_SUBSTITUTES[word] || word
        return word
          .normalize('NFD')
          .replace(/\p{Diacritic}/gu, '')
          .replace(/(\w)-/, '$1_')
          .split(/[_|\s]+/)
      })
      .flat()
      .filter((word, i, words) => {
        return (
          words.indexOf(word) === i &&
          name.toLowerCase().split(/\s/).indexOf(word) == -1
        )
      })

    let s = { unified, native }
    if (!nativeSet) {
      s.x = datum.sheet_x
      s.y = datum.sheet_y
    }

    let skins = [s]

    if (datum.skin_variations) {
      for (let skin of SKINS) {
        let skinDatum =
          datum.skin_variations[skin] ||
          datum.skin_variations[`${skin}-${skin}`]

        if (!skinDatum || (set && !nativeSet && !skinDatum[`has_img_${set}`])) {
          skins.push(null)
          continue
        }

        let unified = skinDatum.unified.toLowerCase()
        let native = unifiedToNative(skinDatum.unified)
        let s = { unified, native }
        if (!nativeSet) {
          s.x = skinDatum.sheet_x
          s.y = skinDatum.sheet_y
        }

        skins.push(s)
      }
    }

    let addedIn = parseFloat(datum.added_in)
    if (addedIn < 1) addedIn = 1

    if (version && addedIn > version) {
      return
    }

    const emoji = {
      id,
      name,
      emoticons,
      keywords,
      skins,
      version: addedIn,
    }

    if (!emoji.emoticons.length) {
      delete emoji.emoticons
    }

    if (datum.category != 'Component') {
      let categoryIndex = categoriesIndex[datum.category]
      data.categories[categoryIndex].emojis.push(emoji.id)
      data.emojis[emoji.id] = emoji
    }
  })

  let flags = data.categories[categoriesIndex['Flags']]
  flags.emojis = flags.emojis.sort()

  // Merge “Smileys & Emotion” and “People & Body” into a single category
  let smileys = data.categories[0]
  let people = data.categories[1]
  let smileysAndPeople = { id: 'people' }
  smileysAndPeople.emojis = []
    .concat(smileys.emojis.slice(0, 114))
    .concat(people.emojis)
    .concat(smileys.emojis.slice(114))

  data.categories.unshift(smileysAndPeople)
  data.categories.splice(1, 2)

  if (!DRY_RUN) {
    let folder = 'sets'
    if (version) folder += `/${version}`

    mkdir(folder, { recursive: true }, () => {
      writeFile(
        `${folder}/${set || 'all'}.json`,
        JSON.stringify(data),
        (err) => {
          if (err) throw err
        },
      )
    })
  }
}

if (!DRY_RUN) {
  rmSync('sets', { recursive: true })
}

for (let version of VERSIONS) {
  buildData({ version })

  for (let set of SETS) {
    buildData({ set, version })
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/ar.json
================================================
{
  "rtl": true,

  "search": "البحث",
  "search_no_results_1": "أوه لا!",
  "search_no_results_2": "لا يمكن العثور على هذا الرمز التعبيري",
  "pick": "اختر رمزًا تعبيريًا…",
  "add_custom": "أضف رمزًا تعبيري مخصص",
  "categories": {
    "activity": "نشاط",
    "custom": "مخصص",
    "flags": "أعلام",
    "foods": "طعام & شراب",
    "frequent": "تم أستخدامه مؤخرا",
    "nature": "الحيوانات & الطبيعة",
    "objects": "أجسام",
    "people": "وجوه ضاحكه & اشخاص",
    "places": "السفر & الأماكن",
    "search": "نتائج البحث",
    "symbols": "حرف او رمز"
  },
  "skins": {
    "choose": "اختر لون البشرة الافتراضي",
    "1": "إفتراضي",
    "2": "فاتح",
    "3": "فاتح متوسط",
    "4": "متوسط",
    "5": "داكن متوسط",
    "6": "داكن"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/be.json
================================================
{
  "search": "Пошук",
  "search_no_results_1": "О не!",
  "search_no_results_2": "Эмодзі ня знойдзены",
  "pick": "Выберыце эмодзі…",
  "add_custom": "Дадаць свой эмодзі",
  "categories": {
    "activity": "Актыўнасці",
    "custom": "Свае",
    "flags": "Сцягі",
    "foods": "Ежа і напоі",
    "frequent": "Часта выкарыстоўваемыя",
    "nature": "Жывёлы і прырода",
    "objects": "Прадметы",
    "people": "Эмоцыі і людзі",
    "places": "Падарожжы і месцы",
    "search": "Рэзультаты пошуку",
    "symbols": "Сімвалы"
  },
  "skins": {
    "choose": "Выберыце колер скуры па змаўчанні",
    "1": "Па змаўчанні",
    "2": "Светлы",
    "3": "Сярэдне-светлы",
    "4": "Сярэдні",
    "5": "Сярэдне-цёмны",
    "6": "Цёмны"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/cs.json
================================================
{
  "search": "Vyhledat",
  "search_no_results_1": "Ale ne!",
  "search_no_results_2": "Emoji nebylo nalezeno",
  "pick": "Vyberte emoji…",
  "add_custom": "Přidat vlastní emoji",
  "categories": {
    "activity": "Aktivity",
    "custom": "Vlastní",
    "flags": "Vlajky",
    "foods": "Jídlo a pití",
    "frequent": "Často používané",
    "nature": "Zvířata a příroda",
    "objects": "Objekty",
    "people": "Smajlíci a lidé",
    "places": "Cestování a místa",
    "search": "Výsledky vyhledávání",
    "symbols": "Symboly"
  },
  "skins": {
    "choose": "Vyberte výchozí odstín pleti",
    "1": "Výchozí",
    "2": "Světlý",
    "3": "Středně světlý",
    "4": "Střední",
    "5": "Středně tmavý",
    "6": "Tmavý"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/de.json
================================================
{
  "search": "Suchen",
  "search_no_results_1": "Oh nein!",
  "search_no_results_2": "Das Emoji konnte nicht gefunden werden",
  "pick": "Wähle ein Emoji…",
  "add_custom": "Füge ein benutzerdefiniertes Emoji hinzu",
  "categories": {
    "activity": "Aktivität",
    "custom": "Benutzerdefiniert",
    "flags": "Flaggen",
    "foods": "Essen & Trinken",
    "frequent": "Oft genutzt",
    "nature": "Tiere & Natur",
    "objects": "Objekte",
    "people": "Smileys & Personen",
    "places": "Reisen & Orte",
    "search": "Suchergebnisse",
    "symbols": "Symbole"
  },
  "skins": {
    "choose": "Wähle eine Standard-Hautfarbe",
    "1": "Standard",
    "2": "Hell",
    "3": "Mittelhell",
    "4": "Mittel",
    "5": "Mitteldunkel",
    "6": "Dunkel"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/en.json
================================================
{
  "search": "Search",
  "search_no_results_1": "Oh no!",
  "search_no_results_2": "That emoji couldn’t be found",
  "pick": "Pick an emoji…",
  "add_custom": "Add custom emoji",
  "categories": {
    "activity": "Activity",
    "custom": "Custom",
    "flags": "Flags",
    "foods": "Food & Drink",
    "frequent": "Frequently used",
    "nature": "Animals & Nature",
    "objects": "Objects",
    "people": "Smileys & People",
    "places": "Travel & Places",
    "search": "Search Results",
    "symbols": "Symbols"
  },
  "skins": {
    "choose": "Choose default skin tone",
    "1": "Default",
    "2": "Light",
    "3": "Medium-Light",
    "4": "Medium",
    "5": "Medium-Dark",
    "6": "Dark"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/es.json
================================================
{
  "search": "Buscar",
  "search_no_results_1": "Vaya!",
  "search_no_results_2": "Ese emoji no se pudo encontrar",
  "pick": "Elige un emoji…",
  "add_custom": "Añadir emoji personalizado",
  "categories": {
    "activity": "Actividades",
    "custom": "Personalizados",
    "flags": "Banderas",
    "foods": "Comida y Bebida",
    "frequent": "Usados con frecuencia",
    "nature": "Animales y Naturaleza",
    "objects": "Objetos",
    "people": "Emoticonos y Personas",
    "places": "Viajes y Destinos",
    "search": "Resultados de la búsqueda",
    "symbols": "Símbolos"
  },
  "skins": {
    "choose": "Elige el tono de piel predeterminado",
    "1": "Sin tono",
    "2": "Claro",
    "3": "Medio-Claro",
    "4": "Medio",
    "5": "Medio-Oscuro",
    "6": "Oscuro"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/fa.json
================================================
{
  "rtl": true,

  "search": "جستجو",
  "search_no_results_1": "اوه نه!",
  "search_no_results_2": "این ایموجی یافت نشد",
  "pick": "یک ایموجی انتخاب کنید",
  "add_custom": "ایموجی سفارشی اضافه کنید",
  "categories": {
    "activity": "فعالیت‌ها",
    "custom": "سفارشی",
    "flags": "پرچم‌ها",
    "foods": "غذا و نوشیدنی",
    "frequent": "پر استفاده‌ها",
    "nature": "حیوانات و طبیعت",
    "objects": "اشیاء",
    "people": "شکلک‌ها و مردم",
    "places": "سفر و مکان‌ها",
    "search": "نتایج جستجو",
    "symbols": "نمادها"
  },
  "skins": {
    "choose": "رنگ پوسته پیش‌فرض را انتخاب کنید",
    "1": "پیش‌فرض",
    "2": "روشن",
    "3": "میانه-روشن",
    "4": "میانه",
    "5": "میانه-تاریک",
    "6": "تاریک"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/fi.json
================================================
{
  "search": "Hae",
  "search_no_results_1": "Voi ei!",
  "search_no_results_2": "Hakemaasi emojia ei löytynyt",
  "pick": "Valitse emoji…",
  "add_custom": "Lisää räätälöity emoji",
  "categories": {
    "activity": "Toiminta",
    "custom": "Räätälöity",
    "flags": "Liput",
    "foods": "Ruoka & Juoma",
    "frequent": "Usein käytetyt",
    "nature": "Eläimet & Luonto",
    "objects": "Esineet",
    "people": "Hymiöt & Ihmiset",
    "places": "Matkustelu & Paikat",
    "search": "Hakutulokset",
    "symbols": "Symbolit"
  },
  "skins": {
    "choose": "Valitse oletusihonväri",
    "1": "Oletus",
    "2": "Vaalea",
    "3": "Keskivaalea",
    "4": "Keskimmäinen",
    "5": "Keskitumma",
    "6": "Tumma"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/fr.json
================================================
{
  "search": "Rechercher",
  "search_no_results_1": "Oh non!",
  "search_no_results_2": "Cet emoji ne peut être trouvé",
  "pick": "Choisissez un emoji…",
  "add_custom": "Ajouter un emoji personnalisé",
  "categories": {
    "activity": "Activités",
    "custom": "Personnalisé",
    "flags": "Drapeaux",
    "foods": "Nourriture & Boissons",
    "frequent": "Fréquemment utilisé",
    "nature": "Animaux & Nature",
    "objects": "Objets",
    "people": "Smileys & Personnes",
    "places": "Voyages & Lieux",
    "search": "Résultats de recherche",
    "symbols": "Symboles"
  },
  "skins": {
    "choose": "Choisissez une couleur de peau",
    "1": "Défaut",
    "2": "Clair",
    "3": "Moyen-clair",
    "4": "Moyen",
    "5": "Moyen-foncé",
    "6": "Foncé"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/hi.json
================================================
{
  "search": "खोज",
  "search_no_results_1": "धत्तेरे की!",
  "search_no_results_2": "वह भाव चित्र नहीं मिला",
  "pick": "कोई भाव चित्र चुनें...",
  "add_custom": "रीति भाव चित्र जोड़ें",
  "categories": {
    "activity": "गतिविधि",
    "custom": "रीति",
    "flags": "झंडे",
    "foods": "भोजन पेय",
    "frequent": "बहुधा प्रयुक्त",
    "nature": "पशु और प्रकृति",
    "objects": "वस्तुओं",
    "people": "मुस्कुराहट और लोग",
    "places": "यात्रा और स्थान",
    "search": "खोज के परिणाम",
    "symbols": "प्रतीक"
  },
  "skins": {
    "choose": "शुरुआती रूप चुनें",
    "1": "शुरुआती",
    "2": "हल्का",
    "3": "मध्यम-हल्का",
    "4": "मध्यम",
    "5": "मध्यम-गहरा",
    "6": "गहरा"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/it.json
================================================
{
  "search": "Cerca",
  "search_no_results_1": "Oh no!",
  "search_no_results_2": "Impossibile trovare l'emoji",
  "pick": "Scegli un'emoji…",
  "add_custom": "Aggiungi emoji personalizzata",
  "categories": {
    "activity": "Attività",
    "custom": "Personalizzate",
    "flags": "Bandiere",
    "foods": "Cibi e bevande",
    "frequent": "Usate di frequente",
    "nature": "Animali e natura",
    "objects": "Oggetti",
    "people": "Faccine e persone",
    "places": "Viaggi e luoghi",
    "search": "Risultati della ricerca",
    "symbols": "Simboli"
  },
  "skins": {
    "choose": "Scegli tono della pelle predefinito",
    "1": "Predefinito",
    "2": "Chiaro",
    "3": "Medio-chiaro",
    "4": "Medio",
    "5": "Medio-scuro",
    "6": "Scuro"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/ja.json
================================================
{
  "search": "検索",
  "search_no_results_1": "残念!",
  "search_no_results_2": "その絵文字は見つかりませんでした",
  "pick": "絵文字を選択...",
  "add_custom": "絵文字を追加する",
  "categories": {
    "activity": "アクティビティ",
    "custom": "カスタム",
    "flags": "旗",
    "foods": "フード&ドリンク",
    "frequent": "よく使う絵文字",
    "nature": "動物&自然",
    "objects": "オブジェクト",
    "people": "スマイリー&人",
    "places": "トラベル&場所",
    "search": "検索結果",
    "symbols": "記号"
  },
  "skins": {
    "choose": "デフォルトの肌の色を選択する",
    "1": "標準",
    "2": "明るい肌色",
    "3": "やや明るい肌色",
    "4": "肌色",
    "5": "やや濃い肌色",
    "6": "濃い肌色"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/ko.json
================================================
{
  "search": "검색",
  "search_no_results_1": "어머나!",
  "search_no_results_2": "결과를 찾을 수 없어요",
  "pick": "이모지 선택하기",
  "add_custom": "이모지 추가하기",
  "categories": {
    "activity": "활동",
    "custom": "커스텀",
    "flags": "깃발",
    "foods": "음식 및 음료",
    "frequent": "자주 사용하는 항목",
    "nature": "동물 및 자연",
    "objects": "사물",
    "people": "스마일리 및 사람",
    "places": "여행 및 장소",
    "search": "검색 결과",
    "symbols": "기호"
  },
  "skins": {
    "choose": "기준 피부색 선택하기",
    "1": "표준",
    "2": "밝은 피부색",
    "3": "약간 밝은 피부색",
    "4": "중간 피부색",
    "5": "약간 어두운 피부색",
    "6": "어두운 피부색"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/nl.json
================================================
{
  "search": "Zoek",
  "search_no_results_1": "Mislukt!",
  "search_no_results_2": "Die emoji werd niet gevonden",
  "pick": "Kies een emoji…",
  "add_custom": "Voeg eigen emoji toe",
  "categories": {
    "activity": "Activiteit",
    "custom": "Eigen",
    "flags": "Vlaggen",
    "foods": "Eten & Drinken",
    "frequent": "Vaak gebruikt",
    "nature": "Dieren & Natuur",
    "objects": "Voorwerpen",
    "people": "Smileys & Mensen",
    "places": "Reizen & Plaatsen",
    "search": "Zoek resultaten",
    "symbols": "Symbolen"
  },
  "skins": {
    "choose": "Kies standaard huidskleur",
    "1": "Standaard",
    "2": "Licht",
    "3": "Medium-Licht",
    "4": "Medium",
    "5": "Medium-Donker",
    "6": "Donker"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/pl.json
================================================
{
  "search": "Szukaj",
  "search_no_results_1": "O nie!",
  "search_no_results_2": "Nie znaleziono emoji",
  "pick": "Wybierz emoji",
  "add_custom": "Dodaj niestandardowe emoji",
  "categories": {
    "activity": "Aktywność",
    "custom": "Niestandardowe",
    "flags": "Flagi",
    "foods": "Żywność i napoje",
    "frequent": "Często używane",
    "nature": "Zwierzęta i natura",
    "objects": "Obiekty",
    "people": "Buźki i Osoby",
    "places": "Podróże i miejsca",
    "search": "Wyniki wyszukiwania",
    "symbols": "Symbole"
  },
  "skins": {
    "choose": "Wybierz domyślny odcień skóry",
    "1": "Domyślny",
    "2": "Jasny",
    "3": "Średnio-jasny",
    "4": "Średni",
    "5": "Średnio-ciemny",
    "6": "Ciemny"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/pt.json
================================================
{
  "search": "Procurar",
  "search_no_results_1": "Oh não!",
  "search_no_results_2": "Esse emoji não foi encontrado",
  "pick": "Escolha um emoji...",
  "add_custom": "Adicione um emoji customizado",
  "categories": {
    "activity": "Atividade",
    "custom": "Customizado",
    "flags": "Bandeiras",
    "foods": "Comidas & Bebidas",
    "frequent": "Usados recentemente",
    "nature": "Animais & Natureza",
    "objects": "Objetos",
    "people": "Carinhas & Pessoas",
    "places": "Viagens & Lugares",
    "search": "Resultados encontrados",
    "symbols": "Símbolos"
  },
  "skins": {
    "choose": "Escolha a cor de pele padrão",
    "1": "Padrão",
    "2": "Clara",
    "3": "Morena-Clara",
    "4": "Morena",
    "5": "Morena-Escura",
    "6": "Escura"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/ru.json
================================================
{
  "search": "Поиск",
  "search_no_results_1": "О нет!",
  "search_no_results_2": "Эмодзи не найден",
  "pick": "Выберите эмодзи…",
  "add_custom": "Добавить свой эмодзи",
  "categories": {
    "activity": "Активности",
    "custom": "Свои",
    "flags": "Флаги",
    "foods": "Еда и напитки",
    "frequent": "Часто используемые",
    "nature": "Животные и природа",
    "objects": "Предметы",
    "people": "Эмоции и люди",
    "places": "Путешествия и места",
    "search": "Результаты поиска",
    "symbols": "Символы"
  },
  "skins": {
    "choose": "Выберите цвет кожи по умолчанию",
    "1": "По умолчанию",
    "2": "Светлый",
    "3": "Средне-светлый",
    "4": "Средний",
    "5": "Средне-тёмный",
    "6": "Тёмный"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/sa.json
================================================
{
  "search": "अन्वेषण",
  "search_no_results_1": "अहो न!",
  "search_no_results_2": "भावः चित्रम् न प्राप्तम्",
  "pick": "एकं भावः चित्रम् चिनोतु...",
  "add_custom": "आचारः भावः चित्रम् योजयन्तु",
  "categories": {
    "activity": "गतिविधि",
    "custom": "आचारः",
    "flags": "ध्वजाः",
    "foods": "भोजन एवं पेय",
    "frequent": "बहुधा प्रयुक्तम्",
    "nature": "पशवः प्रकृतिश्च",
    "objects": "विषयाः",
    "people": "स्मितं तथा जनाः",
    "places": "यात्रां स्थानानि च",
    "search": "अन्वेषणस्य परिणाम:",
    "symbols": "प्रतीकाः"
  },
  "skins": {
    "choose": "पूर्वनिर्धारितं रूपस्वरं चिनोतु",
    "1": "पूर्वनिर्धारितं",
    "2": "मृदु",
    "3": "मध्यम-मृदु",
    "4": "मध्यम",
    "5": "मध्यम-तिमिर",
    "6": "तिमिर"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/tr.json
================================================
{
  "search": "Arama",
  "search_no_results_1": "Oh hayır!",
  "search_no_results_2": "Bu emoji bulunamadı",
  "pick": "Bir emoji seçin…",
  "add_custom": "Özel emoji ekle",
  "categories": {
    "activity": "Aktivite",
    "custom": "Özel",
    "flags": "Bayraklar",
    "foods": "Yiyecek & İçecek",
    "frequent": "Sık kullanılanlar",
    "nature": "Hayvanlar & Doğa",
    "objects": "Nesneler",
    "people": "Suratlar & İnsanlar",
    "places": "Seyahat & Yerler",
    "search": "Arama sonuçları",
    "symbols": "Semboller"
  },
  "skins": {
    "choose": "Varsayılan cilt tonunu seçiniz",
    "1": "Normal",
    "2": "Açık",
    "3": "Orta Açık",
    "4": "Orta",
    "5": "Orta Koyu",
    "6": "Koyu"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/uk.json
================================================
{
  "search": "Пошук",
  "search_no_results_1": "О ні!",
  "search_no_results_2": "Не вдалося знайти це емодзі",
  "pick": "Виберіть емодзі…",
  "add_custom": "Додайте власні емодзі",
  "categories": {
    "activity": "Діяльність",
    "custom": "Кастомні",
    "flags": "Флаги",
    "foods": "Їжа та напої",
    "frequent": "Часто використовується",
    "nature": "Тварини і природа",
    "objects": "Об'єкти",
    "people": "Смайли та люди",
    "places": "Подорожі та місця",
    "search": "Результати пошуку",
    "symbols": "Символи"
  },
  "skins": {
    "choose": "Виберіть колір шкіри за замовчуванням",
    "1": "За замовчуванням",
    "2": "Світла",
    "3": "Середньо-світла",
    "4": "Середня",
    "5": "Середньо-темна",
    "6": "Темна"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/vi.json
================================================
{
  "search": "Tìm kiếm",
  "search_no_results_1": "Ôi không!",
  "search_no_results_2": "Không thể tìm thấy biểu tượng cảm xúc",
  "pick": "Chọn biểu tượng cảm xúc..",
  "add_custom": "Thêm biểu tượng cảm xúc",
  "categories": {
    "activity": "Hoạt động",
    "custom": "Chỉnh sửa",
    "flags": "Cờ",
    "foods": "Đồ Ăn",
    "frequent": "Dùng thường xuyên",
    "nature": "Thiên nhiên",
    "objects": "Dụng cụ",
    "people": "Con người",
    "places": "Địa điểm",
    "search": "Tìm kiếm",
    "symbols": "Ký hiệu"
  },
  "skins": {
    "choose": "Chọn tông mặc định",
    "1": "Mặc định",
    "2": "Sáng",
    "3": "Trung bình sáng",
    "4": "Trung bình",
    "5": "Trung bình tối",
    "6": "Tối"
  }
}


================================================
FILE: packages/emoji-mart-data/i18n/zh.json
================================================
{
  "search": "搜索",
  "search_no_results_1": "哦不!",
  "search_no_results_2": "没有找到相关表情",
  "pick": "选择一个表情…",
  "add_custom": "添加自定义表情",
  "categories": {
    "activity": "活动",
    "custom": "自定义",
    "flags": "旗帜",
    "foods": "食物与饮品",
    "frequent": "最近使用",
    "nature": "动物与自然",
    "objects": "物品",
    "people": "表情与角色",
    "places": "旅行与景点",
    "search": "搜索结果",
    "symbols": "符号"
  },
  "skins": {
    "choose": "选择默认肤色",
    "1": "默认",
    "2": "白色",
    "3": "偏白",
    "4": "中等",
    "5": "偏黑",
    "6": "黑色"
  }
}


================================================
FILE: packages/emoji-mart-data/index.d.ts
================================================
export interface EmojiMartData {
  categories: Category[]
  emojis: { [key: string]: Emoji }
  aliases: { [key: string]: string }
  sheet: Sheet
}

export interface Category {
  id: string
  emojis: string[]
}

export interface Emoji {
  id: string
  name: string
  keywords: string[]
  skins: Skin[]
  version: number
  emoticons?: string[]
}

export interface Skin {
  unified: string
  native: string
  x?: number
  y?: number
}

export interface Sheet {
  cols: number
  rows: number
}


================================================
FILE: packages/emoji-mart-data/package.json
================================================
{
  "name": "@emoji-mart/data",
  "version": "1.2.1",
  "description": "Data for Emoji Mart; the emoji picker for the web.",
  "license": "MIT",
  "homepage": "https://missiveapp.com/open/emoji-mart",
  "repository": {
    "type": "git",
    "url": "https://github.com/missive/emoji-mart",
    "directory": "packages/emoji-mart-data"
  },
  "main": "sets/15/native.json",
  "types": "index.d.ts",
  "scripts": {
    "build": "node ./build.js"
  },
  "sideEffects": false,
  "devDependencies": {
    "emoji-datasource": "15.0.1",
    "emojilib": "3.0.10",
    "inflection": "2.0.1",
    "unicode-emoji-json": "0.4.0"
  },
  "files": [
    "/i18n",
    "/sets",
    "index.d.ts",
    "LICENSE"
  ]
}


================================================
FILE: packages/emoji-mart-data/sets/1/all.json
================================================
{"categories":[{"id":"people","emojis":["grinning","smiley","smile","grin","laughing","sweat_smile","joy","slightly_smiling_face","upside_down_face","wink","blush","innocent","heart_eyes","kissing_heart","kissing","relaxed","kissing_closed_eyes","kissing_smiling_eyes","yum","stuck_out_tongue","stuck_out_tongue_winking_eye","stuck_out_tongue_closed_eyes","money_mouth_face","hugging_face","thinking_face","zipper_mouth_face","neutral_face","expressionless","no_mouth","smirk","unamused","face_with_rolling_eyes","grimacing","relieved","pensive","sleepy","sleeping","mask","face_with_thermometer","face_with_head_bandage","dizzy_face","sunglasses","nerd_face","confused","worried","slightly_frowning_face","white_frowning_face","open_mouth","hushed","astonished","flushed","frowning","anguished","fearful","cold_sweat","disappointed_relieved","cry","sob","scream","confounded","persevere","disappointed","sweat","weary","tired_face","triumph","rage","angry","smiling_imp","imp","skull","skull_and_crossbones","hankey","japanese_ogre","japanese_goblin","ghost","alien","space_invader","robot_face","smiley_cat","smile_cat","joy_cat","heart_eyes_cat","smirk_cat","kissing_cat","scream_cat","crying_cat_face","pouting_cat","see_no_evil","hear_no_evil","speak_no_evil","love_letter","cupid","gift_heart","sparkling_heart","heartpulse","heartbeat","revolving_hearts","two_hearts","heart_decoration","heavy_heart_exclamation_mark_ornament","broken_heart","heart","yellow_heart","green_heart","blue_heart","purple_heart","kiss","100","anger","boom","dizzy","sweat_drops","dash","wave","raised_hand_with_fingers_splayed","hand","spock-hand","ok_hand","v","the_horns","point_left","point_right","point_up_2","middle_finger","point_down","point_up","+1","-1","fist","facepunch","clap","raised_hands","open_hands","pray","writing_hand","nail_care","muscle","ear","nose","eyes","eye","tongue","lips","baby","boy","girl","person_with_blond_hair","man","woman","older_man","older_woman","person_frowning","person_with_pouting_face","no_good","ok_woman","information_desk_person","raising_hand","bow","cop","sleuth_or_spy","guardsman","construction_worker","princess","man_with_turban","man_with_gua_pi_mao","bride_with_veil","angel","santa","massage","haircut","walking","runner","dancer","man_in_business_suit_levitating","dancers","horse_racing","skier","snowboarder","golfer","surfer","rowboat","swimmer","person_with_ball","weight_lifter","bicyclist","mountain_bicyclist","bath","sleeping_accommodation","two_women_holding_hands","man_and_woman_holding_hands","two_men_holding_hands","couplekiss","couple_with_heart","family","speaking_head_in_silhouette","bust_in_silhouette","busts_in_silhouette","footprints","hole","speech_balloon","right_anger_bubble","thought_balloon","zzz"]},{"id":"nature","emojis":["monkey_face","monkey","dog","dog2","poodle","wolf","cat","cat2","lion_face","tiger","tiger2","leopard","horse","racehorse","unicorn_face","cow","ox","water_buffalo","cow2","pig","pig2","boar","pig_nose","ram","sheep","goat","dromedary_camel","camel","elephant","mouse","mouse2","rat","hamster","rabbit","rabbit2","chipmunk","bear","koala","panda_face","feet","turkey","chicken","rooster","hatching_chick","baby_chick","hatched_chick","bird","penguin","dove_of_peace","frog","crocodile","turtle","snake","dragon_face","dragon","whale","whale2","dolphin","fish","tropical_fish","blowfish","octopus","shell","snail","bug","ant","bee","ladybug","spider","spider_web","scorpion","bouquet","cherry_blossom","white_flower","rosette","rose","hibiscus","sunflower","blossom","tulip","seedling","evergreen_tree","deciduous_tree","palm_tree","cactus","ear_of_rice","herb","shamrock","four_leaf_clover","maple_leaf","fallen_leaf","leaves","mushroom"]},{"id":"foods","emojis":["grapes","melon","watermelon","tangerine","lemon","banana","pineapple","apple","green_apple","pear","peach","cherries","strawberry","tomato","eggplant","corn","hot_pepper","chestnut","bread","cheese_wedge","meat_on_bone","poultry_leg","hamburger","fries","pizza","hotdog","taco","burrito","fried_egg","stew","popcorn","bento","rice_cracker","rice_ball","rice","curry","ramen","spaghetti","sweet_potato","oden","sushi","fried_shrimp","fish_cake","dango","crab","icecream","shaved_ice","ice_cream","doughnut","cookie","birthday","cake","chocolate_bar","candy","lollipop","custard","honey_pot","baby_bottle","coffee","tea","sake","champagne","wine_glass","cocktail","tropical_drink","beer","beers","knife_fork_plate","fork_and_knife","hocho","amphora"]},{"id":"activity","emojis":["jack_o_lantern","christmas_tree","fireworks","sparkler","sparkles","balloon","tada","confetti_ball","tanabata_tree","bamboo","dolls","flags","wind_chime","rice_scene","ribbon","gift","reminder_ribbon","admission_tickets","ticket","medal","trophy","sports_medal","soccer","baseball","basketball","volleyball","football","rugby_football","tennis","bowling","cricket_bat_and_ball","field_hockey_stick_and_ball","ice_hockey_stick_and_puck","table_tennis_paddle_and_ball","badminton_racquet_and_shuttlecock","golf","ice_skate","fishing_pole_and_fish","running_shirt_with_sash","ski","dart","gun","8ball","crystal_ball","video_game","joystick","slot_machine","game_die","spades","hearts","diamonds","clubs","black_joker","mahjong","flower_playing_cards","performing_arts","frame_with_picture","art"]},{"id":"places","emojis":["earth_africa","earth_americas","earth_asia","globe_with_meridians","world_map","japan","snow_capped_mountain","mountain","volcano","mount_fuji","camping","beach_with_umbrella","desert","desert_island","national_park","stadium","classical_building","building_construction","house_buildings","derelict_house_building","house","house_with_garden","office","post_office","european_post_office","hospital","bank","hotel","love_hotel","convenience_store","school","department_store","factory","japanese_castle","european_castle","wedding","tokyo_tower","statue_of_liberty","church","mosque","synagogue","shinto_shrine","kaaba","fountain","tent","foggy","night_with_stars","cityscape","sunrise_over_mountains","sunrise","city_sunset","city_sunrise","bridge_at_night","hotsprings","carousel_horse","ferris_wheel","roller_coaster","barber","circus_tent","steam_locomotive","railway_car","bullettrain_side","bullettrain_front","train2","metro","light_rail","station","tram","monorail","mountain_railway","train","bus","oncoming_bus","trolleybus","minibus","ambulance","fire_engine","police_car","oncoming_police_car","taxi","oncoming_taxi","car","oncoming_automobile","blue_car","truck","articulated_lorry","tractor","racing_car","racing_motorcycle","bike","busstop","motorway","railway_track","oil_drum","fuelpump","rotating_light","traffic_light","vertical_traffic_light","construction","anchor","boat","speedboat","passenger_ship","ferry","motor_boat","ship","airplane","small_airplane","airplane_departure","airplane_arriving","seat","helicopter","suspension_railway","mountain_cableway","aerial_tramway","satellite","rocket","bellhop_bell","hourglass","hourglass_flowing_sand","watch","alarm_clock","stopwatch","timer_clock","mantelpiece_clock","clock12","clock1230","clock1","clock130","clock2","clock230","clock3","clock330","clock4","clock430","clock5","clock530","clock6","clock630","clock7","clock730","clock8","clock830","clock9","clock930","clock10","clock1030","clock11","clock1130","new_moon","waxing_crescent_moon","first_quarter_moon","moon","full_moon","waning_gibbous_moon","last_quarter_moon","waning_crescent_moon","crescent_moon","new_moon_with_face","first_quarter_moon_with_face","last_quarter_moon_with_face","thermometer","sunny","full_moon_with_face","sun_with_face","star","star2","stars","milky_way","cloud","partly_sunny","thunder_cloud_and_rain","mostly_sunny","barely_sunny","partly_sunny_rain","rain_cloud","snow_cloud","lightning","tornado","fog","wind_blowing_face","cyclone","rainbow","closed_umbrella","umbrella","umbrella_with_rain_drops","umbrella_on_ground","zap","snowflake","snowman","snowman_without_snow","comet","fire","droplet","ocean"]},{"id":"objects","emojis":["eyeglasses","dark_sunglasses","necktie","shirt","jeans","dress","kimono","bikini","womans_clothes","purse","handbag","pouch","shopping_bags","school_satchel","mans_shoe","athletic_shoe","high_heel","sandal","boot","crown","womans_hat","tophat","mortar_board","helmet_with_white_cross","prayer_beads","lipstick","ring","gem","mute","speaker","sound","loud_sound","loudspeaker","mega","postal_horn","bell","no_bell","musical_score","musical_note","notes","studio_microphone","level_slider","control_knobs","microphone","headphones","radio","saxophone","guitar","musical_keyboard","trumpet","violin","iphone","calling","phone","telephone_receiver","pager","fax","battery","electric_plug","computer","desktop_computer","printer","keyboard","three_button_mouse","trackball","minidisc","floppy_disk","cd","dvd","movie_camera","film_frames","film_projector","clapper","tv","camera","camera_with_flash","video_camera","vhs","mag","mag_right","candle","bulb","flashlight","izakaya_lantern","notebook_with_decorative_cover","closed_book","book","green_book","blue_book","orange_book","books","notebook","ledger","page_with_curl","scroll","page_facing_up","newspaper","rolled_up_newspaper","bookmark_tabs","bookmark","label","moneybag","yen","dollar","euro","pound","money_with_wings","credit_card","chart","email","e-mail","incoming_envelope","envelope_with_arrow","outbox_tray","inbox_tray","package","mailbox","mailbox_closed","mailbox_with_mail","mailbox_with_no_mail","postbox","ballot_box_with_ballot","pencil2","black_nib","lower_left_fountain_pen","lower_left_ballpoint_pen","lower_left_paintbrush","lower_left_crayon","memo","briefcase","file_folder","open_file_folder","card_index_dividers","date","calendar","spiral_note_pad","spiral_calendar_pad","card_index","chart_with_upwards_trend","chart_with_downwards_trend","bar_chart","clipboard","pushpin","round_pushpin","paperclip","linked_paperclips","straight_ruler","triangular_ruler","scissors","card_file_box","file_cabinet","wastebasket","lock","unlock","lock_with_ink_pen","closed_lock_with_key","key","old_key","hammer","pick","hammer_and_pick","hammer_and_wrench","dagger_knife","crossed_swords","bomb","bow_and_arrow","shield","wrench","nut_and_bolt","gear","compression","scales","link","chains","alembic","microscope","telescope","satellite_antenna","syringe","pill","door","bed","couch_and_lamp","toilet","shower","bathtub","smoking","coffin","funeral_urn","moyai"]},{"id":"symbols","emojis":["atm","put_litter_in_its_place","potable_water","wheelchair","mens","womens","restroom","baby_symbol","wc","passport_control","customs","baggage_claim","left_luggage","warning","children_crossing","no_entry","no_entry_sign","no_bicycles","no_smoking","do_not_litter","non-potable_water","no_pedestrians","no_mobile_phones","underage","radioactive_sign","biohazard_sign","arrow_up","arrow_upper_right","arrow_right","arrow_lower_right","arrow_down","arrow_lower_left","arrow_left","arrow_upper_left","arrow_up_down","left_right_arrow","leftwards_arrow_with_hook","arrow_right_hook","arrow_heading_up","arrow_heading_down","arrows_clockwise","arrows_counterclockwise","back","end","on","soon","top","place_of_worship","atom_symbol","om_symbol","star_of_david","wheel_of_dharma","yin_yang","latin_cross","orthodox_cross","star_and_crescent","peace_symbol","menorah_with_nine_branches","six_pointed_star","aries","taurus","gemini","cancer","leo","virgo","libra","scorpius","sagittarius","capricorn","aquarius","pisces","ophiuchus","twisted_rightwards_arrows","repeat","repeat_one","arrow_forward","fast_forward","black_right_pointing_double_triangle_with_vertical_bar","black_right_pointing_triangle_with_double_vertical_bar","arrow_backward","rewind","black_left_pointing_double_triangle_with_vertical_bar","arrow_up_small","arrow_double_up","arrow_down_small","arrow_double_down","double_vertical_bar","black_square_for_stop","black_circle_for_record","eject","cinema","low_brightness","high_brightness","signal_strength","vibration_mode","mobile_phone_off","heavy_multiplication_x","heavy_plus_sign","heavy_minus_sign","heavy_division_sign","bangbang","interrobang","question","grey_question","grey_exclamation","exclamation","wavy_dash","currency_exchange","heavy_dollar_sign","recycle","fleur_de_lis","trident","name_badge","beginner","o","white_check_mark","ballot_box_with_check","heavy_check_mark","x","negative_squared_cross_mark","curly_loop","loop","part_alternation_mark","eight_spoked_asterisk","eight_pointed_black_star","sparkle","copyright","registered","tm","hash","zero","one","two","three","four","five","six","seven","eight","nine","keycap_ten","capital_abcd","abcd","1234","symbols","abc","a","ab","b","cl","cool","free","information_source","id","m","new","ng","o2","ok","parking","sos","up","vs","koko","sa","u6708","u6709","u6307","ideograph_advantage","u5272","u7121","u7981","accept","u7533","u5408","u7a7a","congratulations","secret","u55b6","u6e80","red_circle","large_blue_circle","black_circle","white_circle","black_large_square","white_large_square","black_medium_square","white_medium_square","black_medium_small_square","white_medium_small_square","black_small_square","white_small_square","large_orange_diamond","large_blue_diamond","small_orange_diamond","small_blue_diamond","small_red_triangle","small_red_triangle_down","diamond_shape_with_a_dot_inside","radio_button","white_square_button","black_square_button"]},{"id":"flags","emojis":["checkered_flag","cn","crossed_flags","de","es","fr","gb","it","jp","kr","ru","triangular_flag_on_post","us","waving_black_flag","waving_white_flag"]}],"emojis":{"100":{"id":"100","name":"Hundred Points","keywords":["100","score","perfect","numbers","century","exam","quiz","test","pass"],"skins":[{"unified":"1f4af","native":"💯","x":28,"y":7}],"version":1},"1234":{"id":"1234","name":"Input Numbers","keywords":["1234","blue","square","1","2","3","4"],"skins":[{"unified":"1f522","native":"🔢","x":29,"y":60}],"version":1},"grinning":{"id":"grinning","name":"Grinning Face","emoticons":[":D"],"keywords":["smile","happy","joy",":D","grin"],"skins":[{"unified":"1f600","native":"😀","x":32,"y":21}],"version":1},"smiley":{"id":"smiley","name":"Grinning Face with Big Eyes","emoticons":[":)","=)","=-)"],"keywords":["smiley","happy","joy","haha",":D",":)","smile","funny"],"skins":[{"unified":"1f603","native":"😃","x":32,"y":24}],"version":1},"smile":{"id":"smile","name":"Grinning Face with Smiling Eyes","emoticons":[":)","C:","c:",":D",":-D"],"keywords":["smile","happy","joy","funny","haha","laugh","like",":D",":)"],"skins":[{"unified":"1f604","native":"😄","x":32,"y":25}],"version":1},"grin":{"id":"grin","name":"Beaming Face with Smiling Eyes","keywords":["grin","happy","smile","joy","kawaii"],"skins":[{"unified":"1f601","native":"😁","x":32,"y":22}],"version":1},"laughing":{"id":"laughing","name":"Grinning Squinting Face","emoticons":[":>",":->"],"keywords":["laughing","satisfied","happy","joy","lol","haha","glad","XD","laugh"],"skins":[{"unified":"1f606","native":"😆","x":32,"y":27}],"version":1},"sweat_smile":{"id":"sweat_smile","name":"Grinning Face with Sweat","keywords":["smile","hot","happy","laugh","relief"],"skins":[{"unified":"1f605","native":"😅","x":32,"y":26}],"version":1},"joy":{"id":"joy","name":"Face with Tears of Joy","keywords":["cry","weep","happy","happytears","haha"],"skins":[{"unified":"1f602","native":"😂","x":32,"y":23}],"version":1},"slightly_smiling_face":{"id":"slightly_smiling_face","name":"Slightly Smiling Face","emoticons":[":)","(:",":-)"],"keywords":["smile"],"skins":[{"unified":"1f642","native":"🙂","x":33,"y":29}],"version":1},"upside_down_face":{"id":"upside_down_face","name":"Upside-Down Face","keywords":["upside","down","flipped","silly","smile"],"skins":[{"unified":"1f643","native":"🙃","x":33,"y":30}],"version":1},"wink":{"id":"wink","name":"Winking Face","emoticons":[";)",";-)"],"keywords":["wink","happy","mischievous","secret",";)","smile","eye"],"skins":[{"unified":"1f609","native":"😉","x":32,"y":30}],"version":1},"blush":{"id":"blush","name":"Smiling Face with Smiling Eyes","emoticons":[":)"],"keywords":["blush","smile","happy","flushed","crush","embarrassed","shy","joy"],"skins":[{"unified":"1f60a","native":"😊","x":32,"y":31}],"version":1},"innocent":{"id":"innocent","name":"Smiling Face with Halo","keywords":["innocent","angel","heaven"],"skins":[{"unified":"1f607","native":"😇","x":32,"y":28}],"version":1},"heart_eyes":{"id":"heart_eyes","name":"Smiling Face with Heart-Eyes","keywords":["heart","eyes","love","like","affection","valentines","infatuation","crush"],"skins":[{"unified":"1f60d","native":"😍","x":32,"y":34}],"version":1},"kissing_heart":{"id":"kissing_heart","name":"Face Blowing a Kiss","emoticons":[":*",":-*"],"keywords":["kissing","heart","love","like","affection","valentines","infatuation"],"skins":[{"unified":"1f618","native":"😘","x":32,"y":45}],"version":1},"kissing":{"id":"kissing","name":"Kissing Face","keywords":["love","like","3","valentines","infatuation","kiss"],"skins":[{"unified":"1f617","native":"😗","x":32,"y":44}],"version":1},"relaxed":{"id":"relaxed","name":"Smiling Face","keywords":["relaxed","blush","massage","happiness"],"skins":[{"unified":"263a-fe0f","native":"☺️","x":57,"y":35}],"version":1},"kissing_closed_eyes":{"id":"kissing_closed_eyes","name":"Kissing Face with Closed Eyes","keywords":["love","like","affection","valentines","infatuation","kiss"],"skins":[{"unified":"1f61a","native":"😚","x":32,"y":47}],"version":1},"kissing_smiling_eyes":{"id":"kissing_smiling_eyes","name":"Kissing Face with Smiling Eyes","keywords":["affection","valentines","infatuation","kiss"],"skins":[{"unified":"1f619","native":"😙","x":32,"y":46}],"version":1},"yum":{"id":"yum","name":"Face Savoring Food","keywords":["yum","happy","joy","tongue","smile","silly","yummy","nom","delicious","savouring"],"skins":[{"unified":"1f60b","native":"😋","x":32,"y":32}],"version":1},"stuck_out_tongue":{"id":"stuck_out_tongue","name":"Face with Tongue","emoticons":[":p",":-p",":P",":-P",":b",":-b"],"keywords":["stuck","out","prank","childish","playful","mischievous","smile"],"skins":[{"unified":"1f61b","native":"😛","x":32,"y":48}],"version":1},"stuck_out_tongue_winking_eye":{"id":"stuck_out_tongue_winking_eye","name":"Winking Face with Tongue","emoticons":[";p",";-p",";b",";-b",";P",";-P"],"keywords":["stuck","out","eye","prank","childish","playful","mischievous","smile","wink"],"skins":[{"unified":"1f61c","native":"😜","x":32,"y":49}],"version":1},"stuck_out_tongue_closed_eyes":{"id":"stuck_out_tongue_closed_eyes","name":"Squinting Face with Tongue","keywords":["stuck","out","closed","eyes","prank","playful","mischievous","smile"],"skins":[{"unified":"1f61d","native":"😝","x":32,"y":50}],"version":1},"money_mouth_face":{"id":"money_mouth_face","name":"Money-Mouth Face","keywords":["money","mouth","rich","dollar"],"skins":[{"unified":"1f911","native":"🤑","x":39,"y":0}],"version":1},"hugging_face":{"id":"hugging_face","name":"Hugging Face","keywords":["smile","hug"],"skins":[{"unified":"1f917","native":"🤗","x":39,"y":6}],"version":1},"thinking_face":{"id":"thinking_face","name":"Thinking Face","keywords":["hmmm","think","consider"],"skins":[{"unified":"1f914","native":"🤔","x":39,"y":3}],"version":1},"zipper_mouth_face":{"id":"zipper_mouth_face","name":"Zipper-Mouth Face","keywords":["zipper","mouth","sealed","secret"],"skins":[{"unified":"1f910","native":"🤐","x":38,"y":60}],"version":1},"neutral_face":{"id":"neutral_face","name":"Neutral Face","emoticons":[":|",":-|"],"keywords":["indifference","meh",":",""],"skins":[{"unified":"1f610","native":"😐","x":32,"y":37}],"version":1},"expressionless":{"id":"expressionless","name":"Expressionless Face","emoticons":["-_-"],"keywords":["indifferent","-","","meh","deadpan"],"skins":[{"unified":"1f611","native":"😑","x":32,"y":38}],"version":1},"no_mouth":{"id":"no_mouth","name":"Face Without Mouth","keywords":["no","hellokitty"],"skins":[{"unified":"1f636","native":"😶","x":33,"y":17}],"version":1},"smirk":{"id":"smirk","name":"Smirking Face","keywords":["smirk","smile","mean","prank","smug","sarcasm"],"skins":[{"unified":"1f60f","native":"😏","x":32,"y":36}],"version":1},"unamused":{"id":"unamused","name":"Unamused Face","emoticons":[":("],"keywords":["indifference","bored","straight","serious","sarcasm","unimpressed","skeptical","dubious","side","eye"],"skins":[{"unified":"1f612","native":"😒","x":32,"y":39}],"version":1},"face_with_rolling_eyes":{"id":"face_with_rolling_eyes","name":"Face with Rolling Eyes","keywords":["eyeroll","frustrated"],"skins":[{"unified":"1f644","native":"🙄","x":33,"y":31}],"version":1},"grimacing":{"id":"grimacing","name":"Grimacing Face","keywords":["grimace","teeth"],"skins":[{"unified":"1f62c","native":"😬","x":33,"y":4}],"version":1},"relieved":{"id":"relieved","name":"Relieved Face","keywords":["relaxed","phew","massage","happiness"],"skins":[{"unified":"1f60c","native":"😌","x":32,"y":33}],"version":1},"pensive":{"id":"pensive","name":"Pensive Face","keywords":["sad","depressed","upset"],"skins":[{"unified":"1f614","native":"😔","x":32,"y":41}],"version":1},"sleepy":{"id":"sleepy","name":"Sleepy Face","keywords":["tired","rest","nap"],"skins":[{"unified":"1f62a","native":"😪","x":33,"y":2}],"version":1},"sleeping":{"id":"sleeping","name":"Sleeping Face","keywords":["tired","sleepy","night","zzz"],"skins":[{"unified":"1f634","native":"😴","x":33,"y":13}],"version":1},"mask":{"id":"mask","name":"Face with Medical Mask","keywords":["sick","ill","disease","covid"],"skins":[{"unified":"1f637","native":"😷","x":33,"y":18}],"version":1},"face_with_thermometer":{"id":"face_with_thermometer","name":"Face with Thermometer","keywords":["sick","temperature","cold","fever","covid"],"skins":[{"unified":"1f912","native":"🤒","x":39,"y":1}],"version":1},"face_with_head_bandage":{"id":"face_with_head_bandage","name":"Face with Head-Bandage","keywords":["head","bandage","injured","clumsy","hurt"],"skins":[{"unified":"1f915","native":"🤕","x":39,"y":4}],"version":1},"dizzy_face":{"id":"dizzy_face","name":"Dizzy Face","keywords":["spent","unconscious","xox"],"skins":[{"unified":"1f635","native":"😵","x":33,"y":15}],"version":1},"sunglasses":{"id":"sunglasses","name":"Smiling Face with Sunglasses","emoticons":["8)"],"keywords":["cool","smile","summer","beach","sunglass"],"skins":[{"unified":"1f60e","native":"😎","x":32,"y":35}],"version":1},"nerd_face":{"id":"nerd_face","name":"Nerd Face","keywords":["nerdy","geek","dork"],"skins":[{"unified":"1f913","native":"🤓","x":39,"y":2}],"version":1},"confused":{"id":"confused","name":"Confused Face","emoticons":[":\\",":-\\",":/",":-/"],"keywords":["indifference","huh","weird","hmmm",":/"],"skins":[{"unified":"1f615","native":"😕","x":32,"y":42}],"version":1},"worried":{"id":"worried","name":"Worried Face","keywords":["concern","nervous",":("],"skins":[{"unified":"1f61f","native":"😟","x":32,"y":52}],"version":1},"slightly_frowning_face":{"id":"slightly_frowning_face","name":"Slightly Frowning Face","keywords":["disappointed","sad","upset"],"skins":[{"unified":"1f641","native":"🙁","x":33,"y":28}],"version":1},"white_frowning_face":{"id":"white_frowning_face","name":"Frowning Face","keywords":["white","sad","upset","frown"],"skins":[{"unified":"2639-fe0f","native":"☹️","x":57,"y":34}],"version":1},"open_mouth":{"id":"open_mouth","name":"Face with Open Mouth","emoticons":[":o",":-o",":O",":-O"],"keywords":["surprise","impressed","wow","whoa",":O"],"skins":[{"unified":"1f62e","native":"😮","x":33,"y":7}],"version":1},"hushed":{"id":"hushed","name":"Hushed Face","keywords":["woo","shh"],"skins":[{"unified":"1f62f","native":"😯","x":33,"y":8}],"version":1},"astonished":{"id":"astonished","name":"Astonished Face","keywords":["xox","surprised","poisoned"],"skins":[{"unified":"1f632","native":"😲","x":33,"y":11}],"version":1},"flushed":{"id":"flushed","name":"Flushed Face","keywords":["blush","shy","flattered"],"skins":[{"unified":"1f633","native":"😳","x":33,"y":12}],"version":1},"frowning":{"id":"frowning","name":"Frowning Face with Open Mouth","keywords":["aw","what"],"skins":[{"unified":"1f626","native":"😦","x":32,"y":59}],"version":1},"anguished":{"id":"anguished","name":"Anguished Face","emoticons":["D:"],"keywords":["stunned","nervous"],"skins":[{"unified":"1f627","native":"😧","x":32,"y":60}],"version":1},"fearful":{"id":"fearful","name":"Fearful Face","keywords":["scared","terrified","nervous"],"skins":[{"unified":"1f628","native":"😨","x":33,"y":0}],"version":1},"cold_sweat":{"id":"cold_sweat","name":"Anxious Face with Sweat","keywords":["cold","nervous"],"skins":[{"unified":"1f630","native":"😰","x":33,"y":9}],"version":1},"disappointed_relieved":{"id":"disappointed_relieved","name":"Sad but Relieved Face","keywords":["disappointed","phew","sweat","nervous"],"skins":[{"unified":"1f625","native":"😥","x":32,"y":58}],"version":1},"cry":{"id":"cry","name":"Crying Face","emoticons":[":'("],"keywords":["cry","tears","sad","depressed","upset",":'("],"skins":[{"unified":"1f622","native":"😢","x":32,"y":55}],"version":1},"sob":{"id":"sob","name":"Loudly Crying Face","emoticons":[":'("],"keywords":["sob","cry","tears","sad","upset","depressed"],"skins":[{"unified":"1f62d","native":"😭","x":33,"y":5}],"version":1},"scream":{"id":"scream","name":"Face Screaming in Fear","keywords":["scream","munch","scared","omg"],"skins":[{"unified":"1f631","native":"😱","x":33,"y":10}],"version":1},"confounded":{"id":"confounded","name":"Confounded Face","keywords":["confused","sick","unwell","oops",":S"],"skins":[{"unified":"1f616","native":"😖","x":32,"y":43}],"version":1},"persevere":{"id":"persevere","name":"Persevering Face","keywords":["persevere","sick","no","upset","oops"],"skins":[{"unified":"1f623","native":"😣","x":32,"y":56}],"version":1},"disappointed":{"id":"disappointed","name":"Disappointed Face","emoticons":["):",":(",":-("],"keywords":["sad","upset","depressed",":("],"skins":[{"unified":"1f61e","native":"😞","x":32,"y":51}],"version":1},"sweat":{"id":"sweat","name":"Face with Cold Sweat","keywords":["downcast","hot","sad","tired","exercise"],"skins":[{"unified":"1f613","native":"😓","x":32,"y":40}],"version":1},"weary":{"id":"weary","name":"Weary Face","keywords":["tired","sleepy","sad","frustrated","upset"],"skins":[{"unified":"1f629","native":"😩","x":33,"y":1}],"version":1},"tired_face":{"id":"tired_face","name":"Tired Face","keywords":["sick","whine","upset","frustrated"],"skins":[{"unified":"1f62b","native":"😫","x":33,"y":3}],"version":1},"triumph":{"id":"triumph","name":"Face with Look of Triumph","keywords":["steam","from","nose","gas","phew","proud","pride"],"skins":[{"unified":"1f624","native":"😤","x":32,"y":57}],"version":1},"rage":{"id":"rage","name":"Pouting Face","keywords":["rage","angry","mad","hate","despise"],"skins":[{"unified":"1f621","native":"😡","x":32,"y":54}],"version":1},"angry":{"id":"angry","name":"Angry Face","emoticons":[">:(",">:-("],"keywords":["mad","annoyed","frustrated"],"skins":[{"unified":"1f620","native":"😠","x":32,"y":53}],"version":1},"smiling_imp":{"id":"smiling_imp","name":"Smiling Face with Horns","keywords":["imp","devil"],"skins":[{"unified":"1f608","native":"😈","x":32,"y":29}],"version":1},"imp":{"id":"imp","name":"Imp","keywords":["angry","face","with","horns","devil"],"skins":[{"unified":"1f47f","native":"👿","x":25,"y":9}],"version":1},"skull":{"id":"skull","name":"Skull","keywords":["dead","skeleton","creepy","death"],"skins":[{"unified":"1f480","native":"💀","x":25,"y":10}],"version":1},"skull_and_crossbones":{"id":"skull_and_crossbones","name":"Skull and Crossbones","keywords":["poison","danger","deadly","scary","death","pirate","evil"],"skins":[{"unified":"2620-fe0f","native":"☠️","x":57,"y":26}],"version":1},"hankey":{"id":"hankey","name":"Pile of Poo","keywords":["hankey","poop","shit","shitface","fail","turd"],"skins":[{"unified":"1f4a9","native":"💩","x":27,"y":57}],"version":1},"japanese_ogre":{"id":"japanese_ogre","name":"Ogre","keywords":["japanese","monster","red","mask","halloween","scary","creepy","devil","demon"],"skins":[{"unified":"1f479","native":"👹","x":24,"y":59}],"version":1},"japanese_goblin":{"id":"japanese_goblin","name":"Goblin","keywords":["japanese","red","evil","mask","monster","scary","creepy"],"skins":[{"unified":"1f47a","native":"👺","x":24,"y":60}],"version":1},"ghost":{"id":"ghost","name":"Ghost","keywords":["halloween","spooky","scary"],"skins":[{"unified":"1f47b","native":"👻","x":25,"y":0}],"version":1},"alien":{"id":"alien","name":"Alien","keywords":["UFO","paul","weird","outer","space"],"skins":[{"unified":"1f47d","native":"👽","x":25,"y":7}],"version":1},"space_invader":{"id":"space_invader","name":"Alien Monster","keywords":["space","invader","game","arcade","play"],"skins":[{"unified":"1f47e","native":"👾","x":25,"y":8}],"version":1},"robot_face":{"id":"robot_face","name":"Robot","keywords":["face","computer","machine","bot"],"skins":[{"unified":"1f916","native":"🤖","x":39,"y":5}],"version":1},"smiley_cat":{"id":"smiley_cat","name":"Grinning Cat","keywords":["smiley","animal","cats","happy","smile"],"skins":[{"unified":"1f63a","native":"😺","x":33,"y":21}],"version":1},"smile_cat":{"id":"smile_cat","name":"Grinning Cat with Smiling Eyes","keywords":["smile","animal","cats"],"skins":[{"unified":"1f638","native":"😸","x":33,"y":19}],"version":1},"joy_cat":{"id":"joy_cat","name":"Cat with Tears of Joy","keywords":["animal","cats","haha","happy"],"skins":[{"unified":"1f639","native":"😹","x":33,"y":20}],"version":1},"heart_eyes_cat":{"id":"heart_eyes_cat","name":"Smiling Cat with Heart-Eyes","keywords":["heart","eyes","animal","love","like","affection","cats","valentines"],"skins":[{"unified":"1f63b","native":"😻","x":33,"y":22}],"version":1},"smirk_cat":{"id":"smirk_cat","name":"Cat with Wry Smile","keywords":["smirk","animal","cats"],"skins":[{"unified":"1f63c","native":"😼","x":33,"y":23}],"version":1},"kissing_cat":{"id":"kissing_cat","name":"Kissing Cat","keywords":["animal","cats","kiss"],"skins":[{"unified":"1f63d","native":"😽","x":33,"y":24}],"version":1},"scream_cat":{"id":"scream_cat","name":"Weary Cat","keywords":["scream","animal","cats","munch","scared"],"skins":[{"unified":"1f640","native":"🙀","x":33,"y":27}],"version":1},"crying_cat_face":{"id":"crying_cat_face","name":"Crying Cat","keywords":["face","animal","tears","weep","sad","cats","upset","cry"],"skins":[{"unified":"1f63f","native":"😿","x":33,"y":26}],"version":1},"pouting_cat":{"id":"pouting_cat","name":"Pouting Cat","keywords":["animal","cats"],"skins":[{"unified":"1f63e","native":"😾","x":33,"y":25}],"version":1},"see_no_evil":{"id":"see_no_evil","name":"See-No-Evil Monkey","keywords":["see","no","evil","animal","nature","haha"],"skins":[{"unified":"1f648","native":"🙈","x":34,"y":25}],"version":1},"hear_no_evil":{"id":"hear_no_evil","name":"Hear-No-Evil Monkey","keywords":["hear","no","evil","animal","nature"],"skins":[{"unified":"1f649","native":"🙉","x":34,"y":26}],"version":1},"speak_no_evil":{"id":"speak_no_evil","name":"Speak-No-Evil Monkey","keywords":["speak","no","evil","animal","nature","omg"],"skins":[{"unified":"1f64a","native":"🙊","x":34,"y":27}],"version":1},"love_letter":{"id":"love_letter","name":"Love Letter","keywords":["email","like","affection","envelope","valentines"],"skins":[{"unified":"1f48c","native":"💌","x":26,"y":39}],"version":1},"cupid":{"id":"cupid","name":"Heart with Arrow","keywords":["cupid","love","like","affection","valentines"],"skins":[{"unified":"1f498","native":"💘","x":27,"y":40}],"version":1},"gift_heart":{"id":"gift_heart","name":"Heart with Ribbon","keywords":["gift","love","valentines"],"skins":[{"unified":"1f49d","native":"💝","x":27,"y":45}],"version":1},"sparkling_heart":{"id":"sparkling_heart","name":"Sparkling Heart","keywords":["love","like","affection","valentines"],"skins":[{"unified":"1f496","native":"💖","x":27,"y":38}],"version":1},"heartpulse":{"id":"heartpulse","name":"Growing Heart","keywords":["heartpulse","like","love","affection","valentines","pink"],"skins":[{"unified":"1f497","native":"💗","x":27,"y":39}],"version":1},"heartbeat":{"id":"heartbeat","name":"Beating Heart","keywords":["heartbeat","love","like","affection","valentines","pink"],"skins":[{"unified":"1f493","native":"💓","x":27,"y":35}],"version":1},"revolving_hearts":{"id":"revolving_hearts","name":"Revolving Hearts","keywords":["love","like","affection","valentines"],"skins":[{"unified":"1f49e","native":"💞","x":27,"y":46}],"version":1},"two_hearts":{"id":"two_hearts","name":"Two Hearts","keywords":["love","like","affection","valentines","heart"],"skins":[{"unified":"1f495","native":"💕","x":27,"y":37}],"version":1},"heart_decoration":{"id":"heart_decoration","name":"Heart Decoration","keywords":["purple","square","love","like"],"skins":[{"unified":"1f49f","native":"💟","x":27,"y":47}],"version":1},"heavy_heart_exclamation_mark_ornament":{"id":"heavy_heart_exclamation_mark_ornament","name":"Heart Exclamation","keywords":["heavy","mark","ornament","decoration","love"],"skins":[{"unified":"2763-fe0f","native":"❣️","x":59,"y":38}],"version":1},"broken_heart":{"id":"broken_heart","name":"Broken Heart","emoticons":["</3"],"keywords":["sad","sorry","break","heartbreak"],"skins":[{"unified":"1f494","native":"💔","x":27,"y":36}],"version":1},"heart":{"id":"heart","name":"Red Heart","emoticons":["<3"],"keywords":["love","like","valentines"],"skins":[{"unified":"2764-fe0f","native":"❤️","x":59,"y":41}],"version":1},"yellow_heart":{"id":"yellow_heart","name":"Yellow Heart","emoticons":["<3"],"keywords":["love","like","affection","valentines"],"skins":[{"unified":"1f49b","native":"💛","x":27,"y":43}],"version":1},"green_heart":{"id":"green_heart","name":"Green Heart","emoticons":["<3"],"keywords":["love","like","affection","valentines"],"skins":[{"unified":"1f49a","native":"💚","x":27,"y":42}],"version":1},"blue_heart":{"id":"blue_heart","name":"Blue Heart","emoticons":["<3"],"keywords":["love","like","affection","valentines"],"skins":[{"unified":"1f499","native":"💙","x":27,"y":41}],"version":1},"purple_heart":{"id":"purple_heart","name":"Purple Heart","emoticons":["<3"],"keywords":["love","like","affection","valentines"],"skins":[{"unified":"1f49c","native":"💜","x":27,"y":44}],"version":1},"kiss":{"id":"kiss","name":"Kiss Mark","keywords":["face","lips","love","like","affection","valentines"],"skins":[{"unified":"1f48b","native":"💋","x":26,"y":38}],"version":1},"anger":{"id":"anger","name":"Anger Symbol","keywords":["angry","mad"],"skins":[{"unified":"1f4a2","native":"💢","x":27,"y":50}],"version":1},"boom":{"id":"boom","name":"Collision","keywords":["boom","bomb","explode","explosion","blown"],"skins":[{"unified":"1f4a5","native":"💥","x":27,"y":53}],"version":1},"dizzy":{"id":"dizzy","name":"Dizzy","keywords":["star","sparkle","shoot","magic"],"skins":[{"unified":"1f4ab","native":"💫","x":28,"y":3}],"version":1},"sweat_drops":{"id":"sweat_drops","name":"Sweat Droplets","keywords":["drops","water","drip","oops"],"skins":[{"unified":"1f4a6","native":"💦","x":27,"y":54}],"version":1},"dash":{"id":"dash","name":"Dash Symbol","keywords":["dashing","away","wind","air","fast","shoo","fart","smoke","puff"],"skins":[{"unified":"1f4a8","native":"💨","x":27,"y":56}],"version":1},"hole":{"id":"hole","name":"Hole","keywords":["embarrassing"],"skins":[{"unified":"1f573-fe0f","native":"🕳️","x":30,"y":59}],"version":1},"speech_balloon":{"id":"speech_balloon","name":"Speech Balloon","keywords":["bubble","words","message","talk","chatting"],"skins":[{"unified":"1f4ac","native":"💬","x":28,"y":4}],"version":1},"right_anger_bubble":{"id":"right_anger_bubble","name":"Right Anger Bubble","keywords":["caption","speech","thinking","mad"],"skins":[{"unified":"1f5ef-fe0f","native":"🗯️","x":32,"y":13}],"version":1},"thought_balloon":{"id":"thought_balloon","name":"Thought Balloon","keywords":["bubble","cloud","speech","thinking","dream"],"skins":[{"unified":"1f4ad","native":"💭","x":28,"y":5}],"version":1},"zzz":{"id":"zzz","name":"Zzz","keywords":["sleepy","tired","dream"],"skins":[{"unified":"1f4a4","native":"💤","x":27,"y":52}],"version":1},"wave":{"id":"wave","name":"Waving Hand","keywords":["wave","hands","gesture","goodbye","solong","farewell","hello","hi","palm"],"skins":[{"unified":"1f44b","native":"👋","x":12,"y":39},{"unified":"1f44b-1f3fb","native":"👋🏻","x":12,"y":40},{"unified":"1f44b-1f3fc","native":"👋🏼","x":12,"y":41},{"unified":"1f44b-1f3fd","native":"👋🏽","x":12,"y":42},{"unified":"1f44b-1f3fe","native":"👋🏾","x":12,"y":43},{"unified":"1f44b-1f3ff","native":"👋🏿","x":12,"y":44}],"version":1},"raised_hand_with_fingers_splayed":{"id":"raised_hand_with_fingers_splayed","name":"Hand with Fingers Splayed","keywords":["raised","palm"],"skins":[{"unified":"1f590-fe0f","native":"🖐️","x":31,"y":38},{"unified":"1f590-1f3fb","native":"🖐🏻","x":31,"y":39},{"unified":"1f590-1f3fc","native":"🖐🏼","x":31,"y":40},{"unified":"1f590-1f3fd","native":"🖐🏽","x":31,"y":41},{"unified":"1f590-1f3fe","native":"🖐🏾","x":31,"y":42},{"unified":"1f590-1f3ff","native":"🖐🏿","x":31,"y":43}],"version":1},"hand":{"id":"hand","name":"Raised Hand","keywords":["fingers","stop","hi
Download .txt
gitextract_eixd0uz8/

├── .editorconfig
├── .github/
│   └── workflows/
│       └── test.yml
├── .gitignore
├── .node-version
├── .npmignore
├── .prettierignore
├── LICENSE
├── README.md
├── jest/
│   └── esm-transformer.js
├── jest.config.js
├── package.json
├── packages/
│   ├── emoji-mart/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── package.json
│   │   └── src/
│   │       ├── __tests__/
│   │       │   ├── config.test.js
│   │       │   └── utils.test.js
│   │       ├── browser.js
│   │       ├── components/
│   │       │   ├── Emoji/
│   │       │   │   ├── Emoji.tsx
│   │       │   │   ├── EmojiElement.jsx
│   │       │   │   ├── EmojiProps.ts
│   │       │   │   └── index.ts
│   │       │   ├── HOCs/
│   │       │   │   ├── PureInlineComponent.ts
│   │       │   │   └── index.ts
│   │       │   ├── HTMLElement/
│   │       │   │   ├── HTMLElement.ts
│   │       │   │   ├── ShadowElement.ts
│   │       │   │   └── index.ts
│   │       │   ├── Navigation/
│   │       │   │   ├── Navigation.tsx
│   │       │   │   └── index.ts
│   │       │   └── Picker/
│   │       │       ├── Picker.tsx
│   │       │       ├── PickerElement.tsx
│   │       │       ├── PickerProps.ts
│   │       │       ├── PickerStyles.scss
│   │       │       └── index.ts
│   │       ├── config.ts
│   │       ├── declaration.d.ts
│   │       ├── helpers/
│   │       │   ├── __tests__/
│   │       │   │   ├── frequently-used.test.js
│   │       │   │   ├── native-support.test.js
│   │       │   │   ├── search-index.test.js
│   │       │   │   └── store.test.js
│   │       │   ├── frequently-used.ts
│   │       │   ├── index.ts
│   │       │   ├── native-support.ts
│   │       │   ├── search-index.ts
│   │       │   └── store.ts
│   │       ├── icons.tsx
│   │       ├── index.ts
│   │       └── utils.ts
│   ├── emoji-mart-data/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── build.js
│   │   ├── i18n/
│   │   │   ├── ar.json
│   │   │   ├── be.json
│   │   │   ├── cs.json
│   │   │   ├── de.json
│   │   │   ├── en.json
│   │   │   ├── es.json
│   │   │   ├── fa.json
│   │   │   ├── fi.json
│   │   │   ├── fr.json
│   │   │   ├── hi.json
│   │   │   ├── it.json
│   │   │   ├── ja.json
│   │   │   ├── ko.json
│   │   │   ├── nl.json
│   │   │   ├── pl.json
│   │   │   ├── pt.json
│   │   │   ├── ru.json
│   │   │   ├── sa.json
│   │   │   ├── tr.json
│   │   │   ├── uk.json
│   │   │   ├── vi.json
│   │   │   └── zh.json
│   │   ├── index.d.ts
│   │   ├── package.json
│   │   └── sets/
│   │       ├── 1/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 11/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 12/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 12.1/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 13/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 13.1/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 14/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 15/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 2/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 3/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       ├── 4/
│   │       │   ├── all.json
│   │       │   ├── apple.json
│   │       │   ├── facebook.json
│   │       │   ├── google.json
│   │       │   ├── native.json
│   │       │   └── twitter.json
│   │       └── 5/
│   │           ├── all.json
│   │           ├── apple.json
│   │           ├── facebook.json
│   │           ├── google.json
│   │           ├── native.json
│   │           └── twitter.json
│   ├── emoji-mart-react/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── package.json
│   │   └── react.tsx
│   └── emoji-mart-website/
│       ├── .posthtmlrc
│       ├── example-categories.html
│       ├── example-custom-font.html
│       ├── example-custom-styles.html
│       ├── example-dynamic-width.html
│       ├── example-emoji-component.html
│       ├── example-headless-search.html
│       ├── example-slack-colors.html
│       ├── examples.html
│       ├── index.html
│       ├── layout.html
│       ├── package.json
│       └── styles.scss
└── tsconfig.json
Download .txt
SYMBOL INDEX (102 symbols across 18 files)

FILE: jest/esm-transformer.js
  method process (line 4) | process(src) {

FILE: packages/emoji-mart-data/build.js
  constant DRY_RUN (line 8) | const DRY_RUN = process.argv.indexOf('--dry') != -1
  constant VERSIONS (line 10) | const VERSIONS = [1, 2, 3, 4, 5, 11, 12, 12.1, 13, 13.1, 14, 15]
  constant SKINS (line 11) | const SKINS = ['1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']
  constant SETS (line 12) | const SETS = ['native', 'apple', 'facebook', 'google', 'twitter']
  constant CATEGORIES (line 13) | const CATEGORIES = [
  constant KEYWORD_SUBSTITUTES (line 25) | const KEYWORD_SUBSTITUTES = {
  function unifiedToNative (line 29) | function unifiedToNative(unified) {
  function buildData (line 36) | function buildData({ set, version } = {}) {

FILE: packages/emoji-mart-data/index.d.ts
  type EmojiMartData (line 1) | interface EmojiMartData {
  type Category (line 8) | interface Category {
  type Emoji (line 13) | interface Emoji {
  type Skin (line 22) | interface Skin {
  type Sheet (line 29) | interface Sheet {

FILE: packages/emoji-mart-react/react.tsx
  function EmojiPicker (line 5) | function EmojiPicker(props) {

FILE: packages/emoji-mart/src/components/Emoji/Emoji.tsx
  function Emoji (line 4) | function Emoji(props) {

FILE: packages/emoji-mart/src/components/Emoji/EmojiElement.jsx
  class EmojiElement (line 8) | class EmojiElement extends HTMLElement {
    method constructor (line 11) | constructor(props) {
    method connectedCallback (line 15) | async connectedCallback() {

FILE: packages/emoji-mart/src/components/HOCs/PureInlineComponent.ts
  class PureInlineComponent (line 3) | class PureInlineComponent extends PureComponent {
    method shouldComponentUpdate (line 4) | shouldComponentUpdate(nextProps) {
    method render (line 16) | render() {

FILE: packages/emoji-mart/src/components/HTMLElement/HTMLElement.ts
  class HTMLElement (line 9) | class HTMLElement extends WindowHTMLElement {
    method observedAttributes (line 10) | static get observedAttributes() {
    method constructor (line 14) | constructor(props = {}) {
    method update (line 27) | update(props = {}) {
    method attributeChangedCallback (line 33) | attributeChangedCallback(attr, _, newValue) {
    method disconnectedCallback (line 51) | disconnectedCallback() {

FILE: packages/emoji-mart/src/components/HTMLElement/ShadowElement.ts
  class ShadowElement (line 4) | class ShadowElement extends HTMLElement {
    method constructor (line 5) | constructor(props, { styles } = {}) {
    method setShadow (line 12) | setShadow() {
    method injectStyles (line 16) | injectStyles(styles) {

FILE: packages/emoji-mart/src/components/Navigation/Navigation.tsx
  constant THEME_ICONS (line 6) | const THEME_ICONS = {
  class Navigation (line 11) | class Navigation extends PureComponent {
    method constructor (line 12) | constructor() {
    method renderIcon (line 24) | renderIcon(category) {
    method render (line 53) | render() {

FILE: packages/emoji-mart/src/components/Picker/Picker.tsx
  class Picker (line 17) | class Picker extends Component {
    method constructor (line 18) | constructor(props) {
    method getInitialState (line 31) | getInitialState(props = this.props) {
    method componentWillMount (line 38) | componentWillMount() {
    method componentDidMount (line 64) | componentDidMount() {
    method componentWillReceiveProps (line 77) | componentWillReceiveProps(nextProps) {
    method componentWillUnmount (line 107) | componentWillUnmount() {
    method reset (line 111) | async reset(nextState = {}) {
    method register (line 123) | register() {
    method unregister (line 128) | unregister() {
    method observe (line 134) | observe() {
    method unobserve (line 139) | unobserve({ except = [] } = {}) {
    method initGrid (line 152) | initGrid() {
    method initTheme (line 203) | initTheme(theme) {
    method initDynamicPerLine (line 250) | initDynamicPerLine(props = this.props) {
    method getPerLine (line 276) | getPerLine() {
    method getEmojiByPos (line 280) | getEmojiByPos([p1, p2]) {
    method observeCategories (line 288) | observeCategories() {
    method observeRows (line 326) | observeRows() {
    method preventDefault (line 362) | preventDefault(e) {
    method unfocusSearch (line 467) | unfocusSearch() {
    method navigate (line 474) | navigate({ e, input, left, right, up, down }) {
    method scrollTo (line 555) | scrollTo({ categoryId, row }) {
    method ignoreMouse (line 601) | ignoreMouse() {
    method handleEmojiOver (line 613) | handleEmojiOver(pos) {
    method handleEmojiClick (line 618) | handleEmojiClick({ e, emoji, pos }) {
    method closeSkins (line 655) | closeSkins() {
    method handleSkinMouseOver (line 663) | handleSkinMouseOver(tempSkin) {
    method handleSkinClick (line 667) | handleSkinClick(skin) {
    method renderNav (line 675) | renderNav() {
    method renderPreview (line 690) | renderPreview() {
    method renderEmojiButton (line 751) | renderEmojiButton(emoji, { pos, posinset, grid }) {
    method renderSearch (line 806) | renderSearch() {
    method renderSearchResults (line 846) | renderSearchResults() {
    method renderCategories (line 882) | renderCategories() {
    method renderSkinToneButton (line 971) | renderSkinToneButton() {
    method renderLiveRegion (line 1004) | renderLiveRegion() {
    method renderSkins (line 1015) | renderSkins() {
    method render (line 1092) | render() {

FILE: packages/emoji-mart/src/components/Picker/PickerElement.tsx
  class PickerElement (line 9) | class PickerElement extends ShadowElement {
    method constructor (line 12) | constructor(props) {
    method connectedCallback (line 16) | async connectedCallback() {

FILE: packages/emoji-mart/src/config.ts
  function fetchJSON (line 15) | async function fetchJSON(src) {
  function init (line 32) | function init(options, { caller } = {}) {
  function _init (line 49) | async function _init(props) {
  function getProps (line 258) | function getProps(props, defaultProps, element) {
  function getProp (line 269) | function getProp(propName, props, defaultProps, element) {

FILE: packages/emoji-mart/src/helpers/frequently-used.ts
  constant DEFAULTS (line 4) | const DEFAULTS = [
  function add (line 24) | function add(emoji: { id: string }) {
  function get (line 37) | function get({ maxFrequentRows, perLine }) {

FILE: packages/emoji-mart/src/helpers/native-support.ts
  constant CACHE (line 1) | const CACHE = new Map()
  constant VERSIONS (line 2) | const VERSIONS = [
  function latestVersion (line 17) | function latestVersion() {
  function noCountryFlags (line 25) | function noCountryFlags() {
  function isSupported (line 33) | function isSupported(emoji) {

FILE: packages/emoji-mart/src/helpers/search-index.ts
  constant SHORTCODES_REGEX (line 4) | const SHORTCODES_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/
  function get (line 7) | function get(emojiId) {
  function reset (line 19) | function reset() {
  function search (line 23) | async function search(value, { maxResults, caller } = {}) {

FILE: packages/emoji-mart/src/helpers/store.ts
  function set (line 1) | function set(key: string, value: string) {
  function get (line 7) | function get(key: string): any {

FILE: packages/emoji-mart/src/utils.ts
  function deepEqual (line 3) | function deepEqual(a: any, b: any): boolean {
  function sleep (line 12) | async function sleep(frames = 1) {
  function getEmojiData (line 18) | function getEmojiData(emoji, { skinIndex = 0 } = {}) {
  function getEmojiDataFromNative (line 54) | async function getEmojiDataFromNative(nativeString) {
Copy disabled (too large) Download .json
Condensed preview — 164 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (32,189K chars).
[
  {
    "path": ".editorconfig",
    "chars": 20,
    "preview": "[*]\nindent_size = 2\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 944,
    "preview": "name: EmojiMart Tests\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    types: [opened, synchronize, reopened]"
  },
  {
    "path": ".gitignore",
    "chars": 41,
    "preview": ".parcel-cache\ncoverage\nnode_modules\ndist\n"
  },
  {
    "path": ".node-version",
    "chars": 8,
    "preview": "16.13.0\n"
  },
  {
    "path": ".npmignore",
    "chars": 43,
    "preview": ".*\n*.config.js\n*.lock\n\nsrc/\ndocs/\nscripts/\n"
  },
  {
    "path": ".prettierignore",
    "chars": 34,
    "preview": "*.md\n*.css\n*.scss\n**/dist\n**/sets\n"
  },
  {
    "path": "LICENSE",
    "chars": 1060,
    "preview": "MIT License\n\nCopyright (c) Missive.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof thi"
  },
  {
    "path": "README.md",
    "chars": 13002,
    "preview": "<div align=\"center\">\n  <br><b>Emoji Mart</b> is a customizable<br>emoji picker HTML component for the web\n  <br><a href="
  },
  {
    "path": "jest/esm-transformer.js",
    "chars": 277,
    "preview": "const babel = require('@babel/core')\n\nmodule.exports = {\n  process(src) {\n    const transform = babel.transform(src, {\n "
  },
  {
    "path": "jest.config.js",
    "chars": 6559,
    "preview": "/*\n * For a detailed explanation regarding each configuration property, visit:\n * https://jestjs.io/docs/configuration\n "
  },
  {
    "path": "package.json",
    "chars": 1166,
    "preview": "{\n  \"name\": \"@emoji-mart/monorepo\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"workspaces\": [\n    \"packages/*\"\n  ],\n  \""
  },
  {
    "path": "packages/emoji-mart/LICENSE",
    "chars": 1060,
    "preview": "MIT License\n\nCopyright (c) Missive.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof thi"
  },
  {
    "path": "packages/emoji-mart/README.md",
    "chars": 13002,
    "preview": "<div align=\"center\">\n  <br><b>Emoji Mart</b> is a customizable<br>emoji picker HTML component for the web\n  <br><a href="
  },
  {
    "path": "packages/emoji-mart/package.json",
    "chars": 1229,
    "preview": "{\n  \"name\": \"emoji-mart\",\n  \"version\": \"5.6.0\",\n  \"description\": \"Emoji picker for the web\",\n  \"license\": \"MIT\",\n  \"home"
  },
  {
    "path": "packages/emoji-mart/src/__tests__/config.test.js",
    "chars": 88,
    "preview": "import { init } from '../config'\n\ndescribe('init', () => {\n  test.skip('', () => {})\n})\n"
  },
  {
    "path": "packages/emoji-mart/src/__tests__/utils.test.js",
    "chars": 751,
    "preview": "import { jest } from '@jest/globals'\nimport { deepEqual, sleep } from '../utils'\n\ndescribe('deepEqual', () => {\n  test('"
  },
  {
    "path": "packages/emoji-mart/src/browser.js",
    "chars": 66,
    "preview": "import * as EmojiMart from './index'\nwindow.EmojiMart = EmojiMart\n"
  },
  {
    "path": "packages/emoji-mart/src/components/Emoji/Emoji.tsx",
    "chars": 2315,
    "preview": "import { Data } from '../../config'\nimport { SearchIndex } from '../../helpers'\n\nexport default function Emoji(props) {\n"
  },
  {
    "path": "packages/emoji-mart/src/components/Emoji/EmojiElement.jsx",
    "chars": 734,
    "preview": "import { render } from 'preact'\n\nimport { init, getProps } from '../../config'\nimport { HTMLElement } from '../HTMLEleme"
  },
  {
    "path": "packages/emoji-mart/src/components/Emoji/EmojiProps.ts",
    "chars": 411,
    "preview": "import PickerProps from '../Picker/PickerProps'\n\nexport default {\n  fallback: '',\n  id: '',\n  native: '',\n  shortcodes: "
  },
  {
    "path": "packages/emoji-mart/src/components/Emoji/index.ts",
    "chars": 100,
    "preview": "export { default as Emoji } from './Emoji'\nexport { default as EmojiElement } from './EmojiElement'\n"
  },
  {
    "path": "packages/emoji-mart/src/components/HOCs/PureInlineComponent.ts",
    "chars": 367,
    "preview": "import { PureComponent } from 'preact/compat'\n\nexport default class PureInlineComponent extends PureComponent {\n  should"
  },
  {
    "path": "packages/emoji-mart/src/components/HOCs/index.ts",
    "chars": 71,
    "preview": "export { default as PureInlineComponent } from './PureInlineComponent'\n"
  },
  {
    "path": "packages/emoji-mart/src/components/HTMLElement/HTMLElement.ts",
    "chars": 1287,
    "preview": "// @ts-nocheck\nimport { getProp } from '../../config'\n\nconst WindowHTMLElement =\n  typeof window !== 'undefined' && wind"
  },
  {
    "path": "packages/emoji-mart/src/components/HTMLElement/ShadowElement.ts",
    "chars": 486,
    "preview": "// @ts-nocheck\nimport { HTMLElement } from '.'\n\nexport default class ShadowElement extends HTMLElement {\n  constructor(p"
  },
  {
    "path": "packages/emoji-mart/src/components/HTMLElement/index.ts",
    "chars": 114,
    "preview": "export { default as HTMLElement } from './HTMLElement'\nexport { default as ShadowElement } from './ShadowElement'\n"
  },
  {
    "path": "packages/emoji-mart/src/components/Navigation/Navigation.tsx",
    "chars": 2566,
    "preview": "// @ts-nocheck\nimport { PureComponent } from 'preact/compat'\nimport { Data, I18n } from '../../config'\nimport Icons from"
  },
  {
    "path": "packages/emoji-mart/src/components/Navigation/index.ts",
    "chars": 53,
    "preview": "export { default as Navigation } from './Navigation'\n"
  },
  {
    "path": "packages/emoji-mart/src/components/Picker/Picker.tsx",
    "chars": 30030,
    "preview": "// @ts-nocheck\nimport { Component, createRef } from 'preact'\n\nimport { deepEqual, sleep, getEmojiData } from '../../util"
  },
  {
    "path": "packages/emoji-mart/src/components/Picker/PickerElement.tsx",
    "chars": 837,
    "preview": "// @ts-nocheck\nimport { render } from 'preact'\n\nimport { init, getProps } from '../../config'\nimport { ShadowElement } f"
  },
  {
    "path": "packages/emoji-mart/src/components/Picker/PickerProps.ts",
    "chars": 1901,
    "preview": "export default {\n  autoFocus: {\n    value: false,\n  },\n  dynamicWidth: {\n    value: false,\n  },\n  emojiButtonColors: {\n "
  },
  {
    "path": "packages/emoji-mart/src/components/Picker/PickerStyles.scss",
    "chars": 12135,
    "preview": ":host {\n  display: flex;\n  width: min-content;\n  height: 435px;\n  min-height: 230px;\n  border-radius: var(--border-radiu"
  },
  {
    "path": "packages/emoji-mart/src/components/Picker/index.ts",
    "chars": 193,
    "preview": "// @ts-nocheck\nexport { default as Picker } from './Picker'\nexport { default as PickerElement } from './PickerElement'\ne"
  },
  {
    "path": "packages/emoji-mart/src/config.ts",
    "chars": 7423,
    "preview": "// @ts-nocheck\nimport i18n_en from '@emoji-mart/data/i18n/en.json'\nimport PickerProps from './components/Picker/PickerPr"
  },
  {
    "path": "packages/emoji-mart/src/declaration.d.ts",
    "chars": 24,
    "preview": "declare module '*.scss'\n"
  },
  {
    "path": "packages/emoji-mart/src/helpers/__tests__/frequently-used.test.js",
    "chars": 113,
    "preview": "import FrequentlyUsed from '../frequently-used'\n\ndescribe('FrequentlyUsed', () => {\n  test.skip('', () => {})\n})\n"
  },
  {
    "path": "packages/emoji-mart/src/helpers/__tests__/native-support.test.js",
    "chars": 110,
    "preview": "import NativeSupport from '../native-support'\n\ndescribe('NativeSupport', () => {\n  test.skip('', () => {})\n})\n"
  },
  {
    "path": "packages/emoji-mart/src/helpers/__tests__/search-index.test.js",
    "chars": 104,
    "preview": "import SearchIndex from '../search-index'\n\ndescribe('SearchIndex', () => {\n  test.skip('', () => {})\n})\n"
  },
  {
    "path": "packages/emoji-mart/src/helpers/__tests__/store.test.js",
    "chars": 85,
    "preview": "import Store from '../store'\n\ndescribe('Store', () => {\n  test.skip('', () => {})\n})\n"
  },
  {
    "path": "packages/emoji-mart/src/helpers/frequently-used.ts",
    "chars": 1750,
    "preview": "// @ts-nocheck\nimport { Store } from '../helpers'\n\nconst DEFAULTS = [\n  '+1',\n  'grinning',\n  'kissing_heart',\n  'heart_"
  },
  {
    "path": "packages/emoji-mart/src/helpers/index.ts",
    "chars": 423,
    "preview": "export { default as Store } from './store'\n\nexport { default as NativeSupport } from './native-support'\nexport { default"
  },
  {
    "path": "packages/emoji-mart/src/helpers/native-support.ts",
    "chars": 2605,
    "preview": "const CACHE = new Map()\nconst VERSIONS = [\n  { v: 15, emoji: '🫨' },\n  { v: 14, emoji: '🫠' },\n  { v: 13.1, emoji: '😶‍🌫️' "
  },
  {
    "path": "packages/emoji-mart/src/helpers/search-index.ts",
    "chars": 1704,
    "preview": "// @ts-nocheck\nimport { init, Data } from '../config'\n\nconst SHORTCODES_REGEX = /^(?:\\:([^\\:]+)\\:)(?:\\:skin-tone-(\\d)\\:)"
  },
  {
    "path": "packages/emoji-mart/src/helpers/store.ts",
    "chars": 351,
    "preview": "function set(key: string, value: string) {\n  try {\n    window.localStorage[`emoji-mart.${key}`] = JSON.stringify(value)\n"
  },
  {
    "path": "packages/emoji-mart/src/icons.tsx",
    "chars": 18765,
    "preview": "const categories = {\n  activity: {\n    outline: (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n   "
  },
  {
    "path": "packages/emoji-mart/src/index.ts",
    "chars": 291,
    "preview": "export { PickerElement as Picker } from './components/Picker'\nexport { EmojiElement as Emoji } from './components/Emoji'"
  },
  {
    "path": "packages/emoji-mart/src/utils.ts",
    "chars": 1537,
    "preview": "import { SearchIndex } from './helpers'\n\nexport function deepEqual(a: any, b: any): boolean {\n  return (\n    Array.isArr"
  },
  {
    "path": "packages/emoji-mart-data/LICENSE",
    "chars": 1060,
    "preview": "MIT License\n\nCopyright (c) Missive.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof thi"
  },
  {
    "path": "packages/emoji-mart-data/README.md",
    "chars": 114,
    "preview": "# `@emoji-mart/data`\n\nThis package contains the data used by [EmojiMart](https://missiveapp.com/open/emoji-mart).\n"
  },
  {
    "path": "packages/emoji-mart-data/build.js",
    "chars": 5537,
    "preview": "const { mkdir, writeFile, rmSync } = require('fs')\n\nconst inflection = require('inflection')\nconst emojiLib = require('e"
  },
  {
    "path": "packages/emoji-mart-data/i18n/ar.json",
    "chars": 738,
    "preview": "{\n  \"rtl\": true,\n\n  \"search\": \"البحث\",\n  \"search_no_results_1\": \"أوه لا!\",\n  \"search_no_results_2\": \"لا يمكن العثور على "
  },
  {
    "path": "packages/emoji-mart-data/i18n/be.json",
    "chars": 732,
    "preview": "{\n  \"search\": \"Пошук\",\n  \"search_no_results_1\": \"О не!\",\n  \"search_no_results_2\": \"Эмодзі ня знойдзены\",\n  \"pick\": \"Выбе"
  },
  {
    "path": "packages/emoji-mart-data/i18n/cs.json",
    "chars": 729,
    "preview": "{\n  \"search\": \"Vyhledat\",\n  \"search_no_results_1\": \"Ale ne!\",\n  \"search_no_results_2\": \"Emoji nebylo nalezeno\",\n  \"pick\""
  },
  {
    "path": "packages/emoji-mart-data/i18n/de.json",
    "chars": 762,
    "preview": "{\n  \"search\": \"Suchen\",\n  \"search_no_results_1\": \"Oh nein!\",\n  \"search_no_results_2\": \"Das Emoji konnte nicht gefunden w"
  },
  {
    "path": "packages/emoji-mart-data/i18n/en.json",
    "chars": 708,
    "preview": "{\n  \"search\": \"Search\",\n  \"search_no_results_1\": \"Oh no!\",\n  \"search_no_results_2\": \"That emoji couldn’t be found\",\n  \"p"
  },
  {
    "path": "packages/emoji-mart-data/i18n/es.json",
    "chars": 781,
    "preview": "{\n  \"search\": \"Buscar\",\n  \"search_no_results_1\": \"Vaya!\",\n  \"search_no_results_2\": \"Ese emoji no se pudo encontrar\",\n  \""
  },
  {
    "path": "packages/emoji-mart-data/i18n/fa.json",
    "chars": 726,
    "preview": "{\n  \"rtl\": true,\n\n  \"search\": \"جستجو\",\n  \"search_no_results_1\": \"اوه نه!\",\n  \"search_no_results_2\": \"این ایموجی یافت نشد"
  },
  {
    "path": "packages/emoji-mart-data/i18n/fi.json",
    "chars": 722,
    "preview": "{\n  \"search\": \"Hae\",\n  \"search_no_results_1\": \"Voi ei!\",\n  \"search_no_results_2\": \"Hakemaasi emojia ei löytynyt\",\n  \"pic"
  },
  {
    "path": "packages/emoji-mart-data/i18n/fr.json",
    "chars": 771,
    "preview": "{\n  \"search\": \"Rechercher\",\n  \"search_no_results_1\": \"Oh non!\",\n  \"search_no_results_2\": \"Cet emoji ne peut être trouvé\""
  },
  {
    "path": "packages/emoji-mart-data/i18n/hi.json",
    "chars": 695,
    "preview": "{\n  \"search\": \"खोज\",\n  \"search_no_results_1\": \"धत्तेरे की!\",\n  \"search_no_results_2\": \"वह भाव चित्र नहीं मिला\",\n  \"pick\""
  },
  {
    "path": "packages/emoji-mart-data/i18n/it.json",
    "chars": 763,
    "preview": "{\n  \"search\": \"Cerca\",\n  \"search_no_results_1\": \"Oh no!\",\n  \"search_no_results_2\": \"Impossibile trovare l'emoji\",\n  \"pic"
  },
  {
    "path": "packages/emoji-mart-data/i18n/ja.json",
    "chars": 584,
    "preview": "{\n  \"search\": \"検索\",\n  \"search_no_results_1\": \"残念!\",\n  \"search_no_results_2\": \"その絵文字は見つかりませんでした\",\n  \"pick\": \"絵文字を選択...\",\n"
  },
  {
    "path": "packages/emoji-mart-data/i18n/ko.json",
    "chars": 589,
    "preview": "{\n  \"search\": \"검색\",\n  \"search_no_results_1\": \"어머나!\",\n  \"search_no_results_2\": \"결과를 찾을 수 없어요\",\n  \"pick\": \"이모지 선택하기\",\n  \"a"
  },
  {
    "path": "packages/emoji-mart-data/i18n/nl.json",
    "chars": 729,
    "preview": "{\n  \"search\": \"Zoek\",\n  \"search_no_results_1\": \"Mislukt!\",\n  \"search_no_results_2\": \"Die emoji werd niet gevonden\",\n  \"p"
  },
  {
    "path": "packages/emoji-mart-data/i18n/pl.json",
    "chars": 739,
    "preview": "{\n  \"search\": \"Szukaj\",\n  \"search_no_results_1\": \"O nie!\",\n  \"search_no_results_2\": \"Nie znaleziono emoji\",\n  \"pick\": \"W"
  },
  {
    "path": "packages/emoji-mart-data/i18n/pt.json",
    "chars": 771,
    "preview": "{\n  \"search\": \"Procurar\",\n  \"search_no_results_1\": \"Oh não!\",\n  \"search_no_results_2\": \"Esse emoji não foi encontrado\",\n"
  },
  {
    "path": "packages/emoji-mart-data/i18n/ru.json",
    "chars": 733,
    "preview": "{\n  \"search\": \"Поиск\",\n  \"search_no_results_1\": \"О нет!\",\n  \"search_no_results_2\": \"Эмодзи не найден\",\n  \"pick\": \"Выбери"
  },
  {
    "path": "packages/emoji-mart-data/i18n/sa.json",
    "chars": 745,
    "preview": "{\n  \"search\": \"अन्वेषण\",\n  \"search_no_results_1\": \"अहो न!\",\n  \"search_no_results_2\": \"भावः चित्रम् न प्राप्तम्\",\n  \"pick"
  },
  {
    "path": "packages/emoji-mart-data/i18n/tr.json",
    "chars": 715,
    "preview": "{\n  \"search\": \"Arama\",\n  \"search_no_results_1\": \"Oh hayır!\",\n  \"search_no_results_2\": \"Bu emoji bulunamadı\",\n  \"pick\": \""
  },
  {
    "path": "packages/emoji-mart-data/i18n/uk.json",
    "chars": 758,
    "preview": "{\n  \"search\": \"Пошук\",\n  \"search_no_results_1\": \"О ні!\",\n  \"search_no_results_2\": \"Не вдалося знайти це емодзі\",\n  \"pick"
  },
  {
    "path": "packages/emoji-mart-data/i18n/vi.json",
    "chars": 714,
    "preview": "{\n  \"search\": \"Tìm kiếm\",\n  \"search_no_results_1\": \"Ôi không!\",\n  \"search_no_results_2\": \"Không thể tìm thấy biểu tượng "
  },
  {
    "path": "packages/emoji-mart-data/i18n/zh.json",
    "chars": 532,
    "preview": "{\n  \"search\": \"搜索\",\n  \"search_no_results_1\": \"哦不!\",\n  \"search_no_results_2\": \"没有找到相关表情\",\n  \"pick\": \"选择一个表情…\",\n  \"add_cus"
  },
  {
    "path": "packages/emoji-mart-data/index.d.ts",
    "chars": 490,
    "preview": "export interface EmojiMartData {\n  categories: Category[]\n  emojis: { [key: string]: Emoji }\n  aliases: { [key: string]:"
  },
  {
    "path": "packages/emoji-mart-data/package.json",
    "chars": 698,
    "preview": "{\n  \"name\": \"@emoji-mart/data\",\n  \"version\": \"1.2.1\",\n  \"description\": \"Data for Emoji Mart; the emoji picker for the we"
  },
  {
    "path": "packages/emoji-mart-data/sets/1/all.json",
    "chars": 219067,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/1/apple.json",
    "chars": 219027,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/1/facebook.json",
    "chars": 216784,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/1/google.json",
    "chars": 219067,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/1/native.json",
    "chars": 200018,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/1/twitter.json",
    "chars": 219067,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/11/all.json",
    "chars": 394707,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/11/apple.json",
    "chars": 394098,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/11/facebook.json",
    "chars": 387369,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/11/google.json",
    "chars": 394707,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/11/native.json",
    "chars": 356016,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/11/twitter.json",
    "chars": 394707,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12/all.json",
    "chars": 413896,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12/apple.json",
    "chars": 413287,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12/facebook.json",
    "chars": 406558,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12/google.json",
    "chars": 413896,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12/native.json",
    "chars": 372930,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12/twitter.json",
    "chars": 413896,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12.1/all.json",
    "chars": 426077,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12.1/apple.json",
    "chars": 425468,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12.1/facebook.json",
    "chars": 418739,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12.1/google.json",
    "chars": 426077,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12.1/native.json",
    "chars": 383198,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/12.1/twitter.json",
    "chars": 426077,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13/all.json",
    "chars": 440483,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13/apple.json",
    "chars": 439874,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13/facebook.json",
    "chars": 432940,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13/google.json",
    "chars": 440483,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13/native.json",
    "chars": 395985,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13/twitter.json",
    "chars": 440483,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13.1/all.json",
    "chars": 442724,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13.1/apple.json",
    "chars": 442115,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13.1/facebook.json",
    "chars": 435181,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13.1/google.json",
    "chars": 442724,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13.1/native.json",
    "chars": 397989,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/13.1/twitter.json",
    "chars": 442724,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/14/all.json",
    "chars": 452289,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/14/apple.json",
    "chars": 451680,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/14/facebook.json",
    "chars": 444746,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/14/google.json",
    "chars": 452289,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/14/native.json",
    "chars": 406356,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/14/twitter.json",
    "chars": 452289,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/15/all.json",
    "chars": 456522,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/15/apple.json",
    "chars": 455912,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/15/facebook.json",
    "chars": 444746,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/15/google.json",
    "chars": 456521,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/15/native.json",
    "chars": 410157,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/15/twitter.json",
    "chars": 452289,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/2/all.json",
    "chars": 274150,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/2/apple.json",
    "chars": 274110,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/2/facebook.json",
    "chars": 271450,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/2/google.json",
    "chars": 274150,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/2/native.json",
    "chars": 251183,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/2/twitter.json",
    "chars": 274150,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"joy\",\"slightly_smil"
  },
  {
    "path": "packages/emoji-mart-data/sets/3/all.json",
    "chars": 292034,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/3/apple.json",
    "chars": 291994,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/3/facebook.json",
    "chars": 289334,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/3/google.json",
    "chars": 292034,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/3/native.json",
    "chars": 266818,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/3/twitter.json",
    "chars": 292034,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/4/all.json",
    "chars": 350882,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/4/apple.json",
    "chars": 350273,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/4/facebook.json",
    "chars": 343544,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/4/google.json",
    "chars": 350882,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/4/native.json",
    "chars": 317677,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/4/twitter.json",
    "chars": 350882,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/5/all.json",
    "chars": 375833,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/5/apple.json",
    "chars": 375224,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/5/facebook.json",
    "chars": 368495,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/5/google.json",
    "chars": 375833,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/5/native.json",
    "chars": 339321,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-data/sets/5/twitter.json",
    "chars": 375833,
    "preview": "{\"categories\":[{\"id\":\"people\",\"emojis\":[\"grinning\",\"smiley\",\"smile\",\"grin\",\"laughing\",\"sweat_smile\",\"rolling_on_the_floo"
  },
  {
    "path": "packages/emoji-mart-react/LICENSE",
    "chars": 1060,
    "preview": "MIT License\n\nCopyright (c) Missive.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof thi"
  },
  {
    "path": "packages/emoji-mart-react/README.md",
    "chars": 429,
    "preview": "# `@emoji-mart/react`\n\nA React wrapper for [EmojiMart](https://missiveapp.com/open/emoji-mart).\n\n## 🧑‍💻 Usage\n```sh\nnpm "
  },
  {
    "path": "packages/emoji-mart-react/package.json",
    "chars": 698,
    "preview": "{\n  \"name\": \"@emoji-mart/react\",\n  \"version\": \"1.1.1\",\n  \"description\": \"React wrapper for Emoji Mart; the emoji picker "
  },
  {
    "path": "packages/emoji-mart-react/react.tsx",
    "chars": 458,
    "preview": "// @ts-nocheck\nimport React, { useEffect, useRef } from 'react'\nimport { Picker } from 'emoji-mart'\n\nexport default func"
  },
  {
    "path": "packages/emoji-mart-website/.posthtmlrc",
    "chars": 109,
    "preview": "{\n  \"plugins\": {\n    \"posthtml-include\": {},\n    \"posthtml-expressions\": {},\n    \"posthtml-extend\": {}\n  }\n}\n"
  },
  {
    "path": "packages/emoji-mart-website/example-categories.html",
    "chars": 1629,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Categories\", \"exampleFile\": \"example-categories.html\" }'\n>\n  <b"
  },
  {
    "path": "packages/emoji-mart-website/example-custom-font.html",
    "chars": 640,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Custom font\", \"exampleFile\": \"example-custom-font.html\" }'\n>\n  "
  },
  {
    "path": "packages/emoji-mart-website/example-custom-styles.html",
    "chars": 1203,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Custom styles\", \"exampleFile\": \"example-custom-styles.html\" }'\n"
  },
  {
    "path": "packages/emoji-mart-website/example-dynamic-width.html",
    "chars": 578,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Dynamic width\", \"exampleFile\": \"example-dynamic-width.html\" }'\n"
  },
  {
    "path": "packages/emoji-mart-website/example-emoji-component.html",
    "chars": 1953,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Emoji component\", \"exampleFile\": \"example-emoji-component.html\""
  },
  {
    "path": "packages/emoji-mart-website/example-headless-search.html",
    "chars": 1246,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Headless search\", \"exampleFile\": \"example-headless-search.html\""
  },
  {
    "path": "packages/emoji-mart-website/example-slack-colors.html",
    "chars": 667,
    "preview": "<extends\n  src=\"layout.html\"\n  locals='{ \"exampleName\": \"Slack colors\", \"exampleFile\": \"example-slack-colors.html\" }'\n>\n"
  },
  {
    "path": "packages/emoji-mart-website/examples.html",
    "chars": 831,
    "preview": "<extends src=\"layout.html\" locals='{ \"exampleName\": \"\", \"exampleFile\": \" \" }'>\n  <block name=\"content\">\n    <ul>\n      <"
  },
  {
    "path": "packages/emoji-mart-website/index.html",
    "chars": 11836,
    "preview": "<extends src=\"layout.html\" locals='{ \"exampleName\": \"\", \"exampleFile\": \"\" }'>\n  <block name=\"content\" type=\"append\">\n   "
  },
  {
    "path": "packages/emoji-mart-website/layout.html",
    "chars": 5982,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Emoji Mart • One component to pick them all</tit"
  },
  {
    "path": "packages/emoji-mart-website/package.json",
    "chars": 368,
    "preview": "{\n  \"name\": \"@emoji-mart/website\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"parcel index.html"
  },
  {
    "path": "packages/emoji-mart-website/styles.scss",
    "chars": 5779,
    "preview": ":root {\n  --color: #202124;\n  --rgb-accent: 9, 105, 218;\n  --background-color: #f4f4f4;\n  --dark-background-color: rgba("
  },
  {
    "path": "tsconfig.json",
    "chars": 399,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"commonjs\",\n    \"allowJs\": true,\n    \"esModuleInterop\": t"
  }
]

About this extraction

This page contains the full source code of the missive/emoji-mart GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 164 files (25.6 MB), approximately 6.7M tokens, and a symbol index with 102 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!