@dorsk/tsumikit 0.38.0 → 0.39.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/dist/autoresize.d.ts +2 -0
- package/dist/autoresize.js +15 -1
- package/dist/components/atoms/Artwork.svelte +19 -18
- package/dist/components/atoms/Artwork.svelte.d.ts +3 -2
- package/dist/components/atoms/Badge.svelte +60 -26
- package/dist/components/atoms/Badge.svelte.d.ts +14 -3
- package/dist/components/atoms/Button.svelte +30 -12
- package/dist/components/atoms/Button.svelte.d.ts +4 -2
- package/dist/components/atoms/Card.svelte +47 -30
- package/dist/components/atoms/Card.svelte.d.ts +12 -3
- package/dist/components/atoms/Checkbox.svelte +16 -2
- package/dist/components/atoms/Checkbox.svelte.d.ts +2 -0
- package/dist/components/atoms/Dot.svelte +17 -11
- package/dist/components/atoms/Dot.svelte.d.ts +5 -2
- package/dist/components/atoms/Gauge.svelte +19 -18
- package/dist/components/atoms/Gauge.svelte.d.ts +3 -2
- package/dist/components/atoms/Heading.svelte +20 -19
- package/dist/components/atoms/Heading.svelte.d.ts +3 -2
- package/dist/components/atoms/Icon.svelte +33 -13
- package/dist/components/atoms/Icon.svelte.d.ts +17 -2
- package/dist/components/atoms/Input.svelte +17 -3
- package/dist/components/atoms/Input.svelte.d.ts +2 -1
- package/dist/components/atoms/Kbd.svelte +25 -3
- package/dist/components/atoms/Kbd.svelte.d.ts +5 -1
- package/dist/components/atoms/Link.svelte +16 -12
- package/dist/components/atoms/Link.svelte.d.ts +6 -2
- package/dist/components/atoms/Progress.svelte +119 -4
- package/dist/components/atoms/Progress.svelte.d.ts +28 -2
- package/dist/components/atoms/Scrim.svelte +7 -2
- package/dist/components/atoms/Scrim.svelte.d.ts +2 -0
- package/dist/components/atoms/SegmentedProgress.svelte +14 -2
- package/dist/components/atoms/SegmentedProgress.svelte.d.ts +5 -2
- package/dist/components/atoms/Select.svelte +18 -6
- package/dist/components/atoms/Select.svelte.d.ts +3 -3
- package/dist/components/atoms/Skeleton.svelte +12 -11
- package/dist/components/atoms/Skeleton.svelte.d.ts +3 -2
- package/dist/components/atoms/Slider.svelte +45 -3
- package/dist/components/atoms/Slider.svelte.d.ts +7 -0
- package/dist/components/atoms/Spinner.svelte +2 -0
- package/dist/components/atoms/Spinner.svelte.d.ts +2 -0
- package/dist/components/atoms/Switch.svelte +70 -18
- package/dist/components/atoms/Switch.svelte.d.ts +5 -1
- package/dist/components/atoms/Text.svelte +39 -26
- package/dist/components/atoms/Text.svelte.d.ts +7 -3
- package/dist/components/atoms/Textarea.svelte +47 -10
- package/dist/components/atoms/Textarea.svelte.d.ts +10 -3
- package/dist/components/layouts/AppShell.svelte +7 -3
- package/dist/components/layouts/AppShell.svelte.d.ts +2 -0
- package/dist/components/layouts/AutoGrid.svelte +4 -0
- package/dist/components/layouts/AutoGrid.svelte.d.ts +2 -0
- package/dist/components/layouts/Cluster.svelte +62 -1
- package/dist/components/layouts/Cluster.svelte.d.ts +9 -0
- package/dist/components/layouts/NavItem.svelte +22 -1
- package/dist/components/layouts/NavItem.svelte.d.ts +5 -0
- package/dist/components/layouts/NavSection.svelte +4 -1
- package/dist/components/layouts/NavSection.svelte.d.ts +2 -0
- package/dist/components/layouts/ResizablePanel.svelte +14 -3
- package/dist/components/layouts/ResizablePanel.svelte.d.ts +5 -0
- package/dist/components/layouts/Stack.svelte +41 -0
- package/dist/components/layouts/Stack.svelte.d.ts +9 -0
- package/dist/components/layouts/Toolbar.svelte +122 -0
- package/dist/components/layouts/Toolbar.svelte.d.ts +22 -0
- package/dist/components/molecules/AttachmentList.svelte +59 -0
- package/dist/components/molecules/AttachmentList.svelte.d.ts +13 -0
- package/dist/components/molecules/Breadcrumb.svelte +6 -2
- package/dist/components/molecules/Breadcrumb.svelte.d.ts +2 -0
- package/dist/components/molecules/Callout.svelte +10 -4
- package/dist/components/molecules/Callout.svelte.d.ts +1 -1
- package/dist/components/molecules/CapBar.svelte +5 -1
- package/dist/components/molecules/ChatBubble.svelte +158 -0
- package/dist/components/molecules/ChatBubble.svelte.d.ts +26 -0
- package/dist/components/molecules/CodeBlock.svelte +36 -3
- package/dist/components/molecules/CodeBlock.svelte.d.ts +8 -0
- package/dist/components/molecules/Composer.svelte +195 -0
- package/dist/components/molecules/Composer.svelte.d.ts +27 -0
- package/dist/components/molecules/ConfirmModal.svelte +15 -5
- package/dist/components/molecules/ConfirmModal.svelte.d.ts +5 -1
- package/dist/components/molecules/Dropzone.svelte +9 -3
- package/dist/components/molecules/Dropzone.svelte.d.ts +2 -0
- package/dist/components/molecules/EmptyState.svelte +9 -5
- package/dist/components/molecules/EmptyState.svelte.d.ts +3 -1
- package/dist/components/molecules/Field.svelte +7 -1
- package/dist/components/molecules/Field.svelte.d.ts +2 -0
- package/dist/components/molecules/FileButton.svelte +2 -1
- package/dist/components/molecules/FileButton.svelte.d.ts +2 -1
- package/dist/components/molecules/FilterInput.svelte +13 -3
- package/dist/components/molecules/FilterInput.svelte.d.ts +4 -1
- package/dist/components/molecules/FontScalePicker.svelte +9 -4
- package/dist/components/molecules/IconButton.svelte +32 -7
- package/dist/components/molecules/IconButton.svelte.d.ts +9 -1
- package/dist/components/molecules/KeyValue.svelte +4 -1
- package/dist/components/molecules/KeyValue.svelte.d.ts +2 -1
- package/dist/components/molecules/Menu.svelte +50 -5
- package/dist/components/molecules/Menu.svelte.d.ts +10 -1
- package/dist/components/molecules/Meter.svelte +91 -0
- package/dist/components/molecules/Meter.svelte.d.ts +29 -0
- package/dist/components/molecules/Metric.svelte +134 -8
- package/dist/components/molecules/Metric.svelte.d.ts +20 -2
- package/dist/components/molecules/Modal.svelte +26 -12
- package/dist/components/molecules/Modal.svelte.d.ts +7 -1
- package/dist/components/molecules/Pagination.svelte +25 -1
- package/dist/components/molecules/Pagination.svelte.d.ts +9 -2
- package/dist/components/molecules/Popover.svelte +14 -3
- package/dist/components/molecules/Popover.svelte.d.ts +5 -0
- package/dist/components/molecules/Prose.svelte +140 -0
- package/dist/components/molecules/Prose.svelte.d.ts +13 -0
- package/dist/components/molecules/RadioGroup.svelte +42 -2
- package/dist/components/molecules/RadioGroup.svelte.d.ts +4 -1
- package/dist/components/molecules/SectionHeader.svelte +5 -2
- package/dist/components/molecules/SectionHeader.svelte.d.ts +1 -1
- package/dist/components/molecules/SegmentedControl.svelte +36 -1
- package/dist/components/molecules/SegmentedControl.svelte.d.ts +11 -1
- package/dist/components/molecules/SelectButton.svelte +64 -4
- package/dist/components/molecules/SelectButton.svelte.d.ts +18 -1
- package/dist/components/molecules/Tabs.svelte +21 -3
- package/dist/components/molecules/Tabs.svelte.d.ts +6 -0
- package/dist/components/molecules/Timestamp.svelte +13 -6
- package/dist/components/molecules/Timestamp.svelte.d.ts +4 -0
- package/dist/components/molecules/Toaster.svelte +54 -38
- package/dist/components/molecules/Toaster.svelte.d.ts +5 -1
- package/dist/components/molecules/Toggle.svelte +2 -1
- package/dist/components/molecules/Toggle.svelte.d.ts +2 -1
- package/dist/components/molecules/Tooltip.svelte +32 -5
- package/dist/components/molecules/Tooltip.svelte.d.ts +9 -0
- package/dist/components/molecules/Truncate.svelte +156 -18
- package/dist/components/molecules/Truncate.svelte.d.ts +17 -1
- package/dist/components/molecules/WorkingDir.svelte +6 -0
- package/dist/components/molecules/WorkingDir.svelte.d.ts +2 -0
- package/dist/components/organisms/DataTable.svelte +38 -10
- package/dist/components/organisms/DataTable.svelte.d.ts +4 -0
- package/dist/components/organisms/FilterSearchBar.svelte +9 -2
- package/dist/components/organisms/FilterSearchBar.svelte.d.ts +4 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.js +8 -1
- package/dist/size.d.ts +2 -0
- package/dist/size.js +1 -0
- package/dist/styles/tokens.css +3 -0
- package/dist/timestamp.d.ts +2 -2
- package/dist/timestamp.js +4 -4
- package/dist/tone.d.ts +1 -1
- package/dist/tone.js +1 -1
- package/dist/truncate.d.ts +13 -1
- package/dist/truncate.js +39 -0
- package/package.json +5 -3
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { ControlSize } from '../../size';
|
|
3
|
+
import { canonicalTone, type Tone } from '../../tone';
|
|
2
4
|
// Progress bar. Determinate when `value` is a number (0..max); omit `value`
|
|
3
5
|
// (or pass `indeterminate`) for an indeterminate animation. Uses
|
|
4
6
|
// role="progressbar" with the right aria-value* attributes. Token-styled.
|
|
@@ -16,8 +18,17 @@
|
|
|
16
18
|
size = 'md',
|
|
17
19
|
gradient = false,
|
|
18
20
|
striped = false,
|
|
21
|
+
grow = false,
|
|
22
|
+
shrink = true,
|
|
23
|
+
block = false,
|
|
19
24
|
indeterminate: indeterminateProp = false,
|
|
20
|
-
|
|
25
|
+
markers = [],
|
|
26
|
+
toneAt,
|
|
27
|
+
color,
|
|
28
|
+
showValue = false,
|
|
29
|
+
format = (v: number, m: number) => `${Math.round((v / m) * 100)}%`,
|
|
30
|
+
class: klass = '',
|
|
31
|
+
...rest
|
|
21
32
|
}: {
|
|
22
33
|
value?: number;
|
|
23
34
|
max?: number;
|
|
@@ -25,27 +36,57 @@
|
|
|
25
36
|
// Fill colour. `accent` is the default brand fill; the semantic tones
|
|
26
37
|
// retint the bar for severity (e.g. usage meters going warm/hot).
|
|
27
38
|
// `ok` and `success` are aliases.
|
|
28
|
-
tone?:
|
|
39
|
+
tone?: Tone;
|
|
29
40
|
// Track height. `sm` is a thin ~5px track for inline rows.
|
|
30
|
-
size?:
|
|
41
|
+
size?: ControlSize;
|
|
42
|
+
/** Fill the free space of a flex row (`flex: 1 1 0`). */
|
|
43
|
+
grow?: boolean;
|
|
44
|
+
/** `false` pins the box (`flex: none`) so a flex row cannot squeeze it. */
|
|
45
|
+
shrink?: boolean;
|
|
46
|
+
/** Full-width block. */
|
|
47
|
+
block?: boolean;
|
|
31
48
|
// Accent→teal gradient fill (overrides the flat tone colour).
|
|
32
49
|
gradient?: boolean;
|
|
33
50
|
// Diagonal stripes; animated in indeterminate mode.
|
|
34
51
|
striped?: boolean;
|
|
35
52
|
// Force indeterminate mode even when a `value` is supplied.
|
|
36
53
|
indeterminate?: boolean;
|
|
54
|
+
/** Thin vertical lines at `at / max` (caps, thresholds). */
|
|
55
|
+
markers?: { at: number; label?: string; tone?: Tone }[];
|
|
56
|
+
/** Percent thresholds that auto-pick warn/danger; an explicit `tone` other
|
|
57
|
+
* than the default `accent` wins. */
|
|
58
|
+
toneAt?: { warn?: number; danger?: number };
|
|
59
|
+
/** Any CSS colour for the fill; wins over `tone`. */
|
|
60
|
+
color?: string;
|
|
61
|
+
/** Trailing numeric readout after the track. */
|
|
62
|
+
showValue?: boolean;
|
|
63
|
+
format?: (value: number, max: number) => string;
|
|
37
64
|
class?: string;
|
|
65
|
+
[key: string]: unknown;
|
|
38
66
|
} = $props();
|
|
39
67
|
|
|
40
68
|
const pct = $derived(value == null ? 0 : Math.max(0, Math.min(100, (value / max) * 100)));
|
|
41
69
|
const indeterminate = $derived(indeterminateProp || value == null);
|
|
42
|
-
const
|
|
70
|
+
const autoTone = $derived.by((): Tone => {
|
|
71
|
+
if (!toneAt || tone !== 'accent' || indeterminate) return tone;
|
|
72
|
+
if (toneAt.danger !== undefined && pct >= toneAt.danger) return 'danger';
|
|
73
|
+
if (toneAt.warn !== undefined && pct >= toneAt.warn) return 'warn';
|
|
74
|
+
return tone;
|
|
75
|
+
});
|
|
76
|
+
const toneClass = $derived(canonicalTone(autoTone) === 'ok' ? 'success' : canonicalTone(autoTone));
|
|
77
|
+
const markerPct = (at: number) => Math.max(0, Math.min(100, (at / max) * 100));
|
|
43
78
|
</script>
|
|
44
79
|
|
|
80
|
+
{#snippet track()}
|
|
45
81
|
<div
|
|
46
82
|
data-tsu="Progress"
|
|
47
83
|
class="progress tone-{toneClass} size-{size} {klass}"
|
|
84
|
+
class:grow={grow}
|
|
85
|
+
class:no-shrink={!shrink}
|
|
86
|
+
class:block={block}
|
|
48
87
|
class:indeterminate
|
|
88
|
+
style:--fill={color}
|
|
89
|
+
{...rest}
|
|
49
90
|
class:gradient
|
|
50
91
|
class:striped
|
|
51
92
|
role="progressbar"
|
|
@@ -55,10 +96,54 @@
|
|
|
55
96
|
aria-valuenow={indeterminate ? undefined : value}
|
|
56
97
|
>
|
|
57
98
|
<div class="bar" style={indeterminate ? undefined : `width: ${pct}%`}></div>
|
|
99
|
+
{#each markers as m (m.at)}
|
|
100
|
+
<span
|
|
101
|
+
class="marker tone-{m.tone ? canonicalTone(m.tone) : 'text'}"
|
|
102
|
+
style="left: {markerPct(m.at)}%"
|
|
103
|
+
title={m.label}
|
|
104
|
+
aria-hidden="true"
|
|
105
|
+
></span>
|
|
106
|
+
{/each}
|
|
58
107
|
</div>
|
|
108
|
+
{/snippet}
|
|
109
|
+
|
|
110
|
+
{#if showValue}
|
|
111
|
+
<span class="progress-row" class:grow={grow} class:no-shrink={!shrink} class:block={block}>
|
|
112
|
+
{@render track()}
|
|
113
|
+
<span class="progress-value">{indeterminate || value == null ? '' : format(value, max)}</span>
|
|
114
|
+
</span>
|
|
115
|
+
{:else}
|
|
116
|
+
{@render track()}
|
|
117
|
+
{/if}
|
|
59
118
|
|
|
60
119
|
<style>
|
|
120
|
+
.progress-row {
|
|
121
|
+
display: inline-flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
gap: var(--sp-2);
|
|
124
|
+
width: 100%;
|
|
125
|
+
}
|
|
126
|
+
.progress-value {
|
|
127
|
+
flex: none;
|
|
128
|
+
min-width: 3ch;
|
|
129
|
+
text-align: right;
|
|
130
|
+
font-size: var(--fs-xs);
|
|
131
|
+
font-variant-numeric: tabular-nums;
|
|
132
|
+
color: var(--text-muted);
|
|
133
|
+
}
|
|
134
|
+
.grow {
|
|
135
|
+
flex: 1 1 0;
|
|
136
|
+
min-width: 0;
|
|
137
|
+
}
|
|
138
|
+
.no-shrink {
|
|
139
|
+
flex: none;
|
|
140
|
+
}
|
|
141
|
+
.block {
|
|
142
|
+
display: flex;
|
|
143
|
+
width: 100%;
|
|
144
|
+
}
|
|
61
145
|
.progress {
|
|
146
|
+
position: relative;
|
|
62
147
|
width: 100%;
|
|
63
148
|
height: 0.5rem;
|
|
64
149
|
background: var(--bg-elevated-2);
|
|
@@ -74,9 +159,39 @@
|
|
|
74
159
|
border-radius: inherit;
|
|
75
160
|
transition: width 0.2s var(--ease);
|
|
76
161
|
}
|
|
162
|
+
.marker {
|
|
163
|
+
position: absolute;
|
|
164
|
+
top: 0;
|
|
165
|
+
bottom: 0;
|
|
166
|
+
width: 2px;
|
|
167
|
+
transform: translateX(-50%);
|
|
168
|
+
background: var(--marker, var(--text));
|
|
169
|
+
pointer-events: none;
|
|
170
|
+
}
|
|
171
|
+
.marker.tone-ok {
|
|
172
|
+
--marker: var(--ok);
|
|
173
|
+
}
|
|
174
|
+
.marker.tone-warn {
|
|
175
|
+
--marker: var(--warn);
|
|
176
|
+
}
|
|
177
|
+
.marker.tone-danger {
|
|
178
|
+
--marker: var(--danger);
|
|
179
|
+
}
|
|
180
|
+
.marker.tone-info {
|
|
181
|
+
--marker: var(--info);
|
|
182
|
+
}
|
|
183
|
+
.marker.tone-accent {
|
|
184
|
+
--marker: var(--accent);
|
|
185
|
+
}
|
|
77
186
|
.tone-success {
|
|
78
187
|
--fill: var(--ok);
|
|
79
188
|
}
|
|
189
|
+
.tone-info {
|
|
190
|
+
--fill: var(--info);
|
|
191
|
+
}
|
|
192
|
+
.tone-neutral {
|
|
193
|
+
--fill: var(--text-faint);
|
|
194
|
+
}
|
|
80
195
|
.tone-warn {
|
|
81
196
|
--fill: var(--warn);
|
|
82
197
|
}
|
|
@@ -1,13 +1,39 @@
|
|
|
1
|
+
import type { ControlSize } from '../../size';
|
|
2
|
+
import { type Tone } from '../../tone';
|
|
1
3
|
type $$ComponentProps = {
|
|
2
4
|
value?: number;
|
|
3
5
|
max?: number;
|
|
4
6
|
label?: string;
|
|
5
|
-
tone?:
|
|
6
|
-
size?:
|
|
7
|
+
tone?: Tone;
|
|
8
|
+
size?: ControlSize;
|
|
9
|
+
/** Fill the free space of a flex row (`flex: 1 1 0`). */
|
|
10
|
+
grow?: boolean;
|
|
11
|
+
/** `false` pins the box (`flex: none`) so a flex row cannot squeeze it. */
|
|
12
|
+
shrink?: boolean;
|
|
13
|
+
/** Full-width block. */
|
|
14
|
+
block?: boolean;
|
|
7
15
|
gradient?: boolean;
|
|
8
16
|
striped?: boolean;
|
|
9
17
|
indeterminate?: boolean;
|
|
18
|
+
/** Thin vertical lines at `at / max` (caps, thresholds). */
|
|
19
|
+
markers?: {
|
|
20
|
+
at: number;
|
|
21
|
+
label?: string;
|
|
22
|
+
tone?: Tone;
|
|
23
|
+
}[];
|
|
24
|
+
/** Percent thresholds that auto-pick warn/danger; an explicit `tone` other
|
|
25
|
+
* than the default `accent` wins. */
|
|
26
|
+
toneAt?: {
|
|
27
|
+
warn?: number;
|
|
28
|
+
danger?: number;
|
|
29
|
+
};
|
|
30
|
+
/** Any CSS colour for the fill; wins over `tone`. */
|
|
31
|
+
color?: string;
|
|
32
|
+
/** Trailing numeric readout after the track. */
|
|
33
|
+
showValue?: boolean;
|
|
34
|
+
format?: (value: number, max: number) => string;
|
|
10
35
|
class?: string;
|
|
36
|
+
[key: string]: unknown;
|
|
11
37
|
};
|
|
12
38
|
declare const Progress: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
39
|
type Progress = ReturnType<typeof Progress>;
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
onclose,
|
|
6
6
|
hideBelow,
|
|
7
7
|
z = 'var(--z-drawer)',
|
|
8
|
-
label = 'Close'
|
|
8
|
+
label = 'Close',
|
|
9
|
+
class: klass = '',
|
|
10
|
+
style: styleProp = '',
|
|
9
11
|
}: {
|
|
10
12
|
/** Called on click anywhere on the scrim and on Escape (document-level). */
|
|
11
13
|
onclose?: () => void;
|
|
@@ -16,6 +18,8 @@
|
|
|
16
18
|
z?: string | number;
|
|
17
19
|
/** Accessible name of the click target. */
|
|
18
20
|
label?: string;
|
|
21
|
+
class?: string;
|
|
22
|
+
style?: string;
|
|
19
23
|
} = $props();
|
|
20
24
|
|
|
21
25
|
let hidden = $state(false);
|
|
@@ -49,7 +53,8 @@
|
|
|
49
53
|
{#if !hidden}
|
|
50
54
|
<button
|
|
51
55
|
type="button"
|
|
52
|
-
class="scrim"
|
|
56
|
+
class="scrim {klass}"
|
|
57
|
+
style={styleProp}
|
|
53
58
|
style:z-index={z}
|
|
54
59
|
aria-label={label}
|
|
55
60
|
tabindex="-1"
|
|
@@ -8,6 +8,8 @@ type $$ComponentProps = {
|
|
|
8
8
|
z?: string | number;
|
|
9
9
|
/** Accessible name of the click target. */
|
|
10
10
|
label?: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
style?: string;
|
|
11
13
|
};
|
|
12
14
|
declare const Scrim: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
15
|
type Scrim = ReturnType<typeof Scrim>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
+
import type { Tone } from '../../tone';
|
|
2
3
|
// One bar split into segments, each with its own tone. Two modes:
|
|
3
4
|
// • segments (default): widths ∝ `max`, each filled value/max, thin gaps.
|
|
4
5
|
// • stacked: one shared track, widths ∝ `value` (Σvalue = full width, or
|
|
@@ -10,7 +11,7 @@
|
|
|
10
11
|
max: number;
|
|
11
12
|
// Fill colour per segment. `ok` is an alias of `success`; `muted` renders a
|
|
12
13
|
// faint fill for empty parts.
|
|
13
|
-
tone?:
|
|
14
|
+
tone?: Tone | 'muted';
|
|
14
15
|
// Native tooltip / accessible name / legend caption for the segment.
|
|
15
16
|
label?: string;
|
|
16
17
|
};
|
|
@@ -21,11 +22,14 @@
|
|
|
21
22
|
ok: 'var(--ok)',
|
|
22
23
|
warn: 'var(--warn)',
|
|
23
24
|
danger: 'var(--danger)',
|
|
25
|
+
info: 'var(--info)',
|
|
26
|
+
neutral: 'var(--text-faint)',
|
|
24
27
|
muted: 'var(--text-faint)',
|
|
25
28
|
};
|
|
26
29
|
</script>
|
|
27
30
|
|
|
28
31
|
<script lang="ts">
|
|
32
|
+
import type { ControlSize } from '../../size';
|
|
29
33
|
import type { Snippet } from 'svelte';
|
|
30
34
|
import Dot from './Dot.svelte';
|
|
31
35
|
import Text from './Text.svelte';
|
|
@@ -39,11 +43,12 @@
|
|
|
39
43
|
max,
|
|
40
44
|
legend = false,
|
|
41
45
|
class: klass = '',
|
|
46
|
+
...rest
|
|
42
47
|
}: {
|
|
43
48
|
segments: ProgressSegment[];
|
|
44
49
|
label?: string;
|
|
45
50
|
// Track height. `sm` is a thin ~5px track for inline rows.
|
|
46
|
-
size?:
|
|
51
|
+
size?: ControlSize;
|
|
47
52
|
mode?: 'segments' | 'stacked';
|
|
48
53
|
// Space between segments in `segments` mode; a bare number is px.
|
|
49
54
|
gap?: number | string;
|
|
@@ -53,6 +58,7 @@
|
|
|
53
58
|
// `true` = 'below'. A snippet receives the segments for custom rendering.
|
|
54
59
|
legend?: boolean | 'inline' | 'below' | Snippet<[ProgressSegment[]]>;
|
|
55
60
|
class?: string;
|
|
61
|
+
[key: string]: unknown;
|
|
56
62
|
} = $props();
|
|
57
63
|
|
|
58
64
|
const stacked = $derived(mode === 'stacked');
|
|
@@ -90,6 +96,7 @@
|
|
|
90
96
|
<div
|
|
91
97
|
data-tsu="SegmentedProgress"
|
|
92
98
|
class="segmented-progress stacked size-{size} {rootClass}"
|
|
99
|
+
{...rest}
|
|
93
100
|
style="gap: {gapCss}"
|
|
94
101
|
role="img"
|
|
95
102
|
aria-label={stackedLabel}
|
|
@@ -107,6 +114,7 @@
|
|
|
107
114
|
<div
|
|
108
115
|
data-tsu="SegmentedProgress"
|
|
109
116
|
class="segmented-progress size-{size} {rootClass}"
|
|
117
|
+
{...rest}
|
|
110
118
|
style="gap: {gapCss}"
|
|
111
119
|
role="progressbar"
|
|
112
120
|
aria-label={label}
|
|
@@ -186,6 +194,10 @@
|
|
|
186
194
|
.tone-danger {
|
|
187
195
|
--fill: var(--danger);
|
|
188
196
|
}
|
|
197
|
+
.tone-info {
|
|
198
|
+
--seg-fill: var(--info);
|
|
199
|
+
}
|
|
200
|
+
.tone-neutral,
|
|
189
201
|
.tone-muted {
|
|
190
202
|
--fill: var(--text-faint);
|
|
191
203
|
}
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
+
import type { Tone } from '../../tone';
|
|
1
2
|
export type ProgressSegment = {
|
|
2
3
|
value: number;
|
|
3
4
|
max: number;
|
|
4
|
-
tone?:
|
|
5
|
+
tone?: Tone | 'muted';
|
|
5
6
|
label?: string;
|
|
6
7
|
};
|
|
7
8
|
export declare const TONE_FILL: Record<NonNullable<ProgressSegment['tone']>, string>;
|
|
9
|
+
import type { ControlSize } from '../../size';
|
|
8
10
|
import type { Snippet } from 'svelte';
|
|
9
11
|
type $$ComponentProps = {
|
|
10
12
|
segments: ProgressSegment[];
|
|
11
13
|
label?: string;
|
|
12
|
-
size?:
|
|
14
|
+
size?: ControlSize;
|
|
13
15
|
mode?: 'segments' | 'stacked';
|
|
14
16
|
gap?: number | string;
|
|
15
17
|
max?: number;
|
|
16
18
|
legend?: boolean | 'inline' | 'below' | Snippet<[ProgressSegment[]]>;
|
|
17
19
|
class?: string;
|
|
20
|
+
[key: string]: unknown;
|
|
18
21
|
};
|
|
19
22
|
declare const SegmentedProgress: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
20
23
|
type SegmentedProgress = ReturnType<typeof SegmentedProgress>;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<script lang="ts">
|
|
16
|
+
import type { ControlSize } from '../../size';
|
|
16
17
|
// Native <select> primitive. Owns its styling from theme tokens; supports
|
|
17
18
|
// `bind:value` and passes through every native attribute. Options are either
|
|
18
19
|
// slotted children (full control over <option> rendering) or an `options`
|
|
@@ -48,12 +49,11 @@
|
|
|
48
49
|
variant?: 'default' | 'ghost' | 'embedded';
|
|
49
50
|
/** Error state: danger border + aria-invalid. */
|
|
50
51
|
invalid?: boolean;
|
|
51
|
-
/**
|
|
52
|
-
* Deprecated alias for `size="sm"` (kept for backward compatibility). */
|
|
52
|
+
/** @deprecated use `size="sm"`; `size` wins when both are set. */
|
|
53
53
|
compact?: boolean;
|
|
54
54
|
/** Size scale matching Button/SegmentedControl: `sm` also adopts the shared
|
|
55
55
|
* `--control-height-compact` toolbar height so it lines up with siblings. */
|
|
56
|
-
size?:
|
|
56
|
+
size?: ControlSize;
|
|
57
57
|
/** Draw the custom chevron (default). Set false for a bare inline select. */
|
|
58
58
|
chevron?: boolean;
|
|
59
59
|
/** `auto` sizes to the selected option instead of filling the row. */
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
variant = 'default',
|
|
75
75
|
invalid = false,
|
|
76
76
|
compact = false,
|
|
77
|
-
size
|
|
77
|
+
size,
|
|
78
78
|
chevron,
|
|
79
79
|
width = 'full',
|
|
80
80
|
grow = false,
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
|
|
95
95
|
$effect(() => warnUnlabelled(el, 'Select'));
|
|
96
96
|
|
|
97
|
-
const small = $derived(compact
|
|
97
|
+
const small = $derived((size ?? (compact ? 'sm' : 'md')) === 'sm');
|
|
98
98
|
const showChevron = $derived(chevron ?? variant !== 'embedded');
|
|
99
99
|
const selected = $derived(options?.find((o) => o.value === value));
|
|
100
100
|
const hasFace = $derived(!!options && variant !== 'ghost');
|
|
@@ -138,6 +138,7 @@
|
|
|
138
138
|
bind:this={el}
|
|
139
139
|
class="select"
|
|
140
140
|
class:compact={small}
|
|
141
|
+
class:select-lg={size === 'lg'}
|
|
141
142
|
class:select-sm={size === 'sm'}
|
|
142
143
|
class:w-auto={width === 'auto'}
|
|
143
144
|
class:embedded={variant === 'embedded'}
|
|
@@ -187,7 +188,9 @@
|
|
|
187
188
|
}
|
|
188
189
|
.select {
|
|
189
190
|
width: 100%;
|
|
190
|
-
|
|
191
|
+
min-height: var(--control-height-default);
|
|
192
|
+
padding: var(--sp-2) var(--sp-3);
|
|
193
|
+
line-height: var(--lh-tight);
|
|
191
194
|
background: var(--bg);
|
|
192
195
|
border: 1px solid var(--border-strong);
|
|
193
196
|
border-radius: var(--r-md);
|
|
@@ -205,6 +208,11 @@
|
|
|
205
208
|
padding-right: var(--sp-3);
|
|
206
209
|
}
|
|
207
210
|
/* Compact inline form for dense headers/toolbars. */
|
|
211
|
+
.select.select-lg {
|
|
212
|
+
min-height: var(--control-height-large);
|
|
213
|
+
padding: var(--sp-3) var(--sp-4);
|
|
214
|
+
font-size: var(--fs-base);
|
|
215
|
+
}
|
|
208
216
|
.select.compact {
|
|
209
217
|
padding: var(--sp-1) var(--sp-2);
|
|
210
218
|
font-size: var(--fs-xs);
|
|
@@ -229,6 +237,10 @@
|
|
|
229
237
|
outline: none;
|
|
230
238
|
border-color: var(--accent);
|
|
231
239
|
}
|
|
240
|
+
.select:focus-visible {
|
|
241
|
+
outline: var(--focus-ring);
|
|
242
|
+
outline-offset: var(--focus-ring-offset);
|
|
243
|
+
}
|
|
232
244
|
.select[aria-invalid='true'],
|
|
233
245
|
.select[aria-invalid='true']:focus {
|
|
234
246
|
border-color: var(--danger);
|
|
@@ -8,18 +8,18 @@ export type SelectOption = {
|
|
|
8
8
|
hint?: string;
|
|
9
9
|
disabled?: boolean;
|
|
10
10
|
};
|
|
11
|
+
import type { ControlSize } from '../../size';
|
|
11
12
|
import type { Snippet } from 'svelte';
|
|
12
13
|
import type { HTMLSelectAttributes } from 'svelte/elements';
|
|
13
14
|
type Props = Omit<HTMLSelectAttributes, 'size'> & {
|
|
14
15
|
variant?: 'default' | 'ghost' | 'embedded';
|
|
15
16
|
/** Error state: danger border + aria-invalid. */
|
|
16
17
|
invalid?: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Deprecated alias for `size="sm"` (kept for backward compatibility). */
|
|
18
|
+
/** @deprecated use `size="sm"`; `size` wins when both are set. */
|
|
19
19
|
compact?: boolean;
|
|
20
20
|
/** Size scale matching Button/SegmentedControl: `sm` also adopts the shared
|
|
21
21
|
* `--control-height-compact` toolbar height so it lines up with siblings. */
|
|
22
|
-
size?:
|
|
22
|
+
size?: ControlSize;
|
|
23
23
|
/** Draw the custom chevron (default). Set false for a bare inline select. */
|
|
24
24
|
chevron?: boolean;
|
|
25
25
|
/** `auto` sizes to the selected option instead of filling the row. */
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
3
|
// Shimmering placeholder bar(s) standing in for content that is still
|
|
3
4
|
// loading. Decorative only — the surrounding region should carry aria-busy.
|
|
4
|
-
|
|
5
|
-
width = '100%',
|
|
6
|
-
height = '1em',
|
|
7
|
-
lines = 1,
|
|
8
|
-
circle = false,
|
|
9
|
-
radius = 'var(--r-sm)',
|
|
10
|
-
class: klass = '',
|
|
11
|
-
...rest
|
|
12
|
-
}: {
|
|
5
|
+
type Own = {
|
|
13
6
|
width?: string;
|
|
14
7
|
height?: string;
|
|
15
8
|
/** Stacked bars; the last one is shortened to read as a paragraph. */
|
|
@@ -18,8 +11,16 @@
|
|
|
18
11
|
circle?: boolean;
|
|
19
12
|
radius?: string;
|
|
20
13
|
class?: string;
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
};
|
|
15
|
+
let {
|
|
16
|
+
width = '100%',
|
|
17
|
+
height = '1em',
|
|
18
|
+
lines = 1,
|
|
19
|
+
circle = false,
|
|
20
|
+
radius = 'var(--r-sm)',
|
|
21
|
+
class: klass = '',
|
|
22
|
+
...rest
|
|
23
|
+
}: Omit<HTMLAttributes<HTMLElement>, keyof Own> & Own = $props();
|
|
23
24
|
|
|
24
25
|
const w = $derived(circle ? height : width);
|
|
25
26
|
const r = $derived(circle ? '50%' : radius);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
type
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
type Own = {
|
|
2
3
|
width?: string;
|
|
3
4
|
height?: string;
|
|
4
5
|
/** Stacked bars; the last one is shortened to read as a paragraph. */
|
|
@@ -7,8 +8,8 @@ type $$ComponentProps = {
|
|
|
7
8
|
circle?: boolean;
|
|
8
9
|
radius?: string;
|
|
9
10
|
class?: string;
|
|
10
|
-
[key: string]: unknown;
|
|
11
11
|
};
|
|
12
|
+
type $$ComponentProps = Omit<HTMLAttributes<HTMLElement>, keyof Own> & Own;
|
|
12
13
|
declare const Skeleton: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
14
|
type Skeleton = ReturnType<typeof Skeleton>;
|
|
14
15
|
export default Skeleton;
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
'aria-invalid': ariaInvalid,
|
|
22
22
|
invalid = false,
|
|
23
23
|
ticks = false,
|
|
24
|
+
marks = [],
|
|
25
|
+
width,
|
|
24
26
|
class: klass = '',
|
|
25
27
|
el = $bindable(null),
|
|
26
28
|
...rest
|
|
@@ -37,6 +39,10 @@
|
|
|
37
39
|
/** Visible dots at each step (segmented slider). `true` = one per `step`;
|
|
38
40
|
* a number array places dots at those values. */
|
|
39
41
|
ticks?: boolean | number[];
|
|
42
|
+
/** Clickable labelled tick row under the track. */
|
|
43
|
+
marks?: { value: number; label: string }[];
|
|
44
|
+
/** Fixed width (`flex: none`). */
|
|
45
|
+
width?: string;
|
|
40
46
|
id?: string;
|
|
41
47
|
'aria-describedby'?: string | null;
|
|
42
48
|
'aria-invalid'?: HTMLInputAttributes['aria-invalid'];
|
|
@@ -61,7 +67,7 @@
|
|
|
61
67
|
});
|
|
62
68
|
</script>
|
|
63
69
|
|
|
64
|
-
<div class="slider {klass}" class:has-ticks={tickValues.length > 0} style="--pct: {pct}
|
|
70
|
+
<div class="slider {klass}" class:has-ticks={tickValues.length > 0} class:has-marks={marks.length > 0} class:fixed={!!width} style="--pct: {pct}%; {width ? `width: ${width}` : ''}" data-tsu="Slider">
|
|
65
71
|
<span class="range">
|
|
66
72
|
<input
|
|
67
73
|
bind:this={el}
|
|
@@ -87,9 +93,45 @@
|
|
|
87
93
|
{#if showValue}
|
|
88
94
|
<output for={id} class="slider-out">{format(Number(value))}</output>
|
|
89
95
|
{/if}
|
|
96
|
+
{#if marks.length > 0}
|
|
97
|
+
<span class="marks" aria-hidden="true">
|
|
98
|
+
{#each marks as m (m.value)}
|
|
99
|
+
<button type="button" class="mark" class:on={Number(value) === m.value} style="--f: {frac(m.value)}" tabindex="-1" onclick={() => (value = m.value)}>{m.label}</button>
|
|
100
|
+
{/each}
|
|
101
|
+
</span>
|
|
102
|
+
{/if}
|
|
90
103
|
</div>
|
|
91
104
|
|
|
92
105
|
<style>
|
|
106
|
+
.slider.fixed {
|
|
107
|
+
flex: none;
|
|
108
|
+
}
|
|
109
|
+
.slider.has-marks {
|
|
110
|
+
flex-wrap: wrap;
|
|
111
|
+
row-gap: var(--sp-1);
|
|
112
|
+
}
|
|
113
|
+
.marks {
|
|
114
|
+
position: relative;
|
|
115
|
+
flex: 1 0 100%;
|
|
116
|
+
height: 1.2em;
|
|
117
|
+
font-size: var(--fs-xs);
|
|
118
|
+
color: var(--text-faint);
|
|
119
|
+
}
|
|
120
|
+
.mark {
|
|
121
|
+
position: absolute;
|
|
122
|
+
left: calc(var(--f) * 100%);
|
|
123
|
+
transform: translateX(-50%);
|
|
124
|
+
border: 0;
|
|
125
|
+
background: none;
|
|
126
|
+
padding: 0;
|
|
127
|
+
font: inherit;
|
|
128
|
+
color: inherit;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
white-space: nowrap;
|
|
131
|
+
}
|
|
132
|
+
.mark.on {
|
|
133
|
+
color: var(--text);
|
|
134
|
+
}
|
|
93
135
|
.slider {
|
|
94
136
|
display: flex;
|
|
95
137
|
align-items: center;
|
|
@@ -160,11 +202,11 @@
|
|
|
160
202
|
outline: none;
|
|
161
203
|
}
|
|
162
204
|
input[type='range']:focus-visible::-webkit-slider-thumb {
|
|
163
|
-
outline:
|
|
205
|
+
outline: var(--focus-ring);
|
|
164
206
|
outline-offset: 2px;
|
|
165
207
|
}
|
|
166
208
|
input[type='range']:focus-visible::-moz-range-thumb {
|
|
167
|
-
outline:
|
|
209
|
+
outline: var(--focus-ring);
|
|
168
210
|
outline-offset: 2px;
|
|
169
211
|
}
|
|
170
212
|
input[type='range']:disabled {
|
|
@@ -12,6 +12,13 @@ type $$ComponentProps = HTMLInputAttributes & {
|
|
|
12
12
|
/** Visible dots at each step (segmented slider). `true` = one per `step`;
|
|
13
13
|
* a number array places dots at those values. */
|
|
14
14
|
ticks?: boolean | number[];
|
|
15
|
+
/** Clickable labelled tick row under the track. */
|
|
16
|
+
marks?: {
|
|
17
|
+
value: number;
|
|
18
|
+
label: string;
|
|
19
|
+
}[];
|
|
20
|
+
/** Fixed width (`flex: none`). */
|
|
21
|
+
width?: string;
|
|
15
22
|
id?: string;
|
|
16
23
|
'aria-describedby'?: string | null;
|
|
17
24
|
'aria-invalid'?: HTMLInputAttributes['aria-invalid'];
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
/** AT label announcing the busy state. Set to undefined to make the
|
|
16
16
|
* spinner decorative when an ancestor already conveys the loading state. */
|
|
17
17
|
label?: string;
|
|
18
|
+
class?: string;
|
|
19
|
+
style?: string;
|
|
18
20
|
[key: string]: unknown;
|
|
19
21
|
} = $props();
|
|
20
22
|
</script>
|
|
@@ -4,6 +4,8 @@ type $$ComponentProps = {
|
|
|
4
4
|
/** AT label announcing the busy state. Set to undefined to make the
|
|
5
5
|
* spinner decorative when an ancestor already conveys the loading state. */
|
|
6
6
|
label?: string;
|
|
7
|
+
class?: string;
|
|
8
|
+
style?: string;
|
|
7
9
|
[key: string]: unknown;
|
|
8
10
|
};
|
|
9
11
|
declare const Spinner: import("svelte").Component<$$ComponentProps, {}, "">;
|