@wick-charts/vue 0.8.0 → 0.8.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.
Files changed (48) hide show
  1. package/README.md +2 -0
  2. package/dist/BandSeries.vue.js +43 -32
  3. package/dist/BarSeries.vue.js +44 -33
  4. package/dist/CandlestickSeries.vue.js +24 -23
  5. package/dist/ChartContainer.vue.js +1 -1
  6. package/dist/HeatmapSeries.vue.js +21 -20
  7. package/dist/LineSeries.vue.js +43 -32
  8. package/dist/PieSeries.vue.js +25 -24
  9. package/dist/composables.js +63 -36
  10. package/dist/core/dist/axis/dom-labels.js +64 -53
  11. package/dist/core/dist/chart/badge-animator.js +38 -28
  12. package/dist/core/dist/chart/options.js +1 -1
  13. package/dist/core/dist/chart/y-target.js +38 -32
  14. package/dist/core/dist/chart.js +852 -709
  15. package/dist/core/dist/data/decimation.js +52 -51
  16. package/dist/core/dist/data/store.js +38 -20
  17. package/dist/core/dist/data/sync.js +97 -59
  18. package/dist/core/dist/navigator/controller.js +11 -11
  19. package/dist/core/dist/perf/perf-hud.js +3 -3
  20. package/dist/core/dist/scales/tick-tracker.js +2 -1
  21. package/dist/core/dist/scales/time-ticks.js +99 -0
  22. package/dist/core/dist/scales/x-scale.js +33 -27
  23. package/dist/core/dist/series/band.js +83 -83
  24. package/dist/core/dist/series/bar.js +240 -211
  25. package/dist/core/dist/series/base-multi-layer.js +288 -240
  26. package/dist/core/dist/series/candlestick.js +168 -168
  27. package/dist/core/dist/series/line.js +545 -455
  28. package/dist/core/dist/snapshots.js +109 -86
  29. package/dist/core/dist/utils/point.js +4 -0
  30. package/dist/core/dist/utils/time.js +42 -26
  31. package/dist/index.d.ts +67 -28
  32. package/dist/ui/InfoBar.vue.js +69 -69
  33. package/dist/ui/NumberFlow.vue.js +36 -27
  34. package/dist/ui/Tooltip.vue.js +128 -131
  35. package/dist/ui/YLabel.vue.js +47 -47
  36. package/package.json +2 -2
  37. package/src/BandSeries.vue +20 -5
  38. package/src/BarSeries.vue +20 -5
  39. package/src/CandlestickSeries.vue +5 -4
  40. package/src/ChartContainer.vue +15 -9
  41. package/src/HeatmapSeries.vue +5 -4
  42. package/src/LineSeries.vue +20 -5
  43. package/src/PieSeries.vue +6 -5
  44. package/src/composables.ts +64 -1
  45. package/src/ui/InfoBar.vue +11 -3
  46. package/src/ui/NumberFlow.vue +17 -3
  47. package/src/ui/Tooltip.vue +23 -12
  48. package/src/ui/YLabel.vue +28 -27
