@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,13 +1,14 @@
1
- import { formatTime as m, niceTimeIntervals as c } from "../utils/time.js";
2
- import { AxisTickTracker as f } from "./tick-tracker.js";
3
- const o = 50, v = 80;
4
- class p {
1
+ import { crispCenterOffset as m } from "../utils/pixel-grid.js";
2
+ import { formatTime as c, niceTimeIntervals as f } from "../utils/time.js";
3
+ import { AxisTickTracker as v } from "./tick-tracker.js";
4
+ const o = 50, d = 80;
5
+ class b {
5
6
  /**
6
7
  * Shared fade state for time ticks. Grid lines (canvas) and DOM tick labels
7
8
  * read opacity from the same tracker, so a tick fading in/out looks
8
9
  * identical on both surfaces.
9
10
  */
10
- tickTracker = new f();
11
+ tickTracker = new v();
11
12
  from = 0;
12
13
  to = 0;
13
14
  width = 1;
@@ -37,17 +38,17 @@ class p {
37
38
  return this.labelCountHintValue;
38
39
  }
39
40
  get minLabelSpacing() {
40
- return this.minSpacingValue ?? v;
41
+ return this.minSpacingValue ?? d;
41
42
  }
42
- update(t, e, n, r) {
43
- if (this.from = t.from, this.to = t.to, this.width = e, this.pixelRatio = n, r !== void 0 && r > 0) {
44
- const a = h(r);
45
- this.lastBucketKey !== null && this.lastBucketKey !== a && this.resetHysteresis(), this.lastBucketKey = a, this.dataInterval = r;
43
+ update(t, e, n, l) {
44
+ if (this.from = t.from, this.to = t.to, this.width = e, this.pixelRatio = n, l !== void 0 && l > 0) {
45
+ const a = h(l);
46
+ this.lastBucketKey !== null && this.lastBucketKey !== a && this.resetHysteresis(), this.lastBucketKey = a, this.dataInterval = l;
46
47
  }
47
48
  this.resolveInterval();
48
49
  }
49
50
  setLabelCount(t) {
50
- this.labelCountHintValue = d(t), this.resetHysteresis(), this.resolveInterval();
51
+ this.labelCountHintValue = p(t), this.resetHysteresis(), this.resolveInterval();
51
52
  }
52
53
  setMinSpacing(t) {
53
54
  this.minSpacingValue = I(t), this.resetHysteresis(), this.resolveInterval();
@@ -88,7 +89,7 @@ class p {
88
89
  * `formatTime`, applying the installed locale/timezone.
89
90
  */
90
91
  formatX(t, e) {
91
- return this.customFormat ? this.customFormat(t, e) : m(t, e, { locale: this.localeValue, timeZone: this.timeZoneValue });
92
+ return this.customFormat ? this.customFormat(t, e) : c(t, e, { locale: this.localeValue, timeZone: this.timeZoneValue });
92
93
  }
93
94
  resetHysteresis() {
94
95
  this.lastInterval = null, this.lastWant = null;
@@ -96,8 +97,22 @@ class p {
96
97
  timeToX(t) {
97
98
  return this.to <= this.from ? 0 : (t - this.from) / (this.to - this.from) * this.width;
98
99
  }
100
+ /** X in physical (bitmap) pixels, snapped to the pixel grid — for
101
+ * axis-aligned edges that have to stay crisp. */
99
102
  timeToBitmapX(t) {
100
- return Math.round(this.timeToX(t) * this.pixelRatio);
103
+ return Math.round(this.timeToBitmapXExact(t));
104
+ }
105
+ /** Same in physical pixels, off the grid — see {@link YScale.valueToBitmapYExact}. */
106
+ timeToBitmapXExact(t) {
107
+ return this.timeToX(t) * this.pixelRatio;
108
+ }
109
+ /**
110
+ * X position in CSS pixels of the *stroke center* the canvas grid draws for
111
+ * `time`. DOM axis labels position off this instead of raw {@link timeToX}
112
+ * so text and gridline share one pixel grid.
113
+ */
114
+ timeToSnappedX(t) {
115
+ return (this.timeToBitmapX(t) + m(this.pixelRatio)) / this.pixelRatio;
101
116
  }
102
117
  xToTime(t) {
103
118
  return this.to <= this.from ? this.from : this.from + t / this.width * (this.to - this.from);
@@ -119,16 +134,16 @@ class p {
119
134
  niceTickValues(t) {
120
135
  if (this.to <= this.from) return { ticks: [], tickInterval: 0 };
121
136
  if (this.customTickGenerator) {
122
- const i = this.customTickGenerator({ from: this.from, to: this.to }, t).slice(0, o), l = i.length >= 2 ? i[1] - i[0] : t;
123
- return { ticks: i, tickInterval: l };
137
+ const i = this.customTickGenerator({ from: this.from, to: this.to }, t).slice(0, o), r = i.length >= 2 ? i[1] - i[0] : t;
138
+ return { ticks: i, tickInterval: r };
124
139
  }
125
140
  if (this.dataInterval !== t) {
126
141
  const i = h(t);
127
142
  this.lastBucketKey !== null && this.lastBucketKey !== i && this.resetHysteresis(), this.lastBucketKey = i, this.dataInterval = t, this.resolveInterval();
128
143
  }
129
144
  if (this.resolvedInterval == null) return { ticks: [], tickInterval: 0 };
130
- const e = this.resolvedInterval, n = Math.ceil(this.from / e) * e, r = Math.max(0, Math.min(o, Math.floor((this.to - n) / e) + 1)), a = [];
131
- for (let i = 0; i < r; i++) a.push(n + i * e);
145
+ const e = this.resolvedInterval, n = Math.ceil(this.from / e) * e, l = Math.max(0, Math.min(o, Math.floor((this.to - n) / e) + 1)), a = [];
146
+ for (let i = 0; i < l; i++) a.push(n + i * e);
132
147
  return { ticks: a, tickInterval: e };
133
148
  }
134
149
  getRange() {
@@ -147,31 +162,31 @@ class p {
147
162
  this.resolvedInterval = null;
148
163
  return;
149
164
  }
150
- const t = c(this.dataInterval), e = this.to - this.from, n = e / this.width * this.minLabelSpacing;
151
- let r;
165
+ const t = f(this.dataInterval), e = this.to - this.from, n = e / this.width * this.minLabelSpacing;
166
+ let l;
152
167
  if (this.labelCountHint != null) {
153
- const l = Math.max(1, this.labelCountHint);
154
- r = Math.max(e / l, n);
168
+ const r = Math.max(1, this.labelCountHint);
169
+ l = Math.max(e / r, n);
155
170
  } else
156
- r = n;
171
+ l = n;
157
172
  if (this.lastInterval != null && this.lastWant != null && t.includes(this.lastInterval)) {
158
- const l = r >= this.lastWant * 0.8 && r <= this.lastWant * 1.25, u = this.lastInterval >= n;
159
- if (l && u) {
173
+ const r = l >= this.lastWant * 0.8 && l <= this.lastWant * 1.25, u = this.lastInterval >= n;
174
+ if (r && u) {
160
175
  this.resolvedInterval = this.lastInterval;
161
176
  return;
162
177
  }
163
178
  }
164
179
  let a = t[t.length - 1], i = t.length - 1;
165
- for (let l = 0; l < t.length; l++)
166
- if (t[l] >= r) {
167
- a = t[l], i = l;
180
+ for (let r = 0; r < t.length; r++)
181
+ if (t[r] >= l) {
182
+ a = t[r], i = r;
168
183
  break;
169
184
  }
170
185
  if (this.labelCountHint != null && i > 0 && this.countTicks(a) < this.labelCountHint) {
171
- const l = t[i - 1];
172
- l >= n && (a = l);
186
+ const r = t[i - 1];
187
+ r >= n && (a = r);
173
188
  }
174
- this.resolvedInterval = a, this.lastInterval = a, this.lastWant = r;
189
+ this.resolvedInterval = a, this.lastInterval = a, this.lastWant = l;
175
190
  }
176
191
  countTicks(t) {
177
192
  if (!(t > 0)) return 0;
@@ -182,12 +197,12 @@ class p {
182
197
  function h(s) {
183
198
  return s < 6e4 ? 0 : s < 36e5 ? 1 : s < 864e5 ? 2 : 3;
184
199
  }
185
- function d(s) {
200
+ function p(s) {
186
201
  return typeof s == "number" && Number.isFinite(s) && s >= 2 ? Math.floor(s) : null;
187
202
  }
188
203
  function I(s) {
189
204
  return typeof s == "number" && Number.isFinite(s) && s > 0 ? s : null;
190
205
  }
191
206
  export {
192
- p as XScale
207
+ b as XScale
193
208
  };
@@ -1,21 +1,30 @@
1
1
  import { formatCompact as o } from "../utils/format.js";
2
- import { AxisTickTracker as u } from "./tick-tracker.js";
3
- function m(e) {
2
+ import { crispCenterOffset as u } from "../utils/pixel-grid.js";
3
+ import { AxisTickTracker as m } from "./tick-tracker.js";
4
+ function c(e) {
4
5
  if (!Number.isFinite(e) || e <= 0) return 1;
5
6
  const t = 10 ** Math.floor(Math.log10(e)), i = e / t;
6
7
  return (i <= 1 ? 1 : i <= 2 ? 2 : i <= 5 ? 5 : 10) * t;
7
8
  }
8
- function c(e) {
9
+ function f(e) {
9
10
  if (!Number.isFinite(e) || e <= 0) return 1;
10
11
  const t = 10 ** Math.floor(Math.log10(e)), i = e / t;
11
12
  return (i >= 5 ? 5 : i >= 2 ? 2 : 1) * t;
12
13
  }
13
- const r = 50, v = 50;
14
- class M {
14
+ const a = 50, v = 50;
15
+ function g(e, t) {
16
+ return Number.isFinite(t) ? e?.isPlottable?.(t) ?? !0 : !1;
17
+ }
18
+ class d {
15
19
  /** Shared fade state for Y ticks; see {@link TimeScale.tickTracker}. */
16
- tickTracker = new u();
20
+ tickTracker = new m();
21
+ /** Non-linear value mapping (`axis.y.scale`); `null` is linear. */
22
+ transform = null;
17
23
  min = 0;
18
24
  max = 0;
25
+ /** Domain bounds in scale space — `transform.forward` of `min` / `max`. */
26
+ lo = 0;
27
+ hi = 0;
19
28
  height = 1;
20
29
  pixelRatio = 1;
21
30
  // Label density knobs — written by <YAxis labelCount=… minLabelSpacing=…>.
@@ -33,6 +42,8 @@ class M {
33
42
  * the boundary doesn't instantly flip back.
34
43
  */
35
44
  lastRawInterval = null;
45
+ /** The transform's own ticks (e.g. powers of ten); `null` while linear ticks are in use. */
46
+ ownTicks = null;
36
47
  /** Custom formatter (driven by `<YAxis format=…>`). */
37
48
  customFormat = null;
38
49
  /** Custom tick generator — bypasses {1,2,5}×10^k resolution in `niceTickValues` when set. */
@@ -44,20 +55,46 @@ class M {
44
55
  return this.minSpacingValue ?? v;
45
56
  }
46
57
  /** Recalculate the scale with a new Y range, chart height, and device pixel ratio. */
47
- update(t, i, a) {
48
- this.min = t.min, this.max = t.max, this.height = i, this.pixelRatio = a, this.resolveInterval();
58
+ update(t, i, s) {
59
+ this.min = t.min, this.max = t.max, this.height = i, this.pixelRatio = s, this.updateDomain(), this.resolveTicks();
60
+ }
61
+ /** Install a non-linear value mapping, or `null` for linear. The range is kept as-is — the chart refits it. */
62
+ setTransform(t) {
63
+ t !== this.transform && (this.transform = t, this.resetHysteresis(), this.updateDomain(), this.resolveTicks());
64
+ }
65
+ getTransform() {
66
+ return this.transform;
67
+ }
68
+ /**
69
+ * Whether `value` has a position on this scale: finite, and inside the
70
+ * transform's domain (positive on log). Renderers skip values that fail —
71
+ * {@link valueToY} still maps them (to the plot floor) so nothing
72
+ * downstream sees NaN.
73
+ */
74
+ isPlottable(t) {
75
+ return g(this.transform, t);
49
76
  }
50
77
  /** Desired label count. Invalid values (NaN, <2, Infinity) clear the hint. */
51
78
  setLabelCount(t) {
52
- this.labelCountHintValue = f(t), this.resetHysteresis(), this.resolveInterval();
79
+ this.labelCountHintValue = p(t), this.resetHysteresis(), this.resolveTicks();
53
80
  }
54
81
  /** Minimum pixel gap between adjacent labels. */
55
82
  setMinSpacing(t) {
56
- this.minSpacingValue = g(t), this.resetHysteresis(), this.resolveInterval();
83
+ this.minSpacingValue = x(t), this.resetHysteresis(), this.resolveTicks();
57
84
  }
58
85
  resetHysteresis() {
59
86
  this.lastInterval = null, this.lastRawInterval = null;
60
87
  }
88
+ /** A transformed domain needs both bounds plottable; anything else collapses to a flat one. */
89
+ updateDomain() {
90
+ const t = this.transform;
91
+ if (t === null) {
92
+ this.lo = this.min, this.hi = this.max;
93
+ return;
94
+ }
95
+ const i = this.isPlottable(this.min) && this.isPlottable(this.max);
96
+ this.lo = i ? t.forward(this.min) : 0, this.hi = i ? t.forward(this.max) : 0;
97
+ }
61
98
  /** Install (or clear) a custom formatter. */
62
99
  setFormat(t) {
63
100
  this.customFormat = t;
@@ -74,30 +111,73 @@ class M {
74
111
  setTickGenerator(t) {
75
112
  this.customTickGenerator = t, this.resetHysteresis();
76
113
  }
77
- /** Convert a value to a Y position in CSS (media) pixels. */
114
+ /**
115
+ * Convert a value to a Y position in CSS (media) pixels. A value the
116
+ * transform can't place (≤ 0 on log) lands on the plot floor.
117
+ */
78
118
  valueToY(t) {
79
- const i = this.max - this.min;
80
- return i === 0 ? this.height / 2 : (1 - (t - this.min) / i) * this.height;
119
+ const i = this.hi - this.lo;
120
+ if (i === 0) return this.height / 2;
121
+ const s = this.transform;
122
+ return s === null ? (1 - (t - this.lo) / i) * this.height : this.isPlottable(t) ? (1 - (s.forward(t) - this.lo) / i) * this.height : this.height;
81
123
  }
82
- /** Convert a value to a Y position in physical (bitmap) pixels. */
124
+ /** Convert a value to a Y position in physical (bitmap) pixels, snapped to
125
+ * the pixel grid — for axis-aligned edges that have to stay crisp. */
83
126
  valueToBitmapY(t) {
84
- return Math.round(this.valueToY(t) * this.pixelRatio);
127
+ return Math.round(this.valueToBitmapYExact(t));
85
128
  }
86
- /** Convert a Y position in CSS pixels back to a value. */
129
+ /**
130
+ * Same in physical pixels, off the grid. Anti-aliased geometry reads this
131
+ * one: snapping buys a diagonal stroke no sharpness, and during a slow
132
+ * animation it quantises the motion into whole-pixel jumps.
133
+ */
134
+ valueToBitmapYExact(t) {
135
+ return this.valueToY(t) * this.pixelRatio;
136
+ }
137
+ /**
138
+ * Y position in CSS pixels of the *stroke center* the canvas grid draws for
139
+ * `value`. DOM axis labels position off this instead of raw {@link valueToY}
140
+ * so text and gridline share one pixel grid.
141
+ */
142
+ valueToSnappedY(t) {
143
+ return (this.valueToBitmapY(t) + u(this.pixelRatio)) / this.pixelRatio;
144
+ }
145
+ /** Convert a Y position in CSS pixels back to a value — the exact inverse of {@link valueToY}. */
87
146
  yToValue(t) {
88
- const i = this.max - this.min;
89
- return i === 0 ? this.min : this.max - t / this.height * i;
147
+ const i = this.hi - this.lo;
148
+ if (i === 0) return this.min;
149
+ const s = this.hi - t / this.height * i;
150
+ return this.transform === null ? s : this.transform.inverse(s);
151
+ }
152
+ /** The value bars and stacks grow from: `0`, or the plot floor's value on a scale with no place for 0 (log). */
153
+ baselineValue() {
154
+ return this.isPlottable(0) ? 0 : this.min;
155
+ }
156
+ /**
157
+ * The value `t` of the way from `from` to `to` in pixels — a plain lerp on a
158
+ * linear axis, a geometric one on log. `t` past `[0, 1]` overshoots along the
159
+ * axis. An endpoint the transform can't place returns `to`, so a gap stays a gap.
160
+ */
161
+ lerpValue(t, i, s) {
162
+ const n = this.transform;
163
+ if (n === null) return t + (i - t) * s;
164
+ if (!this.isPlottable(t) || !this.isPlottable(i)) return i;
165
+ const r = n.forward(t);
166
+ return n.inverse(r + (n.forward(i) - r) * s);
90
167
  }
91
168
  /**
92
169
  * Generate evenly spaced "nice" tick values for the current range and
93
170
  * chart height. Pure read — resolution happens in `update()`.
94
171
  */
95
172
  niceTickValues() {
96
- if (this.customTickGenerator) return this.customTickGenerator({ min: this.min, max: this.max }).slice(0, r);
173
+ return this.customTickGenerator ? this.customTickGenerator({ min: this.min, max: this.max }).slice(0, a) : this.ownTicks !== null ? this.ownTicks.slice(0, a) : this.linearTickValues();
174
+ }
175
+ /** {1,2,5}×10^k ticks at the resolved interval, limited to what the transform can place. */
176
+ linearTickValues() {
97
177
  if (this.resolvedInterval == null) return [];
98
- const t = this.resolvedInterval, i = Math.ceil(this.min / t) * t, a = Math.max(0, Math.min(r, Math.floor((this.max - i) / t) + 1)), s = [];
99
- for (let n = 0; n < a; n++) s.push(i + n * t);
100
- return s;
178
+ const t = this.resolvedInterval, i = Math.ceil(this.min / t) * t, s = Math.max(0, Math.min(a, Math.floor((this.max - i) / t) + 1)), n = [];
179
+ for (let r = 0; r < s; r++) n.push(i + r * t);
180
+ return this.transform === null ? n : n.filter((r) => this.isPlottable(r));
101
181
  }
102
182
  getRange() {
103
183
  return { min: this.min, max: this.max };
@@ -114,13 +194,49 @@ class M {
114
194
  */
115
195
  formatY(t) {
116
196
  if (this.customFormat) return this.customFormat(t);
197
+ const i = this.ownTicks !== null ? this.transform?.format : void 0;
198
+ if (i) return i(t);
117
199
  if (this.max - this.min >= 1e6) return o(t);
118
- const i = this.resolvedInterval, a = i != null && i > 0 ? Math.max(0, -Math.floor(Math.log10(i))) : 1;
119
- return t.toFixed(a);
200
+ const s = this.resolvedInterval, n = s != null && s > 0 ? Math.max(0, -Math.floor(Math.log10(s))) : 1;
201
+ return t.toFixed(n);
202
+ }
203
+ resolveTicks() {
204
+ this.ownTicks = null;
205
+ const t = this.transform;
206
+ if (t === null) {
207
+ this.resolveInterval((this.max - this.min) * this.minLabelSpacing / this.height);
208
+ return;
209
+ }
210
+ const i = this.hi - this.lo;
211
+ if (!(i > 0) || this.height <= 0) {
212
+ this.resolvedInterval = null;
213
+ return;
214
+ }
215
+ if (this.resolveInterval(this.transformedGapFloor(t, i)), !t.ticks) return;
216
+ const s = this.linearTickValues(), n = t.ticks({
217
+ min: this.min,
218
+ max: this.max,
219
+ height: this.height,
220
+ minSpacing: this.minLabelSpacing,
221
+ labelCount: this.labelCountHint,
222
+ linear: s
223
+ });
224
+ this.ownTicks = n === s ? null : n;
225
+ }
226
+ /**
227
+ * Smallest linear interval whose ticks stay `minLabelSpacing` apart on the
228
+ * transformed axis. A monotonic mapping squeezes its gaps hardest at one
229
+ * end — the top for log (concave), the bottom for a convex one — so
230
+ * checking both ends covers it.
231
+ */
232
+ transformedGapFloor(t, i) {
233
+ const s = this.minLabelSpacing / this.height * i, n = this.max - t.inverse(Math.max(this.lo, this.hi - s)), r = t.inverse(Math.min(this.hi, this.lo + s)) - this.min;
234
+ return Math.max(n, r);
120
235
  }
121
236
  /**
122
237
  * Resolve the interval to a {1,2,5}×10^k tick size that satisfies the pixel
123
- * floor and (optionally) targets `labelCountHint` labels.
238
+ * floor and (optionally) targets `labelCountHint` labels. `gapFloorValue` is
239
+ * the smallest interval that clears `minLabelSpacing` anywhere on the axis.
124
240
  *
125
241
  * Hysteresis: the band [0.8×, 1.25×] is anchored to **rawInterval at last
126
242
  * snap**, not to `lastInterval`. After an escalation (e.g. 100 → 200),
@@ -129,26 +245,26 @@ class M {
129
245
  * *not* de-escalate. This prevents the 2-tier flicker users see when new
130
246
  * candles nudge the Y range across a raw-interval threshold.
131
247
  */
132
- resolveInterval() {
248
+ resolveInterval(t) {
133
249
  if (this.max <= this.min || this.height <= 0) {
134
250
  this.resolvedInterval = null;
135
251
  return;
136
252
  }
137
- const t = this.max - this.min, i = t * this.minLabelSpacing / this.height, a = this.labelCountHint != null ? Math.max(1, this.labelCountHint) : Math.max(1, Math.floor(this.height / this.minLabelSpacing));
138
- let s = t / a;
139
- if (s < i && (s = i), this.lastInterval != null && this.lastRawInterval != null) {
140
- const l = s >= this.lastRawInterval * 0.8 && s <= this.lastRawInterval * 1.25, h = this.lastInterval >= i;
253
+ const i = this.max - this.min, s = this.labelCountHint != null ? Math.max(1, this.labelCountHint) : Math.max(1, Math.floor(this.height / this.minLabelSpacing));
254
+ let n = i / s;
255
+ if (n < t && (n = t), this.lastInterval != null && this.lastRawInterval != null) {
256
+ const l = n >= this.lastRawInterval * 0.8 && n <= this.lastRawInterval * 1.25, h = this.lastInterval >= t;
141
257
  if (l && h) {
142
258
  this.resolvedInterval = this.lastInterval;
143
259
  return;
144
260
  }
145
261
  }
146
- let n = m(s);
147
- if (this.labelCountHint != null && this.countTicks(n) < this.labelCountHint) {
148
- const l = c(s);
149
- l >= i && l > 0 && (n = l);
262
+ let r = c(n);
263
+ if (this.labelCountHint != null && this.countTicks(r) < this.labelCountHint) {
264
+ const l = f(n);
265
+ l >= t && l > 0 && (r = l);
150
266
  }
151
- this.resolvedInterval = n, this.lastInterval = n, this.lastRawInterval = s;
267
+ this.resolvedInterval = r, this.lastInterval = r, this.lastRawInterval = n;
152
268
  }
153
269
  countTicks(t) {
154
270
  if (!(t > 0)) return 0;
@@ -156,12 +272,13 @@ class M {
156
272
  return Math.max(0, Math.floor((this.max - i) / t) + 1);
157
273
  }
158
274
  }
159
- function f(e) {
275
+ function p(e) {
160
276
  return typeof e == "number" && Number.isFinite(e) && e >= 2 ? Math.floor(e) : null;
161
277
  }
162
- function g(e) {
278
+ function x(e) {
163
279
  return typeof e == "number" && Number.isFinite(e) && e > 0 ? e : null;
164
280
  }
165
281
  export {
166
- M as YScale
282
+ d as YScale,
283
+ g as isPlottableOn
167
284
  };
@@ -1,18 +1,18 @@
1
- import { easeOutBack as a } from "../animation/easing.js";
2
- function t() {
3
- return () => ({
4
- value: ({ value: e, progress: r }) => e * r,
1
+ import { easeOutBack as s } from "../animation/easing.js";
2
+ function n() {
3
+ return (r) => ({
4
+ value: ({ value: e, progress: a }) => r.lerpValue(r.baseline, e, a),
5
5
  element: (e) => ({ alpha: e.progress })
6
6
  });
7
7
  }
8
- const o = 0.3;
9
- function n() {
10
- return () => ({
11
- value: ({ value: e, progress: r }) => e * a(r),
12
- element: (e) => ({ alpha: Math.min(1, e.progress / o) })
8
+ const l = 0.3;
9
+ function t() {
10
+ return (r) => ({
11
+ value: ({ value: e, progress: a }) => r.lerpValue(r.baseline, e, s(a)),
12
+ element: (e) => ({ alpha: Math.min(1, e.progress / l) })
13
13
  });
14
14
  }
15
15
  export {
16
- t as growIntro,
17
- n as springIntro
16
+ n as growIntro,
17
+ t as springIntro
18
18
  };