@wick-charts/vue 0.6.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +21 -7
  2. package/dist/BandSeries.vue.js +20 -18
  3. package/dist/BarSeries.vue.js +15 -13
  4. package/dist/CandlestickSeries.vue.js +31 -29
  5. package/dist/ChartContainer.vue.js +77 -70
  6. package/dist/LineSeries.vue.js +19 -17
  7. package/dist/composables.js +46 -36
  8. package/dist/core/dist/animation/viewport-engine.js +155 -96
  9. package/dist/core/dist/axis/dom-labels.js +56 -51
  10. package/dist/core/dist/chart/scale-guards.js +23 -5
  11. package/dist/core/dist/chart/x-guards.js +37 -0
  12. package/dist/core/dist/chart.js +1286 -843
  13. package/dist/core/dist/data/sync.js +37 -31
  14. package/dist/core/dist/navigator/controller.js +37 -37
  15. package/dist/core/dist/perf/perf-hud.js +3 -3
  16. package/dist/core/dist/scales/tick-tracker.js +2 -2
  17. package/dist/core/dist/scales/x-scale.js +167 -53
  18. package/dist/core/dist/scales/y-scale.js +36 -34
  19. package/dist/core/dist/series/band.js +266 -213
  20. package/dist/core/dist/series/bar.js +297 -291
  21. package/dist/core/dist/series/base-multi-layer.js +283 -237
  22. package/dist/core/dist/series/candlestick.js +1 -0
  23. package/dist/core/dist/series/line.js +21 -20
  24. package/dist/core/dist/snapshots.js +55 -43
  25. package/dist/index.d.ts +323 -58
  26. package/dist/index.js +9 -9
  27. package/dist/ui/Crosshair.vue.js +51 -27
  28. package/dist/ui/InfoBar.vue.js +37 -37
  29. package/dist/ui/Marker.vue.js +14 -11
  30. package/dist/ui/Navigator.vue.js +23 -23
  31. package/dist/ui/ReferenceLine.vue.js +19 -16
  32. package/dist/ui/Tooltip.vue.js +91 -86
  33. package/dist/ui/XAxis.vue.js +48 -0
  34. package/dist/ui/XAxis.vue2.js +4 -0
  35. package/dist/ui/YAxis.vue.js +44 -28
  36. package/dist/ui/YLabel.vue.js +78 -74
  37. package/package.json +9 -3
  38. package/src/BandSeries.vue +11 -6
  39. package/src/BarSeries.vue +13 -6
  40. package/src/CandlestickSeries.vue +9 -5
  41. package/src/ChartContainer.vue +20 -0
  42. package/src/LineSeries.vue +13 -6
  43. package/src/composables.ts +23 -4
  44. package/src/index.ts +8 -1
  45. package/src/ui/Crosshair.vue +41 -1
  46. package/src/ui/InfoBar.vue +2 -1
  47. package/src/ui/Marker.vue +5 -1
  48. package/src/ui/Navigator.vue +2 -1
  49. package/src/ui/ReferenceLine.vue +5 -1
  50. package/src/ui/Tooltip.vue +7 -4
  51. package/src/ui/{TimeAxis.vue → XAxis.vue} +18 -5
  52. package/src/ui/YAxis.vue +66 -12
  53. package/src/ui/YLabel.vue +35 -5
  54. package/dist/ui/TimeAxis.vue.js +0 -44
  55. package/dist/ui/TimeAxis.vue2.js +0 -4
