hyperprop-charting-library 0.1.112 → 0.1.114
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.
|
@@ -1035,6 +1035,7 @@ function createChart(element, options = {}) {
|
|
|
1035
1035
|
let magnetModifierActive = false;
|
|
1036
1036
|
let shiftKeyActive = false;
|
|
1037
1037
|
const MAGNET_WEAK_THRESHOLD_PX = 16;
|
|
1038
|
+
const MAGNET_STRONG_THRESHOLD_PX = 48;
|
|
1038
1039
|
let drawingHoverHandler = null;
|
|
1039
1040
|
let lastHoveredDrawingId = null;
|
|
1040
1041
|
let selectedDrawingId = null;
|
|
@@ -3942,7 +3943,8 @@ function createChart(element, options = {}) {
|
|
|
3942
3943
|
nearest = candidate;
|
|
3943
3944
|
}
|
|
3944
3945
|
}
|
|
3945
|
-
|
|
3946
|
+
const snapThresholdPx = effective === "weak" ? MAGNET_WEAK_THRESHOLD_PX : MAGNET_STRONG_THRESHOLD_PX;
|
|
3947
|
+
if (Math.abs(canvasYFromDrawingPrice(nearest) - y) > snapThresholdPx) {
|
|
3946
3948
|
return { index, price };
|
|
3947
3949
|
}
|
|
3948
3950
|
return { index: barIndex, price: nearest };
|
|
@@ -5196,6 +5198,50 @@ function createChart(element, options = {}) {
|
|
|
5196
5198
|
}
|
|
5197
5199
|
scheduleDraw();
|
|
5198
5200
|
};
|
|
5201
|
+
const upsertBar = (point) => {
|
|
5202
|
+
const time = new Date(point.t);
|
|
5203
|
+
const timeMs = time.getTime();
|
|
5204
|
+
const open = Number(point.o);
|
|
5205
|
+
const close = Number(point.c);
|
|
5206
|
+
const highInput = Number(point.h);
|
|
5207
|
+
const lowInput = Number(point.l);
|
|
5208
|
+
if (!Number.isFinite(timeMs) || !Number.isFinite(open) || !Number.isFinite(close) || !Number.isFinite(highInput) || !Number.isFinite(lowInput)) {
|
|
5209
|
+
return;
|
|
5210
|
+
}
|
|
5211
|
+
const volumeValue = point.v === void 0 ? void 0 : Number(point.v);
|
|
5212
|
+
const parsed = {
|
|
5213
|
+
time,
|
|
5214
|
+
o: open,
|
|
5215
|
+
h: Math.max(highInput, open, close),
|
|
5216
|
+
l: Math.min(lowInput, open, close),
|
|
5217
|
+
c: close,
|
|
5218
|
+
...volumeValue === void 0 || !Number.isFinite(volumeValue) ? {} : { v: volumeValue }
|
|
5219
|
+
};
|
|
5220
|
+
const last = data[data.length - 1];
|
|
5221
|
+
if (!last) {
|
|
5222
|
+
setData([point]);
|
|
5223
|
+
return;
|
|
5224
|
+
}
|
|
5225
|
+
const lastMs = last.time.getTime();
|
|
5226
|
+
if (timeMs === lastMs) {
|
|
5227
|
+
data[data.length - 1] = parsed;
|
|
5228
|
+
} else if (timeMs > lastMs) {
|
|
5229
|
+
data.push(parsed);
|
|
5230
|
+
if (mergedOptions.preserveViewportOnDataUpdate && followLatest) {
|
|
5231
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
5232
|
+
clampXViewport();
|
|
5233
|
+
}
|
|
5234
|
+
} else {
|
|
5235
|
+
const merged = /* @__PURE__ */ new Map();
|
|
5236
|
+
for (const existing of data) {
|
|
5237
|
+
merged.set(existing.time.getTime(), existing);
|
|
5238
|
+
}
|
|
5239
|
+
merged.set(timeMs, parsed);
|
|
5240
|
+
data = Array.from(merged.values()).sort((a, b) => a.time.getTime() - b.time.getTime());
|
|
5241
|
+
}
|
|
5242
|
+
pushSmoothedTicker(parsed.c, parsed.v);
|
|
5243
|
+
scheduleDraw();
|
|
5244
|
+
};
|
|
5199
5245
|
const setPriceLines = (lines) => {
|
|
5200
5246
|
priceLines = lines.map((line, index) => ({
|
|
5201
5247
|
...line,
|
|
@@ -5451,6 +5497,7 @@ function createChart(element, options = {}) {
|
|
|
5451
5497
|
return {
|
|
5452
5498
|
updateOptions,
|
|
5453
5499
|
setData,
|
|
5500
|
+
upsertBar,
|
|
5454
5501
|
setPriceLines,
|
|
5455
5502
|
addPriceLine,
|
|
5456
5503
|
removePriceLine,
|
|
@@ -412,6 +412,13 @@ interface LabelsOptions {
|
|
|
412
412
|
interface ChartInstance {
|
|
413
413
|
updateOptions: (options: ChartOptions) => void;
|
|
414
414
|
setData: (data: OhlcDataPoint[]) => void;
|
|
415
|
+
/**
|
|
416
|
+
* Incrementally upsert a single bar: O(1) update-in-place for the live
|
|
417
|
+
* (forming) bar and O(1) append for a new bar, instead of re-ingesting the
|
|
418
|
+
* full series through `setData`. Out-of-order timestamps fall back to a
|
|
419
|
+
* full merge, so correctness never depends on call ordering.
|
|
420
|
+
*/
|
|
421
|
+
upsertBar: (point: OhlcDataPoint) => void;
|
|
415
422
|
setPriceLines: (lines: PriceLineOptions[]) => void;
|
|
416
423
|
addPriceLine: (line: PriceLineOptions) => string;
|
|
417
424
|
removePriceLine: (id: string) => void;
|
|
@@ -1009,6 +1009,7 @@ function createChart(element, options = {}) {
|
|
|
1009
1009
|
let magnetModifierActive = false;
|
|
1010
1010
|
let shiftKeyActive = false;
|
|
1011
1011
|
const MAGNET_WEAK_THRESHOLD_PX = 16;
|
|
1012
|
+
const MAGNET_STRONG_THRESHOLD_PX = 48;
|
|
1012
1013
|
let drawingHoverHandler = null;
|
|
1013
1014
|
let lastHoveredDrawingId = null;
|
|
1014
1015
|
let selectedDrawingId = null;
|
|
@@ -3916,7 +3917,8 @@ function createChart(element, options = {}) {
|
|
|
3916
3917
|
nearest = candidate;
|
|
3917
3918
|
}
|
|
3918
3919
|
}
|
|
3919
|
-
|
|
3920
|
+
const snapThresholdPx = effective === "weak" ? MAGNET_WEAK_THRESHOLD_PX : MAGNET_STRONG_THRESHOLD_PX;
|
|
3921
|
+
if (Math.abs(canvasYFromDrawingPrice(nearest) - y) > snapThresholdPx) {
|
|
3920
3922
|
return { index, price };
|
|
3921
3923
|
}
|
|
3922
3924
|
return { index: barIndex, price: nearest };
|
|
@@ -5170,6 +5172,50 @@ function createChart(element, options = {}) {
|
|
|
5170
5172
|
}
|
|
5171
5173
|
scheduleDraw();
|
|
5172
5174
|
};
|
|
5175
|
+
const upsertBar = (point) => {
|
|
5176
|
+
const time = new Date(point.t);
|
|
5177
|
+
const timeMs = time.getTime();
|
|
5178
|
+
const open = Number(point.o);
|
|
5179
|
+
const close = Number(point.c);
|
|
5180
|
+
const highInput = Number(point.h);
|
|
5181
|
+
const lowInput = Number(point.l);
|
|
5182
|
+
if (!Number.isFinite(timeMs) || !Number.isFinite(open) || !Number.isFinite(close) || !Number.isFinite(highInput) || !Number.isFinite(lowInput)) {
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
5185
|
+
const volumeValue = point.v === void 0 ? void 0 : Number(point.v);
|
|
5186
|
+
const parsed = {
|
|
5187
|
+
time,
|
|
5188
|
+
o: open,
|
|
5189
|
+
h: Math.max(highInput, open, close),
|
|
5190
|
+
l: Math.min(lowInput, open, close),
|
|
5191
|
+
c: close,
|
|
5192
|
+
...volumeValue === void 0 || !Number.isFinite(volumeValue) ? {} : { v: volumeValue }
|
|
5193
|
+
};
|
|
5194
|
+
const last = data[data.length - 1];
|
|
5195
|
+
if (!last) {
|
|
5196
|
+
setData([point]);
|
|
5197
|
+
return;
|
|
5198
|
+
}
|
|
5199
|
+
const lastMs = last.time.getTime();
|
|
5200
|
+
if (timeMs === lastMs) {
|
|
5201
|
+
data[data.length - 1] = parsed;
|
|
5202
|
+
} else if (timeMs > lastMs) {
|
|
5203
|
+
data.push(parsed);
|
|
5204
|
+
if (mergedOptions.preserveViewportOnDataUpdate && followLatest) {
|
|
5205
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
5206
|
+
clampXViewport();
|
|
5207
|
+
}
|
|
5208
|
+
} else {
|
|
5209
|
+
const merged = /* @__PURE__ */ new Map();
|
|
5210
|
+
for (const existing of data) {
|
|
5211
|
+
merged.set(existing.time.getTime(), existing);
|
|
5212
|
+
}
|
|
5213
|
+
merged.set(timeMs, parsed);
|
|
5214
|
+
data = Array.from(merged.values()).sort((a, b) => a.time.getTime() - b.time.getTime());
|
|
5215
|
+
}
|
|
5216
|
+
pushSmoothedTicker(parsed.c, parsed.v);
|
|
5217
|
+
scheduleDraw();
|
|
5218
|
+
};
|
|
5173
5219
|
const setPriceLines = (lines) => {
|
|
5174
5220
|
priceLines = lines.map((line, index) => ({
|
|
5175
5221
|
...line,
|
|
@@ -5425,6 +5471,7 @@ function createChart(element, options = {}) {
|
|
|
5425
5471
|
return {
|
|
5426
5472
|
updateOptions,
|
|
5427
5473
|
setData,
|
|
5474
|
+
upsertBar,
|
|
5428
5475
|
setPriceLines,
|
|
5429
5476
|
addPriceLine,
|
|
5430
5477
|
removePriceLine,
|
package/dist/index.cjs
CHANGED
|
@@ -1035,6 +1035,7 @@ function createChart(element, options = {}) {
|
|
|
1035
1035
|
let magnetModifierActive = false;
|
|
1036
1036
|
let shiftKeyActive = false;
|
|
1037
1037
|
const MAGNET_WEAK_THRESHOLD_PX = 16;
|
|
1038
|
+
const MAGNET_STRONG_THRESHOLD_PX = 48;
|
|
1038
1039
|
let drawingHoverHandler = null;
|
|
1039
1040
|
let lastHoveredDrawingId = null;
|
|
1040
1041
|
let selectedDrawingId = null;
|
|
@@ -3942,7 +3943,8 @@ function createChart(element, options = {}) {
|
|
|
3942
3943
|
nearest = candidate;
|
|
3943
3944
|
}
|
|
3944
3945
|
}
|
|
3945
|
-
|
|
3946
|
+
const snapThresholdPx = effective === "weak" ? MAGNET_WEAK_THRESHOLD_PX : MAGNET_STRONG_THRESHOLD_PX;
|
|
3947
|
+
if (Math.abs(canvasYFromDrawingPrice(nearest) - y) > snapThresholdPx) {
|
|
3946
3948
|
return { index, price };
|
|
3947
3949
|
}
|
|
3948
3950
|
return { index: barIndex, price: nearest };
|
|
@@ -5196,6 +5198,50 @@ function createChart(element, options = {}) {
|
|
|
5196
5198
|
}
|
|
5197
5199
|
scheduleDraw();
|
|
5198
5200
|
};
|
|
5201
|
+
const upsertBar = (point) => {
|
|
5202
|
+
const time = new Date(point.t);
|
|
5203
|
+
const timeMs = time.getTime();
|
|
5204
|
+
const open = Number(point.o);
|
|
5205
|
+
const close = Number(point.c);
|
|
5206
|
+
const highInput = Number(point.h);
|
|
5207
|
+
const lowInput = Number(point.l);
|
|
5208
|
+
if (!Number.isFinite(timeMs) || !Number.isFinite(open) || !Number.isFinite(close) || !Number.isFinite(highInput) || !Number.isFinite(lowInput)) {
|
|
5209
|
+
return;
|
|
5210
|
+
}
|
|
5211
|
+
const volumeValue = point.v === void 0 ? void 0 : Number(point.v);
|
|
5212
|
+
const parsed = {
|
|
5213
|
+
time,
|
|
5214
|
+
o: open,
|
|
5215
|
+
h: Math.max(highInput, open, close),
|
|
5216
|
+
l: Math.min(lowInput, open, close),
|
|
5217
|
+
c: close,
|
|
5218
|
+
...volumeValue === void 0 || !Number.isFinite(volumeValue) ? {} : { v: volumeValue }
|
|
5219
|
+
};
|
|
5220
|
+
const last = data[data.length - 1];
|
|
5221
|
+
if (!last) {
|
|
5222
|
+
setData([point]);
|
|
5223
|
+
return;
|
|
5224
|
+
}
|
|
5225
|
+
const lastMs = last.time.getTime();
|
|
5226
|
+
if (timeMs === lastMs) {
|
|
5227
|
+
data[data.length - 1] = parsed;
|
|
5228
|
+
} else if (timeMs > lastMs) {
|
|
5229
|
+
data.push(parsed);
|
|
5230
|
+
if (mergedOptions.preserveViewportOnDataUpdate && followLatest) {
|
|
5231
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
5232
|
+
clampXViewport();
|
|
5233
|
+
}
|
|
5234
|
+
} else {
|
|
5235
|
+
const merged = /* @__PURE__ */ new Map();
|
|
5236
|
+
for (const existing of data) {
|
|
5237
|
+
merged.set(existing.time.getTime(), existing);
|
|
5238
|
+
}
|
|
5239
|
+
merged.set(timeMs, parsed);
|
|
5240
|
+
data = Array.from(merged.values()).sort((a, b) => a.time.getTime() - b.time.getTime());
|
|
5241
|
+
}
|
|
5242
|
+
pushSmoothedTicker(parsed.c, parsed.v);
|
|
5243
|
+
scheduleDraw();
|
|
5244
|
+
};
|
|
5199
5245
|
const setPriceLines = (lines) => {
|
|
5200
5246
|
priceLines = lines.map((line, index) => ({
|
|
5201
5247
|
...line,
|
|
@@ -5451,6 +5497,7 @@ function createChart(element, options = {}) {
|
|
|
5451
5497
|
return {
|
|
5452
5498
|
updateOptions,
|
|
5453
5499
|
setData,
|
|
5500
|
+
upsertBar,
|
|
5454
5501
|
setPriceLines,
|
|
5455
5502
|
addPriceLine,
|
|
5456
5503
|
removePriceLine,
|
package/dist/index.d.cts
CHANGED
|
@@ -412,6 +412,13 @@ interface LabelsOptions {
|
|
|
412
412
|
interface ChartInstance {
|
|
413
413
|
updateOptions: (options: ChartOptions) => void;
|
|
414
414
|
setData: (data: OhlcDataPoint[]) => void;
|
|
415
|
+
/**
|
|
416
|
+
* Incrementally upsert a single bar: O(1) update-in-place for the live
|
|
417
|
+
* (forming) bar and O(1) append for a new bar, instead of re-ingesting the
|
|
418
|
+
* full series through `setData`. Out-of-order timestamps fall back to a
|
|
419
|
+
* full merge, so correctness never depends on call ordering.
|
|
420
|
+
*/
|
|
421
|
+
upsertBar: (point: OhlcDataPoint) => void;
|
|
415
422
|
setPriceLines: (lines: PriceLineOptions[]) => void;
|
|
416
423
|
addPriceLine: (line: PriceLineOptions) => string;
|
|
417
424
|
removePriceLine: (id: string) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -412,6 +412,13 @@ interface LabelsOptions {
|
|
|
412
412
|
interface ChartInstance {
|
|
413
413
|
updateOptions: (options: ChartOptions) => void;
|
|
414
414
|
setData: (data: OhlcDataPoint[]) => void;
|
|
415
|
+
/**
|
|
416
|
+
* Incrementally upsert a single bar: O(1) update-in-place for the live
|
|
417
|
+
* (forming) bar and O(1) append for a new bar, instead of re-ingesting the
|
|
418
|
+
* full series through `setData`. Out-of-order timestamps fall back to a
|
|
419
|
+
* full merge, so correctness never depends on call ordering.
|
|
420
|
+
*/
|
|
421
|
+
upsertBar: (point: OhlcDataPoint) => void;
|
|
415
422
|
setPriceLines: (lines: PriceLineOptions[]) => void;
|
|
416
423
|
addPriceLine: (line: PriceLineOptions) => string;
|
|
417
424
|
removePriceLine: (id: string) => void;
|
package/dist/index.js
CHANGED
|
@@ -1009,6 +1009,7 @@ function createChart(element, options = {}) {
|
|
|
1009
1009
|
let magnetModifierActive = false;
|
|
1010
1010
|
let shiftKeyActive = false;
|
|
1011
1011
|
const MAGNET_WEAK_THRESHOLD_PX = 16;
|
|
1012
|
+
const MAGNET_STRONG_THRESHOLD_PX = 48;
|
|
1012
1013
|
let drawingHoverHandler = null;
|
|
1013
1014
|
let lastHoveredDrawingId = null;
|
|
1014
1015
|
let selectedDrawingId = null;
|
|
@@ -3916,7 +3917,8 @@ function createChart(element, options = {}) {
|
|
|
3916
3917
|
nearest = candidate;
|
|
3917
3918
|
}
|
|
3918
3919
|
}
|
|
3919
|
-
|
|
3920
|
+
const snapThresholdPx = effective === "weak" ? MAGNET_WEAK_THRESHOLD_PX : MAGNET_STRONG_THRESHOLD_PX;
|
|
3921
|
+
if (Math.abs(canvasYFromDrawingPrice(nearest) - y) > snapThresholdPx) {
|
|
3920
3922
|
return { index, price };
|
|
3921
3923
|
}
|
|
3922
3924
|
return { index: barIndex, price: nearest };
|
|
@@ -5170,6 +5172,50 @@ function createChart(element, options = {}) {
|
|
|
5170
5172
|
}
|
|
5171
5173
|
scheduleDraw();
|
|
5172
5174
|
};
|
|
5175
|
+
const upsertBar = (point) => {
|
|
5176
|
+
const time = new Date(point.t);
|
|
5177
|
+
const timeMs = time.getTime();
|
|
5178
|
+
const open = Number(point.o);
|
|
5179
|
+
const close = Number(point.c);
|
|
5180
|
+
const highInput = Number(point.h);
|
|
5181
|
+
const lowInput = Number(point.l);
|
|
5182
|
+
if (!Number.isFinite(timeMs) || !Number.isFinite(open) || !Number.isFinite(close) || !Number.isFinite(highInput) || !Number.isFinite(lowInput)) {
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
5185
|
+
const volumeValue = point.v === void 0 ? void 0 : Number(point.v);
|
|
5186
|
+
const parsed = {
|
|
5187
|
+
time,
|
|
5188
|
+
o: open,
|
|
5189
|
+
h: Math.max(highInput, open, close),
|
|
5190
|
+
l: Math.min(lowInput, open, close),
|
|
5191
|
+
c: close,
|
|
5192
|
+
...volumeValue === void 0 || !Number.isFinite(volumeValue) ? {} : { v: volumeValue }
|
|
5193
|
+
};
|
|
5194
|
+
const last = data[data.length - 1];
|
|
5195
|
+
if (!last) {
|
|
5196
|
+
setData([point]);
|
|
5197
|
+
return;
|
|
5198
|
+
}
|
|
5199
|
+
const lastMs = last.time.getTime();
|
|
5200
|
+
if (timeMs === lastMs) {
|
|
5201
|
+
data[data.length - 1] = parsed;
|
|
5202
|
+
} else if (timeMs > lastMs) {
|
|
5203
|
+
data.push(parsed);
|
|
5204
|
+
if (mergedOptions.preserveViewportOnDataUpdate && followLatest) {
|
|
5205
|
+
xCenter = data.length - xSpan / 2 + rightEdgePaddingBars;
|
|
5206
|
+
clampXViewport();
|
|
5207
|
+
}
|
|
5208
|
+
} else {
|
|
5209
|
+
const merged = /* @__PURE__ */ new Map();
|
|
5210
|
+
for (const existing of data) {
|
|
5211
|
+
merged.set(existing.time.getTime(), existing);
|
|
5212
|
+
}
|
|
5213
|
+
merged.set(timeMs, parsed);
|
|
5214
|
+
data = Array.from(merged.values()).sort((a, b) => a.time.getTime() - b.time.getTime());
|
|
5215
|
+
}
|
|
5216
|
+
pushSmoothedTicker(parsed.c, parsed.v);
|
|
5217
|
+
scheduleDraw();
|
|
5218
|
+
};
|
|
5173
5219
|
const setPriceLines = (lines) => {
|
|
5174
5220
|
priceLines = lines.map((line, index) => ({
|
|
5175
5221
|
...line,
|
|
@@ -5425,6 +5471,7 @@ function createChart(element, options = {}) {
|
|
|
5425
5471
|
return {
|
|
5426
5472
|
updateOptions,
|
|
5427
5473
|
setData,
|
|
5474
|
+
upsertBar,
|
|
5428
5475
|
setPriceLines,
|
|
5429
5476
|
addPriceLine,
|
|
5430
5477
|
removePriceLine,
|