quotacap 0.0.28 → 0.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/codex.js +11 -4
- package/dist/advisory/engine.d.ts +3 -1
- package/dist/advisory/engine.js +32 -8
- package/dist/advisory/snapshot.js +1 -0
- package/dist/advisory/types.d.ts +14 -0
- package/dist/advisory/types.js +7 -1
- package/dist/cli/runtime.d.ts +1 -0
- package/dist/cli/runtime.js +8 -1
- package/dist/format/markdown.js +3 -3
- package/dist/format/rows.d.ts +4 -1
- package/dist/format/rows.js +25 -1
- package/dist/format/terminal.js +10 -3
- package/dist/mcp/server.js +1 -1
- package/dist/store/quotas.js +2 -1
- package/dist/version.js +1 -1
- package/dist/web/src/components/AdviceDrawer.js +2 -1
- package/dist/web/src/components/PaceBar.d.ts +53 -3
- package/dist/web/src/components/PaceBar.js +76 -11
- package/dist/web/src/components/PacingLegend.js +3 -2
- package/dist/web/src/components/ProviderCard.js +3 -2
- package/dist/web/src/components/ProviderDrawer.js +16 -4
- package/dist/web/src/components/ProviderRow.js +3 -3
- package/dist/web/src/components/ResetRail.js +1 -1
- package/dist/web/src/components/SubscriptionList.js +1 -1
- package/dist/web/src/state.d.ts +2 -0
- package/dist/webAssets.js +1 -1
- package/dist/webHtml.js +1 -1
- package/package.json +1 -1
- package/web/dist/assets/{index-TJk_KDbS.css → index-BRBtLIOV.css} +1 -1
- package/web/dist/assets/{index-hmABfkqB.js → index-XVPB92eL.js} +2 -2
- package/web/dist/index.html +2 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
const STATES = [
|
|
4
|
-
{ label: "On track", cls: "pace-ontrack", meaning: "
|
|
4
|
+
{ label: "On track", cls: "pace-ontrack", meaning: "Burning at a rate the window sustains" },
|
|
5
5
|
{ label: "Behind pace", cls: "pace-behind", meaning: "Burning slow; risk of unused quota waste" },
|
|
6
6
|
{ label: "Ahead of pace", cls: "pace-ahead", meaning: "Burning faster than time; monitor usage" },
|
|
7
7
|
{ label: "Cap risk", cls: "pace-cap", meaning: "Will hit cap before reset window closes" },
|
|
8
|
+
{ label: "Measuring", cls: "pace-out", meaning: "Not enough data yet; pace appears after 6h" },
|
|
8
9
|
{ label: "Not reporting", cls: "pace-out", meaning: "No usable reading; excluded from ranking" },
|
|
9
10
|
];
|
|
10
11
|
export function PacingLegend() {
|
|
@@ -28,7 +29,7 @@ export function PacingLegend() {
|
|
|
28
29
|
document.removeEventListener("keydown", onKey);
|
|
29
30
|
};
|
|
30
31
|
}, [open]);
|
|
31
|
-
return (_jsxs("div", { className: "legend-wrap", ref: rootRef, children: [_jsx("button", { type: "button", className: "legend-btn", "aria-expanded": open, "aria-controls": "pacing-legend", onClick: () => setOpen((v) => !v), children: "Pacing Legend \u25BE" }), open && (_jsxs("div", { id: "pacing-legend", className: "legend-popover", role: "dialog", "aria-label": "Pacing legend", children: [_jsxs("div", { className: "legend-head", children: [_jsx("b", { children: "Pacing Scale Legend" }), _jsx("button", { type: "button", className: "legend-close", "aria-label": "Close pacing legend", onClick: () => setOpen(false), children: "\u00D7" })] }), _jsx("p", { className: "legend-intro", children: "Pacing measures quota burn against elapsed window time:" }), _jsx("div", { className: "legend-rows", children: STATES.map((s) => (_jsxs("div", { className: "legend-row", children: [_jsx("span", { className: `pace ${s.cls}`, children: s.label }), _jsx("span", { children: s.meaning })] }, s.label))) }), _jsxs("div", { className: "legend-foot", children: [_jsx("code", { children: "\u2588" }), " allowance used \u00B7 ", _jsx("code", { children: "\u2502" }), " time elapsed \u00B7 ", _jsx("code", { children: "\u2591" }), " projected waste"] })] }))] }));
|
|
32
|
+
return (_jsxs("div", { className: "legend-wrap", ref: rootRef, children: [_jsx("button", { type: "button", className: "legend-btn", "aria-expanded": open, "aria-controls": "pacing-legend", onClick: () => setOpen((v) => !v), children: "Pacing Legend \u25BE" }), open && (_jsxs("div", { id: "pacing-legend", className: "legend-popover", role: "dialog", "aria-label": "Pacing legend", children: [_jsxs("div", { className: "legend-head", children: [_jsx("b", { children: "Pacing Scale Legend" }), _jsx("button", { type: "button", className: "legend-close", "aria-label": "Close pacing legend", onClick: () => setOpen(false), children: "\u00D7" })] }), _jsx("p", { className: "legend-intro", children: "Pacing measures quota burn against elapsed window time:" }), _jsx("div", { className: "legend-rows", children: STATES.map((s) => (_jsxs("div", { className: "legend-row", children: [_jsx("span", { className: `pace ${s.cls}`, children: s.label }), _jsx("span", { children: s.meaning })] }, s.label))) }), _jsxs("div", { className: "legend-foot", children: [_jsx("code", { children: "\u2588" }), " allowance used \u00B7 ", _jsx("code", { children: "\u2502" }), " time elapsed \u00B7 ", _jsx("code", { children: "\u2591" }), " projected waste"] }), _jsx("div", { className: "legend-foot", children: "Avg = used \u00F7 days elapsed \u00B7 24h = burn over the last day \u00B7 Ideal = remaining \u00F7 days left" })] }))] }));
|
|
32
33
|
}
|
|
33
34
|
function servingHost() {
|
|
34
35
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ageDuration } from "../state.js";
|
|
3
|
-
import { Badge, PaceBar, isEstimated, resetClock, resetCountdown, timeLeft, } from "./PaceBar.js";
|
|
3
|
+
import { Badge, PACE_TIPS, PaceBar, isEstimated, paceCells, resetClock, resetCountdown, timeLeft, } from "./PaceBar.js";
|
|
4
4
|
import { ProviderIcon, providerTint } from "./ProviderIcon.js";
|
|
5
5
|
function resetsDate(provider) {
|
|
6
6
|
if (!provider.quota)
|
|
@@ -13,6 +13,7 @@ function resetsDate(provider) {
|
|
|
13
13
|
export function ProviderCard({ provider, recommended, asOf, onSelect, }) {
|
|
14
14
|
const quota = provider.quota;
|
|
15
15
|
const advisory = provider.advisory;
|
|
16
|
+
const pace = paceCells(advisory);
|
|
16
17
|
const asOfMs = Date.parse(asOf);
|
|
17
18
|
const updated = ageDuration(provider.ageMs);
|
|
18
19
|
const resetsIn = quota ? timeLeft(quota.resetsAt, asOfMs) : null;
|
|
@@ -22,5 +23,5 @@ export function ProviderCard({ provider, recommended, asOf, onSelect, }) {
|
|
|
22
23
|
e.preventDefault();
|
|
23
24
|
onSelect(provider.id);
|
|
24
25
|
}
|
|
25
|
-
}, className: `pcard ${recommended ? "is-recommended is-top-pick" : ""}`, children: [_jsxs("div", { className: "pcard-head", children: [_jsx("span", { className: "picon", style: providerTint(provider.id), "aria-hidden": "true", children: _jsx(ProviderIcon, { id: provider.id, title: name }) }), _jsxs("div", { className: "who", children: [_jsxs("b", { children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota && quota.plan && _jsx("span", { className: "pl", children: quota.plan }), updated && _jsxs("span", { className: "src", children: ["Updated ", updated, " ago"] })] }), _jsx(Badge, { provider: provider })] }), _jsxs("div", { className: "pcard-body", children: [_jsx(PaceBar, { provider: provider, asOf: asOf }), _jsxs("div", { className: "pstats", children: [_jsxs("div", { children: [_jsx("span", { className: "l", children: "
|
|
26
|
+
}, className: `pcard ${recommended ? "is-recommended is-top-pick" : ""}`, children: [_jsxs("div", { className: "pcard-head", children: [_jsx("span", { className: "picon", style: providerTint(provider.id), "aria-hidden": "true", children: _jsx(ProviderIcon, { id: provider.id, title: name }) }), _jsxs("div", { className: "who", children: [_jsxs("b", { children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota && quota.plan && _jsx("span", { className: "pl", children: quota.plan }), updated && _jsxs("span", { className: "src", children: ["Updated ", updated, " ago"] })] }), _jsx(Badge, { provider: provider })] }), _jsxs("div", { className: "pcard-body", children: [_jsx(PaceBar, { provider: provider, asOf: asOf }), _jsxs("div", { className: "pstats", children: [_jsxs("div", { title: PACE_TIPS.avg, children: [_jsx("span", { className: "l", children: "Avg pace" }), _jsx("span", { className: "v", children: pace.avg })] }), _jsxs("div", { title: PACE_TIPS.recent, children: [_jsx("span", { className: "l", children: "24h pace" }), _jsx("span", { className: "v", children: pace.recent })] }), _jsxs("div", { title: PACE_TIPS.ideal, children: [_jsx("span", { className: "l", children: "Ideal pace" }), _jsx("span", { className: "v", children: advisory ? `${advisory.idealRate.toFixed(1)}%/day` : "—" })] }), _jsxs("div", { children: [_jsx("span", { className: "l", children: "Resets in" }), _jsx("span", { className: "v", children: resetsIn ? `${resetsIn}${isEstimated(provider) ? " (est.)" : ""}` : resetCountdown(provider, asOfMs) })] })] })] }), _jsxs("div", { className: "pcard-foot", children: [_jsx("span", { children: resetsDate(provider) ?? resetCountdown(provider, asOfMs) }), _jsx("span", { className: "rowbtn", "aria-hidden": "true", children: "Inspect" })] })] }));
|
|
26
27
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { ageDuration, providerSubtitle } from "../state.js";
|
|
4
|
-
import { Badge, PaceBar, barGeometry, isEstimated, paceBadge, resetClock, timeLeft, } from "./PaceBar.js";
|
|
4
|
+
import { Badge, PaceBar, barGeometry, isEstimated, paceBadge, paceFigures, resetClock, timeLeft, } from "./PaceBar.js";
|
|
5
5
|
import { ProviderIcon, providerTint } from "./ProviderIcon.js";
|
|
6
6
|
import { renameProvider } from "../api.js";
|
|
7
7
|
export function exclusionWords(reason) {
|
|
@@ -122,6 +122,8 @@ export function pacingStatusToken(provider) {
|
|
|
122
122
|
return "ahead";
|
|
123
123
|
case "Cap risk":
|
|
124
124
|
return "cap";
|
|
125
|
+
case "Measuring":
|
|
126
|
+
return "measuring";
|
|
125
127
|
case "Not reporting":
|
|
126
128
|
return "out";
|
|
127
129
|
}
|
|
@@ -153,11 +155,21 @@ export function rankingCopy(provider, recommendation) {
|
|
|
153
155
|
if (!advisory || advisory.paceSource === "unknown" || advisory.burnRate === null) {
|
|
154
156
|
pace = modelFailure(provider) ?? "No current pace.";
|
|
155
157
|
}
|
|
156
|
-
else if (advisory.
|
|
157
|
-
pace =
|
|
158
|
+
else if (advisory.remaining <= 0) {
|
|
159
|
+
pace = `Exhausted at ${quota?.usedPct ?? 100}% used.${stamp ? ` Resets ${stamp}.` : ""}`;
|
|
158
160
|
}
|
|
159
161
|
else {
|
|
160
|
-
|
|
162
|
+
const { avg, recent } = paceFigures(advisory);
|
|
163
|
+
const figures = avg !== null && recent !== null && avg.toFixed(1) !== recent.toFixed(1)
|
|
164
|
+
? `${avg.toFixed(1)}%/day window average and ${recent.toFixed(1)}%/day over the last 24h`
|
|
165
|
+
: avg !== null
|
|
166
|
+
? `${avg.toFixed(1)}%/day window average`
|
|
167
|
+
: `${recent.toFixed(1)}%/day over the last 24h`;
|
|
168
|
+
const ideal = `${advisory.idealRate.toFixed(1)}%/day`;
|
|
169
|
+
pace =
|
|
170
|
+
advisory.status === "at risk"
|
|
171
|
+
? `${figures}, against an ideal pace of ${ideal}.`
|
|
172
|
+
: `${figures}. The ideal pace to finish is ${ideal}.`;
|
|
161
173
|
}
|
|
162
174
|
let decision;
|
|
163
175
|
if (provider.exclusionReason) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Badge, PaceBar,
|
|
2
|
+
import { Badge, PaceBar, forecastLine, paceLines, resetCell, } from "./PaceBar.js";
|
|
3
3
|
export function ProviderRow({ provider, recommended, asOf, onSelect, }) {
|
|
4
4
|
const quota = provider.quota;
|
|
5
5
|
const advisory = provider.advisory;
|
|
6
6
|
const asOfMs = Date.parse(asOf);
|
|
7
|
-
const
|
|
7
|
+
const lines = paceLines(advisory);
|
|
8
8
|
const name = provider.displayName;
|
|
9
|
-
return (_jsxs("div", { "data-testid": `provider-row-${provider.id}`, className: `lrow ${recommended ? "is-recommended is-top-pick" : ""}`, onClick: () => onSelect(provider.id), children: [_jsxs("div", { className: "prov", "data-label": "Provider", children: [_jsx("span", { className: "dot", style: { background: `var(--p-${provider.id.split(":")[0]}, var(--surface-raised))` }, "aria-hidden": "true" }), _jsxs("span", { children: [_jsxs("span", { className: "nm", children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota?.plan && _jsx("span", { className: "pl", children: quota.plan }), quota?.sessionPct !== undefined && quota.sessionPct !== null && (_jsxs("span", { className: "src", children: ["Session use ", quota.sessionPct, "%"] }))] })] }), _jsx("div", { "data-label": "Used vs elapsed", children: quota ? _jsx(PaceBar, { provider: provider, asOf: asOf }) : "—" }), _jsx("div", { "data-label": "
|
|
9
|
+
return (_jsxs("div", { "data-testid": `provider-row-${provider.id}`, className: `lrow ${recommended ? "is-recommended is-top-pick" : ""}`, onClick: () => onSelect(provider.id), children: [_jsxs("div", { className: "prov", "data-label": "Provider", children: [_jsx("span", { className: "dot", style: { background: `var(--p-${provider.id.split(":")[0]}, var(--surface-raised))` }, "aria-hidden": "true" }), _jsxs("span", { children: [_jsxs("span", { className: "nm", children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota?.plan && _jsx("span", { className: "pl", children: quota.plan }), quota?.sessionPct !== undefined && quota.sessionPct !== null && (_jsxs("span", { className: "src", children: ["Session use ", quota.sessionPct, "%"] }))] })] }), _jsx("div", { "data-label": "Used vs elapsed", children: quota ? _jsx(PaceBar, { provider: provider, asOf: asOf }) : "—" }), _jsx("div", { "data-label": "Reset", children: _jsx("span", { className: "cell-b", children: resetCell(provider, asOfMs) }) }), _jsxs("div", { "data-label": "Pace", children: [_jsx(Badge, { provider: provider }), lines.length > 0 && (_jsx("div", { style: { marginTop: 2 }, children: lines.map((l) => (_jsxs("div", { className: "cell-s paceline", title: l.tip, children: [_jsx("span", { children: l.label }), _jsx("span", { className: "cell-b", children: l.value })] }, l.label))) }))] }), _jsx("button", { type: "button", className: "rowbtn", onClick: (e) => {
|
|
10
10
|
e.stopPropagation();
|
|
11
11
|
onSelect(provider.id);
|
|
12
12
|
}, children: "Inspect" }), _jsx("span", { className: "sr-only", children: forecastLine(provider) })] }));
|
|
@@ -6,7 +6,7 @@ const RAIL_MS = RAIL_DAYS * 24 * 60 * 60 * 1000;
|
|
|
6
6
|
/** Pins within this span of rail group into one collision window. */
|
|
7
7
|
const COLLISION_PCT = 3;
|
|
8
8
|
/** Pins per window before they group into a cluster pin. */
|
|
9
|
-
const WINDOW_CAPACITY =
|
|
9
|
+
const WINDOW_CAPACITY = 3;
|
|
10
10
|
/**
|
|
11
11
|
* Place reset pins proportionally over the next 7 days from `asOf`.
|
|
12
12
|
* Crowded windows past tier capacity group into clusters; resets beyond the
|
|
@@ -102,5 +102,5 @@ export function SubscriptionList({ providers, recommendation, asOf, lastComplete
|
|
|
102
102
|
const asOfMs = Date.parse(asOf);
|
|
103
103
|
const ranked = enabled.filter((p) => p.exclusionReason === null);
|
|
104
104
|
const excluded = enabled.filter((p) => p.exclusionReason !== null);
|
|
105
|
-
return (_jsxs("section", { "aria-label": "Subscriptions", children: [_jsxs("div", { className: "section-head", children: [_jsx("h2", { children: "All subscriptions" }), _jsxs("div", { className: "section-head-controls", children: [_jsx(SortDropdown, { value: sortKey, onChange: setSortKey }), _jsxs("div", { role: "group", "aria-label": "Display density", className: "seg", children: [_jsxs("button", { type: "button", "aria-pressed": effective === "cards", onClick: () => setDensity("cards"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "3", y: "13", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "13", width: "8", height: "8", rx: "2" })] }), "Cards"] }), _jsxs("button", { type: "button", "aria-pressed": effective === "table", onClick: () => setDensity("table"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "5", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "11", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "17", width: "18", height: "2.6", rx: "1.3" })] }), "Table"] })] })] })] }), effective === "cards" ? (_jsx("div", { "data-testid": "cards-grid", className: "cards cards-grid", children: enabled.map((p) => (_jsx(ProviderCard, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id))) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("div", { "data-testid": "ledger-table", className: "ledger", role: "table", children: [_jsxs("div", { className: "lrow lhead", role: "row", children: [_jsx("span", { role: "columnheader", children: "Provider" }), _jsx("span", { role: "columnheader", children: "Used vs elapsed" }), _jsx("span", { role: "columnheader", children: "
|
|
105
|
+
return (_jsxs("section", { "aria-label": "Subscriptions", children: [_jsxs("div", { className: "section-head", children: [_jsx("h2", { children: "All subscriptions" }), _jsxs("div", { className: "section-head-controls", children: [_jsx(SortDropdown, { value: sortKey, onChange: setSortKey }), _jsxs("div", { role: "group", "aria-label": "Display density", className: "seg", children: [_jsxs("button", { type: "button", "aria-pressed": effective === "cards", onClick: () => setDensity("cards"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "3", y: "13", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "13", width: "8", height: "8", rx: "2" })] }), "Cards"] }), _jsxs("button", { type: "button", "aria-pressed": effective === "table", onClick: () => setDensity("table"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "5", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "11", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "17", width: "18", height: "2.6", rx: "1.3" })] }), "Table"] })] })] })] }), effective === "cards" ? (_jsx("div", { "data-testid": "cards-grid", className: "cards cards-grid", children: enabled.map((p) => (_jsx(ProviderCard, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id))) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("div", { "data-testid": "ledger-table", className: "ledger", role: "table", children: [_jsxs("div", { className: "lrow lhead", role: "row", children: [_jsx("span", { role: "columnheader", children: "Provider" }), _jsx("span", { role: "columnheader", children: "Used vs elapsed" }), _jsx("span", { role: "columnheader", children: "Reset" }), _jsx("span", { role: "columnheader", children: "Pace" }), _jsx("span", { role: "columnheader" })] }), enabled.map((p) => (_jsx(ProviderRow, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id)))] }) })), _jsxs("footer", { className: "health", children: [_jsxs("ul", { children: [_jsxs("li", { className: "legend-rec", children: [_jsx("svg", { className: "legend-star", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }), _jsx("span", { children: "Recommended to use next" })] }), _jsxs("li", { children: [_jsx("span", { className: "dot", style: { background: "var(--good)" } }), _jsxs("span", { children: [ranked.length, " used in ranking"] })] }), excluded.length > 0 && (_jsxs("li", { children: [_jsx("span", { className: "dot", style: { background: "var(--fill-out)" } }), _jsxs("span", { children: [excluded.length, " not reporting", excluded.length <= 2 ? ` · ${excluded.map((p) => p.displayName).join(", ")}` : ""] })] }))] }), _jsx("span", { children: nextRefreshLabel(lastCompletedPollAt, polling) })] }), disabled.length > 0 && (_jsxs("section", { "aria-label": "Disabled providers", children: [_jsxs("h3", { children: ["Disabled (", disabled.length, ")"] }), _jsx("ul", { children: disabled.map((p) => (_jsxs("li", { style: { fontSize: "var(--t-2)" }, children: [p.displayName, " \u00B7 disabled \u00B7 ", resetCountdown(p, asOfMs)] }, p.id))) })] }))] }));
|
|
106
106
|
}
|
package/dist/web/src/state.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface AdvisoryView {
|
|
|
9
9
|
remaining: number;
|
|
10
10
|
idealRate: number;
|
|
11
11
|
burnRate: number | null;
|
|
12
|
+
/** Window-average pace (used % ÷ days elapsed); null before the window start is known. */
|
|
13
|
+
avgPace: number | null;
|
|
12
14
|
burnMeasured: boolean;
|
|
13
15
|
paceSource: PaceSource;
|
|
14
16
|
daysToExhaust: number | null;
|