@cortexkit/opencode-anthropic-auth 2.4.7 → 2.4.9

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,909 @@
1
+ // @bun
2
+ // ../../node_modules/@cortexkit/common-auth/src/quota-sidebar/index.tsx
3
+ import { createTextNode as _$createTextNode } from "@opentui/solid";
4
+ import { createComponent as _$createComponent } from "@opentui/solid";
5
+ import { use as _$use } from "@opentui/solid";
6
+ import { memo as _$memo } from "@opentui/solid";
7
+ import { effect as _$effect } from "@opentui/solid";
8
+ import { insertNode as _$insertNode } from "@opentui/solid";
9
+ import { insert as _$insert } from "@opentui/solid";
10
+ import { setProp as _$setProp } from "@opentui/solid";
11
+ import { createElement as _$createElement } from "@opentui/solid";
12
+ import { createContext, createMemo, createSignal, For, Index, mergeProps, Show, useContext } from "solid-js";
13
+
14
+ // ../../node_modules/@cortexkit/common-auth/src/quota/map.ts
15
+ var ALL_SCOPE = "all";
16
+ var DEFAULT_REQUIRED_LABELS = Object.freeze([
17
+ "primary"
18
+ ]);
19
+
20
+ // ../../node_modules/@cortexkit/common-auth/src/quota/format.ts
21
+ var QUOTA_STALE_AFTER_MS = 15 * 60000;
22
+ var NO_QUOTA_READING = "no quota reading yet";
23
+ var NO_LIMITS_REPORTED = "no limits reported";
24
+ function shortSpan(ms) {
25
+ const minutes = Math.max(1, Math.floor(ms / 60000));
26
+ if (minutes < 60)
27
+ return `${minutes}m`;
28
+ if (minutes < 1440) {
29
+ const hours2 = Math.floor(minutes / 60);
30
+ const rest = minutes % 60;
31
+ return rest === 0 ? `${hours2}h` : `${hours2}h${rest}m`;
32
+ }
33
+ const days = Math.floor(minutes / 1440);
34
+ const hours = Math.floor(minutes % 1440 / 60);
35
+ return hours === 0 ? `${days}d` : `${days}d${hours}h`;
36
+ }
37
+ function lengthName(minutes) {
38
+ if (minutes % 1440 === 0)
39
+ return `${minutes / 1440}d`;
40
+ if (minutes % 60 === 0)
41
+ return `${minutes / 60}h`;
42
+ return `${minutes}m`;
43
+ }
44
+ function quotaWindowName(limit) {
45
+ if (limit.scope !== ALL_SCOPE || limit.windowMinutes === undefined)
46
+ return limit.label;
47
+ return lengthName(limit.windowMinutes);
48
+ }
49
+ function clampPercent(remaining) {
50
+ return Math.min(100, Math.max(0, remaining));
51
+ }
52
+ function wholePercent(remaining) {
53
+ return Math.round(clampPercent(remaining));
54
+ }
55
+ function percentLeft(remaining) {
56
+ return `${wholePercent(remaining)}% left`;
57
+ }
58
+ function resetDetails(resetsAt, checkedAt, now) {
59
+ const at = resetsAt === undefined ? Number.NaN : Date.parse(resetsAt);
60
+ return {
61
+ ...Number.isFinite(at) && at > now ? { resetIn: shortSpan(at - now) } : {},
62
+ resetSinceReading: Number.isFinite(at) && at > checkedAt && at <= now
63
+ };
64
+ }
65
+ function displayOrder(left, right) {
66
+ const l = left.windowMinutes;
67
+ const r = right.windowMinutes;
68
+ if (l !== undefined && r !== undefined && l !== r)
69
+ return l - r;
70
+ if (l === undefined !== (r === undefined))
71
+ return l === undefined ? 1 : -1;
72
+ if (left.scope !== right.scope) {
73
+ if (left.scope === ALL_SCOPE)
74
+ return -1;
75
+ if (right.scope === ALL_SCOPE)
76
+ return 1;
77
+ return left.scope < right.scope ? -1 : 1;
78
+ }
79
+ return left.label < right.label ? -1 : left.label > right.label ? 1 : 0;
80
+ }
81
+ function quotaWindowParts(quota, options) {
82
+ const { windows, age } = scopedWindowParts(quota, options, true);
83
+ const parts = windows.map(({ part }) => part);
84
+ return age === undefined ? { windows: parts } : { windows: parts, age };
85
+ }
86
+ function withShortNames(windows) {
87
+ const abbreviations = scopeAbbreviations(windows.filter(({ part, scope }) => part.kind === "window" && scope !== ALL_SCOPE).map(({ scope }) => scope));
88
+ for (const window of windows) {
89
+ window.part.short = window.part.kind === "budget" ? "cr" : window.scope === ALL_SCOPE ? window.part.name : abbreviations.get(window.scope) ?? window.scope;
90
+ }
91
+ return windows;
92
+ }
93
+ function hasWindowReading(limit) {
94
+ return Number.isFinite(limit.remainingPercent) && Number.isFinite(limit.checkedAt);
95
+ }
96
+ function scopedWindowParts(quota, options, includeUnknown = false) {
97
+ if (!quota)
98
+ return { windows: [] };
99
+ const { now } = options;
100
+ const readings = quota.limits.filter((limit) => limit.kind === "reading" && (includeUnknown || hasWindowReading(limit))).sort(displayOrder);
101
+ const windows = readings.map((limit) => {
102
+ const part = hasWindowReading(limit) ? {
103
+ kind: "window",
104
+ reading: "known",
105
+ name: quotaWindowName(limit),
106
+ short: "",
107
+ figure: percentLeft(limit.remainingPercent),
108
+ remainingPercent: clampPercent(limit.remainingPercent),
109
+ checkedAt: limit.checkedAt,
110
+ ...resetDetails(limit.resetsAt, limit.checkedAt, now)
111
+ } : {
112
+ kind: "window",
113
+ reading: "unknown",
114
+ name: quotaWindowName(limit),
115
+ short: "",
116
+ figure: "no reading",
117
+ resetSinceReading: false
118
+ };
119
+ return {
120
+ scope: limit.scope,
121
+ ...limit.windowMinutes === undefined ? {} : { windowMinutes: limit.windowMinutes },
122
+ part
123
+ };
124
+ });
125
+ const budget = quota.budget;
126
+ if (budget) {
127
+ const remainingPercent = budget.remainingPercent;
128
+ const figure = budget.reached ? "credits spent" : remainingPercent !== undefined ? `credits ${percentLeft(remainingPercent)}` : "credits available";
129
+ windows.push({
130
+ scope: ALL_SCOPE,
131
+ spent: budget.reached,
132
+ part: {
133
+ kind: "budget",
134
+ reading: "known",
135
+ name: "credits",
136
+ short: "",
137
+ figure,
138
+ ...remainingPercent === undefined ? {} : { remainingPercent: clampPercent(remainingPercent) },
139
+ checkedAt: budget.checkedAt,
140
+ ...resetDetails(budget.resetsAt, budget.checkedAt, now)
141
+ }
142
+ });
143
+ }
144
+ withShortNames(windows);
145
+ const readingTimes = windows.flatMap(({ part }) => part.reading === "known" && part.checkedAt !== undefined ? [part.checkedAt] : []);
146
+ if (readingTimes.length > 0) {
147
+ const age = now - Math.min(...readingTimes);
148
+ if (age > (options.staleAfterMs ?? QUOTA_STALE_AFTER_MS)) {
149
+ return { windows, age: `checked ${shortSpan(age)} ago` };
150
+ }
151
+ }
152
+ return { windows };
153
+ }
154
+ function scopeDisplayName(scope) {
155
+ const model = scope.slice(scope.indexOf(":") + 1);
156
+ return model.charAt(0).toUpperCase() + model.slice(1);
157
+ }
158
+ function scopeAbbreviations(scopes) {
159
+ const names = [...new Set(scopes.map(scopeDisplayName))];
160
+ const lengths = new Map(names.map((name) => [name, 2]));
161
+ const short = (name) => name.slice(0, lengths.get(name));
162
+ for (;; ) {
163
+ const byShort = new Map;
164
+ for (const name of names) {
165
+ byShort.set(short(name), [...byShort.get(short(name)) ?? [], name]);
166
+ }
167
+ let extended = false;
168
+ for (const group of byShort.values()) {
169
+ if (group.length < 2)
170
+ continue;
171
+ for (const name of group) {
172
+ const length = lengths.get(name) ?? 2;
173
+ if (length < name.length) {
174
+ lengths.set(name, length + 1);
175
+ extended = true;
176
+ }
177
+ }
178
+ }
179
+ if (!extended)
180
+ break;
181
+ }
182
+ return new Map(scopes.map((scope) => [scope, short(scopeDisplayName(scope))]));
183
+ }
184
+ var NARROW_GROUP_LIMIT = 2;
185
+ function groupShortNames(groups) {
186
+ const labels = groups.map((group) => group.label.trim() || group.scope);
187
+ const short = scopeAbbreviations(labels);
188
+ return labels.map((label) => short.get(label) ?? label);
189
+ }
190
+ function groupedNarrowPieces(groups, windows) {
191
+ if (!groups || groups.length === 0)
192
+ return;
193
+ const reported = windows.filter(({ part }) => part.kind === "window");
194
+ if (reported.some(({ scope }) => scope === ALL_SCOPE))
195
+ return;
196
+ const candidates = groups.flatMap((group, listed) => {
197
+ const inGroup = reported.filter(({ scope }) => scope === group.scope);
198
+ const groupTightest = inGroup.reduce((least, window) => least === undefined || (window.part.remainingPercent ?? 0) < (least.part.remainingPercent ?? 0) ? window : least, undefined);
199
+ return groupTightest ? [{ group, listed, window: groupTightest }] : [];
200
+ });
201
+ if (candidates.length === 0)
202
+ return;
203
+ const names = groupShortNames(groups);
204
+ const left = (candidate) => candidate.window.part.remainingPercent ?? 0;
205
+ const shown = [...candidates].sort((a, b) => left(a) - left(b) || a.listed - b.listed).slice(0, NARROW_GROUP_LIMIT).sort((a, b) => a.listed - b.listed);
206
+ return shown.map((candidate, index) => {
207
+ const { windowMinutes } = candidate.window;
208
+ const piece = [
209
+ names[candidate.listed] ?? candidate.group.scope,
210
+ ...windowMinutes === undefined ? [] : [lengthName(windowMinutes)],
211
+ `${wholePercent(left(candidate))}%`
212
+ ].join(" ");
213
+ return index === shown.length - 1 ? `${piece} left` : piece;
214
+ });
215
+ }
216
+ function narrowTextParts(quota, options) {
217
+ const { windows } = scopedWindowParts(quota, options);
218
+ const grouped = groupedNarrowPieces(quota?.groups, windows);
219
+ if (grouped)
220
+ return grouped;
221
+ const general = windows.filter(({ part, scope }) => part.kind === "window" && scope === ALL_SCOPE);
222
+ const scoped = windows.filter(({ part, scope }) => part.kind === "window" && scope !== ALL_SCOPE);
223
+ const budget = windows.find(({ part }) => part.kind === "budget");
224
+ const budgetLeft = budget?.spent ? 0 : budget?.part.remainingPercent;
225
+ const extras = [
226
+ ...scoped.map(({ part }) => ({
227
+ label: part.short,
228
+ remaining: part.remainingPercent ?? 0
229
+ })),
230
+ ...budgetLeft === undefined || budget === undefined ? [] : [{ label: budget.part.short, remaining: budgetLeft }]
231
+ ];
232
+ const tightest = extras.reduce((best, item) => best === undefined || item.remaining < best.remaining ? item : best, undefined);
233
+ const pieces = general.map(({ part }) => `${part.name} ${wholePercent(part.remainingPercent ?? 0)}%`);
234
+ if (tightest) {
235
+ pieces.push(`${tightest.label} ${wholePercent(tightest.remaining)}%`);
236
+ }
237
+ if (pieces.length === 0)
238
+ return windows.map(({ part }) => part.figure);
239
+ return pieces.map((piece, index) => index === pieces.length - 1 ? `${piece} left` : piece);
240
+ }
241
+ function quotaTextParts(quota, options) {
242
+ if (options.form === "narrow")
243
+ return narrowTextParts(quota, options);
244
+ const { windows, age } = scopedWindowParts(quota, options);
245
+ const full = (options.form ?? "full") === "full";
246
+ const text = windows.map(({ part }) => {
247
+ const reset = full && part.resetIn ? `, resets ${part.resetIn}` : "";
248
+ return `${part.kind === "budget" ? "" : `${part.name} `}${part.figure}${reset}`;
249
+ });
250
+ return age === undefined ? text : [...text, age];
251
+ }
252
+ function formatQuota(quota, options) {
253
+ const parts = quotaTextParts(quota, options);
254
+ if (parts.length > 0)
255
+ return parts.join(" \xB7 ");
256
+ return quota && quota.limits.length > 0 ? NO_LIMITS_REPORTED : NO_QUOTA_READING;
257
+ }
258
+
259
+ // ../../node_modules/@cortexkit/common-auth/src/quota-sidebar/index.tsx
260
+ var FrameContext = createContext();
261
+ function frameContext() {
262
+ const context = useContext(FrameContext);
263
+ if (!context)
264
+ throw new Error("Sidebar primitives must be inside SidebarFrame");
265
+ return context;
266
+ }
267
+ function displayWidth(text) {
268
+ const bun = globalThis.Bun;
269
+ return bun?.stringWidth ? bun.stringWidth(text) : Array.from(text).length;
270
+ }
271
+ function fitText(text, columns) {
272
+ if (displayWidth(text) <= columns)
273
+ return text;
274
+ if (columns < 1)
275
+ return "";
276
+ let kept = "";
277
+ let used = 0;
278
+ for (const char of text) {
279
+ const width = displayWidth(char);
280
+ if (used + width > columns - 1)
281
+ break;
282
+ kept += char;
283
+ used += width;
284
+ }
285
+ return `${kept}\u2026`;
286
+ }
287
+ function SidebarSection(props) {
288
+ const context = frameContext();
289
+ return [(() => {
290
+ var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("b");
291
+ _$insertNode(_el$, _el$2);
292
+ _$setProp(_el$, "width", "100%");
293
+ _$setProp(_el$, "marginTop", 1);
294
+ _$insertNode(_el$2, _el$3);
295
+ _$insert(_el$3, () => props.title);
296
+ _$effect((_$p) => _$setProp(_el$2, "fg", context.theme.text, _$p));
297
+ return _el$;
298
+ })(), _$memo(() => props.children)];
299
+ }
300
+ function SidebarStatRow(props) {
301
+ const context = frameContext();
302
+ const [width, setWidth] = createSignal(0);
303
+ let row;
304
+ const value = () => width() <= 0 ? props.value : fitText(props.value, width() - displayWidth(props.label) - 1);
305
+ return (() => {
306
+ var _el$4 = _$createElement("box"), _el$5 = _$createElement("text"), _el$6 = _$createElement("text"), _el$7 = _$createElement("b");
307
+ _$insertNode(_el$4, _el$5);
308
+ _$insertNode(_el$4, _el$6);
309
+ _$use((element) => {
310
+ row = element;
311
+ }, _el$4);
312
+ _$setProp(_el$4, "onSizeChange", () => setWidth(row?.width ?? 0));
313
+ _$setProp(_el$4, "width", "100%");
314
+ _$setProp(_el$4, "flexDirection", "row");
315
+ _$setProp(_el$4, "justifyContent", "space-between");
316
+ _$setProp(_el$4, "columnGap", 1);
317
+ _$setProp(_el$5, "wrapMode", "none");
318
+ _$setProp(_el$5, "flexShrink", 0);
319
+ _$insert(_el$5, () => props.label);
320
+ _$insertNode(_el$6, _el$7);
321
+ _$setProp(_el$6, "wrapMode", "none");
322
+ _$setProp(_el$6, "flexShrink", 1);
323
+ _$insert(_el$7, value);
324
+ _$effect((_p$) => {
325
+ var _v$ = context.theme.textMuted, _v$2 = context.theme[props.tone ?? "text"];
326
+ _v$ !== _p$.e && (_p$.e = _$setProp(_el$5, "fg", _v$, _p$.e));
327
+ _v$2 !== _p$.t && (_p$.t = _$setProp(_el$6, "fg", _v$2, _p$.t));
328
+ return _p$;
329
+ }, {
330
+ e: undefined,
331
+ t: undefined
332
+ });
333
+ return _el$4;
334
+ })();
335
+ }
336
+ function SidebarTextRow(props) {
337
+ const context = frameContext();
338
+ return (() => {
339
+ var _el$8 = _$createElement("text");
340
+ _$insert(_el$8, () => props.text);
341
+ _$effect((_p$) => {
342
+ var _v$3 = context.theme[props.tone ?? "textMuted"], _v$4 = props.wrapMode;
343
+ _v$3 !== _p$.e && (_p$.e = _$setProp(_el$8, "fg", _v$3, _p$.e));
344
+ _v$4 !== _p$.t && (_p$.t = _$setProp(_el$8, "wrapMode", _v$4, _p$.t));
345
+ return _p$;
346
+ }, {
347
+ e: undefined,
348
+ t: undefined
349
+ });
350
+ return _el$8;
351
+ })();
352
+ }
353
+ function usageTone(used, appearance) {
354
+ if (used >= appearance.errorThreshold)
355
+ return "error";
356
+ if (used >= appearance.warnThreshold)
357
+ return "warning";
358
+ return "success";
359
+ }
360
+ function barSegments(used, appearance, pace) {
361
+ const width = appearance.barWidth;
362
+ const cells = (pct) => Math.max(0, Math.min(Math.round(pct / 100 * width), width));
363
+ const usedCells = cells(used);
364
+ const tone = usageTone(used, appearance);
365
+ const plain = [{
366
+ text: appearance.barFilledChar.repeat(usedCells),
367
+ tone
368
+ }, {
369
+ text: "",
370
+ tone
371
+ }, {
372
+ text: appearance.barEmptyChar.repeat(width - usedCells),
373
+ tone
374
+ }];
375
+ const overlay = pace?.overlay;
376
+ if (!overlay)
377
+ return plain;
378
+ const paceCells = cells(overlay.percent);
379
+ const lo = Math.min(usedCells, paceCells);
380
+ const hi = Math.max(usedCells, paceCells);
381
+ if (lo === hi)
382
+ return plain;
383
+ return [{
384
+ text: appearance.barFilledChar.repeat(lo),
385
+ tone
386
+ }, {
387
+ text: (overlay.kind === "deficit" ? "\u2593" : "\u2592").repeat(hi - lo),
388
+ tone: overlay.kind === "deficit" ? "error" : "success"
389
+ }, {
390
+ text: appearance.barEmptyChar.repeat(width - hi),
391
+ tone
392
+ }];
393
+ }
394
+ function QuotaRow(props) {
395
+ const context = frameContext();
396
+ const [columns, setColumns] = createSignal(0);
397
+ let row;
398
+ const label = () => props.part.name + " ".repeat(Math.max(0, props.labelWidth - displayWidth(props.part.name)));
399
+ const figure = () => ` ${props.part.kind === "budget" && props.part.figure.startsWith(`${props.part.name} `) ? props.part.figure.slice(props.part.name.length + 1) : props.part.figure}`;
400
+ const hasReading = () => props.part.reading === "known";
401
+ const used = () => 100 - (props.part.remainingPercent ?? 100);
402
+ const segments = createMemo(() => hasReading() ? barSegments(used(), {
403
+ ...context.appearance,
404
+ barWidth: props.barCells
405
+ }, props.pace) : [], undefined, {
406
+ equals: (previous, next) => previous.length === next.length && previous.every((segment, index) => segment.text === next[index]?.text && segment.tone === next[index]?.tone)
407
+ });
408
+ const paceLine = () => {
409
+ const text = props.pace?.text;
410
+ if (!text || columns() <= 0)
411
+ return text;
412
+ return fitText(text, columns() - props.labelWidth);
413
+ };
414
+ return [(() => {
415
+ var _el$9 = _$createElement("box"), _el$0 = _$createElement("box");
416
+ _$insertNode(_el$9, _el$0);
417
+ _$use((element) => {
418
+ row = element;
419
+ }, _el$9);
420
+ _$setProp(_el$9, "onSizeChange", () => setColumns(row?.width ?? 0));
421
+ _$setProp(_el$9, "width", "100%");
422
+ _$setProp(_el$9, "flexDirection", "row");
423
+ _$setProp(_el$9, "justifyContent", "space-between");
424
+ _$setProp(_el$0, "flexDirection", "row");
425
+ _$insert(_el$0, _$createComponent(Show, {
426
+ get when() {
427
+ return props.labelWidth > 0;
428
+ },
429
+ get children() {
430
+ var _el$1 = _$createElement("text");
431
+ _$setProp(_el$1, "wrapMode", "none");
432
+ _$setProp(_el$1, "flexShrink", 0);
433
+ _$insert(_el$1, label);
434
+ _$effect((_$p) => _$setProp(_el$1, "fg", context.theme.textMuted, _$p));
435
+ return _el$1;
436
+ }
437
+ }), null);
438
+ _$insert(_el$0, _$createComponent(Show, {
439
+ get when() {
440
+ return hasReading();
441
+ },
442
+ get fallback() {
443
+ return (() => {
444
+ var _el$13 = _$createElement("text");
445
+ _$insertNode(_el$13, _$createTextNode(`no reading`));
446
+ _$setProp(_el$13, "wrapMode", "none");
447
+ _$effect((_$p) => _$setProp(_el$13, "fg", context.theme.textMuted, _$p));
448
+ return _el$13;
449
+ })();
450
+ },
451
+ get children() {
452
+ return _$createComponent(Show, {
453
+ get when() {
454
+ return !props.part.resetSinceReading;
455
+ },
456
+ get fallback() {
457
+ return (() => {
458
+ var _el$15 = _$createElement("text");
459
+ _$insertNode(_el$15, _$createTextNode(`reset since last check`));
460
+ _$setProp(_el$15, "wrapMode", "none");
461
+ _$effect((_$p) => _$setProp(_el$15, "fg", context.theme.textMuted, _$p));
462
+ return _el$15;
463
+ })();
464
+ },
465
+ get children() {
466
+ return [_$createComponent(Show, {
467
+ get when() {
468
+ return props.barCells > 0;
469
+ },
470
+ get children() {
471
+ return _$createComponent(Index, {
472
+ get each() {
473
+ return segments();
474
+ },
475
+ children: (segment) => (() => {
476
+ var _el$17 = _$createElement("text");
477
+ _$setProp(_el$17, "wrapMode", "none");
478
+ _$insert(_el$17, () => segment().text);
479
+ _$effect((_p$) => {
480
+ var _v$5 = context.theme[segment().tone], _v$6 = segment().text ? undefined : 0;
481
+ _v$5 !== _p$.e && (_p$.e = _$setProp(_el$17, "fg", _v$5, _p$.e));
482
+ _v$6 !== _p$.t && (_p$.t = _$setProp(_el$17, "width", _v$6, _p$.t));
483
+ return _p$;
484
+ }, {
485
+ e: undefined,
486
+ t: undefined
487
+ });
488
+ return _el$17;
489
+ })()
490
+ });
491
+ }
492
+ }), (() => {
493
+ var _el$10 = _$createElement("text");
494
+ _$setProp(_el$10, "wrapMode", "none");
495
+ _$insert(_el$10, figure);
496
+ _$effect((_$p) => _$setProp(_el$10, "fg", context.theme[usageTone(used(), context.appearance)], _$p));
497
+ return _el$10;
498
+ })()];
499
+ }
500
+ });
501
+ }
502
+ }), null);
503
+ _$insert(_el$9, _$createComponent(Show, {
504
+ get when() {
505
+ return _$memo(() => !!(hasReading() && props.showReset))() && !props.part.resetSinceReading;
506
+ },
507
+ get children() {
508
+ var _el$11 = _$createElement("box");
509
+ _$setProp(_el$11, "flexShrink", 0);
510
+ _$setProp(_el$11, "flexDirection", "row");
511
+ _$setProp(_el$11, "justifyContent", "flex-end");
512
+ _$insert(_el$11, _$createComponent(Show, {
513
+ get when() {
514
+ return props.part.resetIn;
515
+ },
516
+ get children() {
517
+ var _el$12 = _$createElement("text");
518
+ _$setProp(_el$12, "wrapMode", "none");
519
+ _$insert(_el$12, () => props.part.resetIn);
520
+ _$effect((_$p) => _$setProp(_el$12, "fg", context.theme.textMuted, _$p));
521
+ return _el$12;
522
+ }
523
+ }));
524
+ _$effect((_$p) => _$setProp(_el$11, "width", props.resetWidth, _$p));
525
+ return _el$11;
526
+ }
527
+ }), null);
528
+ _$effect((_$p) => _$setProp(_el$0, "flexShrink", props.part.resetSinceReading ? 1 : 0, _$p));
529
+ return _el$9;
530
+ })(), _$createComponent(Show, {
531
+ get when() {
532
+ return _$memo(() => !!(hasReading() && !props.part.resetSinceReading))() && paceLine();
533
+ },
534
+ keyed: true,
535
+ children: (line) => (() => {
536
+ var _el$18 = _$createElement("box"), _el$20 = _$createElement("text");
537
+ _$insertNode(_el$18, _el$20);
538
+ _$setProp(_el$18, "width", "100%");
539
+ _$setProp(_el$18, "flexDirection", "row");
540
+ _$insert(_el$18, _$createComponent(Show, {
541
+ get when() {
542
+ return props.labelWidth > 0;
543
+ },
544
+ get children() {
545
+ var _el$19 = _$createElement("text");
546
+ _$insert(_el$19, () => "".padEnd(props.labelWidth));
547
+ _$effect((_$p) => _$setProp(_el$19, "fg", context.theme.textMuted, _$p));
548
+ return _el$19;
549
+ }
550
+ }), _el$20);
551
+ _$setProp(_el$20, "wrapMode", "none");
552
+ _$insert(_el$20, line);
553
+ _$effect((_$p) => _$setProp(_el$20, "fg", context.theme[props.pace?.tone ?? "textMuted"], _$p));
554
+ return _el$18;
555
+ })()
556
+ })];
557
+ }
558
+ function CollapsedAccountRow(props) {
559
+ const context = frameContext();
560
+ const [width, setWidth] = createSignal(0);
561
+ let row;
562
+ const hasQuota = () => quotaWindowParts(props.account.quota, {
563
+ now: context.now
564
+ }).windows.some((part) => part.reading === "known");
565
+ const text = () => hasQuota() ? formatQuota(props.account.quota, {
566
+ now: context.now,
567
+ form: "narrow"
568
+ }) : props.account.emptyQuotaText?.collapsed ?? "\u2014";
569
+ const showQuota = () => width() <= 0 || displayWidth(text()) + 4 <= width();
570
+ const label = () => {
571
+ if (width() <= 0)
572
+ return props.account.label;
573
+ return fitText(props.account.label, width() - (showQuota() ? displayWidth(text()) + 3 : 2));
574
+ };
575
+ const muted = () => props.account.collapsed?.muted ?? false;
576
+ const quotaTone = () => muted() ? "textMuted" : props.account.collapsed?.quotaTone ?? "success";
577
+ return (() => {
578
+ var _el$21 = _$createElement("box"), _el$23 = _$createElement("box"), _el$26 = _$createElement("text");
579
+ _$insertNode(_el$21, _el$23);
580
+ _$use((element) => {
581
+ row = element;
582
+ }, _el$21);
583
+ _$setProp(_el$21, "onSizeChange", () => setWidth(row?.width ?? 0));
584
+ _$setProp(_el$21, "width", "100%");
585
+ _$setProp(_el$21, "flexDirection", "row");
586
+ _$setProp(_el$21, "justifyContent", "space-between");
587
+ _$insert(_el$21, _$createComponent(Show, {
588
+ get when() {
589
+ return label();
590
+ },
591
+ get children() {
592
+ var _el$22 = _$createElement("text");
593
+ _$setProp(_el$22, "wrapMode", "none");
594
+ _$setProp(_el$22, "flexShrink", 1);
595
+ _$insert(_el$22, label);
596
+ _$effect((_$p) => _$setProp(_el$22, "fg", context.theme[muted() ? "textMuted" : "text"], _$p));
597
+ return _el$22;
598
+ }
599
+ }), _el$23);
600
+ _$insertNode(_el$23, _el$26);
601
+ _$setProp(_el$23, "flexDirection", "row");
602
+ _$setProp(_el$23, "flexShrink", 0);
603
+ _$insert(_el$23, _$createComponent(Show, {
604
+ get when() {
605
+ return showQuota();
606
+ },
607
+ get children() {
608
+ return _$createComponent(Show, {
609
+ get when() {
610
+ return _$memo(() => !!hasQuota())() && !muted();
611
+ },
612
+ get fallback() {
613
+ return (() => {
614
+ var _el$27 = _$createElement("text");
615
+ _$insert(_el$27, text);
616
+ _$effect((_$p) => _$setProp(_el$27, "fg", context.theme.textMuted, _$p));
617
+ return _el$27;
618
+ })();
619
+ },
620
+ get children() {
621
+ var _el$24 = _$createElement("text"), _el$25 = _$createElement("b");
622
+ _$insertNode(_el$24, _el$25);
623
+ _$insert(_el$25, text);
624
+ _$effect((_$p) => _$setProp(_el$24, "fg", context.theme[quotaTone()], _$p));
625
+ return _el$24;
626
+ }
627
+ });
628
+ }
629
+ }), _el$26);
630
+ _$insert(_el$26, () => showQuota() ? " " : "", null);
631
+ _$insert(_el$26, () => props.account.blocked ? "\u2298" : "\u25CF", null);
632
+ _$effect((_p$) => {
633
+ var _v$7 = label() ? 1 : 0, _v$8 = context.theme[props.account.indicatorTone];
634
+ _v$7 !== _p$.e && (_p$.e = _$setProp(_el$21, "columnGap", _v$7, _p$.e));
635
+ _v$8 !== _p$.t && (_p$.t = _$setProp(_el$26, "fg", _v$8, _p$.t));
636
+ return _p$;
637
+ }, {
638
+ e: undefined,
639
+ t: undefined
640
+ });
641
+ return _el$21;
642
+ })();
643
+ }
644
+ function AccountBlock(props) {
645
+ const context = frameContext();
646
+ const [columns, setColumns] = createSignal(0);
647
+ let block;
648
+ const rows = () => props.account.groups.flatMap((group) => group.rows);
649
+ const labelWidth = () => Math.max(0, ...rows().map(({
650
+ part
651
+ }) => part.name ? Math.max(3, displayWidth(part.name) + 1) : 0));
652
+ const resetWidth = () => Math.max(0, ...rows().map(({
653
+ part
654
+ }) => part.reading === "unknown" || part.resetSinceReading ? 0 : displayWidth(part.resetIn ?? "")));
655
+ const figureWidth = createMemo(() => Math.max(10, ...rows().filter(({
656
+ part
657
+ }) => part.reading === "known" && !part.resetSinceReading).map(({
658
+ part
659
+ }) => displayWidth(` ${part.kind === "budget" && part.figure.startsWith(`${part.name} `) ? part.figure.slice(part.name.length + 1) : part.figure}`))));
660
+ const fit = (rowLabelWidth) => {
661
+ const desired = context.appearance.barWidth;
662
+ const minimum = Math.min(4, desired);
663
+ if (columns() <= 0)
664
+ return {
665
+ barCells: desired,
666
+ showReset: resetWidth() > 0
667
+ };
668
+ const room = columns() - rowLabelWidth - figureWidth();
669
+ const withReset = room - resetWidth() - 1;
670
+ const showReset = resetWidth() > 0 && withReset >= minimum;
671
+ const available = showReset ? withReset : room;
672
+ return {
673
+ barCells: available >= minimum ? Math.min(desired, available) : 0,
674
+ showReset
675
+ };
676
+ };
677
+ const label = () => {
678
+ const full = `${props.account.label}${props.account.titleSuffix ? ` \xB7 ${props.account.titleSuffix}` : ""}`;
679
+ return columns() <= 0 ? full : fitText(full, columns() - displayWidth(props.account.status.text) - 1);
680
+ };
681
+ const age = () => quotaWindowParts(props.account.quota, {
682
+ now: context.now
683
+ }).age;
684
+ const hasRows = () => props.account.groups.some((group) => group.rows.length > 0);
685
+ return (() => {
686
+ var _el$28 = _$createElement("box"), _el$29 = _$createElement("box"), _el$30 = _$createElement("text"), _el$31 = _$createElement("b"), _el$32 = _$createElement("text"), _el$33 = _$createElement("b");
687
+ _$insertNode(_el$28, _el$29);
688
+ _$use((element) => {
689
+ block = element;
690
+ }, _el$28);
691
+ _$setProp(_el$28, "onSizeChange", () => setColumns(block?.width ?? 0));
692
+ _$setProp(_el$28, "width", "100%");
693
+ _$setProp(_el$28, "flexDirection", "column");
694
+ _$insertNode(_el$29, _el$30);
695
+ _$insertNode(_el$29, _el$32);
696
+ _$setProp(_el$29, "width", "100%");
697
+ _$setProp(_el$29, "flexDirection", "row");
698
+ _$setProp(_el$29, "justifyContent", "space-between");
699
+ _$setProp(_el$29, "columnGap", 1);
700
+ _$insertNode(_el$30, _el$31);
701
+ _$setProp(_el$30, "wrapMode", "none");
702
+ _$setProp(_el$30, "flexShrink", 1);
703
+ _$insert(_el$31, label);
704
+ _$insertNode(_el$32, _el$33);
705
+ _$setProp(_el$32, "wrapMode", "none");
706
+ _$setProp(_el$32, "flexShrink", 0);
707
+ _$insert(_el$33, () => props.account.status.text);
708
+ _$insert(_el$28, () => context.beforeQuota?.(props.account), null);
709
+ _$insert(_el$28, _$createComponent(Show, {
710
+ get when() {
711
+ return hasRows();
712
+ },
713
+ get fallback() {
714
+ return _$createComponent(SidebarTextRow, {
715
+ get text() {
716
+ return props.account.emptyQuotaText?.expanded ?? "\u2014";
717
+ },
718
+ wrapMode: "none"
719
+ });
720
+ },
721
+ get children() {
722
+ return _$createComponent(For, {
723
+ get each() {
724
+ return props.account.groups;
725
+ },
726
+ children: (group) => [_$createComponent(Show, {
727
+ get when() {
728
+ return group.title;
729
+ },
730
+ get children() {
731
+ return _$createComponent(SidebarTextRow, {
732
+ get text() {
733
+ return group.title ?? "";
734
+ },
735
+ tone: "text",
736
+ wrapMode: "none"
737
+ });
738
+ }
739
+ }), _$createComponent(For, {
740
+ get each() {
741
+ return group.rows;
742
+ },
743
+ children: (row) => {
744
+ const rowLabelWidth = () => row.part.name ? labelWidth() : 0;
745
+ const rowFit = createMemo(() => fit(rowLabelWidth()));
746
+ return _$createComponent(QuotaRow, {
747
+ get part() {
748
+ return row.part;
749
+ },
750
+ get pace() {
751
+ return row.pace;
752
+ },
753
+ get labelWidth() {
754
+ return rowLabelWidth();
755
+ },
756
+ get barCells() {
757
+ return rowFit().barCells;
758
+ },
759
+ get resetWidth() {
760
+ return resetWidth();
761
+ },
762
+ get showReset() {
763
+ return rowFit().showReset;
764
+ }
765
+ });
766
+ }
767
+ })]
768
+ });
769
+ }
770
+ }), null);
771
+ _$insert(_el$28, _$createComponent(Show, {
772
+ get when() {
773
+ return age();
774
+ },
775
+ children: (text) => _$createComponent(SidebarTextRow, {
776
+ get text() {
777
+ return text();
778
+ },
779
+ wrapMode: "none"
780
+ })
781
+ }), null);
782
+ _$insert(_el$28, () => context.afterQuota?.(props.account), null);
783
+ _$effect((_p$) => {
784
+ var _v$9 = props.marginTop, _v$0 = context.theme.text, _v$1 = context.theme[props.account.status.tone];
785
+ _v$9 !== _p$.e && (_p$.e = _$setProp(_el$28, "marginTop", _v$9, _p$.e));
786
+ _v$0 !== _p$.t && (_p$.t = _$setProp(_el$30, "fg", _v$0, _p$.t));
787
+ _v$1 !== _p$.a && (_p$.a = _$setProp(_el$32, "fg", _v$1, _p$.a));
788
+ return _p$;
789
+ }, {
790
+ e: undefined,
791
+ t: undefined,
792
+ a: undefined
793
+ });
794
+ return _el$28;
795
+ })();
796
+ }
797
+ function SidebarFrame(props) {
798
+ const hasData = () => props.accounts.length > 0;
799
+ const headerLabel = () => !hasData() ? props.header.badge : `${props.collapsed ? "\u25B6" : "\u25BC"} ${props.header.badge}`;
800
+ const context = mergeProps(props, {
801
+ get theme() {
802
+ const theme = props.theme;
803
+ return {
804
+ ...theme,
805
+ textMuted: theme?.textMuted ?? theme?.text,
806
+ accent: theme?.accent ?? theme?.text,
807
+ success: theme?.success ?? theme?.text,
808
+ warning: theme?.warning ?? theme?.text,
809
+ error: theme?.error ?? theme?.text
810
+ };
811
+ }
812
+ });
813
+ const invertBadge = () => props.theme?.accent !== undefined && props.theme?.background !== undefined;
814
+ return _$createComponent(FrameContext.Provider, {
815
+ value: context,
816
+ get children() {
817
+ var _el$34 = _$createElement("box"), _el$35 = _$createElement("box"), _el$36 = _$createElement("box"), _el$37 = _$createElement("text"), _el$38 = _$createElement("b");
818
+ _$insertNode(_el$34, _el$35);
819
+ _$setProp(_el$34, "width", "100%");
820
+ _$setProp(_el$34, "flexDirection", "column");
821
+ _$insertNode(_el$35, _el$36);
822
+ _$setProp(_el$35, "width", "100%");
823
+ _$setProp(_el$35, "flexDirection", "row");
824
+ _$setProp(_el$35, "justifyContent", "space-between");
825
+ _$setProp(_el$35, "alignItems", "center");
826
+ _$setProp(_el$35, "onMouseDown", () => {
827
+ if (hasData())
828
+ props.onToggle();
829
+ });
830
+ _$insertNode(_el$36, _el$37);
831
+ _$setProp(_el$36, "paddingLeft", 1);
832
+ _$setProp(_el$36, "paddingRight", 1);
833
+ _$insertNode(_el$37, _el$38);
834
+ _$insert(_el$38, headerLabel);
835
+ _$insert(_el$35, _$createComponent(Show, {
836
+ get when() {
837
+ return props.header.version;
838
+ },
839
+ get children() {
840
+ var _el$39 = _$createElement("text");
841
+ _$insert(_el$39, () => props.header.version);
842
+ _$effect((_$p) => _$setProp(_el$39, "fg", context.theme.textMuted, _$p));
843
+ return _el$39;
844
+ }
845
+ }), null);
846
+ _$insert(_el$34, _$createComponent(Show, {
847
+ get when() {
848
+ return _$memo(() => !!props.collapsed)() && hasData();
849
+ },
850
+ get children() {
851
+ return [_$createComponent(For, {
852
+ get each() {
853
+ return props.accounts;
854
+ },
855
+ children: (account) => _$createComponent(CollapsedAccountRow, {
856
+ account
857
+ })
858
+ }), _$memo(() => props.collapsedSections?.())];
859
+ }
860
+ }), null);
861
+ _$insert(_el$34, _$createComponent(Show, {
862
+ get when() {
863
+ return !props.collapsed || !hasData();
864
+ },
865
+ get children() {
866
+ return [_$createComponent(Show, {
867
+ get when() {
868
+ return _$memo(() => !!props.showQuota)() && hasData();
869
+ },
870
+ get children() {
871
+ return _$createComponent(SidebarSection, {
872
+ title: "Quota",
873
+ get children() {
874
+ return _$createComponent(For, {
875
+ get each() {
876
+ return props.accounts;
877
+ },
878
+ children: (account, index) => _$createComponent(AccountBlock, {
879
+ account,
880
+ get marginTop() {
881
+ return index() === 0 ? 0 : 1;
882
+ }
883
+ })
884
+ });
885
+ }
886
+ });
887
+ }
888
+ }), _$memo(() => props.sections?.())];
889
+ }
890
+ }), null);
891
+ _$effect((_p$) => {
892
+ var _v$10 = invertBadge() ? props.theme?.accent : undefined, _v$11 = invertBadge() ? props.theme?.background : context.theme.accent;
893
+ _v$10 !== _p$.e && (_p$.e = _$setProp(_el$36, "backgroundColor", _v$10, _p$.e));
894
+ _v$11 !== _p$.t && (_p$.t = _$setProp(_el$37, "fg", _v$11, _p$.t));
895
+ return _p$;
896
+ }, {
897
+ e: undefined,
898
+ t: undefined
899
+ });
900
+ return _el$34;
901
+ }
902
+ });
903
+ }
904
+ export {
905
+ SidebarTextRow,
906
+ SidebarStatRow,
907
+ SidebarSection,
908
+ SidebarFrame
909
+ };