emberwick 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +530 -0
- package/index.d.ts +257 -0
- package/index.js +1310 -0
- package/index.js.map +1 -0
- package/package.json +56 -0
- package/react.d.ts +31 -0
- package/react.js +76 -0
- package/react.js.map +1 -0
- package/umd/emberwick.umd.js +2 -0
- package/umd/emberwick.umd.js.map +1 -0
- package/webcomponent.d.ts +16 -0
- package/webcomponent.js +75 -0
- package/webcomponent.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberwick.umd.js","sources":["../../src/chart/core/Layers.js","../../src/chart/core/Loop.js","../../src/chart/motion/Tween.js","../../src/chart/core/TimeScale.js","../../src/chart/core/PriceScale.js","../../src/chart/core/palette.js","../../src/chart/motion/LiveCandle.js","../../src/chart/motion/Inertia.js","../../src/chart/core/formatters.js","../../src/chart/render/grid.js","../../src/chart/render/candles.js","../../src/chart/render/crosshair.js","../../src/chart/core/Chart.js","../../src/chart/data/DataFeed.js","../../src/chart/data/RandomFeed.js","../../src/chart/index.js"],"sourcesContent":["/**\n * Layers — stacked canvases sharing one coordinate space.\n *\n * Why: the crosshair repaints on every pointer move, the candles do not.\n * Separate canvases mean moving the cursor never touches candle pixels.\n * All contexts are pre-scaled by devicePixelRatio, so every renderer draws\n * in CSS pixels and gets crisp output on retina.\n */\nexport class Layers {\n constructor(container, names) {\n this.container = container\n this.names = names\n this.canvas = {}\n this.ctx = {}\n this.width = 0\n this.height = 0\n this.dpr = 0\n this.onResize = null\n\n if (getComputedStyle(container).position === 'static') {\n container.style.position = 'relative'\n }\n\n names.forEach((name, i) => {\n const c = document.createElement('canvas')\n Object.assign(c.style, {\n position: 'absolute',\n left: '0',\n top: '0',\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n zIndex: String(i + 1),\n })\n container.appendChild(c)\n this.canvas[name] = c\n this.ctx[name] = c.getContext('2d')\n })\n\n this._ro = new ResizeObserver(() => this.measure())\n this._ro.observe(container)\n this.measure()\n }\n\n measure() {\n const r = this.container.getBoundingClientRect()\n const w = Math.max(1, Math.floor(r.width))\n const h = Math.max(1, Math.floor(r.height))\n const dpr = Math.min(window.devicePixelRatio || 1, 2)\n if (w === this.width && h === this.height && dpr === this.dpr) return\n this.width = w\n this.height = h\n this.dpr = dpr\n for (const n of this.names) {\n const c = this.canvas[n]\n c.width = Math.floor(w * dpr)\n c.height = Math.floor(h * dpr)\n this.ctx[n].setTransform(dpr, 0, 0, dpr, 0, 0)\n }\n if (this.onResize) this.onResize(w, h)\n }\n\n /** Flatten all layers into a single canvas (for toImage/export). */\n composite() {\n const out = document.createElement('canvas')\n out.width = Math.floor(this.width * this.dpr)\n out.height = Math.floor(this.height * this.dpr)\n const c = out.getContext('2d')\n for (const n of this.names) c.drawImage(this.canvas[n], 0, 0)\n return out\n }\n\n destroy() {\n this._ro.disconnect()\n for (const n of this.names) this.canvas[n].remove()\n this.canvas = {}\n this.ctx = {}\n }\n}\n","/**\n * Loop — ONE requestAnimationFrame loop for the whole chart, driven by\n * dirty flags. 500 feed ticks between two frames still cost one repaint.\n *\n * The frame callback returns `true` while animation is in flight, which is\n * what keeps the loop running; otherwise it idles at zero CPU until something\n * calls invalidate().\n */\nexport class Loop {\n constructor(onFrame) {\n this.onFrame = onFrame\n this.fps = 0\n this._raf = 0\n this._dirty = new Set()\n this._last = 0\n this._running = false\n this._frames = 0\n this._fpsAt = 0\n this._tick = this._tick.bind(this)\n }\n\n invalidate(...layers) {\n if (!layers.length) this._dirty.add('all')\n else for (const l of layers) this._dirty.add(l)\n this._schedule()\n }\n\n start() {\n if (this._running) return\n this._running = true\n this._last = performance.now()\n this._fpsAt = this._last\n this.invalidate('all')\n }\n\n stop() {\n this._running = false\n if (this._raf) cancelAnimationFrame(this._raf)\n this._raf = 0\n }\n\n _schedule() {\n if (this._raf || !this._running) return\n this._raf = requestAnimationFrame(this._tick)\n }\n\n _tick(now) {\n this._raf = 0\n if (!this._running) return\n const dt = Math.min(Math.max(now - this._last, 1), 64)\n this._last = now\n\n this._frames++\n if (now - this._fpsAt >= 500) {\n this.fps = Math.round((this._frames * 1000) / (now - this._fpsAt))\n this._frames = 0\n this._fpsAt = now\n }\n\n const dirty = this._dirty\n this._dirty = new Set()\n\n let wantMore = false\n try {\n wantMore = this.onFrame(dirty, dt, now) === true\n } catch (e) {\n console.error('[Emberwick] frame error', e)\n }\n if (wantMore || this._dirty.size) this._schedule()\n }\n}\n","// Motion primitives. Everything animated in Emberwick goes through one of these\n// two classes so there is exactly one place that owns easing behaviour.\n\nexport const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3)\nexport const easeInOutCubic = (t) =>\n t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2\n\n/**\n * Smoothed — exponential smoothing toward a target that may move every frame.\n * Frame-rate independent: the same visual speed at 30fps and 144fps.\n * Use for values that are continuously re-targeted (autoscale, live candle, zoom).\n */\nexport class Smoothed {\n constructor(value = 0, tau = 90) {\n this.value = value\n this.target = value\n this.tau = tau\n }\n\n set(target) {\n this.target = target\n }\n\n /** Snap with no animation. */\n jump(v) {\n this.value = v\n this.target = v\n }\n\n get settled() {\n const eps = 1e-9 + Math.abs(this.target) * 1e-6\n return Math.abs(this.target - this.value) <= eps\n }\n\n /** @returns {boolean} true while still moving (caller keeps the loop alive) */\n tick(dt) {\n if (this.settled) {\n this.value = this.target\n return false\n }\n this.value += (this.target - this.value) * (1 - Math.exp(-dt / this.tau))\n return true\n }\n}\n\n/**\n * Tween — fixed-duration one-shot, for discrete events (a candle being born).\n */\nexport class Tween {\n constructor(duration = 200, ease = easeOutCubic) {\n this.duration = duration\n this.ease = ease\n this.t = duration\n }\n\n restart() {\n this.t = 0\n }\n\n get done() {\n return this.t >= this.duration\n }\n\n get progress() {\n return this.ease(Math.min(1, this.t / this.duration))\n }\n\n tick(dt) {\n if (this.done) return false\n this.t += dt\n return true\n }\n}\n","import { Smoothed } from '../motion/Tween.js'\n\nconst clamp = (v, a, b) => (v < a ? a : v > b ? b : v)\n\n/**\n * TimeScale — maps bar index <-> x pixels.\n *\n * Two smoothed values define the view:\n * spacing : px per bar (zoom)\n * right : float bar index sitting at the right edge of the plot\n *\n * Both are Smoothed, so a wheel zoom eases instead of stepping, and new bars\n * glide in rather than jumping. Dragging uses jump() so the chart stays glued\n * to the pointer — easing a drag feels like lag, not smoothness.\n */\nexport class TimeScale {\n constructor({ spacing = 9, minSpacing = 0.8, maxSpacing = 160, rightOffset = 12 } = {}) {\n this.minSpacing = minSpacing\n this.maxSpacing = maxSpacing\n this.rightOffset = rightOffset\n this.width = 0\n this.barCount = 0\n this.follow = true\n this.timeframeMs = 60000\n this._spacing = new Smoothed(spacing, 65)\n this._right = new Smoothed(rightOffset, 65)\n this._initial = spacing\n }\n\n get spacing() { return this._spacing.value }\n get right() { return this._right.value }\n\n resize(w) { this.width = Math.max(1, w) }\n\n setBarCount(n) {\n const grew = n > this.barCount\n this.barCount = n\n if (this.follow) {\n // target the new last bar; Smoothed turns this into a glide\n const t = n - 1 + this.rightOffset\n if (grew) this._right.set(t)\n else this._right.jump(t)\n }\n }\n\n x(i) { return this.width - (this._right.value - i) * this._spacing.value }\n\n /** Centre-x of bar i (bars are drawn centred on their slot). */\n index(x) { return this._right.value - (this.width - x) / this._spacing.value }\n\n barWidth() {\n const s = this._spacing.value\n // leave a gap between candles, but never thinner than a hairline\n return Math.max(1, Math.floor(s * 0.72))\n }\n\n visibleRange() {\n const first = Math.floor(this.index(0)) - 1\n const last = Math.ceil(this.index(this.width)) + 1\n return {\n from: clamp(first, 0, Math.max(0, this.barCount - 1)),\n to: clamp(last, 0, Math.max(0, this.barCount - 1)),\n }\n }\n\n _clampRight(v) {\n const max = this.barCount - 1 + this.rightOffset + this.width / this._spacing.target\n const min = Math.min(4, this.barCount - 1 + this.rightOffset)\n return clamp(v, min, max)\n }\n\n /** Immediate pan, in pixels. Positive dx drags content right (back in time). */\n panBy(dxPx) {\n if (!dxPx) return false\n const next = this._clampRight(this._right.value - dxPx / this._spacing.value)\n this._right.jump(next)\n this.follow = false\n return true\n }\n\n /** Zoom by `factor`, keeping the bar under `x` pinned. */\n zoomAt(x, factor) {\n const s0 = this._spacing.target\n const s1 = clamp(s0 * factor, this.minSpacing, this.maxSpacing)\n if (Math.abs(s1 - s0) < 1e-9) return false\n\n // While following realtime, pin the right edge instead of the cursor so the\n // latest candle stays put — that is what traders expect.\n const anchorX = this.follow ? this.width : x\n const r0 = this._right.target\n const idx = r0 - (this.width - anchorX) / s0\n const r1 = idx + (this.width - anchorX) / s1\n\n this._spacing.set(s1)\n this._right.set(this._clampRight(r1))\n return true\n }\n\n snapToRealtime() {\n this.follow = true\n this._right.set(this.barCount - 1 + this.rightOffset)\n }\n\n reset() {\n this._spacing.set(this._initial)\n this.snapToRealtime()\n }\n\n /** True while the view is still easing. */\n tick(dt) {\n const a = this._spacing.tick(dt)\n const b = this._right.tick(dt)\n return a || b\n }\n\n get settled() { return this._spacing.settled && this._right.settled }\n}\n","import { Smoothed } from '../motion/Tween.js'\n\nconst clamp = (v, a, b) => (v < a ? a : v > b ? b : v)\n\n/**\n * PriceScale — maps price <-> y pixels, with animated autoscale.\n *\n * Bounds live in *transformed* space (identity for linear, log for log), so\n * switching modes is a one-line change and the easing still behaves.\n * The whole point of smoothing here: when a spike arrives the range glides to\n * its new bounds instead of the chart snapping and losing the reader.\n */\nexport class PriceScale {\n constructor({ mode = 'linear', tau = 120, marginTop = 0.12, marginBottom = 0.12 } = {}) {\n this.mode = mode\n this.marginTop = marginTop\n this.marginBottom = marginBottom\n this.auto = true\n this.top = 0\n this.height = 1\n this._lo = new Smoothed(0, tau)\n this._hi = new Smoothed(1, tau)\n this._primed = false\n }\n\n _fwd(v) { return this.mode === 'log' ? Math.log(Math.max(v, 1e-9)) : v }\n _inv(v) { return this.mode === 'log' ? Math.exp(v) : v }\n\n setMode(mode) {\n if (mode === this.mode) return\n const lo = this._inv(this._lo.value)\n const hi = this._inv(this._hi.value)\n this.mode = mode\n this._lo.jump(this._fwd(lo))\n this._hi.jump(this._fwd(hi))\n }\n\n layout(top, height) {\n this.top = top\n this.height = Math.max(1, height)\n }\n\n get lo() { return this._inv(this._lo.value) }\n get hi() { return this._inv(this._hi.value) }\n\n y(price) {\n const a = this._lo.value\n const b = this._hi.value\n const t = (this._fwd(price) - a) / (b - a || 1)\n return this.top + this.height * (1 - t)\n }\n\n price(y) {\n const a = this._lo.value\n const b = this._hi.value\n const t = 1 - (y - this.top) / this.height\n return this._inv(a + t * (b - a))\n }\n\n /** Fit visible bars. `extra` lets the forming candle influence the range. */\n fit(bars, from, to, extra) {\n if (!this.auto || !bars.length) return\n let min = Infinity\n let max = -Infinity\n for (let i = from; i <= to; i++) {\n const b = bars[i]\n if (!b) continue\n if (b.low < min) min = b.low\n if (b.high > max) max = b.high\n }\n if (extra) {\n if (extra.low < min) min = extra.low\n if (extra.high > max) max = extra.high\n }\n if (!isFinite(min) || !isFinite(max)) return\n\n let a = this._fwd(min)\n let b = this._fwd(max)\n let pad = (b - a) * this.marginTop\n if (!(pad > 0)) pad = Math.abs(b) * 0.01 || 1\n a -= pad\n b += (b - a) * 0 + pad\n\n this._lo.set(a)\n this._hi.set(b)\n if (!this._primed) {\n this._lo.jump(a)\n this._hi.jump(b)\n this._primed = true\n }\n }\n\n /** Manual axis-drag scaling around the vertical centre. */\n scaleBy(factor) {\n this.auto = false\n const a = this._lo.target\n const b = this._hi.target\n const mid = (a + b) / 2\n const half = ((b - a) / 2) * clamp(factor, 0.2, 5)\n this._lo.set(mid - half)\n this._hi.set(mid + half)\n }\n\n resetAuto() {\n this.auto = true\n }\n\n tick(dt) {\n const a = this._lo.tick(dt)\n const b = this._hi.tick(dt)\n return a || b\n }\n}\n","export const defaultTheme = {\n background: '#0b0e14',\n grid: 'rgba(255,255,255,0.045)',\n axisLine: 'rgba(255,255,255,0.10)',\n text: '#8b93a7',\n textStrong: '#e6e9ef',\n up: '#26a69a',\n down: '#ef5350',\n upFill: '#26a69a',\n downFill: '#ef5350',\n wickUp: '#26a69a',\n wickDown: '#ef5350',\n volumeUp: 'rgba(38,166,154,0.30)',\n volumeDown: 'rgba(239,83,80,0.30)',\n crosshair: 'rgba(255,255,255,0.32)',\n labelBg: '#2a3040',\n labelText: '#e6e9ef',\n tagText: '#06080d',\n font: '11px ui-sans-serif, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n priceAxisWidth: 68,\n timeAxisHeight: 26,\n}\n\nexport const lightTheme = {\n ...defaultTheme,\n background: '#ffffff',\n grid: 'rgba(0,0,0,0.06)',\n axisLine: 'rgba(0,0,0,0.14)',\n text: '#6b7280',\n textStrong: '#111827',\n labelBg: '#374151',\n volumeUp: 'rgba(38,166,154,0.25)',\n volumeDown: 'rgba(239,83,80,0.25)',\n crosshair: 'rgba(0,0,0,0.35)',\n tagText: '#ffffff',\n}\n","import { Smoothed, Tween } from './Tween.js'\n\n/**\n * LiveCandle — makes the forming (rightmost) candle *flow* instead of snapping.\n *\n * A raw feed tick replaces close/high/low instantly, which reads as a jitter.\n * Here every component eases toward the incoming value, and a brand new candle\n * plays a short grow-from-centre animation as it scrolls in.\n */\nexport class LiveCandle {\n constructor(tau = 55) {\n this.enabled = true\n this.o = new Smoothed(0, tau)\n this.h = new Smoothed(0, tau)\n this.l = new Smoothed(0, tau)\n this.c = new Smoothed(0, tau)\n this.vol = new Smoothed(0, tau * 2)\n this.spawn = new Tween(240)\n this._has = false\n this._time = null\n }\n\n setTarget(bar) {\n if (!bar) {\n this._has = false\n return\n }\n if (!this._has || bar.time !== this._time) {\n // New candle: start collapsed at its open, then animate outward.\n this.o.jump(bar.open)\n this.h.jump(bar.open)\n this.l.jump(bar.open)\n this.c.jump(bar.open)\n this.vol.jump(0)\n this.spawn.restart()\n this._time = bar.time\n this._has = true\n }\n this.o.set(bar.open)\n this.h.set(bar.high)\n this.l.set(bar.low)\n this.c.set(bar.close)\n this.vol.set(bar.volume || 0)\n }\n\n reset() {\n this._has = false\n this._time = null\n }\n\n /** @returns {boolean} true while animating */\n tick(dt) {\n if (!this._has) return false\n let moving = false\n if (this.o.tick(dt)) moving = true\n if (this.h.tick(dt)) moving = true\n if (this.l.tick(dt)) moving = true\n if (this.c.tick(dt)) moving = true\n if (this.vol.tick(dt)) moving = true\n if (this.spawn.tick(dt)) moving = true\n return moving\n }\n\n /** Interpolated view of `bar`, or `bar` itself when disabled. */\n read(bar) {\n if (!this._has || !this.enabled || bar.time !== this._time) return bar\n const o = this.o.value\n const c = this.c.value\n return {\n time: bar.time,\n open: o,\n close: c,\n // keep the wick consistent while values chase each other\n high: Math.max(this.h.value, o, c),\n low: Math.min(this.l.value, o, c),\n volume: this.vol.value,\n _spawn: this.spawn.progress,\n }\n }\n}\n","/**\n * Inertia — momentum panning with friction decay.\n * sample() while dragging, release() on pointer up, then tick() each frame\n * until it returns 0.\n */\nexport class Inertia {\n constructor({ friction = 0.92, min = 0.015 } = {}) {\n this.friction = friction\n this.min = min\n this.v = 0 // px per ms\n this.active = false\n }\n\n sample(dx, dt) {\n if (dt <= 0) return\n const instant = dx / dt\n // low-pass so one jittery frame doesn't define the throw\n this.v = this.v * 0.6 + instant * 0.4\n this.active = false\n }\n\n release() {\n if (Math.abs(this.v) > this.min) this.active = true\n }\n\n stop() {\n this.v = 0\n this.active = false\n }\n\n /** @returns {number} px to pan this frame (0 when idle) */\n tick(dt) {\n if (!this.active) return 0\n const dx = this.v * dt\n this.v *= Math.pow(this.friction, dt / 16.6667)\n if (Math.abs(this.v) < this.min) this.stop()\n return dx\n }\n}\n","/** \"Nice\" step size (1/2/5 x 10^n) covering `span` in about `count` steps. */\nexport function niceStep(span, count) {\n const raw = span / Math.max(1, count)\n if (!(raw > 0) || !isFinite(raw)) return 1\n const mag = Math.pow(10, Math.floor(Math.log10(raw)))\n const n = raw / mag\n const s = n < 1.5 ? 1 : n < 3 ? 2 : n < 7 ? 5 : 10\n return s * mag\n}\n\nexport function priceTicks(lo, hi, count) {\n const step = niceStep(hi - lo, count)\n const ticks = []\n const start = Math.ceil(lo / step) * step\n for (let v = start; v <= hi + step * 1e-9; v += step) ticks.push(v)\n return { ticks, step }\n}\n\nexport function decimalsFor(step) {\n if (!isFinite(step) || step <= 0) return 2\n if (step >= 100) return 0\n if (step >= 1) return 2\n return Math.min(8, Math.ceil(-Math.log10(step)) + 1)\n}\n\n/** Bar-index step that keeps time labels at least `minPx` apart. */\nexport function niceBarStep(minBars) {\n const opts = [1, 2, 5, 10, 15, 20, 30, 60, 120, 240, 480, 960, 1920, 3840, 7680]\n for (const o of opts) if (o >= minBars) return o\n return Math.ceil(minBars / 1000) * 1000\n}\n\nconst p2 = (n) => String(n).padStart(2, '0')\n\nexport function fmtAxisTime(ms, tfMs) {\n const d = new Date(ms)\n if (tfMs >= 864e5) return `${d.getDate()} ${d.toLocaleString('en', { month: 'short' })}`\n if (d.getHours() === 0 && d.getMinutes() === 0) {\n return `${d.getDate()} ${d.toLocaleString('en', { month: 'short' })}`\n }\n return `${p2(d.getHours())}:${p2(d.getMinutes())}`\n}\n\nexport function fmtDateTime(ms) {\n const d = new Date(ms)\n return `${d.getFullYear()}-${p2(d.getMonth() + 1)}-${p2(d.getDate())} ${p2(d.getHours())}:${p2(d.getMinutes())}`\n}\n\nexport function fmtVolume(v) {\n if (!isFinite(v)) return '—'\n if (v >= 1e9) return (v / 1e9).toFixed(2) + 'B'\n if (v >= 1e6) return (v / 1e6).toFixed(2) + 'M'\n if (v >= 1e3) return (v / 1e3).toFixed(1) + 'K'\n return String(Math.round(v))\n}\n","import { priceTicks, decimalsFor, niceBarStep, fmtAxisTime } from '../core/formatters.js'\n\n/** Background, grid, and both axes. Repaints only when the view changes. */\nexport function drawGrid(ctx, s) {\n const { theme, ts, ps, plot, bars, width, height } = s\n\n ctx.clearRect(0, 0, width, height)\n ctx.fillStyle = theme.background\n ctx.fillRect(0, 0, width, height)\n\n ctx.font = theme.font\n ctx.textBaseline = 'middle'\n\n // ---- price grid + labels -------------------------------------------------\n const rows = Math.max(2, Math.floor(plot.h / 58))\n const { ticks, step } = priceTicks(ps.lo, ps.hi, rows)\n const dec = decimalsFor(step)\n\n ctx.strokeStyle = theme.grid\n ctx.lineWidth = 1\n ctx.beginPath()\n for (const v of ticks) {\n const y = Math.round(ps.y(v)) + 0.5\n if (y < plot.y || y > plot.y + plot.h) continue\n ctx.moveTo(0, y)\n ctx.lineTo(plot.w, y)\n }\n ctx.stroke()\n\n ctx.fillStyle = theme.text\n ctx.textAlign = 'left'\n for (const v of ticks) {\n const y = Math.round(ps.y(v))\n if (y < plot.y + 6 || y > plot.y + plot.h - 6) continue\n ctx.fillText(v.toFixed(dec), plot.w + 8, y)\n }\n\n // ---- time grid + labels --------------------------------------------------\n if (bars.length) {\n const minBars = Math.ceil(74 / Math.max(0.0001, ts.spacing))\n const stepBars = niceBarStep(minBars)\n const { from, to } = ts.visibleRange()\n const first = Math.ceil(from / stepBars) * stepBars\n\n ctx.strokeStyle = theme.grid\n ctx.beginPath()\n for (let i = first; i <= to; i += stepBars) {\n const x = Math.round(ts.x(i)) + 0.5\n if (x < 0 || x > plot.w) continue\n ctx.moveTo(x, 0)\n ctx.lineTo(x, plot.h)\n }\n ctx.stroke()\n\n ctx.fillStyle = theme.text\n ctx.textAlign = 'center'\n const ty = plot.h + theme.timeAxisHeight / 2\n for (let i = first; i <= to; i += stepBars) {\n const bar = bars[i]\n if (!bar) continue\n const x = Math.round(ts.x(i))\n if (x < 28 || x > plot.w - 28) continue\n ctx.fillText(fmtAxisTime(bar.time, ts.timeframeMs), x, ty)\n }\n }\n\n // ---- axis separators -----------------------------------------------------\n ctx.strokeStyle = theme.axisLine\n ctx.beginPath()\n ctx.moveTo(plot.w + 0.5, 0)\n ctx.lineTo(plot.w + 0.5, plot.h)\n ctx.moveTo(0, plot.h + 0.5)\n ctx.lineTo(width, plot.h + 0.5)\n ctx.stroke()\n}\n","import { decimalsFor, priceTicks } from '../core/formatters.js'\n\n/**\n * Candles + volume. Everything here is culled to the visible index range —\n * 500k bars loaded still costs only the ~200 on screen.\n */\nexport function drawCandles(ctx, s) {\n const { theme, ts, ps, plot, bars, width, height, live, volumeRatio } = s\n\n ctx.clearRect(0, 0, width, height)\n if (!bars.length) return\n\n const { from, to } = ts.visibleRange()\n const bw = ts.barWidth()\n const half = bw / 2\n const thin = bw <= 2\n\n // ---- volume strip --------------------------------------------------------\n const volH = plot.h * volumeRatio\n const volTop = plot.y + plot.h - volH\n let vmax = 0\n for (let i = from; i <= to; i++) {\n const b = bars[i]\n if (b && b.volume > vmax) vmax = b.volume\n }\n if (vmax > 0) {\n for (let i = from; i <= to; i++) {\n let b = bars[i]\n if (!b) continue\n if (live && i === bars.length - 1) b = live\n const x = ts.x(i)\n if (x < -bw || x > plot.w + bw) continue\n const h = (b.volume / vmax) * volH * 0.9\n ctx.fillStyle = b.close >= b.open ? theme.volumeUp : theme.volumeDown\n ctx.fillRect(Math.round(x - half), volTop + (volH - h), Math.max(1, bw), h)\n }\n }\n\n // ---- candles -------------------------------------------------------------\n for (let i = from; i <= to; i++) {\n let b = bars[i]\n if (!b) continue\n const isLast = i === bars.length - 1\n if (live && isLast) b = live\n\n const x = ts.x(i)\n if (x < -bw || x > plot.w + bw) continue\n\n const up = b.close >= b.open\n const color = up ? theme.up : theme.down\n const yO = ps.y(b.open)\n const yC = ps.y(b.close)\n const yH = ps.y(b.high)\n const yL = ps.y(b.low)\n\n // grow-from-centre on a freshly opened candle\n let scale = 1\n if (live && isLast && typeof b._spawn === 'number') scale = 0.35 + 0.65 * b._spawn\n\n const cx = Math.round(x) + (bw % 2 ? 0.5 : 0)\n\n // wick\n ctx.strokeStyle = up ? theme.wickUp : theme.wickDown\n ctx.lineWidth = Math.max(1, Math.min(2, bw * 0.16))\n ctx.beginPath()\n ctx.moveTo(cx, yH)\n ctx.lineTo(cx, yL)\n ctx.stroke()\n\n if (thin) continue\n\n // body\n const top = Math.min(yO, yC)\n const bodyH = Math.max(1, Math.abs(yC - yO))\n const w = Math.max(1, bw * scale)\n ctx.fillStyle = color\n ctx.fillRect(Math.round(x - w / 2), Math.round(top), Math.round(w), Math.round(bodyH))\n }\n\n // ---- last price line -----------------------------------------------------\n const lastBar = live || bars[bars.length - 1]\n if (lastBar) {\n const y = Math.round(ps.y(lastBar.close)) + 0.5\n if (y > plot.y && y < plot.y + plot.h) {\n const up = lastBar.close >= lastBar.open\n ctx.save()\n ctx.setLineDash([3, 3])\n ctx.strokeStyle = up ? theme.up : theme.down\n ctx.lineWidth = 1\n ctx.globalAlpha = 0.7\n ctx.beginPath()\n ctx.moveTo(0, y)\n ctx.lineTo(plot.w, y)\n ctx.stroke()\n ctx.restore()\n\n const { step } = priceTicks(ps.lo, ps.hi, Math.max(2, Math.floor(plot.h / 58)))\n const label = lastBar.close.toFixed(decimalsFor(step))\n ctx.font = theme.font\n ctx.textBaseline = 'middle'\n ctx.textAlign = 'left'\n const tw = ctx.measureText(label).width\n ctx.fillStyle = up ? theme.up : theme.down\n ctx.fillRect(plot.w + 1, y - 9, tw + 14, 18)\n ctx.fillStyle = theme.tagText\n ctx.fillText(label, plot.w + 8, y)\n }\n }\n}\n","import { decimalsFor, priceTicks, fmtDateTime } from '../core/formatters.js'\n\n/**\n * Crosshair lives alone on the top canvas: moving the pointer repaints only\n * these few pixels, never the candles underneath.\n */\nexport function drawCrosshair(ctx, s) {\n const { theme, ts, ps, plot, bars, width, height, cursor, magnet } = s\n\n ctx.clearRect(0, 0, width, height)\n if (!cursor || !bars.length) return\n if (cursor.x < 0 || cursor.x > plot.w || cursor.y < 0 || cursor.y > plot.h) return\n\n const i = Math.round(ts.index(cursor.x))\n const bar = bars[i]\n\n let x = cursor.x\n let y = cursor.y\n if (bar) {\n x = ts.x(i) // snap to the bar slot\n if (magnet) {\n // magnet to the nearest OHLC value\n const cands = [bar.open, bar.high, bar.low, bar.close]\n let best = null\n let bestD = Infinity\n for (const p of cands) {\n const py = ps.y(p)\n const d = Math.abs(py - cursor.y)\n if (d < bestD) { bestD = d; best = py }\n }\n if (bestD < 22) y = best\n }\n }\n\n ctx.save()\n ctx.setLineDash([4, 4])\n ctx.strokeStyle = theme.crosshair\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(Math.round(x) + 0.5, 0)\n ctx.lineTo(Math.round(x) + 0.5, plot.h)\n ctx.moveTo(0, Math.round(y) + 0.5)\n ctx.lineTo(plot.w, Math.round(y) + 0.5)\n ctx.stroke()\n ctx.restore()\n\n ctx.font = theme.font\n ctx.textBaseline = 'middle'\n\n // price tag\n const { step } = priceTicks(ps.lo, ps.hi, Math.max(2, Math.floor(plot.h / 58)))\n const priceLabel = ps.price(y).toFixed(decimalsFor(step))\n ctx.textAlign = 'left'\n const pw = ctx.measureText(priceLabel).width\n ctx.fillStyle = theme.labelBg\n ctx.fillRect(plot.w + 1, y - 9, pw + 14, 18)\n ctx.fillStyle = theme.labelText\n ctx.fillText(priceLabel, plot.w + 8, y)\n\n // time tag\n if (bar) {\n const t = fmtDateTime(bar.time)\n ctx.textAlign = 'center'\n const tw = ctx.measureText(t).width\n const bx = Math.min(Math.max(x, tw / 2 + 6), plot.w - tw / 2 - 6)\n ctx.fillStyle = theme.labelBg\n ctx.fillRect(bx - tw / 2 - 7, plot.h + 3, tw + 14, 18)\n ctx.fillStyle = theme.labelText\n ctx.fillText(t, bx, plot.h + 12)\n }\n}\n\n","import { Layers } from './Layers.js'\nimport { Loop } from './Loop.js'\nimport { TimeScale } from './TimeScale.js'\nimport { PriceScale } from './PriceScale.js'\nimport { defaultTheme } from './palette.js'\nimport { LiveCandle } from '../motion/LiveCandle.js'\nimport { Inertia } from '../motion/Inertia.js'\nimport { drawGrid } from '../render/grid.js'\nimport { drawCandles } from '../render/candles.js'\nimport { drawCrosshair } from '../render/crosshair.js'\n\n/**\n * Chart — the orchestrator. Owns the bar store, the scales, the input\n * handling and the frame composition. Framework-free by design: this file\n * touches nothing but DOM and Canvas, which is what lets the same core ship\n * as a React component, a Web Component, or a plain script tag.\n */\nexport class Chart {\n constructor(container, options = {}) {\n if (!container) throw new Error('Chart: container element is required')\n\n this.container = container\n this.theme = { ...defaultTheme, ...(options.theme || {}) }\n this.options = {\n volumeRatio: 0.18,\n magnet: true,\n animate: true,\n ...options,\n }\n\n this.bars = []\n this.feed = null\n this._unsub = null\n this._loadingHistory = false\n this._exhausted = false\n this._listeners = { crosshair: new Set(), visibleRange: new Set() }\n\n this.layers = new Layers(container, ['base', 'main', 'overlay'])\n this.ts = new TimeScale(options.timeScale)\n this.ps = new PriceScale(options.priceScale)\n this.live = new LiveCandle()\n this.live.enabled = this.options.animate !== false\n this.inertia = new Inertia()\n\n this.cursor = null\n this.plot = { x: 0, y: 0, w: 1, h: 1 }\n\n this.loop = new Loop((dirty, dt) => this._frame(dirty, dt))\n this.layers.onResize = () => {\n this._layout()\n this.loop.invalidate('all')\n }\n\n this._layout()\n this._bindEvents()\n this.loop.start()\n }\n\n // ---------------------------------------------------------------- layout --\n _layout() {\n const { width, height } = this.layers\n const w = Math.max(1, width - this.theme.priceAxisWidth)\n const h = Math.max(1, height - this.theme.timeAxisHeight)\n this.plot = { x: 0, y: 0, w, h }\n this.ts.resize(w)\n this.ps.layout(0, h)\n }\n\n // ------------------------------------------------------------------ data --\n setData(bars) {\n this.bars = Array.isArray(bars) ? bars.slice() : []\n this._exhausted = false\n if (this.bars.length > 1) {\n this.ts.timeframeMs = this.bars[1].time - this.bars[0].time\n }\n this.ts.setBarCount(this.bars.length)\n this.ts.snapToRealtime()\n this.live.reset()\n this.ps._primed = false\n this.loop.invalidate('all')\n }\n\n /** Merge a tick into the forming candle (animated). */\n update(bar) {\n if (!bar) return\n const n = this.bars.length\n if (n && this.bars[n - 1].time === bar.time) {\n this.bars[n - 1] = bar\n } else {\n this.append(bar)\n return\n }\n this.live.setTarget(bar)\n this.loop.invalidate('main')\n }\n\n /** Open a new candle; the previous one is now closed. */\n append(bar) {\n if (!bar) return\n const n = this.bars.length\n if (n && bar.time <= this.bars[n - 1].time) {\n this.bars[n - 1] = bar\n } else {\n this.bars.push(bar)\n this.ts.setBarCount(this.bars.length)\n }\n this.live.setTarget(bar)\n this.loop.invalidate('main')\n }\n\n async setFeed(feed) {\n this.detachFeed()\n this.feed = feed\n if (!feed) return\n this.ts.timeframeMs = feed.timeframe || this.ts.timeframeMs\n const bars = await feed.getBars({\n symbol: feed.symbol,\n timeframe: feed.timeframe,\n to: null,\n limit: this.options.initialBars || 1500,\n })\n this.setData(bars)\n if (typeof feed.prime === 'function') feed.prime(bars[bars.length - 1])\n this._unsub = feed.subscribe((msg) => {\n if (!msg || !msg.bar) return\n if (msg.type === 'append') this.append(msg.bar)\n else this.update(msg.bar)\n })\n }\n\n detachFeed() {\n if (this._unsub) this._unsub()\n this._unsub = null\n this.feed = null\n }\n\n async _maybeLoadHistory() {\n if (this._loadingHistory || this._exhausted || !this.feed) return\n const { from } = this.ts.visibleRange()\n if (from > 80 || !this.bars.length) return\n\n this._loadingHistory = true\n try {\n const oldest = this.bars[0].time\n const older = await this.feed.getBars({\n symbol: this.feed.symbol,\n timeframe: this.feed.timeframe,\n to: oldest,\n limit: 1000,\n })\n if (!older || !older.length) {\n this._exhausted = true\n } else {\n const added = older.filter((b) => b.time < oldest)\n if (!added.length) {\n this._exhausted = true\n } else {\n this.bars = added.concat(this.bars)\n // keep the view pinned to the same bars: indices all shifted right\n const wasFollowing = this.ts.follow\n this.ts.barCount = this.bars.length\n this.ts._right.jump(this.ts._right.value + added.length)\n this.ts._right.set(this.ts._right.target + added.length)\n this.ts.follow = wasFollowing\n this.loop.invalidate('all')\n }\n }\n } catch (e) {\n console.error('[Emberwick] history load failed', e)\n this._exhausted = true\n } finally {\n this._loadingHistory = false\n }\n }\n\n // ---------------------------------------------------------------- events --\n _bindEvents() {\n const el = this.container\n el.style.touchAction = 'none'\n el.style.cursor = 'crosshair'\n\n let dragging = false\n let mode = null\n let lastX = 0\n let lastY = 0\n let lastT = 0\n let moved = false\n const pointers = new Map()\n let pinchDist = 0\n\n const localPos = (e) => {\n const r = el.getBoundingClientRect()\n return { x: e.clientX - r.left, y: e.clientY - r.top }\n }\n\n this._onDown = (e) => {\n pointers.set(e.pointerId, localPos(e))\n if (pointers.size === 2) {\n const [a, b] = [...pointers.values()]\n pinchDist = Math.hypot(a.x - b.x, a.y - b.y)\n dragging = false\n return\n }\n const p = localPos(e)\n dragging = true\n moved = false\n mode = p.x > this.plot.w ? 'price' : p.y > this.plot.h ? 'time' : 'pan'\n lastX = p.x\n lastY = p.y\n lastT = performance.now()\n this.inertia.stop()\n el.setPointerCapture(e.pointerId)\n }\n\n this._onMove = (e) => {\n const p = localPos(e)\n if (pointers.has(e.pointerId)) pointers.set(e.pointerId, p)\n\n if (pointers.size === 2) {\n const [a, b] = [...pointers.values()]\n const d = Math.hypot(a.x - b.x, a.y - b.y)\n if (pinchDist > 0 && d > 0) {\n const mid = (a.x + b.x) / 2\n this.ts.zoomAt(mid, d / pinchDist)\n this.loop.invalidate('all')\n }\n pinchDist = d\n return\n }\n\n this.cursor = p\n this._emitCrosshair(p)\n this.loop.invalidate('overlay')\n\n if (!dragging) return\n const now = performance.now()\n const dt = now - lastT\n const dx = p.x - lastX\n const dy = p.y - lastY\n if (Math.abs(dx) > 1 || Math.abs(dy) > 1) moved = true\n\n if (mode === 'pan') {\n this.ts.panBy(dx)\n this.inertia.sample(dx, dt)\n this.loop.invalidate('all')\n this._maybeLoadHistory()\n } else if (mode === 'price') {\n this.ps.scaleBy(1 + dy / 220)\n this.loop.invalidate('all')\n } else if (mode === 'time') {\n this.ts.zoomAt(this.plot.w, 1 - dx / 260)\n this.loop.invalidate('all')\n }\n\n lastX = p.x\n lastY = p.y\n lastT = now\n }\n\n this._onUp = (e) => {\n pointers.delete(e.pointerId)\n if (pointers.size < 2) pinchDist = 0\n if (dragging && mode === 'pan' && moved) {\n this.inertia.release()\n this.loop.invalidate('all')\n }\n dragging = false\n mode = null\n try { el.releasePointerCapture(e.pointerId) } catch (_) {}\n }\n\n this._onLeave = () => {\n this.cursor = null\n this._emitCrosshair(null)\n this.loop.invalidate('overlay')\n }\n\n this._onWheel = (e) => {\n e.preventDefault()\n const r = el.getBoundingClientRect()\n const x = e.clientX - r.left\n const factor = Math.pow(0.999, e.deltaY)\n this.ts.zoomAt(x, factor)\n this.loop.invalidate('all')\n this._maybeLoadHistory()\n }\n\n this._onDbl = () => {\n this.ts.reset()\n this.ps.resetAuto()\n this.loop.invalidate('all')\n }\n\n this._onKey = (e) => {\n const step = e.shiftKey ? 120 : 40\n if (e.key === 'ArrowLeft') { this.ts.panBy(step); this.loop.invalidate('all'); this._maybeLoadHistory() }\n else if (e.key === 'ArrowRight') { this.ts.panBy(-step); this.loop.invalidate('all') }\n else if (e.key === '+' || e.key === '=') { this.ts.zoomAt(this.plot.w / 2, 1.2); this.loop.invalidate('all') }\n else if (e.key === '-' || e.key === '_') { this.ts.zoomAt(this.plot.w / 2, 0.8); this.loop.invalidate('all') }\n else return\n e.preventDefault()\n }\n\n el.addEventListener('pointerdown', this._onDown)\n el.addEventListener('pointermove', this._onMove)\n el.addEventListener('pointerup', this._onUp)\n el.addEventListener('pointercancel', this._onUp)\n el.addEventListener('pointerleave', this._onLeave)\n el.addEventListener('wheel', this._onWheel, { passive: false })\n el.addEventListener('dblclick', this._onDbl)\n el.addEventListener('keydown', this._onKey)\n if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0')\n }\n\n _emitCrosshair(p) {\n if (!this._listeners.crosshair.size) return\n let payload = null\n if (p && this.bars.length && p.x <= this.plot.w && p.y <= this.plot.h) {\n const i = Math.round(this.ts.index(p.x))\n const bar = this.bars[i]\n if (bar) payload = { index: i, bar, price: this.ps.price(p.y) }\n }\n for (const fn of this._listeners.crosshair) fn(payload)\n }\n\n subscribe(event, fn) {\n const set = this._listeners[event]\n if (!set) throw new Error(`Chart: unknown event \"${event}\"`)\n set.add(fn)\n return () => set.delete(fn)\n }\n\n // ----------------------------------------------------------------- frame --\n _frame(dirty, dt) {\n let animating = false\n\n if (this.ts.tick(dt)) animating = true\n\n const dx = this.inertia.tick(dt)\n if (dx) {\n this.ts.panBy(dx)\n animating = true\n this._maybeLoadHistory()\n }\n\n if (this.live.tick(dt)) animating = true\n\n const { from, to } = this.ts.visibleRange()\n const lastIdx = this.bars.length - 1\n const liveBar = this.bars.length ? this.live.read(this.bars[lastIdx]) : null\n const liveVisible = liveBar && to >= lastIdx ? liveBar : null\n\n this.ps.fit(this.bars, from, to, liveVisible)\n if (this.ps.tick(dt)) animating = true\n\n const redrawAll = animating || dirty.has('all') || dirty.has('base') || dirty.has('main')\n const state = {\n theme: this.theme,\n ts: this.ts,\n ps: this.ps,\n plot: this.plot,\n bars: this.bars,\n width: this.layers.width,\n height: this.layers.height,\n live: liveVisible,\n volumeRatio: this.options.volumeRatio,\n cursor: this.cursor,\n magnet: this.options.magnet,\n }\n\n if (redrawAll) {\n drawGrid(this.layers.ctx.base, state)\n drawCandles(this.layers.ctx.main, state)\n }\n if (redrawAll || dirty.has('overlay')) {\n drawCrosshair(this.layers.ctx.overlay, state)\n }\n\n return animating\n }\n\n // ------------------------------------------------------------------- api --\n get fps() { return this.loop.fps }\n\n setTheme(theme) {\n this.theme = { ...this.theme, ...theme }\n this._layout()\n this.loop.invalidate('all')\n }\n\n setPriceMode(mode) {\n this.ps.setMode(mode)\n this.loop.invalidate('all')\n }\n\n setAnimate(on) {\n this.live.enabled = !!on\n this.loop.invalidate('all')\n }\n\n setMagnet(on) {\n this.options.magnet = !!on\n this.loop.invalidate('overlay')\n }\n\n snapToRealtime() {\n this.ts.snapToRealtime()\n this.ps.resetAuto()\n this.loop.invalidate('all')\n }\n\n toImage() {\n return this.layers.composite().toDataURL('image/png')\n }\n\n destroy() {\n const el = this.container\n el.removeEventListener('pointerdown', this._onDown)\n el.removeEventListener('pointermove', this._onMove)\n el.removeEventListener('pointerup', this._onUp)\n el.removeEventListener('pointercancel', this._onUp)\n el.removeEventListener('pointerleave', this._onLeave)\n el.removeEventListener('wheel', this._onWheel)\n el.removeEventListener('dblclick', this._onDbl)\n el.removeEventListener('keydown', this._onKey)\n this.detachFeed()\n this.loop.stop()\n this.layers.destroy()\n this._listeners.crosshair.clear()\n this._listeners.visibleRange.clear()\n this.bars = []\n }\n}\n\n","/**\n * DataFeed — THE seam of this library.\n *\n * The chart core never knows where bars come from. Anything that implements\n * this interface can drive it: a REST endpoint, a WebSocket, a Lambda behind\n * API Gateway, a CSV in memory, or the bundled RandomFeed.\n *\n * Bar shape (the only contract that matters):\n * { time: number (ms epoch), open, high, low, close, volume }\n * Bars MUST be ascending by time and de-duplicated by the feed.\n *\n * Implement:\n * getBars({ symbol, timeframe, to, limit }) -> Promise<Bar[]>\n * Historical bars ENDING at `to` (exclusive). Return [] when exhausted;\n * the chart stops asking for more history once it sees an empty page.\n * subscribe(handler) -> unsubscribe fn\n * handler({ type: 'update'|'append', bar }) where\n * 'update' = the forming candle changed (animates)\n * 'append' = a new candle opened (previous one is now closed)\n */\nexport class DataFeed {\n constructor({ symbol = 'DEMO', timeframe = 60000 } = {}) {\n this.symbol = symbol\n this.timeframe = timeframe\n }\n\n // eslint-disable-next-line no-unused-vars\n async getBars({ symbol, timeframe, to, limit }) {\n throw new Error('DataFeed.getBars() not implemented')\n }\n\n // eslint-disable-next-line no-unused-vars\n subscribe(handler) {\n return () => {}\n }\n\n destroy() {}\n}\n\n/** Deterministic PRNG so a given seed always renders the same chart. */\nexport function mulberry32(seed) {\n let a = seed >>> 0\n return function () {\n a = (a + 0x6d2b79f5) | 0\n let t = Math.imul(a ^ (a >>> 15), 1 | a)\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n","import { DataFeed, mulberry32 } from './DataFeed.js'\n\n/**\n * RandomFeed — a plausible synthetic market. One implementation of DataFeed,\n * nothing more: swapping in a real provider is writing another class, with\n * zero changes to the chart core.\n *\n * Generates a GBM-ish random walk with volatility clustering and a volume\n * profile, then drives a live forming candle from sub-bar ticks.\n */\nexport class RandomFeed extends DataFeed {\n constructor({\n symbol = 'EMBR',\n timeframe = 60000,\n seed = 7,\n start = 100,\n volatility = 0.0022,\n drift = 0.00002,\n ticksPerSecond = 8,\n speed = 1,\n } = {}) {\n super({ symbol, timeframe })\n this.seed = seed\n this.start = start\n this.volatility = volatility\n this.drift = drift\n this.ticksPerSecond = ticksPerSecond\n this.speed = speed\n\n this._rnd = mulberry32(seed)\n this._handlers = new Set()\n this._timer = null\n this._forming = null\n this._last = start\n this._vol = volatility\n this._anchorTime = Math.floor(Date.now() / timeframe) * timeframe\n }\n\n _gauss() {\n // Box-Muller\n let u = 0\n let v = 0\n while (u === 0) u = this._rnd()\n while (v === 0) v = this._rnd()\n return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v)\n }\n\n _step(price) {\n // volatility clusters: vol mean-reverts but gets kicked by shocks\n const shock = this._gauss()\n this._vol += (this.volatility - this._vol) * 0.02 + Math.abs(shock) * this.volatility * 0.015\n this._vol = Math.min(this._vol, this.volatility * 6)\n return Math.max(0.01, price * (1 + this.drift + shock * this._vol))\n }\n\n _makeBar(time, open) {\n let c = open\n const n = 14\n let hi = open\n let lo = open\n for (let i = 0; i < n; i++) {\n c = this._step(c)\n if (c > hi) hi = c\n if (c < lo) lo = c\n }\n const range = Math.max(1e-9, hi - lo)\n const volume = Math.round(\n (300 + this._rnd() * 900) * (1 + (range / open) * 260)\n )\n return { time, open, high: hi, low: lo, close: c, volume }\n }\n\n /**\n * Historical bars ending just before `to`. Walks BACKWARDS from a synthetic\n * anchor, so paging further left keeps producing coherent history.\n */\n async getBars({ to, limit = 1500, timeframe = this.timeframe } = {}) {\n const end = to == null ? this._anchorTime : to\n const bars = []\n // generate forward from an earlier point for realistic shape, then slice\n const startTime = end - limit * timeframe\n const gen = mulberry32(this.seed ^ Math.floor(startTime / timeframe))\n const saved = this._rnd\n this._rnd = gen\n\n let price = this.start * (1 + (gen() - 0.5) * 0.04)\n for (let i = 0; i < limit; i++) {\n const t = startTime + i * timeframe\n const bar = this._makeBar(t, price)\n price = bar.close\n bars.push(bar)\n }\n this._rnd = saved\n\n if (to == null) {\n this._last = bars.length ? bars[bars.length - 1].close : this.start\n }\n return bars\n }\n\n subscribe(handler) {\n this._handlers.add(handler)\n if (!this._timer) this._start()\n return () => {\n this._handlers.delete(handler)\n if (!this._handlers.size) this.stop()\n }\n }\n\n _emit(msg) {\n for (const h of this._handlers) h(msg)\n }\n\n _start() {\n const interval = Math.max(16, 1000 / this.ticksPerSecond)\n this._timer = setInterval(() => this._tick(), interval)\n }\n\n /** Seed the live candle from wherever history ended. */\n prime(lastBar) {\n if (lastBar) {\n this._last = lastBar.close\n this._forming = { ...lastBar }\n }\n }\n\n _tick() {\n const tf = this.timeframe / this.speed\n const now = Date.now()\n const slot = Math.floor(now / tf) * tf\n\n if (!this._forming || this._forming.time !== slot) {\n const open = this._last\n this._forming = { time: slot, open, high: open, low: open, close: open, volume: 0 }\n this._emit({ type: 'append', bar: { ...this._forming } })\n return\n }\n\n const next = this._step(this._last)\n this._last = next\n const f = this._forming\n f.close = next\n if (next > f.high) f.high = next\n if (next < f.low) f.low = next\n f.volume += Math.round(20 + this._rnd() * 120)\n this._emit({ type: 'update', bar: { ...f } })\n }\n\n setSpeed(s) { this.speed = s }\n\n setTicksPerSecond(n) {\n this.ticksPerSecond = n\n if (this._timer) { this.stop(); this._start() }\n }\n\n setPaused(paused) {\n if (paused) this.stop()\n else if (!this._timer && this._handlers.size) this._start()\n }\n\n get paused() { return !this._timer }\n\n stop() {\n if (this._timer) clearInterval(this._timer)\n this._timer = null\n }\n\n destroy() {\n this.stop()\n this._handlers.clear()\n }\n}\n","/**\n * Emberwick — public API surface.\n *\n * This file is the future package entry point. Nothing below imports a\n * framework, so the same build drops into React, Vue, Svelte or a script tag.\n *\n * import { createChart, RandomFeed } from './chart/index.js'\n * const chart = createChart(el, { theme: { background: '#000' } })\n * await chart.setFeed(new RandomFeed({ timeframe: 60000 }))\n */\nexport { Chart } from './core/Chart.js'\nexport { TimeScale } from './core/TimeScale.js'\nexport { PriceScale } from './core/PriceScale.js'\nexport { defaultTheme, lightTheme } from './core/palette.js'\nexport { DataFeed, mulberry32 } from './data/DataFeed.js'\nexport { RandomFeed } from './data/RandomFeed.js'\nexport { Smoothed, Tween, easeOutCubic, easeInOutCubic } from './motion/Tween.js'\nexport { Inertia } from './motion/Inertia.js'\nexport { LiveCandle } from './motion/LiveCandle.js'\n\nimport { Chart } from './core/Chart.js'\n\n/** Preferred entry point. */\nexport function createChart(container, options) {\n return new Chart(container, options)\n}\n\nexport const version = '0.1.0'\n\n"],"names":["Layers","container","names","name","i","c","r","w","h","dpr","n","out","Loop","onFrame","layers","l","now","dt","dirty","wantMore","e","easeOutCubic","t","easeInOutCubic","Smoothed","value","tau","target","v","eps","Tween","duration","ease","clamp","a","b","TimeScale","spacing","minSpacing","maxSpacing","rightOffset","grew","x","s","first","last","max","min","dxPx","next","factor","s0","s1","anchorX","r1","PriceScale","mode","marginTop","marginBottom","lo","hi","top","height","price","y","bars","from","to","extra","pad","mid","half","defaultTheme","lightTheme","LiveCandle","bar","moving","o","Inertia","friction","dx","instant","niceStep","span","count","raw","mag","priceTicks","step","ticks","start","decimalsFor","niceBarStep","minBars","opts","p2","fmtAxisTime","ms","tfMs","d","fmtDateTime","drawGrid","ctx","theme","ts","ps","plot","width","rows","dec","stepBars","ty","drawCandles","live","volumeRatio","bw","thin","volH","volTop","vmax","isLast","up","color","yO","yC","yH","yL","scale","cx","bodyH","lastBar","label","tw","drawCrosshair","cursor","magnet","cands","best","bestD","p","py","priceLabel","pw","bx","Chart","options","feed","msg","oldest","older","added","wasFollowing","el","dragging","lastX","lastY","lastT","moved","pointers","pinchDist","localPos","dy","payload","fn","event","set","animating","lastIdx","liveBar","liveVisible","redrawAll","state","on","DataFeed","symbol","timeframe","limit","handler","mulberry32","seed","RandomFeed","volatility","drift","ticksPerSecond","speed","u","shock","time","open","range","volume","end","startTime","gen","saved","interval","tf","slot","f","paused","createChart","version"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Bar, Chart, Feed } from './index.js'
|
|
2
|
+
|
|
3
|
+
export declare class EmberwickChartElement extends HTMLElement {
|
|
4
|
+
readonly chart: Chart | null
|
|
5
|
+
feed: Feed | null
|
|
6
|
+
data: Bar[] | null
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Registers <emberwick-chart>. Safe to call more than once. */
|
|
10
|
+
export declare function register(tagName?: string): void
|
|
11
|
+
|
|
12
|
+
declare global {
|
|
13
|
+
interface HTMLElementTagNameMap {
|
|
14
|
+
'emberwick-chart': EmberwickChartElement
|
|
15
|
+
}
|
|
16
|
+
}
|
package/webcomponent.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createChart, lightTheme, defaultTheme } from "./index.js";
|
|
2
|
+
class EmberwickChartElement extends HTMLElement {
|
|
3
|
+
static get observedAttributes() {
|
|
4
|
+
return ["theme", "animate", "magnet"];
|
|
5
|
+
}
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this._chart = null;
|
|
9
|
+
this._feed = null;
|
|
10
|
+
this._data = null;
|
|
11
|
+
this._host = null;
|
|
12
|
+
this._off = null;
|
|
13
|
+
}
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
if (this._chart) return;
|
|
16
|
+
const root = this.shadowRoot || this.attachShadow({ mode: "open" });
|
|
17
|
+
root.innerHTML = `
|
|
18
|
+
<style>
|
|
19
|
+
:host { display: block; position: relative; width: 100%; height: 100%; min-height: 240px; }
|
|
20
|
+
.host { position: relative; width: 100%; height: 100%; }
|
|
21
|
+
</style>
|
|
22
|
+
<div class="host"></div>
|
|
23
|
+
`;
|
|
24
|
+
this._host = root.querySelector(".host");
|
|
25
|
+
this._chart = createChart(this._host, {
|
|
26
|
+
theme: this.getAttribute("theme") === "light" ? lightTheme : defaultTheme,
|
|
27
|
+
animate: this.getAttribute("animate") !== "false",
|
|
28
|
+
magnet: this.getAttribute("magnet") !== "false"
|
|
29
|
+
});
|
|
30
|
+
this._off = this._chart.subscribe("crosshair", (payload) => {
|
|
31
|
+
this.dispatchEvent(new CustomEvent("crosshair", { detail: payload }));
|
|
32
|
+
});
|
|
33
|
+
if (this._data) this._chart.setData(this._data);
|
|
34
|
+
if (this._feed) this._chart.setFeed(this._feed);
|
|
35
|
+
}
|
|
36
|
+
disconnectedCallback() {
|
|
37
|
+
if (this._off) this._off();
|
|
38
|
+
this._off = null;
|
|
39
|
+
if (this._chart) this._chart.destroy();
|
|
40
|
+
this._chart = null;
|
|
41
|
+
}
|
|
42
|
+
attributeChangedCallback(name, oldValue, value) {
|
|
43
|
+
if (!this._chart || oldValue === value) return;
|
|
44
|
+
if (name === "theme") this._chart.setTheme(value === "light" ? lightTheme : defaultTheme);
|
|
45
|
+
else if (name === "animate") this._chart.setAnimate(value !== "false");
|
|
46
|
+
else if (name === "magnet") this._chart.setMagnet(value !== "false");
|
|
47
|
+
}
|
|
48
|
+
get chart() {
|
|
49
|
+
return this._chart;
|
|
50
|
+
}
|
|
51
|
+
set feed(feed) {
|
|
52
|
+
this._feed = feed;
|
|
53
|
+
if (this._chart) this._chart.setFeed(feed);
|
|
54
|
+
}
|
|
55
|
+
get feed() {
|
|
56
|
+
return this._feed;
|
|
57
|
+
}
|
|
58
|
+
set data(bars) {
|
|
59
|
+
this._data = bars;
|
|
60
|
+
if (this._chart) this._chart.setData(bars);
|
|
61
|
+
}
|
|
62
|
+
get data() {
|
|
63
|
+
return this._data;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function register(tagName = "emberwick-chart") {
|
|
67
|
+
if (typeof customElements === "undefined") return;
|
|
68
|
+
if (!customElements.get(tagName)) customElements.define(tagName, EmberwickChartElement);
|
|
69
|
+
}
|
|
70
|
+
register();
|
|
71
|
+
export {
|
|
72
|
+
EmberwickChartElement,
|
|
73
|
+
register
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=webcomponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webcomponent.js","sources":["../src/adapters/webcomponent/EmberwickChartElement.js","../src/adapters/webcomponent/index.js"],"sourcesContent":["import { createChart, defaultTheme, lightTheme } from '../../chart/index.js'\n\n/**\n * <emberwick-chart> — drop-in custom element, no framework required.\n *\n * <emberwick-chart theme=\"dark\" style=\"height:420px\"></emberwick-chart>\n * document.querySelector('emberwick-chart').feed = myFeed\n *\n * Attributes : theme=\"dark|light\", animate=\"false\", magnet=\"false\"\n * Properties : feed, data, chart (read-only)\n * Events : \"crosshair\" (detail = payload | null)\n *\n * The chart is built in a shadow root so the host page's CSS can't reach in\n * and reposition the stacked canvases.\n */\nexport class EmberwickChartElement extends HTMLElement {\n static get observedAttributes() {\n return ['theme', 'animate', 'magnet']\n }\n\n constructor() {\n super()\n this._chart = null\n this._feed = null\n this._data = null\n this._host = null\n this._off = null\n }\n\n connectedCallback() {\n if (this._chart) return\n\n const root = this.shadowRoot || this.attachShadow({ mode: 'open' })\n root.innerHTML = `\n <style>\n :host { display: block; position: relative; width: 100%; height: 100%; min-height: 240px; }\n .host { position: relative; width: 100%; height: 100%; }\n </style>\n <div class=\"host\"></div>\n `\n this._host = root.querySelector('.host')\n\n this._chart = createChart(this._host, {\n theme: this.getAttribute('theme') === 'light' ? lightTheme : defaultTheme,\n animate: this.getAttribute('animate') !== 'false',\n magnet: this.getAttribute('magnet') !== 'false',\n })\n\n this._off = this._chart.subscribe('crosshair', (payload) => {\n this.dispatchEvent(new CustomEvent('crosshair', { detail: payload }))\n })\n\n // Values assigned before upgrade/connection still apply.\n if (this._data) this._chart.setData(this._data)\n if (this._feed) this._chart.setFeed(this._feed)\n }\n\n disconnectedCallback() {\n if (this._off) this._off()\n this._off = null\n if (this._chart) this._chart.destroy()\n this._chart = null\n }\n\n attributeChangedCallback(name, oldValue, value) {\n if (!this._chart || oldValue === value) return\n if (name === 'theme') this._chart.setTheme(value === 'light' ? lightTheme : defaultTheme)\n else if (name === 'animate') this._chart.setAnimate(value !== 'false')\n else if (name === 'magnet') this._chart.setMagnet(value !== 'false')\n }\n\n get chart() {\n return this._chart\n }\n\n set feed(feed) {\n this._feed = feed\n if (this._chart) this._chart.setFeed(feed)\n }\n\n get feed() {\n return this._feed\n }\n\n set data(bars) {\n this._data = bars\n if (this._chart) this._chart.setData(bars)\n }\n\n get data() {\n return this._data\n }\n}\n\n/** Registers <emberwick-chart>. Safe to call more than once. */\nexport function register(tagName = 'emberwick-chart') {\n if (typeof customElements === 'undefined') return\n if (!customElements.get(tagName)) customElements.define(tagName, EmberwickChartElement)\n}\n","import { register } from './EmberwickChartElement.js'\n\nexport { EmberwickChartElement, register } from './EmberwickChartElement.js'\n\n// Side-effecting entry: importing \"emberwick/webcomponent\" registers the tag.\nregister()\n"],"names":[],"mappings":";AAeO,MAAM,8BAA8B,YAAY;AAAA,EACrD,WAAW,qBAAqB;AAC9B,WAAO,CAAC,SAAS,WAAW,QAAQ;AAAA,EACtC;AAAA,EAEA,cAAc;AACZ,UAAK;AACL,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,QAAQ;AACb,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,oBAAoB;AAClB,QAAI,KAAK,OAAQ;AAEjB,UAAM,OAAO,KAAK,cAAc,KAAK,aAAa,EAAE,MAAM,OAAM,CAAE;AAClE,SAAK,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOjB,SAAK,QAAQ,KAAK,cAAc,OAAO;AAEvC,SAAK,SAAS,YAAY,KAAK,OAAO;AAAA,MACpC,OAAO,KAAK,aAAa,OAAO,MAAM,UAAU,aAAa;AAAA,MAC7D,SAAS,KAAK,aAAa,SAAS,MAAM;AAAA,MAC1C,QAAQ,KAAK,aAAa,QAAQ,MAAM;AAAA,IAC9C,CAAK;AAED,SAAK,OAAO,KAAK,OAAO,UAAU,aAAa,CAAC,YAAY;AAC1D,WAAK,cAAc,IAAI,YAAY,aAAa,EAAE,QAAQ,SAAS,CAAC;AAAA,IACtE,CAAC;AAGD,QAAI,KAAK,MAAO,MAAK,OAAO,QAAQ,KAAK,KAAK;AAC9C,QAAI,KAAK,MAAO,MAAK,OAAO,QAAQ,KAAK,KAAK;AAAA,EAChD;AAAA,EAEA,uBAAuB;AACrB,QAAI,KAAK,KAAM,MAAK,KAAI;AACxB,SAAK,OAAO;AACZ,QAAI,KAAK,OAAQ,MAAK,OAAO,QAAO;AACpC,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,yBAAyB,MAAM,UAAU,OAAO;AAC9C,QAAI,CAAC,KAAK,UAAU,aAAa,MAAO;AACxC,QAAI,SAAS,QAAS,MAAK,OAAO,SAAS,UAAU,UAAU,aAAa,YAAY;AAAA,aAC/E,SAAS,UAAW,MAAK,OAAO,WAAW,UAAU,OAAO;AAAA,aAC5D,SAAS,SAAU,MAAK,OAAO,UAAU,UAAU,OAAO;AAAA,EACrE;AAAA,EAEA,IAAI,QAAQ;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAK,MAAM;AACb,SAAK,QAAQ;AACb,QAAI,KAAK,OAAQ,MAAK,OAAO,QAAQ,IAAI;AAAA,EAC3C;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAK,MAAM;AACb,SAAK,QAAQ;AACb,QAAI,KAAK,OAAQ,MAAK,OAAO,QAAQ,IAAI;AAAA,EAC3C;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AACF;AAGO,SAAS,SAAS,UAAU,mBAAmB;AACpD,MAAI,OAAO,mBAAmB,YAAa;AAC3C,MAAI,CAAC,eAAe,IAAI,OAAO,EAAG,gBAAe,OAAO,SAAS,qBAAqB;AACxF;AC7FA,SAAQ;"}
|