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

@pixoopal/clockface

v0.2.4

Published

Clockface SDK for PixooPal.

Readme

@pixoopal/clockface SDK

Small SDK for building PixooPal Clockfaces.

Examples of usage can be found at this repository.

Author note: Please note that this SDK, including this readme, was generated by AI. You are warned. It's fully usable though.

Main API

defineClockface(options)

Creates a Clockface instance from a friendly object API.

  • resolution: number or (context) => number.
  • data: persistent string-backed fields created with data.*.
  • inputs: UI controls created with input.*; nested arrays render as rows.
  • interval: requested render interval in ms. You may want to use this to lower your FPS. This will not help you make clockface more speedier, as we're currently capped at [180ms for 64-64, 80ms for 32-32]. It's Pixoo's limitation. Maybe in the future some hero will write a custom firmware with optimized API, but I wouldn't count on that.
  • getInterval(context): dynamic interval.
  • frameQueueSize: queued frame count; This can help you to deal with CPU spikes in lower-spec machines. 5-10 recommended for predicable clockfaces, and 0 recommended for games like Snake.
  • setup(context): runs before first render. Good place for initialization.
  • render(context): draws the frame.
  • start(context): runs when the Clockface starts.
  • stop(context): runs when the Clockface stops.

Clockface Resolution

If you want a Community Clockface to follow PixooPal's RESOLUTION environment variable, you can do so like this:

export default defineClockface({
  resolution: Number.parseInt(process.env.RESOLUTION) ?? 32,
  render: (context) => {
    
  }
});

16*16 clockfaces will be correctly shown by 32/64 Pixoo.

Data Helpers

All data.* helpers return a typed default field; values are stored as strings in context.data.

  • data.string(defaultValue = '')
  • data.number(defaultValue = 0)
  • data.color(defaultValue = '#ffffff')
  • data.select(defaultValue)

Input Helpers

All inputs take id, friendlyName, and optional settings. If id exists in data, non-button inputs update context.data[id] automatically before onSubmit.

  • input.text(id, friendlyName, options?)
  • input.number(id, friendlyName, options?)
  • input.color(id, friendlyName, options?)
  • input.file(id, friendlyName, options?)
  • input.select(id, friendlyName, options, inputOptions?)
  • input.button(id, friendlyName, options?)

