@joewinke/jatui 0.22.0 → 0.24.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/CLAUDE.md +72 -2
- package/dist/actions/reveal.d.ts +37 -0
- package/dist/actions/reveal.js +42 -0
- package/dist/components/AudioRecorder.svelte +529 -0
- package/dist/components/AudioRecorder.svelte.d.ts +30 -0
- package/dist/components/BulkActionBar.svelte +40 -0
- package/dist/components/BulkActionBar.svelte.d.ts +9 -0
- package/dist/components/ConfirmDialog.svelte +39 -35
- package/dist/components/CopyButton.svelte +5 -2
- package/dist/components/FloatingActionBar.svelte +55 -1
- package/dist/components/FloatingActionBar.svelte.d.ts +8 -1
- package/dist/components/IconSelector.svelte +417 -0
- package/dist/components/IconSelector.svelte.d.ts +55 -0
- package/dist/components/InfiniteGrid.svelte +305 -0
- package/dist/components/InfiniteGrid.svelte.d.ts +71 -0
- package/dist/components/InfiniteSearchGrid.svelte +131 -0
- package/dist/components/InfiniteSearchGrid.svelte.d.ts +67 -0
- package/dist/components/InputDialog.svelte +49 -38
- package/dist/components/KeyboardShortcutsOverlay.svelte +94 -3
- package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +61 -16
- package/dist/components/MediaCaptureIcon.svelte +23 -0
- package/dist/components/MediaCaptureIcon.svelte.d.ts +1 -1
- package/dist/components/ThumbnailGrid.svelte +137 -0
- package/dist/components/ThumbnailGrid.svelte.d.ts +42 -0
- package/dist/components/batch/BatchJobTable.svelte +549 -0
- package/dist/components/batch/BatchJobTable.svelte.d.ts +114 -0
- package/dist/components/batch/QuotaMeter.svelte +78 -0
- package/dist/components/batch/QuotaMeter.svelte.d.ts +16 -0
- package/dist/components/batch/batchQueue.d.ts +56 -0
- package/dist/components/batch/batchQueue.js +81 -0
- package/dist/components/batch/elapsedEstimate.d.ts +24 -0
- package/dist/components/batch/elapsedEstimate.js +25 -0
- package/dist/components/batch/pollOperation.d.ts +45 -0
- package/dist/components/batch/pollOperation.js +80 -0
- package/dist/components/batch/useElapsedEstimate.d.ts +10 -0
- package/dist/components/batch/useElapsedEstimate.js +38 -0
- package/dist/components/bulkActionBarKeys.d.ts +40 -0
- package/dist/components/bulkActionBarKeys.js +38 -0
- package/dist/components/infiniteGridLoader.d.ts +70 -0
- package/dist/components/infiniteGridLoader.js +141 -0
- package/dist/components/linked-columns/LinkedColumns.svelte +10 -22
- package/dist/components/linked-columns/LinkedColumns.svelte.d.ts +1 -9
- package/dist/components/linked-columns/types.d.ts +9 -0
- package/dist/components/linked-columns/types.js +1 -0
- package/dist/components/replay/ChapterTimeline.svelte +43 -25
- package/dist/components/replay/ChapterTimeline.svelte.d.ts +26 -1
- package/dist/components/table/columnResize.d.ts +38 -0
- package/dist/components/table/columnResize.js +117 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/toast/ToastItem.svelte +47 -2
- package/dist/components/variant/VariantMatrixPicker.svelte +181 -0
- package/dist/components/variant/VariantMatrixPicker.svelte.d.ts +37 -0
- package/dist/components/variant/variantCombinations.d.ts +75 -0
- package/dist/components/variant/variantCombinations.js +100 -0
- package/dist/index.d.ts +34 -3
- package/dist/index.js +30 -1
- package/dist/stores/toast.d.ts +8 -0
- package/dist/stores/toast.js +2 -0
- package/dist/styles/motion.css +100 -0
- package/dist/utils/audioRecorder.d.ts +28 -0
- package/dist/utils/audioRecorder.js +58 -0
- package/dist/utils/audioRecorderCore.d.ts +132 -0
- package/dist/utils/audioRecorderCore.js +447 -0
- package/dist/utils/clipboard.d.ts +25 -0
- package/dist/utils/clipboard.js +59 -0
- package/dist/utils/dateFormatters.d.ts +11 -2
- package/dist/utils/dateFormatters.js +22 -2
- package/dist/utils/keyboardShortcutRegistry.d.ts +152 -0
- package/dist/utils/keyboardShortcutRegistry.js +365 -0
- package/package.json +1 -1
|
@@ -151,10 +151,15 @@
|
|
|
151
151
|
{/if}
|
|
152
152
|
|
|
153
153
|
<style>
|
|
154
|
+
/* Theme tokens (jatui-is2ow.3): every colour derives from var(--color-*) —
|
|
155
|
+
relative-color `oklch(from var(--x) l c h / a)` keeps the token's hue/chroma
|
|
156
|
+
and only swaps alpha, so light and dark themes both render correctly.
|
|
157
|
+
--n-00 (pure black) is a jat-IDE neutral; the inline fallback keeps
|
|
158
|
+
standalone consumers (no app.css) rendering the same value. */
|
|
154
159
|
.cd-scrim {
|
|
155
160
|
position: fixed;
|
|
156
161
|
inset: 0;
|
|
157
|
-
background: oklch(0 0 0 / 0.45);
|
|
162
|
+
background: oklch(from var(--n-00, oklch(0 0 0)) l c h / 0.45);
|
|
158
163
|
z-index: 9990;
|
|
159
164
|
backdrop-filter: blur(2px);
|
|
160
165
|
}
|
|
@@ -175,21 +180,21 @@
|
|
|
175
180
|
flex-direction: column;
|
|
176
181
|
gap: 0.625rem;
|
|
177
182
|
padding: 1rem 1.125rem 0.625rem;
|
|
178
|
-
background:
|
|
179
|
-
border: 1px solid var(--color-base-
|
|
183
|
+
background: oklch(from var(--color-base-200) l c h / 98%);
|
|
184
|
+
border: 1px solid var(--color-base-100);
|
|
180
185
|
border-radius: 0.875rem;
|
|
181
186
|
box-shadow:
|
|
182
|
-
0 20px 60px oklch(0 0 0 / 0.55),
|
|
183
|
-
0 0 0 1px
|
|
187
|
+
0 20px 60px oklch(from var(--n-00, oklch(0 0 0)) l c h / 0.55),
|
|
188
|
+
0 0 0 1px oklch(from var(--color-base-100) l c h / 50%);
|
|
184
189
|
backdrop-filter: blur(16px);
|
|
185
190
|
}
|
|
186
191
|
|
|
187
192
|
.cd-box.cd-danger {
|
|
188
|
-
border-color:
|
|
193
|
+
border-color: oklch(from var(--color-error) l c h / 55%);
|
|
189
194
|
box-shadow:
|
|
190
|
-
0 20px 60px oklch(0 0 0 / 0.6),
|
|
191
|
-
0 0 0 1px
|
|
192
|
-
0 0 30px
|
|
195
|
+
0 20px 60px oklch(from var(--n-00, oklch(0 0 0)) l c h / 0.6),
|
|
196
|
+
0 0 0 1px oklch(from var(--color-error) l c h / 25%),
|
|
197
|
+
0 0 30px oklch(from var(--color-error) l c h / 12%);
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
.cd-header {
|
|
@@ -206,7 +211,7 @@
|
|
|
206
211
|
display: flex;
|
|
207
212
|
align-items: center;
|
|
208
213
|
justify-content: center;
|
|
209
|
-
background: color-mix(in oklch, var(--color-info)
|
|
214
|
+
background: color-mix(in oklch, var(--color-info) 20%, transparent);
|
|
210
215
|
border: 1px solid color-mix(in oklch, var(--color-info) 40%, transparent);
|
|
211
216
|
color: var(--color-info);
|
|
212
217
|
}
|
|
@@ -217,9 +222,9 @@
|
|
|
217
222
|
}
|
|
218
223
|
|
|
219
224
|
.cd-icon.cd-icon-danger {
|
|
220
|
-
background: color-mix(in oklch, var(--color-error)
|
|
221
|
-
border-color:
|
|
222
|
-
color: var(--color-error
|
|
225
|
+
background: color-mix(in oklch, var(--color-error) 20%, transparent);
|
|
226
|
+
border-color: oklch(from var(--color-error) l c h / 40%);
|
|
227
|
+
color: var(--color-error);
|
|
223
228
|
}
|
|
224
229
|
|
|
225
230
|
.cd-title-group {
|
|
@@ -241,13 +246,12 @@
|
|
|
241
246
|
.cd-body {
|
|
242
247
|
margin: 0;
|
|
243
248
|
font-size: 0.8rem;
|
|
244
|
-
color:
|
|
249
|
+
color: oklch(from var(--color-base-content) l c h / 70%);
|
|
245
250
|
line-height: 1.5;
|
|
246
251
|
}
|
|
247
252
|
|
|
248
253
|
.cd-actions {
|
|
249
254
|
display: flex;
|
|
250
|
-
justify-content: flex-end;
|
|
251
255
|
align-items: center;
|
|
252
256
|
gap: 0.375rem;
|
|
253
257
|
padding-top: 0.125rem;
|
|
@@ -263,15 +267,15 @@
|
|
|
263
267
|
border-radius: 0.5rem;
|
|
264
268
|
border: 1px solid transparent;
|
|
265
269
|
background: transparent;
|
|
266
|
-
color:
|
|
270
|
+
color: oklch(from var(--color-base-content) l c h / 95%);
|
|
267
271
|
cursor: pointer;
|
|
268
272
|
transition: background 0.1s ease, border-color 0.1s ease, color 0.1s ease;
|
|
269
273
|
white-space: nowrap;
|
|
270
274
|
}
|
|
271
275
|
|
|
272
276
|
.cd-btn:hover {
|
|
273
|
-
background: var(--color-base-
|
|
274
|
-
border-color: var(--color-base-
|
|
277
|
+
background: var(--color-base-100);
|
|
278
|
+
border-color: var(--color-base-100);
|
|
275
279
|
}
|
|
276
280
|
|
|
277
281
|
.cd-btn-cancel:focus-visible {
|
|
@@ -280,25 +284,25 @@
|
|
|
280
284
|
}
|
|
281
285
|
|
|
282
286
|
.cd-btn-confirm {
|
|
283
|
-
background:
|
|
284
|
-
border-color: var(--color-
|
|
287
|
+
background: oklch(from var(--color-base-100) l c h / 60%);
|
|
288
|
+
border-color: color-mix(in oklch, var(--color-primary) 40%, transparent);
|
|
285
289
|
}
|
|
286
290
|
|
|
287
291
|
.cd-btn-confirm:hover {
|
|
288
|
-
background: var(--color-base-200);
|
|
289
|
-
border-color: color-mix(in oklch, var(--color-
|
|
292
|
+
background: color-mix(in oklch, var(--color-primary) 20%, var(--color-base-200));
|
|
293
|
+
border-color: color-mix(in oklch, var(--color-primary) 50%, transparent);
|
|
290
294
|
}
|
|
291
295
|
|
|
292
296
|
.cd-btn-danger {
|
|
293
|
-
background: color-mix(in oklch, var(--color-error)
|
|
294
|
-
border-color:
|
|
295
|
-
color: var(--color-error
|
|
297
|
+
background: color-mix(in oklch, var(--color-error) 30%, transparent);
|
|
298
|
+
border-color: oklch(from var(--color-error) l c h / 55%);
|
|
299
|
+
color: oklch(from var(--color-error) calc(l + 0.2) c h);
|
|
296
300
|
}
|
|
297
301
|
|
|
298
302
|
.cd-btn-danger:hover {
|
|
299
|
-
background: color-mix(in oklch, var(--color-error)
|
|
300
|
-
border-color:
|
|
301
|
-
color: var(--color-error
|
|
303
|
+
background: color-mix(in oklch, var(--color-error) 45%, transparent);
|
|
304
|
+
border-color: oklch(from var(--color-error) l c h / 70%);
|
|
305
|
+
color: oklch(from var(--color-error) calc(l + 0.25) c h);
|
|
302
306
|
}
|
|
303
307
|
|
|
304
308
|
.cd-btn-confirm:focus-visible,
|
|
@@ -311,11 +315,11 @@
|
|
|
311
315
|
font-family: ui-monospace, monospace;
|
|
312
316
|
font-size: 0.65rem;
|
|
313
317
|
padding: 0.0625rem 0.3125rem;
|
|
314
|
-
background: var(--color-base-
|
|
315
|
-
border: 1px solid var(--color-base-
|
|
318
|
+
background: var(--color-base-100);
|
|
319
|
+
border: 1px solid var(--color-base-100);
|
|
316
320
|
border-bottom-width: 2px;
|
|
317
321
|
border-radius: 0.25rem;
|
|
318
|
-
color:
|
|
322
|
+
color: oklch(from var(--color-base-content) l c h / 85%);
|
|
319
323
|
line-height: 1.6;
|
|
320
324
|
}
|
|
321
325
|
|
|
@@ -323,7 +327,7 @@
|
|
|
323
327
|
margin-left: auto;
|
|
324
328
|
font-family: ui-monospace, monospace;
|
|
325
329
|
font-size: 0.7rem;
|
|
326
|
-
color:
|
|
330
|
+
color: oklch(from var(--color-base-content) l c h / 55%);
|
|
327
331
|
font-variant-numeric: tabular-nums;
|
|
328
332
|
min-width: 2ch;
|
|
329
333
|
text-align: right;
|
|
@@ -331,20 +335,20 @@
|
|
|
331
335
|
|
|
332
336
|
.cd-progress {
|
|
333
337
|
height: 2px;
|
|
334
|
-
background: var(--color-base-
|
|
338
|
+
background: var(--color-base-100);
|
|
335
339
|
border-radius: 999px;
|
|
336
340
|
overflow: hidden;
|
|
337
341
|
}
|
|
338
342
|
|
|
339
343
|
.cd-progress-fill {
|
|
340
344
|
height: 100%;
|
|
341
|
-
background: linear-gradient(90deg, var(--color-
|
|
345
|
+
background: linear-gradient(90deg, var(--color-primary), var(--color-info));
|
|
342
346
|
border-radius: 999px;
|
|
343
347
|
transition: width 60ms linear;
|
|
344
348
|
}
|
|
345
349
|
|
|
346
350
|
.cd-progress-fill.cd-progress-danger {
|
|
347
|
-
background: linear-gradient(90deg, var(--color-error), var(--color-
|
|
351
|
+
background: linear-gradient(90deg, var(--color-error), var(--color-warning));
|
|
348
352
|
}
|
|
349
353
|
|
|
350
354
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { copyText } from '../utils/clipboard';
|
|
3
|
+
|
|
2
4
|
interface Props {
|
|
3
5
|
text?: string;
|
|
4
6
|
getText?: () => string | Promise<string>;
|
|
@@ -42,14 +44,15 @@
|
|
|
42
44
|
if (copied) return;
|
|
43
45
|
try {
|
|
44
46
|
const value = getText ? await getText() : (text ?? '');
|
|
45
|
-
await
|
|
47
|
+
const ok = await copyText(value);
|
|
48
|
+
if (!ok) return;
|
|
46
49
|
copied = true;
|
|
47
50
|
clearTimeout(timer);
|
|
48
51
|
timer = setTimeout(() => {
|
|
49
52
|
copied = false;
|
|
50
53
|
}, 1400);
|
|
51
54
|
} catch {
|
|
52
|
-
// clipboard
|
|
55
|
+
// clipboard unavailable — no-op
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
</script>
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* loading={bulkActionLoading}
|
|
12
12
|
* onClear={clearSelection}
|
|
13
13
|
* />
|
|
14
|
+
*
|
|
15
|
+
* Per-action `key` renders a <kbd> hotkey hint on the button (advisory —
|
|
16
|
+
* the matching keydown handling lives in the host/BulkActionBar). While
|
|
17
|
+
* `loading` with a `loadingMessage` set, the buttons are replaced by a
|
|
18
|
+
* spinner + message row (matching the IDE's fork, audit jat-1alfp #15).
|
|
14
19
|
*/
|
|
15
20
|
|
|
16
21
|
import { fade } from 'svelte/transition';
|
|
@@ -24,6 +29,8 @@
|
|
|
24
29
|
icon?: string;
|
|
25
30
|
/** Color variant */
|
|
26
31
|
variant?: 'default' | 'primary' | 'danger' | 'warning' | 'success';
|
|
32
|
+
/** Single-key hotkey hint rendered as a <kbd> chip (advisory only). */
|
|
33
|
+
key?: string;
|
|
27
34
|
/** Called when clicked */
|
|
28
35
|
onclick: () => void;
|
|
29
36
|
}
|
|
@@ -59,8 +66,13 @@
|
|
|
59
66
|
actions?: ActionButton[];
|
|
60
67
|
/** Dropdown menus (open upward from the bar) */
|
|
61
68
|
dropdowns?: ActionDropdown[];
|
|
62
|
-
/**
|
|
69
|
+
/** While loading, disables all buttons. With `loadingMessage` also set,
|
|
70
|
+
* the buttons are replaced by a spinner + message row. */
|
|
63
71
|
loading?: boolean;
|
|
72
|
+
/** When set, replaces the action buttons with a spinner + this message
|
|
73
|
+
* (role="status", aria-live="polite") — matching the IDE's fork, where
|
|
74
|
+
* this alone signals the in-flight state. */
|
|
75
|
+
loadingMessage?: string | null;
|
|
64
76
|
/** Called when the "Clear" button is clicked */
|
|
65
77
|
onClear?: () => void;
|
|
66
78
|
/** Label for the selection count (default: "selected") */
|
|
@@ -72,6 +84,7 @@
|
|
|
72
84
|
actions = [],
|
|
73
85
|
dropdowns = [],
|
|
74
86
|
loading = false,
|
|
87
|
+
loadingMessage = null,
|
|
75
88
|
onClear,
|
|
76
89
|
countLabel = 'selected',
|
|
77
90
|
}: Props = $props();
|
|
@@ -110,6 +123,12 @@
|
|
|
110
123
|
<div class="fab" transition:fade={{ duration: 150 }}>
|
|
111
124
|
<span class="fab-count">{count} {countLabel}</span>
|
|
112
125
|
|
|
126
|
+
{#if loadingMessage}
|
|
127
|
+
<div class="fab-loading" role="status" aria-live="polite">
|
|
128
|
+
<span class="fab-spinner"></span>
|
|
129
|
+
<span class="fab-loading-msg">{loadingMessage}</span>
|
|
130
|
+
</div>
|
|
131
|
+
{:else}
|
|
113
132
|
{#if actions.length > 0}
|
|
114
133
|
<div class="fab-divider"></div>
|
|
115
134
|
{#each actions as action}
|
|
@@ -118,6 +137,7 @@
|
|
|
118
137
|
class="fab-btn {variantClass(action.variant)}"
|
|
119
138
|
onclick={action.onclick}
|
|
120
139
|
disabled={loading}
|
|
140
|
+
title={action.key ? `${action.label} (${action.key})` : undefined}
|
|
121
141
|
>
|
|
122
142
|
{#if action.icon}
|
|
123
143
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
|
|
@@ -126,6 +146,9 @@
|
|
|
126
146
|
</svg>
|
|
127
147
|
{/if}
|
|
128
148
|
{action.label}
|
|
149
|
+
{#if action.key}
|
|
150
|
+
<kbd class="fab-key">{action.key}</kbd>
|
|
151
|
+
{/if}
|
|
129
152
|
</button>
|
|
130
153
|
{/each}
|
|
131
154
|
{/if}
|
|
@@ -175,6 +198,7 @@
|
|
|
175
198
|
</div>
|
|
176
199
|
{/each}
|
|
177
200
|
{/if}
|
|
201
|
+
{/if}
|
|
178
202
|
|
|
179
203
|
{#if onClear}
|
|
180
204
|
<div class="fab-divider"></div>
|
|
@@ -310,6 +334,36 @@
|
|
|
310
334
|
to { transform: rotate(360deg); }
|
|
311
335
|
}
|
|
312
336
|
|
|
337
|
+
.fab-key {
|
|
338
|
+
display: inline-flex;
|
|
339
|
+
align-items: center;
|
|
340
|
+
justify-content: center;
|
|
341
|
+
min-width: 1.125rem;
|
|
342
|
+
height: 1.125rem;
|
|
343
|
+
padding: 0 0.25rem;
|
|
344
|
+
background: var(--color-base-100);
|
|
345
|
+
border: 1px solid oklch(from var(--color-base-content) l c h / 35%);
|
|
346
|
+
border-radius: 0.25rem;
|
|
347
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
348
|
+
font-size: 0.6875rem;
|
|
349
|
+
font-weight: 600;
|
|
350
|
+
line-height: 1;
|
|
351
|
+
color: oklch(from var(--color-base-content) l c h / 80%);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.fab-loading {
|
|
355
|
+
display: flex;
|
|
356
|
+
align-items: center;
|
|
357
|
+
gap: 0.5rem;
|
|
358
|
+
padding: 0.125rem 0.375rem;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.fab-loading-msg {
|
|
362
|
+
font-size: 0.8125rem;
|
|
363
|
+
color: var(--color-primary);
|
|
364
|
+
white-space: nowrap;
|
|
365
|
+
}
|
|
366
|
+
|
|
313
367
|
/* Dropdown */
|
|
314
368
|
.fab-dropdown-wrapper {
|
|
315
369
|
position: relative;
|
|
@@ -7,6 +7,8 @@ export interface ActionButton {
|
|
|
7
7
|
icon?: string;
|
|
8
8
|
/** Color variant */
|
|
9
9
|
variant?: 'default' | 'primary' | 'danger' | 'warning' | 'success';
|
|
10
|
+
/** Single-key hotkey hint rendered as a <kbd> chip (advisory only). */
|
|
11
|
+
key?: string;
|
|
10
12
|
/** Called when clicked */
|
|
11
13
|
onclick: () => void;
|
|
12
14
|
}
|
|
@@ -39,8 +41,13 @@ interface Props {
|
|
|
39
41
|
actions?: ActionButton[];
|
|
40
42
|
/** Dropdown menus (open upward from the bar) */
|
|
41
43
|
dropdowns?: ActionDropdown[];
|
|
42
|
-
/**
|
|
44
|
+
/** While loading, disables all buttons. With `loadingMessage` also set,
|
|
45
|
+
* the buttons are replaced by a spinner + message row. */
|
|
43
46
|
loading?: boolean;
|
|
47
|
+
/** When set, replaces the action buttons with a spinner + this message
|
|
48
|
+
* (role="status", aria-live="polite") — matching the IDE's fork, where
|
|
49
|
+
* this alone signals the in-flight state. */
|
|
50
|
+
loadingMessage?: string | null;
|
|
44
51
|
/** Called when the "Clear" button is clicked */
|
|
45
52
|
onClear?: () => void;
|
|
46
53
|
/** Label for the selection count (default: "selected") */
|