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

@open-pencil-lowcode/motion-runtime

v0.15.0

Published

Framework-neutral playback and DOM adapters for OpenPencil `MotionSpec` documents. The package uses the same prepared-plan sampler as the editor and compiler, does not evaluate arbitrary CSS or JavaScript, and reads no browser globals at module evaluation

Readme

@open-pencil-lowcode/motion-runtime

Framework-neutral playback and DOM adapters for OpenPencil MotionSpec documents. The package uses the same prepared-plan sampler as the editor and compiler, does not evaluate arbitrary CSS or JavaScript, and reads no browser globals at module evaluation time.

Installation

bun add @open-pencil-lowcode/motion-runtime @open-pencil-lowcode/motion @open-pencil-lowcode/scene-graph

Install vue only when using the optional @open-pencil-lowcode/motion-runtime/vue entrypoint.

Framework-neutral runtime

import { createMotionRuntime } from '@open-pencil-lowcode/motion-runtime'

const runtime = createMotionRuntime({ prefersReducedMotion: false })
const animation = runtime.register({
  id: 'hero',
  motion,
  selection: { mode: 'trigger', trigger: 'mount' },
  apply: ({ sample }) => renderVisualState(sample.visual)
})

animation.play()
// Later: animation.pause(), animation.seek(250), animation.reverse(), animation.dispose()
runtime.setPrefersReducedMotion(true)

One runtime coalesces every active binding into one frame request. Prepared plans are reused across frames, registrations are bounded, equal-time application order is stable, and every adapter has an explicit cleanup path. createManualMotionClock() provides exact fixed-time playback for tests, server-side work, and deterministic exports. setPrefersReducedMotion() rebuilds canonical prepared plans in place while preserving logical progress, playback state, and playback rate, including finite, infinite, and temporarily disabled plans.

The public @open-pencil-lowcode/motion-runtime/kernel entrypoint owns the easing, sampled-channel, iteration/fill, and cancellation-safe frame-loop implementation. OpenPencil's React compiler uses that entrypoint at compile time and embeds the exact package-owned kernel into generated projects. The generated application therefore keeps no OpenPencil runtime dependency while still sharing the SDK's scheduler and sampling behavior. The embedded kernel is pure and reads no DOM or browser globals; browser event ownership and reversible style projection remain in the generated adapter.

DOM and Vanilla adapters

import { createVanillaMotion } from '@open-pencil-lowcode/motion-runtime/vanilla'

const controller = createVanillaMotion({
  element: document.querySelector('.hero')!,
  motion,
  trigger: 'hover'
})

// Removes listeners, cancels playback, and restores the original inline styles.
controller.dispose()

The DOM adapter projects common transform, opacity, geometry, simple paint/effect, layout, and variable-font channels. Unicode text reveal requires an explicit textContent reader/writer; it uses the same Array.from code-point split and rounding as the reference renderer and restores the authored snapshot on cleanup. Indexed paints, gradient stops, structured effects, and vector morphs require both applyAdvanced and the matching advancedCapabilities declaration. Otherwise DOMMotionCapabilityError is raised before any style is changed, rather than silently approximating or dropping the channel. A reduced-motion policy that selects no tracks restores authored DOM state instead of writing identity transforms, opacity, or custom properties.

Continuous drivers

import { createDOMMotionDrivers } from '@open-pencil-lowcode/motion-runtime/drivers'

const drivers = createDOMMotionDrivers({
  id: 'page-home',
  owner: document.querySelector('[data-op-motion-scope]')!,
  spec: motionDrivers,
  resolveElement: (id, owner) =>
    owner.querySelector<HTMLElement>(`[data-node-id="${CSS.escape(id)}"]`) ?? undefined,
  resolveMotion: (id) => motionByNodeId.get(id)
})

drivers.setPageState('progress', 0.5)
drivers.setDocumentState('onboarding', 1)
drivers.setVariable('motion.intensity', 0.8)
drivers.dispose()

Scroll, pointer, drag, and visibility sources install bounded owner-scoped browser listeners; page state, document state, and variables are explicit host bridges. Input updates are coalesced into one frame and use the same direct-progress reference sampler. Disposal removes all listeners and observers, cancels scheduled work, restores owned styles/attributes, and prevents stale writes.

Vue adapter

import { useMotion } from '@open-pencil-lowcode/motion-runtime/vue'

const element = useTemplateRef<HTMLElement>('hero')
const animation = useMotion(element, () => props.motion, { trigger: 'mount' })

useMotion() reacts to element/spec replacement and disposes listeners, styles, and owned runtime state with its Vue effect scope. Importing the package root or DOM entrypoint never loads Vue, which keeps SSR and non-Vue bundles tree-shakeable. Vanilla and Vue-owned runtimes follow live prefers-reduced-motion changes when no explicit preference is supplied. Injected runtimes are never observed or disposed; their host owns setPrefersReducedMotion() and lifecycle cleanup.