@runwisp/ui 0.15.0 → 0.15.1
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 +4 -4
- package/src/lib/components/DurationInput.svelte +1 -1
- package/src/lib/components/FormField.svelte +1 -1
- package/src/lib/components/Input.svelte +1 -1
- package/src/lib/components/dashboard/RunDetailPanel.svelte +31 -12
- package/src/lib/theme-tokens.css +0 -2
- package/src/lib/components/FeatureCard.svelte +0 -35
- package/src/lib/components/FeatureGrid.svelte +0 -37
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.15.
|
|
4
|
+
"version": "0.15.1",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@chromatic-com/storybook": "^5.2.1",
|
|
51
51
|
"@eslint/js": "^10.0.1",
|
|
52
|
-
"@runwisp/eslint-config": "0.15.
|
|
53
|
-
"@runwisp/typescript-config": "0.15.
|
|
52
|
+
"@runwisp/eslint-config": "0.15.1",
|
|
53
|
+
"@runwisp/typescript-config": "0.15.1",
|
|
54
54
|
"@storybook/addon-a11y": "^10.5.5",
|
|
55
55
|
"@storybook/addon-docs": "^10.5.5",
|
|
56
56
|
"@storybook/addon-svelte-csf": "^5.1.2",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"@fontsource-variable/geist-mono": "^5.3.0",
|
|
94
94
|
"@fontsource/tasa-orbiter": "^5.3.0",
|
|
95
95
|
"@lucide/svelte": "^1.28.0",
|
|
96
|
-
"@runwisp/common": "0.15.
|
|
96
|
+
"@runwisp/common": "0.15.1",
|
|
97
97
|
"@tanstack/svelte-virtual": "^3.13.35",
|
|
98
98
|
"ansi-to-html": "^0.7.2",
|
|
99
99
|
"cron-parser": "^5.7.0",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
import Tooltip from "../Tooltip.svelte";
|
|
31
31
|
import { portal } from "../../actions/portal.js";
|
|
32
32
|
import type { Run } from "./types.js";
|
|
33
|
-
import type
|
|
33
|
+
import { isLogEvent, type LogEvent, type LogSlice } from "../../log-console/types.js";
|
|
34
34
|
import { formatClockTime, formatCalendarDate } from "../../utils/format.js";
|
|
35
35
|
import { formatShortId } from "../../utils/id.js";
|
|
36
36
|
import { TickingNow } from "../../utils/ticking-now.svelte.js";
|
|
@@ -146,22 +146,41 @@
|
|
|
146
146
|
if (!stream) return;
|
|
147
147
|
|
|
148
148
|
let cleanup: (() => void) | undefined;
|
|
149
|
+
let cancelled = false;
|
|
149
150
|
|
|
150
151
|
untrack(() => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
152
|
+
void (async () => {
|
|
153
|
+
// Paint the tail in one batched page so the console opens
|
|
154
|
+
// already at the newest output, instead of replaying 1000
|
|
155
|
+
// backfill lines over SSE and visibly scrolling down to reach
|
|
156
|
+
// the end. The live stream then picks up after the seeded tail
|
|
157
|
+
// (its disk backfill from that anchor closes the fetch↔stream
|
|
158
|
+
// race, and the daemon dedupes anything already shown).
|
|
159
|
+
let fromLine = -TAIL_LINES;
|
|
160
|
+
try {
|
|
161
|
+
const seed = await fetchLogs(id, -TAIL_LINES, -1);
|
|
162
|
+
if (cancelled) return;
|
|
163
|
+
if (isLogEvent(seed)) {
|
|
164
|
+
if (logConsole) logConsole.onStream(seed);
|
|
165
|
+
if (seed.finished) return; // ended run: nothing live to follow
|
|
166
|
+
if (seed.sizeLines > 0) fromLine = seed.sizeLines;
|
|
167
|
+
}
|
|
168
|
+
} catch {
|
|
169
|
+
// Seed failed — fall back to the SSE tail backfill.
|
|
170
|
+
}
|
|
171
|
+
if (cancelled) return;
|
|
172
|
+
cleanup = stream(
|
|
173
|
+
id,
|
|
174
|
+
(event: LogEvent) => {
|
|
175
|
+
if (logConsole) logConsole.onStream(event);
|
|
176
|
+
},
|
|
177
|
+
{ fromLine },
|
|
178
|
+
);
|
|
179
|
+
})();
|
|
162
180
|
});
|
|
163
181
|
|
|
164
182
|
return () => {
|
|
183
|
+
cancelled = true;
|
|
165
184
|
if (cleanup) cleanup();
|
|
166
185
|
};
|
|
167
186
|
});
|
package/src/lib/theme-tokens.css
CHANGED
|
@@ -35,9 +35,7 @@
|
|
|
35
35
|
--rw-font-sans: "TASA Orbiter", system-ui, -apple-system, sans-serif;
|
|
36
36
|
--rw-font-mono:
|
|
37
37
|
"Geist Mono Variable", "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
38
|
-
}
|
|
39
38
|
|
|
40
|
-
:root {
|
|
41
39
|
/* Primary — Wisp Teal (brand = #0E7C86, the artifact's deep teal). Deeper
|
|
42
40
|
* and less cyan than Aurora (running/info) so the two stay distinct. */
|
|
43
41
|
--rw-color-wisp-50: oklch(0.97 0.02 205);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
-
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
-
|
|
4
|
-
<script lang="ts">
|
|
5
|
-
import type { Component, Snippet } from "svelte";
|
|
6
|
-
|
|
7
|
-
interface Props {
|
|
8
|
-
title: string;
|
|
9
|
-
icon?: Component;
|
|
10
|
-
children?: Snippet;
|
|
11
|
-
class?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let { title, icon: Icon, children, class: className = "" }: Props = $props();
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<article
|
|
18
|
-
class="overflow-hidden rounded-[4px] border border-outline bg-surface-raised p-6 hover:border-outline-hover {className}"
|
|
19
|
-
>
|
|
20
|
-
<div class="flex flex-col gap-3">
|
|
21
|
-
{#if Icon}
|
|
22
|
-
<span
|
|
23
|
-
class="inline-flex h-10 w-10 items-center justify-center rounded-[3px] border border-primary-soft-border bg-primary-soft text-primary-soft-text"
|
|
24
|
-
>
|
|
25
|
-
<Icon size={20} />
|
|
26
|
-
</span>
|
|
27
|
-
{/if}
|
|
28
|
-
<h3 class="font-mono text-base text-primary">{title}</h3>
|
|
29
|
-
{#if children}
|
|
30
|
-
<div class="font-sans text-sm leading-relaxed text-on-surface-muted">
|
|
31
|
-
{@render children()}
|
|
32
|
-
</div>
|
|
33
|
-
{/if}
|
|
34
|
-
</div>
|
|
35
|
-
</article>
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
-
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
-
|
|
4
|
-
<script lang="ts">
|
|
5
|
-
import type { Snippet } from "svelte";
|
|
6
|
-
|
|
7
|
-
interface Props {
|
|
8
|
-
columns?: 1 | 2 | 3 | 4;
|
|
9
|
-
gap?: "sm" | "md" | "lg";
|
|
10
|
-
children?: Snippet;
|
|
11
|
-
class?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let { columns = 3, gap = "md", children, class: className = "" }: Props = $props();
|
|
15
|
-
|
|
16
|
-
const colClasses: Record<1 | 2 | 3 | 4, string> = {
|
|
17
|
-
1: "grid-cols-1",
|
|
18
|
-
2: "grid-cols-1 sm:grid-cols-2",
|
|
19
|
-
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
20
|
-
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const gapClasses: Record<"sm" | "md" | "lg", string> = {
|
|
24
|
-
sm: "gap-3",
|
|
25
|
-
md: "gap-4",
|
|
26
|
-
lg: "gap-6",
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const colClass = $derived(colClasses[columns]);
|
|
30
|
-
const gapClass = $derived(gapClasses[gap]);
|
|
31
|
-
</script>
|
|
32
|
-
|
|
33
|
-
<div class="grid {colClass} {gapClass} {className}">
|
|
34
|
-
{#if children}
|
|
35
|
-
{@render children()}
|
|
36
|
-
{/if}
|
|
37
|
-
</div>
|