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

@meonode/canvas

v2.0.5

Published

A declarative, component-based library for server-side canvas image generation. Write complex visuals with simple functions, similar to the composition style of @meonode/ui.

Readme

@meonode/canvas

A declarative, component-based library for server-side canvas image generation. Write complex visuals with simple functions, similar to the composition style of @meonode/ui. It uses skia-canvas for drawing and yoga-layout for flexbox-based layouts.

This library allows you to build complex image layouts using a familiar component-based approach. You can define your image structure with components like Box, Text, Image, and Grid, and the library will handle the layout and rendering to a canvas.

Key Features

  • Declarative API: Build images using a component tree, just like in React.
  • Flexbox Layout: Powered by yoga-layout, it supports flexbox for powerful and flexible layouts.
  • Rich Text: Render text with custom fonts and inline styling using simple HTML-like tags. Supported tags include <color="value">, <weight="value">, <size="value">, <b>, and <i>.
  • Image Support: Render images from URLs, file paths, or buffers, with object-fit and object-position support.
  • Chart Support: Render bar, line, pie, and doughnut charts with customizable data and options.
  • Styling: Style your components with properties that mimic CSS, including borders, padding, margins, and more.
  • Grid Layout: A Grid component is provided for easy grid-based layouts.
  • TypeScript Support: Fully typed for a better development experience.

Showcase

Installation

yarn add @meonode/canvas

Usage

Simple Example

A minimal example that renders a title and description to a PNG file:

import {Root, Box, Text} from '@meonode/canvas';

async function generateImage() {
  const canvas = await Root({
    width: 500,
    height: 300,
    scale: 1,          // increase to 2 for 2× retina resolution
    workerMode: true,  // renders in a worker thread — keeps the main thread free (default)
    fonts: [
      {
        family: 'Roboto',
        paths: ['./fonts/Roboto-Regular.ttf', './fonts/Roboto-Bold.ttf'],
      },
    ],
    children: [
      Box({
        width: '100%',
        height: '100%',
        backgroundColor: '#f0f0f0',
        padding: 20,
        children: [
          Text('Hello, World!', {
            fontSize: 32,
            fontWeight: 'bold',
            fontFamily: 'Roboto',
            color: '#333',
          }),
          Text('This is a basic example of using @meonode/canvas.', {
            fontSize: 18,
            fontFamily: 'Roboto',
            color: '#666',
            margin: {Top: 10},
          }),
        ],
      }),
    ],
  });

  await canvas.toFile('output.png');  // saves directly to disk
  canvas.release();                   // free worker memory after use
}

generateImage().catch(console.error);

Complex Layout

A more complete example using Column, Row, Image, and advanced flexbox properties to build a structured page layout with a header, content area, and footer:

import {Root, Column, Row, Text, Image, Style} from '@meonode/canvas';

async function generateComplexImage() {
  const canvas = await Root({
    width: 800,
    height: 600,
    scale: 2,              // 2× resolution — canvas output will be 1600×1200px
    workerMode: true,      // renders off the main thread (default)
    useDiskCache: true,    // caches fetched remote images to disk for faster re-decode
    fonts: [
      {
        family: 'Roboto',
        paths: ['./fonts/Roboto-Regular.ttf', './fonts/Roboto-Bold.ttf'],
      },
      {
        family: 'Open Sans',
        paths: ['./fonts/OpenSans-Regular.ttf'],
      },
    ],
    children: [
      Column({
        width: '100%',
        height: '100%',
        backgroundColor: '#f0f0f0',
        padding: 20,
        justifyContent: Style.Justify.SpaceBetween, // evenly space header, body, footer
        children: [
          // Header: avatar + title side by side
          Row({
            width: '100%',
            alignItems: Style.Align.Center,
            marginBottom: 20,
            children: [
              Image({
                src: 'https://via.placeholder.com/80x80/FF0000/FFFFFF?text=Logo',
                width: 80,
                height: 80,
                borderRadius: 40, // circle crop
                marginRight: 20,
                objectFit: 'cover',
              }),
              Text('Welcome to MeoNode Canvas!', {
                fontSize: 40,
                fontWeight: 'bold',
                fontFamily: 'Roboto',
                color: '#333',
              }),
            ],
          }),

          // Body: grows to fill remaining vertical space
          Column({
            flexGrow: 1,
            width: '100%',
            backgroundColor: '#ffffff',
            borderRadius: 10,
            padding: 30,
            boxShadow: {blur: 10, color: 'rgba(0,0,0,0.1)'},
            children: [
              Text('A New Way to Render Graphics', {
                fontSize: 28,
                fontWeight: 'bold',
                fontFamily: 'Open Sans',
                color: '#555',
                marginBottom: 15,
              }),
              Text(
                `This example demonstrates a more complex layout using various components.
        We have a header with a logo and title, a main content area with text,
        and a footer. Notice how flexbox properties are used to arrange elements.`,
                {
                  fontSize: 18,
                  fontFamily: 'Open Sans',
                  color: '#777',
                  lineHeight: 24,
                },
              ),
              Image({
                src: 'https://via.placeholder.com/600x200/007bff/ffffff?text=Feature+Image',
                width: '100%',
                height: 200,
                marginTop: 20,
                borderRadius: 8,
                objectFit: 'contain',
                objectPosition: {Top: '50%', Left: '50%'}, // center within box
              }),
            ],
          }),

          // Footer: centered copyright line
          Row({
            width: '100%',
            marginTop: 20,
            justifyContent: Style.Justify.Center,
            children: [
              Text('© 2025 MeoNode Canvas. All rights reserved.', {
                fontSize: 14,
                fontFamily: 'Open Sans',
                color: '#999',
              }),
            ],
          }),
        ],
      }),
    ],
  });

  await canvas.toFile('complex_output.png');  // saves directly to disk
  canvas.release();                           // free worker memory after use
}

