Replace picmo with emoji-mart (#4001)

* Add emoji-mart deps

* Change EmojiPicker to use emoji-mart

* Change ChatTextField to work with the emoji-mart data object

* Remove picmo, commit package-lock

* Fix mutant svgs having a size of 0

* Get the custom emojis to show up earlier in the picker

* Set emoji-mart to exact semver. Later versions break custom category sorting.
This commit is contained in:
mahmed2000 2024-11-09 21:58:38 +00:00 committed by GitHub
parent f215809f1d
commit eca880ac1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 72 additions and 70 deletions

View file

@ -152,15 +152,14 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, fo
contentEditable.innerHTML += textToInsert; contentEditable.innerHTML += textToInsert;
}; };
// Native emoji const onEmojiSelect = emoji => {
const onEmojiSelect = (emoji: string) => { if (emoji.native) {
insertTextAtEnd(emoji); insertTextAtEnd(emoji.native);
}; } else {
// Custom emoji images
// Custom emoji images const html = `<img src="${emoji.src}" alt=":${emoji.name}:" title=":${emoji.name}:" class="emoji" />`;
const onCustomEmojiSelect = (name: string, emoji: string) => { insertTextAtEnd(html);
const html = `<img src="${emoji}" alt=":${name}:" title=":${name}:" class="emoji" />`; }
insertTextAtEnd(html);
}; };
const onKeyDown = (e: React.KeyboardEvent) => { const onKeyDown = (e: React.KeyboardEvent) => {
@ -277,13 +276,7 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, fo
{enabled && ( {enabled && (
<div style={{ display: 'flex', paddingLeft: '5px' }}> <div style={{ display: 'flex', paddingLeft: '5px' }}>
<Popover <Popover
content={ content={<EmojiPicker customEmoji={customEmoji} onEmojiSelect={onEmojiSelect} />}
<EmojiPicker
customEmoji={customEmoji}
onEmojiSelect={onEmojiSelect}
onCustomEmojiSelect={onCustomEmojiSelect}
/>
}
trigger="click" trigger="click"
placement="topRight" placement="topRight"
> >

View file

@ -1,42 +1,44 @@
import React, { FC, useEffect, useRef } from 'react'; import React, { FC, useEffect, useState } from 'react';
import { createPicker } from 'picmo'; import Picker from '@emoji-mart/react';
import data from '@emoji-mart/data';
export type EmojiPickerProps = { export type EmojiPickerProps = {
onEmojiSelect: (emoji: string) => void; onEmojiSelect: (emoji) => void;
onCustomEmojiSelect: (name: string, url: string) => void;
customEmoji: any[]; customEmoji: any[];
}; };
export const EmojiPicker: FC<EmojiPickerProps> = ({ export const EmojiPicker: FC<EmojiPickerProps> = ({ onEmojiSelect, customEmoji }) => {
onEmojiSelect, const [custom, setCustom] = useState({});
onCustomEmojiSelect, const categories = [
customEmoji, 'frequent',
}) => { 'custom', // same id as in the setCustom call below
const ref = useRef(); 'people',
'nature',
'foods',
'activity',
'places',
'objects',
'symbols',
'flags',
];
// Recreate the emoji picker when the custom emoji changes. // Recreate the emoji picker when the custom emoji changes.
useEffect(() => { useEffect(() => {
const e = customEmoji.map(emoji => ({ const e = customEmoji.map(emoji => ({
emoji: emoji.name, id: emoji.name,
label: emoji.name, name: emoji.name,
url: emoji.url, skins: [{ src: emoji.url }],
})); }));
const picker = createPicker({ setCustom([{ id: 'custom', name: 'Custom', emojis: e }]);
rootElement: ref.current,
custom: e, // hack to make the picker work with viewbox only svgs, 24px is default size
initialCategory: 'custom', const shadow = document.querySelector('em-emoji-picker').shadowRoot;
showPreview: false, const pickerStyles = new CSSStyleSheet();
showRecents: true, pickerStyles.replaceSync('.emoji-mart-emoji {width: 24px;}');
}); shadow.adoptedStyleSheets = [pickerStyles];
picker.addEventListener('emoji:select', event => {
if (event.url) {
onCustomEmojiSelect(event.label, event.url);
} else {
onEmojiSelect(event.emoji);
}
});
}, []); }, []);
return <div ref={ref} />; return (
<Picker data={data} custom={custom} onEmojiSelect={onEmojiSelect} categories={categories} />
);
}; };

49
web/package-lock.json generated
View file

@ -14,6 +14,8 @@
"@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-javascript": "^6.1.2",
"@codemirror/lang-markdown": "6.3.1", "@codemirror/lang-markdown": "6.3.1",
"@codemirror/language-data": "6.5.1", "@codemirror/language-data": "6.5.1",
"@emoji-mart/data": "^1.2.1",
"@emoji-mart/react": "^1.1.1",
"@fontsource/inter": "^5.0.0", "@fontsource/inter": "^5.0.0",
"@fontsource/poppins": "5.1.0", "@fontsource/poppins": "5.1.0",
"@next/bundle-analyzer": "^14.0.0", "@next/bundle-analyzer": "^14.0.0",
@ -33,7 +35,6 @@
"next": "14.2.17", "next": "14.2.17",
"next-pwa": "^5.6.0", "next-pwa": "^5.6.0",
"next-with-less": "3.0.1", "next-with-less": "3.0.1",
"picmo": "5.8.5",
"postcss-flexbugs-fixes": "5.0.2", "postcss-flexbugs-fixes": "5.0.2",
"react": "18.3.1", "react": "18.3.1",
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",
@ -3278,6 +3279,22 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@emoji-mart/data": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz",
"integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==",
"license": "MIT"
},
"node_modules/@emoji-mart/react": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@emoji-mart/react/-/react-1.1.1.tgz",
"integrity": "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==",
"license": "MIT",
"peerDependencies": {
"emoji-mart": "^5.2",
"react": "^16.8 || ^17 || ^18"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.24.0", "version": "0.24.0",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz",
@ -14563,6 +14580,13 @@
"url": "https://github.com/sindresorhus/emittery?sponsor=1" "url": "https://github.com/sindresorhus/emittery?sponsor=1"
} }
}, },
"node_modules/emoji-mart": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.2.2.tgz",
"integrity": "sha512-BvcrX+Ps9MxSVEjnvxupclU3MBD6WVC4WZOY26csfC6oFdaWpFhdrzeVNVBmCLPOmzY1SE0aAsqZJRNVbZ1yhQ==",
"license": "MIT",
"peer": true
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@ -14570,16 +14594,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/emojibase": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz",
"integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ==",
"license": "MIT",
"funding": {
"type": "ko-fi",
"url": "https://ko-fi.com/milesjohnson"
}
},
"node_modules/emojis-list": { "node_modules/emojis-list": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
@ -32757,19 +32771,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/picmo": {
"version": "5.8.5",
"resolved": "https://registry.npmjs.org/picmo/-/picmo-5.8.5.tgz",
"integrity": "sha512-7I8jfuHALF9lkt3d+XCZGP+IwH7g91vYZv6XtRnJ99IDjnm92zel0L5DEo2FX0oaHUwRMBD/kn2knTZqwItudQ==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT",
"dependencies": {
"emojibase": "^6.1.0"
},
"funding": {
"url": "https://github.com/sponsors/joeattardi"
}
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",

View file

@ -23,6 +23,8 @@
"@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-javascript": "^6.1.2",
"@codemirror/lang-markdown": "6.3.1", "@codemirror/lang-markdown": "6.3.1",
"@codemirror/language-data": "6.5.1", "@codemirror/language-data": "6.5.1",
"@emoji-mart/data": "^1.2.1",
"@emoji-mart/react": "^1.1.1",
"@fontsource/inter": "^5.0.0", "@fontsource/inter": "^5.0.0",
"@fontsource/poppins": "5.1.0", "@fontsource/poppins": "5.1.0",
"@next/bundle-analyzer": "^14.0.0", "@next/bundle-analyzer": "^14.0.0",
@ -42,7 +44,6 @@
"next": "14.2.17", "next": "14.2.17",
"next-pwa": "^5.6.0", "next-pwa": "^5.6.0",
"next-with-less": "3.0.1", "next-with-less": "3.0.1",
"picmo": "5.8.5",
"postcss-flexbugs-fixes": "5.0.2", "postcss-flexbugs-fixes": "5.0.2",
"react": "18.3.1", "react": "18.3.1",
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",
@ -137,5 +138,10 @@
"stylelint-config-standard-scss": "^13.0.0", "stylelint-config-standard-scss": "^13.0.0",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",
"typescript": "5.6.3" "typescript": "5.6.3"
},
"overrides": {
"@emoji-mart/react": {
"emoji-mart": "~5.2.2"
}
} }
} }