🐛(frontend) fix multiple EmojiPicker
emoji-mart is used to display emojis in the editor. It is used by the callout block and by Blocknotes editor. The problem is that the emoji-mart is a singleton, so if Blocknotes components init the emoji-mart first, the picker in the callout block will not display correctly. This commit fixes the issue by initializing the emoji-mart in the callout block first.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import data from '@emoji-mart/data';
|
||||
import { EmojiMartData } from '@emoji-mart/data';
|
||||
import Picker from '@emoji-mart/react';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -6,19 +6,15 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Box } from '@/components';
|
||||
|
||||
interface EmojiPickerProps {
|
||||
emojiData: EmojiMartData;
|
||||
categories: string[];
|
||||
custom: {
|
||||
name: string;
|
||||
id: string;
|
||||
emojis: string[];
|
||||
}[];
|
||||
onClickOutside: () => void;
|
||||
onEmojiSelect: ({ native }: { native: string }) => void;
|
||||
}
|
||||
|
||||
export const EmojiPicker = ({
|
||||
emojiData,
|
||||
categories,
|
||||
custom,
|
||||
onClickOutside,
|
||||
onEmojiSelect,
|
||||
}: EmojiPickerProps) => {
|
||||
@@ -27,9 +23,8 @@ export const EmojiPicker = ({
|
||||
return (
|
||||
<Box $position="absolute" $zIndex={1000} $margin="2rem 0 0 0">
|
||||
<Picker
|
||||
data={emojiData}
|
||||
categories={categories}
|
||||
custom={custom}
|
||||
data={data}
|
||||
locale={i18n.resolvedLanguage}
|
||||
navPosition="none"
|
||||
onClickOutside={onClickOutside}
|
||||
|
||||
@@ -10,52 +10,7 @@ import { Box, BoxButton, Icon } from '@/components';
|
||||
import { DocsBlockNoteEditor } from '../../types';
|
||||
import { EmojiPicker } from '../EmojiPicker';
|
||||
|
||||
const calloutCustom = [
|
||||
{
|
||||
name: 'Callout',
|
||||
id: 'callout',
|
||||
emojis: [
|
||||
'bulb',
|
||||
'point_right',
|
||||
'point_up',
|
||||
'ok_hand',
|
||||
'key',
|
||||
'construction',
|
||||
'warning',
|
||||
'fire',
|
||||
'pushpin',
|
||||
'scissors',
|
||||
'question',
|
||||
'no_entry',
|
||||
'no_entry_sign',
|
||||
'alarm_clock',
|
||||
'phone',
|
||||
'rotating_light',
|
||||
'recycle',
|
||||
'white_check_mark',
|
||||
'lock',
|
||||
'paperclip',
|
||||
'book',
|
||||
'speaking_head_in_silhouette',
|
||||
'arrow_right',
|
||||
'loudspeaker',
|
||||
'hammer_and_wrench',
|
||||
'gear',
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const calloutCategories = [
|
||||
'callout',
|
||||
'people',
|
||||
'nature',
|
||||
'foods',
|
||||
'activity',
|
||||
'places',
|
||||
'flags',
|
||||
'objects',
|
||||
'symbols',
|
||||
];
|
||||
import InitEmojiCallout from './initEmojiCallout';
|
||||
|
||||
export const CalloutBlock = createReactBlockSpec(
|
||||
{
|
||||
@@ -124,8 +79,8 @@ export const CalloutBlock = createReactBlockSpec(
|
||||
|
||||
{openEmojiPicker && (
|
||||
<EmojiPicker
|
||||
categories={calloutCategories}
|
||||
custom={calloutCustom}
|
||||
emojiData={InitEmojiCallout.emojidata}
|
||||
categories={InitEmojiCallout.calloutCategories}
|
||||
onClickOutside={onClickOutside}
|
||||
onEmojiSelect={onEmojiSelect}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* "emoji-mart" is a singleton, multiple imports in the same
|
||||
* application could cause issues.
|
||||
* BlockNote uses "emoji-mart" internally as well, if
|
||||
* Blocknote emoji picker is init before the callout emoji picker,
|
||||
* the callout emoji picker will not be set up correctly.
|
||||
* To avoid this, we initialize emoji-mart here and before any
|
||||
* other components that uses it.
|
||||
*/
|
||||
import data, { Category, EmojiMartData } from '@emoji-mart/data';
|
||||
import { init } from 'emoji-mart';
|
||||
|
||||
type EmojiMartDataFixed = Omit<EmojiMartData, 'categories'> & {
|
||||
categories: (Category & { name: string })[];
|
||||
};
|
||||
|
||||
const emojidata = structuredClone(data) as EmojiMartDataFixed;
|
||||
|
||||
const CALLOUT_ID = 'callout';
|
||||
const CALLOUT_EMOJIS = [
|
||||
'bulb',
|
||||
'point_right',
|
||||
'point_up',
|
||||
'ok_hand',
|
||||
'key',
|
||||
'construction',
|
||||
'warning',
|
||||
'fire',
|
||||
'pushpin',
|
||||
'scissors',
|
||||
'question',
|
||||
'no_entry',
|
||||
'no_entry_sign',
|
||||
'alarm_clock',
|
||||
'phone',
|
||||
'rotating_light',
|
||||
'recycle',
|
||||
'white_check_mark',
|
||||
'lock',
|
||||
'paperclip',
|
||||
'book',
|
||||
'speaking_head_in_silhouette',
|
||||
'arrow_right',
|
||||
'loudspeaker',
|
||||
'hammer_and_wrench',
|
||||
'gear',
|
||||
];
|
||||
|
||||
if (!emojidata.categories.some((c) => c.id === CALLOUT_ID)) {
|
||||
emojidata.categories.unshift({
|
||||
id: CALLOUT_ID,
|
||||
name: 'Callout',
|
||||
emojis: CALLOUT_EMOJIS,
|
||||
});
|
||||
}
|
||||
|
||||
void init({ data: emojidata });
|
||||
|
||||
const calloutCategories = [
|
||||
'callout',
|
||||
'people',
|
||||
'nature',
|
||||
'foods',
|
||||
'activity',
|
||||
'places',
|
||||
'flags',
|
||||
'objects',
|
||||
'symbols',
|
||||
];
|
||||
|
||||
const calloutEmojiData = {
|
||||
emojidata,
|
||||
calloutCategories,
|
||||
};
|
||||
|
||||
export default calloutEmojiData;
|
||||
Reference in New Issue
Block a user