@data-vision/interactive-chart 0.0.8

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 (47) hide show
  1. package/README.md +144 -0
  2. package/build/bar.cjs +1 -0
  3. package/build/bar.d.ts +10 -0
  4. package/build/bar.js +44 -0
  5. package/build/base/chart.d.ts +137 -0
  6. package/build/base/color.d.ts +18 -0
  7. package/build/base/dragable.d.ts +29 -0
  8. package/build/base/field.d.ts +18 -0
  9. package/build/base/index.d.ts +5 -0
  10. package/build/base/point.d.ts +15 -0
  11. package/build/brush/brush.d.ts +49 -0
  12. package/build/brush/crop.d.ts +12 -0
  13. package/build/brush/index.d.ts +2 -0
  14. package/build/brush/range.d.ts +6 -0
  15. package/build/brush/thumb.d.ts +6 -0
  16. package/build/chart-Cj4Fiwnb.js +965 -0
  17. package/build/chart-Dr9ZOezr.cjs +1 -0
  18. package/build/dataset-Bv37sY1L.js +18 -0
  19. package/build/dataset-D4KLCpTU.cjs +1 -0
  20. package/build/heatmap-BlMqliH5.cjs +1 -0
  21. package/build/heatmap-Br4YjrBg.js +859 -0
  22. package/build/heatmap.cjs +1 -0
  23. package/build/heatmap.d.ts +91 -0
  24. package/build/heatmap.js +5 -0
  25. package/build/index.cjs +1 -0
  26. package/build/index.d.ts +7 -0
  27. package/build/index.js +20 -0
  28. package/build/legend/index.d.ts +1 -0
  29. package/build/legend/legend.d.ts +20 -0
  30. package/build/line.cjs +1 -0
  31. package/build/line.d.ts +11 -0
  32. package/build/line.js +23 -0
  33. package/build/otdr.cjs +1 -0
  34. package/build/otdr.d.ts +186 -0
  35. package/build/otdr.js +417 -0
  36. package/build/tooltip/crosshair.d.ts +20 -0
  37. package/build/tooltip/index.d.ts +2 -0
  38. package/build/tooltip/tooltip.d.ts +12 -0
  39. package/build/type.d.ts +78 -0
  40. package/build/util/dataset.d.ts +6 -0
  41. package/build/util/date.d.ts +1 -0
  42. package/build/util/env.d.ts +15 -0
  43. package/build/util/event.d.ts +6 -0
  44. package/build/util/index.d.ts +6 -0
  45. package/build/util/numeric.d.ts +26 -0
  46. package/build/util/style.d.ts +3 -0
  47. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ <p align="center">
