hyperprop-charting-library 0.1.103 → 0.1.105

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.
@@ -75,7 +75,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
75
75
  priceActionButtonSize: 16,
76
76
  priceActionButtonGap: 4,
77
77
  priceActionButtonRounded: true,
78
- priceActionButtonBorderRadius: 8
78
+ priceActionButtonBorderRadius: 8,
79
+ sideHintLeft: "",
80
+ sideHintRight: "",
81
+ sideHintLeftColor: "#26a69a",
82
+ sideHintRightColor: "#ef5350"
79
83
  };
80
84
  var DEFAULT_WATERMARK_OPTIONS = {
81
85
  visible: false,
@@ -1292,10 +1296,19 @@ function createChart(element, options = {}) {
1292
1296
  }
1293
1297
  return Math.round(price / tickSize) * tickSize;
1294
1298
  };
1299
+ const groupThousands = (value, decimals) => {
1300
+ const negative = value < 0;
1301
+ const fixed = Math.abs(value).toFixed(decimals);
1302
+ const dot = fixed.indexOf(".");
1303
+ const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
1304
+ const decPart = dot === -1 ? "" : fixed.slice(dot);
1305
+ const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1306
+ return `${negative ? "-" : ""}${grouped}${decPart}`;
1307
+ };
1295
1308
  const formatPrice = (price) => {
1296
1309
  const rounded = quantizeToTickSize(price);
1297
1310
  const decimals = getDisplayPriceDecimals();
1298
- return rounded.toFixed(decimals);
1311
+ return groupThousands(rounded, decimals);
1299
1312
  };
1300
1313
  const roundToPricePrecision = (price) => {
1301
1314
  const rounded = quantizeToTickSize(price);
@@ -1333,7 +1346,7 @@ function createChart(element, options = {}) {
1333
1346
  }
1334
1347
  const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
1335
1348
  const integerDigits = Math.max(configuredDigits, observedDigits);
1336
- const integerPart = "8".repeat(integerDigits);
1349
+ const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1337
1350
  const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
1338
1351
  return `${integerPart}${decimalPart}`;
1339
1352
  };
@@ -3008,6 +3021,25 @@ function createChart(element, options = {}) {
3008
3021
  }
3009
3022
  ctx.restore();
3010
3023
  }
3024
+ if (crosshair.sideHintLeft || crosshair.sideHintRight) {
3025
+ ctx.save();
3026
+ ctx.font = `600 11px ${mergedOptions.fontFamily}`;
3027
+ ctx.textBaseline = "middle";
3028
+ ctx.setLineDash([]);
3029
+ const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
3030
+ const hintGap = 8;
3031
+ if (crosshair.sideHintLeft) {
3032
+ ctx.fillStyle = crosshair.sideHintLeftColor;
3033
+ ctx.textAlign = "right";
3034
+ ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
3035
+ }
3036
+ if (crosshair.sideHintRight) {
3037
+ ctx.fillStyle = crosshair.sideHintRightColor;
3038
+ ctx.textAlign = "left";
3039
+ ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
3040
+ }
3041
+ ctx.restore();
3042
+ }
3011
3043
  }
3012
3044
  ctx.restore();
3013
3045
  const positionAxisGutter = Math.max(0, width - chartRight);
@@ -3432,16 +3464,18 @@ function createChart(element, options = {}) {
3432
3464
  ctx.font = prevFont;
3433
3465
  }
3434
3466
  }
3467
+ const axisStepMs = getTimeStepMs();
3468
+ const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
3469
+ let prevAxisTickTime = null;
3435
3470
  for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
3436
3471
  const tickTime = getTimeForIndex(index);
3437
3472
  if (!tickTime) {
3438
3473
  continue;
3439
3474
  }
3440
3475
  const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
3441
- const timeLabel = tickTime.toLocaleDateString(void 0, {
3442
- month: "short",
3443
- day: "numeric"
3444
- });
3476
+ const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
3477
+ const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
3478
+ prevAxisTickTime = tickTime;
3445
3479
  const prevFont = ctx.font;
3446
3480
  ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
3447
3481
  drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
@@ -241,6 +241,10 @@ interface CrosshairOptions {
241
241
  priceActionButtonGap?: number;
242
242
  priceActionButtonRounded?: boolean;
243
243
  priceActionButtonBorderRadius?: number;
244
+ sideHintLeft?: string;
245
+ sideHintRight?: string;
246
+ sideHintLeftColor?: string;
247
+ sideHintRightColor?: string;
244
248
  }