generateComplexImage().catch(console.error);

Examples

Charts

The Chart component supports bar, line, pie, and doughnut chart types.

Bar Chart

import {Root, Chart} from '@meonode/canvas';

async function generateBarChart() {
  const canvas = await Root({
    width: 600,
    height: 400,
    workerMode: true, // default — render in a worker thread
    children: [
      Chart({
        type: 'bar',
        width: '100%',
        height: '100%',
        data: {
          labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
          datasets: [
            {
              label: 'Sales',
              data: [120, 150, 180, 90, 200],
              color: '#36A2EB',
            },
          ],
        },
        options: {
          grid: {show: true, style: 'dashed'},
          axisColor: '#333',
          labelColor: '#333',
          showValues: true,   // display value labels above each bar
          valueFontSize: 12,
          showYAxis: true,    // show Y-axis tick labels on the left
          yAxisColor: '#666',
        },
      }),
    ],
  });

  await canvas.toFile('bar_chart.png');
  canvas.release();
}

generateBarChart().catch(console.error);

Doughnut Chart with Custom Legend

import {Root, Chart, Row, Box, Text} from '@meonode/canvas';

async function generateDoughnutChart() {
  const canvas = await Root({
    width: 600,
    height: 400,
    workerMode: true, // default — render in a worker thread
    children: [
      Chart({
        type: 'doughnut',
        width: '100%',
        height: '100%',
        data: [
          {label: 'Red', value: 300, color: '#FF6384'},
          {label: 'Blue', value: 50, color: '#36A2EB'},
          {label: 'Yellow', value: 100, color: '#FFCE56'},
        ],
        options: {
          innerRadius: 0.7,      // 0 = full pie, 1 = empty ring; 0.7 gives a thick doughnut
          sliceBorderRadius: 5,  // rounded corners on each slice
          // custom legend item: colored dot + "Label: value" text
          renderLegendItem: ({item, color}) =>
            Row({
              alignItems: 'center',
              children: [
                Box({width: 12, height: 12, backgroundColor: color, borderRadius: 6}),
                Text(`${item.label}: ${item.value}`, {fontSize: 16, marginLeft: 8}),
              ],
            }),
        },
      }),
    ],
  });

  await canvas.toFile('doughnut_chart.png');
  canvas.release();
}

generateDoughnutChart().catch(console.error);

Grid

The Grid component simplifies creating complex layouts. It mimics CSS Grid Layout.

Basic Grid

A simple grid with 3 columns, each 100 pixels wide.

import {Root, Grid, Box, Text} from '@meonode/canvas';

async function generateBasicGrid() {
  const canvas = await Root({
    width: 400,
    height: 300,
    workerMode: true, // default — render in a worker thread
    children: [
      Grid({
        columns: 3,
        templateColumns: [100, 100, 100], // fixed widths; also accepts ['100px', '100px', '100px']
        gap: 10,
        children: [
          Box({backgroundColor: 'red', height: 50, children: [Text('1')]}),
          Box({backgroundColor: 'blue', height: 50, children: [Text('2')]}),
          Box({backgroundColor: 'green', height: 50, children: [Text('3')]}),
          Box({backgroundColor: 'yellow', height: 50, children: [Text('4')]}), // wraps to row 2
        ],
      }),
    ],
  });

  await canvas.toFile('grid_basic.png');
  canvas.release();
}

