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

@wicklib/core

v0.29.2

Published

Wicklib core charting engine

Readme

@wicklib/core

Canvas2D charting engine: scales, series, axes, crosshair, interactions, panes, indicators, drawings, annotations, themes, and export.

Status: 0.1.0. The public API remains 0.x until 1.0, but the package is on the stable release channel.

pnpm add @wicklib/core

Quick start

import { CandlestickSeries, createChart, type OhlcData } from "@wicklib/core";

const chart = createChart(document.getElementById("chart")!, {
  autoSize: true,
  timeScale: { maxVisibleBars: 720 },
});

const series = chart.addSeries(CandlestickSeries, {
  title: "BTC/USD",
  upColor: "#26a69a",
  downColor: "#ef5350",
});

series.setData([
  {
    time: Date.UTC(2024, 0, 1),
    open: 100,
    high: 105,
    low: 95,
    close: 102,
  } satisfies OhlcData,
]);
chart.timeScale().fitContent();

Times are non-negative integer milliseconds since the Unix epoch.

Series types

import { AreaSeries, HistogramSeries, LineSeries } from "@wicklib/core";

const line = chart.addSeries(LineSeries, { color: "#2962ff", lineWidth: 2 });
const area = chart.addSeries(AreaSeries, { topColor: "rgba(41,98,255,0.4)" });
const histogram = chart.addSeries(HistogramSeries, { base: 0 });

line.setData([
  { time: 0, value: 100 },
  { time: 60_000, value: 104 },
]);
area.setData([
  { time: 0, value: 90 },
  { time: 60_000, value: 96 },
]);
histogram.setData([
  { time: 0, value: 4 },
  { time: 60_000, value: -2 },
]);

Indicators currently require a candlestick source series. Custom series renderers are not part of the public API.

Last value labels

The last-value axis label follows the right visible edge by default:

series.setOptions({ lastValueMode: "visible" });

The mode can follow the newest data point, or show both labels:

series.setOptions({ lastValueMode: "data" });
series.setOptions({ lastValueMode: "both" });

const current = series.lastValue();
const visible = series.visibleLastValue();

lastValue() returns the newest data point even when it is outside the visible time range. visibleLastValue() returns the value at the right edge. With "both", a current price outside the visible price range is clamped to the top or bottom of the axis and marked with an arrow. The price line remains attached to the visible edge; the legend also reflects the visible edge.

Annotations

Price lines can place their title in the plot while keeping the price on the axis:

const line = series.createPriceLine({
  price: 105,
  color: "#10b981",
  lineStyle: "dashed",
  title: "Entry",
  titlePosition: "plot",
});

line.applyOptions({ price: 106 });
line.remove();

series.setMarkers([
  { time: 60_000, position: "belowBar", shape: "arrowUp", color: "#10b981", text: "Buy" },
]);

Markers are replaced as a complete set. Pass an empty array to clear them.

Themes

Neutral presets can be applied at creation or switched without recreating the chart:

import { DarkTheme, LightTheme, createChart } from "@wicklib/core";

const chart = createChart(container, { ...DarkTheme });
chart.setOptions(LightTheme);

Themes cover chart chrome only. Series, candle, drawing, and indicator colors remain explicit options. Core never reads CSS variables or prefers-color-scheme.

Datafeeds

A series can be driven by a host-provided async feed:

series.setDatafeed(feed, {
  symbol: "BTC/USD",
  interval: "1m",
  initialBars: 500,
});

chart.on("data-loading", ({ loading }) => console.log("loading", loading));

The feed owns transport, authentication, retries, and reconnection. Core handles initial loads, debounced range loads, prefetch, aborting stale requests, prepend anchoring, realtime revisions, and typed loading/error events.

Calling setDatafeed() again stops the previous subscription, aborts its pending requests, clears loaded bars, and starts the replacement. The previous feed is unsubscribed.

series.setDatafeed(feed, {
  symbol: "ETH/USD",
  interval: "5m",
  initialView: "fit",
});

initialView controls the time view after the first load: auto fits only when the host has not chosen a view, fit always fits the new data, and preserve keeps the current view. getDatafeedOptions() returns the active symbol, interval, initial bar count, and view mode.

Price formatting

Price labels use the generated tick step by default. Instrument-specific precision can be set for the whole chart or updated at runtime:

const chart = createChart(container, {
  priceScale: {
    priceFormat: {
      precision: 2,
      minMove: 0.01,
    },
  },
});

const scale = series.priceScale();
scale.setOptions({ priceFormat: { precision: 4 } });

const current = scale.getOptions().priceFormat;

precision controls the displayed decimal places. When omitted, minMove determines the precision, for example 0.25 renders two decimals. If neither is set, Wicklib infers precision from the generated ticks. The format applies to axis ticks, crosshair labels, drawing labels, price lines, and last-value labels.

Price scales

Price scales are linear by default. A pane can use a logarithmic scale without recreating the chart:

chart.setOptions({ priceScale: { mode: "logarithmic" } });

// Or update only one pane.
series.priceScale().setOptions({ mode: "logarithmic" });

Logarithmic scales require positive prices. Explicit non-positive ranges throw INVALID_ARGUMENT; automatic ranges containing non-positive values are ignored so the last valid range stays visible. Margins are applied in log space, and narrow ranges fall back to linear price ticks for familiar labels.

Drawing presentation

Drawings support semantic theme colors and presentation options:

