@enigmax/dashboard 0.1.19 → 0.1.20
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/assets/index.html +990 -23
- package/package.json +1 -1
package/assets/index.html
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
--border: #232a36; --border-soft: #1b212d;
|
|
13
13
|
--text: #eceef2; --muted: #8a93a3; --accent: #e0a458; --accent2: #d7875f; --good: #6fcf97;
|
|
14
14
|
--accent-weak: rgba(224,164,88,0.13); --good-weak: rgba(111,207,151,0.12);
|
|
15
|
+
/* Usage/consumption thresholds: green -> yellow -> orange (--accent) -> red. */
|
|
16
|
+
--warn: #e3c14e; --bad: #e0564f;
|
|
15
17
|
/* Type roles: a monospace "machine readout" face carries the brand, headings,
|
|
16
18
|
labels and numeric data (this is a CLI tool's dashboard); sans carries prose. */
|
|
17
19
|
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
|
|
@@ -245,10 +247,23 @@
|
|
|
245
247
|
.sys-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 0 24px; }
|
|
246
248
|
.sys-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--surface2); font-size: 13px; }
|
|
247
249
|
.sys-item .k { color: var(--muted); }
|
|
250
|
+
/* Rows whose value is a list of chips span the full width and let the chips wrap with
|
|
251
|
+
even spacing, instead of cramming many tags into one compact half-column cell. */
|
|
252
|
+
.sys-item.wide { grid-column: 1 / -1; flex-direction: column; align-items: stretch; gap: 8px; }
|
|
253
|
+
.sys-item.wide .v { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
254
|
+
.sys-item.wide .v .tag { margin-left: 0; }
|
|
248
255
|
.pill { font-size: 11px; border-radius: 6px; padding: 2px 9px; border: 1px solid var(--border); white-space: nowrap; }
|
|
249
256
|
.pill.on { color: #06210f; background: var(--good); border-color: var(--good); font-weight: 600; }
|
|
250
257
|
.pill.off { color: var(--muted); background: var(--surface2); }
|
|
251
258
|
.pill.lvl { color: #1a1206; background: var(--accent); border-color: var(--accent); font-weight: 600; }
|
|
259
|
+
/* Claude operational-status pill (status.claude.com). */
|
|
260
|
+
.cstatus { display: inline-flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: 12px; color: var(--muted); padding: 5px 11px; background: rgba(0,0,0,0.25); border: 1px solid var(--border-soft); border-radius: 999px; white-space: nowrap; }
|
|
261
|
+
.cdot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
|
|
262
|
+
.cstatus.ok .cdot { background: var(--good); box-shadow: 0 0 8px var(--good); }
|
|
263
|
+
.cstatus.ok { color: var(--text); }
|
|
264
|
+
.cstatus.warn .cdot { background: var(--warn); }
|
|
265
|
+
.cstatus.orange .cdot { background: var(--accent); }
|
|
266
|
+
.cstatus.bad .cdot { background: var(--bad); box-shadow: 0 0 8px var(--bad); }
|
|
252
267
|
@media (max-width: 720px) {
|
|
253
268
|
body { padding: 16px; }
|
|
254
269
|
.grid { grid-template-columns: repeat(2, 1fr); }
|
|
@@ -410,9 +425,15 @@
|
|
|
410
425
|
</main>
|
|
411
426
|
|
|
412
427
|
<section id="view-usage" style="display:none">
|
|
413
|
-
<div class="page-head">
|
|
414
|
-
<
|
|
415
|
-
|
|
428
|
+
<div class="page-head" style="display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap">
|
|
429
|
+
<div style="flex:1;min-width:280px">
|
|
430
|
+
<h1>Claude Usage</h1>
|
|
431
|
+
<p>Measured token consumption and estimated cost, read-only from your own Claude Code session transcripts (<code>~/.claude/projects</code>). Cost is an estimate from a per-model price table; real spend is billed by Anthropic. Nothing is sent anywhere.</p>
|
|
432
|
+
</div>
|
|
433
|
+
<div style="display:flex;flex-direction:column;align-items:flex-end;gap:8px">
|
|
434
|
+
<span id="claudeStatus" class="cstatus"><span class="cdot"></span><span class="ctext">Checking Claude status...</span></span>
|
|
435
|
+
<a href="https://claude.ai/settings/usage" target="_blank" rel="noopener noreferrer" class="toggle" style="white-space:nowrap">View in Claude -></a>
|
|
436
|
+
</div>
|
|
416
437
|
</div>
|
|
417
438
|
<div class="panel" id="usagePanel" style="display:none">
|
|
418
439
|
<h2 style="margin:0 0 4px">Usage limits <small>same windows Claude Code shows</small></h2>
|
|
@@ -456,7 +477,7 @@
|
|
|
456
477
|
<div class="page-head" style="display:flex;align-items:flex-start;gap:16px">
|
|
457
478
|
<div style="flex:1">
|
|
458
479
|
<h1>Accounts & Profiles</h1>
|
|
459
|
-
<p>Manage per-tool logins and profiles
|
|
480
|
+
<p>Manage per-tool logins and profiles. A profile pins one account per tool and drives every launch. Logging an account in happens in a terminal - the browser shows you the command to run.</p>
|
|
460
481
|
</div>
|
|
461
482
|
</div>
|
|
462
483
|
<div class="panel">
|
|
@@ -512,6 +533,931 @@
|
|
|
512
533
|
Data source: <code>~/.enigma/ccr/stats.json</code> + <code>history.jsonl</code> - reset it with <code>enigma compress --clear</code>. Enigma <span id="ver"></span>
|
|
513
534
|
</footer>
|
|
514
535
|
|
|
536
|
+
<!-- Vendored @github/relative-time-element v5.2.0 (MIT) - inlined so there is no CDN and no extra server route; defines <relative-time>. -->
|
|
537
|
+
<script type="module">
|
|
538
|
+
/*! @github/relative-time-element v5.2.0 | (c) GitHub, Inc. | MIT License | https://github.com/github/relative-time-element */
|
|
539
|
+
var __defProp = Object.defineProperty;
|
|
540
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
541
|
+
|
|
542
|
+
// dist/duration-format-ponyfill.js
|
|
543
|
+
var __classPrivateFieldSet = function(receiver, state, value, kind, f) {
|
|
544
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
545
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
546
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
547
|
+
return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
|
|
548
|
+
};
|
|
549
|
+
var __classPrivateFieldGet = function(receiver, state, kind, f) {
|
|
550
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
551
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
552
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
553
|
+
};
|
|
554
|
+
var _DurationFormat_options;
|
|
555
|
+
var ListFormatPonyFill = class {
|
|
556
|
+
static {
|
|
557
|
+
__name(this, "ListFormatPonyFill");
|
|
558
|
+
}
|
|
559
|
+
formatToParts(members) {
|
|
560
|
+
const parts = [];
|
|
561
|
+
for (const value of members) {
|
|
562
|
+
parts.push({ type: "element", value });
|
|
563
|
+
parts.push({ type: "literal", value: ", " });
|
|
564
|
+
}
|
|
565
|
+
return parts.slice(0, -1);
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
var ListFormat = typeof Intl !== "undefined" && Intl.ListFormat || ListFormatPonyFill;
|
|
569
|
+
var partsTable = [
|
|
570
|
+
["years", "year"],
|
|
571
|
+
["months", "month"],
|
|
572
|
+
["weeks", "week"],
|
|
573
|
+
["days", "day"],
|
|
574
|
+
["hours", "hour"],
|
|
575
|
+
["minutes", "minute"],
|
|
576
|
+
["seconds", "second"],
|
|
577
|
+
["milliseconds", "millisecond"]
|
|
578
|
+
];
|
|
579
|
+
var twoDigitFormatOptions = { minimumIntegerDigits: 2 };
|
|
580
|
+
var DurationFormat = class {
|
|
581
|
+
static {
|
|
582
|
+
__name(this, "DurationFormat");
|
|
583
|
+
}
|
|
584
|
+
constructor(locale, options = {}) {
|
|
585
|
+
_DurationFormat_options.set(this, void 0);
|
|
586
|
+
let style = String(options.style || "short");
|
|
587
|
+
if (style !== "long" && style !== "short" && style !== "narrow" && style !== "digital")
|
|
588
|
+
style = "short";
|
|
589
|
+
let prevStyle = style === "digital" ? "numeric" : style;
|
|
590
|
+
const hours = options.hours || prevStyle;
|
|
591
|
+
prevStyle = hours === "2-digit" ? "numeric" : hours;
|
|
592
|
+
const minutes = options.minutes || prevStyle;
|
|
593
|
+
prevStyle = minutes === "2-digit" ? "numeric" : minutes;
|
|
594
|
+
const seconds = options.seconds || prevStyle;
|
|
595
|
+
prevStyle = seconds === "2-digit" ? "numeric" : seconds;
|
|
596
|
+
const milliseconds = options.milliseconds || prevStyle;
|
|
597
|
+
__classPrivateFieldSet(this, _DurationFormat_options, {
|
|
598
|
+
locale,
|
|
599
|
+
style,
|
|
600
|
+
years: options.years || style === "digital" ? "short" : style,
|
|
601
|
+
yearsDisplay: options.yearsDisplay === "always" ? "always" : "auto",
|
|
602
|
+
months: options.months || style === "digital" ? "short" : style,
|
|
603
|
+
monthsDisplay: options.monthsDisplay === "always" ? "always" : "auto",
|
|
604
|
+
weeks: options.weeks || style === "digital" ? "short" : style,
|
|
605
|
+
weeksDisplay: options.weeksDisplay === "always" ? "always" : "auto",
|
|
606
|
+
days: options.days || style === "digital" ? "short" : style,
|
|
607
|
+
daysDisplay: options.daysDisplay === "always" ? "always" : "auto",
|
|
608
|
+
hours,
|
|
609
|
+
hoursDisplay: options.hoursDisplay === "always" ? "always" : style === "digital" ? "always" : "auto",
|
|
610
|
+
minutes,
|
|
611
|
+
minutesDisplay: options.minutesDisplay === "always" ? "always" : style === "digital" ? "always" : "auto",
|
|
612
|
+
seconds,
|
|
613
|
+
secondsDisplay: options.secondsDisplay === "always" ? "always" : style === "digital" ? "always" : "auto",
|
|
614
|
+
milliseconds,
|
|
615
|
+
millisecondsDisplay: options.millisecondsDisplay === "always" ? "always" : "auto"
|
|
616
|
+
}, "f");
|
|
617
|
+
}
|
|
618
|
+
resolvedOptions() {
|
|
619
|
+
return __classPrivateFieldGet(this, _DurationFormat_options, "f");
|
|
620
|
+
}
|
|
621
|
+
formatToParts(duration) {
|
|
622
|
+
const list = [];
|
|
623
|
+
const options = __classPrivateFieldGet(this, _DurationFormat_options, "f");
|
|
624
|
+
const style = options.style;
|
|
625
|
+
const locale = options.locale;
|
|
626
|
+
for (const [unit, nfUnit] of partsTable) {
|
|
627
|
+
const value = duration[unit];
|
|
628
|
+
if (options[`${unit}Display`] === "auto" && !value)
|
|
629
|
+
continue;
|
|
630
|
+
const unitStyle = options[unit];
|
|
631
|
+
const nfOpts = unitStyle === "2-digit" ? twoDigitFormatOptions : unitStyle === "numeric" ? {} : { style: "unit", unit: nfUnit, unitDisplay: unitStyle };
|
|
632
|
+
let formattedValue = new Intl.NumberFormat(locale, nfOpts).format(value);
|
|
633
|
+
if (unit === "months" && (unitStyle === "narrow" || style === "narrow" && formattedValue.endsWith("m"))) {
|
|
634
|
+
formattedValue = formattedValue.replace(/(\d+)m$/, "$1mo");
|
|
635
|
+
}
|
|
636
|
+
list.push(formattedValue);
|
|
637
|
+
}
|
|
638
|
+
return new ListFormat(locale, {
|
|
639
|
+
type: "unit",
|
|
640
|
+
style: style === "digital" ? "short" : style
|
|
641
|
+
}).formatToParts(list);
|
|
642
|
+
}
|
|
643
|
+
format(duration) {
|
|
644
|
+
return this.formatToParts(duration).map((p) => p.value).join("");
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
_DurationFormat_options = /* @__PURE__ */ new WeakMap();
|
|
648
|
+
|
|
649
|
+
// dist/duration.js
|
|
650
|
+
var durationRe = /^[-+]?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/;
|
|
651
|
+
var unitNames = ["year", "month", "week", "day", "hour", "minute", "second", "millisecond"];
|
|
652
|
+
var isDuration = /* @__PURE__ */ __name((str) => durationRe.test(str), "isDuration");
|
|
653
|
+
var Duration = class _Duration {
|
|
654
|
+
static {
|
|
655
|
+
__name(this, "Duration");
|
|
656
|
+
}
|
|
657
|
+
constructor(years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0) {
|
|
658
|
+
this.years = years;
|
|
659
|
+
this.months = months;
|
|
660
|
+
this.weeks = weeks;
|
|
661
|
+
this.days = days;
|
|
662
|
+
this.hours = hours;
|
|
663
|
+
this.minutes = minutes;
|
|
664
|
+
this.seconds = seconds;
|
|
665
|
+
this.milliseconds = milliseconds;
|
|
666
|
+
this.years || (this.years = 0);
|
|
667
|
+
this.sign || (this.sign = Math.sign(this.years));
|
|
668
|
+
this.months || (this.months = 0);
|
|
669
|
+
this.sign || (this.sign = Math.sign(this.months));
|
|
670
|
+
this.weeks || (this.weeks = 0);
|
|
671
|
+
this.sign || (this.sign = Math.sign(this.weeks));
|
|
672
|
+
this.days || (this.days = 0);
|
|
673
|
+
this.sign || (this.sign = Math.sign(this.days));
|
|
674
|
+
this.hours || (this.hours = 0);
|
|
675
|
+
this.sign || (this.sign = Math.sign(this.hours));
|
|
676
|
+
this.minutes || (this.minutes = 0);
|
|
677
|
+
this.sign || (this.sign = Math.sign(this.minutes));
|
|
678
|
+
this.seconds || (this.seconds = 0);
|
|
679
|
+
this.sign || (this.sign = Math.sign(this.seconds));
|
|
680
|
+
this.milliseconds || (this.milliseconds = 0);
|
|
681
|
+
this.sign || (this.sign = Math.sign(this.milliseconds));
|
|
682
|
+
this.blank = this.sign === 0;
|
|
683
|
+
}
|
|
684
|
+
abs() {
|
|
685
|
+
return new _Duration(Math.abs(this.years), Math.abs(this.months), Math.abs(this.weeks), Math.abs(this.days), Math.abs(this.hours), Math.abs(this.minutes), Math.abs(this.seconds), Math.abs(this.milliseconds));
|
|
686
|
+
}
|
|
687
|
+
static from(durationLike) {
|
|
688
|
+
var _a;
|
|
689
|
+
if (typeof durationLike === "string") {
|
|
690
|
+
const str = String(durationLike).trim();
|
|
691
|
+
const factor = str.startsWith("-") ? -1 : 1;
|
|
692
|
+
const parsed = (_a = str.match(durationRe)) === null || _a === void 0 ? void 0 : _a.slice(1).map((x) => (Number(x) || 0) * factor);
|
|
693
|
+
if (!parsed)
|
|
694
|
+
return new _Duration();
|
|
695
|
+
return new _Duration(...parsed);
|
|
696
|
+
} else if (typeof durationLike === "object") {
|
|
697
|
+
const { years, months, weeks, days, hours, minutes, seconds, milliseconds } = durationLike;
|
|
698
|
+
return new _Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds);
|
|
699
|
+
}
|
|
700
|
+
throw new RangeError("invalid duration");
|
|
701
|
+
}
|
|
702
|
+
static compare(one, two) {
|
|
703
|
+
const now = Date.now();
|
|
704
|
+
const oneApplied = Math.abs(applyDuration(now, _Duration.from(one)).getTime() - now);
|
|
705
|
+
const twoApplied = Math.abs(applyDuration(now, _Duration.from(two)).getTime() - now);
|
|
706
|
+
return oneApplied > twoApplied ? -1 : oneApplied < twoApplied ? 1 : 0;
|
|
707
|
+
}
|
|
708
|
+
toLocaleString(locale, opts) {
|
|
709
|
+
return new DurationFormat(locale, opts).format(this);
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
function applyDuration(date, duration) {
|
|
713
|
+
const r = new Date(date);
|
|
714
|
+
if (duration.sign < 0) {
|
|
715
|
+
r.setUTCSeconds(r.getUTCSeconds() + duration.seconds);
|
|
716
|
+
r.setUTCMinutes(r.getUTCMinutes() + duration.minutes);
|
|
717
|
+
r.setUTCHours(r.getUTCHours() + duration.hours);
|
|
718
|
+
r.setUTCDate(r.getUTCDate() + duration.weeks * 7 + duration.days);
|
|
719
|
+
r.setUTCMonth(r.getUTCMonth() + duration.months);
|
|
720
|
+
r.setUTCFullYear(r.getUTCFullYear() + duration.years);
|
|
721
|
+
} else {
|
|
722
|
+
r.setUTCFullYear(r.getUTCFullYear() + duration.years);
|
|
723
|
+
r.setUTCMonth(r.getUTCMonth() + duration.months);
|
|
724
|
+
r.setUTCDate(r.getUTCDate() + duration.weeks * 7 + duration.days);
|
|
725
|
+
r.setUTCHours(r.getUTCHours() + duration.hours);
|
|
726
|
+
r.setUTCMinutes(r.getUTCMinutes() + duration.minutes);
|
|
727
|
+
r.setUTCSeconds(r.getUTCSeconds() + duration.seconds);
|
|
728
|
+
}
|
|
729
|
+
return r;
|
|
730
|
+
}
|
|
731
|
+
__name(applyDuration, "applyDuration");
|
|
732
|
+
function elapsedTime(date, precision = "second", now = Date.now()) {
|
|
733
|
+
const delta = date.getTime() - now;
|
|
734
|
+
if (delta === 0)
|
|
735
|
+
return new Duration();
|
|
736
|
+
const sign = Math.sign(delta);
|
|
737
|
+
const ms = Math.abs(delta);
|
|
738
|
+
const sec = Math.floor(ms / 1e3);
|
|
739
|
+
const min = Math.floor(sec / 60);
|
|
740
|
+
const hr = Math.floor(min / 60);
|
|
741
|
+
const day = Math.floor(hr / 24);
|
|
742
|
+
const month = Math.floor(day / 30);
|
|
743
|
+
const year = Math.floor(month / 12);
|
|
744
|
+
const i = unitNames.indexOf(precision) || unitNames.length;
|
|
745
|
+
return new Duration(i >= 0 ? year * sign : 0, i >= 1 ? (month - year * 12) * sign : 0, 0, i >= 3 ? (day - month * 30) * sign : 0, i >= 4 ? (hr - day * 24) * sign : 0, i >= 5 ? (min - hr * 60) * sign : 0, i >= 6 ? (sec - min * 60) * sign : 0, i >= 7 ? (ms - sec * 1e3) * sign : 0);
|
|
746
|
+
}
|
|
747
|
+
__name(elapsedTime, "elapsedTime");
|
|
748
|
+
function roundToSingleUnit(duration, { relativeTo = Date.now() } = {}) {
|
|
749
|
+
relativeTo = new Date(relativeTo);
|
|
750
|
+
if (duration.blank)
|
|
751
|
+
return duration;
|
|
752
|
+
const sign = duration.sign;
|
|
753
|
+
let years = Math.abs(duration.years);
|
|
754
|
+
let months = Math.abs(duration.months);
|
|
755
|
+
let weeks = Math.abs(duration.weeks);
|
|
756
|
+
let days = Math.abs(duration.days);
|
|
757
|
+
let hours = Math.abs(duration.hours);
|
|
758
|
+
let minutes = Math.abs(duration.minutes);
|
|
759
|
+
let seconds = Math.abs(duration.seconds);
|
|
760
|
+
let milliseconds = Math.abs(duration.milliseconds);
|
|
761
|
+
if (milliseconds >= 900)
|
|
762
|
+
seconds += Math.round(milliseconds / 1e3);
|
|
763
|
+
if (seconds || minutes || hours || days || weeks || months || years) {
|
|
764
|
+
milliseconds = 0;
|
|
765
|
+
}
|
|
766
|
+
if (seconds >= 55)
|
|
767
|
+
minutes += Math.round(seconds / 60);
|
|
768
|
+
if (minutes || hours || days || weeks || months || years)
|
|
769
|
+
seconds = 0;
|
|
770
|
+
if (minutes >= 55)
|
|
771
|
+
hours += Math.round(minutes / 60);
|
|
772
|
+
if (hours || days || weeks || months || years)
|
|
773
|
+
minutes = 0;
|
|
774
|
+
if (days && hours >= 12)
|
|
775
|
+
days += Math.round(hours / 24);
|
|
776
|
+
if (!days && hours >= 21)
|
|
777
|
+
days += Math.round(hours / 24);
|
|
778
|
+
if (days || weeks || months || years)
|
|
779
|
+
hours = 0;
|
|
780
|
+
const currentYear = relativeTo.getFullYear();
|
|
781
|
+
const currentMonth = relativeTo.getMonth();
|
|
782
|
+
const currentDate = relativeTo.getDate();
|
|
783
|
+
if (days >= 27 || years + months + days) {
|
|
784
|
+
const newMonthDate = new Date(relativeTo);
|
|
785
|
+
newMonthDate.setDate(1);
|
|
786
|
+
newMonthDate.setMonth(currentMonth + months * sign + 1);
|
|
787
|
+
newMonthDate.setDate(0);
|
|
788
|
+
const monthDateCorrection = Math.max(0, currentDate - newMonthDate.getDate());
|
|
789
|
+
const newDate = new Date(relativeTo);
|
|
790
|
+
newDate.setFullYear(currentYear + years * sign);
|
|
791
|
+
newDate.setDate(currentDate - monthDateCorrection);
|
|
792
|
+
newDate.setMonth(currentMonth + months * sign);
|
|
793
|
+
newDate.setDate(currentDate - monthDateCorrection + days * sign);
|
|
794
|
+
const yearDiff = newDate.getFullYear() - relativeTo.getFullYear();
|
|
795
|
+
const monthDiff = newDate.getMonth() - relativeTo.getMonth();
|
|
796
|
+
const daysDiff = Math.abs(Math.round((Number(newDate) - Number(relativeTo)) / 864e5)) + monthDateCorrection;
|
|
797
|
+
const monthsDiff = Math.abs(yearDiff * 12 + monthDiff);
|
|
798
|
+
if (daysDiff < 27) {
|
|
799
|
+
if (days >= 6) {
|
|
800
|
+
weeks += Math.round(days / 7);
|
|
801
|
+
days = 0;
|
|
802
|
+
} else {
|
|
803
|
+
days = daysDiff;
|
|
804
|
+
}
|
|
805
|
+
months = years = 0;
|
|
806
|
+
} else if (monthsDiff <= 11) {
|
|
807
|
+
months = monthsDiff;
|
|
808
|
+
years = 0;
|
|
809
|
+
} else {
|
|
810
|
+
months = 0;
|
|
811
|
+
years = yearDiff * sign;
|
|
812
|
+
}
|
|
813
|
+
if (months || years)
|
|
814
|
+
days = 0;
|
|
815
|
+
}
|
|
816
|
+
if (years)
|
|
817
|
+
months = 0;
|
|
818
|
+
if (weeks >= 4)
|
|
819
|
+
months += Math.round(weeks / 4);
|
|
820
|
+
if (months || years)
|
|
821
|
+
weeks = 0;
|
|
822
|
+
if (days && weeks && !months && !years) {
|
|
823
|
+
weeks += Math.round(days / 7);
|
|
824
|
+
days = 0;
|
|
825
|
+
}
|
|
826
|
+
return new Duration(years * sign, months * sign, weeks * sign, days * sign, hours * sign, minutes * sign, seconds * sign, milliseconds * sign);
|
|
827
|
+
}
|
|
828
|
+
__name(roundToSingleUnit, "roundToSingleUnit");
|
|
829
|
+
function getRelativeTimeUnit(duration, opts) {
|
|
830
|
+
const rounded = roundToSingleUnit(duration, opts);
|
|
831
|
+
if (rounded.blank)
|
|
832
|
+
return [0, "second"];
|
|
833
|
+
for (const unit of unitNames) {
|
|
834
|
+
if (unit === "millisecond")
|
|
835
|
+
continue;
|
|
836
|
+
const val = rounded[`${unit}s`];
|
|
837
|
+
if (val)
|
|
838
|
+
return [val, unit];
|
|
839
|
+
}
|
|
840
|
+
return [0, "second"];
|
|
841
|
+
}
|
|
842
|
+
__name(getRelativeTimeUnit, "getRelativeTimeUnit");
|
|
843
|
+
|
|
844
|
+
// dist/relative-time-element.js
|
|
845
|
+
var __classPrivateFieldGet2 = function(receiver, state, kind, f) {
|
|
846
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
847
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
848
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
849
|
+
};
|
|
850
|
+
var __classPrivateFieldSet2 = function(receiver, state, value, kind, f) {
|
|
851
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
852
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
853
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
854
|
+
return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
|
|
855
|
+
};
|
|
856
|
+
var _RelativeTimeElement_instances;
|
|
857
|
+
var _RelativeTimeElement_customTitle;
|
|
858
|
+
var _RelativeTimeElement_updating;
|
|
859
|
+
var _RelativeTimeElement_lang_get;
|
|
860
|
+
var _RelativeTimeElement_renderRoot;
|
|
861
|
+
var _RelativeTimeElement_getFormattedTitle;
|
|
862
|
+
var _RelativeTimeElement_getExplicitThreshold;
|
|
863
|
+
var _RelativeTimeElement_resolveFormat;
|
|
864
|
+
var _RelativeTimeElement_getMicroDuration;
|
|
865
|
+
var _RelativeTimeElement_getMicroRelativeFormat;
|
|
866
|
+
var _RelativeTimeElement_getDurationFormat;
|
|
867
|
+
var _RelativeTimeElement_getRelativeFormat;
|
|
868
|
+
var _RelativeTimeElement_getDateTimeFormat;
|
|
869
|
+
var _RelativeTimeElement_isToday;
|
|
870
|
+
var _RelativeTimeElement_isCurrentYear;
|
|
871
|
+
var _RelativeTimeElement_getUserPreferredAbsoluteTimeFormat;
|
|
872
|
+
var _RelativeTimeElement_updateRenderRootContent;
|
|
873
|
+
var _RelativeTimeElement_shouldDisplayUserPreferredAbsoluteTime;
|
|
874
|
+
var _RelativeTimeElement_onRelativeTimeUpdated;
|
|
875
|
+
var HTMLElement = globalThis.HTMLElement || null;
|
|
876
|
+
var emptyDuration = new Duration();
|
|
877
|
+
var microEmptyDuration = new Duration(0, 0, 0, 0, 0, 1);
|
|
878
|
+
var RelativeTimeUpdatedEvent = class extends Event {
|
|
879
|
+
static {
|
|
880
|
+
__name(this, "RelativeTimeUpdatedEvent");
|
|
881
|
+
}
|
|
882
|
+
constructor(oldText, newText, oldTitle, newTitle) {
|
|
883
|
+
super("relative-time-updated", { bubbles: true, composed: true });
|
|
884
|
+
this.oldText = oldText;
|
|
885
|
+
this.newText = newText;
|
|
886
|
+
this.oldTitle = oldTitle;
|
|
887
|
+
this.newTitle = newTitle;
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
function getUnitFactor(el) {
|
|
891
|
+
const date = el.date;
|
|
892
|
+
if (!date)
|
|
893
|
+
return Infinity;
|
|
894
|
+
const now = Date.now();
|
|
895
|
+
if (el.format === "duration" || el.format === "elapsed") {
|
|
896
|
+
const precision = el.precision;
|
|
897
|
+
if (precision === "second") {
|
|
898
|
+
return 1e3;
|
|
899
|
+
} else if (precision === "minute") {
|
|
900
|
+
return 60 * 1e3;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
const ms = Math.abs(now - date.getTime());
|
|
904
|
+
let factor = 60 * 60 * 1e3;
|
|
905
|
+
if (ms < 60 * 1e3) {
|
|
906
|
+
factor = 1e3;
|
|
907
|
+
} else if (ms < 60 * 60 * 1e3) {
|
|
908
|
+
factor = 60 * 1e3;
|
|
909
|
+
}
|
|
910
|
+
const threshold = getExplicitThreshold(el);
|
|
911
|
+
if (el.format === "micro" && threshold) {
|
|
912
|
+
const thresholdDuration = Duration.from(threshold);
|
|
913
|
+
const signedThresholdDuration = date.getTime() > now ? negateDuration(thresholdDuration) : thresholdDuration;
|
|
914
|
+
const thresholdTime = applyDuration(date, signedThresholdDuration).getTime();
|
|
915
|
+
const msUntilThreshold = thresholdTime - now;
|
|
916
|
+
if (msUntilThreshold > 0)
|
|
917
|
+
factor = Math.min(factor, msUntilThreshold);
|
|
918
|
+
}
|
|
919
|
+
return factor;
|
|
920
|
+
}
|
|
921
|
+
__name(getUnitFactor, "getUnitFactor");
|
|
922
|
+
function negateDuration(duration) {
|
|
923
|
+
return new Duration(-duration.years, -duration.months, -duration.weeks, -duration.days, -duration.hours, -duration.minutes, -duration.seconds, -duration.milliseconds);
|
|
924
|
+
}
|
|
925
|
+
__name(negateDuration, "negateDuration");
|
|
926
|
+
function getExplicitThreshold(el) {
|
|
927
|
+
const threshold = el.getAttribute("threshold");
|
|
928
|
+
return threshold && isDuration(threshold) ? threshold : null;
|
|
929
|
+
}
|
|
930
|
+
__name(getExplicitThreshold, "getExplicitThreshold");
|
|
931
|
+
function isBrowser12hCycle() {
|
|
932
|
+
try {
|
|
933
|
+
return new Intl.DateTimeFormat([], { hour: "numeric" }).resolvedOptions().hour12 === true;
|
|
934
|
+
} catch (_a) {
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
__name(isBrowser12hCycle, "isBrowser12hCycle");
|
|
939
|
+
var dateObserver = new class {
|
|
940
|
+
constructor() {
|
|
941
|
+
this.elements = /* @__PURE__ */ new Set();
|
|
942
|
+
this.time = Infinity;
|
|
943
|
+
this.updating = false;
|
|
944
|
+
this.timer = -1;
|
|
945
|
+
}
|
|
946
|
+
observe(element) {
|
|
947
|
+
this.elements.add(element);
|
|
948
|
+
if (this.updating)
|
|
949
|
+
return;
|
|
950
|
+
const date = element.date;
|
|
951
|
+
if (date && date.getTime()) {
|
|
952
|
+
const ms = getUnitFactor(element);
|
|
953
|
+
const time = Date.now() + ms;
|
|
954
|
+
if (time < this.time || this.time <= Date.now()) {
|
|
955
|
+
clearTimeout(this.timer);
|
|
956
|
+
this.timer = setTimeout(() => this.update(), ms);
|
|
957
|
+
this.time = time;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
unobserve(element) {
|
|
962
|
+
if (!this.elements.has(element))
|
|
963
|
+
return;
|
|
964
|
+
this.elements.delete(element);
|
|
965
|
+
}
|
|
966
|
+
update() {
|
|
967
|
+
clearTimeout(this.timer);
|
|
968
|
+
if (!this.elements.size)
|
|
969
|
+
return;
|
|
970
|
+
let nearestDistance = Infinity;
|
|
971
|
+
this.updating = true;
|
|
972
|
+
try {
|
|
973
|
+
for (const timeEl of this.elements) {
|
|
974
|
+
nearestDistance = Math.min(nearestDistance, getUnitFactor(timeEl));
|
|
975
|
+
timeEl.update();
|
|
976
|
+
}
|
|
977
|
+
} finally {
|
|
978
|
+
this.updating = false;
|
|
979
|
+
}
|
|
980
|
+
this.time = Math.min(60 * 60 * 1e3, nearestDistance);
|
|
981
|
+
this.timer = setTimeout(() => this.update(), this.time);
|
|
982
|
+
this.time += Date.now();
|
|
983
|
+
}
|
|
984
|
+
}();
|
|
985
|
+
var RelativeTimeElement = class extends HTMLElement {
|
|
986
|
+
static {
|
|
987
|
+
__name(this, "RelativeTimeElement");
|
|
988
|
+
}
|
|
989
|
+
constructor() {
|
|
990
|
+
super(...arguments);
|
|
991
|
+
_RelativeTimeElement_instances.add(this);
|
|
992
|
+
_RelativeTimeElement_customTitle.set(this, false);
|
|
993
|
+
_RelativeTimeElement_updating.set(this, false);
|
|
994
|
+
_RelativeTimeElement_renderRoot.set(this, this.shadowRoot ? this.shadowRoot : this.attachShadow ? this.attachShadow({ mode: "open" }) : this);
|
|
995
|
+
_RelativeTimeElement_onRelativeTimeUpdated.set(this, null);
|
|
996
|
+
}
|
|
997
|
+
static define(tag = "relative-time", registry = customElements) {
|
|
998
|
+
registry.define(tag, this);
|
|
999
|
+
return this;
|
|
1000
|
+
}
|
|
1001
|
+
get timeZone() {
|
|
1002
|
+
var _a;
|
|
1003
|
+
const tz = ((_a = this.closest("[time-zone]")) === null || _a === void 0 ? void 0 : _a.getAttribute("time-zone")) || this.ownerDocument.documentElement.getAttribute("time-zone");
|
|
1004
|
+
return tz || void 0;
|
|
1005
|
+
}
|
|
1006
|
+
get hourCycle() {
|
|
1007
|
+
var _a;
|
|
1008
|
+
const hc = ((_a = this.closest("[hour-cycle]")) === null || _a === void 0 ? void 0 : _a.getAttribute("hour-cycle")) || this.ownerDocument.documentElement.getAttribute("hour-cycle");
|
|
1009
|
+
if (hc === "h11" || hc === "h12" || hc === "h23" || hc === "h24")
|
|
1010
|
+
return hc;
|
|
1011
|
+
return isBrowser12hCycle() ? "h12" : "h23";
|
|
1012
|
+
}
|
|
1013
|
+
static get observedAttributes() {
|
|
1014
|
+
return [
|
|
1015
|
+
"second",
|
|
1016
|
+
"minute",
|
|
1017
|
+
"hour",
|
|
1018
|
+
"weekday",
|
|
1019
|
+
"day",
|
|
1020
|
+
"month",
|
|
1021
|
+
"year",
|
|
1022
|
+
"time-zone-name",
|
|
1023
|
+
"prefix",
|
|
1024
|
+
"threshold",
|
|
1025
|
+
"tense",
|
|
1026
|
+
"precision",
|
|
1027
|
+
"format",
|
|
1028
|
+
"format-style",
|
|
1029
|
+
"no-title",
|
|
1030
|
+
"datetime",
|
|
1031
|
+
"lang",
|
|
1032
|
+
"title",
|
|
1033
|
+
"aria-hidden",
|
|
1034
|
+
"time-zone",
|
|
1035
|
+
"hour-cycle"
|
|
1036
|
+
];
|
|
1037
|
+
}
|
|
1038
|
+
get onRelativeTimeUpdated() {
|
|
1039
|
+
return __classPrivateFieldGet2(this, _RelativeTimeElement_onRelativeTimeUpdated, "f");
|
|
1040
|
+
}
|
|
1041
|
+
set onRelativeTimeUpdated(listener) {
|
|
1042
|
+
if (__classPrivateFieldGet2(this, _RelativeTimeElement_onRelativeTimeUpdated, "f")) {
|
|
1043
|
+
this.removeEventListener("relative-time-updated", __classPrivateFieldGet2(this, _RelativeTimeElement_onRelativeTimeUpdated, "f"));
|
|
1044
|
+
}
|
|
1045
|
+
__classPrivateFieldSet2(this, _RelativeTimeElement_onRelativeTimeUpdated, typeof listener === "object" || typeof listener === "function" ? listener : null, "f");
|
|
1046
|
+
if (typeof listener === "function") {
|
|
1047
|
+
this.addEventListener("relative-time-updated", listener);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
get second() {
|
|
1051
|
+
const second = this.getAttribute("second");
|
|
1052
|
+
if (second === "numeric" || second === "2-digit")
|
|
1053
|
+
return second;
|
|
1054
|
+
}
|
|
1055
|
+
set second(value) {
|
|
1056
|
+
this.setAttribute("second", value || "");
|
|
1057
|
+
}
|
|
1058
|
+
get minute() {
|
|
1059
|
+
const minute = this.getAttribute("minute");
|
|
1060
|
+
if (minute === "numeric" || minute === "2-digit")
|
|
1061
|
+
return minute;
|
|
1062
|
+
}
|
|
1063
|
+
set minute(value) {
|
|
1064
|
+
this.setAttribute("minute", value || "");
|
|
1065
|
+
}
|
|
1066
|
+
get hour() {
|
|
1067
|
+
const hour = this.getAttribute("hour");
|
|
1068
|
+
if (hour === "numeric" || hour === "2-digit")
|
|
1069
|
+
return hour;
|
|
1070
|
+
}
|
|
1071
|
+
set hour(value) {
|
|
1072
|
+
this.setAttribute("hour", value || "");
|
|
1073
|
+
}
|
|
1074
|
+
get weekday() {
|
|
1075
|
+
const weekday = this.getAttribute("weekday");
|
|
1076
|
+
if (weekday === "long" || weekday === "short" || weekday === "narrow") {
|
|
1077
|
+
return weekday;
|
|
1078
|
+
}
|
|
1079
|
+
if (this.format === "datetime" && weekday !== "")
|
|
1080
|
+
return this.formatStyle;
|
|
1081
|
+
}
|
|
1082
|
+
set weekday(value) {
|
|
1083
|
+
this.setAttribute("weekday", value || "");
|
|
1084
|
+
}
|
|
1085
|
+
get day() {
|
|
1086
|
+
var _a;
|
|
1087
|
+
const day = (_a = this.getAttribute("day")) !== null && _a !== void 0 ? _a : "numeric";
|
|
1088
|
+
if (day === "numeric" || day === "2-digit")
|
|
1089
|
+
return day;
|
|
1090
|
+
}
|
|
1091
|
+
set day(value) {
|
|
1092
|
+
this.setAttribute("day", value || "");
|
|
1093
|
+
}
|
|
1094
|
+
get month() {
|
|
1095
|
+
const format = this.format;
|
|
1096
|
+
let month = this.getAttribute("month");
|
|
1097
|
+
if (month === "")
|
|
1098
|
+
return;
|
|
1099
|
+
month !== null && month !== void 0 ? month : month = format === "datetime" ? this.formatStyle : "short";
|
|
1100
|
+
if (month === "numeric" || month === "2-digit" || month === "short" || month === "long" || month === "narrow") {
|
|
1101
|
+
return month;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
set month(value) {
|
|
1105
|
+
this.setAttribute("month", value || "");
|
|
1106
|
+
}
|
|
1107
|
+
get year() {
|
|
1108
|
+
var _a;
|
|
1109
|
+
const year = this.getAttribute("year");
|
|
1110
|
+
if (year === "numeric" || year === "2-digit")
|
|
1111
|
+
return year;
|
|
1112
|
+
if (!this.hasAttribute("year") && (/* @__PURE__ */ new Date()).getUTCFullYear() !== ((_a = this.date) === null || _a === void 0 ? void 0 : _a.getUTCFullYear())) {
|
|
1113
|
+
return "numeric";
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
set year(value) {
|
|
1117
|
+
this.setAttribute("year", value || "");
|
|
1118
|
+
}
|
|
1119
|
+
get timeZoneName() {
|
|
1120
|
+
const name = this.getAttribute("time-zone-name");
|
|
1121
|
+
if (name === "long" || name === "short" || name === "shortOffset" || name === "longOffset" || name === "shortGeneric" || name === "longGeneric") {
|
|
1122
|
+
return name;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
set timeZoneName(value) {
|
|
1126
|
+
this.setAttribute("time-zone-name", value || "");
|
|
1127
|
+
}
|
|
1128
|
+
get prefix() {
|
|
1129
|
+
var _a;
|
|
1130
|
+
return (_a = this.getAttribute("prefix")) !== null && _a !== void 0 ? _a : this.format === "datetime" ? "" : "on";
|
|
1131
|
+
}
|
|
1132
|
+
set prefix(value) {
|
|
1133
|
+
this.setAttribute("prefix", value);
|
|
1134
|
+
}
|
|
1135
|
+
get threshold() {
|
|
1136
|
+
const threshold = this.getAttribute("threshold");
|
|
1137
|
+
return threshold && isDuration(threshold) ? threshold : "P30D";
|
|
1138
|
+
}
|
|
1139
|
+
set threshold(value) {
|
|
1140
|
+
this.setAttribute("threshold", value);
|
|
1141
|
+
}
|
|
1142
|
+
get tense() {
|
|
1143
|
+
const tense = this.getAttribute("tense");
|
|
1144
|
+
if (tense === "past")
|
|
1145
|
+
return "past";
|
|
1146
|
+
if (tense === "future")
|
|
1147
|
+
return "future";
|
|
1148
|
+
return "auto";
|
|
1149
|
+
}
|
|
1150
|
+
set tense(value) {
|
|
1151
|
+
this.setAttribute("tense", value);
|
|
1152
|
+
}
|
|
1153
|
+
get precision() {
|
|
1154
|
+
const precision = this.getAttribute("precision");
|
|
1155
|
+
if (unitNames.includes(precision))
|
|
1156
|
+
return precision;
|
|
1157
|
+
if (this.format === "micro")
|
|
1158
|
+
return "minute";
|
|
1159
|
+
return "second";
|
|
1160
|
+
}
|
|
1161
|
+
set precision(value) {
|
|
1162
|
+
this.setAttribute("precision", value);
|
|
1163
|
+
}
|
|
1164
|
+
get format() {
|
|
1165
|
+
const format = this.getAttribute("format");
|
|
1166
|
+
if (format === "datetime")
|
|
1167
|
+
return "datetime";
|
|
1168
|
+
if (format === "relative")
|
|
1169
|
+
return "relative";
|
|
1170
|
+
if (format === "duration")
|
|
1171
|
+
return "duration";
|
|
1172
|
+
if (format === "micro")
|
|
1173
|
+
return "micro";
|
|
1174
|
+
if (format === "elapsed")
|
|
1175
|
+
return "elapsed";
|
|
1176
|
+
return "auto";
|
|
1177
|
+
}
|
|
1178
|
+
set format(value) {
|
|
1179
|
+
this.setAttribute("format", value);
|
|
1180
|
+
}
|
|
1181
|
+
get formatStyle() {
|
|
1182
|
+
const formatStyle = this.getAttribute("format-style");
|
|
1183
|
+
if (formatStyle === "long")
|
|
1184
|
+
return "long";
|
|
1185
|
+
if (formatStyle === "short")
|
|
1186
|
+
return "short";
|
|
1187
|
+
if (formatStyle === "narrow")
|
|
1188
|
+
return "narrow";
|
|
1189
|
+
const format = this.format;
|
|
1190
|
+
if (format === "elapsed" || format === "micro")
|
|
1191
|
+
return "narrow";
|
|
1192
|
+
if (format === "datetime")
|
|
1193
|
+
return "short";
|
|
1194
|
+
return "long";
|
|
1195
|
+
}
|
|
1196
|
+
set formatStyle(value) {
|
|
1197
|
+
this.setAttribute("format-style", value);
|
|
1198
|
+
}
|
|
1199
|
+
get noTitle() {
|
|
1200
|
+
return this.hasAttribute("no-title");
|
|
1201
|
+
}
|
|
1202
|
+
set noTitle(value) {
|
|
1203
|
+
this.toggleAttribute("no-title", value);
|
|
1204
|
+
}
|
|
1205
|
+
get datetime() {
|
|
1206
|
+
return this.getAttribute("datetime") || "";
|
|
1207
|
+
}
|
|
1208
|
+
set datetime(value) {
|
|
1209
|
+
this.setAttribute("datetime", value);
|
|
1210
|
+
}
|
|
1211
|
+
get date() {
|
|
1212
|
+
const parsed = Date.parse(this.datetime);
|
|
1213
|
+
return Number.isNaN(parsed) ? null : new Date(parsed);
|
|
1214
|
+
}
|
|
1215
|
+
set date(value) {
|
|
1216
|
+
this.datetime = (value === null || value === void 0 ? void 0 : value.toISOString()) || "";
|
|
1217
|
+
}
|
|
1218
|
+
connectedCallback() {
|
|
1219
|
+
this.update();
|
|
1220
|
+
}
|
|
1221
|
+
disconnectedCallback() {
|
|
1222
|
+
dateObserver.unobserve(this);
|
|
1223
|
+
}
|
|
1224
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
|
1225
|
+
if (oldValue === newValue)
|
|
1226
|
+
return;
|
|
1227
|
+
if (attrName === "title") {
|
|
1228
|
+
__classPrivateFieldSet2(this, _RelativeTimeElement_customTitle, newValue !== null && (this.date && __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getFormattedTitle).call(this, this.date)) !== newValue, "f");
|
|
1229
|
+
}
|
|
1230
|
+
if (!__classPrivateFieldGet2(this, _RelativeTimeElement_updating, "f") && !(attrName === "title" && __classPrivateFieldGet2(this, _RelativeTimeElement_customTitle, "f"))) {
|
|
1231
|
+
__classPrivateFieldSet2(this, _RelativeTimeElement_updating, (async () => {
|
|
1232
|
+
await Promise.resolve();
|
|
1233
|
+
this.update();
|
|
1234
|
+
__classPrivateFieldSet2(this, _RelativeTimeElement_updating, false, "f");
|
|
1235
|
+
})(), "f");
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
update() {
|
|
1239
|
+
const oldText = __classPrivateFieldGet2(this, _RelativeTimeElement_renderRoot, "f").textContent || this.textContent || "";
|
|
1240
|
+
const oldTitle = this.getAttribute("title") || "";
|
|
1241
|
+
let newTitle = oldTitle;
|
|
1242
|
+
const date = this.date;
|
|
1243
|
+
if (typeof Intl === "undefined" || !Intl.DateTimeFormat || !date) {
|
|
1244
|
+
__classPrivateFieldGet2(this, _RelativeTimeElement_renderRoot, "f").textContent = oldText;
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
const now = Date.now();
|
|
1248
|
+
if (!__classPrivateFieldGet2(this, _RelativeTimeElement_customTitle, "f")) {
|
|
1249
|
+
newTitle = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getFormattedTitle).call(this, date) || "";
|
|
1250
|
+
if (newTitle && !this.noTitle)
|
|
1251
|
+
this.setAttribute("title", newTitle);
|
|
1252
|
+
}
|
|
1253
|
+
const duration = elapsedTime(date, this.precision, now);
|
|
1254
|
+
const format = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_resolveFormat).call(this, duration, elapsedTime(date, "millisecond", now));
|
|
1255
|
+
let newText = oldText;
|
|
1256
|
+
const displayUserPreferredAbsoluteTime = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_shouldDisplayUserPreferredAbsoluteTime).call(this, format);
|
|
1257
|
+
if (displayUserPreferredAbsoluteTime) {
|
|
1258
|
+
newText = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getUserPreferredAbsoluteTimeFormat).call(this, date);
|
|
1259
|
+
} else {
|
|
1260
|
+
if (format === "duration") {
|
|
1261
|
+
if (this.format === "micro" && this.tense !== "auto" && Intl.RelativeTimeFormat) {
|
|
1262
|
+
newText = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getMicroRelativeFormat).call(this, duration);
|
|
1263
|
+
} else {
|
|
1264
|
+
newText = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getDurationFormat).call(this, duration);
|
|
1265
|
+
}
|
|
1266
|
+
} else if (format === "relative") {
|
|
1267
|
+
newText = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getRelativeFormat).call(this, duration);
|
|
1268
|
+
} else {
|
|
1269
|
+
newText = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getDateTimeFormat).call(this, date);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
if (newText) {
|
|
1273
|
+
__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_updateRenderRootContent).call(this, newText);
|
|
1274
|
+
} else if (this.shadowRoot === __classPrivateFieldGet2(this, _RelativeTimeElement_renderRoot, "f") && this.textContent) {
|
|
1275
|
+
__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_updateRenderRootContent).call(this, this.textContent);
|
|
1276
|
+
}
|
|
1277
|
+
if (newText !== oldText || newTitle !== oldTitle) {
|
|
1278
|
+
this.dispatchEvent(new RelativeTimeUpdatedEvent(oldText, newText, oldTitle, newTitle));
|
|
1279
|
+
}
|
|
1280
|
+
const shouldObserve = !displayUserPreferredAbsoluteTime && (format === "relative" || format === "duration") || this.format === "micro" && Boolean(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getExplicitThreshold).call(this)) && date.getTime() > now || displayUserPreferredAbsoluteTime && (__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_isToday).call(this, date) || __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_isCurrentYear).call(this, date));
|
|
1281
|
+
if (shouldObserve) {
|
|
1282
|
+
dateObserver.observe(this);
|
|
1283
|
+
} else {
|
|
1284
|
+
dateObserver.unobserve(this);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
_RelativeTimeElement_customTitle = /* @__PURE__ */ new WeakMap(), _RelativeTimeElement_updating = /* @__PURE__ */ new WeakMap(), _RelativeTimeElement_renderRoot = /* @__PURE__ */ new WeakMap(), _RelativeTimeElement_onRelativeTimeUpdated = /* @__PURE__ */ new WeakMap(), _RelativeTimeElement_instances = /* @__PURE__ */ new WeakSet(), _RelativeTimeElement_lang_get = /* @__PURE__ */ __name(function _RelativeTimeElement_lang_get2() {
|
|
1289
|
+
var _a;
|
|
1290
|
+
const lang = ((_a = this.closest("[lang]")) === null || _a === void 0 ? void 0 : _a.getAttribute("lang")) || this.ownerDocument.documentElement.getAttribute("lang");
|
|
1291
|
+
try {
|
|
1292
|
+
return new Intl.Locale(lang !== null && lang !== void 0 ? lang : "").toString();
|
|
1293
|
+
} catch (_b) {
|
|
1294
|
+
return "default";
|
|
1295
|
+
}
|
|
1296
|
+
}, "_RelativeTimeElement_lang_get"), _RelativeTimeElement_getFormattedTitle = /* @__PURE__ */ __name(function _RelativeTimeElement_getFormattedTitle2(date) {
|
|
1297
|
+
return new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), {
|
|
1298
|
+
day: "numeric",
|
|
1299
|
+
month: "short",
|
|
1300
|
+
year: "numeric",
|
|
1301
|
+
hour: "numeric",
|
|
1302
|
+
minute: "2-digit",
|
|
1303
|
+
timeZoneName: "short",
|
|
1304
|
+
timeZone: this.timeZone,
|
|
1305
|
+
hourCycle: this.hourCycle
|
|
1306
|
+
}).format(date);
|
|
1307
|
+
}, "_RelativeTimeElement_getFormattedTitle"), _RelativeTimeElement_getExplicitThreshold = /* @__PURE__ */ __name(function _RelativeTimeElement_getExplicitThreshold2() {
|
|
1308
|
+
return getExplicitThreshold(this);
|
|
1309
|
+
}, "_RelativeTimeElement_getExplicitThreshold"), _RelativeTimeElement_resolveFormat = /* @__PURE__ */ __name(function _RelativeTimeElement_resolveFormat2(duration, thresholdDuration = duration) {
|
|
1310
|
+
const format = this.format;
|
|
1311
|
+
if (format === "datetime")
|
|
1312
|
+
return "datetime";
|
|
1313
|
+
if (format === "duration")
|
|
1314
|
+
return "duration";
|
|
1315
|
+
if (format === "elapsed")
|
|
1316
|
+
return "duration";
|
|
1317
|
+
if (format === "micro") {
|
|
1318
|
+
const threshold = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getExplicitThreshold).call(this);
|
|
1319
|
+
if (threshold && Duration.compare(thresholdDuration, threshold) === -1)
|
|
1320
|
+
return "datetime";
|
|
1321
|
+
return "duration";
|
|
1322
|
+
}
|
|
1323
|
+
if ((format === "auto" || format === "relative") && typeof Intl !== "undefined" && Intl.RelativeTimeFormat) {
|
|
1324
|
+
const tense = this.tense;
|
|
1325
|
+
if (tense === "past" || tense === "future")
|
|
1326
|
+
return "relative";
|
|
1327
|
+
if (Duration.compare(duration, this.threshold) === 1)
|
|
1328
|
+
return "relative";
|
|
1329
|
+
}
|
|
1330
|
+
return "datetime";
|
|
1331
|
+
}, "_RelativeTimeElement_resolveFormat"), _RelativeTimeElement_getMicroDuration = /* @__PURE__ */ __name(function _RelativeTimeElement_getMicroDuration2(duration) {
|
|
1332
|
+
duration = roundToSingleUnit(duration);
|
|
1333
|
+
if (duration.months === 0 && (this.tense === "past" && duration.sign !== -1 || this.tense === "future" && duration.sign !== 1)) {
|
|
1334
|
+
return microEmptyDuration;
|
|
1335
|
+
}
|
|
1336
|
+
return duration;
|
|
1337
|
+
}, "_RelativeTimeElement_getMicroDuration"), _RelativeTimeElement_getMicroRelativeFormat = /* @__PURE__ */ __name(function _RelativeTimeElement_getMicroRelativeFormat2(duration) {
|
|
1338
|
+
const relativeFormat = new Intl.RelativeTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), {
|
|
1339
|
+
numeric: "always",
|
|
1340
|
+
style: "narrow"
|
|
1341
|
+
});
|
|
1342
|
+
duration = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getMicroDuration).call(this, duration);
|
|
1343
|
+
const [int, unit] = getRelativeTimeUnit(duration.blank ? microEmptyDuration : duration);
|
|
1344
|
+
return relativeFormat.format(Math.abs(int) * (this.tense === "past" ? -1 : 1), unit);
|
|
1345
|
+
}, "_RelativeTimeElement_getMicroRelativeFormat"), _RelativeTimeElement_getDurationFormat = /* @__PURE__ */ __name(function _RelativeTimeElement_getDurationFormat2(duration) {
|
|
1346
|
+
const locale = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get);
|
|
1347
|
+
const format = this.format;
|
|
1348
|
+
const style = this.formatStyle;
|
|
1349
|
+
const tense = this.tense;
|
|
1350
|
+
let empty = emptyDuration;
|
|
1351
|
+
if (format === "micro") {
|
|
1352
|
+
duration = __classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_getMicroDuration).call(this, duration);
|
|
1353
|
+
empty = microEmptyDuration;
|
|
1354
|
+
} else if (tense === "past" && duration.sign !== -1 || tense === "future" && duration.sign !== 1) {
|
|
1355
|
+
duration = empty;
|
|
1356
|
+
}
|
|
1357
|
+
const display = `${this.precision}sDisplay`;
|
|
1358
|
+
if (duration.blank) {
|
|
1359
|
+
return empty.toLocaleString(locale, { style, [display]: "always" });
|
|
1360
|
+
}
|
|
1361
|
+
return duration.abs().toLocaleString(locale, { style });
|
|
1362
|
+
}, "_RelativeTimeElement_getDurationFormat"), _RelativeTimeElement_getRelativeFormat = /* @__PURE__ */ __name(function _RelativeTimeElement_getRelativeFormat2(duration) {
|
|
1363
|
+
const relativeFormat = new Intl.RelativeTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), {
|
|
1364
|
+
numeric: "auto",
|
|
1365
|
+
style: this.formatStyle
|
|
1366
|
+
});
|
|
1367
|
+
const tense = this.tense;
|
|
1368
|
+
if (tense === "future" && duration.sign !== 1)
|
|
1369
|
+
duration = emptyDuration;
|
|
1370
|
+
if (tense === "past" && duration.sign !== -1)
|
|
1371
|
+
duration = emptyDuration;
|
|
1372
|
+
const [int, unit] = getRelativeTimeUnit(duration);
|
|
1373
|
+
if (unit === "second" && int < 10) {
|
|
1374
|
+
return relativeFormat.format(0, this.precision === "millisecond" ? "second" : this.precision);
|
|
1375
|
+
}
|
|
1376
|
+
return relativeFormat.format(int, unit);
|
|
1377
|
+
}, "_RelativeTimeElement_getRelativeFormat"), _RelativeTimeElement_getDateTimeFormat = /* @__PURE__ */ __name(function _RelativeTimeElement_getDateTimeFormat2(date) {
|
|
1378
|
+
const formatter = new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), {
|
|
1379
|
+
second: this.second,
|
|
1380
|
+
minute: this.minute,
|
|
1381
|
+
hour: this.hour,
|
|
1382
|
+
weekday: this.weekday,
|
|
1383
|
+
day: this.day,
|
|
1384
|
+
month: this.month,
|
|
1385
|
+
year: this.year,
|
|
1386
|
+
timeZoneName: this.timeZoneName,
|
|
1387
|
+
timeZone: this.timeZone,
|
|
1388
|
+
hourCycle: this.hourCycle
|
|
1389
|
+
});
|
|
1390
|
+
return `${this.prefix} ${formatter.format(date)}`.trim();
|
|
1391
|
+
}, "_RelativeTimeElement_getDateTimeFormat"), _RelativeTimeElement_isToday = /* @__PURE__ */ __name(function _RelativeTimeElement_isToday2(date) {
|
|
1392
|
+
const now = /* @__PURE__ */ new Date();
|
|
1393
|
+
const formatter = new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), {
|
|
1394
|
+
timeZone: this.timeZone,
|
|
1395
|
+
year: "numeric",
|
|
1396
|
+
month: "2-digit",
|
|
1397
|
+
day: "2-digit"
|
|
1398
|
+
});
|
|
1399
|
+
return formatter.format(now) === formatter.format(date);
|
|
1400
|
+
}, "_RelativeTimeElement_isToday"), _RelativeTimeElement_isCurrentYear = /* @__PURE__ */ __name(function _RelativeTimeElement_isCurrentYear2(date) {
|
|
1401
|
+
const now = /* @__PURE__ */ new Date();
|
|
1402
|
+
const formatter = new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), {
|
|
1403
|
+
timeZone: this.timeZone,
|
|
1404
|
+
year: "numeric"
|
|
1405
|
+
});
|
|
1406
|
+
return formatter.format(now) === formatter.format(date);
|
|
1407
|
+
}, "_RelativeTimeElement_isCurrentYear"), _RelativeTimeElement_getUserPreferredAbsoluteTimeFormat = /* @__PURE__ */ __name(function _RelativeTimeElement_getUserPreferredAbsoluteTimeFormat2(date) {
|
|
1408
|
+
const timeOnlyOptions = {
|
|
1409
|
+
hour: "numeric",
|
|
1410
|
+
minute: "2-digit",
|
|
1411
|
+
timeZoneName: "short",
|
|
1412
|
+
timeZone: this.timeZone,
|
|
1413
|
+
hourCycle: this.hourCycle
|
|
1414
|
+
};
|
|
1415
|
+
if (__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_isToday).call(this, date)) {
|
|
1416
|
+
const relativeFormatter = new Intl.RelativeTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), { numeric: "auto" });
|
|
1417
|
+
let todayText = relativeFormatter.format(0, "day");
|
|
1418
|
+
todayText = todayText.charAt(0).toLocaleUpperCase(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get)) + todayText.slice(1);
|
|
1419
|
+
const timeOnly = new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), timeOnlyOptions).format(date);
|
|
1420
|
+
return `${todayText} ${timeOnly}`;
|
|
1421
|
+
}
|
|
1422
|
+
const timeAndDateOptions = Object.assign(Object.assign({}, timeOnlyOptions), { day: "numeric", month: "short" });
|
|
1423
|
+
if (__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "m", _RelativeTimeElement_isCurrentYear).call(this, date)) {
|
|
1424
|
+
return new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), timeAndDateOptions).format(date);
|
|
1425
|
+
}
|
|
1426
|
+
return new Intl.DateTimeFormat(__classPrivateFieldGet2(this, _RelativeTimeElement_instances, "a", _RelativeTimeElement_lang_get), Object.assign(Object.assign({}, timeAndDateOptions), { year: "numeric" })).format(date);
|
|
1427
|
+
}, "_RelativeTimeElement_getUserPreferredAbsoluteTimeFormat"), _RelativeTimeElement_updateRenderRootContent = /* @__PURE__ */ __name(function _RelativeTimeElement_updateRenderRootContent2(content) {
|
|
1428
|
+
const span = document.createElement("span");
|
|
1429
|
+
span.setAttribute("part", "root");
|
|
1430
|
+
if (this.hasAttribute("aria-hidden") && this.getAttribute("aria-hidden") === "true") {
|
|
1431
|
+
span.setAttribute("aria-hidden", "true");
|
|
1432
|
+
}
|
|
1433
|
+
span.textContent = content;
|
|
1434
|
+
__classPrivateFieldGet2(this, _RelativeTimeElement_renderRoot, "f").replaceChildren(span);
|
|
1435
|
+
}, "_RelativeTimeElement_updateRenderRootContent"), _RelativeTimeElement_shouldDisplayUserPreferredAbsoluteTime = /* @__PURE__ */ __name(function _RelativeTimeElement_shouldDisplayUserPreferredAbsoluteTime2(format) {
|
|
1436
|
+
var _a;
|
|
1437
|
+
if (format === "duration" && this.format !== "micro")
|
|
1438
|
+
return false;
|
|
1439
|
+
return this.ownerDocument.documentElement.getAttribute("data-prefers-absolute-time") === "true" || ((_a = this.ownerDocument.body) === null || _a === void 0 ? void 0 : _a.getAttribute("data-prefers-absolute-time")) === "true";
|
|
1440
|
+
}, "_RelativeTimeElement_shouldDisplayUserPreferredAbsoluteTime");
|
|
1441
|
+
|
|
1442
|
+
// dist/relative-time-element-define.js
|
|
1443
|
+
var root = typeof globalThis !== "undefined" ? globalThis : window;
|
|
1444
|
+
try {
|
|
1445
|
+
root.RelativeTimeElement = RelativeTimeElement.define();
|
|
1446
|
+
} catch (e) {
|
|
1447
|
+
if (!(root.DOMException && e instanceof DOMException && e.name === "NotSupportedError") && !(e instanceof ReferenceError)) {
|
|
1448
|
+
throw e;
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
var relative_time_element_define_default = RelativeTimeElement;
|
|
1452
|
+
|
|
1453
|
+
// dist/index.js
|
|
1454
|
+
var index_default = relative_time_element_define_default;
|
|
1455
|
+
export {
|
|
1456
|
+
relative_time_element_define_default as RelativeTimeElement,
|
|
1457
|
+
RelativeTimeUpdatedEvent,
|
|
1458
|
+
index_default as default
|
|
1459
|
+
};
|
|
1460
|
+
</script>
|
|
515
1461
|
<script src="/lib/chart.min.js"></script>
|
|
516
1462
|
<script>
|
|
517
1463
|
const POLL_MS = 5000;
|
|
@@ -671,13 +1617,22 @@
|
|
|
671
1617
|
const dt = new Date(ms);
|
|
672
1618
|
return "Resets " + dt.toLocaleDateString([], { weekday: "short" }) + " " + dt.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
|
|
673
1619
|
}
|
|
1620
|
+
// 4-tier consumption color: green < 50, yellow < 75, orange (--accent) < 90, red >= 90.
|
|
1621
|
+
function usageColor(pct) { return pct >= 90 ? "var(--bad)" : pct >= 75 ? "var(--accent)" : pct >= 50 ? "var(--warn)" : "var(--good)"; }
|
|
1622
|
+
|
|
1623
|
+
// A vendored, auto-updating <relative-time> with a pre-formatted fallback string, so the
|
|
1624
|
+
// time still reads if the custom element has not upgraded (or the script failed to load).
|
|
1625
|
+
function rtime(ms, attrs, fallback) {
|
|
1626
|
+
if (!ms) return esc(fallback || "");
|
|
1627
|
+
return '<relative-time datetime="' + new Date(ms).toISOString() + '" ' + attrs + '>' + esc(fallback || "") + "</relative-time>";
|
|
1628
|
+
}
|
|
674
1629
|
function windowCard(w, sub) {
|
|
675
1630
|
const reset = w.kind === "session"
|
|
676
|
-
? (w.resetsAt ? "Resets " + fmtResetIn(w.resetsAt) : "No active session")
|
|
677
|
-
: (w.resetsAt ? fmtResetAt(w.resetsAt) : "");
|
|
1631
|
+
? (w.resetsAt ? "Resets " + rtime(w.resetsAt, 'tense="future" precision="minute" format="relative"', fmtResetIn(w.resetsAt)) : "No active session")
|
|
1632
|
+
: (w.resetsAt ? "Resets " + rtime(w.resetsAt, 'format="datetime" weekday="short" hour="numeric" minute="2-digit"', fmtResetAt(w.resetsAt).replace(/^Resets /, "")) : "");
|
|
678
1633
|
const live = w.live ? ' <span class="tag meas">live</span>' : "";
|
|
679
1634
|
const span = w.kind === "session" ? 5 * 3600000 : 7 * 86400000;
|
|
680
|
-
const head = '<div class="wcard"><div class="wtitle">' + esc(w.label) + live + '</div><div class="wreset">' +
|
|
1635
|
+
const head = '<div class="wcard"><div class="wtitle">' + esc(w.label) + live + '</div><div class="wreset">' + reset + '</div>';
|
|
681
1636
|
if (sub === "weeklySonnet" && (w.used || 0) === 0 && w.pct == null) {
|
|
682
1637
|
return head + '<div class="wval muted">You haven\'t used Sonnet yet</div></div>';
|
|
683
1638
|
}
|
|
@@ -687,7 +1642,7 @@
|
|
|
687
1642
|
let barPct, barCol, barNote, valLine;
|
|
688
1643
|
if (w.pct != null) {
|
|
689
1644
|
barPct = Math.min(100, w.pct);
|
|
690
|
-
barCol = w.pct
|
|
1645
|
+
barCol = usageColor(w.pct);
|
|
691
1646
|
barNote = (w.live ? "live · " : "") + fmt(w.used || 0) + " tok";
|
|
692
1647
|
valLine = Math.round(w.pct) + "% used";
|
|
693
1648
|
} else if (w.resetsAt) {
|
|
@@ -715,6 +1670,24 @@
|
|
|
715
1670
|
+ windowCard(w.weeklySonnet, "weeklySonnet")
|
|
716
1671
|
+ "</div>";
|
|
717
1672
|
}
|
|
1673
|
+
|
|
1674
|
+
// Claude operational status from the public statuspage (CORS-open, no auth). Maps the
|
|
1675
|
+
// indicator to a colored dot; degrades quietly to "unavailable" if the fetch is blocked.
|
|
1676
|
+
async function loadClaudeStatus() {
|
|
1677
|
+
const el = $("claudeStatus");
|
|
1678
|
+
if (!el || document.hidden) return;
|
|
1679
|
+
try {
|
|
1680
|
+
const r = await fetch("https://status.claude.com/api/v2/status.json", { cache: "no-store" });
|
|
1681
|
+
const d = await r.json();
|
|
1682
|
+
const ind = (d.status && d.status.indicator) || "unknown";
|
|
1683
|
+
const desc = (d.status && d.status.description) || "Status unknown";
|
|
1684
|
+
el.className = "cstatus " + (ind === "none" ? "ok" : ind === "minor" ? "warn" : ind === "major" ? "orange" : ind === "critical" ? "bad" : "");
|
|
1685
|
+
el.querySelector(".ctext").textContent = desc;
|
|
1686
|
+
} catch {
|
|
1687
|
+
el.className = "cstatus";
|
|
1688
|
+
el.querySelector(".ctext").textContent = "Claude status unavailable";
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
718
1691
|
async function planSet(key, value) {
|
|
719
1692
|
try { await fetch("/api/plan", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ key, value: Number(value) }) }); refreshAll(true); }
|
|
720
1693
|
catch { /* leave as-is */ }
|
|
@@ -1153,6 +2126,8 @@
|
|
|
1153
2126
|
const el = $("systems");
|
|
1154
2127
|
if (!s) { el.innerHTML = '<div class="empty" style="padding:16px 0">Status unavailable.</div>'; return; }
|
|
1155
2128
|
const item = (k, v) => '<div class="sys-item"><span class="k">' + labelWithBadges(k) + '</span><span class="v">' + v + "</span></div>";
|
|
2129
|
+
// Full-width row for values that are a list of chips (keeps them from cramming).
|
|
2130
|
+
const itemWide = (k, v) => '<div class="sys-item wide"><span class="k">' + labelWithBadges(k) + '</span><span class="v">' + v + "</span></div>";
|
|
1156
2131
|
const sk = s.skills || {};
|
|
1157
2132
|
const skillTags = '<span class="tag">' + (sk.enigma || 0) + " enigma</span>"
|
|
1158
2133
|
+ '<span class="tag ext">' + (sk.external || 0) + " external</span>"
|
|
@@ -1160,11 +2135,11 @@
|
|
|
1160
2135
|
const sec = s.security || {};
|
|
1161
2136
|
const ps = s.proxyStats || {};
|
|
1162
2137
|
const proxyMeasured = (ps.calls || 0) > 0
|
|
1163
|
-
?
|
|
2138
|
+
? itemWide("Proxy measured · real", '<span class="tag">' + fmt(ps.calls) + " calls</span><span class=\"tag\">"
|
|
1164
2139
|
+ fmt(ps.input) + " in</span><span class=\"tag\">" + fmt(ps.output) + " out</span><span class=\"tag\">" + fmt(ps.cacheRead) + " cache</span>")
|
|
1165
2140
|
: "";
|
|
1166
2141
|
const proxyLast = (ps.lastRequestAt || 0) > 0
|
|
1167
|
-
?
|
|
2142
|
+
? itemWide("Proxy last request · real", '<span class="tag">' + esc(fmtDuration((Date.now() - ps.lastRequestAt) / 1000) + " ago")
|
|
1168
2143
|
+ '</span><span class="tag">' + esc(new Date(ps.lastRequestAt).toLocaleString()) + "</span>")
|
|
1169
2144
|
: "";
|
|
1170
2145
|
// Prompt secret guard: configured state + what it has actually blocked (measured).
|
|
@@ -1174,7 +2149,7 @@
|
|
|
1174
2149
|
const promptGuard = item("Prompt secret guard · experimental", guardState);
|
|
1175
2150
|
const blockedTotal = (ps.redacted || 0) + (ps.rejected || 0);
|
|
1176
2151
|
const promptBlocked = blockedTotal > 0
|
|
1177
|
-
?
|
|
2152
|
+
? itemWide("Prompt secrets blocked · real", '<span class="tag">' + fmt(ps.redacted || 0) + " redacted</span><span class=\"tag\">"
|
|
1178
2153
|
+ fmt(ps.rejected || 0) + " rejected</span>"
|
|
1179
2154
|
+ ((ps.lastBlockedAt || 0) > 0 ? '<span class="tag">' + esc(fmtDuration((Date.now() - ps.lastBlockedAt) / 1000) + " ago") + "</span>" : ""))
|
|
1180
2155
|
: "";
|
|
@@ -1194,18 +2169,8 @@
|
|
|
1194
2169
|
+ item("Commit emoji", boolPill(s.commitEmoji))
|
|
1195
2170
|
+ item("Local dashboard", pill(s.dashboard === "off" ? "off" : "lvl", s.dashboard || "off"))
|
|
1196
2171
|
+ item("Permission bypass (security)", boolPill(sec.permissionBypass))
|
|
1197
|
-
+ item("Commit guard blocks", guard || '<span class="tag">set up with enigma security</span>')
|
|
1198
2172
|
+ item("Skills", skillTags)
|
|
1199
|
-
+
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
// Per-tool launch-path status: green when launchable, yellow when off PATH, red when missing.
|
|
1203
|
-
function toolPathTags(tools) {
|
|
1204
|
-
if (!tools || !tools.length) return '<span class="tag">unknown</span>';
|
|
1205
|
-
return tools.map((t) => {
|
|
1206
|
-
const cls = t.status === "not installed" ? "warn" : (t.status === "installed, off PATH" ? "ext" : "");
|
|
1207
|
-
return '<span class="tag ' + cls + '">' + esc(t.label) + ": " + esc(t.status) + "</span>";
|
|
1208
|
-
}).join("");
|
|
2173
|
+
+ itemWide("Commit guard blocks", guard || '<span class="tag">set up with enigma security</span>');
|
|
1209
2174
|
}
|
|
1210
2175
|
|
|
1211
2176
|
async function runUpdate() {
|
|
@@ -1525,8 +2490,10 @@
|
|
|
1525
2490
|
|
|
1526
2491
|
initChart();
|
|
1527
2492
|
poll(true);
|
|
2493
|
+
loadClaudeStatus();
|
|
1528
2494
|
setInterval(() => refreshAll(false), POLL_MS);
|
|
1529
|
-
|
|
2495
|
+
setInterval(loadClaudeStatus, 60000);
|
|
2496
|
+
document.addEventListener("visibilitychange", () => { if (!document.hidden) { refreshAll(true); loadClaudeStatus(); } });
|
|
1530
2497
|
wireSettings();
|
|
1531
2498
|
wireSkills();
|
|
1532
2499
|
wireAccounts();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enigmax/dashboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "Local browser dashboard UI for enigma: the static page and chart assets enigma serves on its loopback dashboard (savings, real tool usage, in-browser settings). Installed on demand by enigma-cli; not a runtime dependency.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|