• Stars
    star
    956
  • Rank 47,818 (Top 1.0 %)
  • Language
    JavaScript
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A lightweight emoji picker for the modern web

emoji-picker-element

Screenshot of emoji-picker-element in light and dark modes

<emoji-picker></emoji-picker>

A lightweight emoji picker, distributed as a web component.

Features:

Table of contents:

Usage

Via npm:

npm install emoji-picker-element
import 'emoji-picker-element';

Or as a <script> tag:

<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"></script>

Then use the HTML:

<emoji-picker></emoji-picker>

And listen for emoji-click events:

document.querySelector('emoji-picker')
  .addEventListener('emoji-click', event => console.log(event.detail));

This will log:

{
  "emoji": {
    "annotation": "grinning face",
    "group": 0,
    "order": 1,
    "shortcodes": [ "grinning_face", "grinning" ],
    "tags": [ "face", "grin" ],
    "unicode": "πŸ˜€",
    "version": 1,
    "emoticon": ":D"
  },
  "skinTone": 0,
  "unicode": "πŸ˜€"
}

Examples

Emoji support

Emoji support varies across browsers and operating systems. By default, emoji-picker-element will hide unsupported emoji from the picker.

To work around this, you can use a custom emoji font or polyfill flag emoji on Windows.

Custom emoji font

To use a custom emoji font, first set the --emoji-font-family CSS property:

emoji-picker {
  --emoji-font-family: MyCustomFont;
}

Then, specify the maximum emoji version supported by the font (see Emojipedia for a list of versions).

In HTML:

<emoji-picker emoji-version="14.0"></emoji-picker>

Or JavaScript:

const picker = new Picker({
  emojiVersion: 14.0
});

If the emoji-version/emojiVersion option is set, then emoji-picker-element will not attempt to detect unsupported emoji or hide them.

Also note that support for color fonts varies across browsers and OSes, and some browsers may have bugs or not render the font at all. Be careful to test your supported browsers when using this approach.

Polyfilling flag emoji on Windows

As of this writing, Windows does not support country flag emoji. This is only a problem in Chromium-based browsers, because Firefox ships with its own emoji font.

To work around this, you can use country-flag-emoji-polyfill:

import { polyfillCountryFlagEmojis } from 'country-flag-emoji-polyfill';

// emoji-picker-element will use "Twemoji Mozilla" and fall back to other fonts for non-flag emoji
polyfillCountryFlagEmojis('Twemoji Mozilla');

Note that you do not need to do this if you are using a custom emoji font.

Styling

emoji-picker-element uses Shadow DOM, so its inner styling cannot be (easily) changed with arbitrary CSS. Refer to the API below for style customization.

Size

emoji-picker-element has a default size, but you can change it to whatever you want:

emoji-picker {
  width: 400px;
  height: 300px;
}

For instance, to make it expand to fit whatever container you give it:

emoji-picker {
  width: 100%;
  height: 100%;
}

Dark mode

By default, emoji-picker-element will automatically switch to dark mode based on prefers-color-scheme. Or you can add the class dark or light to force dark/light mode:

<emoji-picker class="dark"></emoji-picker>
<emoji-picker class="light"></emoji-picker>

CSS variables

Most colors and sizes can be styled with CSS variables. For example:

emoji-picker {
  --num-columns: 6;
  --emoji-size: 3rem;
  --background: gray;
}

Here is a full list of options:

Variable Default Default (dark) Description
--background #fff #222 Background of the entire <emoji-picker>
--border-color #e0e0e0 #444
--border-size 1px Width of border used in most of the picker
--button-active-background #e6e6e6 #555555 Background of an active button
--button-hover-background #d9d9d9 #484848 Background of a hovered button
--category-emoji-padding var(--emoji-padding) Vertical/horizontal padding on category emoji, if you want it to be different from --emoji-padding
--category-emoji-size var(--emoji-size) Width/height of category emoji, if you want it to be different from --emoji-size
--category-font-color #111 #efefef Font color of custom emoji category headings
--category-font-size 1rem Font size of custom emoji category headings
--emoji-font-family "Twemoji Mozilla","Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji","EmojiOne Color","Android Emoji",sans-serif Font family for a custom emoji font (as opposed to native emoji)
--emoji-padding 0.5rem Vertical and horizontal padding on emoji
--emoji-size 1.375rem Width and height of all emoji
--indicator-color #385ac1 #5373ec Color of the nav indicator
--indicator-height 3px Height of the nav indicator
--input-border-color #999 #ccc
--input-border-radius 0.5rem
--input-border-size 1px
--input-font-color #111 #efefef
--input-font-size 1rem
--input-line-height 1.5
--input-padding 0.25rem
--input-placeholder-color #999 #ccc
--num-columns 8 How many columns to display in the emoji grid
--outline-color #999 #fff Focus outline color
--outline-size 2px Focus outline width
--skintone-border-radius 1rem Border radius of the skintone dropdown