245
249
  interface WatermarkOptions {
246
250
  visible?: boolean;
@@ -49,7 +49,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
49
49
  priceActionButtonSize: 16,
50
50
  priceActionButtonGap: 4,
51
51
  priceActionButtonRounded: true,
52
- priceActionButtonBorderRadius: 8
52
+ priceActionButtonBorderRadius: 8,
53
+ sideHintLeft: "",
54
+ sideHintRight: "",
55
+ sideHintLeftColor: "#26a69a",
56
+ sideHintRightColor: "#ef5350"
53
57
  };
54
58
  var DEFAULT_WATERMARK_OPTIONS = {
55
59
  visible: false,
@@ -1266,10 +1270,19 @@ function createChart(element, options = {}) {
1266
1270
  }
1267
1271
  return Math.round(price / tickSize) * tickSize;
1268
1272
  };
1273
+ const groupThousands = (value, decimals) => {
1274
+ const negative = value < 0;
1275
+ const fixed = Math.abs(value).toFixed(decimals);
1276
+ const dot = fixed.indexOf(".");
1277
+ const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
1278
+ const decPart = dot === -1 ? "" : fixed.slice(dot);
1279
+ const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1280
+ return `${negative ? "-" : ""}${grouped}${decPart}`;
1281
+ };
1269
1282
  const formatPrice = (price) => {
1270
1283
  const rounded = quantizeToTickSize(price);
1271
1284
  const decimals = getDisplayPriceDecimals();
1272
- return rounded.toFixed(decimals);
1285
+ return groupThousands(rounded, decimals);
1273
1286
  };
1274
1287
  const roundToPricePrecision = (price) => {
1275
1288
  const rounded = quantizeToTickSize(price);
@@ -1307,7 +1320,7 @@ function createChart(element, options = {}) {
1307
1320
  }
1308
1321
  const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
1309
1322
  const integerDigits = Math.max(configuredDigits, observedDigits);
1310
- const integerPart = "8".repeat(integerDigits);
1323
+ const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1311
1324
  const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
1312
1325
  return `${integerPart}${decimalPart}`;
1313
1326
  };
@@ -2982,6 +2995,25 @@ function createChart(element, options = {}) {
2982
2995
  }
2983
2996
  ctx.restore();
2984
2997
  }
2998
+ if (crosshair.sideHintLeft || crosshair.sideHintRight) {
2999
+ ctx.save();
3000
+ ctx.font = `600 11px ${mergedOptions.fontFamily}`;
3001
+ ctx.textBaseline = "middle";
3002
+ ctx.setLineDash([]);
3003
+ const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
3004
+ const hintGap = 8;
3005
+ if (crosshair.sideHintLeft) {
3006
+ ctx.fillStyle = crosshair.sideHintLeftColor;
3007
+ ctx.textAlign = "right";
3008
+ ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
3009
+ }
3010
+ if (crosshair.sideHintRight) {
3011
+ ctx.fillStyle = crosshair.sideHintRightColor;
3012
+ ctx.textAlign = "left";
3013
+ ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
3014
+ }
3015
+ ctx.restore();
3016
+ }
2985
3017
  }
2986
3018
  ctx.restore();
2987
3019
  const positionAxisGutter = Math.max(0, width - chartRight);
@@ -3406,16 +3438,18 @@ function createChart(element, options = {}) {
3406
3438
  ctx.font = prevFont;
3407
3439
  }
3408
3440
  }
3441
+ const axisStepMs = getTimeStepMs();
3442
+ const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
3443
+ let prevAxisTickTime = null;
3409
3444
  for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
3410
3445
  const tickTime = getTimeForIndex(index);
3411
3446
  if (!tickTime) {
3412
3447
  continue;
3413
3448
  }
3414
3449
  const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
3415
- const timeLabel = tickTime.toLocaleDateString(void 0, {
3416
- month: "short",
3417
- day: "numeric"
3418
- });
3450
+ const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
3451
+ const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
3452
+ prevAxisTickTime = tickTime;
3419
3453
  const prevFont = ctx.font;
3420
3454
  ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
3421
3455
  drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
package/dist/index.cjs CHANGED
@@ -75,7 +75,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
75
75
  priceActionButtonSize: 16,
76
76
  priceActionButtonGap: 4,
77
77
  priceActionButtonRounded: true,
78
- priceActionButtonBorderRadius: 8
78
+ priceActionButtonBorderRadius: 8,
79
+ sideHintLeft: "",
80
+ sideHintRight: "",
81
+ sideHintLeftColor: "#26a69a",
82
+ sideHintRightColor: "#ef5350"
79
83
  };
80
84
  var DEFAULT_WATERMARK_OPTIONS = {
81
85
  visible: false,
@@ -1292,10 +1296,19 @@ function createChart(element, options = {}) {
1292
1296
  }
1293
1297
  return Math.round(price / tickSize) * tickSize;
1294
1298
  };
