blazeplot 0.1.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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +206 -0
  3. package/ROADMAP.md +263 -0
  4. package/dist/core/DataCursor.d.ts +9 -0
  5. package/dist/core/DataCursor.d.ts.map +1 -0
  6. package/dist/core/MinMaxPyramid.d.ts +15 -0
  7. package/dist/core/MinMaxPyramid.d.ts.map +1 -0
  8. package/dist/core/RingBuffer.d.ts +24 -0
  9. package/dist/core/RingBuffer.d.ts.map +1 -0
  10. package/dist/core/SeriesStore.d.ts +22 -0
  11. package/dist/core/SeriesStore.d.ts.map +1 -0
  12. package/dist/core/index.d.ts +6 -0
  13. package/dist/core/index.d.ts.map +1 -0
  14. package/dist/core/types.d.ts +33 -0
  15. package/dist/core/types.d.ts.map +1 -0
  16. package/dist/index.d.ts +10 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +669 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/interaction/AxisController.d.ts +12 -0
  21. package/dist/interaction/AxisController.d.ts.map +1 -0
  22. package/dist/interaction/Camera2D.d.ts +31 -0
  23. package/dist/interaction/Camera2D.d.ts.map +1 -0
  24. package/dist/interaction/InputController.d.ts +23 -0
  25. package/dist/interaction/InputController.d.ts.map +1 -0
  26. package/dist/interaction/index.d.ts +5 -0
  27. package/dist/interaction/index.d.ts.map +1 -0
  28. package/dist/interaction/types.d.ts +18 -0
  29. package/dist/interaction/types.d.ts.map +1 -0
  30. package/dist/render/ReglBackend.d.ts +22 -0
  31. package/dist/render/ReglBackend.d.ts.map +1 -0
  32. package/dist/render/Renderer.d.ts +20 -0
  33. package/dist/render/Renderer.d.ts.map +1 -0
  34. package/dist/render/ShaderPrograms.d.ts +11 -0
  35. package/dist/render/ShaderPrograms.d.ts.map +1 -0
  36. package/dist/render/WebGL2Resources.d.ts +3 -0
  37. package/dist/render/WebGL2Resources.d.ts.map +1 -0
  38. package/dist/render/index.d.ts +6 -0
  39. package/dist/render/index.d.ts.map +1 -0
  40. package/dist/render/types.d.ts +38 -0
  41. package/dist/render/types.d.ts.map +1 -0
  42. package/dist/ui/Axis.d.ts +3 -0
  43. package/dist/ui/Axis.d.ts.map +1 -0
  44. package/dist/ui/Chart.d.ts +55 -0
  45. package/dist/ui/Chart.d.ts.map +1 -0
  46. package/dist/ui/Grid.d.ts +3 -0
  47. package/dist/ui/Grid.d.ts.map +1 -0
  48. package/dist/ui/Legend.d.ts +3 -0
  49. package/dist/ui/Legend.d.ts.map +1 -0
  50. package/dist/ui/Tooltip.d.ts +3 -0
  51. package/dist/ui/Tooltip.d.ts.map +1 -0
  52. package/dist/ui/index.d.ts +7 -0
  53. package/dist/ui/index.d.ts.map +1 -0
  54. package/package.json +49 -0