@@ -1,57 +1,67 @@
1
- import { ref as u, onMounted as a, onUnmounted as l } from "vue";
2
- function x(e) {
3
- const o = u(e.getVisibleRange()), n = () => {
4
- o.value = e.getVisibleRange();
1
+ import { ref as l, onMounted as u, onUnmounted as a } from "vue";
2
+ function A(e) {
3
+ const n = l(e.getVisibleRange()), i = () => {
4
+ n.value = e.getVisibleRange();
5
5
  };
6
- return a(() => e.on("viewportChange", n)), l(() => e.off("viewportChange", n)), o;
6
+ return u(() => e.on("viewportChange", i)), a(() => e.off("viewportChange", i)), n;
7
7
  }
8
8
  function d(e) {
9
- const o = u(e.getYRange()), n = () => {
10
- o.value = e.getYRange();
9
+ const n = l(e.getYRange()), i = () => {
10
+ n.value = e.getYRange();
11
11
  };
12
- return a(() => e.on("viewportChange", n)), l(() => e.off("viewportChange", n)), o;
12
+ return u(() => e.on("viewportChange", i)), a(() => e.off("viewportChange", i)), n;
13
13
  }
14
14
  function r(e) {
15
- return { yAxisPosition: e.yAxisPosition, yAxisWidth: e.yAxisWidth, xAxisHeight: e.xAxisHeight };
15
+ return {
16
+ yAxisPosition: e.yAxisPosition,
17
+ yAxisWidth: e.yAxisWidth,
18
+ xAxisHeight: e.xAxisHeight,
19
+ leftAxisWidth: e.getAxisColumnWidth("left"),
20
+ rightAxisWidth: e.getAxisColumnWidth("right"),
21
+ leftAxisScale: e.getAxisColumnScale("left"),
22
+ rightAxisScale: e.getAxisColumnScale("right")
23
+ };
16
24
  }
17
- function p(e) {
18
- const o = u(r(e)), n = () => {
19
- const i = r(e), s = o.value;
20
- s.yAxisPosition === i.yAxisPosition && s.yAxisWidth === i.yAxisWidth && s.xAxisHeight === i.xAxisHeight || (o.value = i);
25
+ function h(e) {
26
+ const n = l(r(e)), i = () => {
27
+ const t = r(e), o = n.value;
28
+ o.yAxisPosition === t.yAxisPosition && o.yAxisWidth === t.yAxisWidth && o.xAxisHeight === t.xAxisHeight && o.leftAxisWidth === t.leftAxisWidth && o.rightAxisWidth === t.rightAxisWidth && o.leftAxisScale === t.leftAxisScale && o.rightAxisScale === t.rightAxisScale || (n.value = t);
21
29
  };
22
- return a(() => {
23
- n(), e.on("viewportChange", n);
24
- }), l(() => e.off("viewportChange", n)), o;
30
+ return u(() => {
31
+ i(), e.on("viewportChange", i);
32
+ }), a(() => e.off("viewportChange", i)), n;
25
33
  }
26
- function A(e, o) {
27
- let n = e.getLastValue(o), i = n ? e.yScale.valueToY(n.value) : null;
28
- const s = u(n), g = () => {
29
- const t = e.getLastValue(o), v = t ? e.yScale.valueToY(t.value) : null;
30
- n?.value === t?.value && n?.isLive === t?.isLive && i === v || (n = t, i = v, s.value = t);
34
+ function p(e, n) {
35
+ let i = e.getLastValue(n);
36
+ const t = () => e.getYScale(e.getSeriesScale(n));
37
+ let o = i ? t().valueToY(i.value) : null;
38
+ const x = l(i), g = () => {
39
+ const s = e.getLastValue(n), f = s ? t().valueToY(s.value) : null;
40
+ i?.value === s?.value && i?.isLive === s?.isLive && o === f || (i = s, o = f, x.value = s);
31
41
  };
32
- return a(() => {
42
+ return u(() => {
33
43
  e.on("dataUpdate", g), e.on("viewportChange", g);
34
- }), l(() => {
44
+ }), a(() => {
35
45
  e.off("dataUpdate", g), e.off("viewportChange", g);
36
- }), s;
46
+ }), x;
37
47
  }
38
- function C(e, o) {
39
- const n = u(e.getPreviousClose(o)), i = () => {
40
- n.value = e.getPreviousClose(o);
48
+ function C(e, n) {
49
+ const i = l(e.getPreviousClose(n)), t = () => {
50
+ i.value = e.getPreviousClose(n);
41
51
  };
42
- return a(() => e.on("dataUpdate", i)), l(() => e.off("dataUpdate", i)), n;
52
+ return u(() => e.on("dataUpdate", t)), a(() => e.off("dataUpdate", t)), i;
43
53
  }
44
- function y(e) {
45
- const o = u(e.getCrosshairPosition()), n = () => {
46
- o.value = e.getCrosshairPosition();
54
+ function c(e) {
55
+ const n = l(e.getCrosshairPosition()), i = () => {
56
+ n.value = e.getCrosshairPosition();
47
57
  };
48
- return a(() => e.on("crosshairMove", n)), l(() => e.off("crosshairMove", n)), o;
58
+ return u(() => e.on("crosshairMove", i)), a(() => e.off("crosshairMove", i)), n;
49
59
  }
50
60
  export {
51
- p as useAxisLayout,
52
- y as useCrosshairPosition,
53
- A as useLastYValue,
61
+ h as useAxisLayout,
62
+ c as useCrosshairPosition,
63
+ p as useLastYValue,
54
64
  C as usePreviousClose,
55
- x as useVisibleRange,
65
+ A as useVisibleRange,
56
66
  d as useYRange
57
67
  };
@@ -1,31 +1,63 @@
1
- class g {
2
- #t;
1
+ class c {
3
2
  #i;
4
- #r;
5
- #e;
6
- #g;
3
+ /** Y slots of the named scales, keyed by scale id. */
4
+ #s = /* @__PURE__ */ new Map();
5
+ #u;
6
+ #t;
7
+ #a;
8
+ #h;
9
+ #m;
7
10
  /** Per-frame `animating` snapshot — updated by `tick` so `get animating()`
8
11
  * is O(1). Spans both axes; lives at the engine root rather than in
9
12
  * XState/YState because it's a cross-axis flag. */
10
- #s = !1;
13
+ #n = !1;
11
14
  constructor(t) {
12
- this.#t = {
13
- transition: t.y.curve({ initial: t.initial.yRange }),
14
- settleMs: t.y.settleMs,
15
- stickyMs: t.y.stickyMs,
16
- stickyFloorMs: t.y.stickyFloorMs,
17
- gestureMs: t.y.gestureMs,
18
- toggleMs: t.y.toggleMs,
19
- toggleUntil: 0
20
- }, this.#i = {
15
+ this.#u = t.y, this.#i = this.#f({ initial: t.initial.yRange, primed: !0 }), this.#t = {
21
16
  transition: t.x.curve({ initial: t.initial.xRange }),
22
17
  settleMs: t.x.settleMs,
23
18
  gestureMs: t.x.gestureMs,
24
19
  lastTarget: null,
25
20
  gestureUntil: 0
26
- }, this.#r = t.computeXTarget, this.#e = t.computeYTarget, this.#g = t.onWake;
21
+ }, this.#a = t.computeXTarget, this.#h = t.computeYTarget, this.#m = t.onWake;
27
22
  }
28
23
  // --- Helpers -------------------------------------------------------------
24
+ #f(t) {
25
+ const s = this.#u;
26
+ return {
27
+ transition: s.curve({ initial: t.initial }),
28
+ settleMs: s.settleMs,
29
+ stickyMs: s.stickyMs,
30
+ stickyFloorMs: s.stickyFloorMs,
31
+ gestureMs: s.gestureMs,
32
+ toggleMs: s.toggleMs,
33
+ toggleUntil: 0,
34
+ primed: t.primed
35
+ };
36
+ }
37
+ /** Every Y slot with the target the chart computes for it against `xTarget`. */
38
+ #r(t) {
39
+ const s = [{ y: this.#i, target: this.#h({ xTarget: t }) }];
40
+ for (const [i, e] of this.#s)
41
+ s.push({ y: e, target: this.#h({ xTarget: t, scale: i }) });
42
+ return s;
43
+ }
44
+ /** Ease a Y slot to `target` — or snap, when it's the slot's first target. */
45
+ #g(t, s, i) {
46
+ if (!t.primed) {
47
+ this.#o(t, s, i.now);
48
+ return;
49
+ }
50
+ t.transition.retarget(s, i);
51
+ }
52
+ #o(t, s, i) {
53
+ t.transition.snap(s, { now: i }), t.primed = !0;
54
+ }
55
+ #M() {
56
+ if (this.#i.transition.animating) return !0;
57
+ for (const t of this.#s.values())
58
+ if (t.transition.animating) return !0;
59
+ return !1;
60
+ }
29
61
  /**
30
62
  * Retarget X and record `#x.lastTarget` — autoscroll consults that field for
31
63
  * the logical destination, not the in-flight visual.
@@ -34,15 +66,15 @@ class g {
34
66
  * (fast — responsive feel) while stream ticks pass `#x.settleMs` (the
35
67
  * cadence-tuned baseline).
36
68
  */
37
- #a(t, s, i) {
38
- this.#i.transition.retarget(t, { now: s, expandMs: i }), this.#i.lastTarget = { from: t.from, to: t.to };
69
+ #l(t, s, i) {
70
+ this.#t.transition.retarget(t, { now: s, expandMs: i }), this.#t.lastTarget = { from: t.from, to: t.to };
39
71
  }
40
- #o(t, s) {
41
- this.#i.transition.snap({ from: t.from, to: t.to }, { now: s }), this.#i.lastTarget = { from: t.from, to: t.to };
72
+ #c(t, s) {
73
+ this.#t.transition.snap({ from: t.from, to: t.to }, { now: s }), this.#t.lastTarget = { from: t.from, to: t.to };
42
74
  }
43
75
  /** Fire `onWake` once when an idle engine receives a new retarget. */
44
- #n(t) {
45
- t && this.#g?.();
76
+ #e(t) {
77
+ t && this.#m?.();
46
78
  }
47
79
  /**
48
80
  * Magnitude-scaled inward (sticky) settle time. The configured `stickyMs`
@@ -60,115 +92,142 @@ class g {
60
92
  * contracts. `stickyFloorMs === stickyMs` collapses this back to a fixed
61
93
  * duration.
62
94
  */
63
- #h(t, s) {
64
- const i = this.#t.stickyMs;
65
- if (i <= 0) return i;
66
- const n = Math.max(t.max - t.min, Number.EPSILON), e = Math.max(0, s.min - t.min), r = Math.max(0, t.max - s.max), a = Math.min(1, Math.max(e, r) / n), h = Math.min(this.#t.stickyFloorMs, i);
67
- return Math.max(h, i * a);
95
+ #p(t, s) {
96
+ const i = t.transition.current, e = t.stickyMs;
97
+ if (e <= 0) return e;
98
+ const n = Math.max(i.max - i.min, Number.EPSILON), r = Math.max(0, s.min - i.min), o = Math.max(0, i.max - s.max), a = Math.min(1, Math.max(r, o) / n), h = Math.min(t.stickyFloorMs, e);
99
+ return Math.max(h, e * a);
68
100
  }
69
101
  // --- Inputs --------------------------------------------------------------
70
102
  onPointAppended(t) {
71
103
  const s = t ?? performance.now();
72
- if (s < this.#i.gestureUntil) return;
73
- const i = this.#r(), n = i ?? this.#i.transition.target, e = this.#e({ xTarget: n });
74
- if (i === null && e === null) return;
75
- const r = !this.#s, a = s < this.#t.toggleUntil;
76
- i !== null && this.#a(i, s, this.#i.settleMs), e !== null && !a && this.#t.transition.retarget(e, {
77
- now: s,
78
- expandMs: this.#t.settleMs,
79
- contractMs: this.#h(this.#t.transition.current, e)
80
- }), this.#n(r);
104
+ if (s < this.#t.gestureUntil) return;
105
+ const i = this.#a(), e = i ?? this.#t.transition.target, n = this.#r(e), r = n.some((a) => a.target !== null);
106
+ if (i === null && !r) return;
107
+ const o = !this.#n;
108
+ i !== null && this.#l(i, s, this.#t.settleMs);
109
+ for (const { y: a, target: h } of n) {
110
+ const l = s < a.toggleUntil;
111
+ h === null || l || this.#g(a, h, {
112
+ now: s,
113
+ expandMs: a.settleMs,
114
+ contractMs: this.#p(a, h)
115
+ });
116
+ }
117
+ this.#e(o);
81
118
  }
82
119
  onSeriesVisibilityChanged(t) {
83
- const s = this.#e({ xTarget: this.#i.transition.target });
84
- if (s === null) return;
85
- const i = t ?? performance.now(), n = !this.#s;
86
- this.#t.toggleMs > 0 ? (this.#t.transition.snap(this.#t.transition.current, { now: i }), this.#t.transition.retarget(s, {
87
- now: i,
88
- expandMs: this.#t.toggleMs,
89
- contractMs: this.#t.toggleMs
90
- }), this.#t.toggleUntil = i + this.#t.toggleMs) : (this.#t.transition.snap(s, { now: i }), this.#t.toggleUntil = 0), this.#n(n);
120
+ const s = this.#r(this.#t.transition.target);
121
+ if (s.every((n) => n.target === null)) return;
122
+ const i = t ?? performance.now(), e = !this.#n;
123
+ for (const { y: n, target: r } of s)
124
+ r !== null && (n.toggleMs > 0 && n.primed ? (n.transition.snap(n.transition.current, { now: i }), n.transition.retarget(r, {
125
+ now: i,
126
+ expandMs: n.toggleMs,
127
+ contractMs: n.toggleMs
128
+ }), n.toggleUntil = i + n.toggleMs) : (this.#o(n, r, i), n.toggleUntil = 0));
129
+ this.#e(e);
91
130
  }
92
131
  onPanZoom(t, s) {
93
- const i = s ?? performance.now(), n = !this.#s;
94
- if (this.#a(t.xTarget, i, this.#i.gestureMs), this.#i.gestureUntil = i + 100, t.yAuto) {
95
- const e = this.#e({ xTarget: t.xTarget });
96
- e !== null && this.#t.transition.retarget(e, {
97
- now: i,
98
- expandMs: this.#t.gestureMs,
99
- contractMs: this.#t.gestureMs
100
- });
101
- }
102
- this.#n(n);
132
+ const i = s ?? performance.now(), e = !this.#n;
133
+ if (this.#l(t.xTarget, i, this.#t.gestureMs), this.#t.gestureUntil = i + 100, t.yAuto)
134
+ for (const { y: n, target: r } of this.#r(t.xTarget))
135
+ r !== null && this.#g(n, r, {
136
+ now: i,
137
+ expandMs: n.gestureMs,
138
+ contractMs: n.gestureMs
139
+ });
140
+ this.#e(e);
103
141
  }
104
142
  onAxisReconfig(t) {
105
- const s = this.#e({ xTarget: this.#i.transition.target });
106
- if (s === null) return;
107
- const i = t ?? performance.now(), n = !this.#s;
108
- this.#t.transition.snap(s, { now: i }), this.#n(n);
143
+ const s = this.#r(this.#t.transition.target);
144
+ if (s.every((n) => n.target === null)) return;
145
+ const i = t ?? performance.now(), e = !this.#n;
146
+ for (const { y: n, target: r } of s)
147
+ r !== null && this.#o(n, r, i);
148
+ this.#e(e);
109
149
  }
110
150
  onProgrammaticZoom(t, s) {
111
- this.#i.gestureUntil = 0;
112
- const i = this.#e({ xTarget: t.xTarget }), n = s ?? performance.now(), e = !this.#s;
113
- if (t.xEase === !0) {
114
- this.#a(t.xTarget, n, this.#i.gestureMs), i !== null && this.#t.transition.retarget(i, {
115
- now: n,
116
- expandMs: this.#t.settleMs,
117
- contractMs: this.#h(this.#t.transition.current, i)
118
- }), this.#n(e);
119
- return;
120
- }
121
- this.#o(t.xTarget, n), i !== null && this.#t.transition.retarget(i, {
122
- now: n,
123
- expandMs: this.#t.settleMs,
124
- contractMs: this.#h(this.#t.transition.current, i)
125
- }), this.#n(e);
151
+ this.#t.gestureUntil = 0;
152
+ const i = this.#r(t.xTarget), e = s ?? performance.now(), n = !this.#n;
153
+ t.xEase === !0 ? this.#l(t.xTarget, e, this.#t.gestureMs) : this.#c(t.xTarget, e);
154
+ for (const { y: r, target: o } of i)
155
+ o !== null && this.#g(r, o, {
156
+ now: e,
157
+ expandMs: r.settleMs,
158
+ contractMs: this.#p(r, o)
159
+ });
160
+ this.#e(n);
126
161
  }
