hyperprop-charting-library 0.1.5 → 0.1.7
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.
- package/dist/index.cjs +75 -5
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +75 -5
- package/docs/API.md +12 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -51,7 +51,13 @@ var DEFAULT_WATERMARK_OPTIONS = {
|
|
|
51
51
|
opacity: 0.14,
|
|
52
52
|
fontSize: 92,
|
|
53
53
|
fontWeight: 700,
|
|
54
|
-
thickness: 0
|
|
54
|
+
thickness: 0,
|
|
55
|
+
imageSrc: "",
|
|
56
|
+
imageScale: 1,
|
|
57
|
+
imageMaxWidthRatio: 0.42,
|
|
58
|
+
imageMaxHeightRatio: 0.3,
|
|
59
|
+
imageTintColor: "",
|
|
60
|
+
imageTintOpacity: 1
|
|
55
61
|
};
|
|
56
62
|
var DEFAULT_PRICE_LINE_OPTIONS = {
|
|
57
63
|
visible: true,
|
|
@@ -101,6 +107,10 @@ var DEFAULT_OPTIONS = {
|
|
|
101
107
|
axisColor: "#7f8289",
|
|
102
108
|
axis: DEFAULT_AXIS_OPTIONS,
|
|
103
109
|
priceDecimals: 2,
|
|
110
|
+
initialViewport: "latest",
|
|
111
|
+
initialVisibleBars: 60,
|
|
112
|
+
rightEdgePaddingBars: 2,
|
|
113
|
+
preserveViewportOnDataUpdate: true,
|
|
104
114
|
upColor: "#2fb171",
|
|
105
115
|
downColor: "#d35a5a",
|
|
106
116
|
gridColor: "#252932",
|
|
@@ -178,6 +188,9 @@ function createChart(element, options = {}) {
|
|
|
178
188
|
let yMaxOverride = null;
|
|
179
189
|
let autoYMin = null;
|
|
180
190
|
let autoYMax = null;
|
|
191
|
+
let watermarkImageSrc = null;
|
|
192
|
+
let watermarkImage = null;
|
|
193
|
+
let watermarkImageReady = false;
|
|
181
194
|
let drawState = null;
|
|
182
195
|
let orderDragState = null;
|
|
183
196
|
let actionDragState = null;
|
|
@@ -196,13 +209,36 @@ function createChart(element, options = {}) {
|
|
|
196
209
|
element.appendChild(canvas);
|
|
197
210
|
const margin = { top: 16, right: 72, bottom: 34, left: 12 };
|
|
198
211
|
const maxPanBars = 1e6;
|
|
199
|
-
const rightEdgePaddingBars =
|
|
212
|
+
const rightEdgePaddingBars = Math.max(0, mergedOptions.rightEdgePaddingBars);
|
|
200
213
|
const getPixelRatio = () => {
|
|
201
214
|
if (typeof window === "undefined") {
|
|
202
215
|
return 1;
|
|
203
216
|
}
|
|
204
217
|
return Math.max(1, window.devicePixelRatio || 1);
|
|
205
218
|
};
|
|
219
|
+
const ensureWatermarkImage = (src) => {
|
|
220
|
+
if (src === watermarkImageSrc) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
watermarkImageSrc = src;
|
|
224
|
+
watermarkImageReady = false;
|
|
225
|
+
watermarkImage = null;
|
|
226
|
+
if (!src) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const image = new Image();
|
|
230
|
+
image.crossOrigin = "anonymous";
|
|
231
|
+
image.onload = () => {
|
|
232
|
+
watermarkImage = image;
|
|
233
|
+
watermarkImageReady = true;
|
|
234
|
+
draw();
|
|
235
|
+
};
|
|
236
|
+
image.onerror = () => {
|
|
237
|
+
watermarkImage = null;
|
|
238
|
+
watermarkImageReady = false;
|
|
239
|
+
};
|
|
240
|
+
image.src = src;
|
|
241
|
+
};
|
|
206
242
|
const crisp = (value) => Math.round(value) + 0.5;
|
|
207
243
|
const clamp = (value, min, max) => {
|
|
208
244
|
return Math.min(max, Math.max(min, value));
|
|
@@ -226,8 +262,13 @@ function createChart(element, options = {}) {
|
|
|
226
262
|
xSpan = 60;
|
|
227
263
|
return;
|
|
228
264
|
}
|
|
229
|
-
|
|
230
|
-
|
|
265
|
+
const requestedVisibleBars = Math.max(5, Math.floor(mergedOptions.initialVisibleBars));
|
|
266
|
+
xSpan = Math.min(requestedVisibleBars, Math.max(5, count));
|
|
267
|
+
if (mergedOptions.initialViewport === "center") {
|
|
268
|
+
xCenter = count / 2;
|
|
269
|
+
} else {
|
|
270
|
+
xCenter = count - xSpan / 2 + rightEdgePaddingBars;
|
|
271
|
+
}
|
|
231
272
|
clampXViewport();
|
|
232
273
|
};
|
|
233
274
|
const getYBounds = () => {
|
|
@@ -746,6 +787,31 @@ function createChart(element, options = {}) {
|
|
|
746
787
|
const yFromPrice = (price) => {
|
|
747
788
|
return chartBottom - (price - yMin) / yRange * chartHeight;
|
|
748
789
|
};
|
|
790
|
+
if (watermark.visible && watermark.imageSrc.trim().length > 0) {
|
|
791
|
+
ensureWatermarkImage(watermark.imageSrc.trim());
|
|
792
|
+
if (watermarkImageReady && watermarkImage) {
|
|
793
|
+
const maxW = chartWidth * clamp(watermark.imageMaxWidthRatio, 0.05, 1);
|
|
794
|
+
const maxH = chartHeight * clamp(watermark.imageMaxHeightRatio, 0.05, 1);
|
|
795
|
+
const naturalW = Math.max(1, watermarkImage.naturalWidth || watermarkImage.width);
|
|
796
|
+
const naturalH = Math.max(1, watermarkImage.naturalHeight || watermarkImage.height);
|
|
797
|
+
const containScale = Math.min(maxW / naturalW, maxH / naturalH);
|
|
798
|
+
const scale = Math.max(0.05, containScale * Math.max(0.05, watermark.imageScale));
|
|
799
|
+
const drawW = naturalW * scale;
|
|
800
|
+
const drawH = naturalH * scale;
|
|
801
|
+
const drawX = chartLeft + (chartWidth - drawW) / 2;
|
|
802
|
+
const drawY = chartTop + (chartHeight - drawH) / 2;
|
|
803
|
+
ctx.save();
|
|
804
|
+
ctx.globalAlpha = clamp(watermark.opacity, 0, 1);
|
|
805
|
+
ctx.drawImage(watermarkImage, drawX, drawY, drawW, drawH);
|
|
806
|
+
if (watermark.imageTintColor.trim().length > 0) {
|
|
807
|
+
ctx.globalCompositeOperation = "source-atop";
|
|
808
|
+
ctx.globalAlpha = clamp(watermark.opacity, 0, 1) * clamp(watermark.imageTintOpacity, 0, 1);
|
|
809
|
+
ctx.fillStyle = watermark.imageTintColor;
|
|
810
|
+
ctx.fillRect(drawX, drawY, drawW, drawH);
|
|
811
|
+
}
|
|
812
|
+
ctx.restore();
|
|
813
|
+
}
|
|
814
|
+
}
|
|
749
815
|
if (watermark.visible && watermark.text.trim().length > 0) {
|
|
750
816
|
ctx.save();
|
|
751
817
|
ctx.globalAlpha = clamp(watermark.opacity, 0, 1);
|
|
@@ -1370,7 +1436,11 @@ function createChart(element, options = {}) {
|
|
|
1370
1436
|
autoYMin = null;
|
|
1371
1437
|
autoYMax = null;
|
|
1372
1438
|
} else {
|
|
1373
|
-
|
|
1439
|
+
if (mergedOptions.preserveViewportOnDataUpdate) {
|
|
1440
|
+
clampXViewport();
|
|
1441
|
+
} else {
|
|
1442
|
+
fitXViewport();
|
|
1443
|
+
}
|
|
1374
1444
|
}
|
|
1375
1445
|
draw();
|
|
1376
1446
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -5,6 +5,10 @@ interface ChartOptions {
|
|
|
5
5
|
axisColor?: string;
|
|
6
6
|
axis?: AxisOptions;
|
|
7
7
|
priceDecimals?: number;
|
|
8
|
+
initialViewport?: "latest" | "center";
|
|
9
|
+
initialVisibleBars?: number;
|
|
10
|
+
rightEdgePaddingBars?: number;
|
|
11
|
+
preserveViewportOnDataUpdate?: boolean;
|
|
8
12
|
upColor?: string;
|
|
9
13
|
downColor?: string;
|
|
10
14
|
gridColor?: string;
|
|
@@ -52,6 +56,12 @@ interface WatermarkOptions {
|
|
|
52
56
|
fontSize?: number;
|
|
53
57
|
fontWeight?: number | string;
|
|
54
58
|
thickness?: number;
|
|
59
|
+
imageSrc?: string;
|
|
60
|
+
imageScale?: number;
|
|
61
|
+
imageMaxWidthRatio?: number;
|
|
62
|
+
imageMaxHeightRatio?: number;
|
|
63
|
+
imageTintColor?: string;
|
|
64
|
+
imageTintOpacity?: number;
|
|
55
65
|
}
|
|
56
66
|
interface PriceLineOptions {
|
|
57
67
|
id?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ interface ChartOptions {
|
|
|
5
5
|
axisColor?: string;
|
|
6
6
|
axis?: AxisOptions;
|
|
7
7
|
priceDecimals?: number;
|
|
8
|
+
initialViewport?: "latest" | "center";
|
|
9
|
+
initialVisibleBars?: number;
|
|
10
|
+
rightEdgePaddingBars?: number;
|
|
11
|
+
preserveViewportOnDataUpdate?: boolean;
|
|
8
12
|
upColor?: string;
|
|
9
13
|
downColor?: string;
|
|
10
14
|
gridColor?: string;
|
|
@@ -52,6 +56,12 @@ interface WatermarkOptions {
|
|
|
52
56
|
fontSize?: number;
|
|
53
57
|
fontWeight?: number | string;
|
|
54
58
|
thickness?: number;
|
|
59
|
+
imageSrc?: string;
|
|
60
|
+
imageScale?: number;
|
|
61
|
+
imageMaxWidthRatio?: number;
|
|
62
|
+
imageMaxHeightRatio?: number;
|
|
63
|
+
imageTintColor?: string;
|
|
64
|
+
imageTintOpacity?: number;
|
|
55
65
|
}
|
|
56
66
|
interface PriceLineOptions {
|
|
57
67
|
id?: string;
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,13 @@ var DEFAULT_WATERMARK_OPTIONS = {
|
|
|
27
27
|
opacity: 0.14,
|
|
28
28
|
fontSize: 92,
|
|
29
29
|
fontWeight: 700,
|
|
30
|
-
thickness: 0
|
|
30
|
+
thickness: 0,
|
|
31
|
+
imageSrc: "",
|
|
32
|
+
imageScale: 1,
|
|
33
|
+
imageMaxWidthRatio: 0.42,
|
|
34
|
+
imageMaxHeightRatio: 0.3,
|
|
35
|
+
imageTintColor: "",
|
|
36
|
+
imageTintOpacity: 1
|
|
31
37
|
};
|
|
32
38
|
var DEFAULT_PRICE_LINE_OPTIONS = {
|
|
33
39
|
visible: true,
|
|
@@ -77,6 +83,10 @@ var DEFAULT_OPTIONS = {
|
|
|
77
83
|
axisColor: "#7f8289",
|
|
78
84
|
axis: DEFAULT_AXIS_OPTIONS,
|
|
79
85
|
priceDecimals: 2,
|
|
86
|
+
initialViewport: "latest",
|
|
87
|
+
initialVisibleBars: 60,
|
|
88
|
+
rightEdgePaddingBars: 2,
|
|
89
|
+
preserveViewportOnDataUpdate: true,
|
|
80
90
|
upColor: "#2fb171",
|
|
81
91
|
downColor: "#d35a5a",
|
|
82
92
|
gridColor: "#252932",
|
|
@@ -154,6 +164,9 @@ function createChart(element, options = {}) {
|
|
|
154
164
|
let yMaxOverride = null;
|
|
155
165
|
let autoYMin = null;
|
|
156
166
|
let autoYMax = null;
|
|
167
|
+
let watermarkImageSrc = null;
|
|
168
|
+
let watermarkImage = null;
|
|
169
|
+
let watermarkImageReady = false;
|
|
157
170
|
let drawState = null;
|
|
158
171
|
let orderDragState = null;
|
|
159
172
|
let actionDragState = null;
|
|
@@ -172,13 +185,36 @@ function createChart(element, options = {}) {
|
|
|
172
185
|
element.appendChild(canvas);
|
|
173
186
|
const margin = { top: 16, right: 72, bottom: 34, left: 12 };
|
|
174
187
|
const maxPanBars = 1e6;
|
|
175
|
-
const rightEdgePaddingBars =
|
|
188
|
+
const rightEdgePaddingBars = Math.max(0, mergedOptions.rightEdgePaddingBars);
|
|
176
189
|
const getPixelRatio = () => {
|
|
177
190
|
if (typeof window === "undefined") {
|
|
178
191
|
return 1;
|
|
179
192
|
}
|
|
180
193
|
return Math.max(1, window.devicePixelRatio || 1);
|
|
181
194
|
};
|
|
195
|
+
const ensureWatermarkImage = (src) => {
|
|
196
|
+
if (src === watermarkImageSrc) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
watermarkImageSrc = src;
|
|
200
|
+
watermarkImageReady = false;
|
|
201
|
+
watermarkImage = null;
|
|
202
|
+
if (!src) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const image = new Image();
|
|
206
|
+
image.crossOrigin = "anonymous";
|
|
207
|
+
image.onload = () => {
|
|
208
|
+
watermarkImage = image;
|
|
209
|
+
watermarkImageReady = true;
|
|
210
|
+
draw();
|
|
211
|
+
};
|
|
212
|
+
image.onerror = () => {
|
|
213
|
+
watermarkImage = null;
|
|
214
|
+
watermarkImageReady = false;
|
|
215
|
+
};
|
|
216
|
+
image.src = src;
|
|
217
|
+
};
|
|
182
218
|
const crisp = (value) => Math.round(value) + 0.5;
|
|
183
219
|
const clamp = (value, min, max) => {
|
|
184
220
|
return Math.min(max, Math.max(min, value));
|
|
@@ -202,8 +238,13 @@ function createChart(element, options = {}) {
|
|
|
202
238
|
xSpan = 60;
|
|
203
239
|
return;
|
|
204
240
|
}
|
|
205
|
-
|
|
206
|
-
|
|
241
|
+
const requestedVisibleBars = Math.max(5, Math.floor(mergedOptions.initialVisibleBars));
|
|
242
|
+
xSpan = Math.min(requestedVisibleBars, Math.max(5, count));
|
|
243
|
+
if (mergedOptions.initialViewport === "center") {
|
|
244
|
+
xCenter = count / 2;
|
|
245
|
+
} else {
|
|
246
|
+
xCenter = count - xSpan / 2 + rightEdgePaddingBars;
|
|
247
|
+
}
|
|
207
248
|
clampXViewport();
|
|
208
249
|
};
|
|
209
250
|
const getYBounds = () => {
|
|
@@ -722,6 +763,31 @@ function createChart(element, options = {}) {
|
|
|
722
763
|
const yFromPrice = (price) => {
|
|
723
764
|
return chartBottom - (price - yMin) / yRange * chartHeight;
|
|
724
765
|
};
|
|
766
|
+
if (watermark.visible && watermark.imageSrc.trim().length > 0) {
|
|
767
|
+
ensureWatermarkImage(watermark.imageSrc.trim());
|
|
768
|
+
if (watermarkImageReady && watermarkImage) {
|
|
769
|
+
const maxW = chartWidth * clamp(watermark.imageMaxWidthRatio, 0.05, 1);
|
|
770
|
+
const maxH = chartHeight * clamp(watermark.imageMaxHeightRatio, 0.05, 1);
|
|
771
|
+
const naturalW = Math.max(1, watermarkImage.naturalWidth || watermarkImage.width);
|
|
772
|
+
const naturalH = Math.max(1, watermarkImage.naturalHeight || watermarkImage.height);
|
|
773
|
+
const containScale = Math.min(maxW / naturalW, maxH / naturalH);
|
|
774
|
+
const scale = Math.max(0.05, containScale * Math.max(0.05, watermark.imageScale));
|
|
775
|
+
const drawW = naturalW * scale;
|
|
776
|
+
const drawH = naturalH * scale;
|
|
777
|
+
const drawX = chartLeft + (chartWidth - drawW) / 2;
|
|
778
|
+
const drawY = chartTop + (chartHeight - drawH) / 2;
|
|
779
|
+
ctx.save();
|
|
780
|
+
ctx.globalAlpha = clamp(watermark.opacity, 0, 1);
|
|
781
|
+
ctx.drawImage(watermarkImage, drawX, drawY, drawW, drawH);
|
|
782
|
+
if (watermark.imageTintColor.trim().length > 0) {
|
|
783
|
+
ctx.globalCompositeOperation = "source-atop";
|
|
784
|
+
ctx.globalAlpha = clamp(watermark.opacity, 0, 1) * clamp(watermark.imageTintOpacity, 0, 1);
|
|
785
|
+
ctx.fillStyle = watermark.imageTintColor;
|
|
786
|
+
ctx.fillRect(drawX, drawY, drawW, drawH);
|
|
787
|
+
}
|
|
788
|
+
ctx.restore();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
725
791
|
if (watermark.visible && watermark.text.trim().length > 0) {
|
|
726
792
|
ctx.save();
|
|
727
793
|
ctx.globalAlpha = clamp(watermark.opacity, 0, 1);
|
|
@@ -1346,7 +1412,11 @@ function createChart(element, options = {}) {
|
|
|
1346
1412
|
autoYMin = null;
|
|
1347
1413
|
autoYMax = null;
|
|
1348
1414
|
} else {
|
|
1349
|
-
|
|
1415
|
+
if (mergedOptions.preserveViewportOnDataUpdate) {
|
|
1416
|
+
clampXViewport();
|
|
1417
|
+
} else {
|
|
1418
|
+
fitXViewport();
|
|
1419
|
+
}
|
|
1350
1420
|
}
|
|
1351
1421
|
draw();
|
|
1352
1422
|
};
|
package/docs/API.md
CHANGED
|
@@ -33,6 +33,10 @@ Top-level options:
|
|
|
33
33
|
- `axisColor` (legacy shorthand for axis line/text color)
|
|
34
34
|
- `axis?: AxisOptions`
|
|
35
35
|
- `priceDecimals` (default `2`, used for axis/ticker/line price labels)
|
|
36
|
+
- `initialViewport` (`"latest"` | `"center"`, default `"latest"`)
|
|
37
|
+
- `initialVisibleBars` (default `60`)
|
|
38
|
+
- `rightEdgePaddingBars` (default `2`, used by latest-anchored viewport)
|
|
39
|
+
- `preserveViewportOnDataUpdate` (default `true`; set `false` to auto-fit on each `setData`)
|
|
36
40
|
- `upColor` (default `#16a34a`)
|
|
37
41
|
- `downColor` (default `#dc2626`)
|
|
38
42
|
- `gridColor` (default `#e2e8f0`)
|
|
@@ -79,11 +83,17 @@ Top-level options:
|
|
|
79
83
|
|
|
80
84
|
- `visible` (default `false`)
|
|
81
85
|
- `text` (default `""`)
|
|
82
|
-
- `color` (default `#
|
|
83
|
-
- `opacity` (default `0.
|
|
86
|
+
- `color` (default `#81858d`)
|
|
87
|
+
- `opacity` (default `0.14`)
|
|
84
88
|
- `fontSize` (default `92`)
|
|
85
89
|
- `fontWeight` (default `700`)
|
|
86
90
|
- `thickness` (stroke width, default `0`)
|
|
91
|
+
- `imageSrc` (default `""`, URL/path to watermark logo)
|
|
92
|
+
- `imageScale` (default `1`)
|
|
93
|
+
- `imageMaxWidthRatio` (default `0.42`)
|
|
94
|
+
- `imageMaxHeightRatio` (default `0.3`)
|
|
95
|
+
- `imageTintColor` (default `""`, set `"#ffffff"` for white logo tint)
|
|
96
|
+
- `imageTintOpacity` (default `1`)
|
|
87
97
|
|
|
88
98
|
### `TickerLineOptions`
|
|
89
99
|
|