package/dist/index.js ADDED
@@ -0,0 +1,669 @@
1
+ import e from "regl";
2
+ //#region src/core/RingBuffer.ts
3
+ var t = class {
4
+ capacity;
5
+ _length = 0;
6
+ _head = 0;
7
+ xData;
8
+ yData;
9
+ constructor(e) {
10
+ if (!Number.isInteger(e) || e <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
11
+ this.capacity = e, this.xData = new Float64Array(e), this.yData = new Float32Array(e);
12
+ }
13
+ get length() {
14
+ return this._length;
15
+ }
16
+ get range() {
17
+ return this._length === 0 ? null : {
18
+ start: this.getX(0),
19
+ end: this.getX(this._length - 1)
20
+ };
21
+ }
22
+ push(e, t) {
23
+ this.xData[this._head] = e, this.yData[this._head] = t, this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
24
+ }
25
+ get(e) {
26
+ return e < 0 || e >= this._length ? null : {
27
+ x: this.getX(e),
28
+ y: this.getY(e)
29
+ };
30
+ }
31
+ getX(e) {
32
+ return this.assertValidIndex(e), this.xData[this.logicalToPhysical(e)];
33
+ }
34
+ getY(e) {
35
+ return this.assertValidIndex(e), this.yData[this.logicalToPhysical(e)];
36
+ }
37
+ lowerBoundX(e) {
38
+ let t = 0, n = this._length;
39
+ for (; t < n;) {
40
+ let r = t + (n - t >> 1);
41
+ this.getX(r) < e ? t = r + 1 : n = r;
42
+ }
43
+ return t;
44
+ }
45
+ upperBoundX(e) {
46
+ let t = 0, n = this._length;
47
+ for (; t < n;) {
48
+ let r = t + (n - t >> 1);
49
+ this.getX(r) <= e ? t = r + 1 : n = r;
50
+ }
51
+ return t;
52
+ }
53
+ clear() {
54
+ this._length = 0, this._head = 0;
55
+ }
56
+ logicalToPhysical(e) {
57
+ return (this._head - this._length + e + this.capacity) % this.capacity;
58
+ }
59
+ assertValidIndex(e) {
60
+ if (!Number.isInteger(e) || e < 0 || e >= this._length) throw RangeError(`RingBuffer index out of range: ${e}`);
61
+ }
62
+ }, n = 16, r = class {
63
+ bucketSize;
64
+ levels = [];
65
+ levelLengths;
66
+ levelSampleWidths;
67
+ constructor(e = 2) {
68
+ if (this.bucketSize = e, !Number.isInteger(e) || e < 2) throw RangeError("MinMaxPyramid bucketSize must be an integer >= 2.");
69
+ this.levelLengths = new Uint32Array(n), this.levelSampleWidths = new Uint32Array(n);
70
+ }
71
+ build(e) {
72
+ this.levels = [], this.levelLengths.fill(0), this.levelSampleWidths.fill(0);
73
+ let t = e.length;
74
+ if (t === 0) return;
75
+ let r = null, i = 0;
76
+ for (; t > 0 && i < n;) {
77
+ let n = Math.ceil(t / this.bucketSize), a = new Float32Array(n * 2);
78
+ for (let n = 0; n < t; n += this.bucketSize) {
79
+ let i = Infinity, o = -Infinity, s = Math.min(n + this.bucketSize, t);
80
+ for (let t = n; t < s; t++) if (r) {
81
+ let e = r[t * 2], n = r[t * 2 + 1];
82
+ e < i && (i = e), n > o && (o = n);
83
+ } else {
84
+ let n = e.getY(t);
85
+ n < i && (i = n), n > o && (o = n);
86
+ }
87
+ let c = Math.floor(n / this.bucketSize);
88
+ a[c * 2] = i, a[c * 2 + 1] = o;
89
+ }
90
+ if (this.levels[i] = a, this.levelLengths[i] = n, this.levelSampleWidths[i] = this.bucketSize ** (i + 1), n === 1) break;
91
+ r = a, t = n, i++;
92
+ }
93
+ }
94
+ query(e, t, n) {
95
+ if (t <= 0 || n.length <= 0) return {
96
+ buckets: new Float32Array(),
97
+ bucketCount: 0,
98
+ level: 0,
99
+ samplesPerPixel: 0
100
+ };
101
+ let r = n.length, i = Math.max(1, r / t), a = Math.min(Math.max(0, Math.ceil(Math.log2(i)) - 1), this.levels.length - 1), o = this.levels[a], s = this.levelLengths[a], c = this.levelSampleWidths[a];
102
+ if (!o || s === void 0 || c === void 0 || s === 0 || c === 0) return {
103
+ buckets: new Float32Array(),
104
+ bucketCount: 0,
105
+ level: 0,
106
+ samplesPerPixel: i
107
+ };
108
+ let l = Math.max(0, n.start), u = l + n.length, d = Math.max(0, Math.floor(l / c)), f = Math.min(s, Math.ceil(u / c)) - d;
109
+ if (f <= 0) return {
110
+ buckets: new Float32Array(),
111
+ bucketCount: 0,
112
+ level: a,
113
+ samplesPerPixel: i
114
+ };
115
+ let p = new Float32Array(f * 2);
116
+ for (let e = 0; e < f; e++) {
117
+ let t = (d + e) * 2;
118
+ p[e * 2] = o[t], p[e * 2 + 1] = o[t + 1];
119
+ }
120
+ return {
121
+ buckets: p,
122
+ bucketCount: f,
123
+ level: a,
124
+ samplesPerPixel: i
125
+ };
126
+ }
127
+ }, i = class {
128
+ config;
129
+ style;
130
+ buffer;
131
+ pyramid;
132
+ _dirty = !1;
133
+ _visible = !0;
134
+ constructor(e, n) {
135
+ this.config = e, this.buffer = new t(e.capacity), this.pyramid = new r(), this.style = n;
136
+ }
137
+ get dirty() {
138
+ return this._dirty;
139
+ }
140
+ get length() {
141
+ return this.buffer.length;
142
+ }
143
+ get visible() {
144
+ return this._visible;
145
+ }
146
+ setVisible(e) {
147
+ this._visible = e;
148
+ }
149
+ append(e, t) {
150
+ let n = Math.min(e.length, t.length);
151
+ for (let r = 0; r < n; r++) this.buffer.push(e[r], t[r]);
152
+ this._dirty = !0;
153
+ }
154
+ clear() {
155
+ this.buffer.clear(), this.pyramid.build(this.buffer), this._dirty = !1;
156
+ }
157
+ rebuildPyramid() {
158
+ this._dirty &&= (this.pyramid.build(this.buffer), !1);
159
+ }
160
+ query(e, t) {
161
+ if (!this.buffer.range) return {
162
+ buckets: new Float32Array(),
163
+ bucketCount: 0,
164
+ level: 0,
165
+ samplesPerPixel: 0
166
+ };
167
+ let n = this.buffer.lowerBoundX(e.xMin), r = this.buffer.upperBoundX(e.xMax);
168
+ return this.pyramid.query(e, t, {
169
+ start: n,
170
+ length: Math.max(0, r - n)
171
+ });
172
+ }
173
+ visibleSampleCount(e) {
174
+ let t = this.buffer.lowerBoundX(e.xMin), n = this.buffer.upperBoundX(e.xMax);
175
+ return Math.max(0, n - t);
176
+ }
177
+ copyRawVisible(e, t, n) {
178
+ if (n <= 0 || t.length < n * 2) return 0;
179
+ let r = this.buffer.lowerBoundX(e.xMin), i = this.buffer.upperBoundX(e.xMax), a = i - r;
180
+ if (a <= 0) return 0;
181
+ let o = Math.max(1, Math.ceil(a / n)), s = 0;
182
+ for (let e = r; e < i && s < n; e += o) t[s * 2] = this.buffer.getX(e), t[s * 2 + 1] = this.buffer.getY(e), s++;
183
+ return s;
184
+ }
185
+ copyMinMaxVisible(e, t, n) {
186
+ if (n <= 0 || t.length < n * 4) return 0;
187
+ let r = this.buffer.lowerBoundX(e.xMin), i = this.buffer.upperBoundX(e.xMax), a = i - r;
188
+ if (a <= 0) return 0;
189
+ let o = Math.min(n, a), s = 0;
190
+ for (let e = 0; e < o; e++) {
191
+ let n = r + Math.floor(e * a / o), c = r + Math.max(Math.floor((e + 1) * a / o), Math.floor(e * a / o) + 1), l = Math.min(i, c), u = Infinity, d = -Infinity;
192
+ for (let e = n; e < l; e++) {
193
+ let t = this.buffer.getY(e);
194
+ t < u && (u = t), t > d && (d = t);
195
+ }
196
+ let f = this.buffer.getX(n + (l - n >> 1));
197
+ t[s * 2] = f, t[s * 2 + 1] = u, s++, t[s * 2] = f, t[s * 2 + 1] = d, s++;
198
+ }
199
+ return s;
200
+ }
201
+ }, a = {
202
+ line: {
203
+ vert: "attribute vec2 position;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n",
204
+ frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
205
+ },
206
+ segment: {
207
+ vert: "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n float y = (gl_VertexID == 0) ? aMinY : aMaxY;\n vec2 position = vec2(aX, y);\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n",
208
+ frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
209
+ }
210
+ }, o = class {
211
+ backend;
212
+ lineProgram;
213
+ scaleUniform = new Float32Array(2);
214
+ offsetUniform = new Float32Array(2);
215
+ constructor(e) {
216
+ this.backend = e, this.lineProgram = this.backend.createProgram(a.line.vert, a.line.frag);
217
+ }
218
+ clear(e, t, n, r) {
219
+ this.backend.clear(e, t, n, r);
220
+ }
221
+ createFloatBuffer(e) {
222
+ return this.backend.createBuffer({
223
+ usage: "stream",
224
+ type: "float",
225
+ length: e
226
+ });
227
+ }
228
+ updateFloatBuffer(e, t) {
229
+ this.backend.updateBuffer(e, t);
230
+ }
231
+ viewport(e, t, n, r) {
232
+ this.backend.viewport(e, t, n, r);
233
+ }
234
+ drawLines(e, t, n, r) {
235
+ this.drawLinePrimitive("lines", e, t, n, r);
236
+ }
237
+ drawLineStrip(e, t, n, r) {
238
+ this.drawLinePrimitive("line_strip", e, t, n, r);
239
+ }
240
+ drawLinePrimitive(e, t, n, r, i) {
241
+ this.scaleUniform[0] = i.xScale, this.scaleUniform[1] = i.yScale, this.offsetUniform[0] = i.xOffset, this.offsetUniform[1] = i.yOffset, this.backend.draw({
242
+ program: this.lineProgram,
243
+ primitive: e,
244
+ count: n,
245
+ attributes: { position: t },
246
+ uniforms: {
247
+ uScale: this.scaleUniform,
248
+ uOffset: this.offsetUniform,
249
+ uColor: r.color
250
+ }
251
+ });
252
+ }
253
+ drawMinMaxSegments(e, t, n, r) {
254
+ this.drawLines(e, t, n, r);
255
+ }
256
+ dispose() {
257
+ this.backend.destroy();
258
+ }
259
+ };
260
+ //#endregion
261
+ //#region src/render/ReglBackend.ts
262
+ function s(e) {
263
+ return e;
264
+ }
265
+ var c = class {
266
+ gl;
267
+ regl;
268
+ nextProgramId = 1;
269
+ commandCache = /* @__PURE__ */ new Map();
270
+ constructor(t) {
271
+ let n = t.getContext("webgl2", {
272
+ alpha: !0,
273
+ antialias: !1,
274
+ depth: !1,
275
+ stencil: !1,
276
+ premultipliedAlpha: !1,
277
+ preserveDrawingBuffer: !1,
278
+ powerPreference: "high-performance"
279
+ });
280
+ if (!n) throw Error("BlazePlot requires WebGL2, but this browser/context does not support it.");
281
+ this.gl = n, this.regl = e({
282
+ gl: s(this.gl),
283
+ extensions: [],
284
+ optionalExtensions: ["ext_disjoint_timer_query_webgl2"]
285
+ });
286
+ }
287
+ createBuffer(e) {
288
+ let t = e.type === "float" ? 4 : 2;
289
+ return {
290
+ length: e.length,
291
+ type: e.type,
292
+ buffer: this.regl.buffer({
293
+ length: e.length * t,
294
+ usage: e.usage,
295
+ type: e.type === "float" ? "float" : "uint16"
296
+ })
297
+ };
298
+ }
299
+ updateBuffer(e, t, n = 0) {
300
+ if (t.length + n > e.length) throw RangeError("GPU buffer update exceeds allocated buffer length.");
301
+ let r = e.type === "float" ? 4 : 2;
302
+ this.asReglBuffer(e).buffer.subdata(t, n * r);
303
+ }
304
+ createProgram(e, t) {
305
+ return {
306
+ id: this.nextProgramId++,
307
+ vert: e,
308
+ frag: t
309
+ };
310
+ }
311
+ draw(e) {
312
+ if (e.count <= 0) return;
313
+ let t = this.asReglProgram(e.program), n = Object.keys(e.attributes).sort(), r = Object.keys(e.uniforms).sort(), i = [
314
+ t.id,
315
+ e.primitive,
316
+ n.join(","),
317
+ r.join(","),
318
+ e.instances === void 0 ? 0 : 1
319
+ ].join("|"), a = this.commandCache.get(i);
320
+ a || (a = this.createDrawCommand(t, e.primitive, n, r, e.instances !== void 0), this.commandCache.set(i, a));
321
+ let o = {};
322
+ for (let t of n) o[t] = this.asReglBuffer(e.attributes[t]).buffer;
323
+ a({
324
+ count: e.count,
325
+ instances: e.instances ?? 0,
326
+ attributes: o,
327
+ uniforms: e.uniforms
328
+ });
329
+ }
330
+ dispose(e) {
331
+ this.isReglBuffer(e) && e.buffer.destroy();
332
+ }
333
+ clear(e, t, n, r) {
334
+ this.regl.clear({ color: [
335
+ e,
336
+ t,
337
+ n,
338
+ r
339
+ ] });
340
+ }
341
+ viewport(e, t, n, r) {}
342
+ destroy() {
343
+ this.regl.destroy();
344
+ }
345
+ createDrawCommand(e, t, n, r, i) {
346
+ let a = {};
347
+ for (let e of n) a[e] = (t, n) => n.attributes[e];
348
+ let o = {};
349
+ for (let e of r) o[e] = (t, n) => n.uniforms[e];
350
+ return this.regl({
351
+ vert: e.vert,
352
+ frag: e.frag,
353
+ attributes: a,
354
+ uniforms: o,
355
+ primitive: this.toReglPrimitive(t),
356
+ count: (e, t) => t.count,
357
+ instances: i ? (e, t) => t.instances : void 0,
358
+ depth: { enable: !1 }
359
+ });
360
+ }
361
+ asReglBuffer(e) {
362
+ return e;
363
+ }
364
+ asReglProgram(e) {
365
+ return e;
366
+ }
367
+ isReglBuffer(e) {
368
+ return "length" in e && "type" in e && "buffer" in e;
369
+ }
370
+ toReglPrimitive(e) {
371
+ switch (e) {
372
+ case "line_strip": return "line strip";
373
+ case "triangle_strip": return "triangle strip";
374
+ default: return e;
375
+ }
376
+ }
377
+ }, l = class {
378
+ canvas;
379
+ camera;
380
+ policy;
381
+ _enabled = !0;
382
+ activePointerId = null;
383
+ lastX = 0;
384
+ lastY = 0;
385
+ constructor(e, t, n) {
386
+ this.canvas = e, this.camera = t, this.policy = n, this.bindEvents();
387
+ }
388
+ get enabled() {
389
+ return this._enabled;
390
+ }
391
+ set enabled(e) {
392
+ this._enabled = e;
393
+ }
394
+ bindEvents() {
395
+ this.canvas.addEventListener("pointerdown", this.onPointerDown), this.canvas.addEventListener("pointermove", this.onPointerMove), this.canvas.addEventListener("pointerup", this.onPointerUp), this.canvas.addEventListener("pointercancel", this.onPointerUp), this.canvas.addEventListener("wheel", this.onWheel, { passive: !1 });
396
+ }
397
+ onPointerDown = (e) => {
398
+ !this._enabled || this.activePointerId !== null || (this.activePointerId = e.pointerId, this.lastX = e.clientX, this.lastY = e.clientY, this.canvas.setPointerCapture(e.pointerId));
399
+ };
400
+ onPointerMove = (e) => {
401
+ if (!this._enabled || e.pointerId !== this.activePointerId) return;
402
+ let t = this.canvas.getBoundingClientRect(), n = t.width > 0 ? (this.lastX - e.clientX) / t.width : 0, r = t.height > 0 ? (e.clientY - this.lastY) / t.height : 0, i = this.applyPanPolicy({
403
+ dx: n,
404
+ dy: r
405
+ });
406
+ i && this.camera.pan(i), this.lastX = e.clientX, this.lastY = e.clientY;
407
+ };
408
+ onPointerUp = (e) => {
409
+ e.pointerId === this.activePointerId && (this.activePointerId = null, this.canvas.hasPointerCapture(e.pointerId) && this.canvas.releasePointerCapture(e.pointerId));
410
+ };
411
+ onWheel = (e) => {
412
+ if (!this._enabled) return;
413
+ e.preventDefault();
414
+ let t = e.deltaY < 0 ? 1.1 : .9, n = this.canvas.getBoundingClientRect(), r = n.width > 0 ? (e.clientX - n.left) / n.width : .5, i = n.height > 0 ? 1 - (e.clientY - n.top) / n.height : .5, a = this.applyZoomPolicy({
415
+ factor: t,
416
+ cx: r,
417
+ cy: i,
418
+ axis: "xy"
419
+ });
420
+ a && this.camera.zoom(a);
421
+ };
422
+ applyPanPolicy(e) {
423
+ return this.policy?.beforePan ? this.policy.beforePan(this.camera, e) : e;
424
+ }
425
+ applyZoomPolicy(e) {
426
+ return this.policy?.beforeZoom ? this.policy.beforeZoom(this.camera, e) : e;
427
+ }
428
+ dispose() {
429
+ this.canvas.removeEventListener("pointerdown", this.onPointerDown), this.canvas.removeEventListener("pointermove", this.onPointerMove), this.canvas.removeEventListener("pointerup", this.onPointerUp), this.canvas.removeEventListener("pointercancel", this.onPointerUp), this.canvas.removeEventListener("wheel", this.onWheel);
430
+ }
431
+ }, u = class e {
432
+ _xMin = 0;
433
+ _xMax = 1;
434
+ _yMin = 0;
435
+ _yMax = 1;
436
+ get xMin() {
437
+ return this._xMin;
438
+ }
439
+ get xMax() {
440
+ return this._xMax;
441
+ }
442
+ get yMin() {
443
+ return this._yMin;
444
+ }
445
+ get yMax() {
446
+ return this._yMax;
447
+ }
448
+ get viewport() {
449
+ return {
450
+ xMin: this._xMin,
451
+ xMax: this._xMax,
452
+ yMin: this._yMin,
453
+ yMax: this._yMax
454
+ };
455
+ }
456
+ get xScale() {
457
+ return 2 / (this._xMax - this._xMin);
458
+ }
459
+ get xOffset() {
460
+ return -(this._xMin + this._xMax) / (this._xMax - this._xMin);
461
+ }
462
+ get yScale() {
463
+ return 2 / (this._yMax - this._yMin);
464
+ }
465
+ get yOffset() {
466
+ return -(this._yMin + this._yMax) / (this._yMax - this._yMin);
467
+ }
468
+ setViewport(t) {
469
+ let n = {
470
+ xMin: t.xMin ?? this._xMin,
471
+ xMax: t.xMax ?? this._xMax,
472
+ yMin: t.yMin ?? this._yMin,
473
+ yMax: t.yMax ?? this._yMax
474
+ };
475
+ e.assertValidViewport(n), this._xMin = n.xMin, this._xMax = n.xMax, this._yMin = n.yMin, this._yMax = n.yMax;
476
+ }
477
+ pan(t) {
478
+ let { dx: n, dy: r } = t;
479
+ e.assertFinite("dx", n), e.assertFinite("dy", r);
480
+ let i = this._xMax - this._xMin, a = this._yMax - this._yMin;
481
+ this.setViewport({
482
+ xMin: this._xMin + n * i,
483
+ xMax: this._xMax + n * i,
484
+ yMin: this._yMin + r * a,
485
+ yMax: this._yMax + r * a
486
+ });
487
+ }
488
+ zoom(t) {
489
+ let { factor: n, cx: r, cy: i, axis: a } = t;
490
+ if (e.assertFinite("factor", n), e.assertFinite("cx", r), e.assertFinite("cy", i), n <= 0) throw RangeError("Camera2D zoom factor must be > 0.");
491
+ let o = this._xMax - this._xMin, s = this._yMax - this._yMin, c = this._xMin + o * r, l = this._yMin + s * i, u = a === "y" ? o : o / n, d = a === "x" ? s : s / n;
492
+ this.setViewport({
493
+ xMin: c - u * r,
494
+ xMax: c + u * (1 - r),
495
+ yMin: l - d * i,
496
+ yMax: l + d * (1 - i)
497
+ });
498
+ }
499
+ toClip(e, t) {
500
+ return [e * this.xScale + this.xOffset, t * this.yScale + this.yOffset];
501
+ }
502
+ toScreen(e, t, n, r) {
503
+ return [(e + 1) * .5 * n, (1 - t) * .5 * r];
504
+ }
505
+ clone() {
506
+ let t = new e();
507
+ return t.setViewport(this.viewport), t;
508
+ }
509
+ static assertValidViewport(t) {
510
+ if (e.assertFinite("xMin", t.xMin), e.assertFinite("xMax", t.xMax), e.assertFinite("yMin", t.yMin), e.assertFinite("yMax", t.yMax), t.xMax <= t.xMin) throw RangeError("Camera2D requires xMax > xMin.");
511
+ if (t.yMax <= t.yMin) throw RangeError("Camera2D requires yMax > yMin.");
512
+ }
513
+ static assertFinite(e, t) {
514
+ if (!Number.isFinite(t)) throw RangeError(`Camera2D ${e} must be finite.`);
515
+ }
516
+ }, d = class {
517
+ camera;
518
+ constructor(e) {
519
+ this.camera = e;
520
+ }
521
+ getXTickValues(e, t = 10, n = []) {
522
+ return this.getTickValues(this.camera.xMin, this.camera.xMax, e, t, 80, n);
523
+ }
524
+ getYTickValues(e, t = 10, n = []) {
525
+ return this.getTickValues(this.camera.yMin, this.camera.yMax, e, t, 48, n);
526
+ }
527
+ formatValue(e) {
528
+ if (Math.abs(e) < 1e-12) return "0";
529
+ let t = Math.abs(e);
530
+ return t >= 1e6 || t < .001 ? e.toExponential(2) : t >= 100 ? e.toFixed(0) : t >= 10 ? e.toFixed(1) : e.toFixed(2);
531
+ }
532
+ getTickValues(e, t, n, r, i, a) {
533
+ if (a.length = 0, n <= 0 || r <= 0) return a;
534
+ let o = t - e;
535
+ if (!Number.isFinite(o) || o <= 0) return a;
536
+ let s = Math.max(2, Math.min(r, Math.floor(n / i))), c = this.niceStep(o / (s - 1)), l = Math.floor(e / c), u = Math.ceil(t / c);
537
+ for (let e = l; e <= u && a.length < r + 2; e++) a.push(this.normalizeTick(e * c, c));
538
+ return a;
539
+ }
540
+ niceStep(e) {
541
+ let t = 10 ** Math.floor(Math.log10(e)), n = e / t;
542
+ return n <= 1.5 ? t : n <= 3 ? 2 * t : n <= 7 ? 5 * t : 10 * t;
543
+ }
544
+ normalizeTick(e, t) {
545
+ let n = Math.max(0, -Math.floor(Math.log10(t)) + 2), r = Number(e.toFixed(n));
546
+ return Object.is(r, -0) ? 0 : r;
547
+ }
548
+ }, f = 16384, p = 64, m = class {
549
+ canvas;
550
+ options;
551
+ series = [];
552
+ camera;
553
+ axis;
554
+ renderer;
555
+ input;
556
+ rawLineBuffer;
557
+ rawLineData;
558
+ gridBuffer;
559
+ gridData;
560
+ gridStyle;
561
+ xTicks = [];
562
+ yTicks = [];
563
+ stats = {
564
+ fps: 0,
565
+ frameMs: 0,
566
+ pointsRendered: 0,
567
+ drawCalls: 0,
568
+ uploadBytes: 0,
569
+ renderMode: "none"
570
+ };
571
+ resizeObserver = null;
572
+ lastFrameAt = 0;
573
+ _rafId = 0;
574
+ constructor(e, t = {}) {
575
+ this.canvas = e, this.options = t, this.applyCanvasSize(), this.camera = new u(), this.axis = new d(this.camera), this.renderer = new o(new c(e)), this.input = new l(e, this.camera, t.viewportPolicy), this.rawLineData = new Float32Array(f * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.gridData = new Float32Array(p * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
576
+ color: t.gridStyle?.color ?? [
577
+ .22,
578
+ .3,
579
+ .44,
580
+ .45
581
+ ],
582
+ lineWidth: t.gridStyle?.lineWidth ?? 1
583
+ }, typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.resize()), this.resizeObserver.observe(this.canvas));
584
+ }
585
+ addSeries(e, t) {
586
+ let n = new i(e, {
587
+ color: t?.color ?? [
588
+ .3,
589
+ .6,
590
+ 1,
591
+ 1
592
+ ],
593
+ lineWidth: t?.lineWidth ?? 1
594
+ });
595
+ return this.series.push(n), n;
596
+ }
597
+ removeSeries(e) {
598
+ let t = this.series.indexOf(e);
599
+ return t === -1 ? !1 : (this.series.splice(t, 1), !0);
600
+ }
601
+ setViewport(e) {
602
+ this.camera.setViewport(e);
603
+ }
604
+ resize(e = globalThis.devicePixelRatio) {
605
+ let t = this.applyCanvasSize(e);
606
+ return t && this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height), t;
607
+ }
608
+ getFrameStats(e = {
609
+ fps: 0,
610
+ frameMs: 0,
611
+ pointsRendered: 0,
612
+ drawCalls: 0,
613
+ uploadBytes: 0,
614
+ renderMode: "none"
615
+ }) {
616
+ return e.fps = this.stats.fps, e.frameMs = this.stats.frameMs, e.pointsRendered = this.stats.pointsRendered, e.drawCalls = this.stats.drawCalls, e.uploadBytes = this.stats.uploadBytes, e.renderMode = this.stats.renderMode, e;
617
+ }
618
+ start() {
619
+ let e = () => {
620
+ this._rafId = requestAnimationFrame(e), this.render();
621
+ };
622
+ this._rafId = requestAnimationFrame(e);
623
+ }
624
+ stop() {
625
+ cancelAnimationFrame(this._rafId);
626
+ }
627
+ render() {
628
+ let e = performance.now();
629
+ this.lastFrameAt > 0 && (this.stats.fps = 1e3 / (e - this.lastFrameAt)), this.lastFrameAt = e, this.stats.pointsRendered = 0, this.stats.drawCalls = 0, this.stats.uploadBytes = 0, this.stats.renderMode = "none", this.options.viewportPolicy?.beforeRender?.(this.camera), this.renderer.clear(.08, .1, .16, 1);
630
+ let t = this.camera.viewport;
631
+ if (this.options.grid !== !1) {
632
+ let e = this.writeGridVertices(t);
633
+ e > 0 && (this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData), this.renderer.drawLines(this.gridBuffer, e, this.gridStyle, this.camera), this.stats.drawCalls++, this.stats.uploadBytes += this.gridData.byteLength);
634
+ }
635
+ for (let e of this.series) {
636
+ if (!e.visible) continue;
637
+ let n = e.visibleSampleCount(t) > f, r = n ? e.copyMinMaxVisible(t, this.rawLineData, Math.min(this.canvas.width, f >> 1)) : e.copyRawVisible(t, this.rawLineData, f);
638
+ r < 2 || (this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), n ? (this.renderer.drawMinMaxSegments(this.rawLineBuffer, r, e.style, this.camera), this.recordRenderMode("minmax")) : (this.renderer.drawLineStrip(this.rawLineBuffer, r, e.style, this.camera), this.recordRenderMode("raw")), this.stats.pointsRendered += r, this.stats.drawCalls++, this.stats.uploadBytes += this.rawLineData.byteLength);
639
+ }
640
+ this.stats.frameMs = performance.now() - e;
641
+ }
642
+ dispose() {
643
+ this.stop(), this.resizeObserver?.disconnect(), this.input.dispose(), this.renderer.dispose();
644
+ }
645
+ applyCanvasSize(e = globalThis.devicePixelRatio) {
646
+ let t = Number.isFinite(e) ? Math.max(1, e) : 1, n = Math.max(1, Math.floor(this.canvas.clientWidth * t)), r = Math.max(1, Math.floor(this.canvas.clientHeight * t));
647
+ return this.canvas.width === n && this.canvas.height === r ? !1 : (this.canvas.width = n, this.canvas.height = r, !0);
648
+ }
649
+ writeGridVertices(e) {
650
+ this.axis.getXTickValues(this.canvas.width, 12, this.xTicks), this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);
651
+ let t = 0;
652
+ for (let n of this.xTicks) {
653
+ if (t + 2 > p) return t;
654
+ this.gridData[t * 2] = n, this.gridData[t * 2 + 1] = e.yMin, t++, this.gridData[t * 2] = n, this.gridData[t * 2 + 1] = e.yMax, t++;
655
+ }
656
+ for (let n of this.yTicks) {
657
+ if (t + 2 > p) return t;
658
+ this.gridData[t * 2] = e.xMin, this.gridData[t * 2 + 1] = n, t++, this.gridData[t * 2] = e.xMax, this.gridData[t * 2 + 1] = n, t++;
659
+ }
660
+ return t;
661
+ }
662
+ recordRenderMode(e) {
663
+ this.stats.renderMode === "none" ? this.stats.renderMode = e : this.stats.renderMode !== e && (this.stats.renderMode = "mixed");
664
+ }
665
+ };
666
+ //#endregion
667
+ export { d as AxisController, u as Camera2D, m as Chart, r as MinMaxPyramid, t as RingBuffer, i as SeriesStore };
668
+
669
+ //# sourceMappingURL=index.js.map