2
+ <img width="160" src="https://bytebucket.org/icefee/interactive-chart/raw/aef189e3e4799bd815ad126d97c54dd76f8fcc2a/assets/logo.png" alt="interactive chart">
3
+ <br/>
4
+ A interactive chart library(0 dependence)
5
+ </p>
6
+
7
+ ### Features
8
+
9
+ * Built in interaction for mouse and touch, including mouse wheel, crop, pan, zoom
10
+ * High-performance, over 100,000 data points with 60fps render
11
+ * Easy to use, no framework limit
12
+ * Optimize for different screen scaling ratios
13
+ * Rich customization options
14
+
15
+ ### Online Demo
16
+
17
+ [Online Demo](https://interactive-chart-vision.netlify.app/)
18
+
19
+ ### Install
20
+
21
+ ```bash
22
+ // npm
23
+ npm install @data-vision/interactive-chart
24
+
25
+ // yarn
26
+ yarn add @data-vision/interactive-chart
27
+
28
+ // pnpm
29
+ pnpm add @data-vision/interactive-chart
30
+
31
+ // bun
32
+ bun add @data-vision/interactive-chart
33
+ ```
34
+
35
+ ### Support Charts
36
+
37
+ Currently supports 3 types of charts:
38
+
39
+ * Line chart
40
+
41
+ ![<img src="./assets/line.png" alt="line chart">](https://bytebucket.org/icefee/interactive-chart/raw/aef189e3e4799bd815ad126d97c54dd76f8fcc2a/assets/line.png)
42
+
43
+ ```javascript
44
+ // import the library
45
+ import Line from '@data-vision/interactive-chart/line'
46
+
47
+ // get the element for mounting chart instance
48
+ const container = document.querySelector('#chart-line')
49
+
50
+ // create chart instance
51
+ const lineChart = new Line(contaner)
52
+
53
+ // 100,000 data points
54
+ var DATA_COUNT = 100_000
55
+
56
+ // create random data
57
+ const randomData = Array.from(
58
+ { length: DATA_COUNT },
59
+ (_, t) => Math.floor(Math.sin(t) * Math.random() * 20)
60
+ )
61
+
62
+ // set chart data
63
+ lineChart.setData([
64
+ {
65
+ color: 'hsl(200 100% 50%)',
66
+ data: randomData
67
+ },
68
+ {
69
+ color: 'hsl(0 100% 50%)',
70
+ data: randomData
71
+ }
72
+ ])
73
+
74
+ ```
75
+
76
+ * Bar chart
77
+
78
+ ![<img src="./assets/bar.png" alt="bar chart">](https://bytebucket.org/icefee/interactive-chart/raw/aef189e3e4799bd815ad126d97c54dd76f8fcc2a/assets/bar.png)
79
+
80
+ ```javascript
81
+ // import the library
82
+ import Bar from '@data-vision/interactive-chart/bar'
83
+
84
+ // get the element for mounting chart instance
85
+ const container = document.querySelector('#chart-bar')
86
+
87
+ // create chart instance
88
+ const barChart = new Bar(contaner)
89
+
90
+ // 100,000 data points
91
+ var DATA_COUNT = 100_000
92
+
93
+ // create random data
94
+ const randomData = Array.from(
95
+ { length: DATA_COUNT },
96
+ (_, t) => Math.floor(Math.sin(t) * Math.random() * 20)
97
+ )
98
+
99
+ // set chart data
100
+ barChart.setData(
101
+ {
102
+ color: ['hsl(200 100% 50%)', 'hsl(0 100% 50%)'],
103
+ data: randomData
104
+ }
105
+ )
106
+
107
+ ```
108
+
109
+ * Heatmap
110
+
111
+ ![<img src="./assets/heatmap.png" alt="heatmap">](https://bytebucket.org/icefee/interactive-chart/raw/aef189e3e4799bd815ad126d97c54dd76f8fcc2a/assets/heatmap.png)
112
+
113
+ ```javascript
114
+ // import the library
115
+ import HeatMap from '@data-vision/interactive-chart/heatmap'
116
+
117
+ // get the element for mounting chart instance
118
+ const container = document.querySelector('#chart-heat')
119
+
120
+ // set text painting style
121
+ HeatMap.config.textColor = '#ccc'
122
+ // set max data cache size
123
+ HeatMap.config.maxCacheSize = 200
124
+
125
+ // create chart instance
126
+ const barChart = new HeatMap(contaner)
127
+
128
+ // 100,000 data points
129
+ var DATA_COUNT = 100_000
130
+
131
+ let i = 0
132
+ setInterval(
133
+ () => {
134
+ // loop make real data
135
+ const data = Uint8ClampedArray.from({
136
+ length: DATA_COUNT
137
+ }, (_, j) => (j * 32 + i) % 256)
138
+ heatMap.setData(data)
139
+ i += 8
140
+ },
141
+ 10
142
+ )
143
+
144
+ ```
package/build/bar.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const M=require("./chart-Dr9ZOezr.cjs"),G=require("./dataset-D4KLCpTU.cjs");class g extends M.Chart{draw(l){const{data:T,xMin:u,xMax:b,yMin:q,scale:i,grid:o,rect:f,sample:w}=this,n=T;if(n){const{precision:S=1,color:h,data:m}=n,{end:I,loop:j}=G.fitDataset(m,S,[u,b]),d=M.getMin([...m]),x=M.getMax([...m]);if(l.save(),d<1/0&&x>-1/0){const v=q/i.y,r=f.y+v,C=S/i.x;if(typeof h=="string")l.fillStyle=h;else if(h.length<2){const[t]=n.color;t&&(l.fillStyle=t)}else{let t=Math.min(r-d/i.y,f.y),s=Math.max(r-x/i.y,o.top);d===x&&(d>0?t=r:(t=s,s=r));const a=l.createLinearGradient(0,t,0,s);for(let e=0,p=n.color,c=p.length,y=1/(c-1);e<c;e++)a.addColorStop(e*y,p[e]);l.fillStyle=a}j(i.x,(t,s)=>{let a=o.left-u/i.x+C*(t+s*.1),e=C*s*.8;a<o.left?(e=Math.max(0,e-(o.left-a)),a=o.left):a+e>f.x&&(e=Math.max(0,f.x-a));const c=w(n.data.slice(t,Math.min(t+s,I+1)),g.config.dataSampleMethod)/i.y,y=r-c,D=c-Math.max(0,o.top-y)-Math.max(0,v);l.fillRect(a,Math.max(y,o.top),e,D)}),l.restore()}}}}exports.ControlType=M.ControlType;exports.default=g;
package/build/bar.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { Chart } from './base';
2
+ import type { Dataset } from './type';
3
+ export { ControlType, type Dataset } from './type';
4
+ export interface BarDataSet extends Dataset {
5
+ color: string | string[];
6
+ }
7
+ declare class Bar extends Chart<BarDataSet> {
8
+ protected draw(context: CanvasRenderingContext2D): void;
9
+ }
10
+ export default Bar;
package/build/bar.js ADDED
@@ -0,0 +1,44 @@
1
+ import { C as T, g as b, c as j } from "./chart-Cj4Fiwnb.js";
2
+ import { a as E } from "./chart-Cj4Fiwnb.js";
3
+ import { f as k } from "./dataset-Bv37sY1L.js";
4
+ class v extends T {
5
+ // @override
6
+ draw(s) {
7
+ const { data: w, xMin: p, xMax: I, yMin: u, scale: l, grid: o, rect: c, sample: D } = this, n = w;
8
+ if (n) {
9
+ const { precision: g = 1, color: d, data: h } = n, { end: G, loop: L } = k(h, g, [p, I]), m = b([...h]), x = j([...h]);
10
+ if (s.save(), m < 1 / 0 && x > -1 / 0) {
11
+ const S = u / l.y, f = c.y + S, C = g / l.x;
12
+ if (typeof d == "string")
13
+ s.fillStyle = d;
14
+ else if (d.length < 2) {
15
+ const [t] = n.color;
16
+ t && (s.fillStyle = t);
17
+ } else {
18
+ let t = Math.min(f - m / l.y, c.y), i = Math.max(f - x / l.y, o.top);
19
+ m === x && (m > 0 ? t = f : (t = i, i = f));
20
+ const e = s.createLinearGradient(
21
+ 0,
22
+ t,
23
+ // Math.min(t, rect.y),
24
+ 0,
25
+ i
26
+ );
27
+ for (let a = 0, M = n.color, r = M.length, y = 1 / (r - 1); a < r; a++)
28
+ e.addColorStop(a * y, M[a]);
29
+ s.fillStyle = e;
30
+ }
31
+ L(l.x, (t, i) => {
32
+ let e = o.left - p / l.x + C * (t + i * 0.1), a = C * i * 0.8;
33
+ e < o.left ? (a = Math.max(0, a - (o.left - e)), e = o.left) : e + a > c.x && (a = Math.max(0, c.x - e));
34
+ const r = D(n.data.slice(t, Math.min(t + i, G + 1)), v.config.dataSampleMethod) / l.y, y = f - r, R = r - Math.max(0, o.top - y) - Math.max(0, S);
35
+ s.fillRect(e, Math.max(y, o.top), a, R);
36
+ }), s.restore();
37
+ }
38
+ }
39
+ }
40
+ }
41
+ export {
42
+ E as ControlType,
43
+ v as default
44
+ };
@@ -0,0 +1,137 @@
1
+ import { Dragable } from './dragable';
2
+ import { Point } from './point';
3
+ import { ControlType, Edge, type DragUpdateContext, type CSSProperties, type DataSampleMethod, type RangeValue, type Offset, type InteractEvent } from '../type';
4
+ import { Dpr } from '../util';
5
+ interface TooltipLabelRender {
6
+ (value: number, unit: string): string;
7
+ }
8
+ interface FetureConfig {
9
+ enabled?: boolean;
10
+ style?: CSSProperties;
11
+ }
12
+ interface TooltipConfig extends FetureConfig {
13
+ xLabel?: TooltipLabelRender;
14
+ yLabel?: TooltipLabelRender;
15
+ }
16
+ interface CrosshairConfig extends FetureConfig {
17
+ }
18
+ export interface Config {
19
+ xMin: number;
20
+ xMax: number;
21
+ yMin: number;
22
+ yMax: number;
23
+ grid: Edge;
24
+ controlType: ControlType;
25
+ xUnit: string;
26
+ yUnit: string;
27
+ xMinScale: number;
28
+ xMaxScale: number;
29
+ yMinScale: number;
30
+ yMaxScale: number;
31
+ responsiveScale: boolean;
32
+ gridColor: string;
33
+ textColor: string;
34
+ accentColor: string;
35
+ fontSize: number;
36
+ cropStyle: CSSProperties;
37
+ tooltip: TooltipConfig;
38
+ crosshair: CrosshairConfig;
39
+ axisXScaleOffset: Offset;
40
+ axisYScaleOffset: Offset;
41
+ xLimit: RangeValue;
42
+ yLimit: RangeValue;
43
+ wheelZoom: boolean;
44
+ dataSampleMethod: DataSampleMethod;
45
+ }
46
+ declare class Chart<T> extends Dragable {
47
+ private root;
48
+ private resizeObserver;
49
+ protected dpr: Dpr;
50
+ private canvasContainer;
51
+ private canvas;
52
+ static version: string;
53
+ static config: Config;
54
+ protected width: number;
55
+ protected height: number;
56
+ protected context: CanvasRenderingContext2D;
57
+ protected xMin: number;
58
+ protected xMax: number;
59
+ protected yMin: number;
60
+ protected yMax: number;
61
+ protected data: T | null;
62
+ private tooltip;
63
+ private crosshair;
64
+ private crop;
65
+ private controlType;
66
+ private prevControlType;
67
+ private wheelZoom;
68
+ private cropOrigin;
69
+ private cropOffset;
70
+ private inCrop;
71
+ protected grid: Edge;
72
+ private xMinScale;
73
+ private xMaxScale;
74
+ private yMinScale;
75
+ private yMaxScale;
76
+ protected xUnit: string;
77
+ protected yUnit: string;
78
+ private raf;
79
+ protected shouldUpdate: boolean;
80
+ protected snapshot: ImageData | null;
81
+ protected useSnapshot: boolean;
82
+ constructor(root: HTMLElement);
83
+ get $root(): HTMLElement;
84
+ get $canvas(): HTMLCanvasElement;
85
+ setData(data: T): void;
86
+ setControlType(controlType: ControlType): void;
87
+ protected draw(_context: CanvasRenderingContext2D): void;
88
+ protected drawSnapshot(_context: CanvasRenderingContext2D): void;
89
+ protected drawAnnotations(_context: CanvasRenderingContext2D): void;
90
+ protected sample(data: Iterable<number>, method: DataSampleMethod): number;
91
+ private updateDraw;
92
+ private drawVerticalGrid;
93
+ private drawAxisX;
94
+ private drawScaleX;
95
+ private drawHorizontalGrid;
96
+ private drawAxisY;
97
+ private drawScaleY;
98
+ private getScaleText;
99
+ private setRoot;
100
+ protected get cursor(): "move" | "crosshair" | "zoom-in" | "default";
101
+ protected setCursor(cursor?: string): void;
102
+ private initCanvas;
103
+ protected get scaleGrid(): Edge;
104
+ protected get bounds(): {
105
+ x: [number, number];
106
+ y: [number, number];
107
+ };
108
+ protected get rectBounds(): Edge;
109
+ protected get rect(): Point;
110
+ protected get drawWidth(): number;
111
+ protected get drawHeight(): number;
112
+ private updateCanvas;
113
+ private onDprChange;
114
+ setUnit(xUnit?: string | null, yUnit?: string | null): void;
115
+ protected getOffset(event: MouseEvent | TouchEvent): Point;
116
+ protected onMouseMove(event: MouseEvent): void;
117
+ private onMouseLeave;
118
+ private onWheel;
119
+ protected onDblClick(): void;
120
+ private onResize;
121
+ protected get scale(): Point;
122
+ protected getRatioOffset(ratio: number): Offset;
123
+ private setMoveBounds;
124
+ protected onStart(event: InteractEvent): void;
125
+ protected onUpdate({ value, delta }: DragUpdateContext<number>): number;
126
+ protected onEnd(event: InteractEvent): void;
127
+ private get cropRange();
128
+ private updateCrop;
129
+ setCenter(offset: Offset): void;
130
+ setCenter(range: RangeValue): void;
131
+ setCenter(x: number, y: number): void;
132
+ setBounds(xMin?: number, xMax?: number, yMin?: number, yMax?: number): void;
133
+ resize(): void;
134
+ reset(beforeUpdate?: VoidFunction): void;
135
+ dispose(): void;
136
+ }
137
+ export default Chart;
@@ -0,0 +1,18 @@
1
+ export declare class RgbColor {
2
+ r: number;
3
+ g: number;
4
+ b: number;
5
+ constructor(r: number, g: number, b: number);
6
+ private getIntervalValue;
7
+ interval(color: RgbColor, offset: number): RgbColor;
8
+ private toHexValue;
9
+ toHex(): string;
10
+ toString(): string;
11
+ }
12
+ export declare class Gradient {
13
+ colors: RgbColor[];
14
+ constructor(colors: RgbColor[]);
15
+ addColor(color: RgbColor): void;
16
+ toString(): string[];
17
+ getOffsetColor(offset: number): RgbColor;
18
+ }
@@ -0,0 +1,29 @@
1
+ import { Field } from './field';
2
+ import type { InteractEvent, DragableContext, DragableOption, DragUpdateContext } from '../type';
3
+ export declare class Dragable<T = number> extends Field<T> {
4
+ private element;
5
+ protected dragging: boolean;
6
+ private origin;
7
+ constructor(element: HTMLElement, initValue: T);
8
+ set value(value: T);
9
+ private onPointerDown;
10
+ protected getStyle(_context: DragableContext<T>): string;
11
+ protected onUpdate({ value }: DragUpdateContext<T>): T;
12
+ protected isEqual(prev: T, current: T): boolean;
13
+ protected onStart(_event: InteractEvent): void;
14
+ protected onEnd(_event: InteractEvent): void;
15
+ resize(): void;
16
+ private onPointerMove;
17
+ private onPointerUp;
18
+ dispose(): void;
19
+ }
20
+ export declare class DragableThumb<T = number> extends Dragable<T> {
21
+ private root;
22
+ private container;
23
+ protected option: DragableOption<T>;
24
+ constructor(root: HTMLElement, option: DragableOption<T>);
25
+ protected onStart(event: MouseEvent): void;
26
+ protected onUpdate(context: DragUpdateContext<T>): T;
27
+ protected onEnd(event: DragEvent): void;
28
+ dispose(): void;
29
+ }
@@ -0,0 +1,18 @@
1
+ import type { ValueChangeListener } from '../type';
2
+ declare abstract class StateField<T> {
3
+ abstract get value(): T;
4
+ abstract set value(value: T);
5
+ abstract addEventListener(listener: ValueChangeListener<T>): void;
6
+ abstract removeEventListener(listener: ValueChangeListener<T>): void;
7
+ }
8
+ export declare class Field<T> implements StateField<T> {
9
+ protected _value: T;
10
+ protected listeners: ValueChangeListener<T>[];
11
+ constructor(initValue: T);
12
+ get value(): T;
13
+ set value(value: T);
14
+ addEventListener(listener: ValueChangeListener<T>): void;
15
+ removeEventListener(listener: ValueChangeListener<T>): void;
16
+ protected emitChangeEvent(): void;
17
+ }
18
+ export {};
@@ -0,0 +1,5 @@
1
+ export * from './color';
2
+ export * from './dragable';
3
+ export * from './point';
4
+ export * from './field';
5
+ export { default as Chart, type Config } from './chart';
@@ -0,0 +1,15 @@
1
+ import type { Offset } from '../type';
2
+ export declare class Point implements Offset {
3
+ x: number;
4
+ y: number;
5
+ constructor(x: number, y: number);
6
+ add(p: Offset): Point;
7
+ add(s: number): Point;
8
+ sub(p: Offset): Point;
9
+ sub(s: number): Point;
10
+ multiply(p: Offset): Point;
11
+ multiply(s: number): Point;
12
+ divide(p: Offset): Point;
13
+ divide(s: number): Point;
14
+ static origin(): Point;
15
+ }
@@ -0,0 +1,49 @@
1
+ import { Field } from '../base';
2
+ import type { DragableContext, RangeValue, CSSProperties, DragUpdateContext } from '../type';
3
+ interface BrushLabelInputOption {
4
+ from(value: number): number;
5
+ to(value: number): number;
6
+ }
7
+ interface BrushOption {
8
+ initValue?: RangeValue;
9
+ labelInput?: BrushLabelInputOption;
10
+ style?: CSSProperties;
11
+ }
12
+ export declare class Brush extends Field<RangeValue> {
13
+ private root;
14
+ container: HTMLElement;
15
+ protected thumbSize: number;
16
+ private startThumb;
17
+ private endThumb;
18
+ private range;
19
+ private resizeObserver;
20
+ protected width: number;
21
+ protected height: number;
22
+ private brushLabel;
23
+ private labelInput;
24
+ constructor(root: HTMLElement, option?: BrushOption);
25
+ get value(): RangeValue;
26
+ set value([s, e]: RangeValue);
27
+ private getFormatLabel;
28
+ updateBrushLabelInput(): void;
29
+ private initBrushLabelInput;
30
+ private createLabelInput;
31
+ private createThumb;
32
+ protected emitChangeEvent(): void;
33
+ protected getRangeStyle({ value: [s, e] }: DragableContext<RangeValue>): string;
34
+ private createRange;
35
+ private updateRangeValue;
36
+ private onStartValueChange;
37
+ private onStartLabelInputChange;
38
+ private onEndValueChange;
39
+ private onEndLabelInputChange;
40
+ private onRangeValueChange;
41
+ private get trackWidth();
42
+ private onResize;
43
+ protected onUpdate({ delta }: DragUpdateContext<number>): number;
44
+ protected getStyle({ value }: DragableContext<number>): string;
45
+ private createContainer;
46
+ setStyle(style: CSSProperties): void;
47
+ dispose(): void;
48
+ }
49
+ export {};
@@ -0,0 +1,12 @@
1
+ import { CSSProperties, Edge } from '../type';
2
+ export declare class Crop {
3
+ private root;
4
+ private container;
5
+ private style;
6
+ private inheritStyle?;
7
+ constructor(root: HTMLElement, style?: CSSProperties);
8
+ private setContainer;
9
+ update({ top, right, bottom, left }: Edge): void;
10
+ hide(): void;
11
+ dispose(): void;
12
+ }
@@ -0,0 +1,2 @@
1
+ export * from './brush';
2
+ export * from './crop';
@@ -0,0 +1,6 @@
1
+ import { DragableThumb } from '../base';
2
+ import type { RangeValue, DragableOption, DragUpdateContext } from '../type';
3
+ export declare class BrushRange extends DragableThumb<RangeValue> {
4
+ constructor(root: HTMLElement, option: DragableOption<RangeValue>);
5
+ onUpdate(context: DragUpdateContext<RangeValue>): RangeValue;
6
+ }
@@ -0,0 +1,6 @@
1
+ import { DragableThumb } from '../base';
2
+ import type { DragableOption, DragUpdateContext } from '../type';
3
+ export declare class Thumb extends DragableThumb<number> {
4
+ constructor(root: HTMLElement, option: DragableOption<number>);
5
+ onUpdate(context: DragUpdateContext<number>): number;
6
+ }