hyperprop-charting-library 0.1.97 → 0.1.99

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.
@@ -2542,10 +2542,19 @@ function createChart(element, options = {}) {
2542
2542
  const drawPositionPill = (text, lineY, place, bg) => {
2543
2543
  const lines = Array.isArray(text) ? text : [text];
2544
2544
  const prevFont = ctx.font;
2545
+ const prevAlign = ctx.textAlign;
2545
2546
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2546
2547
  const padding = 6;
2547
2548
  const lineH = 14;
2548
- const textW = Math.max(...lines.map((line) => ctx.measureText(line).width));
2549
+ const isDigit = (ch) => ch >= "0" && ch <= "9";
2550
+ const digitW = ctx.measureText("0").width;
2551
+ const charAdvance = (ch) => isDigit(ch) ? digitW : ctx.measureText(ch).width;
2552
+ const lineWidth = (line) => {
2553
+ let w = 0;
2554
+ for (const ch of line) w += charAdvance(ch);
2555
+ return w;
2556
+ };
2557
+ const textW = Math.max(...lines.map(lineWidth));
2549
2558
  const pillW = textW + padding * 2;
2550
2559
  const pillH = lines.length === 1 ? 18 : lines.length * lineH + 6;
2551
2560
  const centerY = place === "above" ? lineY - pillH / 2 - PILL_GAP : lineY + pillH / 2 + PILL_GAP;
@@ -2554,11 +2563,24 @@ function createChart(element, options = {}) {
2554
2563
  ctx.fillStyle = bg;
2555
2564
  fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2556
2565
  ctx.fillStyle = labelTextColor;
2557
- ctx.textAlign = "center";
2566
+ ctx.textAlign = "left";
2558
2567
  ctx.textBaseline = "middle";
2559
2568
  const startY = pillY + pillH / 2 - (lines.length - 1) * lineH / 2;
2560
- lines.forEach((line, lineIndex) => ctx.fillText(line, cx, startY + lineIndex * lineH));
2569
+ lines.forEach((line, lineIndex) => {
2570
+ let x = cx - lineWidth(line) / 2;
2571
+ const y = startY + lineIndex * lineH;
2572
+ for (const ch of line) {
2573
+ if (isDigit(ch)) {
2574
+ ctx.fillText(ch, x + (digitW - ctx.measureText(ch).width) / 2, y);
2575
+ x += digitW;
2576
+ } else {
2577
+ ctx.fillText(ch, x, y);
2578
+ x += ctx.measureText(ch).width;
2579
+ }
2580
+ }
2581
+ });
2561
2582
  ctx.font = prevFont;
2583
+ ctx.textAlign = prevAlign;
2562
2584
  };
2563
2585
  const boxTopY = Math.min(targetY, stopY);
2564
2586
  const boxBotY = Math.max(targetY, stopY);
@@ -2516,10 +2516,19 @@ function createChart(element, options = {}) {
2516
2516
  const drawPositionPill = (text, lineY, place, bg) => {
2517
2517
  const lines = Array.isArray(text) ? text : [text];
2518
2518
  const prevFont = ctx.font;
2519
+ const prevAlign = ctx.textAlign;
2519
2520
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2520
2521
  const padding = 6;
2521
2522
  const lineH = 14;
2522
- const textW = Math.max(...lines.map((line) => ctx.measureText(line).width));
2523
+ const isDigit = (ch) => ch >= "0" && ch <= "9";
2524
+ const digitW = ctx.measureText("0").width;
2525
+ const charAdvance = (ch) => isDigit(ch) ? digitW : ctx.measureText(ch).width;
2526
+ const lineWidth = (line) => {
2527
+ let w = 0;
2528
+ for (const ch of line) w += charAdvance(ch);
2529
+ return w;
2530
+ };
2531
+ const textW = Math.max(...lines.map(lineWidth));
2523
2532
  const pillW = textW + padding * 2;
2524
2533
  const pillH = lines.length === 1 ? 18 : lines.length * lineH + 6;
2525
2534
  const centerY = place === "above" ? lineY - pillH / 2 - PILL_GAP : lineY + pillH / 2 + PILL_GAP;
@@ -2528,11 +2537,24 @@ function createChart(element, options = {}) {
2528
2537
  ctx.fillStyle = bg;
2529
2538
  fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2530
2539
  ctx.fillStyle = labelTextColor;
2531
- ctx.textAlign = "center";
2540
+ ctx.textAlign = "left";
2532
2541
  ctx.textBaseline = "middle";
2533
2542
  const startY = pillY + pillH / 2 - (lines.length - 1) * lineH / 2;
2534
- lines.forEach((line, lineIndex) => ctx.fillText(line, cx, startY + lineIndex * lineH));
2543
+ lines.forEach((line, lineIndex) => {
2544
+ let x = cx - lineWidth(line) / 2;
2545
+ const y = startY + lineIndex * lineH;
2546
+ for (const ch of line) {
2547
+ if (isDigit(ch)) {
2548
+ ctx.fillText(ch, x + (digitW - ctx.measureText(ch).width) / 2, y);
2549
+ x += digitW;
2550
+ } else {
2551
+ ctx.fillText(ch, x, y);
2552
+ x += ctx.measureText(ch).width;
2553
+ }
2554
+ }
2555
+ });
2535
2556
  ctx.font = prevFont;
2557
+ ctx.textAlign = prevAlign;
2536
2558
  };
2537
2559
  const boxTopY = Math.min(targetY, stopY);
2538
2560
  const boxBotY = Math.max(targetY, stopY);
package/dist/index.cjs CHANGED
@@ -2542,10 +2542,19 @@ function createChart(element, options = {}) {
2542
2542
  const drawPositionPill = (text, lineY, place, bg) => {
2543
2543
  const lines = Array.isArray(text) ? text : [text];
2544
2544
  const prevFont = ctx.font;
2545
+ const prevAlign = ctx.textAlign;
2545
2546
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2546
2547
  const padding = 6;
2547
2548
  const lineH = 14;
2548
- const textW = Math.max(...lines.map((line) => ctx.measureText(line).width));
2549
+ const isDigit = (ch) => ch >= "0" && ch <= "9";
2550
+ const digitW = ctx.measureText("0").width;
2551
+ const charAdvance = (ch) => isDigit(ch) ? digitW : ctx.measureText(ch).width;
2552
+ const lineWidth = (line) => {
2553
+ let w = 0;
2554
+ for (const ch of line) w += charAdvance(ch);
2555
+ return w;
2556
+ };
2557
+ const textW = Math.max(...lines.map(lineWidth));
2549
2558
  const pillW = textW + padding * 2;
2550
2559
  const pillH = lines.length === 1 ? 18 : lines.length * lineH + 6;
2551
2560
  const centerY = place === "above" ? lineY - pillH / 2 - PILL_GAP : lineY + pillH / 2 + PILL_GAP;
@@ -2554,11 +2563,24 @@ function createChart(element, options = {}) {
2554
2563
  ctx.fillStyle = bg;
2555
2564
  fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2556
2565
  ctx.fillStyle = labelTextColor;
2557
- ctx.textAlign = "center";
2566
+ ctx.textAlign = "left";
2558
2567
  ctx.textBaseline = "middle";
2559
2568
  const startY = pillY + pillH / 2 - (lines.length - 1) * lineH / 2;
2560
- lines.forEach((line, lineIndex) => ctx.fillText(line, cx, startY + lineIndex * lineH));
2569
+ lines.forEach((line, lineIndex) => {
2570
+ let x = cx - lineWidth(line) / 2;
2571
+ const y = startY + lineIndex * lineH;
2572
+ for (const ch of line) {
2573
+ if (isDigit(ch)) {
2574
+ ctx.fillText(ch, x + (digitW - ctx.measureText(ch).width) / 2, y);
2575
+ x += digitW;
2576
+ } else {
2577
+ ctx.fillText(ch, x, y);
2578
+ x += ctx.measureText(ch).width;
2579
+ }
2580
+ }
2581
+ });
2561
2582
  ctx.font = prevFont;
2583
+ ctx.textAlign = prevAlign;
2562
2584
  };
2563
2585
  const boxTopY = Math.min(targetY, stopY);
2564
2586
  const boxBotY = Math.max(targetY, stopY);
package/dist/index.js CHANGED
@@ -2516,10 +2516,19 @@ function createChart(element, options = {}) {
2516
2516
  const drawPositionPill = (text, lineY, place, bg) => {
2517
2517
  const lines = Array.isArray(text) ? text : [text];
2518
2518
  const prevFont = ctx.font;
2519
+ const prevAlign = ctx.textAlign;
2519
2520
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2520
2521
  const padding = 6;
2521
2522
  const lineH = 14;
2522
- const textW = Math.max(...lines.map((line) => ctx.measureText(line).width));
2523
+ const isDigit = (ch) => ch >= "0" && ch <= "9";
2524
+ const digitW = ctx.measureText("0").width;
2525
+ const charAdvance = (ch) => isDigit(ch) ? digitW : ctx.measureText(ch).width;
2526
+ const lineWidth = (line) => {
2527
+ let w = 0;
2528
+ for (const ch of line) w += charAdvance(ch);
2529
+ return w;
2530
+ };
2531
+ const textW = Math.max(...lines.map(lineWidth));
2523
2532
  const pillW = textW + padding * 2;
2524
2533
  const pillH = lines.length === 1 ? 18 : lines.length * lineH + 6;
2525
2534
  const centerY = place === "above" ? lineY - pillH / 2 - PILL_GAP : lineY + pillH / 2 + PILL_GAP;
@@ -2528,11 +2537,24 @@ function createChart(element, options = {}) {
2528
2537
  ctx.fillStyle = bg;
2529
2538
  fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2530
2539
  ctx.fillStyle = labelTextColor;
2531
- ctx.textAlign = "center";
2540
+ ctx.textAlign = "left";
2532
2541
  ctx.textBaseline = "middle";
2533
2542
  const startY = pillY + pillH / 2 - (lines.length - 1) * lineH / 2;
2534
- lines.forEach((line, lineIndex) => ctx.fillText(line, cx, startY + lineIndex * lineH));
2543
+ lines.forEach((line, lineIndex) => {
2544
+ let x = cx - lineWidth(line) / 2;
2545
+ const y = startY + lineIndex * lineH;
2546
+ for (const ch of line) {
2547
+ if (isDigit(ch)) {
2548
+ ctx.fillText(ch, x + (digitW - ctx.measureText(ch).width) / 2, y);
2549
+ x += digitW;
2550
+ } else {
2551
+ ctx.fillText(ch, x, y);
2552
+ x += ctx.measureText(ch).width;
2553
+ }
2554
+ }
2555
+ });
2535
2556
  ctx.font = prevFont;
2557
+ ctx.textAlign = prevAlign;
2536
2558
  };
2537
2559
  const boxTopY = Math.min(targetY, stopY);
2538
2560
  const boxBotY = Math.max(targetY, stopY);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.97",
3
+ "version": "0.1.99",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",