@runwisp/ui 0.6.0 → 0.7.0
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runwisp/ui",
|
|
3
3
|
"description": "Svelte 5 UI component library for RunWisp dashboards and admin interfaces.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"@chromatic-com/storybook": "^4.1.3",
|
|
59
59
|
"@eslint/compat": "^1.4.0",
|
|
60
60
|
"@eslint/js": "^9.39.1",
|
|
61
|
-
"@runwisp/eslint-config": "0.
|
|
62
|
-
"@runwisp/typescript-config": "0.
|
|
61
|
+
"@runwisp/eslint-config": "0.7.0",
|
|
62
|
+
"@runwisp/typescript-config": "0.7.0",
|
|
63
63
|
"@storybook/addon-a11y": "^10.1.9",
|
|
64
64
|
"@storybook/addon-docs": "^10.1.9",
|
|
65
65
|
"@storybook/addon-svelte-csf": "^5.0.10",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"@floating-ui/dom": "^1.7.4",
|
|
108
108
|
"@fontsource/tasa-orbiter": "^5.2.2",
|
|
109
109
|
"@lucide/svelte": "^0.561.0",
|
|
110
|
-
"@runwisp/common": "0.
|
|
110
|
+
"@runwisp/common": "0.7.0",
|
|
111
111
|
"@tanstack/svelte-virtual": "^3.13.25",
|
|
112
112
|
"ansi-to-html": "^0.7.2",
|
|
113
113
|
"cron-parser": "^5.4.0",
|
|
@@ -21,9 +21,23 @@
|
|
|
21
21
|
chunkSize?: number;
|
|
22
22
|
lineHeight?: number;
|
|
23
23
|
class?: string;
|
|
24
|
+
// highlightLine, when set, scrolls the console so the given absolute
|
|
25
|
+
// line number is visible and pulses a short-lived flash on that row.
|
|
26
|
+
// The pulse is one-shot: changing the prop to a new line restarts the
|
|
27
|
+
// animation; setting it to null clears immediately.
|
|
28
|
+
highlightLine?: number | null;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
let {
|
|
31
|
+
let {
|
|
32
|
+
fetchLogs,
|
|
33
|
+
chunkSize = 4096,
|
|
34
|
+
lineHeight = 20,
|
|
35
|
+
class: className = "",
|
|
36
|
+
highlightLine = null,
|
|
37
|
+
}: Props = $props();
|
|
38
|
+
|
|
39
|
+
let flashLine = $state<number | null>(null);
|
|
40
|
+
let flashTimer: ReturnType<typeof setTimeout> | null = null;
|
|
27
41
|
|
|
28
42
|
const cache = new LogCache();
|
|
29
43
|
let fetcher: LogFetcher | null = $state(null);
|
|
@@ -202,6 +216,30 @@
|
|
|
202
216
|
scrollTop = 0;
|
|
203
217
|
}
|
|
204
218
|
|
|
219
|
+
// Search-hit deep-link: when highlightLine flips to a non-null number,
|
|
220
|
+
// scroll the viewport so that line is centred, and pulse a one-shot
|
|
221
|
+
// flash class for ~1.5s. Cleaning up the timer on prop change keeps a
|
|
222
|
+
// rapid sequence of jumps from leaking timers.
|
|
223
|
+
$effect(() => {
|
|
224
|
+
const target = highlightLine;
|
|
225
|
+
if (target === null || target === undefined) {
|
|
226
|
+
flashLine = null;
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (!containerEl) return;
|
|
230
|
+
const targetY = lineTop(target) - containerHeight / 2 + lineHeight / 2;
|
|
231
|
+
const clamped = Math.max(0, Math.min(targetY, totalHeight - containerHeight));
|
|
232
|
+
containerEl.scrollTo({ top: clamped, behavior: "smooth" });
|
|
233
|
+
isAutoScroll = false;
|
|
234
|
+
userScrolledUp = true;
|
|
235
|
+
flashLine = target;
|
|
236
|
+
if (flashTimer !== null) clearTimeout(flashTimer);
|
|
237
|
+
flashTimer = setTimeout(() => {
|
|
238
|
+
flashLine = null;
|
|
239
|
+
flashTimer = null;
|
|
240
|
+
}, 1500);
|
|
241
|
+
});
|
|
242
|
+
|
|
205
243
|
$effect(() => {
|
|
206
244
|
if (!containerEl) return;
|
|
207
245
|
containerHeight = containerEl.clientHeight;
|
|
@@ -242,7 +280,10 @@
|
|
|
242
280
|
|
|
243
281
|
{#each renderedLines as line (line.num)}
|
|
244
282
|
<div
|
|
245
|
-
class="log-line absolute right-0 left-0 flex items-center hover:bg-slate-900/50
|
|
283
|
+
class="log-line absolute right-0 left-0 flex items-center hover:bg-slate-900/50 {flashLine ===
|
|
284
|
+
line.num
|
|
285
|
+
? 'log-line--flash'
|
|
286
|
+
: ''}"
|
|
246
287
|
style="top: {lineTop(line.num)}px; height: {lineHeight}px;"
|
|
247
288
|
>
|
|
248
289
|
<div
|
|
@@ -376,6 +417,19 @@
|
|
|
376
417
|
--log-line-height: 20px;
|
|
377
418
|
}
|
|
378
419
|
|
|
420
|
+
.log-line--flash {
|
|
421
|
+
animation: log-line-flash 1.5s ease-out;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
@keyframes log-line-flash {
|
|
425
|
+
0% {
|
|
426
|
+
background-color: rgba(251, 191, 36, 0.45);
|
|
427
|
+
}
|
|
428
|
+
100% {
|
|
429
|
+
background-color: transparent;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
379
433
|
.dot {
|
|
380
434
|
display: inline-block;
|
|
381
435
|
width: 4px;
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
streamLogs,
|
|
29
29
|
showTaskName = false,
|
|
30
30
|
onDelete,
|
|
31
|
+
highlightLine = null,
|
|
31
32
|
}: {
|
|
32
33
|
run: Run | undefined;
|
|
33
34
|
fetchLogs: (
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
) => () => void;
|
|
43
44
|
showTaskName?: boolean;
|
|
44
45
|
onDelete?: (runId: string) => void;
|
|
46
|
+
highlightLine?: number | null;
|
|
45
47
|
} = $props();
|
|
46
48
|
|
|
47
49
|
let canDelete = $derived.by(() => {
|
|
@@ -265,6 +267,7 @@
|
|
|
265
267
|
bind:this={logConsole}
|
|
266
268
|
fetchLogs={(f: number, t: number) => fetchLogs(run.id, f, t)}
|
|
267
269
|
class="min-h-0 flex-1"
|
|
270
|
+
{highlightLine}
|
|
268
271
|
/>
|
|
269
272
|
{/key}
|
|
270
273
|
</div>
|