hyperprop-charting-library 0.1.113 → 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.
@@ -5198,6 +5198,50 @@ function createChart(element, options = {}) {
5198
5198
  }
5199
5199
  scheduleDraw();
5200
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
+ };
5201
5245
  const setPriceLines = (lines) => {
5202
5246
  priceLines = lines.map((line, index) => ({
5203
5247
  ...line,
@@ -5453,6 +5497,7 @@ function createChart(element, options = {}) {
5453
5497
  return {
5454
5498
  updateOptions,
5455
5499
  setData,
5500
+ upsertBar,
5456
5501
  setPriceLines,
5457
5502
  addPriceLine,
5458
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;
@@ -5172,6 +5172,50 @@ function createChart(element, options = {}) {
5172
5172
  }
5173
5173
  scheduleDraw();
5174
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
+ };
5175
5219
  const setPriceLines = (lines) => {
5176
5220
  priceLines = lines.map((line, index) => ({
5177
5221
  ...line,
@@ -5427,6 +5471,7 @@ function createChart(element, options = {}) {
5427
5471
  return {
5428
5472
  updateOptions,
5429
5473
  setData,
5474
+ upsertBar,
5430
5475
  setPriceLines,
5431
5476
  addPriceLine,
5432
5477
  removePriceLine,
package/dist/index.cjs CHANGED
@@ -5198,6 +5198,50 @@ function createChart(element, options = {}) {
5198
5198
  }
5199
5199
  scheduleDraw();
5200
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
+ };
5201
5245
  const setPriceLines = (lines) => {
5202
5246
  priceLines = lines.map((line, index) => ({
5203
5247
  ...line,
@@ -5453,6 +5497,7 @@ function createChart(element, options = {}) {
5453
5497
  return {
5454
5498
  updateOptions,
5455
5499
  setData,
5500
+ upsertBar,
5456
5501
  setPriceLines,
5457
5502
  addPriceLine,
5458
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
@@ -5172,6 +5172,50 @@ function createChart(element, options = {}) {
5172
5172
  }
5173
5173
  scheduleDraw();
5174
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
+ };
5175
5219
  const setPriceLines = (lines) => {
5176
5220
  priceLines = lines.map((line, index) => ({
5177
5221
  ...line,
@@ -5427,6 +5471,7 @@ function createChart(element, options = {}) {
5427
5471
  return {
5428
5472
  updateOptions,
5429
5473
  setData,
5474
+ upsertBar,
5430
5475
  setPriceLines,
5431
5476
  addPriceLine,
5432
5477
  removePriceLine,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.113",
3
+ "version": "0.1.114",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",