{"_id":"liveline","_rev":"8-ba3c0d678d1c978520776680fd0094b3","name":"liveline","dist-tags":{"latest":"0.0.7"},"versions":{"0.0.0":{"name":"liveline","version":"0.0.0","license":"ISC","_id":"liveline@0.0.0","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"dist":{"shasum":"9cf64c799cf44e98f4016a5b2607db3611335792","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.0.tgz","fileCount":1,"integrity":"sha512-J03CFu3w/vD6gkd/KqXqaR2zcGqX4Fg7bRgvrnyXUo65bC8X5okT10RvMKbq0yplvXmiXiS1bWPzsfmSa5g0pA==","signatures":[{"sig":"MEYCIQCTMjSNB268z19Pxj281z8e95yW9J/KeywDdY5LAwASBQIhAJfP+0OPAH5UEHbVZG7gNfHnuDhFbfNYbNh2LtAKnoQr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":88},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"_npmVersion":"11.7.0","description":"","directories":{},"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.0_1771269639038_0.3383542402237165","host":"s3://npm-registry-packages-npm-production"}},"0.0.1":{"name":"liveline","version":"0.0.1","keywords":["react","chart","canvas","real-time","animation","line-chart"],"author":{"name":"Benji Taylor"},"license":"MIT","_id":"liveline@0.0.1","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"dist":{"shasum":"a536ea202d2c68a9af12a8f2a25cfa05e29278d2","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.1.tgz","fileCount":7,"integrity":"sha512-vwxs2dQcl3atv9jgyeRJMCIUENNER0BQuxh2m3sQeTgT1u69xBdb/6NDb4NeUEctsDtta+Ugzz5DctfLI2E9vQ==","signatures":[{"sig":"MEUCIFGMLWmvllrdDjK3RE57s2vLx+rLJ8UhCCJBI/R8e7U4AiEA3vHpLMDuYPAYpGJoPbrkaNQjnRxdUPTpL9zu1IqP82I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136179},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"b9441470b5d573f2a71cd126b9b711eac56d639d","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"pnpm build"},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"repository":{"url":"git+https://github.com/benjitaylor/liveline.git","type":"git"},"_npmVersion":"11.7.0","description":"Real-time animated line chart for React","directories":{},"sideEffects":false,"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.1_1771288066583_0.7249859994303303","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"liveline","version":"0.0.2","keywords":["react","chart","canvas","real-time","animation","line-chart"],"author":{"name":"Benji Taylor"},"license":"MIT","_id":"liveline@0.0.2","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"dist":{"shasum":"f3ff9074ed9b282d0e64b22171d9181a539e9bcd","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.2.tgz","fileCount":7,"integrity":"sha512-mZICvbtrHijvYD4ythDpwqGVOqBjB1RwhG9CUID5AAJRIZ96wmJCA8F/6wGCXmktsktdC3rxkhFWk0tIVcicGw==","signatures":[{"sig":"MEUCIEf8wALoqTALBXsGxClTk+37lhRZUeYtKsHTYGAN0wRfAiEAzRm5rp9iBHdD0eQjO352mN+eWoROCsI9nib/xVGsS28=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136079},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"84a2188ae690119159b09d649f5e2789cade9cde","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"pnpm build"},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"repository":{"url":"git+https://github.com/benjitaylor/liveline.git","type":"git"},"_npmVersion":"11.7.0","description":"Real-time animated line chart for React","directories":{},"sideEffects":false,"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.2_1771288314183_0.8435517650585809","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"liveline","version":"0.0.3","keywords":["react","chart","canvas","real-time","animation","line-chart"],"author":{"name":"Benji Taylor"},"license":"MIT","_id":"liveline@0.0.3","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"dist":{"shasum":"f01a2735e71bba68814d8b39eaa824b1c5a9d275","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.3.tgz","fileCount":7,"integrity":"sha512-elwY2o0kyrO72GhgNaEUFFyKT2NfmZux+U+MpmxIUJXrIYhdjjCqDZ1DDPH0IoQxZoOBjcJsJQbZv/9T6OFWGg==","signatures":[{"sig":"MEQCIEx8XzfcKpFzD24DrYGrALKhnI4WV15Uk8rOqItrTGtRAiA/tXKSnAIelrScC9jwSqRFqAl0gP64EXbpNDQZ0Rpm9w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136563},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"f0f6f8d54b5fb9eaa602acc2948a87e185b9a76c","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"pnpm build"},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"repository":{"url":"git+https://github.com/benjitaylor/liveline.git","type":"git"},"_npmVersion":"11.7.0","description":"Real-time animated line chart for React","directories":{},"sideEffects":false,"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.3_1771347359946_0.06253430910503965","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"liveline","version":"0.0.4","keywords":["react","chart","canvas","real-time","animation","line-chart"],"author":{"name":"Benji Taylor"},"license":"MIT","_id":"liveline@0.0.4","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"dist":{"shasum":"655954734e85ec9e7440f914af22ccebec28776f","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.4.tgz","fileCount":7,"integrity":"sha512-l8A8e7AZxRy05OQT/tCszxOKshIYQS3FInzm4G4hhgu9VcDnS4dGubPM1NdbAYpLeVBMYQB7wnLWEcMNZwXx7Q==","signatures":[{"sig":"MEYCIQCcBuQvlTWvKXfnt2HqfBDd6XqVppRpm6o7kyG1z9mxvwIhAMCRoxF5oGYUMNSoPaUftQJeluNkVK9bU0tkMtK83pqm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":161950},"main":"dist/index.cjs","type":"module","_from":"file:liveline-0.0.4.tgz","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"_resolved":"/private/var/folders/pj/d2q07ff97kx7c6qzghb65khm0000gn/T/ab7878f897f40d19a1b66df66c837e6d/liveline-0.0.4.tgz","_integrity":"sha512-l8A8e7AZxRy05OQT/tCszxOKshIYQS3FInzm4G4hhgu9VcDnS4dGubPM1NdbAYpLeVBMYQB7wnLWEcMNZwXx7Q==","repository":{"url":"git+https://github.com/benjitaylor/liveline.git","type":"git"},"_npmVersion":"11.7.0","description":"Real-time animated line chart for React","directories":{},"sideEffects":false,"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.4_1771612440929_0.6558922085432797","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"liveline","version":"0.0.5","keywords":["react","chart","canvas","real-time","animation","line-chart","candlestick","ohlc"],"author":{"name":"Benji Taylor"},"license":"MIT","_id":"liveline@0.0.5","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"dist":{"shasum":"a3c5654a23fca36eea5b730121af4d1da5c56541","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.5.tgz","fileCount":7,"integrity":"sha512-GP9rXoDz/w/NQpX8GAs9XUE417BMIaR4W+Xy7TrFx4EJYQ053w/v6ERYslHsIxst9NKugHxU1L83lTI05S8o+g==","signatures":[{"sig":"MEUCIByIHfHbeUhnj16uK3cBwUWoGgOUfbXrxzBJXGkksXD4AiEApt4xTinsjiFrC/4lbIOdoojG7Auj6XWIxZ3QMpu8mwM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":266292},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"a33912b0c79cbfc494c87a09812c987e03af0e1c","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"pnpm build"},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"repository":{"url":"git+https://github.com/benjitaylor/liveline.git","type":"git"},"_npmVersion":"11.7.0","description":"Real-time animated charts for React — line and candlestick modes","directories":{},"sideEffects":false,"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.5_1771893160705_0.7009820689491502","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"name":"liveline","version":"0.0.6","keywords":["react","chart","canvas","real-time","animation","line-chart","candlestick","ohlc","multi-series","multi-line"],"author":{"name":"Benji Taylor"},"license":"MIT","_id":"liveline@0.0.6","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"dist":{"shasum":"16318c5891bae3fa9839539352991473fbb48ac5","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.6.tgz","fileCount":7,"integrity":"sha512-ZHw/Xgh1elzCc361YFRW4+rqGPl8dWdDDS26XYLxkn4uYBlEs5V6OajpIC75l2Lff1Q+I8TvBvav4rbLGHIpJg==","signatures":[{"sig":"MEQCIF0vwTIz/U3f50s80z9TkiyRnl79KVhwPqJTnHI5jFWoAiBpRKenDyNyd9sl1tEkoiU7nh1mJ9d6Tx2BpwhBw6MxGg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":315737},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"b92143f19ef546e016537e3e93d948cdd8e6bce4","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"pnpm build"},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"repository":{"url":"git+https://github.com/benjitaylor/liveline.git","type":"git"},"_npmVersion":"11.7.0","description":"Real-time animated charts for React — line, candlestick, and multi-series modes","directories":{},"sideEffects":false,"_nodeVersion":"25.3.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/liveline_0.0.6_1771992072990_0.4068925971946211","host":"s3://npm-registry-packages-npm-production"}},"0.0.7":{"name":"liveline","version":"0.0.7","type":"module","description":"Real-time animated charts for React — line, candlestick, and multi-series modes","keywords":["react","chart","canvas","real-time","animation","line-chart","candlestick","ohlc","multi-series","multi-line"],"license":"MIT","author":{"name":"Benji Taylor"},"repository":{"type":"git","url":"git+https://github.com/benjitaylor/liveline.git"},"homepage":"https://github.com/benjitaylor/liveline#readme","bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"sideEffects":false,"main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"engines":{"node":">=18"},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","prepublishOnly":"pnpm build"},"peerDependencies":{"react":">=18"},"devDependencies":{"@types/react":"^18.0.0","tsup":"^8.5.1","typescript":"^5.0.0","vitest":"^4.0.18"},"gitHead":"684021f8d8d79b06ed971da8d96de9a3c8fc174d","_id":"liveline@0.0.7","_nodeVersion":"25.3.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-S1Weo1kmefiOCNaW/WFXErqJXlV8A/ldIkIthaOeT57I2ZhqhKLKQDJ1wfabtMSK9vJeU8PeMNHd8Sr8TLByWQ==","shasum":"90acc45b9bba7f277238dc1b032648be7aa95d80","tarball":"https://registry.npmjs.org/liveline/-/liveline-0.0.7.tgz","fileCount":7,"unpackedSize":318207,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDtRYOpU6QdZwtPgxS7M6Zvdi/3Jtyjso88uRh1rGrx4wIhAP3ObGdxZ+rCbN5owvNKhxhuDfmgSSFcqLI37hnJ96EJ"}]},"_npmUser":{"name":"benjitaylor","email":"accounts@benji.co"},"directories":{},"maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/liveline_0.0.7_1773336421139_0.25333643945310524"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-16T19:20:38.924Z","modified":"2026-03-12T17:27:02.148Z","0.0.0":"2026-02-16T19:20:39.171Z","0.0.1":"2026-02-17T00:27:46.743Z","0.0.2":"2026-02-17T00:31:54.352Z","0.0.3":"2026-02-17T16:56:00.105Z","0.0.4":"2026-02-20T18:34:01.073Z","0.0.5":"2026-02-24T00:32:40.848Z","0.0.6":"2026-02-25T04:01:13.135Z","0.0.7":"2026-03-12T17:27:02.046Z"},"bugs":{"url":"https://github.com/benjitaylor/liveline/issues"},"author":{"name":"Benji Taylor"},"license":"MIT","homepage":"https://github.com/benjitaylor/liveline#readme","keywords":["react","chart","canvas","real-time","animation","line-chart","candlestick","ohlc","multi-series","multi-line"],"repository":{"type":"git","url":"git+https://github.com/benjitaylor/liveline.git"},"description":"Real-time animated charts for React — line, candlestick, and multi-series modes","maintainers":[{"name":"benjitaylor","email":"accounts@benji.co"}],"readme":"# Liveline\r\n\r\nReal-time animated charts for React. Line, multi-series, and candlestick modes, canvas-rendered, 60fps, zero CSS imports.\r\n\r\n## Install\r\n\r\n```bash\r\npnpm add liveline\r\n```\r\n\r\nPeer dependency: `react >=18`.\r\n\r\n## Quick Start\r\n\r\n```tsx\r\nimport { Liveline } from 'liveline'\r\nimport type { LivelinePoint } from 'liveline'\r\n\r\nfunction Chart() {\r\n  const [data, setData] = useState<LivelinePoint[]>([])\r\n  const [value, setValue] = useState(0)\r\n\r\n  // Feed data from WebSocket, polling, etc.\r\n  // Each point: { time: unixSeconds, value: number }\r\n\r\n  return (\r\n    <div style={{ height: 300 }}>\r\n      <Liveline data={data} value={value} color=\"#3b82f6\" theme=\"dark\" />\r\n    </div>\r\n  )\r\n}\r\n```\r\n\r\nThe component fills its parent container. Set a height on the parent. Pass `data` as a growing array of points and `value` as the latest number — Liveline handles smooth interpolation between updates.\r\n\r\n## Props\r\n\r\n**Data**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `data` | `LivelinePoint[]` | required | Array of `{ time, value }` points |\r\n| `value` | `number` | required | Latest value (smoothly interpolated) |\r\n\r\n**Appearance**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `theme` | `'light' \\| 'dark'` | `'dark'` | Color scheme |\r\n| `color` | `string` | `'#3b82f6'` | Accent color — all palette colors derived from this |\r\n| `grid` | `boolean` | `true` | Y-axis grid lines + labels |\r\n| `badge` | `boolean` | `true` | Value pill tracking chart tip |\r\n| `badgeVariant` | `'default' \\| 'minimal'` | `'default'` | Badge style: accent-colored or white with grey text |\r\n| `badgeTail` | `boolean` | `true` | Pointed tail on badge pill |\r\n| `fill` | `boolean` | `true` | Gradient under the curve |\r\n| `pulse` | `boolean` | `true` | Pulsing ring on live dot |\r\n| `lineWidth` | `number` | `2` | Stroke width of the main line in pixels |\r\n\r\n**Features**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `momentum` | `boolean \\| Momentum` | `true` | Dot glow + arrows. `true` = auto-detect, or `'up' \\| 'down' \\| 'flat'` |\r\n| `scrub` | `boolean` | `true` | Crosshair scrubbing on hover |\r\n| `exaggerate` | `boolean` | `false` | Tight Y-axis — small moves fill chart height |\r\n| `showValue` | `boolean` | `false` | Large live value overlay (60fps DOM update, no re-renders) |\r\n| `valueMomentumColor` | `boolean` | `false` | Color the value text green/red by momentum |\r\n| `degen` | `boolean \\| DegenOptions` | `false` | Burst particles + chart shake on momentum swings |\r\n\r\n**Candlestick**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `mode` | `'line' \\| 'candle'` | `'line'` | Chart type |\r\n| `candles` | `CandlePoint[]` | — | OHLC candle data `{ time, open, high, low, close }` |\r\n| `candleWidth` | `number` | — | Seconds per candle |\r\n| `liveCandle` | `CandlePoint` | — | Current in-progress candle with real-time OHLC |\r\n| `lineMode` | `boolean` | `false` | Morph candles into a line display |\r\n| `lineData` | `LivelinePoint[]` | — | Tick-level data for line mode density |\r\n| `lineValue` | `number` | — | Current tick value for line mode |\r\n| `onModeChange` | `(mode) => void` | — | Callback for built-in line/candle toggle |\r\n\r\nWhen `mode=\"candle\"`, pass `candles` (committed OHLC bars) and `liveCandle` (the current bar, updated every tick). `candleWidth` sets the time bucket in seconds. The `lineMode` prop smoothly morphs between candle and line views — candle bodies collapse to close price, then the line extends outward. Provide `lineData` and `lineValue` (tick-level resolution) for a smooth density transition during the morph.\r\n\r\nThe `onModeChange` prop renders a built-in line/candle toggle next to the time window buttons.\r\n\r\n**Multi-series**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `series` | `LivelineSeries[]` | — | Multiple overlapping lines `{ id, data, value, color, label? }` |\r\n| `onSeriesToggle` | `(id, visible) => void` | — | Callback when a series is toggled via built-in chips |\r\n| `seriesToggleCompact` | `boolean` | `false` | Show only colored dots in toggle (no text labels) |\r\n\r\nPass `series` instead of `data`/`value` to draw multiple lines sharing the same axes. Each series gets its own color, label, and endpoint dot. Toggle chips appear automatically when there are 2+ series — clicking one hides/shows that line with a smooth fade. The Y-axis range adjusts when series are hidden. Badge, momentum arrows, and fill are disabled in multi-series mode.\r\n\r\n**State**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `loading` | `boolean` | `false` | Breathing line animation — use while waiting for data |\r\n| `paused` | `boolean` | `false` | Smoothly freeze chart scrolling; resume catches up to real time |\r\n| `emptyText` | `string` | `'No data to display'` | Text shown in the empty state |\r\n\r\nWhen `loading` flips to `false` with data present, the loading line morphs into the actual chart shape. In line mode, the fill, grid, and badge animate in. In candle mode, flat lines expand into full OHLC bodies while the morph line fades out. When `data` is empty and `loading` is `false`, a minimal \"No data\" empty state is shown.\r\n\r\n**Time**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `window` | `number` | `30` | Visible time window in seconds |\r\n| `windows` | `WindowOption[]` | — | Time horizon buttons `[{ label, secs }]` |\r\n| `onWindowChange` | `(secs) => void` | — | Called when a window button is clicked |\r\n| `windowStyle` | `'default' \\| 'rounded' \\| 'text'` | `'default'` | Window button visual style |\r\n\r\n**Crosshair**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `tooltipY` | `number` | `14` | Vertical offset for crosshair tooltip text |\r\n| `tooltipOutline` | `boolean` | `true` | Stroke outline on tooltip text for readability |\r\n\r\n**Orderbook**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `orderbook` | `OrderbookData` | — | Bid/ask depth stream `{ bids, asks }` |\r\n\r\n**Advanced**\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `referenceLine` | `ReferenceLine` | — | Horizontal reference line `{ value, label? }` |\r\n| `formatValue` | `(v: number) => string` | `v.toFixed(2)` | Value label formatter |\r\n| `formatTime` | `(t: number) => string` | `HH:MM:SS` | Time axis formatter |\r\n| `lerpSpeed` | `number` | `0.08` | Interpolation speed (0–1) |\r\n| `padding` | `Padding` | `{ top: 12, right: auto, bottom: 28, left: 12 }` | Chart padding override (`right` is 80/54/12 based on badge/grid) |\r\n| `onHover` | `(point \\| null) => void` | — | Hover callback with `{ time, value, x, y }` |\r\n| `cursor` | `string` | `'crosshair'` | CSS cursor on canvas hover |\r\n| `className` | `string` | — | Container class |\r\n| `style` | `CSSProperties` | — | Container styles |\r\n\r\n## Examples\r\n\r\n### Basic (line + badge)\r\n\r\n```tsx\r\n<Liveline data={data} value={value} color=\"#3b82f6\" theme=\"dark\" />\r\n```\r\n\r\n### Candlestick (minimal)\r\n\r\n```tsx\r\n<Liveline\r\n  mode=\"candle\"\r\n  data={ticks}\r\n  value={latestTick}\r\n  candles={candles}\r\n  candleWidth={60}\r\n  liveCandle={liveCandle}\r\n  color=\"#f7931a\"\r\n  formatValue={(v) => `$${v.toLocaleString('en-US', { minimumFractionDigits: 2 })}`}\r\n/>\r\n```\r\n\r\n### Candlestick (line mode toggle + time windows)\r\n\r\n```tsx\r\n<Liveline\r\n  mode=\"candle\"\r\n  data={ticks}\r\n  value={latestTick}\r\n  candles={candles}\r\n  candleWidth={60}\r\n  liveCandle={liveCandle}\r\n  lineMode={showLine}\r\n  lineData={ticks}\r\n  lineValue={latestTick}\r\n  onModeChange={(mode) => setShowLine(mode === 'line')}\r\n  color=\"#f7931a\"\r\n  formatValue={(v) => `$${v.toLocaleString('en-US', { minimumFractionDigits: 2 })}`}\r\n  windows={[\r\n    { label: '5m', secs: 300 },\r\n    { label: '15m', secs: 900 },\r\n    { label: '1h', secs: 3600 },\r\n  ]}\r\n/>\r\n```\r\n\r\n### Crypto-style (momentum + degen + exaggerate)\r\n\r\n```tsx\r\n<Liveline\r\n  data={data}\r\n  value={value}\r\n  color=\"#f7931a\"\r\n  exaggerate\r\n  degen\r\n  showValue\r\n  valueMomentumColor\r\n  formatValue={(v) => `$${v.toLocaleString('en-US', { minimumFractionDigits: 2 })}`}\r\n/>\r\n```\r\n\r\n### Dashboard (showValue + windows + no badge)\r\n\r\n```tsx\r\n<Liveline\r\n  data={data}\r\n  value={value}\r\n  badge={false}\r\n  showValue\r\n  windows={[\r\n    { label: '15s', secs: 15 },\r\n    { label: '30s', secs: 30 },\r\n    { label: '2m', secs: 120 },\r\n    { label: '5m', secs: 300 },\r\n  ]}\r\n  onWindowChange={(secs) => console.log('window:', secs)}\r\n/>\r\n```\r\n\r\n### Multi-series (prediction market)\r\n\r\n```tsx\r\n<Liveline\r\n  data={[]}\r\n  value={0}\r\n  series={[\r\n    { id: 'yes', data: yesData, value: yesValue, color: '#3b82f6', label: 'Yes' },\r\n    { id: 'no', data: noData, value: noValue, color: '#ef4444', label: 'No' },\r\n  ]}\r\n  grid\r\n  scrub\r\n  pulse\r\n  windowStyle=\"rounded\"\r\n  formatValue={(v) => v.toFixed(1) + '%'}\r\n  onSeriesToggle={(id, visible) => console.log(id, visible)}\r\n  windows={[\r\n    { label: '10s', secs: 10 },\r\n    { label: '30s', secs: 30 },\r\n    { label: '1m', secs: 60 },\r\n  ]}\r\n/>\r\n```\r\n\r\n### Loading + pause\r\n\r\n```tsx\r\n<Liveline\r\n  data={data}\r\n  value={value}\r\n  loading={isConnecting}\r\n  paused={!isTabVisible}\r\n/>\r\n```\r\n\r\n### Orderbook (orderbook data + particles)\r\n\r\n```tsx\r\n<Liveline\r\n  data={data}\r\n  value={value}\r\n  color=\"#f7931a\"\r\n  orderbook={{ bids: [[100, 2], [99, 5]], asks: [[101, 3], [102, 4]] }}\r\n  degen\r\n  showValue\r\n/>\r\n```\r\n\r\n## How It Works\r\n\r\n- **Canvas rendering** — single `<canvas>` element, no DOM nodes per data point\r\n- **requestAnimationFrame** loop pauses when the tab is hidden\r\n- **Fritsch-Carlson monotone splines** for smooth curves — no overshoots beyond local min/max\r\n- **Frame-rate-independent lerp** on value, Y-axis range, badge color, and scrub opacity\r\n- **Candlestick rendering** — OHLC bodies + wicks with bull/bear coloring, smooth live candle updates\r\n- **Line/candle morph** — candle bodies collapse to close price, morph line extends center-out, coordinated alpha crossfade\r\n- **Multi-series** — overlapping lines with per-series toggle, smooth alpha fade, and dynamic Y-axis range\r\n- **ResizeObserver** tracks container size — no per-frame layout reads\r\n- **Theme derivation** — full palette from one accent color + light/dark mode\r\n- **Binary search interpolation** for hover value lookup\r\n\r\nNo CSS imports. No external dependencies beyond React.\r\n\r\n## License\r\n\r\n© 2026 Benji Taylor\r\n\r\nLicensed under MIT\r\n","readmeFilename":"README.md"}