hyperprop-charting-library 0.1.27 → 0.1.29
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/README.md +1 -1
- package/dist/hyperprop-charting-library.cjs +8 -4
- package/dist/hyperprop-charting-library.js +8 -4
- package/dist/index.cjs +8 -4
- package/dist/index.js +8 -4
- package/docs/API.md +1 -1
- package/docs/RECIPES.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -153,7 +153,7 @@ Volume scaling tip (for large spikes):
|
|
|
153
153
|
chart.updateIndicator(volumeId, {
|
|
154
154
|
inputs: {
|
|
155
155
|
scaleMode: "visible", // default; scales using current viewport only
|
|
156
|
-
scaleType: "
|
|
156
|
+
scaleType: "sqrt", // default; balanced compression
|
|
157
157
|
clampPercentile: 0.95 // optional outlier clamp
|
|
158
158
|
}
|
|
159
159
|
});
|
|
@@ -533,7 +533,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
533
533
|
minBarWidth: 1,
|
|
534
534
|
overlayHeightRatio: 0.22,
|
|
535
535
|
scaleMode: "visible",
|
|
536
|
-
scaleType: "
|
|
536
|
+
scaleType: "sqrt",
|
|
537
537
|
clampPercentile: 1
|
|
538
538
|
},
|
|
539
539
|
draw: (ctx, renderContext, inputs) => {
|
|
@@ -544,7 +544,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
544
544
|
const paneHeight = overlayMode ? Math.max(20, Math.round(fullPaneHeight * overlayHeightRatio)) : fullPaneHeight;
|
|
545
545
|
const paneBottom = chartBottom;
|
|
546
546
|
const scaleMode = inputs.scaleMode === "full" ? "full" : "visible";
|
|
547
|
-
const scaleType = inputs.scaleType === "linear" ? "linear" : "log";
|
|
547
|
+
const scaleType = inputs.scaleType === "linear" ? "linear" : inputs.scaleType === "log" ? "log" : "sqrt";
|
|
548
548
|
const scalingPoints = scaleMode === "full" ? data : data.slice(startIndex, endIndex + 1);
|
|
549
549
|
const scalingVolumes = scalingPoints.map((point) => Math.max(0, point.v ?? 0)).filter((value) => value > 0);
|
|
550
550
|
const clampPercentile = Number.isFinite(inputs.clampPercentile) ? Number(inputs.clampPercentile) : 1;
|
|
@@ -561,7 +561,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
561
561
|
continue;
|
|
562
562
|
}
|
|
563
563
|
const clampedVolume = Math.min(maxVolume, Math.max(0, point.v));
|
|
564
|
-
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume)));
|
|
564
|
+
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
565
565
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
566
566
|
const xCenter = xFromIndex(index);
|
|
567
567
|
const barX = Math.round(xCenter - barWidth / 2);
|
|
@@ -2665,9 +2665,11 @@ function createChart(element, options = {}) {
|
|
|
2665
2665
|
};
|
|
2666
2666
|
const setData = (nextData) => {
|
|
2667
2667
|
const hadData = data.length > 0;
|
|
2668
|
+
const previousCount = data.length;
|
|
2668
2669
|
const previousCenterRounded = hadData ? Math.round(xCenter) : 0;
|
|
2669
2670
|
const previousCenterFraction = hadData ? xCenter - previousCenterRounded : 0;
|
|
2670
2671
|
const previousCenterTimeMs = hadData && previousCenterRounded >= 0 && previousCenterRounded < data.length ? data[previousCenterRounded]?.time.getTime() ?? null : null;
|
|
2672
|
+
const wasAtRightEdge = hadData && xCenter + xSpan / 2 >= previousCount - 1;
|
|
2671
2673
|
data = parseData(nextData);
|
|
2672
2674
|
if (data.length === 0) {
|
|
2673
2675
|
xCenter = 0;
|
|
@@ -2681,7 +2683,9 @@ function createChart(element, options = {}) {
|
|
|
2681
2683
|
resetYViewport();
|
|
2682
2684
|
} else {
|
|
2683
2685
|
if (mergedOptions.preserveViewportOnDataUpdate) {
|
|
2684
|
-
if (
|
|
2686
|
+
if (wasAtRightEdge) {
|
|
2687
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
2688
|
+
} else if (previousCenterTimeMs !== null) {
|
|
2685
2689
|
const nextCenter = findNearestIndexForTimeMs(previousCenterTimeMs);
|
|
2686
2690
|
if (nextCenter !== null) {
|
|
2687
2691
|
xCenter = nextCenter + previousCenterFraction;
|
|
@@ -509,7 +509,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
509
509
|
minBarWidth: 1,
|
|
510
510
|
overlayHeightRatio: 0.22,
|
|
511
511
|
scaleMode: "visible",
|
|
512
|
-
scaleType: "
|
|
512
|
+
scaleType: "sqrt",
|
|
513
513
|
clampPercentile: 1
|
|
514
514
|
},
|
|
515
515
|
draw: (ctx, renderContext, inputs) => {
|
|
@@ -520,7 +520,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
520
520
|
const paneHeight = overlayMode ? Math.max(20, Math.round(fullPaneHeight * overlayHeightRatio)) : fullPaneHeight;
|
|
521
521
|
const paneBottom = chartBottom;
|
|
522
522
|
const scaleMode = inputs.scaleMode === "full" ? "full" : "visible";
|
|
523
|
-
const scaleType = inputs.scaleType === "linear" ? "linear" : "log";
|
|
523
|
+
const scaleType = inputs.scaleType === "linear" ? "linear" : inputs.scaleType === "log" ? "log" : "sqrt";
|
|
524
524
|
const scalingPoints = scaleMode === "full" ? data : data.slice(startIndex, endIndex + 1);
|
|
525
525
|
const scalingVolumes = scalingPoints.map((point) => Math.max(0, point.v ?? 0)).filter((value) => value > 0);
|
|
526
526
|
const clampPercentile = Number.isFinite(inputs.clampPercentile) ? Number(inputs.clampPercentile) : 1;
|
|
@@ -537,7 +537,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
537
537
|
continue;
|
|
538
538
|
}
|
|
539
539
|
const clampedVolume = Math.min(maxVolume, Math.max(0, point.v));
|
|
540
|
-
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume)));
|
|
540
|
+
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
541
541
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
542
542
|
const xCenter = xFromIndex(index);
|
|
543
543
|
const barX = Math.round(xCenter - barWidth / 2);
|
|
@@ -2641,9 +2641,11 @@ function createChart(element, options = {}) {
|
|
|
2641
2641
|
};
|
|
2642
2642
|
const setData = (nextData) => {
|
|
2643
2643
|
const hadData = data.length > 0;
|
|
2644
|
+
const previousCount = data.length;
|
|
2644
2645
|
const previousCenterRounded = hadData ? Math.round(xCenter) : 0;
|
|
2645
2646
|
const previousCenterFraction = hadData ? xCenter - previousCenterRounded : 0;
|
|
2646
2647
|
const previousCenterTimeMs = hadData && previousCenterRounded >= 0 && previousCenterRounded < data.length ? data[previousCenterRounded]?.time.getTime() ?? null : null;
|
|
2648
|
+
const wasAtRightEdge = hadData && xCenter + xSpan / 2 >= previousCount - 1;
|
|
2647
2649
|
data = parseData(nextData);
|
|
2648
2650
|
if (data.length === 0) {
|
|
2649
2651
|
xCenter = 0;
|
|
@@ -2657,7 +2659,9 @@ function createChart(element, options = {}) {
|
|
|
2657
2659
|
resetYViewport();
|
|
2658
2660
|
} else {
|
|
2659
2661
|
if (mergedOptions.preserveViewportOnDataUpdate) {
|
|
2660
|
-
if (
|
|
2662
|
+
if (wasAtRightEdge) {
|
|
2663
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
2664
|
+
} else if (previousCenterTimeMs !== null) {
|
|
2661
2665
|
const nextCenter = findNearestIndexForTimeMs(previousCenterTimeMs);
|
|
2662
2666
|
if (nextCenter !== null) {
|
|
2663
2667
|
xCenter = nextCenter + previousCenterFraction;
|
package/dist/index.cjs
CHANGED
|
@@ -533,7 +533,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
533
533
|
minBarWidth: 1,
|
|
534
534
|
overlayHeightRatio: 0.22,
|
|
535
535
|
scaleMode: "visible",
|
|
536
|
-
scaleType: "
|
|
536
|
+
scaleType: "sqrt",
|
|
537
537
|
clampPercentile: 1
|
|
538
538
|
},
|
|
539
539
|
draw: (ctx, renderContext, inputs) => {
|
|
@@ -544,7 +544,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
544
544
|
const paneHeight = overlayMode ? Math.max(20, Math.round(fullPaneHeight * overlayHeightRatio)) : fullPaneHeight;
|
|
545
545
|
const paneBottom = chartBottom;
|
|
546
546
|
const scaleMode = inputs.scaleMode === "full" ? "full" : "visible";
|
|
547
|
-
const scaleType = inputs.scaleType === "linear" ? "linear" : "log";
|
|
547
|
+
const scaleType = inputs.scaleType === "linear" ? "linear" : inputs.scaleType === "log" ? "log" : "sqrt";
|
|
548
548
|
const scalingPoints = scaleMode === "full" ? data : data.slice(startIndex, endIndex + 1);
|
|
549
549
|
const scalingVolumes = scalingPoints.map((point) => Math.max(0, point.v ?? 0)).filter((value) => value > 0);
|
|
550
550
|
const clampPercentile = Number.isFinite(inputs.clampPercentile) ? Number(inputs.clampPercentile) : 1;
|
|
@@ -561,7 +561,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
561
561
|
continue;
|
|
562
562
|
}
|
|
563
563
|
const clampedVolume = Math.min(maxVolume, Math.max(0, point.v));
|
|
564
|
-
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume)));
|
|
564
|
+
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
565
565
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
566
566
|
const xCenter = xFromIndex(index);
|
|
567
567
|
const barX = Math.round(xCenter - barWidth / 2);
|
|
@@ -2665,9 +2665,11 @@ function createChart(element, options = {}) {
|
|
|
2665
2665
|
};
|
|
2666
2666
|
const setData = (nextData) => {
|
|
2667
2667
|
const hadData = data.length > 0;
|
|
2668
|
+
const previousCount = data.length;
|
|
2668
2669
|
const previousCenterRounded = hadData ? Math.round(xCenter) : 0;
|
|
2669
2670
|
const previousCenterFraction = hadData ? xCenter - previousCenterRounded : 0;
|
|
2670
2671
|
const previousCenterTimeMs = hadData && previousCenterRounded >= 0 && previousCenterRounded < data.length ? data[previousCenterRounded]?.time.getTime() ?? null : null;
|
|
2672
|
+
const wasAtRightEdge = hadData && xCenter + xSpan / 2 >= previousCount - 1;
|
|
2671
2673
|
data = parseData(nextData);
|
|
2672
2674
|
if (data.length === 0) {
|
|
2673
2675
|
xCenter = 0;
|
|
@@ -2681,7 +2683,9 @@ function createChart(element, options = {}) {
|
|
|
2681
2683
|
resetYViewport();
|
|
2682
2684
|
} else {
|
|
2683
2685
|
if (mergedOptions.preserveViewportOnDataUpdate) {
|
|
2684
|
-
if (
|
|
2686
|
+
if (wasAtRightEdge) {
|
|
2687
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
2688
|
+
} else if (previousCenterTimeMs !== null) {
|
|
2685
2689
|
const nextCenter = findNearestIndexForTimeMs(previousCenterTimeMs);
|
|
2686
2690
|
if (nextCenter !== null) {
|
|
2687
2691
|
xCenter = nextCenter + previousCenterFraction;
|
package/dist/index.js
CHANGED
|
@@ -509,7 +509,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
509
509
|
minBarWidth: 1,
|
|
510
510
|
overlayHeightRatio: 0.22,
|
|
511
511
|
scaleMode: "visible",
|
|
512
|
-
scaleType: "
|
|
512
|
+
scaleType: "sqrt",
|
|
513
513
|
clampPercentile: 1
|
|
514
514
|
},
|
|
515
515
|
draw: (ctx, renderContext, inputs) => {
|
|
@@ -520,7 +520,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
520
520
|
const paneHeight = overlayMode ? Math.max(20, Math.round(fullPaneHeight * overlayHeightRatio)) : fullPaneHeight;
|
|
521
521
|
const paneBottom = chartBottom;
|
|
522
522
|
const scaleMode = inputs.scaleMode === "full" ? "full" : "visible";
|
|
523
|
-
const scaleType = inputs.scaleType === "linear" ? "linear" : "log";
|
|
523
|
+
const scaleType = inputs.scaleType === "linear" ? "linear" : inputs.scaleType === "log" ? "log" : "sqrt";
|
|
524
524
|
const scalingPoints = scaleMode === "full" ? data : data.slice(startIndex, endIndex + 1);
|
|
525
525
|
const scalingVolumes = scalingPoints.map((point) => Math.max(0, point.v ?? 0)).filter((value) => value > 0);
|
|
526
526
|
const clampPercentile = Number.isFinite(inputs.clampPercentile) ? Number(inputs.clampPercentile) : 1;
|
|
@@ -537,7 +537,7 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
537
537
|
continue;
|
|
538
538
|
}
|
|
539
539
|
const clampedVolume = Math.min(maxVolume, Math.max(0, point.v));
|
|
540
|
-
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume)));
|
|
540
|
+
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
541
541
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
542
542
|
const xCenter = xFromIndex(index);
|
|
543
543
|
const barX = Math.round(xCenter - barWidth / 2);
|
|
@@ -2641,9 +2641,11 @@ function createChart(element, options = {}) {
|
|
|
2641
2641
|
};
|
|
2642
2642
|
const setData = (nextData) => {
|
|
2643
2643
|
const hadData = data.length > 0;
|
|
2644
|
+
const previousCount = data.length;
|
|
2644
2645
|
const previousCenterRounded = hadData ? Math.round(xCenter) : 0;
|
|
2645
2646
|
const previousCenterFraction = hadData ? xCenter - previousCenterRounded : 0;
|
|
2646
2647
|
const previousCenterTimeMs = hadData && previousCenterRounded >= 0 && previousCenterRounded < data.length ? data[previousCenterRounded]?.time.getTime() ?? null : null;
|
|
2648
|
+
const wasAtRightEdge = hadData && xCenter + xSpan / 2 >= previousCount - 1;
|
|
2647
2649
|
data = parseData(nextData);
|
|
2648
2650
|
if (data.length === 0) {
|
|
2649
2651
|
xCenter = 0;
|
|
@@ -2657,7 +2659,9 @@ function createChart(element, options = {}) {
|
|
|
2657
2659
|
resetYViewport();
|
|
2658
2660
|
} else {
|
|
2659
2661
|
if (mergedOptions.preserveViewportOnDataUpdate) {
|
|
2660
|
-
if (
|
|
2662
|
+
if (wasAtRightEdge) {
|
|
2663
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
2664
|
+
} else if (previousCenterTimeMs !== null) {
|
|
2661
2665
|
const nextCenter = findNearestIndexForTimeMs(previousCenterTimeMs);
|
|
2662
2666
|
if (nextCenter !== null) {
|
|
2663
2667
|
xCenter = nextCenter + previousCenterFraction;
|
package/docs/API.md
CHANGED
|
@@ -312,7 +312,7 @@ Volume style inputs:
|
|
|
312
312
|
- `minBarWidth`
|
|
313
313
|
- `overlayHeightRatio` (when used as overlay)
|
|
314
314
|
- `scaleMode` (`"visible"` default, or `"full"`)
|
|
315
|
-
- `scaleType` (`"
|
|
315
|
+
- `scaleType` (`"sqrt"` default, or `"log"` / `"linear"`)
|
|
316
316
|
- `clampPercentile` (`0..1`, default `1`; e.g. `0.95` to reduce outlier crush)
|
|
317
317
|
|
|
318
318
|
---
|
package/docs/RECIPES.md
CHANGED
|
@@ -151,7 +151,7 @@ const volumeId = chart.addIndicator("volume", { upOpacity: 0.72, downOpacity: 0.
|
|
|
151
151
|
```ts
|
|
152
152
|
const volumeId = chart.addIndicator("volume", {
|
|
153
153
|
scaleMode: "visible", // default behavior
|
|
154
|
-
scaleType: "
|
|
154
|
+
scaleType: "sqrt", // default behavior
|
|
155
155
|
clampPercentile: 0.95 // clamp scaling reference to p95 of visible bars
|
|
156
156
|
});
|
|
157
157
|
```
|