dsh-token-pulse 0.4.3 → 0.4.5
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/lib/client.js +316 -329
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -440,29 +440,7 @@ window.__ModuleLoader__.load({
|
|
|
440
440
|
if (day.totalTokens === 0) return `${day.dayKey}: No usage`;
|
|
441
441
|
return `${day.dayKey}: ${formatTokensShort$1(day.totalTokens)} tokens`;
|
|
442
442
|
}
|
|
443
|
-
function
|
|
444
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
445
|
-
title: tooltipTotal(day),
|
|
446
|
-
"aria-label": tooltipTotal(day),
|
|
447
|
-
style: {
|
|
448
|
-
width: size,
|
|
449
|
-
height: size,
|
|
450
|
-
borderRadius: 3,
|
|
451
|
-
background: {
|
|
452
|
-
0: "var(--dsw-alias-bg-layer-2, #ebedf0)",
|
|
453
|
-
1: "#c6e48b",
|
|
454
|
-
2: "#7bc96f",
|
|
455
|
-
3: "#239a3b",
|
|
456
|
-
4: "#196127"
|
|
457
|
-
}[level],
|
|
458
|
-
border: level === 0 ? "1px solid var(--dsw-alias-border-l2, #e5e7eb)" : "1px solid transparent",
|
|
459
|
-
boxSizing: "border-box",
|
|
460
|
-
cursor: "pointer",
|
|
461
|
-
flexShrink: 0
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
function HourStrip({ day, hourLevels }) {
|
|
443
|
+
function HourStrip({ day, hourLevels, baseDelay = 0 }) {
|
|
466
444
|
const hourly = day.hourlyTokens ?? new Array(24).fill(0);
|
|
467
445
|
const colors = {
|
|
468
446
|
0: "var(--dsw-alias-bg-layer-2, #ebedf0)",
|
|
@@ -483,9 +461,11 @@ window.__ModuleLoader__.load({
|
|
|
483
461
|
const lv = hourLevels[h] ?? 0;
|
|
484
462
|
const hh = v === 0 ? `${String(h).padStart(2, "0")}:00 — No usage` : `${String(h).padStart(2, "0")}:00 — ${formatTokensShort$1(v)} tokens`;
|
|
485
463
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
464
|
+
className: "dtp-hm-bar",
|
|
486
465
|
title: hh,
|
|
487
466
|
"aria-label": hh,
|
|
488
467
|
style: {
|
|
468
|
+
animationDelay: `${baseDelay + h * 12}ms`,
|
|
489
469
|
flex: 1,
|
|
490
470
|
height: 6 + lv * 4,
|
|
491
471
|
borderRadius: 1,
|
|
@@ -527,49 +507,6 @@ window.__ModuleLoader__.load({
|
|
|
527
507
|
}, v))
|
|
528
508
|
});
|
|
529
509
|
}
|
|
530
|
-
function MonthHeader({ weeks, cellSize }) {
|
|
531
|
-
const seen = /* @__PURE__ */ new Set();
|
|
532
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
533
|
-
style: {
|
|
534
|
-
display: "flex",
|
|
535
|
-
gap: 3,
|
|
536
|
-
paddingLeft: cellSize + 20,
|
|
537
|
-
marginBottom: 2
|
|
538
|
-
},
|
|
539
|
-
children: weeks.map((week, i) => {
|
|
540
|
-
const m = week.find((d) => d.totalTokens !== -1)?.dayKey.slice(0, 7) ?? "";
|
|
541
|
-
let label = "";
|
|
542
|
-
if (m && !seen.has(m)) {
|
|
543
|
-
seen.add(m);
|
|
544
|
-
label = [
|
|
545
|
-
"Jan",
|
|
546
|
-
"Feb",
|
|
547
|
-
"Mar",
|
|
548
|
-
"Apr",
|
|
549
|
-
"May",
|
|
550
|
-
"Jun",
|
|
551
|
-
"Jul",
|
|
552
|
-
"Aug",
|
|
553
|
-
"Sep",
|
|
554
|
-
"Oct",
|
|
555
|
-
"Nov",
|
|
556
|
-
"Dec"
|
|
557
|
-
][Number(m.slice(5, 7)) - 1];
|
|
558
|
-
}
|
|
559
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
560
|
-
style: {
|
|
561
|
-
width: cellSize,
|
|
562
|
-
fontSize: 10,
|
|
563
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
564
|
-
lineHeight: "12px",
|
|
565
|
-
whiteSpace: "nowrap",
|
|
566
|
-
overflow: "visible"
|
|
567
|
-
},
|
|
568
|
-
children: label
|
|
569
|
-
}, i);
|
|
570
|
-
})
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
510
|
function GitHubGrid({ days, t, cellSize, twoRows, isEn, dayLevels }) {
|
|
574
511
|
const weeks = [];
|
|
575
512
|
let cur = [];
|
|
@@ -613,191 +550,207 @@ window.__ModuleLoader__.load({
|
|
|
613
550
|
});
|
|
614
551
|
weeks.push(cur);
|
|
615
552
|
}
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
553
|
+
const specHistoryRef = react.useRef(/* @__PURE__ */ new Map());
|
|
554
|
+
const labelHistoryRef = react.useRef(/* @__PURE__ */ new Set());
|
|
555
|
+
const gap = 3;
|
|
556
|
+
const colGap = cellSize >= 22 ? 10 : 5;
|
|
557
|
+
const headerH = 16;
|
|
558
|
+
const blockH = 7 * cellSize + 18;
|
|
559
|
+
const rowGap = 34;
|
|
560
|
+
const twoRowsSplit = !!(twoRows && weeks.length > 26);
|
|
561
|
+
const labelW = cellSize + 24;
|
|
562
|
+
const dayByKey = new Map(days.map((d) => [d.dayKey, d]));
|
|
563
|
+
const specs = /* @__PURE__ */ new Map();
|
|
564
|
+
const monthLabels = [];
|
|
565
|
+
const colX = (wi) => labelW + wi * (cellSize + colGap);
|
|
566
|
+
const place = (ws, yBase) => {
|
|
567
|
+
const seen = /* @__PURE__ */ new Set();
|
|
568
|
+
ws.forEach((week, wi) => {
|
|
569
|
+
const m = week.find((d) => d.totalTokens !== -1)?.dayKey.slice(0, 7) ?? "";
|
|
570
|
+
if (m && !seen.has(m)) {
|
|
571
|
+
seen.add(m);
|
|
572
|
+
monthLabels.push({
|
|
573
|
+
key: m,
|
|
574
|
+
x: colX(wi),
|
|
575
|
+
y: yBase - 14
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
week.forEach((d, r) => {
|
|
579
|
+
if (d.totalTokens === -1) return;
|
|
580
|
+
specs.set(d.dayKey, {
|
|
581
|
+
x: colX(wi),
|
|
582
|
+
y: yBase + r * (cellSize + gap)
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
};
|
|
587
|
+
let ncols;
|
|
588
|
+
if (twoRowsSplit) {
|
|
638
589
|
const mid = Math.ceil(weeks.length / 2);
|
|
639
590
|
const top = weeks.slice(0, mid);
|
|
640
591
|
const bot = weeks.slice(mid);
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
},
|
|
648
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthHeader, {
|
|
649
|
-
weeks: top,
|
|
650
|
-
cellSize
|
|
651
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
652
|
-
style: {
|
|
653
|
-
display: "flex",
|
|
654
|
-
gap: 3
|
|
655
|
-
},
|
|
656
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
657
|
-
style: {
|
|
658
|
-
display: "flex",
|
|
659
|
-
flexDirection: "column",
|
|
660
|
-
gap: 3
|
|
661
|
-
},
|
|
662
|
-
children: [
|
|
663
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
664
|
-
style: {
|
|
665
|
-
height: cellSize,
|
|
666
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
667
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
668
|
-
lineHeight: `${cellSize}px`
|
|
669
|
-
},
|
|
670
|
-
children: isEn ? "Sun" : "Mon"
|
|
671
|
-
}),
|
|
672
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } }),
|
|
673
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
674
|
-
style: {
|
|
675
|
-
height: cellSize,
|
|
676
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
677
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
678
|
-
lineHeight: `${cellSize}px`
|
|
679
|
-
},
|
|
680
|
-
children: isEn ? "Tue" : "Wed"
|
|
681
|
-
}),
|
|
682
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } }),
|
|
683
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
684
|
-
style: {
|
|
685
|
-
height: cellSize,
|
|
686
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
687
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
688
|
-
lineHeight: `${cellSize}px`
|
|
689
|
-
},
|
|
690
|
-
children: isEn ? "Thu" : "Fri"
|
|
691
|
-
}),
|
|
692
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } }),
|
|
693
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } })
|
|
694
|
-
]
|
|
695
|
-
}), renderWeeks(top)]
|
|
696
|
-
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthHeader, {
|
|
697
|
-
weeks: bot,
|
|
698
|
-
cellSize
|
|
699
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
700
|
-
style: {
|
|
701
|
-
display: "flex",
|
|
702
|
-
gap: 3
|
|
703
|
-
},
|
|
704
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
705
|
-
style: {
|
|
706
|
-
display: "flex",
|
|
707
|
-
flexDirection: "column",
|
|
708
|
-
gap: 3
|
|
709
|
-
},
|
|
710
|
-
children: [
|
|
711
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
712
|
-
style: {
|
|
713
|
-
height: cellSize,
|
|
714
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
715
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
716
|
-
lineHeight: `${cellSize}px`
|
|
717
|
-
},
|
|
718
|
-
children: isEn ? "Sun" : "Mon"
|
|
719
|
-
}),
|
|
720
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } }),
|
|
721
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
722
|
-
style: {
|
|
723
|
-
height: cellSize,
|
|
724
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
725
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
726
|
-
lineHeight: `${cellSize}px`
|
|
727
|
-
},
|
|
728
|
-
children: isEn ? "Tue" : "Wed"
|
|
729
|
-
}),
|
|
730
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } }),
|
|
731
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
732
|
-
style: {
|
|
733
|
-
height: cellSize,
|
|
734
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
735
|
-
color: "var(--dsw-alias-label-tertiary)",
|
|
736
|
-
lineHeight: `${cellSize}px`
|
|
737
|
-
},
|
|
738
|
-
children: isEn ? "Thu" : "Fri"
|
|
739
|
-
}),
|
|
740
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } }),
|
|
741
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { height: cellSize } })
|
|
742
|
-
]
|
|
743
|
-
}), renderWeeks(bot)]
|
|
744
|
-
})] })]
|
|
745
|
-
});
|
|
592
|
+
place(top, headerH);
|
|
593
|
+
place(bot, headerH + blockH + rowGap);
|
|
594
|
+
ncols = Math.max(top.length, bot.length);
|
|
595
|
+
} else {
|
|
596
|
+
place(weeks, headerH);
|
|
597
|
+
ncols = weeks.length;
|
|
746
598
|
}
|
|
747
|
-
|
|
599
|
+
const width = labelW + ncols * cellSize + Math.max(0, ncols - 1) * colGap;
|
|
600
|
+
const height = twoRowsSplit ? 32 + blockH * 2 + rowGap : headerH + blockH;
|
|
601
|
+
const prevSpecs = specHistoryRef.current;
|
|
602
|
+
const items = [...specs.entries()].map(([k, s]) => ({
|
|
603
|
+
k,
|
|
604
|
+
s,
|
|
605
|
+
isNew: !prevSpecs.has(k)
|
|
606
|
+
}));
|
|
607
|
+
specHistoryRef.current = new Map(specs);
|
|
608
|
+
const prevLabelKeys = labelHistoryRef.current;
|
|
609
|
+
const labelIsNew = (k) => !prevLabelKeys.has(k);
|
|
610
|
+
labelHistoryRef.current = new Set(monthLabels.map((m) => m.key));
|
|
611
|
+
const [ghosts, setGhosts] = react.useState([]);
|
|
612
|
+
react.useEffect(() => {
|
|
613
|
+
const removed = [];
|
|
614
|
+
for (const [k, s] of prevSpecs) if (!specs.has(k)) removed.push({
|
|
615
|
+
k,
|
|
616
|
+
x: s.x,
|
|
617
|
+
y: s.y
|
|
618
|
+
});
|
|
619
|
+
if (removed.length) {
|
|
620
|
+
setGhosts(removed);
|
|
621
|
+
const id = setTimeout(() => setGhosts([]), 300);
|
|
622
|
+
return () => clearTimeout(id);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
const colors = {
|
|
626
|
+
0: "var(--dsw-alias-bg-layer-2, #ebedf0)",
|
|
627
|
+
1: "#c6e48b",
|
|
628
|
+
2: "#7bc96f",
|
|
629
|
+
3: "#239a3b",
|
|
630
|
+
4: "#196127"
|
|
631
|
+
};
|
|
632
|
+
const dayNames = isEn ? [
|
|
633
|
+
"Sun",
|
|
634
|
+
"Mon",
|
|
635
|
+
"Tue",
|
|
636
|
+
"Wed",
|
|
637
|
+
"Thu",
|
|
638
|
+
"Fri",
|
|
639
|
+
"Sat"
|
|
640
|
+
] : [
|
|
641
|
+
"Mon",
|
|
642
|
+
"Tue",
|
|
643
|
+
"Wed",
|
|
644
|
+
"Thu",
|
|
645
|
+
"Fri",
|
|
646
|
+
"Sat",
|
|
647
|
+
"Sun"
|
|
648
|
+
];
|
|
649
|
+
const wdIdx = twoRowsSplit ? [
|
|
650
|
+
0,
|
|
651
|
+
2,
|
|
652
|
+
4
|
|
653
|
+
] : [
|
|
654
|
+
0,
|
|
655
|
+
1,
|
|
656
|
+
2,
|
|
657
|
+
3,
|
|
658
|
+
4,
|
|
659
|
+
5,
|
|
660
|
+
6
|
|
661
|
+
];
|
|
662
|
+
const wdFontSize = cellSize >= 22 ? 13 : 10;
|
|
663
|
+
const monthName = (m) => [
|
|
664
|
+
"Jan",
|
|
665
|
+
"Feb",
|
|
666
|
+
"Mar",
|
|
667
|
+
"Apr",
|
|
668
|
+
"May",
|
|
669
|
+
"Jun",
|
|
670
|
+
"Jul",
|
|
671
|
+
"Aug",
|
|
672
|
+
"Sep",
|
|
673
|
+
"Oct",
|
|
674
|
+
"Nov",
|
|
675
|
+
"Dec"
|
|
676
|
+
][Number(m.slice(5, 7)) - 1];
|
|
677
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
748
678
|
style: {
|
|
749
|
-
overflowX: "auto",
|
|
679
|
+
overflowX: twoRowsSplit ? "auto" : "hidden",
|
|
750
680
|
paddingBottom: 4,
|
|
751
681
|
display: "flex",
|
|
752
|
-
|
|
753
|
-
alignItems: "center",
|
|
754
|
-
gap: 6
|
|
682
|
+
justifyContent: "center"
|
|
755
683
|
},
|
|
756
|
-
children:
|
|
757
|
-
weeks,
|
|
758
|
-
cellSize
|
|
759
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
684
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
760
685
|
style: {
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
686
|
+
position: "relative",
|
|
687
|
+
width,
|
|
688
|
+
height,
|
|
689
|
+
flexShrink: 0
|
|
764
690
|
},
|
|
765
|
-
children: [
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
flexDirection: "column",
|
|
769
|
-
gap: 3,
|
|
770
|
-
fontSize: cellSize >= 22 ? 13 : 10,
|
|
771
|
-
color: "var(--dsw-alias-label-tertiary)"
|
|
772
|
-
},
|
|
773
|
-
children: (isEn ? [
|
|
774
|
-
"Sun",
|
|
775
|
-
"Mon",
|
|
776
|
-
"Tue",
|
|
777
|
-
"Wed",
|
|
778
|
-
"Thu",
|
|
779
|
-
"Fri",
|
|
780
|
-
"Sat"
|
|
781
|
-
] : [
|
|
782
|
-
"Mon",
|
|
783
|
-
"Tue",
|
|
784
|
-
"Wed",
|
|
785
|
-
"Thu",
|
|
786
|
-
"Fri",
|
|
787
|
-
"Sat",
|
|
788
|
-
"Sun"
|
|
789
|
-
]).map((w, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
691
|
+
children: [
|
|
692
|
+
monthLabels.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
693
|
+
className: `dtp-hm-label${labelIsNew(m.key) ? " dtp-hm-new" : ""}`,
|
|
790
694
|
style: {
|
|
791
|
-
|
|
792
|
-
|
|
695
|
+
transform: `translate(${m.x}px, ${m.y}px)`,
|
|
696
|
+
fontSize: 10,
|
|
697
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
698
|
+
lineHeight: "12px"
|
|
699
|
+
},
|
|
700
|
+
children: monthName(m.key)
|
|
701
|
+
}, m.key)),
|
|
702
|
+
wdIdx.map((i) => [{
|
|
703
|
+
y: headerH + i * (cellSize + gap),
|
|
704
|
+
k: `top-${i}`
|
|
705
|
+
}, ...twoRowsSplit ? [{
|
|
706
|
+
y: headerH + blockH + rowGap + i * (cellSize + gap),
|
|
707
|
+
k: `bot-${i}`
|
|
708
|
+
}] : []].map(({ y, k }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
709
|
+
className: "dtp-hm-label",
|
|
710
|
+
style: {
|
|
711
|
+
transform: `translate(0px, ${y}px)`,
|
|
712
|
+
fontSize: wdFontSize,
|
|
713
|
+
width: labelW - 6,
|
|
793
714
|
textAlign: "right",
|
|
794
715
|
paddingRight: 4,
|
|
716
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
717
|
+
lineHeight: `${cellSize}px`,
|
|
795
718
|
fontWeight: 500
|
|
796
719
|
},
|
|
797
|
-
children:
|
|
798
|
-
},
|
|
799
|
-
|
|
800
|
-
|
|
720
|
+
children: dayNames[i]
|
|
721
|
+
}, k))),
|
|
722
|
+
items.map(({ k, s, isNew }) => {
|
|
723
|
+
const d = dayByKey.get(k);
|
|
724
|
+
const lv = dayLevels.get(k) ?? 0;
|
|
725
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
726
|
+
title: tooltipTotal(d),
|
|
727
|
+
"aria-label": tooltipTotal(d),
|
|
728
|
+
className: `dtp-hm-cell${isNew ? " dtp-hm-new" : ""}`,
|
|
729
|
+
style: {
|
|
730
|
+
transform: `translate(${s.x}px, ${s.y}px)`,
|
|
731
|
+
width: cellSize,
|
|
732
|
+
height: cellSize,
|
|
733
|
+
borderRadius: 3,
|
|
734
|
+
background: colors[lv],
|
|
735
|
+
border: lv === 0 ? "1px solid var(--dsw-alias-border-l2, #e5e7eb)" : "1px solid transparent"
|
|
736
|
+
}
|
|
737
|
+
}, k);
|
|
738
|
+
}),
|
|
739
|
+
ghosts.map((g) => {
|
|
740
|
+
const lv = dayByKey.get(g.k) ? dayLevels.get(g.k) ?? 0 : 0;
|
|
741
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
742
|
+
className: "dtp-hm-cell dtp-hm-ghost",
|
|
743
|
+
style: {
|
|
744
|
+
transform: `translate(${g.x}px, ${g.y}px)`,
|
|
745
|
+
width: cellSize,
|
|
746
|
+
height: cellSize,
|
|
747
|
+
borderRadius: 3,
|
|
748
|
+
background: colors[lv]
|
|
749
|
+
}
|
|
750
|
+
}, g.k);
|
|
751
|
+
})
|
|
752
|
+
]
|
|
753
|
+
})
|
|
801
754
|
});
|
|
802
755
|
}
|
|
803
756
|
function CalendarGrid({ days, t, dayLevels, selectedKey, onSelect, isEn }) {
|
|
@@ -846,7 +799,7 @@ window.__ModuleLoader__.load({
|
|
|
846
799
|
] : header).map((w) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
847
800
|
style: {
|
|
848
801
|
textAlign: "center",
|
|
849
|
-
fontSize:
|
|
802
|
+
fontSize: 10,
|
|
850
803
|
fontWeight: 500,
|
|
851
804
|
color: "var(--dsw-alias-label-tertiary)"
|
|
852
805
|
},
|
|
@@ -911,6 +864,20 @@ window.__ModuleLoader__.load({
|
|
|
911
864
|
})]
|
|
912
865
|
});
|
|
913
866
|
}
|
|
867
|
+
const HM_ANIM_CSS = `
|
|
868
|
+
@keyframes dtp-hm-in { from { opacity: 0; transform: translateY(8px); } }
|
|
869
|
+
@keyframes dtp-hm-row { from { opacity: 0; transform: translateX(-14px); } }
|
|
870
|
+
@keyframes dtp-hm-grow { from { transform: scaleY(0); } }
|
|
871
|
+
@keyframes dtp-hm-fade { from { opacity: 0; } }
|
|
872
|
+
@keyframes dtp-hm-fadeout { to { opacity: 0; } }
|
|
873
|
+
.dtp-hm-view { animation: dtp-hm-in 0.4s ease; }
|
|
874
|
+
.dtp-hm-row { animation: dtp-hm-row 0.4s ease both; }
|
|
875
|
+
.dtp-hm-bar { transform-origin: bottom; animation: dtp-hm-grow 0.45s ease both; }
|
|
876
|
+
.dtp-hm-cell { position: absolute; box-sizing: border-box; transition: transform 0.45s ease, width 0.45s ease, height 0.45s ease, opacity 0.45s ease; }
|
|
877
|
+
.dtp-hm-new { animation: dtp-hm-fade 0.45s ease both; }
|
|
878
|
+
.dtp-hm-ghost { animation: dtp-hm-fadeout 0.25s ease forwards; }
|
|
879
|
+
.dtp-hm-label { position: absolute; white-space: nowrap; transition: transform 0.45s ease, opacity 0.45s ease; }
|
|
880
|
+
`;
|
|
914
881
|
function HeatmapGrid({ t, days, view, onViewChange, selectedKey, onSelect, isEn, thresholds = DEFAULT_THRESHOLDS }) {
|
|
915
882
|
const isWeek = view === "week";
|
|
916
883
|
const hasAny = days.some((d) => d.totalTokens > 0);
|
|
@@ -928,6 +895,7 @@ window.__ModuleLoader__.load({
|
|
|
928
895
|
gap: 6
|
|
929
896
|
},
|
|
930
897
|
children: [
|
|
898
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: HM_ANIM_CSS }),
|
|
931
899
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewSwitcher, {
|
|
932
900
|
t,
|
|
933
901
|
value: view,
|
|
@@ -950,7 +918,7 @@ window.__ModuleLoader__.load({
|
|
|
950
918
|
flexDirection: "column",
|
|
951
919
|
gap: 5
|
|
952
920
|
},
|
|
953
|
-
children: days.map((d) => {
|
|
921
|
+
children: days.map((d, di) => {
|
|
954
922
|
const wd = (/* @__PURE__ */ new Date(d.dayKey + "T12:00:00+08:00")).getDay();
|
|
955
923
|
const weekday = isEn ? [
|
|
956
924
|
"Sun",
|
|
@@ -971,9 +939,11 @@ window.__ModuleLoader__.load({
|
|
|
971
939
|
][(wd + 6) % 7];
|
|
972
940
|
const sel = d.dayKey === selectedKey;
|
|
973
941
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
942
|
+
className: "dtp-hm-row",
|
|
974
943
|
onClick: () => onSelect?.(sel ? null : d.dayKey),
|
|
975
944
|
title: tooltipTotal(d),
|
|
976
945
|
style: {
|
|
946
|
+
animationDelay: `${di * 45}ms`,
|
|
977
947
|
display: "flex",
|
|
978
948
|
alignItems: "center",
|
|
979
949
|
gap: 10,
|
|
@@ -1014,7 +984,8 @@ window.__ModuleLoader__.load({
|
|
|
1014
984
|
}),
|
|
1015
985
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HourStrip, {
|
|
1016
986
|
day: d,
|
|
1017
|
-
hourLevels: hourLevels.get(d.dayKey) ?? new Array(24).fill(0)
|
|
987
|
+
hourLevels: hourLevels.get(d.dayKey) ?? new Array(24).fill(0),
|
|
988
|
+
baseDelay: di * 45 + 140
|
|
1018
989
|
}),
|
|
1019
990
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1020
991
|
style: {
|
|
@@ -1029,27 +1000,27 @@ window.__ModuleLoader__.load({
|
|
|
1029
1000
|
]
|
|
1030
1001
|
}, d.dayKey);
|
|
1031
1002
|
})
|
|
1032
|
-
}) : view === "month" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
}),
|
|
1003
|
+
}, "week") : view === "month" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1004
|
+
className: "dtp-hm-view",
|
|
1005
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CalendarGrid, {
|
|
1006
|
+
days,
|
|
1007
|
+
t,
|
|
1008
|
+
dayLevels,
|
|
1009
|
+
selectedKey: selectedKey ?? null,
|
|
1010
|
+
onSelect: onSelect ?? (() => {}),
|
|
1011
|
+
isEn
|
|
1012
|
+
})
|
|
1013
|
+
}, "month") : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1014
|
+
className: "dtp-hm-view",
|
|
1015
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GitHubGrid, {
|
|
1016
|
+
days,
|
|
1017
|
+
t,
|
|
1018
|
+
cellSize,
|
|
1019
|
+
twoRows: view === "year",
|
|
1020
|
+
isEn,
|
|
1021
|
+
dayLevels
|
|
1022
|
+
})
|
|
1023
|
+
}, "github"),
|
|
1053
1024
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1054
1025
|
style: {
|
|
1055
1026
|
display: "flex",
|
|
@@ -1443,9 +1414,13 @@ window.__ModuleLoader__.load({
|
|
|
1443
1414
|
* has an identical command count no matter how many days it represents, so
|
|
1444
1415
|
* CSS `transition: d` can morph lines across range switches too — where raw
|
|
1445
1416
|
* bezier paths (M + n-1 C) have mismatched structures and would jump.
|
|
1446
|
-
*
|
|
1417
|
+
*
|
|
1418
|
+
* Default density 712 = 8 × 89 keeps the polyline visually identical to the
|
|
1419
|
+
* spline (≥ 8 samples per data interval for a 90-day series — the sparse 89
|
|
1420
|
+
* sample grid cut spike corners and left dots floating above the line) while
|
|
1421
|
+
* letting a 90-day series' sample xs land exactly ON its data points.
|
|
1447
1422
|
*/
|
|
1448
|
-
function seriesPathFixed(points, samples =
|
|
1423
|
+
function seriesPathFixed(points, samples = 712) {
|
|
1449
1424
|
if (points.length === 0) return "";
|
|
1450
1425
|
const x0 = points[0][0];
|
|
1451
1426
|
const x1 = points[points.length - 1][0];
|
|
@@ -1729,6 +1704,20 @@ window.__ModuleLoader__.load({
|
|
|
1729
1704
|
color: active ? "var(--dsw-alias-bg-layer-3)" : "var(--dsw-alias-label-secondary)",
|
|
1730
1705
|
transition: "background .25s ease, color .25s ease"
|
|
1731
1706
|
});
|
|
1707
|
+
const linePaths = react.useMemo(() => {
|
|
1708
|
+
const m = /* @__PURE__ */ new Map();
|
|
1709
|
+
if (chartType === "line") for (const s of series) {
|
|
1710
|
+
const pts = s.points.map((v, i) => [xOf(i), yOf(v)]);
|
|
1711
|
+
m.set(s.model, seriesPathFixed(pts));
|
|
1712
|
+
}
|
|
1713
|
+
return m;
|
|
1714
|
+
}, [
|
|
1715
|
+
series,
|
|
1716
|
+
yMax,
|
|
1717
|
+
chartType,
|
|
1718
|
+
dayKeys,
|
|
1719
|
+
hidden
|
|
1720
|
+
]);
|
|
1732
1721
|
const labelsNode = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: tickIdx.map((i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
1733
1722
|
x: 0,
|
|
1734
1723
|
y: 0,
|
|
@@ -1780,7 +1769,7 @@ window.__ModuleLoader__.load({
|
|
|
1780
1769
|
onAnimationEnd: onAnimEnd,
|
|
1781
1770
|
style: { transition: T_FADE },
|
|
1782
1771
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1783
|
-
d:
|
|
1772
|
+
d: linePaths.get(s.model) ?? "",
|
|
1784
1773
|
fill: "none",
|
|
1785
1774
|
stroke: color,
|
|
1786
1775
|
strokeWidth: 2,
|
|
@@ -2607,7 +2596,7 @@ window.__ModuleLoader__.load({
|
|
|
2607
2596
|
color: "var(--dsw-alias-label-tertiary)",
|
|
2608
2597
|
verticalAlign: "middle"
|
|
2609
2598
|
},
|
|
2610
|
-
children: ["v", "0.4.
|
|
2599
|
+
children: ["v", "0.4.5"]
|
|
2611
2600
|
})]
|
|
2612
2601
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2613
2602
|
style: {
|
|
@@ -2905,73 +2894,71 @@ window.__ModuleLoader__.load({
|
|
|
2905
2894
|
}) : null
|
|
2906
2895
|
]
|
|
2907
2896
|
}),
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2897
|
+
(() => {
|
|
2898
|
+
const dOf = (a) => /* @__PURE__ */ new Date(a + "T12:00:00+08:00");
|
|
2899
|
+
const btn = {
|
|
2900
|
+
padding: "4px 10px",
|
|
2901
|
+
fontSize: 12,
|
|
2902
|
+
borderRadius: 6,
|
|
2903
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
2904
|
+
background: "var(--dsw-alias-bg-layer-3)",
|
|
2905
|
+
cursor: "pointer"
|
|
2906
|
+
};
|
|
2907
|
+
const shiftDays = (n) => setAnchor((a) => {
|
|
2908
|
+
const d = dOf(a);
|
|
2909
|
+
d.setDate(d.getDate() + n);
|
|
2910
|
+
return new Date(d.getTime()).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
|
|
2911
|
+
});
|
|
2912
|
+
const shiftMonth = (n) => setAnchor((a) => {
|
|
2913
|
+
const d = dOf(a);
|
|
2914
|
+
d.setMonth(d.getMonth() + n);
|
|
2915
|
+
return new Date(d.getTime()).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
|
|
2916
|
+
});
|
|
2917
|
+
const aD = dOf(anchor);
|
|
2918
|
+
const fmtCn = (x) => `${x.getMonth() + 1}月${x.getDate()}日`;
|
|
2919
|
+
const prevLabel = view === "week" ? "‹ 上一周" : view === "month" ? "‹ 上一月" : view === "quarter" ? "‹ 上一季度" : "‹ 上一年";
|
|
2920
|
+
const nextLabel = view === "week" ? "下一周 ›" : view === "month" ? "下一月 ›" : view === "quarter" ? "下一季度 ›" : "下一年 ›";
|
|
2921
|
+
const prevLabelEn = view === "week" ? "‹ Prev Week" : view === "month" ? "‹ Prev Month" : view === "quarter" ? "‹ Prev Quarter" : "‹ Prev Year";
|
|
2922
|
+
const nextLabelEn = view === "week" ? "Next Week ›" : view === "month" ? "Next Month ›" : view === "quarter" ? "Next Quarter ›" : "Next Year ›";
|
|
2923
|
+
const label = view === "week" ? (() => {
|
|
2924
|
+
const d = aD;
|
|
2925
|
+
const dow = (d.getDay() + 6) % 7;
|
|
2926
|
+
const mon = new Date(d);
|
|
2927
|
+
mon.setDate(d.getDate() - dow);
|
|
2928
|
+
const sun = new Date(mon);
|
|
2929
|
+
sun.setDate(mon.getDate() + 6);
|
|
2930
|
+
const fmt = (x) => `${x.getMonth() + 1}/${x.getDate()}`;
|
|
2931
|
+
return lang === "en" ? `Week of ${fmt(mon)} - ${fmt(sun)}` : `${mon.getMonth() + 1}月${mon.getDate()}日 - ${sun.getMonth() + 1}月${sun.getDate()}日`;
|
|
2932
|
+
})() : view === "month" ? `${Number(anchor.slice(0, 4))}年${Number(anchor.slice(5, 7))}月` + (lang === "en" ? ` ${anchor.slice(0, 7)}` : "") : view === "quarter" ? lang === "en" ? `${(/* @__PURE__ */ new Date(aD.getTime() - 76896e5)).toLocaleDateString("en-CA")} - ${aD.toLocaleDateString("en-CA")}` : `${fmtCn(/* @__PURE__ */ new Date(aD.getTime() - 76896e5))} - ${fmtCn(aD)}` : lang === "en" ? `${aD.getFullYear()}` : `${aD.getFullYear()}年`;
|
|
2933
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2934
|
+
style: {
|
|
2935
|
+
display: "flex",
|
|
2936
|
+
alignItems: "center",
|
|
2937
|
+
gap: 8,
|
|
2938
|
+
justifyContent: "space-between"
|
|
2939
|
+
},
|
|
2940
|
+
children: [
|
|
2941
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2942
|
+
onClick: view === "month" ? () => shiftMonth(-1) : () => shiftDays(view === "week" ? -7 : view === "quarter" ? -90 : -365),
|
|
2943
|
+
style: btn,
|
|
2944
|
+
children: lang === "en" ? prevLabelEn : prevLabel
|
|
2923
2945
|
}),
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
},
|
|
2932
|
-
children: [lang === "en" ? "‹ Prev" : "‹ 上一", view === "week" ? lang === "en" ? " Week" : "周" : lang === "en" ? " Month" : "月"]
|
|
2933
|
-
}),
|
|
2934
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2935
|
-
style: {
|
|
2936
|
-
fontSize: 12,
|
|
2937
|
-
color: "var(--dsw-alias-label-secondary)",
|
|
2938
|
-
fontWeight: 500
|
|
2939
|
-
},
|
|
2940
|
-
children: [view === "week" ? (() => {
|
|
2941
|
-
const d = /* @__PURE__ */ new Date(anchor + "T12:00:00+08:00");
|
|
2942
|
-
const dow = (d.getDay() + 6) % 7;
|
|
2943
|
-
const mon = new Date(d);
|
|
2944
|
-
mon.setDate(d.getDate() - dow);
|
|
2945
|
-
const sun = new Date(mon);
|
|
2946
|
-
sun.setDate(mon.getDate() + 6);
|
|
2947
|
-
const fmt = (x) => `${x.getMonth() + 1}/${x.getDate()}`;
|
|
2948
|
-
return lang === "en" ? `Week of ${fmt(mon)} - ${fmt(sun)}` : `${mon.getMonth() + 1}月${mon.getDate()}日 - ${sun.getMonth() + 1}月${sun.getDate()}日`;
|
|
2949
|
-
})() : `${Number(anchor.slice(0, 4))}年${Number(anchor.slice(5, 7))}月`, lang === "en" && view === "month" ? ` ${anchor.slice(0, 7)}` : ""]
|
|
2950
|
-
}),
|
|
2951
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2952
|
-
onClick: () => setAnchor((a) => {
|
|
2953
|
-
const d = /* @__PURE__ */ new Date(a + "T12:00:00+08:00");
|
|
2954
|
-
if (view === "week") d.setDate(d.getDate() + 7);
|
|
2955
|
-
else d.setMonth(d.getMonth() + 1);
|
|
2956
|
-
const ms = d.getTime();
|
|
2957
|
-
return new Date(ms).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
|
|
2946
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2947
|
+
style: {
|
|
2948
|
+
fontSize: 12,
|
|
2949
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2950
|
+
fontWeight: 500
|
|
2951
|
+
},
|
|
2952
|
+
children: label
|
|
2958
2953
|
}),
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
children: [
|
|
2968
|
-
lang === "en" ? "Next ›" : "下一",
|
|
2969
|
-
view === "week" ? lang === "en" ? " Week" : "周" : lang === "en" ? " Month" : "月",
|
|
2970
|
-
" ›"
|
|
2971
|
-
]
|
|
2972
|
-
})
|
|
2973
|
-
]
|
|
2974
|
-
}) : null,
|
|
2954
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2955
|
+
onClick: view === "month" ? () => shiftMonth(1) : () => shiftDays(view === "week" ? 7 : view === "quarter" ? 90 : 365),
|
|
2956
|
+
style: btn,
|
|
2957
|
+
children: lang === "en" ? nextLabelEn : nextLabel
|
|
2958
|
+
})
|
|
2959
|
+
]
|
|
2960
|
+
});
|
|
2961
|
+
})(),
|
|
2975
2962
|
totals ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatsCards, {
|
|
2976
2963
|
t: lang === "en" ? (k, p) => {
|
|
2977
2964
|
const enMap = {
|