blazeplot 0.2.0 → 0.2.2

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/dist/index.js CHANGED
@@ -152,12 +152,25 @@ function r(e) {
152
152
  function i(e) {
153
153
  return "getOpen" in e && "getHigh" in e && "getLow" in e && "getClose" in e;
154
154
  }
155
- function a(e, t, n, r, i) {
155
+ function a(e) {
156
+ return "copySamplesRange" in e;
157
+ }
158
+ function o(e) {
159
+ return "copyMinMaxSegments" in e;
160
+ }
161
+ function s(e) {
162
+ return "copyVisibleSamples" in e;
163
+ }
164
+ function c(e) {
165
+ return "copyVisiblePoints" in e;
166
+ }
167
+ var l = 64, u = 64, d = 1024;
168
+ function f(e, t, n, r, i) {
156
169
  if (n === e) return t;
157
170
  let a = (i - e) / (n - e);
158
171
  return t + (r - t) * a;
159
172
  }
160
- var o = class {
173
+ var p = class {
161
174
  config;
162
175
  style;
163
176
  dataset;
@@ -169,7 +182,7 @@ var o = class {
169
182
  _lastBuildRangeStart = NaN;
170
183
  _visible = !0;
171
184
  constructor(e, t, i) {
172
- this.dataset = e, this.config = t, this.pyramid = (t.mode === "line" || t.mode === "bar") && t.downsample !== "none" ? new n() : null, this._useDatasetRangeMinMax = r(e), this.style = i, this.pyramid && e.length > 0 && !this._useDatasetRangeMinMax && this.pyramid.build(e), this._lastBuildLength = e.length, this._lastBuildRangeStart = e.range?.start ?? NaN;
185
+ this.dataset = e, this.config = t, this.pyramid = (t.mode === "line" || t.mode === "bar" || t.mode === "scatter") && t.downsample !== "none" ? new n() : null, this._useDatasetRangeMinMax = r(e), this.style = i, this.pyramid && e.length > 0 && !this._useDatasetRangeMinMax && this.pyramid.build(e), this._lastBuildLength = e.length, this._lastBuildRangeStart = e.range?.start ?? NaN;
173
186
  }
174
187
  get hasLOD() {
175
188
  return this.pyramid !== null;
@@ -237,24 +250,72 @@ var o = class {
237
250
  }
238
251
  return this.sampleAt(i);
239
252
  }
240
- nearestSampleByPoint(e, t, n, r, i) {
241
- let a = this.visibleIndexRange(n);
242
- if (a.start >= a.end || r <= 0 || i <= 0) return null;
243
- let o = r / (n.xMax - n.xMin), s = i / (n.yMax - n.yMin), c = -1, l = Infinity;
244
- for (let n = a.start; n < a.end; n++) {
245
- let r = (this.dataset.getX(n) - e) * o, i = (this.dataset.getY(n) - t) * s, a = r * r + i * i;
246
- a < l && (l = a, c = n);
247
- }
248
- if (c < 0) return null;
249
- let u = this.sampleAt(c);
250
- return u ? {
251
- ...u,
252
- distancePx: Math.sqrt(l)
253
+ nearestSampleByPoint(e, t, n, r, i, a = Infinity) {
254
+ let o = this.visibleIndexRange(n), s = n.xMax - n.xMin, c = n.yMax - n.yMin;
255
+ if (o.start >= o.end || r <= 0 || i <= 0 || s <= 0 || c <= 0) return null;
256
+ let u = r / s, d = i / c, f = -1, p = a < 0 ? -1 : Number.isFinite(a) ? a * a : Infinity, m = (n) => {
257
+ let r = (this.dataset.getX(n) - e) * u, i = (this.dataset.getY(n) - t) * d, a = r * r + i * i;
258
+ (a < p || f < 0 && a <= p) && (p = a, f = n);
259
+ }, h = this.dataset.lowerBoundX(e), g = Math.min(Math.max(h, o.start), o.end - 1);
260
+ if (m(g), g > o.start && m(g - 1), g + 1 < o.end && m(g + 1), this.hasPointIntervalBounds() && o.end - o.start > l) {
261
+ let n = this.pointIntervalDistanceSq(o.start, o.end, e, t, u, d), r = n <= p ? [{
262
+ start: o.start,
263
+ end: o.end,
264
+ lowerBoundSq: n
265
+ }] : [];
266
+ for (; r.length > 0;) {
267
+ let n = r.pop();
268
+ if (n.lowerBoundSq > p) continue;
269
+ let i = n.end - n.start;
270
+ if (i <= l) {
271
+ for (let e = n.start; e < n.end; e++) m(e);
272
+ continue;
273
+ }
274
+ let a = n.start + (i >> 1), o = this.pointIntervalDistanceSq(n.start, a, e, t, u, d), s = this.pointIntervalDistanceSq(a, n.end, e, t, u, d), c = {
275
+ start: n.start,
276
+ end: a,
277
+ lowerBoundSq: o
278
+ }, f = {
279
+ start: a,
280
+ end: n.end,
281
+ lowerBoundSq: s
282
+ };
283
+ o < s ? (s <= p && r.push(f), o <= p && r.push(c)) : (o <= p && r.push(c), s <= p && r.push(f));
284
+ }
285
+ } else {
286
+ let t = Math.min(h - 1, o.end - 1), n = Math.max(h, o.start);
287
+ for (; t >= o.start || n < o.end;) {
288
+ let r = t >= o.start ? this.pointXDistanceSq(t, e, u) : Infinity, i = n < o.end ? this.pointXDistanceSq(n, e, u) : Infinity;
289
+ if (r > p && i > p) break;
290
+ r <= i ? (r <= p && m(t), t--) : (i <= p && m(n), n++);
291
+ }
292
+ }
293
+ if (f < 0) return null;
294
+ let _ = this.sampleAt(f);
295
+ return _ ? {
296
+ ..._,
297
+ distancePx: Math.sqrt(p)
253
298
  } : null;
254
299
  }
255
300
  copyRawVisible(e, t, n, r = 0) {
256
301
  return this.copyVisibleSamples(e, t, n, "points", 0, r);
257
302
  }
303
+ copyScatterVisible(e, t, n, r, i, a, o = 0) {
304
+ return this.copyVisiblePoints(e, t, n, r, i, a, o);
305
+ }
306
+ copyScatterRange(e, t, n, r, i, a = 0, o = 0, s = 0) {
307
+ if (i <= 0 || r.length < i * 2) return 0;
308
+ let c = Math.max(0, Math.floor(e)), l = Math.min(this.dataset.length, Math.ceil(t));
309
+ if (l <= c) return 0;
310
+ let u = n.yMax - n.yMin, d = Math.max(0, Math.floor(o)), f = u > 0 && d > 0 ? (Number.isFinite(s) ? Math.max(0, s) : 0) * .5 / d * u : 0, p = n.yMin - f, m = n.yMax + f, h = 0;
311
+ for (let e = c; e < l && h < i; e++) {
312
+ let t = this.dataset.getY(e);
313
+ if (t < p || t > m) continue;
314
+ let n = h * 2;
315
+ r[n] = this.dataset.getX(e) - a, r[n + 1] = t, h++;
316
+ }
317
+ return h;
318
+ }
258
319
  copyRawVisibleClipped(e, t, n, r = 0) {
259
320
  return this.copyClippedVisibleLine(e, t, n, r, "data");
260
321
  }
@@ -285,6 +346,15 @@ var o = class {
285
346
  }
286
347
  return l;
287
348
  }
349
+ copyOhlcTuplesRange(e, t, n, r, a = 0) {
350
+ if (!i(this.dataset) || r <= 0 || n.length < r * 5) return 0;
351
+ let o = Math.max(0, Math.floor(e)), s = Math.min(this.dataset.length, Math.ceil(t)), c = Math.min(r, Math.max(0, s - o));
352
+ for (let e = 0; e < c; e++) {
353
+ let t = o + e, r = e * 5;
354
+ n[r] = this.dataset.getX(t) - a, n[r + 1] = this.dataset.getOpen(t), n[r + 2] = this.dataset.getHigh(t), n[r + 3] = this.dataset.getLow(t), n[r + 4] = this.dataset.getClose(t);
355
+ }
356
+ return c;
357
+ }
288
358
  visibleIndexRange(e, t = 0) {
289
359
  if (!e) return {
290
360
  start: 0,
@@ -296,78 +366,182 @@ var o = class {
296
366
  end: Math.min(this.dataset.length, this.dataset.upperBoundX(e.xMax) + n)
297
367
  };
298
368
  }
369
+ pointXDistanceSq(e, t, n) {
370
+ let r = (this.dataset.getX(e) - t) * n;
371
+ return r * r;
372
+ }
373
+ pointIntervalDistanceSq(e, t, n, r, i, a) {
374
+ if (t <= e) return Infinity;
375
+ let o = this.dataset.getX(e), s = this.dataset.getX(t - 1), c = n < o ? (o - n) * i : n > s ? (n - s) * i : 0, l = this.pointIntervalMinMaxY(e, t);
376
+ if (!l) return Infinity;
377
+ let u = r < l.minY ? (l.minY - r) * a : r > l.maxY ? (r - l.maxY) * a : 0;
378
+ return c * c + u * u;
379
+ }
380
+ hasPointIntervalBounds() {
381
+ return r(this.dataset) || this.pyramid !== null && !this._dirty && !this._useRawMinMaxScan;
382
+ }
383
+ pointIntervalMinMaxY(e, t) {
384
+ return r(this.dataset) ? this.dataset.rangeMinMaxY(e, t) : this.pyramid && !this._dirty && !this._useRawMinMaxScan ? this.pyramid.rangeMinMax(this.dataset, e, t) : null;
385
+ }
299
386
  copyClippedVisibleLine(e, t, n, r, i) {
300
387
  if (n <= 0 || t.length < n * 2) return 0;
301
- let o = e.xMax - e.xMin, s = e.yMax - e.yMin;
302
- if (i === "clip" && (o <= 0 || s <= 0)) return 0;
303
- let c = Math.max(0, this.dataset.lowerBoundX(e.xMin) - 1), l = Math.min(this.dataset.length, this.dataset.upperBoundX(e.xMax) + 1);
304
- if (l - c <= 0) return 0;
305
- let u = 0, d = NaN, f = NaN, p = (a, c) => {
306
- let l = i === "clip" ? (a - e.xMin) / o * 2 - 1 : a - r, p = i === "clip" ? (c - e.yMin) / s * 2 - 1 : c;
307
- if (u > 0 && l === d && p === f) return !0;
308
- if (u >= n) return !1;
309
- let m = u * 2;
310
- return t[m] = l, t[m + 1] = p, u++, d = l, f = p, !0;
388
+ let a = e.xMax - e.xMin, o = e.yMax - e.yMin;
389
+ if (i === "clip" && (a <= 0 || o <= 0)) return 0;
390
+ let s = Math.max(0, this.dataset.lowerBoundX(e.xMin) - 1), c = Math.min(this.dataset.length, this.dataset.upperBoundX(e.xMax) + 1);
391
+ if (c - s <= 0) return 0;
392
+ let l = 0, u = NaN, d = NaN, p = (s, c) => {
393
+ let f = i === "clip" ? (s - e.xMin) / a * 2 - 1 : s - r, p = i === "clip" ? (c - e.yMin) / o * 2 - 1 : c;
394
+ if (l > 0 && f === u && p === d) return !0;
395
+ if (l >= n) return !1;
396
+ let m = l * 2;
397
+ return t[m] = f, t[m + 1] = p, l++, u = f, d = p, !0;
311
398
  };
312
- if (l - c === 1) {
313
- let t = this.dataset.getX(c);
314
- return t < e.xMin || t > e.xMax ? 0 : p(t, this.dataset.getY(c)) ? u : 0;
399
+ if (c - s === 1) {
400
+ let t = this.dataset.getX(s);
401
+ return t < e.xMin || t > e.xMax ? 0 : p(t, this.dataset.getY(s)) ? l : 0;
315
402
  }
316
- for (let t = c; t + 1 < l; t++) {
317
- let n = this.dataset.getX(t), r = this.dataset.getY(t), i = this.dataset.getX(t + 1), o = this.dataset.getY(t + 1);
403
+ for (let t = s; t + 1 < c; t++) {
404
+ let n = this.dataset.getX(t), r = this.dataset.getY(t), i = this.dataset.getX(t + 1), a = this.dataset.getY(t + 1);
318
405
  if (i < e.xMin || n > e.xMax) continue;
319
- let s = Math.max(n, e.xMin), c = Math.min(i, e.xMax);
320
- if (c < s) continue;
321
- let l = a(n, r, i, o, s), u = a(n, r, i, o, c);
322
- if (!p(s, l) || !p(c, u)) break;
406
+ let o = Math.max(n, e.xMin), s = Math.min(i, e.xMax);
407
+ if (s < o) continue;
408
+ let c = f(n, r, i, a, o), l = f(n, r, i, a, s);
409
+ if (!p(o, c) || !p(s, l)) break;
323
410
  }
324
- return u;
411
+ return l;
412
+ }
413
+ copyVisiblePoints(e, t, n, r, i, a, o) {
414
+ if (c(this.dataset)) return this.dataset.copyVisiblePoints(e, t, n, o, r, i, a);
415
+ if (n <= 0 || t.length < n * 2) return 0;
416
+ let s = e.xMax - e.xMin, l = e.yMax - e.yMin, u = Math.max(1, Math.floor(r)), d = Math.max(1, Math.floor(i));
417
+ if (s <= 0 || l <= 0) return 0;
418
+ let f = (Number.isFinite(a) ? Math.max(0, a) : 0) * .5, p = f / u * s, m = f / d * l, h = e.xMin - p, g = e.xMax + p, _ = e.yMin - m, v = e.yMax + m, y = this.dataset.lowerBoundX(h), b = this.dataset.upperBoundX(g);
419
+ if (b <= y) return 0;
420
+ if (b - y <= n) return this.copyVisiblePointRange(y, b, _, v, t, n, o);
421
+ let x = this.hasPointIntervalBounds(), S = x ? this.pointIntervalMinMaxY(y, b) : null;
422
+ if (S && (S.maxY < _ || S.minY > v)) return 0;
423
+ if (b - y <= n * 4) {
424
+ let e = this.copyVisiblePointsExact(y, b, _, v, t, n, o);
425
+ if (!e.overflow) return e.count;
426
+ }
427
+ let C = S !== null && S.minY >= _ && S.maxY <= v;
428
+ return this.copyVisiblePointBuckets(y, b, _, v, t, n, o, C, x);
429
+ }
430
+ copyVisiblePointRange(e, t, n, r, i, a, o) {
431
+ let s = 0;
432
+ for (let c = e; c < t && s < a; c++) {
433
+ let e = this.dataset.getY(c);
434
+ if (e < n || e > r) continue;
435
+ let t = s * 2;
436
+ i[t] = this.dataset.getX(c) - o, i[t + 1] = e, s++;
437
+ }
438
+ return s;
439
+ }
440
+ copyVisiblePointBuckets(e, t, n, r, i, a, o, s, c) {
441
+ let l = t - e, u = this.stableScatterBucketWidth(l, a), f = Math.floor(e / u) * u, p = 0, m = (e) => {
442
+ let t = p * 2;
443
+ i[t] = this.dataset.getX(e) - o, i[t + 1] = this.dataset.getY(e), p++;
444
+ };
445
+ for (let l = f; l < t && p < a; l += u) {
446
+ let a = Math.min(t, l + u), f = Math.max(e, l);
447
+ if (a <= f) continue;
448
+ let h = Math.max(f, Math.min(a - 1, l + (u >> 1)));
449
+ if (s) {
450
+ m(h);
451
+ continue;
452
+ }
453
+ let g = c && a - f >= d ? this.pointIntervalMinMaxY(f, a) : null;
454
+ if (!(g && (g.maxY < n || g.minY > r))) {
455
+ if (g && g.minY >= n && g.maxY <= r) {
456
+ m(h);
457
+ continue;
458
+ }
459
+ for (let e = f; e < a; e++) {
460
+ let t = this.dataset.getY(e);
461
+ if (t < n || t > r) continue;
462
+ let a = p * 2;
463
+ i[a] = this.dataset.getX(e) - o, i[a + 1] = t, p++;
464
+ break;
465
+ }
466
+ }
467
+ }
468
+ return p;
469
+ }
470
+ stableScatterBucketWidth(e, t) {
471
+ let n = Math.max(1, Math.ceil(e / Math.max(1, t)));
472
+ return n <= 8 ? n : Math.ceil(n / 8) * 8;
473
+ }
474
+ copyVisiblePointsExact(e, t, n, r, i, a, o) {
475
+ let s = 0, c = !1, l = this.hasPointIntervalBounds(), d = (e) => {
476
+ let t = this.dataset.getY(e);
477
+ if (t < n || t > r) return !0;
478
+ if (s >= a) return c = !0, !1;
479
+ let l = s * 2;
480
+ return i[l] = this.dataset.getX(e) - o, i[l + 1] = t, s++, !0;
481
+ }, f = (e, t) => {
482
+ for (let n = e; n < t; n++) if (!d(n)) return !1;
483
+ return !0;
484
+ }, p = (e, t) => {
485
+ if (t <= e) return !0;
486
+ let i = l ? this.pointIntervalMinMaxY(e, t) : null;
487
+ if (i && (i.maxY < n || i.minY > r)) return !0;
488
+ if (t - e <= u || !l) return f(e, t);
489
+ let a = e + (t - e >> 1);
490
+ return p(e, a) && p(a, t);
491
+ };
492
+ return p(e, t), {
493
+ count: s,
494
+ overflow: c
495
+ };
325
496
  }
326
497
  copyVisibleSamples(e, t, n, r, i, a) {
498
+ if (s(this.dataset)) return this.dataset.copyVisibleSamples(e, t, n, r, i, a);
327
499
  let o = r === "points" ? 2 : 4;
328
500
  if (n <= 0 || t.length < n * o) return 0;
329
- let s = this.dataset.lowerBoundX(e.xMin), c = this.dataset.upperBoundX(e.xMax), l = c - s;
330
- if (l <= 0) return 0;
331
- let u = Math.max(1, Math.ceil(l / n)), d = 0;
332
- for (let e = s; e < c && d < n; e += u) {
501
+ let c = this.dataset.lowerBoundX(e.xMin), l = this.dataset.upperBoundX(e.xMax), u = l - c;
502
+ if (u <= 0) return 0;
503
+ let d = Math.max(1, Math.ceil(u / n)), f = 0;
504
+ for (let e = c; e < l && f < n; e += d) {
333
505
  let n = this.dataset.getX(e) - a, o = this.dataset.getY(e);
334
506
  if (r === "points") {
335
- let e = d * 2;
507
+ let e = f * 2;
336
508
  t[e] = n, t[e + 1] = o;
337
509
  } else {
338
- let e = d * 4;
510
+ let e = f * 4;
339
511
  t[e] = n, t[e + 1] = i, t[e + 2] = n, t[e + 3] = o;
340
512
  }
341
- d++;
513
+ f++;
342
514
  }
343
- return d;
344
- }
345
- copySampleRange(e, t, n, r, i, a, o) {
346
- let s = i === "points" ? 2 : 4;
347
- if (r <= 0 || n.length < r * s) return 0;
348
- let c = Math.max(0, Math.floor(e)), l = Math.min(this.dataset.length, Math.ceil(t)), u = Math.min(r, Math.max(0, l - c));
349
- for (let e = 0; e < u; e++) {
350
- let t = c + e, r = this.dataset.getX(t) - o, s = this.dataset.getY(t);
515
+ return f;
516
+ }
517
+ copySampleRange(e, t, n, r, i, o, s) {
518
+ if (a(this.dataset)) return this.dataset.copySamplesRange(e, t, n, r, i, o, s);
519
+ let c = i === "points" ? 2 : 4;
520
+ if (r <= 0 || n.length < r * c) return 0;
521
+ let l = Math.max(0, Math.floor(e)), u = Math.min(this.dataset.length, Math.ceil(t)), d = Math.min(r, Math.max(0, u - l));
522
+ for (let e = 0; e < d; e++) {
523
+ let t = l + e, r = this.dataset.getX(t) - s, a = this.dataset.getY(t);
351
524
  if (i === "points") {
352
525
  let t = e * 2;
353
- n[t] = r, n[t + 1] = s;
526
+ n[t] = r, n[t + 1] = a;
354
527
  } else {
355
528
  let t = e * 4;
356
- n[t] = r, n[t + 1] = a, n[t + 2] = r, n[t + 3] = s;
529
+ n[t] = r, n[t + 1] = o, n[t + 2] = r, n[t + 3] = a;
357
530
  }
358
531
  }
359
- return u;
532
+ return d;
360
533
  }
361
534
  copyMinMaxSegments(e, t, n, r, i) {
535
+ if (o(this.dataset)) return this.dataset.copyMinMaxSegments(e, t, n, r, i);
362
536
  let a = r === "line-list" ? 4 : 3;
363
537
  if (!this.pyramid || n <= 0 || t.length < n * a) return 0;
364
- let o = this.dataset.lowerBoundX(e.xMin), s = this.dataset.upperBoundX(e.xMax), c = s - o;
365
- if (c <= 0) return 0;
366
- let l = Math.min(n, c);
367
- for (let e = 0; e < l; e++) {
368
- let n = o + Math.floor(e * c / l), a = o + Math.max(Math.floor((e + 1) * c / l), Math.floor(e * c / l) + 1), u = Math.min(s, a), d = this.minMaxForRange(n, u);
538
+ let s = this.dataset.lowerBoundX(e.xMin), c = this.dataset.upperBoundX(e.xMax), l = c - s;
539
+ if (l <= 0) return 0;
540
+ let u = Math.min(n, l);
541
+ for (let e = 0; e < u; e++) {
542
+ let n = s + Math.floor(e * l / u), a = s + Math.max(Math.floor((e + 1) * l / u), Math.floor(e * l / u) + 1), o = Math.min(c, a), d = this.minMaxForRange(n, o);
369
543
  if (!d) continue;
370
- let f = this.dataset.getX(n + (u - n >> 1)) - i, { minY: p, maxY: m } = d;
544
+ let f = this.dataset.getX(n + (o - n >> 1)) - i, { minY: p, maxY: m } = d;
371
545
  if (r === "line-list") {
372
546
  let n = e * 4;
373
547
  t[n] = f, t[n + 1] = p, t[n + 2] = f, t[n + 3] = m;
@@ -376,7 +550,7 @@ var o = class {
376
550
  t[n] = f, t[n + 1] = p, t[n + 2] = m;
377
551
  }
378
552
  }
379
- return l;
553
+ return u;
380
554
  }
381
555
  minMaxForRange(e, t) {
382
556
  return this._useDatasetRangeMinMax && r(this.dataset) ? this.dataset.rangeMinMaxY(e, t) : !this.pyramid || this._useRawMinMaxScan ? this.rawMinMaxForRange(e, t) : this.pyramid.rangeMinMax(this.dataset, e, t);
@@ -417,7 +591,7 @@ var o = class {
417
591
  };
418
592
  //#endregion
419
593
  //#region src/core/search.ts
420
- function s(e, t, n) {
594
+ function m(e, t, n) {
421
595
  let r = 0, i = e;
422
596
  for (; r < i;) {
423
597
  let e = r + (i - r >> 1);
@@ -425,7 +599,7 @@ function s(e, t, n) {
425
599
  }
426
600
  return r;
427
601
  }
428
- function c(e, t, n) {
602
+ function h(e, t, n) {
429
603
  let r = 0, i = e;
430
604
  for (; r < i;) {
431
605
  let e = r + (i - r >> 1);
@@ -435,7 +609,7 @@ function c(e, t, n) {
435
609
  }
436
610
  //#endregion
437
611
  //#region src/core/RingBuffer.ts
438
- var l = class e {
612
+ var g = class e {
439
613
  capacity;
440
614
  _length = 0;
441
615
  _head = 0;
@@ -497,10 +671,10 @@ var l = class e {
497
671
  return this.assertValidIndex(e), this.yData[this.logicalToPhysical(e)];
498
672
  }
499
673
  lowerBoundX(e) {
500
- return s(this._length, (e) => this.getX(e), e);
674
+ return m(this._length, (e) => this.getX(e), e);
501
675
  }
502
676
  upperBoundX(e) {
503
- return c(this._length, (e) => this.getX(e), e);
677
+ return h(this._length, (e) => this.getX(e), e);
504
678
  }
505
679
  rangeMinMaxY(e, t) {
506
680
  let n = Math.max(0, Math.floor(e)), r = Math.min(this._length, Math.ceil(t));
@@ -577,32 +751,32 @@ var l = class e {
577
751
  static nextPowerOfTwo(e) {
578
752
  return 2 ** Math.ceil(Math.log2(e));
579
753
  }
580
- }, u = "attribute vec2 position;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", d = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", f = "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\nattribute float aSelect;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n float y = (aSelect < 0.5) ? aMinY : aMaxY;\n vec2 position = vec2(aX, y);\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", p = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", m = "attribute vec2 aPosition;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform vec2 uCanvasSize;\nuniform float uPointSize;\n\nvoid main() {\n vec2 centerClip = aPosition * uScale + uOffset;\n vec2 pointSizeClip = vec2(2.0 / uCanvasSize.x, 2.0 / uCanvasSize.y) * uPointSize * 0.5;\n vec2 clipSpace = centerClip + aCorner * pointSizeClip;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", h = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", g = "attribute vec2 aPosition;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uPointSize;\n\nvoid main() {\n vec2 clipSpace = aPosition * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n gl_PointSize = uPointSize;\n}\n", _ = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n vec2 p = gl_PointCoord * 2.0 - 1.0;\n if (dot(p, p) > 1.0) discard;\n gl_FragColor = uColor;\n}\n", v = "attribute vec2 aPosition;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uBarWidth;\nuniform float uBaseline;\n\nvoid main() {\n float x = aPosition.x + aCorner.x * uBarWidth;\n float y = mix(uBaseline, aPosition.y, aCorner.y);\n vec2 clipSpace = vec2(x, y) * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", y = "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uBarWidth;\n\nvoid main() {\n float x = aX + aCorner.x * uBarWidth;\n float y = mix(aMinY, aMaxY, aCorner.y);\n vec2 clipSpace = vec2(x, y) * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", b = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", x = {
754
+ }, _ = "attribute vec2 position;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", v = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", y = "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\nattribute float aSelect;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n float y = (aSelect < 0.5) ? aMinY : aMaxY;\n vec2 position = vec2(aX, y);\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", b = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", x = "attribute vec2 aPosition;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform vec2 uCanvasSize;\nuniform float uPointSize;\n\nvoid main() {\n vec2 centerClip = aPosition * uScale + uOffset;\n vec2 pointSizeClip = vec2(2.0 / uCanvasSize.x, 2.0 / uCanvasSize.y) * uPointSize * 0.5;\n vec2 clipSpace = centerClip + aCorner * pointSizeClip;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", S = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", C = "attribute vec2 aPosition;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uPointSize;\n\nvoid main() {\n vec2 clipSpace = aPosition * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n gl_PointSize = uPointSize;\n}\n", ee = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n vec2 p = gl_PointCoord * 2.0 - 1.0;\n if (dot(p, p) > 1.0) discard;\n gl_FragColor = uColor;\n}\n", te = "attribute vec2 aPosition;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uBarWidth;\nuniform float uBaseline;\n\nvoid main() {\n float x = aPosition.x + aCorner.x * uBarWidth;\n float y = mix(uBaseline, aPosition.y, aCorner.y);\n vec2 clipSpace = vec2(x, y) * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", ne = "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uBarWidth;\n\nvoid main() {\n float x = aX + aCorner.x * uBarWidth;\n float y = mix(aMinY, aMaxY, aCorner.y);\n vec2 clipSpace = vec2(x, y) * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", w = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", T = {
581
755
  line: {
582
- vert: u,
583
- frag: d
756
+ vert: _,
757
+ frag: v
584
758
  },
585
759
  segment: {
586
- vert: f,
587
- frag: p
760
+ vert: y,
761
+ frag: b
588
762
  },
589
763
  point: {
590
- vert: m,
591
- frag: h
764
+ vert: x,
765
+ frag: S
592
766
  },
593
767
  pointSprite: {
594
- vert: g,
595
- frag: _
768
+ vert: C,
769
+ frag: ee
596
770
  },
597
771
  bar: {
598
- vert: v,
599
- frag: b
772
+ vert: te,
773
+ frag: w
600
774
  },
601
775
  barRange: {
602
- vert: y,
603
- frag: b
776
+ vert: ne,
777
+ frag: w
604
778
  }
605
- }, S = 3, C = 2, w = 4, T = 4, E = .8, ee = 0, te = class {
779
+ }, E = 3, D = 2, O = 4, k = 4, A = .8, re = 0, ie = class {
606
780
  backend;
607
781
  lineProgram;
608
782
  segmentProgram;
@@ -618,7 +792,7 @@ var l = class e {
618
792
  canvasSizeUniform = new Float32Array(2);
619
793
  xOrigin = 0;
620
794
  constructor(e) {
621
- this.backend = e, this.lineProgram = this.backend.createProgram(x.line.vert, x.line.frag), this.segmentProgram = this.backend.createProgram(x.segment.vert, x.segment.frag), this.pointProgram = this.backend.createProgram(x.point.vert, x.point.frag), this.pointSpriteProgram = this.backend.createProgram(x.pointSprite.vert, x.pointSprite.frag), this.barProgram = this.backend.createProgram(x.bar.vert, x.bar.frag), this.barRangeProgram = this.backend.createProgram(x.barRange.vert, x.barRange.frag), this.segmentSelectBuffer = this.backend.createBuffer({
795
+ this.backend = e, this.lineProgram = this.backend.createProgram(T.line.vert, T.line.frag), this.segmentProgram = this.backend.createProgram(T.segment.vert, T.segment.frag), this.pointProgram = this.backend.createProgram(T.point.vert, T.point.frag), this.pointSpriteProgram = this.backend.createProgram(T.pointSprite.vert, T.pointSprite.frag), this.barProgram = this.backend.createProgram(T.bar.vert, T.bar.frag), this.barRangeProgram = this.backend.createProgram(T.barRange.vert, T.barRange.frag), this.segmentSelectBuffer = this.backend.createBuffer({
622
796
  usage: "static",
623
797
  type: "float",
624
798
  length: 2
@@ -679,6 +853,9 @@ var l = class e {
679
853
  setXOrigin(e) {
680
854
  this.xOrigin = Number.isFinite(e) ? e : 0;
681
855
  }
856
+ getWebGLContext() {
857
+ return this.backend.getContext?.() ?? null;
858
+ }
682
859
  drawLines(e, t, n, r) {
683
860
  this.drawLinePrimitive("lines", e, t, n, r);
684
861
  }
@@ -696,7 +873,7 @@ var l = class e {
696
873
  }
697
874
  drawMinMaxSegmentsInstanced(e, t, n, r) {
698
875
  this.writeCameraUniforms(r);
699
- let i = S * w, a = {
876
+ let i = E * O, a = {
700
877
  buffer: e,
701
878
  divisor: 1,
702
879
  stride: i,
@@ -705,16 +882,16 @@ var l = class e {
705
882
  buffer: e,
706
883
  divisor: 1,
707
884
  stride: i,
708
- offset: w
885
+ offset: O
709
886
  }, s = {
710
887
  buffer: e,
711
888
  divisor: 1,
712
889
  stride: i,
713
- offset: w * 2
890
+ offset: O * 2
714
891
  }, c = {
715
892
  buffer: this.segmentSelectBuffer,
716
893
  divisor: 0,
717
- stride: w,
894
+ stride: O,
718
895
  offset: 0
719
896
  };
720
897
  this.backend.draw({
@@ -743,13 +920,13 @@ var l = class e {
743
920
  let o = {
744
921
  buffer: e,
745
922
  divisor: 1,
746
- stride: C * w,
923
+ stride: D * O,
747
924
  offset: 0,
748
925
  size: 2
749
926
  }, s = {
750
927
  buffer: this.pointCornerBuffer,
751
928
  divisor: 0,
752
- stride: C * w,
929
+ stride: D * O,
753
930
  offset: 0,
754
931
  size: 2
755
932
  };
@@ -766,7 +943,7 @@ var l = class e {
766
943
  uScale: this.scaleUniform,
767
944
  uOffset: this.offsetUniform,
768
945
  uCanvasSize: this.canvasSizeUniform,
769
- uPointSize: n.pointSize ?? T,
946
+ uPointSize: n.pointSize ?? k,
770
947
  uColor: n.color
771
948
  }
772
949
  });
@@ -780,7 +957,7 @@ var l = class e {
780
957
  uniforms: {
781
958
  uScale: this.scaleUniform,
782
959
  uOffset: this.offsetUniform,
783
- uPointSize: n.pointSize ?? T,
960
+ uPointSize: n.pointSize ?? k,
784
961
  uColor: n.color
785
962
  }
786
963
  });
@@ -803,13 +980,13 @@ var l = class e {
803
980
  let i = {
804
981
  buffer: e,
805
982
  divisor: 1,
806
- stride: C * w,
983
+ stride: D * O,
807
984
  offset: 0,
808
985
  size: 2
809
986
  }, a = {
810
987
  buffer: this.barCornerBuffer,
811
988
  divisor: 0,
812
- stride: C * w,
989
+ stride: D * O,
813
990
  offset: 0,
814
991
  size: 2
815
992
  };
@@ -825,15 +1002,15 @@ var l = class e {
825
1002
  uniforms: {
826
1003
  uScale: this.scaleUniform,
827
1004
  uOffset: this.offsetUniform,
828
- uBarWidth: n.barWidth ?? E,
829
- uBaseline: n.baseline ?? ee,
1005
+ uBarWidth: n.barWidth ?? A,
1006
+ uBaseline: n.baseline ?? re,
830
1007
  uColor: n.color
831
1008
  }
832
1009
  });
833
1010
  }
834
1011
  drawBarRangesInstanced(e, t, n, r) {
835
1012
  this.writeCameraUniforms(r);
836
- let i = S * w, a = {
1013
+ let i = E * O, a = {
837
1014
  buffer: e,
838
1015
  divisor: 1,
839
1016
  stride: i,
@@ -842,16 +1019,16 @@ var l = class e {
842
1019
  buffer: e,
843
1020
  divisor: 1,
844
1021
  stride: i,
845
- offset: w
1022
+ offset: O
846
1023
  }, s = {
847
1024
  buffer: e,
848
1025
  divisor: 1,
849
1026
  stride: i,
850
- offset: w * 2
1027
+ offset: O * 2
851
1028
  }, c = {
852
1029
  buffer: this.barCornerBuffer,
853
1030
  divisor: 0,
854
- stride: C * w,
1031
+ stride: D * O,
855
1032
  offset: 0,
856
1033
  size: 2
857
1034
  };
@@ -869,7 +1046,7 @@ var l = class e {
869
1046
  uniforms: {
870
1047
  uScale: this.scaleUniform,
871
1048
  uOffset: this.offsetUniform,
872
- uBarWidth: n.barWidth ?? E,
1049
+ uBarWidth: n.barWidth ?? A,
873
1050
  uColor: n.color
874
1051
  }
875
1052
  });
@@ -923,13 +1100,13 @@ var l = class e {
923
1100
  dispose() {
924
1101
  this.backend.destroy();
925
1102
  }
926
- }, D = [
1103
+ }, j = [
927
1104
  1024,
928
1105
  4096,
929
1106
  16384,
930
1107
  32768,
931
1108
  131072
932
- ], O = class {
1109
+ ], ae = class {
933
1110
  regl;
934
1111
  pool = [];
935
1112
  preAllocated = !1;
@@ -942,7 +1119,7 @@ var l = class e {
942
1119
  preAllocate() {
943
1120
  if (!this.preAllocated) {
944
1121
  this.preAllocated = !0;
945
- for (let e of D) this.pool.push(this.createEntry(e, "stream"));
1122
+ for (let e of j) this.pool.push(this.createEntry(e, "stream"));
946
1123
  }
947
1124
  }
948
1125
  acquire(e, t = "stream") {
@@ -982,17 +1159,17 @@ var l = class e {
982
1159
  return this.pool.find((t) => !t.inUse && t.floatCapacity >= e);
983
1160
  }
984
1161
  roundUp(e) {
985
- for (let t of D) if (t >= e) return t;
986
- let t = D[D.length - 1], n = 1 << 32 - Math.clz32(e - 1);
1162
+ for (let t of j) if (t >= e) return t;
1163
+ let t = j[j.length - 1], n = 1 << 32 - Math.clz32(e - 1);
987
1164
  return Math.max(t * 2, n);
988
1165
  }
989
1166
  };
990
1167
  //#endregion
991
1168
  //#region src/render/ReglBackend.ts
992
- function k(e) {
1169
+ function oe(e) {
993
1170
  return e;
994
1171
  }
995
- var A = class {
1172
+ var se = class {
996
1173
  gl;
997
1174
  regl;
998
1175
  resources;
@@ -1012,10 +1189,10 @@ var A = class {
1012
1189
  });
1013
1190
  if (!n) throw Error("BlazePlot requires WebGL2, but this browser/context does not support it.");
1014
1191
  this.gl = n, this.regl = e({
1015
- gl: k(this.gl),
1192
+ gl: oe(this.gl),
1016
1193
  extensions: [],
1017
1194
  optionalExtensions: ["angle_instanced_arrays", "ext_disjoint_timer_query_webgl2"]
1018
- }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new O(this.regl), this.resources.preAllocate();
1195
+ }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new ae(this.regl), this.resources.preAllocate();
1019
1196
  }
1020
1197
  createBuffer(e) {
1021
1198
  let { buffer: t } = this.resources.acquire(e.length, e.usage);
@@ -1081,6 +1258,9 @@ var A = class {
1081
1258
  h: r
1082
1259
  };
1083
1260
  }
1261
+ getContext() {
1262
+ return this.gl;
1263
+ }
1084
1264
  destroy() {
1085
1265
  this.resources.destroy(), this.regl.destroy();
1086
1266
  }
@@ -1134,7 +1314,7 @@ var A = class {
1134
1314
  default: return e;
1135
1315
  }
1136
1316
  }
1137
- }, j = class e {
1317
+ }, M = class e {
1138
1318
  _xMin = 0;
1139
1319
  _xMax = 1;
1140
1320
  _yMin = 0;
@@ -1219,7 +1399,7 @@ var A = class {
1219
1399
  static assertFinite(e, t) {
1220
1400
  if (!Number.isFinite(t)) throw RangeError(`Camera2D ${e} must be finite.`);
1221
1401
  }
1222
- }, M = class {
1402
+ }, N = class {
1223
1403
  camera;
1224
1404
  constructor(e) {
1225
1405
  this.camera = e;
@@ -1251,33 +1431,39 @@ var A = class {
1251
1431
  let n = Math.max(0, -Math.floor(Math.log10(t)) + 2), r = Number(e.toFixed(n));
1252
1432
  return Object.is(r, -0) ? 0 : r;
1253
1433
  }
1254
- }, N = class {
1434
+ }, P = class {
1255
1435
  layout;
1256
1436
  config;
1257
1437
  options;
1258
1438
  xPool = [];
1259
1439
  yPool = [];
1440
+ y2Pool = [];
1260
1441
  xTicks = [];
1261
1442
  yTicks = [];
1443
+ y2Ticks = [];
1262
1444
  constructor(e, t, n = {}) {
1263
1445
  this.layout = e, this.config = t, this.options = n;
1264
1446
  }
1265
1447
  setOptions(e) {
1266
1448
  this.options = e;
1267
- for (let e of this.xPool) e.style.font = this.options.font ?? "11px ui-monospace, monospace, sans-serif", e.style.color = this.options.color ?? "#bfd6ff";
1268
- for (let e of this.yPool) e.style.font = this.options.font ?? "11px ui-monospace, monospace, sans-serif", e.style.color = this.options.color ?? "#bfd6ff";
1449
+ for (let e of [
1450
+ ...this.xPool,
1451
+ ...this.yPool,
1452
+ ...this.y2Pool
1453
+ ]) e.style.font = this.options.font ?? "11px ui-monospace, monospace, sans-serif", e.style.color = this.options.color ?? "#bfd6ff";
1269
1454
  }
1270
- update(e, t) {
1271
- let n = Math.max(1, this.layout.plot.clientWidth), r = Math.max(1, this.layout.plot.clientHeight);
1272
- this.config.x.visible ? t.getXTickValues(n, 12, this.xTicks) : this.xTicks.length = 0, this.config.y.visible ? t.getYTickValues(r, 8, this.yTicks) : this.yTicks.length = 0, this.updateAxis(this.xPool, this.xTicks, "x", e, n, r, t), this.updateAxis(this.yPool, this.yTicks, "y", e, n, r, t);
1455
+ update(e, t, n = e, r = t) {
1456
+ let i = Math.max(1, this.layout.plot.clientWidth), a = Math.max(1, this.layout.plot.clientHeight);
1457
+ this.config.x.visible ? t.getXTickValues(i, 12, this.xTicks) : this.xTicks.length = 0, this.config.y.visible ? t.getYTickValues(a, 8, this.yTicks) : this.yTicks.length = 0, this.config.y2.visible ? r.getYTickValues(a, 8, this.y2Ticks) : this.y2Ticks.length = 0, this.updateAxis(this.xPool, this.xTicks, "x", e, i, a, t), this.updateAxis(this.yPool, this.yTicks, "y", e, i, a, t), this.updateAxis(this.y2Pool, this.y2Ticks, "y2", n, i, a, r);
1273
1458
  }
1274
1459
  dispose() {
1275
1460
  for (let e of this.xPool) e.remove();
1276
1461
  for (let e of this.yPool) e.remove();
1277
- this.xPool = [], this.yPool = [];
1462
+ for (let e of this.y2Pool) e.remove();
1463
+ this.xPool = [], this.yPool = [], this.y2Pool = [];
1278
1464
  }
1279
1465
  parentForAxis(e) {
1280
- return e === "x" ? this.config.x.position === "outside" ? this.layout.xAxis : this.layout.plot : this.config.y.position === "outside" ? this.layout.yAxis : this.layout.plot;
1466
+ return e === "x" ? this.config.x.position === "outside" ? this.layout.xAxis : this.layout.plot : e === "y2" ? this.config.y2.position === "outside" ? this.layout.y2Axis : this.layout.plot : this.config.y.position === "outside" ? this.layout.yAxis : this.layout.plot;
1281
1467
  }
1282
1468
  updateAxis(e, t, n, r, i, a, o) {
1283
1469
  let s = this.parentForAxis(n);
@@ -1293,53 +1479,55 @@ var A = class {
1293
1479
  let [e] = r.toClip(l, r.yMin), t = (e + 1) * .5 * i;
1294
1480
  c.style.left = `${t}px`, c.style.right = "auto", c.style.transform = "translateX(-50%)", this.config.x.position === "outside" ? (c.style.top = "4px", c.style.bottom = "auto") : (c.style.top = "auto", c.style.bottom = "4px");
1295
1481
  } else {
1296
- let [, e] = r.toClip(r.xMin, l), t = (1 - e) * .5 * a;
1297
- c.style.top = `${t}px`, c.style.bottom = "auto", c.style.transform = "translateY(-50%)", this.config.y.position === "outside" ? (c.style.left = "auto", c.style.right = "4px") : (c.style.left = "4px", c.style.right = "auto");
1482
+ let e = n === "y2", t = e ? this.config.y2 : this.config.y, [, i] = r.toClip(r.xMin, l), o = (1 - i) * .5 * a;
1483
+ c.style.top = `${o}px`, c.style.bottom = "auto", c.style.transform = "translateY(-50%)", t.position === "outside" ? (c.style.left = e ? "4px" : "auto", c.style.right = e ? "auto" : "4px") : (c.style.left = e ? "auto" : "4px", c.style.right = e ? "4px" : "auto");
1298
1484
  }
1299
1485
  }
1300
1486
  }
1301
- }, ne = class {
1487
+ }, ce = class {
1302
1488
  root;
1303
1489
  plot;
1304
1490
  canvas;
1305
1491
  xAxis;
1306
1492
  yAxis;
1493
+ y2Axis;
1307
1494
  corner;
1495
+ cornerRight;
1308
1496
  externalCanvas;
1309
1497
  originalCanvasCssText;
1310
1498
  originalCanvasParent;
1311
1499
  constructor(e, t) {
1312
1500
  let n = e instanceof HTMLCanvasElement ? e : null;
1313
- this.externalCanvas = n !== null, this.originalCanvasCssText = n?.style.cssText ?? "", this.originalCanvasParent = n?.parentElement ?? null, this.root = document.createElement("div"), this.plot = document.createElement("div"), this.canvas = n ?? document.createElement("canvas"), this.xAxis = document.createElement("div"), this.yAxis = document.createElement("div"), this.corner = document.createElement("div"), this.root.className = "blazeplot-root", this.plot.className = "blazeplot-plot", this.canvas.classList.add("blazeplot-canvas"), this.xAxis.className = "blazeplot-axis blazeplot-axis-x", this.yAxis.className = "blazeplot-axis blazeplot-axis-y", this.corner.className = "blazeplot-axis-corner", this.applyBaseStyles(), this.mount(e), this.update(t);
1501
+ this.externalCanvas = n !== null, this.originalCanvasCssText = n?.style.cssText ?? "", this.originalCanvasParent = n?.parentElement ?? null, this.root = document.createElement("div"), this.plot = document.createElement("div"), this.canvas = n ?? document.createElement("canvas"), this.xAxis = document.createElement("div"), this.yAxis = document.createElement("div"), this.y2Axis = document.createElement("div"), this.corner = document.createElement("div"), this.cornerRight = document.createElement("div"), this.root.className = "blazeplot-root", this.plot.className = "blazeplot-plot", this.canvas.classList.add("blazeplot-canvas"), this.xAxis.className = "blazeplot-axis blazeplot-axis-x", this.yAxis.className = "blazeplot-axis blazeplot-axis-y", this.y2Axis.className = "blazeplot-axis blazeplot-axis-y2", this.corner.className = "blazeplot-axis-corner", this.cornerRight.className = "blazeplot-axis-corner blazeplot-axis-corner-right", this.applyBaseStyles(), this.mount(e), this.update(t);
1314
1502
  }
1315
1503
  update(e) {
1316
- let t = e.y.visible && e.y.position === "outside", n = e.x.visible && e.x.position === "outside";
1317
- this.root.style.gridTemplateColumns = `${t ? 52 : 0}px minmax(0, 1fr)`, this.root.style.gridTemplateRows = `minmax(0, 1fr) ${n ? 28 : 0}px`, this.yAxis.style.display = t ? "block" : "none", this.xAxis.style.display = n ? "block" : "none", this.corner.style.display = n && t ? "block" : "none";
1504
+ let t = e.y.visible && e.y.position === "outside", n = e.y2.visible && e.y2.position === "outside", r = e.x.visible && e.x.position === "outside";
1505
+ this.root.style.gridTemplateColumns = `${t ? 52 : 0}px minmax(0, 1fr) ${n ? 52 : 0}px`, this.root.style.gridTemplateRows = `minmax(0, 1fr) ${r ? 28 : 0}px`, this.yAxis.style.display = t ? "block" : "none", this.y2Axis.style.display = n ? "block" : "none", this.xAxis.style.display = r ? "block" : "none", this.corner.style.display = r && t ? "block" : "none", this.cornerRight.style.display = r && n ? "block" : "none";
1318
1506
  }
1319
1507
  dispose() {
1320
1508
  this.externalCanvas && this.originalCanvasParent && (this.canvas.style.cssText = this.originalCanvasCssText, this.originalCanvasParent.insertBefore(this.canvas, this.root)), this.root.remove();
1321
1509
  }
1322
1510
  mount(e) {
1323
- this.externalCanvas ? this.originalCanvasParent?.insertBefore(this.root, e) : e.appendChild(this.root), this.root.appendChild(this.yAxis), this.root.appendChild(this.plot), this.root.appendChild(this.corner), this.root.appendChild(this.xAxis), this.plot.appendChild(this.canvas);
1511
+ this.externalCanvas ? this.originalCanvasParent?.insertBefore(this.root, e) : e.appendChild(this.root), this.root.appendChild(this.yAxis), this.root.appendChild(this.plot), this.root.appendChild(this.y2Axis), this.root.appendChild(this.corner), this.root.appendChild(this.xAxis), this.root.appendChild(this.cornerRight), this.plot.appendChild(this.canvas);
1324
1512
  }
1325
1513
  applyBaseStyles() {
1326
- this.root.style.position = "relative", this.root.style.display = "grid", this.root.style.width = "100%", this.root.style.height = "100%", this.root.style.minWidth = "0", this.root.style.minHeight = "0", this.root.style.overflow = "hidden", this.plot.style.position = "relative", this.plot.style.gridColumn = "2", this.plot.style.gridRow = "1", this.plot.style.minWidth = "0", this.plot.style.minHeight = "0", this.plot.style.overflow = "hidden", this.canvas.style.position = "absolute", this.canvas.style.inset = "0", this.canvas.style.display = "block", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.touchAction = "none", this.yAxis.style.position = "relative", this.yAxis.style.gridColumn = "1", this.yAxis.style.gridRow = "1", this.yAxis.style.minWidth = "0", this.yAxis.style.minHeight = "0", this.yAxis.style.overflow = "hidden", this.yAxis.style.pointerEvents = "none", this.xAxis.style.position = "relative", this.xAxis.style.gridColumn = "2", this.xAxis.style.gridRow = "2", this.xAxis.style.minWidth = "0", this.xAxis.style.minHeight = "0", this.xAxis.style.overflow = "hidden", this.xAxis.style.pointerEvents = "none", this.corner.style.gridColumn = "1", this.corner.style.gridRow = "2", this.corner.style.minWidth = "0", this.corner.style.minHeight = "0", this.corner.style.pointerEvents = "none";
1514
+ this.root.style.position = "relative", this.root.style.display = "grid", this.root.style.width = "100%", this.root.style.height = "100%", this.root.style.minWidth = "0", this.root.style.minHeight = "0", this.root.style.overflow = "hidden", this.plot.style.position = "relative", this.plot.style.gridColumn = "2", this.plot.style.gridRow = "1", this.plot.style.minWidth = "0", this.plot.style.minHeight = "0", this.plot.style.overflow = "hidden", this.canvas.style.position = "absolute", this.canvas.style.inset = "0", this.canvas.style.display = "block", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.touchAction = "none", this.yAxis.style.position = "relative", this.yAxis.style.gridColumn = "1", this.yAxis.style.gridRow = "1", this.yAxis.style.minWidth = "0", this.yAxis.style.minHeight = "0", this.yAxis.style.overflow = "hidden", this.yAxis.style.pointerEvents = "none", this.y2Axis.style.position = "relative", this.y2Axis.style.gridColumn = "3", this.y2Axis.style.gridRow = "1", this.y2Axis.style.minWidth = "0", this.y2Axis.style.minHeight = "0", this.y2Axis.style.overflow = "hidden", this.y2Axis.style.pointerEvents = "none", this.xAxis.style.position = "relative", this.xAxis.style.gridColumn = "2", this.xAxis.style.gridRow = "2", this.xAxis.style.minWidth = "0", this.xAxis.style.minHeight = "0", this.xAxis.style.overflow = "hidden", this.xAxis.style.pointerEvents = "none", this.corner.style.gridColumn = "1", this.corner.style.gridRow = "2", this.corner.style.minWidth = "0", this.corner.style.minHeight = "0", this.corner.style.pointerEvents = "none", this.cornerRight.style.gridColumn = "3", this.cornerRight.style.gridRow = "2", this.cornerRight.style.minWidth = "0", this.cornerRight.style.minHeight = "0", this.cornerRight.style.pointerEvents = "none";
1327
1515
  }
1328
- }, P = {
1516
+ }, F = {
1329
1517
  backgroundColor: [
1330
- .08,
1331
- .1,
1332
- .16,
1518
+ .02,
1519
+ .02,
1520
+ .02,
1333
1521
  1
1334
1522
  ],
1335
- backgroundCssColor: "rgba(20, 26, 41, 1)",
1523
+ backgroundCssColor: "rgba(5, 5, 5, 1)",
1336
1524
  gridColor: [
1337
1525
  .22,
1338
- .3,
1339
- .44,
1526
+ .22,
1527
+ .22,
1340
1528
  .45
1341
1529
  ],
1342
- axisColor: "#bfd6ff",
1530
+ axisColor: "#d4d4d4",
1343
1531
  axisFont: "11px ui-monospace, monospace, sans-serif",
1344
1532
  seriesColors: [
1345
1533
  [
@@ -1379,48 +1567,48 @@ var A = class {
1379
1567
  1
1380
1568
  ]
1381
1569
  ],
1382
- tooltipBackgroundColor: "rgba(4, 8, 16, 0.85)",
1383
- tooltipTextColor: "#bfd6ff",
1570
+ tooltipBackgroundColor: "rgba(10, 10, 10, 0.88)",
1571
+ tooltipTextColor: "#e5e5e5",
1384
1572
  tooltipFont: "11px/1.35 ui-monospace, monospace",
1385
- legendBackgroundColor: "rgba(4, 8, 16, 0.85)",
1573
+ legendBackgroundColor: "rgba(10, 10, 10, 0.88)",
1386
1574
  legendBorderColor: "transparent",
1387
- legendTextColor: "#bfd6ff",
1388
- legendMutedTextColor: "#789",
1575
+ legendTextColor: "#e5e5e5",
1576
+ legendMutedTextColor: "#888",
1389
1577
  legendFont: "11px/1.35 ui-monospace, monospace"
1390
1578
  };
1391
- function F(e, t) {
1392
- if (!e) return P;
1393
- let n = I(e.backgroundColor, P.backgroundColor, t), r = e.seriesColors?.length ? e.seriesColors.map((e, n) => I(e, P.seriesColors[n % P.seriesColors.length], t)) : P.seriesColors;
1579
+ function I(e, t) {
1580
+ if (!e) return F;
1581
+ let n = L(e.backgroundColor, F.backgroundColor, t), r = e.seriesColors?.length ? e.seriesColors.map((e, n) => L(e, F.seriesColors[n % F.seriesColors.length], t)) : F.seriesColors;
1394
1582
  return {
1395
1583
  backgroundColor: n,
1396
- backgroundCssColor: L(e.backgroundColor, P.backgroundCssColor),
1397
- gridColor: I(e.gridColor, P.gridColor, t),
1398
- axisColor: e.axisColor ?? P.axisColor,
1399
- axisFont: e.axisFont ?? P.axisFont,
1584
+ backgroundCssColor: le(e.backgroundColor, F.backgroundCssColor),
1585
+ gridColor: L(e.gridColor, F.gridColor, t),
1586
+ axisColor: e.axisColor ?? F.axisColor,
1587
+ axisFont: e.axisFont ?? F.axisFont,
1400
1588
  seriesColors: r,
1401
- tooltipBackgroundColor: e.tooltipBackgroundColor ?? P.tooltipBackgroundColor,
1402
- tooltipTextColor: e.tooltipTextColor ?? P.tooltipTextColor,
1403
- tooltipFont: e.tooltipFont ?? P.tooltipFont,
1404
- legendBackgroundColor: e.legendBackgroundColor ?? P.legendBackgroundColor,
1405
- legendBorderColor: e.legendBorderColor ?? P.legendBorderColor,
1406
- legendTextColor: e.legendTextColor ?? P.legendTextColor,
1407
- legendMutedTextColor: e.legendMutedTextColor ?? P.legendMutedTextColor,
1408
- legendFont: e.legendFont ?? P.legendFont
1589
+ tooltipBackgroundColor: e.tooltipBackgroundColor ?? F.tooltipBackgroundColor,
1590
+ tooltipTextColor: e.tooltipTextColor ?? F.tooltipTextColor,
1591
+ tooltipFont: e.tooltipFont ?? F.tooltipFont,
1592
+ legendBackgroundColor: e.legendBackgroundColor ?? F.legendBackgroundColor,
1593
+ legendBorderColor: e.legendBorderColor ?? F.legendBorderColor,
1594
+ legendTextColor: e.legendTextColor ?? F.legendTextColor,
1595
+ legendMutedTextColor: e.legendMutedTextColor ?? F.legendMutedTextColor,
1596
+ legendFont: e.legendFont ?? F.legendFont
1409
1597
  };
1410
1598
  }
1411
- function I(e, t, n) {
1599
+ function L(e, t, n) {
1412
1600
  if (!e) return t;
1413
1601
  if (typeof e != "string") return e;
1414
- let r = re(e, n), i = B(r ?? e, n);
1602
+ let r = ue(e, n), i = de(r ?? e, n);
1415
1603
  return z(r ?? e) ?? z(i ?? "") ?? t;
1416
1604
  }
1417
- function L(e, t) {
1605
+ function le(e, t) {
1418
1606
  return e ? typeof e == "string" ? e : R(e) : t;
1419
1607
  }
1420
1608
  function R(e) {
1421
1609
  return `rgba(${Math.round(e[0] * 255)}, ${Math.round(e[1] * 255)}, ${Math.round(e[2] * 255)}, ${e[3]})`;
1422
1610
  }
1423
- function re(e, t) {
1611
+ function ue(e, t) {
1424
1612
  let n = t?.ownerDocument ?? globalThis.document;
1425
1613
  if (!n?.documentElement || typeof getComputedStyle > "u") return null;
1426
1614
  let r = t instanceof HTMLElement ? t : n.documentElement, i = n.createElement("span");
@@ -1430,9 +1618,9 @@ function re(e, t) {
1430
1618
  }
1431
1619
  function z(e) {
1432
1620
  let t = e.trim();
1433
- return ie(t) ?? ae(t) ?? oe(t);
1621
+ return fe(t) ?? pe(t) ?? me(t);
1434
1622
  }
1435
- function B(e, t) {
1623
+ function de(e, t) {
1436
1624
  let n = t?.ownerDocument ?? globalThis.document;
1437
1625
  if (!n?.createElement) return null;
1438
1626
  let r = n.createElement("canvas").getContext("2d");
@@ -1442,12 +1630,12 @@ function B(e, t) {
1442
1630
  let a = String(r.fillStyle);
1443
1631
  return a === i ? null : a;
1444
1632
  }
1445
- function ie(e) {
1633
+ function fe(e) {
1446
1634
  let t = e.match(/^rgba?\((.*)\)$/i);
1447
1635
  if (!t) return null;
1448
1636
  let n = t[1].trim().split("/").map((e) => e.trim()), r = n[0], i = n[1], a = r.includes(",") ? r.split(",").map((e) => e.trim()).filter(Boolean) : r.split(/\s+/).filter(Boolean);
1449
1637
  if (a.length < 3) return null;
1450
- let o = V(a[0]), s = V(a[1]), c = V(a[2]), l = U(i ?? (a.length > 3 ? a[3] : void 0));
1638
+ let o = B(a[0]), s = B(a[1]), c = B(a[2]), l = H(i ?? (a.length > 3 ? a[3] : void 0));
1451
1639
  return o === null || s === null || c === null || l === null ? null : [
1452
1640
  o,
1453
1641
  s,
@@ -1455,12 +1643,12 @@ function ie(e) {
1455
1643
  l
1456
1644
  ];
1457
1645
  }
1458
- function ae(e) {
1646
+ function pe(e) {
1459
1647
  let t = e.match(/^color\(\s*srgb\s+(.+)\)$/i);
1460
1648
  if (!t) return null;
1461
1649
  let n = t[1].split("/").map((e) => e.trim()), r = n[0].split(/\s+/).filter(Boolean);
1462
1650
  if (r.length < 3) return null;
1463
- let i = H(r[0]), a = H(r[1]), o = H(r[2]), s = U(n[1]);
1651
+ let i = V(r[0]), a = V(r[1]), o = V(r[2]), s = H(n[1]);
1464
1652
  return i === null || a === null || o === null || s === null ? null : [
1465
1653
  i,
1466
1654
  a,
@@ -1468,7 +1656,7 @@ function ae(e) {
1468
1656
  s
1469
1657
  ];
1470
1658
  }
1471
- function oe(e) {
1659
+ function me(e) {
1472
1660
  let t = e.startsWith("#") ? e.slice(1) : "";
1473
1661
  if (![
1474
1662
  3,
@@ -1484,21 +1672,21 @@ function oe(e) {
1484
1672
  n.length === 8 ? (r & 255) / 255 : 1
1485
1673
  ] : null;
1486
1674
  }
1675
+ function B(e) {
1676
+ return e.endsWith("%") ? U(Number.parseFloat(e) / 100) : U(Number.parseFloat(e) / 255);
1677
+ }
1487
1678
  function V(e) {
1488
- return e.endsWith("%") ? W(Number.parseFloat(e) / 100) : W(Number.parseFloat(e) / 255);
1679
+ return e.endsWith("%") ? U(Number.parseFloat(e) / 100) : U(Number.parseFloat(e));
1489
1680
  }
1490
1681
  function H(e) {
1491
- return e.endsWith("%") ? W(Number.parseFloat(e) / 100) : W(Number.parseFloat(e));
1682
+ return e ? e.endsWith("%") ? U(Number.parseFloat(e) / 100) : U(Number.parseFloat(e)) : 1;
1492
1683
  }
1493
1684
  function U(e) {
1494
- return e ? e.endsWith("%") ? W(Number.parseFloat(e) / 100) : W(Number.parseFloat(e)) : 1;
1495
- }
1496
- function W(e) {
1497
1685
  return Number.isFinite(e) ? Math.min(1, Math.max(0, e)) : null;
1498
1686
  }
1499
1687
  //#endregion
1500
1688
  //#region src/ui/Chart.ts
1501
- var G = 16384, K = G >> 1, q = G >> 1, J = 3, Y = 4096, X = 12, se = 12, Z = 64;
1689
+ var W = 16384, G = W >> 1, K = W >> 1, q = 3, J = 4096, Y = 12, he = 12, X = 5, Z = 64, ge = 4, _e = W * 4;
1502
1690
  function Q(e) {
1503
1691
  return e === !1 ? {
1504
1692
  visible: !1,
@@ -1520,6 +1708,10 @@ function $(e) {
1520
1708
  y: {
1521
1709
  visible: !1,
1522
1710
  position: "inside"
1711
+ },
1712
+ y2: {
1713
+ visible: !1,
1714
+ position: "inside"
1523
1715
  }
1524
1716
  } : e === !0 || e === void 0 ? {
1525
1717
  x: {
@@ -1529,17 +1721,24 @@ function $(e) {
1529
1721
  y: {
1530
1722
  visible: !0,
1531
1723
  position: "inside"
1724
+ },
1725
+ y2: {
1726
+ visible: !1,
1727
+ position: "inside"
1532
1728
  }
1533
1729
  } : {
1534
1730
  x: Q(e.x),
1535
- y: Q(e.y)
1731
+ y: Q(e.y),
1732
+ y2: Q(e.y2 ?? !1)
1536
1733
  };
1537
1734
  }
1538
- var ce = class {
1735
+ var ve = class {
1539
1736
  options;
1540
1737
  series = [];
1541
1738
  camera;
1739
+ rightCamera;
1542
1740
  axis;
1741
+ rightAxis;
1543
1742
  renderer;
1544
1743
  rawLineBuffer;
1545
1744
  rawLineData;
@@ -1570,6 +1769,7 @@ var ce = class {
1570
1769
  hoverSubscribers = /* @__PURE__ */ new Set();
1571
1770
  seriesSubscribers = /* @__PURE__ */ new Set();
1572
1771
  themeSubscribers = /* @__PURE__ */ new Set();
1772
+ renderSubscribers = /* @__PURE__ */ new Set();
1573
1773
  currentHover = null;
1574
1774
  lastPointerClientX = 0;
1575
1775
  lastPointerClientY = 0;
@@ -1584,10 +1784,10 @@ var ce = class {
1584
1784
  this.pointerInPlot = !1, this.emitHover(null);
1585
1785
  };
1586
1786
  constructor(e, t = {}) {
1587
- this.options = t, this.resolvedTheme = F(t.theme, e), this.normalizedAxes = $(t.axes), this._gridVisible = t.grid !== !1, this.layout = new ne(e, this.normalizedAxes), this.layout.root.style.background = this.resolvedTheme.backgroundCssColor, this.applyCanvasSize(), this.camera = new j(), this.axis = new M(this.camera), this.renderer = new te(new A(this.layout.canvas)), this.rawLineData = new Float32Array(G * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.minMaxInstanceData = new Float32Array(q * J), this.minMaxInstanceBuffer = this.renderer.createFloatBuffer(this.minMaxInstanceData.length), this.barTriangleData = new Float32Array(Y * X), this.barTriangleBuffer = this.renderer.createFloatBuffer(this.barTriangleData.length), this.gridData = new Float32Array(Z * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
1787
+ this.options = t, this.resolvedTheme = I(t.theme, e), this.normalizedAxes = $(t.axes), this._gridVisible = t.grid !== !1, this.layout = new ce(e, this.normalizedAxes), this.layout.root.style.background = this.resolvedTheme.backgroundCssColor, this.applyCanvasSize(), this.camera = new M(), this.rightCamera = new M(), this.axis = new N(this.camera), this.rightAxis = new N(this.rightCamera), this.renderer = new ie(new se(this.layout.canvas)), this.rawLineData = new Float32Array(W * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.minMaxInstanceData = new Float32Array(K * q), this.minMaxInstanceBuffer = this.renderer.createFloatBuffer(this.minMaxInstanceData.length), this.barTriangleData = new Float32Array(J * Y), this.barTriangleBuffer = this.renderer.createFloatBuffer(this.barTriangleData.length), this.gridData = new Float32Array(Z * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
1588
1788
  color: t.gridStyle?.color ?? this.resolvedTheme.gridColor,
1589
1789
  lineWidth: t.gridStyle?.lineWidth ?? 1
1590
- }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new N(this.layout, this.normalizedAxes, {
1790
+ }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible || this.normalizedAxes.y2.visible) && (this.axisOverlay = new P(this.layout, this.normalizedAxes, {
1591
1791
  color: this.resolvedTheme.axisColor,
1592
1792
  font: this.resolvedTheme.axisFont
1593
1793
  })), this.canvas.addEventListener("pointermove", this.handlePointerMove), this.canvas.addEventListener("pointerleave", this.handlePointerLeave), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.resize()), this.resizeObserver.observe(this.layout.plot));
@@ -1611,36 +1811,42 @@ var ce = class {
1611
1811
  get yAxisElement() {
1612
1812
  return this.layout.yAxis;
1613
1813
  }
1814
+ get y2AxisElement() {
1815
+ return this.layout.y2Axis;
1816
+ }
1614
1817
  get theme() {
1615
1818
  return this.resolvedTheme;
1616
1819
  }
1617
- getCamera() {
1618
- return this.camera;
1820
+ getWebGLContext() {
1821
+ return this.renderer.getWebGLContext();
1619
1822
  }
1620
- dataToPlot(e, t) {
1621
- let [n, r] = this.camera.toClip(e, t);
1622
- return this.camera.toScreen(n, r, this.canvas.clientWidth, this.canvas.clientHeight);
1823
+ getCamera(e = "left") {
1824
+ return e === "right" ? this.rightCamera : this.camera;
1623
1825
  }
1624
- clientToData(e, t) {
1625
- let n = this.canvas.getBoundingClientRect();
1626
- if (n.width <= 0 || n.height <= 0) return null;
1627
- let r = e - n.left, i = t - n.top;
1628
- if (r < 0 || i < 0 || r > n.width || i > n.height) return null;
1629
- let a = this.camera.viewport;
1630
- return [a.xMin + r / n.width * (a.xMax - a.xMin), a.yMax - i / n.height * (a.yMax - a.yMin)];
1826
+ dataToPlot(e, t, n = "left") {
1827
+ let r = this.getCamera(n), [i, a] = r.toClip(e, t);
1828
+ return r.toScreen(i, a, this.canvas.clientWidth, this.canvas.clientHeight);
1829
+ }
1830
+ clientToData(e, t, n = "left") {
1831
+ let r = this.canvas.getBoundingClientRect();
1832
+ if (r.width <= 0 || r.height <= 0) return null;
1833
+ let i = e - r.left, a = t - r.top;
1834
+ if (i < 0 || a < 0 || i > r.width || a > r.height) return null;
1835
+ let o = this.getCamera(n).viewport;
1836
+ return [o.xMin + i / r.width * (o.xMax - o.xMin), o.yMax - a / r.height * (o.yMax - o.yMin)];
1631
1837
  }
1632
- getViewport() {
1633
- return this.camera.viewport;
1838
+ getViewport(e = "left") {
1839
+ return this.getCamera(e).viewport;
1634
1840
  }
1635
1841
  pan(e) {
1636
- this.camera.pan(e), this.refreshHover();
1842
+ this.camera.pan(e), this.syncRightCameraX(), this.refreshHover();
1637
1843
  }
1638
1844
  zoom(e) {
1639
- this.camera.zoom(e), this.refreshHover();
1845
+ this.camera.zoom(e), this.syncRightCameraX(), this.refreshHover();
1640
1846
  }
1641
1847
  addSeries(e, t) {
1642
- if (e.mode === "ohlc" && !e.dataset) throw TypeError("OHLC series require an OhlcDataset.");
1643
- let n = e.dataset ?? new l(e.capacity, { overflow: e.overflow }), r = this.resolvedTheme.seriesColors, i = r[this.series.length % r.length] ?? this.resolvedTheme.seriesColors[0], a = t?.color ?? i, s = new o(n, e, {
1848
+ if ((e.mode === "ohlc" || e.mode === "candlestick") && !e.dataset) throw TypeError("OHLC and candlestick series require an OhlcDataset.");
1849
+ let n = e.dataset ?? new g(e.capacity, { overflow: e.overflow }), r = this.resolvedTheme.seriesColors, i = r[this.series.length % r.length] ?? this.resolvedTheme.seriesColors[0], a = t?.color ?? i, o = new p(n, e, {
1644
1850
  color: a,
1645
1851
  lineWidth: t?.lineWidth ?? 1,
1646
1852
  pointSize: t?.pointSize ?? 4,
@@ -1652,9 +1858,17 @@ var ce = class {
1652
1858
  a[2],
1653
1859
  a[3] * .25
1654
1860
  ],
1655
- tickWidth: t?.tickWidth ?? t?.barWidth ?? .8
1861
+ tickWidth: t?.tickWidth ?? t?.barWidth ?? .8,
1862
+ upColor: t?.upColor ?? a,
1863
+ downColor: t?.downColor ?? t?.fillColor ?? [
1864
+ a[0],
1865
+ a[1],
1866
+ a[2],
1867
+ a[3] * .45
1868
+ ],
1869
+ wickColor: t?.wickColor ?? a
1656
1870
  });
1657
- return this.series.push(s), this.emitSeriesChange(), s;
1871
+ return this.series.push(o), this.emitSeriesChange(), o;
1658
1872
  }
1659
1873
  addLine(e, t) {
1660
1874
  return this.addSeries({
@@ -1686,6 +1900,12 @@ var ce = class {
1686
1900
  mode: "ohlc"
1687
1901
  }, t);
1688
1902
  }
1903
+ addCandlestick(e, t) {
1904
+ return this.addSeries({
1905
+ ...e,
1906
+ mode: "candlestick"
1907
+ }, t);
1908
+ }
1689
1909
  removeSeries(e) {
1690
1910
  let t = this.series.indexOf(e);
1691
1911
  return t === -1 ? !1 : (this.series.splice(t, 1), this.emitSeriesChange(), !0);
@@ -1701,11 +1921,15 @@ var ce = class {
1701
1921
  name: e.config.name,
1702
1922
  mode: e.config.mode,
1703
1923
  visible: e.visible,
1704
- color: e.style.color
1924
+ color: e.style.color,
1925
+ yAxis: e.config.yAxis ?? "left"
1705
1926
  }));
1706
1927
  }
1707
1928
  setViewport(e) {
1708
- this.camera.setViewport(e), this.refreshHover();
1929
+ this.camera.setViewport(e), this.rightCamera.setViewport(e), this.refreshHover();
1930
+ }
1931
+ setYViewport(e, t) {
1932
+ this.getCamera(e).setViewport(t), this.refreshHover();
1709
1933
  }
1710
1934
  resize(e = globalThis.devicePixelRatio) {
1711
1935
  let t = this.applyCanvasSize(e);
@@ -1733,11 +1957,15 @@ var ce = class {
1733
1957
  let e = t;
1734
1958
  return this.themeSubscribers.add(e), () => this.themeSubscribers.delete(e);
1735
1959
  }
1960
+ if (e === "render") {
1961
+ let e = t;
1962
+ return this.renderSubscribers.add(e), () => this.renderSubscribers.delete(e);
1963
+ }
1736
1964
  let n = t;
1737
1965
  return this.seriesSubscribers.add(n), () => this.seriesSubscribers.delete(n);
1738
1966
  }
1739
1967
  setTheme(e) {
1740
- this.resolvedTheme = F(e, this.layout.root), this.applyTheme(), this.emitThemeChange(), this.refreshHover();
1968
+ this.resolvedTheme = I(e, this.layout.root), this.applyTheme(), this.emitThemeChange(), this.refreshHover();
1741
1969
  }
1742
1970
  setGridVisible(e) {
1743
1971
  this._gridVisible = e;
@@ -1746,7 +1974,7 @@ var ce = class {
1746
1974
  return this._gridVisible;
1747
1975
  }
1748
1976
  setAxes(e) {
1749
- this.normalizedAxes = $(e), this.layout.update(this.normalizedAxes), this.axisOverlay?.dispose(), this.axisOverlay = null, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new N(this.layout, this.normalizedAxes, {
1977
+ this.normalizedAxes = $(e), this.layout.update(this.normalizedAxes), this.axisOverlay?.dispose(), this.axisOverlay = null, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible || this.normalizedAxes.y2.visible) && (this.axisOverlay = new P(this.layout, this.normalizedAxes, {
1750
1978
  color: this.resolvedTheme.axisColor,
1751
1979
  font: this.resolvedTheme.axisFont
1752
1980
  })), this.resize(), this.refreshHover();
@@ -1756,17 +1984,21 @@ var ce = class {
1756
1984
  if (r.width <= 0 || r.height <= 0) return null;
1757
1985
  let i = e - r.left, a = t - r.top;
1758
1986
  if (i < 0 || a < 0 || i > r.width || a > r.height) return null;
1759
- let o = this.camera.viewport, s = o.xMin + i / r.width * (o.xMax - o.xMin), c = o.yMax - a / r.height * (o.yMax - o.yMin), l = n.mode ?? this.options.hover?.mode ?? "nearest-x", u = n.maxDistancePx ?? this.options.hover?.maxDistancePx ?? Infinity, d = l === "nearest-point" ? this.findNearestPointAnchor(s, c, o, r.width, r.height, u) : this.findNearestXAnchor(s, o, r.width, u);
1760
- return d === null ? null : {
1987
+ let o = this.camera.viewport, s = o.xMin + i / r.width * (o.xMax - o.xMin), c = o.yMax - a / r.height * (o.yMax - o.yMin), l = n.mode ?? this.options.hover?.mode ?? "nearest-x", u = n.group ?? this.options.hover?.group ?? "x", d = n.maxDistancePx ?? this.options.hover?.maxDistancePx ?? Infinity, f = l === "nearest-point" ? this.findNearestPointCandidate(s, a, r.width, r.height, d) : this.findNearestXCandidate(s, r.width, d);
1988
+ if (!f) return null;
1989
+ let p = f.sample.x;
1990
+ return {
1761
1991
  clientX: e,
1762
1992
  clientY: t,
1763
1993
  plotX: i,
1764
1994
  plotY: a,
1765
1995
  dataX: s,
1766
1996
  dataY: c,
1767
- anchorX: d,
1997
+ anchorX: p,
1768
1998
  mode: l,
1769
- items: this.collectPickItems(d, e, t, o, r)
1999
+ group: u,
2000
+ maxDistancePx: d,
2001
+ items: u === "none" ? [this.createPickItem(f.sample, f.series, f.seriesIndex, e, t, r)] : this.collectPickItems(p, e, t, r)
1770
2002
  };
1771
2003
  }
1772
2004
  async screenshot(e = {}) {
@@ -1790,7 +2022,7 @@ var ce = class {
1790
2022
  }
1791
2023
  render() {
1792
2024
  let e = performance.now();
1793
- this.lastFrameAt > 0 && (this.stats.fps = 1e3 / (e - this.lastFrameAt)), this.lastFrameAt = e, this.stats.pointsRendered = 0, this.stats.drawCalls = 0, this.stats.uploadBytes = 0, this.stats.renderMode = "none", this.options.viewportPolicy?.beforeRender?.(this.camera);
2025
+ this.lastFrameAt > 0 && (this.stats.fps = 1e3 / (e - this.lastFrameAt)), this.lastFrameAt = e, this.stats.pointsRendered = 0, this.stats.drawCalls = 0, this.stats.uploadBytes = 0, this.stats.renderMode = "none", this.options.viewportPolicy?.beforeRender?.(this.camera), this.syncRightCameraX();
1794
2026
  let [t, n, r, i] = this.resolvedTheme.backgroundColor;
1795
2027
  this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height), this.renderer.clear(t, n, r, i);
1796
2028
  let a = this.camera.viewport;
@@ -1798,8 +2030,8 @@ var ce = class {
1798
2030
  let e = this.writeGridVertices(a);
1799
2031
  e > 0 && (this.uploadGridData(e), this.renderer.drawClipLines(this.gridBuffer, e, this.gridStyle), this.stats.drawCalls++);
1800
2032
  }
1801
- for (let e of this.series) e.visible && (e.rebuildPyramid(), this.drawSeries(e, a));
1802
- this.axisOverlay?.update(this.camera, this.axis), this.stats.frameMs = performance.now() - e, this.refreshHover();
2033
+ for (let e of this.series) e.visible && (e.rebuildPyramid(), this.drawSeries(e));
2034
+ this.axisOverlay?.update(this.camera, this.axis, this.rightCamera, this.rightAxis), this.emitRender(), this.stats.frameMs = performance.now() - e, this.refreshHover();
1803
2035
  }
1804
2036
  dispose() {
1805
2037
  this.stop(), this.resizeObserver?.disconnect(), this.canvas.removeEventListener("pointermove", this.handlePointerMove), this.canvas.removeEventListener("pointerleave", this.handlePointerLeave);
@@ -1819,96 +2051,141 @@ var ce = class {
1819
2051
  let t = Number.isFinite(e) ? Math.max(1, e) : 1, n = Math.max(1, Math.floor(this.canvas.clientWidth * t)), r = Math.max(1, Math.floor(this.canvas.clientHeight * t));
1820
2052
  return this.canvas.width === n && this.canvas.height === r ? !1 : (this.canvas.width = n, this.canvas.height = r, !0);
1821
2053
  }
1822
- drawSeries(e, t) {
2054
+ cameraForSeries(e) {
2055
+ return e.config.yAxis === "right" ? this.rightCamera : this.camera;
2056
+ }
2057
+ syncRightCameraX() {
2058
+ this.rightCamera.setViewport({
2059
+ xMin: this.camera.xMin,
2060
+ xMax: this.camera.xMax
2061
+ });
2062
+ }
2063
+ drawSeries(e) {
2064
+ let t = this.cameraForSeries(e), n = t.viewport;
1823
2065
  switch (e.config.mode) {
1824
2066
  case "area":
1825
- this.drawAreaSeries(e, t);
2067
+ this.drawAreaSeries(e, n, t);
1826
2068
  return;
1827
2069
  case "bar":
1828
- this.drawBarSeries(e, t);
2070
+ this.drawBarSeries(e, n, t);
1829
2071
  return;
1830
2072
  case "ohlc":
1831
- this.drawOhlcSeries(e, t);
2073
+ this.drawOhlcSeries(e, n, t);
2074
+ return;
2075
+ case "candlestick":
2076
+ this.drawCandlestickSeries(e, n, t);
1832
2077
  return;
1833
2078
  case "scatter":
1834
- this.drawScatterSeries(e, t);
2079
+ this.drawScatterSeries(e, n, t);
1835
2080
  return;
1836
- default: this.drawLineSeries(e, t);
2081
+ default: this.drawLineSeries(e, n, t);
1837
2082
  }
1838
2083
  }
1839
- drawLineSeries(e, t) {
1840
- let n = e.visibleSampleCount(t), r = e.hasLOD && n > G - 2;
1841
- if (r && this.renderer.supportsInstancedSegments) {
1842
- let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxMinMaxSegments(), this.currentXOrigin);
1843
- if (n <= 0) return;
1844
- this.uploadMinMaxInstanceData(n), this.renderer.drawMinMaxSegmentsInstanced(this.minMaxInstanceBuffer, n, e.style, this.camera), this.recordDraw("minmax", n * 2);
2084
+ drawLineSeries(e, t, n) {
2085
+ let r = e.visibleSampleCount(t), i = e.hasLOD && r > W - 2;
2086
+ if (i && this.renderer.supportsInstancedSegments) {
2087
+ let r = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxMinMaxSegments(), this.currentXOrigin);
2088
+ if (r <= 0) return;
2089
+ this.uploadMinMaxInstanceData(r), this.renderer.drawMinMaxSegmentsInstanced(this.minMaxInstanceBuffer, r, e.style, n), this.recordDraw("minmax", r * 2);
1845
2090
  return;
1846
2091
  }
1847
- if (r) {
1848
- let n = e.copyMinMaxVisible(t, this.rawLineData, this.maxMinMaxSegments(), this.currentXOrigin);
1849
- if (n < 2) return;
1850
- this.uploadRawLineData(n), this.renderer.drawMinMaxSegments(this.rawLineBuffer, n, e.style, this.camera), this.recordDraw("minmax", n);
2092
+ if (i) {
2093
+ let r = e.copyMinMaxVisible(t, this.rawLineData, this.maxMinMaxSegments(), this.currentXOrigin);
2094
+ if (r < 2) return;
2095
+ this.uploadRawLineData(r), this.renderer.drawMinMaxSegments(this.rawLineBuffer, r, e.style, n), this.recordDraw("minmax", r);
1851
2096
  return;
1852
2097
  }
1853
- let i = e.copyRawVisibleClipSpace(t, this.rawLineData, G);
1854
- i < 2 || (this.uploadRawLineData(i), this.renderer.drawClipLineStrip(this.rawLineBuffer, i, e.style), this.recordDraw("raw", i));
1855
- }
1856
- drawAreaSeries(e, t) {
1857
- let n = e.visibleIndexRange(t, 1);
1858
- if (n.end - n.start < 2) return;
1859
- let r = e.style.baseline ?? 0;
1860
- for (let t = n.start; t < n.end;) {
1861
- let i = e.copyAreaRange(t, n.end, this.rawLineData, K, r, this.currentXOrigin);
1862
- if (i < 4) break;
1863
- this.uploadRawLineData(i), this.renderer.drawAreaStrip(this.rawLineBuffer, i, e.style, this.camera), this.recordDraw("area", i), t += Math.max(1, (i >> 1) - 1);
1864
- }
1865
- for (let t = n.start; t < n.end;) {
1866
- let r = e.copyRawRange(t, n.end, this.rawLineData, K, this.currentXOrigin);
1867
- if (r < 2) break;
1868
- this.uploadRawLineData(r), this.renderer.drawLineStrip(this.rawLineBuffer, r, e.style, this.camera), this.recordDraw("area", r), t += Math.max(1, r - 1);
1869
- }
1870
- }
1871
- drawOhlcSeries(e, t) {
1872
- let n = e.visibleIndexRange(t), r = Math.floor(this.rawLineData.length / se);
1873
- for (let t = n.start; t < n.end;) {
1874
- let i = e.copyOhlcRange(t, n.end, this.rawLineData, r, e.style.tickWidth ?? e.style.barWidth ?? .8, this.currentXOrigin);
1875
- if (i <= 0) break;
1876
- let a = i * 6;
1877
- this.uploadRawLineData(a), this.renderer.drawLines(this.rawLineBuffer, a, e.style, this.camera), this.recordDraw("raw", a), t += i;
1878
- }
1879
- }
1880
- drawScatterSeries(e, t) {
1881
- let n = e.visibleIndexRange(t);
1882
- for (let t = n.start; t < n.end;) {
1883
- let r = e.copyRawRange(t, n.end, this.rawLineData, G, this.currentXOrigin);
1884
- if (r <= 0) break;
1885
- this.uploadRawLineData(r), this.renderer.drawPoints(this.rawLineBuffer, r, e.style, this.camera, this.canvas.width, this.canvas.height), this.recordDraw("points", r), t += r;
1886
- }
1887
- }
1888
- drawBarSeries(e, t) {
1889
- let n = e.visibleSampleCount(t), r = this.maxRawBarInstances();
1890
- if (e.hasLOD && n > r) {
1891
- let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxBarTriangleBars(), this.currentXOrigin);
1892
- if (n <= 0) return;
1893
- this.includeBaselineInBarRanges(n, e.style.baseline ?? 0);
1894
- let r = this.writeBarBucketTriangles(n, t);
1895
- this.drawBarTriangles(r, e.style);
2098
+ let a = e.copyRawVisibleClipSpace(t, this.rawLineData, W);
2099
+ a < 2 || (this.uploadRawLineData(a), this.renderer.drawClipLineStrip(this.rawLineBuffer, a, e.style), this.recordDraw("raw", a));
2100
+ }
2101
+ drawAreaSeries(e, t, n) {
2102
+ let r = e.visibleIndexRange(t, 1);
2103
+ if (r.end - r.start < 2) return;
2104
+ let i = e.style.baseline ?? 0;
2105
+ if (r.end - r.start > G) {
2106
+ let r = e.copyAreaVisible(t, this.rawLineData, G, i, this.currentXOrigin);
2107
+ r >= 4 && (this.uploadRawLineData(r), this.renderer.drawAreaStrip(this.rawLineBuffer, r, e.style, n), this.recordDraw("area", r));
2108
+ let a = e.copyRawVisible(t, this.rawLineData, G, this.currentXOrigin);
2109
+ a >= 2 && (this.uploadRawLineData(a), this.renderer.drawLineStrip(this.rawLineBuffer, a, e.style, n), this.recordDraw("area", a));
1896
2110
  return;
1897
2111
  }
1898
- let i = e.visibleIndexRange(t, 1), a = e.copyRawRange(i.start, i.end, this.rawLineData, r, this.currentXOrigin);
1899
- if (a <= 0) return;
2112
+ for (let t = r.start; t < r.end;) {
2113
+ let a = e.copyAreaRange(t, r.end, this.rawLineData, G, i, this.currentXOrigin);
2114
+ if (a < 4) break;
2115
+ this.uploadRawLineData(a), this.renderer.drawAreaStrip(this.rawLineBuffer, a, e.style, n), this.recordDraw("area", a), t += Math.max(1, (a >> 1) - 1);
2116
+ }
2117
+ for (let t = r.start; t < r.end;) {
2118
+ let i = e.copyRawRange(t, r.end, this.rawLineData, G, this.currentXOrigin);
2119
+ if (i < 2) break;
2120
+ this.uploadRawLineData(i), this.renderer.drawLineStrip(this.rawLineBuffer, i, e.style, n), this.recordDraw("area", i), t += Math.max(1, i - 1);
2121
+ }
2122
+ }
2123
+ drawOhlcSeries(e, t, n) {
2124
+ let r = e.visibleIndexRange(t), i = Math.floor(this.rawLineData.length / he);
2125
+ for (let t = r.start; t < r.end;) {
2126
+ let a = e.copyOhlcRange(t, r.end, this.rawLineData, i, e.style.tickWidth ?? e.style.barWidth ?? .8, this.currentXOrigin);
2127
+ if (a <= 0) break;
2128
+ let o = a * 6;
2129
+ this.uploadRawLineData(o), this.renderer.drawLines(this.rawLineBuffer, o, e.style, n), this.recordDraw("raw", o), t += a;
2130
+ }
2131
+ }
2132
+ drawCandlestickSeries(e, t, n) {
2133
+ let r = e.visibleIndexRange(t, 1), i = Math.min(Math.floor(this.rawLineData.length / X), this.maxBarTriangleBars()), a = {
2134
+ ...e.style,
2135
+ color: e.style.wickColor ?? e.style.color
2136
+ }, o = {
2137
+ ...e.style,
2138
+ color: e.style.upColor ?? e.style.color
2139
+ }, s = {
2140
+ ...e.style,
2141
+ color: e.style.downColor ?? e.style.fillColor ?? e.style.color
2142
+ };
2143
+ for (let t = r.start; t < r.end;) {
2144
+ let c = e.copyOhlcTuplesRange(t, r.end, this.rawLineData, i, this.currentXOrigin);
2145
+ if (c <= 0) break;
2146
+ let l = this.writeCandlestickWicks(c);
2147
+ l > 0 && (this.uploadBarTriangleData(l), this.renderer.drawLines(this.barTriangleBuffer, l, a, n), this.recordDraw("raw", l));
2148
+ let u = e.style.barWidth ?? e.style.tickWidth ?? .8;
2149
+ this.drawCandlestickBodies(c, u, "up", o, n), this.drawCandlestickBodies(c, u, "down", s, n), t += c;
2150
+ }
2151
+ }
2152
+ drawScatterSeries(e, t, n) {
2153
+ let r = e.style.pointSize ?? ge, i = e.visibleSampleCount(t);
2154
+ if (e.config.downsample === "none" && i <= _e) {
2155
+ let i = e.visibleIndexRange(t);
2156
+ for (let a = i.start; a < i.end; a += W) {
2157
+ let o = e.copyScatterRange(a, Math.min(i.end, a + W), t, this.rawLineData, W, this.currentXOrigin, this.canvas.height, r);
2158
+ o <= 0 || (this.uploadRawLineData(o), this.renderer.drawPoints(this.rawLineBuffer, o, e.style, n, this.canvas.width, this.canvas.height), this.recordDraw("points", o));
2159
+ }
2160
+ return;
2161
+ }
2162
+ let a = e.copyScatterVisible(t, this.rawLineData, W, this.canvas.width, this.canvas.height, r, this.currentXOrigin);
2163
+ a <= 0 || (this.uploadRawLineData(a), this.renderer.drawPoints(this.rawLineBuffer, a, e.style, n, this.canvas.width, this.canvas.height), this.recordDraw("points", a));
2164
+ }
2165
+ drawBarSeries(e, t, n) {
2166
+ let r = e.visibleSampleCount(t), i = this.maxRawBarInstances();
2167
+ if (e.hasLOD && r > i) {
2168
+ let r = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxBarTriangleBars(), this.currentXOrigin);
2169
+ if (r <= 0) return;
2170
+ this.includeBaselineInBarRanges(r, e.style.baseline ?? 0);
2171
+ let i = this.writeBarBucketTriangles(r, t);
2172
+ this.drawBarTriangles(i, e.style, n);
2173
+ return;
2174
+ }
2175
+ let a = e.visibleIndexRange(t, 1), o = e.copyRawRange(a.start, a.end, this.rawLineData, i, this.currentXOrigin);
2176
+ if (o <= 0) return;
1900
2177
  if (this.renderer.supportsInstancedBars) {
1901
- this.uploadRawLineData(a), this.renderer.drawBarsInstanced(this.rawLineBuffer, a, e.style, this.camera), this.recordDraw("bars", a);
2178
+ this.uploadRawLineData(o), this.renderer.drawBarsInstanced(this.rawLineBuffer, o, e.style, n), this.recordDraw("bars", o);
1902
2179
  return;
1903
2180
  }
1904
- let o = this.writeBarTriangles(a, e.style.baseline ?? 0, e.style.barWidth ?? .8);
1905
- this.drawBarTriangles(o, e.style);
2181
+ let s = this.writeBarTriangles(o, e.style.baseline ?? 0, e.style.barWidth ?? .8);
2182
+ this.drawBarTriangles(s, e.style, n);
1906
2183
  }
1907
2184
  uploadRawLineData(e) {
1908
2185
  this.uploadFloatData(this.rawLineBuffer, this.rawLineData, e * 2);
1909
2186
  }
1910
2187
  uploadMinMaxInstanceData(e) {
1911
- this.uploadFloatData(this.minMaxInstanceBuffer, this.minMaxInstanceData, e * J);
2188
+ this.uploadFloatData(this.minMaxInstanceBuffer, this.minMaxInstanceData, e * q);
1912
2189
  }
1913
2190
  uploadBarTriangleData(e) {
1914
2191
  this.uploadFloatData(this.barTriangleBuffer, this.barTriangleData, e * 2);
@@ -1922,7 +2199,7 @@ var ce = class {
1922
2199
  }
1923
2200
  includeBaselineInBarRanges(e, t) {
1924
2201
  for (let n = 0; n < e; n++) {
1925
- let e = n * J, r = this.minMaxInstanceData[e + 1], i = this.minMaxInstanceData[e + 2];
2202
+ let e = n * q, r = this.minMaxInstanceData[e + 1], i = this.minMaxInstanceData[e + 2];
1926
2203
  this.minMaxInstanceData[e + 1] = Math.min(t, r), this.minMaxInstanceData[e + 2] = Math.max(t, i);
1927
2204
  }
1928
2205
  }
@@ -1955,59 +2232,86 @@ var ce = class {
1955
2232
  }
1956
2233
  return [Math.max(i, l), Math.min(a, u)];
1957
2234
  }
2235
+ writeCandlestickWicks(e) {
2236
+ for (let t = 0; t < e; t++) {
2237
+ let e = t * X, n = t * 4, r = this.rawLineData[e], i = this.rawLineData[e + 2], a = this.rawLineData[e + 3];
2238
+ this.barTriangleData[n] = r, this.barTriangleData[n + 1] = a, this.barTriangleData[n + 2] = r, this.barTriangleData[n + 3] = i;
2239
+ }
2240
+ return e * 2;
2241
+ }
2242
+ drawCandlestickBodies(e, t, n, r, i) {
2243
+ let a = t * .5, o = 0;
2244
+ for (let t = 0; t < e && o < this.maxBarTriangleBars(); t++) {
2245
+ let e = t * X, r = this.rawLineData[e], i = this.rawLineData[e + 1], s = this.rawLineData[e + 4];
2246
+ n === "up" == s >= i && (this.writeBarTriangle(o, r - a, r + a, Math.min(i, s), Math.max(i, s)), o++);
2247
+ }
2248
+ this.drawBarTriangles(o * 6, r, i);
2249
+ }
1958
2250
  writeBarTriangle(e, t, n, r, i) {
1959
- let a = e * X;
2251
+ let a = e * Y;
1960
2252
  this.barTriangleData[a] = t, this.barTriangleData[a + 1] = r, this.barTriangleData[a + 2] = n, this.barTriangleData[a + 3] = r, this.barTriangleData[a + 4] = t, this.barTriangleData[a + 5] = i, this.barTriangleData[a + 6] = t, this.barTriangleData[a + 7] = i, this.barTriangleData[a + 8] = n, this.barTriangleData[a + 9] = r, this.barTriangleData[a + 10] = n, this.barTriangleData[a + 11] = i;
1961
2253
  }
1962
- drawBarTriangles(e, t) {
1963
- e <= 0 || (this.uploadBarTriangleData(e), this.renderer.drawBarTriangles(this.barTriangleBuffer, e, t, this.camera), this.recordDraw("bars", e));
2254
+ drawBarTriangles(e, t, n, r = "bars") {
2255
+ e <= 0 || (this.uploadBarTriangleData(e), this.renderer.drawBarTriangles(this.barTriangleBuffer, e, t, n), this.recordDraw(r, e));
1964
2256
  }
1965
2257
  recordDraw(e, t, n = 1) {
1966
2258
  this.recordRenderMode(e), this.stats.pointsRendered += t, this.stats.drawCalls += n;
1967
2259
  }
1968
- findNearestXAnchor(e, t, n, r) {
1969
- let i = null, a = Infinity, o = n / (t.xMax - t.xMin);
1970
- for (let n of this.series) {
1971
- if (!n.visible) continue;
1972
- let r = n.nearestSampleByX(e, t);
1973
- if (!r) continue;
1974
- let s = Math.abs(r.x - e) * o;
1975
- s < a && (i = r, a = s);
1976
- }
1977
- return !i || a > r ? null : i.x;
1978
- }
1979
- findNearestPointAnchor(e, t, n, r, i, a) {
1980
- let o = null;
1981
- for (let a of this.series) {
2260
+ findNearestXCandidate(e, t, n) {
2261
+ let r = null, i = Infinity;
2262
+ for (let n = 0; n < this.series.length; n++) {
2263
+ let a = this.series[n];
1982
2264
  if (!a.visible) continue;
1983
- let s = a.nearestSampleByPoint(e, t, n, r, i);
1984
- s && (!o || (s.distancePx ?? Infinity) < (o.distancePx ?? Infinity)) && (o = s);
2265
+ let o = this.cameraForSeries(a).viewport, s = t / (o.xMax - o.xMin), c = a.nearestSampleByX(e, o);
2266
+ if (!c) continue;
2267
+ let l = Math.abs(c.x - e) * s;
2268
+ l < i && (r = {
2269
+ sample: c,
2270
+ series: a,
2271
+ seriesIndex: n
2272
+ }, i = l);
1985
2273
  }
1986
- return !o || (o.distancePx ?? Infinity) > a ? null : o.x;
2274
+ return r && i <= n ? r : null;
1987
2275
  }
1988
- collectPickItems(e, t, n, r, i) {
1989
- let a = [];
2276
+ findNearestPointCandidate(e, t, n, r, i) {
2277
+ let a = null;
1990
2278
  for (let o = 0; o < this.series.length; o++) {
1991
2279
  let s = this.series[o];
1992
2280
  if (!s.visible) continue;
1993
- let c = s.nearestSampleByX(e, r);
1994
- if (!c) continue;
1995
- let [l, u] = this.camera.toClip(c.x, c.y), [d, f] = this.camera.toScreen(l, u, i.width, i.height), p = i.left + d, m = i.top + f, h = p - t, g = m - n;
1996
- a.push({
1997
- ...c,
1998
- distancePx: Math.hypot(h, g),
2281
+ let c = this.cameraForSeries(s).viewport, l = c.yMax - t / r * (c.yMax - c.yMin), u = s.nearestSampleByPoint(e, l, c, n, r, i);
2282
+ u && (!a || (u.distancePx ?? Infinity) < (a.sample.distancePx ?? Infinity)) && (a = {
2283
+ sample: u,
1999
2284
  series: s,
2000
- seriesIndex: o,
2001
- id: s.config.id,
2002
- name: s.config.name,
2003
- mode: s.config.mode,
2004
- plotX: d,
2005
- plotY: f,
2006
- clientX: p,
2007
- clientY: m
2285
+ seriesIndex: o
2008
2286
  });
2009
2287
  }
2010
- return a;
2288
+ return a && (a.sample.distancePx ?? Infinity) <= i ? a : null;
2289
+ }
2290
+ collectPickItems(e, t, n, r) {
2291
+ let i = [];
2292
+ for (let a = 0; a < this.series.length; a++) {
2293
+ let o = this.series[a];
2294
+ if (!o.visible) continue;
2295
+ let s = o.nearestSampleByX(e, this.cameraForSeries(o).viewport);
2296
+ s && i.push(this.createPickItem(s, o, a, t, n, r));
2297
+ }
2298
+ return i;
2299
+ }
2300
+ createPickItem(e, t, n, r, i, a) {
2301
+ let o = this.cameraForSeries(t), [s, c] = o.toClip(e.x, e.y), [l, u] = o.toScreen(s, c, a.width, a.height), d = a.left + l, f = a.top + u, p = d - r, m = f - i;
2302
+ return {
2303
+ ...e,
2304
+ distancePx: Math.hypot(p, m),
2305
+ series: t,
2306
+ seriesIndex: n,
2307
+ id: t.config.id,
2308
+ name: t.config.name,
2309
+ mode: t.config.mode,
2310
+ plotX: l,
2311
+ plotY: u,
2312
+ clientX: d,
2313
+ clientY: f
2314
+ };
2011
2315
  }
2012
2316
  refreshHover() {
2013
2317
  this.pointerInPlot && this.emitHover(this.pick(this.lastPointerClientX, this.lastPointerClientY));
@@ -2023,6 +2327,9 @@ var ce = class {
2023
2327
  emitThemeChange() {
2024
2328
  for (let e of this.themeSubscribers) e();
2025
2329
  }
2330
+ emitRender() {
2331
+ for (let e of this.renderSubscribers) e(this);
2332
+ }
2026
2333
  drawDomTextForScreenshot(e, t, n) {
2027
2334
  let r = this.layout.root.querySelectorAll("div");
2028
2335
  for (let i of r) {
@@ -2035,13 +2342,13 @@ var ce = class {
2035
2342
  }
2036
2343
  }
2037
2344
  maxMinMaxSegments() {
2038
- return Math.min(this.canvas.width, q);
2345
+ return Math.min(this.canvas.width, K);
2039
2346
  }
2040
2347
  maxBarTriangleBars() {
2041
- return Math.min(Y, G);
2348
+ return Math.min(J, W);
2042
2349
  }
2043
2350
  maxRawBarInstances() {
2044
- return this.renderer.supportsInstancedBars ? G : this.maxBarTriangleBars();
2351
+ return this.renderer.supportsInstancedBars ? W : this.maxBarTriangleBars();
2045
2352
  }
2046
2353
  writeGridVertices(e) {
2047
2354
  let t = Math.max(1, this.canvas.clientWidth), n = Math.max(1, this.canvas.clientHeight);
@@ -2066,7 +2373,7 @@ var ce = class {
2066
2373
  recordRenderMode(e) {
2067
2374
  this.stats.renderMode === "none" ? this.stats.renderMode = e : this.stats.renderMode !== e && (this.stats.renderMode = "mixed");
2068
2375
  }
2069
- }, le = class {
2376
+ }, ye = class {
2070
2377
  xData;
2071
2378
  yData;
2072
2379
  constructor(e, t) {
@@ -2088,15 +2395,15 @@ var ce = class {
2088
2395
  return this.assertValidIndex(e), this.yData[e];
2089
2396
  }
2090
2397
  lowerBoundX(e) {
2091
- return s(this.length, (e) => this.xData[e], e);
2398
+ return m(this.length, (e) => this.xData[e], e);
2092
2399
  }
2093
2400
  upperBoundX(e) {
2094
- return c(this.length, (e) => this.xData[e], e);
2401
+ return h(this.length, (e) => this.xData[e], e);
2095
2402
  }
2096
2403
  assertValidIndex(e) {
2097
2404
  if (!Number.isInteger(e) || e < 0 || e >= this.length) throw RangeError(`StaticDataset index out of range: ${e}`);
2098
2405
  }
2099
- }, ue = class {
2406
+ }, be = class {
2100
2407
  length;
2101
2408
  xs;
2102
2409
  opens;
@@ -2131,15 +2438,15 @@ var ce = class {
2131
2438
  return this.assertValidIndex(e), this.closes[e];
2132
2439
  }
2133
2440
  lowerBoundX(e) {
2134
- return s(this.length, (e) => this.xs[e], e);
2441
+ return m(this.length, (e) => this.xs[e], e);
2135
2442
  }
2136
2443
  upperBoundX(e) {
2137
- return c(this.length, (e) => this.xs[e], e);
2444
+ return h(this.length, (e) => this.xs[e], e);
2138
2445
  }
2139
2446
  assertValidIndex(e) {
2140
2447
  if (!Number.isInteger(e) || e < 0 || e >= this.length) throw RangeError(`StaticOhlcDataset index out of range: ${e}`);
2141
2448
  }
2142
- }, de = class {
2449
+ }, xe = class {
2143
2450
  capacity;
2144
2451
  overflow;
2145
2452
  xData;
@@ -2204,10 +2511,10 @@ var ce = class {
2204
2511
  return this.assertValidIndex(e), this.closeData[this.logicalToPhysical(e)];
2205
2512
  }
2206
2513
  lowerBoundX(e) {
2207
- return s(this._length, (e) => this.getX(e), e);
2514
+ return m(this._length, (e) => this.getX(e), e);
2208
2515
  }
2209
2516
  upperBoundX(e) {
2210
- return c(this._length, (e) => this.getX(e), e);
2517
+ return h(this._length, (e) => this.getX(e), e);
2211
2518
  }
2212
2519
  logicalToPhysical(e) {
2213
2520
  return (this._head - this._length + e + this.capacity) % this.capacity;
@@ -2217,6 +2524,6 @@ var ce = class {
2217
2524
  }
2218
2525
  };
2219
2526
  //#endregion
2220
- export { M as AxisController, j as Camera2D, ce as Chart, P as DEFAULT_CHART_THEME, n as MinMaxPyramid, de as OhlcRingBuffer, l as RingBuffer, o as SeriesStore, le as StaticDataset, ue as StaticOhlcDataset };
2527
+ export { N as AxisController, M as Camera2D, ve as Chart, F as DEFAULT_CHART_THEME, n as MinMaxPyramid, xe as OhlcRingBuffer, g as RingBuffer, p as SeriesStore, ye as StaticDataset, be as StaticOhlcDataset };
2221
2528
 
2222
2529
  //# sourceMappingURL=index.js.map