taskchef 7.23.3 → 7.23.4
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/.codex-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/src/dashboard/app.js +2 -82
- package/src/dashboard/styles.css +16 -3
package/package.json
CHANGED
package/src/dashboard/app.js
CHANGED
|
@@ -440,82 +440,8 @@ function usageBreakdownText(usage) {
|
|
|
440
440
|
].join(" · ");
|
|
441
441
|
}
|
|
442
442
|
|
|
443
|
-
const SHIMMER_STEP_MS = 420;
|
|
444
|
-
const SHIMMER_PAUSE_MS = 1_800;
|
|
445
|
-
const SHIMMER_PULSE_MS = 420;
|
|
446
|
-
const SHIMMER_ANIMATION_ID = "taskchef-text-shimmer";
|
|
447
|
-
const shimmerMotionQuery = globalThis.matchMedia?.("(prefers-reduced-motion: reduce)") ?? null;
|
|
448
|
-
const shimmerRecords = new Set();
|
|
449
|
-
|
|
450
|
-
function animateShimmerRecord(record, reducedMotion) {
|
|
451
|
-
for (const animation of record.animations) animation.cancel();
|
|
452
|
-
record.animations = [];
|
|
453
|
-
if (reducedMotion) return;
|
|
454
|
-
for (const [shimmerIndex, glyph] of record.glyphs.entries()) {
|
|
455
|
-
if (typeof glyph.animate !== "function") continue;
|
|
456
|
-
const pulseEnd = SHIMMER_PULSE_MS / record.cycleMs;
|
|
457
|
-
const animation = glyph.animate([
|
|
458
|
-
{ color: "var(--muted)", textShadow: "none", offset: 0 },
|
|
459
|
-
{
|
|
460
|
-
color: "var(--text)",
|
|
461
|
-
textShadow: "0 0 0.28em color-mix(in srgb, var(--text) 22%, transparent)",
|
|
462
|
-
offset: pulseEnd / 2,
|
|
463
|
-
},
|
|
464
|
-
{ color: "var(--muted)", textShadow: "none", offset: pulseEnd },
|
|
465
|
-
{ color: "var(--muted)", textShadow: "none", offset: 1 },
|
|
466
|
-
], {
|
|
467
|
-
delay: shimmerIndex * SHIMMER_STEP_MS,
|
|
468
|
-
duration: record.cycleMs,
|
|
469
|
-
easing: "linear",
|
|
470
|
-
iterations: Infinity,
|
|
471
|
-
});
|
|
472
|
-
animation.id = SHIMMER_ANIMATION_ID;
|
|
473
|
-
record.animations.push(animation);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
shimmerMotionQuery?.addEventListener?.("change", ({ matches }) => {
|
|
478
|
-
for (const record of shimmerRecords) animateShimmerRecord(record, matches);
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
export function cancelTextShimmers(root) {
|
|
482
|
-
for (const record of shimmerRecords) {
|
|
483
|
-
if (root !== record.element && !root?.contains?.(record.element)) continue;
|
|
484
|
-
for (const animation of record.animations) animation.cancel();
|
|
485
|
-
shimmerRecords.delete(record);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
443
|
export function renderTextShimmer(element, value) {
|
|
490
|
-
|
|
491
|
-
const characters = Array.from(text);
|
|
492
|
-
const highlightedCharacters = characters.filter((character) => !/\s/u.test(character));
|
|
493
|
-
const cycleMs = Math.max(
|
|
494
|
-
SHIMMER_PULSE_MS + SHIMMER_PAUSE_MS,
|
|
495
|
-
(highlightedCharacters.length - 1) * SHIMMER_STEP_MS
|
|
496
|
-
+ SHIMMER_PULSE_MS
|
|
497
|
-
+ SHIMMER_PAUSE_MS,
|
|
498
|
-
);
|
|
499
|
-
const glyphs = [];
|
|
500
|
-
const nodes = characters.map((character) => {
|
|
501
|
-
if (/\s/u.test(character)) return document.createTextNode(character);
|
|
502
|
-
const glyph = document.createElement("span");
|
|
503
|
-
glyph.className = "text-shimmer-glyph";
|
|
504
|
-
glyph.textContent = character;
|
|
505
|
-
glyphs.push(glyph);
|
|
506
|
-
return glyph;
|
|
507
|
-
});
|
|
508
|
-
const accessibleText = document.createElement("span");
|
|
509
|
-
accessibleText.className = "visually-hidden";
|
|
510
|
-
accessibleText.textContent = text;
|
|
511
|
-
const animatedText = document.createElement("span");
|
|
512
|
-
animatedText.className = "text-shimmer-visual";
|
|
513
|
-
animatedText.setAttribute("aria-hidden", "true");
|
|
514
|
-
animatedText.append(...nodes);
|
|
515
|
-
element.replaceChildren(accessibleText, animatedText);
|
|
516
|
-
const record = { animations: [], cycleMs, element, glyphs };
|
|
517
|
-
shimmerRecords.add(record);
|
|
518
|
-
animateShimmerRecord(record, shimmerMotionQuery?.matches ?? false);
|
|
444
|
+
element.textContent = String(value ?? "");
|
|
519
445
|
return element;
|
|
520
446
|
}
|
|
521
447
|
|
|
@@ -851,7 +777,6 @@ function renderDialog(task, { highlightTurnRef = null } = {}) {
|
|
|
851
777
|
(task.relatedGitHubLinks?.length ?? 0) === 0 && !task.relatedGitHubLinksTruncated
|
|
852
778
|
);
|
|
853
779
|
const timeline = turnTimeline(detailedTask, { highlightTurnRef });
|
|
854
|
-
cancelTextShimmers(elements.dialogResults);
|
|
855
780
|
elements.dialogResults.replaceChildren(...timeline);
|
|
856
781
|
const highlightedTurn = timeline.find((item) => item.dataset.turnRef === highlightTurnRef) ?? null;
|
|
857
782
|
const replacedFocusedTurn = timeline.find((item) => item.dataset.turnRef === focusedTurnRef) ?? null;
|
|
@@ -891,7 +816,6 @@ function renderDialog(task, { highlightTurnRef = null } = {}) {
|
|
|
891
816
|
? "calculating"
|
|
892
817
|
: "unavailable",
|
|
893
818
|
};
|
|
894
|
-
cancelTextShimmers(elements.dialogUsage);
|
|
895
819
|
elements.dialogUsage.replaceChildren(usagePresentation(
|
|
896
820
|
taskUsage,
|
|
897
821
|
{ wholeTask: true },
|
|
@@ -1074,9 +998,7 @@ function render() {
|
|
|
1074
998
|
const value = label.dataset.statusLabel;
|
|
1075
999
|
label.textContent = statusFilterText(value, counts[value]);
|
|
1076
1000
|
}
|
|
1077
|
-
|
|
1078
|
-
cancelTextShimmers(elements.taskList);
|
|
1079
|
-
elements.taskList.replaceChildren(...cards);
|
|
1001
|
+
elements.taskList.replaceChildren(...visible.map(taskCard));
|
|
1080
1002
|
elements.emptyState.hidden = visible.length > 0;
|
|
1081
1003
|
elements.taskCount.textContent = `${visible.length} of ${state.tasks.length} task${state.tasks.length === 1 ? "" : "s"}`;
|
|
1082
1004
|
clearTimeout(dateRefreshTimer);
|
|
@@ -1181,8 +1103,6 @@ elements.dialog.addEventListener("cancel", (event) => {
|
|
|
1181
1103
|
if (!manualTransitionPending()) resetManualTransition({ focus: true });
|
|
1182
1104
|
});
|
|
1183
1105
|
elements.dialog.addEventListener("close", () => {
|
|
1184
|
-
cancelTextShimmers(elements.dialogResults);
|
|
1185
|
-
cancelTextShimmers(elements.dialogUsage);
|
|
1186
1106
|
if (!manualTransitionPending()) state.manualTransition = null;
|
|
1187
1107
|
state.detailNavigation = null;
|
|
1188
1108
|
renderNotifications();
|
package/src/dashboard/styles.css
CHANGED
|
@@ -185,12 +185,25 @@ dialog section + section { margin-top: 24px; }
|
|
|
185
185
|
.usage-pending, .usage-calculating { display: flex; align-items: center; }
|
|
186
186
|
.text-shimmer {
|
|
187
187
|
color: var(--muted);
|
|
188
|
+
display: inline-block;
|
|
189
|
+
width: fit-content;
|
|
190
|
+
max-width: 100%;
|
|
191
|
+
justify-self: start;
|
|
192
|
+
vertical-align: top;
|
|
193
|
+
background: linear-gradient(100deg, var(--muted) 48%, var(--text) 50%, var(--muted) 52%);
|
|
194
|
+
background-size: 250% 100%;
|
|
195
|
+
background-position: 100% 0;
|
|
196
|
+
background-clip: text;
|
|
197
|
+
-webkit-background-clip: text;
|
|
198
|
+
-webkit-text-fill-color: transparent;
|
|
199
|
+
animation: text-shimmer-sweep 6.4s linear infinite;
|
|
188
200
|
}
|
|
189
|
-
|
|
190
|
-
|
|
201
|
+
@keyframes text-shimmer-sweep {
|
|
202
|
+
0% { background-position: 100% 0; }
|
|
203
|
+
72%, 100% { background-position: -100% 0; }
|
|
191
204
|
}
|
|
192
205
|
@media (prefers-reduced-motion: reduce) {
|
|
193
|
-
.text-shimmer
|
|
206
|
+
.text-shimmer { background: none; animation: none; -webkit-text-fill-color: currentcolor; }
|
|
194
207
|
}
|
|
195
208
|
pre { max-height: 280px; margin: 0; padding: 14px; overflow: auto; border-radius: 7px; background: var(--surface-muted); white-space: pre-wrap; overflow-wrap: anywhere; font: 0.86rem/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
196
209
|
.metadata { display: grid; grid-template-columns: minmax(100px, 150px) 1fr; margin: 0; font-size: 0.88rem; }
|