Focus outline

For accessibility reasons, emoji-picker-element displays a prominent focus ring. If you want to hide the focus ring for non-keyboard users (e.g. mouse and touch only), then use the focus-visible polyfill, e.g.:

import 'focus-visible';

const picker = new Picker();
applyFocusVisiblePolyfill(picker.shadowRoot);

emoji-picker-element already ships with the proper CSS for both the :focus-visible standard and the polyfill.

Small screen sizes

For small screen sizes, you should probably add some CSS like the following:

@media screen and (max-width: 320px) {
  emoji-picker {
    --num-columns: 6;
    --category-emoji-size: 1.125rem;
  }
}

emoji-picker-element does not ship with any CSS to explicitly handle small screen sizes. The right CSS depends on which screen sizes your app supports, and the size of the picker within your app. Perhaps in the future container queries can solve this problem.

Custom styling

If you absolutely must go beyond the styling API above, you can do something like this:

const style = document.createElement('style');
style.textContent = `/* custom shadow dom styles here */`
picker.shadowRoot.appendChild(style);

JavaScript API

Picker

Basic usage:

import { Picker } from 'emoji-picker-element';
const picker = new Picker();
document.body.appendChild(picker);

The new Picker(options) constructor supports several options:

Name Type Default Description
customCategorySorting function - Function to sort custom category strings (sorted alphabetically by default)
customEmoji CustomEmoji[] - Array of custom emoji
dataSource string "https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json" URL to fetch the emoji data from (data-source when used as an attribute)
emojiVersion number - Maximum supported emoji version as a number (e.g. 14.0 or 13.1). Setting this disables the default emoji support detection.
i18n I18n - i18n object (see below for details)
locale string "en" Locale string
skinToneEmoji string "πŸ–οΈ" The emoji to use for the skin tone picker (skin-tone-emoji when used as an attribute)

For instance:

const picker = new Picker({
  locale: 'fr',
  dataSource: '/fr-emoji.json'
})

These values can also be set at runtime:

const picker = new Picker();
picker.dataSource = '/my-emoji.json';

Some values can also be set as declarative attributes:

<emoji-picker
  locale="fr"
  data-source="/fr-emoji.json"
  skin-tone-emoji="✌"
></emoji-picker>

Note that complex properties like i18n or customEmoji are not supported as attributes, because the DOM only supports string attributes, not complex objects.

Events

emoji-click

The emoji-click event is fired when an emoji is selected by the user. Example format:

{
  emoji: {
    annotation: 'thumbs up',
    group: 1,
    order: 280,
    shortcodes: ['thumbsup', '+1', 'yes'],
    tags: ['+1', 'hand', 'thumb', 'up'],
    unicode: 'πŸ‘οΈ',
    version: 0.6,
    skins: [
      { tone: 1, unicode: 'πŸ‘πŸ»', version: 1 },
      { tone: 2, unicode: 'πŸ‘πŸΌ', version: 1 },
      { tone: 3, unicode: 'πŸ‘πŸ½', version: 1 },
      { tone: 4, unicode: 'πŸ‘πŸΎ', version: 1 },
      { tone: 5, unicode: 'πŸ‘πŸΏ', version: 1 }
    ]
  },
  skinTone: 4,
  unicode: 'πŸ‘πŸΎ'
}

And usage:

picker.addEventListener('emoji-click', event => {
  console.log(event.detail); // will log something like the above
});

Note that unicode will represent whatever the emoji should look like with the given skinTone. If the skinTone is 0, or if the emoji has no skin tones, then no skin tone is applied to unicode.

skin-tone-change

This event is fired whenever the user selects a new skin tone. Example format:

{
  skinTone: 5
}

And usage:

picker.addEventListener('skin-tone-change', event => {
  console.log(event.detail); // will log something like the above
})

Note that skin tones are an integer from 0 (default) to 1 (light) through 5 (dark).

Internationalization

The i18n parameter specifies translations for the picker interface. Here is the default English i18n object:

{
  "categories": {
    "custom": "Custom",
    "smileys-emotion": "Smileys and emoticons",
    "people-body": "People and body",
    "animals-nature": "Animals and nature",
    "food-drink": "Food and drink",
    "travel-places": "Travel and places",
    "activities": "Activities",
    "objects": "Objects",
    "symbols": "Symbols",
    "flags": "Flags"
  },
  "categoriesLabel": "Categories",
  "emojiUnsupportedMessage": "Your browser does not support color emoji.",
  "favoritesLabel": "Favorites",
  "loadingMessage": "Loading…",
  "networkErrorMessage": "Could not load emoji.",
  "regionLabel": "Emoji picker",
  "searchDescription": "When search results are available, press up or down to select and enter to choose.",
  "searchLabel": "Search",
  "searchResultsLabel": "Search results",
  "skinToneDescription": "When expanded, press up or down to select and enter to choose.",
  "skinToneLabel": "Choose a skin tone (currently {skinTone})",
  "skinTones": [
    "Default",
    "Light",
    "Medium-Light",
    "Medium",
    "Medium-Dark",
    "Dark"
  ],
  "skinTonesLabel": "Skin tones"
}

Note that some of these strings are only visible to users of screen readers. They are still important for accessibility!

Built-in translations

Community-provided translations for some languages are available. You can use them like so:

import fr from 'emoji-picker-element/i18n/fr';
import de from 'emoji-picker-element/i18n/de';

// French
picker.i18n = fr;

// German
picker.i18n = de;

Note that translations for the interface (i18n) are not the same as translations for the emoji data (dataSource and locale). To support both, you should do something like:

import fr from 'emoji-picker-element/i18n/fr';

const picker = new Picker({ 
  i18n: fr,
  locale: 'fr',
  dataSource: 'https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/fr/emojibase/data.json',
});

If a built-in translation for your target language is not available, you can also write your own translation and pass it in as i18n. Please feel free to contribute your translation here.

Custom category order

By default, custom categories are sorted alphabetically. To change this, pass in your own customCategorySorting:

picker.customCategorySorting = (category1, category2) => { /* your sorting code */ };

This function should accept two strings and return a number.

Custom emoji with no category will pass in undefined. By default, these are shown first, with the label "Custom" (determined by i18n.categories.custom).

Database

You can work with the database API separately, which allows you to query emoji the same way that the picker does:

import { Database } from 'emoji-picker-element';

const database = new Database();
await database.getEmojiBySearchPrefix('elephant'); // [{unicode: "🐘", ...}]

Note that under the hood, IndexedDB data is partitioned based on the locale. So if you create two Databases with two different locales, it will store twice as much data.

Also note that, unlike the picker, the database does not filter emoji based on whether they are supported by the current browser/OS or not. To detect emoji support, you can use a library like is-emoji-supported.

Full API:

Constructors

constructor

+ new Database(__namedParameters: object): Database

Create a new Database.

Note that multiple Databases pointing to the same locale will share the same underlying IndexedDB connection and database.

Parameters:

β–ͺDefault value __namedParameters: object= {}

Name Type Default Description
customEmoji CustomEmoji[] [] Array of custom emoji
dataSource string "https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json" URL to fetch the emoji data from
locale string "en" Locale string

Returns: Database

Accessors

customEmoji

β€’ get customEmoji(): CustomEmoji[]

Return the custom emoji associated with this Database, or the empty array if none.

Returns: CustomEmoji[]

β€’ set customEmoji(customEmoji: CustomEmoji[]): void

Set the custom emoji for this database. Throws an error if custom emoji are not in the correct format.

Parameters:

Name Type Description
customEmoji CustomEmoji[]

Returns: void

Methods

close

β–Έ close(): Promiseβ€Ήvoidβ€Ί

Closes the underlying IndexedDB connection. The Database is not usable after that (or any other Databases with the same locale).

Note that as soon as any other non-close/delete method is called, the database will automatically reopen.

Returns: Promiseβ€Ήvoidβ€Ί


delete

β–Έ delete(): Promiseβ€Ήvoidβ€Ί

Deletes the underlying IndexedDB database. The Database is not usable after that (or any other Databases with the same locale).

Note that as soon as any other non-close/delete method is called, the database will be recreated.

Returns: Promiseβ€Ήvoidβ€Ί


getEmojiByGroup

β–Έ getEmojiByGroup(group: number): Promiseβ€ΉNativeEmoji[]β€Ί

Returns all emoji belonging to a group, ordered by order. Only returns native emoji; custom emoji don't belong to a group.

Non-numbers throw an error.

Parameters:

Name Type Description
group number the group number

Returns: Promiseβ€ΉNativeEmoji[]β€Ί


getEmojiBySearchQuery

β–Έ getEmojiBySearchQuery(query: string): Promiseβ€ΉEmoji[]β€Ί

Returns all emoji matching the given search query, ordered by order.

Empty/null strings throw an error.

Parameters:

Name Type Description
query string search query string

Returns: Promiseβ€ΉEmoji[]β€Ί


getEmojiByShortcode

β–Έ getEmojiByShortcode(shortcode: string): Promiseβ€ΉEmoji | nullβ€Ί

Return a single emoji matching the shortcode, or null if not found.

The colons around the shortcode should not be included when querying, e.g. use "slight_smile", not ":slight_smile:". Uppercase versus lowercase does not matter. Empty/null strings throw an error.

Parameters:

Name Type Description
shortcode string

Returns: Promiseβ€ΉEmoji | nullβ€Ί


getEmojiByUnicodeOrName

β–Έ getEmojiByUnicodeOrName(unicodeOrName: string): Promiseβ€ΉEmoji | nullβ€Ί

Return a single native emoji matching the unicode string, or a custom emoji matching the name, or null if not found.

In the case of native emoji, the unicode string can be either the main unicode string, or the unicode of one of the skin tone variants.

Empty/null strings throw an error.

Parameters:

Name Type Description
unicodeOrName string unicode (native emoji) or name (custom emoji)

Returns: Promiseβ€ΉEmoji | nullβ€Ί


getPreferredSkinTone

β–Έ getPreferredSkinTone(): Promiseβ€ΉSkinToneβ€Ί

Get the user's preferred skin tone. Returns 0 if not found.

Returns: Promiseβ€ΉSkinToneβ€Ί


getTopFavoriteEmoji

β–Έ getTopFavoriteEmoji(limit: number): Promiseβ€ΉEmoji[]β€Ί

Get the top favorite emoji in descending order. If there are no favorite emoji yet, returns an empty array.

Parameters:

Name Type Description
limit number maximum number of results to return

Returns: Promiseβ€ΉEmoji[]β€Ί


incrementFavoriteEmojiCount

β–Έ incrementFavoriteEmojiCount(unicodeOrName: string): Promiseβ€Ήvoidβ€Ί

Increment the favorite count for an emoji by one. The unicode string must be non-empty. It should correspond to the base (non-skin-tone) unicode string from the emoji object, or in the case of custom emoji, it should be the name.

Parameters:

Name Type Description
unicodeOrName string unicode of a native emoji, or name of a custom emoji

Returns: Promiseβ€Ήvoidβ€Ί


ready

β–Έ ready(): Promiseβ€Ήvoidβ€Ί

Resolves when the Database is ready, or throws an error if the Database could not initialize.

Note that you don't need to do this before calling other APIs – they will all wait for this promise to resolve before doing anything.

Returns: Promiseβ€Ήvoidβ€Ί


setPreferredSkinTone

β–Έ setPreferredSkinTone(skinTone: SkinTone): Promiseβ€Ήvoidβ€Ί

Set the user's preferred skin tone. Non-numbers throw an error.

Parameters:

Name Type Description
skinTone SkinTone preferred skin tone

Returns: Promiseβ€Ήvoidβ€Ί

Custom emoji