@@ -1,165 +1,162 @@
1
- import { defineComponent as X, computed as h, ref as z, onMounted as Y, onUnmounted as Z, useSlots as $, watchEffect as K, openBlock as i, createElementBlock as n, Fragment as f, unref as d, normalizeStyle as m, createElementVNode as s, createTextVNode as R, toDisplayString as c, createCommentVNode as w, renderList as H, renderSlot as U } from "vue";
2
- import { buildHoverSnapshots as j, formatHeaderX as q } from "../core/dist/snapshots.js";
3
- import { resolveCandlestickBodyColor as G } from "../core/dist/theme/resolve.js";
4
- import { computeTooltipPosition as I } from "../core/dist/tooltip-position.js";
5
- import { formatCompact as J, formatPriceAdaptive as Q } from "../core/dist/utils/format.js";
6
- import { formatDate as ee } from "../core/dist/utils/time.js";
7
- import { useCrosshairPosition as te } from "../composables.js";
8
- import { useChartInstance as oe } from "../context.js";
9
- const ae = {
1
+ import { defineComponent as Y, computed as c, ref as z, onMounted as $, onUnmounted as K, useSlots as U, watchEffect as j, openBlock as r, createElementBlock as s, Fragment as x, unref as f, normalizeStyle as v, createElementVNode as u, toDisplayString as h, renderList as I, createCommentVNode as F, renderSlot as q } from "vue";
2
+ import { buildHoverSnapshots as G, formatTooltipHeader as J, formatRowValue as Q } from "../core/dist/snapshots.js";
3
+ import { resolveCandlestickBodyColor as Z } from "../core/dist/theme/resolve.js";
4
+ import { computeTooltipPosition as L } from "../core/dist/tooltip-position.js";
5
+ import { formatCompact as ee, formatPriceAdaptive as te } from "../core/dist/utils/format.js";
6
+ import { useCrosshairPosition as oe } from "../composables.js";
7
+ import { useChartInstance as ae } from "../context.js";
8
+ const le = {
10
9
  key: 0,
11
10
  style: { display: "grid", gridTemplateColumns: "auto 1fr", gap: "4px 12px" }
12
- }, le = { style: { opacity: 0.5 } }, ie = {
11
+ }, ie = { style: { opacity: 0.5 } }, ne = {
13
12
  key: 1,
14
13
  style: { display: "flex", alignItems: "center", gap: "8px", padding: "2px 0" }
15
- }, ne = { style: {
14
+ }, re = { style: {
16
15
  opacity: 0.6,
17
16
  flex: "1",
18
17
  minWidth: 0,
19
18
  overflow: "hidden",
20
19
  textOverflow: "ellipsis",
21
20
  whiteSpace: "nowrap"
22
- } }, re = {
21
+ } }, se = {
23
22
  key: 2,
24
23
  style: { display: "flex", alignItems: "center", gap: "8px", padding: "2px 0" }
25
- }, se = { style: { opacity: 0.6, flex: "1" } }, ue = ["data-measured"], ye = /* @__PURE__ */ X({
24
+ }, ue = { style: { opacity: 0.6, flex: "1" } }, pe = ["data-measured"], ge = /* @__PURE__ */ Y({
26
25
  __name: "Tooltip",
27
26
  props: {
28
27
  sort: {},
29
28
  format: { type: Function }
30
29
  },
31
- setup(T) {
32
- const F = T, O = h(() => F.sort ?? "none"), x = h(
33
- () => F.format ?? ((a, r) => r === "volume" ? J(a) : Q(a))
34
- ), t = oe(), u = te(t), C = z(0), W = () => {
35
- C.value++;
30
+ setup(V) {
31
+ const W = V, O = c(() => W.sort ?? "none"), g = c(
32
+ () => W.format ?? ((l, n) => n === "volume" ? ee(l) : te(l))
33
+ ), o = ae(), p = oe(o), y = z(0), w = () => {
34
+ y.value++;
36
35
  };
37
- Y(() => {
38
- t.on("overlayChange", W), t.getSeriesIds().length > 0 && C.value++;
39
- }), Z(() => {
40
- t.off("overlayChange", W);
36
+ $(() => {
37
+ o.on("overlayChange", w), o.on("seriesFrame", w), o.getSeriesIds().length > 0 && y.value++;
38
+ }), K(() => {
39
+ o.off("overlayChange", w), o.off("seriesFrame", w);
41
40
  });
42
- const o = h(() => t.getTheme()), V = h(() => t.getDataInterval()), v = h(() => (C.value, u.value ? j(t, {
43
- time: u.value.time,
41
+ const t = c(() => (y.value, o.getTheme())), T = c(() => (y.value, o.getDataInterval())), d = c(() => (y.value, p.value ? G(o, {
42
+ time: p.value.time,
44
43
  sort: O.value,
45
44
  cacheKey: "tooltip"
46
- }) : [])), _ = h(() => u.value?.time ?? 0), A = $(), y = h(() => typeof A.default == "function"), B = z(null), b = z(null);
47
- let S = null;
48
- K((a) => {
49
- if (!y.value) return;
50
- const r = B.value;
51
- !r || typeof ResizeObserver > "u" || (S = new ResizeObserver((e) => {
52
- const l = e[0]?.contentRect;
53
- if (!l) return;
54
- const k = b.value;
55
- (!k || k.width !== l.width || k.height !== l.height) && (b.value = { width: l.width, height: l.height });
56
- }), S.observe(r), a(() => {
57
- S?.disconnect(), S = null;
45
+ }) : [])), R = c(() => p.value?.time ?? 0), A = U(), b = c(() => typeof A.default == "function"), B = z(null), k = z(null);
46
+ let C = null;
47
+ j((l) => {
48
+ if (!b.value) return;
49
+ const n = B.value;
50
+ !n || typeof ResizeObserver > "u" || (C = new ResizeObserver((e) => {
51
+ const a = e[0]?.contentRect;
52
+ if (!a) return;
53
+ const S = k.value;
54
+ (!S || S.width !== a.width || S.height !== a.height) && (k.value = { width: a.width, height: a.height });
55
+ }), C.observe(n), l(() => {
56
+ C?.disconnect(), C = null;
58
57
  }));
59
58
  });
60
- const g = h(() => {
61
- if (!u.value || v.value.length === 0) return null;
62
- const a = t.getMediaSize(), r = t.plotLeft, e = t.getLayout().chartArea.width, l = a.height - t.xAxisHeight;
63
- if (y.value) {
64
- const p = b.value;
65
- return p ? I({
66
- x: u.value.mediaX,
67
- y: u.value.mediaY,
68
- chartLeft: r,
59
+ const m = c(() => {
60
+ if (!p.value || d.value.length === 0) return null;
61
+ const l = o.getMediaSize(), n = o.plotLeft, e = o.getLayout().chartArea.width, a = l.height - o.xAxisHeight;
62
+ if (b.value) {
63
+ const i = k.value;
64
+ return i ? L({
65
+ x: p.value.mediaX,
66
+ y: p.value.mediaY,
67
+ chartLeft: n,
69
68
  chartWidth: e,
70
- chartHeight: l,
71
- tooltipWidth: p.width,
72
- tooltipHeight: p.height
73
- }) : { left: r, top: 0 };
69
+ chartHeight: a,
70
+ tooltipWidth: i.width,
71
+ tooltipHeight: i.height
72
+ }) : { left: n, top: 0 };
74
73
  }
75
- const k = v.value.some((p) => "open" in p.data), P = v.value.filter((p) => !("open" in p.data)).length, D = v.value.some((p) => "high" in p.data && !("open" in p.data)) ? 220 : 160, M = k ? 140 : 40 + P * 22;
76
- return I({
77
- x: u.value.mediaX,
78
- y: u.value.mediaY,
79
- chartLeft: r,
74
+ const S = d.value.some((i) => "open" in i.data), P = d.value.filter((i) => !("open" in i.data)).length, M = d.value.some((i) => "high" in i.data && !("open" in i.data)), D = d.value.some((i) => i.share !== void 0);
75
+ let _ = 160;
76
+ M && (_ = 220), D && (_ = 240);
77
+ const X = S ? 140 : 40 + P * 22;
78
+ return L({
79
+ x: p.value.mediaX,
80
+ y: p.value.mediaY,
81
+ chartLeft: n,
80
82
  chartWidth: e,
81
- chartHeight: l,
82
- tooltipWidth: D,
83
- tooltipHeight: M
83
+ chartHeight: a,
84
+ tooltipWidth: _,
85
+ tooltipHeight: X
84
86
  });
85
- }), E = h(() => !y.value || b.value !== null);
86
- function L(a) {
87
- return "open" in a;
87
+ }), E = c(() => !b.value || k.value !== null);
88
+ function H(l) {
89
+ return "open" in l;
88
90
  }
89
- function N(a) {
90
- return "high" in a && !L(a);
91
+ function N(l) {
92
+ return "high" in l && !H(l);
91
93
  }
92
- return (a, r) => (i(), n(f, null, [
93
- d(u) && v.value.length > 0 && g.value && !y.value ? (i(), n("div", {
94
+ return (l, n) => (r(), s(x, null, [
95
+ f(p) && d.value.length > 0 && m.value && !b.value ? (r(), s("div", {
94
96
  key: 0,
95
- style: m({
97
+ style: v({
96
98
  position: "absolute",
97
- left: g.value.left + "px",
98
- top: g.value.top + "px",
99
+ left: m.value.left + "px",
100
+ top: m.value.top + "px",
99
101
  pointerEvents: "none",
100
- background: o.value.tooltip.background,
102
+ background: t.value.tooltip.background,
101
103
  backdropFilter: "blur(12px)",
102
104
  WebkitBackdropFilter: "blur(12px)",
103
- border: "1px solid " + o.value.tooltip.borderColor,
105
+ border: "1px solid " + t.value.tooltip.borderColor,
104
106
  borderRadius: "8px",
105
107
  padding: "10px 14px",
106
108
  boxShadow: "0 4px 16px rgba(0,0,0,0.1), 0 1px 4px rgba(0,0,0,0.06)",
107
- fontSize: o.value.tooltip.fontSize + "px",
108
- fontFamily: o.value.typography.fontFamily,
109
+ fontSize: t.value.tooltip.fontSize + "px",
110
+ fontFamily: t.value.typography.fontFamily,
109
111
  fontVariantNumeric: "tabular-nums",
110
- color: o.value.tooltip.textColor,
112
+ color: t.value.tooltip.textColor,
111
113
  minWidth: "140px",
112
114
  zIndex: 10,
113
115
  transition: "opacity 0.15s ease"
114
116
  })
115
117
  }, [
116
- s("div", {
117
- style: m({
118
- fontSize: o.value.axis.fontSize + "px",
119
- color: o.value.axis.textColor,
118
+ u("div", {
119
+ style: v({
120
+ fontSize: t.value.axis.fontSize + "px",
121
+ color: t.value.axis.textColor,
120
122
  marginBottom: "8px",
121
123
  paddingBottom: "6px",
122
- borderBottom: "1px solid " + o.value.tooltip.borderColor,
124
+ borderBottom: "1px solid " + t.value.tooltip.borderColor,
123
125
  letterSpacing: "0.02em"
124
126
  })
125
- }, [
126
- d(t).timeScale.getType() === "time" ? (i(), n(f, { key: 0 }, [
127
- R(c(d(ee)(_.value, { locale: d(t).timeScale.getLocale(), timeZone: d(t).timeScale.getTimeZone() })), 1)
128
- ], 64)) : w("", !0),
129
- R(" " + c(d(q)(d(t), { time: _.value, snapshots: v.value, interval: V.value })), 1)
130
- ], 4),
131
- (i(!0), n(f, null, H(v.value, (e) => (i(), n(f, {
127
+ }, h(f(J)(f(o), { time: R.value, snapshots: d.value, interval: T.value })), 5),
128
+ (r(!0), s(x, null, I(d.value, (e) => (r(), s(x, {
132
129
  key: e.id
133
130
  }, [
134
- L(e.data) ? (i(), n("div", ae, [
135
- (i(!0), n(f, null, H([
131
+ H(e.data) ? (r(), s("div", le, [
132
+ (r(!0), s(x, null, I([
136
133
  { label: "Open", val: e.data.open, field: "open" },
137
134
  { label: "High", val: e.data.high, field: "high" },
138
135
  { label: "Low", val: e.data.low, field: "low" },
139
136
  { label: "Close", val: e.data.close, field: "close" }
140
- ], (l) => (i(), n(f, {
141
- key: l.label
137
+ ], (a) => (r(), s(x, {
138
+ key: a.label
142
139
  }, [
143
- s("span", le, c(l.label), 1),
144
- s("span", {
145
- style: m({
140
+ u("span", ie, h(a.label), 1),
141
+ u("span", {
142
+ style: v({
146
143
  fontWeight: 600,
147
- color: d(G)(
148
- e.data.close >= e.data.open ? o.value.candlestick.up.body : o.value.candlestick.down.body
144
+ color: f(Z)(
145
+ e.data.close >= e.data.open ? t.value.candlestick.up.body : t.value.candlestick.down.body
149
146
  ),
150
147
  textAlign: "right"
151
148
  })
152
- }, c(x.value(l.val, l.field)), 5)
149
+ }, h(g.value(a.val, a.field)), 5)
153
150
  ], 64))), 128)),
154
- e.data.volume != null ? (i(), n(f, { key: 0 }, [
155
- r[0] || (r[0] = s("span", { style: { opacity: 0.5 } }, "Volume", -1)),
156
- s("span", {
157
- style: m({ fontWeight: 600, color: o.value.tooltip.textColor, textAlign: "right" })
158
- }, c(x.value(e.data.volume, "volume")), 5)
159
- ], 64)) : w("", !0)
160
- ])) : N(e.data) ? (i(), n("div", ie, [
161
- s("span", {
162
- style: m({
151
+ e.data.volume != null ? (r(), s(x, { key: 0 }, [
152
+ n[0] || (n[0] = u("span", { style: { opacity: 0.5 } }, "Volume", -1)),
153
+ u("span", {
154
+ style: v({ fontWeight: 600, color: t.value.tooltip.textColor, textAlign: "right" })
155
+ }, h(g.value(e.data.volume, "volume")), 5)
156
+ ], 64)) : F("", !0)
157
+ ])) : N(e.data) ? (r(), s("div", ne, [
158
+ u("span", {
159
+ style: v({
163
160
  width: "8px",
164
161
  height: "8px",
165
162
  borderRadius: "2px",
@@ -167,13 +164,13 @@ const ae = {
167
164
  flexShrink: 0
168
165
  })
169
166
  }, null, 4),
170
- s("span", ne, c(e.label ?? "Range"), 1),
171
- s("span", {
172
- style: m({ fontWeight: 600, color: e.color, whiteSpace: "nowrap" })
173
- }, c(x.value(e.data.low, "low")) + " – " + c(x.value(e.data.high, "high")), 5)
174
- ])) : (i(), n("div", re, [
175
- s("span", {
176
- style: m({
167
+ u("span", re, h(e.label ?? "Range"), 1),
168
+ u("span", {
169
+ style: v({ fontWeight: 600, color: e.color, whiteSpace: "nowrap" })
170
+ }, h(g.value(e.data.low, "low")) + " – " + h(g.value(e.data.high, "high")), 5)
171
+ ])) : (r(), s("div", se, [
172
+ u("span", {
173
+ style: v({
177
174
  width: "8px",
178
175
  height: "8px",
179
176
  borderRadius: "50%",
@@ -181,49 +178,49 @@ const ae = {
181
178
  flexShrink: 0
182
179
  })
183
180
  }, null, 4),
184
- s("span", se, c(e.label ?? "Value"), 1),
185
- s("span", {
186
- style: m({ fontWeight: 600, color: e.color })
187
- }, c(x.value(e.data.value, "value")), 5)
181
+ u("span", ue, h(e.label ?? "Value"), 1),
182
+ u("span", {
183
+ style: v({ fontWeight: 600, color: e.color })
184
+ }, h(f(Q)(e, (a) => g.value(a, "value"))), 5)
188
185
  ]))
189
186
  ], 64))), 128))
190
- ], 4)) : w("", !0),
191
- d(u) && v.value.length > 0 && g.value && y.value ? (i(), n("div", {
187
+ ], 4)) : F("", !0),
188
+ f(p) && d.value.length > 0 && m.value && b.value ? (r(), s("div", {
192
189
  key: 1,
193
190
  ref_key: "containerRef",
194
191
  ref: B,
195
192
  "data-measured": E.value ? "true" : "false",
196
- style: m({
193
+ style: v({
197
194
  position: "absolute",
198
- left: g.value.left + "px",
199
- top: g.value.top + "px",
195
+ left: m.value.left + "px",
196
+ top: m.value.top + "px",
200
197
  pointerEvents: "none",
201
- background: o.value.tooltip.background,
198
+ background: t.value.tooltip.background,
202
199
  backdropFilter: "blur(12px)",
203
200
  WebkitBackdropFilter: "blur(12px)",
204
- border: "1px solid " + o.value.tooltip.borderColor,
201
+ border: "1px solid " + t.value.tooltip.borderColor,
205
202
  borderRadius: "8px",
206
203
  padding: "10px 14px",
207
204
  boxShadow: "0 4px 16px rgba(0,0,0,0.1), 0 1px 4px rgba(0,0,0,0.06)",
208
- fontFamily: o.value.typography.fontFamily,
209
- fontSize: o.value.tooltip.fontSize + "px",
205
+ fontFamily: t.value.typography.fontFamily,
206
+ fontSize: t.value.tooltip.fontSize + "px",
210
207
  fontVariantNumeric: "tabular-nums",
211
- color: o.value.tooltip.textColor,
208
+ color: t.value.tooltip.textColor,
212
209
  width: "max-content",
213
- maxWidth: d(t).getLayout().chartArea.width + "px",
210
+ maxWidth: f(o).getLayout().chartArea.width + "px",
214
211
  boxSizing: "border-box",
215
212
  zIndex: 10,
216
- visibility: b.value !== null ? "visible" : "hidden"
213
+ visibility: k.value !== null ? "visible" : "hidden"
217
214
  })
218
215
  }, [
219
- U(a.$slots, "default", {
220
- snapshots: v.value,
221
- time: _.value
216
+ q(l.$slots, "default", {
217
+ snapshots: d.value,
218
+ time: R.value
222
219
  })
223
- ], 12, ue)) : w("", !0)
220
+ ], 12, pe)) : F("", !0)
224
221
  ], 64));
225
222
  }
226
223
  });
227
224
  export {
228
- ye as default
225
+ ge as default
229
226
  };
@@ -1,85 +1,85 @@
1
- import { defineComponent as O, useSlots as W, computed as t, ref as w, onMounted as H, onUnmounted as J, openBlock as A, createElementBlock as B, Fragment as Y, renderSlot as K, createElementVNode as _, normalizeStyle as z, unref as M, createVNode as Q, createCommentVNode as X } from "vue";
1
+ import { defineComponent as O, useSlots as W, computed as t, ref as w, onMounted as H, onUnmounted as J, openBlock as A, createElementBlock as B, Fragment as Y, renderSlot as K, createElementVNode as _, normalizeStyle as z, unref as D, createVNode as Q, createCommentVNode as X } from "vue";
2
2
  import { prefersReducedMotion as Z } from "../core/dist/animation/reduced-motion.js";
3
- import { resolveAnimate as ee, resolveYLabelSeriesId as te, firstVisibleValue as ae, BadgeAnimator as le } from "../core/dist/chart/badge-animator.js";
4
- import { useChartInstance as ne } from "../context.js";
5
- import oe from "./NumberFlow.vue.js";
6
- const ce = /* @__PURE__ */ O({
3
+ import { resolveAnimate as ee, resolveYLabelSeriesId as te, yLabelFractionDigits as ae, firstVisibleValue as le, BadgeAnimator as ne } from "../core/dist/chart/badge-animator.js";
4
+ import { useChartInstance as oe } from "../context.js";
5
+ import ue from "./NumberFlow.vue.js";
6
+ const fe = /* @__PURE__ */ O({
7
7
  __name: "YLabel",
8
8
  props: {
9
9
  seriesId: {},
10
10
  color: {},
11
- format: { type: Function },
12
- animate: { type: [Boolean, Object] },
11
+ format: {},
12
+ animate: { type: [Boolean, Object], default: void 0 },
13
13
  scale: {}
14
14
  },
15
15
  setup(E) {
16
- const r = E, e = ne(), N = W(), R = t(() => typeof N.default == "function"), l = w(0), i = w(null);
17
- let m = null, g = null, s = null;
18
- const T = t(() => ee(r.animate));
16
+ const u = E, e = oe(), M = W(), N = t(() => typeof M.default == "function"), l = w(0), r = w(null);
17
+ let m = null, g = null, i = null;
18
+ const R = t(() => ee(u.animate));
19
19
  function S() {
20
- s = null;
21
- const a = o.value, u = a !== null ? e.getStackedLastValue(a) : null;
22
- if (a === null || !u) {
20
+ i = null;
21
+ const a = o.value, d = a !== null ? e.getStackedLastValue(a) : null;
22
+ if (a === null || !d) {
23
23
  m = null, g = null;
24
24
  return;
25
25
  }
26
- const f = u.value;
27
- (m === null || g !== a) && (m = new le(f), g = a);
28
- const { glide: $, countUp: j, settleMs: G } = T.value, I = e.getIntroFront(a), c = m.frame({
29
- target: f,
26
+ const c = d.value;
27
+ (m === null || g !== a) && (m = new ne(c), g = a);
28
+ const { glide: $, countUp: j, settleMs: G } = R.value, I = e.getIntroFront(a), v = m.frame({
29
+ target: c,
30
30
  // Only needed for the intro count-up; skip the visible-range binary search
31
31
  // entirely once the reveal has settled (the hot streaming path).
32
- firstVisible: I < 1 ? ae(e, a, f) : f,
32
+ firstVisible: I < 1 ? le(e, a, c) : c,
33
33
  introFront: I,
34
34
  now: performance.now(),
35
35
  glide: $,
36
36
  countUp: j,
37
37
  settleMs: G,
38
38
  reducedMotion: Z()
39
- }), d = i.value;
40
- (d === null || d.positionValue !== c.positionValue || d.textValue !== c.textValue || d.opacity !== c.opacity) && (i.value = { positionValue: c.positionValue, textValue: c.textValue, opacity: c.opacity }), c.animating && s === null && (s = requestAnimationFrame(S));
39
+ }), p = r.value;
40
+ (p === null || p.positionValue !== v.positionValue || p.textValue !== v.textValue || p.opacity !== v.opacity) && (r.value = { positionValue: v.positionValue, textValue: v.textValue, opacity: v.opacity }), v.animating && i === null && (i = requestAnimationFrame(S));
41
41
  }
42
- function D() {
43
- s === null && (s = requestAnimationFrame(S));
42
+ function T() {
43
+ i === null && (i = requestAnimationFrame(S));
44
44
  }
45
- const p = () => {
46
- l.value++, D();
45
+ const f = () => {
46
+ l.value++, T();
47
47
  };
48
48
  H(() => {
49
- e.setYLabel(!0), e.on("overlayChange", p), e.on("viewportChange", p), e.getSeriesIds().length > 0 && p();
49
+ e.setYLabel(!0), e.on("overlayChange", f), e.on("viewportChange", f), e.getSeriesIds().length > 0 && f();
50
50
  }), J(() => {
51
- e.setYLabel(!1), e.off("overlayChange", p), e.off("viewportChange", p), s !== null && cancelAnimationFrame(s), s = null;
51
+ e.setYLabel(!1), e.off("overlayChange", f), e.off("viewportChange", f), i !== null && cancelAnimationFrame(i), i = null;
52
52
  });
53
- const o = t(() => (l.value, te(e, r.seriesId))), n = t(() => (l.value, o.value !== null ? e.getStackedLastValue(o.value) : null)), y = t(() => (l.value, o.value !== null ? e.getPreviousClose(o.value) : null)), v = t(() => (l.value, e.getTheme())), C = t(() => (l.value, r.scale !== void 0 ? r.scale : o.value !== null ? e.getSeriesScale(o.value) : void 0)), x = t(() => (l.value, e.getYScale(C.value))), U = t(() => (l.value, e.getYScaleColumn(C.value)?.position ?? e.yAxisPosition)), q = t(() => i.value !== null ? i.value.positionValue : n.value?.value ?? 0), P = t(() => i.value !== null ? i.value.textValue : n.value?.value ?? 0), b = t(() => i.value !== null ? i.value.opacity : o.value === null ? 1 : e.getIntroFront(o.value) < 1 ? 0 : 1), h = t(() => (l.value, n.value === null ? 0 : x.value.valueToY(q.value))), F = t(() => n.value === null || y.value === null ? "neutral" : n.value.value > y.value ? "up" : n.value.value < y.value ? "down" : "neutral"), V = t(() => {
54
- if (n.value === null) return v.value.yLabel.neutralBackground;
55
- if (!n.value.isLive) return v.value.axis.textColor;
56
- if (r.color) return r.color;
53
+ const o = t(() => (l.value, te(e, u.seriesId))), n = t(() => (l.value, o.value !== null ? e.getStackedLastValue(o.value) : null)), y = t(() => (l.value, o.value !== null ? e.getPreviousClose(o.value) : null)), s = t(() => (l.value, e.getTheme())), C = t(() => (l.value, u.scale !== void 0 ? u.scale : o.value !== null ? e.getSeriesScale(o.value) : void 0)), x = t(() => (l.value, e.getYScale(C.value))), U = t(() => (l.value, e.getYScaleColumn(C.value)?.position ?? e.yAxisPosition)), q = t(() => r.value !== null ? r.value.positionValue : n.value?.value ?? 0), P = t(() => r.value !== null ? r.value.textValue : n.value?.value ?? 0), b = t(() => r.value !== null ? r.value.opacity : o.value === null ? 1 : e.getIntroFront(o.value) < 1 ? 0 : 1), h = t(() => (l.value, n.value === null ? 0 : x.value.valueToY(q.value))), F = t(() => n.value === null || y.value === null ? "neutral" : n.value.value > y.value ? "up" : n.value.value < y.value ? "down" : "neutral"), V = t(() => {
54
+ if (n.value === null) return s.value.yLabel.neutralBackground;
55
+ if (!n.value.isLive) return s.value.axis.textColor;
56
+ if (u.color) return u.color;
57
57
  switch (F.value) {
58
58
  case "up":
59
- return v.value.yLabel.upBackground;
59
+ return s.value.yLabel.upBackground;
60
60
  case "down":
61
- return v.value.yLabel.downBackground;
61
+ return s.value.yLabel.downBackground;
62
62
  default:
63
- return v.value.yLabel.neutralBackground;
63
+ return s.value.yLabel.neutralBackground;
64
64
  }
65
65
  }), L = t(() => {
66
66
  l.value;
67
- const a = x.value.getRange(), u = a.max - a.min;
68
- return u < 0.1 ? 6 : u < 10 ? 4 : u < 1e3 ? 2 : 0;
67
+ const a = x.value.getRange();
68
+ return ae(a.max - a.min);
69
69
  }), k = t(() => {
70
- if (r.format) return r.format;
70
+ if (u.format) return u.format;
71
71
  l.value;
72
72
  const a = x.value.getFormat();
73
73
  if (a) return a;
74
- const u = new Intl.NumberFormat("en-US", {
74
+ const d = new Intl.NumberFormat("en-US", {
75
75
  minimumFractionDigits: L.value,
76
76
  maximumFractionDigits: L.value,
77
77
  useGrouping: !1
78
78
  });
79
- return (f) => u.format(f);
79
+ return (c) => d.format(c);
80
80
  });
81
- return (a, u) => n.value !== null ? (A(), B(Y, { key: 0 }, [
82
- R.value ? K(a.$slots, "default", {
81
+ return (a, d) => n.value !== null ? (A(), B(Y, { key: 0 }, [
82
+ N.value ? K(a.$slots, "default", {
83
83
  key: 0,
84
84
  value: n.value.value,
85
85
  y: h.value,
@@ -92,8 +92,8 @@ const ce = /* @__PURE__ */ O({
92
92
  _("div", {
93
93
  style: z({
94
94
  position: "absolute",
95
- left: M(e).plotLeft + "px",
96
- right: M(e).getAxisColumnWidth("right") + "px",
95
+ left: D(e).plotLeft + "px",
96
+ right: D(e).getAxisColumnWidth("right") + "px",
97
97
  top: h.value + "px",
98
98
  height: "0",
99
99
  borderTop: "1px dashed " + V.value,
@@ -112,16 +112,16 @@ const ce = /* @__PURE__ */ O({
112
112
  pointerEvents: "auto",
113
113
  zIndex: 3,
114
114
  background: V.value,
115
- color: v.value.yLabel.textColor,
116
- fontSize: v.value.yLabel.fontSize + "px",
117
- fontFamily: v.value.typography.fontFamily,
115
+ color: s.value.yLabel.textColor,
116
+ fontSize: s.value.yLabel.fontSize + "px",
117
+ fontFamily: s.value.typography.fontFamily,
118
118
  padding: "3px 8px",
119
119
  borderRadius: "3px",
120
120
  whiteSpace: "nowrap",
121
121
  transition: "background-color 0.3s ease"
122
122
  })
123
123
  }, [
124
- Q(oe, {
124
+ Q(ue, {
125
125
  value: P.value,
126
126
  format: k.value,
127
127
  "spin-duration": 350
@@ -132,5 +132,5 @@ const ce = /* @__PURE__ */ O({
132
132
  }
133
133
  });
134
134
  export {
135
- ce as default
135
+ fe as default
136
136
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wick-charts/vue",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Realtime, animated canvas charts for Vue: candlestick, line, bar, heatmap, pie and more. Tree-shakeable, zero runtime deps.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -51,7 +51,7 @@
51
51
  "vue": ">=3.3.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@wick-charts/core": "^0.8.0"
54
+ "@wick-charts/core": "^0.8.2"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "vite build"
@@ -3,6 +3,7 @@ import type { BandData, BandSeriesOptions, SeriesSyncState } from '@wick-charts/
3
3
  import { BandSeriesDef, EMPTY_SYNC_STATE, syncLayers, toLayers } from '@wick-charts/core';
4
4
  import { onMounted, onUnmounted, ref, watch } from 'vue';
5
5
 
6
+ import { rawSeriesData, seriesDataSource } from './composables';
6
7
  import { useChartInstance } from './context';
7
8
 
8
9
  const props = withDefaults(
@@ -36,13 +37,14 @@ const seriesId = ref<string | null>(null);
36
37
  // reconciliation (plus per-layer labels/colors) so streaming eases instead of
37
38
  // snapping Y every tick.
38
39
  let prevSync: SeriesSyncState[] = [];
40
+ let layerCount = 0;
39
41
 
40
42
  function applyData(id: string, data: BandData): void {
41
43
  prevSync = syncLayers({ chart, id, data, prev: prevSync });
42
44
  }
43
45
 
44
- onMounted(() => {
45
- const layerCount = toLayers(props.data).length;
46
+ function createSeries(data: BandData): void {
47
+ layerCount = toLayers(data).length;
46
48
  const id = chart.addSeries(BandSeriesDef, {
47
49
  ...props.options,
48
50
  scale: props.scale,
@@ -52,8 +54,12 @@ onMounted(() => {
52
54
  seriesId.value = id;
53
55
  prevSync = new Array(layerCount).fill(EMPTY_SYNC_STATE);
54
56
  // Lazy watcher — apply initial data here so static-data mounts render without a no-op first frame.
55
- applyData(id, props.data);
57
+ applyData(id, data);
56
58
  chart.setSeriesVisible(id, props.visible);
59
+ }
60
+
61
+ onMounted(() => {
62
+ createSeries(rawSeriesData(props.data));
57
63
  });
58
64
 
59
65
  onUnmounted(() => {
@@ -61,11 +67,20 @@ onUnmounted(() => {
61
67
  });
62
68
 
63
69
  watch(
64
- () => props.data,
65
- (data) => {
70
+ seriesDataSource(() => props.data),
71
+ () => {
72
+ const data = rawSeriesData(props.data);
66
73
  const id = seriesId.value;
67
74
  if (!id) return;
68
75
 
76
+ // The layer count is fixed when a series is created; a new count re-creates it, as in React.
77
+ if (toLayers(data).length !== layerCount) {
78
+ chart.removeSeries(id);
79
+ createSeries(data);
80
+
81
+ return;
82
+ }
83
+
69
84
  applyData(id, data);
70
85
  },
71
86
  );