generateBasicGrid().catch(console.error);

Responsive Grid (Fractional Units)

Using fractional units (fr) allows columns to take up proportional space.

Grid({
  // First column takes 1 part, second takes 2 parts, third takes 1 part
  templateColumns: ['1fr', '2fr', '1fr'],
  gap: 10,
  children: [
    Box({backgroundColor: 'red', height: 50, children: [Text('1fr')]}),
    Box({backgroundColor: 'blue', height: 50, children: [Text('2fr')]}),
    Box({backgroundColor: 'green', height: 50, children: [Text('1fr')]}),
  ],
});

Spanning Items

Use GridItem (or pass gridColumn/gridRow props directly to any child) to span multiple columns or rows.

import {Grid, GridItem, Box, Text} from '@meonode/canvas';

Grid({
  templateColumns: ['1fr', '1fr', '1fr'],
  gap: 10,
  children: [
    // Spans all 3 columns
    GridItem({
      gridColumn: 'span 3',
      height: 50,
      backgroundColor: '#333',
      children: [Text('Header', {color: 'white'})],
    }),
    // Standard items
    Box({backgroundColor: '#eee', height: 100, children: [Text('Content')]}),
    Box({backgroundColor: '#ccc', height: 100, children: [Text('Sidebar')]}),
    // Spans 2 columns
    GridItem({
      gridColumn: 'span 2',
      height: 50,
      backgroundColor: '#555',
      children: [Text('Footer', {color: 'white'})],
    }),
  ],
});

Yoga Layout

This library leverages yoga-layout for its powerful flexbox engine. Many layout properties directly map to Yoga's concepts. You can access Yoga-specific constants through the Style export from @meonode/canvas.

import {Box, Style} from '@meonode/canvas';

Box({
  flexDirection: Style.FlexDirection.Row,
  justifyContent: Style.Justify.Center,
  alignItems: Style.Align.Center,
  children: [
    Box({
      width: 100,
      height: 100,
      backgroundColor: 'red',
      positionType: Style.PositionType.Absolute,
      position: {Top: 10, Left: 10},
    }),
    // ... other children
  ],
});

Refer to the Yoga Layout documentation for a comprehensive understanding of these properties.

API Reference

Root

The Root function is the entry point for rendering. It returns a Canvas object. It is a specialized ColumnNode that inherits all BoxProps.

Root Props

| Prop | Type | Default | Description | | -------------- | --------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------- | | width | number | - | Required. Width of the canvas in pixels. | | height | number | - | Optional height of the canvas. If not set, it's calculated from content. | | children | CanvasElement | CanvasElement[] | - | Required. The component tree to render. | | scale | number | 1 | Scale factor for rendering (e.g., 2 for 2x resolution). | | fonts | FontRegistrationInfo[] | - | An array of font files to register for use in the canvas. | | useDiskCache | boolean | false | Write fetched images to disk during render for faster re-decode. Entries are cleaned up after render. | | workerMode | boolean | true | Enable worker thread rendering for non-blocking operation. | | workers | number | cpus().length - 1 | Number of worker threads to use (only applies on first render withworkerMode: true). |

Since Root extends BoxProps, it also accepts backgroundColor, padding, gradient, boxShadow, and all other layout props. See Box, Row, and Column for the full list.

Canvas Methods

The Root() function returns a Canvas object with the following methods and properties.

Export Methods

| Method | Signature | Description | | -------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | toBufferSync | (format?: ExportFormat, options?: ExportOptions) => Buffer | Synchronously returns a buffer. In worker mode, returns the pre-encoded PNG. | | toBuffer | (format: ExportFormat, options?: ExportOptions) => Promise<Buffer> | Asynchronously encodes to the specified format. | | toURL | (format: ExportFormat, options?: ExportOptions) => Promise<string> | Returns a data URL. | | toURLSync | (format?: ExportFormat, options?: ExportOptions) => string | Synchronously returns a data URL (from pre-encoded PNG in worker mode). | | toFile | (filename: string, options?: SaveOptions) => Promise<void> | Saves the canvas to a file. | | toSharp | (options?: RenderOptions) => Promise<Buffer> | Returns a Sharp instance buffer for further processing. | | toSharpSync | (options?: RenderOptions) => never | Throws error. Use toSharp() instead in worker mode. |