127
162
  onDataReplaced(t) {
128
- const s = this.#r(), i = this.#e({ xTarget: s ?? this.#i.transition.target });
129
- if (s === null && i === null) return;
130
- const n = t ?? performance.now(), e = !this.#s;
131
- s !== null && this.#o(s, n), i !== null && this.#t.transition.snap(i, { now: n }), this.#n(e);
163
+ const s = this.#a(), i = this.#r(s ?? this.#t.transition.target), e = i.some((o) => o.target !== null);
164
+ if (s === null && !e) return;
165
+ const n = t ?? performance.now(), r = !this.#n;
166
+ s !== null && this.#c(s, n);
167
+ for (const { y: o, target: a } of i)
168
+ a !== null && this.#o(o, a, n);
169
+ this.#e(r);
132
170
  }
133
171
  snap(t, s) {
134
- this.#i.gestureUntil = 0;
135
- const i = s ?? performance.now(), n = !this.#s;
136
- t.x !== void 0 && this.#o(t.x, i), t.y !== void 0 && this.#t.transition.snap(t.y, { now: i }), this.#n(n);
172
+ this.#t.gestureUntil = 0;
173
+ const i = s ?? performance.now(), e = !this.#n;
174
+ t.x !== void 0 && this.#c(t.x, i), t.y !== void 0 && this.#o(this.#i, t.y, i);
175
+ for (const [n, r] of Object.entries(t.scales ?? {})) {
176
+ const o = this.#s.get(n);
177
+ o !== void 0 && this.#o(o, r, i);
178
+ }
179
+ this.#e(e);
180
+ }
181
+ /**
182
+ * Keep one Y slot per named scale: add slots for new ids (empty until their
183
+ * first target, which snaps) and drop slots for ids no longer listed.
184
+ */
185
+ setYScales(t) {
186
+ for (const s of this.#s.keys())
187
+ t.includes(s) || this.#s.delete(s);
188
+ for (const s of t)
189
+ this.#s.has(s) || this.#s.set(s, this.#f({ initial: { min: 0, max: 0 }, primed: !1 }));
137
190
  }
138
191
  // --- Outputs -------------------------------------------------------------
139
192
  tick(t) {
140
- this.#i.transition.tick(t), this.#t.transition.tick(t);
141
- const s = this.#i.transition.animating || this.#t.transition.animating;
142
- return this.#s = s, {
143
- xRange: this.#i.transition.current,
144
- yRange: this.#t.transition.current,
193
+ this.#t.transition.tick(t), this.#i.transition.tick(t);
194
+ for (const i of this.#s.values())
195
+ i.transition.tick(t);
196
+ const s = this.#t.transition.animating || this.#M();
197
+ return this.#n = s, {
198
+ xRange: this.#t.transition.current,
199
+ yRange: this.#i.transition.current,
145
200
  animating: s
146
201
  };
147
202
  }
148
203
  getAnimationState() {
149
204
  return {
150
- xRange: this.#i.transition.current,
151
- yRange: this.#t.transition.current,
152
- animating: this.#i.transition.animating || this.#t.transition.animating
205
+ xRange: this.#t.transition.current,
206
+ yRange: this.#i.transition.current,
207
+ animating: this.animating
153
208
  };
154
209
  }
210
+ /** Current (eased) Y of a named scale, `null` for an unknown id. */
211
+ getScaleYRange(t) {
212
+ return this.#s.get(t)?.transition.current ?? null;
213
+ }
155
214
  getTarget() {
156
- return { x: this.#i.transition.target, y: this.#t.transition.target };
215
+ return { x: this.#t.transition.target, y: this.#i.transition.target };
157
216
  }
158
217
  get animating() {
159
- return this.#i.transition.animating || this.#t.transition.animating;
218
+ return this.#t.transition.animating || this.#M();
160
219
  }
161
220
  get lastXTarget() {
162
- return this.#i.lastTarget;
221
+ return this.#t.lastTarget;
163
222
  }
164
223
  setXSettleMs(t) {
165
- this.#i.settleMs = t;
224
+ this.#t.settleMs = t;
166
225
  }
167
226
  }
168
- function l(o) {
169
- return new g(o);
227
+ function u(g) {
228
+ return new c(g);
170
229
  }
171
230
  export {
172
- g as ViewportEngine,
173
- l as createViewportEngine
231
+ c as ViewportEngine,
232
+ u as createViewportEngine
174
233
  };
@@ -1,72 +1,77 @@
1
- import { resolveAxisTextColor as I, resolveAxisFontSize as C } from "../theme/resolve.js";
2
- import { clamp as P } from "../utils/math.js";
3
- const V = 0.01;
4
- function E(T) {
5
- const { chart: e, container: w, axis: a } = T, r = /* @__PURE__ */ new Map();
6
- let p = null, m = null;
7
- const x = a === "x" ? e.timeScale.tickTracker : e.yScale.tickTracker;
8
- function A() {
9
- return a === "x" ? e.timeScale.niceTickValues(e.getDataInterval()) : { ticks: e.yScale.niceTickValues(), tickInterval: 0 };
1
+ import { resolveAxisTextColor as X, resolveAxisFontSize as w } from "../theme/resolve.js";
2
+ import { clamp as z } from "../utils/math.js";
3
+ const E = 0.01;
4
+ function D(A) {
5
+ const { chart: n, container: F, axis: a, scale: x } = A, s = /* @__PURE__ */ new Map();
6
+ let g = null, h = null;
7
+ function c() {
8
+ return n.getYScale(x);
9
+ }
10
+ function m() {
11
+ return n.getYScaleColumn(x)?.position ?? n.yAxisPosition;
12
+ }
13
+ function Y() {
14
+ return a === "x" ? n.timeScale.niceTickValues(n.getDataInterval()) : { ticks: c().niceTickValues(), tickInterval: 0 };
10
15
  }
11
16
  function S(t, o) {
12
- return a === "x" ? e.timeScale.formatX(t, o) : e.yScale.formatY(t);
17
+ return a === "x" ? n.timeScale.formatX(t, o) : c().formatY(t);
13
18
  }
14
19
  function $(t, o) {
15
20
  if (a === "x") {
16
- t.style.left = `${e.timeScale.timeToSnappedX(o)}px`;
21
+ t.style.left = `${n.timeScale.timeToSnappedX(o)}px`, n.timeScale.getType() === "category" && (t.style.maxWidth = `${n.timeScale.barWidthMedia(1)}px`);
17
22
  return;
18
23
  }
19
- t.style.top = `${e.yScale.valueToSnappedY(o)}px`;
20
- }
21
- function h(t, o) {
22
- t.style.color = I(o, a), t.style.fontSize = `${C(o, a)}px`, t.style.fontFamily = o.typography.fontFamily;
24
+ t.style.top = `${c().valueToSnappedY(o)}px`;
23
25
  }
24
26
  function v(t, o) {
25
- const i = o === "left" ? "left" : "right", n = o === "left" ? "right" : "left";
26
- t.style[i] = "8px", t.style[n] = "";
27
+ t.style.color = X(o, a), t.style.fontSize = `${w(o, a)}px`, t.style.fontFamily = o.typography.fontFamily;
27
28
  }
28
- function F(t, o) {
29
- const i = e.headerHeight;
30
- if (a !== "y" || i <= 0 || e.yAxisPosition !== "left") return 1;
31
- const n = C(o, a), y = e.yScale.valueToSnappedY(t) - n / 2;
32
- return P((y - i + n) / n, 0, 1);
29
+ function d(t, o) {
30
+ const i = o === "left" ? "left" : "right", e = o === "left" ? "right" : "left";
31
+ t.style[i] = "8px", t.style[e] = "";
33
32
  }
34
- function Y(t, o, i) {
35
- const n = document.createElement("span");
36
- return n.textContent = S(t, o), n.style.position = "absolute", n.style.userSelect = "none", h(n, i), n.style.willChange = "opacity", a === "x" ? (n.style.transform = "translateX(-50%)", n.style.whiteSpace = "nowrap") : (v(n, e.yAxisPosition), n.style.transform = "translateY(-50%)", n.style.fontVariantNumeric = "tabular-nums"), w.appendChild(n), n;
33
+ function b(t, o) {
34
+ const i = n.headerHeight;
35
+ if (a !== "y" || i <= 0 || m() !== "left") return 1;
36
+ const e = w(o, a), p = c().valueToSnappedY(t) - e / 2;
37
+ return z((p - i + e) / e, 0, 1);
37
38
  }
38
- function c() {
39
- const t = e.getTheme(), o = t !== p;
40
- p = t;
41
- const i = e.yAxisPosition, n = a === "y" && i !== m;
42
- m = i;
43
- const { ticks: y, tickInterval: g } = A();
44
- x.setCurrentTicks(y);
45
- const { entries: b } = x.snapshot(), k = /* @__PURE__ */ new Set();
46
- for (const { value: s, opacity: u } of b) {
47
- if (u <= V) continue;
48
- k.add(s);
49
- let l = r.get(s);
50
- if (l === void 0)
51
- l = Y(s, g, t), r.set(s, l);
39
+ function I(t, o, i) {
40
+ const e = document.createElement("span");
41
+ return e.textContent = S(t, o), e.style.position = "absolute", e.style.userSelect = "none", v(e, i), e.style.willChange = "opacity", a === "x" ? (e.style.transform = "translateX(-50%)", e.style.whiteSpace = "nowrap", n.timeScale.getType() === "category" && (e.style.overflow = "hidden", e.style.textOverflow = "ellipsis")) : (d(e, m()), e.style.transform = "translateY(-50%)", e.style.fontVariantNumeric = "tabular-nums"), F.appendChild(e), e;
42
+ }
43
+ function f() {
44
+ const t = n.getTheme(), o = t !== g;
45
+ g = t;
46
+ const i = m(), e = a === "y" && i !== h;
47
+ h = i;
48
+ const p = a === "x" ? n.timeScale.tickTracker : c().tickTracker, { ticks: V, tickInterval: k } = Y();
49
+ p.setCurrentTicks(V);
50
+ const { entries: W } = p.snapshot(), C = /* @__PURE__ */ new Set();
51
+ for (const { value: l, opacity: y } of W) {
52
+ if (y <= E) continue;
53
+ C.add(l);
54
+ let r = s.get(l);
55
+ if (r === void 0)
56
+ r = I(l, k, t), s.set(l, r);
52
57
  else {
53
- const d = S(s, g);
54
- l.textContent !== d && (l.textContent = d), o && h(l, t), n && v(l, i);
58
+ const T = S(l, k);
59
+ r.textContent !== T && (r.textContent = T), o && v(r, t), e && d(r, i);
55
60
  }
56
- $(l, s), l.style.opacity = String(u * F(s, t));
61
+ $(r, l), r.style.opacity = String(y * b(l, t));
57
62
  }
58
- for (const [s, u] of r)
59
- k.has(s) || (u.remove(), r.delete(s));
63
+ for (const [l, y] of s)
64
+ C.has(l) || (y.remove(), s.delete(l));
60
65
  }
61
- function f() {
62
- e.getAnimationState().animating || c();
66
+ function u() {
67
+ n.getAnimationState().animating || f();
63
68
  }
64
- return c(), e.on("tickFrame", c), e.on("viewportChange", f), e.on("overlayChange", f), () => {
65
- e.off("tickFrame", c), e.off("viewportChange", f), e.off("overlayChange", f);
66
- for (const t of r.values()) t.remove();
67
- r.clear();
69
+ return f(), n.on("tickFrame", f), n.on("viewportChange", u), n.on("overlayChange", u), () => {
70
+ n.off("tickFrame", f), n.off("viewportChange", u), n.off("overlayChange", u);
71
+ for (const t of s.values()) t.remove();
72
+ s.clear();
68
73
  };
69
74
  }
70
75
  export {
71
- E as mountAxisLabels
76
+ D as mountAxisLabels
72
77
  };
@@ -1,4 +1,4 @@
1
- function o(a) {
1
+ function c(a) {
2
2
  if (!(a.stacking !== "percent" || a.isPlottable(0)))
3
3
  throw new Error(
4
4
  `[wick-charts] Series '${a.seriesId}' uses stacking: 'percent', which this Y scale can't show — a 0–100% axis starts at 0, and the scale has no position for 0. Use a linear axis, or stacking: 'normal' / 'off'.`
@@ -6,11 +6,11 @@ function o(a) {
6
6
  }
7
7
  function i(a) {
8
8
  if (process.env.NODE_ENV === "production") return;
9
- const { y: n, isPlottable: t } = a;
9
+ const { y: n, isPlottable: o, path: t = "axis.y" } = a;
10
10
  for (const e of ["min", "max"]) {
11
11
  const s = n?.[e];
12
- typeof s != "number" || t(s) || console.warn(
13
- `[wick-charts] axis.y.${e} is ${s}, which the Y scale can't place — falling back to 'auto'. Use a bound inside the scale's domain.`
12
+ typeof s != "number" || o(s) || console.warn(
13
+ `[wick-charts] ${t}.${e} is ${s}, which the Y scale can't place — falling back to 'auto'. Use a bound inside the scale's domain.`
14
14
  );
15
15
  }
16
16
  }
@@ -19,8 +19,26 @@ function r(a) {
19
19
  `[wick-charts] Series '${a.seriesId}' has values in view the Y scale can't place (e.g. ${a.value}; a log axis has no position for values ≤ 0). They are skipped — gaps in a line, no bar or candle. Filter or offset the data, or use a linear axis.`
20
20
  );
21
21
  }
22
+ function l(a) {
23
+ process.env.NODE_ENV !== "production" && console.warn(
24
+ `[wick-charts] Series '${a.seriesId}' uses scale '${a.scaleId}', which \`scales\` doesn't define — it maps through the default Y scale.`
25
+ );
26
+ }
27
+ function h(a) {
28
+ process.env.NODE_ENV !== "production" && console.warn(
29
+ `[wick-charts] Scale '${a.scaleId}' asks for the ${a.side} axis column, which another Y axis already holds — it renders as an overlay scale with no column. One axis column fits on each side.`
30
+ );
31
+ }
32
+ function u(a) {
33
+ process.env.NODE_ENV !== "production" && console.warn(
34
+ `[wick-charts] Series '${a.seriesId}' uses stacking: 'percent' on a Y scale that can't place 0 — a 0–100% axis starts at 0. Put it on a linear scale, or use stacking: 'normal' / 'off'.`
35
+ );
36
+ }
22
37
  export {
23
- o as assertStackingFitsScale,
38
+ c as assertStackingFitsScale,
39
+ h as warnScaleSideTaken,
40
+ u as warnStackingOffScale,
41
+ l as warnUnknownScale,
24
42
  i as warnUnplottableBounds,
25
43
  r as warnUnplottableValues
26
44
  };
@@ -0,0 +1,37 @@
1
+ function a(e) {
2
+ const { seriesType: s, axisType: t, supported: i } = e;
3
+ if (i.includes(t)) return;
4
+ const n = i.map((r) => `'${r}'`).join(", ");
5
+ throw new Error(
6
+ `[wick-charts] A '${s}' series can't plot on a '${t}' X axis — it supports ${n}. Set axis.x.type to a supported type, or declare \`xTypes\` on a custom series definition.`
7
+ );
8
+ }
9
+ function o(e) {
10
+ if (process.env.NODE_ENV === "production") return;
11
+ const s = e.axisType === "category" ? "a string `x` (the category name)" : "a number `x`";
12
+ console.warn(
13
+ `[wick-charts] Series '${e.seriesId}' has a point with x = ${String(e.x)}, which doesn't fit the '${e.axisType}' X axis — it needs ${s}. Such points are skipped.`
14
+ );
15
+ }
16
+ function c(e) {
17
+ process.env.NODE_ENV !== "production" && console.warn(
18
+ `[wick-charts] Series '${e.seriesId}' mixes \`x\` and \`time\` keys. On a numeric or category X axis key every point by \`x\`.`
19
+ );
20
+ }
21
+ function p(e) {
22
+ process.env.NODE_ENV !== "production" && console.warn(
23
+ `[wick-charts] ${e.feature} works on a time X axis only — it is disabled on this '${e.axisType}' axis.`
24
+ );
25
+ }
26
+ function x(e) {
27
+ process.env.NODE_ENV !== "production" && console.warn(
28
+ `[wick-charts] axis.x.type changed from '${e.from}' to '${e.to}' after the chart was created — the change is ignored. Remount the chart (e.g. a React \`key\`) to switch the X axis type.`
29
+ );
30
+ }
31
+ export {
32
+ a as assertSeriesFitsXAxis,
33
+ p as warnTimeOnlyFeature,
34
+ o as warnXMisfit,
35
+ c as warnXTimeMixed,
36
+ x as warnXTypeChange
37
+ };