diff --git a/CHANGELOG.md b/CHANGELOG.md index 7141eaa0b..d024be730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,7 @@ - HedgeDoc instances can now be branded either with a '@ ' or '@ ' after the HedgeDoc logo and text - Images will be loaded via proxy if an image proxy is configured in the backend - Asciinema videos may now be embedded by pasting the URL of one video into a single line -- The toolbar includes an EmojiPicker +- The toolbar includes an emoji and fork-awesome icon picker. - Collapsable blocks can be added via a toolbar button or via autocompletion of " [ diff --git a/cypress/integration/autocompletion.spec.ts b/cypress/integration/autocompletion.spec.ts index b3f4d54f4..c2d26f613 100644 --- a/cypress/integration/autocompletion.spec.ts +++ b/cypress/integration/autocompletion.spec.ts @@ -80,7 +80,7 @@ describe('Autocompletion', () => { describe('normal emoji', () => { it('via Enter', () => { cy.get('.CodeMirror textarea') - .type(':book') + .type(':hedg') cy.get('.CodeMirror-hints') .should('exist') cy.get('.CodeMirror textarea') @@ -88,29 +88,29 @@ describe('Autocompletion', () => { cy.get('.CodeMirror-hints') .should('not.exist') cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', ':book:') + .should('have.text', ':hedgehog:') cy.get('.markdown-body') - .should('have.text', '📖') + .should('have.text', '🦔') }) it('via doubleclick', () => { cy.get('.CodeMirror textarea') - .type(':book') + .type(':hedg') cy.get('.CodeMirror-hints > li') .first() .dblclick() cy.get('.CodeMirror-hints') .should('not.exist') cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', ':book:') + .should('have.text', ':hedgehog:') cy.get('.markdown-body') - .should('have.text', '📖') + .should('have.text', '🦔') }) }) describe('fork-awesome-icon', () => { it('via Enter', () => { cy.get('.CodeMirror textarea') - .type(':facebook') + .type(':fa-face') cy.get('.CodeMirror-hints') .should('exist') cy.get('.CodeMirror textarea') @@ -124,7 +124,7 @@ describe('Autocompletion', () => { }) it('via doubleclick', () => { cy.get('.CodeMirror textarea') - .type(':facebook') + .type(':fa-face') cy.get('.CodeMirror-hints > li') .first() .dblclick() diff --git a/cypress/integration/toolbar.spec.ts b/cypress/integration/toolbar.spec.ts index 4cc62e835..c50856ca6 100644 --- a/cypress/integration/toolbar.spec.ts +++ b/cypress/integration/toolbar.spec.ts @@ -275,28 +275,14 @@ describe('Toolbar', () => { .should('have.text', '> []') }) - describe('emoji', () => { - it('picker is show when clicked', () => { - cy.get('.emoji-mart') - .should('not.exist') + describe('emoji-picker', () => { + it('show when clicked', () => { + cy.get('emoji-picker') + .should('not.be.visible') cy.get('.fa-smile-o') .click() - cy.get('.emoji-mart') - .should('exist') - }) - - it('picker is show when clicked', () => { - cy.get('.fa-smile-o') - .click() - cy.get('.emoji-mart') - .should('exist') - cy.get('.emoji-mart-emoji-native') - .first() - .click() - cy.get('.markdown-body') - .should('have.text', '👍') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span ') - .should('have.text', ':+1:') + cy.get('emoji-picker') + .should('be.visible') }) }) diff --git a/package.json b/package.json index a2d8aa999..9bb699330 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "@types/d3-graphviz": "2.6.6", "@types/diff": "4.0.2", "@types/domhandler": "2.4.1", - "@types/emoji-mart": "3.0.2", "@types/highlight.js": "9.12.4", "@types/jest": "26.0.14", "@types/js-yaml": "3.12.5", @@ -41,7 +40,8 @@ "copy-webpack-plugin": "6.2.1", "d3-graphviz": "3.1.0", "diff": "4.0.2", - "emoji-mart": "3.0.0", + "emoji-picker-element": "^1.2.1", + "emojibase-data": "5", "eslint-config-react-app": "5.2.1", "eslint-config-standard": "14.1.1", "eslint-plugin-flowtype": "5.2.0", diff --git a/src/components/editor/editor-pane/autocompletion/emoji.ts b/src/components/editor/editor-pane/autocompletion/emoji.ts index 41fcfc5b3..038161db9 100644 --- a/src/components/editor/editor-pane/autocompletion/emoji.ts +++ b/src/components/editor/editor-pane/autocompletion/emoji.ts @@ -1,11 +1,14 @@ import { Editor, Hint, Hints, Pos } from 'codemirror' -import { Data, EmojiData, NimbleEmojiIndex } from 'emoji-mart' -import data from 'emoji-mart/data/twitter.json' +import Database from 'emoji-picker-element/database' +import { Emoji, EmojiClickEventDetail, NativeEmoji } from 'emoji-picker-element/shared' import { customEmojis } from '../tool-bar/emoji-picker/emoji-picker' import { getEmojiIcon, getEmojiShortCode } from '../tool-bar/utils/emojiUtils' import { findWordAtCursor, Hinter } from './index' -const emojiIndex = new NimbleEmojiIndex(data as unknown as Data) +const emojiIndex = new Database({ + customEmoji: customEmojis, + dataSource: '/static/js/emoji-data.json' +}) const emojiWordRegex = /^:([\w-_+]*)$/ const generateEmojiHints = (editor: Editor): Promise< Hints| null > => { @@ -17,34 +20,40 @@ const generateEmojiHints = (editor: Editor): Promise< Hints| null > => { return } const term = searchResult[1] - let search: EmojiData[] | null = emojiIndex.search(term, { - emojisToShowFilter: () => true, - maxResults: 7, - include: [], - exclude: [], - custom: customEmojis as EmojiData[] - }) - if (search === null) { - // set search to the first seven emojis in data - search = Object.values(emojiIndex.emojis).slice(0, 7) - } - const cursor = editor.getCursor() - if (!search) { - resolve(null) - } else { - resolve({ - list: search.map((emojiData): Hint => ({ - text: getEmojiShortCode(emojiData), - render: (parent: HTMLLIElement) => { - const wrapper = document.createElement('div') - wrapper.innerHTML = `${getEmojiIcon(emojiData)} ${getEmojiShortCode(emojiData)}` - parent.appendChild(wrapper) + let suggestionList: Emoji[] + emojiIndex.getEmojiBySearchQuery(term) + .then(async (result) => { + suggestionList = result + if (result.length === 0) { + suggestionList = await emojiIndex.getTopFavoriteEmoji(7) + } + const cursor = editor.getCursor() + const skinTone = await emojiIndex.getPreferredSkinTone() + const emojiEventDetails: EmojiClickEventDetail[] = suggestionList.map((emoji) => { + return { + emoji, + skinTone: skinTone, + unicode: ((emoji as NativeEmoji).unicode ? (emoji as NativeEmoji).unicode : undefined), + name: emoji.name } - })), - from: Pos(cursor.line, searchTerm.start), - to: Pos(cursor.line, searchTerm.end) + }) + resolve({ + list: emojiEventDetails.map((emojiData): Hint => ({ + text: getEmojiShortCode(emojiData), + render: (parent: HTMLLIElement) => { + const wrapper = document.createElement('div') + wrapper.innerHTML = `${getEmojiIcon(emojiData)} ${getEmojiShortCode(emojiData)}` + parent.appendChild(wrapper) + } + })), + from: Pos(cursor.line, searchTerm.start), + to: Pos(cursor.line, searchTerm.end) + }) + }) + .catch(error => { + console.error(error) + resolve(null) }) - } }) } diff --git a/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker-button.tsx b/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker-button.tsx index 214fe69b0..0e32379cb 100644 --- a/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker-button.tsx +++ b/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker-button.tsx @@ -16,10 +16,13 @@ export const EmojiPickerButton: React.FC = ({ editor }) return ( - { - setShowEmojiPicker(false) - addEmoji(emoji, editor) - }} onDismiss={() => setShowEmojiPicker(false)}/> + { + setShowEmojiPicker(false) + addEmoji(emoji, editor) + }} + onDismiss={() => setShowEmojiPicker(false)}/> diff --git a/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.scss b/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.scss index 63b5a7b17..07b4d9e88 100644 --- a/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.scss +++ b/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.scss @@ -1,10 +1,3 @@ -@import '../../../../../../node_modules/emoji-mart/css/emoji-mart'; - -.emoji-mart { - position: absolute; - z-index: 10000; -} - -.emoji-mart-emoji-native { - font-family: "twemoji", monospace; +.emoji-picker-container { + z-index: 1111; } diff --git a/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.tsx b/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.tsx index b81bbabac..3b981083f 100644 --- a/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.tsx +++ b/src/components/editor/editor-pane/tool-bar/emoji-picker/emoji-picker.tsx @@ -1,47 +1,81 @@ -import { CustomEmoji, Data, EmojiData, NimblePicker } from 'emoji-mart' -import emojiData from 'emoji-mart/data/twitter.json' -import React, { useRef } from 'react' +import { Picker } from 'emoji-picker-element' +import { CustomEmoji, EmojiClickEvent, EmojiClickEventDetail } from 'emoji-picker-element/shared' +import React, { useCallback, useEffect, useMemo, useRef } from 'react' +import { useSelector } from 'react-redux' import { useClickAway } from 'react-use' -import { ShowIf } from '../../../../common/show-if/show-if' +import { ApplicationState } from '../../../../../redux' import './emoji-picker.scss' import forkawesomeIcon from './forkawesome.png' import { ForkAwesomeIcons } from './icon-names' export interface EmojiPickerProps { show: boolean - onEmojiSelected: (emoji: EmojiData) => void + onEmojiSelected: (emoji: EmojiClickEventDetail) => void onDismiss: () => void } export const customEmojis: CustomEmoji[] = Object.keys(ForkAwesomeIcons).map((name) => ({ name: `fa-${name}`, - short_names: [`fa-${name.toLowerCase()}`], - text: '', - emoticons: [], - keywords: ['fork awesome'], - imageUrl: forkawesomeIcon, - customCategory: 'ForkAwesome' + shortcodes: [`fa-${name.toLowerCase()}`], + url: forkawesomeIcon, + category: 'ForkAwesome' })) export const EmojiPicker: React.FC = ({ show, onEmojiSelected, onDismiss }) => { - const pickerRef = useRef(null) + const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode) + const pickerContainerRef = useRef(null) + const firstOpened = useRef(false) - useClickAway(pickerRef, () => { + useClickAway(pickerContainerRef, () => { onDismiss() }) + const emojiClickListener = useCallback((event) => { + onEmojiSelected((event as EmojiClickEvent).detail) + }, [onEmojiSelected]) + + const twemojiStyle = useMemo(() => { + const style = document.createElement('style') + style.textContent = 'section.picker { --font-family: "twemoji" !important; }' + return style + }, []) + + useEffect(() => { + if (!pickerContainerRef.current || firstOpened.current) { + return + } + const picker = new Picker({ + customEmoji: customEmojis, + dataSource: '/static/js/emoji-data.json' + }) + const container = pickerContainerRef.current + picker.addEventListener('emoji-click', emojiClickListener) + if (picker.shadowRoot) { + picker.shadowRoot.appendChild(twemojiStyle) + } + container.appendChild(picker) + firstOpened.current = true + }, [pickerContainerRef, emojiClickListener, darkModeEnabled, twemojiStyle]) + + useEffect(() => { + if (!pickerContainerRef.current) { + return + } + const pickerDomList = pickerContainerRef.current.getElementsByTagName('emoji-picker') + if (pickerDomList.length === 0) { + return + } + const picker = pickerDomList[0] + picker.setAttribute('class', darkModeEnabled ? 'dark' : 'light') + if (darkModeEnabled) { + picker.removeAttribute('style') + } else { + picker.setAttribute('style', '--background: #f8f9fa') + } + }, [darkModeEnabled, pickerContainerRef, firstOpened]) + + // noinspection CheckTagEmptyBody return ( - -
- -
-
+
) } diff --git a/src/components/editor/editor-pane/tool-bar/utils/emojiUtils.ts b/src/components/editor/editor-pane/tool-bar/utils/emojiUtils.ts index e42469da5..55485a318 100644 --- a/src/components/editor/editor-pane/tool-bar/utils/emojiUtils.ts +++ b/src/components/editor/editor-pane/tool-bar/utils/emojiUtils.ts @@ -1,15 +1,20 @@ -import { BaseEmoji, CustomEmoji, EmojiData } from 'emoji-mart' +import { EmojiClickEventDetail, NativeEmoji } from 'emoji-picker-element/shared' -export const getEmojiIcon = (emoji: EmojiData):string => { - if ((emoji as BaseEmoji).native) { - return (emoji as BaseEmoji).native - } else if ((emoji as CustomEmoji).imageUrl) { +export const getEmojiIcon = (emoji: EmojiClickEventDetail): string => { + if (emoji.unicode) { + return emoji.unicode + } + if (emoji.name) { // noinspection CheckTagEmptyBody - return `` + return `` } return '' } -export const getEmojiShortCode = (emoji: EmojiData):string => { - return (emoji as BaseEmoji).colons +export const getEmojiShortCode = (emoji: EmojiClickEventDetail): string => { + let skinToneModifier = '' + if ((emoji.emoji as NativeEmoji).skins && emoji.skinTone !== 0) { + skinToneModifier = `:skin-tone-${emoji.skinTone as number}:` + } + return `:${emoji.emoji.shortcodes[0]}:${skinToneModifier}` } diff --git a/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.test.ts b/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.test.ts index 53c296b15..e857bda78 100644 --- a/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.test.ts +++ b/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.test.ts @@ -1,5 +1,5 @@ -import { Editor, Position, Range } from 'codemirror' -import { EmojiData } from 'emoji-mart' +import CodeMirror, { Editor, Position, Range } from 'codemirror' +import { EmojiClickEventDetail } from 'emoji-picker-element/shared' import { Mock } from 'ts-mockery' import { addCodeFences, @@ -1762,8 +1762,23 @@ describe('test addTable', () => { describe('test addEmoji with native emoji', () => { const { cursor, firstLine, multiline, multilineOffset } = buildRanges() const textFirstLine = testContent.split('\n')[0] - const emoji = Mock.of({ - colons: ':+1:' + const emoji = Mock.of({ + emoji: { + annotation: 'input numbers', + group: 8, + order: 3809, + shortcodes: [ + '1234' + ], + tags: [ + '1234', + 'input', + 'numbers' + ], + unicode: '🔢', + version: 0.6 + }, + unicode: '🔢' }) it('just cursor', done => { Mock.extend(editor).with({ @@ -1778,7 +1793,7 @@ describe('test addEmoji with native emoji', () => { ), getLine: (): string => (textFirstLine), replaceRange: (replacement: string | string[]) => { - expect(replacement).toEqual(':+1:') + expect(replacement).toEqual(':1234:') done() } }) @@ -1800,7 +1815,7 @@ describe('test addEmoji with native emoji', () => { replaceRange: (replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => { expect(from).toEqual(firstLine.from) expect(to).toEqual(firstLine.to) - expect(replacement).toEqual(':+1:') + expect(replacement).toEqual(':1234:') done() } }) @@ -1822,7 +1837,7 @@ describe('test addEmoji with native emoji', () => { replaceRange: (replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => { expect(from).toEqual(multiline.from) expect(to).toEqual(multiline.to) - expect(replacement).toEqual(':+1:') + expect(replacement).toEqual(':1234:') done() } }) @@ -1844,7 +1859,7 @@ describe('test addEmoji with native emoji', () => { replaceRange: (replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => { expect(from).toEqual(multilineOffset.from) expect(to).toEqual(multilineOffset.to) - expect(replacement).toEqual(':+1:') + expect(replacement).toEqual(':1234:') done() } }) @@ -1856,10 +1871,16 @@ describe('test addEmoji with native emoji', () => { const { cursor, firstLine, multiline, multilineOffset } = buildRanges() const textFirstLine = testContent.split('\n')[0] const forkAwesomeIcon = ':fa-star:' - const emoji = Mock.of({ - name: 'star', - colons: ':fa-star:', - imageUrl: '/img/forkawesome.png' + const emoji = Mock.of({ + emoji: { + name: 'fa-star', + shortcodes: [ + 'fa-star' + ], + url: '/img/forkawesome.png' + }, + skinTone: 0, + name: 'fa-star' }) it('just cursor', done => { Mock.extend(editor).with({ diff --git a/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.ts b/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.ts index cfffe1f77..16b6a9eb4 100644 --- a/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.ts +++ b/src/components/editor/editor-pane/tool-bar/utils/toolbarButtonUtils.ts @@ -1,5 +1,5 @@ import { Editor } from 'codemirror' -import { EmojiData } from 'emoji-mart' +import { EmojiClickEventDetail } from 'emoji-picker-element/shared' import { getEmojiShortCode } from './emojiUtils' export const makeSelectionBold = (editor: Editor): void => wrapTextWith(editor, '**') @@ -25,7 +25,7 @@ export const addCollapsableBlock = (editor: Editor): void => changeLines(editor, export const addComment = (editor: Editor): void => changeLines(editor, line => `${line}\n> []`) export const addTable = (editor: Editor): void => changeLines(editor, line => `${line}\n| # 1 | # 2 | # 3 |\n| ---- | ---- | ---- |\n| Text | Text | Text |`) -export const addEmoji = (emoji: EmojiData, editor: Editor): void => { +export const addEmoji = (emoji: EmojiClickEventDetail, editor: Editor): void => { insertAtCursor(editor, getEmojiShortCode(emoji)) } diff --git a/src/components/markdown-renderer/markdown-it-plugins/emoji/mapping.ts b/src/components/markdown-renderer/markdown-it-plugins/emoji/mapping.ts index 79285a6c7..ebc67cc96 100644 --- a/src/components/markdown-renderer/markdown-it-plugins/emoji/mapping.ts +++ b/src/components/markdown-renderer/markdown-it-plugins/emoji/mapping.ts @@ -1,36 +1,40 @@ -import emojiData from 'emoji-mart/data/twitter.json' -import { Data } from 'emoji-mart/dist-es/utils/data' import { ForkAwesomeIcons } from '../../../editor/editor-pane/tool-bar/emoji-picker/icon-names' +import emojiData from 'emojibase-data/en/compact.json' -export const markdownItTwitterEmojis = Object.keys((emojiData as unknown as Data).emojis) - .reduce((reduceObject, emojiIdentifier) => { - const emoji = (emojiData as unknown as Data).emojis[emojiIdentifier] - const emojiCodes = emoji.unified ?? emoji.b - if (emojiCodes) { - reduceObject[emojiIdentifier] = emojiCodes.split('-').map(char => `&#x${char};`).join('') - } +interface EmojiEntry { + shortcodes: string[] + unicode: string +} + +type ShortCodeMap = { [key: string]: string } + +const shortCodeMap = (emojiData as unknown as EmojiEntry[]) + .reduce((reduceObject, emoji) => { + emoji.shortcodes.forEach(shortcode => { + reduceObject[shortcode] = emoji.unicode + }) return reduceObject - }, {} as { [key: string]: string }) + }, {} as ShortCodeMap) -export const emojiSkinToneModifierMap = [2, 3, 4, 5, 6] +const emojiSkinToneModifierMap = [1, 2, 3, 4, 5] .reduce((reduceObject, modifierValue) => { const lightSkinCode = 127995 - const codepoint = lightSkinCode + (modifierValue - 2) + const codepoint = lightSkinCode + (modifierValue - 1) const shortcode = `skin-tone-${modifierValue}` reduceObject[shortcode] = `&#${codepoint};` return reduceObject - }, {} as { [key: string]: string }) + }, {} as ShortCodeMap) -export const forkAwesomeIconMap = Object.keys(ForkAwesomeIcons) +const forkAwesomeIconMap = Object.keys(ForkAwesomeIcons) .reduce((reduceObject, icon) => { const shortcode = `fa-${icon}` // noinspection CheckTagEmptyBody reduceObject[shortcode] = `` return reduceObject - }, {} as { [key: string]: string }) + }, {} as ShortCodeMap) export const combinedEmojiData = { - ...markdownItTwitterEmojis, + ...shortCodeMap, ...emojiSkinToneModifierMap, ...forkAwesomeIconMap } diff --git a/src/external-types/emoji-mart/dist-es/utils/emoji-index/nimble-emoji-index.d.ts b/src/external-types/emoji-mart/dist-es/utils/emoji-index/nimble-emoji-index.d.ts deleted file mode 100644 index ff06da275..000000000 --- a/src/external-types/emoji-mart/dist-es/utils/emoji-index/nimble-emoji-index.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import 'emoji-mart' - -declare module 'emoji-mart' { - export interface SearchOption { - emojisToShowFilter: (emoji: EmojiData) => boolean - maxResults: number, - include: EmojiData[] - exclude: EmojiData[] - custom: EmojiData[] - } - - export class NimbleEmojiIndex { - search (query: string, options: SearchOption): EmojiData[] | null; - } -} diff --git a/yarn.lock b/yarn.lock index b625efa16..64b0970d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2066,13 +2066,6 @@ dependencies: domhandler "^2.4.0" -"@types/emoji-mart@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/emoji-mart/-/emoji-mart-3.0.2.tgz#5814064ce7c622069adf1583e17b3851a00802cb" - integrity sha512-Cmq8xpPK5Va+fjQE7ZaE5oykXzACBQ64CpNnYOIU7gWcR6nYTxWjMR3yPhnAMzw4yQn9R9761FpTvAyi/SH9MQ== - dependencies: - "@types/react" "*" - "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -5755,13 +5748,10 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emoji-mart@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-3.0.0.tgz#eca24a04881e27752a6921e09f65a86ce8539a50" - integrity sha512-r5DXyzOLJttdwRYfJmPq/XL3W5tiAE/VsRnS0Hqyn27SqPA/GOYwVUSx50px/dXdJyDSnvmoPbuJ/zzhwSaU4A== - dependencies: - "@babel/runtime" "^7.0.0" - prop-types "^15.6.0" +emoji-picker-element@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/emoji-picker-element/-/emoji-picker-element-1.2.1.tgz#a8eb99035e07f970c16e202a6e0588dce15dda02" + integrity sha512-gk0NBg7G/S6ClfIUjRKchXLrl4o1dcvKmEamFT9GERHfCeAyi+afUeMhwVY168I65RiqjGCJkGpoTV2CVa2QNA== emoji-regex@^7.0.1, emoji-regex@^7.0.2: version "7.0.3" @@ -5778,6 +5768,11 @@ emoji-regex@^9.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w== +emojibase-data@5: + version "5.1.1" + resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-5.1.1.tgz#0a0d63dd07ce1376b3d27642f28cafa46f651de6" + integrity sha512-za/ma5SfogHjwUmGFnDbTvSfm8GGFvFaPS27GPti16YZSp5EPgz+UDsZCATXvJGit+oRNBbG/FtybXHKi2UQgQ== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -11513,7 +11508,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==