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

@medalsocial/pencil-canvas

v0.1.2

Published

React component for rendering .pen file node trees as SVG

Downloads

371

Readme

@medalsocial/pencil-canvas

npm License: Apache 2.0

React component for rendering .pen file node trees as SVG. Drop a parsed Pencil document into your app and get pixel-faithful vector output with optional toolbar controls (export, zoom, theme variables).

Install

pnpm add @medalsocial/pencil-canvas
npm install @medalsocial/pencil-canvas
yarn add @medalsocial/pencil-canvas

Peer dependencies: react >= 18.

Quick start

import { PenViewer } from '@medalsocial/pencil-canvas';

export function MyDocument({ penNodes }: { penNodes: unknown[] }) {
  return <PenViewer data={penNodes} width={800} height={600} />;
}

data is the raw node array as exported from a .pen file (or returned by the Pencil MCP batch_get API). PenViewer parses, resolves layout, and renders the tree as SVG.

API

<PenViewer>

| Prop | Type | Default | Description | |---|---|---|---| | data | unknown[] | required | Raw .pen node array | | width | number | 1440 | Render width in px | | height | number | 900 | Render height in px | | className | string | — | Class on the root SVG container | | style | React.CSSProperties | — | Inline style on the root | | showToolbar | boolean | true | Render the export/zoom toolbar | | variables | Record<string, string> | — | Override design-token variable values at render time |

Lower-level helpers

If you want to parse + lay out without rendering, the underlying utilities are exported too:

import { parseNodeTree, resolveLayout } from '@medalsocial/pencil-canvas';
import type { PenNode, ResolvedNode } from '@medalsocial/pencil-canvas';

const rawData: unknown[] = /* nodes from a .pen file */ [];
const width = 1440;
const height = 900;

const parsed: PenNode[] = parseNodeTree(rawData);
const resolved: ResolvedNode[] = parsed.map((node) =>
  resolveLayout(node, 0, 0, width, height)
);

resolveLayout operates on a single PenNode and takes positional offsets plus the available width/height of its parent (resolveLayout(node, parentX, parentY, availableWidth, availableHeight)), matching what PenViewer uses internally.

Supported node types

frame, group, rectangle, ellipse, line, polygon, path, text, icon_font, image, ref.

Effects supported: linear/radial gradients, drop shadows, inner shadows, blurs, strokes (with dash patterns).

Development

pnpm install
pnpm test           # Vitest unit tests
pnpm build          # tsup → dist/
pnpm lint           # Biome

Authoritative source lives in medal-monorepo/open/pencil-canvas.

Releases

Releases are driven by Changesets and the Medal Social Release Bot. To ship a change:

  1. Add a changeset on your feature branch: pnpm changeset
  2. Open a PR to prod
  3. After merge, the Release Bot opens a release PR; Medal Approvals auto-approves it
  4. Merge the release PR → npm publish via OIDC trusted publishing

License

Apache-2.0 © Medal Social