@selvajs/ui 6.6.0-beta.15 → 6.6.0-beta.16
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/README.md +0 -3
- package/dist/components/compute/AppLayout.svelte +5 -3
- package/dist/components/compute/CollapsedPanelStrip.svelte +1 -1
- package/dist/components/compute/ParameterPresetManager.svelte +1 -1
- package/dist/components/compute/SolveMessages.svelte +2 -2
- package/dist/components/layout/FooterItemRenderer.svelte +1 -1
- package/dist/components/layout/PageFooter.svelte +2 -2
- package/dist/components/layout/PageHeader.svelte +1 -1
- package/dist/components/layout/SideNav.svelte +3 -3
- package/dist/components/layout/SubNav.svelte +2 -2
- package/dist/components/preview/ChartOutput.svelte +3 -3
- package/dist/components/preview/Group.svelte +7 -7
- package/dist/components/preview/ImageOutput.svelte +6 -6
- package/dist/components/preview/InputControl.svelte +1 -0
- package/dist/components/preview/OutputDisplay.svelte +8 -6
- package/dist/components/preview/TabBar.svelte +6 -4
- package/dist/components/preview/TabBar.svelte.d.ts +2 -0
- package/dist/components/preview/TabContent.svelte +1 -1
- package/dist/components/preview/TabLayout.svelte +3 -4
- package/dist/components/preview/inputs/ChecklistInput.svelte +3 -3
- package/dist/components/preview/inputs/ColorInput.svelte +356 -14
- package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
- package/dist/components/preview/inputs/FileInput.svelte +3 -3
- package/dist/components/preview/inputs/SegmentedInput.svelte +2 -1
- package/dist/components/preview/inputs/TileInput.svelte +1 -1
- package/dist/components/primitives/CalculateButton.svelte +2 -2
- package/dist/components/primitives/Callout.svelte +7 -5
- package/dist/components/primitives/Callout.svelte.d.ts +4 -4
- package/dist/components/primitives/DataTable.svelte +1 -1
- package/dist/components/primitives/ImageUploadField.svelte +1 -1
- package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/dist/components/primitives/badge/badge.svelte +2 -2
- package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
- package/dist/components/primitives/button/button.svelte +6 -7
- package/dist/components/primitives/button/button.svelte.d.ts +18 -18
- package/dist/components/primitives/card/card.svelte +1 -1
- package/dist/components/primitives/card/card.svelte.d.ts +1 -1
- package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
- package/dist/components/primitives/command/command-input.svelte +1 -1
- package/dist/components/primitives/command/command-item.svelte +1 -1
- package/dist/components/primitives/command/command-link-item.svelte +1 -1
- package/dist/components/primitives/command/command.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
- package/dist/components/primitives/dialog/dialog-content.svelte +2 -2
- package/dist/components/primitives/drawer/Drawer.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/index.js +1 -1
- package/dist/components/primitives/input/input.svelte +2 -2
- package/dist/components/primitives/input-group/input-group.svelte +1 -1
- package/dist/components/primitives/popover/popover-content.svelte +1 -1
- package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
- package/dist/components/primitives/search/search.svelte +1 -1
- package/dist/components/primitives/select/select-content.svelte +1 -1
- package/dist/components/primitives/select/select-item.svelte +1 -1
- package/dist/components/primitives/select/select-trigger.svelte +1 -1
- package/dist/components/primitives/slider/slider.svelte +1 -1
- package/dist/components/primitives/switch/switch.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-list.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +3 -3
- package/dist/components/primitives/tabs/tabs-trigger.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +3 -3
- package/dist/components/primitives/textarea/textarea.svelte +1 -1
- package/dist/components/primitives/toggle/toggle.svelte +6 -3
- package/dist/components/primitives/toggle/toggle.svelte.d.ts +10 -7
- package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
- package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
- package/dist/components/primitives/tooltip/index.d.ts +6 -0
- package/dist/components/primitives/tooltip/index.js +8 -0
- package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
- package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
- package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/components/viewer/MeshMetadataPanel.svelte +1 -1
- package/dist/components/viewer/SceneManager.svelte +19 -19
- package/dist/components/viewer/Viewer.svelte +68 -157
- package/dist/components/viewer/ViewerDock.svelte +404 -0
- package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
- package/dist/i18n/messages.d.ts +11 -0
- package/dist/i18n/messages.js +18 -0
- package/dist/styles/base.css +81 -80
- package/dist/utils/color-space.d.ts +21 -0
- package/dist/utils/color-space.js +90 -0
- package/package.json +9 -10
- package/src/lib/components/compute/AppLayout.svelte +5 -3
- package/src/lib/components/compute/CollapsedPanelStrip.svelte +1 -1
- package/src/lib/components/compute/ParameterPresetManager.svelte +1 -1
- package/src/lib/components/compute/SolveMessages.svelte +2 -2
- package/src/lib/components/layout/FooterItemRenderer.svelte +1 -1
- package/src/lib/components/layout/PageFooter.svelte +2 -2
- package/src/lib/components/layout/PageHeader.svelte +1 -1
- package/src/lib/components/layout/SideNav.svelte +3 -3
- package/src/lib/components/layout/SubNav.svelte +2 -2
- package/src/lib/components/preview/ChartOutput.svelte +3 -3
- package/src/lib/components/preview/Group.svelte +7 -7
- package/src/lib/components/preview/ImageOutput.svelte +6 -6
- package/src/lib/components/preview/InputControl.svelte +1 -0
- package/src/lib/components/preview/OutputDisplay.svelte +8 -6
- package/src/lib/components/preview/TabBar.svelte +6 -4
- package/src/lib/components/preview/TabContent.svelte +1 -1
- package/src/lib/components/preview/TabLayout.svelte +3 -4
- package/src/lib/components/preview/inputs/ChecklistInput.svelte +3 -3
- package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
- package/src/lib/components/preview/inputs/FileInput.svelte +3 -3
- package/src/lib/components/preview/inputs/SegmentedInput.svelte +2 -1
- package/src/lib/components/preview/inputs/TileInput.svelte +1 -1
- package/src/lib/components/primitives/CalculateButton.svelte +2 -2
- package/src/lib/components/primitives/Callout.svelte +7 -5
- package/src/lib/components/primitives/DataTable.svelte +1 -1
- package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/src/lib/components/primitives/badge/badge.svelte +2 -2
- package/src/lib/components/primitives/button/button.svelte +6 -7
- package/src/lib/components/primitives/card/card.svelte +1 -1
- package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
- package/src/lib/components/primitives/command/command-input.svelte +1 -1
- package/src/lib/components/primitives/command/command-item.svelte +1 -1
- package/src/lib/components/primitives/command/command-link-item.svelte +1 -1
- package/src/lib/components/primitives/command/command.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-item.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-content.svelte +2 -2
- package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
- package/src/lib/components/primitives/index.ts +1 -1
- package/src/lib/components/primitives/input/input.svelte +2 -2
- package/src/lib/components/primitives/input-group/input-group.svelte +1 -1
- package/src/lib/components/primitives/popover/popover-content.svelte +1 -1
- package/src/lib/components/primitives/resizable/resizable-handle.svelte +2 -2
- package/src/lib/components/primitives/search/search.svelte +1 -1
- package/src/lib/components/primitives/select/select-content.svelte +1 -1
- package/src/lib/components/primitives/select/select-item.svelte +1 -1
- package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
- package/src/lib/components/primitives/slider/slider.svelte +1 -1
- package/src/lib/components/primitives/switch/switch.svelte +1 -1
- package/src/lib/components/primitives/tabs/tabs-list.svelte +1 -1
- package/src/lib/components/primitives/tabs/tabs-trigger.svelte +1 -1
- package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
- package/src/lib/components/primitives/toggle/toggle.svelte +6 -3
- package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
- package/src/lib/components/primitives/toggle-group/toggle-group.svelte +1 -1
- package/src/lib/components/primitives/tooltip/index.ts +19 -0
- package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
- package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
- package/src/lib/components/viewer/MeshMetadataPanel.svelte +1 -1
- package/src/lib/components/viewer/SceneManager.svelte +19 -19
- package/src/lib/components/viewer/Viewer.svelte +68 -157
- package/src/lib/components/viewer/ViewerDock.svelte +404 -0
- package/src/lib/i18n/messages.ts +29 -0
- package/src/lib/styles/base.css +81 -80
- package/src/lib/utils/color-space.ts +107 -0
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
- package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
- package/dist/components/primitives/theme-switcher/index.js +0 -1
- package/dist/styles/themes/cyberpunk.css +0 -98
- package/dist/styles/themes/neutral.css +0 -72
- package/dist/styles/themes/ocean.css +0 -75
- package/dist/styles/themes/selva.css +0 -105
- package/dist/theme/themeStore.svelte.d.ts +0 -12
- package/dist/theme/themeStore.svelte.js +0 -40
- package/dist/theme/themes.d.ts +0 -5
- package/dist/theme/themes.js +0 -13
- package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
- package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
- package/src/lib/styles/themes/cyberpunk.css +0 -98
- package/src/lib/styles/themes/neutral.css +0 -72
- package/src/lib/styles/themes/ocean.css +0 -75
- package/src/lib/styles/themes/selva.css +0 -105
- package/src/lib/theme/themeStore.svelte.ts +0 -50
- package/src/lib/theme/themes.ts +0 -18
|
@@ -297,14 +297,14 @@
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
const toolButton =
|
|
300
|
-
'flex h-7 min-w-7 items-center justify-center rounded px-1.5 text-muted-foreground transition-colors hover:bg-
|
|
300
|
+
'flex h-7 min-w-7 items-center justify-center rounded-sm px-1.5 text-muted-foreground transition-colors hover:bg-hover hover:text-foreground disabled:pointer-events-none disabled:opacity-40';
|
|
301
301
|
</script>
|
|
302
302
|
|
|
303
303
|
<!-- The layout hides this output until a solve returns a file, so there is no empty state here. -->
|
|
304
304
|
{#if error || unsupported || current}
|
|
305
305
|
<div
|
|
306
306
|
bind:this={wrapperEl}
|
|
307
|
-
class="flex flex-col overflow-hidden rounded-lg border border-border bg-background {isFullscreen
|
|
307
|
+
class="flex flex-col overflow-hidden rounded-lg border border-border-strong bg-background {isFullscreen
|
|
308
308
|
? 'h-dvh'
|
|
309
309
|
: ''}"
|
|
310
310
|
>
|
|
@@ -375,7 +375,7 @@
|
|
|
375
375
|
onclick={() => step(-1)}
|
|
376
376
|
title="{t.previousImage} (←)"
|
|
377
377
|
aria-label={t.previousImage}
|
|
378
|
-
class="left-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border bg-background/80 text-foreground hover:bg-background"
|
|
378
|
+
class="left-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border-strong bg-background/80 text-foreground hover:bg-background"
|
|
379
379
|
>
|
|
380
380
|
<ChevronLeft size={16} />
|
|
381
381
|
</button>
|
|
@@ -383,14 +383,14 @@
|
|
|
383
383
|
onclick={() => step(1)}
|
|
384
384
|
title="{t.nextImage} (→)"
|
|
385
385
|
aria-label={t.nextImage}
|
|
386
|
-
class="right-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border bg-background/80 text-foreground hover:bg-background"
|
|
386
|
+
class="right-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border-strong bg-background/80 text-foreground hover:bg-background"
|
|
387
387
|
>
|
|
388
388
|
<ChevronRight size={16} />
|
|
389
389
|
</button>
|
|
390
390
|
{/if}
|
|
391
391
|
|
|
392
392
|
<div
|
|
393
|
-
class="px-2.5 py-1 text-xs bottom-2
|
|
393
|
+
class="px-2.5 py-1 text-xs bottom-2 pointer-events-none absolute left-1/2 -translate-x-1/2 rounded-sm bg-foreground text-background transition-opacity {showWheelHint
|
|
394
394
|
? 'opacity-100'
|
|
395
395
|
: 'opacity-0'}"
|
|
396
396
|
>
|
|
@@ -404,7 +404,7 @@
|
|
|
404
404
|
<button
|
|
405
405
|
onclick={() => select(i)}
|
|
406
406
|
title="{image.fileName}{image.fileType}"
|
|
407
|
-
class="h-12 w-16
|
|
407
|
+
class="h-12 w-16 shrink-0 overflow-hidden rounded-sm border-2 bg-muted transition-colors {i ===
|
|
408
408
|
currentIndex
|
|
409
409
|
? 'border-primary'
|
|
410
410
|
: 'border-transparent opacity-70 hover:opacity-100'}"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
);
|
|
39
39
|
const hasValue = $derived(value != null);
|
|
40
40
|
|
|
41
|
-
const boxClass = 'min-h-12.5 rounded-md px-3 py-3 text-sm border border-border
|
|
41
|
+
const boxClass = 'min-h-12.5 rounded-md px-3 py-3 text-sm border border-border-strong';
|
|
42
42
|
|
|
43
43
|
async function copyToClipboard() {
|
|
44
44
|
try {
|
|
@@ -194,7 +194,7 @@
|
|
|
194
194
|
<span class="font-medium">{node.name}</span>
|
|
195
195
|
</button>
|
|
196
196
|
{#if isOpen}
|
|
197
|
-
<div class="ml-4 pl-2 border-l border-border
|
|
197
|
+
<div class="ml-4 pl-2 border-l border-border-strong">
|
|
198
198
|
{@render treeNodes(node.children, folderPath)}
|
|
199
199
|
</div>
|
|
200
200
|
{/if}
|
|
@@ -217,12 +217,14 @@
|
|
|
217
217
|
|
|
218
218
|
{#snippet fileDisplay()}
|
|
219
219
|
{#if fileCount === 0}
|
|
220
|
-
<div
|
|
220
|
+
<div
|
|
221
|
+
class="px-3 py-3 text-sm rounded-md border border-border-strong bg-muted text-muted-foreground"
|
|
222
|
+
>
|
|
221
223
|
{t.waitingForFiles}
|
|
222
224
|
</div>
|
|
223
225
|
{:else}
|
|
224
226
|
<div class="gap-2 flex flex-col">
|
|
225
|
-
<div class="px-3 py-2 rounded-md border border-border bg-muted">
|
|
227
|
+
<div class="px-3 py-2 rounded-md border border-border-strong bg-muted">
|
|
226
228
|
<div class="gap-2 flex items-center justify-between">
|
|
227
229
|
<span class="min-w-0 text-sm font-medium truncate text-foreground">
|
|
228
230
|
{fileCount === 1
|
|
@@ -313,10 +315,10 @@
|
|
|
313
315
|
<div class="group relative">
|
|
314
316
|
{#if isObjectValue}
|
|
315
317
|
<pre
|
|
316
|
-
class="{boxClass} max-h-96 font-mono overflow-auto bg-muted
|
|
318
|
+
class="{boxClass} max-h-96 font-mono overflow-auto bg-muted wrap-anywhere text-foreground">{formattedValue}</pre>
|
|
317
319
|
{:else}
|
|
318
320
|
<div
|
|
319
|
-
class="{boxClass} bg-muted
|
|
321
|
+
class="{boxClass} bg-muted wrap-anywhere wrap-break-word whitespace-pre-wrap text-foreground"
|
|
320
322
|
>
|
|
321
323
|
{#if hasValue}{value}{:else}{@render placeholder()}{/if}
|
|
322
324
|
</div>
|
|
@@ -12,9 +12,11 @@
|
|
|
12
12
|
tabs: TabConfig[];
|
|
13
13
|
activeTabId: string;
|
|
14
14
|
onTabChange: (tabId: string) => void;
|
|
15
|
+
/** Matches TabContent's tighter gutter in the stacked phone layout. */
|
|
16
|
+
bare?: boolean;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
let { tabs, activeTabId, onTabChange }: Props = $props();
|
|
19
|
+
let { tabs, activeTabId, onTabChange, bare = false }: Props = $props();
|
|
18
20
|
|
|
19
21
|
const SCROLL_BUTTON_WIDTH = 32;
|
|
20
22
|
|
|
@@ -64,7 +66,7 @@
|
|
|
64
66
|
}
|
|
65
67
|
</script>
|
|
66
68
|
|
|
67
|
-
<div class="tab-bar relative shrink-0 border-b border-border">
|
|
69
|
+
<div class="tab-bar relative shrink-0 border-b border-border {bare ? 'mx-1' : 'mx-3'}">
|
|
68
70
|
<Tabs.List bind:ref={listRef} variant="line" onscroll={updateOverflow} onwheel={handleWheel}>
|
|
69
71
|
{#each tabs as tab (tab.id)}
|
|
70
72
|
<Tabs.Trigger value={tab.id} onclick={() => onTabChange(tab.id)} variant="line">
|
|
@@ -127,11 +129,11 @@
|
|
|
127
129
|
.scroll-button.back {
|
|
128
130
|
left: 0;
|
|
129
131
|
padding: 0 1.25rem 0 0.375rem;
|
|
130
|
-
background: linear-gradient(to right, var(--
|
|
132
|
+
background: linear-gradient(to right, var(--tab-bar-bg, var(--background)) 55%, transparent);
|
|
131
133
|
}
|
|
132
134
|
.scroll-button.forward {
|
|
133
135
|
right: 0;
|
|
134
136
|
padding: 0 0.375rem 0 1.25rem;
|
|
135
|
-
background: linear-gradient(to left, var(--
|
|
137
|
+
background: linear-gradient(to left, var(--tab-bar-bg, var(--background)) 55%, transparent);
|
|
136
138
|
}
|
|
137
139
|
</style>
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
{#if bare}
|
|
138
138
|
{@render body()}
|
|
139
139
|
{:else}
|
|
140
|
-
<div class="h-full
|
|
140
|
+
<div class="h-full">
|
|
141
141
|
<!-- `auto`, not the default `hover`: a hover-only bar comes and goes with the pointer,
|
|
142
142
|
and a host that freezes mid-solve drops the pointer state with it. -->
|
|
143
143
|
<ScrollArea class="h-full" orientation="vertical" type="auto">
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { UISchema, SupportedTypes } from '@selvajs/schemas';
|
|
3
|
-
import * as Card from '$lib/components/primitives/card';
|
|
4
3
|
import * as Tabs from '$lib/components/primitives/tabs';
|
|
5
4
|
import TabBar from './TabBar.svelte';
|
|
6
5
|
import TabContent from './TabContent.svelte';
|
|
@@ -81,7 +80,7 @@
|
|
|
81
80
|
{#snippet tabs()}
|
|
82
81
|
<Tabs.Root value={activeTabId} variant="line" class="min-h-0 flex-1">
|
|
83
82
|
{#if showTabBar}
|
|
84
|
-
<TabBar tabs={visibleTabs} {activeTabId} onTabChange={handleTabChange} />
|
|
83
|
+
<TabBar tabs={visibleTabs} {activeTabId} onTabChange={handleTabChange} {bare} />
|
|
85
84
|
{/if}
|
|
86
85
|
|
|
87
86
|
{#each visibleTabs as tab (tab.id)}
|
|
@@ -104,7 +103,7 @@
|
|
|
104
103
|
{#if bare}
|
|
105
104
|
{@render tabs()}
|
|
106
105
|
{:else}
|
|
107
|
-
<
|
|
106
|
+
<div class="min-h-0 flex flex-1 flex-col">
|
|
108
107
|
{@render tabs()}
|
|
109
|
-
</
|
|
108
|
+
</div>
|
|
110
109
|
{/if}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
}
|
|
31
31
|
</script>
|
|
32
32
|
|
|
33
|
-
<div class="divide-y divide-border
|
|
33
|
+
<div class="divide-y divide-border overflow-hidden rounded-md border border-input">
|
|
34
34
|
{#each Object.entries(options) as [name, expr] (name)}
|
|
35
35
|
{@const optionValue = expr ?? name}
|
|
36
36
|
{@const optionId = `${inputId}-${optionValue}`}
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
{@const glyph = optionGlyph(config?.optionMedia?.[name], assets)}
|
|
39
39
|
<label
|
|
40
40
|
for={optionId}
|
|
41
|
-
class="gap-3 px-3 py-2 text-sm flex items-center transition-colors select-none hover:bg-
|
|
42
|
-
? 'bg-
|
|
41
|
+
class="gap-3 px-3 py-2 text-sm flex items-center transition-colors select-none hover:bg-hover {isSelected
|
|
42
|
+
? 'bg-selected'
|
|
43
43
|
: ''} {disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}"
|
|
44
44
|
>
|
|
45
45
|
<Checkbox
|
|
@@ -1,23 +1,365 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { untrack } from 'svelte';
|
|
3
|
+
import { Check, Pipette } from '@lucide/svelte';
|
|
4
|
+
import * as Popover from '$lib/components/primitives/popover';
|
|
5
|
+
import { Input } from '$lib/components/primitives/input';
|
|
6
|
+
import { getLocaleContext } from '$lib/i18n/localeContext.svelte';
|
|
7
|
+
import { formatMessage } from '$lib/i18n/messages';
|
|
8
|
+
import { debounce } from '$lib/utils/debounce';
|
|
9
|
+
import {
|
|
10
|
+
contrastRatio,
|
|
11
|
+
hexToHsv,
|
|
12
|
+
hsvToHex,
|
|
13
|
+
normalizeHex,
|
|
14
|
+
type Hsv
|
|
15
|
+
} from '$lib/utils/color-space';
|
|
16
|
+
|
|
2
17
|
interface Props {
|
|
3
18
|
inputId: string;
|
|
4
19
|
value?: string;
|
|
5
20
|
onChange: (value: string) => void;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let { inputId, value = '#000000', onChange, disabled = false }: Props = $props();
|
|
25
|
+
|
|
26
|
+
const PRESETS = [
|
|
27
|
+
'#000000',
|
|
28
|
+
'#ffffff',
|
|
29
|
+
'#9ca3af',
|
|
30
|
+
'#ef4444',
|
|
31
|
+
'#f97316',
|
|
32
|
+
'#eab308',
|
|
33
|
+
'#22c55e',
|
|
34
|
+
'#14b8a6',
|
|
35
|
+
'#3b82f6',
|
|
36
|
+
'#8b5cf6',
|
|
37
|
+
'#ec4899',
|
|
38
|
+
'#78350f'
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
interface EyeDropperApi {
|
|
42
|
+
open(): Promise<{ sRGBHex: string }>;
|
|
43
|
+
}
|
|
44
|
+
const eyeDropperCtor = (globalThis as { EyeDropper?: new () => EyeDropperApi }).EyeDropper;
|
|
45
|
+
|
|
46
|
+
const locale = getLocaleContext();
|
|
47
|
+
const t = $derived(locale.messages);
|
|
48
|
+
|
|
49
|
+
const parse = (hex: string): Hsv => hexToHsv(normalizeHex(hex) ?? '#000000')!;
|
|
50
|
+
|
|
51
|
+
let hsv = $state<Hsv>(untrack(() => parse(value)));
|
|
52
|
+
let draft = $state('');
|
|
53
|
+
let hexError = $state(false);
|
|
54
|
+
let areaEl = $state<HTMLElement | null>(null);
|
|
55
|
+
|
|
56
|
+
const currentHex = $derived(hsvToHex(hsv));
|
|
57
|
+
const hueColor = $derived(hsvToHex({ h: hsv.h, s: 1, v: 1 }));
|
|
58
|
+
|
|
59
|
+
// An external value only replaces the picker's state when it names a different color.
|
|
60
|
+
// Rebuilding from the hex alone would reset the hue whenever s or v hits 0.
|
|
61
|
+
$effect(() => {
|
|
62
|
+
const next = normalizeHex(value) ?? '#000000';
|
|
63
|
+
if (next !== untrack(() => currentHex)) hsv = parse(next);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
$effect(() => {
|
|
67
|
+
draft = currentHex;
|
|
68
|
+
hexError = false;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Dragging only updates local state; the host sees one change per gesture, since each
|
|
72
|
+
// change can trigger a solve.
|
|
73
|
+
function commit() {
|
|
74
|
+
commitDebounced.cancel();
|
|
75
|
+
if (currentHex !== normalizeHex(value)) onChange(currentHex);
|
|
76
|
+
}
|
|
77
|
+
const commitDebounced = debounce(commit, 150);
|
|
78
|
+
|
|
79
|
+
const clamp01 = (n: number) => Math.min(1, Math.max(0, n));
|
|
80
|
+
|
|
81
|
+
function setFromPointer(e: PointerEvent) {
|
|
82
|
+
if (!areaEl) return;
|
|
83
|
+
const rect = areaEl.getBoundingClientRect();
|
|
84
|
+
hsv = {
|
|
85
|
+
h: hsv.h,
|
|
86
|
+
s: clamp01((e.clientX - rect.left) / rect.width),
|
|
87
|
+
v: clamp01(1 - (e.clientY - rect.top) / rect.height)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function onAreaPointerDown(e: PointerEvent) {
|
|
92
|
+
if (disabled || e.button !== 0) return;
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
areaEl?.focus();
|
|
95
|
+
areaEl?.setPointerCapture(e.pointerId);
|
|
96
|
+
setFromPointer(e);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function onAreaPointerMove(e: PointerEvent) {
|
|
100
|
+
if (areaEl?.hasPointerCapture(e.pointerId)) setFromPointer(e);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function onAreaPointerUp(e: PointerEvent) {
|
|
104
|
+
if (!areaEl?.hasPointerCapture(e.pointerId)) return;
|
|
105
|
+
areaEl.releasePointerCapture(e.pointerId);
|
|
106
|
+
commit();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function onAreaKeydown(e: KeyboardEvent) {
|
|
110
|
+
const step = e.shiftKey ? 0.1 : 0.01;
|
|
111
|
+
let { s, v } = hsv;
|
|
112
|
+
switch (e.key) {
|
|
113
|
+
case 'ArrowLeft':
|
|
114
|
+
s -= step;
|
|
115
|
+
break;
|
|
116
|
+
case 'ArrowRight':
|
|
117
|
+
s += step;
|
|
118
|
+
break;
|
|
119
|
+
case 'ArrowUp':
|
|
120
|
+
v += step;
|
|
121
|
+
break;
|
|
122
|
+
case 'ArrowDown':
|
|
123
|
+
v -= step;
|
|
124
|
+
break;
|
|
125
|
+
case 'PageUp':
|
|
126
|
+
v += 0.1;
|
|
127
|
+
break;
|
|
128
|
+
case 'PageDown':
|
|
129
|
+
v -= 0.1;
|
|
130
|
+
break;
|
|
131
|
+
default:
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
hsv = { h: hsv.h, s: clamp01(s), v: clamp01(v) };
|
|
136
|
+
commitDebounced();
|
|
6
137
|
}
|
|
7
138
|
|
|
8
|
-
|
|
139
|
+
function onHueInput(e: Event) {
|
|
140
|
+
hsv = { ...hsv, h: Number((e.currentTarget as HTMLInputElement).value) };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function applyHex(hex: string) {
|
|
144
|
+
hsv = parse(hex);
|
|
145
|
+
commit();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function commitDraft() {
|
|
149
|
+
const hex = normalizeHex(draft);
|
|
150
|
+
if (!hex) {
|
|
151
|
+
hexError = true;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
hexError = false;
|
|
155
|
+
applyHex(hex);
|
|
156
|
+
draft = hex;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function onHexKeydown(e: KeyboardEvent) {
|
|
160
|
+
if (e.key === 'Enter') {
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
commitDraft();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function onHexBlur() {
|
|
167
|
+
if (normalizeHex(draft)) commitDraft();
|
|
168
|
+
else {
|
|
169
|
+
draft = currentHex;
|
|
170
|
+
hexError = false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function pickFromScreen() {
|
|
175
|
+
if (!eyeDropperCtor) return;
|
|
176
|
+
try {
|
|
177
|
+
const { sRGBHex } = await new eyeDropperCtor().open();
|
|
178
|
+
applyHex(sRGBHex);
|
|
179
|
+
} catch {
|
|
180
|
+
// The user dismissed the eyedropper.
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const checkOn = (hex: string) =>
|
|
185
|
+
(contrastRatio(hex, '#000000') ?? 0) > (contrastRatio(hex, '#ffffff') ?? 0)
|
|
186
|
+
? 'text-black'
|
|
187
|
+
: 'text-white';
|
|
9
188
|
</script>
|
|
10
189
|
|
|
11
|
-
<
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
190
|
+
<Popover.Root>
|
|
191
|
+
<Popover.Trigger>
|
|
192
|
+
{#snippet child({ props })}
|
|
193
|
+
<button
|
|
194
|
+
{...props}
|
|
195
|
+
type="button"
|
|
196
|
+
id={inputId}
|
|
197
|
+
{disabled}
|
|
198
|
+
aria-label={formatMessage(t.colorPick, { color: currentHex })}
|
|
199
|
+
class="h-9 gap-2.5 px-2.5 shadow-xs max-w-48 flex w-full cursor-pointer items-center rounded-md border border-input bg-background text-left outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
|
200
|
+
>
|
|
201
|
+
<span
|
|
202
|
+
class="size-5 shrink-0 rounded-md bg-(--swatch) ring-1 ring-border ring-inset"
|
|
203
|
+
style:--swatch={currentHex}
|
|
204
|
+
></span>
|
|
205
|
+
<span class="font-mono text-sm text-muted-foreground">{currentHex}</span>
|
|
206
|
+
</button>
|
|
207
|
+
{/snippet}
|
|
208
|
+
</Popover.Trigger>
|
|
209
|
+
|
|
210
|
+
<Popover.Content align="start">
|
|
211
|
+
<div
|
|
212
|
+
bind:this={areaEl}
|
|
213
|
+
role="slider"
|
|
214
|
+
tabindex={disabled ? -1 : 0}
|
|
215
|
+
aria-label={t.colorArea}
|
|
216
|
+
aria-valuemin={0}
|
|
217
|
+
aria-valuemax={100}
|
|
218
|
+
aria-valuenow={Math.round(hsv.v * 100)}
|
|
219
|
+
aria-valuetext={formatMessage(t.colorAreaValue, {
|
|
220
|
+
s: Math.round(hsv.s * 100),
|
|
221
|
+
v: Math.round(hsv.v * 100)
|
|
222
|
+
})}
|
|
223
|
+
aria-disabled={disabled}
|
|
224
|
+
class="color-area h-36 relative w-full cursor-crosshair touch-none rounded-md outline-none focus-visible:ring-3 focus-visible:ring-ring"
|
|
225
|
+
style:--hue={hueColor}
|
|
226
|
+
onpointerdown={onAreaPointerDown}
|
|
227
|
+
onpointermove={onAreaPointerMove}
|
|
228
|
+
onpointerup={onAreaPointerUp}
|
|
229
|
+
onpointercancel={onAreaPointerUp}
|
|
230
|
+
onkeydown={onAreaKeydown}
|
|
231
|
+
>
|
|
232
|
+
<span
|
|
233
|
+
class="color-thumb size-4 border-white pointer-events-none absolute -translate-x-1/2 -translate-y-1/2 rounded-full border-2 bg-(--swatch)"
|
|
234
|
+
style:--x="{hsv.s * 100}%"
|
|
235
|
+
style:--y="{(1 - hsv.v) * 100}%"
|
|
236
|
+
style:--swatch={currentHex}
|
|
237
|
+
></span>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<input
|
|
241
|
+
type="range"
|
|
242
|
+
class="color-hue"
|
|
243
|
+
min="0"
|
|
244
|
+
max="360"
|
|
245
|
+
step="1"
|
|
246
|
+
aria-label={t.colorHue}
|
|
247
|
+
value={Math.round(hsv.h)}
|
|
248
|
+
{disabled}
|
|
249
|
+
oninput={onHueInput}
|
|
250
|
+
onchange={commit}
|
|
251
|
+
/>
|
|
252
|
+
|
|
253
|
+
<div class="gap-2 flex items-start">
|
|
254
|
+
<div class="min-w-0 flex-1">
|
|
255
|
+
<Input
|
|
256
|
+
type="text"
|
|
257
|
+
aria-label={t.colorHex}
|
|
258
|
+
aria-invalid={hexError}
|
|
259
|
+
aria-describedby={hexError ? `${inputId}-hex-error` : undefined}
|
|
260
|
+
autocomplete="off"
|
|
261
|
+
spellcheck={false}
|
|
262
|
+
maxlength={7}
|
|
263
|
+
{disabled}
|
|
264
|
+
bind:value={draft}
|
|
265
|
+
onkeydown={onHexKeydown}
|
|
266
|
+
onblur={onHexBlur}
|
|
267
|
+
/>
|
|
268
|
+
</div>
|
|
269
|
+
{#if eyeDropperCtor}
|
|
270
|
+
<button
|
|
271
|
+
type="button"
|
|
272
|
+
{disabled}
|
|
273
|
+
aria-label={t.colorEyedropper}
|
|
274
|
+
title={t.colorEyedropper}
|
|
275
|
+
class="size-9 flex shrink-0 cursor-pointer items-center justify-center rounded-md border border-input bg-background outline-none hover:bg-hover focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
|
276
|
+
onclick={pickFromScreen}
|
|
277
|
+
>
|
|
278
|
+
<Pipette class="size-4" aria-hidden="true" />
|
|
279
|
+
</button>
|
|
280
|
+
{/if}
|
|
281
|
+
</div>
|
|
282
|
+
{#if hexError}
|
|
283
|
+
<p id="{inputId}-hex-error" role="alert" class="text-xs text-destructive">
|
|
284
|
+
{t.colorHexInvalid}
|
|
285
|
+
</p>
|
|
286
|
+
{/if}
|
|
287
|
+
|
|
288
|
+
<div role="group" aria-label={t.colorPresets} class="gap-1.5 grid grid-cols-6">
|
|
289
|
+
{#each PRESETS as preset (preset)}
|
|
290
|
+
{@const selected = preset === currentHex}
|
|
291
|
+
<button
|
|
292
|
+
type="button"
|
|
293
|
+
{disabled}
|
|
294
|
+
aria-label={preset}
|
|
295
|
+
aria-pressed={selected}
|
|
296
|
+
class="h-6 flex cursor-pointer items-center justify-center rounded-md bg-(--swatch) ring-1 ring-border outline-none ring-inset focus-visible:ring-3 focus-visible:ring-ring disabled:cursor-not-allowed"
|
|
297
|
+
style:--swatch={preset}
|
|
298
|
+
onclick={() => applyHex(preset)}
|
|
299
|
+
>
|
|
300
|
+
{#if selected}
|
|
301
|
+
<Check class="size-3.5 {checkOn(preset)}" aria-hidden="true" />
|
|
302
|
+
{/if}
|
|
303
|
+
</button>
|
|
304
|
+
{/each}
|
|
305
|
+
</div>
|
|
306
|
+
</Popover.Content>
|
|
307
|
+
</Popover.Root>
|
|
308
|
+
|
|
309
|
+
<style>
|
|
310
|
+
.color-area {
|
|
311
|
+
background-color: var(--hue);
|
|
312
|
+
background-image:
|
|
313
|
+
linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent);
|
|
314
|
+
}
|
|
315
|
+
.color-thumb {
|
|
316
|
+
left: var(--x);
|
|
317
|
+
top: var(--y);
|
|
318
|
+
box-shadow: 0 0 0 1px rgb(0 0 0 / 0.4);
|
|
319
|
+
}
|
|
320
|
+
.color-hue {
|
|
321
|
+
appearance: none;
|
|
322
|
+
-webkit-appearance: none;
|
|
323
|
+
height: 0.75rem;
|
|
324
|
+
width: 100%;
|
|
325
|
+
margin: 0;
|
|
326
|
+
border-radius: 9999px;
|
|
327
|
+
cursor: pointer;
|
|
328
|
+
outline: none;
|
|
329
|
+
background: linear-gradient(
|
|
330
|
+
to right,
|
|
331
|
+
#f00 0%,
|
|
332
|
+
#ff0 16.67%,
|
|
333
|
+
#0f0 33.33%,
|
|
334
|
+
#0ff 50%,
|
|
335
|
+
#00f 66.67%,
|
|
336
|
+
#f0f 83.33%,
|
|
337
|
+
#f00 100%
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
.color-hue::-webkit-slider-thumb {
|
|
341
|
+
-webkit-appearance: none;
|
|
342
|
+
height: 1rem;
|
|
343
|
+
width: 1rem;
|
|
344
|
+
border-radius: 9999px;
|
|
345
|
+
border: 2px solid #fff;
|
|
346
|
+
background: transparent;
|
|
347
|
+
box-shadow: 0 0 0 1px rgb(0 0 0 / 0.4);
|
|
348
|
+
}
|
|
349
|
+
.color-hue::-moz-range-thumb {
|
|
350
|
+
height: 1rem;
|
|
351
|
+
width: 1rem;
|
|
352
|
+
box-sizing: border-box;
|
|
353
|
+
border-radius: 9999px;
|
|
354
|
+
border: 2px solid #fff;
|
|
355
|
+
background: transparent;
|
|
356
|
+
box-shadow: 0 0 0 1px rgb(0 0 0 / 0.4);
|
|
357
|
+
}
|
|
358
|
+
.color-hue:focus-visible {
|
|
359
|
+
box-shadow: 0 0 0 3px var(--ring);
|
|
360
|
+
}
|
|
361
|
+
.color-hue:disabled {
|
|
362
|
+
cursor: not-allowed;
|
|
363
|
+
opacity: 0.5;
|
|
364
|
+
}
|
|
365
|
+
</style>
|
|
@@ -282,10 +282,10 @@
|
|
|
282
282
|
type="button"
|
|
283
283
|
onclick={() => (activeMode = mode)}
|
|
284
284
|
aria-pressed={activeMode === mode}
|
|
285
|
-
class={`px-3 py-1 font-medium flex-1 rounded-sm transition-colors ${
|
|
285
|
+
class={`px-3 py-1 font-medium flex-1 rounded-sm border transition-colors ${
|
|
286
286
|
activeMode === mode
|
|
287
|
-
? 'shadow-xs bg-
|
|
288
|
-
: 'text-muted-foreground hover:text-foreground'
|
|
287
|
+
? 'shadow-xs border-border-strong bg-raised text-foreground'
|
|
288
|
+
: 'border-transparent text-muted-foreground hover:text-foreground'
|
|
289
289
|
}`}
|
|
290
290
|
>
|
|
291
291
|
{mode === 'upload' ? t.fileModeUpload : t.fileModeUrl}
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
onkeydown={(e) => onKeydown(e, index)}
|
|
54
54
|
class="gap-1.5 p-1.5 min-w-0 flex flex-col rounded-lg border text-left transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 {selected
|
|
55
55
|
? 'border-primary bg-primary/5 ring-1 ring-primary'
|
|
56
|
-
: 'border-input hover:bg-
|
|
56
|
+
: 'border-input hover:bg-hover'}"
|
|
57
57
|
>
|
|
58
58
|
<span
|
|
59
59
|
class="flex aspect-square w-full items-center justify-center overflow-hidden rounded-md bg-muted text-muted-foreground"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
});
|
|
39
39
|
</script>
|
|
40
40
|
|
|
41
|
-
<div class="bottom-0 mt-3 pb-3 pt-2 backdrop-blur-sm px-2 sticky border-t border-border
|
|
41
|
+
<div class="bottom-0 mt-3 pb-3 pt-2 backdrop-blur-sm px-2 sticky border-t border-border">
|
|
42
42
|
<span class="sr-only" role="status" aria-live="polite">{announcement}</span>
|
|
43
43
|
<div class="gap-2 flex">
|
|
44
44
|
<Button
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<Loader class="h-4 w-4 animate-spin" />
|
|
56
56
|
{t.solvingEllipsis}
|
|
57
57
|
<kbd
|
|
58
|
-
class="px-1 font-sans rounded border border-current/30 text-2xs opacity-70"
|
|
58
|
+
class="px-1 font-sans rounded-sm border border-current/30 text-2xs opacity-70"
|
|
59
59
|
title={t.solveMessagesEscHint}
|
|
60
60
|
>
|
|
61
61
|
Esc
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
variants: {
|
|
9
9
|
tone: {
|
|
10
10
|
info: 'border-info/40 bg-info/10',
|
|
11
|
-
tip: 'border-border bg-muted
|
|
11
|
+
tip: 'border-border bg-muted',
|
|
12
12
|
success: 'border-success/40 bg-success/10',
|
|
13
13
|
warning: 'border-warning/40 bg-warning/10',
|
|
14
14
|
danger: 'border-destructive/40 bg-destructive/10'
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
title?: string;
|
|
39
39
|
/** Replaces the tone's default icon. `null` drops the icon entirely. */
|
|
40
40
|
icon?: Component | null;
|
|
41
|
-
children
|
|
41
|
+
children?: Snippet;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
let { tone = 'info', title, icon, class: className, children, ...restProps }: Props = $props();
|
|
@@ -59,8 +59,10 @@
|
|
|
59
59
|
{#if title}
|
|
60
60
|
<p class={cn('leading-tight font-medium', accent)}>{title}</p>
|
|
61
61
|
{/if}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
{#if children}
|
|
63
|
+
<div class="leading-relaxed text-muted-foreground [&_a]:underline [&_strong]:text-foreground">
|
|
64
|
+
{@render children()}
|
|
65
|
+
</div>
|
|
66
|
+
{/if}
|
|
65
67
|
</div>
|
|
66
68
|
</div>
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
style:--table-cols-sm={mobileTemplate}
|
|
42
42
|
>
|
|
43
43
|
<div
|
|
44
|
-
class="data-table-row gap-4 px-4 py-2 text-xs font-medium tracking-wide sm:grid-cols-(--table-cols) grid grid-cols-(--table-cols-sm) bg-muted
|
|
44
|
+
class="data-table-row gap-4 px-4 py-2 text-xs font-medium tracking-wide sm:grid-cols-(--table-cols) grid grid-cols-(--table-cols-sm) bg-muted text-muted-foreground uppercase {hiddenCols}"
|
|
45
45
|
>
|
|
46
46
|
{#each columns as col (col.label)}
|
|
47
47
|
<span class={col.align === 'right' ? 'text-right' : ''}>{col.label}</span>
|