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

liveline-svelte

v0.0.3

Published

Independent real-time chart library for Svelte 5, with animated line, candlestick, and multi-series modes. Originally forked from Liveline.

Readme

liveline-svelte

liveline-svelte is an independently developed chart library for Svelte 5.

It began as a Svelte fork of Liveline by Benji Taylor and now follows its own direction. APIs, features, and behavior evolve around Svelte and its use cases; maintaining 1:1 parity or compatibility with the original project is not a direct goal. Use this repository's documentation and releases when integrating the library.

Real-time animated charts for Svelte. Line, multi-series, and candlestick modes, canvas-rendered, 60fps, no CSS imports.

Install

pnpm add liveline-svelte
yarn add liveline-svelte
npm install liveline-svelte

Peer dependency: svelte ^5.

Quick Start

<script lang="ts">
  import { Liveline } from 'liveline-svelte'
  import type { LivelinePoint } from 'liveline-svelte'

  let data = $state.raw<LivelinePoint[]>([])
  let value = $state(0)
</script>

<div style="height: 320px;">
  <Liveline data={data} {value} color="#3b82f6" theme="dark" />
</div>

The component fills its parent container. Set a height on the parent, then pass a growing data array and the latest value. Liveline handles the interpolation and drawing loop internally. Points and candles should be ordered by ascending time (Unix seconds).

The examples use $state.raw for arrays that are replaced on updates, such as data = [...data, point], avoiding deep proxy overhead for historical data. Use $state instead if you prefer to mutate arrays or individual points in place.

Props

Any standard div attributes such as class, style, id, data-*, or aria-* are forwarded to the root container.

Data

| Prop | Type | Default | Description | |------|------|---------|-------------| | data | LivelinePoint[] | required | Array of { time, value } points | | value | number | required | Latest value |

Appearance

| Prop | Type | Default | Description | |------|------|---------|-------------| | theme | 'light' \| 'dark' | 'dark' | Color scheme | | color | string | '#3b82f6' | Accent color used to derive the palette | | grid | boolean | true | Y-axis grid lines and labels | | badge | boolean | true | Value pill tracking the chart tip | | badgeVariant | 'default' \| 'minimal' | 'default' | Accent badge or neutral badge | | badgeTail | boolean | true | Pointed tail on the badge pill | | fill | boolean | true | Gradient under the curve | | pulse | boolean | true | Pulsing ring on the live dot | | lineWidth | number | 2 | Main line width in pixels |

Features

| Prop | Type | Default | Description | |------|------|---------|-------------| | momentum | boolean \| Momentum | true | Dot glow and arrows. true auto-detects, or pass 'up' \| 'down' \| 'flat' | | scrub | boolean | true | Crosshair scrubbing on hover. On touch, a drag that starts sideways scrubs and stays locked to the chart; one that starts up or down scrolls the page | | exaggerate | boolean | false | Tight Y-axis range so smaller moves fill more height | | showValue | boolean | false | Large live value overlay | | valueMomentumColor | boolean | false | Colors the value overlay by momentum | | degen | boolean \| DegenOptions | false | Particle bursts and shake on strong swings |

Candlestick

| Prop | Type | Default | Description | |------|------|---------|-------------| | mode | 'line' \| 'candle' | 'line' | Chart type | | candles | CandlePoint[] | — | Committed OHLC candles | | candleWidth | number | — | Seconds per candle | | liveCandle | CandlePoint | — | Current in-progress candle | | lineMode | boolean | false | Morph candles toward a line view | | lineData | LivelinePoint[] | — | Tick-level data for density blending in line mode | | lineValue | number | — | Current tick value for line mode | | onModeChange | (mode) => void | — | Callback for the built-in candle/line toggle |

When mode="candle", pass candles, liveCandle, and candleWidth. If you also pass lineMode, lineData, and lineValue, Liveline smoothly morphs candle bodies into a denser line representation.

Multi-series

| Prop | Type | Default | Description | |------|------|---------|-------------| | series | LivelineSeries[] | — | Overlapping line series { id, data, value, color, label? } | | onSeriesToggle | (id, visible) => void | — | Called when a built-in series chip is toggled | | showSeriesToggle | boolean | true | Show built-in series chips; disable to manage series externally | | seriesToggleCompact | boolean | false | Dot-only series toggle chips |

When series is provided, Liveline disables single-series badge, fill, and momentum affordances automatically, and the right gutter shrinks to fit the grid labels. degen particles burst from each series' own live dot.

State

| Prop | Type | Default | Description | |------|------|---------|-------------| | loading | boolean | false | Shows the breathing loading line | | paused | boolean | false | Freezes scrolling while preserving visual continuity | | emptyText | string | 'No data to display' | Empty-state label |

Time

| Prop | Type | Default | Description | |------|------|---------|-------------| | window | number | 30 | Visible time window in seconds | | windows | WindowOption[] | — | Built-in time horizon buttons | | onWindowChange | (secs) => void | — | Called when a horizon button is clicked | | windowStyle | 'default' \| 'rounded' \| 'text' | 'default' | Time-button visual style |

Crosshair

While scrubbing, the values and time at the crosshair are read out in a band above the plot, so they never cover the lines. The band wraps on narrow charts and is reserved whenever scrub is on, sized for the live values, so the plot does not move when a hover starts. With a badge, the crosshair fades out as it nears the live dot, since the badge shows that value.

Orderbook

| Prop | Type | Default | Description | |------|------|---------|-------------| | orderbook | OrderbookData | — | Bid/ask depth data { bids, asks } |

Advanced

