npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

emoji-main-color-react-native

v1.1.0

Published

React Native library that extracts the dominant color and optional palette for an emoji.

Readme

emoji-main-color-react-native

A React Native library that renders an emoji into a native bitmap, extracts its dominant color, real darker and lighter representative colors, and can optionally return a small palette.

The package is built for real React Native apps:

  • TypeScript-first public API
  • small native bridge on iOS and Android
  • memory and disk cache support
  • concurrent request deduplication
  • no external runtime dependencies

Installation

npm install emoji-main-color-react-native
# or
yarn add emoji-main-color-react-native

iOS

bundle install
cd ios && bundle exec pod install && cd ..

If your app uses static framework linkage for Swift pods, keep this in your Podfile:

use_frameworks! :linkage => :static

Android

No extra setup is required beyond React Native autolinking.

Usage

getEmojiColor

import {getEmojiColor} from 'emoji-main-color-react-native';

const result = await getEmojiColor('🍋', {
  cache: 'disk',
  paletteSize: 4,
  renderSize: 72,
});

console.log(result);
// {
//   emoji: '🍋',
//   mainColor: '#F4D83D',
//   mainDarkColor: '#6D8D3F',
//   mainLightColor: '#F8E789',
//   palette: ['#F4D83D', '#A8C15A', '#6D8D3F', '#D89C36'],
//   source: 'computed' | 'memory-cache' | 'disk-cache'
// }

getEmojiColors

import {getEmojiColors} from 'emoji-main-color-react-native';

const results = await getEmojiColors(['🍋', '🦊', '🌵'], {
  cache: 'memory',
  renderSize: 64,
});

useEmojiColor

import React from 'react';
import {Text, View} from 'react-native';
import {useEmojiColor} from 'emoji-main-color-react-native';

export function EmojiPreview() {
  const {result, loading, error, reload} = useEmojiColor('🦊', {
    cache: 'disk',
    paletteSize: 3,
  });

  if (loading) {
    return <Text>Loading…</Text>;
  }

  if (error != null) {
    return <Text onPress={reload}>{error.message}</Text>;
  }

  return (
    <View>
      <Text>{result?.emoji}</Text>
      <Text>{result?.mainColor}</Text>
    </View>
  );
}

API

Functions

getEmojiColor(emoji, options?)

Returns a Promise<EmojiColorResult>.

getEmojiColors(emojis, options?)

Runs getEmojiColor for each entry and preserves order.

useEmojiColor(emoji, options?)

Returns:

type UseEmojiColorResult = {
  result: EmojiColorResult | null;
  loading: boolean;
  error: Error | null;
  reload: () => void;
};

Types

type CacheMode = 'memory' | 'disk';

type GetEmojiColorOptions = {
  cache?: CacheMode;
  paletteSize?: number;
  renderSize?: number;
  fallbackColor?: string;
};

type EmojiColorResult = {
  emoji: string;
  mainColor: string;
  mainDarkColor: string;
  mainLightColor: string;
  palette?: string[];
  source: 'computed' | 'memory-cache' | 'disk-cache';
};

mainDarkColor and mainLightColor are selected from the same sampled native emoji clusters as mainColor. They are not generated by darkening or lightening mainColor.

Cache behavior

  • When cache is omitted, the library computes each request fresh.
  • When cache: 'memory', the library checks an in-memory JS cache before computing.
  • When cache: 'disk', the library checks memory first, then native disk cache, then computes and stores in both.
  • Cache keys include the emoji, the algorithm version, paletteSize, and renderSize.
  • In-flight work is deduplicated so repeated concurrent calls for the same emoji and options share one native computation.

Invalid input and fallback behavior

  • Empty or clearly invalid emoji input throws EmojiColorError.
  • If fallbackColor is provided, invalid input or native extraction failures return that color instead of throwing.
  • fallbackColor must be a 6-digit hex string like #F4D83D.

How color extraction works

Each platform follows the same high-level pipeline:

  1. Render the emoji to a transparent bitmap natively.
  2. Sample pixels with transparency filtering.
  3. Quantize colors into compact buckets for speed.
  4. Downweight tiny highlights, very dark outlines, and near-white glare.
  5. Merge similar buckets into broader clusters.
  6. Return the top cluster as mainColor, the strongest real darker and lighter clusters as mainDarkColor and mainLightColor, and the top paletteSize clusters as palette.

This is intentionally a practical dominant-color algorithm rather than a perfect pixel histogram. It favors stable, visually useful colors for UI work.

Performance notes

  • Default renderSize is 64, which balances visual fidelity and speed well for most apps.
  • Larger render sizes can improve palette quality for complex emoji sequences, but they cost more CPU.
  • Memory cache is the best option for repeated lookups during one app session.
  • Disk cache is useful when the same emoji set appears across launches.

Platform notes

  • Results can differ slightly between iOS and Android because each OS renders emoji using its own native font artwork.
  • The algorithm is kept intentionally similar across platforms, but platform rendering still affects the final sampled pixels.
  • Disk cache is stored in each platform’s cache directory, so the OS may clear it at any time.

Example

See example/App.tsx for a demo screen.

Development

npm install
npm run verify

Testing

The test suite covers:

  • memory cache behavior
  • disk cache behavior
  • result shape normalization
  • invalid input handling
  • hook behavior
  • concurrent request deduplication

Tradeoffs

  • The native bridge is deliberately small and synchronous in scope: render, analyze, and cache.
  • The extraction algorithm is heuristic rather than ML-based, which keeps the package dependency-free and fast.
  • The hook returns a small state object instead of trying to hide loading and error states.
  • Results are deterministic per platform, but not guaranteed to match across platforms because emoji glyphs differ.