@runwisp/ui 0.13.0 → 0.15.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 +39 -47
- package/src/astro/CTABand.astro +19 -12
- package/src/astro/Hero.astro +3 -3
- package/src/astro/SiteFooter.astro +4 -4
- package/src/astro/SiteHeader.astro +4 -4
- package/src/lib/actions/portal.ts +0 -3
- package/src/lib/assets/runwisp-logo.svg +1 -8
- package/src/lib/components/AccordionItem.svelte +4 -10
- package/src/lib/components/Alert.svelte +11 -11
- package/src/lib/components/Avatar.svelte +1 -1
- package/src/lib/components/Badge.svelte +13 -13
- package/src/lib/components/Breadcrumb.svelte +3 -3
- package/src/lib/components/Button.svelte +2 -2
- package/src/lib/components/Card.svelte +4 -4
- package/src/lib/components/Checkbox.svelte +12 -10
- package/src/lib/components/CodeBlock.svelte +7 -13
- package/src/lib/components/CronInput.svelte +12 -15
- package/src/lib/components/DataGrid.svelte +14 -13
- package/src/lib/components/Drawer.svelte +9 -9
- package/src/lib/components/Dropdown.svelte +12 -20
- package/src/lib/components/DurationInput.svelte +10 -14
- package/src/lib/components/EmptyState.svelte +1 -1
- package/src/lib/components/ErrorState.svelte +4 -4
- package/src/lib/components/FeatureCard.svelte +4 -4
- package/src/lib/components/FormField.svelte +4 -6
- package/src/lib/components/Heading.svelte +4 -1
- package/src/lib/components/Input.svelte +10 -12
- package/src/lib/components/Kbd.svelte +1 -1
- package/src/lib/components/Link.svelte +2 -3
- package/src/lib/components/LinkButton.svelte +2 -2
- package/src/lib/components/LogConsole.svelte +22 -21
- package/src/lib/components/Logo.svelte +3 -1
- package/src/lib/components/Modal.svelte +9 -11
- package/src/lib/components/PageContainer.svelte +1 -1
- package/src/lib/components/PageHeader.svelte +1 -1
- package/src/lib/components/Pagination.svelte +4 -4
- package/src/lib/components/Popover.svelte +5 -7
- package/src/lib/components/Progress.svelte +6 -4
- package/src/lib/components/Prose.svelte +4 -4
- package/src/lib/components/Radio.svelte +11 -10
- package/src/lib/components/RadioGroup.svelte +3 -5
- package/src/lib/components/Select.svelte +23 -36
- package/src/lib/components/Separator.svelte +4 -1
- package/src/lib/components/Skeleton.svelte +6 -6
- package/src/lib/components/StatusIndicator.svelte +7 -18
- package/src/lib/components/Table.svelte +1 -1
- package/src/lib/components/TableCell.svelte +1 -1
- package/src/lib/components/TableRow.svelte +1 -5
- package/src/lib/components/Tabs.svelte +10 -13
- package/src/lib/components/TaskCard.svelte +7 -4
- package/src/lib/components/Textarea.svelte +10 -11
- package/src/lib/components/ThemeToggle.svelte +1 -1
- package/src/lib/components/ToastContainer.svelte +3 -8
- package/src/lib/components/Toggle.svelte +2 -3
- package/src/lib/components/Tooltip.svelte +12 -10
- package/src/lib/components/button-styles.ts +17 -18
- package/src/lib/components/dashboard/RunDetailPanel.svelte +160 -249
- package/src/lib/components/dashboard/RunFilterPopover.svelte +31 -25
- package/src/lib/components/dashboard/RunsList.svelte +55 -50
- package/src/lib/components/dashboard/run-filters.test.ts +31 -33
- package/src/lib/components/dashboard/run-filters.ts +33 -33
- package/src/lib/components/dashboard/run-helpers.test.ts +42 -17
- package/src/lib/components/dashboard/run-helpers.ts +53 -17
- package/src/lib/components/dashboard/status-config.ts +9 -8
- package/src/lib/theme-tokens.css +179 -114
- package/src/lib/theme.css +49 -35
- package/src/lib/utils/error.ts +0 -3
- package/src/lib/utils/format.test.ts +2 -6
- package/src/lib/utils/format.ts +28 -3
|
@@ -42,7 +42,6 @@
|
|
|
42
42
|
// but we want to catch it to show "Invalid cron expression".
|
|
43
43
|
const text = cronstrue.toString(value, { throwExceptionOnParseError: true });
|
|
44
44
|
|
|
45
|
-
// Calculate next run
|
|
46
45
|
let next: Date | undefined;
|
|
47
46
|
try {
|
|
48
47
|
const interval = CronExpressionParser.parse(value);
|
|
@@ -57,16 +56,15 @@
|
|
|
57
56
|
}
|
|
58
57
|
});
|
|
59
58
|
|
|
60
|
-
// Determine state for styling
|
|
61
59
|
let isError = $derived(!disabled && value && value.trim() !== "" && !explanation.isValid);
|
|
62
60
|
</script>
|
|
63
61
|
|
|
64
62
|
<div class="space-y-2">
|
|
65
63
|
<div class="flex items-center justify-between">
|
|
66
|
-
<div class="text-
|
|
64
|
+
<div class="font-mono text-xs font-medium text-on-surface-muted">Cron Schedule</div>
|
|
67
65
|
<button
|
|
68
66
|
type="button"
|
|
69
|
-
class="flex items-center gap-1 text-xs text-primary hover:text-primary-hover"
|
|
67
|
+
class="flex items-center gap-1 font-mono text-xs text-primary hover:text-primary-hover"
|
|
70
68
|
onclick={() => (examplesModalOpen = true)}
|
|
71
69
|
>
|
|
72
70
|
Examples <Info size={12} />
|
|
@@ -74,32 +72,31 @@
|
|
|
74
72
|
</div>
|
|
75
73
|
<div class="flex gap-4">
|
|
76
74
|
<div class="flex-1">
|
|
77
|
-
<!-- Pass connection-status-like classes effectively by using the component props or class -->
|
|
78
75
|
<Input
|
|
79
76
|
placeholder="* * * * *"
|
|
80
77
|
bind:value
|
|
81
78
|
{disabled}
|
|
82
|
-
class="font-mono {isError
|
|
83
|
-
? '!focus:border-danger-500 !focus:ring-danger-500 border-danger-300!'
|
|
84
|
-
: ''}"
|
|
79
|
+
class="font-mono {isError ? 'border-danger-surface!' : ''}"
|
|
85
80
|
/>
|
|
86
81
|
</div>
|
|
87
82
|
</div>
|
|
88
|
-
<!-- Live Feedback -->
|
|
89
83
|
<div
|
|
90
|
-
class="flex items-start gap-3 rounded-
|
|
91
|
-
|
|
84
|
+
class="flex items-start gap-3 rounded-[4px] border p-3 {isError
|
|
85
|
+
? 'border-danger-soft-border bg-danger-soft'
|
|
86
|
+
: 'border-outline bg-surface-sunken'}"
|
|
92
87
|
>
|
|
93
88
|
<Info size={18} class="mt-0.5 {isError ? 'text-danger-surface' : 'text-primary'}" />
|
|
94
89
|
<div>
|
|
95
90
|
<div
|
|
96
|
-
class="text-sm font-medium {isError
|
|
91
|
+
class="font-sans text-sm font-medium {isError
|
|
92
|
+
? 'text-danger-soft-text'
|
|
93
|
+
: 'text-on-surface'}"
|
|
97
94
|
>
|
|
98
95
|
{explanation.text}
|
|
99
96
|
</div>
|
|
100
97
|
{#if explanation.next}
|
|
101
|
-
<div class="mt-0.5 text-xs text-on-surface-muted">
|
|
102
|
-
Next run: <span class="font-medium text-on-surface"
|
|
98
|
+
<div class="mt-0.5 font-sans text-xs text-on-surface-muted">
|
|
99
|
+
Next run: <span class="font-mono font-medium text-on-surface"
|
|
103
100
|
>{explanation.next.toLocaleString()}</span
|
|
104
101
|
>
|
|
105
102
|
</div>
|
|
@@ -118,7 +115,7 @@
|
|
|
118
115
|
{#each cronExamples as example (example.cron)}
|
|
119
116
|
<button
|
|
120
117
|
type="button"
|
|
121
|
-
class="flex w-full items-center justify-between rounded-
|
|
118
|
+
class="flex w-full items-center justify-between rounded-[3px] px-3 py-2 text-left hover:bg-surface-sunken"
|
|
122
119
|
onclick={() => selectExample(example.cron)}
|
|
123
120
|
>
|
|
124
121
|
<code class="font-mono text-sm text-on-surface">{example.cron}</code>
|
|
@@ -55,8 +55,6 @@
|
|
|
55
55
|
import Pagination from "./Pagination.svelte";
|
|
56
56
|
import Fuse from "fuse.js";
|
|
57
57
|
|
|
58
|
-
import dlv from "dlv";
|
|
59
|
-
|
|
60
58
|
let {
|
|
61
59
|
columns,
|
|
62
60
|
data,
|
|
@@ -169,7 +167,7 @@
|
|
|
169
167
|
</script>
|
|
170
168
|
|
|
171
169
|
<div
|
|
172
|
-
class="relative flex flex-col rounded-
|
|
170
|
+
class="relative flex flex-col rounded-[4px] border border-outline bg-surface-raised shadow-sm {className}"
|
|
173
171
|
>
|
|
174
172
|
{#if filterable}
|
|
175
173
|
<div class="border-b border-outline p-3">
|
|
@@ -188,7 +186,7 @@
|
|
|
188
186
|
{/if}
|
|
189
187
|
|
|
190
188
|
<div
|
|
191
|
-
class="relative min-h-0 flex-1 rounded-
|
|
189
|
+
class="relative min-h-0 flex-1 rounded-[4px] {wrapperClass ??
|
|
192
190
|
(stickyHeader ? '' : 'overflow-x-auto')}"
|
|
193
191
|
>
|
|
194
192
|
{#if loading}
|
|
@@ -196,7 +194,7 @@
|
|
|
196
194
|
class="absolute inset-0 z-10 flex items-center justify-center bg-surface-raised/50 backdrop-blur-[1px]"
|
|
197
195
|
>
|
|
198
196
|
<div
|
|
199
|
-
class="flex items-center gap-3 rounded-full border border-outline
|
|
197
|
+
class="flex items-center gap-3 rounded-full border border-outline bg-surface-raised px-4 py-2 shadow-md"
|
|
200
198
|
>
|
|
201
199
|
<svg class="h-5 w-5 animate-spin text-primary" viewBox="0 0 24 24" fill="none">
|
|
202
200
|
<circle
|
|
@@ -213,7 +211,7 @@
|
|
|
213
211
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
214
212
|
></path>
|
|
215
213
|
</svg>
|
|
216
|
-
<span class="text-sm
|
|
214
|
+
<span class="font-mono text-sm text-on-surface-muted">Loading...</span>
|
|
217
215
|
</div>
|
|
218
216
|
</div>
|
|
219
217
|
{/if}
|
|
@@ -239,7 +237,7 @@
|
|
|
239
237
|
<th
|
|
240
238
|
class="
|
|
241
239
|
group px-4 {compact ? 'py-2' : 'py-3'}
|
|
242
|
-
font-
|
|
240
|
+
font-mono text-xs tracking-wide text-on-surface-faint uppercase
|
|
243
241
|
{column.align === 'center' ? 'text-center' : ''}
|
|
244
242
|
{column.align === 'right' ? 'text-right' : ''}
|
|
245
243
|
"
|
|
@@ -249,7 +247,7 @@
|
|
|
249
247
|
<button
|
|
250
248
|
onclick={() => handleSort(column.key as string)}
|
|
251
249
|
class="
|
|
252
|
-
inline-flex items-center gap-1
|
|
250
|
+
inline-flex items-center gap-1 group-hover:text-on-surface
|
|
253
251
|
{sortKey === column.key ? 'text-on-surface' : ''}
|
|
254
252
|
"
|
|
255
253
|
>
|
|
@@ -263,7 +261,7 @@
|
|
|
263
261
|
{:else}
|
|
264
262
|
<ArrowUpDown
|
|
265
263
|
size={14}
|
|
266
|
-
class="text-on-surface-faint opacity-0
|
|
264
|
+
class="text-on-surface-faint opacity-0 group-hover:opacity-100"
|
|
267
265
|
/>
|
|
268
266
|
{/if}
|
|
269
267
|
</button>
|
|
@@ -295,13 +293,12 @@
|
|
|
295
293
|
{#each pagedData as row, idx (idx)}
|
|
296
294
|
<tr
|
|
297
295
|
class="
|
|
298
|
-
border-b border-outline
|
|
296
|
+
border-b border-outline last:border-b-0
|
|
299
297
|
{striped && idx % 2 === 1 ? 'bg-surface-sunken/30' : ''}
|
|
300
298
|
{hoverable ? 'hover:bg-surface-sunken' : ''}
|
|
301
299
|
{isSelected(row) ? 'bg-primary-soft/30' : ''}
|
|
302
300
|
{onRowClick ? 'cursor-pointer' : ''}
|
|
303
|
-
|
|
304
|
-
"
|
|
301
|
+
"
|
|
305
302
|
onclick={() => onRowClick?.(row)}
|
|
306
303
|
>
|
|
307
304
|
{#if selectable}
|
|
@@ -329,7 +326,11 @@
|
|
|
329
326
|
{#if column.render}
|
|
330
327
|
{@render column.render(row)}
|
|
331
328
|
{:else}
|
|
332
|
-
|
|
329
|
+
<!-- Raw field value: a token, so mono. Snippet-rendered
|
|
330
|
+
cells choose their own voice. -->
|
|
331
|
+
<span class="font-mono"
|
|
332
|
+
>{row[column.key as keyof T] ?? "-"}</span
|
|
333
|
+
>
|
|
333
334
|
{/if}
|
|
334
335
|
</td>
|
|
335
336
|
{/each}
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
<div
|
|
101
101
|
class="
|
|
102
102
|
absolute z-10 flex flex-col
|
|
103
|
-
bg-surface-overlay shadow-
|
|
103
|
+
border border-outline bg-surface-overlay shadow-lg
|
|
104
104
|
{positionClasses[side]}
|
|
105
105
|
{className}
|
|
106
106
|
"
|
|
@@ -110,18 +110,20 @@
|
|
|
110
110
|
aria-labelledby={title ? "drawer-title" : undefined}
|
|
111
111
|
transition:fly={{ ...flyParams[side], duration: 250 }}
|
|
112
112
|
>
|
|
113
|
-
<!-- Header -->
|
|
114
113
|
{#if header}
|
|
115
|
-
<div class="border-b border-outline
|
|
114
|
+
<div class="border-b border-outline px-6 py-4">
|
|
116
115
|
{@render header()}
|
|
117
116
|
</div>
|
|
118
117
|
{:else if title || closable}
|
|
119
118
|
<div
|
|
120
|
-
class="flex items-start justify-between gap-4 border-b border-outline
|
|
119
|
+
class="flex items-start justify-between gap-4 border-b border-outline px-6 py-4"
|
|
121
120
|
>
|
|
122
121
|
<div>
|
|
123
122
|
{#if title}
|
|
124
|
-
<h2
|
|
123
|
+
<h2
|
|
124
|
+
id="drawer-title"
|
|
125
|
+
class="font-mono text-lg font-semibold text-on-surface"
|
|
126
|
+
>
|
|
125
127
|
{title}
|
|
126
128
|
</h2>
|
|
127
129
|
{/if}
|
|
@@ -129,7 +131,7 @@
|
|
|
129
131
|
{#if closable}
|
|
130
132
|
<button
|
|
131
133
|
onclick={handleClose}
|
|
132
|
-
class="-m-2 shrink-0 rounded-
|
|
134
|
+
class="-m-2 shrink-0 rounded-[3px] p-2 text-on-surface-faint hover:bg-surface-sunken hover:text-on-surface-muted"
|
|
133
135
|
aria-label="Close"
|
|
134
136
|
>
|
|
135
137
|
<X size={20} />
|
|
@@ -138,16 +140,14 @@
|
|
|
138
140
|
</div>
|
|
139
141
|
{/if}
|
|
140
142
|
|
|
141
|
-
<!-- Body -->
|
|
142
143
|
{#if children}
|
|
143
144
|
<div class="flex-1 overflow-y-auto px-6 py-4">
|
|
144
145
|
{@render children()}
|
|
145
146
|
</div>
|
|
146
147
|
{/if}
|
|
147
148
|
|
|
148
|
-
<!-- Footer -->
|
|
149
149
|
{#if footer}
|
|
150
|
-
<div class="border-t border-outline
|
|
150
|
+
<div class="border-t border-outline bg-surface-sunken px-6 py-4">
|
|
151
151
|
{@render footer()}
|
|
152
152
|
</div>
|
|
153
153
|
{/if}
|
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
import type { Component } from "svelte";
|
|
7
7
|
import { tick, onDestroy } from "svelte";
|
|
8
8
|
import { EllipsisVertical, Check } from "@lucide/svelte";
|
|
9
|
-
import { scale } from "svelte/transition";
|
|
10
|
-
import { quintOut } from "svelte/easing";
|
|
11
9
|
import { computePosition, autoUpdate, flip, shift, offset } from "@floating-ui/dom";
|
|
12
10
|
|
|
13
11
|
interface MenuItem {
|
|
@@ -58,11 +56,7 @@
|
|
|
58
56
|
|
|
59
57
|
void computePosition(triggerEl, menuEl, {
|
|
60
58
|
placement,
|
|
61
|
-
middleware: [
|
|
62
|
-
offset(4), // MENU_OFFSET
|
|
63
|
-
flip(),
|
|
64
|
-
shift({ padding: 8 }), // VIEWPORT_PADDING
|
|
65
|
-
],
|
|
59
|
+
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
66
60
|
}).then(({ x, y, placement }) => {
|
|
67
61
|
if (menuEl) {
|
|
68
62
|
Object.assign(menuEl.style, {
|
|
@@ -71,7 +65,7 @@
|
|
|
71
65
|
position: "absolute",
|
|
72
66
|
});
|
|
73
67
|
|
|
74
|
-
//
|
|
68
|
+
// Flip transform origin vertically when the menu flips above the trigger
|
|
75
69
|
const isTop = placement.startsWith("top");
|
|
76
70
|
transformOrigin = `${isTop ? "bottom" : "top"} ${align}`;
|
|
77
71
|
}
|
|
@@ -127,7 +121,7 @@
|
|
|
127
121
|
bind:this={triggerEl}
|
|
128
122
|
aria-label={triggerLabel}
|
|
129
123
|
aria-expanded={open}
|
|
130
|
-
class="rounded-
|
|
124
|
+
class="rounded-[3px] p-2 text-on-surface-muted hover:bg-surface-sunken hover:text-on-surface focus:ring-2 focus:ring-outline focus:outline-none active:bg-surface-sunken"
|
|
131
125
|
>
|
|
132
126
|
{#if trigger}
|
|
133
127
|
{@render trigger()}
|
|
@@ -141,12 +135,11 @@
|
|
|
141
135
|
use:portal
|
|
142
136
|
bind:this={menuEl}
|
|
143
137
|
role="menu"
|
|
144
|
-
transition:scale={{ duration: 150, start: 0.95, easing: quintOut }}
|
|
145
138
|
class="
|
|
146
139
|
z-[9999]
|
|
147
140
|
min-w-48 overflow-y-auto
|
|
148
|
-
rounded-
|
|
149
|
-
border border-outline bg-surface-overlay py-1 shadow-
|
|
141
|
+
rounded-[4px]
|
|
142
|
+
border border-outline bg-surface-overlay py-1 shadow-lg
|
|
150
143
|
"
|
|
151
144
|
style="transform-origin: {transformOrigin};"
|
|
152
145
|
>
|
|
@@ -155,20 +148,19 @@
|
|
|
155
148
|
{:else}
|
|
156
149
|
{#each items as item, idx (idx)}
|
|
157
150
|
{#if item.divider}
|
|
158
|
-
<hr class="my-1 border-outline
|
|
151
|
+
<hr class="my-1 border-outline" />
|
|
159
152
|
{:else if item.href}
|
|
160
153
|
<a
|
|
161
154
|
href={item.href}
|
|
162
155
|
title={item.title}
|
|
163
156
|
role="menuitem"
|
|
164
157
|
class="
|
|
165
|
-
mx-1 flex items-center gap-3 rounded-
|
|
158
|
+
mx-1 flex items-center gap-3 rounded-[3px] px-3 py-2 font-mono text-sm
|
|
166
159
|
{item.danger
|
|
167
160
|
? 'text-danger-soft-text hover:bg-danger-soft'
|
|
168
|
-
: 'text-on-surface-muted hover:bg-surface-sunken'}
|
|
161
|
+
: 'text-on-surface-muted hover:bg-surface-sunken hover:text-on-surface'}
|
|
169
162
|
{item.disabled ? 'cursor-not-allowed opacity-50' : ''}
|
|
170
|
-
|
|
171
|
-
"
|
|
163
|
+
"
|
|
172
164
|
>
|
|
173
165
|
{#if item.icon}
|
|
174
166
|
{@const Icon = item.icon}
|
|
@@ -183,11 +175,11 @@
|
|
|
183
175
|
title={item.title}
|
|
184
176
|
role="menuitem"
|
|
185
177
|
class="
|
|
186
|
-
mx-1 box-border flex w-full max-w-[calc(100%-8px)] items-center gap-3 rounded-
|
|
178
|
+
mx-1 box-border flex w-full max-w-[calc(100%-8px)] items-center gap-3 rounded-[3px] px-3 py-2 text-left font-mono text-sm
|
|
187
179
|
{item.danger
|
|
188
180
|
? 'text-danger-soft-text hover:bg-danger-soft'
|
|
189
|
-
: 'text-on-surface-muted hover:bg-surface-sunken'}
|
|
190
|
-
|
|
181
|
+
: 'text-on-surface-muted hover:bg-surface-sunken hover:text-on-surface'}
|
|
182
|
+
disabled:cursor-not-allowed
|
|
191
183
|
disabled:opacity-50
|
|
192
184
|
"
|
|
193
185
|
>
|
|
@@ -46,15 +46,15 @@
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
const inputClasses = `
|
|
49
|
-
w-full rounded-
|
|
49
|
+
w-full rounded-[3px] border font-mono
|
|
50
50
|
bg-surface-raised text-on-surface placeholder:text-on-surface-faint
|
|
51
|
-
focus:outline-none focus:ring-
|
|
51
|
+
focus:outline-none focus:border-ring focus:ring-2 focus:ring-ring focus:ring-offset-2
|
|
52
52
|
disabled:bg-surface-sunken disabled:text-on-surface-muted disabled:cursor-not-allowed
|
|
53
|
-
|
|
54
|
-
`;
|
|
53
|
+
`;
|
|
55
54
|
|
|
56
55
|
const normalBorder = "border-outline hover:border-outline-hover shadow-sm";
|
|
57
|
-
const errorBorder =
|
|
56
|
+
const errorBorder =
|
|
57
|
+
"border-danger-surface focus:border-danger-surface focus:ring-danger-surface";
|
|
58
58
|
|
|
59
59
|
function formatMs(msValue: number): string {
|
|
60
60
|
if (typeof msValue !== "number" || isNaN(msValue)) return "";
|
|
@@ -113,14 +113,14 @@
|
|
|
113
113
|
|
|
114
114
|
<div class="space-y-1.5 {className}">
|
|
115
115
|
{#if label}
|
|
116
|
-
<label for={inputId} class="block text-
|
|
116
|
+
<label for={inputId} class="block font-mono text-xs font-medium text-on-surface-muted">
|
|
117
117
|
{label}
|
|
118
118
|
</label>
|
|
119
119
|
{/if}
|
|
120
120
|
|
|
121
121
|
<div class="group relative">
|
|
122
122
|
<div
|
|
123
|
-
class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-on-surface-faint
|
|
123
|
+
class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-on-surface-faint group-focus-within:text-primary"
|
|
124
124
|
>
|
|
125
125
|
<Clock size={16} />
|
|
126
126
|
</div>
|
|
@@ -155,18 +155,14 @@
|
|
|
155
155
|
</div>
|
|
156
156
|
|
|
157
157
|
{#if parsedHuman && isFocused}
|
|
158
|
-
<p
|
|
159
|
-
class="animate-in slide-in-from-top-1 fade-in text-xs font-medium text-primary duration-200"
|
|
160
|
-
>
|
|
158
|
+
<p class="font-sans text-xs font-medium text-primary">
|
|
161
159
|
{parsedHuman}
|
|
162
160
|
</p>
|
|
163
161
|
{:else if error}
|
|
164
|
-
<p
|
|
165
|
-
class="animate-in slide-in-from-top-1 fade-in text-sm text-danger-soft-text duration-200"
|
|
166
|
-
>
|
|
162
|
+
<p class="font-sans text-xs text-danger-soft-text">
|
|
167
163
|
{error}
|
|
168
164
|
</p>
|
|
169
165
|
{:else if hint}
|
|
170
|
-
<p class="text-
|
|
166
|
+
<p class="font-sans text-xs text-on-surface-muted">{hint}</p>
|
|
171
167
|
{/if}
|
|
172
168
|
</div>
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<Icon size={iconSize} class="text-on-surface-faint" />
|
|
33
33
|
</div>
|
|
34
34
|
|
|
35
|
-
<h3 class="mb-1 text-lg font-semibold text-on-surface">{title}</h3>
|
|
35
|
+
<h3 class="mb-1 font-mono text-lg font-semibold text-on-surface">{title}</h3>
|
|
36
36
|
|
|
37
37
|
{#if description}
|
|
38
38
|
<p class="mb-6 max-w-sm text-sm text-on-surface-muted">{description}</p>
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
|
|
42
42
|
const IconComponent = $derived(icon ?? (variant === "disconnected" ? WifiOff : TriangleAlert));
|
|
43
43
|
|
|
44
|
-
const iconBg = $derived(variant === "disconnected" ? "bg-
|
|
44
|
+
const iconBg = $derived(variant === "disconnected" ? "bg-warning-soft" : "bg-danger-soft");
|
|
45
45
|
const iconColor = $derived(
|
|
46
|
-
variant === "disconnected" ? "text-
|
|
46
|
+
variant === "disconnected" ? "text-warning-soft-text" : "text-danger-soft-text",
|
|
47
47
|
);
|
|
48
48
|
</script>
|
|
49
49
|
|
|
50
50
|
<div
|
|
51
|
-
class="flex flex-col items-center justify-center gap-4 rounded-
|
|
51
|
+
class="flex flex-col items-center justify-center gap-4 rounded-[4px] border border-outline bg-surface-raised px-6 py-12 text-center {className}"
|
|
52
52
|
role="alert"
|
|
53
53
|
>
|
|
54
54
|
<div class="rounded-full {iconBg} p-3">
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
</div>
|
|
57
57
|
|
|
58
58
|
<div class="space-y-1">
|
|
59
|
-
<h3 class="text-lg font-semibold text-on-surface">{defaultTitle}</h3>
|
|
59
|
+
<h3 class="font-mono text-lg font-semibold text-on-surface">{defaultTitle}</h3>
|
|
60
60
|
<p class="max-w-sm text-sm text-on-surface-muted">{message}</p>
|
|
61
61
|
</div>
|
|
62
62
|
|
|
@@ -15,19 +15,19 @@
|
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
17
|
<article
|
|
18
|
-
class="overflow-hidden rounded-
|
|
18
|
+
class="overflow-hidden rounded-[4px] border border-outline bg-surface-raised p-6 hover:border-outline-hover {className}"
|
|
19
19
|
>
|
|
20
20
|
<div class="flex flex-col gap-3">
|
|
21
21
|
{#if Icon}
|
|
22
22
|
<span
|
|
23
|
-
class="inline-flex h-10 w-10 items-center justify-center rounded-
|
|
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
24
|
>
|
|
25
25
|
<Icon size={20} />
|
|
26
26
|
</span>
|
|
27
27
|
{/if}
|
|
28
|
-
<h3 class="
|
|
28
|
+
<h3 class="font-mono text-base text-primary">{title}</h3>
|
|
29
29
|
{#if children}
|
|
30
|
-
<div class="text-sm leading-relaxed text-on-surface-muted">
|
|
30
|
+
<div class="font-sans text-sm leading-relaxed text-on-surface-muted">
|
|
31
31
|
{@render children()}
|
|
32
32
|
</div>
|
|
33
33
|
{/if}
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
<div class="space-y-1.5 {className}">
|
|
38
38
|
{#if label}
|
|
39
|
-
<label for={fieldId} class="block text-
|
|
39
|
+
<label for={fieldId} class="block font-mono text-xs font-medium text-on-surface-muted">
|
|
40
40
|
{label}
|
|
41
41
|
{#if required}
|
|
42
42
|
<span class="text-danger-soft-text">*</span>
|
|
@@ -45,18 +45,16 @@
|
|
|
45
45
|
{/if}
|
|
46
46
|
|
|
47
47
|
{#if description}
|
|
48
|
-
<p class="text-
|
|
48
|
+
<p class="font-sans text-xs text-on-surface-faint">{description}</p>
|
|
49
49
|
{/if}
|
|
50
50
|
|
|
51
51
|
{@render children()}
|
|
52
52
|
|
|
53
53
|
{#if error}
|
|
54
|
-
<p
|
|
55
|
-
class="animate-in slide-in-from-top-1 fade-in text-sm text-danger-soft-text duration-200"
|
|
56
|
-
>
|
|
54
|
+
<p class="font-sans text-xs text-danger-soft-text">
|
|
57
55
|
{error}
|
|
58
56
|
</p>
|
|
59
57
|
{:else if hint}
|
|
60
|
-
<p class="text-
|
|
58
|
+
<p class="font-sans text-xs text-on-surface-muted">{hint}</p>
|
|
61
59
|
{/if}
|
|
62
60
|
</div>
|
|
@@ -40,6 +40,9 @@
|
|
|
40
40
|
const tag = $derived(`h${level}` as const);
|
|
41
41
|
</script>
|
|
42
42
|
|
|
43
|
-
<svelte:element
|
|
43
|
+
<svelte:element
|
|
44
|
+
this={tag}
|
|
45
|
+
class="font-mono tracking-tight text-on-surface {sizeClasses[resolvedSize]} {className}"
|
|
46
|
+
>
|
|
44
47
|
{@render children()}
|
|
45
48
|
</svelte:element>
|
|
@@ -43,20 +43,20 @@
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const inputClasses = `
|
|
46
|
-
w-full rounded-
|
|
46
|
+
w-full rounded-[3px] border font-mono
|
|
47
47
|
bg-surface-raised text-on-surface placeholder:text-on-surface-faint
|
|
48
|
-
focus:outline-none focus:ring-
|
|
48
|
+
focus:outline-none focus:border-ring focus:ring-2 focus:ring-ring focus:ring-offset-2
|
|
49
49
|
disabled:bg-surface-sunken disabled:text-on-surface-muted disabled:cursor-not-allowed
|
|
50
|
-
|
|
51
|
-
`;
|
|
50
|
+
`;
|
|
52
51
|
|
|
53
52
|
const normalBorder = "border-outline hover:border-outline-hover shadow-sm";
|
|
54
|
-
const errorBorder =
|
|
53
|
+
const errorBorder =
|
|
54
|
+
"border-danger-surface focus:border-danger-surface focus:ring-danger-surface";
|
|
55
55
|
</script>
|
|
56
56
|
|
|
57
57
|
<div class="space-y-1.5 {className}">
|
|
58
58
|
{#if label}
|
|
59
|
-
<label for={inputId} class="block text-
|
|
59
|
+
<label for={inputId} class="block font-mono text-xs font-medium text-on-surface-muted">
|
|
60
60
|
{label}
|
|
61
61
|
</label>
|
|
62
62
|
{/if}
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
<div class="group relative">
|
|
65
65
|
{#if leadingIcon}
|
|
66
66
|
<div
|
|
67
|
-
class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-on-surface-faint
|
|
67
|
+
class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-on-surface-faint group-focus-within:text-on-surface-muted"
|
|
68
68
|
>
|
|
69
69
|
{@render leadingIcon()}
|
|
70
70
|
</div>
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
</div>
|
|
98
98
|
{:else if trailingIcon}
|
|
99
99
|
<div
|
|
100
|
-
class="pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-on-surface-faint
|
|
100
|
+
class="pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-on-surface-faint group-focus-within:text-on-surface-muted"
|
|
101
101
|
>
|
|
102
102
|
{@render trailingIcon()}
|
|
103
103
|
</div>
|
|
@@ -105,12 +105,10 @@
|
|
|
105
105
|
</div>
|
|
106
106
|
|
|
107
107
|
{#if error}
|
|
108
|
-
<p
|
|
109
|
-
class="animate-in slide-in-from-top-1 fade-in text-sm text-danger-soft-text duration-200"
|
|
110
|
-
>
|
|
108
|
+
<p class="font-sans text-xs text-danger-soft-text">
|
|
111
109
|
{error}
|
|
112
110
|
</p>
|
|
113
111
|
{:else if hint}
|
|
114
|
-
<p class="text-
|
|
112
|
+
<p class="font-sans text-xs text-on-surface-muted">{hint}</p>
|
|
115
113
|
{/if}
|
|
116
114
|
</div>
|
|
@@ -27,9 +27,8 @@
|
|
|
27
27
|
|
|
28
28
|
const baseClasses = `
|
|
29
29
|
inline-flex items-center gap-1
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
rounded-sm
|
|
30
|
+
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
|
|
31
|
+
rounded-[3px]
|
|
33
32
|
`;
|
|
34
33
|
|
|
35
34
|
const variantClasses: Record<LinkVariant, string> = {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
{...restProps}
|
|
41
41
|
>
|
|
42
42
|
{#if icon}
|
|
43
|
-
<span class="shrink-0
|
|
43
|
+
<span class="shrink-0 group-active:scale-95">
|
|
44
44
|
{@render icon()}
|
|
45
45
|
</span>
|
|
46
46
|
{/if}
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
{@render children()}
|
|
49
49
|
{/if}
|
|
50
50
|
{#if iconRight}
|
|
51
|
-
<span class="shrink-0
|
|
51
|
+
<span class="shrink-0 group-active:scale-95">
|
|
52
52
|
{@render iconRight()}
|
|
53
53
|
</span>
|
|
54
54
|
{/if}
|