@dorsk/tsumikit 0.74.0 → 0.75.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 +38 -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/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/organisms/ConversationFeed.svelte +4 -0
- package/dist/components/organisms/DataTable.svelte +37 -14
- package/dist/floating.js +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -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/package.json +1 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import Icon from '../atoms/Icon.svelte';
|
|
9
9
|
import type { IconName } from '../atoms/Icon.svelte';
|
|
10
10
|
import { formatCount, hasCount } from '../../count';
|
|
11
|
+
import { playSound } from '../../sound';
|
|
11
12
|
|
|
12
13
|
export interface TabBarItem {
|
|
13
14
|
id: string;
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
onselect,
|
|
28
29
|
label = 'Primary',
|
|
29
30
|
placement = 'bar',
|
|
31
|
+
sound = true,
|
|
30
32
|
class: klass = '',
|
|
31
33
|
...rest
|
|
32
34
|
}: {
|
|
@@ -38,6 +40,8 @@
|
|
|
38
40
|
label?: string;
|
|
39
41
|
/** 'bar' = fixed to the bottom edge; 'inline' = flows with its parent. */
|
|
40
42
|
placement?: 'bar' | 'inline';
|
|
43
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
44
|
+
sound?: boolean;
|
|
41
45
|
class?: string;
|
|
42
46
|
[key: string]: unknown;
|
|
43
47
|
} = $props();
|
|
@@ -60,6 +64,7 @@
|
|
|
60
64
|
function select(item: TabBarItem) {
|
|
61
65
|
if (item.id === value) return;
|
|
62
66
|
value = item.id;
|
|
67
|
+
playSound('click', sound);
|
|
63
68
|
onselect?.(item.id, item);
|
|
64
69
|
}
|
|
65
70
|
|
|
@@ -82,7 +87,7 @@
|
|
|
82
87
|
{#snippet glyph(item: TabBarItem)}
|
|
83
88
|
<span class="tabbar-glyph">
|
|
84
89
|
{#if item.icon}
|
|
85
|
-
<Icon name={item.icon}
|
|
90
|
+
<Icon name={item.icon} />
|
|
86
91
|
{/if}
|
|
87
92
|
{#if badgeText(item.badge)}
|
|
88
93
|
<Badge class="tabbar-badge" tone="accent" size="xs" border={false} active numeric={typeof item.badge === 'number'}>
|
|
@@ -167,7 +172,7 @@
|
|
|
167
172
|
flex-direction: column;
|
|
168
173
|
align-items: center;
|
|
169
174
|
justify-content: center;
|
|
170
|
-
gap:
|
|
175
|
+
gap: var(--sp-0-5);
|
|
171
176
|
padding: var(--sp-1) var(--sp-2);
|
|
172
177
|
border: none;
|
|
173
178
|
border-radius: 0;
|
|
@@ -179,15 +184,17 @@
|
|
|
179
184
|
text-decoration: none;
|
|
180
185
|
cursor: pointer;
|
|
181
186
|
-webkit-tap-highlight-color: transparent;
|
|
182
|
-
transition: color
|
|
187
|
+
transition: color var(--dur-fast) var(--ease);
|
|
183
188
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
189
|
+
@media (hover: hover) and (pointer: fine) {
|
|
190
|
+
.tabbar-item:hover {
|
|
191
|
+
color: var(--text);
|
|
192
|
+
text-decoration: none;
|
|
193
|
+
}
|
|
187
194
|
}
|
|
188
195
|
.tabbar-item:focus-visible {
|
|
189
|
-
outline:
|
|
190
|
-
outline-offset: -
|
|
196
|
+
outline: var(--focus-ring);
|
|
197
|
+
outline-offset: var(--focus-ring-offset-inset);
|
|
191
198
|
}
|
|
192
199
|
.tabbar-item.current {
|
|
193
200
|
color: var(--accent);
|
|
@@ -197,6 +204,13 @@
|
|
|
197
204
|
display: inline-flex;
|
|
198
205
|
flex: none;
|
|
199
206
|
align-items: center;
|
|
207
|
+
font-size: var(--icon-xl);
|
|
208
|
+
--icon-size: var(--icon-xl);
|
|
209
|
+
transition: scale var(--dur-fast) var(--ease-out);
|
|
210
|
+
}
|
|
211
|
+
.tabbar-item:active .tabbar-glyph {
|
|
212
|
+
scale: var(--press-scale-sm);
|
|
213
|
+
transition-duration: var(--dur-press);
|
|
200
214
|
}
|
|
201
215
|
.tabbar-label {
|
|
202
216
|
max-width: 100%;
|
|
@@ -209,11 +223,7 @@
|
|
|
209
223
|
top: -0.4rem;
|
|
210
224
|
left: calc(100% - 2px);
|
|
211
225
|
max-width: none;
|
|
212
|
-
padding-inline:
|
|
213
|
-
|
|
214
|
-
@media (prefers-reduced-motion: reduce) {
|
|
215
|
-
.tabbar-item {
|
|
216
|
-
transition: none;
|
|
217
|
-
}
|
|
226
|
+
padding-inline: var(--sp-1-5);
|
|
227
|
+
font-size: var(--fs-xs);
|
|
218
228
|
}
|
|
219
229
|
</style>
|
|
@@ -19,6 +19,8 @@ type $$ComponentProps = {
|
|
|
19
19
|
label?: string;
|
|
20
20
|
/** 'bar' = fixed to the bottom edge; 'inline' = flows with its parent. */
|
|
21
21
|
placement?: 'bar' | 'inline';
|
|
22
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
23
|
+
sound?: boolean;
|
|
22
24
|
class?: string;
|
|
23
25
|
[key: string]: unknown;
|
|
24
26
|
};
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
variant = 'default',
|
|
38
38
|
size = 'default',
|
|
39
39
|
onchange,
|
|
40
|
+
sound = true,
|
|
40
41
|
class: klass = '',
|
|
41
42
|
style: styleProp = '',
|
|
42
43
|
...rest
|
|
@@ -52,6 +53,8 @@
|
|
|
52
53
|
/** Header/panel density of every item; forwarded to `Disclosure`. */
|
|
53
54
|
size?: DisclosureSize;
|
|
54
55
|
onchange?: (id: string, open: boolean) => void;
|
|
56
|
+
/** Play UI sounds when enabled globally; false silences every item. */
|
|
57
|
+
sound?: boolean;
|
|
55
58
|
class?: string;
|
|
56
59
|
style?: string;
|
|
57
60
|
};
|
|
@@ -105,6 +108,7 @@
|
|
|
105
108
|
disabled={item.disabled}
|
|
106
109
|
{chevron}
|
|
107
110
|
{size}
|
|
111
|
+
{sound}
|
|
108
112
|
>
|
|
109
113
|
{#snippet header(ctx)}
|
|
110
114
|
{#if item.summary}
|
|
@@ -31,6 +31,8 @@ type Own = {
|
|
|
31
31
|
/** Header/panel density of every item; forwarded to `Disclosure`. */
|
|
32
32
|
size?: DisclosureSize;
|
|
33
33
|
onchange?: (id: string, open: boolean) => void;
|
|
34
|
+
/** Play UI sounds when enabled globally; false silences every item. */
|
|
35
|
+
sound?: boolean;
|
|
34
36
|
class?: string;
|
|
35
37
|
style?: string;
|
|
36
38
|
};
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
{#if src}
|
|
129
129
|
<img class="thumb" {src} alt="" />
|
|
130
130
|
{:else}
|
|
131
|
-
<Icon name={isImage(f) ? 'image' : 'file'} size
|
|
131
|
+
<Icon name={isImage(f) ? 'image' : 'file'} style="font-size: var(--icon-lg)" />
|
|
132
132
|
{/if}
|
|
133
133
|
{#if numbered}<span class="num tile-num">{i + 1}</span>{/if}
|
|
134
134
|
</span>
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
onremove?.(i);
|
|
150
150
|
}}
|
|
151
151
|
>
|
|
152
|
-
<Icon name="trash" size
|
|
152
|
+
<Icon name="trash" style="font-size: var(--control-icon-sm)" />
|
|
153
153
|
</Button>
|
|
154
154
|
{/if}
|
|
155
155
|
</div>
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
width: 100%;
|
|
224
224
|
height: 100%;
|
|
225
225
|
object-fit: cover;
|
|
226
|
-
border-radius: calc(var(--r-md) -
|
|
226
|
+
border-radius: calc(var(--r-md) - var(--sp-px));
|
|
227
227
|
}
|
|
228
228
|
.detail {
|
|
229
229
|
display: flex;
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
overflow-wrap: anywhere;
|
|
248
248
|
}
|
|
249
249
|
.chip :global(.action) {
|
|
250
|
-
font-size:
|
|
250
|
+
font-size: var(--fs-md);
|
|
251
251
|
}
|
|
252
252
|
.chip :global(.clip) {
|
|
253
253
|
display: inline-flex;
|
|
@@ -278,13 +278,16 @@
|
|
|
278
278
|
color: inherit;
|
|
279
279
|
cursor: pointer;
|
|
280
280
|
}
|
|
281
|
-
|
|
282
|
-
|
|
281
|
+
@media (hover: hover) and (pointer: fine) {
|
|
282
|
+
.open:hover {
|
|
283
|
+
text-decoration: underline;
|
|
284
|
+
}
|
|
283
285
|
}
|
|
286
|
+
/* The clip span hides overflow, so the ring sits inside the name. */
|
|
284
287
|
.open:focus-visible {
|
|
285
288
|
outline: var(--focus-ring);
|
|
286
|
-
outline-offset: var(--focus-ring-offset);
|
|
287
|
-
border-radius: var(--r-
|
|
289
|
+
outline-offset: var(--focus-ring-offset-inset);
|
|
290
|
+
border-radius: var(--r-xs);
|
|
288
291
|
}
|
|
289
292
|
.mini {
|
|
290
293
|
flex: none;
|
|
@@ -295,9 +298,9 @@
|
|
|
295
298
|
}
|
|
296
299
|
.num {
|
|
297
300
|
flex: none;
|
|
298
|
-
font-size:
|
|
299
|
-
font-weight:
|
|
300
|
-
line-height:
|
|
301
|
+
font-size: var(--fs-2xs);
|
|
302
|
+
font-weight: var(--fw-semibold);
|
|
303
|
+
line-height: var(--lh-none);
|
|
301
304
|
color: var(--text-muted);
|
|
302
305
|
}
|
|
303
306
|
.face {
|
|
@@ -72,10 +72,7 @@
|
|
|
72
72
|
{/if}
|
|
73
73
|
{#if i < shown.length - 1}
|
|
74
74
|
<span class="sep" aria-hidden="true">
|
|
75
|
-
{#if separator}{@render separator()}{:else if char}{char}{:else}<Icon
|
|
76
|
-
name="chevron-right"
|
|
77
|
-
size={size === 'md' ? 16 : 14}
|
|
78
|
-
/>{/if}
|
|
75
|
+
{#if separator}{@render separator()}{:else if char}{char}{:else}<Icon name="chevron-right" />{/if}
|
|
79
76
|
</span>
|
|
80
77
|
{/if}
|
|
81
78
|
</li>
|
|
@@ -127,11 +124,14 @@
|
|
|
127
124
|
overflow: hidden;
|
|
128
125
|
text-overflow: ellipsis;
|
|
129
126
|
max-width: 16ch;
|
|
130
|
-
transition: color
|
|
127
|
+
transition: color var(--dur-fast) ease;
|
|
131
128
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
129
|
+
@media (hover: hover) and (pointer: fine) {
|
|
130
|
+
.link:hover {
|
|
131
|
+
color: var(--text);
|
|
132
|
+
text-decoration: underline;
|
|
133
|
+
transition-duration: var(--dur-instant);
|
|
134
|
+
}
|
|
135
135
|
}
|
|
136
136
|
.current {
|
|
137
137
|
color: var(--text);
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
}
|
|
144
144
|
@media (hover: none) and (pointer: coarse) {
|
|
145
145
|
.link {
|
|
146
|
-
min-height:
|
|
146
|
+
min-height: var(--control-md);
|
|
147
147
|
align-content: center;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -154,5 +154,9 @@
|
|
|
154
154
|
display: inline-flex;
|
|
155
155
|
align-items: center;
|
|
156
156
|
color: var(--text-subtle, var(--text-muted));
|
|
157
|
+
font-size: var(--icon-sm);
|
|
158
|
+
}
|
|
159
|
+
.crumbs--md .sep {
|
|
160
|
+
font-size: var(--icon-md);
|
|
157
161
|
}
|
|
158
162
|
</style>
|
|
@@ -111,8 +111,8 @@
|
|
|
111
111
|
flex: none;
|
|
112
112
|
align-items: center;
|
|
113
113
|
color: var(--callout-tone);
|
|
114
|
-
font-size:
|
|
115
|
-
line-height:
|
|
114
|
+
font-size: var(--fs-lg);
|
|
115
|
+
line-height: var(--lh-none);
|
|
116
116
|
min-height: 1.4em;
|
|
117
117
|
}
|
|
118
118
|
.callout-body {
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
flex-direction: column;
|
|
123
123
|
gap: var(--sp-1);
|
|
124
124
|
font-size: var(--fs-sm);
|
|
125
|
-
line-height:
|
|
125
|
+
line-height: var(--lh-normal);
|
|
126
126
|
color: var(--text);
|
|
127
127
|
}
|
|
128
128
|
.callout-title {
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
onpointerup={pointerUp}
|
|
208
208
|
onpointercancel={pointerUp}
|
|
209
209
|
>
|
|
210
|
-
<div class="fill"></div>
|
|
210
|
+
<div class="fill-clip"><div class="fill"></div></div>
|
|
211
211
|
{#if markerPct !== null}
|
|
212
212
|
<div class="marker marker-{markerTone}" title={markerLabel} aria-hidden="true"></div>
|
|
213
213
|
{#if markerLabel}
|
|
@@ -287,14 +287,20 @@
|
|
|
287
287
|
box-shadow: inset 0 0 0 1px var(--border);
|
|
288
288
|
pointer-events: none;
|
|
289
289
|
}
|
|
290
|
+
.fill-clip {
|
|
291
|
+
position: absolute;
|
|
292
|
+
inset: 0;
|
|
293
|
+
border-radius: var(--r-pill);
|
|
294
|
+
overflow: hidden;
|
|
295
|
+
z-index: 1;
|
|
296
|
+
}
|
|
290
297
|
.fill {
|
|
291
298
|
position: absolute;
|
|
292
|
-
inset: 0
|
|
293
|
-
width: var(--pct);
|
|
299
|
+
inset: 0;
|
|
294
300
|
border-radius: var(--r-pill);
|
|
295
301
|
background: var(--fill);
|
|
296
|
-
|
|
297
|
-
|
|
302
|
+
translate: calc(var(--pct) - 100%) 0;
|
|
303
|
+
transition: translate var(--dur-base) var(--ease-out);
|
|
298
304
|
}
|
|
299
305
|
.uncapped .track::after {
|
|
300
306
|
display: none;
|
|
@@ -306,7 +312,7 @@
|
|
|
306
312
|
width: 2px;
|
|
307
313
|
height: calc(var(--track-h) + 6px);
|
|
308
314
|
transform: translate(-50%, -50%);
|
|
309
|
-
border-radius:
|
|
315
|
+
border-radius: var(--r-xs);
|
|
310
316
|
background: var(--marker-color, var(--text-muted));
|
|
311
317
|
pointer-events: none;
|
|
312
318
|
z-index: 2;
|
|
@@ -338,7 +344,7 @@
|
|
|
338
344
|
width: 3px;
|
|
339
345
|
height: 16px;
|
|
340
346
|
transform: translate(-50%, -50%);
|
|
341
|
-
border-radius:
|
|
347
|
+
border-radius: var(--r-xs);
|
|
342
348
|
background: var(--text);
|
|
343
349
|
box-shadow: 0 0 0 2px var(--surface);
|
|
344
350
|
cursor: ew-resize;
|
|
@@ -348,36 +354,37 @@
|
|
|
348
354
|
opacity: 0.4;
|
|
349
355
|
}
|
|
350
356
|
.handle:focus-visible {
|
|
351
|
-
outline:
|
|
352
|
-
outline-offset:
|
|
357
|
+
outline: var(--focus-ring);
|
|
358
|
+
outline-offset: var(--focus-ring-offset);
|
|
353
359
|
}
|
|
354
360
|
.bubble {
|
|
355
361
|
position: absolute;
|
|
356
|
-
bottom: calc(100% +
|
|
357
|
-
left: var(--cap);
|
|
358
|
-
|
|
359
|
-
padding:
|
|
362
|
+
bottom: calc(100% + var(--sp-2));
|
|
363
|
+
left: clamp(0%, var(--cap), 100%);
|
|
364
|
+
translate: calc(-1 * clamp(0%, var(--cap), 100%)) 0;
|
|
365
|
+
padding: var(--sp-px) var(--sp-1);
|
|
360
366
|
border: 1px solid var(--border-strong);
|
|
361
367
|
border-radius: var(--r-sm);
|
|
362
368
|
background: var(--bg-elevated-2);
|
|
363
369
|
box-shadow: var(--shadow-sm);
|
|
364
370
|
color: var(--text);
|
|
365
371
|
font-size: var(--fs-xs);
|
|
366
|
-
line-height:
|
|
372
|
+
line-height: var(--lh-snug);
|
|
367
373
|
font-variant-numeric: tabular-nums;
|
|
368
374
|
white-space: nowrap;
|
|
369
375
|
pointer-events: none;
|
|
370
376
|
opacity: 0;
|
|
371
377
|
visibility: hidden;
|
|
372
378
|
transition:
|
|
373
|
-
opacity
|
|
374
|
-
visibility
|
|
379
|
+
opacity var(--dur-exit) var(--ease),
|
|
380
|
+
visibility var(--dur-exit);
|
|
375
381
|
z-index: 3;
|
|
376
382
|
}
|
|
377
383
|
.dragging .bubble,
|
|
378
384
|
.keying .bubble {
|
|
379
385
|
opacity: 1;
|
|
380
386
|
visibility: visible;
|
|
387
|
+
transition-duration: var(--dur-fast);
|
|
381
388
|
}
|
|
382
389
|
.readonly .track,
|
|
383
390
|
.readonly .handle {
|
|
@@ -419,10 +426,4 @@
|
|
|
419
426
|
.cap-bar.stacked .caption {
|
|
420
427
|
grid-column: 1 / -1;
|
|
421
428
|
}
|
|
422
|
-
@media (prefers-reduced-motion: reduce) {
|
|
423
|
-
.fill,
|
|
424
|
-
.bubble {
|
|
425
|
-
transition: none;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
429
|
</style>
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
{onpointerup}
|
|
144
144
|
{onpointercancel}
|
|
145
145
|
>
|
|
146
|
-
<div class="track" style:
|
|
146
|
+
<div class="track" style:translate="{-index * 100}% 0">
|
|
147
147
|
{#each slides as item, i (i)}
|
|
148
148
|
<div
|
|
149
149
|
class="slide {slideClass}"
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
.track {
|
|
223
223
|
display: flex;
|
|
224
224
|
width: 100%;
|
|
225
|
-
transition:
|
|
225
|
+
transition: translate var(--dur-sheet) var(--ease-in-out);
|
|
226
226
|
}
|
|
227
227
|
.slide {
|
|
228
228
|
flex: 0 0 100%;
|
|
@@ -240,37 +240,47 @@
|
|
|
240
240
|
gap: var(--sp-2);
|
|
241
241
|
}
|
|
242
242
|
.dot {
|
|
243
|
-
|
|
244
|
-
|
|
243
|
+
position: relative;
|
|
244
|
+
width: var(--sp-2);
|
|
245
|
+
height: var(--sp-2);
|
|
245
246
|
padding: 0;
|
|
246
247
|
border: 0;
|
|
247
248
|
border-radius: var(--r-pill);
|
|
248
249
|
background: var(--border);
|
|
249
250
|
cursor: pointer;
|
|
250
251
|
transition:
|
|
251
|
-
background
|
|
252
|
-
|
|
252
|
+
background var(--dur-fast) var(--ease),
|
|
253
|
+
scale var(--dur-fast) var(--ease);
|
|
253
254
|
}
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
@media (hover: hover) and (pointer: fine) {
|
|
256
|
+
.dot:hover {
|
|
257
|
+
background: var(--text-faint);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
.dot:active {
|
|
261
|
+
scale: var(--press-scale-sm);
|
|
256
262
|
}
|
|
257
263
|
.dot.active {
|
|
258
264
|
background: var(--accent);
|
|
259
|
-
|
|
265
|
+
scale: 1.25;
|
|
260
266
|
}
|
|
261
267
|
.dot:focus-visible {
|
|
262
|
-
outline:
|
|
263
|
-
outline-offset:
|
|
268
|
+
outline: var(--focus-ring);
|
|
269
|
+
outline-offset: var(--focus-ring-offset);
|
|
270
|
+
}
|
|
271
|
+
@media (pointer: coarse) {
|
|
272
|
+
.dots {
|
|
273
|
+
gap: var(--sp-4);
|
|
274
|
+
}
|
|
275
|
+
.dot::before {
|
|
276
|
+
content: '';
|
|
277
|
+
position: absolute;
|
|
278
|
+
inset: calc((100% - var(--sp-6)) / 2);
|
|
279
|
+
}
|
|
264
280
|
}
|
|
265
281
|
.counter {
|
|
266
282
|
color: var(--text-muted);
|
|
267
283
|
font-size: var(--fs-sm);
|
|
268
284
|
font-variant-numeric: tabular-nums;
|
|
269
285
|
}
|
|
270
|
-
@media (prefers-reduced-motion: reduce) {
|
|
271
|
-
.track,
|
|
272
|
-
.dot {
|
|
273
|
-
transition: none;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
286
|
</style>
|
|
@@ -134,8 +134,8 @@
|
|
|
134
134
|
align-self: flex-start;
|
|
135
135
|
}
|
|
136
136
|
.selected {
|
|
137
|
-
outline:
|
|
138
|
-
outline-offset:
|
|
137
|
+
outline: var(--focus-ring);
|
|
138
|
+
outline-offset: var(--focus-ring-offset);
|
|
139
139
|
}
|
|
140
140
|
.bubble[data-state='sending'] {
|
|
141
141
|
opacity: 0.7;
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
user-select: none;
|
|
119
119
|
font-family: var(--font-mono);
|
|
120
120
|
font-size: var(--fs-sm);
|
|
121
|
-
line-height:
|
|
121
|
+
line-height: var(--lh-normal);
|
|
122
122
|
}
|
|
123
123
|
.cb-pre {
|
|
124
124
|
margin: 0;
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
flex: 1;
|
|
127
127
|
font-family: var(--font-mono);
|
|
128
128
|
font-size: var(--fs-sm);
|
|
129
|
-
line-height:
|
|
129
|
+
line-height: var(--lh-normal);
|
|
130
130
|
color: var(--md-text, var(--text));
|
|
131
131
|
tab-size: 2;
|
|
132
132
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { tick, type Snippet } from 'svelte';
|
|
8
8
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
9
9
|
import { type AnchorRect, placeAt } from '../../floating';
|
|
10
|
+
import { playSound } from '../../sound';
|
|
10
11
|
import { caretRect, comboboxAction } from './combobox-keyboard.js';
|
|
11
12
|
|
|
12
13
|
type FieldEl = HTMLInputElement | HTMLTextAreaElement;
|
|
@@ -46,6 +47,8 @@
|
|
|
46
47
|
option?: Snippet<[T, { active: boolean; index: number }]>;
|
|
47
48
|
/** Shown instead of rows when `options` is empty; without it the listbox hides. */
|
|
48
49
|
empty?: string | Snippet;
|
|
50
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
51
|
+
sound?: boolean;
|
|
49
52
|
children: Snippet;
|
|
50
53
|
class?: string;
|
|
51
54
|
style?: string;
|
|
@@ -73,6 +76,7 @@
|
|
|
73
76
|
onclose,
|
|
74
77
|
option,
|
|
75
78
|
empty,
|
|
79
|
+
sound = true,
|
|
76
80
|
children,
|
|
77
81
|
class: klass = '',
|
|
78
82
|
style: styleProp = '',
|
|
@@ -136,6 +140,13 @@
|
|
|
136
140
|
placeAt(r, panelEl, placement, gap);
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
let wasVisible: boolean | null = null;
|
|
144
|
+
$effect(() => {
|
|
145
|
+
const v = visible;
|
|
146
|
+
if (wasVisible !== null && v !== wasVisible) playSound(v ? 'open' : 'close', sound);
|
|
147
|
+
wasVisible = v;
|
|
148
|
+
});
|
|
149
|
+
|
|
139
150
|
$effect(() => {
|
|
140
151
|
const p = panelEl;
|
|
141
152
|
if (!visible || !p) return;
|
|
@@ -264,7 +275,7 @@
|
|
|
264
275
|
box-sizing: border-box;
|
|
265
276
|
display: flex;
|
|
266
277
|
flex-direction: column;
|
|
267
|
-
gap:
|
|
278
|
+
gap: var(--sp-px);
|
|
268
279
|
min-width: var(--cb-min-width, 10rem);
|
|
269
280
|
max-width: calc(100vw - 2 * var(--sp-3));
|
|
270
281
|
max-height: var(--cb-max-height, min(16rem, 40vh));
|
|
@@ -275,6 +286,21 @@
|
|
|
275
286
|
border: 1px solid var(--cb-border, var(--border-strong));
|
|
276
287
|
border-radius: var(--cb-radius, var(--r-md));
|
|
277
288
|
box-shadow: var(--shadow-md);
|
|
289
|
+
transform-origin: var(--tsu-origin, top left);
|
|
290
|
+
opacity: 1;
|
|
291
|
+
scale: 1;
|
|
292
|
+
translate: 0;
|
|
293
|
+
transition:
|
|
294
|
+
opacity var(--dur-fast) var(--ease-out),
|
|
295
|
+
scale var(--dur-fast) var(--ease-out),
|
|
296
|
+
translate var(--dur-fast) var(--ease-out);
|
|
297
|
+
}
|
|
298
|
+
@starting-style {
|
|
299
|
+
.cb-panel:popover-open {
|
|
300
|
+
opacity: 0;
|
|
301
|
+
scale: var(--enter-scale);
|
|
302
|
+
translate: var(--tsu-shift, 0 calc(-1 * var(--shift-sm)));
|
|
303
|
+
}
|
|
278
304
|
}
|
|
279
305
|
.cb-panel.cb-caret {
|
|
280
306
|
max-width: min(22rem, calc(100vw - 2 * var(--sp-3)));
|
|
@@ -287,9 +313,12 @@
|
|
|
287
313
|
overflow: hidden;
|
|
288
314
|
text-overflow: ellipsis;
|
|
289
315
|
white-space: nowrap;
|
|
316
|
+
transition: background-color var(--dur-fast) ease;
|
|
290
317
|
}
|
|
318
|
+
/* Highlight lands instantly and fades out: list navigation is high frequency. */
|
|
291
319
|
.cb-option.active {
|
|
292
320
|
background: var(--cb-active-bg, var(--bg-elevated-2));
|
|
321
|
+
transition-duration: var(--dur-instant);
|
|
293
322
|
}
|
|
294
323
|
.cb-empty {
|
|
295
324
|
padding: var(--sp-1) var(--sp-2);
|
|
@@ -37,6 +37,8 @@ declare function $$render<T>(): {
|
|
|
37
37
|
}]>;
|
|
38
38
|
/** Shown instead of rows when `options` is empty; without it the listbox hides. */
|
|
39
39
|
empty?: string | Snippet;
|
|
40
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
41
|
+
sound?: boolean;
|
|
40
42
|
children: Snippet;
|
|
41
43
|
class?: string;
|
|
42
44
|
style?: string;
|
|
@@ -78,6 +80,8 @@ declare function $$render<T>(): {
|
|
|
78
80
|
}]>;
|
|
79
81
|
/** Shown instead of rows when `options` is empty; without it the listbox hides. */
|
|
80
82
|
empty?: string | Snippet;
|
|
83
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
84
|
+
sound?: boolean;
|
|
81
85
|
children: Snippet;
|
|
82
86
|
class?: string;
|
|
83
87
|
style?: string;
|
|
@@ -229,8 +229,8 @@
|
|
|
229
229
|
border-radius: var(--r-lg);
|
|
230
230
|
}
|
|
231
231
|
.composer.dragging {
|
|
232
|
-
outline:
|
|
233
|
-
outline-offset: var(--
|
|
232
|
+
outline: var(--focus-ring-width) dashed var(--accent);
|
|
233
|
+
outline-offset: var(--focus-ring-offset);
|
|
234
234
|
}
|
|
235
235
|
.toolbar {
|
|
236
236
|
display: flex;
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
oncancel,
|
|
22
22
|
class: klass = '',
|
|
23
23
|
style: styleProp = '',
|
|
24
|
+
sound = true,
|
|
24
25
|
}: {
|
|
25
26
|
open?: boolean;
|
|
26
27
|
title: string;
|
|
@@ -35,6 +36,8 @@
|
|
|
35
36
|
oncancel?: () => void;
|
|
36
37
|
class?: string;
|
|
37
38
|
style?: string;
|
|
39
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
40
|
+
sound?: boolean;
|
|
38
41
|
} = $props();
|
|
39
42
|
const t = $derived(canonicalTone(tone));
|
|
40
43
|
const modalTone = $derived(t === 'danger' || t === 'warn' || t === 'info' ? t : 'neutral');
|
|
@@ -80,6 +83,7 @@
|
|
|
80
83
|
size="sm"
|
|
81
84
|
class={klass}
|
|
82
85
|
style={styleProp}
|
|
86
|
+
{sound}
|
|
83
87
|
>
|
|
84
88
|
{#snippet body()}
|
|
85
89
|
<div class="confirm-body" data-tsu="ConfirmModal">
|
|
@@ -14,6 +14,8 @@ type $$ComponentProps = {
|
|
|
14
14
|
oncancel?: () => void;
|
|
15
15
|
class?: string;
|
|
16
16
|
style?: string;
|
|
17
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
18
|
+
sound?: boolean;
|
|
17
19
|
};
|
|
18
20
|
declare const ConfirmModal: import("svelte").Component<$$ComponentProps, {}, "open">;
|
|
19
21
|
type ConfirmModal = ReturnType<typeof ConfirmModal>;
|