Supported Export Formats: 'png', 'jpg' (or 'jpeg'), 'webp', 'pdf', 'svg', 'raw'

Convenience Getters

| Getter | Returns | Description | | ------- | ----------------- | ----------------------------------------------- | | .png | Promise<Buffer> | Shortcut fortoBuffer('png') | | .jpg | Promise<Buffer> | Shortcut fortoBuffer('jpg') | | .webp | Promise<Buffer> | Shortcut fortoBuffer('webp') | | .svg | Promise<Buffer> | Shortcut fortoBuffer('svg') | | .pdf | Promise<Buffer> | Shortcut fortoBuffer('pdf') | | .raw | Promise<Buffer> | Shortcut fortoBuffer('raw') — raw pixel data |

Canvas Properties

| Property | Type | Description | | --------- | -------- | -------------------------------------- | | .width | number | Canvas width in pixels (after scale). | | .height | number | Canvas height in pixels (after scale). |

Memory Management (Worker Mode)

| Method | Description | | ------------ | ------------------------------------------------------------------------------------------------------------ | | .release() | Required in worker mode. Releases the Canvas from worker memory. Call when done to prevent memory leaks. |

import {Root} from '@meonode/canvas'

// Render with default worker mode (enabled)
const canvas = await Root({width: 400, height: 400, children: [...]})

// Or explicitly disable worker mode
const canvas = await Root({width: 400, height: 400, children: [...], workerMode: false})

// Use the canvas
const png = await canvas.png
const jpg = await canvas.jpg
await canvas.toFile('output.png')

// Release memory (worker mode only)
canvas.release()

Note: A FinalizationRegistry provides automatic cleanup for forgotten .release() calls, but explicit cleanup is recommended for deterministic memory management in production.


Box, Row, and Column

These are the fundamental layout components. Row and Column are wrappers around Box with a pre-set flexDirection. They all share the same props.

Layout Props

| Prop | Type | Description | | ----------------------- | -------------------------- | ----------------------------------------------------------------------------- | | width, height | number | string | Sets the size of the node in pixels or percentage. | | minWidth, minHeight | number | string | Sets the minimum size of the node. | | maxWidth, maxHeight | number | string | Sets the maximum size of the node. | | flexDirection | Style.FlexDirection | Defines the direction of the main axis (Row, Column, etc.). | | justifyContent | Style.Justify | Defines how items are distributed along the main axis. | | alignItems | Style.Align | Defines how items are aligned along the cross axis. | | alignSelf | Style.Align | Overrides the parent'salignItems for a specific item. | | alignContent | Style.Align | Defines how lines are distributed when content wraps. | | flexGrow | number | Defines the ability of an item to grow. | | flexShrink | number | Defines the ability of an item to shrink. | | flexBasis | number | 'auto' | string | Defines the default size of an item along the main axis. | | flexWrap | Style.Wrap | Controls whether flex items wrap to multiple lines. | | positionType | Style.PositionType | Sets the positioning method (Relative or Absolute). | | position | object | number | string | Sets the offset for a positioned element. | | margin | object | number | string | Sets the margin space on the outside of the node. | | padding | object | number | string | Sets the padding space on the inside of the node. | | border | object | number | Sets the width of the node's border. | | aspectRatio | number | Locks the aspect ratio (width / height) of the node. | | overflow | Style.Overflow | Defines how content that overflows is handled (Visible, Hidden). | | display | Style.Display | Controls if the node is included in layout (Flex, None). | | direction | Style.Direction | Sets the primary layout direction (LTR, RTL). | | gap | object | number | string | Defines the space between flex items. | | boxSizing | Style.BoxSizing | Defines howwidth and height are interpreted (ContentBox, BorderBox). | | zIndex | number | Specifies the stack order of an element (only forpositionType: 'absolute'). | | children | CanvasElement \| CanvasElement[] | Child nodes to render inside this node. |

Styling Props

