@wick-charts/vue 0.6.1 → 0.6.3

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.
Files changed (52) hide show
  1. package/dist/ChartContainer.vue.js +43 -37
  2. package/dist/LineSeries.vue.js +2 -2
  3. package/dist/composables.js +39 -26
  4. package/dist/core/dist/animation/config.js +66 -64
  5. package/dist/core/dist/animation/intro-wave.js +19 -21
  6. package/dist/core/dist/animation/reduced-motion.js +6 -0
  7. package/dist/core/dist/axis/dom-labels.js +58 -45
  8. package/dist/core/dist/chart/badge-animator.js +15 -19
  9. package/dist/core/dist/chart/options.js +5 -5
  10. package/dist/core/dist/chart/scale-guards.js +26 -0
  11. package/dist/core/dist/chart/y-target.js +46 -19
  12. package/dist/core/dist/chart.js +752 -570
  13. package/dist/core/dist/components/crosshair.js +8 -8
  14. package/dist/core/dist/components/grid.js +28 -15
  15. package/dist/core/dist/components/marker.js +28 -28
  16. package/dist/core/dist/components/reference-line.js +16 -16
  17. package/dist/core/dist/interactions/handler.js +3 -2
  18. package/dist/core/dist/interactions/zoom.js +6 -5
  19. package/dist/core/dist/navigator/controller.js +43 -40
  20. package/dist/core/dist/perf/perf-hud.js +3 -3
  21. package/dist/core/dist/scales/log-scale.js +76 -0
  22. package/dist/core/dist/scales/tick-tracker.js +2 -2
  23. package/dist/core/dist/scales/x-scale.js +47 -32
  24. package/dist/core/dist/scales/y-scale.js +155 -38
  25. package/dist/core/dist/series/bar-intro.js +11 -11
  26. package/dist/core/dist/series/bar.js +299 -249
  27. package/dist/core/dist/series/base-multi-layer.js +100 -76
  28. package/dist/core/dist/series/candlestick.js +252 -249
  29. package/dist/core/dist/series/heatmap.js +16 -16
  30. package/dist/core/dist/series/line-intro.js +18 -18
  31. package/dist/core/dist/series/line.js +522 -424
  32. package/dist/core/dist/series/scale-stack.js +25 -0
  33. package/dist/core/dist/tooltip-position.js +5 -5
  34. package/dist/core/dist/utils/pixel-grid.js +10 -0
  35. package/dist/index.d.ts +279 -32
  36. package/dist/index.js +59 -57
  37. package/dist/ui/Crosshair.vue.js +14 -14
  38. package/dist/ui/HeatmapTooltip.vue.js +6 -6
  39. package/dist/ui/PieTooltip.vue.js +4 -4
  40. package/dist/ui/TimeAxis.vue.js +23 -22
  41. package/dist/ui/Tooltip.vue.js +71 -69
  42. package/dist/ui/YAxis.vue.js +25 -24
  43. package/dist/ui/YLabel.vue.js +50 -49
  44. package/package.json +2 -2
  45. package/src/ChartContainer.vue +20 -8
  46. package/src/composables.ts +35 -1
  47. package/src/index.ts +5 -0
  48. package/src/ui/Crosshair.vue +2 -2
  49. package/src/ui/TimeAxis.vue +7 -4
  50. package/src/ui/Tooltip.vue +4 -1
  51. package/src/ui/YAxis.vue +5 -3
  52. package/src/ui/YLabel.vue +3 -3
@@ -1,35 +1,45 @@
1
- import { DEFAULT_HISTORY_REVEAL as _, DEFAULT_BAR_INTRO as C, DEFAULT_BAR_SMOOTH as F, DEFAULT_BAR_ENTRY as N } from "../animation/config.js";
2
- import { growIntro as Q } from "./bar-intro.js";
3
- import { BaseMultiLayerSeries as $ } from "./base-multi-layer.js";
1
+ import { DEFAULT_HISTORY_REVEAL as N, DEFAULT_BAR_INTRO as J, DEFAULT_BAR_SMOOTH as $, DEFAULT_BAR_ENTRY as q } from "../animation/config.js";
2
+ import { growIntro as K } from "./bar-intro.js";
3
+ import { BaseMultiLayerSeries as Q } from "./base-multi-layer.js";
4
4
  import { resolveBarPainter as Z } from "./painters/resolve.js";
