@dorsk/tsumikit 0.74.0 → 0.76.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/README.md +38 -1
- package/dist/autoresize.d.ts +2 -0
- package/dist/autoresize.js +8 -1
- package/dist/components/atoms/Artwork.svelte +12 -5
- package/dist/components/atoms/Avatar.svelte +1 -1
- package/dist/components/atoms/Badge.svelte +59 -23
- package/dist/components/atoms/Button.svelte +130 -96
- package/dist/components/atoms/Button.svelte.d.ts +2 -0
- package/dist/components/atoms/Card.svelte +10 -4
- package/dist/components/atoms/Checkbox.svelte +36 -9
- package/dist/components/atoms/Checkbox.svelte.d.ts +2 -0
- package/dist/components/atoms/Gauge.svelte +20 -14
- package/dist/components/atoms/Heading.svelte +1 -1
- package/dist/components/atoms/Icon.svelte +1 -0
- package/dist/components/atoms/Input.svelte +67 -13
- package/dist/components/atoms/Kbd.svelte +3 -3
- package/dist/components/atoms/Link.svelte +7 -2
- package/dist/components/atoms/Progress.svelte +4 -2
- package/dist/components/atoms/Scrim.svelte +3 -8
- package/dist/components/atoms/SegmentedProgress.svelte +5 -4
- package/dist/components/atoms/Select.svelte +58 -27
- package/dist/components/atoms/Slider.svelte +79 -22
- package/dist/components/atoms/Slider.svelte.d.ts +2 -0
- package/dist/components/atoms/Swatch.svelte +19 -8
- package/dist/components/atoms/Switch.svelte +34 -21
- package/dist/components/atoms/Switch.svelte.d.ts +2 -0
- package/dist/components/atoms/Text.svelte +1 -1
- package/dist/components/atoms/Textarea.svelte +34 -12
- package/dist/components/atoms/TimeDisplay.svelte +4 -2
- package/dist/components/layouts/AppShell.svelte +26 -15
- package/dist/components/layouts/MasterDetail.svelte +23 -21
- package/dist/components/layouts/NavBar.svelte +11 -8
- package/dist/components/layouts/NavItem.svelte +15 -7
- package/dist/components/layouts/NavSection.svelte +1 -1
- package/dist/components/layouts/ResizablePanel.svelte +37 -16
- package/dist/components/layouts/TabBar.svelte +24 -14
- package/dist/components/layouts/TabBar.svelte.d.ts +2 -0
- package/dist/components/molecules/Accordion.svelte +4 -0
- package/dist/components/molecules/Accordion.svelte.d.ts +2 -0
- package/dist/components/molecules/AttachmentList.svelte +14 -11
- package/dist/components/molecules/Breadcrumb.svelte +13 -9
- package/dist/components/molecules/Callout.svelte +3 -3
- package/dist/components/molecules/CapBar.svelte +23 -22
- package/dist/components/molecules/Carousel.svelte +27 -17
- package/dist/components/molecules/ChatBubble.svelte +2 -2
- package/dist/components/molecules/CodeBlock.svelte +2 -2
- package/dist/components/molecules/Combobox.svelte +30 -1
- package/dist/components/molecules/Combobox.svelte.d.ts +4 -0
- package/dist/components/molecules/Composer.svelte +2 -2
- package/dist/components/molecules/ConfirmModal.svelte +4 -0
- package/dist/components/molecules/ConfirmModal.svelte.d.ts +2 -0
- package/dist/components/molecules/CopyButton.svelte +46 -2
- package/dist/components/molecules/CopyButton.svelte.d.ts +2 -0
- package/dist/components/molecules/Disclosure.svelte +23 -12
- package/dist/components/molecules/Disclosure.svelte.d.ts +2 -0
- package/dist/components/molecules/Drawer.svelte +43 -23
- package/dist/components/molecules/Drawer.svelte.d.ts +2 -0
- package/dist/components/molecules/Dropzone.svelte +24 -8
- package/dist/components/molecules/EmojiPicker.svelte +27 -8
- package/dist/components/molecules/EmojiPicker.svelte.d.ts +2 -0
- package/dist/components/molecules/EmptyState.svelte +5 -5
- package/dist/components/molecules/Fieldset.svelte +8 -13
- package/dist/components/molecules/FileButton.svelte +57 -31
- package/dist/components/molecules/FileButton.svelte.d.ts +2 -0
- package/dist/components/molecules/FilterInput.svelte +51 -11
- package/dist/components/molecules/FontScalePicker.svelte +20 -9
- package/dist/components/molecules/GitRef.svelte +9 -7
- package/dist/components/molecules/GlyphStack.svelte +46 -14
- package/dist/components/molecules/IconButton.svelte +6 -3
- package/dist/components/molecules/IconButton.svelte.d.ts +2 -0
- package/dist/components/molecules/InputGroup.svelte +13 -12
- package/dist/components/molecules/LoadMore.svelte +6 -1
- package/dist/components/molecules/LoadMore.svelte.d.ts +2 -0
- package/dist/components/molecules/Menu.svelte +33 -7
- package/dist/components/molecules/Menu.svelte.d.ts +2 -0
- package/dist/components/molecules/Metric.svelte +11 -9
- package/dist/components/molecules/Modal.svelte +76 -26
- package/dist/components/molecules/Modal.svelte.d.ts +2 -0
- package/dist/components/molecules/OptionButton.svelte +28 -10
- package/dist/components/molecules/OptionButton.svelte.d.ts +2 -0
- package/dist/components/molecules/Pagination.svelte +26 -9
- package/dist/components/molecules/Pagination.svelte.d.ts +2 -0
- package/dist/components/molecules/Popover.svelte +107 -51
- package/dist/components/molecules/Popover.svelte.d.ts +2 -0
- package/dist/components/molecules/Prose.svelte +1 -1
- package/dist/components/molecules/PullToRefresh.svelte +14 -10
- package/dist/components/molecules/PullToRefresh.svelte.d.ts +2 -0
- package/dist/components/molecules/RadialMenu.svelte +52 -19
- package/dist/components/molecules/RadialMenu.svelte.d.ts +2 -0
- package/dist/components/molecules/RadioGroup.svelte +38 -23
- package/dist/components/molecules/RadioGroup.svelte.d.ts +2 -0
- package/dist/components/molecules/RichSelect.svelte +583 -0
- package/dist/components/molecules/RichSelect.svelte.d.ts +68 -0
- package/dist/components/molecules/SectionHeader.svelte +13 -8
- package/dist/components/molecules/SeekSlider.svelte +38 -27
- package/dist/components/molecules/SeekSlider.svelte.d.ts +2 -0
- package/dist/components/molecules/SegmentedControl.svelte +139 -86
- package/dist/components/molecules/SegmentedControl.svelte.d.ts +2 -0
- package/dist/components/molecules/SelectButton.svelte +21 -6
- package/dist/components/molecules/SelectButton.svelte.d.ts +2 -0
- package/dist/components/molecules/SortableList.svelte +10 -11
- package/dist/components/molecules/SoundSettings.svelte +161 -0
- package/dist/components/molecules/SoundSettings.svelte.d.ts +17 -0
- package/dist/components/molecules/SplitButton.svelte +30 -3
- package/dist/components/molecules/SplitButton.svelte.d.ts +2 -0
- package/dist/components/molecules/SwipeRow.svelte +18 -15
- package/dist/components/molecules/SwipeRow.svelte.d.ts +2 -0
- package/dist/components/molecules/Tabs.svelte +92 -10
- package/dist/components/molecules/Tabs.svelte.d.ts +2 -0
- package/dist/components/molecules/ThemePicker.svelte +25 -10
- package/dist/components/molecules/Timestamp.svelte +12 -7
- package/dist/components/molecules/Toaster.svelte +65 -14
- package/dist/components/molecules/Toaster.svelte.d.ts +2 -0
- package/dist/components/molecules/Toggle.svelte +36 -13
- package/dist/components/molecules/Toggle.svelte.d.ts +2 -0
- package/dist/components/molecules/Tooltip.svelte +41 -10
- package/dist/components/molecules/Tooltip.svelte.d.ts +1 -1
- package/dist/components/molecules/VolumeSlider.svelte +34 -14
- package/dist/components/molecules/VolumeSlider.svelte.d.ts +2 -0
- package/dist/components/molecules/WorkingDir.svelte +1 -0
- package/dist/components/molecules/rich-select-keyboard.d.ts +82 -0
- package/dist/components/molecules/rich-select-keyboard.js +114 -0
- package/dist/components/organisms/ConversationFeed.svelte +24 -1
- package/dist/components/organisms/DataTable.svelte +37 -14
- package/dist/floating.js +26 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/sound-synth.js +17 -12
- package/dist/stores/toast.svelte.d.ts +9 -0
- package/dist/stores/toast.svelte.js +45 -9
- package/dist/styles/reset.css +3 -3
- package/package.json +1 -1
|
@@ -136,15 +136,17 @@
|
|
|
136
136
|
|
|
137
137
|
<style>
|
|
138
138
|
.input {
|
|
139
|
+
--input-icon: var(--control-icon-md);
|
|
139
140
|
width: 100%;
|
|
140
141
|
min-height: var(--input-size, var(--control-height-default));
|
|
141
|
-
padding: var(--sp-2) var(--
|
|
142
|
+
padding: var(--sp-2) var(--control-px-md);
|
|
143
|
+
font-size: var(--control-fs-md);
|
|
142
144
|
line-height: var(--lh-tight);
|
|
143
145
|
background: var(--input-bg, var(--bg));
|
|
144
146
|
border: 1px solid var(--input-border, var(--border-strong));
|
|
145
147
|
border-radius: var(--input-radius, var(--r-md));
|
|
146
148
|
color: var(--input-fg, var(--text));
|
|
147
|
-
transition: border-color
|
|
149
|
+
transition: border-color var(--dur-fast) ease;
|
|
148
150
|
}
|
|
149
151
|
.input:focus {
|
|
150
152
|
outline: none;
|
|
@@ -154,21 +156,33 @@
|
|
|
154
156
|
outline: var(--focus-ring);
|
|
155
157
|
outline-offset: var(--focus-ring-offset);
|
|
156
158
|
}
|
|
159
|
+
.input:disabled {
|
|
160
|
+
opacity: var(--disabled-opacity);
|
|
161
|
+
cursor: not-allowed;
|
|
162
|
+
}
|
|
157
163
|
.input-sm {
|
|
158
164
|
min-height: var(--input-size, var(--control-height-compact));
|
|
159
|
-
padding: var(--sp-1) var(--
|
|
160
|
-
font-size: var(--fs-sm);
|
|
165
|
+
padding: var(--sp-1) var(--control-px-sm);
|
|
166
|
+
font-size: var(--control-fs-sm);
|
|
167
|
+
--input-icon: var(--control-icon-sm);
|
|
161
168
|
}
|
|
162
169
|
.input-lg {
|
|
163
170
|
min-height: var(--input-size, var(--control-height-large));
|
|
164
|
-
padding: var(--sp-3) var(--
|
|
165
|
-
font-size:
|
|
171
|
+
padding: var(--sp-3) var(--control-px-lg);
|
|
172
|
+
font-size: var(--control-fs-lg);
|
|
173
|
+
--input-icon: var(--control-icon-lg);
|
|
166
174
|
}
|
|
167
175
|
/* iOS auto-zooms any field under 16px on focus; on touch the size modifiers
|
|
168
176
|
carry their difference through padding and height alone. */
|
|
169
177
|
@media (pointer: coarse) {
|
|
178
|
+
.input {
|
|
179
|
+
font-size: max(16px, var(--control-fs-md));
|
|
180
|
+
}
|
|
170
181
|
.input-sm {
|
|
171
|
-
font-size: max(16px, var(--fs-sm));
|
|
182
|
+
font-size: max(16px, var(--control-fs-sm));
|
|
183
|
+
}
|
|
184
|
+
.input-lg {
|
|
185
|
+
font-size: max(16px, var(--control-fs-lg));
|
|
172
186
|
}
|
|
173
187
|
.input-sm:not(.grouped) {
|
|
174
188
|
min-height: max(var(--touch-target-compact), var(--input-size, var(--control-height-compact)));
|
|
@@ -192,8 +206,8 @@
|
|
|
192
206
|
.input[aria-invalid='true']:focus {
|
|
193
207
|
border-color: var(--danger);
|
|
194
208
|
}
|
|
195
|
-
/* Inside an InputGroup the group draws the focus ring
|
|
196
|
-
adornments report their widths; the text stays clear of them. */
|
|
209
|
+
/* Inside an InputGroup the group draws the focus ring, dims the whole group
|
|
210
|
+
and the overlaid adornments report their widths; the text stays clear of them. */
|
|
197
211
|
.input.grouped {
|
|
198
212
|
width: 100%;
|
|
199
213
|
border-radius: var(--ig-radius);
|
|
@@ -203,6 +217,9 @@
|
|
|
203
217
|
.input.grouped:focus-visible {
|
|
204
218
|
outline: none;
|
|
205
219
|
}
|
|
220
|
+
.input.grouped:disabled {
|
|
221
|
+
opacity: 1;
|
|
222
|
+
}
|
|
206
223
|
.mono {
|
|
207
224
|
font-family: var(--font-mono);
|
|
208
225
|
}
|
|
@@ -216,11 +233,18 @@
|
|
|
216
233
|
.input-wrap .input {
|
|
217
234
|
width: 100%;
|
|
218
235
|
}
|
|
236
|
+
/* The wrap dims as one so the icon and the clear button fade with the field. */
|
|
237
|
+
.input-wrap:has(.input:disabled) {
|
|
238
|
+
opacity: var(--disabled-opacity);
|
|
239
|
+
}
|
|
240
|
+
.input-wrap .input:disabled {
|
|
241
|
+
opacity: 1;
|
|
242
|
+
}
|
|
219
243
|
.has-icon {
|
|
220
|
-
padding-inline-start: calc(var(--
|
|
244
|
+
padding-inline-start: calc(var(--control-px-md) + var(--input-icon) + var(--sp-2));
|
|
221
245
|
}
|
|
222
246
|
.has-clear {
|
|
223
|
-
padding-inline-end: calc(var(--
|
|
247
|
+
padding-inline-end: calc(var(--control-px-md) + var(--input-icon) + var(--sp-2));
|
|
224
248
|
}
|
|
225
249
|
.input-icon,
|
|
226
250
|
.input-clear {
|
|
@@ -229,13 +253,21 @@
|
|
|
229
253
|
bottom: 0;
|
|
230
254
|
display: flex;
|
|
231
255
|
align-items: center;
|
|
256
|
+
font-size: var(--input-icon, var(--control-icon-md));
|
|
232
257
|
color: var(--text-faint);
|
|
233
258
|
pointer-events: none;
|
|
234
259
|
}
|
|
260
|
+
.input-wrap:has(.input-sm) {
|
|
261
|
+
--input-icon: var(--control-icon-sm);
|
|
262
|
+
}
|
|
263
|
+
.input-wrap:has(.input-lg) {
|
|
264
|
+
--input-icon: var(--control-icon-lg);
|
|
265
|
+
}
|
|
235
266
|
.input-icon {
|
|
236
|
-
left: var(--
|
|
267
|
+
left: var(--control-px-md);
|
|
237
268
|
}
|
|
238
269
|
.input-clear {
|
|
270
|
+
--clear-scale-dur: var(--dur-fast);
|
|
239
271
|
right: var(--sp-2);
|
|
240
272
|
pointer-events: auto;
|
|
241
273
|
border: 0;
|
|
@@ -243,9 +275,31 @@
|
|
|
243
275
|
padding: 0 var(--sp-1);
|
|
244
276
|
cursor: pointer;
|
|
245
277
|
border-radius: var(--r-sm);
|
|
278
|
+
transition:
|
|
279
|
+
color var(--dur-fast) ease,
|
|
280
|
+
opacity var(--dur-fast) ease,
|
|
281
|
+
scale var(--clear-scale-dur) var(--ease-out);
|
|
282
|
+
}
|
|
283
|
+
@starting-style {
|
|
284
|
+
.input-clear {
|
|
285
|
+
opacity: 0;
|
|
286
|
+
}
|
|
246
287
|
}
|
|
247
|
-
.input-clear:hover,
|
|
248
288
|
.input-clear:focus-visible {
|
|
249
289
|
color: var(--text);
|
|
290
|
+
outline: var(--focus-ring);
|
|
291
|
+
outline-offset: var(--focus-ring-offset-inset);
|
|
292
|
+
}
|
|
293
|
+
.input-clear:active {
|
|
294
|
+
--clear-scale-dur: var(--dur-press);
|
|
295
|
+
scale: var(--press-scale-sm);
|
|
296
|
+
}
|
|
297
|
+
@media (hover: hover) and (pointer: fine) {
|
|
298
|
+
.input:hover:not(:disabled, :focus, [aria-invalid='true']) {
|
|
299
|
+
border-color: var(--text-faint);
|
|
300
|
+
}
|
|
301
|
+
.input-clear:hover {
|
|
302
|
+
color: var(--text);
|
|
303
|
+
}
|
|
250
304
|
}
|
|
251
305
|
</style>
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
.kbd-group {
|
|
96
96
|
display: inline-flex;
|
|
97
97
|
align-items: center;
|
|
98
|
-
gap:
|
|
98
|
+
gap: var(--sp-0-5);
|
|
99
99
|
font-size: var(--fs-xs);
|
|
100
100
|
color: var(--text-muted);
|
|
101
101
|
vertical-align: baseline;
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
.kbd {
|
|
107
107
|
font-family: var(--font-mono);
|
|
108
108
|
font-size: inherit;
|
|
109
|
-
line-height:
|
|
109
|
+
line-height: var(--lh-snug);
|
|
110
110
|
padding: 0 var(--sp-1);
|
|
111
111
|
border: 1px solid var(--border-strong);
|
|
112
112
|
border-bottom-width: 2px;
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
white-space: nowrap;
|
|
125
125
|
}
|
|
126
126
|
.kbd-sep {
|
|
127
|
-
font-size:
|
|
127
|
+
font-size: var(--fs-2xs);
|
|
128
128
|
color: var(--text-faint);
|
|
129
129
|
}
|
|
130
130
|
</style>
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
text-decoration: underline;
|
|
57
57
|
font: inherit;
|
|
58
58
|
text-align: start;
|
|
59
|
+
transition:
|
|
60
|
+
color var(--dur-fast) ease,
|
|
61
|
+
text-decoration-color var(--dur-fast) ease;
|
|
59
62
|
}
|
|
60
63
|
.tone-info {
|
|
61
64
|
color: var(--info);
|
|
@@ -70,8 +73,10 @@
|
|
|
70
73
|
.underline-none {
|
|
71
74
|
text-decoration: none;
|
|
72
75
|
}
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
@media (hover: hover) and (pointer: fine) {
|
|
77
|
+
.underline-hover:hover {
|
|
78
|
+
text-decoration: underline;
|
|
79
|
+
}
|
|
75
80
|
}
|
|
76
81
|
.align-center {
|
|
77
82
|
text-align: center;
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
aria-valuemax={indeterminate ? undefined : max}
|
|
96
96
|
aria-valuenow={indeterminate ? undefined : value}
|
|
97
97
|
>
|
|
98
|
-
<div class="bar" style={indeterminate ? undefined :
|
|
98
|
+
<div class="bar" style={indeterminate ? undefined : `--p: ${pct / 100}`}></div>
|
|
99
99
|
{#each markers as m, i (`${i}:${m.at}`)}
|
|
100
100
|
<span
|
|
101
101
|
class="marker tone-{m.tone ? canonicalTone(m.tone) : 'text'}"
|
|
@@ -154,10 +154,12 @@
|
|
|
154
154
|
height: 0.3125rem;
|
|
155
155
|
}
|
|
156
156
|
.bar {
|
|
157
|
+
width: 100%;
|
|
157
158
|
height: 100%;
|
|
158
159
|
background: var(--fill, var(--accent));
|
|
159
160
|
border-radius: inherit;
|
|
160
|
-
|
|
161
|
+
translate: calc((var(--p, 1) - 1) * 100%) 0;
|
|
162
|
+
transition: translate var(--dur-base) var(--ease-out);
|
|
161
163
|
}
|
|
162
164
|
.marker {
|
|
163
165
|
position: absolute;
|
|
@@ -88,16 +88,11 @@
|
|
|
88
88
|
border: 0;
|
|
89
89
|
background: color-mix(in srgb, var(--bg) 45%, transparent);
|
|
90
90
|
cursor: default;
|
|
91
|
-
|
|
91
|
+
transition: opacity var(--dur-base) var(--ease-out);
|
|
92
92
|
}
|
|
93
|
-
@
|
|
94
|
-
from {
|
|
95
|
-
opacity: 0;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
@media (prefers-reduced-motion: reduce) {
|
|
93
|
+
@starting-style {
|
|
99
94
|
.scrim {
|
|
100
|
-
|
|
95
|
+
opacity: 0;
|
|
101
96
|
}
|
|
102
97
|
}
|
|
103
98
|
</style>
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
>
|
|
104
104
|
{#each segments as seg, i (i)}
|
|
105
105
|
<div class="segment tone-{seg.tone ?? 'accent'}" style="flex-grow: {grow(seg)}" title={seg.label}>
|
|
106
|
-
<div class="bar" style="
|
|
106
|
+
<div class="bar" style="--p: {pct(seg) / 100}"></div>
|
|
107
107
|
</div>
|
|
108
108
|
{/each}
|
|
109
109
|
{#if remainder > 0}
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
>
|
|
125
125
|
{#each segments as seg, i (i)}
|
|
126
126
|
<div class="segment tone-{seg.tone ?? 'accent'}" style="flex-grow: {grow(seg)}" title={seg.label}>
|
|
127
|
-
<div class="bar" style="
|
|
127
|
+
<div class="bar" style="--p: {pct(seg) / 100}"></div>
|
|
128
128
|
</div>
|
|
129
129
|
{/each}
|
|
130
130
|
</div>
|
|
@@ -180,9 +180,11 @@
|
|
|
180
180
|
border-bottom-right-radius: var(--r-pill);
|
|
181
181
|
}
|
|
182
182
|
.bar {
|
|
183
|
+
width: 100%;
|
|
183
184
|
height: 100%;
|
|
184
185
|
background: var(--fill, var(--accent));
|
|
185
|
-
|
|
186
|
+
translate: calc((var(--p, 1) - 1) * 100%) 0;
|
|
187
|
+
transition: translate var(--dur-base) var(--ease-out);
|
|
186
188
|
}
|
|
187
189
|
.tone-success,
|
|
188
190
|
.tone-ok {
|
|
@@ -210,7 +212,6 @@
|
|
|
210
212
|
min-width: 0;
|
|
211
213
|
border-radius: 0;
|
|
212
214
|
background: transparent;
|
|
213
|
-
transition: flex-grow 0.2s var(--ease);
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
.segmented-progress-wrap {
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
{#if hasFace}
|
|
172
172
|
<span class="select-face" class:compact={small} aria-hidden="true">
|
|
173
173
|
{#if selected?.icon}
|
|
174
|
-
<Icon name={selected.icon}
|
|
174
|
+
<Icon name={selected.icon} />
|
|
175
175
|
{:else if selected?.emoji}
|
|
176
176
|
<span class="select-emoji">{selected.emoji}</span>
|
|
177
177
|
{/if}
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
{/if}
|
|
184
184
|
{#if showChevron}
|
|
185
185
|
<span class="select-chevron" aria-hidden="true">
|
|
186
|
-
<Icon name="chevron-down"
|
|
186
|
+
<Icon name="chevron-down" />
|
|
187
187
|
</span>
|
|
188
188
|
{/if}
|
|
189
189
|
</div>
|
|
@@ -191,6 +191,7 @@
|
|
|
191
191
|
|
|
192
192
|
<style>
|
|
193
193
|
.select-wrap {
|
|
194
|
+
--select-icon: var(--control-icon-md);
|
|
194
195
|
position: relative;
|
|
195
196
|
display: block;
|
|
196
197
|
width: 100%;
|
|
@@ -203,39 +204,46 @@
|
|
|
203
204
|
flex: 1 1 0;
|
|
204
205
|
min-width: 0;
|
|
205
206
|
}
|
|
207
|
+
.select-wrap:has(.select.compact) {
|
|
208
|
+
--select-icon: var(--control-icon-sm);
|
|
209
|
+
}
|
|
210
|
+
.select-wrap:has(.select.select-lg) {
|
|
211
|
+
--select-icon: var(--control-icon-lg);
|
|
212
|
+
}
|
|
206
213
|
.select {
|
|
207
214
|
width: 100%;
|
|
208
215
|
min-height: var(--select-size, var(--control-height-default));
|
|
209
|
-
padding: var(--sp-2) var(--
|
|
216
|
+
padding: var(--sp-2) var(--control-px-md);
|
|
217
|
+
font-size: var(--control-fs-md);
|
|
210
218
|
line-height: var(--lh-tight);
|
|
211
219
|
background: var(--select-bg, var(--bg));
|
|
212
220
|
border: 1px solid var(--select-border, var(--border-strong));
|
|
213
221
|
border-radius: var(--select-radius, var(--r-md));
|
|
214
222
|
color: var(--select-fg, var(--text));
|
|
215
|
-
transition: border-color
|
|
223
|
+
transition: border-color var(--dur-fast) ease;
|
|
216
224
|
}
|
|
217
225
|
/* Default variant: drop the OS chevron, reserve room for our own. */
|
|
218
226
|
.select-wrap .select {
|
|
219
227
|
appearance: none;
|
|
220
228
|
-webkit-appearance: none;
|
|
221
|
-
padding-right: calc(var(--
|
|
229
|
+
padding-right: calc(var(--control-px-md) + var(--select-icon) + var(--sp-1));
|
|
222
230
|
}
|
|
223
231
|
/* No custom chevron: reclaim the reserved right padding. */
|
|
224
232
|
.select-wrap.no-chevron .select {
|
|
225
|
-
padding-right: var(--
|
|
233
|
+
padding-right: var(--control-px-md);
|
|
226
234
|
}
|
|
227
|
-
/* Compact inline form for dense headers/toolbars. */
|
|
228
235
|
.select.select-lg {
|
|
229
236
|
min-height: var(--select-size, var(--control-height-large));
|
|
230
|
-
padding: var(--sp-3) var(--
|
|
231
|
-
font-size:
|
|
237
|
+
padding: var(--sp-3) var(--control-px-lg);
|
|
238
|
+
font-size: var(--control-fs-lg);
|
|
232
239
|
}
|
|
240
|
+
/* Compact inline form for dense headers/toolbars. */
|
|
233
241
|
.select.compact {
|
|
234
|
-
padding: var(--sp-1) var(--
|
|
235
|
-
font-size: var(--fs-
|
|
242
|
+
padding: var(--sp-1) var(--control-px-sm);
|
|
243
|
+
font-size: var(--control-fs-sm);
|
|
236
244
|
}
|
|
237
245
|
.select-wrap:not(.no-chevron) .select.compact {
|
|
238
|
-
padding-right: calc(var(--
|
|
246
|
+
padding-right: calc(var(--control-px-sm) + var(--select-icon) + var(--sp-1));
|
|
239
247
|
}
|
|
240
248
|
/* Toolbar contract: size="sm" shares the compact control height so it lines up
|
|
241
249
|
with Button size="sm", Popover size="sm" and SegmentedControl size="sm". */
|
|
@@ -263,6 +271,13 @@
|
|
|
263
271
|
.select[aria-invalid='true']:focus {
|
|
264
272
|
border-color: var(--danger);
|
|
265
273
|
}
|
|
274
|
+
.select:disabled {
|
|
275
|
+
cursor: not-allowed;
|
|
276
|
+
}
|
|
277
|
+
/* The wrap dims as one so the face and the chevron fade with the control. */
|
|
278
|
+
.select-wrap:has(.select:disabled) {
|
|
279
|
+
opacity: var(--disabled-opacity);
|
|
280
|
+
}
|
|
266
281
|
/* The face draws the trigger text; the native text underneath stays laid out
|
|
267
282
|
(so `width="auto"` still sizes to it) but invisible. Popup options keep
|
|
268
283
|
their own colour so the transparency does not inherit into the list. */
|
|
@@ -280,38 +295,45 @@
|
|
|
280
295
|
display: flex;
|
|
281
296
|
align-items: center;
|
|
282
297
|
gap: var(--sp-2);
|
|
283
|
-
padding: 0 var(--
|
|
284
|
-
padding-right: calc(var(--
|
|
298
|
+
padding: 0 var(--control-px-md);
|
|
299
|
+
padding-right: calc(var(--control-px-md) + var(--select-icon) + var(--sp-1));
|
|
300
|
+
font-size: var(--control-fs-md);
|
|
285
301
|
color: var(--select-fg, var(--text));
|
|
286
302
|
pointer-events: none;
|
|
287
303
|
overflow: hidden;
|
|
288
304
|
}
|
|
305
|
+
.select-face > :global(svg) {
|
|
306
|
+
flex: none;
|
|
307
|
+
font-size: var(--select-icon);
|
|
308
|
+
}
|
|
289
309
|
.select-wrap.no-chevron .select-face {
|
|
290
|
-
padding-right: var(--
|
|
310
|
+
padding-right: var(--control-px-md);
|
|
291
311
|
}
|
|
292
312
|
.select-face.compact {
|
|
293
|
-
padding: 0 var(--
|
|
294
|
-
padding-right: calc(var(--
|
|
295
|
-
font-size: var(--fs-
|
|
313
|
+
padding: 0 var(--control-px-sm);
|
|
314
|
+
padding-right: calc(var(--control-px-sm) + var(--select-icon) + var(--sp-1));
|
|
315
|
+
font-size: var(--control-fs-sm);
|
|
296
316
|
}
|
|
297
317
|
.select-wrap.no-chevron .select-face.compact {
|
|
298
|
-
padding-right: var(--
|
|
318
|
+
padding-right: var(--control-px-sm);
|
|
299
319
|
}
|
|
300
320
|
/* iOS auto-zooms any field under 16px on focus; on touch the size modifiers
|
|
301
321
|
carry their difference through padding and height alone. */
|
|
302
322
|
@media (pointer: coarse) {
|
|
303
|
-
.select
|
|
304
|
-
|
|
323
|
+
.select,
|
|
324
|
+
.select-face {
|
|
325
|
+
font-size: max(16px, var(--control-fs-md));
|
|
305
326
|
}
|
|
327
|
+
.select.select-lg {
|
|
328
|
+
font-size: max(16px, var(--control-fs-lg));
|
|
329
|
+
}
|
|
330
|
+
.select.compact,
|
|
306
331
|
.select-face.compact {
|
|
307
|
-
font-size: max(16px, var(--fs-
|
|
332
|
+
font-size: max(16px, var(--control-fs-sm));
|
|
308
333
|
}
|
|
309
334
|
}
|
|
310
|
-
.select:disabled ~ .select-face {
|
|
311
|
-
color: var(--text-muted);
|
|
312
|
-
}
|
|
313
335
|
.select-emoji {
|
|
314
|
-
line-height:
|
|
336
|
+
line-height: var(--lh-none);
|
|
315
337
|
}
|
|
316
338
|
.select-label {
|
|
317
339
|
flex: 1 1 auto;
|
|
@@ -330,12 +352,21 @@
|
|
|
330
352
|
.select-chevron {
|
|
331
353
|
position: absolute;
|
|
332
354
|
top: 50%;
|
|
333
|
-
right: var(--
|
|
355
|
+
right: var(--control-px-md);
|
|
334
356
|
transform: translateY(-50%);
|
|
335
357
|
display: inline-flex;
|
|
358
|
+
font-size: var(--select-icon);
|
|
336
359
|
color: var(--text-muted);
|
|
337
360
|
pointer-events: none; /* clicks fall through to the select */
|
|
338
361
|
}
|
|
362
|
+
.select-wrap:has(.select.compact) .select-chevron {
|
|
363
|
+
right: var(--control-px-sm);
|
|
364
|
+
}
|
|
365
|
+
@media (hover: hover) and (pointer: fine) {
|
|
366
|
+
.select:hover:not(:disabled, :focus, [aria-invalid='true'], .ghost, .embedded) {
|
|
367
|
+
border-color: var(--text-faint);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
339
370
|
/* Transparent overlay: fills the positioned parent, the trigger shows through. */
|
|
340
371
|
.select.ghost {
|
|
341
372
|
position: absolute;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// Recolor per-instance via `--slider-accent` (defaults to the theme accent).
|
|
8
8
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
9
9
|
import { getFieldContext, warnUnlabelled } from '../../field-context';
|
|
10
|
+
import { playSound } from '../../sound';
|
|
10
11
|
|
|
11
12
|
let {
|
|
12
13
|
value = $bindable(0),
|
|
@@ -23,6 +24,11 @@
|
|
|
23
24
|
ticks = false,
|
|
24
25
|
marks = [],
|
|
25
26
|
width,
|
|
27
|
+
sound = true,
|
|
28
|
+
oninput,
|
|
29
|
+
onpointerdown,
|
|
30
|
+
onpointerup,
|
|
31
|
+
onpointercancel,
|
|
26
32
|
class: klass = '',
|
|
27
33
|
el = $bindable(null),
|
|
28
34
|
...rest
|
|
@@ -43,6 +49,8 @@
|
|
|
43
49
|
marks?: { value: number; label: string }[];
|
|
44
50
|
/** Fixed width (`flex: none`). */
|
|
45
51
|
width?: string;
|
|
52
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
53
|
+
sound?: boolean;
|
|
46
54
|
id?: string;
|
|
47
55
|
'aria-describedby'?: string | null;
|
|
48
56
|
'aria-invalid'?: HTMLInputAttributes['aria-invalid'];
|
|
@@ -60,6 +68,32 @@
|
|
|
60
68
|
|
|
61
69
|
$effect(() => warnUnlabelled(el, 'Slider'));
|
|
62
70
|
|
|
71
|
+
let dragging = false;
|
|
72
|
+
const discrete = $derived((+max - +min) / (+step || 1) <= 20);
|
|
73
|
+
function tick() {
|
|
74
|
+
if (!dragging || discrete) playSound('tick', sound);
|
|
75
|
+
}
|
|
76
|
+
function handleInput(e: Event & { currentTarget: EventTarget & HTMLInputElement }) {
|
|
77
|
+
tick();
|
|
78
|
+
oninput?.(e);
|
|
79
|
+
}
|
|
80
|
+
function handlePointerDown(e: PointerEvent & { currentTarget: EventTarget & HTMLInputElement }) {
|
|
81
|
+
dragging = true;
|
|
82
|
+
onpointerdown?.(e);
|
|
83
|
+
}
|
|
84
|
+
function handlePointerUp(e: PointerEvent & { currentTarget: EventTarget & HTMLInputElement }) {
|
|
85
|
+
dragging = false;
|
|
86
|
+
onpointerup?.(e);
|
|
87
|
+
}
|
|
88
|
+
function handlePointerCancel(e: PointerEvent & { currentTarget: EventTarget & HTMLInputElement }) {
|
|
89
|
+
dragging = false;
|
|
90
|
+
onpointercancel?.(e);
|
|
91
|
+
}
|
|
92
|
+
function pick(v: number) {
|
|
93
|
+
value = v;
|
|
94
|
+
playSound('tick', sound);
|
|
95
|
+
}
|
|
96
|
+
|
|
63
97
|
const frac = (v: number) => Math.max(0, Math.min(1, (v - +min) / (+max - +min || 1)));
|
|
64
98
|
const pct = $derived(frac(Number(value)) * 100);
|
|
65
99
|
const tickValues = $derived.by(() => {
|
|
@@ -84,6 +118,10 @@
|
|
|
84
118
|
aria-label={label}
|
|
85
119
|
aria-valuetext={valueText}
|
|
86
120
|
{...rest}
|
|
121
|
+
oninput={handleInput}
|
|
122
|
+
onpointerdown={handlePointerDown}
|
|
123
|
+
onpointerup={handlePointerUp}
|
|
124
|
+
onpointercancel={handlePointerCancel}
|
|
87
125
|
aria-describedby={ariaDescribedby ?? field?.describedBy}
|
|
88
126
|
aria-invalid={ariaInvalid ?? (isInvalid ? 'true' : undefined)}
|
|
89
127
|
/>
|
|
@@ -101,7 +139,7 @@
|
|
|
101
139
|
{#if marks.length > 0}
|
|
102
140
|
<span class="marks" aria-hidden="true">
|
|
103
141
|
{#each marks as m, i (`${i}:${m.value}`)}
|
|
104
|
-
<button type="button" class="mark" class:on={Number(value) === m.value} style="--f: {frac(m.value)}" tabindex="-1" onclick={() => (
|
|
142
|
+
<button type="button" class="mark" class:on={Number(value) === m.value} style="--f: {frac(m.value)}" tabindex="-1" onclick={() => pick(m.value)}>{m.label}</button>
|
|
105
143
|
{/each}
|
|
106
144
|
</span>
|
|
107
145
|
{/if}
|
|
@@ -138,6 +176,9 @@
|
|
|
138
176
|
color: var(--text);
|
|
139
177
|
}
|
|
140
178
|
.slider {
|
|
179
|
+
--thumb: 1.2rem;
|
|
180
|
+
--track: 0.35rem;
|
|
181
|
+
--halo: 0 0 0 4px color-mix(in srgb, var(--slider-accent, var(--accent)) 20%, transparent);
|
|
141
182
|
display: flex;
|
|
142
183
|
align-items: center;
|
|
143
184
|
gap: var(--sp-3);
|
|
@@ -164,7 +205,7 @@
|
|
|
164
205
|
}
|
|
165
206
|
/* Track — WebKit/Blink. Filled up to --pct with the accent, then the rail. */
|
|
166
207
|
input[type='range']::-webkit-slider-runnable-track {
|
|
167
|
-
height:
|
|
208
|
+
height: var(--track);
|
|
168
209
|
border-radius: var(--r-pill);
|
|
169
210
|
background: linear-gradient(
|
|
170
211
|
to right,
|
|
@@ -173,12 +214,12 @@
|
|
|
173
214
|
);
|
|
174
215
|
}
|
|
175
216
|
input[type='range']::-moz-range-track {
|
|
176
|
-
height:
|
|
217
|
+
height: var(--track);
|
|
177
218
|
border-radius: var(--r-pill);
|
|
178
219
|
background: var(--bg-elevated-2);
|
|
179
220
|
}
|
|
180
221
|
input[type='range']::-moz-range-progress {
|
|
181
|
-
height:
|
|
222
|
+
height: var(--track);
|
|
182
223
|
border-radius: var(--r-pill);
|
|
183
224
|
background: var(--slider-accent, var(--accent));
|
|
184
225
|
}
|
|
@@ -186,36 +227,52 @@
|
|
|
186
227
|
input[type='range']::-webkit-slider-thumb {
|
|
187
228
|
appearance: none;
|
|
188
229
|
-webkit-appearance: none;
|
|
189
|
-
margin-top: -
|
|
190
|
-
width:
|
|
191
|
-
height:
|
|
192
|
-
border-radius:
|
|
230
|
+
margin-top: calc((var(--track) - var(--thumb)) / 2);
|
|
231
|
+
width: var(--thumb);
|
|
232
|
+
height: var(--thumb);
|
|
233
|
+
border-radius: var(--r-pill);
|
|
193
234
|
background: var(--slider-accent, var(--accent));
|
|
194
235
|
border: 2px solid var(--bg);
|
|
195
236
|
box-shadow: var(--shadow-sm);
|
|
196
|
-
transition:
|
|
237
|
+
transition:
|
|
238
|
+
scale var(--dur-press) var(--ease-out),
|
|
239
|
+
box-shadow var(--dur-fast) var(--ease);
|
|
197
240
|
}
|
|
198
241
|
input[type='range']::-moz-range-thumb {
|
|
199
|
-
width:
|
|
200
|
-
height:
|
|
201
|
-
border-radius:
|
|
242
|
+
width: var(--thumb);
|
|
243
|
+
height: var(--thumb);
|
|
244
|
+
border-radius: var(--r-pill);
|
|
202
245
|
background: var(--slider-accent, var(--accent));
|
|
203
246
|
border: 2px solid var(--bg);
|
|
204
247
|
box-shadow: var(--shadow-sm);
|
|
248
|
+
transition:
|
|
249
|
+
scale var(--dur-press) var(--ease-out),
|
|
250
|
+
box-shadow var(--dur-fast) var(--ease);
|
|
205
251
|
}
|
|
206
|
-
|
|
207
|
-
|
|
252
|
+
@media (hover: hover) and (pointer: fine) {
|
|
253
|
+
input[type='range']:not(:disabled):hover::-webkit-slider-thumb {
|
|
254
|
+
box-shadow: var(--shadow-sm), var(--halo);
|
|
255
|
+
}
|
|
256
|
+
input[type='range']:not(:disabled):hover::-moz-range-thumb {
|
|
257
|
+
box-shadow: var(--shadow-sm), var(--halo);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
input[type='range']:not(:disabled):active::-webkit-slider-thumb {
|
|
261
|
+
scale: 1.15;
|
|
262
|
+
}
|
|
263
|
+
input[type='range']:not(:disabled):active::-moz-range-thumb {
|
|
264
|
+
scale: 1.15;
|
|
208
265
|
}
|
|
209
266
|
input[type='range']:focus-visible {
|
|
210
267
|
outline: none;
|
|
211
268
|
}
|
|
212
269
|
input[type='range']:focus-visible::-webkit-slider-thumb {
|
|
213
270
|
outline: var(--focus-ring);
|
|
214
|
-
outline-offset:
|
|
271
|
+
outline-offset: var(--focus-ring-offset);
|
|
215
272
|
}
|
|
216
273
|
input[type='range']:focus-visible::-moz-range-thumb {
|
|
217
274
|
outline: var(--focus-ring);
|
|
218
|
-
outline-offset:
|
|
275
|
+
outline-offset: var(--focus-ring-offset);
|
|
219
276
|
}
|
|
220
277
|
@media (pointer: coarse) {
|
|
221
278
|
input[type='range'] {
|
|
@@ -223,7 +280,7 @@
|
|
|
223
280
|
}
|
|
224
281
|
}
|
|
225
282
|
input[type='range']:disabled {
|
|
226
|
-
opacity:
|
|
283
|
+
opacity: var(--disabled-opacity);
|
|
227
284
|
cursor: not-allowed;
|
|
228
285
|
}
|
|
229
286
|
.ticks {
|
|
@@ -235,11 +292,11 @@
|
|
|
235
292
|
.tick {
|
|
236
293
|
position: absolute;
|
|
237
294
|
top: 50%;
|
|
238
|
-
left: calc(
|
|
239
|
-
width:
|
|
240
|
-
height:
|
|
241
|
-
margin: -
|
|
242
|
-
border-radius:
|
|
295
|
+
left: calc(var(--thumb) / 2 + (100% - var(--thumb)) * var(--f));
|
|
296
|
+
width: var(--track);
|
|
297
|
+
height: var(--track);
|
|
298
|
+
margin: calc(var(--track) / -2) 0 0 calc(var(--track) / -2);
|
|
299
|
+
border-radius: var(--r-pill);
|
|
243
300
|
background: var(--border-strong);
|
|
244
301
|
}
|
|
245
302
|
.tick.reached {
|
|
@@ -19,6 +19,8 @@ type $$ComponentProps = HTMLInputAttributes & {
|
|
|
19
19
|
}[];
|
|
20
20
|
/** Fixed width (`flex: none`). */
|
|
21
21
|
width?: string;
|
|
22
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
23
|
+
sound?: boolean;
|
|
22
24
|
id?: string;
|
|
23
25
|
'aria-describedby'?: string | null;
|
|
24
26
|
'aria-invalid'?: HTMLInputAttributes['aria-invalid'];
|