| Prop | Type | Description | | ----------------- | ----------------------------------- | ------------------------------------------------------ | | backgroundColor | string | Sets the background color of the node. | | borderColor | string | Sets the color of the node's border. | | borderStyle | Style.Border | Sets the style of the border (Solid, Dashed, Dotted). | | borderRadius | object | number | Sets the radius of the node's corners. | | opacity | number | Sets the opacity of the node and its children (0-1). | | gradient | object | Sets a linear or radial gradient as the background. | | boxShadow | BoxShadowProps | BoxShadowProps[] | Applies one or more box-shadow effects. | | transform | TransformProps | Applies 2D transformations (translate, rotate, scale). |

Font & Text Props (Inheritable)

These props, when set on a Box, Row, or Column, are inherited by any descendant Text nodes.

| Prop | Type | Description | | --------------- | ----------------------------------------------------------- | ------------------------------------------ | | fontSize | number | Font size in pixels. | | fontFamily | string | Font family name. | | fontWeight | string | number | Font weight ('normal', 'bold', 400, etc.). | | fontStyle | 'normal' | 'italic' | Font style. | | color | string | Text color. | | textAlign | 'start' | 'end' | 'left' | 'center' | 'right' | 'justify' | Horizontal text alignment. | | verticalAlign | 'top' | 'middle' | 'bottom' | Vertical text alignment. | | lineHeight | number | Line height in pixels. | | lineGap | number | Additional vertical spacing between lines. | | letterSpacing | number | string | Spacing between letters. | | wordSpacing | number | string | Spacing between words. | | fontVariant | FontVariantSetting | Specifies font variation settings. |


Text

The Text component renders text content. It inherits all BoxProps except for children, gap, and flex container properties.

Text-Specific Props

| Prop | Type | Description | | ------------ | ------------------------------------- | ------------------------------------------------------------------------- | | maxLines | number | Maximum number of lines to display before truncating. | | ellipsis | boolean | string | Iftrue, adds '...' when text is truncated. Can also be a custom string. | | textShadow | TextShadowProps | TextShadowProps[] | Applies one or more shadow effects to the text itself. |


Image

The Image component renders an image. It inherits all BoxProps except for children.

Image-Specific Props

| Prop | Type | Description | | ---------------- | ------------------------------------------------------ | --------------------------------------------------------------------- | | src | string | Buffer | The source URL, file path, or buffer of the image. | | objectFit | 'fill' | 'contain' | 'cover' | 'none' | 'scale-down' | Specifies how the image should be resized to fit its container. | | objectPosition | object | Specifies the alignment of the image within its box. | | saturate | number | Adjusts the image's saturation level (0 is grayscale, 1 is original). | | dropShadow | DropShadowProps | Applies a drop-shadow effect based on the image's alpha channel. | | alt | string | Alternative text description (for accessibility). | | onLoad | () => void | Callback function that executes when the image loads successfully. | | onError | (error: Error) => void | Callback function that executes when the image fails to load. |


Grid

The Grid component arranges its children in a grid layout. It is a specialized RowNode and inherits most BoxProps.

Grid-Specific Props

| Prop | Type | Description | | ----------------- | ----------------------------------------------------- | ------------------------------------------------------ | | columns | number | The number of columns in the grid. Default is 1. | | templateColumns | GridTrackSize[] | Defines the columns of the grid (e.g.,[100, '1fr']). | | templateRows | GridTrackSize[] | Defines the rows of the grid. | | autoRows | GridTrackSize | Specifies the size of implicitly created rows. | | autoFlow | 'row' \| 'column' \| 'row-dense' \| 'column-dense' | Controls how the auto-placement algorithm works. Default is 'row'. |

Gap control: gap is inherited from BoxProps. Pass a number for uniform spacing, or an object for per-axis control: gap: { Row: 10, Column: 20 }.


GridItem

The GridItem component represents a child item within a Grid. It inherits all BoxProps and adds grid placement properties.

GridItem-Specific Props

| Prop | Type | Description | | ------------ | -------- | ----------------------------------------------------------- | | gridColumn | string | Specifies the column span (e.g.,'span 2', '1 / 3'). | | gridRow | string | Specifies the row span (e.g.,'span 2', '1 / 3'). | | gridArea | string | Shorthand forgridRow and gridColumn (e.g., 'header'). |

Note: You can also use gridColumn and gridRow props directly on any child component (Box, Text, etc.) without wrapping in GridItem.


Chart

The Chart component renders various types of charts. It inherits all BoxProps.

Chart-Specific Props

| Prop | Type | Description | | --------- | ------------------------------------------ | ----------------------------------------------------------------------------- | | type | 'bar' | 'line' | 'pie' | 'doughnut' | The type of chart to render. | | data | CartesianChartData | PieChartDataPoint[] | The data for the chart, which varies based on thetype. | | options | ChartOptions<T> | An object containing rendering and style options, specific to the chart type. |