5
- import { fadeIntro as q } from "./wave-intro.js";
6
- const U = 2, G = {
5
+ import { ScaleStack as F } from "./scale-stack.js";
6
+ import { fadeIntro as tt } from "./wave-intro.js";
7
+ const G = 2, et = {
7
8
  // Single fallback resolver; the definition's `create` swaps in `theme.bar.color`.
8
9
  colors: ["#26a69a"],
9
10
  barWidthRatio: 0.6,
10
11
  stacking: "off",
11
12
  anchor: "center",
12
- cornerRadius: U,
13
- entryMs: N,
14
- smoothMs: F,
15
- introMs: C,
16
- historyRevealMs: _
13
+ cornerRadius: G,
14
+ entryMs: q,
15
+ smoothMs: $,
16
+ introMs: J,
17
+ historyRevealMs: N
17
18
  };
18
- function I(y) {
19
+ function U(y) {
19
20
  return {
20
21
  ...y,
21
- entryMs: y.entryMs === !1 ? 0 : y.entryMs ?? N,
22
- smoothMs: y.smoothMs === !1 ? 0 : y.smoothMs ?? F,
23
- introMs: y.introMs === !1 ? 0 : y.introMs ?? C,
24
- historyRevealMs: y.historyRevealMs === !1 ? 0 : y.historyRevealMs ?? _
22
+ entryMs: y.entryMs === !1 ? 0 : y.entryMs ?? q,
23
+ smoothMs: y.smoothMs === !1 ? 0 : y.smoothMs ?? $,
24
+ introMs: y.introMs === !1 ? 0 : y.introMs ?? J,
25
+ historyRevealMs: y.historyRevealMs === !1 ? 0 : y.historyRevealMs ?? N
25
26
  };
26
27
  }
27
- const J = Q(), K = q(), tt = {
28
+ const it = K(), ot = tt(), at = {
28
29
  top: { tl: !0, tr: !0, br: !1, bl: !1 },
29
30
  bottom: { tl: !1, tr: !1, br: !0, bl: !0 },
30
31
  none: { tl: !1, tr: !1, br: !1, bl: !1 }
31
32
  };
32
- class et extends $ {
33
+ function st(y) {
34
+ const e = [], t = [];
35
+ let o = 0, s = 0;
36
+ for (const a of y) {
37
+ const n = a > 0 ? o : s;
38
+ e.push(n), t.push(n + a), a > 0 ? o += a : s += a;
39
+ }
40
+ return { base: e, end: t };
41
+ }
42
+ class rt extends Q {
33
43
  kind = "bar";
34
44
  /** Resolved drawing context for the in-flight render pass. Set at the top of
35
45
  * {@link render}, read by {@link drawAnimatedBar}. */
@@ -43,10 +53,10 @@ class et extends $ {
43
53
  /** Per-frame history-reveal directives; `null` when no reveal is in flight. */
44
54
  #t = null;
45
55
  constructor(e, t) {
46
- super(e), this.options = I({ ...G, ...t });
56
+ super(e), this.options = U({ ...et, ...t });
47
57
  }
48
58
  updateOptions(e) {
49
- this.options = I({ ...this.options, ...e });
59
+ this.options = U({ ...this.options, ...e });
50
60
  }
51
61
  isEntryEnabled() {
52
62
  return (this.options.entryAnimation ?? "fade-grow") !== "none";
@@ -58,7 +68,7 @@ class et extends $ {
58
68
  #a(e) {
59
69
  const t = this.#i;
60
70
  if (t === null) return null;
61
- const o = t.to - t.from, n = o > 0 ? (e - t.from) / o : 0, a = Math.min(1, Math.max(0, n));
71
+ const o = t.to - t.from, s = o > 0 ? (e - t.from) / o : 0, a = Math.min(1, Math.max(0, s));
62
72
  return { position: a, progress: this.introWave.progressAt(a) };
63
73
  }
64
74
  /**
@@ -67,10 +77,10 @@ class et extends $ {
67
77
  * the deepest prepended point). `null` for bars outside the prepended
68
78
  * span or when no reveal is in flight this frame.
69
79
  */
70
- #r(e) {
80
+ #s(e) {
71
81
  const t = this.historyRange;
72
82
  if (this.#t === null || t === null || e >= t.to) return null;
73
- const o = t.to - t.from, n = o > 0 ? (t.to - e) / o : 0, a = Math.min(1, Math.max(0, n));
83
+ const o = t.to - t.from, s = o > 0 ? (t.to - e) / o : 0, a = Math.min(1, Math.max(0, s));
74
84
  return { position: a, progress: this.historyWave.progressAt(a) };
75
85
  }
76
86
  /**
@@ -85,16 +95,16 @@ class et extends $ {
85
95
  if (this.isProjectedTime(e.time)) return e.value;
86
96
  const t = this.#t?.value;
87
97
  if (t !== void 0) {
88
- const a = this.#r(e.time);
98
+ const a = this.#s(e.time);
89
99
  if (a !== null) return t({ ...e, ...a });
90
100
  }
91
101
  const o = this.#e?.value;
92
102
  if (o === void 0) return e.value;
93
- const n = this.#a(e.time);
94
- return n === null ? e.value : o({ ...e, ...n });
103
+ const s = this.#a(e.time);
104
+ return s === null ? e.value : o({ ...e, ...s });
95
105
  }
96
106
  applyTheme(e, t) {
97
- const o = this.stores.length === 1, n = e.seriesColors[0] ?? "#26a69a", a = o ? [e.bar?.color ?? n] : e.seriesColors.slice(0, this.stores.length);
107
+ const o = this.stores.length === 1, s = e.seriesColors[0] ?? "#26a69a", a = o ? [e.bar?.color ?? s] : e.seriesColors.slice(0, this.stores.length);
98
108
  this.updateOptions({ colors: a });
99
109
  }
100
110
  /** True when `time` is at/after the configured `projectedFrom` forecast cut. */
@@ -108,20 +118,20 @@ class et extends $ {
108
118
  * each render path.
109
119
  */
110
120
  applyBarTransform(e, t) {
111
- const { baselineY: o, topY: n, barHeight: a, x: m, barWidth: v } = e, b = this.options.entryAnimation ?? "fade-grow";
112
- if (t >= 1 || b === "none")
113
- return { topY: n, barHeight: a, x: m, barWidth: v, alpha: 1 };
114
- let l = n, u = a, x = m, R = 1;
115
- if ((b === "fade" || b === "fade-grow") && (R = t), (b === "grow" || b === "fade-grow") && !e.growBaked) {
121
+ const { baselineY: o, topY: s, barHeight: a, x: n, barWidth: b } = e, d = this.options.entryAnimation ?? "fade-grow";
122
+ if (t >= 1 || d === "none")
123
+ return { topY: s, barHeight: a, x: n, barWidth: b, alpha: 1 };
124
+ let p = s, l = a, c = n, x = 1;
125
+ if ((d === "fade" || d === "fade-grow") && (x = t), (d === "grow" || d === "fade-grow") && !e.growBaked) {
116
126
  const r = a * t;
117
- n < o ? l = o - r : l = o, u = Math.max(1, r);
127
+ s < o ? p = o - r : p = o, l = Math.max(1, r);
118
128
  }
119
- return b === "slide" && (x = m + (1 - t) * v, R = t), { topY: l, barHeight: u, x, barWidth: v, alpha: R };
129
+ return d === "slide" && (c = n + (1 - t) * b, x = t), { topY: p, barHeight: l, x: c, barWidth: b, alpha: x };
120
130
  }
121
131
  render(e) {
122
132
  this.tickAnimations(performance.now());
123
- const { scope: t, timeScale: o, yScale: n } = e;
124
- if (this.#o = {
133
+ const { scope: t, timeScale: o, yScale: s } = e;
134
+ this.#o = {
125
135
  painter: Z(this.options.barPainter),
126
136
  env: {
127
137
  ctx: t.context,
@@ -129,42 +139,49 @@ class et extends $ {
129
139
  horizontalPixelRatio: t.horizontalPixelRatio,
130
140
  verticalPixelRatio: t.verticalPixelRatio
131
141
  },
132
- radius: (this.options.cornerRadius ?? U) * t.horizontalPixelRatio
133
- }, this.#e = null, this.#i = null, this.introWave.active) {
134
- const l = this.options.introAnimation ?? J, u = o.getRange();
135
- this.#i = u, this.#e = l({
142
+ radius: (this.options.cornerRadius ?? G) * t.horizontalPixelRatio
143
+ };
144
+ const a = {
145
+ baseline: s.baselineValue(),
146
+ lerpValue: (l, c, x) => s.lerpValue(l, c, x)
147
+ };
148
+ if (this.#e = null, this.#i = null, this.introWave.active) {
149
+ const l = this.options.introAnimation ?? it, c = o.getRange();
150
+ this.#i = c, this.#e = l({
136
151
  progress: this.introWave.linear(),
137
152
  // Plot-area extent, not the canvas bitmap — the canvas also carries
138
153
  // the axis strips, so a width-based front (wipeIntro) would overshoot
139
154
  // the data area.
140
155
  width: o.getMediaWidth() * t.horizontalPixelRatio,
141
- height: n.getMediaHeight() * t.verticalPixelRatio,
142
- range: u,
143
- timeToX: (x) => o.timeToBitmapX(x)
156
+ height: s.getMediaHeight() * t.verticalPixelRatio,
157
+ range: c,
158
+ timeToX: (x) => o.timeToBitmapX(x),
159
+ ...a
144
160
  });
145
161
  }
146
162
  this.#t = null;
147
- const a = this.historyRange;
148
- if (this.historyWave.active && a !== null) {
149
- const l = this.options.historyReveal ?? K;
163
+ const n = this.historyRange;
164
+ if (this.historyWave.active && n !== null) {
165
+ const l = this.options.historyReveal ?? ot;
150
166
  l !== "none" && (this.#t = l({
151
167
  progress: this.historyWave.linear(),
152
- width: Math.abs(o.timeToBitmapX(a.to) - o.timeToBitmapX(a.from)),
153
- height: n.getMediaHeight() * t.verticalPixelRatio,
154
- range: a,
155
- timeToX: (u) => o.timeToBitmapX(u)
168
+ width: Math.abs(o.timeToBitmapX(n.to) - o.timeToBitmapX(n.from)),
169
+ height: s.getMediaHeight() * t.verticalPixelRatio,
170
+ range: n,
171
+ timeToX: (c) => o.timeToBitmapX(c),
172
+ ...a
156
173
  }));
157
174
  }
158
- const m = this.#e?.clip;
159
- if (m !== void 0) {
160
- const l = m.fromX ?? 0, u = m.toX ?? t.bitmapSize.width;
161
- t.context.save(), t.context.beginPath(), t.context.rect(l, 0, Math.max(0, u - l), t.bitmapSize.height), t.context.clip();
175
+ const b = this.#e?.clip;
176
+ if (b !== void 0) {
177
+ const l = b.fromX ?? 0, c = b.toX ?? t.bitmapSize.width;
178
+ t.context.save(), t.context.beginPath(), t.context.rect(l, 0, Math.max(0, c - l), t.bitmapSize.height), t.context.clip();
162
179
  }
163
- const v = this.#t?.clip;
164
- let b = !1;
165
- if (v !== void 0 && a !== null) {
166
- const l = o.timeToBitmapX(a.to), u = Math.abs(l - o.timeToBitmapX(a.from)), x = o.barWidthBitmap(e.dataInterval), R = v.fromX ?? 0, r = v.toX ?? u;
167
- t.context.save(), t.context.beginPath(), t.context.rect(l - r - x, 0, Math.max(0, r - R + x), t.bitmapSize.height), t.context.rect(l, 0, Math.max(0, t.bitmapSize.width - l), t.bitmapSize.height), t.context.clip(), b = !0;
180
+ const d = this.#t?.clip;
181
+ let p = !1;
182
+ if (d !== void 0 && n !== null) {
183
+ const l = o.timeToBitmapX(n.to), c = Math.abs(l - o.timeToBitmapX(n.from)), x = o.barWidthBitmap(e.dataInterval), r = d.fromX ?? 0, w = d.toX ?? c;
184
+ t.context.save(), t.context.beginPath(), t.context.rect(l - w - x, 0, Math.max(0, w - r + x), t.bitmapSize.height), t.context.rect(l, 0, Math.max(0, t.bitmapSize.width - l), t.bitmapSize.height), t.context.clip(), p = !0;
168
185
  }
169
186
  switch (this.options.stacking) {
170
187
  case "normal":
@@ -177,240 +194,273 @@ class et extends $ {
177
194
  this.renderOff(e);
178
195
  break;
179
196
  }
180
- b && t.context.restore(), m !== void 0 && t.context.restore();
197
+ p && t.context.restore(), b !== void 0 && t.context.restore();
181
198
  }
182
199
  /** Stacking off — each layer drawn independently from zero, overlapping */
183
200
  renderOff(e) {
184
- const { scope: t, timeScale: o, yScale: n, dataInterval: a } = e, { context: m, horizontalPixelRatio: v } = t, b = o.getRange();
185
- let l = 0;
186
- for (const M of this.stores) {
187
- if (!M.isVisible()) continue;
188
- const p = M.getVisibleData(b.from, b.to).length;
189
- if (p > l && (l = p), l > 2) break;
201
+ const { scope: t, timeScale: o, yScale: s, dataInterval: a } = e, { context: n, horizontalPixelRatio: b } = t, d = o.getRange();
202
+ let p = 0;
203
+ for (const B of this.stores) {
204
+ if (!B.isVisible()) continue;
205
+ const f = B.getVisibleData(d.from, d.to).length;
206
+ if (f > p && (p = f), p > 2) break;
190
207
  }
191
- const u = o.barWidthBitmap(a), x = Math.round(30 * v), R = l <= 2 ? Math.min(x, u) : u, r = Math.max(1, Math.round(R * this.options.barWidthRatio) - 2), W = Math.floor(r / 2), H = this.options.anchor === "right" ? r : W, T = n.getRange().min < 0, f = T ? n.valueToBitmapY(0) : t.bitmapSize.height;
208
+ const l = o.barWidthBitmap(a), c = Math.round(30 * b), x = p <= 2 ? Math.min(c, l) : l, r = Math.max(1, Math.round(x * this.options.barWidthRatio) - 2), w = Math.floor(r / 2), j = this.options.anchor === "right" ? r : w, E = s.getRange().min < 0, u = E ? s.valueToBitmapY(0) : t.bitmapSize.height;
192
209
  if (this.stores.length === 1) {
193
210
  if (!this.stores[0].isVisible()) return;
194
- const M = this.stores[0].getVisibleData(b.from, b.to);
195
- for (const p of M) {
196
- if (!Number.isFinite(p.value)) continue;
197
- const d = this.effectiveValue(e, 0, p.time, p.value), P = this.introValue({ layerIndex: 0, time: p.time, value: d }), B = this.entranceProgress(0, p.time), i = this.isProjectedTime(p.time), h = o.timeToBitmapX(p.time), s = this.resolveLayerColor(0, d);
198
- if (P >= 0) {
199
- const g = n.valueToBitmapY(P), c = Math.max(1, f - g);
211
+ const B = this.stores[0].getVisibleData(d.from, d.to);
212
+ for (const f of B) {
213
+ if (!s.isPlottable(f.value)) continue;
214
+ const I = this.effectiveValue(e, 0, f.time, f.value), g = this.introValue({ layerIndex: 0, time: f.time, value: I }), M = this.entranceProgress(0, f.time), Y = this.isProjectedTime(f.time), R = o.timeToBitmapX(f.time), A = this.resolveLayerColor(0, I);
215
+ if (g >= 0) {
216
+ const i = s.valueToBitmapY(g), m = Math.max(1, u - i);
200
217
  this.drawAnimatedBar({
201
- context: m,
202
- time: p.time,
203
- progress: B,
204
- baselineY: f,
205
- topY: g,
206
- barHeight: c,
207
- x: h - H,
218
+ context: n,
219
+ time: f.time,
220
+ progress: M,
221
+ baselineY: u,
222
+ topY: i,
223
+ barHeight: m,
224
+ x: R - j,
208
225
  barWidth: r,
209
- color: s,
226
+ color: A,
210
227
  roundEdge: "top",
211
- isProjected: i
228
+ isProjected: Y
212
229
  });
213
230
  } else {
214
- const g = n.valueToBitmapY(P), c = Math.max(1, g - f);
231
+ const i = s.valueToBitmapY(g), m = Math.max(1, i - u);
215
232
  this.drawAnimatedBar({
216
- context: m,
217
- time: p.time,
218
- progress: B,
219
- baselineY: f,
220
- topY: f,
221
- barHeight: c,
222
- x: h - H,
233
+ context: n,
234
+ time: f.time,
235
+ progress: M,
236
+ baselineY: u,
237
+ topY: u,
238
+ barHeight: m,
239
+ x: R - j,
223
240
  barWidth: r,
224
- color: s,
241
+ color: A,
225
242
  roundEdge: "bottom",
226
- isProjected: i
243
+ isProjected: Y
227
244
  });
228
245
  }
229
246
  }
230
247
  } else {
231
- const M = this.stores.map(
232
- (d, P) => this.getLayerAlpha(P) > 0 ? d.getVisibleData(b.from, b.to) : []
233
- ), p = /* @__PURE__ */ new Map();
234
- for (let d = 0; d < M.length; d++) {
235
- const P = this.getLayerAlpha(d);
236
- for (const B of M[d]) {
237
- if (!Number.isFinite(B.value)) continue;
238
- let i = p.get(B.time);
239
- i || (i = [], p.set(B.time, i));
240
- const h = this.effectiveValue(e, d, B.time, B.value) * P;
241
- i.push({
242
- layer: d,
243
- value: this.introValue({ layerIndex: d, time: B.time, value: h }),
248
+ const B = this.stores.map(
249
+ (g, M) => this.getLayerAlpha(M) > 0 ? g.getVisibleData(d.from, d.to) : []
250
+ ), f = /* @__PURE__ */ new Map(), I = s.baselineValue();
251
+ for (let g = 0; g < B.length; g++) {
252
+ const M = this.getLayerAlpha(g);
253
+ for (const Y of B[g]) {
254
+ if (!s.isPlottable(Y.value)) continue;
255
+ let R = f.get(Y.time);
256
+ R || (R = [], f.set(Y.time, R));
257
+ const A = this.effectiveValue(e, g, Y.time, Y.value), i = M === 1 ? A : s.lerpValue(I, A, M);
258
+ R.push({
259
+ layer: g,
260
+ value: this.introValue({ layerIndex: g, time: Y.time, value: i }),
244
261
  // Color resolves from the settled data value — same contract as
245
262
  // the single-layer path — so a threshold value-fn doesn't flicker
246
263
  // hues while the intro sweeps the drawn value from 0 to final.
247
- colorValue: B.value
264
+ colorValue: Y.value
248
265
  });
249
266
  }
250
267
  }
251
- for (const [d, P] of p) {
252
- P.sort(
253
- (h, s) => Math.abs(s.value) - Math.abs(h.value)
268
+ for (const [g, M] of f) {
269
+ M.sort(
270
+ (A, i) => Math.abs(i.value) - Math.abs(A.value)
254
271
  );
255
- const B = o.timeToBitmapX(d), i = this.isProjectedTime(d);
256
- for (let h = 0; h < P.length; h++) {
257
- const { layer: s, value: g, colorValue: c } = P[h], S = this.resolveLayerColor(s, c), E = this.entranceProgress(s, d);
258
- if (g >= 0) {
259
- const k = n.valueToBitmapY(g), V = Math.max(1, f - k);
272
+ const Y = o.timeToBitmapX(g), R = this.isProjectedTime(g);
273
+ for (let A = 0; A < M.length; A++) {
274
+ const { layer: i, value: m, colorValue: h } = M[A], T = this.resolveLayerColor(i, h), v = this.entranceProgress(i, g);
275
+ if (m >= 0) {
276
+ const V = s.valueToBitmapY(m), S = Math.max(1, u - V);
260
277
  this.drawAnimatedBar({
261
- context: m,
262
- time: d,
263
- progress: E,
264
- baselineY: f,
265
- topY: k,
266
- barHeight: V,
267
- x: B - H,
278
+ context: n,
279
+ time: g,
280
+ progress: v,
281
+ baselineY: u,
282
+ topY: V,
283
+ barHeight: S,
284
+ x: Y - j,
268
285
  barWidth: r,
269
- color: S,
286
+ color: T,
270
287
  roundEdge: "top",
271
- isProjected: i
288
+ isProjected: R
272
289
  });
273
290
  } else {
274
- const k = n.valueToBitmapY(g), V = Math.max(1, k - f);
291
+ const V = s.valueToBitmapY(m), S = Math.max(1, V - u);
275
292
  this.drawAnimatedBar({
276
- context: m,
277
- time: d,
278
- progress: E,
279
- baselineY: f,
280
- topY: f,
281
- barHeight: V,
282
- x: B - H,
293
+ context: n,
294
+ time: g,
295
+ progress: v,
296
+ baselineY: u,
297
+ topY: u,
298
+ barHeight: S,
299
+ x: Y - j,
283
300
  barWidth: r,
284
- color: S,
301
+ color: T,
285
302
  roundEdge: "bottom",
286
- isProjected: i
303
+ isProjected: R
287
304
  });
288
305
  }
289
306
  }
290
307
  }
291
308
  }
292
- if (T) {
293
- m.strokeStyle = e.theme.grid.color, m.lineWidth = 1;
294
- const M = Math.round(f) + 0.5;
295
- m.beginPath(), m.moveTo(0, M), m.lineTo(t.bitmapSize.width, M), m.stroke();
309
+ if (E) {
310
+ n.strokeStyle = e.theme.grid.color, n.lineWidth = 1;
311
+ const B = Math.round(u) + 0.5;
312
+ n.beginPath(), n.moveTo(0, B), n.lineTo(t.bitmapSize.width, B), n.stroke();
296
313
  }
297
314
  }
298
315
  /** Stacked (normal or percent) rendering */
299
316
  renderStacked(e, t) {
300
- const { scope: o, timeScale: n, yScale: a, dataInterval: m } = e, { context: v, horizontalPixelRatio: b } = o, l = n.getRange();
301
- let u = 0;
317
+ const { scope: o, timeScale: s, yScale: a, dataInterval: n } = e, { context: b, horizontalPixelRatio: d } = o, p = s.getRange();
318
+ let l = 0;
302
319
  for (const i of this.stores) {
303
320
  if (!i.isVisible()) continue;
304
- const h = i.getVisibleData(l.from, l.to).length;
305
- if (h > u && (u = h), u > 2) break;
321
+ const m = i.getVisibleData(p.from, p.to).length;
322
+ if (m > l && (l = m), l > 2) break;
306
323
  }
307
- const x = n.barWidthBitmap(m), R = Math.round(30 * b), r = u <= 2 ? Math.min(R, x) : x, W = Math.max(1, Math.round(r * this.options.barWidthRatio) - 2), H = Math.floor(W / 2), T = this.options.anchor === "right" ? W : H, f = this.stores.map(
308
- (i, h) => this.getLayerAlpha(h) > 0 ? i.getVisibleData(l.from, l.to) : []
324
+ const c = s.barWidthBitmap(n), x = Math.round(30 * d), r = l <= 2 ? Math.min(x, c) : c, w = Math.max(1, Math.round(r * this.options.barWidthRatio) - 2), j = Math.floor(w / 2), E = this.options.anchor === "right" ? w : j, u = this.stores.map(
325
+ (i, m) => this.getLayerAlpha(m) > 0 ? i.getVisibleData(p.from, p.to) : []
309
326
  );
310
- if (f.every((i) => i.length === 0)) return;
311
- const M = this.options.entryAnimation ?? "fade-grow", p = M === "grow" || M === "fade-grow", d = /* @__PURE__ */ new Map();
312
- for (let i = 0; i < f.length; i++) {
313
- const h = this.getLayerAlpha(i);
314
- for (const s of f[i]) {
315
- let g = d.get(s.time);
316
- g || (g = new Array(f.length).fill(0), d.set(s.time, g));
317
- const c = Number.isFinite(s.value) ? s.value : 0;
318
- let S = this.effectiveValue(e, i, s.time, c) * h;
319
- p && !this.isProjectedTime(s.time) && (S *= this.entranceProgress(i, s.time)), g[i] = this.introValue({ layerIndex: i, time: s.time, value: S });
327
+ if (u.every((i) => i.length === 0)) return;
328
+ const B = this.options.entryAnimation ?? "fade-grow", f = B === "grow" || B === "fade-grow", I = a.getTransform() !== null && !t, g = /* @__PURE__ */ new Map(), M = /* @__PURE__ */ new Map();
329
+ for (let i = 0; i < u.length; i++) {
330
+ const m = this.getLayerAlpha(i);
331
+ for (const h of u[i]) {
332
+ let T = M.get(h.time);
333
+ T || (T = new Array(u.length).fill(0), M.set(h.time, T));
334
+ const v = a.isPlottable(h.value) ? h.value : 0, V = this.effectiveValue(e, i, h.time, v);
335
+ let S = V * m, X = m;
336
+ if (f && !this.isProjectedTime(h.time)) {
337
+ const W = this.entranceProgress(i, h.time);
338
+ S *= W, X *= W;
339
+ }
340
+ if (I) {
341
+ T[i] = S;
342
+ let W = g.get(h.time);
343
+ W || (W = { settled: new Array(u.length).fill(0), weights: new Array(u.length).fill(0) }, g.set(h.time, W)), W.settled[i] = V, W.weights[i] = X;
344
+ continue;
345
+ }
346
+ T[i] = this.introValue({ layerIndex: i, time: h.time, value: S });
320
347
  }
321
348
  }
322
- const P = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Map();
323
- for (const [i, h] of d) {
324
- let s = -1, g = -1;
325
- for (let c = 0; c < h.length; c++)
326
- h[c] > 0 && (s = c), h[c] < 0 && (g = c);
327
- s >= 0 && P.set(i, s), g >= 0 && B.set(i, g);
349
+ const Y = /* @__PURE__ */ new Map();
350
+ if (!t)
351
+ for (const [i, m] of M) {
352
+ const h = g.get(i);
353
+ Y.set(i, h === void 0 ? st(m) : this.scaleEdges({ time: i, share: h, yScale: a }));
354
+ }
355
+ const R = /* @__PURE__ */ new Map(), A = /* @__PURE__ */ new Map();
356
+ for (const [i, m] of M) {
357
+ let h = -1, T = -1;
358
+ for (let v = 0; v < m.length; v++)
359
+ m[v] > 0 && (h = v), m[v] < 0 && (T = v);
360
+ h >= 0 && R.set(i, h), T >= 0 && A.set(i, T);
328
361
  }
329
- for (let i = 0; i < f.length; i++) {
330
- const h = this.resolveLayerColor(i, this.stores[i].last()?.value ?? 0);
331
- for (const [s, g] of d) {
332
- const c = g[i];
333
- if (c === 0) continue;
334
- const S = n.timeToBitmapX(s);
335
- let E = 0, k = 0;
336
- for (let Y = 0; Y < i; Y++) {
337
- const w = g[Y];
338
- w > 0 ? E += w : k += w;
339
- }
340
- const V = this.entranceProgress(i, s), X = this.isProjectedTime(s), z = c > 0 ? P.get(s) === i ? "top" : "none" : B.get(s) === i ? "bottom" : "none";
362
+ for (let i = 0; i < u.length; i++) {
363
+ const m = this.resolveLayerColor(i, this.stores[i].last()?.value ?? 0);
364
+ for (const [h, T] of M) {
365
+ const v = T[i];
366
+ if (v === 0) continue;
367
+ const V = s.timeToBitmapX(h), S = this.entranceProgress(i, h), X = this.isProjectedTime(h), W = v > 0 ? R.get(h) === i ? "top" : "none" : A.get(h) === i ? "bottom" : "none";
341
368
  if (t) {
342
- let Y = 0, w = 0;
343
- for (const A of g)
344
- A > 0 ? Y += A : w += A;
345
- if (c > 0 && Y > 0) {
346
- const A = E / Y * 100, D = (E + c) / Y * 100, j = a.valueToBitmapY(D), L = a.valueToBitmapY(A), O = Math.max(1, L - j);
369
+ let L = 0, D = 0;
370
+ for (let P = 0; P < i; P++) {
371
+ const k = T[P];
372
+ k > 0 ? L += k : D += k;
373
+ }
374
+ let z = 0, H = 0;
375
+ for (const P of T)
376
+ P > 0 ? z += P : H += P;
377
+ if (v > 0 && z > 0) {
378
+ const P = L / z * 100, k = (L + v) / z * 100, C = a.valueToBitmapY(k), O = a.valueToBitmapY(P), _ = Math.max(1, O - C);
347
379
  this.drawAnimatedBar({
348
- context: v,
349
- time: s,
350
- progress: V,
351
- baselineY: L,
352
- topY: j,
353
- barHeight: O,
354
- x: S - T,
355
- barWidth: W,
356
- color: h,
357
- roundEdge: z,
380
+ context: b,
381
+ time: h,
382
+ progress: S,
383
+ baselineY: O,
384
+ topY: C,
385
+ barHeight: _,
386
+ x: V - E,
387
+ barWidth: w,
388
+ color: m,
389
+ roundEdge: W,
358
390
  isProjected: X,
359
391
  growBaked: !0
360
392
  });
361
- } else if (c < 0 && w < 0) {
362
- const A = k / w * -100, D = (k + c) / w * -100, j = a.valueToBitmapY(A), L = a.valueToBitmapY(D), O = Math.max(1, L - j);
393
+ } else if (v < 0 && H < 0) {
394
+ const P = D / H * -100, k = (D + v) / H * -100, C = a.valueToBitmapY(P), O = a.valueToBitmapY(k), _ = Math.max(1, O - C);
363
395
  this.drawAnimatedBar({
364
- context: v,
365
- time: s,
366
- progress: V,
367
- baselineY: j,
368
- topY: j,
369
- barHeight: O,
370
- x: S - T,
371
- barWidth: W,
372
- color: h,
373
- roundEdge: z,
396
+ context: b,
397
+ time: h,
398
+ progress: S,
399
+ baselineY: C,
400
+ topY: C,
401
+ barHeight: _,
402
+ x: V - E,
403
+ barWidth: w,
404
+ color: m,
405
+ roundEdge: W,
374
406
  isProjected: X,
375
407
  growBaked: !0
376
408
  });
377
409
  }
378
- } else if (c > 0) {
379
- const Y = a.valueToBitmapY(E + c), w = a.valueToBitmapY(E), A = Math.max(1, w - Y);
380
- this.drawAnimatedBar({
381
- context: v,
382
- time: s,
383
- progress: V,
384
- baselineY: w,
385
- topY: Y,
386
- barHeight: A,
387
- x: S - T,
388
- barWidth: W,
389
- color: h,
390
- roundEdge: z,
391
- isProjected: X,
392
- growBaked: !0
393
- });
394
410
  } else {
395
- const Y = a.valueToBitmapY(k), w = a.valueToBitmapY(k + c), A = Math.max(1, w - Y);
396
- this.drawAnimatedBar({
397
- context: v,
398
- time: s,
399
- progress: V,
400
- baselineY: Y,
401
- topY: Y,
402
- barHeight: A,
403
- x: S - T,
404
- barWidth: W,
405
- color: h,
406
- roundEdge: z,
407
- isProjected: X,
408
- growBaked: !0
409
- });
411
+ const L = Y.get(h);
412
+ if (L === void 0) continue;
413
+ const D = L.base[i], z = L.end[i];
414
+ if (v > 0) {
415
+ const H = a.valueToBitmapY(z), P = a.valueToBitmapY(D), k = Math.max(1, P - H);
416
+ this.drawAnimatedBar({
417
+ context: b,
418
+ time: h,
419
+ progress: S,
420
+ baselineY: P,
421
+ topY: H,
422
+ barHeight: k,
423
+ x: V - E,
424
+ barWidth: w,
425
+ color: m,
426
+ roundEdge: W,
427
+ isProjected: X,
428
+ growBaked: !0
429
+ });
430
+ } else {
431
+ const H = a.valueToBitmapY(D), P = a.valueToBitmapY(z), k = Math.max(1, P - H);
432
+ this.drawAnimatedBar({
433
+ context: b,
434
+ time: h,
435
+ progress: S,
436
+ baselineY: H,
437
+ topY: H,
438
+ barHeight: k,
439
+ x: V - E,
440
+ barWidth: w,
441
+ color: m,
442
+ roundEdge: W,
443
+ isProjected: X,
444
+ growBaked: !0
445
+ });
446
+ }
410
447
  }
411
448
  }
412
449
  }
413
450
  }
451
+ /**
452
+ * Segment edges of one column on a non-linear axis. Fades and entrances
453
+ * stack through {@link ScaleStack}; the intro then moves each drawn edge,
454
+ * so the column grows from the floor as one unit at an even pixel speed.
455
+ */
456
+ scaleEdges(e) {
457
+ const { time: t, share: o, yScale: s } = e, a = { positive: new F(s), negative: new F(s) }, n = { positive: a.positive.edge, negative: a.negative.edge }, b = [], d = [];
458
+ for (let p = 0; p < o.settled.length; p++) {
459
+ const l = o.settled[p], c = l < 0 ? "negative" : "positive", x = a[c].push(l, o.weights[p]), r = this.introValue({ layerIndex: p, time: t, value: x });
460
+ b.push(n[c]), d.push(r), n[c] = r;
461
+ }
462
+ return { base: b, end: d };
463
+ }
414
464
  /**
415
465
  * Paint one bar through the resolved painter, applying any entrance transform
416
466
  * and per-bar alpha first. The painter owns the fill (and the rounded-corner
@@ -420,54 +470,54 @@ class et extends $ {
420
470
  drawAnimatedBar(e) {
421
471
  const t = this.#o;
422
472
  if (t === null) return;
423
- const { context: o, baselineY: n, topY: a, barHeight: m, x: v, barWidth: b, color: l, roundEdge: u } = e, x = e.isProjected ? 1 : e.progress, R = this.options.entryAnimation ?? "fade-grow";
424
- let r = x >= 1 || R === "none" ? { x: v, topY: a, barWidth: b, barHeight: m, alpha: 1 } : this.applyBarTransform(e, x);
473
+ const { context: o, baselineY: s, topY: a, barHeight: n, x: b, barWidth: d, color: p, roundEdge: l } = e, c = e.isProjected ? 1 : e.progress, x = this.options.entryAnimation ?? "fade-grow";
474
+ let r = c >= 1 || x === "none" ? { x: b, topY: a, barWidth: d, barHeight: n, alpha: 1 } : this.applyBarTransform(e, c);
425
475
  if (!e.isProjected) {
426
- const H = this.#t?.element, T = H !== void 0 ? this.#r(e.time) : null, f = T !== null ? H : this.#e?.element, M = T ?? (f !== void 0 ? this.#a(e.time) : null);
427
- if (f !== void 0 && M !== null) {
428
- const p = f({
429
- ...M,
476
+ const j = this.#t?.element, E = j !== void 0 ? this.#s(e.time) : null, u = E !== null ? j : this.#e?.element, B = E ?? (u !== void 0 ? this.#a(e.time) : null);
477
+ if (u !== void 0 && B !== null) {
478
+ const f = u({
479
+ ...B,
430
480
  time: e.time,
431
481
  x: r.x,
432
482
  topY: r.topY,
433
483
  barHeight: r.barHeight,
434
- baselineY: n,
484
+ baselineY: s,
435
485
  barWidth: r.barWidth
436
486
  });
437
487
  r = {
438
488
  ...r,
439
- x: r.x + (p.offsetX ?? 0),
440
- topY: r.topY + (p.offsetY ?? 0),
441
- alpha: r.alpha * (p.alpha ?? 1)
489
+ x: r.x + (f.offsetX ?? 0),
490
+ topY: r.topY + (f.offsetY ?? 0),
491
+ alpha: r.alpha * (f.alpha ?? 1)
442
492
  };
443
493
  }
444
494
  }
445
- const W = {
446
- geom: { x: r.x, y: r.topY, width: r.barWidth, height: r.barHeight, baselineY: n },
447
- color: l,
448
- corners: tt[u],
495
+ const w = {
496
+ geom: { x: r.x, y: r.topY, width: r.barWidth, height: r.barHeight, baselineY: s },
497
+ color: p,
498
+ corners: at[l],
449
499
  // Clamp to this bar's geometry so `radius` honors its pre-clamped contract
450
500
  // for custom painters; `fillRoundedRect` re-clamps to the same bound, so
451
501
  // the built-in output is unchanged.
452
502
  radius: Math.min(t.radius, r.barWidth / 2, r.barHeight / 2),
453
- progress: x,
503
+ progress: c,
454
504
  isProjected: e.isProjected
455
505
  };
456
506
  if (r.alpha < 1) {
457
- o.save(), o.globalAlpha = r.alpha, t.painter(t.env, W), o.restore();
507
+ o.save(), o.globalAlpha = r.alpha, t.painter(t.env, w), o.restore();
458
508
  return;
459
509
  }
460
- t.painter(t.env, W);
510
+ t.painter(t.env, w);
461
511
  }
462
512
  }
463
- const nt = {
513
+ const pt = {
464
514
  type: "bar",
465
515
  create: ({ theme: y, layerCount: e }, t) => {
466
516
  const o = e === 1 ? [y.bar?.color ?? y.seriesColors[0] ?? "#26a69a"] : y.seriesColors.slice(0, e);
467
- return new et(e, { colors: o, ...t });
517
+ return new rt(e, { colors: o, ...t });
468
518
  }
469
519
  };
470
520
  export {
471
- et as BarRenderer,
472
- nt as BarSeriesDef
521
+ rt as BarRenderer,
522
+ pt as BarSeriesDef
473
523
  };