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
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.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":["clamp","b"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "emberwick",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": [
|
|
8
|
+
"./webcomponent.js"
|
|
9
|
+
],
|
|
10
|
+
"main": "./index.js",
|
|
11
|
+
"module": "./index.js",
|
|
12
|
+
"types": "./index.d.ts",
|
|
13
|
+
"unpkg": "./umd/emberwick.umd.js",
|
|
14
|
+
"jsdelivr": "./umd/emberwick.umd.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./index.d.ts",
|
|
18
|
+
"import": "./index.js"
|
|
19
|
+
},
|
|
20
|
+
"./react": {
|
|
21
|
+
"types": "./react.d.ts",
|
|
22
|
+
"import": "./react.js"
|
|
23
|
+
},
|
|
24
|
+
"./webcomponent": {
|
|
25
|
+
"types": "./webcomponent.d.ts",
|
|
26
|
+
"import": "./webcomponent.js"
|
|
27
|
+
},
|
|
28
|
+
"./umd": "./umd/emberwick.umd.js",
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": ">=17"
|
|
33
|
+
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"react": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"candlestick",
|
|
41
|
+
"chart",
|
|
42
|
+
"charting",
|
|
43
|
+
"financial",
|
|
44
|
+
"trading",
|
|
45
|
+
"ohlc",
|
|
46
|
+
"canvas",
|
|
47
|
+
"realtime",
|
|
48
|
+
"tradingview-alternative"
|
|
49
|
+
],
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/react.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
import type { Bar, Chart, ChartOptions, CrosshairPayload, Feed, PriceMode, Theme } from './index.js'
|
|
3
|
+
|
|
4
|
+
export interface EmberwickChartProps
|
|
5
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
6
|
+
/** Static dataset. Ignored while a feed is attached and driving updates. */
|
|
7
|
+
data?: Bar[]
|
|
8
|
+
/** Data source. Passing a new instance re-loads history. */
|
|
9
|
+
feed?: Feed
|
|
10
|
+
/** Options applied at construction time only. */
|
|
11
|
+
options?: ChartOptions
|
|
12
|
+
/** Partial theme; re-applied whenever the object identity changes. */
|
|
13
|
+
theme?: Partial<Theme>
|
|
14
|
+
priceMode?: PriceMode
|
|
15
|
+
animate?: boolean
|
|
16
|
+
magnet?: boolean
|
|
17
|
+
onCrosshair?: (payload: CrosshairPayload | null) => void
|
|
18
|
+
className?: string
|
|
19
|
+
style?: React.CSSProperties
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface EmberwickChartHandle {
|
|
23
|
+
/** The underlying chart instance, or null before mount / after unmount. */
|
|
24
|
+
readonly chart: Chart | null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare const EmberwickChart: React.ForwardRefExoticComponent<
|
|
28
|
+
EmberwickChartProps & React.RefAttributes<EmberwickChartHandle>
|
|
29
|
+
>
|
|
30
|
+
|
|
31
|
+
export default EmberwickChart
|
package/react.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { forwardRef, useRef, useEffect, useImperativeHandle, createElement } from "react";
|
|
2
|
+
import { createChart } from "./index.js";
|
|
3
|
+
const EmberwickChart = forwardRef(function EmberwickChart2(props, ref) {
|
|
4
|
+
const {
|
|
5
|
+
data,
|
|
6
|
+
feed,
|
|
7
|
+
options,
|
|
8
|
+
theme,
|
|
9
|
+
priceMode,
|
|
10
|
+
animate,
|
|
11
|
+
magnet,
|
|
12
|
+
onCrosshair,
|
|
13
|
+
className,
|
|
14
|
+
style,
|
|
15
|
+
...rest
|
|
16
|
+
} = props;
|
|
17
|
+
const hostRef = useRef(null);
|
|
18
|
+
const chartRef = useRef(null);
|
|
19
|
+
const crosshairRef = useRef(onCrosshair);
|
|
20
|
+
crosshairRef.current = onCrosshair;
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const chart = createChart(hostRef.current, {
|
|
23
|
+
...options || {},
|
|
24
|
+
...theme ? { theme } : {},
|
|
25
|
+
...animate !== void 0 ? { animate } : {},
|
|
26
|
+
...magnet !== void 0 ? { magnet } : {}
|
|
27
|
+
});
|
|
28
|
+
chartRef.current = chart;
|
|
29
|
+
const off = chart.subscribe("crosshair", (payload) => {
|
|
30
|
+
const fn = crosshairRef.current;
|
|
31
|
+
if (fn) fn(payload);
|
|
32
|
+
});
|
|
33
|
+
return () => {
|
|
34
|
+
off();
|
|
35
|
+
chart.destroy();
|
|
36
|
+
chartRef.current = null;
|
|
37
|
+
};
|
|
38
|
+
}, []);
|
|
39
|
+
useImperativeHandle(ref, () => ({
|
|
40
|
+
get chart() {
|
|
41
|
+
return chartRef.current;
|
|
42
|
+
}
|
|
43
|
+
}), []);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (chartRef.current && data) chartRef.current.setData(data);
|
|
46
|
+
}, [data]);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (!chartRef.current) return;
|
|
49
|
+
if (feed) chartRef.current.setFeed(feed);
|
|
50
|
+
else chartRef.current.detachFeed();
|
|
51
|
+
}, [feed]);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (chartRef.current && theme) chartRef.current.setTheme(theme);
|
|
54
|
+
}, [theme]);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (chartRef.current && priceMode) chartRef.current.setPriceMode(priceMode);
|
|
57
|
+
}, [priceMode]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (chartRef.current && animate !== void 0) chartRef.current.setAnimate(animate);
|
|
60
|
+
}, [animate]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (chartRef.current && magnet !== void 0) chartRef.current.setMagnet(magnet);
|
|
63
|
+
}, [magnet]);
|
|
64
|
+
return createElement("div", {
|
|
65
|
+
ref: hostRef,
|
|
66
|
+
className,
|
|
67
|
+
// The chart measures its container, so it needs real dimensions.
|
|
68
|
+
style: { position: "relative", width: "100%", height: "100%", ...style || {} },
|
|
69
|
+
...rest
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
export {
|
|
73
|
+
EmberwickChart,
|
|
74
|
+
EmberwickChart as default
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=react.js.map
|
package/react.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sources":["../src/adapters/react/EmberwickChart.js"],"sourcesContent":["import { createElement, forwardRef, useEffect, useImperativeHandle, useRef } from 'react'\nimport { createChart } from '../../chart/index.js'\n\n/**\n * React adapter.\n *\n * Deliberately written with createElement instead of JSX so the library build\n * needs no JSX transform and no react/jsx-runtime external.\n *\n * The chart instance is created ONCE and then driven imperatively by effects —\n * re-creating a canvas chart on every render would throw away the animation\n * state (and the user's pan/zoom position) on each prop change.\n *\n * <EmberwickChart feed={feed} theme={{ up: '#0f0' }} onCrosshair={fn} />\n *\n * Imperative escape hatch:\n * const ref = useRef(null)\n * <EmberwickChart ref={ref} />\n * ref.current.chart.snapToRealtime()\n */\nexport const EmberwickChart = forwardRef(function EmberwickChart(props, ref) {\n const {\n data,\n feed,\n options,\n theme,\n priceMode,\n animate,\n magnet,\n onCrosshair,\n className,\n style,\n ...rest\n } = props\n\n const hostRef = useRef(null)\n const chartRef = useRef(null)\n const crosshairRef = useRef(onCrosshair)\n\n // Keep the latest callback without re-subscribing on every render.\n crosshairRef.current = onCrosshair\n\n // --- create / destroy (once) ---------------------------------------------\n useEffect(() => {\n const chart = createChart(hostRef.current, {\n ...(options || {}),\n ...(theme ? { theme } : {}),\n ...(animate !== undefined ? { animate } : {}),\n ...(magnet !== undefined ? { magnet } : {}),\n })\n chartRef.current = chart\n\n const off = chart.subscribe('crosshair', (payload) => {\n const fn = crosshairRef.current\n if (fn) fn(payload)\n })\n\n return () => {\n off()\n chart.destroy()\n chartRef.current = null\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // --- imperative handle ----------------------------------------------------\n useImperativeHandle(ref, () => ({\n get chart() {\n return chartRef.current\n },\n }), [])\n\n // --- prop -> chart wiring -------------------------------------------------\n useEffect(() => {\n if (chartRef.current && data) chartRef.current.setData(data)\n }, [data])\n\n useEffect(() => {\n if (!chartRef.current) return\n if (feed) chartRef.current.setFeed(feed)\n else chartRef.current.detachFeed()\n }, [feed])\n\n useEffect(() => {\n if (chartRef.current && theme) chartRef.current.setTheme(theme)\n }, [theme])\n\n useEffect(() => {\n if (chartRef.current && priceMode) chartRef.current.setPriceMode(priceMode)\n }, [priceMode])\n\n useEffect(() => {\n if (chartRef.current && animate !== undefined) chartRef.current.setAnimate(animate)\n }, [animate])\n\n useEffect(() => {\n if (chartRef.current && magnet !== undefined) chartRef.current.setMagnet(magnet)\n }, [magnet])\n\n return createElement('div', {\n ref: hostRef,\n className,\n // The chart measures its container, so it needs real dimensions.\n style: { position: 'relative', width: '100%', height: '100%', ...(style || {}) },\n ...rest,\n })\n})\n\nexport default EmberwickChart\n"],"names":["EmberwickChart"],"mappings":";;AAoBY,MAAC,iBAAiB,WAAW,SAASA,gBAAe,OAAO,KAAK;AAC3E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACP,IAAM;AAEJ,QAAM,UAAU,OAAO,IAAI;AAC3B,QAAM,WAAW,OAAO,IAAI;AAC5B,QAAM,eAAe,OAAO,WAAW;AAGvC,eAAa,UAAU;AAGvB,YAAU,MAAM;AACd,UAAM,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACzC,GAAI,WAAW,CAAA;AAAA,MACf,GAAI,QAAQ,EAAE,MAAK,IAAK;MACxB,GAAI,YAAY,SAAY,EAAE,QAAO,IAAK,CAAA;AAAA,MAC1C,GAAI,WAAW,SAAY,EAAE,OAAM,IAAK,CAAA;AAAA,IAC9C,CAAK;AACD,aAAS,UAAU;AAEnB,UAAM,MAAM,MAAM,UAAU,aAAa,CAAC,YAAY;AACpD,YAAM,KAAK,aAAa;AACxB,UAAI,GAAI,IAAG,OAAO;AAAA,IACpB,CAAC;AAED,WAAO,MAAM;AACX,UAAG;AACH,YAAM,QAAO;AACb,eAAS,UAAU;AAAA,IACrB;AAAA,EAEF,GAAG,CAAA,CAAE;AAGL,sBAAoB,KAAK,OAAO;AAAA,IAC9B,IAAI,QAAQ;AACV,aAAO,SAAS;AAAA,IAClB;AAAA,EACJ,IAAM,CAAA,CAAE;AAGN,YAAU,MAAM;AACd,QAAI,SAAS,WAAW,KAAM,UAAS,QAAQ,QAAQ,IAAI;AAAA,EAC7D,GAAG,CAAC,IAAI,CAAC;AAET,YAAU,MAAM;AACd,QAAI,CAAC,SAAS,QAAS;AACvB,QAAI,KAAM,UAAS,QAAQ,QAAQ,IAAI;AAAA,QAClC,UAAS,QAAQ,WAAU;AAAA,EAClC,GAAG,CAAC,IAAI,CAAC;AAET,YAAU,MAAM;AACd,QAAI,SAAS,WAAW,MAAO,UAAS,QAAQ,SAAS,KAAK;AAAA,EAChE,GAAG,CAAC,KAAK,CAAC;AAEV,YAAU,MAAM;AACd,QAAI,SAAS,WAAW,UAAW,UAAS,QAAQ,aAAa,SAAS;AAAA,EAC5E,GAAG,CAAC,SAAS,CAAC;AAEd,YAAU,MAAM;AACd,QAAI,SAAS,WAAW,YAAY,OAAW,UAAS,QAAQ,WAAW,OAAO;AAAA,EACpF,GAAG,CAAC,OAAO,CAAC;AAEZ,YAAU,MAAM;AACd,QAAI,SAAS,WAAW,WAAW,OAAW,UAAS,QAAQ,UAAU,MAAM;AAAA,EACjF,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO,cAAc,OAAO;AAAA,IAC1B,KAAK;AAAA,IACL;AAAA;AAAA,IAEA,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,GAAI,SAAS,CAAA,EAAG;AAAA,IAC9E,GAAG;AAAA,EACP,CAAG;AACH,CAAC;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(_,x){typeof exports=="object"&&typeof module!="undefined"?x(exports):typeof define=="function"&&define.amd?define(["exports"],x):(_=typeof globalThis!="undefined"?globalThis:_||self,x(_.Emberwick={}))})(this,function(_){"use strict";class x{constructor(t,i){this.container=t,this.names=i,this.canvas={},this.ctx={},this.width=0,this.height=0,this.dpr=0,this.onResize=null,getComputedStyle(t).position==="static"&&(t.style.position="relative"),i.forEach((e,n)=>{const h=document.createElement("canvas");Object.assign(h.style,{position:"absolute",left:"0",top:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:String(n+1)}),t.appendChild(h),this.canvas[e]=h,this.ctx[e]=h.getContext("2d")}),this._ro=new ResizeObserver(()=>this.measure()),this._ro.observe(t),this.measure()}measure(){const t=this.container.getBoundingClientRect(),i=Math.max(1,Math.floor(t.width)),e=Math.max(1,Math.floor(t.height)),n=Math.min(window.devicePixelRatio||1,2);if(!(i===this.width&&e===this.height&&n===this.dpr)){this.width=i,this.height=e,this.dpr=n;for(const h of this.names){const o=this.canvas[h];o.width=Math.floor(i*n),o.height=Math.floor(e*n),this.ctx[h].setTransform(n,0,0,n,0,0)}this.onResize&&this.onResize(i,e)}}composite(){const t=document.createElement("canvas");t.width=Math.floor(this.width*this.dpr),t.height=Math.floor(this.height*this.dpr);const i=t.getContext("2d");for(const e of this.names)i.drawImage(this.canvas[e],0,0);return t}destroy(){this._ro.disconnect();for(const t of this.names)this.canvas[t].remove();this.canvas={},this.ctx={}}}class q{constructor(t){this.onFrame=t,this.fps=0,this._raf=0,this._dirty=new Set,this._last=0,this._running=!1,this._frames=0,this._fpsAt=0,this._tick=this._tick.bind(this)}invalidate(...t){if(!t.length)this._dirty.add("all");else for(const i of t)this._dirty.add(i);this._schedule()}start(){this._running||(this._running=!0,this._last=performance.now(),this._fpsAt=this._last,this.invalidate("all"))}stop(){this._running=!1,this._raf&&cancelAnimationFrame(this._raf),this._raf=0}_schedule(){this._raf||!this._running||(this._raf=requestAnimationFrame(this._tick))}_tick(t){if(this._raf=0,!this._running)return;const i=Math.min(Math.max(t-this._last,1),64);this._last=t,this._frames++,t-this._fpsAt>=500&&(this.fps=Math.round(this._frames*1e3/(t-this._fpsAt)),this._frames=0,this._fpsAt=t);const e=this._dirty;this._dirty=new Set;let n=!1;try{n=this.onFrame(e,i,t)===!0}catch(h){console.error("[Emberwick] frame error",h)}(n||this._dirty.size)&&this._schedule()}}const F=s=>1-Math.pow(1-s,3),G=s=>s<.5?4*s*s*s:1-Math.pow(-2*s+2,3)/2;class k{constructor(t=0,i=90){this.value=t,this.target=t,this.tau=i}set(t){this.target=t}jump(t){this.value=t,this.target=t}get settled(){const t=1e-9+Math.abs(this.target)*1e-6;return Math.abs(this.target-this.value)<=t}tick(t){return this.settled?(this.value=this.target,!1):(this.value+=(this.target-this.value)*(1-Math.exp(-t/this.tau)),!0)}}class z{constructor(t=200,i=F){this.duration=t,this.ease=i,this.t=t}restart(){this.t=0}get done(){return this.t>=this.duration}get progress(){return this.ease(Math.min(1,this.t/this.duration))}tick(t){return this.done?!1:(this.t+=t,!0)}}const L=(s,t,i)=>s<t?t:s>i?i:s;class I{constructor({spacing:t=9,minSpacing:i=.8,maxSpacing:e=160,rightOffset:n=12}={}){this.minSpacing=i,this.maxSpacing=e,this.rightOffset=n,this.width=0,this.barCount=0,this.follow=!0,this.timeframeMs=6e4,this._spacing=new k(t,65),this._right=new k(n,65),this._initial=t}get spacing(){return this._spacing.value}get right(){return this._right.value}resize(t){this.width=Math.max(1,t)}setBarCount(t){const i=t>this.barCount;if(this.barCount=t,this.follow){const e=t-1+this.rightOffset;i?this._right.set(e):this._right.jump(e)}}x(t){return this.width-(this._right.value-t)*this._spacing.value}index(t){return this._right.value-(this.width-t)/this._spacing.value}barWidth(){const t=this._spacing.value;return Math.max(1,Math.floor(t*.72))}visibleRange(){const t=Math.floor(this.index(0))-1,i=Math.ceil(this.index(this.width))+1;return{from:L(t,0,Math.max(0,this.barCount-1)),to:L(i,0,Math.max(0,this.barCount-1))}}_clampRight(t){const i=this.barCount-1+this.rightOffset+this.width/this._spacing.target,e=Math.min(4,this.barCount-1+this.rightOffset);return L(t,e,i)}panBy(t){if(!t)return!1;const i=this._clampRight(this._right.value-t/this._spacing.value);return this._right.jump(i),this.follow=!1,!0}zoomAt(t,i){const e=this._spacing.target,n=L(e*i,this.minSpacing,this.maxSpacing);if(Math.abs(n-e)<1e-9)return!1;const h=this.follow?this.width:t,u=this._right.target-(this.width-h)/e+(this.width-h)/n;return this._spacing.set(n),this._right.set(this._clampRight(u)),!0}snapToRealtime(){this.follow=!0,this._right.set(this.barCount-1+this.rightOffset)}reset(){this._spacing.set(this._initial),this.snapToRealtime()}tick(t){const i=this._spacing.tick(t),e=this._right.tick(t);return i||e}get settled(){return this._spacing.settled&&this._right.settled}}const V=(s,t,i)=>s<t?t:s>i?i:s;class P{constructor({mode:t="linear",tau:i=120,marginTop:e=.12,marginBottom:n=.12}={}){this.mode=t,this.marginTop=e,this.marginBottom=n,this.auto=!0,this.top=0,this.height=1,this._lo=new k(0,i),this._hi=new k(1,i),this._primed=!1}_fwd(t){return this.mode==="log"?Math.log(Math.max(t,1e-9)):t}_inv(t){return this.mode==="log"?Math.exp(t):t}setMode(t){if(t===this.mode)return;const i=this._inv(this._lo.value),e=this._inv(this._hi.value);this.mode=t,this._lo.jump(this._fwd(i)),this._hi.jump(this._fwd(e))}layout(t,i){this.top=t,this.height=Math.max(1,i)}get lo(){return this._inv(this._lo.value)}get hi(){return this._inv(this._hi.value)}y(t){const i=this._lo.value,e=this._hi.value,n=(this._fwd(t)-i)/(e-i||1);return this.top+this.height*(1-n)}price(t){const i=this._lo.value,e=this._hi.value,n=1-(t-this.top)/this.height;return this._inv(i+n*(e-i))}fit(t,i,e,n){if(!this.auto||!t.length)return;let h=1/0,o=-1/0;for(let v=i;v<=e;v++){const a=t[v];a&&(a.low<h&&(h=a.low),a.high>o&&(o=a.high))}if(n&&(n.low<h&&(h=n.low),n.high>o&&(o=n.high)),!isFinite(h)||!isFinite(o))return;let p=this._fwd(h),u=this._fwd(o),l=(u-p)*this.marginTop;l>0||(l=Math.abs(u)*.01||1),p-=l,u+=(u-p)*0+l,this._lo.set(p),this._hi.set(u),this._primed||(this._lo.jump(p),this._hi.jump(u),this._primed=!0)}scaleBy(t){this.auto=!1;const i=this._lo.target,e=this._hi.target,n=(i+e)/2,h=(e-i)/2*V(t,.2,5);this._lo.set(n-h),this._hi.set(n+h)}resetAuto(){this.auto=!0}tick(t){const i=this._lo.tick(t),e=this._hi.tick(t);return i||e}}const A={background:"#0b0e14",grid:"rgba(255,255,255,0.045)",axisLine:"rgba(255,255,255,0.10)",text:"#8b93a7",textStrong:"#e6e9ef",up:"#26a69a",down:"#ef5350",upFill:"#26a69a",downFill:"#ef5350",wickUp:"#26a69a",wickDown:"#ef5350",volumeUp:"rgba(38,166,154,0.30)",volumeDown:"rgba(239,83,80,0.30)",crosshair:"rgba(255,255,255,0.32)",labelBg:"#2a3040",labelText:"#e6e9ef",tagText:"#06080d",font:'11px ui-sans-serif, -apple-system, "Segoe UI", Roboto, sans-serif',priceAxisWidth:68,timeAxisHeight:26},J={...A,background:"#ffffff",grid:"rgba(0,0,0,0.06)",axisLine:"rgba(0,0,0,0.14)",text:"#6b7280",textStrong:"#111827",labelBg:"#374151",volumeUp:"rgba(38,166,154,0.25)",volumeDown:"rgba(239,83,80,0.25)",crosshair:"rgba(0,0,0,0.35)",tagText:"#ffffff"};class H{constructor(t=55){this.enabled=!0,this.o=new k(0,t),this.h=new k(0,t),this.l=new k(0,t),this.c=new k(0,t),this.vol=new k(0,t*2),this.spawn=new z(240),this._has=!1,this._time=null}setTarget(t){if(!t){this._has=!1;return}(!this._has||t.time!==this._time)&&(this.o.jump(t.open),this.h.jump(t.open),this.l.jump(t.open),this.c.jump(t.open),this.vol.jump(0),this.spawn.restart(),this._time=t.time,this._has=!0),this.o.set(t.open),this.h.set(t.high),this.l.set(t.low),this.c.set(t.close),this.vol.set(t.volume||0)}reset(){this._has=!1,this._time=null}tick(t){if(!this._has)return!1;let i=!1;return this.o.tick(t)&&(i=!0),this.h.tick(t)&&(i=!0),this.l.tick(t)&&(i=!0),this.c.tick(t)&&(i=!0),this.vol.tick(t)&&(i=!0),this.spawn.tick(t)&&(i=!0),i}read(t){if(!this._has||!this.enabled||t.time!==this._time)return t;const i=this.o.value,e=this.c.value;return{time:t.time,open:i,close:e,high:Math.max(this.h.value,i,e),low:Math.min(this.l.value,i,e),volume:this.vol.value,_spawn:this.spawn.progress}}}class j{constructor({friction:t=.92,min:i=.015}={}){this.friction=t,this.min=i,this.v=0,this.active=!1}sample(t,i){if(i<=0)return;const e=t/i;this.v=this.v*.6+e*.4,this.active=!1}release(){Math.abs(this.v)>this.min&&(this.active=!0)}stop(){this.v=0,this.active=!1}tick(t){if(!this.active)return 0;const i=this.v*t;return this.v*=Math.pow(this.friction,t/16.6667),Math.abs(this.v)<this.min&&this.stop(),i}}function N(s,t){const i=s/Math.max(1,t);if(!(i>0)||!isFinite(i))return 1;const e=Math.pow(10,Math.floor(Math.log10(i))),n=i/e;return(n<1.5?1:n<3?2:n<7?5:10)*e}function B(s,t,i){const e=N(t-s,i),n=[],h=Math.ceil(s/e)*e;for(let o=h;o<=t+e*1e-9;o+=e)n.push(o);return{ticks:n,step:e}}function D(s){return!isFinite(s)||s<=0?2:s>=100?0:s>=1?2:Math.min(8,Math.ceil(-Math.log10(s))+1)}function Q(s){const t=[1,2,5,10,15,20,30,60,120,240,480,960,1920,3840,7680];for(const i of t)if(i>=s)return i;return Math.ceil(s/1e3)*1e3}const R=s=>String(s).padStart(2,"0");function Z(s,t){const i=new Date(s);return t>=864e5?`${i.getDate()} ${i.toLocaleString("en",{month:"short"})}`:i.getHours()===0&&i.getMinutes()===0?`${i.getDate()} ${i.toLocaleString("en",{month:"short"})}`:`${R(i.getHours())}:${R(i.getMinutes())}`}function tt(s){const t=new Date(s);return`${t.getFullYear()}-${R(t.getMonth()+1)}-${R(t.getDate())} ${R(t.getHours())}:${R(t.getMinutes())}`}function it(s,t){const{theme:i,ts:e,ps:n,plot:h,bars:o,width:p,height:u}=t;s.clearRect(0,0,p,u),s.fillStyle=i.background,s.fillRect(0,0,p,u),s.font=i.font,s.textBaseline="middle";const l=Math.max(2,Math.floor(h.h/58)),{ticks:v,step:a}=B(n.lo,n.hi,l),c=D(a);s.strokeStyle=i.grid,s.lineWidth=1,s.beginPath();for(const f of v){const d=Math.round(n.y(f))+.5;d<h.y||d>h.y+h.h||(s.moveTo(0,d),s.lineTo(h.w,d))}s.stroke(),s.fillStyle=i.text,s.textAlign="left";for(const f of v){const d=Math.round(n.y(f));d<h.y+6||d>h.y+h.h-6||s.fillText(f.toFixed(c),h.w+8,d)}if(o.length){const f=Math.ceil(74/Math.max(1e-4,e.spacing)),d=Q(f),{from:T,to:b}=e.visibleRange(),S=Math.ceil(T/d)*d;s.strokeStyle=i.grid,s.beginPath();for(let g=S;g<=b;g+=d){const r=Math.round(e.x(g))+.5;r<0||r>h.w||(s.moveTo(r,0),s.lineTo(r,h.h))}s.stroke(),s.fillStyle=i.text,s.textAlign="center";const w=h.h+i.timeAxisHeight/2;for(let g=S;g<=b;g+=d){const r=o[g];if(!r)continue;const m=Math.round(e.x(g));m<28||m>h.w-28||s.fillText(Z(r.time,e.timeframeMs),m,w)}}s.strokeStyle=i.axisLine,s.beginPath(),s.moveTo(h.w+.5,0),s.lineTo(h.w+.5,h.h),s.moveTo(0,h.h+.5),s.lineTo(p,h.h+.5),s.stroke()}function st(s,t){const{theme:i,ts:e,ps:n,plot:h,bars:o,width:p,height:u,live:l,volumeRatio:v}=t;if(s.clearRect(0,0,p,u),!o.length)return;const{from:a,to:c}=e.visibleRange(),f=e.barWidth(),d=f/2,T=f<=2,b=h.h*v,S=h.y+h.h-b;let w=0;for(let r=a;r<=c;r++){const m=o[r];m&&m.volume>w&&(w=m.volume)}if(w>0)for(let r=a;r<=c;r++){let m=o[r];if(!m)continue;l&&r===o.length-1&&(m=l);const M=e.x(r);if(M<-f||M>h.w+f)continue;const y=m.volume/w*b*.9;s.fillStyle=m.close>=m.open?i.volumeUp:i.volumeDown,s.fillRect(Math.round(M-d),S+(b-y),Math.max(1,f),y)}for(let r=a;r<=c;r++){let m=o[r];if(!m)continue;const M=r===o.length-1;l&&M&&(m=l);const y=e.x(r);if(y<-f||y>h.w+f)continue;const C=m.close>=m.open,at=C?i.up:i.down,U=n.y(m.open),W=n.y(m.close),rt=n.y(m.high),lt=n.y(m.low);let K=1;l&&M&&typeof m._spawn=="number"&&(K=.35+.65*m._spawn);const X=Math.round(y)+(f%2?.5:0);if(s.strokeStyle=C?i.wickUp:i.wickDown,s.lineWidth=Math.max(1,Math.min(2,f*.16)),s.beginPath(),s.moveTo(X,rt),s.lineTo(X,lt),s.stroke(),T)continue;const ct=Math.min(U,W),ut=Math.max(1,Math.abs(W-U)),Y=Math.max(1,f*K);s.fillStyle=at,s.fillRect(Math.round(y-Y/2),Math.round(ct),Math.round(Y),Math.round(ut))}const g=l||o[o.length-1];if(g){const r=Math.round(n.y(g.close))+.5;if(r>h.y&&r<h.y+h.h){const m=g.close>=g.open;s.save(),s.setLineDash([3,3]),s.strokeStyle=m?i.up:i.down,s.lineWidth=1,s.globalAlpha=.7,s.beginPath(),s.moveTo(0,r),s.lineTo(h.w,r),s.stroke(),s.restore();const{step:M}=B(n.lo,n.hi,Math.max(2,Math.floor(h.h/58))),y=g.close.toFixed(D(M));s.font=i.font,s.textBaseline="middle",s.textAlign="left";const C=s.measureText(y).width;s.fillStyle=m?i.up:i.down,s.fillRect(h.w+1,r-9,C+14,18),s.fillStyle=i.tagText,s.fillText(y,h.w+8,r)}}}function et(s,t){const{theme:i,ts:e,ps:n,plot:h,bars:o,width:p,height:u,cursor:l,magnet:v}=t;if(s.clearRect(0,0,p,u),!l||!o.length||l.x<0||l.x>h.w||l.y<0||l.y>h.h)return;const a=Math.round(e.index(l.x)),c=o[a];let f=l.x,d=l.y;if(c&&(f=e.x(a),v)){const w=[c.open,c.high,c.low,c.close];let g=null,r=1/0;for(const m of w){const M=n.y(m),y=Math.abs(M-l.y);y<r&&(r=y,g=M)}r<22&&(d=g)}s.save(),s.setLineDash([4,4]),s.strokeStyle=i.crosshair,s.lineWidth=1,s.beginPath(),s.moveTo(Math.round(f)+.5,0),s.lineTo(Math.round(f)+.5,h.h),s.moveTo(0,Math.round(d)+.5),s.lineTo(h.w,Math.round(d)+.5),s.stroke(),s.restore(),s.font=i.font,s.textBaseline="middle";const{step:T}=B(n.lo,n.hi,Math.max(2,Math.floor(h.h/58))),b=n.price(d).toFixed(D(T));s.textAlign="left";const S=s.measureText(b).width;if(s.fillStyle=i.labelBg,s.fillRect(h.w+1,d-9,S+14,18),s.fillStyle=i.labelText,s.fillText(b,h.w+8,d),c){const w=tt(c.time);s.textAlign="center";const g=s.measureText(w).width,r=Math.min(Math.max(f,g/2+6),h.w-g/2-6);s.fillStyle=i.labelBg,s.fillRect(r-g/2-7,h.h+3,g+14,18),s.fillStyle=i.labelText,s.fillText(w,r,h.h+12)}}class O{constructor(t,i={}){if(!t)throw new Error("Chart: container element is required");this.container=t,this.theme={...A,...i.theme||{}},this.options={volumeRatio:.18,magnet:!0,animate:!0,...i},this.bars=[],this.feed=null,this._unsub=null,this._loadingHistory=!1,this._exhausted=!1,this._listeners={crosshair:new Set,visibleRange:new Set},this.layers=new x(t,["base","main","overlay"]),this.ts=new I(i.timeScale),this.ps=new P(i.priceScale),this.live=new H,this.live.enabled=this.options.animate!==!1,this.inertia=new j,this.cursor=null,this.plot={x:0,y:0,w:1,h:1},this.loop=new q((e,n)=>this._frame(e,n)),this.layers.onResize=()=>{this._layout(),this.loop.invalidate("all")},this._layout(),this._bindEvents(),this.loop.start()}_layout(){const{width:t,height:i}=this.layers,e=Math.max(1,t-this.theme.priceAxisWidth),n=Math.max(1,i-this.theme.timeAxisHeight);this.plot={x:0,y:0,w:e,h:n},this.ts.resize(e),this.ps.layout(0,n)}setData(t){this.bars=Array.isArray(t)?t.slice():[],this._exhausted=!1,this.bars.length>1&&(this.ts.timeframeMs=this.bars[1].time-this.bars[0].time),this.ts.setBarCount(this.bars.length),this.ts.snapToRealtime(),this.live.reset(),this.ps._primed=!1,this.loop.invalidate("all")}update(t){if(!t)return;const i=this.bars.length;if(i&&this.bars[i-1].time===t.time)this.bars[i-1]=t;else{this.append(t);return}this.live.setTarget(t),this.loop.invalidate("main")}append(t){if(!t)return;const i=this.bars.length;i&&t.time<=this.bars[i-1].time?this.bars[i-1]=t:(this.bars.push(t),this.ts.setBarCount(this.bars.length)),this.live.setTarget(t),this.loop.invalidate("main")}async setFeed(t){if(this.detachFeed(),this.feed=t,!t)return;this.ts.timeframeMs=t.timeframe||this.ts.timeframeMs;const i=await t.getBars({symbol:t.symbol,timeframe:t.timeframe,to:null,limit:this.options.initialBars||1500});this.setData(i),typeof t.prime=="function"&&t.prime(i[i.length-1]),this._unsub=t.subscribe(e=>{!e||!e.bar||(e.type==="append"?this.append(e.bar):this.update(e.bar))})}detachFeed(){this._unsub&&this._unsub(),this._unsub=null,this.feed=null}async _maybeLoadHistory(){if(this._loadingHistory||this._exhausted||!this.feed)return;const{from:t}=this.ts.visibleRange();if(!(t>80||!this.bars.length)){this._loadingHistory=!0;try{const i=this.bars[0].time,e=await this.feed.getBars({symbol:this.feed.symbol,timeframe:this.feed.timeframe,to:i,limit:1e3});if(!e||!e.length)this._exhausted=!0;else{const n=e.filter(h=>h.time<i);if(!n.length)this._exhausted=!0;else{this.bars=n.concat(this.bars);const h=this.ts.follow;this.ts.barCount=this.bars.length,this.ts._right.jump(this.ts._right.value+n.length),this.ts._right.set(this.ts._right.target+n.length),this.ts.follow=h,this.loop.invalidate("all")}}}catch(i){console.error("[Emberwick] history load failed",i),this._exhausted=!0}finally{this._loadingHistory=!1}}}_bindEvents(){const t=this.container;t.style.touchAction="none",t.style.cursor="crosshair";let i=!1,e=null,n=0,h=0,o=0,p=!1;const u=new Map;let l=0;const v=a=>{const c=t.getBoundingClientRect();return{x:a.clientX-c.left,y:a.clientY-c.top}};this._onDown=a=>{if(u.set(a.pointerId,v(a)),u.size===2){const[f,d]=[...u.values()];l=Math.hypot(f.x-d.x,f.y-d.y),i=!1;return}const c=v(a);i=!0,p=!1,e=c.x>this.plot.w?"price":c.y>this.plot.h?"time":"pan",n=c.x,h=c.y,o=performance.now(),this.inertia.stop(),t.setPointerCapture(a.pointerId)},this._onMove=a=>{const c=v(a);if(u.has(a.pointerId)&&u.set(a.pointerId,c),u.size===2){const[S,w]=[...u.values()],g=Math.hypot(S.x-w.x,S.y-w.y);if(l>0&&g>0){const r=(S.x+w.x)/2;this.ts.zoomAt(r,g/l),this.loop.invalidate("all")}l=g;return}if(this.cursor=c,this._emitCrosshair(c),this.loop.invalidate("overlay"),!i)return;const f=performance.now(),d=f-o,T=c.x-n,b=c.y-h;(Math.abs(T)>1||Math.abs(b)>1)&&(p=!0),e==="pan"?(this.ts.panBy(T),this.inertia.sample(T,d),this.loop.invalidate("all"),this._maybeLoadHistory()):e==="price"?(this.ps.scaleBy(1+b/220),this.loop.invalidate("all")):e==="time"&&(this.ts.zoomAt(this.plot.w,1-T/260),this.loop.invalidate("all")),n=c.x,h=c.y,o=f},this._onUp=a=>{u.delete(a.pointerId),u.size<2&&(l=0),i&&e==="pan"&&p&&(this.inertia.release(),this.loop.invalidate("all")),i=!1,e=null;try{t.releasePointerCapture(a.pointerId)}catch{}},this._onLeave=()=>{this.cursor=null,this._emitCrosshair(null),this.loop.invalidate("overlay")},this._onWheel=a=>{a.preventDefault();const c=t.getBoundingClientRect(),f=a.clientX-c.left,d=Math.pow(.999,a.deltaY);this.ts.zoomAt(f,d),this.loop.invalidate("all"),this._maybeLoadHistory()},this._onDbl=()=>{this.ts.reset(),this.ps.resetAuto(),this.loop.invalidate("all")},this._onKey=a=>{const c=a.shiftKey?120:40;if(a.key==="ArrowLeft")this.ts.panBy(c),this.loop.invalidate("all"),this._maybeLoadHistory();else if(a.key==="ArrowRight")this.ts.panBy(-c),this.loop.invalidate("all");else if(a.key==="+"||a.key==="=")this.ts.zoomAt(this.plot.w/2,1.2),this.loop.invalidate("all");else if(a.key==="-"||a.key==="_")this.ts.zoomAt(this.plot.w/2,.8),this.loop.invalidate("all");else return;a.preventDefault()},t.addEventListener("pointerdown",this._onDown),t.addEventListener("pointermove",this._onMove),t.addEventListener("pointerup",this._onUp),t.addEventListener("pointercancel",this._onUp),t.addEventListener("pointerleave",this._onLeave),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("dblclick",this._onDbl),t.addEventListener("keydown",this._onKey),t.hasAttribute("tabindex")||t.setAttribute("tabindex","0")}_emitCrosshair(t){if(!this._listeners.crosshair.size)return;let i=null;if(t&&this.bars.length&&t.x<=this.plot.w&&t.y<=this.plot.h){const e=Math.round(this.ts.index(t.x)),n=this.bars[e];n&&(i={index:e,bar:n,price:this.ps.price(t.y)})}for(const e of this._listeners.crosshair)e(i)}subscribe(t,i){const e=this._listeners[t];if(!e)throw new Error(`Chart: unknown event "${t}"`);return e.add(i),()=>e.delete(i)}_frame(t,i){let e=!1;this.ts.tick(i)&&(e=!0);const n=this.inertia.tick(i);n&&(this.ts.panBy(n),e=!0,this._maybeLoadHistory()),this.live.tick(i)&&(e=!0);const{from:h,to:o}=this.ts.visibleRange(),p=this.bars.length-1,u=this.bars.length?this.live.read(this.bars[p]):null,l=u&&o>=p?u:null;this.ps.fit(this.bars,h,o,l),this.ps.tick(i)&&(e=!0);const v=e||t.has("all")||t.has("base")||t.has("main"),a={theme:this.theme,ts:this.ts,ps:this.ps,plot:this.plot,bars:this.bars,width:this.layers.width,height:this.layers.height,live:l,volumeRatio:this.options.volumeRatio,cursor:this.cursor,magnet:this.options.magnet};return v&&(it(this.layers.ctx.base,a),st(this.layers.ctx.main,a)),(v||t.has("overlay"))&&et(this.layers.ctx.overlay,a),e}get fps(){return this.loop.fps}setTheme(t){this.theme={...this.theme,...t},this._layout(),this.loop.invalidate("all")}setPriceMode(t){this.ps.setMode(t),this.loop.invalidate("all")}setAnimate(t){this.live.enabled=!!t,this.loop.invalidate("all")}setMagnet(t){this.options.magnet=!!t,this.loop.invalidate("overlay")}snapToRealtime(){this.ts.snapToRealtime(),this.ps.resetAuto(),this.loop.invalidate("all")}toImage(){return this.layers.composite().toDataURL("image/png")}destroy(){const t=this.container;t.removeEventListener("pointerdown",this._onDown),t.removeEventListener("pointermove",this._onMove),t.removeEventListener("pointerup",this._onUp),t.removeEventListener("pointercancel",this._onUp),t.removeEventListener("pointerleave",this._onLeave),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("dblclick",this._onDbl),t.removeEventListener("keydown",this._onKey),this.detachFeed(),this.loop.stop(),this.layers.destroy(),this._listeners.crosshair.clear(),this._listeners.visibleRange.clear(),this.bars=[]}}class ${constructor({symbol:t="DEMO",timeframe:i=6e4}={}){this.symbol=t,this.timeframe=i}async getBars({symbol:t,timeframe:i,to:e,limit:n}){throw new Error("DataFeed.getBars() not implemented")}subscribe(t){return()=>{}}destroy(){}}function E(s){let t=s>>>0;return function(){t=t+1831565813|0;let i=Math.imul(t^t>>>15,1|t);return i=i+Math.imul(i^i>>>7,61|i)^i,((i^i>>>14)>>>0)/4294967296}}class ht extends ${constructor({symbol:t="EMBR",timeframe:i=6e4,seed:e=7,start:n=100,volatility:h=.0022,drift:o=2e-5,ticksPerSecond:p=8,speed:u=1}={}){super({symbol:t,timeframe:i}),this.seed=e,this.start=n,this.volatility=h,this.drift=o,this.ticksPerSecond=p,this.speed=u,this._rnd=E(e),this._handlers=new Set,this._timer=null,this._forming=null,this._last=n,this._vol=h,this._anchorTime=Math.floor(Date.now()/i)*i}_gauss(){let t=0,i=0;for(;t===0;)t=this._rnd();for(;i===0;)i=this._rnd();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*i)}_step(t){const i=this._gauss();return this._vol+=(this.volatility-this._vol)*.02+Math.abs(i)*this.volatility*.015,this._vol=Math.min(this._vol,this.volatility*6),Math.max(.01,t*(1+this.drift+i*this._vol))}_makeBar(t,i){let e=i;const n=14;let h=i,o=i;for(let l=0;l<n;l++)e=this._step(e),e>h&&(h=e),e<o&&(o=e);const p=Math.max(1e-9,h-o),u=Math.round((300+this._rnd()*900)*(1+p/i*260));return{time:t,open:i,high:h,low:o,close:e,volume:u}}async getBars({to:t,limit:i=1500,timeframe:e=this.timeframe}={}){const n=t==null?this._anchorTime:t,h=[],o=n-i*e,p=E(this.seed^Math.floor(o/e)),u=this._rnd;this._rnd=p;let l=this.start*(1+(p()-.5)*.04);for(let v=0;v<i;v++){const a=o+v*e,c=this._makeBar(a,l);l=c.close,h.push(c)}return this._rnd=u,t==null&&(this._last=h.length?h[h.length-1].close:this.start),h}subscribe(t){return this._handlers.add(t),this._timer||this._start(),()=>{this._handlers.delete(t),this._handlers.size||this.stop()}}_emit(t){for(const i of this._handlers)i(t)}_start(){const t=Math.max(16,1e3/this.ticksPerSecond);this._timer=setInterval(()=>this._tick(),t)}prime(t){t&&(this._last=t.close,this._forming={...t})}_tick(){const t=this.timeframe/this.speed,i=Date.now(),e=Math.floor(i/t)*t;if(!this._forming||this._forming.time!==e){const o=this._last;this._forming={time:e,open:o,high:o,low:o,close:o,volume:0},this._emit({type:"append",bar:{...this._forming}});return}const n=this._step(this._last);this._last=n;const h=this._forming;h.close=n,n>h.high&&(h.high=n),n<h.low&&(h.low=n),h.volume+=Math.round(20+this._rnd()*120),this._emit({type:"update",bar:{...h}})}setSpeed(t){this.speed=t}setTicksPerSecond(t){this.ticksPerSecond=t,this._timer&&(this.stop(),this._start())}setPaused(t){t?this.stop():!this._timer&&this._handlers.size&&this._start()}get paused(){return!this._timer}stop(){this._timer&&clearInterval(this._timer),this._timer=null}destroy(){this.stop(),this._handlers.clear()}}function nt(s,t){return new O(s,t)}const ot="0.1.0";_.Chart=O,_.DataFeed=$,_.Inertia=j,_.LiveCandle=H,_.PriceScale=P,_.RandomFeed=ht,_.Smoothed=k,_.TimeScale=I,_.Tween=z,_.createChart=nt,_.defaultTheme=A,_.easeInOutCubic=G,_.easeOutCubic=F,_.lightTheme=J,_.mulberry32=E,_.version=ot,Object.defineProperty(_,Symbol.toStringTag,{value:"Module"})});
|
|
2
|
+
//# sourceMappingURL=emberwick.umd.js.map
|