@miozu/jera 0.3.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +350 -59
- package/README.md +30 -22
- package/llms.txt +37 -4
- package/package.json +12 -2
- package/src/components/docs/CodeBlock.svelte +203 -0
- package/src/components/docs/DocSection.svelte +120 -0
- package/src/components/docs/PropsTable.svelte +136 -0
- package/src/components/docs/SplitPane.svelte +98 -0
- package/src/components/docs/index.js +14 -0
- package/src/components/feedback/Alert.svelte +234 -0
- package/src/components/feedback/EmptyState.svelte +6 -6
- package/src/components/feedback/ProgressBar.svelte +8 -8
- package/src/components/feedback/Skeleton.svelte +4 -4
- package/src/components/feedback/Spinner.svelte +1 -1
- package/src/components/feedback/Toast.svelte +137 -173
- package/src/components/forms/Checkbox.svelte +10 -10
- package/src/components/forms/Dropzone.svelte +14 -14
- package/src/components/forms/FileUpload.svelte +16 -16
- package/src/components/forms/IconInput.svelte +4 -4
- package/src/components/forms/Input.svelte +14 -14
- package/src/components/forms/NumberInput.svelte +13 -13
- package/src/components/forms/PinInput.svelte +8 -8
- package/src/components/forms/Radio.svelte +8 -8
- package/src/components/forms/RangeSlider.svelte +12 -12
- package/src/components/forms/SearchInput.svelte +10 -10
- package/src/components/forms/Select.svelte +156 -158
- package/src/components/forms/Switch.svelte +4 -4
- package/src/components/forms/Textarea.svelte +9 -9
- package/src/components/navigation/Accordion.svelte +1 -1
- package/src/components/navigation/AccordionItem.svelte +6 -6
- package/src/components/navigation/NavigationContainer.svelte +344 -0
- package/src/components/navigation/Sidebar.svelte +334 -0
- package/src/components/navigation/SidebarAccountGroup.svelte +495 -0
- package/src/components/navigation/SidebarAccountItem.svelte +492 -0
- package/src/components/navigation/SidebarGroup.svelte +230 -0
- package/src/components/navigation/SidebarGroupSwitcher.svelte +262 -0
- package/src/components/navigation/SidebarItem.svelte +210 -0
- package/src/components/navigation/SidebarNavigationItem.svelte +470 -0
- package/src/components/navigation/SidebarPopover.svelte +145 -0
- package/src/components/navigation/SidebarSearch.svelte +236 -0
- package/src/components/navigation/SidebarSection.svelte +158 -0
- package/src/components/navigation/SidebarToggle.svelte +86 -0
- package/src/components/navigation/Tabs.svelte +18 -18
- package/src/components/navigation/WorkspaceMenu.svelte +416 -0
- package/src/components/navigation/blocks/NavigationAccountGroup.svelte +396 -0
- package/src/components/navigation/blocks/NavigationCustomBlock.svelte +74 -0
- package/src/components/navigation/blocks/NavigationGroupSwitcher.svelte +277 -0
- package/src/components/navigation/blocks/NavigationSearch.svelte +300 -0
- package/src/components/navigation/blocks/NavigationSection.svelte +230 -0
- package/src/components/navigation/index.js +22 -0
- package/src/components/overlays/ConfirmDialog.svelte +18 -18
- package/src/components/overlays/Dropdown.svelte +2 -2
- package/src/components/overlays/DropdownDivider.svelte +1 -1
- package/src/components/overlays/DropdownItem.svelte +5 -5
- package/src/components/overlays/Modal.svelte +13 -13
- package/src/components/overlays/Popover.svelte +3 -3
- package/src/components/primitives/Avatar.svelte +12 -12
- package/src/components/primitives/Badge.svelte +7 -7
- package/src/components/primitives/Button.svelte +126 -174
- package/src/components/primitives/Card.svelte +15 -15
- package/src/components/primitives/Divider.svelte +3 -3
- package/src/components/primitives/LazyImage.svelte +1 -1
- package/src/components/primitives/Link.svelte +2 -2
- package/src/components/primitives/Stat.svelte +197 -0
- package/src/components/primitives/StatusBadge.svelte +24 -24
- package/src/index.js +62 -7
- package/src/tokens/colors.css +96 -128
- package/src/utils/highlighter.js +124 -0
- package/src/utils/index.js +7 -2
- package/src/utils/navigation.svelte.js +423 -0
- package/src/utils/reactive.svelte.js +126 -37
- package/src/utils/sidebar.svelte.js +211 -0
|
@@ -2,78 +2,37 @@
|
|
|
2
2
|
@component Toast
|
|
3
3
|
|
|
4
4
|
A toast notification system with stacking, auto-dismiss, and animations.
|
|
5
|
-
Demonstrates advanced Svelte 5 patterns:
|
|
6
|
-
|
|
7
|
-
- Reactive class with ThemeState pattern
|
|
8
|
-
- $state.raw for non-proxied arrays (performance)
|
|
9
|
-
- $effect with cleanup for timers
|
|
10
|
-
- Context API for global toast access
|
|
11
|
-
- Portal action for DOM placement
|
|
12
|
-
- Compound variant styling
|
|
13
5
|
|
|
14
6
|
@example
|
|
15
7
|
// In your root layout
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
<script>
|
|
9
|
+
import { Toast, createToastContext } from '@miozu/jera';
|
|
10
|
+
const toast = createToastContext();
|
|
11
|
+
</script>
|
|
12
|
+
<Toast />
|
|
19
13
|
|
|
20
14
|
// In any component
|
|
21
|
-
import {
|
|
15
|
+
import { getToastContext } from '@miozu/jera';
|
|
16
|
+
const toast = getToastContext();
|
|
22
17
|
toast.success('Saved successfully!');
|
|
23
|
-
toast.error('Something went wrong');
|
|
24
|
-
toast.info('Did you know?');
|
|
25
|
-
toast.custom({ title: 'Custom', message: 'With title', duration: 5000 });
|
|
26
18
|
-->
|
|
27
19
|
<script module>
|
|
28
20
|
import { getContext, setContext } from 'svelte';
|
|
29
|
-
import { cv } from '../../utils/cn.svelte.js';
|
|
30
21
|
|
|
31
22
|
const TOAST_KEY = Symbol('jera-toast');
|
|
32
23
|
|
|
33
|
-
/**
|
|
34
|
-
* @typedef {'info' | 'success' | 'warning' | 'error'} ToastType
|
|
35
|
-
* @typedef {'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'} ToastPosition
|
|
36
|
-
*
|
|
37
|
-
* @typedef {{
|
|
38
|
-
* id: string,
|
|
39
|
-
* type: ToastType,
|
|
40
|
-
* title?: string,
|
|
41
|
-
* message: string,
|
|
42
|
-
* duration: number,
|
|
43
|
-
* createdAt: number,
|
|
44
|
-
* pausedAt?: number
|
|
45
|
-
* }} ToastItem
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
24
|
/**
|
|
49
25
|
* Toast Controller Class
|
|
50
|
-
*
|
|
51
|
-
* Manages toast state and provides methods for showing toasts.
|
|
52
|
-
* Uses Svelte 5 reactive class pattern.
|
|
53
26
|
*/
|
|
54
27
|
export class ToastController {
|
|
55
|
-
/** @type {ToastItem[]} */
|
|
56
28
|
toasts = $state.raw([]);
|
|
57
|
-
|
|
58
|
-
/** @type {ToastPosition} */
|
|
59
29
|
position = $state('bottom-right');
|
|
60
|
-
|
|
61
|
-
/** @type {number} */
|
|
62
30
|
defaultDuration = 4000;
|
|
63
|
-
|
|
64
|
-
/** @type {number} */
|
|
65
31
|
maxToasts = 5;
|
|
66
|
-
|
|
67
32
|
#counter = 0;
|
|
68
33
|
|
|
69
|
-
/**
|
|
70
|
-
* Show a toast
|
|
71
|
-
* @param {Partial<ToastItem> & { message: string }} options
|
|
72
|
-
* @returns {string} Toast ID
|
|
73
|
-
*/
|
|
74
34
|
show(options) {
|
|
75
35
|
const id = `toast-${++this.#counter}`;
|
|
76
|
-
|
|
77
36
|
const toast = {
|
|
78
37
|
id,
|
|
79
38
|
type: options.type ?? 'info',
|
|
@@ -82,196 +41,99 @@
|
|
|
82
41
|
duration: options.duration ?? this.defaultDuration,
|
|
83
42
|
createdAt: Date.now()
|
|
84
43
|
};
|
|
85
|
-
|
|
86
|
-
// Add to beginning (newest first for top positions)
|
|
87
44
|
this.toasts = [toast, ...this.toasts].slice(0, this.maxToasts);
|
|
88
|
-
|
|
89
45
|
return id;
|
|
90
46
|
}
|
|
91
47
|
|
|
92
|
-
/**
|
|
93
|
-
* Dismiss a toast by ID
|
|
94
|
-
* @param {string} id
|
|
95
|
-
*/
|
|
96
48
|
dismiss(id) {
|
|
97
49
|
this.toasts = this.toasts.filter(t => t.id !== id);
|
|
98
50
|
}
|
|
99
51
|
|
|
100
|
-
/**
|
|
101
|
-
* Dismiss all toasts
|
|
102
|
-
*/
|
|
103
52
|
dismissAll() {
|
|
104
53
|
this.toasts = [];
|
|
105
54
|
}
|
|
106
55
|
|
|
107
|
-
/**
|
|
108
|
-
* Pause a toast's auto-dismiss timer
|
|
109
|
-
* @param {string} id
|
|
110
|
-
*/
|
|
111
56
|
pause(id) {
|
|
112
57
|
this.toasts = this.toasts.map(t =>
|
|
113
58
|
t.id === id ? { ...t, pausedAt: Date.now() } : t
|
|
114
59
|
);
|
|
115
60
|
}
|
|
116
61
|
|
|
117
|
-
/**
|
|
118
|
-
* Resume a toast's auto-dismiss timer
|
|
119
|
-
* @param {string} id
|
|
120
|
-
*/
|
|
121
62
|
resume(id) {
|
|
122
63
|
this.toasts = this.toasts.map(t => {
|
|
123
64
|
if (t.id !== id || !t.pausedAt) return t;
|
|
124
65
|
const pausedDuration = Date.now() - t.pausedAt;
|
|
125
|
-
return {
|
|
126
|
-
...t,
|
|
127
|
-
createdAt: t.createdAt + pausedDuration,
|
|
128
|
-
pausedAt: undefined
|
|
129
|
-
};
|
|
66
|
+
return { ...t, createdAt: t.createdAt + pausedDuration, pausedAt: undefined };
|
|
130
67
|
});
|
|
131
68
|
}
|
|
132
69
|
|
|
133
|
-
// Convenience methods
|
|
134
70
|
info = (message, options = {}) => this.show({ ...options, message, type: 'info' });
|
|
135
71
|
success = (message, options = {}) => this.show({ ...options, message, type: 'success' });
|
|
136
72
|
warning = (message, options = {}) => this.show({ ...options, message, type: 'warning' });
|
|
137
73
|
error = (message, options = {}) => this.show({ ...options, message, type: 'error' });
|
|
138
74
|
}
|
|
139
75
|
|
|
140
|
-
/**
|
|
141
|
-
* Create toast context (call in ToastProvider)
|
|
142
|
-
*/
|
|
143
76
|
export function createToastContext() {
|
|
144
77
|
const controller = new ToastController();
|
|
145
78
|
setContext(TOAST_KEY, controller);
|
|
146
79
|
return controller;
|
|
147
80
|
}
|
|
148
81
|
|
|
149
|
-
/**
|
|
150
|
-
* Get toast controller from context
|
|
151
|
-
* @returns {ToastController}
|
|
152
|
-
*/
|
|
153
82
|
export function getToastContext() {
|
|
154
83
|
return getContext(TOAST_KEY);
|
|
155
84
|
}
|
|
156
|
-
|
|
157
|
-
// Toast styles
|
|
158
|
-
export const toastStyles = cv({
|
|
159
|
-
base: [
|
|
160
|
-
'relative flex items-start gap-3 w-full max-w-sm',
|
|
161
|
-
'p-4 rounded-lg shadow-lg',
|
|
162
|
-
'border',
|
|
163
|
-
'animate-in fade-in slide-in-from-right-4 duration-200'
|
|
164
|
-
].join(' '),
|
|
165
|
-
|
|
166
|
-
variants: {
|
|
167
|
-
type: {
|
|
168
|
-
info: 'bg-surface border-border text-text',
|
|
169
|
-
success: 'bg-success/10 border-success/30 text-success',
|
|
170
|
-
warning: 'bg-warning/10 border-warning/30 text-warning',
|
|
171
|
-
error: 'bg-error/10 border-error/30 text-error'
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
defaults: { type: 'info' }
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
export const positionStyles = {
|
|
179
|
-
'top-left': 'top-4 left-4 flex-col',
|
|
180
|
-
'top-center': 'top-4 left-1/2 -translate-x-1/2 flex-col',
|
|
181
|
-
'top-right': 'top-4 right-4 flex-col',
|
|
182
|
-
'bottom-left': 'bottom-4 left-4 flex-col-reverse',
|
|
183
|
-
'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2 flex-col-reverse',
|
|
184
|
-
'bottom-right': 'bottom-4 right-4 flex-col-reverse'
|
|
185
|
-
};
|
|
186
85
|
</script>
|
|
187
86
|
|
|
188
87
|
<script>
|
|
189
88
|
import { cn } from '../../utils/cn.svelte.js';
|
|
190
89
|
import { portal } from '../../actions/index.js';
|
|
191
90
|
|
|
192
|
-
// Get toast controller from context
|
|
193
91
|
const toast = getToastContext();
|
|
194
92
|
|
|
195
|
-
// Icon components for each type
|
|
196
93
|
const icons = {
|
|
197
94
|
info: `<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>`,
|
|
198
95
|
success: `<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>`,
|
|
199
96
|
warning: `<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>`,
|
|
200
97
|
error: `<circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>`
|
|
201
98
|
};
|
|
99
|
+
|
|
100
|
+
const positionClass = $derived({
|
|
101
|
+
'top-left': 'toast-top-left',
|
|
102
|
+
'top-center': 'toast-top-center',
|
|
103
|
+
'top-right': 'toast-top-right',
|
|
104
|
+
'bottom-left': 'toast-bottom-left',
|
|
105
|
+
'bottom-center': 'toast-bottom-center',
|
|
106
|
+
'bottom-right': 'toast-bottom-right'
|
|
107
|
+
}[toast.position]);
|
|
202
108
|
</script>
|
|
203
109
|
|
|
204
110
|
{#if toast.toasts.length > 0}
|
|
205
|
-
<div
|
|
206
|
-
use:portal
|
|
207
|
-
class={cn(
|
|
208
|
-
'fixed z-[var(--z-toast)] flex gap-2 pointer-events-none',
|
|
209
|
-
positionStyles[toast.position]
|
|
210
|
-
)}
|
|
211
|
-
role="region"
|
|
212
|
-
aria-label="Notifications"
|
|
213
|
-
>
|
|
111
|
+
<div use:portal class={cn('toast-container', positionClass)} role="region" aria-label="Notifications">
|
|
214
112
|
{#each toast.toasts as item (item.id)}
|
|
215
113
|
{@const remaining = item.duration - (Date.now() - item.createdAt)}
|
|
216
|
-
|
|
217
114
|
<div
|
|
218
|
-
class={cn(
|
|
115
|
+
class={cn('toast-item', `toast-${item.type}`)}
|
|
219
116
|
role="alert"
|
|
220
117
|
aria-live="polite"
|
|
221
118
|
onmouseenter={() => toast.pause(item.id)}
|
|
222
119
|
onmouseleave={() => toast.resume(item.id)}
|
|
223
120
|
>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
<svg
|
|
227
|
-
viewBox="0 0 24 24"
|
|
228
|
-
fill="none"
|
|
229
|
-
stroke="currentColor"
|
|
230
|
-
stroke-width="2"
|
|
231
|
-
stroke-linecap="round"
|
|
232
|
-
stroke-linejoin="round"
|
|
233
|
-
>
|
|
121
|
+
<span class="toast-icon">
|
|
122
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
234
123
|
{@html icons[item.type]}
|
|
235
124
|
</svg>
|
|
236
125
|
</span>
|
|
237
|
-
|
|
238
|
-
<!-- Content -->
|
|
239
|
-
<div class="flex-1 min-w-0">
|
|
126
|
+
<div class="toast-content">
|
|
240
127
|
{#if item.title}
|
|
241
|
-
<p class="
|
|
128
|
+
<p class="toast-title">{item.title}</p>
|
|
242
129
|
{/if}
|
|
243
|
-
<p class={cn('
|
|
244
|
-
{item.message}
|
|
245
|
-
</p>
|
|
130
|
+
<p class={cn('toast-message', item.title && 'has-title')}>{item.message}</p>
|
|
246
131
|
</div>
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
type="button"
|
|
251
|
-
class={cn(
|
|
252
|
-
'shrink-0 p-1 rounded-md',
|
|
253
|
-
'opacity-60 hover:opacity-100',
|
|
254
|
-
'transition-opacity duration-150',
|
|
255
|
-
'focus:outline-none focus-visible:ring-2 focus-visible:ring-current/50'
|
|
256
|
-
)}
|
|
257
|
-
onclick={() => toast.dismiss(item.id)}
|
|
258
|
-
aria-label="Dismiss notification"
|
|
259
|
-
>
|
|
260
|
-
<svg
|
|
261
|
-
class="w-4 h-4"
|
|
262
|
-
viewBox="0 0 24 24"
|
|
263
|
-
fill="none"
|
|
264
|
-
stroke="currentColor"
|
|
265
|
-
stroke-width="2"
|
|
266
|
-
stroke-linecap="round"
|
|
267
|
-
stroke-linejoin="round"
|
|
268
|
-
>
|
|
269
|
-
<path d="M18 6 6 18" />
|
|
270
|
-
<path d="m6 6 12 12" />
|
|
132
|
+
<button type="button" class="toast-close" onclick={() => toast.dismiss(item.id)} aria-label="Dismiss">
|
|
133
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
134
|
+
<path d="M18 6 6 18" /><path d="m6 6 12 12" />
|
|
271
135
|
</svg>
|
|
272
136
|
</button>
|
|
273
|
-
|
|
274
|
-
<!-- Auto-dismiss timer -->
|
|
275
137
|
{#if item.duration > 0 && !item.pausedAt}
|
|
276
138
|
{@const _ = setTimeout(() => toast.dismiss(item.id), remaining)}
|
|
277
139
|
{/if}
|
|
@@ -281,17 +143,119 @@
|
|
|
281
143
|
{/if}
|
|
282
144
|
|
|
283
145
|
<style>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
146
|
+
.toast-container {
|
|
147
|
+
position: fixed;
|
|
148
|
+
z-index: 9999;
|
|
149
|
+
display: flex;
|
|
150
|
+
gap: 0.5rem;
|
|
151
|
+
pointer-events: none;
|
|
287
152
|
}
|
|
288
153
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
154
|
+
.toast-top-left { top: 1rem; left: 1rem; flex-direction: column; }
|
|
155
|
+
.toast-top-center { top: 1rem; left: 50%; transform: translateX(-50%); flex-direction: column; }
|
|
156
|
+
.toast-top-right { top: 1rem; right: 1rem; flex-direction: column; }
|
|
157
|
+
.toast-bottom-left { bottom: 1rem; left: 1rem; flex-direction: column-reverse; }
|
|
158
|
+
.toast-bottom-center { bottom: 1rem; left: 50%; transform: translateX(-50%); flex-direction: column-reverse; }
|
|
159
|
+
.toast-bottom-right { bottom: 1rem; right: 1rem; flex-direction: column-reverse; }
|
|
160
|
+
|
|
161
|
+
.toast-item {
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: flex-start;
|
|
164
|
+
gap: 0.75rem;
|
|
165
|
+
width: 100%;
|
|
166
|
+
max-width: 24rem;
|
|
167
|
+
padding: 1rem;
|
|
168
|
+
border-radius: 0.5rem;
|
|
169
|
+
border: 1px solid;
|
|
170
|
+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.3);
|
|
171
|
+
pointer-events: auto;
|
|
172
|
+
animation: toast-in 200ms ease-out;
|
|
292
173
|
}
|
|
293
174
|
|
|
294
|
-
.
|
|
295
|
-
|
|
175
|
+
.toast-info {
|
|
176
|
+
background-color: var(--color-base01);
|
|
177
|
+
border-color: var(--color-base03);
|
|
178
|
+
color: var(--color-base05);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.toast-success {
|
|
182
|
+
background-color: color-mix(in srgb, var(--color-base0B) 10%, var(--color-base00));
|
|
183
|
+
border-color: color-mix(in srgb, var(--color-base0B) 30%, transparent);
|
|
184
|
+
color: var(--color-base0B);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.toast-warning {
|
|
188
|
+
background-color: color-mix(in srgb, var(--color-base0A) 10%, var(--color-base00));
|
|
189
|
+
border-color: color-mix(in srgb, var(--color-base0A) 30%, transparent);
|
|
190
|
+
color: var(--color-base0A);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.toast-error {
|
|
194
|
+
background-color: color-mix(in srgb, var(--color-base08) 10%, var(--color-base00));
|
|
195
|
+
border-color: color-mix(in srgb, var(--color-base08) 30%, transparent);
|
|
196
|
+
color: var(--color-base08);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.toast-icon {
|
|
200
|
+
flex-shrink: 0;
|
|
201
|
+
width: 1.25rem;
|
|
202
|
+
height: 1.25rem;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.toast-icon svg {
|
|
206
|
+
width: 100%;
|
|
207
|
+
height: 100%;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.toast-content {
|
|
211
|
+
flex: 1;
|
|
212
|
+
min-width: 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.toast-title {
|
|
216
|
+
font-weight: 500;
|
|
217
|
+
font-size: 0.875rem;
|
|
218
|
+
margin: 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.toast-message {
|
|
222
|
+
font-size: 0.875rem;
|
|
223
|
+
margin: 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.toast-message.has-title {
|
|
227
|
+
margin-top: 0.25rem;
|
|
228
|
+
opacity: 0.9;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.toast-close {
|
|
232
|
+
flex-shrink: 0;
|
|
233
|
+
padding: 0.25rem;
|
|
234
|
+
border-radius: 0.375rem;
|
|
235
|
+
background: transparent;
|
|
236
|
+
border: none;
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
opacity: 0.6;
|
|
239
|
+
transition: opacity 150ms;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.toast-close:hover {
|
|
243
|
+
opacity: 1;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.toast-close svg {
|
|
247
|
+
width: 1rem;
|
|
248
|
+
height: 1rem;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@keyframes toast-in {
|
|
252
|
+
from {
|
|
253
|
+
opacity: 0;
|
|
254
|
+
transform: translateX(1rem);
|
|
255
|
+
}
|
|
256
|
+
to {
|
|
257
|
+
opacity: 1;
|
|
258
|
+
transform: translateX(0);
|
|
259
|
+
}
|
|
296
260
|
}
|
|
297
261
|
</style>
|
|
@@ -105,33 +105,33 @@
|
|
|
105
105
|
justify-content: center;
|
|
106
106
|
width: 18px;
|
|
107
107
|
height: 18px;
|
|
108
|
-
border: 2px solid var(--color-
|
|
108
|
+
border: 2px solid var(--color-base03);
|
|
109
109
|
border-radius: var(--radius-default);
|
|
110
|
-
background-color: var(--color-
|
|
110
|
+
background-color: var(--color-base00);
|
|
111
111
|
transition: var(--transition-all);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
.checkbox-input:checked + .checkbox-box {
|
|
115
|
-
background-color: var(--color-
|
|
116
|
-
border-color: var(--color-
|
|
115
|
+
background-color: var(--color-base0D);
|
|
116
|
+
border-color: var(--color-base0D);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
.checkbox-error {
|
|
120
|
-
border-color: var(--color-
|
|
120
|
+
border-color: var(--color-base08);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
.checkbox-input:checked + .checkbox-error {
|
|
124
|
-
background-color: var(--color-
|
|
125
|
-
border-color: var(--color-
|
|
124
|
+
background-color: var(--color-base08);
|
|
125
|
+
border-color: var(--color-base08);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
.checkbox-input:focus-visible + .checkbox-box {
|
|
129
|
-
outline: 2px solid var(--color-
|
|
129
|
+
outline: 2px solid var(--color-base0D);
|
|
130
130
|
outline-offset: 2px;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
.checkbox-input:focus-visible + .checkbox-error {
|
|
134
|
-
outline-color: var(--color-
|
|
134
|
+
outline-color: var(--color-base08);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
.checkbox-icon {
|
|
@@ -142,6 +142,6 @@
|
|
|
142
142
|
|
|
143
143
|
.checkbox-label {
|
|
144
144
|
font-size: var(--text-sm);
|
|
145
|
-
color: var(--color-
|
|
145
|
+
color: var(--color-base05);
|
|
146
146
|
}
|
|
147
147
|
</style>
|
|
@@ -151,21 +151,21 @@
|
|
|
151
151
|
justify-content: center;
|
|
152
152
|
min-height: 8rem;
|
|
153
153
|
padding: var(--space-4);
|
|
154
|
-
border: 2px dashed var(--color-
|
|
154
|
+
border: 2px dashed var(--color-base02);
|
|
155
155
|
border-radius: var(--radius-lg);
|
|
156
|
-
background: var(--color-
|
|
156
|
+
background: var(--color-base01);
|
|
157
157
|
cursor: pointer;
|
|
158
158
|
transition: border-color 0.2s ease, background 0.2s ease;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
.dropzone:hover:not(.dropzone-disabled) {
|
|
162
|
-
border-color: var(--color-
|
|
163
|
-
background: color-mix(in srgb, var(--color-
|
|
162
|
+
border-color: var(--color-base0D);
|
|
163
|
+
background: color-mix(in srgb, var(--color-base0D) 5%, transparent);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
.dropzone-dragging {
|
|
167
|
-
border-color: var(--color-
|
|
168
|
-
background: color-mix(in srgb, var(--color-
|
|
167
|
+
border-color: var(--color-base0D);
|
|
168
|
+
background: color-mix(in srgb, var(--color-base0D) 10%, transparent);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
.dropzone-disabled {
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
.dropzone-message {
|
|
177
177
|
margin: 0;
|
|
178
178
|
font-size: var(--text-sm);
|
|
179
|
-
color: var(--color-
|
|
179
|
+
color: var(--color-base04);
|
|
180
180
|
text-align: center;
|
|
181
181
|
pointer-events: none;
|
|
182
182
|
}
|
|
@@ -200,8 +200,8 @@
|
|
|
200
200
|
gap: var(--space-3);
|
|
201
201
|
width: 100%;
|
|
202
202
|
padding: var(--space-3);
|
|
203
|
-
background: var(--color-
|
|
204
|
-
border: 1px solid var(--color-
|
|
203
|
+
background: var(--color-base00);
|
|
204
|
+
border: 1px solid var(--color-base02);
|
|
205
205
|
border-radius: var(--radius-md);
|
|
206
206
|
}
|
|
207
207
|
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
margin: 0;
|
|
215
215
|
font-size: var(--text-sm);
|
|
216
216
|
font-weight: 500;
|
|
217
|
-
color: var(--color-
|
|
217
|
+
color: var(--color-base07);
|
|
218
218
|
white-space: nowrap;
|
|
219
219
|
overflow: hidden;
|
|
220
220
|
text-overflow: ellipsis;
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
.dropzone-file-meta {
|
|
224
224
|
margin: var(--space-1) 0 0 0;
|
|
225
225
|
font-size: var(--text-xs);
|
|
226
|
-
color: var(--color-
|
|
226
|
+
color: var(--color-base04);
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
.dropzone-clear {
|
|
@@ -235,14 +235,14 @@
|
|
|
235
235
|
background: transparent;
|
|
236
236
|
border: none;
|
|
237
237
|
border-radius: var(--radius-sm);
|
|
238
|
-
color: var(--color-
|
|
238
|
+
color: var(--color-base04);
|
|
239
239
|
cursor: pointer;
|
|
240
240
|
transition: background 0.15s ease, color 0.15s ease;
|
|
241
241
|
z-index: 1;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
.dropzone-clear:hover {
|
|
245
|
-
background: var(--color-
|
|
246
|
-
color: var(--color-
|
|
245
|
+
background: var(--color-base02);
|
|
246
|
+
color: var(--color-base05);
|
|
247
247
|
}
|
|
248
248
|
</style>
|
|
@@ -171,21 +171,21 @@
|
|
|
171
171
|
gap: var(--space-2);
|
|
172
172
|
width: 100%;
|
|
173
173
|
padding: var(--space-6) var(--space-4);
|
|
174
|
-
background: var(--color-
|
|
175
|
-
border: 2px dashed var(--color-
|
|
174
|
+
background: var(--color-base00);
|
|
175
|
+
border: 2px dashed var(--color-base03);
|
|
176
176
|
border-radius: var(--radius-lg);
|
|
177
177
|
cursor: pointer;
|
|
178
178
|
transition: var(--transition-colors);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
.upload-zone:hover:not(:disabled) {
|
|
182
|
-
border-color: var(--color-
|
|
183
|
-
background: color-mix(in srgb, var(--color-
|
|
182
|
+
border-color: var(--color-base0D);
|
|
183
|
+
background: color-mix(in srgb, var(--color-base0D) 5%, transparent);
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
.upload-zone-dragging {
|
|
187
|
-
border-color: var(--color-
|
|
188
|
-
background: color-mix(in srgb, var(--color-
|
|
187
|
+
border-color: var(--color-base0D);
|
|
188
|
+
background: color-mix(in srgb, var(--color-base0D) 10%, transparent);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
.upload-zone-disabled {
|
|
@@ -194,18 +194,18 @@
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
.upload-icon {
|
|
197
|
-
color: var(--color-
|
|
197
|
+
color: var(--color-base04);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
.upload-label {
|
|
201
201
|
font-size: var(--text-sm);
|
|
202
202
|
font-weight: 500;
|
|
203
|
-
color: var(--color-
|
|
203
|
+
color: var(--color-base05);
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
.upload-hint {
|
|
207
207
|
font-size: var(--text-xs);
|
|
208
|
-
color: var(--color-
|
|
208
|
+
color: var(--color-base04);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
.upload-input {
|
|
@@ -226,15 +226,15 @@
|
|
|
226
226
|
align-items: center;
|
|
227
227
|
gap: var(--space-2);
|
|
228
228
|
padding: var(--space-2) var(--space-3);
|
|
229
|
-
background: var(--color-
|
|
230
|
-
border: 1px solid var(--color-
|
|
229
|
+
background: var(--color-base01);
|
|
230
|
+
border: 1px solid var(--color-base02);
|
|
231
231
|
border-radius: var(--radius-md);
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
.file-name {
|
|
235
235
|
flex: 1;
|
|
236
236
|
font-size: var(--text-sm);
|
|
237
|
-
color: var(--color-
|
|
237
|
+
color: var(--color-base05);
|
|
238
238
|
overflow: hidden;
|
|
239
239
|
text-overflow: ellipsis;
|
|
240
240
|
white-space: nowrap;
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
|
|
243
243
|
.file-size {
|
|
244
244
|
font-size: var(--text-xs);
|
|
245
|
-
color: var(--color-
|
|
245
|
+
color: var(--color-base04);
|
|
246
246
|
white-space: nowrap;
|
|
247
247
|
}
|
|
248
248
|
|
|
@@ -254,13 +254,13 @@
|
|
|
254
254
|
background: transparent;
|
|
255
255
|
border: none;
|
|
256
256
|
border-radius: var(--radius-sm);
|
|
257
|
-
color: var(--color-
|
|
257
|
+
color: var(--color-base04);
|
|
258
258
|
cursor: pointer;
|
|
259
259
|
transition: var(--transition-colors);
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
.file-remove:hover {
|
|
263
|
-
color: var(--color-
|
|
264
|
-
background: color-mix(in srgb, var(--color-
|
|
263
|
+
color: var(--color-base08);
|
|
264
|
+
background: color-mix(in srgb, var(--color-base08) 10%, transparent);
|
|
265
265
|
}
|
|
266
266
|
</style>
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
display: flex;
|
|
125
125
|
align-items: center;
|
|
126
126
|
justify-content: center;
|
|
127
|
-
color: var(--color-
|
|
127
|
+
color: var(--color-base04);
|
|
128
128
|
pointer-events: none;
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -172,13 +172,13 @@
|
|
|
172
172
|
background: transparent;
|
|
173
173
|
border: none;
|
|
174
174
|
border-radius: var(--radius-sm);
|
|
175
|
-
color: var(--color-
|
|
175
|
+
color: var(--color-base04);
|
|
176
176
|
cursor: pointer;
|
|
177
177
|
transition: var(--transition-colors);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
.icon-clear:hover {
|
|
181
|
-
color: var(--color-
|
|
182
|
-
background: var(--color-
|
|
181
|
+
color: var(--color-base05);
|
|
182
|
+
background: var(--color-base02);
|
|
183
183
|
}
|
|
184
184
|
</style>
|