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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@siali/canvas-viewer

v0.2.0

Published

Canvas viewer for Siali

Downloads

36

Readme

@siali/canvas-viewer

Canvas viewer component with support for rectangles and polygons annotations.

Installation

pnpm add @siali/canvas-viewer

Usage

Basic Example (Rectangles)

import { CanvasViewer } from '@siali/canvas-viewer'

<CanvasViewer
  width={600}
  height={400}
  shapeList={[
    [100, 100, 50, 30], // [centerX, centerY, width, height]
    [200, 150, 80, 40],
  ]}
  shapeType="rectangle"
  colorList={[
    { fill: "#ff0000", stroke: "#ffffff", textColor: "#ffffff" },
    { fill: "#00ff00", stroke: "#ffffff", textColor: "#ffffff" },
  ]}
  textList={["Label 1", "Label 2"]}
  imageState={imageState}
  image={image}
/>

Polygons Example

<CanvasViewer
  width={600}
  height={400}
  shapeList={[
    [100, 100, 150, 120, 200, 200, 50, 180], // [x1, y1, x2, y2, x3, y3, x4, y4, ...]
  ]}
  shapeType="polygon"
  colorList={[
    { fill: "#ff0000", stroke: "#ffffff", textColor: "#ffffff" },
  ]}
  textList={["Polygon Label"]}
  imageState={imageState}
  image={image}
/>

Mixed Shape Types

To render a mix of rectangles and polygons, set shapeType="multiShape". This changes the expected format of the shapeList prop to an array of objects, where each object explicitly defines the shape's type and its data.

This is the recommended approach for handling mixed shapes as it is explicit and robust.

<CanvasViewer
  width={600}
  height={400}
  shapeType="multiShape"
  shapeList={[
    { type: "rectangle", value: [100, 100, 50, 30] },
    { type: "polygon", value: [100, 100, 150, 120, 200, 200] },
    { type: "rectangle", value: [200, 150, 80, 40] },
  ]}
  colorList={[
    { fill: "#ff0000", stroke: "#ffffff", textColor: "#ffffff" },
    { fill: "#0000ff", stroke: "#ffffff", textColor: "#ffffff" },
    { fill: "#00ff00", stroke: "#ffffff", textColor: "#ffffff" },
  ]}
  textList={["Rectangle 1", "Polygon 1", "Rectangle 2"]}
  imageState={imageState}
  image={image}
/>

Advanced Styling Examples

Custom Fill and Stroke

<CanvasViewer
  shapeList={rectangles}
  showFill={false} // No fill, only stroke
  strokeWidth={3} // Thicker border
  cornerRadius={8} // More rounded corners
/>

Global Shape Styling

<CanvasViewer
  shapeList={rectangles}
  strokeWidth={3} // All shapes have thick border
  cornerRadius={10} // All rectangles have rounded corners
  showFill={false} // No fill, only borders
  labelOpacity={0.8} // More opaque labels
/>

Mixed Visibility

<CanvasViewer
  shapeList={shapes}
  visibilityList={[true, false, true]} // Hide middle shape
  showFill={true}
  dashedList={[false, false, true]} // Last shape dashed
/>

Secondary Labels

// Secondary labels positioned above primary labels (always on TOP). Secondary background is gray.
<CanvasViewer
  shapeList={shapes}
  textList={["Label 1", "Label 2", "Label 3"]}
  secondaryTextList={["Shape ok", "Shape ko", ""]} // Empty strings are ignored
/>

Breaking Changes

🚨 v0.2.0:

✅ After (v0.2.0):

// For mixed shapes, be explicit
<CanvasViewer shapeType="multiShape" shapeList={shapeObjects} />

// For single shape types, be explicit
<CanvasViewer shapeType="polygon" shapeList={polygons} />
<CanvasViewer shapeType="rectangle" shapeList={rectangles} />

🚨 v0.1.3 → v0.1.4: API Changes

❌ Before (v0.1.3):

<CanvasViewer
  bboxList={rectangles}
  shapeList={polygons}
/>

✅ After (v0.1.4):

<CanvasViewer
  shapeList={rectangles} // or polygons, or mixed
  shapeType="rectangle" // optional, auto-detected
/>

Migration Guide

  1. Rename prop:

    • bboxListshapeList
  2. Simplify conditional logic:

    // Before:
    bboxList={usePolygons ? undefined : rectangles}
    shapeList={usePolygons ? polygons : undefined}
    
    // After:
    shapeList={usePolygons ? polygons : rectangles}
  3. No data format changes needed:

    • Rectangle arrays remain: [centerX, centerY, width, height]
    • Polygon arrays remain: [x1, y1, x2, y2, x3, y3, ...]

Props

Core Props

| Prop | Type | Default | Description | | ------------ | ------------------------------------------ | ------------- | ------------------------------------------------------------------------- | | width | number | required | Canvas width | | height | number | required | Canvas height | | shapeList | ShapeData[] | [] | Array of shapes (see shapeType prop) | | shapeType | "rectangle" \| "polygon" \| "multiShape" | "rectangle" | Defines how to interpret shapeList. Use "multiShape" for mixed types. | | colorList | ColorLabel[] | [] | Colors for each shape | | textList | string[] | [] | Labels for each shape | | enableZoom | boolean | false | Enable zoom and pan | | imageState | object | undefined | Image dimensions and position | | image | HTMLImageElement | undefined | Image to display behind shapes |

Label Props

| Prop | Type | Default | Description | | ------------------- | ----------- | --------- | ---------------------------------------------------------------- | -------------------------------- | | showLabels | boolean | true | Show/hide labels | | labelPosition | "TOP" | "BOTTOM" | "TOP" | Label position relative to shape | | labelOpacity | number | 0.2 | Opacity of label background (0-1) | | hideLabelsList | boolean[] | [] | Hide specific labels by index | | iconMap | object | {} | Icon mapping for labels | | secondaryTextList | string[] | [] | Secondary labels for each shape (always on TOP, gray background) |

Shape Styling Props

| Prop | Type | Default | Description | | -------------- | ----------- | ------- | -------------------------------- | | showFill | boolean | true | Show/hide shape fill | | strokeWidth | number | 2 | Stroke width for all shapes | | cornerRadius | number | 4 | Corner radius for all rectangles | | dashedList | boolean[] | [] | Dashed border for each shape |

Visibility & Interaction Props

| Prop | Type | Default | Description | | ---------------- | ----------- | ------- | --------------------------------------- | | visibilityList | boolean[] | [] | Show/hide specific shapes by index | | ignoreList | boolean[] | [] | Ignore specific shapes (no interaction) |

Types

type bbox = [number, number, number, number] // [centerX, centerY, width, height]
type polygon = number[] // [x1, y1, x2, y2, x3, y3, ...]
type ShapeType = "rectangle" | "polygon" | "multiShape"

// The object format used when shapeType="multiShape"
type ShapeObject = {
  type: "rectangle" | "polygon"
  value: bbox | polygon
}

// The shapeList prop accepts an array of one of these types
type ShapeData = bbox | polygon | ShapeObject

type ColorLabel = {
  fill: string
  stroke: string
  textColor: string
}

Version History

  • v0.1.7: Added secondaryTextList (secondary labels always on TOP with gray background)
  • v0.1.4: Added polygon support, breaking changes in API
  • v0.1.3: Rectangle support only