@ibanzajoe/uploader 0.1.0 → 0.3.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 +83 -0
- package/dist/index.cjs +752 -289
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +193 -9
- package/dist/index.d.ts +193 -9
- package/dist/index.js +750 -291
- package/dist/index.js.map +1 -1
- package/dist/styles.css +561 -129
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -11,31 +11,65 @@
|
|
|
11
11
|
|
|
12
12
|
/* ─── Design tokens ─────────────────────────────────────────────────────────── */
|
|
13
13
|
|
|
14
|
+
/*
|
|
15
|
+
* Three theming knobs are all that host apps need to override:
|
|
16
|
+
* --uploader-accent Primary brand color (default: Tideline teal #0CA187)
|
|
17
|
+
* --uploader-accent-soft Tinted background for icon swatches and hover fills
|
|
18
|
+
* --uploader-accent-ring Focus ring / drag-over glow (20-30% opacity of accent)
|
|
19
|
+
*
|
|
20
|
+
* Example — adapting to a purple host brand:
|
|
21
|
+
* .my-app { --uploader-accent:#7C3AED; --uploader-accent-soft:#F1ECFD; --uploader-accent-ring:rgba(124,58,237,.28); }
|
|
22
|
+
*/
|
|
14
23
|
:root {
|
|
15
|
-
|
|
16
|
-
--uploader-accent
|
|
17
|
-
--uploader-
|
|
24
|
+
/* ── Accent (the only brand color the host app needs to set) ── */
|
|
25
|
+
--uploader-accent: #0CA187;
|
|
26
|
+
--uploader-accent-hover: #0A8270;
|
|
27
|
+
--uploader-accent-soft: #ECFBF7;
|
|
28
|
+
--uploader-accent-ring: rgba(12, 161, 135, 0.28);
|
|
29
|
+
|
|
30
|
+
/* ── Surface / structure ── */
|
|
31
|
+
--uploader-radius: 10px;
|
|
18
32
|
--uploader-bg: #ffffff;
|
|
19
|
-
--uploader-surface: #
|
|
20
|
-
--uploader-
|
|
21
|
-
--uploader-
|
|
22
|
-
--uploader-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
--uploader-
|
|
33
|
+
--uploader-surface: #FAF9F7;
|
|
34
|
+
--uploader-surface-hover: #F4F2EE;
|
|
35
|
+
--uploader-border: #D5CFC5;
|
|
36
|
+
--uploader-border-subtle: #F0EDE8;
|
|
37
|
+
|
|
38
|
+
/* ── Typography ── */
|
|
39
|
+
--uploader-text: #211E1A;
|
|
40
|
+
--uploader-text-muted: #8E8678;
|
|
41
|
+
--uploader-text-xmuted: #A39A8C;
|
|
42
|
+
|
|
43
|
+
/* ── Semantic ── */
|
|
44
|
+
--uploader-error: #D8442F;
|
|
45
|
+
--uploader-error-soft: #FCF0EE;
|
|
46
|
+
--uploader-success: #0CA187;
|
|
47
|
+
|
|
48
|
+
/* ── Elevation ── */
|
|
49
|
+
--uploader-shadow-sm: 0 1px 4px rgba(31, 28, 25, 0.08);
|
|
50
|
+
--uploader-shadow: 0 8px 30px rgba(31, 28, 25, 0.12);
|
|
51
|
+
--uploader-shadow-lg: 0 24px 60px -16px rgba(31, 28, 25, 0.4);
|
|
52
|
+
|
|
53
|
+
/* ── Z-index ── */
|
|
26
54
|
--uploader-z-backdrop: 1000;
|
|
27
55
|
--uploader-z-panel: 1001;
|
|
56
|
+
|
|
57
|
+
/* ── Misc ── */
|
|
28
58
|
--uploader-font: inherit;
|
|
29
59
|
--uploader-transition: 0.15s ease;
|
|
30
60
|
}
|
|
31
61
|
|
|
32
62
|
[data-theme="dark"] {
|
|
33
|
-
--uploader-bg: #
|
|
34
|
-
--uploader-surface: #
|
|
35
|
-
--uploader-
|
|
36
|
-
--uploader-
|
|
37
|
-
--uploader-
|
|
38
|
-
--uploader-
|
|
63
|
+
--uploader-bg: #1C1A17;
|
|
64
|
+
--uploader-surface: #252219;
|
|
65
|
+
--uploader-surface-hover: #2E2A22;
|
|
66
|
+
--uploader-border: #3D3830;
|
|
67
|
+
--uploader-border-subtle: #2A2620;
|
|
68
|
+
--uploader-text: #F0EDE8;
|
|
69
|
+
--uploader-text-muted: #9A9185;
|
|
70
|
+
--uploader-text-xmuted: #6B6358;
|
|
71
|
+
--uploader-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
|
|
72
|
+
--uploader-shadow-lg: 0 24px 60px -16px rgba(0, 0, 0, 0.55);
|
|
39
73
|
}
|
|
40
74
|
|
|
41
75
|
/* ─── Backdrop ──────────────────────────────────────────────────────────────── */
|
|
@@ -55,10 +89,10 @@
|
|
|
55
89
|
|
|
56
90
|
.uploader-picker-panel {
|
|
57
91
|
background: var(--uploader-bg);
|
|
58
|
-
border-radius:
|
|
59
|
-
box-shadow: var(--uploader-shadow);
|
|
60
|
-
width: min(
|
|
61
|
-
max-height: calc(100dvh -
|
|
92
|
+
border-radius: 16px;
|
|
93
|
+
box-shadow: var(--uploader-shadow-lg);
|
|
94
|
+
width: min(480px, calc(100vw - 32px));
|
|
95
|
+
max-height: calc(100dvh - 48px);
|
|
62
96
|
display: flex;
|
|
63
97
|
flex-direction: column;
|
|
64
98
|
overflow: hidden;
|
|
@@ -70,8 +104,8 @@
|
|
|
70
104
|
display: flex;
|
|
71
105
|
align-items: center;
|
|
72
106
|
justify-content: space-between;
|
|
73
|
-
padding:
|
|
74
|
-
border-bottom: 1px solid var(--uploader-border);
|
|
107
|
+
padding: 18px 20px;
|
|
108
|
+
border-bottom: 1px solid var(--uploader-border-subtle);
|
|
75
109
|
flex-shrink: 0;
|
|
76
110
|
}
|
|
77
111
|
|
|
@@ -83,44 +117,63 @@
|
|
|
83
117
|
}
|
|
84
118
|
|
|
85
119
|
.uploader-btn-close {
|
|
86
|
-
|
|
120
|
+
width: 26px;
|
|
121
|
+
height: 26px;
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
background: var(--uploader-surface);
|
|
87
126
|
border: none;
|
|
127
|
+
border-radius: 8px;
|
|
88
128
|
cursor: pointer;
|
|
89
|
-
font-size:
|
|
129
|
+
font-size: 13px;
|
|
90
130
|
line-height: 1;
|
|
91
131
|
color: var(--uploader-text-muted);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
transition: color var(--uploader-transition), background var(--uploader-transition);
|
|
132
|
+
transition: background var(--uploader-transition), color var(--uploader-transition);
|
|
133
|
+
flex-shrink: 0;
|
|
95
134
|
}
|
|
96
135
|
|
|
97
136
|
.uploader-btn-close:hover {
|
|
98
137
|
color: var(--uploader-text);
|
|
99
|
-
background: var(--uploader-surface);
|
|
138
|
+
background: var(--uploader-surface-hover);
|
|
100
139
|
}
|
|
101
140
|
|
|
102
141
|
.uploader-picker-footer {
|
|
103
142
|
display: flex;
|
|
104
|
-
|
|
143
|
+
align-items: center;
|
|
144
|
+
justify-content: space-between;
|
|
105
145
|
gap: 8px;
|
|
106
|
-
padding:
|
|
107
|
-
border-top: 1px solid var(--uploader-border);
|
|
146
|
+
padding: 14px 20px;
|
|
147
|
+
border-top: 1px solid var(--uploader-border-subtle);
|
|
148
|
+
background: var(--uploader-surface);
|
|
108
149
|
flex-shrink: 0;
|
|
109
150
|
}
|
|
110
151
|
|
|
152
|
+
.uploader-picker-footer-esc {
|
|
153
|
+
font-family: var(--uploader-font-mono, 'JetBrains Mono', monospace);
|
|
154
|
+
font-size: 11px;
|
|
155
|
+
color: var(--uploader-text-xmuted);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.uploader-picker-footer-actions {
|
|
159
|
+
display: flex;
|
|
160
|
+
gap: 9px;
|
|
161
|
+
}
|
|
162
|
+
|
|
111
163
|
/* ─── Drop zone (shared by PickerOverlay and DropPane) ──────────────────────── */
|
|
112
164
|
|
|
113
165
|
.uploader-dropzone {
|
|
114
|
-
margin:
|
|
115
|
-
border:
|
|
116
|
-
border-radius:
|
|
117
|
-
background:
|
|
118
|
-
padding:
|
|
166
|
+
margin: 20px;
|
|
167
|
+
border: 1.5px dashed var(--uploader-border);
|
|
168
|
+
border-radius: 13px;
|
|
169
|
+
background: transparent;
|
|
170
|
+
padding: 38px 20px;
|
|
119
171
|
display: flex;
|
|
120
172
|
flex-direction: column;
|
|
121
173
|
align-items: center;
|
|
122
174
|
gap: 10px;
|
|
123
175
|
cursor: pointer;
|
|
176
|
+
text-align: center;
|
|
124
177
|
transition:
|
|
125
178
|
border-color var(--uploader-transition),
|
|
126
179
|
background var(--uploader-transition);
|
|
@@ -128,67 +181,178 @@
|
|
|
128
181
|
}
|
|
129
182
|
|
|
130
183
|
.uploader-dropzone:hover,
|
|
131
|
-
.uploader-dropzone:focus-visible
|
|
132
|
-
.uploader-drag-over .uploader-dropzone {
|
|
184
|
+
.uploader-dropzone:focus-visible {
|
|
133
185
|
border-color: var(--uploader-accent);
|
|
134
|
-
background:
|
|
186
|
+
background: var(--uploader-accent-soft);
|
|
135
187
|
outline: none;
|
|
136
188
|
}
|
|
137
189
|
|
|
138
190
|
.uploader-dropzone:focus-visible {
|
|
139
|
-
|
|
140
|
-
|
|
191
|
+
box-shadow: 0 0 0 3px var(--uploader-accent-ring);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Applied to the PickerOverlay panel when a drag is in progress */
|
|
195
|
+
.uploader-picker-panel[data-drag-over="true"] .uploader-dropzone,
|
|
196
|
+
.uploader-drop-pane[data-drag-over="true"] .uploader-dropzone {
|
|
197
|
+
border-color: var(--uploader-accent);
|
|
198
|
+
background: var(--uploader-accent-soft);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* Upload icon swatch */
|
|
202
|
+
.uploader-dropzone-icon-wrap {
|
|
203
|
+
width: 50px;
|
|
204
|
+
height: 50px;
|
|
205
|
+
border-radius: 14px;
|
|
206
|
+
background: var(--uploader-accent-soft);
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
justify-content: center;
|
|
210
|
+
margin-bottom: 6px;
|
|
211
|
+
flex-shrink: 0;
|
|
141
212
|
}
|
|
142
213
|
|
|
143
214
|
.uploader-dropzone-icon {
|
|
144
|
-
|
|
145
|
-
|
|
215
|
+
/* SVG upload arrow rendered via CSS borders — no external icon dep */
|
|
216
|
+
position: relative;
|
|
217
|
+
width: 16px;
|
|
218
|
+
height: 14px;
|
|
219
|
+
border: 2.4px solid var(--uploader-accent);
|
|
220
|
+
border-radius: 0 0 5px 5px;
|
|
221
|
+
border-top: none;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.uploader-dropzone-icon::before {
|
|
225
|
+
content: '';
|
|
226
|
+
position: absolute;
|
|
227
|
+
left: 50%;
|
|
228
|
+
top: -10px;
|
|
229
|
+
transform: translateX(-50%);
|
|
230
|
+
width: 0;
|
|
231
|
+
height: 0;
|
|
232
|
+
border-left: 5px solid transparent;
|
|
233
|
+
border-right: 5px solid transparent;
|
|
234
|
+
border-bottom: 8px solid var(--uploader-accent);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.uploader-dropzone-icon::after {
|
|
238
|
+
content: '';
|
|
239
|
+
position: absolute;
|
|
240
|
+
left: 50%;
|
|
241
|
+
top: -2px;
|
|
242
|
+
transform: translateX(-50%);
|
|
243
|
+
width: 2.4px;
|
|
244
|
+
height: 9px;
|
|
245
|
+
background: var(--uploader-accent);
|
|
146
246
|
}
|
|
147
247
|
|
|
148
248
|
.uploader-dropzone-label {
|
|
149
249
|
margin: 0;
|
|
250
|
+
font-size: 15px;
|
|
251
|
+
font-weight: 600;
|
|
252
|
+
color: var(--uploader-text);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.uploader-dropzone-sublabel {
|
|
256
|
+
margin: 0;
|
|
257
|
+
font-size: 13px;
|
|
150
258
|
color: var(--uploader-text-muted);
|
|
151
|
-
|
|
152
|
-
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.uploader-dropzone-hint {
|
|
262
|
+
margin-top: 4px;
|
|
263
|
+
font-size: 11.5px;
|
|
264
|
+
color: var(--uploader-text-xmuted);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Source button row (Browse files + optional Take photo) */
|
|
268
|
+
.uploader-dropzone-actions {
|
|
269
|
+
display: flex;
|
|
270
|
+
align-items: center;
|
|
271
|
+
justify-content: center;
|
|
272
|
+
flex-wrap: wrap;
|
|
273
|
+
gap: 8px;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* "Take photo" — secondary-styled source button with a camera glyph */
|
|
277
|
+
.uploader-btn-camera {
|
|
278
|
+
display: inline-flex;
|
|
279
|
+
align-items: center;
|
|
280
|
+
gap: 7px;
|
|
281
|
+
padding: 9px 16px;
|
|
282
|
+
border: 1px solid var(--uploader-border);
|
|
283
|
+
border-radius: 10px;
|
|
284
|
+
background: var(--uploader-bg);
|
|
285
|
+
color: var(--uploader-text);
|
|
286
|
+
font-family: var(--uploader-font);
|
|
287
|
+
font-weight: 600;
|
|
288
|
+
font-size: 14px;
|
|
289
|
+
cursor: pointer;
|
|
290
|
+
transition: border-color var(--uploader-transition), background var(--uploader-transition),
|
|
291
|
+
color var(--uploader-transition);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.uploader-btn-camera:hover {
|
|
295
|
+
border-color: var(--uploader-accent);
|
|
296
|
+
background: var(--uploader-accent-soft);
|
|
297
|
+
color: var(--uploader-accent);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.uploader-btn-camera:focus-visible {
|
|
301
|
+
outline: none;
|
|
302
|
+
border-color: var(--uploader-accent);
|
|
303
|
+
box-shadow: 0 0 0 3px var(--uploader-accent-ring);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.uploader-btn-camera-icon {
|
|
307
|
+
flex-shrink: 0;
|
|
153
308
|
}
|
|
154
309
|
|
|
155
310
|
/* ─── File list ─────────────────────────────────────────────────────────────── */
|
|
156
311
|
|
|
157
312
|
.uploader-file-list {
|
|
158
313
|
list-style: none;
|
|
159
|
-
margin: 0
|
|
160
|
-
padding: 0;
|
|
314
|
+
margin: 0;
|
|
315
|
+
padding: 0 20px;
|
|
161
316
|
overflow-y: auto;
|
|
162
|
-
max-height:
|
|
317
|
+
max-height: 220px;
|
|
163
318
|
display: flex;
|
|
164
319
|
flex-direction: column;
|
|
165
|
-
gap:
|
|
320
|
+
gap: 12px;
|
|
166
321
|
}
|
|
167
322
|
|
|
168
323
|
.uploader-file-item {
|
|
169
324
|
display: flex;
|
|
170
325
|
align-items: center;
|
|
171
|
-
gap:
|
|
172
|
-
padding:
|
|
173
|
-
border-radius:
|
|
174
|
-
background:
|
|
175
|
-
border:
|
|
326
|
+
gap: 12px;
|
|
327
|
+
padding: 0;
|
|
328
|
+
border-radius: 0;
|
|
329
|
+
background: transparent;
|
|
330
|
+
border: none;
|
|
176
331
|
}
|
|
177
332
|
|
|
178
|
-
.uploader-file-item.uploader-file-error {
|
|
179
|
-
|
|
180
|
-
background: color-mix(in srgb, var(--uploader-error) 6%, var(--uploader-surface));
|
|
333
|
+
.uploader-file-item.uploader-file-error .uploader-file-name {
|
|
334
|
+
color: var(--uploader-error);
|
|
181
335
|
}
|
|
182
336
|
|
|
183
|
-
.uploader-file-item.uploader-file-done {
|
|
184
|
-
|
|
337
|
+
.uploader-file-item.uploader-file-done .uploader-file-status {
|
|
338
|
+
color: var(--uploader-accent);
|
|
185
339
|
}
|
|
186
340
|
|
|
187
341
|
.uploader-file-thumb {
|
|
188
|
-
width:
|
|
189
|
-
height:
|
|
342
|
+
width: 38px;
|
|
343
|
+
height: 38px;
|
|
190
344
|
object-fit: cover;
|
|
191
|
-
border-radius:
|
|
345
|
+
border-radius: 9px;
|
|
346
|
+
flex-shrink: 0;
|
|
347
|
+
background: var(--uploader-surface);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* Placeholder swatch when no preview is available */
|
|
351
|
+
.uploader-file-thumb-placeholder {
|
|
352
|
+
width: 38px;
|
|
353
|
+
height: 38px;
|
|
354
|
+
border-radius: 9px;
|
|
355
|
+
background: var(--uploader-surface);
|
|
192
356
|
flex-shrink: 0;
|
|
193
357
|
}
|
|
194
358
|
|
|
@@ -197,50 +361,68 @@
|
|
|
197
361
|
min-width: 0;
|
|
198
362
|
display: flex;
|
|
199
363
|
flex-direction: column;
|
|
200
|
-
gap:
|
|
364
|
+
gap: 5px;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.uploader-file-info-row {
|
|
368
|
+
display: flex;
|
|
369
|
+
align-items: center;
|
|
370
|
+
justify-content: space-between;
|
|
201
371
|
}
|
|
202
372
|
|
|
203
373
|
.uploader-file-name {
|
|
204
|
-
font-size:
|
|
374
|
+
font-size: 13px;
|
|
375
|
+
font-weight: 500;
|
|
205
376
|
color: var(--uploader-text);
|
|
206
377
|
white-space: nowrap;
|
|
207
378
|
overflow: hidden;
|
|
208
379
|
text-overflow: ellipsis;
|
|
209
380
|
}
|
|
210
381
|
|
|
211
|
-
.uploader-file-
|
|
212
|
-
font-size:
|
|
213
|
-
|
|
382
|
+
.uploader-file-status {
|
|
383
|
+
font-size: 11.5px;
|
|
384
|
+
font-weight: 600;
|
|
385
|
+
color: var(--uploader-text-muted);
|
|
386
|
+
flex-shrink: 0;
|
|
214
387
|
}
|
|
215
388
|
|
|
216
|
-
.uploader-file-done {
|
|
217
|
-
|
|
218
|
-
color: var(--uploader-success);
|
|
389
|
+
.uploader-file-status[data-state="done"] {
|
|
390
|
+
color: var(--uploader-accent);
|
|
219
391
|
}
|
|
220
392
|
|
|
221
|
-
.uploader-file-
|
|
222
|
-
|
|
223
|
-
height: 6px;
|
|
224
|
-
appearance: none;
|
|
225
|
-
border-radius: 3px;
|
|
226
|
-
overflow: hidden;
|
|
227
|
-
flex-shrink: 0;
|
|
393
|
+
.uploader-file-status[data-state="error"] {
|
|
394
|
+
color: var(--uploader-error);
|
|
228
395
|
}
|
|
229
396
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
397
|
+
/* Thin progress track used inside FileQueueRow */
|
|
398
|
+
.uploader-file-progress-track {
|
|
399
|
+
height: 5px;
|
|
400
|
+
border-radius: 99px;
|
|
401
|
+
background: var(--uploader-border-subtle);
|
|
402
|
+
overflow: hidden;
|
|
233
403
|
}
|
|
234
404
|
|
|
235
|
-
.uploader-file-progress
|
|
405
|
+
.uploader-file-progress-fill {
|
|
406
|
+
height: 100%;
|
|
236
407
|
background: var(--uploader-accent);
|
|
237
|
-
border-radius:
|
|
238
|
-
transition: width
|
|
408
|
+
border-radius: 99px;
|
|
409
|
+
transition: width 0.2s ease;
|
|
239
410
|
}
|
|
240
411
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
412
|
+
/* Done checkmark badge */
|
|
413
|
+
.uploader-file-done-badge {
|
|
414
|
+
width: 18px;
|
|
415
|
+
height: 18px;
|
|
416
|
+
border-radius: 99px;
|
|
417
|
+
background: var(--uploader-accent-soft);
|
|
418
|
+
display: flex;
|
|
419
|
+
align-items: center;
|
|
420
|
+
justify-content: center;
|
|
421
|
+
flex-shrink: 0;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.uploader-file-done-badge svg {
|
|
425
|
+
color: var(--uploader-accent);
|
|
244
426
|
}
|
|
245
427
|
|
|
246
428
|
.uploader-file-actions {
|
|
@@ -255,86 +437,148 @@
|
|
|
255
437
|
display: flex;
|
|
256
438
|
align-items: center;
|
|
257
439
|
gap: 10px;
|
|
258
|
-
padding:
|
|
440
|
+
padding: 6px 20px 12px;
|
|
259
441
|
flex-shrink: 0;
|
|
260
442
|
}
|
|
261
443
|
|
|
262
|
-
.uploader-aggregate-progress
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
444
|
+
.uploader-aggregate-progress-label {
|
|
445
|
+
font-size: 12px;
|
|
446
|
+
color: var(--uploader-text-muted);
|
|
447
|
+
font-weight: 600;
|
|
448
|
+
white-space: nowrap;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.uploader-aggregate-progress-pct {
|
|
452
|
+
font-size: 12px;
|
|
453
|
+
color: var(--uploader-text-muted);
|
|
454
|
+
min-width: 3ch;
|
|
455
|
+
text-align: right;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* ─── Standalone ProgressBar primitive ─────────────────────────────────────── */
|
|
459
|
+
|
|
460
|
+
/*
|
|
461
|
+
* .uploader-progress-bar — wraps the track+fill div pair.
|
|
462
|
+
* Height, radius, and color are set via CSS vars so they can be overridden
|
|
463
|
+
* at any ancestor (e.g. a taller bar for the aggregate slot).
|
|
464
|
+
*/
|
|
465
|
+
.uploader-progress-bar {
|
|
466
|
+
--uploader-progress-height: 5px;
|
|
467
|
+
--uploader-progress-radius: 99px;
|
|
468
|
+
height: var(--uploader-progress-height);
|
|
469
|
+
border-radius: var(--uploader-progress-radius);
|
|
470
|
+
background: var(--uploader-border-subtle);
|
|
267
471
|
overflow: hidden;
|
|
472
|
+
flex: 1;
|
|
268
473
|
}
|
|
269
474
|
|
|
270
|
-
.uploader-
|
|
271
|
-
|
|
272
|
-
border-radius: 4px;
|
|
475
|
+
.uploader-progress-bar[data-size="lg"] {
|
|
476
|
+
--uploader-progress-height: 8px;
|
|
273
477
|
}
|
|
274
478
|
|
|
275
|
-
.uploader-
|
|
479
|
+
.uploader-progress-bar-fill {
|
|
480
|
+
height: 100%;
|
|
276
481
|
background: var(--uploader-accent);
|
|
277
|
-
border-radius:
|
|
482
|
+
border-radius: var(--uploader-progress-radius);
|
|
278
483
|
transition: width 0.2s ease;
|
|
484
|
+
min-width: 4px; /* visible nub at 0% */
|
|
279
485
|
}
|
|
280
486
|
|
|
281
|
-
|
|
487
|
+
/* ─── Buttons ───────────────────────────────────────────────────────────────── */
|
|
488
|
+
|
|
489
|
+
.uploader-btn-primary {
|
|
490
|
+
padding: 8px 14px;
|
|
491
|
+
border: none;
|
|
492
|
+
border-radius: 9px;
|
|
282
493
|
background: var(--uploader-accent);
|
|
494
|
+
color: #fff;
|
|
495
|
+
font-family: var(--uploader-font);
|
|
496
|
+
font-weight: 600;
|
|
497
|
+
font-size: 13px;
|
|
498
|
+
cursor: pointer;
|
|
499
|
+
transition: background var(--uploader-transition), opacity var(--uploader-transition);
|
|
283
500
|
}
|
|
284
501
|
|
|
285
|
-
.uploader-
|
|
286
|
-
|
|
287
|
-
color: var(--uploader-text-muted);
|
|
288
|
-
min-width: 3ch;
|
|
502
|
+
.uploader-btn-primary:hover {
|
|
503
|
+
background: var(--uploader-accent-hover);
|
|
289
504
|
}
|
|
290
505
|
|
|
291
|
-
|
|
506
|
+
.uploader-btn-primary:disabled {
|
|
507
|
+
opacity: 0.4;
|
|
508
|
+
cursor: not-allowed;
|
|
509
|
+
}
|
|
292
510
|
|
|
293
|
-
|
|
294
|
-
.uploader-btn-browse
|
|
295
|
-
|
|
511
|
+
/* Browse files button inside the dropzone gets a focus ring matching the accent */
|
|
512
|
+
.uploader-btn-browse {
|
|
513
|
+
padding: 9px 18px;
|
|
514
|
+
border: none;
|
|
515
|
+
border-radius: 10px;
|
|
296
516
|
background: var(--uploader-accent);
|
|
297
517
|
color: #fff;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
font-size: 0.875rem;
|
|
302
|
-
font-weight: 500;
|
|
518
|
+
font-family: var(--uploader-font);
|
|
519
|
+
font-weight: 600;
|
|
520
|
+
font-size: 14px;
|
|
303
521
|
cursor: pointer;
|
|
522
|
+
box-shadow: 0 0 0 3px var(--uploader-accent-ring);
|
|
304
523
|
transition: background var(--uploader-transition);
|
|
305
524
|
}
|
|
306
525
|
|
|
307
|
-
.uploader-btn-
|
|
308
|
-
.uploader-btn-browse:hover,
|
|
309
|
-
.uploader-btn-done:hover {
|
|
526
|
+
.uploader-btn-browse:hover {
|
|
310
527
|
background: var(--uploader-accent-hover);
|
|
311
528
|
}
|
|
312
529
|
|
|
313
|
-
.uploader-btn-
|
|
314
|
-
|
|
315
|
-
|
|
530
|
+
.uploader-btn-browse:focus-visible {
|
|
531
|
+
outline: none;
|
|
532
|
+
box-shadow: 0 0 0 3px var(--uploader-accent-ring);
|
|
316
533
|
}
|
|
317
534
|
|
|
318
|
-
.uploader-btn-
|
|
319
|
-
|
|
320
|
-
color: var(--uploader-text);
|
|
535
|
+
.uploader-btn-secondary {
|
|
536
|
+
padding: 8px 14px;
|
|
321
537
|
border: 1px solid var(--uploader-border);
|
|
322
|
-
border-radius:
|
|
323
|
-
|
|
324
|
-
|
|
538
|
+
border-radius: 9px;
|
|
539
|
+
background: var(--uploader-bg);
|
|
540
|
+
color: var(--uploader-text);
|
|
541
|
+
font-family: var(--uploader-font);
|
|
542
|
+
font-weight: 600;
|
|
543
|
+
font-size: 13px;
|
|
325
544
|
cursor: pointer;
|
|
326
545
|
transition: background var(--uploader-transition);
|
|
327
546
|
}
|
|
328
547
|
|
|
329
|
-
.uploader-btn-
|
|
330
|
-
background: var(--uploader-
|
|
548
|
+
.uploader-btn-secondary:hover {
|
|
549
|
+
background: var(--uploader-surface);
|
|
331
550
|
}
|
|
332
551
|
|
|
333
|
-
.uploader-btn-
|
|
552
|
+
.uploader-btn-secondary:disabled {
|
|
334
553
|
opacity: 0.5;
|
|
335
554
|
cursor: not-allowed;
|
|
336
555
|
}
|
|
337
556
|
|
|
557
|
+
/* Aliases used in existing markup — map to the new button styles */
|
|
558
|
+
.uploader-btn-upload { composes: uploader-btn-primary; }
|
|
559
|
+
.uploader-btn-done { composes: uploader-btn-primary; }
|
|
560
|
+
.uploader-btn-cancel { composes: uploader-btn-secondary; }
|
|
561
|
+
|
|
562
|
+
.uploader-btn-icon {
|
|
563
|
+
width: 18px;
|
|
564
|
+
height: 18px;
|
|
565
|
+
display: flex;
|
|
566
|
+
align-items: center;
|
|
567
|
+
justify-content: center;
|
|
568
|
+
background: none;
|
|
569
|
+
border: none;
|
|
570
|
+
padding: 0;
|
|
571
|
+
cursor: pointer;
|
|
572
|
+
color: var(--uploader-text-muted);
|
|
573
|
+
border-radius: 4px;
|
|
574
|
+
transition: color var(--uploader-transition);
|
|
575
|
+
flex-shrink: 0;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.uploader-btn-icon:hover {
|
|
579
|
+
color: var(--uploader-text);
|
|
580
|
+
}
|
|
581
|
+
|
|
338
582
|
.uploader-btn-retry,
|
|
339
583
|
.uploader-btn-remove {
|
|
340
584
|
background: none;
|
|
@@ -371,9 +615,41 @@
|
|
|
371
615
|
border: 0;
|
|
372
616
|
}
|
|
373
617
|
|
|
618
|
+
/* ─── PickerOverlay done state ──────────────────────────────────────────────── */
|
|
619
|
+
|
|
620
|
+
.uploader-done-body {
|
|
621
|
+
display: flex;
|
|
622
|
+
flex-direction: column;
|
|
623
|
+
align-items: center;
|
|
624
|
+
text-align: center;
|
|
625
|
+
padding: 24px 20px;
|
|
626
|
+
gap: 0;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
.uploader-done-subtitle {
|
|
630
|
+
font-size: 13.5px;
|
|
631
|
+
color: var(--uploader-text-muted);
|
|
632
|
+
margin: 0 0 24px;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.uploader-done-list {
|
|
636
|
+
width: 100%;
|
|
637
|
+
text-align: left;
|
|
638
|
+
margin: 0 0 24px !important;
|
|
639
|
+
padding: 0 !important;
|
|
640
|
+
max-height: 180px;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.uploader-btn-done-full {
|
|
644
|
+
width: 100%;
|
|
645
|
+
padding: 11px;
|
|
646
|
+
font-size: 14px;
|
|
647
|
+
}
|
|
648
|
+
|
|
374
649
|
/* ─── DropPane root ─────────────────────────────────────────────────────────── */
|
|
375
650
|
|
|
376
651
|
.uploader-drop-pane {
|
|
652
|
+
position: relative;
|
|
377
653
|
display: flex;
|
|
378
654
|
flex-direction: column;
|
|
379
655
|
gap: 12px;
|
|
@@ -381,21 +657,51 @@
|
|
|
381
657
|
color: var(--uploader-text);
|
|
382
658
|
}
|
|
383
659
|
|
|
660
|
+
/* Dropzone inside DropPane has no side margin — fills the pane width */
|
|
384
661
|
.uploader-drop-pane .uploader-dropzone {
|
|
385
662
|
margin: 0;
|
|
386
663
|
}
|
|
387
664
|
|
|
388
|
-
.uploader-drop-pane
|
|
665
|
+
.uploader-drop-pane-file-list {
|
|
389
666
|
margin: 0;
|
|
667
|
+
padding: 0;
|
|
390
668
|
max-height: 200px;
|
|
391
669
|
}
|
|
392
670
|
|
|
393
|
-
|
|
671
|
+
/* Drag-over overlay — covers queued file list when user drags over a non-empty pane */
|
|
672
|
+
.uploader-drop-pane-drag-overlay {
|
|
673
|
+
position: absolute;
|
|
674
|
+
inset: 0;
|
|
675
|
+
border: 2px dashed var(--uploader-accent);
|
|
676
|
+
border-radius: 13px;
|
|
677
|
+
background: var(--uploader-accent-soft);
|
|
394
678
|
display: flex;
|
|
679
|
+
align-items: center;
|
|
680
|
+
justify-content: center;
|
|
681
|
+
z-index: 10;
|
|
682
|
+
pointer-events: all;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.uploader-drop-pane-drag-label {
|
|
686
|
+
font-size: 14px;
|
|
687
|
+
font-weight: 700;
|
|
688
|
+
color: var(--uploader-accent);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/* Action bar at the bottom of the pane */
|
|
692
|
+
.uploader-drop-pane-actions {
|
|
693
|
+
display: flex;
|
|
694
|
+
align-items: center;
|
|
695
|
+
justify-content: flex-end;
|
|
395
696
|
gap: 8px;
|
|
396
697
|
}
|
|
397
698
|
|
|
398
|
-
/*
|
|
699
|
+
/* Aggregate progress inside DropPane — no side padding (pane handles spacing) */
|
|
700
|
+
.uploader-drop-pane .uploader-aggregate-progress {
|
|
701
|
+
padding: 0;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/* ─── Browse link (DropPane inline variant) ─────────────────────────────────── */
|
|
399
705
|
|
|
400
706
|
.uploader-browse-link {
|
|
401
707
|
color: var(--uploader-accent);
|
|
@@ -587,3 +893,129 @@
|
|
|
587
893
|
opacity: 0.4;
|
|
588
894
|
cursor: not-allowed;
|
|
589
895
|
}
|
|
896
|
+
|
|
897
|
+
/* ─── Camera capture (in-picker webcam) ─────────────────────────────────────── */
|
|
898
|
+
|
|
899
|
+
.uploader-camera {
|
|
900
|
+
display: flex;
|
|
901
|
+
flex-direction: column;
|
|
902
|
+
gap: 14px;
|
|
903
|
+
padding: 16px 20px 18px;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
.uploader-camera-stage {
|
|
907
|
+
position: relative;
|
|
908
|
+
width: 100%;
|
|
909
|
+
aspect-ratio: 4 / 3;
|
|
910
|
+
max-height: 60vh;
|
|
911
|
+
background: #111418;
|
|
912
|
+
border-radius: var(--uploader-radius);
|
|
913
|
+
overflow: hidden;
|
|
914
|
+
display: flex;
|
|
915
|
+
align-items: center;
|
|
916
|
+
justify-content: center;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.uploader-camera-video,
|
|
920
|
+
.uploader-camera-still {
|
|
921
|
+
width: 100%;
|
|
922
|
+
height: 100%;
|
|
923
|
+
object-fit: contain;
|
|
924
|
+
display: block;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/* Front-camera preview/still are mirrored so the selfie matches the user. */
|
|
928
|
+
.uploader-camera-video[data-mirror='true'] {
|
|
929
|
+
transform: scaleX(-1);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.uploader-camera-status {
|
|
933
|
+
position: absolute;
|
|
934
|
+
inset: 0;
|
|
935
|
+
display: flex;
|
|
936
|
+
align-items: center;
|
|
937
|
+
justify-content: center;
|
|
938
|
+
color: #c9c4bc;
|
|
939
|
+
font-size: 13px;
|
|
940
|
+
pointer-events: none;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
.uploader-camera-error {
|
|
944
|
+
padding: 24px 28px;
|
|
945
|
+
text-align: center;
|
|
946
|
+
color: #f0ede8;
|
|
947
|
+
font-size: 13.5px;
|
|
948
|
+
line-height: 1.5;
|
|
949
|
+
max-width: 320px;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.uploader-camera-hint {
|
|
953
|
+
margin: -4px 0 0;
|
|
954
|
+
font-size: 12px;
|
|
955
|
+
color: var(--uploader-text-muted);
|
|
956
|
+
text-align: center;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.uploader-camera-actions {
|
|
960
|
+
display: flex;
|
|
961
|
+
align-items: center;
|
|
962
|
+
justify-content: space-between;
|
|
963
|
+
gap: 10px;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/*
|
|
967
|
+
* Live (shutter) row: Back · shutter · spacer, spread with space-between. The
|
|
968
|
+
* spacer is an invisible twin of the Back button, so both sides of the row have
|
|
969
|
+
* identical width and the shutter sits perfectly centered. visibility:hidden
|
|
970
|
+
* keeps its layout box (and thus its width) while removing it visually.
|
|
971
|
+
*/
|
|
972
|
+
.uploader-camera-actions-spacer {
|
|
973
|
+
visibility: hidden;
|
|
974
|
+
pointer-events: none;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
/* Round shutter button with an inner ring */
|
|
978
|
+
.uploader-camera-shutter {
|
|
979
|
+
width: 62px;
|
|
980
|
+
height: 62px;
|
|
981
|
+
border-radius: 999px;
|
|
982
|
+
border: 3px solid var(--uploader-accent);
|
|
983
|
+
background: var(--uploader-bg);
|
|
984
|
+
cursor: pointer;
|
|
985
|
+
display: inline-flex;
|
|
986
|
+
align-items: center;
|
|
987
|
+
justify-content: center;
|
|
988
|
+
padding: 0;
|
|
989
|
+
transition: transform var(--uploader-transition), box-shadow var(--uploader-transition);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.uploader-camera-shutter-ring {
|
|
993
|
+
width: 46px;
|
|
994
|
+
height: 46px;
|
|
995
|
+
border-radius: 999px;
|
|
996
|
+
background: var(--uploader-accent);
|
|
997
|
+
transition: background var(--uploader-transition);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.uploader-camera-shutter:hover:not(:disabled) {
|
|
1001
|
+
box-shadow: 0 0 0 4px var(--uploader-accent-ring);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.uploader-camera-shutter:active:not(:disabled) {
|
|
1005
|
+
transform: scale(0.94);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.uploader-camera-shutter:focus-visible {
|
|
1009
|
+
outline: none;
|
|
1010
|
+
box-shadow: 0 0 0 4px var(--uploader-accent-ring);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
.uploader-camera-shutter:disabled {
|
|
1014
|
+
opacity: 0.5;
|
|
1015
|
+
cursor: not-allowed;
|
|
1016
|
+
border-color: var(--uploader-border);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
.uploader-camera-shutter:disabled .uploader-camera-shutter-ring {
|
|
1020
|
+
background: var(--uploader-border);
|
|
1021
|
+
}
|