| Prop | Type | Default | Description | |------|------|---------|-------------| | referenceLine | ReferenceLine | — | Horizontal reference line { value, label? } | | formatValue | (v: number) => string | v.toFixed(2) | Value formatter | | formatTime | (time, step?) => string | HH:MM:SS, HH:MM from a minute up | Time formatter. step is the seconds a label stands for: an axis tick's interval or a candle's width, absent for the exact moment under the crosshair | | lerpSpeed | number | 0.08 | Interpolation speed | | padding | Padding | { top: 12, right: auto, bottom: 28, left: 12 } | Chart padding override; right defaults to 80 with a badge, 54 with grid labels, else 12 | | onHover | (point \| null) => void | — | Hover callback with { time, value, x, y } | | cursor | string | 'crosshair' | Canvas hover cursor |

Examples

Basic line

<script lang="ts">
  import { Liveline } from 'liveline-svelte'
  import type { LivelinePoint } from 'liveline-svelte'

  let data = $state.raw<LivelinePoint[]>([])
  let value = $state(0)
</script>

<div style="height: 300px;">
  <Liveline data={data} {value} color="#3b82f6" theme="dark" />
</div>

Candlestick with built-in line toggle

<script lang="ts">
  import { Liveline } from 'liveline-svelte'
  import type { CandlePoint, LivelinePoint } from 'liveline-svelte'

  let ticks = $state.raw<LivelinePoint[]>([])
  let value = $state(0)
  let candles = $state.raw<CandlePoint[]>([])
  let liveCandle = $state.raw<CandlePoint>()
  let lineMode = $state(true)
</script>

<div style="height: 360px;">
  <Liveline
    data={ticks}
    {value}
    mode="candle"
    {candles}
    candleWidth={60}
    {liveCandle}
    {lineMode}
    lineData={ticks}
    lineValue={value}
    onModeChange={(mode) => (lineMode = mode === 'line')}
    color="#f97316"
    formatValue={(amount) =>
      `$${amount.toLocaleString('en-US', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      })}`
    }
  />
</div>

Multi-series

<script lang="ts">
  import { Liveline } from 'liveline-svelte'
  import type { LivelinePoint, LivelineSeries } from 'liveline-svelte'

  let alpha = $state.raw<LivelinePoint[]>([])
  let beta = $state.raw<LivelinePoint[]>([])
  let alphaValue = $state(0)
  let betaValue = $state(0)

  let series = $derived<LivelineSeries[]>([
    { id: 'alpha', label: 'Alpha', data: alpha, value: alphaValue, color: '#3b82f6' },
    { id: 'beta', label: 'Beta', data: beta, value: betaValue, color: '#f97316' }
  ])
</script>

<div style="height: 320px;">
  <Liveline data={alpha} value={alphaValue} {series} />
</div>

Transitioning between chart scenes

LivelineTransition uses a Svelte snippet instead of React-style keyed children:

<script lang="ts">
  import { Liveline, LivelineTransition } from 'liveline-svelte'
  import type { CandlePoint, LivelinePoint } from 'liveline-svelte'

  let active = $state<'line' | 'candle'>('line')
  let data = $state.raw<LivelinePoint[]>([])
  let value = $state(0)
  let candles = $state.raw<CandlePoint[]>([])
  let liveCandle = $state.raw<CandlePoint>()
</script>

<div style="height: 360px;">
  <LivelineTransition {active}>
    {#snippet children(key)}
      {#if key === 'line'}
        <Liveline {data} {value} color="#22c55e" />
      {:else if key === 'candle'}
        <Liveline
          {data}
          {value}
          mode="candle"
          {candles}
          candleWidth={60}
          {liveCandle}
          color="#f97316"
        />
      {/if}
    {/snippet}
  </LivelineTransition>
</div>

Notes

  • Liveline ships as a Svelte 5 component library and forwards standard root div attributes.
  • The package has no runtime dependencies beyond svelte.
  • The drawing engine stays framework-neutral and runs outside Svelte’s templating work, which keeps updates cheap even under rapid tick streams.
  • The project builds on Benji Taylor's original Liveline work. Original attribution is preserved in LICENSE.

Development

Use Node.js 24 and pnpm 12, then start the showcase:

pnpm install --frozen-lockfile
pnpm dev

Open the local URL printed by Vite (normally http://localhost:5173/). The root page showcases streaming line, multi-series, and candlestick charts, theme and appearance controls, and loading, empty, and paused states. Its data is simulated; no API keys or external feed are needed.

src/lib/        Library components, public types, drawing engine, and unit tests
src/routes/     SvelteKit showcase page and demo helpers
src/app.html    Demo HTML template
vite.config.ts  SvelteKit, static adapter, preprocessing, and package alias
wrangler.jsonc  Cloudflare static asset configuration
dist/           Generated npm package
build/          Prerendered static showcase

The demo imports from liveline-svelte, just like a consumer. The alias in vite.config.ts resolves that name to src/lib/index.ts for Vite and TypeScript, so library edits update the demo without a separate build. svelte-package builds only src/lib; the demo is excluded from the published package.

pnpm check       # Svelte/TypeScript and lint checks
pnpm test        # Library unit tests
pnpm package     # Build the library into dist/
pnpm build:site  # Prerender the static showcase into build/
pnpm build       # Build both the showcase and the library
pnpm preview     # Preview the built showcase locally

Demo deployment

Connect this repository to a Cloudflare Worker named liveline-svelte. Set the root directory to the repository root, use pnpm build:site as the build command, and keep npx wrangler deploy as the deploy command. The included wrangler.jsonc serves build/ as static assets. No Worker script, server runtime, or Wrangler dependency is needed.

For Cloudflare Pages, use the same pnpm build:site build command and set the build output directory to build. Select the None framework preset if needed to enter these settings manually.

Set PNPM_VERSION=12.3.4 in Cloudflare's build environment. The .node-version file selects Node.js 24 for the build.