tokmon 0.10.0 → 0.11.1
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/dist/cli.js +209 -39
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { MouseProvider } from "@zenobius/ink-mouse";
|
|
|
8
8
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
9
9
|
import { join } from "path";
|
|
10
10
|
import { homedir } from "os";
|
|
11
|
-
var DEFAULTS = { interval: 2, billingInterval: 5, clearScreen: true };
|
|
11
|
+
var DEFAULTS = { interval: 2, billingInterval: 5, clearScreen: true, timezone: null };
|
|
12
12
|
function configDir() {
|
|
13
13
|
if (process.platform === "win32") {
|
|
14
14
|
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "tokmon");
|
|
@@ -45,6 +45,117 @@ import { createReadStream } from "fs";
|
|
|
45
45
|
import { createInterface } from "readline";
|
|
46
46
|
import { join as join2 } from "path";
|
|
47
47
|
import { homedir as homedir2 } from "os";
|
|
48
|
+
|
|
49
|
+
// src/tz.ts
|
|
50
|
+
function systemTimezone() {
|
|
51
|
+
try {
|
|
52
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
53
|
+
} catch {
|
|
54
|
+
return "UTC";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function isValidTimezone(tz) {
|
|
58
|
+
try {
|
|
59
|
+
new Intl.DateTimeFormat("en-CA", { timeZone: tz });
|
|
60
|
+
return true;
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function resolveTimezone(cfg) {
|
|
66
|
+
if (!cfg) return systemTimezone();
|
|
67
|
+
return isValidTimezone(cfg) ? cfg : systemTimezone();
|
|
68
|
+
}
|
|
69
|
+
var dayFmtCache = /* @__PURE__ */ new Map();
|
|
70
|
+
function dayFmt(tz) {
|
|
71
|
+
let f = dayFmtCache.get(tz);
|
|
72
|
+
if (!f) {
|
|
73
|
+
f = new Intl.DateTimeFormat("en-CA", {
|
|
74
|
+
timeZone: tz,
|
|
75
|
+
year: "numeric",
|
|
76
|
+
month: "2-digit",
|
|
77
|
+
day: "2-digit"
|
|
78
|
+
});
|
|
79
|
+
dayFmtCache.set(tz, f);
|
|
80
|
+
}
|
|
81
|
+
return f;
|
|
82
|
+
}
|
|
83
|
+
function dayKey(ts, tz) {
|
|
84
|
+
return dayFmt(tz).format(new Date(ts));
|
|
85
|
+
}
|
|
86
|
+
function monthKey(ts, tz) {
|
|
87
|
+
return dayKey(ts, tz).slice(0, 7);
|
|
88
|
+
}
|
|
89
|
+
var partsFmtCache = /* @__PURE__ */ new Map();
|
|
90
|
+
function partsFmt(tz) {
|
|
91
|
+
let f = partsFmtCache.get(tz);
|
|
92
|
+
if (!f) {
|
|
93
|
+
f = new Intl.DateTimeFormat("en-US", {
|
|
94
|
+
timeZone: tz,
|
|
95
|
+
hourCycle: "h23",
|
|
96
|
+
year: "numeric",
|
|
97
|
+
month: "2-digit",
|
|
98
|
+
day: "2-digit",
|
|
99
|
+
hour: "2-digit",
|
|
100
|
+
minute: "2-digit",
|
|
101
|
+
second: "2-digit",
|
|
102
|
+
weekday: "short"
|
|
103
|
+
});
|
|
104
|
+
partsFmtCache.set(tz, f);
|
|
105
|
+
}
|
|
106
|
+
return f;
|
|
107
|
+
}
|
|
108
|
+
var WEEKDAY_MAP = {
|
|
109
|
+
Sun: 0,
|
|
110
|
+
Mon: 1,
|
|
111
|
+
Tue: 2,
|
|
112
|
+
Wed: 3,
|
|
113
|
+
Thu: 4,
|
|
114
|
+
Fri: 5,
|
|
115
|
+
Sat: 6
|
|
116
|
+
};
|
|
117
|
+
function tzParts(ts, tz) {
|
|
118
|
+
const parts = partsFmt(tz).formatToParts(new Date(ts));
|
|
119
|
+
const get = (t) => parts.find((p) => p.type === t)?.value ?? "";
|
|
120
|
+
return {
|
|
121
|
+
y: Number(get("year")),
|
|
122
|
+
m: Number(get("month")),
|
|
123
|
+
d: Number(get("day")),
|
|
124
|
+
hh: Number(get("hour")),
|
|
125
|
+
mm: Number(get("minute")),
|
|
126
|
+
ss: Number(get("second")),
|
|
127
|
+
weekday: WEEKDAY_MAP[get("weekday")] ?? 0
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function instantFromTz(y, m, d, hh, mm, ss, tz) {
|
|
131
|
+
const guess = Date.UTC(y, m - 1, d, hh, mm, ss);
|
|
132
|
+
const r = tzParts(guess, tz);
|
|
133
|
+
const rendered = Date.UTC(r.y, r.m - 1, r.d, r.hh, r.mm, r.ss);
|
|
134
|
+
const offset = rendered - guess;
|
|
135
|
+
return guess - offset;
|
|
136
|
+
}
|
|
137
|
+
function startOfDay(ts, tz) {
|
|
138
|
+
const p = tzParts(ts, tz);
|
|
139
|
+
return instantFromTz(p.y, p.m, p.d, 0, 0, 0, tz);
|
|
140
|
+
}
|
|
141
|
+
function startOfMonth(ts, tz) {
|
|
142
|
+
const p = tzParts(ts, tz);
|
|
143
|
+
return instantFromTz(p.y, p.m, 1, 0, 0, 0, tz);
|
|
144
|
+
}
|
|
145
|
+
function startOfWeek(ts, tz) {
|
|
146
|
+
const p = tzParts(ts, tz);
|
|
147
|
+
const offset = p.weekday === 0 ? 6 : p.weekday - 1;
|
|
148
|
+
return instantFromTz(p.y, p.m, p.d - offset, 0, 0, 0, tz);
|
|
149
|
+
}
|
|
150
|
+
function monthsAgoStart(ts, months, tz) {
|
|
151
|
+
const p = tzParts(ts, tz);
|
|
152
|
+
return instantFromTz(p.y, p.m - months, 1, 0, 0, 0, tz);
|
|
153
|
+
}
|
|
154
|
+
function weekKey(ts, tz) {
|
|
155
|
+
return dayKey(startOfWeek(ts, tz), tz);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/data.ts
|
|
48
159
|
var PRICING = {
|
|
49
160
|
"claude-opus-4": { i: 5e-6, o: 25e-6, cc: 625e-8, cr: 5e-7 },
|
|
50
161
|
"claude-sonnet-4": { i: 3e-6, o: 15e-6, cc: 375e-8, cr: 3e-7 },
|
|
@@ -207,24 +318,11 @@ function groupBy(entries, keyFn) {
|
|
|
207
318
|
}
|
|
208
319
|
return rows.sort((a, b) => a.label.localeCompare(b.label));
|
|
209
320
|
}
|
|
210
|
-
function
|
|
211
|
-
const d = new Date(ts);
|
|
212
|
-
const day = d.getDay();
|
|
213
|
-
const mondayOffset = day === 0 ? 6 : day - 1;
|
|
214
|
-
const monday = new Date(d);
|
|
215
|
-
monday.setDate(d.getDate() - mondayOffset);
|
|
216
|
-
return monday.toISOString().slice(0, 10);
|
|
217
|
-
}
|
|
218
|
-
function monthLabel(ts) {
|
|
219
|
-
return new Date(ts).toISOString().slice(0, 7);
|
|
220
|
-
}
|
|
221
|
-
async function fetchDashboard() {
|
|
222
|
-
const d = /* @__PURE__ */ new Date();
|
|
223
|
-
const monthStart = new Date(d.getFullYear(), d.getMonth(), 1).getTime();
|
|
224
|
-
const todayStart = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
|
225
|
-
const weekDay = d.getDay();
|
|
226
|
-
const weekStart = new Date(d.getFullYear(), d.getMonth(), d.getDate() - (weekDay === 0 ? 6 : weekDay - 1)).getTime();
|
|
321
|
+
async function fetchDashboard(tz) {
|
|
227
322
|
const now = Date.now();
|
|
323
|
+
const monthStart = startOfMonth(now, tz);
|
|
324
|
+
const todayStart = startOfDay(now, tz);
|
|
325
|
+
const weekStart = startOfWeek(now, tz);
|
|
228
326
|
const entries = await loadEntries(monthStart);
|
|
229
327
|
const todayEntries = entries.filter((e) => e.ts >= todayStart);
|
|
230
328
|
let burnRate = 0;
|
|
@@ -245,14 +343,13 @@ async function fetchDashboard() {
|
|
|
245
343
|
burnRate
|
|
246
344
|
};
|
|
247
345
|
}
|
|
248
|
-
async function fetchTable() {
|
|
249
|
-
const
|
|
250
|
-
const lookback = new Date(d.getFullYear(), d.getMonth() - 6, 1).getTime();
|
|
346
|
+
async function fetchTable(tz) {
|
|
347
|
+
const lookback = monthsAgoStart(Date.now(), 6, tz);
|
|
251
348
|
const entries = await loadEntries(lookback);
|
|
252
349
|
return {
|
|
253
|
-
daily: groupBy(entries, (e) =>
|
|
254
|
-
weekly: groupBy(entries, (e) =>
|
|
255
|
-
monthly: groupBy(entries, (e) =>
|
|
350
|
+
daily: groupBy(entries, (e) => dayKey(e.ts, tz)),
|
|
351
|
+
weekly: groupBy(entries, (e) => weekKey(e.ts, tz)),
|
|
352
|
+
monthly: groupBy(entries, (e) => monthKey(e.ts, tz))
|
|
256
353
|
};
|
|
257
354
|
}
|
|
258
355
|
|
|
@@ -385,6 +482,9 @@ function formatReset(iso) {
|
|
|
385
482
|
|
|
386
483
|
// src/format.ts
|
|
387
484
|
function currency(value) {
|
|
485
|
+
if (value >= 1e4) {
|
|
486
|
+
return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
487
|
+
}
|
|
388
488
|
return `$${value.toFixed(2)}`;
|
|
389
489
|
}
|
|
390
490
|
function tokens(value) {
|
|
@@ -393,11 +493,12 @@ function tokens(value) {
|
|
|
393
493
|
if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
|
|
394
494
|
return String(value);
|
|
395
495
|
}
|
|
396
|
-
function time(date) {
|
|
496
|
+
function time(date, tz) {
|
|
397
497
|
return date.toLocaleTimeString(void 0, {
|
|
398
498
|
hour: "2-digit",
|
|
399
499
|
minute: "2-digit",
|
|
400
|
-
second: "2-digit"
|
|
500
|
+
second: "2-digit",
|
|
501
|
+
timeZone: tz
|
|
401
502
|
});
|
|
402
503
|
}
|
|
403
504
|
var SHORT_MONTHS = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
@@ -418,7 +519,8 @@ var VIEWS = ["Daily", "Weekly", "Monthly"];
|
|
|
418
519
|
var SORTS = ["date \u2191", "date \u2193", "cost \u2191", "cost \u2193"];
|
|
419
520
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
420
521
|
var MONTHS = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
421
|
-
var DEFAULT_CONFIG = { interval: 2, billingInterval: 5, clearScreen: true };
|
|
522
|
+
var DEFAULT_CONFIG = { interval: 2, billingInterval: 5, clearScreen: true, timezone: null };
|
|
523
|
+
var SETTINGS_ROWS = 4;
|
|
422
524
|
var IS_TTY = process.stdin.isTTY === true;
|
|
423
525
|
function App({ interval: cliInterval }) {
|
|
424
526
|
const [dashboard, setDashboard] = useState(null);
|
|
@@ -431,10 +533,12 @@ function App({ interval: cliInterval }) {
|
|
|
431
533
|
const [view, setView] = useState(0);
|
|
432
534
|
const [cursor, setCursor] = useState(0);
|
|
433
535
|
const [expanded, setExpanded] = useState(-1);
|
|
434
|
-
const [sort, setSort] = useState(
|
|
536
|
+
const [sort, setSort] = useState(1);
|
|
435
537
|
const [showSettings, setShowSettings] = useState(false);
|
|
436
538
|
const [config2, setConfig] = useState(null);
|
|
437
539
|
const [settingsCursor, setSettingsCursor] = useState(0);
|
|
540
|
+
const [tzEdit, setTzEdit] = useState(null);
|
|
541
|
+
const [tzError, setTzError] = useState(null);
|
|
438
542
|
const tableLoadedOnce = useRef(false);
|
|
439
543
|
const { stdout } = useStdout();
|
|
440
544
|
const { exit } = useApp();
|
|
@@ -442,6 +546,7 @@ function App({ interval: cliInterval }) {
|
|
|
442
546
|
const cols = stdout?.columns ?? 80;
|
|
443
547
|
const interval2 = cliInterval ?? (config2?.interval ?? 2) * 1e3;
|
|
444
548
|
const cfg = config2 ?? DEFAULT_CONFIG;
|
|
549
|
+
const tz = resolveTimezone(cfg.timezone);
|
|
445
550
|
useEffect(() => {
|
|
446
551
|
loadConfig().then((c) => {
|
|
447
552
|
if (cliInterval) c = { ...c, interval: cliInterval / 1e3 };
|
|
@@ -452,7 +557,7 @@ function App({ interval: cliInterval }) {
|
|
|
452
557
|
let active = true;
|
|
453
558
|
const load = async () => {
|
|
454
559
|
try {
|
|
455
|
-
const result = await fetchDashboard();
|
|
560
|
+
const result = await fetchDashboard(tz);
|
|
456
561
|
if (active) {
|
|
457
562
|
setDashboard(result);
|
|
458
563
|
setError(null);
|
|
@@ -468,7 +573,7 @@ function App({ interval: cliInterval }) {
|
|
|
468
573
|
active = false;
|
|
469
574
|
clearInterval(id);
|
|
470
575
|
};
|
|
471
|
-
}, [interval2]);
|
|
576
|
+
}, [interval2, tz]);
|
|
472
577
|
const billingMs = cfg.billingInterval * 6e4;
|
|
473
578
|
useEffect(() => {
|
|
474
579
|
let active = true;
|
|
@@ -483,12 +588,16 @@ function App({ interval: cliInterval }) {
|
|
|
483
588
|
clearInterval(id);
|
|
484
589
|
};
|
|
485
590
|
}, [billingMs]);
|
|
591
|
+
useEffect(() => {
|
|
592
|
+
tableLoadedOnce.current = false;
|
|
593
|
+
setTable(null);
|
|
594
|
+
}, [tz]);
|
|
486
595
|
useEffect(() => {
|
|
487
596
|
if (tab !== 1) return;
|
|
488
597
|
if (tableLoadedOnce.current && table) return;
|
|
489
598
|
let active = true;
|
|
490
599
|
setTableLoading(true);
|
|
491
|
-
fetchTable().then((result) => {
|
|
600
|
+
fetchTable(tz).then((result) => {
|
|
492
601
|
if (active) {
|
|
493
602
|
setTable(result);
|
|
494
603
|
setTableLoading(false);
|
|
@@ -500,13 +609,13 @@ function App({ interval: cliInterval }) {
|
|
|
500
609
|
return () => {
|
|
501
610
|
active = false;
|
|
502
611
|
};
|
|
503
|
-
}, [tab]);
|
|
612
|
+
}, [tab, tz]);
|
|
504
613
|
useEffect(() => {
|
|
505
614
|
if (tab !== 1 || !tableLoadedOnce.current) return;
|
|
506
615
|
let active = true;
|
|
507
616
|
const id = setInterval(async () => {
|
|
508
617
|
try {
|
|
509
|
-
const result = await fetchTable();
|
|
618
|
+
const result = await fetchTable(tz);
|
|
510
619
|
if (active) setTable(result);
|
|
511
620
|
} catch {
|
|
512
621
|
}
|
|
@@ -515,7 +624,7 @@ function App({ interval: cliInterval }) {
|
|
|
515
624
|
active = false;
|
|
516
625
|
clearInterval(id);
|
|
517
626
|
};
|
|
518
|
-
}, [tab, interval2]);
|
|
627
|
+
}, [tab, interval2, tz]);
|
|
519
628
|
const resetView = useCallback(() => {
|
|
520
629
|
setCursor(0);
|
|
521
630
|
setExpanded(-1);
|
|
@@ -535,6 +644,39 @@ function App({ interval: cliInterval }) {
|
|
|
535
644
|
};
|
|
536
645
|
}, [tab]);
|
|
537
646
|
useInput((input, key) => {
|
|
647
|
+
if (showSettings && tzEdit !== null) {
|
|
648
|
+
if (key.escape) {
|
|
649
|
+
setTzEdit(null);
|
|
650
|
+
setTzError(null);
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if (key.return) {
|
|
654
|
+
const val = tzEdit.trim();
|
|
655
|
+
if (val === "" || val.toLowerCase() === "system") {
|
|
656
|
+
updateConfig((c) => ({ ...c, timezone: null }));
|
|
657
|
+
setTzEdit(null);
|
|
658
|
+
setTzError(null);
|
|
659
|
+
} else if (isValidTimezone(val)) {
|
|
660
|
+
updateConfig((c) => ({ ...c, timezone: val }));
|
|
661
|
+
setTzEdit(null);
|
|
662
|
+
setTzError(null);
|
|
663
|
+
} else {
|
|
664
|
+
setTzError(`Invalid: ${val}`);
|
|
665
|
+
}
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (key.backspace || key.delete) {
|
|
669
|
+
setTzEdit((s) => (s ?? "").slice(0, -1));
|
|
670
|
+
setTzError(null);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
if (input && !key.ctrl && !key.meta) {
|
|
674
|
+
setTzEdit((s) => (s ?? "") + input);
|
|
675
|
+
setTzError(null);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
538
680
|
if (input === "q") {
|
|
539
681
|
exit();
|
|
540
682
|
return;
|
|
@@ -542,7 +684,7 @@ function App({ interval: cliInterval }) {
|
|
|
542
684
|
if (showSettings) {
|
|
543
685
|
if (key.escape || input === "s") setShowSettings(false);
|
|
544
686
|
if (key.upArrow) setSettingsCursor((c) => Math.max(0, c - 1));
|
|
545
|
-
if (key.downArrow) setSettingsCursor((c) => Math.min(
|
|
687
|
+
if (key.downArrow) setSettingsCursor((c) => Math.min(SETTINGS_ROWS - 1, c + 1));
|
|
546
688
|
if (settingsCursor === 0) {
|
|
547
689
|
if (key.leftArrow) updateConfig((c) => ({ ...c, interval: Math.max(1, c.interval - 1) }));
|
|
548
690
|
if (key.rightArrow) updateConfig((c) => ({ ...c, interval: c.interval + 1 }));
|
|
@@ -554,6 +696,15 @@ function App({ interval: cliInterval }) {
|
|
|
554
696
|
if (settingsCursor === 2 && (key.leftArrow || key.rightArrow || key.return)) {
|
|
555
697
|
updateConfig((c) => ({ ...c, clearScreen: !c.clearScreen }));
|
|
556
698
|
}
|
|
699
|
+
if (settingsCursor === 3) {
|
|
700
|
+
if (key.return) {
|
|
701
|
+
setTzEdit(cfg.timezone ?? "");
|
|
702
|
+
setTzError(null);
|
|
703
|
+
}
|
|
704
|
+
if (key.leftArrow || key.rightArrow) {
|
|
705
|
+
updateConfig((c) => ({ ...c, timezone: c.timezone === null ? systemTimezone() : null }));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
557
708
|
return;
|
|
558
709
|
}
|
|
559
710
|
if (input === "s") {
|
|
@@ -667,10 +818,10 @@ function App({ interval: cliInterval }) {
|
|
|
667
818
|
/* @__PURE__ */ jsx(PeakBadge, { peak: billing.peak }),
|
|
668
819
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " })
|
|
669
820
|
] }),
|
|
670
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: time(updated) })
|
|
821
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: time(updated, tz) })
|
|
671
822
|
] })
|
|
672
823
|
] }),
|
|
673
|
-
showSettings ? /* @__PURE__ */ jsx(SettingsView, { config: cfg, cursor: settingsCursor }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
824
|
+
showSettings ? /* @__PURE__ */ jsx(SettingsView, { config: cfg, cursor: settingsCursor, tzEdit, tzError, resolvedTz: tz }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
674
825
|
/* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
|
|
675
826
|
/* @__PURE__ */ jsx(TabBar, { tabs: TABS, active: tab, onSelect: (i) => {
|
|
676
827
|
setTab(i);
|
|
@@ -753,7 +904,9 @@ function sortRows(rows, sortIdx) {
|
|
|
753
904
|
return sorted;
|
|
754
905
|
}
|
|
755
906
|
}
|
|
756
|
-
function SettingsView({ config: config2, cursor }) {
|
|
907
|
+
function SettingsView({ config: config2, cursor, tzEdit, tzError, resolvedTz }) {
|
|
908
|
+
const editing = tzEdit !== null;
|
|
909
|
+
const tzDisplay = config2.timezone === null ? `System (${resolvedTz})` : config2.timezone;
|
|
757
910
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
758
911
|
/* @__PURE__ */ jsx(Text, { bold: true, children: "Settings" }),
|
|
759
912
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: configLocation() }),
|
|
@@ -804,8 +957,25 @@ function SettingsView({ config: config2, cursor }) {
|
|
|
804
957
|
/* @__PURE__ */ jsx(Text, { children: "Clear screen " }),
|
|
805
958
|
/* @__PURE__ */ jsx(Text, { bold: true, color: config2.clearScreen ? "green" : "red", children: config2.clearScreen ? "on" : "off" })
|
|
806
959
|
] }),
|
|
960
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
961
|
+
/* @__PURE__ */ jsxs(Text, { color: cursor === 3 ? "green" : void 0, children: [
|
|
962
|
+
cursor === 3 ? "\u25B8" : " ",
|
|
963
|
+
" "
|
|
964
|
+
] }),
|
|
965
|
+
/* @__PURE__ */ jsx(Text, { children: "Timezone " }),
|
|
966
|
+
editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
967
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[" }),
|
|
968
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: tzEdit }),
|
|
969
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" }),
|
|
970
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "]" })
|
|
971
|
+
] }) : /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: tzDisplay })
|
|
972
|
+
] }),
|
|
973
|
+
cursor === 3 && tzError && /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
974
|
+
" ",
|
|
975
|
+
tzError
|
|
976
|
+
] }),
|
|
807
977
|
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
808
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 select \u2190\u2192 adjust s/Esc close" })
|
|
978
|
+
editing ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "type IANA name (e.g. Europe/London) \xB7 empty = System \xB7 Enter save \xB7 Esc cancel" }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 select \u2190\u2192 adjust Enter edit tz s/Esc close" })
|
|
809
979
|
] });
|
|
810
980
|
}
|
|
811
981
|
function DashboardView({ data, billing }) {
|