Frimousse API Reference
This file is the package-level API reference for @slithy/frimousse.
It covers:
EmojiPickercomponents- hooks
- additive supplemental APIs
- supplemental item helpers
- custom emoji helpers
- frequency helpers
- search configuration
- styling hooks
- exported types
Packages
Entry Points
Namespace export
import { EmojiPicker } from "@slithy/frimousse";
Available parts:
EmojiPicker.RootEmojiPicker.SearchEmojiPicker.ViewportEmojiPicker.ListEmojiPicker.LoadingEmojiPicker.EmptyEmojiPicker.SkinToneSelectorEmojiPicker.ActiveEmojiEmojiPicker.ActiveItemEmojiPicker.SkinTone
Preferred consumer-facing types
If you are building on the additive API, start from these public aliases rather than the lower-level internal type names:
ItemNativeItemSupplementalItemItemSelectionSectionSupplementalConfigSupplementalSearch
Those are the stable consumer-facing types used throughout the docs below.
Named exports
import {
buildEmojiPickerFrequentSection,
buildNativeSearchTermsMap,
createCustomEmoji,
createCustomSection,
createSupplementalItem,
createSupplementalSection,
formatAsShortcode,
getEmojiPrimaryShortcode,
getEmojiShortcodes,
getEmojiPickerUsageKey,
isCustomEmoji,
isNativeSelection,
isSupplementalSelection,
rankEmojiPickerUsage,
recordEmojiPickerUsage,
sanitizeEmojiPickerUsageEntries,
useActiveEmoji,
useActiveItem,
useSkinTone,
} from "@slithy/frimousse";
Native Search Helpers
buildNativeSearchTermsMap(entries)
Builds a search.native.terms map from app-owned or companion-package metadata.
type NativeSearchTermSource = {
emoji: string;
shortcodes?: string[];
aliases?: string[];
terms?: string[];
};
Notes:
- combines
shortcodes,aliases, andterms - trims empty strings and removes blank entries
- deduplicates repeated values per emoji
- returns the plain object shape expected by
search.native.terms
formatAsShortcode(value)
Formats a display label into a normalized shortcode-like token.
Notes:
- returns colon-wrapped values like
:party_parrot: - useful when your app persists shortcode-first identifiers
- intentionally small in scope; it does not provide a full shortcode dataset
getEmojiShortcodes(source, options?)
Returns normalized shortcode-like display tokens for an item or widened item selection.
Notes:
- supplemental items use
shortcodewhen provided, otherwise fall back toid - supplemental
aliasesare included as alternate shortcode-like display forms - native items only return values when
nativeShortcodesare provided by the consumer - use this for display-oriented shortcode output, not for defining item identity
getEmojiPrimaryShortcode(source, options?)
Returns the first normalized shortcode-like display token for an item or widened item selection.
Useful for footer or preview UIs that want one canonical :shortcode: string.
Components
EmojiPicker.Root
Base provider and interaction boundary for the picker tree.
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
onEmojiSelect |
(emoji: Emoji) => void |
- | Called when a native emoji is selected. |
onItemSelect |
(selection: ItemSelection) => void |
- | Called when any picker item is selected, including supplemental items. Additive; does not replace onEmojiSelect. |
locale |
Locale |
"en" |
Emojibase locale. |
skinTone |
SkinTone |
"none" |
Initial skin tone. |
columns |
number |
9 |
Number of visible list columns. |
emojiVersion |
number |
browser-supported latest | Restricts visible emoji by Emoji version. |
emojibaseUrl |
string |
"https://cdn.jsdelivr.net/npm/emojibase-data" |
Base URL used to fetch Emojibase JSON datasets. Point this at your own hosted emojibase-data files when you want a self-hosted or offline-capable setup. |
sticky |
boolean |
true |
Makes category headers sticky. |
supplemental |
SupplementalConfig |
- | Adds consumer-owned sections and supplemental search behavior. |
search |
EmojiPickerSearchConfig |
- | Adds native search enrichment data. |
searchValue |
string |
- | Controls the picker search value at the root level, including use cases that do not render EmojiPicker.Search. |
onSearchValueChange |
(search: string) => void |
- | Called whenever the picker search value changes. Useful with an external input or autocomplete field. |
Built-in element props:
- All built-in
divprops.
Attributes:
[frimousse-root][data-focused]when the picker or one of its descendants is focused
CSS variables:
--frimousse-emoji-font--frimousse-viewport-width
Self-hosting with emojibaseUrl
@slithy/frimousse does not bundle the native emoji dataset into the package.
By default it fetches emojibase-data JSON at runtime, but you can stage and
host those files yourself.
Use the included staging helper:
pnpm exec frimousse-stage-emojibase-data --out ./public/emojibase-data
For multiple locales:
pnpm exec frimousse-stage-emojibase-data --out ./public/emojibase-data --locales en,fr,ja
Then point emojibaseUrl at that hosted path:
<EmojiPicker.Root locale="en" emojibaseUrl="/emojibase-data">
<EmojiPicker.Search />
<EmojiPicker.Viewport>
<EmojiPicker.Loading>Loading…</EmojiPicker.Loading>
<EmojiPicker.Empty>No emoji found.</EmojiPicker.Empty>
<EmojiPicker.List />
</EmojiPicker.Viewport>
</EmojiPicker.Root>
With that setup, the picker no longer depends on the public CDN. If your app can serve those files offline, the picker can work offline too.
--frimousse-viewport-height--frimousse-row-height--frimousse-category-header-height
EmojiPicker.Search
Search input for the picker.
Notes:
- Can be used as an uncontrolled input.
- Can also be controlled with
valueandonChange. - Is optional when
EmojiPicker.Rootis usingsearchValueandonSearchValueChange. - Prefer one control surface at a time: either control
EmojiPicker.Searchdirectly, or drive search fromEmojiPicker.Root.
Built-in element props:
- All built-in
inputprops.
Attributes:
[frimousse-search]
EmojiPicker.Viewport
Scrollable viewport for loading, empty, and list content.
Built-in element props:
- All built-in
divprops.
Attributes:
[frimousse-viewport]
EmojiPicker.List
Virtualized list renderer for categories, rows, and emoji buttons.
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
components |
Partial<EmojiPickerListComponents> |
- | Replaces internal renderers for category headers, rows, native emoji buttons, and supplemental emoji buttons. |
Built-in element props:
- All built-in
divprops.
Attributes:
[frimousse-list]
EmojiPickerListComponents shape:
CategoryHeader: ComponentType<EmojiPickerListCategoryHeaderProps>Row: ComponentType<EmojiPickerListRowProps>Emoji: ComponentType<EmojiPickerListEmojiProps>SupplementalEmoji: ComponentType<EmojiPickerListSupplementalEmojiProps>
Inner components:
CategoryHeader- props:
EmojiPickerListCategoryHeaderProps - attributes:
[frimousse-category-header] - notes: all category headers should be the same size
- shape:
- inherits built-in
divprops exceptchildren category: Category
- inherits built-in
- props:
Row- props:
EmojiPickerListRowProps - attributes:
[frimousse-row] - notes: all rows should be the same size
- shape:
- inherits built-in
divprops
- inherits built-in
- props:
Emoji- props:
EmojiPickerListEmojiProps - attributes:
[frimousse-emoji] - state:
[data-active] - notes: all emoji buttons should be the same size
- shape:
- inherits built-in
buttonprops exceptchildren emoji: Emoji & { isActive: boolean }
- inherits built-in
- props:
SupplementalEmoji- props:
EmojiPickerListSupplementalEmojiProps - notes: supplemental button renderer for additive sections
- shape:
- inherits built-in
buttonprops exceptchildren emoji: SupplementalItem & { isActive: boolean }
- inherits built-in
- props:
EmojiPicker.Loading
Rendered while emoji data is loading.
Built-in element props:
- All built-in
spanprops.
Attributes:
[frimousse-loading]
EmojiPicker.Empty
Rendered when the current search has no results.
Props:
| Prop | Type | Notes |
|---|---|---|
children |
ReactNode | ((props: EmojiPickerEmptyRenderProps) => ReactNode) |
Can be static content or a render callback. |
Built-in element props:
- All built-in
spanprops exceptchildren.
Attributes:
[frimousse-empty]
EmojiPickerEmptyRenderProps:
search: string
EmojiPicker.SkinToneSelector
Built-in skin tone toggle button.
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
emoji |
string |
"✋" |
Emoji used as the visual basis for skin tone variations. |
Notes:
- Cycles through available skin tones.
- Use
EmojiPicker.SkinToneoruseSkinTonefor a custom selector.
Built-in element props:
- All built-in
buttonprops exceptchildren.
Attributes:
[frimousse-skin-tone-selector]
EmojiPicker.ActiveEmoji
Render-prop component for the currently active native emoji.
Props:
| Prop | Type | Notes |
|---|---|---|
children |
(props: EmojiPickerActiveEmojiRenderProps) => ReactNode |
Native-only active item surface. |
EmojiPickerActiveEmojiRenderProps:
emoji?: Emoji
Prefer this when your UI is intentionally native-only.
EmojiPicker.ActiveItem
Render-prop component for the currently active item, including supplemental items.
Props:
| Prop | Type | Notes |
|---|---|---|
children |
(props: EmojiPickerActiveItemRenderProps) => ReactNode |
Widened active-item surface. |
EmojiPickerActiveItemRenderProps:
item?: ItemSelection
Prefer this for any picker that may include supplemental items now or later.
EmojiPicker.SkinTone
Render-prop component for the current skin tone state.
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
emoji |
string |
"✋" |
Emoji used to derive the variation list. |
children |
(props: EmojiPickerSkinToneRenderProps) => ReactNode |
Render callback. |
EmojiPickerSkinToneRenderProps:
skinTone: SkinTonesetSkinTone: (skinTone: SkinTone) => voidskinToneVariations: SkinToneVariation[]
Hooks
useActiveEmoji()
Returns the currently active native emoji, or undefined.
const activeEmoji = useActiveEmoji();
Return type:
Emoji | undefined
Notes:
- Native-only.
- Returns the hovered item or the keyboard-active item.
- Prefer
useActiveItem()if your picker may include supplemental items. - If you later add supplemental items, switch alongside
onItemSelectandEmojiPicker.ActiveItem.
useActiveItem()
Returns the currently active item, including supplemental items.
const activeItem = useActiveItem();
Return type:
ItemSelection | undefined
Notes:
- Widened additive active-item surface.
- Prefer this when your picker may include supplemental items now or later.
- Pair this with
onItemSelectandEmojiPicker.ActiveItemfor a consistent mixed-item surface.
useSkinTone(emoji = "✋")
Returns skin tone state, setter, and skin tone variations for the provided emoji.
const [skinTone, setSkinTone, skinToneVariations] = useSkinTone();
Return type:
[SkinTone, (skinTone: SkinTone) => void, SkinToneVariation[]]
Additive Supplemental API
The additive contract is centered on a few concepts:
SupplementalItem: a consumer-owned non-native picker itemSection: a consumer-owned section that can contain native items, supplemental items, or bothItemSelection: a discriminated selection union withkind: "native"orkind: "supplemental"SupplementalConfig: theEmojiPicker.Rootprop that wires additive sections and supplemental search behavior into the picker
supplemental root prop
EmojiPickerRootProps["supplemental"] accepts:
type SupplementalConfig = {
sections?: Section[];
search?: SupplementalSearch;
};
Use SupplementalConfig, Section, Item, and ItemSelection as the consumer-facing additive types.
SupplementalSearch:
| Prop | Type | Default | Notes |
|---|---|---|---|
mode |
"grouped" | "unified" |
"grouped" |
Grouped mode preserves native category headings and matching supplemental section labels; unified mode merges everything into one results section. |
resultsLabel |
string |
- | Label used for unified result sections only. Ignored in grouped mode. |
weights |
SupplementalSearchWeights |
built-in relevance defaults | Overrides how strongly label, aliases, keywords, tags, and id contribute to supplemental match ranking. Applies to supplemental items only. |
Grouped-mode guarantees:
- native matches stay under native category headings
- matching supplemental sections keep their own labels
- sections with no matches are omitted
resultsLabelis ignored
Unified-mode guarantees:
- native and supplemental matches merge into one results section
resultsLabelnames that merged section- section labels no longer partition the rendered result set
Items, sections, and item selections
type NativeItem = {
kind: "native";
id: string;
emoji: string;
label: string;
};
type SupplementalItem = {
kind: "supplemental";
id: string;
label: string;
imageUrl?: string;
tags?: string[];
keywords?: string[];
aliases?: string[];
data?: unknown;
};
type Item =
| NativeItem
| SupplementalItem;
type Section = {
id: string;
label?: string;
position?: "prepend" | "append";
items: Item[];
searchable?: boolean;
};
type NativeItemSelection = {
kind: "native";
item: NativeItem;
};
type SupplementalItemSelection = {
kind: "supplemental";
item: SupplementalItem;
};
type ItemSelection =
| NativeItemSelection
| SupplementalItemSelection;
searchable behavior:
trueor omitted: the section participates in searchfalse: the section still renders when search is empty, but contributes no matches once search is active
Selection guards
isNativeSelection(selection)
isSupplementalSelection(selection)
Use these to narrow ItemSelection unions safely.
Supplemental Item Helpers
createSupplementalItem(input)
Creates a normalized supplemental item.
Input type:
type SupplementalItemInput = {
id: string;
label?: string;
shortcode?: string;
imageUrl?: string;
tags?: string[];
keywords?: string[];
aliases?: string[];
data?: unknown;
};
Field semantics:
id: required stable identity owned by the consumerlabel: display label; defaults toidwhen omittedshortcode: optional canonical display-oriented:shortcode:tokenimageUrl: optional presentation data for image-backed renderingaliases: alternate names that participate in supplemental searchkeywords: search-oriented descriptors that participate in supplemental searchtags: broader search hints that also participate in supplemental searchdata: opaque consumer payload carried through unchanged and not interpreted by the picker
Recommended mental model:
idanswers “which item is this?”shortcodeanswers “which:shortcode:should I display for this item?”aliases,keywords, andtagsanswer “how should this item be found?”
Common patterns:
- Shortcode-first custom emoji
{
id: "shipit",
label: "Ship It",
shortcode: ":shipit:",
aliases: ["ship-it", ":ship_it:"],
}
Use this when the shortcode-like name is the stable identity your app stores or exchanges.
- Plain supplemental item with search metadata
{
id: "design-review",
label: "Design review",
imageUrl: "/emoji/design-review.png",
keywords: ["review", "feedback"],
tags: ["team"],
}
Use this when the item needs discoverability metadata but does not need a shortcode-oriented identity model.
Avoid treating these fields as interchangeable:
idis for identity, not just displayshortcodeis for canonical display text, not required identityaliasesare alternate names, not arbitrary payloadkeywordsandtagsare for discovery, not canonical namingdatais the escape hatch only for metadata the picker should carry but not interpret
Built-in supplemental search treats label and aliases as name-like matches, keeps keywords and tags as weaker discovery signals, and treats an exact canonical id match as a first-class name-like hit in unified shortcode-first search.
SupplementalSearchWeights:
type SupplementalSearchWeights = {
label?: number;
aliases?: number;
keywords?: number;
tags?: number;
id?: number;
};
Use this only to tune supplemental item ranking. Native emoji ranking still comes from the native dataset plus search.native.terms, with an opinionated built-in ranking policy rather than a public weighting API.
Set a weight to 0 when you want that field ignored entirely.
Return type:
SupplementalItem
createSupplementalSection(items, options)
Creates a normalized supplemental section that can contain plain or image-backed supplemental items.
Arguments:
items: readonly SupplementalItemInput[]options: SupplementalSectionOptions
SupplementalSectionOptions:
type SupplementalSectionOptions = {
id: string;
label?: string;
position?: "prepend" | "append";
searchable?: boolean;
};
Return type:
SupplementalSection
Custom Emoji Helpers
createCustomEmoji(input)
Creates a normalized image-backed supplemental item with required id and imageUrl.
Input type:
type CustomEmojiInput = {
id: string;
label?: string;
imageUrl: string;
tags?: string[];
keywords?: string[];
aliases?: string[];
data?: unknown;
};
CustomEmojiInput keeps the same metadata semantics as SupplementalItemInput, but requires imageUrl.
Return type:
CustomEmoji
createCustomSection(items, options)
Creates a normalized section of image-backed custom emoji.
Arguments:
items: readonly CustomEmojiInput[]options: CustomSectionOptions
CustomSectionOptions:
type CustomSectionOptions = {
id: string;
label?: string;
position?: "prepend" | "append";
searchable?: boolean;
};
Return type:
CustomSection
isCustomEmoji(item)
Type guard for a supplemental item with a required imageUrl.
Frequency Helpers
Types
type EmojiPickerUsageSource = Item | ItemSelection;
type EmojiPickerUsageEntry = {
key: string;
item: Item;
score: number;
uses: number;
lastUsedAt: number;
};
type EmojiPickerUsageOptions = {
mode?: "frecency" | "recent";
halfLifeMs?: number;
maxEntries?: number;
now?: Date | number;
};
type EmojiPickerFrequentSectionOptions = EmojiPickerUsageOptions & {
id?: string;
label?: string;
limit?: number;
position?: "prepend" | "append";
searchable?: boolean;
};
getEmojiPickerUsageKey(source)
Returns a stable usage key in the form ${kind}:${id}.
rankEmojiPickerUsage(entries, options?)
Decays and sorts usage entries.
Behavior:
- uses
mode: "frecency"by default - decays each entry’s
scoreusinghalfLifeMs - drops entries whose decayed score reaches
0 - sorts by decayed
score, thenlastUsedAt, thenuses - defaults
halfLifeMsto30days andmaxEntriesto100 - in
recentmode, sorts bylastUsedAt, thenuses, thenscore
Return type:
EmojiPickerUsageEntry[]
recordEmojiPickerUsage(entries, source, options?)
Adds or updates a usage entry and returns the re-ranked collection.
Behavior:
- resolves the stable key as
${kind}:${id} - in
frecencymode, decays any existing score before adding the new usage - increments
usesby1 - updates
lastUsedAttonow - inserts a new entry with
score: 1when the item has not been seen before - in
recentmode, keeps the same storedscorebehavior but ranks by recency instead
Return type:
EmojiPickerUsageEntry[]
sanitizeEmojiPickerUsageEntries(value)
Sanitizes persisted usage-entry data from consumer-owned storage.
Behavior:
- accepts unknown input and returns a valid
EmojiPickerUsageEntry[] - drops malformed entries instead of throwing
- drops entries with non-finite or non-positive
scoreandusesvalues - drops entries with non-finite or negative
lastUsedAtvalues - deduplicates entries by sanitized usage key
- re-derives each entry key from the sanitized item shape
- normalizes supplemental items with the same rules as
createSupplementalItem
Typical use:
function readEmojiPickerUsageEntries() {
if (typeof window === "undefined") {
return [];
}
try {
const raw = window.localStorage.getItem("emoji-picker-usage");
return sanitizeEmojiPickerUsageEntries(raw ? JSON.parse(raw) : []);
} catch {
return [];
}
}
Return type:
EmojiPickerUsageEntry[]
buildEmojiPickerFrequentSection(entries, options?)
Builds a frequent-items section from ranked usage.
This uses the same frecency ranking as rankEmojiPickerUsage, then takes the top
limit items and turns them into a supplemental section.
Use mode: "recent" when you want a “Recently used” section instead.
Return type:
EmojiPickerFrequentSection | null
Defaults:
- section id:
"frequently-used" - section label:
"Frequently used" - section position:
"prepend" - section searchable:
false - section limit:
20
Search Configuration
EmojiPickerRootProps["search"] accepts:
type EmojiPickerNativeSearchConfig = {
terms?: Record<string, string[]>;
};
type EmojiPickerSearchConfig = {
native?: EmojiPickerNativeSearchConfig;
};
Use this to enrich native emoji matching with consumer-owned search terms.
Styling Hooks
Stable styling hooks exposed on built-in parts:
[frimousse-root][frimousse-search][frimousse-viewport][frimousse-list][frimousse-category-header][frimousse-row][frimousse-emoji][frimousse-loading][frimousse-empty][frimousse-skin-tone-selector]
Relevant state hook:
[data-active]on emoji buttons
The implementation also uses internal measurement and sizing attributes. Treat those as implementation details unless documented elsewhere.
Exported Types
This section lists the types re-exported from the package entrypoint.
Core
CategoryEmojiLocaleSkinTone
Items and selections
ItemNativeItemSupplementalItemItemSelectionNativeItemSelectionSupplementalItemSelection
Sections and search
SectionSupplementalConfigSectionPositionSupplementalSearchSupplementalSearchWeightsSearchConfigEmojiPickerNativeSearchConfigEmojiPickerSearchConfigNativeSearchTermSource
Component props and render props
EmojiPickerRootPropsEmojiPickerSearchPropsEmojiPickerViewportPropsEmojiPickerListPropsEmojiPickerLoadingPropsEmojiPickerEmptyPropsEmojiPickerSkinToneSelectorPropsEmojiPickerActiveEmojiPropsEmojiPickerActiveEmojiRenderPropsEmojiPickerActiveItemPropsEmojiPickerActiveItemRenderPropsEmojiPickerSkinTonePropsEmojiPickerSkinToneRenderPropsEmojiPickerListComponentsEmojiPickerListCategoryHeaderPropsEmojiPickerListRowPropsEmojiPickerListEmojiPropsEmojiPickerListSupplementalEmojiProps
Custom emoji and sections
SupplementalItemInputSupplementalSectionSupplementalSectionOptionsCustomEmojiCustomEmojiInputCustomSectionCustomSectionOptions
Frequency
EmojiPickerUsageEntryEmojiPickerUsageModeEmojiPickerUsageOptionsEmojiPickerUsageSourceEmojiPickerFrequentSectionEmojiPickerFrequentSectionOptions
Notes
- If you later introduce supplemental items to a native-only picker, switch the three related surfaces together:
onEmojiSelect->onItemSelect,useActiveEmoji->useActiveItem, andEmojiPicker.ActiveEmoji->EmojiPicker.ActiveItem. useActiveEmojiandEmojiPicker.ActiveEmojiremain native-only.useActiveItemandEmojiPicker.ActiveIteminclude supplemental items.onEmojiSelectremains native-only.onItemSelectis the widened additive callback for both native and supplemental items.
Companion Package API Reference
The sections below cover optional companion packages. They are documented here for convenience, but they are separate installs and separate entry points.
@slithy/emoji-transforms
Install:
pnpm add @slithy/emoji-transforms
Purpose:
- transforms consumer-owned emoji metadata into plain data structures for shortcode lookup and native search enrichment
Boundary:
- this package does not render anything
- this package does not bundle shortcode datasets
- this package does not expose picker-specific UI contracts
Entry point:
import {
adaptNativeEmojiSearchEntries,
adaptEmojibaseNativeEmojiSearchEntries,
buildFallbackTermsFromEmojibase,
buildNativeEmojiSearchTermMap,
buildNativeEmojiSearchTermMapFromAdapter,
buildNativeEmojiSearchTermMapFromEmojibase,
mergeNativeEmojiSearchTermMaps,
buildShortcodeMap,
buildShortcodeMapFromAdapter,
buildShortcodeMapFromEmojibase,
buildShortcodeMapFromPreset,
getNativeEmojiSearchTerms,
getPrimaryShortcode,
getShortcodes,
normalizeNativeEmojiSearchKey,
} from "@slithy/emoji-transforms";
Search term and shortcode builders
buildNativeEmojiSearchTermMap(entries)
Builds a plain Record<string, string[]> keyed by normalized base emoji.
Input shape:
type NativeEmojiShortcodeEntry = {
emoji: string;
shortcodes?: readonly string[];
aliases?: readonly string[];
};
Notes:
- combines
shortcodesandaliases - trims, lowercases, and deduplicates values
- adds spaced variants for separator-based terms
- returns the plain shape expected by
@slithy/frimoussesearch.native.terms
buildShortcodeMap(entries)
Builds a shortcode-only Record<string, string[]> keyed by normalized base
emoji.
Notes:
- stays shortcode-only
- does not widen into label or tag aliases
- useful when your app wants a canonical native shortcode display map
buildNativeEmojiSearchTermMapFromAdapter(entries, adapter)
Combines an adapter step with native-search map construction.
buildShortcodeMapFromAdapter(entries, adapter)
Combines an adapter step with shortcode-map construction.
adaptNativeEmojiSearchEntries(entries, adapter)
Maps arbitrary source records into the package’s neutral
NativeEmojiShortcodeEntry format.
adaptEmojibaseNativeEmojiSearchEntries(entries, options?)
Adapts a common Emojibase-like record shape into the package’s neutral entry format.
buildFallbackTermsFromEmojibase(entries, options?)
Builds a native-search term map from a secondary Emojibase locale dataset for fallback search use cases.
Notes:
- includes
label-based fallback terms by default - keeps
tagsopt-in throughoptions - useful when a picker renders in one locale but should still match English search terms
Build-time example:
// scripts/build-fr-search-terms.ts
import { writeFile } from "node:fs/promises";
import englishData from "emojibase-data/en/data.json";
import frenchData from "emojibase-data/fr/data.json";
import {
buildFallbackTermsFromEmojibase,
buildNativeEmojiSearchTermMapFromEmojibase,
mergeNativeEmojiSearchTermMaps,
} from "@slithy/emoji-transforms";
const searchTerms = mergeNativeEmojiSearchTermMaps(
buildNativeEmojiSearchTermMapFromEmojibase(frenchData, {
includeLabel: true,
}),
buildFallbackTermsFromEmojibase(englishData),
);
await writeFile(
new URL("../src/generated/fr-search-terms.json", import.meta.url),
`${JSON.stringify(searchTerms, null, 2)}\n`,
);
Run example:
pnpm tsx scripts/build-fr-search-terms.ts
That writes src/generated/fr-search-terms.json, which you can then pass to
the picker:
import frSearchTerms from "./generated/fr-search-terms.json";
<EmojiPicker.Root
locale="fr"
search={{ native: { terms: frSearchTerms } }}
>
{/* ... */}
</EmojiPicker.Root>;
buildNativeEmojiSearchTermMapFromEmojibase(entries, options?)
Builds a native-search term map directly from Emojibase-like records.
Notes:
- shortcode data is included by default
labelandtagsare opt-in throughoptions
mergeNativeEmojiSearchTermMaps(...maps)
Combines multiple plain native-search term maps into one normalized result.
Notes:
- normalizes keys to the base emoji form
- deduplicates terms across maps
- useful for layering locale-fallback terms onto existing consumer-owned maps
buildShortcodeMapFromEmojibase(entries)
Builds a shortcode-only map directly from Emojibase-like records.
buildShortcodeMapFromPreset(entries, preset)
Joins Emojibase records with a hexcode-keyed shortcode preset such as
emojibase-data/en/shortcodes/iamcal.json.
Use this when your app treats a preset like iamcal as the source of truth for
native shortcode names.
Lookup helpers
getNativeEmojiSearchTerms(termMap, emoji)
Performs normalized lookup against a native-search term map.
getShortcodes(shortcodeMap, emoji)
Performs normalized lookup against a native shortcode map.
getPrimaryShortcode(shortcodeMap, emoji)
Returns the first normalized shortcode for that emoji.
normalizeNativeEmojiSearchKey(emoji)
Exposes the base-key normalization used by the package.
Normalization behavior:
- removes variation selectors
- removes skin-tone modifiers
- normalizes to a base-emoji lookup key
Exported types
NativeEmojiShortcodeEntryNativeEmojiSearchAdapter<TEntry>EmojibaseNativeEmojiRecordEmojibaseNativeEmojiSkinRecordEmojibaseNativeEmojiSearchOptionsEmojibaseLocaleFallbackSearchOptionsEmojibaseShortcodePresetNativeEmojiSearchTermMapNativeEmojiShortcodeMap
@slithy/emoji-compat
Install:
pnpm add @slithy/emoji-compat
Purpose:
- detects native emoji support and builds fallback metadata for apps that need image fallbacks for newer emoji
Boundary:
- this package does not render anything
- this package does not bundle Twemoji assets
- this package does not choose your app’s fallback policy
Entry point:
import {
buildCompatMap,
detectSupportedVersion,
getCompatEntry,
getFallbackUrl,
isEmojiSupported,
normalizeEmojiCompatKey,
} from "@slithy/emoji-compat";
Build-time asset helpers:
import {
buildFallbackAssetManifest,
collectFallbackHexcodes,
downloadFallbackAssets,
} from "@slithy/emoji-compat/assets";
Runtime helpers
buildCompatMap(records, options?)
Builds fallback metadata keyed by native emoji strings.
Input shape:
type EmojiCompatRecord = {
emoji: string;
version: number;
hexcode?: string;
skins?: readonly {
emoji: string;
hexcode?: string;
}[];
};
Notes:
- if
supportedVersionis provided, that version is treated as the native support floor - if omitted, the package detects support at runtime with its built-in probe
detectSupportedVersion(records, options?)
Determines the highest emoji version supported by the current browser across the provided records.
isEmojiSupported(emoji)
Low-level native-support probe for one emoji glyph.
getCompatEntry(compatMap, emoji)
Looks up one compat entry by normalized emoji key.
getFallbackUrl(compatMap, emoji, options?)
Returns a fallback asset URL when the emoji needs image fallback rendering.
Default convention:
/emoji/{hexcode}.svg
normalizeEmojiCompatKey(emoji)
Exposes the normalization used for compat-map storage and lookup.
Build-time asset helpers
buildFallbackAssetManifest(records, options)
Builds a stable manifest of fallback assets needed above a chosen
versionFloor.
collectFallbackHexcodes(records, options)
Returns just the normalized lowercase hexcodes from that manifest.
downloadFallbackAssets(manifest, options)
Downloads matching fallback assets for a manifest.
Notes:
- intended for build-time scripts
- defaults to the
jdecked/twemojiSVG source - does not run automatically at install or runtime
Exported types
CollectFallbackHexcodesOptionsDownloadFallbackAssetsOptionsDownloadFallbackAssetsResultEmojiCompatRecordEmojiCompatSkinRecordEmojiCompatEntryEmojiCompatMapEmojiCompatOptionsEmojiFallbackUrlOptionsFallbackAssetKindFallbackAssetRecord