drawing.setOptions({
  color: "theme",
  fillColor: null,
  showLine: true,
  extendLeft: true,
  extendRight: true,
  showMidpoint: true,
  priceLabels: "selected",
  stats: "selected",
  statsPosition: "auto",
});
  • "theme" resolves to the chart layout text color. "" and null also clear a color override to theme.
  • showLine hides line geometry without hiding labels or stats.
  • Trend lines support extendLeft, extendRight, and showMidpoint.
  • Trend-line text uses text, textColor, fontSize, textStyle, textAlign, and textVerticalAlign.
  • priceLabels controls endpoint prices on the price axis: never, selected, or always.
  • stats controls the stats box: off, selected, or always.
  • statsPosition is auto, left, center, or right.
  • Stats include price range, percentage change, bar count, date range, and line angle where applicable.

Drawing label style

Labels use the chart layout font size and draw with a background by default. Both can be overridden per drawing:

drawing.setOptions({
  labelPlacement: "auto",
  labelFontSize: 24,
  labelBackgroundVisible: false,
});

labelPlacement defaults to auto: Elliott labels center on their anchor, above local highs and below local lows. Use "above" or "below" to force a side. Labels flip to the opposite side when they would leave the pane. Labels are not drawn when their anchor is outside the visible plot.

With labelBackgroundVisible: false, the background box is skipped and the label text uses the drawing-specific label color. This applies to Elliott labels and other label-bearing tools. Text drawings continue to use fontSize for their own text size.

Elliott labels

Elliott tools use the built-in label sequence by default. A degree or custom convention can override one label per anchor:

const wave = chart.addDrawing(ElliottImpulse, {
  anchors,
  options: {
    labels: ["0", "i", "ii", "iii", "iv", "v"],
  },
});

wave.setOptions({ labels: ["0", "(i)", "(ii)", "(iii)", "(iv)", "(v)"] });

Label overrides are stored with the drawing and survive save/load. Degree catalogs, menu labels, and per-user defaults remain host-owned.

Workspace state

Wicklib does not persist application state. The host can read the state it needs to save:

const workspace = {
  visibleRange: chart.timeScale().getVisibleRange(),
  timeScale: chart.timeScale().getOptions(),
  panes: chart.getPanes().map((pane) => ({
    id: pane.id,
    height: pane.getHeight(),
    options: pane.getOptions(),
  })),
  series: [
    {
      id: series.id,
      type: series.typeId,
      options: series.getOptions(),
      datafeed: series.getDatafeedOptions(),
    },
  ],
  indicator: {
    inputs: indicator.getInputs(),
    plot: indicator.getPlotOptions("line"),
  },
  drawings: chart.serializeDrawings(),
};

Bar data, symbol lists, and the indicator definition registry remain host-owned. Restore by recreating the chart and series with the host's stored configuration, reattaching datafeeds, and calling loadDrawings().

Interaction and layout

  • Continuous index-based time scale and linear or logarithmic price scale.
  • Time-axis drag zooms; price-axis drag scales the price range.
  • Wheel zoom, trackpad pan, drag pan, and two-pointer pinch zoom.
  • Keyboard pan/zoom/fit, Delete/Backspace, [/] drawing navigation, Cmd/Ctrl+A select-all, and a polite live announcement of selection changes.
  • Automatic price-axis width from rendered labels.
  • Multi-pane layouts with independent price scales and a shared time axis.
  • Session calendars, DST, holidays, and optional fixed-width closed-session gaps.
  • Drawing tools: trend/horizontal/vertical/cross lines, diagonal rays, extended lines, trend angles, arrows, stats lines, parallel/regression/flat/disjoint/Fib channels, rectangles, Fibonacci retracement/extension/time zones, pitchforks, Gann fans, speed lines, long/short positions, price/date ranges, circles, Elliott impulse/correction/triangle/combo patterns, brush/highlighter/path freehand tools, text, and measurements. The first Elliott click is the labelled origin.
  • Multi-selection: Cmd/Ctrl-click to toggle, Cmd/Ctrl-drag for an additive marquee, group move, and group delete. selectedDrawings() returns the complete selection.
  • Drawing settings: read with getOptions(), patch the selection with updateSelectedDrawings(), and configure future drawings with setDrawingDefaults(). Use drawingToolSettings(toolId) or DRAWING_TOOL_CATALOG to build host menus and show only relevant controls per tool. drawing-double-click lets a host open tool-specific editors, such as a text prompt. The menu, icons, settings controls, and persistence remain host-owned.
  • Extension overlays clipped to panes with time/price coordinate helpers.

Use interaction to disable wheel, drag, pinch, or axis handling. Use resetView() to fit the time scale and restore auto-scale on every pane.

Screenshots

const canvas = chart.takeScreenshot();
const png = chart.exportImage("image/png");

Screenshots flush pending rendering and composite every canvas layer at backing-store resolution.

lightweight-charts migration

import { createChart, mapLightweightChartOptions } from "@wicklib/core";

const chart = createChart(container, mapLightweightChartOptions(lightweightOptions));

The mapper covers the supported layout, grid, crosshair, price-scale, time-scale, locale, and interaction subset. Unsupported price modes fail with NOT_IMPLEMENTED; unknown fields are ignored.

Extensions and licensing

  • Public per-pane overlay API with stable ids and pane cascade.
  • Per-chart extension snapshot; duplicate ids are rejected.
  • Host-owned licensing; core does not inspect paid entitlements.
  • Commercial analytics live in the separate @wicklib/pro package.

What is not included

  • Host persistence, accounts, data vendors, or server-side rendering.
  • Custom series renderers, multiple price axes, or indicator input over line series.
  • WebGL rendering.

Rules

  • No runtime dependencies.
  • Never imports sibling Wicklib packages.
  • The public surface is gated by API Extractor; etc/core.api.md is reviewed like code.
  • All free packages share one fixed release train.

See the repository docs/ directory for RFCs, the playground, benchmarks, and release procedures.

License

Apache-2.0.