1299
+ const groupThousands = (value, decimals) => {
1300
+ const negative = value < 0;
1301
+ const fixed = Math.abs(value).toFixed(decimals);
1302
+ const dot = fixed.indexOf(".");
1303
+ const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
1304
+ const decPart = dot === -1 ? "" : fixed.slice(dot);
1305
+ const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1306
+ return `${negative ? "-" : ""}${grouped}${decPart}`;
1307
+ };
1295
1308
  const formatPrice = (price) => {
1296
1309
  const rounded = quantizeToTickSize(price);
1297
1310
  const decimals = getDisplayPriceDecimals();
1298
- return rounded.toFixed(decimals);
1311
+ return groupThousands(rounded, decimals);
1299
1312
  };
1300
1313
  const roundToPricePrecision = (price) => {
1301
1314
  const rounded = quantizeToTickSize(price);
@@ -1333,7 +1346,7 @@ function createChart(element, options = {}) {
1333
1346
  }
1334
1347
  const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
1335
1348
  const integerDigits = Math.max(configuredDigits, observedDigits);
1336
- const integerPart = "8".repeat(integerDigits);
1349
+ const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1337
1350
  const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
1338
1351
  return `${integerPart}${decimalPart}`;
1339
1352
  };
@@ -3008,6 +3021,25 @@ function createChart(element, options = {}) {
3008
3021
  }
3009
3022
  ctx.restore();
3010
3023
  }
3024
+ if (crosshair.sideHintLeft || crosshair.sideHintRight) {
3025
+ ctx.save();
3026
+ ctx.font = `600 11px ${mergedOptions.fontFamily}`;
3027
+ ctx.textBaseline = "middle";
3028
+ ctx.setLineDash([]);
3029
+ const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
3030
+ const hintGap = 8;
3031
+ if (crosshair.sideHintLeft) {
3032
+ ctx.fillStyle = crosshair.sideHintLeftColor;
3033
+ ctx.textAlign = "right";
3034
+ ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
3035
+ }
3036
+ if (crosshair.sideHintRight) {
3037
+ ctx.fillStyle = crosshair.sideHintRightColor;
3038
+ ctx.textAlign = "left";
3039
+ ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
3040
+ }
3041
+ ctx.restore();
3042
+ }
3011
3043
  }
3012
3044
  ctx.restore();
3013
3045
  const positionAxisGutter = Math.max(0, width - chartRight);
@@ -3432,16 +3464,18 @@ function createChart(element, options = {}) {
3432
3464
  ctx.font = prevFont;
3433
3465
  }
3434
3466
  }
3467
+ const axisStepMs = getTimeStepMs();
3468
+ const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
3469
+ let prevAxisTickTime = null;
3435
3470
  for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
3436
3471
  const tickTime = getTimeForIndex(index);
3437
3472
  if (!tickTime) {
3438
3473
  continue;
3439
3474
  }
3440
3475
  const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
3441
- const timeLabel = tickTime.toLocaleDateString(void 0, {
3442
- month: "short",
3443
- day: "numeric"
3444
- });
3476
+ const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
3477
+ const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
3478
+ prevAxisTickTime = tickTime;
3445
3479
  const prevFont = ctx.font;
3446
3480
  ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
3447
3481
  drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
package/dist/index.d.cts CHANGED
@@ -241,6 +241,10 @@ interface CrosshairOptions {
241
241
  priceActionButtonGap?: number;
242
242
  priceActionButtonRounded?: boolean;
243
243
  priceActionButtonBorderRadius?: number;
244
+ sideHintLeft?: string;
245
+ sideHintRight?: string;
246
+ sideHintLeftColor?: string;
247
+ sideHintRightColor?: string;
244
248
  }
