machud 0.0.0 → 0.0.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.
@@ -0,0 +1,1859 @@
1
+ #!/usr/bin/env node
2
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createTextVNode, createVNode, defineComponent, h, onMounted, onUnmounted, openBlock, reactive, ref, renderList, renderSlot, shallowRef, toDisplayString, unref, watchEffect, withCtx } from "vue";
3
+ import { Box, Text, createApp, renderToString, useApp, useBoxMetrics, useInput, useWindowSize } from "@vue-tui/runtime";
4
+ import os from "node:os";
5
+ import { execFile } from "node:child_process";
6
+ import chalk from "chalk";
7
+ //#region src/lib/empty.ts
8
+ function emptyMetrics() {
9
+ return {
10
+ cpu: {
11
+ model: "CPU",
12
+ usage: 0,
13
+ cores: [],
14
+ topProcs: [],
15
+ pUsage: 0,
16
+ eUsage: 0,
17
+ pCount: 0,
18
+ eCount: 0,
19
+ loadAvg: [
20
+ 0,
21
+ 0,
22
+ 0
23
+ ],
24
+ freqMHz: null
25
+ },
26
+ memory: {
27
+ total: 0,
28
+ used: 0,
29
+ free: 0,
30
+ wired: 0,
31
+ compressed: 0,
32
+ app: 0,
33
+ usedPct: 0,
34
+ pressure: "Normal",
35
+ swapTotal: 0,
36
+ swapUsed: 0,
37
+ topApps: []
38
+ },
39
+ gpu: {
40
+ usage: null,
41
+ renderer: null,
42
+ vram: null
43
+ },
44
+ disk: {
45
+ total: 0,
46
+ used: 0,
47
+ free: 0,
48
+ usedPct: 0,
49
+ readBps: 0,
50
+ writeBps: 0,
51
+ mount: "/"
52
+ },
53
+ net: {
54
+ iface: "—",
55
+ rxBps: 0,
56
+ txBps: 0,
57
+ rxTotal: 0,
58
+ txTotal: 0
59
+ },
60
+ battery: {
61
+ present: false,
62
+ pct: 0,
63
+ state: "—",
64
+ charging: false,
65
+ timeRemaining: null,
66
+ cycleCount: null,
67
+ healthPct: null,
68
+ tempC: null,
69
+ adapterWatts: null,
70
+ chargeWatts: null
71
+ },
72
+ sensors: {
73
+ thermalPressure: "Nominal",
74
+ speedLimit: 100,
75
+ batteryTempC: null,
76
+ fanRpm: null
77
+ },
78
+ appearance: { mode: "light" },
79
+ ts: 0
80
+ };
81
+ }
82
+ //#endregion
83
+ //#region src/lib/exec.ts
84
+ function sh(cmd, args = [], timeoutMs = 4e3) {
85
+ return new Promise((resolve) => {
86
+ execFile(cmd, args, {
87
+ timeout: timeoutMs,
88
+ maxBuffer: 16 * 1024 * 1024
89
+ }, (err, stdout) => {
90
+ if (err && !stdout) {
91
+ resolve("");
92
+ return;
93
+ }
94
+ resolve(stdout ?? "");
95
+ });
96
+ });
97
+ }
98
+ //#endregion
99
+ //#region src/lib/format.ts
100
+ function clamp(n, lo = 0, hi = 100) {
101
+ return Math.max(lo, Math.min(hi, n));
102
+ }
103
+ function humanBytes(n, perSec = false) {
104
+ if (n == null || !isFinite(n) || n < 0) return "—";
105
+ const units = [
106
+ "B",
107
+ "KB",
108
+ "MB",
109
+ "GB",
110
+ "TB"
111
+ ];
112
+ let v = n;
113
+ let i = 0;
114
+ while (v >= 1024 && i < units.length - 1) {
115
+ v /= 1024;
116
+ i++;
117
+ }
118
+ return `${v >= 100 || i === 0 ? v.toFixed(0) : v.toFixed(1)} ${units[i]}${perSec ? "/s" : ""}`;
119
+ }
120
+ function pct(n) {
121
+ return n == null || !isFinite(n) ? "—" : `${Math.round(n)}%`;
122
+ }
123
+ function temp(c) {
124
+ return c == null || !isFinite(c) ? "—" : `${c.toFixed(0)}°C`;
125
+ }
126
+ //#endregion
127
+ //#region src/lib/collectors/cpu.ts
128
+ var prev$2 = null;
129
+ var counts = null;
130
+ var model = "";
131
+ async function clusterCounts() {
132
+ if (counts) return counts;
133
+ const nums = (process.env.MACHUD_TEST_NO_PERFLEVEL ? "" : await sh("sysctl", [
134
+ "-n",
135
+ "hw.perflevel0.logicalcpu",
136
+ "hw.perflevel1.logicalcpu"
137
+ ])).trim().split(/\s+/).map(Number);
138
+ const p = nums[0] || 0;
139
+ const e = nums[1] || 0;
140
+ counts = p + e === 0 ? {
141
+ p: os.cpus().length,
142
+ e: 0
143
+ } : {
144
+ p,
145
+ e
146
+ };
147
+ return counts;
148
+ }
149
+ async function collectCpu() {
150
+ if (!model) model = (await sh("sysctl", ["-n", "machdep.cpu.brand_string"])).trim() || "CPU";
151
+ const { p: pCount, e: eCount } = await clusterCounts();
152
+ const times = os.cpus().map((c) => c.times);
153
+ const cores = times.map((t, i) => {
154
+ let usage = 0;
155
+ const p = prev$2?.[i];
156
+ if (p) {
157
+ const idle = t.idle - p.idle;
158
+ const total = t.user - p.user + (t.nice - p.nice) + (t.sys - p.sys) + (t.irq - p.irq) + idle;
159
+ usage = total > 0 ? clamp((1 - idle / total) * 100) : 0;
160
+ }
161
+ return {
162
+ usage,
163
+ cluster: i < eCount ? "E" : "P"
164
+ };
165
+ });
166
+ prev$2 = times;
167
+ const avg = (xs) => xs.length ? xs.reduce((s, c) => s + c.usage, 0) / xs.length : 0;
168
+ const eCores = cores.filter((c) => c.cluster === "E");
169
+ const pCores = cores.filter((c) => c.cluster === "P");
170
+ const topProcs = (await sh("ps", [
171
+ "-A",
172
+ "-o",
173
+ "pcpu=,comm=",
174
+ "-r"
175
+ ])).split("\n").map((l) => l.trim()).filter(Boolean).slice(0, 5).map((l) => {
176
+ const sp = l.indexOf(" ");
177
+ const pctNum = Number(l.slice(0, sp));
178
+ const comm = l.slice(sp + 1).trim();
179
+ return {
180
+ name: comm.split("/").pop() || comm,
181
+ pct: isFinite(pctNum) ? pctNum : 0
182
+ };
183
+ });
184
+ return {
185
+ model,
186
+ usage: avg(cores),
187
+ cores,
188
+ topProcs,
189
+ pUsage: avg(pCores),
190
+ eUsage: avg(eCores),
191
+ pCount,
192
+ eCount,
193
+ loadAvg: os.loadavg(),
194
+ freqMHz: null
195
+ };
196
+ }
197
+ //#endregion
198
+ //#region src/lib/collectors/memory.ts
199
+ function parseSwap(s, key) {
200
+ const m = s.match(new RegExp(`${key}\\s*=\\s*([\\d.]+)([MGK])`));
201
+ if (!m) return 0;
202
+ const v = parseFloat(m[1]);
203
+ const unit = m[2];
204
+ return v * (unit === "G" ? 2 ** 30 : unit === "K" ? 2 ** 10 : 2 ** 20);
205
+ }
206
+ async function collectMemory() {
207
+ const total = os.totalmem();
208
+ const vm = await sh("vm_stat");
209
+ const pageSize = Number(vm.match(/page size of (\d+) bytes/)?.[1] ?? 16384);
210
+ const pages = (name) => {
211
+ const m = vm.match(new RegExp(`${name}:\\s+(\\d+)\\.`));
212
+ return m ? Number(m[1]) * pageSize : 0;
213
+ };
214
+ const free = pages("Pages free") + pages("Pages speculative");
215
+ const wired = pages("Pages wired down");
216
+ const compressed = pages("Pages occupied by compressor");
217
+ const active = pages("Pages active");
218
+ const used = clamp(wired + compressed + active, 0, total);
219
+ const app = clamp(active, 0, total);
220
+ const usedPct = total > 0 ? clamp(used / total * 100) : 0;
221
+ const swap = await sh("sysctl", ["-n", "vm.swapusage"]);
222
+ const swapTotal = parseSwap(swap, "total");
223
+ const swapUsed = parseSwap(swap, "used");
224
+ const lvl = (process.env.MACHUD_TEST_PRESSURE_LEVEL ?? await sh("sysctl", ["-n", "kern.memorystatus_vm_pressure_level"])).trim();
225
+ return {
226
+ total,
227
+ used,
228
+ free,
229
+ wired,
230
+ compressed,
231
+ app,
232
+ usedPct,
233
+ pressure: lvl === "4" ? "High" : lvl === "2" ? "Elevated" : lvl === "1" ? "Normal" : usedPct >= 88 || swapUsed > 2 ** 30 ? "High" : usedPct >= 72 ? "Elevated" : "Normal",
234
+ swapTotal,
235
+ swapUsed,
236
+ topApps: (await sh("ps", [
237
+ "-A",
238
+ "-o",
239
+ "rss=,comm=",
240
+ "-m"
241
+ ])).split("\n").map((l) => l.trim()).filter(Boolean).slice(0, 5).map((l) => {
242
+ const sp = l.indexOf(" ");
243
+ const rss = Number(l.slice(0, sp));
244
+ const comm = l.slice(sp + 1).trim();
245
+ return {
246
+ name: comm.split("/").pop() || comm,
247
+ bytes: (isFinite(rss) ? rss : 0) * 1024
248
+ };
249
+ })
250
+ };
251
+ }
252
+ //#endregion
253
+ //#region src/lib/collectors/gpu.ts
254
+ async function collectGpu() {
255
+ const out = await sh("ioreg", [
256
+ "-r",
257
+ "-d",
258
+ "1",
259
+ "-w",
260
+ "0",
261
+ "-c",
262
+ "IOAccelerator"
263
+ ]);
264
+ const num = (key) => {
265
+ const m = out.match(new RegExp(`"${key}"=([0-9]+)`));
266
+ return m ? Number(m[1]) : null;
267
+ };
268
+ return {
269
+ usage: num("Device Utilization %"),
270
+ renderer: num("Renderer Utilization %"),
271
+ vram: num("In use system memory")
272
+ };
273
+ }
274
+ //#endregion
275
+ //#region src/lib/collectors/disk.ts
276
+ var prev$1 = null;
277
+ async function collectDisk() {
278
+ const f = ((await sh("df", [
279
+ "-k",
280
+ "-P",
281
+ "/"
282
+ ])).trim().split("\n").pop() ?? "").split(/\s+/);
283
+ const total = (Number(f[1]) || 0) * 1024;
284
+ const free = (Number(f[3]) || 0) * 1024;
285
+ const used = clamp(total - free, 0, total);
286
+ const usedPct = total > 0 ? clamp(used / total * 100) : 0;
287
+ const io = await sh("ioreg", [
288
+ "-r",
289
+ "-c",
290
+ "IOBlockStorageDriver",
291
+ "-w",
292
+ "0"
293
+ ]);
294
+ const sum = (key) => [...io.matchAll(new RegExp(`"${key}"=(\\d+)`, "g"))].reduce((s, m) => s + Number(m[1]), 0);
295
+ const read = sum("Bytes \\(Read\\)");
296
+ const write = sum("Bytes \\(Write\\)");
297
+ const now = Date.now();
298
+ let readBps = 0;
299
+ let writeBps = 0;
300
+ if (prev$1) {
301
+ const dt = (now - prev$1.t) / 1e3;
302
+ if (dt > 0) {
303
+ readBps = Math.max(0, (read - prev$1.read) / dt);
304
+ writeBps = Math.max(0, (write - prev$1.write) / dt);
305
+ }
306
+ }
307
+ prev$1 = {
308
+ read,
309
+ write,
310
+ t: now
311
+ };
312
+ return {
313
+ total,
314
+ used,
315
+ free,
316
+ usedPct,
317
+ readBps,
318
+ writeBps,
319
+ mount: f[5] || "/"
320
+ };
321
+ }
322
+ //#endregion
323
+ //#region src/lib/collectors/network.ts
324
+ var prev = null;
325
+ async function collectNet() {
326
+ const iface = (await sh("route", [
327
+ "-n",
328
+ "get",
329
+ "default"
330
+ ])).match(/interface:\s*(\S+)/)?.[1] || "en0";
331
+ const ns = await sh("netstat", ["-ibn"]);
332
+ let rx = 0;
333
+ let tx = 0;
334
+ for (const l of ns.split("\n")) if (l.startsWith(`${iface} `) && l.includes("<Link#")) {
335
+ const p = l.trim().split(/\s+/);
336
+ rx = Number(p[6]) || 0;
337
+ tx = Number(p[9]) || 0;
338
+ break;
339
+ }
340
+ const now = Date.now();
341
+ let rxBps = 0;
342
+ let txBps = 0;
343
+ if (prev && prev.rx <= rx && prev.tx <= tx) {
344
+ const dt = (now - prev.t) / 1e3;
345
+ if (dt > 0) {
346
+ rxBps = (rx - prev.rx) / dt;
347
+ txBps = (tx - prev.tx) / dt;
348
+ }
349
+ }
350
+ prev = {
351
+ rx,
352
+ tx,
353
+ t: now
354
+ };
355
+ return {
356
+ iface,
357
+ rxBps,
358
+ txBps,
359
+ rxTotal: rx,
360
+ txTotal: tx
361
+ };
362
+ }
363
+ //#endregion
364
+ //#region src/lib/collectors/battery.ts
365
+ async function collectBattery() {
366
+ const batt = await sh("pmset", ["-g", "batt"]);
367
+ const present = /InternalBattery/.test(batt);
368
+ const pct = Number(batt.match(/(\d+)%/)?.[1] ?? (present ? 0 : 100));
369
+ const state = batt.match(/\d+%;\s*([^;]+);/)?.[1]?.trim() || (batt.includes("AC Power") ? "AC power" : "unknown");
370
+ const charging = /\bcharging\b/i.test(state) && !/discharging|not charging/i.test(state);
371
+ const tm = batt.match(/(\d+):(\d+)\s+remaining/);
372
+ const timeRemaining = tm && !(tm[1] === "0" && tm[2] === "00") ? `${tm[1]}:${tm[2]}` : null;
373
+ const io = await sh("ioreg", [
374
+ "-r",
375
+ "-c",
376
+ "AppleSmartBattery",
377
+ "-w",
378
+ "0"
379
+ ]);
380
+ const ioNum = (k) => {
381
+ const m = io.match(new RegExp(`"${k}" = (-?\\d+)`));
382
+ return m ? Number(m[1]) : null;
383
+ };
384
+ const cycleCount = ioNum("CycleCount");
385
+ const design = ioNum("DesignCapacity");
386
+ const rawMax = ioNum("AppleRawMaxCapacity");
387
+ const healthPct = design && rawMax ? clamp(rawMax / design * 100) : null;
388
+ const tRaw = ioNum("Temperature");
389
+ const tempC = tRaw != null ? tRaw / 100 : null;
390
+ const toSigned64 = (s) => {
391
+ if (s == null) return null;
392
+ try {
393
+ let v = BigInt(s);
394
+ if (v >= 1n << 63n) v -= 1n << 64n;
395
+ return Number(v);
396
+ } catch {
397
+ return null;
398
+ }
399
+ };
400
+ const voltage = ioNum("Voltage");
401
+ const amperage = toSigned64(process.env.MACHUD_TEST_AMPERAGE ?? io.match(/"Amperage" = (-?\d+)/)?.[1]);
402
+ const chargeWatts = voltage != null && amperage != null ? voltage * amperage / 1e6 : null;
403
+ const externalConnected = /"ExternalConnected" = Yes/.test(io);
404
+ const wattsMatch = io.match(/"Watts"=(\d+)/);
405
+ return {
406
+ present,
407
+ pct,
408
+ state,
409
+ charging,
410
+ timeRemaining,
411
+ cycleCount,
412
+ healthPct,
413
+ tempC,
414
+ adapterWatts: externalConnected && wattsMatch ? Number(wattsMatch[1]) : null,
415
+ chargeWatts
416
+ };
417
+ }
418
+ //#endregion
419
+ //#region src/lib/collectors/sensors.ts
420
+ async function collectSensors() {
421
+ const therm = await sh("pmset", ["-g", "therm"]);
422
+ const speedLimit = Number(therm.match(/CPU_Speed_Limit\s*=\s*(\d+)/)?.[1] ?? 100);
423
+ let thermalPressure = "Nominal";
424
+ if (speedLimit < 50) thermalPressure = "Critical";
425
+ else if (speedLimit < 75) thermalPressure = "Serious";
426
+ else if (speedLimit < 100) thermalPressure = "Fair";
427
+ const tRaw = (await sh("ioreg", [
428
+ "-r",
429
+ "-c",
430
+ "AppleSmartBattery",
431
+ "-w",
432
+ "0"
433
+ ])).match(/"Temperature" = (\d+)/)?.[1];
434
+ const batteryTempC = tRaw ? Number(tRaw) / 100 : null;
435
+ return {
436
+ thermalPressure,
437
+ speedLimit,
438
+ batteryTempC,
439
+ fanRpm: null
440
+ };
441
+ }
442
+ //#endregion
443
+ //#region src/lib/collectors/appearance.ts
444
+ var TEST_APPEARANCE = "MACHUD_TEST_APPEARANCE";
445
+ var cached = null;
446
+ var cachedAt = 0;
447
+ async function collectAppearance() {
448
+ const testMode = process.env[TEST_APPEARANCE];
449
+ if (testMode === "dark" || testMode === "light") return { mode: testMode };
450
+ const now = Date.now();
451
+ if (cached && now - cachedAt < 5e3) return cached;
452
+ const out = await sh("defaults", [
453
+ "read",
454
+ "-g",
455
+ "AppleInterfaceStyle"
456
+ ], 1e3);
457
+ cached = { mode: /dark/i.test(out) ? "dark" : "light" };
458
+ cachedAt = now;
459
+ return cached;
460
+ }
461
+ //#endregion
462
+ //#region src/lib/collectors/index.ts
463
+ async function safe(p, fallback) {
464
+ try {
465
+ return await p;
466
+ } catch {
467
+ return fallback;
468
+ }
469
+ }
470
+ async function collectAll() {
471
+ const e = emptyMetrics();
472
+ const [cpu, memory, gpu, disk, net, battery, sensors, appearance] = await Promise.all([
473
+ safe(collectCpu(), e.cpu),
474
+ safe(collectMemory(), e.memory),
475
+ safe(collectGpu(), e.gpu),
476
+ safe(collectDisk(), e.disk),
477
+ safe(collectNet(), e.net),
478
+ safe(collectBattery(), e.battery),
479
+ safe(collectSensors(), e.sensors),
480
+ safe(collectAppearance(), e.appearance)
481
+ ]);
482
+ return applyTestOverride({
483
+ cpu,
484
+ memory,
485
+ gpu,
486
+ disk,
487
+ net,
488
+ battery,
489
+ sensors,
490
+ appearance,
491
+ ts: Date.now()
492
+ });
493
+ }
494
+ function applyTestOverride(m) {
495
+ const raw = process.env.MACHUD_TEST_OVERRIDE;
496
+ if (!raw) return m;
497
+ try {
498
+ return deepMerge(m, JSON.parse(raw));
499
+ } catch {
500
+ return m;
501
+ }
502
+ }
503
+ function deepMerge(base, over) {
504
+ if (over === null || typeof over !== "object" || Array.isArray(over)) return over;
505
+ const out = { ...base };
506
+ for (const [k, v] of Object.entries(over)) out[k] = deepMerge(base?.[k], v);
507
+ return out;
508
+ }
509
+ //#endregion
510
+ //#region src/composables/useMetrics.ts
511
+ var MAX_SAMPLES = 240;
512
+ function useMetrics(intervalMs = 1e3) {
513
+ const metrics = shallowRef(null);
514
+ const history = ref({
515
+ cpu: [],
516
+ gpu: [],
517
+ mem: [],
518
+ rx: [],
519
+ tx: []
520
+ });
521
+ const now = shallowRef(Date.now());
522
+ let timer = null;
523
+ let inFlight = false;
524
+ let stopped = false;
525
+ const push = (arr, v) => {
526
+ arr.push(v);
527
+ if (arr.length > MAX_SAMPLES) arr.shift();
528
+ };
529
+ async function tick() {
530
+ if (inFlight) return;
531
+ inFlight = true;
532
+ try {
533
+ const m = await collectAll();
534
+ if (stopped) return;
535
+ now.value = m.ts;
536
+ metrics.value = m;
537
+ const h = history.value;
538
+ push(h.cpu, m.cpu.usage);
539
+ push(h.gpu, m.gpu.usage ?? 0);
540
+ push(h.mem, m.memory.usedPct);
541
+ push(h.rx, m.net.rxBps);
542
+ push(h.tx, m.net.txBps);
543
+ history.value = { ...h };
544
+ } finally {
545
+ inFlight = false;
546
+ }
547
+ }
548
+ onMounted(() => {
549
+ tick();
550
+ timer = setInterval(() => void tick(), intervalMs);
551
+ });
552
+ onUnmounted(() => {
553
+ stopped = true;
554
+ if (timer) clearInterval(timer);
555
+ });
556
+ return {
557
+ metrics,
558
+ history,
559
+ now
560
+ };
561
+ }
562
+ //#endregion
563
+ //#region src/theme.ts
564
+ var palettes = {
565
+ dark: {
566
+ bg: "#2d353b",
567
+ bgLift: "#343f44",
568
+ frame: "#4f5b58",
569
+ title: "#d3c6aa",
570
+ text: "#9da9a0",
571
+ dim: "#7a8478",
572
+ accent: "#a7c080",
573
+ silver: "#c4c9cf",
574
+ cpu: "#a7c080",
575
+ mem: "#d699b6",
576
+ gpu: "#7fbbb3",
577
+ disk: "#dbbc7f",
578
+ net: "#83c092",
579
+ battery: "#e69875",
580
+ sensor: "#e67e80",
581
+ good: "#a7c080",
582
+ warn: "#dbbc7f",
583
+ bad: "#e67e80"
584
+ },
585
+ light: {
586
+ bg: "#fdf6e3",
587
+ bgLift: "#f4f0d9",
588
+ frame: "#ddd8be",
589
+ title: "#5c6a72",
590
+ text: "#5c6a72",
591
+ dim: "#939f91",
592
+ accent: "#8da101",
593
+ silver: "#8d939a",
594
+ cpu: "#8da101",
595
+ mem: "#df69ba",
596
+ gpu: "#3a94c5",
597
+ disk: "#dfa000",
598
+ net: "#35a77c",
599
+ battery: "#f57d26",
600
+ sensor: "#f85552",
601
+ good: "#8da101",
602
+ warn: "#dfa000",
603
+ bad: "#f85552"
604
+ }
605
+ };
606
+ var theme = reactive({ ...palettes.light });
607
+ function setThemeMode(mode) {
608
+ Object.assign(theme, palettes[mode]);
609
+ }
610
+ function levelColor(pct) {
611
+ if (pct >= 85) return theme.bad;
612
+ if (pct >= 60) return theme.warn;
613
+ return theme.good;
614
+ }
615
+ //#endregion
616
+ //#region src/components/panels/HeaderBar.vue
617
+ var HeaderBar_default = /* @__PURE__ */ defineComponent({
618
+ __name: "HeaderBar",
619
+ props: {
620
+ m: {},
621
+ now: {},
622
+ width: {}
623
+ },
624
+ setup(__props) {
625
+ const props = __props;
626
+ const wide = computed(() => (props.width ?? 120) >= 100);
627
+ const clock = computed(() => {
628
+ const d = new Date(props.now || Date.now());
629
+ const p = (n) => String(n).padStart(2, "0");
630
+ return `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
631
+ });
632
+ return (_ctx, _cache) => {
633
+ return openBlock(), createBlock(unref(Box), {
634
+ paddingX: 1,
635
+ justifyContent: "space-between"
636
+ }, {
637
+ default: withCtx(() => [createVNode(unref(Box), null, {
638
+ default: withCtx(() => [
639
+ createVNode(unref(Text), {
640
+ color: unref(theme).silver,
641
+ bold: ""
642
+ }, {
643
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("mac", -1)])]),
644
+ _: 1
645
+ }, 8, ["color"]),
646
+ createVNode(unref(Text), {
647
+ color: unref(theme).accent,
648
+ bold: ""
649
+ }, {
650
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode("hud", -1)])]),
651
+ _: 1
652
+ }, 8, ["color"]),
653
+ wide.value ? (openBlock(), createBlock(unref(Text), {
654
+ key: 0,
655
+ color: unref(theme).dim
656
+ }, {
657
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode(" · macOS system monitor", -1)])]),
658
+ _: 1
659
+ }, 8, ["color"])) : createCommentVNode("", true)
660
+ ]),
661
+ _: 1
662
+ }), createVNode(unref(Box), null, {
663
+ default: withCtx(() => [wide.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
664
+ createVNode(unref(Text), { color: unref(theme).cpu }, {
665
+ default: withCtx(() => [createTextVNode("CPU " + toDisplayString(unref(pct)(__props.m.cpu.usage)), 1)]),
666
+ _: 1
667
+ }, 8, ["color"]),
668
+ createVNode(unref(Text), { color: unref(theme).dim }, {
669
+ default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode(" · ", -1)])]),
670
+ _: 1
671
+ }, 8, ["color"]),
672
+ createVNode(unref(Text), { color: unref(theme).mem }, {
673
+ default: withCtx(() => [createTextVNode("MEM " + toDisplayString(unref(pct)(__props.m.memory.usedPct)), 1)]),
674
+ _: 1
675
+ }, 8, ["color"]),
676
+ createVNode(unref(Text), { color: unref(theme).dim }, {
677
+ default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode(" · ", -1)])]),
678
+ _: 1
679
+ }, 8, ["color"]),
680
+ createVNode(unref(Text), { color: unref(theme).gpu }, {
681
+ default: withCtx(() => [createTextVNode("GPU " + toDisplayString(unref(pct)(__props.m.gpu.usage)), 1)]),
682
+ _: 1
683
+ }, 8, ["color"]),
684
+ createVNode(unref(Text), { color: unref(theme).dim }, {
685
+ default: withCtx(() => [..._cache[5] || (_cache[5] = [createTextVNode(" · ", -1)])]),
686
+ _: 1
687
+ }, 8, ["color"]),
688
+ createVNode(unref(Text), { color: unref(theme).battery }, {
689
+ default: withCtx(() => [createTextVNode("BAT " + toDisplayString(unref(pct)(__props.m.battery.pct)) + toDisplayString(__props.m.battery.charging ? " ⇡" : ""), 1)]),
690
+ _: 1
691
+ }, 8, ["color"]),
692
+ createVNode(unref(Text), { color: unref(theme).dim }, {
693
+ default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode(" · ", -1)])]),
694
+ _: 1
695
+ }, 8, ["color"])
696
+ ], 64)) : createCommentVNode("", true), createVNode(unref(Text), {
697
+ color: unref(theme).title,
698
+ bold: ""
699
+ }, {
700
+ default: withCtx(() => [createTextVNode(toDisplayString(clock.value), 1)]),
701
+ _: 1
702
+ }, 8, ["color"])]),
703
+ _: 1
704
+ })]),
705
+ _: 1
706
+ });
707
+ };
708
+ }
709
+ });
710
+ //#endregion
711
+ //#region src/components/Panel.vue
712
+ var Panel_default = /* @__PURE__ */ defineComponent({
713
+ __name: "Panel",
714
+ props: {
715
+ title: {},
716
+ accent: { default: theme.frame },
717
+ flexGrow: { default: 1 },
718
+ flexBasis: { default: 0 },
719
+ minWidth: {},
720
+ width: {}
721
+ },
722
+ setup(__props) {
723
+ return (_ctx, _cache) => {
724
+ return openBlock(), createBlock(unref(Box), {
725
+ flexDirection: "column",
726
+ flexGrow: __props.flexGrow,
727
+ flexBasis: __props.flexBasis,
728
+ minWidth: __props.minWidth,
729
+ width: __props.width,
730
+ borderStyle: "round",
731
+ borderColor: __props.accent,
732
+ paddingX: 1
733
+ }, {
734
+ default: withCtx(() => [createVNode(unref(Box), { justifyContent: "space-between" }, {
735
+ default: withCtx(() => [createVNode(unref(Text), {
736
+ color: __props.accent,
737
+ bold: ""
738
+ }, {
739
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.title), 1)]),
740
+ _: 1
741
+ }, 8, ["color"]), renderSlot(_ctx.$slots, "header-right")]),
742
+ _: 3
743
+ }), renderSlot(_ctx.$slots, "default")]),
744
+ _: 3
745
+ }, 8, [
746
+ "flexGrow",
747
+ "flexBasis",
748
+ "minWidth",
749
+ "width",
750
+ "borderColor"
751
+ ]);
752
+ };
753
+ }
754
+ });
755
+ //#endregion
756
+ //#region src/lib/sparkline.ts
757
+ var BLOCKS = "▁▂▃▄▅▆▇█";
758
+ function sparkline(values, width, max) {
759
+ if (width <= 0) return "";
760
+ const slice = values.slice(-width);
761
+ const peak = max ?? Math.max(1, ...slice);
762
+ const cells = slice.map((v) => {
763
+ const t = clamp(v / (peak || 1), 0, 1);
764
+ return BLOCKS[Math.min(7, Math.max(0, Math.round(t * 7)))];
765
+ });
766
+ const pad = Math.max(0, width - cells.length);
767
+ return " ".repeat(pad) + cells.join("");
768
+ }
769
+ var DOT = [
770
+ [1, 8],
771
+ [2, 16],
772
+ [4, 32],
773
+ [64, 128]
774
+ ];
775
+ function brailleArea(values, width, height, max) {
776
+ if (width <= 0 || height <= 0) return [];
777
+ const dotsW = width * 2;
778
+ const dotsH = height * 4;
779
+ const slice = values.slice(-dotsW);
780
+ const peak = max ?? Math.max(1, ...slice);
781
+ const pad = Math.max(0, dotsW - slice.length);
782
+ const cells = Array.from({ length: height }, () => Array.from({ length: width }, () => 0));
783
+ for (let x = 0; x < dotsW; x++) {
784
+ const v = clamp((x < pad ? 0 : slice[x - pad]) / (peak || 1), 0, 1);
785
+ const top = Math.round((1 - v) * (dotsH - 1));
786
+ for (let y = top; y < dotsH; y++) cells[Math.floor(y / 4)][Math.floor(x / 2)] |= DOT[y % 4][x % 2];
787
+ }
788
+ return cells.map((row) => row.map((b) => String.fromCharCode(10240 | b)).join(""));
789
+ }
790
+ function barCells(value, max, width) {
791
+ const ratio = max > 0 && Number.isFinite(value) ? clamp(value / max, 0, 1) : 0;
792
+ const filled = Math.round(ratio * width);
793
+ return {
794
+ fill: "█".repeat(filled),
795
+ rest: "░".repeat(Math.max(0, width - filled))
796
+ };
797
+ }
798
+ //#endregion
799
+ //#region src/lib/color.ts
800
+ function hexToRgb(hex) {
801
+ const h = hex.replace("#", "");
802
+ const ch = (a, b) => {
803
+ const v = parseInt(h.slice(a, b), 16);
804
+ return Number.isFinite(v) ? v : 0;
805
+ };
806
+ return [
807
+ ch(0, 2),
808
+ ch(2, 4),
809
+ ch(4, 6)
810
+ ];
811
+ }
812
+ function toHex([r, g, b]) {
813
+ const c = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0");
814
+ return `#${c(r)}${c(g)}${c(b)}`;
815
+ }
816
+ function mix(a, b, t) {
817
+ const x = hexToRgb(a);
818
+ const y = hexToRgb(b);
819
+ return toHex([
820
+ x[0] + (y[0] - x[0]) * t,
821
+ x[1] + (y[1] - x[1]) * t,
822
+ x[2] + (y[2] - x[2]) * t
823
+ ]);
824
+ }
825
+ function ramp(hex, n) {
826
+ const dim = mix("#000000", hex, .5);
827
+ return Array.from({ length: n }, (_, i) => mix(dim, hex, n > 1 ? i / (n - 1) : 1));
828
+ }
829
+ function supportsTruecolor() {
830
+ return chalk.level >= 3;
831
+ }
832
+ //#endregion
833
+ //#region src/components/Bar.vue
834
+ var Bar_default = /* @__PURE__ */ defineComponent({
835
+ __name: "Bar",
836
+ props: {
837
+ value: {},
838
+ max: { default: 100 },
839
+ width: { default: 12 },
840
+ color: {}
841
+ },
842
+ setup(__props) {
843
+ const props = __props;
844
+ const cells = computed(() => barCells(props.value, props.max, props.width));
845
+ const col = computed(() => props.color ?? levelColor(props.max > 0 ? props.value / props.max * 100 : 0));
846
+ const fillChars = computed(() => [...cells.value.fill]);
847
+ const gradient = computed(() => supportsTruecolor() && fillChars.value.length > 1);
848
+ const fillColors = computed(() => ramp(col.value, fillChars.value.length));
849
+ return (_ctx, _cache) => {
850
+ return openBlock(), createElementBlock(Fragment, null, [gradient.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(fillChars.value, (c, i) => {
851
+ return openBlock(), createBlock(unref(Text), {
852
+ key: i,
853
+ color: fillColors.value[i]
854
+ }, {
855
+ default: withCtx(() => [createTextVNode(toDisplayString(c), 1)]),
856
+ _: 2
857
+ }, 1032, ["color"]);
858
+ }), 128)) : (openBlock(), createBlock(unref(Text), {
859
+ key: 1,
860
+ color: col.value
861
+ }, {
862
+ default: withCtx(() => [createTextVNode(toDisplayString(cells.value.fill), 1)]),
863
+ _: 1
864
+ }, 8, ["color"])), createVNode(unref(Text), { color: unref(theme).frame }, {
865
+ default: withCtx(() => [createTextVNode(toDisplayString(cells.value.rest), 1)]),
866
+ _: 1
867
+ }, 8, ["color"])], 64);
868
+ };
869
+ }
870
+ });
871
+ //#endregion
872
+ //#region src/components/Graph.vue
873
+ var Graph_default = /* @__PURE__ */ defineComponent({
874
+ __name: "Graph",
875
+ props: {
876
+ values: {},
877
+ height: { default: 3 },
878
+ max: {},
879
+ color: { default: theme.cpu }
880
+ },
881
+ setup(__props) {
882
+ const props = __props;
883
+ const box = ref();
884
+ const bm = useBoxMetrics(box);
885
+ const rows = computed(() => brailleArea(props.values, Math.max(1, bm.width.value || 24), props.height, props.max));
886
+ const rowColors = computed(() => supportsTruecolor() ? ramp(props.color, props.height).slice().reverse() : Array(props.height).fill(props.color));
887
+ return (_ctx, _cache) => {
888
+ return openBlock(), createBlock(unref(Box), {
889
+ ref_key: "box",
890
+ ref: box,
891
+ flexDirection: "column",
892
+ width: "100%"
893
+ }, {
894
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(rows.value, (row, i) => {
895
+ return openBlock(), createBlock(unref(Text), {
896
+ key: i,
897
+ color: rowColors.value[i],
898
+ wrap: "truncate"
899
+ }, {
900
+ default: withCtx(() => [createTextVNode(toDisplayString(row), 1)]),
901
+ _: 2
902
+ }, 1032, ["color"]);
903
+ }), 128))]),
904
+ _: 1
905
+ }, 512);
906
+ };
907
+ }
908
+ });
909
+ //#endregion
910
+ //#region src/lib/bignum.ts
911
+ var HEIGHT = 5;
912
+ var FONT = {
913
+ "0": [
914
+ "███",
915
+ "█ █",
916
+ "█ █",
917
+ "█ █",
918
+ "███"
919
+ ],
920
+ "1": [
921
+ " █ ",
922
+ " █ ",
923
+ " █ ",
924
+ " █ ",
925
+ " █ "
926
+ ],
927
+ "2": [
928
+ "███",
929
+ " █",
930
+ "███",
931
+ "█ ",
932
+ "███"
933
+ ],
934
+ "3": [
935
+ "███",
936
+ " █",
937
+ "███",
938
+ " █",
939
+ "███"
940
+ ],
941
+ "4": [
942
+ "█ █",
943
+ "█ █",
944
+ "███",
945
+ " █",
946
+ " █"
947
+ ],
948
+ "5": [
949
+ "███",
950
+ "█ ",
951
+ "███",
952
+ " █",
953
+ "███"
954
+ ],
955
+ "6": [
956
+ "███",
957
+ "█ ",
958
+ "███",
959
+ "█ █",
960
+ "███"
961
+ ],
962
+ "7": [
963
+ "███",
964
+ " █",
965
+ " █",
966
+ " █",
967
+ " █"
968
+ ],
969
+ "8": [
970
+ "███",
971
+ "█ █",
972
+ "███",
973
+ "█ █",
974
+ "███"
975
+ ],
976
+ "9": [
977
+ "███",
978
+ "█ █",
979
+ "███",
980
+ " █",
981
+ "███"
982
+ ],
983
+ "-": [
984
+ " ",
985
+ " ",
986
+ "███",
987
+ " ",
988
+ " "
989
+ ],
990
+ " ": [
991
+ " ",
992
+ " ",
993
+ " ",
994
+ " ",
995
+ " "
996
+ ]
997
+ };
998
+ var BLANK = FONT[" "];
999
+ function bigDigits(s) {
1000
+ const glyphs = [...s].map((c) => FONT[c] ?? BLANK);
1001
+ if (glyphs.length === 0) glyphs.push(BLANK);
1002
+ return Array.from({ length: HEIGHT }, (_, r) => glyphs.map((g) => g[r]).join(" "));
1003
+ }
1004
+ //#endregion
1005
+ //#region src/components/BigNumber.vue
1006
+ var BigNumber_default = /* @__PURE__ */ defineComponent({
1007
+ __name: "BigNumber",
1008
+ props: {
1009
+ value: {},
1010
+ suffix: { default: "" },
1011
+ color: { default: theme.cpu }
1012
+ },
1013
+ setup(__props) {
1014
+ const props = __props;
1015
+ const rows = computed(() => bigDigits(String(Math.round(props.value))));
1016
+ const rowColors = computed(() => supportsTruecolor() ? ramp(props.color, rows.value.length).slice().reverse() : Array(rows.value.length).fill(props.color));
1017
+ return (_ctx, _cache) => {
1018
+ return openBlock(), createBlock(unref(Box), { flexDirection: "column" }, {
1019
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(rows.value, (row, i) => {
1020
+ return openBlock(), createBlock(unref(Box), { key: i }, {
1021
+ default: withCtx(() => [createVNode(unref(Text), { color: rowColors.value[i] }, {
1022
+ default: withCtx(() => [createTextVNode(toDisplayString(row), 1)]),
1023
+ _: 2
1024
+ }, 1032, ["color"]), __props.suffix && i === rows.value.length - 1 ? (openBlock(), createBlock(unref(Text), {
1025
+ key: 0,
1026
+ color: unref(theme).dim
1027
+ }, {
1028
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.suffix), 1)]),
1029
+ _: 1
1030
+ }, 8, ["color"])) : createCommentVNode("", true)]),
1031
+ _: 2
1032
+ }, 1024);
1033
+ }), 128))]),
1034
+ _: 1
1035
+ });
1036
+ };
1037
+ }
1038
+ });
1039
+ //#endregion
1040
+ //#region src/components/CoreGrid.vue?vue&type=script&setup=true&lang.ts
1041
+ var LEVELS = "▁▂▃▄▅▆▇█";
1042
+ //#endregion
1043
+ //#region src/components/CoreGrid.vue
1044
+ var CoreGrid_default = /* @__PURE__ */ defineComponent({
1045
+ __name: "CoreGrid",
1046
+ props: { cores: {} },
1047
+ setup(__props) {
1048
+ const props = __props;
1049
+ const glyph = (u) => LEVELS[Math.min(7, Math.max(0, Math.round(u / 100 * 7)))];
1050
+ const groups = computed(() => {
1051
+ const e = props.cores.filter((c) => c.cluster === "E");
1052
+ const p = props.cores.filter((c) => c.cluster === "P");
1053
+ if (e.length === 0 || p.length === 0) return [{
1054
+ label: "",
1055
+ cores: props.cores
1056
+ }];
1057
+ return [{
1058
+ label: "E",
1059
+ cores: e
1060
+ }, {
1061
+ label: "P",
1062
+ cores: p
1063
+ }];
1064
+ });
1065
+ return (_ctx, _cache) => {
1066
+ return openBlock(true), createElementBlock(Fragment, null, renderList(groups.value, (g, gi) => {
1067
+ return openBlock(), createBlock(unref(Box), { key: gi }, {
1068
+ default: withCtx(() => [g.label ? (openBlock(), createBlock(unref(Text), {
1069
+ key: 0,
1070
+ color: unref(theme).dim
1071
+ }, {
1072
+ default: withCtx(() => [createTextVNode(toDisplayString(g.label), 1)]),
1073
+ _: 2
1074
+ }, 1032, ["color"])) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(g.cores, (c, ci) => {
1075
+ return openBlock(), createBlock(unref(Text), {
1076
+ key: ci,
1077
+ color: unref(levelColor)(c.usage)
1078
+ }, {
1079
+ default: withCtx(() => [createTextVNode(toDisplayString(glyph(c.usage)), 1)]),
1080
+ _: 2
1081
+ }, 1032, ["color"]);
1082
+ }), 128))]),
1083
+ _: 2
1084
+ }, 1024);
1085
+ }), 128);
1086
+ };
1087
+ }
1088
+ });
1089
+ //#endregion
1090
+ //#region src/components/panels/CpuPanel.vue
1091
+ var CpuPanel_default = /* @__PURE__ */ defineComponent({
1092
+ __name: "CpuPanel",
1093
+ props: {
1094
+ cpu: {},
1095
+ history: {}
1096
+ },
1097
+ setup(__props) {
1098
+ return (_ctx, _cache) => {
1099
+ return openBlock(), createBlock(Panel_default, {
1100
+ title: " CPU",
1101
+ accent: unref(theme).cpu,
1102
+ flexGrow: 3,
1103
+ minWidth: 32
1104
+ }, {
1105
+ "header-right": withCtx(() => [createVNode(unref(Text), {
1106
+ color: unref(theme).dim,
1107
+ wrap: "truncate"
1108
+ }, {
1109
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.cpu.model), 1)]),
1110
+ _: 1
1111
+ }, 8, ["color"])]),
1112
+ default: withCtx(() => [
1113
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1114
+ default: withCtx(() => [createVNode(BigNumber_default, {
1115
+ value: __props.cpu.usage,
1116
+ suffix: "%",
1117
+ color: unref(theme).cpu
1118
+ }, null, 8, ["value", "color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1119
+ default: withCtx(() => [createTextVNode("load " + toDisplayString(__props.cpu.loadAvg[0].toFixed(2)), 1)]),
1120
+ _: 1
1121
+ }, 8, ["color"])]),
1122
+ _: 1
1123
+ }),
1124
+ createVNode(Graph_default, {
1125
+ values: __props.history,
1126
+ max: 100,
1127
+ height: 4,
1128
+ color: unref(theme).cpu
1129
+ }, null, 8, ["values", "color"]),
1130
+ createVNode(unref(Box), null, {
1131
+ default: withCtx(() => [
1132
+ createVNode(unref(Text), { color: unref(theme).dim }, {
1133
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("P ", -1)])]),
1134
+ _: 1
1135
+ }, 8, ["color"]),
1136
+ createVNode(Bar_default, {
1137
+ value: __props.cpu.pUsage,
1138
+ width: 12
1139
+ }, null, 8, ["value"]),
1140
+ createVNode(unref(Text), { color: unref(theme).text }, {
1141
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(pct)(__props.cpu.pUsage)), 1)]),
1142
+ _: 1
1143
+ }, 8, ["color"])
1144
+ ]),
1145
+ _: 1
1146
+ }),
1147
+ createVNode(unref(Box), null, {
1148
+ default: withCtx(() => [
1149
+ createVNode(unref(Text), { color: unref(theme).dim }, {
1150
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode("E ", -1)])]),
1151
+ _: 1
1152
+ }, 8, ["color"]),
1153
+ createVNode(Bar_default, {
1154
+ value: __props.cpu.eUsage,
1155
+ width: 12
1156
+ }, null, 8, ["value"]),
1157
+ createVNode(unref(Text), { color: unref(theme).text }, {
1158
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(pct)(__props.cpu.eUsage)), 1)]),
1159
+ _: 1
1160
+ }, 8, ["color"])
1161
+ ]),
1162
+ _: 1
1163
+ }),
1164
+ createVNode(CoreGrid_default, { cores: __props.cpu.cores }, null, 8, ["cores"]),
1165
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.cpu.topProcs.slice(0, 3), (p) => {
1166
+ return openBlock(), createBlock(unref(Box), {
1167
+ key: p.name,
1168
+ justifyContent: "space-between"
1169
+ }, {
1170
+ default: withCtx(() => [createVNode(unref(Text), {
1171
+ color: unref(theme).text,
1172
+ wrap: "truncate"
1173
+ }, {
1174
+ default: withCtx(() => [createTextVNode(toDisplayString(p.name), 1)]),
1175
+ _: 2
1176
+ }, 1032, ["color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1177
+ default: withCtx(() => [createTextVNode(toDisplayString(p.pct.toFixed(0)) + "%", 1)]),
1178
+ _: 2
1179
+ }, 1032, ["color"])]),
1180
+ _: 2
1181
+ }, 1024);
1182
+ }), 128))
1183
+ ]),
1184
+ _: 1
1185
+ }, 8, ["accent"]);
1186
+ };
1187
+ }
1188
+ });
1189
+ //#endregion
1190
+ //#region src/components/panels/MemoryPanel.vue
1191
+ var MemoryPanel_default = /* @__PURE__ */ defineComponent({
1192
+ __name: "MemoryPanel",
1193
+ props: {
1194
+ memory: {},
1195
+ history: {}
1196
+ },
1197
+ setup(__props) {
1198
+ const pressureColor = (p) => p === "High" ? theme.bad : p === "Elevated" ? theme.warn : theme.good;
1199
+ return (_ctx, _cache) => {
1200
+ return openBlock(), createBlock(Panel_default, {
1201
+ title: " MEMORY",
1202
+ accent: unref(theme).mem,
1203
+ flexGrow: 2,
1204
+ minWidth: 28
1205
+ }, {
1206
+ "header-right": withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1207
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(humanBytes)(__props.memory.used)) + " / " + toDisplayString(unref(humanBytes)(__props.memory.total)), 1)]),
1208
+ _: 1
1209
+ }, 8, ["color"])]),
1210
+ default: withCtx(() => [
1211
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1212
+ default: withCtx(() => [createVNode(BigNumber_default, {
1213
+ value: __props.memory.usedPct,
1214
+ suffix: "%",
1215
+ color: unref(theme).mem
1216
+ }, null, 8, ["value", "color"]), createVNode(unref(Text), { color: pressureColor(__props.memory.pressure) }, {
1217
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.memory.pressure), 1)]),
1218
+ _: 1
1219
+ }, 8, ["color"])]),
1220
+ _: 1
1221
+ }),
1222
+ createVNode(Graph_default, {
1223
+ values: __props.history,
1224
+ max: 100,
1225
+ height: 4,
1226
+ color: unref(theme).mem
1227
+ }, null, 8, ["values", "color"]),
1228
+ createVNode(unref(Box), null, {
1229
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1230
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("used ", -1)])]),
1231
+ _: 1
1232
+ }, 8, ["color"]), createVNode(Bar_default, {
1233
+ value: __props.memory.usedPct,
1234
+ width: 14
1235
+ }, null, 8, ["value"])]),
1236
+ _: 1
1237
+ }),
1238
+ createVNode(unref(Box), null, {
1239
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1240
+ default: withCtx(() => [createTextVNode("wired " + toDisplayString(unref(humanBytes)(__props.memory.wired)) + " · swap " + toDisplayString(unref(humanBytes)(__props.memory.swapUsed)), 1)]),
1241
+ _: 1
1242
+ }, 8, ["color"])]),
1243
+ _: 1
1244
+ }),
1245
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.memory.topApps.slice(0, 3), (app) => {
1246
+ return openBlock(), createBlock(unref(Box), {
1247
+ key: app.name,
1248
+ justifyContent: "space-between"
1249
+ }, {
1250
+ default: withCtx(() => [createVNode(unref(Text), {
1251
+ color: unref(theme).text,
1252
+ wrap: "truncate"
1253
+ }, {
1254
+ default: withCtx(() => [createTextVNode(toDisplayString(app.name), 1)]),
1255
+ _: 2
1256
+ }, 1032, ["color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1257
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(humanBytes)(app.bytes)), 1)]),
1258
+ _: 2
1259
+ }, 1032, ["color"])]),
1260
+ _: 2
1261
+ }, 1024);
1262
+ }), 128))
1263
+ ]),
1264
+ _: 1
1265
+ }, 8, ["accent"]);
1266
+ };
1267
+ }
1268
+ });
1269
+ //#endregion
1270
+ //#region src/components/panels/GpuPanel.vue
1271
+ var GpuPanel_default = /* @__PURE__ */ defineComponent({
1272
+ __name: "GpuPanel",
1273
+ props: {
1274
+ gpu: {},
1275
+ history: {}
1276
+ },
1277
+ setup(__props) {
1278
+ return (_ctx, _cache) => {
1279
+ return openBlock(), createBlock(Panel_default, {
1280
+ title: " GPU",
1281
+ accent: unref(theme).gpu,
1282
+ flexGrow: 6,
1283
+ minWidth: 22
1284
+ }, {
1285
+ default: withCtx(() => [
1286
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1287
+ default: withCtx(() => [createVNode(unref(Text), {
1288
+ color: unref(theme).gpu,
1289
+ bold: ""
1290
+ }, {
1291
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(pct)(__props.gpu.usage)), 1)]),
1292
+ _: 1
1293
+ }, 8, ["color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1294
+ default: withCtx(() => [createTextVNode("render " + toDisplayString(unref(pct)(__props.gpu.renderer)), 1)]),
1295
+ _: 1
1296
+ }, 8, ["color"])]),
1297
+ _: 1
1298
+ }),
1299
+ createVNode(Graph_default, {
1300
+ values: __props.history,
1301
+ max: 100,
1302
+ height: 3,
1303
+ color: unref(theme).gpu
1304
+ }, null, 8, ["values", "color"]),
1305
+ createVNode(unref(Box), null, {
1306
+ default: withCtx(() => [createVNode(Bar_default, {
1307
+ value: __props.gpu.usage ?? 0,
1308
+ width: 14,
1309
+ color: unref(theme).accent
1310
+ }, null, 8, ["value", "color"])]),
1311
+ _: 1
1312
+ }),
1313
+ createVNode(unref(Box), null, {
1314
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1315
+ default: withCtx(() => [createTextVNode("vram " + toDisplayString(unref(humanBytes)(__props.gpu.vram)), 1)]),
1316
+ _: 1
1317
+ }, 8, ["color"])]),
1318
+ _: 1
1319
+ })
1320
+ ]),
1321
+ _: 1
1322
+ }, 8, ["accent"]);
1323
+ };
1324
+ }
1325
+ });
1326
+ //#endregion
1327
+ //#region src/components/panels/DiskPanel.vue
1328
+ var DiskPanel_default = /* @__PURE__ */ defineComponent({
1329
+ __name: "DiskPanel",
1330
+ props: { disk: {} },
1331
+ setup(__props) {
1332
+ const props = __props;
1333
+ const diskColor = computed(() => props.disk.usedPct >= 95 ? theme.bad : props.disk.usedPct >= 85 ? theme.warn : theme.accent);
1334
+ const diskState = computed(() => props.disk.usedPct >= 95 ? "FULL" : props.disk.usedPct >= 85 ? "NEAR FULL" : "");
1335
+ return (_ctx, _cache) => {
1336
+ return openBlock(), createBlock(Panel_default, {
1337
+ title: " DISK",
1338
+ accent: unref(theme).disk,
1339
+ flexGrow: 3,
1340
+ minWidth: 22
1341
+ }, {
1342
+ "header-right": withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1343
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.disk.mount), 1)]),
1344
+ _: 1
1345
+ }, 8, ["color"])]),
1346
+ default: withCtx(() => [
1347
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1348
+ default: withCtx(() => [createVNode(unref(Text), {
1349
+ color: unref(theme).disk,
1350
+ bold: ""
1351
+ }, {
1352
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(pct)(__props.disk.usedPct)), 1)]),
1353
+ _: 1
1354
+ }, 8, ["color"]), createVNode(unref(Text), { color: diskState.value ? diskColor.value : unref(theme).dim }, {
1355
+ default: withCtx(() => [createTextVNode(toDisplayString(diskState.value || `${unref(humanBytes)(__props.disk.free)} free`), 1)]),
1356
+ _: 1
1357
+ }, 8, ["color"])]),
1358
+ _: 1
1359
+ }),
1360
+ createVNode(unref(Box), null, {
1361
+ default: withCtx(() => [createVNode(Bar_default, {
1362
+ value: __props.disk.usedPct,
1363
+ width: 16,
1364
+ color: diskColor.value
1365
+ }, null, 8, ["value", "color"])]),
1366
+ _: 1
1367
+ }),
1368
+ createVNode(unref(Box), null, {
1369
+ default: withCtx(() => [
1370
+ createVNode(unref(Text), { color: unref(theme).dim }, {
1371
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("R ", -1)])]),
1372
+ _: 1
1373
+ }, 8, ["color"]),
1374
+ createVNode(unref(Text), { color: unref(theme).text }, {
1375
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(humanBytes)(__props.disk.readBps, true)), 1)]),
1376
+ _: 1
1377
+ }, 8, ["color"]),
1378
+ createVNode(unref(Text), { color: unref(theme).dim }, {
1379
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode(" W ", -1)])]),
1380
+ _: 1
1381
+ }, 8, ["color"]),
1382
+ createVNode(unref(Text), { color: unref(theme).text }, {
1383
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(humanBytes)(__props.disk.writeBps, true)), 1)]),
1384
+ _: 1
1385
+ }, 8, ["color"])
1386
+ ]),
1387
+ _: 1
1388
+ }),
1389
+ createVNode(unref(Box), null, {
1390
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1391
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(humanBytes)(__props.disk.used)) + " / " + toDisplayString(unref(humanBytes)(__props.disk.total)), 1)]),
1392
+ _: 1
1393
+ }, 8, ["color"])]),
1394
+ _: 1
1395
+ })
1396
+ ]),
1397
+ _: 1
1398
+ }, 8, ["accent"]);
1399
+ };
1400
+ }
1401
+ });
1402
+ //#endregion
1403
+ //#region src/components/Sparkline.vue
1404
+ var Sparkline_default = /* @__PURE__ */ defineComponent({
1405
+ __name: "Sparkline",
1406
+ props: {
1407
+ values: {},
1408
+ max: {},
1409
+ color: { default: theme.cpu }
1410
+ },
1411
+ setup(__props) {
1412
+ const props = __props;
1413
+ const box = ref();
1414
+ const bm = useBoxMetrics(box);
1415
+ const line = computed(() => sparkline(props.values, Math.max(1, bm.width.value || 24), props.max));
1416
+ return (_ctx, _cache) => {
1417
+ return openBlock(), createBlock(unref(Box), {
1418
+ ref_key: "box",
1419
+ ref: box,
1420
+ width: "100%"
1421
+ }, {
1422
+ default: withCtx(() => [createVNode(unref(Text), {
1423
+ color: __props.color,
1424
+ wrap: "truncate"
1425
+ }, {
1426
+ default: withCtx(() => [createTextVNode(toDisplayString(line.value), 1)]),
1427
+ _: 1
1428
+ }, 8, ["color"])]),
1429
+ _: 1
1430
+ }, 512);
1431
+ };
1432
+ }
1433
+ });
1434
+ //#endregion
1435
+ //#region src/components/panels/NetworkPanel.vue
1436
+ var NetworkPanel_default = /* @__PURE__ */ defineComponent({
1437
+ __name: "NetworkPanel",
1438
+ props: {
1439
+ net: {},
1440
+ rx: {},
1441
+ tx: {}
1442
+ },
1443
+ setup(__props) {
1444
+ return (_ctx, _cache) => {
1445
+ return openBlock(), createBlock(Panel_default, {
1446
+ title: " NETWORK",
1447
+ accent: unref(theme).net,
1448
+ flexGrow: 2,
1449
+ minWidth: 26
1450
+ }, {
1451
+ "header-right": withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1452
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.net.iface), 1)]),
1453
+ _: 1
1454
+ }, 8, ["color"])]),
1455
+ default: withCtx(() => [
1456
+ createVNode(unref(Box), null, {
1457
+ default: withCtx(() => [createVNode(unref(Text), {
1458
+ color: unref(theme).net,
1459
+ bold: ""
1460
+ }, {
1461
+ default: withCtx(() => [createTextVNode("▼ " + toDisplayString(unref(humanBytes)(__props.net.rxBps, true)), 1)]),
1462
+ _: 1
1463
+ }, 8, ["color"])]),
1464
+ _: 1
1465
+ }),
1466
+ createVNode(Sparkline_default, {
1467
+ values: __props.rx,
1468
+ color: unref(theme).net
1469
+ }, null, 8, ["values", "color"]),
1470
+ createVNode(unref(Box), null, {
1471
+ default: withCtx(() => [createVNode(unref(Text), {
1472
+ color: unref(theme).gpu,
1473
+ bold: ""
1474
+ }, {
1475
+ default: withCtx(() => [createTextVNode("▲ " + toDisplayString(unref(humanBytes)(__props.net.txBps, true)), 1)]),
1476
+ _: 1
1477
+ }, 8, ["color"])]),
1478
+ _: 1
1479
+ }),
1480
+ createVNode(Sparkline_default, {
1481
+ values: __props.tx,
1482
+ color: unref(theme).gpu
1483
+ }, null, 8, ["values", "color"])
1484
+ ]),
1485
+ _: 1
1486
+ }, 8, ["accent"]);
1487
+ };
1488
+ }
1489
+ });
1490
+ //#endregion
1491
+ //#region src/components/panels/BatteryPanel.vue
1492
+ var BatteryPanel_default = /* @__PURE__ */ defineComponent({
1493
+ __name: "BatteryPanel",
1494
+ props: { battery: {} },
1495
+ setup(__props) {
1496
+ const props = __props;
1497
+ const watts = computed(() => {
1498
+ const b = props.battery;
1499
+ const parts = [];
1500
+ if (b.chargeWatts != null && Math.abs(b.chargeWatts) >= .1) parts.push(`${b.chargeWatts >= 0 ? "+" : "−"}${Math.abs(b.chargeWatts).toFixed(1)}W`);
1501
+ if (b.adapterWatts != null) parts.push(`${b.adapterWatts}W adapter`);
1502
+ return parts.join(" · ");
1503
+ });
1504
+ return (_ctx, _cache) => {
1505
+ return openBlock(), createBlock(Panel_default, {
1506
+ title: " BATTERY",
1507
+ accent: unref(theme).battery,
1508
+ flexGrow: 1,
1509
+ minWidth: 24
1510
+ }, {
1511
+ "header-right": withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1512
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.battery.charging ? "⇡ charging" : __props.battery.state), 1)]),
1513
+ _: 1
1514
+ }, 8, ["color"])]),
1515
+ default: withCtx(() => [
1516
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1517
+ default: withCtx(() => [createVNode(unref(Text), {
1518
+ color: unref(theme).battery,
1519
+ bold: ""
1520
+ }, {
1521
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(pct)(__props.battery.pct)), 1)]),
1522
+ _: 1
1523
+ }, 8, ["color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1524
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.battery.timeRemaining ?? (__props.battery.charging ? "—" : "on AC")), 1)]),
1525
+ _: 1
1526
+ }, 8, ["color"])]),
1527
+ _: 1
1528
+ }),
1529
+ createVNode(unref(Box), null, {
1530
+ default: withCtx(() => [createVNode(Bar_default, {
1531
+ value: __props.battery.pct,
1532
+ width: 16,
1533
+ color: unref(theme).accent
1534
+ }, null, 8, ["value", "color"])]),
1535
+ _: 1
1536
+ }),
1537
+ createVNode(unref(Box), null, {
1538
+ default: withCtx(() => [
1539
+ createVNode(unref(Text), { color: unref(theme).dim }, {
1540
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("health ", -1)])]),
1541
+ _: 1
1542
+ }, 8, ["color"]),
1543
+ createVNode(unref(Text), { color: unref(theme).text }, {
1544
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(pct)(__props.battery.healthPct)), 1)]),
1545
+ _: 1
1546
+ }, 8, ["color"]),
1547
+ createVNode(unref(Text), { color: unref(theme).dim }, {
1548
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode(" cycles ", -1)])]),
1549
+ _: 1
1550
+ }, 8, ["color"]),
1551
+ createVNode(unref(Text), { color: unref(theme).text }, {
1552
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.battery.cycleCount ?? "—"), 1)]),
1553
+ _: 1
1554
+ }, 8, ["color"])
1555
+ ]),
1556
+ _: 1
1557
+ }),
1558
+ createVNode(unref(Box), null, {
1559
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1560
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("power ", -1)])]),
1561
+ _: 1
1562
+ }, 8, ["color"]), createVNode(unref(Text), { color: unref(theme).text }, {
1563
+ default: withCtx(() => [createTextVNode(toDisplayString(watts.value || (__props.battery.present ? "on AC" : "—")), 1)]),
1564
+ _: 1
1565
+ }, 8, ["color"])]),
1566
+ _: 1
1567
+ })
1568
+ ]),
1569
+ _: 1
1570
+ }, 8, ["accent"]);
1571
+ };
1572
+ }
1573
+ });
1574
+ //#endregion
1575
+ //#region src/components/panels/SensorsPanel.vue
1576
+ var SensorsPanel_default = /* @__PURE__ */ defineComponent({
1577
+ __name: "SensorsPanel",
1578
+ props: { sensors: {} },
1579
+ setup(__props) {
1580
+ const props = __props;
1581
+ const pressureColor = computed(() => props.sensors.thermalPressure === "Nominal" ? theme.good : props.sensors.thermalPressure === "Fair" ? theme.warn : theme.bad);
1582
+ return (_ctx, _cache) => {
1583
+ return openBlock(), createBlock(Panel_default, {
1584
+ title: " SENSORS",
1585
+ accent: unref(theme).sensor,
1586
+ flexGrow: 2,
1587
+ minWidth: 24
1588
+ }, {
1589
+ default: withCtx(() => [
1590
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1591
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1592
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("thermal", -1)])]),
1593
+ _: 1
1594
+ }, 8, ["color"]), createVNode(unref(Text), {
1595
+ color: pressureColor.value,
1596
+ bold: ""
1597
+ }, {
1598
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.sensors.thermalPressure), 1)]),
1599
+ _: 1
1600
+ }, 8, ["color"])]),
1601
+ _: 1
1602
+ }),
1603
+ createVNode(unref(Box), null, {
1604
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1605
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode("cpu cap ", -1)])]),
1606
+ _: 1
1607
+ }, 8, ["color"]), createVNode(Bar_default, {
1608
+ value: __props.sensors.speedLimit,
1609
+ width: 12,
1610
+ color: unref(theme).sensor
1611
+ }, null, 8, ["value", "color"])]),
1612
+ _: 1
1613
+ }),
1614
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1615
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1616
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("battery temp", -1)])]),
1617
+ _: 1
1618
+ }, 8, ["color"]), createVNode(unref(Text), { color: unref(theme).text }, {
1619
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(temp)(__props.sensors.batteryTempC)), 1)]),
1620
+ _: 1
1621
+ }, 8, ["color"])]),
1622
+ _: 1
1623
+ })
1624
+ ]),
1625
+ _: 1
1626
+ }, 8, ["accent"]);
1627
+ };
1628
+ }
1629
+ });
1630
+ //#endregion
1631
+ //#region src/components/NarrowView.vue
1632
+ var NarrowView_default = /* @__PURE__ */ defineComponent({
1633
+ __name: "NarrowView",
1634
+ props: { m: {} },
1635
+ setup(__props) {
1636
+ return (_ctx, _cache) => {
1637
+ return openBlock(), createBlock(unref(Box), {
1638
+ flexDirection: "column",
1639
+ paddingX: 1
1640
+ }, {
1641
+ default: withCtx(() => [
1642
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1643
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).cpu }, {
1644
+ default: withCtx(() => [createTextVNode("CPU " + toDisplayString(unref(pct)(__props.m.cpu.usage)), 1)]),
1645
+ _: 1
1646
+ }, 8, ["color"]), createVNode(unref(Box), null, {
1647
+ default: withCtx(() => [createVNode(Bar_default, {
1648
+ value: __props.m.cpu.usage,
1649
+ width: 10
1650
+ }, null, 8, ["value"])]),
1651
+ _: 1
1652
+ })]),
1653
+ _: 1
1654
+ }),
1655
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1656
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).mem }, {
1657
+ default: withCtx(() => [createTextVNode("MEM " + toDisplayString(unref(pct)(__props.m.memory.usedPct)), 1)]),
1658
+ _: 1
1659
+ }, 8, ["color"]), createVNode(unref(Box), null, {
1660
+ default: withCtx(() => [createVNode(Bar_default, {
1661
+ value: __props.m.memory.usedPct,
1662
+ width: 10
1663
+ }, null, 8, ["value"])]),
1664
+ _: 1
1665
+ })]),
1666
+ _: 1
1667
+ }),
1668
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1669
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).gpu }, {
1670
+ default: withCtx(() => [createTextVNode("GPU " + toDisplayString(unref(pct)(__props.m.gpu.usage)), 1)]),
1671
+ _: 1
1672
+ }, 8, ["color"]), createVNode(unref(Box), null, {
1673
+ default: withCtx(() => [createVNode(Bar_default, {
1674
+ value: __props.m.gpu.usage ?? 0,
1675
+ width: 10,
1676
+ color: unref(theme).accent
1677
+ }, null, 8, ["value", "color"])]),
1678
+ _: 1
1679
+ })]),
1680
+ _: 1
1681
+ }),
1682
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1683
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).disk }, {
1684
+ default: withCtx(() => [createTextVNode("DISK " + toDisplayString(unref(pct)(__props.m.disk.usedPct)), 1)]),
1685
+ _: 1
1686
+ }, 8, ["color"]), createVNode(unref(Box), null, {
1687
+ default: withCtx(() => [createVNode(Bar_default, {
1688
+ value: __props.m.disk.usedPct,
1689
+ width: 10
1690
+ }, null, 8, ["value"])]),
1691
+ _: 1
1692
+ })]),
1693
+ _: 1
1694
+ }),
1695
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1696
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).net }, {
1697
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("NET", -1)])]),
1698
+ _: 1
1699
+ }, 8, ["color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1700
+ default: withCtx(() => [createTextVNode("▼" + toDisplayString(unref(humanBytes)(__props.m.net.rxBps, true)) + " ▲" + toDisplayString(unref(humanBytes)(__props.m.net.txBps, true)), 1)]),
1701
+ _: 1
1702
+ }, 8, ["color"])]),
1703
+ _: 1
1704
+ }),
1705
+ createVNode(unref(Box), { justifyContent: "space-between" }, {
1706
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).battery }, {
1707
+ default: withCtx(() => [createTextVNode("BAT " + toDisplayString(unref(pct)(__props.m.battery.pct)), 1)]),
1708
+ _: 1
1709
+ }, 8, ["color"]), createVNode(unref(Text), { color: unref(theme).dim }, {
1710
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.m.battery.charging ? "⇡ charging" : __props.m.battery.present ? "on AC" : "—"), 1)]),
1711
+ _: 1
1712
+ }, 8, ["color"])]),
1713
+ _: 1
1714
+ })
1715
+ ]),
1716
+ _: 1
1717
+ });
1718
+ };
1719
+ }
1720
+ });
1721
+ //#endregion
1722
+ //#region src/App.vue
1723
+ var App_default = /* @__PURE__ */ defineComponent({
1724
+ __name: "App",
1725
+ props: {
1726
+ snapshot: {},
1727
+ columns: {}
1728
+ },
1729
+ setup(__props) {
1730
+ const props = __props;
1731
+ const { metrics, history, now } = useMetrics();
1732
+ const { columns } = useWindowSize();
1733
+ const m = computed(() => props.snapshot ?? metrics.value ?? emptyMetrics());
1734
+ const clockTs = computed(() => props.snapshot ? props.snapshot.ts || Date.now() : now.value);
1735
+ const width = computed(() => props.columns || columns.value || 120);
1736
+ const hist = computed(() => {
1737
+ if (!props.snapshot) return history.value;
1738
+ const s = props.snapshot;
1739
+ const flat = (v) => Array.from({ length: 48 }, () => v);
1740
+ return {
1741
+ cpu: flat(s.cpu.usage),
1742
+ gpu: flat(s.gpu.usage ?? 0),
1743
+ mem: flat(s.memory.usedPct),
1744
+ rx: flat(s.net.rxBps),
1745
+ tx: flat(s.net.txBps)
1746
+ };
1747
+ });
1748
+ watchEffect(() => setThemeMode(m.value.appearance.mode));
1749
+ let quit = () => process.exit(0);
1750
+ try {
1751
+ const app = useApp();
1752
+ quit = () => app.exit();
1753
+ } catch {}
1754
+ try {
1755
+ useInput((input) => {
1756
+ if (input === "q") quit();
1757
+ });
1758
+ } catch {}
1759
+ return (_ctx, _cache) => {
1760
+ return openBlock(), createBlock(unref(Box), {
1761
+ flexDirection: "column",
1762
+ width: width.value
1763
+ }, {
1764
+ default: withCtx(() => [
1765
+ createVNode(HeaderBar_default, {
1766
+ m: m.value,
1767
+ now: clockTs.value,
1768
+ width: width.value
1769
+ }, null, 8, [
1770
+ "m",
1771
+ "now",
1772
+ "width"
1773
+ ]),
1774
+ width.value >= 100 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
1775
+ createVNode(unref(Box), {
1776
+ flexDirection: "row",
1777
+ gap: 1
1778
+ }, {
1779
+ default: withCtx(() => [createVNode(CpuPanel_default, {
1780
+ cpu: m.value.cpu,
1781
+ history: hist.value.cpu
1782
+ }, null, 8, ["cpu", "history"]), createVNode(MemoryPanel_default, {
1783
+ memory: m.value.memory,
1784
+ history: hist.value.mem
1785
+ }, null, 8, ["memory", "history"])]),
1786
+ _: 1
1787
+ }),
1788
+ createVNode(unref(Box), {
1789
+ flexDirection: "row",
1790
+ gap: 1
1791
+ }, {
1792
+ default: withCtx(() => [
1793
+ createVNode(NetworkPanel_default, {
1794
+ net: m.value.net,
1795
+ rx: hist.value.rx,
1796
+ tx: hist.value.tx
1797
+ }, null, 8, [
1798
+ "net",
1799
+ "rx",
1800
+ "tx"
1801
+ ]),
1802
+ createVNode(BatteryPanel_default, { battery: m.value.battery }, null, 8, ["battery"]),
1803
+ createVNode(GpuPanel_default, {
1804
+ gpu: m.value.gpu,
1805
+ history: hist.value.gpu
1806
+ }, null, 8, ["gpu", "history"])
1807
+ ]),
1808
+ _: 1
1809
+ }),
1810
+ createVNode(unref(Box), {
1811
+ flexDirection: "row",
1812
+ gap: 1
1813
+ }, {
1814
+ default: withCtx(() => [createVNode(DiskPanel_default, { disk: m.value.disk }, null, 8, ["disk"]), createVNode(SensorsPanel_default, { sensors: m.value.sensors }, null, 8, ["sensors"])]),
1815
+ _: 1
1816
+ })
1817
+ ], 64)) : (openBlock(), createBlock(NarrowView_default, {
1818
+ key: 1,
1819
+ m: m.value
1820
+ }, null, 8, ["m"])),
1821
+ createVNode(unref(Box), { paddingX: 1 }, {
1822
+ default: withCtx(() => [createVNode(unref(Text), { color: unref(theme).dim }, {
1823
+ default: withCtx(() => [createTextVNode(toDisplayString(width.value >= 100 ? "q quit · refresh 1s" : "q quit"), 1)]),
1824
+ _: 1
1825
+ }, 8, ["color"])]),
1826
+ _: 1
1827
+ })
1828
+ ]),
1829
+ _: 1
1830
+ }, 8, ["width"]);
1831
+ };
1832
+ }
1833
+ });
1834
+ //#endregion
1835
+ //#region src/main.ts
1836
+ var args = process.argv.slice(2);
1837
+ async function realSnapshot() {
1838
+ await collectAll();
1839
+ await new Promise((r) => setTimeout(r, 700));
1840
+ return collectAll();
1841
+ }
1842
+ if (args.includes("--json")) {
1843
+ const snapshot = await realSnapshot();
1844
+ process.stdout.write(JSON.stringify(snapshot, null, 2) + "\n");
1845
+ process.exit(0);
1846
+ } else if (args.includes("--once") || args.includes("--snapshot")) {
1847
+ const snapshot = await realSnapshot();
1848
+ const columns = Number(process.env.COLUMNS) || process.stdout.columns || 120;
1849
+ const Snapshot = defineComponent({
1850
+ name: "MachudSnapshot",
1851
+ setup: () => () => h(App_default, {
1852
+ snapshot,
1853
+ columns
1854
+ })
1855
+ });
1856
+ process.stdout.write(renderToString(Snapshot, { columns }) + "\n");
1857
+ process.exit(0);
1858
+ } else createApp(App_default).mount({ alternateScreen: true });
1859
+ //#endregion