Both the Picker and the Database support custom emoji. Unlike regular emoji, custom emoji are kept in-memory. (It's assumed that they're small, and they might frequently change, so there's not much point in storing them in IndexedDB.)

Custom emoji should follow the format:

[
  {
    name: 'Garfield',
    shortcodes: ['garfield'],
    url: 'http://example.com/garfield.png',
    category: 'Cats'
  },
  {
    name: 'Heathcliff',
    shortcodes: ['heathcliff'],
    url: 'http://example.com/heathcliff.png',
    category: 'Cats'
  },
  {
    name: 'Scooby-Doo',
    shortcodes: ['scooby'],
    url: 'http://example.com/scooby.png',
    category: 'Dogs'
  }  
]

Note that names are assumed to be unique (case-insensitive), and it's assumed that the shortcodes have at least one entry.

The category is optional. If you don't provide it, then the custom emoji will appear in a single category called "Custom".

To pass custom emoji into the Picker:

const picker = new Picker({
  customEmoji: [ /* ... */ ]
});

Or the Database:

const database = new Database({
  customEmoji: [ /* ... */ ]
});

Custom emoji can also be set at runtime:

picker.customEmoji = [ /* ... */ ];
database.customEmoji = [ /* ... */ ];

Tree-shaking

If you want to import the Database without the Picker, or you want to code-split them separately, then do:

import Picker from 'emoji-picker-element/picker';
import Database from 'emoji-picker-element/database';

The reason for this is that Picker automatically registers itself as a custom element, following web component best practices. But this adds side effects, so bundlers like Webpack and Rollup do not tree-shake as well, unless the modules are imported from completely separate files.

Within a Svelte project

emoji-picker-element is explicitly designed as a custom element, and won't work as a direct Svelte component. However, if you're already using Svelte 3, then you can avoid importing Svelte twice by using:

import Picker from 'emoji-picker-element/svelte';

svelte.js is the same as picker.js, except it imports Svelte rather than bundling it.

While this option can reduce your bundle size, note that it only works if your Svelte version is compatible with emoji-picker-element's Svelte version (v3 currently).

Data and offline

Data source and JSON format

If you'd like to host the emoji data (dataSource) yourself, you can do:

npm install emoji-picker-element-data@^1

Then host node_modules/emoji-picker-element-data/en/emojibase/data.json (or other JSON files) on your web server.

const picker = new Picker({
  dataSource: '/path/to/my/webserver/data.json'
});

See emoji-picker-element-data for details.

Shortcodes

There is no standard for shortcodes, so unlike other emoji data, there is some disagreement as to what a "shortcode" actually is.

emoji-picker-element-data is based on emojibase-data, which offers several shortcode packs per language. For instance, you may choose shortcodes from GitHub, Slack, Discord, or Emojibase (the default). You can browse the available data files on jsdelivr and see more details on shortcodes in the Emojibase docs.

Cache performance

For optimal cache performance, it's recommended that your server expose an ETag header. If so, emoji-picker-element can avoid re-downloading the entire JSON file over and over again. Instead, it will do a HEAD request and just check the ETag.

If the server hosting the JSON file is not the same as the one containing the emoji picker, then the cross-origin server will also need to expose Access-Control-Allow-Origin: * and Access-Control-Allow-Headers: ETag (or Access-Control-Allow-Headers: * ). jsdelivr already does this, which is partly why it is the default.

Note that Safari does not currently support Access-Control-Allow-Headers: *, but it does support Access-Control-Allow-Headers: ETag.

If emoji-picker-element cannot use the ETag for any reason, it will fall back to the less performant option, doing a full GET request on every page load.

emojibase-data compatibility (deprecated)

Deprecated: in v1.3.0, emoji-picker-element switched from emojibase-data to emoji-picker-element-data as its default data source. You can still use emojibase-data, but only v5 is supported, not v6. Support may be removed in a later release.

When using emojibase-data, you must use the full emojibase-data JSON file, not the "compact" one (i.e. data.json, not compact.json).

Trimming the emoji data (deprecated)

Deprecated: in v1.3.0, emoji-picker-element switched from emojibase-data to emoji-picker-element-data as its default data source. With the new emoji-picker-element-data, there is no need to trim the emoji down to size. This function is deprecated and may be removed eventually.

If you are hosting the emojibase-data JSON file yourself and would like it to be as small as possible, then you can use the utility trimEmojiData function:

import trimEmojiData from 'emoji-picker-element/trimEmojiData.js';
import emojiBaseData from 'emojibase-data/en/data.json';

const trimmedData = trimEmojiData(emojiBaseData);

Or if your version of Node doesn't support ES modules:

const trimEmojiData = require('emoji-picker-element/trimEmojiData.cjs');

Offline-first

emoji-picker-element uses a "stale while revalidate" strategy to update emoji data. In other words, it will use any existing data it finds in IndexedDB, and lazily update via the dataSource in case that data has changed. This means it will work offline-first the second time it runs.

If you would like to manage the database yourself (e.g. to ensure that it's correctly populated before displaying the Picker), then create a new Database instance and wait for its ready() promise to resolve:

const database = new Database();
try {
  await database.ready();
} catch (err) {
  // Deal with any errors (e.g. offline)
}

If emoji-picker-element fails to fetch the JSON data the first time it loads, then it will display an error message.

Environments without IndexedDB

emoji-picker-element has a hard requirement on IndexedDB, and will not work without it.

For browsers that don't support IndexedDB, such as Firefox in private browsing mode, you can polyfill it using fake-indexeddb. Here is a working example and more details.

For Node.js environments such as Jest or JSDom, you can also use fake-indexeddb. A working example can be found in the tests for this very project.

Design decisions

Some of the reasoning behind why emoji-picker-element is built the way it is.

IndexedDB

The emojibase-data English JSON file is 854kB, and the "compact" version is still 543kB. That's a lot of data to keep in memory just for an emoji picker. And it's not as if that number is ever going down; the Unicode Consortium keeps adding more emoji every year.

Using IndexedDB has a few advantages:

  1. We don't need to keep the full emoji data in memory at all times.
  2. After the first load, there is no need to download, parse, and index the JSON file again, because it's already available in IndexedDB.
  3. If you want, you can even load the IndexedDB data in a web worker, keeping the main thread free from non-UI data processing.

Native emoji

To avoid downloading a large sprite sheet or font file – which may look out-of-place on different platforms, or may have IP issues – emoji-picker-element only renders native emoji by default. This means it is limited to the emoji font actually installed on the user's device.

To avoid rendering ugly unsupported or half-supported emoji, emoji-picker-element will automatically detect emoji support and only render the supported characters. (So no empty boxes or awkward double emoji.) If no color emoji are supported by the browser/OS, then an error message is displayed (e.g. older browsers, some odd Linux configurations).

That said, emoji-picker-element does support custom emoji fonts if you really want.

JSON loading

Browsers deal with JSON more efficiently when it's loaded via fetch() rather than embedded in JavaScript. It's faster for the browser to parse JSON than JavaScript, becuase the data is being parsed in the more tightly-constrained JSON format than the generic JavaScript format.

Plus, embedding the JSON directly would mean re-parsing the entire object on second load, which is something we want to avoid since the data is already in IndexedDB.

Browser support

emoji-picker-element only supports the latest versions of Chrome, Firefox, and Safari, as well as equivalent browsers (Edge, Opera, etc.). If you need support for older browsers, you will need polyfills for the following things (non-exhaustive list):

  • Custom elements
  • Shadow DOM
  • ES2019+

That said, older browsers may not have a color emoji font installed at all, so emoji-picker-element will not work in those cases.

Contributing

See CONTRIBUTING.md.

More Repositories

1

optimize-js

Optimize a JS file for faster parsing (UNMAINTAINED)
JavaScript
3,754
star
2

fuite

A tool for finding memory leaks in web apps
JavaScript
3,488
star
3

pokedex.org

Offline-capable PokΓ©dex web site (unmaintained)
JavaScript
2,269
star
4

marky

High-resolution JavaScript timer based on performance.mark/measure (491 bytes min+gz)
JavaScript
1,097
star
5

pinafore

Alternative web client for Mastodon (UNMAINTAINED)
JavaScript
1,020
star
6

slow-deps

🐌 Measure which dependencies in a project are slowest to npm install (UNMAINTAINED)
JavaScript
513
star
7

blob-util

Cross-browser utils for working with binary Blobs
TypeScript
489
star
8

Catlog

Logcat-reading app for Android (UNMAINTAINED)
Java
471
star
9

promise-worker

Promise-based messaging for Web Workers and Service Workers
JavaScript
465
star
10

pouchdb-find

Easy-to-use query language for PouchDB. ⚠️ NOTICE ⚠️: moved to the PouchDB repo
JavaScript
433
star
11

rollupify

Browserify transform to apply Rollup (UNMAINTAINED)
JavaScript
386
star
12

cjs-to-es6

CLI to convert CommonJS to ES6 modules (UNMAINTAINED)
JavaScript
262
star
13

pseudo-worker

A tiny and mostly spec-compliant WebWorker polyfill
JavaScript
243
star
14

cordova-plugin-sqlite-2

Native SQLite database API for Cordova/PhoneGap/Ionic, modeled after WebSQL (UNMAINTAINED)
JavaScript
169
star
15

CustomFastScrollViewDemo

Demo of an Android app using a FastScrollView with non-alphabetic overlays.
Java
130
star
16

pouchdb-electron

PouchDB for Electron (formerly Atom Shell)
126
star
17

hello-javascript

Demo of a JavaScript module that supports many publishing options
JavaScript
121
star
18

jison-debugger

UI for debugging Jison grammars (UNMAINTAINED)
JavaScript
117
star
19

pretty-s3-index-html

A prettier index.html for listing public files and folders in Amazon S3 buckets. (UNMAINTAINED)
HTML
112
star
20

node-websql

The WebSQL Database API, implemented for Node.js
JavaScript
87
star
21

SuperSaiyanScrollView

Super-fast, super-lightweight sectioned lists for Android
Java
81
star
22

state-of-binary-data-in-the-browser

The state of binary data in the browser (2015)
79
star
23

KeepScore

Score keeping app for Android (unmaintained)
Java
68
star
24

rollup-comparison

compare rollup to browserify/webpack
JavaScript
67
star
25

vdom-as-json

Convert virtual-dom objects to and from JSON (UNMAINTAINED)
JavaScript
64
star
26

database-comparison

Compare DOM-blocking in browser databases
JavaScript
58
star
27

vdom-serialized-patch

Serialize virtual-dom patches as a minimal JSON object (UNMAINTAINED)
JavaScript
56
star
28

pouchdb-phonegap-cordova

PouchDB for PhoneGap/Cordova
55
star
29

chord-magic

Musical chord parser, transposer, and disambiguator in JavaScript
JavaScript
54
star
30

html5workertest

Show which APIs are supported in Web Workers and Service Workers (UNMAINTAINED)
JavaScript
53
star
31

resources-for-mastodon-newbies

Links and tips for Mastodon newbies
53
star
32

fruitdown

Browser-based LevelDOWN adapter that works over Apple IndexedDB (UNMAINTAINED)
JavaScript
50
star
33

vuvuzela

Simple and non-recursive JSON parse/stringify library
JavaScript
45
star
34

AppTracker

Android app that logs app usage statistics in a background Service and displays app information (most frequently used, most recently used, etc.) in a widget or in the main activity.
Java
42
star
35

cost-of-small-modules

Benchmark showing the cost of various bundlers (repo locked πŸ”’)
Shell
38
star
36

pouchdb-async-storage

PouchDB adapter for AsyncStorageDOWN for use in React Native (INCOMPLETE)
JavaScript
37
star
37

ChordReaderRoot

Android app for reading and transposing downloaded guitar chord charts. (unmaintained)
Java
29
star
38

PouchDroid

PouchDB + Android = deliciously synchronous (DEPRECATED! DO NOT USE!)
JavaScript
29
star
39

async-functions-in-pouchdb

Demo of ES7 async functions in PouchDB
JavaScript
28
star
40

pouchdb-ionic

PouchDB for Ionic Framework
27
star
41

arrow-key-navigation

Add left/right focus navigation to a web app or KaiOS app
JavaScript
23
star
42

base64-encode-string

Simple module that converts a string to base64 (for educational purposes)
JavaScript
23
star
43

pouchdb-with-service-workers

Repo for brainstorming on PouchDB replication with service workers
22
star
44

tiny-queue

Simple JavaScript FIFO queue implementation to avoid having to do shift()
JavaScript
21
star
45

css-talk-2022

Talk given in October 2022 for perf.now about CSS runtime performance
JavaScript
21
star
46

pouchdb-nw

PouchDB for NW.js (aka Node-Webkit)
20
star
47

OfflineBrowser

Android app to view HTML pages offline.
Java
19
star
48

test-optimize-js

Web page to test optimize-js against any JavaScript file
JavaScript
19
star
49

serviceworker-update-demo

Effort to write a ServiceWorker demo app that properly manages updates
JavaScript
16
star
50

JapaneseNameConverterRoot

Android app to convert English names into Japanese characters.
Java
16
star
51

SimpleTalker

Simple Android app to speak some text passed in as a parameter. Intended to be used from the command line.
Java
16
star
52

pouchdb-ionic-hello-world

PouchDB Ionic "hello world" app (using Ionic v1)
JavaScript
15
star
53

pouchdb-cordova-hello-world-with-sqlite-plugin

"Hello world" Cordova app with PouchDB, using the SQLite Plugin
CSS
15
star
54

mingz

Check the browserified+min+gz size of any npm module (bash script)
14
star
55

braziljs-2016

Nolan's BrazilJS talk: "We can work it out: from Web Workers to Service Workers"
JavaScript
14
star
56

PopupDemo

Demo of a Quick Action-like popup in Android
Java
14
star
57

open-stylable

Web component where styles leak in, but they don't leak out
JavaScript
13
star
58

substring-trie

Minimalistic trie implementation for prefix searches
JavaScript
13
star
59

cordova-prepopulated-database-demo

Demo of prepopulated databases in Cordova SQLite Plugin 2
JavaScript
12
star
60

pouchdb-nw-hello-world

Demo of using PouchDB in NW.js (aka Node-WebKit)
JavaScript
12
star
61

package-json-versionify

Browserify transform to strip everything from package.json except for the "version" field.
JavaScript
12
star
62

measure-style-and-layout

Demo of measuring style and layout in a webapp
HTML
10
star
63

pouchdb-ionic-2-typescript-demo

Demo of PouchDB with Ionic 2 and TypeScript
JavaScript
10
star
64

browserify-count-modules

Count the total number of modules in a Browserify bundle.
JavaScript
10
star
65

web-starter-kit-rollupify

web starter kit, but with browserify+watchify+rollupify
HTML
10
star
66

webworker-postmessage-perf-test

Web Worker postMessage() benchmark
HTML
9
star
67

pouchdb-chrome-app

PouchDB for Chrome packaged apps
9
star
68

lodash-bundle-size-test

Test repo for experimenting with babel-plugin-lodash and lodash-webpack-plugin
JavaScript
8
star
69

emoji-mart-outside-react

Demo of how to use emoji-mart outside of React
JavaScript
8
star
70

throw-max-listeners-error

Throw an error if the max number of EventEmitter listeners is exceeded
JavaScript
7
star
71

pouchdb-getting-started-todo

Complete PouchDB "Getting Started" Todo app
CSS
7
star
72

memory-leaks-2020

Slides for a talk given at QueensJS in August 2020
HTML
7
star
73

database-comparison-worker-pouch

Fork of https://github.com/nolanlawson/database-comparison to demo worker-pouch
JavaScript
7
star
74

pouchdb-adapter-cordova-sqlite-demo

Demo of using pouchdb-adapter-cordova-sqlite in an Ionic 1 project (note: PouchDB v6, Ionic v1)
JavaScript
7
star
75

pouchdb-chrome-app-hello-world

"Hello world" Chrome app with PouchDB
JavaScript
6
star
76

shadow-selector-benchmark

Benchmark of shadow DOM with various CSS selectors
JavaScript
6
star
77

debug-websql

Simple script to console.log every SQL query received by Web SQL
JavaScript
6
star
78

sqlite-plugin-fork

Fork of the SQLite plugin from 2014, back when it was compatible with PouchDB
JavaScript
6
star
79

pouchdb-cordova-hello-world

"Hello world" Cordova app with PouchDB
CSS
6
star
80

fabric-calculator

Web app to calculate how much fabric you need for a sewing project
Svelte
6
star
81

RelatednessCalculator

Java library for parsing English relative names ("mom," "dad," "grandma," etc.) and calculating relatedness coefficients.
Java
6
star
82

sugar-pouch

A sweeter, simpler interface for PouchDB (work in progress)
6
star
83

pouchdb-perf-report-3.10

PouchDB Performance Report for v3.1.0, November 2014
5
star
84

pouchdb-prebuilt-demo

Demo of a prebult PouchDB database, used in a Cordova app.
JavaScript
5
star
85

async-functions-with-regenerator

A "hello world" for async/await with Babel and Regenerator
JavaScript
5
star
86

CatLogDonate

Java
5
star
87

ultimate-crossword-app

The Ultimate Crossword - an online crossword puzzle (UNMAINTAINED)
JavaScript
5
star
88

react-wheel-jank-demo

Demo of a React app that causes janky scrolling by attaching a wheel event to the entire document
JavaScript
5
star
89

webperf-2016-03

Nolan's 30-minute talk on Web Workers for the NYC Web Performance meetup in March 2016.
JavaScript
5
star
90

couch-community-compat-table

The state of sync pairs in the Couch community
4
star
91

offlinefirst-2016-03

Nolan's presentation for Offline First meetup, Boston March 2016
JavaScript
4
star
92

cascadia-2016

Nolan's talk on Web Workers and Service Workers for Cascadia Fest 2016
JavaScript
4
star
93

pouchdb-ionic-2-hello-world-with-sqlite

PouchDB "Hello world" app using Ionic v2, with native SQLite
TypeScript
4
star
94

async-rect

DEPRECATED - do not use
JavaScript
4
star
95

RelatednessCalculatorInterface

Grails frontend interface for the RelatednessCalculator
JavaScript
4
star
96

jnameconverter-server

JapaneseNameConverter simple RESTful web server
Java
4
star
97

starwars-data

generate data for the starwars-offline app
Python
4
star
98

pwa-deploy

Deploy a Progressive Web App to a connected Android device or emulator (EXPERIMENTAL - DON'T USE THIS)
Java
4
star
99

async-functions-with-kneden

A "hello world" for async/await with Babel and Kneden
JavaScript
3
star
100

independent-rendering-test

Independent Rendering test demo
JavaScript
3
star