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

@lordicon/runtime

v0.2.0

Published

The engine of Lordicon players: icons rendered by ThorVG to pixels, natively (C++) and in WebAssembly, with live colours and stroke.

Readme

Lordicon Runtime

The engine under Lordicon players. It takes an animated Lordicon icon and turns it into pixels with ThorVG, natively (C++) and in WebAssembly, and it looks the same on every platform.

This is for player authors. The runtime knows frames, segments, colours and stroke. States, triggers and components are the job of the players built on it. In an app, use a player: @lordicon/react-native for React Native, @lordicon/element or @lordicon/react for the web.

What it adds to ThorVG:

  • it resolves the expressions Lordicon icons use for colours and stroke into values and ThorVG slots, so ThorVG runs without a JavaScript engine and colours and stroke change live (animated stroke widths keep their keyframes),
  • it plays a segment (speed, direction, loop, a rest between rounds) on your clock: call tick(dt), and render when something changed,
  • it parses an icon once for any number of drawings of it, each with its own frame and look,
  • it renders into an RGBA buffer: a canvas on the web, a bitmap or a layer on mobile, a file,
  • it ships ThorVG with patches that make icons play as they were designed in After Effects (blend modes, trims, easing, mattes; see below).

Install

npm install @lordicon/runtime

The package holds the TypeScript API with the WebAssembly (dist/), and the C++ sources for native builds (core/, CMakeLists.txt, ThorVG already patched in thorvg-src/).

The .wasm file

lordicon.wasm (about 140 KB gzipped) sits next to the code in dist and loads from there.

  • With a bundler (Vite, webpack): nothing to do, it finds the file and copies it.
  • Served as it is: serve dist from one place and import its index.js.
  • From elsewhere: createRuntime({ wasm: '/libs/lordicon.wasm' }).
  • Node, or bytes you have: createRuntime({ wasm: readFileSync(path) }).

Example: frames of an icon to PNG in Node.

Web: a first frame

import { createRuntime, Events } from '@lordicon/runtime';

const runtime = await createRuntime();
const icon = runtime.load(await (await fetch('/icons/download.json')).text());

const hover = icon.markers.find((m) => m.name === 'default:hover-pinch');
icon.segment(hover.begin, hover.end);
icon.play();

const context = canvas.getContext('2d');
let last = 0;
requestAnimationFrame(function frame(now) {
    const events = icon.tick(last ? (now - last) / 1000 : 0);
    last = now;
    if (events & Events.frame) icon.draw(context);
    if (icon.playing) requestAnimationFrame(frame);
});

load() throws when the text is not a Lottie icon. Example: 01 Playback; all examples are listed at the end.

Icons and models

runtime.load(json) takes the icon's Lottie JSON, as text or an object, and returns an Icon. For an icon shown in many places at once, parse it once into a model and draw icons from it: one copy in memory (50 to 470 KB saved per icon after the first), no parsing for the next ones, and each has its own playback and look.

const model = runtime.model(json);
const icons = [model.icon(), model.icon()];
model.destroy(); // the icons keep the model

An Icon:

| | | | ------------------------------------------------------------------- | ----------------------------------------------------------------------------- | | width, height | the composition size | | frameRate, totalFrames, firstFrame | totalFrames is op - ip, firstFrame is ip (widened to the markers) | | markers | [{ name: 'default:hover-pinch', begin, end }, ...] | | colors, setColor(name, '#rrggbb') | the icon's named colours; a change takes effect on the next frame | | stroke, setStroke(1 \| 2 \| 3) | light, regular, bold; stroke is 0 for icons without a stroke control | | setTint('#rrggbb' \| null) | the whole icon in one colour, alpha kept, like CSS currentColor | | segment(begin, end), playback({ speed, direction, loop, rest }) | what to play; rest: seconds on the last frame between loop rounds | | play(), pause(), playing, seek(frame), frame | | | tick(dt) | advances by dt seconds, returns Events flags: complete, loop, frame | | draw(context, width?, height?) | renders onto a 2D canvas context, its whole size by default | | render(width, height) | renders into a new Uint8ClampedArray, RGBA with straight alpha | | destroy() | frees the icon |

Markers name the icon's states: default: marks the default one, a suffix like :0.5 the point of a morph's turn. Frames are absolute, as markers count them: from firstFrame to firstFrame + totalFrames - 1. A file narrowed to one state (ip, op around it, as lordicon.com often gives it) still holds all its states: its frames are widened to its markers, so every state plays, as in the Lordicon players. Examples: 02 Colours, stroke and tint, 04 Models.