245
249
  interface WatermarkOptions {
246
250
  visible?: boolean;
package/dist/index.d.ts CHANGED
@@ -241,6 +241,10 @@ interface CrosshairOptions {
241
241
  priceActionButtonGap?: number;
242
242
  priceActionButtonRounded?: boolean;
243
243
  priceActionButtonBorderRadius?: number;
244
+ sideHintLeft?: string;
245
+ sideHintRight?: string;
246
+ sideHintLeftColor?: string;
247
+ sideHintRightColor?: string;
244
248
  }
245
249
  interface WatermarkOptions {
246
250
  visible?: boolean;
package/dist/index.js CHANGED
@@ -49,7 +49,11 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
49
49
  priceActionButtonSize: 16,
50
50
  priceActionButtonGap: 4,
51
51
  priceActionButtonRounded: true,
52
- priceActionButtonBorderRadius: 8
52
+ priceActionButtonBorderRadius: 8,
53
+ sideHintLeft: "",
54
+ sideHintRight: "",
55
+ sideHintLeftColor: "#26a69a",
56
+ sideHintRightColor: "#ef5350"
53
57
  };
54
58
  var DEFAULT_WATERMARK_OPTIONS = {
55
59
  visible: false,
@@ -1266,10 +1270,19 @@ function createChart(element, options = {}) {
1266
1270
  }
1267
1271
  return Math.round(price / tickSize) * tickSize;
1268
1272
  };
1273
+ const groupThousands = (value, decimals) => {
1274
+ const negative = value < 0;
1275
+ const fixed = Math.abs(value).toFixed(decimals);
1276
+ const dot = fixed.indexOf(".");
1277
+ const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
1278
+ const decPart = dot === -1 ? "" : fixed.slice(dot);
1279
+ const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1280
+ return `${negative ? "-" : ""}${grouped}${decPart}`;
1281
+ };
1269
1282
  const formatPrice = (price) => {
1270
1283
  const rounded = quantizeToTickSize(price);
1271
1284
  const decimals = getDisplayPriceDecimals();
1272
- return rounded.toFixed(decimals);
1285
+ return groupThousands(rounded, decimals);
1273
1286
  };
1274
1287
  const roundToPricePrecision = (price) => {
1275
1288
  const rounded = quantizeToTickSize(price);
@@ -1307,7 +1320,7 @@ function createChart(element, options = {}) {
1307
1320
  }
1308
1321
  const observedDigits = maxAbsPrice >= 1 ? Math.floor(Math.log10(maxAbsPrice)) + 1 : 1;
1309
1322
  const integerDigits = Math.max(configuredDigits, observedDigits);
1310
- const integerPart = "8".repeat(integerDigits);
1323
+ const integerPart = "8".repeat(integerDigits).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1311
1324
  const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
1312
1325
  return `${integerPart}${decimalPart}`;
1313
1326
  };
@@ -2982,6 +2995,25 @@ function createChart(element, options = {}) {
2982
2995
  }
2983
2996
  ctx.restore();
2984
2997
  }
2998
+ if (crosshair.sideHintLeft || crosshair.sideHintRight) {
2999
+ ctx.save();
3000
+ ctx.font = `600 11px ${mergedOptions.fontFamily}`;
3001
+ ctx.textBaseline = "middle";
3002
+ ctx.setLineDash([]);
3003
+ const hintY = clamp(cy - 14, chartTop + 8, chartBottom - 8);
3004
+ const hintGap = 8;
3005
+ if (crosshair.sideHintLeft) {
3006
+ ctx.fillStyle = crosshair.sideHintLeftColor;
3007
+ ctx.textAlign = "right";
3008
+ ctx.fillText(crosshair.sideHintLeft, cx - hintGap, hintY);
3009
+ }
3010
+ if (crosshair.sideHintRight) {
3011
+ ctx.fillStyle = crosshair.sideHintRightColor;
3012
+ ctx.textAlign = "left";
3013
+ ctx.fillText(crosshair.sideHintRight, cx + hintGap, hintY);
3014
+ }
3015
+ ctx.restore();
3016
+ }
2985
3017
  }
2986
3018
  ctx.restore();
2987
3019
  const positionAxisGutter = Math.max(0, width - chartRight);
@@ -3406,16 +3438,18 @@ function createChart(element, options = {}) {
3406
3438
  ctx.font = prevFont;
3407
3439
  }
3408
3440
  }
3441
+ const axisStepMs = getTimeStepMs();
3442
+ const axisIntraday = axisStepMs > 0 && axisStepMs < 24 * 60 * 60 * 1e3;
3443
+ let prevAxisTickTime = null;
3409
3444
  for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
3410
3445
  const tickTime = getTimeForIndex(index);
3411
3446
  if (!tickTime) {
3412
3447
  continue;
3413
3448
  }
3414
3449
  const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
3415
- const timeLabel = tickTime.toLocaleDateString(void 0, {
3416
- month: "short",
3417
- day: "numeric"
3418
- });
3450
+ const isNewDay = !prevAxisTickTime || prevAxisTickTime.getDate() !== tickTime.getDate() || prevAxisTickTime.getMonth() !== tickTime.getMonth() || prevAxisTickTime.getFullYear() !== tickTime.getFullYear();
3451
+ const timeLabel = axisIntraday && !isNewDay ? tickTime.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }) : tickTime.toLocaleDateString(void 0, { month: "short", day: "numeric" });
3452
+ prevAxisTickTime = tickTime;
3419
3453
  const prevFont = ctx.font;
3420
3454
  ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
3421
3455
  drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.103",
3
+ "version": "0.1.105",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",