unicode-picker
v0.1.1
Published
A framework-agnostic, tree-shakable Unicode character picker component in vanilla TypeScript
Maintainers
Readme
unicode-picker
Vanilla TypeScript framework-agnostic Unicode character picker component.
- Data-agnostic core — bring your own characters (a few hardcoded glyphs, a whole Unicode block, or the full set). The core bundle ships no character data.
- Tree-shakable dataset —
import { greek, math } from 'unicode-picker/data'pulls only those blocks. - Popover positioning via the native Popover API, anchored to any element.
- Insert = event only — a
unicode-picker:insertevent and anonInsertcallback; the library never touches your editor. - Light / dark / auto theme, Shadow DOM style isolation, keyboard navigation, search.
- Ships as an ESM module and a browser IIFE (
<script>,window.Picker).
Built on Unicode 17.0.0 data (via @unicode/unicode-17.0.0,
used only at build time).
Screenshots

Install
npm install unicode-pickerQuick start
import Picker from 'unicode-picker';
import { emoji, arrows, mathematicalOperators } from 'unicode-picker/data';
const picker = Picker({
width: 380, // px
height: 480, // px
include: [emoji, arrows, mathematicalOperators],
});
picker.append(document.body);
const button = document.querySelector('#open')!;
button.addEventListener('click', () => picker.toggle({ anchor: button }));
picker.on('insert', ({ char }) => {
// do whatever you want with the character
document.querySelector('textarea')!.value += char;
});
picker.on('select', (data) => {
console.log(data);
});Omit include to load the entire Unicode set lazily from unicode-picker/data
(virtualized, so it stays fast):
const picker = Picker(); // everything, loaded on first show()Options
| Option | Type | Default | Description |
| ---------- | -------------------------------- | -------- | ------------------------------------------------------------ |
| width | number | 380 | Width in pixels. |
| height | number | 480 | Height in pixels. |
| include | BlockSource | full set | Characters to show (see Data). Omit for everything. |
| theme | 'light' \| 'dark' \| 'auto' | 'auto' | Colour theme (auto follows prefers-color-scheme). |
| onInsert | (detail: InsertDetail) => void | — | Convenience callback, fired with the insert event. |
Instance API
interface PickerInstance {
append(parent: HTMLElement): PickerInstance;
show(opts?: ShowOptions): PickerInstance; // ShowOptions: { anchor?, placement? }
hide(): PickerInstance;
toggle(opts?: ShowOptions): PickerInstance;
on(event, cb): () => void; // returns an unsubscribe function
setTheme(theme): PickerInstance;
search(query: string): PickerInstance;
destroy(): void;
readonly element: HTMLElement;
}show({ anchor, placement }) positions the popover against anchor
(placement: 'top' | 'bottom' | 'left' | 'right' | 'auto', default 'auto').
Events
Subscribe with picker.on(name, cb) (returns an unsubscribe function). insert is also
dispatched as a bubbling, composed DOM CustomEvent named unicode-picker:insert on
picker.element.
| Event | Detail |
| -------- | --------------------------------------- |
| insert | { char, codePoint, name, block, hex } |
| select | same shape as insert |
| copy | { value, char, codePoint } |
| show | void |
| hide | void |
Data
The include option is a BlockSource — the core renders whatever you give it:
interface PickerChar {
char: string; // the symbol (may be a surrogate pair)
name?: string; // enables the inspector title + name search
codePoint?: number; // derived from `char` when omitted
}
interface PickerBlock {
name: string; // chip + section header label
characters: string | Array<string | PickerChar>; // a string is split by code point
range?: [number, number]; // derived from the characters otherwise
}
type BlockSource = PickerBlock[] | (() => PickerBlock[] | Promise<PickerBlock[]>);Examples:
// Hardcoded — tiny bundle, no dataset dependency
Picker({ include: [{ name: 'Arrows', characters: '←↑→↓' }] });
// Named blocks from the bundled dataset (tree-shaken)
import { emoji, greekAndCoptic } from 'unicode-picker/data';
Picker({ include: [emoji, greekAndCoptic] });
// Lazy / async source
Picker({ include: async () => (await fetch('/my-chars.json')).json() });
// Straight from @unicode via the adapter (pairs symbols with names)
import { fromUnicodePackage } from 'unicode-picker/adapters';
Picker({ include: () => fromUnicodePackage(() => import('@unicode/unicode-17.0.0/Block')) });unicode-picker/data
Named exports, one PickerBlock per Unicode block (camelCase of the official name),
plus a curated emoji set and heavy all / blocks arrays:
import { basicLatin, greekAndCoptic, mathematicalOperators, emoji, all } from 'unicode-picker/data';Importing individual blocks is tree-shakable — only the blocks you name end up in your
bundle. all / blocks include everything and intentionally opt out of tree-shaking.
The curated emoji export names every emoji — including multi-code-point sequences such as
flags (🇬🇧 → “flag: United Kingdom”) and ZWJ families — using the CLDR annotations from
emojibase-data (build-time only).
IIFE note: tree-shaking is an ESM/bundler feature. For plain
<script>usage, the data script (unicode-picker-data.global.js) exposes the whole dataset onwindow.UnicodePickerData; it cannot be tree-shaken.
See the full list of blocks below.
Usage in the browser (<script>)
<script src="https://unpkg.com/unicode-picker"></script>
<!-- optional: the full dataset on window.UnicodePickerData -->
<script src="https://unpkg.com/unicode-picker/dist/unicode-picker-data.global.js"></script>
<script>
const { emoji, arrows } = window.UnicodePickerData;
const picker = Picker({ include: [emoji, arrows] });
picker.append(document.body);
document.querySelector('#open').onclick = (e) => picker.toggle({ anchor: e.currentTarget });
picker.on('insert', ({ char }) => console.log('picked', char));
</script>Usage with React
import { useEffect, useRef, useState } from 'react';
import Picker, { type PickerInstance } from 'unicode-picker';
import { emoji, arrows } from 'unicode-picker/data';
export function CharField() {
const btn = useRef<HTMLButtonElement>(null);
const picker = useRef<PickerInstance | null>(null);
const [value, setValue] = useState('');
useEffect(() => {
const p = Picker({ include: [emoji, arrows] });
p.append(document.body);
p.on('insert', ({ char }) => setValue((v) => v + char));
picker.current = p;
return () => p.destroy();
}, []);
return (
<>
<button ref={btn} onClick={() => picker.current?.toggle({ anchor: btn.current! })}>
Pick a character ❖
</button>
<textarea value={value} onChange={(e) => setValue(e.target.value)} />
</>
);
}Usage with Vue
<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref } from 'vue';
import Picker, { type PickerInstance } from 'unicode-picker';
import { emoji, arrows } from 'unicode-picker/data';
const btn = ref<HTMLButtonElement>();
const value = ref('');
let picker: PickerInstance;
onMounted(() => {
picker = Picker({ include: [emoji, arrows] });
picker.append(document.body);
picker.on('insert', ({ char }) => (value.value += char));
});
onBeforeUnmount(() => picker.destroy());
</script>
<template>
<button ref="btn" @click="picker.toggle({ anchor: btn })">Pick a character ❖</button>
<textarea v-model="value" />
</template>Unicode blocks
Each block below is a named export of unicode-picker/data. Click a reference to see every
character in that block.
| Import | Unicode block | Chars | Reference |
| --------------------------------------------- | ------------------------------------------------ | ----- | ------------------------------------------------------------------------------------------------------------------------------ |
| emoji | Emoji | 1940 | chars |
| adlam | Adlam | 88 | chars |
| aegeanNumbers | Aegean Numbers | 57 | chars |
| ahom | Ahom | 65 | chars |
| alchemicalSymbols | Alchemical Symbols | 128 | chars |
| alphabeticPresentationForms | Alphabetic Presentation Forms | 58 | chars |
| anatolianHieroglyphs | Anatolian Hieroglyphs | 583 | chars |
| ancientGreekMusicalNotation | Ancient Greek Musical Notation | 70 | chars |
| ancientGreekNumbers | Ancient Greek Numbers | 79 | chars |
| ancientSymbols | Ancient Symbols | 14 | chars |
| arabic | Arabic | 248 | chars |
| arabicExtendedA | Arabic Extended a | 95 | chars |
| arabicExtendedB | Arabic Extended B | 41 | chars |
| arabicExtendedC | Arabic Extended C | 21 | chars |
| arabicMathematicalAlphabeticSymbols | Arabic Mathematical Alphabetic Symbols | 143 | chars |
| arabicPresentationFormsA | Arabic Presentation Forms a | 656 | chars |
| arabicPresentationFormsB | Arabic Presentation Forms B | 140 | chars |
| arabicSupplement | Arabic Supplement | 48 | chars |
| armenian | Armenian | 91 | chars |
| arrows | Arrows | 112 | chars |
| avestan | Avestan | 61 | chars |
| balinese | Balinese | 127 | chars |
| bamum | Bamum | 88 | chars |
| bamumSupplement | Bamum Supplement | 569 | chars |
| basicLatin | Basic Latin | 95 | chars |
| bassaVah | Bassa Vah | 36 | chars |
| batak | Batak | 56 | chars |
| bengali | Bengali | 96 | chars |
| beriaErfe | Beria Erfe | 50 | chars |
| bhaiksuki | Bhaiksuki | 97 | chars |
| blockElements | Block Elements | 32 | chars |
| bopomofo | Bopomofo | 43 | chars |
| bopomofoExtended | Bopomofo Extended | 32 | chars |
| boxDrawing | Box Drawing | 128 | chars |
| brahmi | Brahmi | 115 | chars |
| braillePatterns | Braille Patterns | 256 | chars |
| buginese | Buginese | 30 | chars |
| buhid | Buhid | 20 | chars |
| byzantineMusicalSymbols | Byzantine Musical Symbols | 246 | chars |
| cjkCompatibility | CJK Compatibility | 256 | chars |
| cjkCompatibilityForms | CJK Compatibility Forms | 32 | chars |
| cjkCompatibilityIdeographs | CJK Compatibility Ideographs | 472 | chars |
| cjkCompatibilityIdeographsSupplement | CJK Compatibility Ideographs Supplement | 542 | chars |
| cjkRadicalsSupplement | CJK Radicals Supplement | 115 | chars |
| cjkStrokes | CJK Strokes | 39 | chars |
| cjkSymbolsAndPunctuation | CJK Symbols and Punctuation | 64 | chars |
| cjkUnifiedIdeographs | CJK Unified Ideographs | 20992 | chars |
| cjkUnifiedIdeographsExtensionA | CJK Unified Ideographs Extension a | 6592 | chars |
| cjkUnifiedIdeographsExtensionB | CJK Unified Ideographs Extension B | 42720 | chars |
| cjkUnifiedIdeographsExtensionC | CJK Unified Ideographs Extension C | 4160 | chars |
| cjkUnifiedIdeographsExtensionD | CJK Unified Ideographs Extension D | 222 | chars |
| cjkUnifiedIdeographsExtensionE | CJK Unified Ideographs Extension E | 5774 | chars |
| cjkUnifiedIdeographsExtensionF | CJK Unified Ideographs Extension F | 7473 | chars |
| cjkUnifiedIdeographsExtensionG | CJK Unified Ideographs Extension G | 4939 | chars |
| cjkUnifiedIdeographsExtensionH | CJK Unified Ideographs Extension H | 4192 | chars |
| cjkUnifiedIdeographsExtensionI | CJK Unified Ideographs Extension I | 622 | chars |
| cjkUnifiedIdeographsExtensionJ | CJK Unified Ideographs Extension J | 4298 | chars |
| carian | Carian | 49 | chars |
| caucasianAlbanian | Caucasian Albanian | 53 | chars |
| chakma | Chakma | 71 | chars |
| cham | Cham | 83 | chars |
| cherokee | Cherokee | 92 | chars |
| cherokeeSupplement | Cherokee Supplement | 80 | chars |
| chessSymbols | Chess Symbols | 102 | chars |
| chorasmian | Chorasmian | 28 | chars |
| combiningDiacriticalMarks | Combining Diacritical Marks | 112 | chars |
| combiningDiacriticalMarksExtended | Combining Diacritical Marks Extended | 58 | chars |
| combiningDiacriticalMarksForSymbols | Combining Diacritical Marks for Symbols | 33 | chars |
| combiningDiacriticalMarksSupplement | Combining Diacritical Marks Supplement | 64 | chars |
| combiningHalfMarks | Combining Half Marks | 16 | chars |
| commonIndicNumberForms | Common Indic Number Forms | 10 | chars |
| controlPictures | Control Pictures | 42 | chars |
| coptic | Coptic | 123 | chars |
| copticEpactNumbers | Coptic Epact Numbers | 28 | chars |
| countingRodNumerals | Counting Rod Numerals | 25 | chars |
| cuneiform | Cuneiform | 922 | chars |
| cuneiformNumbersAndPunctuation | Cuneiform Numbers and Punctuation | 116 | chars |
| currencySymbols | Currency Symbols | 34 | chars |
| cypriotSyllabary | Cypriot Syllabary | 55 | chars |
| cyproMinoan | Cypro Minoan | 99 | chars |
| cyrillic | Cyrillic | 256 | chars |
| cyrillicExtendedA | Cyrillic Extended a | 32 | chars |
| cyrillicExtendedB | Cyrillic Extended B | 96 | chars |
| cyrillicExtendedC | Cyrillic Extended C | 11 | chars |
| cyrillicExtendedD | Cyrillic Extended D | 63 | chars |
| cyrillicSupplement | Cyrillic Supplement | 48 | chars |
| deseret | Deseret | 80 | chars |
| devanagari | Devanagari | 128 | chars |
| devanagariExtended | Devanagari Extended | 32 | chars |
| devanagariExtendedA | Devanagari Extended a | 10 | chars |
| dingbats | Dingbats | 192 | chars |
| divesAkuru | Dives Akuru | 72 | chars |
| dogra | Dogra | 60 | chars |
| dominoTiles | Domino Tiles | 100 | chars |
| duployan | Duployan | 143 | chars |
| earlyDynasticCuneiform | Early Dynastic Cuneiform | 196 | chars |
| egyptianHieroglyphFormatControls | Egyptian Hieroglyph Format Controls | 22 | chars |
| egyptianHieroglyphs | Egyptian Hieroglyphs | 1072 | chars |
| egyptianHieroglyphsExtendedA | Egyptian Hieroglyphs Extended a | 3995 | chars |
| elbasan | Elbasan | 40 | chars |
| elymaic | Elymaic | 23 | chars |
| emoticons | Emoticons | 80 | chars |
| enclosedAlphanumericSupplement | Enclosed Alphanumeric Supplement | 200 | chars |
| enclosedAlphanumerics | Enclosed Alphanumerics | 160 | chars |
| enclosedCjkLettersAndMonths | Enclosed CJK Letters and Months | 255 | chars |
| enclosedIdeographicSupplement | Enclosed Ideographic Supplement | 64 | chars |
| ethiopic | Ethiopic | 358 | chars |
| ethiopicExtended | Ethiopic Extended | 79 | chars |
| ethiopicExtendedA | Ethiopic Extended a | 32 | chars |
| ethiopicExtendedB | Ethiopic Extended B | 28 | chars |
| ethiopicSupplement | Ethiopic Supplement | 26 | chars |
| garay | Garay | 69 | chars |
| generalPunctuation | General Punctuation | 86 | chars |
| geometricShapes | Geometric Shapes | 96 | chars |
| geometricShapesExtended | Geometric Shapes Extended | 103 | chars |
| georgian | Georgian | 88 | chars |
| georgianExtended | Georgian Extended | 46 | chars |
| georgianSupplement | Georgian Supplement | 40 | chars |
| glagolitic | Glagolitic | 96 | chars |
| glagoliticSupplement | Glagolitic Supplement | 38 | chars |
| gothic | Gothic | 27 | chars |
| grantha | Grantha | 86 | chars |
| greekAndCoptic | Greek and Coptic | 135 | chars |
| greekExtended | Greek Extended | 233 | chars |
| gujarati | Gujarati | 91 | chars |
| gunjalaGondi | Gunjala Gondi | 63 | chars |
| gurmukhi | Gurmukhi | 80 | chars |
| gurungKhema | Gurung Khema | 58 | chars |
| halfwidthAndFullwidthForms | Halfwidth and Fullwidth Forms | 225 | chars |
| hangulCompatibilityJamo | Hangul Compatibility Jamo | 94 | chars |
| hangulJamo | Hangul Jamo | 256 | chars |
| hangulJamoExtendedA | Hangul Jamo Extended a | 29 | chars |
| hangulJamoExtendedB | Hangul Jamo Extended B | 72 | chars |
| hangulSyllables | Hangul Syllables | 11172 | chars |
| hanifiRohingya | Hanifi Rohingya | 50 | chars |
| hanunoo | Hanunoo | 23 | chars |
| hatran | Hatran | 26 | chars |
| hebrew | Hebrew | 88 | chars |
| hiragana | Hiragana | 93 | chars |
| ipaExtensions | IPA Extensions | 96 | chars |
| ideographicDescriptionCharacters | Ideographic Description Characters | 16 | chars |
| ideographicSymbolsAndPunctuation | Ideographic Symbols and Punctuation | 12 | chars |
| imperialAramaic | Imperial Aramaic | 31 | chars |
| indicSiyaqNumbers | Indic Siyaq Numbers | 68 | chars |
| inscriptionalPahlavi | Inscriptional Pahlavi | 27 | chars |
| inscriptionalParthian | Inscriptional Parthian | 30 | chars |
| javanese | Javanese | 91 | chars |
| kaithi | Kaithi | 66 | chars |
| kaktovikNumerals | Kaktovik Numerals | 20 | chars |
| kanaExtendedA | Kana Extended a | 35 | chars |
| kanaExtendedB | Kana Extended B | 13 | chars |
| kanaSupplement | Kana Supplement | 256 | chars |
| kanbun | Kanbun | 16 | chars |
| kangxiRadicals | Kangxi Radicals | 214 | chars |
| kannada | Kannada | 92 | chars |
| katakana | Katakana | 96 | chars |
| katakanaPhoneticExtensions | Katakana Phonetic Extensions | 16 | chars |
| kawi | Kawi | 87 | chars |
| kayahLi | Kayah Li | 48 | chars |
| kharoshthi | Kharoshthi | 68 | chars |
| khitanSmallScript | Khitan Small Script | 471 | chars |
| khmer | Khmer | 114 | chars |
| khmerSymbols | Khmer Symbols | 32 | chars |
| khojki | Khojki | 65 | chars |
| khudawadi | Khudawadi | 69 | chars |
| kiratRai | Kirat Rai | 58 | chars |
| lao | Lao | 83 | chars |
| latin1Supplement | Latin 1 Supplement | 95 | chars |
| latinExtendedA | Latin Extended a | 128 | chars |
| latinExtendedAdditional | Latin Extended Additional | 256 | chars |
| latinExtendedB | Latin Extended B | 208 | chars |
| latinExtendedC | Latin Extended C | 32 | chars |
| latinExtendedD | Latin Extended D | 204 | chars |
| latinExtendedE | Latin Extended E | 60 | chars |
| latinExtendedF | Latin Extended F | 57 | chars |
| latinExtendedG | Latin Extended G | 37 | chars |
| lepcha | Lepcha | 74 | chars |
| letterlikeSymbols | Letterlike Symbols | 80 | chars |
| limbu | Limbu | 68 | chars |
| linearA | Linear a | 341 | chars |
| linearBIdeograms | Linear B Ideograms | 123 | chars |
| linearBSyllabary | Linear B Syllabary | 88 | chars |
| lisu | Lisu | 48 | chars |
| lisuSupplement | Lisu Supplement | 1 | chars |
| lycian | Lycian | 29 | chars |
| lydian | Lydian | 27 | chars |
| mahajani | Mahajani | 39 | chars |
| mahjongTiles | Mahjong Tiles | 44 | chars |
| makasar | Makasar | 25 | chars |
| malayalam | Malayalam | 118 | chars |
| mandaic | Mandaic | 29 | chars |
| manichaean | Manichaean | 51 | chars |
| marchen | Marchen | 68 | chars |
| masaramGondi | Masaram Gondi | 75 | chars |
| mathematicalAlphanumericSymbols | Mathematical Alphanumeric Symbols | 996 | chars |
| mathematicalOperators | Mathematical Operators | 256 | chars |
| mayanNumerals | Mayan Numerals | 20 | chars |
| medefaidrin | Medefaidrin | 91 | chars |
| meeteiMayek | Meetei Mayek | 56 | chars |
| meeteiMayekExtensions | Meetei Mayek Extensions | 23 | chars |
| mendeKikakui | Mende Kikakui | 213 | chars |
| meroiticCursive | Meroitic Cursive | 90 | chars |
| meroiticHieroglyphs | Meroitic Hieroglyphs | 32 | chars |
| miao | Miao | 149 | chars |
| miscellaneousMathematicalSymbolsA | Miscellaneous Mathematical Symbols a | 48 | chars |
| miscellaneousMathematicalSymbolsB | Miscellaneous Mathematical Symbols B | 128 | chars |
| miscellaneousSymbols | Miscellaneous Symbols | 256 | chars |
| miscellaneousSymbolsAndArrows | Miscellaneous Symbols and Arrows | 254 | chars |
| miscellaneousSymbolsAndPictographs | Miscellaneous Symbols and Pictographs | 768 | chars |
| miscellaneousSymbolsSupplement | Miscellaneous Symbols Supplement | 34 | chars |
| miscellaneousTechnical | Miscellaneous Technical | 256 | chars |
| modi | Modi | 79 | chars |
| modifierToneLetters | Modifier Tone Letters | 32 | chars |
| mongolian | Mongolian | 157 | chars |
| mongolianSupplement | Mongolian Supplement | 13 | chars |
| mro | Mro | 43 | chars |
| multani | Multani | 38 | chars |
| musicalSymbols | Musical Symbols | 225 | chars |
| myanmar | Myanmar | 160 | chars |
| myanmarExtendedA | Myanmar Extended a | 32 | chars |
| myanmarExtendedB | Myanmar Extended B | 31 | chars |
| myanmarExtendedC | Myanmar Extended C | 20 | chars |
| nko | NKo | 62 | chars |
| nabataean | Nabataean | 40 | chars |
| nagMundari | Nag Mundari | 42 | chars |
| nandinagari | Nandinagari | 65 | chars |
| newTaiLue | New Tai Lue | 83 | chars |
| newa | Newa | 97 | chars |
| numberForms | Number Forms | 60 | chars |
| nushu | Nushu | 396 | chars |
| nyiakengPuachueHmong | Nyiakeng Puachue Hmong | 71 | chars |
| ogham | Ogham | 29 | chars |
| olChiki | Ol Chiki | 48 | chars |
| olOnal | Ol Onal | 44 | chars |
| oldHungarian | Old Hungarian