Common input options:

  • isSetting: whether the input is a setting. Settings are only shown inside WebUI (and not inside HA's Card) under gear icon.
  • keyCodes: keyboard shortcuts using KeyboardEvent.code, for example 'ArrowUp'. Unlocks ext level gaming.
input.button('moveLeft', 'Left', {
  keyCodes: ['ArrowLeft', 'KeyA'],
  onSubmit: (_value, context) => {
    context.persistence.set('direction', 'left');
  }
});
  • onSubmit(value, context): custom submit handler.
  • min, max, step: number input bounds.
  • accept: file input accept string.
  • options: select options as { value, label }.

Color Helpers

  • color.black: [0, 0, 0].
  • color.white: [255, 255, 255].
  • color.parse(value): parses '#rrggbb', '#rgb', or RGB tuples.
  • color.mix(start, end, amount): blends two colors, with amount clamped to 0..1.

Clockface Context

Every lifecycle method receives context.

  • context.resolution: current size.
  • context.data: string-backed persistent data.
  • context.inputs: flat input list.
  • context.buffer: mutable flat RGB buffer.
  • context.canvas: drawing helpers.
  • context.persistence: custom persisted state helpers.
  • context.homeAssistant: Home Assistant bridge.
  • context.lifecycle: timer and cleanup helpers.

Canvas Methods

context.canvas writes into context.buffer.

  • clear(fill?): fills the whole frame; default is black.
  • getPixel(x, y): reads one RGB pixel.
  • pixel(x, y, colorOrOptions): writes one pixel.
  • blendPixel(x, y, color, opacity): alpha-blends one pixel.
  • rect(x, y, width, height, options?): draws a rectangle with fill, stroke, opacity.
  • circle(x, y, radius, options?): draws a circle with fill, stroke, opacity.
  • text(text, x, y, options?): draws bitmap text; options include fill, fontName, opacity.
  • media(asset, type, options?): draws image, gif, or video media; options include x, y, width, height.

Pixel buffer layout: ClockfacePixelBuffer is Uint8Array RGB. Pixel (x, y) starts at (x + y * size) * 3.

Persistence Methods

context.persistence stores extra state separately from context.data.

  • state: current raw persisted state object.
  • get(key, fallback): reads one value.
  • set(key, value): writes one value.
  • update(values): merges several values.

Home Assistant Methods

context.homeAssistant is available when the host provides an integration.

  • connected: boolean connection state.
  • renderJinja(template, variables?): renders a Jinja template.
  • fetchBinary(url): fetches binary data and returns { bytes, type }.
  • callService(domain, service, data?, options?): calls a Home Assistant service; options.returnResponse requests a response.

Lifecycle Methods

Use context.lifecycle for work that must be cleaned up on stop.

  • cleanup(dispose): registers a cleanup callback.
  • setInterval(handler, ms): creates an interval and auto-cleans it.
  • setTimeout(handler, ms): creates a timeout and auto-cleans it.

Media API

Import from @pixoopal/clockface/media or @pixoopal/clockface/gif.

  • decodeMediaFile(file, options?): decodes GIF or video frames.
  • decodeImageFile(file, options?): decodes and resizes an image to an ImageFrame.
  • decodeGifFile(file, options?): decodes GIF frames.
  • decodeVideoFile(file, options?): decodes video frames through ffmpeg.
  • createMediaAnimation(frames): creates an animation with reset, getFrame(index), and getCurrentFrame(speed?).
  • createGifAnimation(frames): alias of createMediaAnimation.
  • drawMediaFrame(context, frame): copies a full media frame into the buffer.
  • drawGifFrame(context, frame): alias of drawMediaFrame.
  • drawImageFrame(context, frame, options?): draws an image frame at x, y.
  • drawImageFile(context, file, options?): decodes and draws an image file.
  • drawMediaAnimationFrame(context, animation, speed?): draws the current animation frame.
  • drawGifAnimationFrame(context, animation, speed?): alias of drawMediaAnimationFrame.
  • normalizeGifPlaybackSpeed(value): clamps playback speed to the supported range.
  • isGifFileInput(value): checks for file input shape.
  • isMediaFileInput(value): alias-compatible media file check.
  • isImageFileInput(value): checks for image-like file input.

Useful media options:

  • resolution, width, height
  • fit: 'contain' | 'cover' | 'fill' | 'inside' | 'outside'
  • background: { r, g, b, alpha? }
  • maxFrames
  • videoFrameRate

Image API

Import from @pixoopal/clockface/image for image-only helpers:

  • decodeImageFile
  • drawImageFile
  • drawImageFrame
  • isImageFileInput

Bitmap Text API

Import from @pixoopal/clockface/bitmap-text.

  • configureBitmapTextAssets(assets): overrides bitmap font and emoji assets.
  • getBitmapTextLineHeight(fontName?): returns font line height.
  • getBitmapTextRenderHeight(text, fontName?): returns rendered text height.
  • measureBitmapText(text, fontName?): returns text width in pixels.
  • drawBitmapText(options): draws text into a raw buffer with { buffer, size, text, x, y, fontName?, color?, clip? }.

Custom fonts and emoji packs in Community Clockfaces

Community Clockfaces can bundle their own bitmap fonts and emoji sheets. Put assets next to the Clockface source, import them, then call configureBitmapTextAssets before rendering text.

PixooPal loads .png, .jpg, .webp, .gif and .fnt files as text. Example of assets (could be found here)[https://github.com/Drun555/PixooPal-SDK/tree/master/src/assets]

import { defineClockface } from '@pixoopal/clockface';
import { configureBitmapTextAssets } from '@pixoopal/clockface/bitmap-text';
import fontDefinition from './assets/fonts/tiny.fnt';
import fontAtlas from './assets/fonts/tiny.png';
import emojiAtlas from './assets/emojis/tiny-emoji.png';
import emojiManifest from './assets/emojis/tiny-emoji.json' with { type: 'json' };

configureBitmapTextAssets({
  fonts: {
    veryCoolFont: { // your font name
      definition: fontDefinition,
      atlasPath: fontAtlas
    }
  },
  emojiManifest,
  emojiAtlasPath: emojiAtlas
});

export default defineClockface({
  resolution: 64,
  render: ({ canvas }) => {
    canvas.clear();
    canvas.text('Hi 🙂', 0, 0, { fontName: 'veryCoolFont', fill: '#ffffff' });
  }
});

Assets used by this repository: