Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"update-tlds": "node scripts/update-tlds.mjs"
},
"dependencies": {
"@emoji-mart/data": "^1.2.1",
"@blocknote/emoji-data": "workspace:^",
"@handlewithcare/prosemirror-inputrules": "^0.1.4",
"@shikijs/types": "^4",
"@tanstack/store": "^0.7.7",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Emoji, EmojiMartData } from "@emoji-mart/data";
import type { Emoji, EmojiMartData } from "@blocknote/emoji-data";

import { defaultInlineContentSchema } from "../../blocks/defaultBlocks.js";
import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
Expand All @@ -10,35 +10,41 @@ import {
import { DefaultGridSuggestionItem } from "./DefaultGridSuggestionItem.js";

// Temporary fix for https://github.com/missive/emoji-mart/pull/929
let currentLocale: string | undefined;
let emojiLoadingPromise:
| Promise<{
emojiMart: typeof import("emoji-mart");
emojiData: EmojiMartData;
}>
| undefined;

async function loadEmojiMart() {
if (emojiLoadingPromise) {
async function loadEmojiMart(locale?: string) {
const targetLocale = locale ?? "en";

if (emojiLoadingPromise && currentLocale === targetLocale) {
return emojiLoadingPromise;
}

currentLocale = targetLocale;
emojiLoadingPromise = (async () => {
// load dynamically because emoji-mart doesn't specify type: module and breaks in nodejs
const [emojiMartModule, emojiDataModule] = await Promise.all([
import("emoji-mart"),
// use a dynamic import to encourage bundle-splitting
// and a smaller initial client bundle size
import("@emoji-mart/data"),
import("@blocknote/emoji-data"),
]);

const emojiMart =
"default" in emojiMartModule ? emojiMartModule.default : emojiMartModule;
const emojiData =
"default" in emojiDataModule
? (emojiDataModule.default as EmojiMartData)
: (emojiDataModule as EmojiMartData);

await emojiMart.init({ data: emojiData });
let { emojiData } = emojiDataModule;

if (targetLocale !== "en") {
const overlay = await emojiDataModule.loadSearchData(targetLocale);
if (overlay) {
emojiData = emojiDataModule.applySearchOverlay(emojiData, overlay);
}
}

await emojiMart.init({ data: emojiData as any });

return { emojiMart, emojiData };
})();
Expand All @@ -62,7 +68,9 @@ export async function getDefaultEmojiPickerItems<
return [];
}

const { emojiData, emojiMart } = await loadEmojiMart();
const { emojiData, emojiMart } = await loadEmojiMart(
editor.dictionary.locale,
);

const emojisToShow =
query.trim() === ""
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const ar: Dictionary = {
locale: "ar",
slash_menu: {
heading: {
title: "عنوان 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/de.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const de: Dictionary = {
locale: "de",
slash_menu: {
heading: {
title: "Überschrift 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const en = {
locale: "en",
slash_menu: {
heading: {
title: "Heading 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/es.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const es: Dictionary = {
locale: "es",
slash_menu: {
heading: {
title: "Encabezado 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/fr.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const fr: Dictionary = {
locale: "fr",
slash_menu: {
heading: {
title: "Titre 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/he.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const he: Dictionary = {
locale: "he",
slash_menu: {
heading: {
title: "כותרת 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/hr.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const hr: Dictionary = {
locale: "hr",
slash_menu: {
heading: {
title: "Naslov 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/is.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const is: Dictionary = {
locale: "is",
slash_menu: {
heading: {
title: "Fyrirsögn 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/it.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const it: Dictionary = {
locale: "it",
slash_menu: {
heading: {
title: "Intestazione 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ja.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const ja: Dictionary = {
locale: "ja",
slash_menu: {
heading: {
title: "見出し1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ko.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const ko: Dictionary = {
locale: "ko",
slash_menu: {
heading: {
title: "제목1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/nl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const nl: Dictionary = {
locale: "nl",
slash_menu: {
heading: {
title: "Kop 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/no.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const no: Dictionary = {
locale: "no",
slash_menu: {
heading: {
title: "Overskrift 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/pl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const pl: Dictionary = {
locale: "pl",
slash_menu: {
heading: {
title: "Nagłówek 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/pt.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const pt: Dictionary = {
locale: "pt",
slash_menu: {
heading: {
title: "Título",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/ru.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const ru: Dictionary = {
locale: "ru",
slash_menu: {
heading: {
title: "Заголовок 1 уровня",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/uk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const uk: Dictionary = {
locale: "uk",
slash_menu: {
heading: {
title: "Заголовок 1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/uz.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dictionary } from "../dictionary.js";

export const uz: Dictionary = {
locale: "uz",
slash_menu: {
heading: {
title: "1-darajali sarlavha",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/vi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const vi: Dictionary = {
locale: "vi",
slash_menu: {
heading: {
title: "Tiêu đề H1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/zh-tw.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const zhTW: Dictionary = {
locale: "zh-tw",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
slash_menu: {
heading: {
title: "一級標題",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Dictionary } from "../dictionary.js";

export const zh: Dictionary = {
locale: "zh",
slash_menu: {
heading: {
title: "一级标题",
Expand Down
86 changes: 86 additions & 0 deletions packages/emoji-data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# @blocknote/emoji-data

Trimmed, localized emoji dataset for [BlockNote](https://www.blocknotejs.org), compatible with [emoji-mart](https://github.com/missive/emoji-mart).

This package replaces `@emoji-mart/data` with a smaller, i18n-capable dataset built from [emojibase](https://emojibase.dev). It provides:

- **Emoji dataset** — ~1,900 emojis in emoji-mart's native data format, with keyword search support
- **28 locale files** — Localized category names, skin-tone labels, and UI strings, each individually importable for minimal bundle impact
- **Automatic localization** — When using BlockNote, the emoji picker automatically localizes based on the editor's `dictionary.locale`

## Installation

```bash
npm install @blocknote/emoji-data
```

> **Note:** If you're using BlockNote, this package is already included as a dependency of `@blocknote/core` — you don't need to install it separately. The emoji picker automatically uses the locale from your editor's dictionary.

## Usage

### Emoji data

```ts
import { emojiData } from "@blocknote/emoji-data";
import { init } from "emoji-mart";

await init({ data: emojiData });
```

### Loading a locale dynamically

Use `loadEmojiLocale()` to load only the locale you need at runtime:

```ts
import { emojiData, loadEmojiLocale } from "@blocknote/emoji-data";
import { init } from "emoji-mart";

const i18n = await loadEmojiLocale("fr");
await init({ data: emojiData, i18n });
```

This dynamically imports only the requested locale file (~0.5KB gzipped), not all 28.

### Importing a specific locale directly

Each locale has its own entry point:

```ts
import { fr } from "@blocknote/emoji-data/locales/fr";
```

Or import multiple from the barrel:

```ts
import { fr, de } from "@blocknote/emoji-data/locales";
```

Available locales: `bn`, `da`, `de`, `en`, `enGb`, `es`, `esMx`, `et`, `fi`, `fr`, `hi`, `hu`, `it`, `ja`, `ko`, `lt`, `ms`, `nb`, `nl`, `pl`, `pt`, `ru`, `sv`, `th`, `uk`, `vi`, `zh`, `zhHant`.

## Regenerating the data

The emoji dataset and locale files are generated from [emojibase-data](https://www.npmjs.com/package/emojibase-data) and [@emoji-mart/data](https://www.npmjs.com/package/@emoji-mart/data) (build-time only). To regenerate:

```bash
pnpm --filter @blocknote/emoji-data generate-emoji-data
```

## Bundle size

| Entry | Raw | Gzipped |
| -------------------- | ------- | ------- |
| Emoji data | 280 KB | 63 KB |
| Single locale | ~0.7 KB | ~0.5 KB |
| All locales (barrel) | 22 KB | 6 KB |

Compare to `@emoji-mart/data`: 27 MB installed, 432 KB runtime (native set).

## Types

The package exports the following types:

- `EmojiMartData` — The top-level data object (categories, emojis, aliases, sheet)
- `Emoji` — A single emoji entry (id, name, keywords, skins)
- `EmojiSkin` — A skin variant ({ native: string })
- `EmojiCategory` — A category ({ id, emojis: string[] })
- `EmojiI18n` — The i18n locale object shape
62 changes: 62 additions & 0 deletions packages/emoji-data/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "@blocknote/emoji-data",
"homepage": "https://github.com/TypeCellOS/BlockNote",
"private": false,
"sideEffects": false,
"repository": {
"type": "git",
"url": "git+https://github.com/TypeCellOS/BlockNote.git",
"directory": "packages/emoji-data"
},
"license": "MPL-2.0",
"version": "0.52.1",
"files": [
"dist",
"types",
"src"
],
"keywords": [
"emoji",
"emoji-mart",
"blocknote",
"i18n"
],
"description": "Trimmed, localized emoji dataset for BlockNote (emoji-mart compatible, built from emojibase).",
"type": "module",
"source": "src/index.ts",
"types": "./types/src/index.d.ts",
"main": "./dist/blocknote-emoji-data.cjs",
"module": "./dist/blocknote-emoji-data.js",
"exports": {
".": {
"types": "./types/src/index.d.ts",
"import": "./dist/blocknote-emoji-data.js",
"require": "./dist/blocknote-emoji-data.cjs"
},
"./locales": {
"types": "./types/src/i18n/index.d.ts",
"import": "./dist/locales.js",
"require": "./dist/locales.cjs"
},
"./locales/*": {
"types": "./types/src/i18n/locales/*.d.ts",
"import": "./dist/locales/*.js",
"require": "./dist/locales/*.cjs"
}
},
"scripts": {
"dev": "vp dev",
"lint": "vp lint src",
"clean": "rimraf dist && rimraf types",
"generate-emoji-data": "node scripts/generate.mjs"
},
"dependencies": {},
"devDependencies": {
"@emoji-mart/data": "^1.2.1",
"emojibase-data": "^16.0.1",
"rimraf": "^5.0.10",
"rollup-plugin-webpack-stats": "^0.2.6",
"typescript": "^5.9.3",
"vite-plus": "catalog:"
}
}
Loading
Loading