Playback

icon.segment(cycle.begin, cycle.end);
icon.playback({ loop: true, rest: 0.5 }); // half a second on the last frame between rounds
icon.play();

const events = icon.tick(dt);
if (events & Events.frame) icon.draw(context);
if (events & Events.loop) console.log('a round ended');
if (events & Events.complete) console.log('the segment ended');

The runtime has no clock: the caller ticks every icon with the time since the last tick, and draws when tick() says there is a new frame. pause() holds a rest too; turning the loop off ends the round in progress. Example: 03 Loops and events.

Threads and workers

A runtime and its icons belong to one thread. To render on several, create a runtime in each Web Worker and hand canvases over with transferControlToOffscreen(): the main thread stays free, and icons keep moving while it is busy. Example: 05 Workers.

Native

The core is C++ with a C API, core/lordicon_c.h, for JNI, Objective-C++ or anything that links C. CMakeLists.txt builds ThorVG and the core from a source list, with no other build system:

add_subdirectory(path/to/@lordicon/runtime lordicon)
target_link_libraries(your_target PRIVATE lordicon_core)
li_init(0);
li_shared_canvas(1);                          /* one ThorVG canvas per thread */
li_model* model = li_model_load(json, size, -1);
li_icon* icon = li_icon_new(model);           /* or li_load(json, size, -1) for one */
li_model_free(model);                         /* the icon keeps it */
li_segment(icon, begin, end);
li_play(icon);

/* on every frame of the platform clock */
if (li_tick(icon, dt) & LI_EVENT_FRAME)
    li_render_into(icon, pixels, width, height, stride, 1 /* premultiplied */);

| Group | Functions | | --------- | ---------------------------------------------------------------------------------------------------------- | | setup | li_init, li_shared_canvas, li_term | | loading | li_model_load, li_model_free, li_icon_new, li_load, li_free | | the file | li_width, li_height, li_frame_rate, li_total_frames, li_first_frame, li_marker_* | | looks | li_color_count, li_color_name, li_color, li_set_color, li_stroke, li_set_stroke, li_set_tint | | playback | li_segment, li_playback, li_play, li_pause, li_playing, li_seek, li_current_frame, li_tick | | rendering | li_render (the icon's own buffer), li_render_into (yours, straight or premultiplied alpha) |

Threads: a model and its icons are used from one thread, always the same one with li_shared_canvas(1), also to free them. Different models can render on different threads at the same time. Before rendering, an icon puts its frame and look on the model; equal looks share one ThorVG slot.

The ThorVG sources come from, in this order: -DTHORVG_SRC=<patched tree>, thorvg-src/ next to CMakeLists.txt (in the npm package), or the thorvg/ submodule of a clone, exported and patched into the build directory. core/thorvg/config.h is ThorVG's build configuration for any build system: @lordicon/react-native compiles the same files with CMake on Android and CocoaPods on iOS. Size (stripped, core and ThorVG, C API only): about 375 KB on arm64 with -Os and the shared C++ runtime, as in an Android app.

Example: the C API from a CMake project.

Examples

npm start in a clone serves the web ones at http://localhost:8080.

| Example | What | | --------------------------------------------------- | ------------------------------------------------------ | | 01 Playback | states from markers, play, pause, loop, speed | | 02 Colours, stroke and tint | changed live, without reloading | | 03 Loops and events | a rest between rounds, the flags of tick() | | 04 Models | an icon parsed once for many, one clock for all | | 05 Workers | icons rendered on several threads | | Node | frames of an icon to PNG files | | Native | a model, two icons, a clock, frames to PNG, from CMake |

How faithful it is

Icons play as they do in the Lordicon web player. Small differences can show up, such as a line a pixel off in fast motion. If an icon looks clearly wrong, please open an issue with the icon file.

Like the web player, the runtime applies the expressions Lordicon icons use for colours and stroke, resolved when the icon loads. Any other expression keeps the value stored in the file.

ThorVG and its patches

patches/ holds our changes to ThorVG. Each patch starts with a header that says what it fixes and where it comes from. Most of them make ThorVG draw icons the way After Effects does; two are based on unmerged pull requests by ThorVG contributors. Each fix comes with a minimal Lottie file in patches/cases/ and a test. See THIRD_PARTY.md and, to update ThorVG, CONTRIBUTING.md.

License

MIT, see LICENSE.md. ThorVG, RapidJSON and Emscripten: see THIRD_PARTY.md.