ChartOptions

The options prop is a conditional type that changes based on the chart type.

Common Options (All Chart Types)

| Prop | Type | Description | | ------------------ | -------------------------------------------- | ------------------------------------------------- | | showLabels | boolean | Iftrue, displays labels on the chart. | | showLegend | boolean | Iftrue, displays the chart legend. | | labelFontSize | number | Font size for labels and legend text. | | labelColor | string | Color for labels and legend text. | | legendPosition | 'top' | 'bottom' | 'left' | 'right' | The position of the legend relative to the chart. | | renderLabelItem | (props: { item, index }) => BoxNode | A custom render function for chart labels. | | renderLegendItem | (props: { item, index, color }) => BoxNode | A custom render function for legend items. |

Cartesian Chart Options (bar, line)

| Prop | Type | Description | | --------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | grid | GridOptions | Configures grid lines (show, color, style: 'solid' \| 'dashed' \| 'dotted'). | | axisColor | string | The color of the chart axes. | | showValues | boolean | If true, displays values on top of bars or points. | | valueColor | string | Color of the value labels. | | valueFontSize | number | Font size of the value labels. | | renderValueItem | (props: { item: number; index: number; datasetIndex: number }) => BoxNode | Custom render function for each value label above a bar or point. | | showYAxis | boolean | If true, displays the Y-axis labels on the left. | | yAxisColor | string | Color of the Y-axis labels. | | yAxisFontSize | number | Font size of the Y-axis labels. | | yAxisLabelFormatter | (value: number) => string | Custom formatter for Y-axis labels. Smart defaults adjust decimal precision based on value range. | | xAxisLabelFormatter | (value: string, index: number) => string | Custom formatter for X-axis labels. Useful for truncating or transforming labels. |

Y-Axis Label Formatter

The yAxisLabelFormatter enables custom Y-axis label formatting. By default, it uses smart formatting:

  • Values < 1: 4 decimals (e.g., 0.0025)
  • Values 1-100: 2 decimals (e.g., 25.43)
  • Values 100-1000: 1 decimal (e.g., 250.5)
  • Values 1000-1M: 0 decimals (e.g., 50000)
  • Values ≥ 1M: 1 decimal with "M" suffix (e.g., 1.5M)

Custom example:

options: {
  yAxisLabelFormatter: (value) => `$${value.toFixed(2)}`,
}
X-Axis Label Formatter

The xAxisLabelFormatter allows custom X-axis label transformations. It receives the label string and its index.

Custom example:

options: {
  xAxisLabelFormatter: (label, index) =>
    label.length > 5 ? label.substring(0, 5) + '...' : label,
}
Pie & Doughnut Chart Options (pie, doughnut)

| Prop | Type | Description | | ------------------- | -------- | ---------------------------------------------------------------------------- | | innerRadius | number | The radius of the inner circle in a doughnut chart (0 to 1). Default is 0.6. | | sliceBorderRadius | number | The border radius for the corners of each slice. Default is 0. |


Cleanup Functions

terminate()

Terminate all worker pools and free worker thread resources. Call this when shutting down a long-running server.

import {terminate} from '@meonode/canvas'

// Call on server shutdown
process.on('SIGTERM', () => {
  terminate()
  process.exit(0)
})

After calling terminate(), you must call configure() again before rendering.

clearDiskCache()

Manually clear the entire disk cache directory. Useful for debugging or forced cleanup.

import {clearDiskCache} from '@meonode/canvas'

await clearDiskCache()

Note: Disk cache is automatically cleaned up after each render when useDiskCache: true, and on process exit.


Configuration (Legacy)

configure(options)

Deprecated: Pass workerMode and workers directly to Root() props instead.

Configure the canvas rendering engine. Call once at startup.

import {configure} from '@meonode/canvas'

configure({
  workerMode: true, // Default: true
  workers: 4,       // Default: cpus().length - 1
})

| Option | Type | Default | Description | | ------------ | --------- | ------------------- | --------------------------------------------------------- | | workerMode | boolean | true | Enable worker thread rendering for non-blocking operation | | workers | number | cpus().length - 1 | Number of worker threads in the pool |

Contributing

Contributions are welcome! Please see the Contributing Guidelines for more details on how to get started.

License

This project is licensed under the MIT License - see the LICENSE file for details.