UNPKG

@ferrucc-io/emoji-picker

Version:

A beautiful and modern emoji picker for React

1,755 lines (1,751 loc) 745 kB
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); // ../../node_modules/jotai/esm/vanilla.mjs var keyCount = 0; function atom(read, write) { const key = `atom${++keyCount}`; const config = { toString() { return (import.meta.env ? import.meta.env.MODE : void 0) !== "production" && this.debugLabel ? key + ":" + this.debugLabel : key; } }; if (typeof read === "function") { config.read = read; } else { config.init = read; config.read = defaultRead; config.write = defaultWrite; } if (write) { config.write = write; } return config; } function defaultRead(get) { return get(this); } function defaultWrite(get, set, arg) { return set( this, typeof arg === "function" ? arg(get(this)) : arg ); } var isSelfAtom = (atom2, a) => atom2.unstable_is ? atom2.unstable_is(a) : a === atom2; var hasInitialValue = (atom2) => "init" in atom2; var isActuallyWritableAtom = (atom2) => !!atom2.write; var cancelablePromiseMap = /* @__PURE__ */ new WeakMap(); var isPendingPromise = (value) => { var _a; return isPromiseLike(value) && !((_a = cancelablePromiseMap.get(value)) == null ? void 0 : _a[1]); }; var cancelPromise = (promise, nextValue) => { const promiseState = cancelablePromiseMap.get(promise); if (promiseState) { promiseState[1] = true; promiseState[0].forEach((fn) => fn(nextValue)); } else if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production") { throw new Error("[Bug] cancelable promise not found"); } }; var patchPromiseForCancelability = (promise) => { if (cancelablePromiseMap.has(promise)) { return; } const promiseState = [/* @__PURE__ */ new Set(), false]; cancelablePromiseMap.set(promise, promiseState); const settle = () => { promiseState[1] = true; }; promise.then(settle, settle); promise.onCancel = (fn) => { promiseState[0].add(fn); }; }; var isPromiseLike = (p) => typeof (p == null ? void 0 : p.then) === "function"; var isAtomStateInitialized = (atomState) => "v" in atomState || "e" in atomState; var returnAtomValue = (atomState) => { if ("e" in atomState) { throw atomState.e; } if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && !("v" in atomState)) { throw new Error("[Bug] atom state is not initialized"); } return atomState.v; }; var addPendingPromiseToDependency = (atom2, promise, dependencyAtomState) => { if (!dependencyAtomState.p.has(atom2)) { dependencyAtomState.p.add(atom2); promise.then( () => { dependencyAtomState.p.delete(atom2); }, () => { dependencyAtomState.p.delete(atom2); } ); } }; var addDependency = (atom2, atomState, a, aState) => { var _a; if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && a === atom2) { throw new Error("[Bug] atom cannot depend on itself"); } atomState.d.set(a, aState.n); if (isPendingPromise(atomState.v)) { addPendingPromiseToDependency(atom2, atomState.v, aState); } (_a = aState.m) == null ? void 0 : _a.t.add(atom2); }; var INTERNAL_flushStoreHook = Symbol.for("JOTAI.EXPERIMENTAL.FLUSHSTOREHOOK"); var buildStore = (...storeArgs) => { const [ getAtomState, setAtomState, atomRead, atomWrite, atomOnInit, atomOnMount ] = storeArgs; const ensureAtomState = (atom2) => { if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && !atom2) { throw new Error("Atom is undefined or null"); } let atomState = getAtomState(atom2); if (!atomState) { atomState = { d: /* @__PURE__ */ new Map(), p: /* @__PURE__ */ new Set(), n: 0 }; setAtomState(atom2, atomState); atomOnInit == null ? void 0 : atomOnInit(atom2, store); } return atomState; }; const invalidatedAtoms = /* @__PURE__ */ new WeakMap(); const changedAtoms = /* @__PURE__ */ new Map(); const unmountCallbacks = /* @__PURE__ */ new Set(); const mountCallbacks = /* @__PURE__ */ new Set(); const flushCallbacks = () => { var _a; const errors = []; const call = (fn) => { try { fn(); } catch (e) { errors.push(e); } }; do { (_a = store[INTERNAL_flushStoreHook]) == null ? void 0 : _a.call(store); const callbacks = /* @__PURE__ */ new Set(); const add = callbacks.add.bind(callbacks); changedAtoms.forEach((atomState) => { var _a2; return (_a2 = atomState.m) == null ? void 0 : _a2.l.forEach(add); }); changedAtoms.clear(); unmountCallbacks.forEach(add); unmountCallbacks.clear(); mountCallbacks.forEach(add); mountCallbacks.clear(); callbacks.forEach(call); if (changedAtoms.size) { recomputeInvalidatedAtoms(); } } while (changedAtoms.size || unmountCallbacks.size || mountCallbacks.size); if (errors.length) { throw errors[0]; } }; const setAtomStateValueOrPromise = (atom2, atomState, valueOrPromise) => { const hasPrevValue = "v" in atomState; const prevValue = atomState.v; const pendingPromise = isPendingPromise(atomState.v) ? atomState.v : null; if (isPromiseLike(valueOrPromise)) { patchPromiseForCancelability(valueOrPromise); for (const a of atomState.d.keys()) { addPendingPromiseToDependency(atom2, valueOrPromise, ensureAtomState(a)); } atomState.v = valueOrPromise; } else { atomState.v = valueOrPromise; } delete atomState.e; if (!hasPrevValue || !Object.is(prevValue, atomState.v)) { ++atomState.n; if (pendingPromise) { cancelPromise(pendingPromise, valueOrPromise); } } }; const readAtomState = (atom2) => { var _a; const atomState = ensureAtomState(atom2); if (isAtomStateInitialized(atomState)) { if (atomState.m && invalidatedAtoms.get(atom2) !== atomState.n) { return atomState; } if (Array.from(atomState.d).every( ([a, n]) => ( // Recursively, read the atom state of the dependency, and // check if the atom epoch number is unchanged readAtomState(a).n === n ) )) { return atomState; } } atomState.d.clear(); let isSync = true; const mountDependenciesIfAsync = () => { if (atomState.m) { mountDependencies(atom2, atomState); recomputeInvalidatedAtoms(); flushCallbacks(); } }; const getter = (a) => { if (isSelfAtom(atom2, a)) { const aState2 = ensureAtomState(a); if (!isAtomStateInitialized(aState2)) { if (hasInitialValue(a)) { setAtomStateValueOrPromise(a, aState2, a.init); } else { throw new Error("no atom init"); } } return returnAtomValue(aState2); } const aState = readAtomState(a); try { return returnAtomValue(aState); } finally { addDependency(atom2, atomState, a, aState); if (!isSync) { mountDependenciesIfAsync(); } } }; let controller; let setSelf; const options = { get signal() { if (!controller) { controller = new AbortController(); } return controller.signal; }, get setSelf() { if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && !isActuallyWritableAtom(atom2)) { console.warn("setSelf function cannot be used with read-only atom"); } if (!setSelf && isActuallyWritableAtom(atom2)) { setSelf = (...args) => { if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && isSync) { console.warn("setSelf function cannot be called in sync"); } if (!isSync) { return writeAtom(atom2, ...args); } }; } return setSelf; } }; try { const valueOrPromise = atomRead(atom2, getter, options); setAtomStateValueOrPromise(atom2, atomState, valueOrPromise); if (isPromiseLike(valueOrPromise)) { (_a = valueOrPromise.onCancel) == null ? void 0 : _a.call(valueOrPromise, () => controller == null ? void 0 : controller.abort()); valueOrPromise.then(mountDependenciesIfAsync, mountDependenciesIfAsync); } return atomState; } catch (error) { delete atomState.v; atomState.e = error; ++atomState.n; return atomState; } finally { isSync = false; } }; const readAtom = (atom2) => returnAtomValue(readAtomState(atom2)); const getMountedOrPendingDependents = (atomState) => { var _a; const dependents = /* @__PURE__ */ new Map(); for (const a of ((_a = atomState.m) == null ? void 0 : _a.t) || []) { const aState = ensureAtomState(a); if (aState.m) { dependents.set(a, aState); } } for (const atomWithPendingPromise of atomState.p) { dependents.set( atomWithPendingPromise, ensureAtomState(atomWithPendingPromise) ); } return dependents; }; const invalidateDependents = (atomState) => { const stack = [atomState]; while (stack.length) { const aState = stack.pop(); for (const [d, s] of getMountedOrPendingDependents(aState)) { if (!invalidatedAtoms.has(d)) { invalidatedAtoms.set(d, s.n); stack.push(s); } } } }; const recomputeInvalidatedAtoms = () => { var _a; const topSortedReversed = []; const visiting = /* @__PURE__ */ new WeakSet(); const visited = /* @__PURE__ */ new WeakSet(); const stack = Array.from(changedAtoms); while (stack.length) { const [a, aState] = stack[stack.length - 1]; if (visited.has(a)) { stack.pop(); continue; } if (visiting.has(a)) { if (invalidatedAtoms.get(a) === aState.n) { topSortedReversed.push([a, aState, aState.n]); } else { invalidatedAtoms.delete(a); changedAtoms.set(a, aState); } visited.add(a); stack.pop(); continue; } visiting.add(a); for (const [d, s] of getMountedOrPendingDependents(aState)) { if (!visiting.has(d)) { stack.push([d, s]); } } } for (let i = topSortedReversed.length - 1; i >= 0; --i) { const [a, aState, prevEpochNumber] = topSortedReversed[i]; let hasChangedDeps = false; for (const dep of aState.d.keys()) { if (dep !== a && changedAtoms.has(dep)) { hasChangedDeps = true; break; } } if (hasChangedDeps) { readAtomState(a); mountDependencies(a, aState); if (prevEpochNumber !== aState.n) { changedAtoms.set(a, aState); (_a = aState.u) == null ? void 0 : _a.call(aState); } } invalidatedAtoms.delete(a); } }; const writeAtomState = (atom2, ...args) => { let isSync = true; const getter = (a) => returnAtomValue(readAtomState(a)); const setter = (a, ...args2) => { var _a; const aState = ensureAtomState(a); try { if (isSelfAtom(atom2, a)) { if (!hasInitialValue(a)) { throw new Error("atom not writable"); } const prevEpochNumber = aState.n; const v = args2[0]; setAtomStateValueOrPromise(a, aState, v); mountDependencies(a, aState); if (prevEpochNumber !== aState.n) { changedAtoms.set(a, aState); (_a = aState.u) == null ? void 0 : _a.call(aState); invalidateDependents(aState); } return void 0; } else { return writeAtomState(a, ...args2); } } finally { if (!isSync) { recomputeInvalidatedAtoms(); flushCallbacks(); } } }; try { return atomWrite(atom2, getter, setter, ...args); } finally { isSync = false; } }; const writeAtom = (atom2, ...args) => { try { return writeAtomState(atom2, ...args); } finally { recomputeInvalidatedAtoms(); flushCallbacks(); } }; const mountDependencies = (atom2, atomState) => { var _a; if (atomState.m && !isPendingPromise(atomState.v)) { for (const [a, n] of atomState.d) { if (!atomState.m.d.has(a)) { const aState = ensureAtomState(a); const aMounted = mountAtom(a, aState); aMounted.t.add(atom2); atomState.m.d.add(a); if (n !== aState.n) { changedAtoms.set(a, aState); (_a = aState.u) == null ? void 0 : _a.call(aState); invalidateDependents(aState); } } } for (const a of atomState.m.d || []) { if (!atomState.d.has(a)) { atomState.m.d.delete(a); const aMounted = unmountAtom(a, ensureAtomState(a)); aMounted == null ? void 0 : aMounted.t.delete(atom2); } } } }; const mountAtom = (atom2, atomState) => { var _a; if (!atomState.m) { readAtomState(atom2); for (const a of atomState.d.keys()) { const aMounted = mountAtom(a, ensureAtomState(a)); aMounted.t.add(atom2); } atomState.m = { l: /* @__PURE__ */ new Set(), d: new Set(atomState.d.keys()), t: /* @__PURE__ */ new Set() }; (_a = atomState.h) == null ? void 0 : _a.call(atomState); if (isActuallyWritableAtom(atom2)) { const mounted = atomState.m; const processOnMount = () => { let isSync = true; const setAtom = (...args) => { try { return writeAtomState(atom2, ...args); } finally { if (!isSync) { recomputeInvalidatedAtoms(); flushCallbacks(); } } }; try { const onUnmount = atomOnMount(atom2, setAtom); if (onUnmount) { mounted.u = () => { isSync = true; try { onUnmount(); } finally { isSync = false; } }; } } finally { isSync = false; } }; mountCallbacks.add(processOnMount); } } return atomState.m; }; const unmountAtom = (atom2, atomState) => { var _a; if (atomState.m && !atomState.m.l.size && !Array.from(atomState.m.t).some((a) => { var _a2; return (_a2 = ensureAtomState(a).m) == null ? void 0 : _a2.d.has(atom2); })) { const onUnmount = atomState.m.u; if (onUnmount) { unmountCallbacks.add(onUnmount); } delete atomState.m; (_a = atomState.h) == null ? void 0 : _a.call(atomState); for (const a of atomState.d.keys()) { const aMounted = unmountAtom(a, ensureAtomState(a)); aMounted == null ? void 0 : aMounted.t.delete(atom2); } return void 0; } return atomState.m; }; const subscribeAtom = (atom2, listener) => { const atomState = ensureAtomState(atom2); const mounted = mountAtom(atom2, atomState); const listeners = mounted.l; listeners.add(listener); flushCallbacks(); return () => { listeners.delete(listener); unmountAtom(atom2, atomState); flushCallbacks(); }; }; const unstable_derive = (fn) => buildStore(...fn(...storeArgs)); const store = { get: readAtom, set: writeAtom, sub: subscribeAtom, unstable_derive }; return store; }; var deriveDevStoreRev4 = (store) => { const debugMountedAtoms = /* @__PURE__ */ new Set(); let savedGetAtomState; let inRestoreAtom = 0; const derivedStore = store.unstable_derive((...storeArgs) => { const [getAtomState, setAtomState, , atomWrite] = storeArgs; savedGetAtomState = getAtomState; storeArgs[1] = function devSetAtomState(atom2, atomState) { setAtomState(atom2, atomState); const originalMounted = atomState.h; atomState.h = () => { originalMounted == null ? void 0 : originalMounted(); if (atomState.m) { debugMountedAtoms.add(atom2); } else { debugMountedAtoms.delete(atom2); } }; }; storeArgs[3] = function devAtomWrite(atom2, getter, setter, ...args) { if (inRestoreAtom) { return setter(atom2, ...args); } return atomWrite(atom2, getter, setter, ...args); }; return storeArgs; }); const savedStoreSet = derivedStore.set; const devStore = { // store dev methods (these are tentative and subject to change without notice) dev4_get_internal_weak_map: () => ({ get: (atom2) => { const atomState = savedGetAtomState(atom2); if (!atomState || atomState.n === 0) { return void 0; } return atomState; } }), dev4_get_mounted_atoms: () => debugMountedAtoms, dev4_restore_atoms: (values) => { const restoreAtom = { read: () => null, write: (_get, set) => { ++inRestoreAtom; try { for (const [atom2, value] of values) { if (hasInitialValue(atom2)) { set(atom2, value); } } } finally { --inRestoreAtom; } } }; savedStoreSet(restoreAtom); } }; return Object.assign(derivedStore, devStore); }; var createStore = () => { const atomStateMap = /* @__PURE__ */ new WeakMap(); const store = buildStore( (atom2) => atomStateMap.get(atom2), (atom2, atomState) => atomStateMap.set(atom2, atomState).get(atom2), (atom2, ...params) => atom2.read(...params), (atom2, ...params) => atom2.write(...params), (atom2, ...params) => { var _a; return (_a = atom2.unstable_onInit) == null ? void 0 : _a.call(atom2, ...params); }, (atom2, ...params) => { var _a; return (_a = atom2.onMount) == null ? void 0 : _a.call(atom2, ...params); } ); if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production") { return deriveDevStoreRev4(store); } return store; }; var defaultStore; var getDefaultStore = () => { if (!defaultStore) { defaultStore = createStore(); if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production") { globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore); if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) { console.warn( "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044" ); } } } return defaultStore; }; // ../../node_modules/jotai/esm/react.mjs import ReactExports, { createContext, useContext, useRef, createElement, useReducer, useEffect, useDebugValue, useCallback } from "react"; var StoreContext = createContext( void 0 ); var useStore = (options) => { const store = useContext(StoreContext); return (options == null ? void 0 : options.store) || store || getDefaultStore(); }; var Provider = ({ children, store }) => { const storeRef = useRef(void 0); if (!store && !storeRef.current) { storeRef.current = createStore(); } return createElement( StoreContext.Provider, { value: store || storeRef.current }, children ); }; var isPromiseLike2 = (x) => typeof (x == null ? void 0 : x.then) === "function"; var attachPromiseMeta = (promise) => { promise.status = "pending"; promise.then( (v) => { promise.status = "fulfilled"; promise.value = v; }, (e) => { promise.status = "rejected"; promise.reason = e; } ); }; var use = ReactExports.use || ((promise) => { if (promise.status === "pending") { throw promise; } else if (promise.status === "fulfilled") { return promise.value; } else if (promise.status === "rejected") { throw promise.reason; } else { attachPromiseMeta(promise); throw promise; } }); var continuablePromiseMap = /* @__PURE__ */ new WeakMap(); var createContinuablePromise = (promise) => { let continuablePromise = continuablePromiseMap.get(promise); if (!continuablePromise) { continuablePromise = new Promise((resolve, reject) => { let curr = promise; const onFulfilled = (me) => (v) => { if (curr === me) { resolve(v); } }; const onRejected = (me) => (e) => { if (curr === me) { reject(e); } }; const registerCancelHandler = (p) => { if ("onCancel" in p && typeof p.onCancel === "function") { p.onCancel((nextValue) => { if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && nextValue === p) { throw new Error("[Bug] p is not updated even after cancelation"); } if (isPromiseLike2(nextValue)) { continuablePromiseMap.set(nextValue, continuablePromise); curr = nextValue; nextValue.then(onFulfilled(nextValue), onRejected(nextValue)); registerCancelHandler(nextValue); } else { resolve(nextValue); } }); } }; promise.then(onFulfilled(promise), onRejected(promise)); registerCancelHandler(promise); }); continuablePromiseMap.set(promise, continuablePromise); } return continuablePromise; }; function useAtomValue(atom2, options) { const store = useStore(options); const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = useReducer( (prev) => { const nextValue = store.get(atom2); if (Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom2) { return prev; } return [nextValue, store, atom2]; }, void 0, () => [store.get(atom2), store, atom2] ); let value = valueFromReducer; if (storeFromReducer !== store || atomFromReducer !== atom2) { rerender(); value = store.get(atom2); } const delay = options == null ? void 0 : options.delay; useEffect(() => { const unsub = store.sub(atom2, () => { if (typeof delay === "number") { const value2 = store.get(atom2); if (isPromiseLike2(value2)) { attachPromiseMeta(createContinuablePromise(value2)); } setTimeout(rerender, delay); return; } rerender(); }); rerender(); return unsub; }, [store, atom2, delay]); useDebugValue(value); if (isPromiseLike2(value)) { const promise = createContinuablePromise(value); return use(promise); } return value; } function useSetAtom(atom2, options) { const store = useStore(options); const setAtom = useCallback( (...args) => { if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && !("write" in atom2)) { throw new Error("not writable atom"); } return store.set(atom2, ...args); }, [store, atom2] ); return setAtom; } function useAtom(atom2, options) { return [ useAtomValue(atom2, options), // We do wrong type assertion here, which results in throwing an error. useSetAtom(atom2, options) ]; } // src/EmojiPicker/EmojiPickerSkinTone.tsx import { useState } from "react"; // ../../node_modules/unicode-emoji-json/data-by-group.json var data_by_group_default = [ { name: "Smileys & Emotion", slug: "smileys_emotion", emojis: [ { emoji: "\u{1F600}", skin_tone_support: false, name: "grinning face", slug: "grinning_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F603}", skin_tone_support: false, name: "grinning face with big eyes", slug: "grinning_face_with_big_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F604}", skin_tone_support: false, name: "grinning face with smiling eyes", slug: "grinning_face_with_smiling_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F601}", skin_tone_support: false, name: "beaming face with smiling eyes", slug: "beaming_face_with_smiling_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F606}", skin_tone_support: false, name: "grinning squinting face", slug: "grinning_squinting_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F605}", skin_tone_support: false, name: "grinning face with sweat", slug: "grinning_face_with_sweat", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F923}", skin_tone_support: false, name: "rolling on the floor laughing", slug: "rolling_on_the_floor_laughing", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1F602}", skin_tone_support: false, name: "face with tears of joy", slug: "face_with_tears_of_joy", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F642}", skin_tone_support: false, name: "slightly smiling face", slug: "slightly_smiling_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F643}", skin_tone_support: false, name: "upside-down face", slug: "upside_down_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1FAE0}", skin_tone_support: false, name: "melting face", slug: "melting_face", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1F609}", skin_tone_support: false, name: "winking face", slug: "winking_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F60A}", skin_tone_support: false, name: "smiling face with smiling eyes", slug: "smiling_face_with_smiling_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F607}", skin_tone_support: false, name: "smiling face with halo", slug: "smiling_face_with_halo", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F970}", skin_tone_support: false, name: "smiling face with hearts", slug: "smiling_face_with_hearts", unicode_version: "11.0", emoji_version: "11.0" }, { emoji: "\u{1F60D}", skin_tone_support: false, name: "smiling face with heart-eyes", slug: "smiling_face_with_heart_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F929}", skin_tone_support: false, name: "star-struck", slug: "star_struck", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F618}", skin_tone_support: false, name: "face blowing a kiss", slug: "face_blowing_a_kiss", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F617}", skin_tone_support: false, name: "kissing face", slug: "kissing_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u263A\uFE0F", skin_tone_support: false, name: "smiling face", slug: "smiling_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F61A}", skin_tone_support: false, name: "kissing face with closed eyes", slug: "kissing_face_with_closed_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F619}", skin_tone_support: false, name: "kissing face with smiling eyes", slug: "kissing_face_with_smiling_eyes", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F972}", skin_tone_support: false, name: "smiling face with tear", slug: "smiling_face_with_tear", unicode_version: "13.0", emoji_version: "13.0" }, { emoji: "\u{1F60B}", skin_tone_support: false, name: "face savoring food", slug: "face_savoring_food", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F61B}", skin_tone_support: false, name: "face with tongue", slug: "face_with_tongue", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F61C}", skin_tone_support: false, name: "winking face with tongue", slug: "winking_face_with_tongue", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F92A}", skin_tone_support: false, name: "zany face", slug: "zany_face", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F61D}", skin_tone_support: false, name: "squinting face with tongue", slug: "squinting_face_with_tongue", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F911}", skin_tone_support: false, name: "money-mouth face", slug: "money_mouth_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F917}", skin_tone_support: false, name: "smiling face with open hands", slug: "smiling_face_with_open_hands", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F92D}", skin_tone_support: false, name: "face with hand over mouth", slug: "face_with_hand_over_mouth", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1FAE2}", skin_tone_support: false, name: "face with open eyes and hand over mouth", slug: "face_with_open_eyes_and_hand_over_mouth", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1FAE3}", skin_tone_support: false, name: "face with peeking eye", slug: "face_with_peeking_eye", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1F92B}", skin_tone_support: false, name: "shushing face", slug: "shushing_face", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F914}", skin_tone_support: false, name: "thinking face", slug: "thinking_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1FAE1}", skin_tone_support: false, name: "saluting face", slug: "saluting_face", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1F910}", skin_tone_support: false, name: "zipper-mouth face", slug: "zipper_mouth_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F928}", skin_tone_support: false, name: "face with raised eyebrow", slug: "face_with_raised_eyebrow", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F610}", skin_tone_support: false, name: "neutral face", slug: "neutral_face", unicode_version: "0.7", emoji_version: "0.7" }, { emoji: "\u{1F611}", skin_tone_support: false, name: "expressionless face", slug: "expressionless_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F636}", skin_tone_support: false, name: "face without mouth", slug: "face_without_mouth", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1FAE5}", skin_tone_support: false, name: "dotted line face", slug: "dotted_line_face", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1F636}\u200D\u{1F32B}\uFE0F", skin_tone_support: false, name: "face in clouds", slug: "face_in_clouds", unicode_version: "13.1", emoji_version: "13.1" }, { emoji: "\u{1F60F}", skin_tone_support: false, name: "smirking face", slug: "smirking_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F612}", skin_tone_support: false, name: "unamused face", slug: "unamused_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F644}", skin_tone_support: false, name: "face with rolling eyes", slug: "face_with_rolling_eyes", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F62C}", skin_tone_support: false, name: "grimacing face", slug: "grimacing_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F62E}\u200D\u{1F4A8}", skin_tone_support: false, name: "face exhaling", slug: "face_exhaling", unicode_version: "13.1", emoji_version: "13.1" }, { emoji: "\u{1F925}", skin_tone_support: false, name: "lying face", slug: "lying_face", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1FAE8}", skin_tone_support: false, name: "shaking face", slug: "shaking_face", unicode_version: "15.0", emoji_version: "15.0" }, { emoji: "\u{1F642}\u200D\u2194\uFE0F", skin_tone_support: false, name: "head shaking horizontally", slug: "head_shaking_horizontally", unicode_version: "15.1", emoji_version: "15.1" }, { emoji: "\u{1F642}\u200D\u2195\uFE0F", skin_tone_support: false, name: "head shaking vertically", slug: "head_shaking_vertically", unicode_version: "15.1", emoji_version: "15.1" }, { emoji: "\u{1F60C}", skin_tone_support: false, name: "relieved face", slug: "relieved_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F614}", skin_tone_support: false, name: "pensive face", slug: "pensive_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F62A}", skin_tone_support: false, name: "sleepy face", slug: "sleepy_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F924}", skin_tone_support: false, name: "drooling face", slug: "drooling_face", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1F634}", skin_tone_support: false, name: "sleeping face", slug: "sleeping_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1FAE9}", skin_tone_support: false, name: "face with bags under eyes", slug: "face_with_bags_under_eyes", unicode_version: "16.0", emoji_version: "16.0" }, { emoji: "\u{1F637}", skin_tone_support: false, name: "face with medical mask", slug: "face_with_medical_mask", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F912}", skin_tone_support: false, name: "face with thermometer", slug: "face_with_thermometer", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F915}", skin_tone_support: false, name: "face with head-bandage", slug: "face_with_head_bandage", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F922}", skin_tone_support: false, name: "nauseated face", slug: "nauseated_face", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1F92E}", skin_tone_support: false, name: "face vomiting", slug: "face_vomiting", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F927}", skin_tone_support: false, name: "sneezing face", slug: "sneezing_face", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1F975}", skin_tone_support: false, name: "hot face", slug: "hot_face", unicode_version: "11.0", emoji_version: "11.0" }, { emoji: "\u{1F976}", skin_tone_support: false, name: "cold face", slug: "cold_face", unicode_version: "11.0", emoji_version: "11.0" }, { emoji: "\u{1F974}", skin_tone_support: false, name: "woozy face", slug: "woozy_face", unicode_version: "11.0", emoji_version: "11.0" }, { emoji: "\u{1F635}", skin_tone_support: false, name: "face with crossed-out eyes", slug: "face_with_crossed_out_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F635}\u200D\u{1F4AB}", skin_tone_support: false, name: "face with spiral eyes", slug: "face_with_spiral_eyes", unicode_version: "13.1", emoji_version: "13.1" }, { emoji: "\u{1F92F}", skin_tone_support: false, name: "exploding head", slug: "exploding_head", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F920}", skin_tone_support: false, name: "cowboy hat face", slug: "cowboy_hat_face", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1F973}", skin_tone_support: false, name: "partying face", slug: "partying_face", unicode_version: "11.0", emoji_version: "11.0" }, { emoji: "\u{1F978}", skin_tone_support: false, name: "disguised face", slug: "disguised_face", unicode_version: "13.0", emoji_version: "13.0" }, { emoji: "\u{1F60E}", skin_tone_support: false, name: "smiling face with sunglasses", slug: "smiling_face_with_sunglasses", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F913}", skin_tone_support: false, name: "nerd face", slug: "nerd_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F9D0}", skin_tone_support: false, name: "face with monocle", slug: "face_with_monocle", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F615}", skin_tone_support: false, name: "confused face", slug: "confused_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1FAE4}", skin_tone_support: false, name: "face with diagonal mouth", slug: "face_with_diagonal_mouth", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1F61F}", skin_tone_support: false, name: "worried face", slug: "worried_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F641}", skin_tone_support: false, name: "slightly frowning face", slug: "slightly_frowning_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u2639\uFE0F", skin_tone_support: false, name: "frowning face", slug: "frowning_face", unicode_version: "0.7", emoji_version: "0.7" }, { emoji: "\u{1F62E}", skin_tone_support: false, name: "face with open mouth", slug: "face_with_open_mouth", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F62F}", skin_tone_support: false, name: "hushed face", slug: "hushed_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F632}", skin_tone_support: false, name: "astonished face", slug: "astonished_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F633}", skin_tone_support: false, name: "flushed face", slug: "flushed_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F97A}", skin_tone_support: false, name: "pleading face", slug: "pleading_face", unicode_version: "11.0", emoji_version: "11.0" }, { emoji: "\u{1F979}", skin_tone_support: false, name: "face holding back tears", slug: "face_holding_back_tears", unicode_version: "14.0", emoji_version: "14.0" }, { emoji: "\u{1F626}", skin_tone_support: false, name: "frowning face with open mouth", slug: "frowning_face_with_open_mouth", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F627}", skin_tone_support: false, name: "anguished face", slug: "anguished_face", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F628}", skin_tone_support: false, name: "fearful face", slug: "fearful_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F630}", skin_tone_support: false, name: "anxious face with sweat", slug: "anxious_face_with_sweat", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F625}", skin_tone_support: false, name: "sad but relieved face", slug: "sad_but_relieved_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F622}", skin_tone_support: false, name: "crying face", slug: "crying_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F62D}", skin_tone_support: false, name: "loudly crying face", slug: "loudly_crying_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F631}", skin_tone_support: false, name: "face screaming in fear", slug: "face_screaming_in_fear", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F616}", skin_tone_support: false, name: "confounded face", slug: "confounded_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F623}", skin_tone_support: false, name: "persevering face", slug: "persevering_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F61E}", skin_tone_support: false, name: "disappointed face", slug: "disappointed_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F613}", skin_tone_support: false, name: "downcast face with sweat", slug: "downcast_face_with_sweat", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F629}", skin_tone_support: false, name: "weary face", slug: "weary_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F62B}", skin_tone_support: false, name: "tired face", slug: "tired_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F971}", skin_tone_support: false, name: "yawning face", slug: "yawning_face", unicode_version: "12.0", emoji_version: "12.0" }, { emoji: "\u{1F624}", skin_tone_support: false, name: "face with steam from nose", slug: "face_with_steam_from_nose", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F621}", skin_tone_support: false, name: "enraged face", slug: "enraged_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F620}", skin_tone_support: false, name: "angry face", slug: "angry_face", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F92C}", skin_tone_support: false, name: "face with symbols on mouth", slug: "face_with_symbols_on_mouth", unicode_version: "5.0", emoji_version: "5.0" }, { emoji: "\u{1F608}", skin_tone_support: false, name: "smiling face with horns", slug: "smiling_face_with_horns", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F47F}", skin_tone_support: false, name: "angry face with horns", slug: "angry_face_with_horns", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F480}", skin_tone_support: false, name: "skull", slug: "skull", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u2620\uFE0F", skin_tone_support: false, name: "skull and crossbones", slug: "skull_and_crossbones", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F4A9}", skin_tone_support: false, name: "pile of poo", slug: "pile_of_poo", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F921}", skin_tone_support: false, name: "clown face", slug: "clown_face", unicode_version: "3.0", emoji_version: "3.0" }, { emoji: "\u{1F479}", skin_tone_support: false, name: "ogre", slug: "ogre", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F47A}", skin_tone_support: false, name: "goblin", slug: "goblin", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F47B}", skin_tone_support: false, name: "ghost", slug: "ghost", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F47D}", skin_tone_support: false, name: "alien", slug: "alien", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F47E}", skin_tone_support: false, name: "alien monster", slug: "alien_monster", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F916}", skin_tone_support: false, name: "robot", slug: "robot", unicode_version: "1.0", emoji_version: "1.0" }, { emoji: "\u{1F63A}", skin_tone_support: false, name: "grinning cat", slug: "grinning_cat", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F638}", skin_tone_support: false, name: "grinning cat with smiling eyes", slug: "grinning_cat_with_smiling_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F639}", skin_tone_support: false, name: "cat with tears of joy", slug: "cat_with_tears_of_joy", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F63B}", skin_tone_support: false, name: "smiling cat with heart-eyes", slug: "smiling_cat_with_heart_eyes", unicode_version: "0.6", emoji_version: "0.6" }, { emoji: "\u{1F63C}", skin_tone_support: false, name: "cat with wry smile", slug: "cat_with_wry_smile", unicode_version: "0.