@ibanzajoe/uploader 0.1.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.
@@ -0,0 +1,589 @@
1
+ /**
2
+ * @uploader/react — component styles
3
+ *
4
+ * Themeable via CSS custom properties. Override any variable in your own
5
+ * stylesheet or on a parent element. Light / dark modes are handled via the
6
+ * `data-theme="dark"` attribute on any ancestor.
7
+ *
8
+ * Import once in your app:
9
+ * import '@uploader/react/styles.css'
10
+ */
11
+
12
+ /* ─── Design tokens ─────────────────────────────────────────────────────────── */
13
+
14
+ :root {
15
+ --uploader-accent: #0057ff;
16
+ --uploader-accent-hover: #0041cc;
17
+ --uploader-radius: 8px;
18
+ --uploader-bg: #ffffff;
19
+ --uploader-surface: #f5f7fa;
20
+ --uploader-border: #d4d8e1;
21
+ --uploader-text: #1a1d23;
22
+ --uploader-text-muted: #6b7280;
23
+ --uploader-error: #dc2626;
24
+ --uploader-success: #16a34a;
25
+ --uploader-shadow: 0 8px 32px rgba(0, 0, 0, 0.14);
26
+ --uploader-z-backdrop: 1000;
27
+ --uploader-z-panel: 1001;
28
+ --uploader-font: inherit;
29
+ --uploader-transition: 0.15s ease;
30
+ }
31
+
32
+ [data-theme="dark"] {
33
+ --uploader-bg: #1e2130;
34
+ --uploader-surface: #282c3e;
35
+ --uploader-border: #3b4060;
36
+ --uploader-text: #e8eaf0;
37
+ --uploader-text-muted: #9ba3b8;
38
+ --uploader-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
39
+ }
40
+
41
+ /* ─── Backdrop ──────────────────────────────────────────────────────────────── */
42
+
43
+ .uploader-backdrop {
44
+ position: fixed;
45
+ inset: 0;
46
+ background: rgba(0, 0, 0, 0.45);
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ z-index: var(--uploader-z-backdrop);
51
+ font-family: var(--uploader-font);
52
+ }
53
+
54
+ /* ─── Modal panel ───────────────────────────────────────────────────────────── */
55
+
56
+ .uploader-picker-panel {
57
+ background: var(--uploader-bg);
58
+ border-radius: var(--uploader-radius);
59
+ box-shadow: var(--uploader-shadow);
60
+ width: min(560px, calc(100vw - 32px));
61
+ max-height: calc(100dvh - 32px);
62
+ display: flex;
63
+ flex-direction: column;
64
+ overflow: hidden;
65
+ z-index: var(--uploader-z-panel);
66
+ color: var(--uploader-text);
67
+ }
68
+
69
+ .uploader-picker-header {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: space-between;
73
+ padding: 16px 20px;
74
+ border-bottom: 1px solid var(--uploader-border);
75
+ flex-shrink: 0;
76
+ }
77
+
78
+ .uploader-picker-title {
79
+ margin: 0;
80
+ font-size: 1.05rem;
81
+ font-weight: 600;
82
+ color: var(--uploader-text);
83
+ }
84
+
85
+ .uploader-btn-close {
86
+ background: none;
87
+ border: none;
88
+ cursor: pointer;
89
+ font-size: 1.4rem;
90
+ line-height: 1;
91
+ color: var(--uploader-text-muted);
92
+ padding: 4px 6px;
93
+ border-radius: 4px;
94
+ transition: color var(--uploader-transition), background var(--uploader-transition);
95
+ }
96
+
97
+ .uploader-btn-close:hover {
98
+ color: var(--uploader-text);
99
+ background: var(--uploader-surface);
100
+ }
101
+
102
+ .uploader-picker-footer {
103
+ display: flex;
104
+ justify-content: flex-end;
105
+ gap: 8px;
106
+ padding: 12px 20px;
107
+ border-top: 1px solid var(--uploader-border);
108
+ flex-shrink: 0;
109
+ }
110
+
111
+ /* ─── Drop zone (shared by PickerOverlay and DropPane) ──────────────────────── */
112
+
113
+ .uploader-dropzone {
114
+ margin: 16px 20px;
115
+ border: 2px dashed var(--uploader-border);
116
+ border-radius: var(--uploader-radius);
117
+ background: var(--uploader-surface);
118
+ padding: 32px 20px;
119
+ display: flex;
120
+ flex-direction: column;
121
+ align-items: center;
122
+ gap: 10px;
123
+ cursor: pointer;
124
+ transition:
125
+ border-color var(--uploader-transition),
126
+ background var(--uploader-transition);
127
+ flex-shrink: 0;
128
+ }
129
+
130
+ .uploader-dropzone:hover,
131
+ .uploader-dropzone:focus-visible,
132
+ .uploader-drag-over .uploader-dropzone {
133
+ border-color: var(--uploader-accent);
134
+ background: color-mix(in srgb, var(--uploader-accent) 5%, var(--uploader-surface));
135
+ outline: none;
136
+ }
137
+
138
+ .uploader-dropzone:focus-visible {
139
+ outline: 2px solid var(--uploader-accent);
140
+ outline-offset: 2px;
141
+ }
142
+
143
+ .uploader-dropzone-icon {
144
+ font-size: 2.5rem;
145
+ color: var(--uploader-accent);
146
+ }
147
+
148
+ .uploader-dropzone-label {
149
+ margin: 0;
150
+ color: var(--uploader-text-muted);
151
+ font-size: 0.9rem;
152
+ text-align: center;
153
+ }
154
+
155
+ /* ─── File list ─────────────────────────────────────────────────────────────── */
156
+
157
+ .uploader-file-list {
158
+ list-style: none;
159
+ margin: 0 20px;
160
+ padding: 0;
161
+ overflow-y: auto;
162
+ max-height: 260px;
163
+ display: flex;
164
+ flex-direction: column;
165
+ gap: 6px;
166
+ }
167
+
168
+ .uploader-file-item {
169
+ display: flex;
170
+ align-items: center;
171
+ gap: 10px;
172
+ padding: 8px 10px;
173
+ border-radius: calc(var(--uploader-radius) - 2px);
174
+ background: var(--uploader-surface);
175
+ border: 1px solid var(--uploader-border);
176
+ }
177
+
178
+ .uploader-file-item.uploader-file-error {
179
+ border-color: var(--uploader-error);
180
+ background: color-mix(in srgb, var(--uploader-error) 6%, var(--uploader-surface));
181
+ }
182
+
183
+ .uploader-file-item.uploader-file-done {
184
+ border-color: var(--uploader-success);
185
+ }
186
+
187
+ .uploader-file-thumb {
188
+ width: 36px;
189
+ height: 36px;
190
+ object-fit: cover;
191
+ border-radius: 4px;
192
+ flex-shrink: 0;
193
+ }
194
+
195
+ .uploader-file-info {
196
+ flex: 1;
197
+ min-width: 0;
198
+ display: flex;
199
+ flex-direction: column;
200
+ gap: 2px;
201
+ }
202
+
203
+ .uploader-file-name {
204
+ font-size: 0.875rem;
205
+ color: var(--uploader-text);
206
+ white-space: nowrap;
207
+ overflow: hidden;
208
+ text-overflow: ellipsis;
209
+ }
210
+
211
+ .uploader-file-error {
212
+ font-size: 0.75rem;
213
+ color: var(--uploader-error);
214
+ }
215
+
216
+ .uploader-file-done {
217
+ font-size: 0.75rem;
218
+ color: var(--uploader-success);
219
+ }
220
+
221
+ .uploader-file-progress {
222
+ width: 80px;
223
+ height: 6px;
224
+ appearance: none;
225
+ border-radius: 3px;
226
+ overflow: hidden;
227
+ flex-shrink: 0;
228
+ }
229
+
230
+ .uploader-file-progress::-webkit-progress-bar {
231
+ background: var(--uploader-border);
232
+ border-radius: 3px;
233
+ }
234
+
235
+ .uploader-file-progress::-webkit-progress-value {
236
+ background: var(--uploader-accent);
237
+ border-radius: 3px;
238
+ transition: width var(--uploader-transition);
239
+ }
240
+
241
+ .uploader-file-progress::-moz-progress-bar {
242
+ background: var(--uploader-accent);
243
+ border-radius: 3px;
244
+ }
245
+
246
+ .uploader-file-actions {
247
+ display: flex;
248
+ gap: 6px;
249
+ flex-shrink: 0;
250
+ }
251
+
252
+ /* ─── Aggregate progress ────────────────────────────────────────────────────── */
253
+
254
+ .uploader-aggregate-progress {
255
+ display: flex;
256
+ align-items: center;
257
+ gap: 10px;
258
+ padding: 8px 20px;
259
+ flex-shrink: 0;
260
+ }
261
+
262
+ .uploader-aggregate-progress progress {
263
+ flex: 1;
264
+ height: 8px;
265
+ appearance: none;
266
+ border-radius: 4px;
267
+ overflow: hidden;
268
+ }
269
+
270
+ .uploader-aggregate-progress progress::-webkit-progress-bar {
271
+ background: var(--uploader-border);
272
+ border-radius: 4px;
273
+ }
274
+
275
+ .uploader-aggregate-progress progress::-webkit-progress-value {
276
+ background: var(--uploader-accent);
277
+ border-radius: 4px;
278
+ transition: width 0.2s ease;
279
+ }
280
+
281
+ .uploader-aggregate-progress progress::-moz-progress-bar {
282
+ background: var(--uploader-accent);
283
+ }
284
+
285
+ .uploader-aggregate-progress span {
286
+ font-size: 0.8rem;
287
+ color: var(--uploader-text-muted);
288
+ min-width: 3ch;
289
+ }
290
+
291
+ /* ─── Buttons ───────────────────────────────────────────────────────────────── */
292
+
293
+ .uploader-btn-upload,
294
+ .uploader-btn-browse,
295
+ .uploader-btn-done {
296
+ background: var(--uploader-accent);
297
+ color: #fff;
298
+ border: none;
299
+ border-radius: calc(var(--uploader-radius) - 2px);
300
+ padding: 8px 18px;
301
+ font-size: 0.875rem;
302
+ font-weight: 500;
303
+ cursor: pointer;
304
+ transition: background var(--uploader-transition);
305
+ }
306
+
307
+ .uploader-btn-upload:hover,
308
+ .uploader-btn-browse:hover,
309
+ .uploader-btn-done:hover {
310
+ background: var(--uploader-accent-hover);
311
+ }
312
+
313
+ .uploader-btn-upload:disabled {
314
+ opacity: 0.5;
315
+ cursor: not-allowed;
316
+ }
317
+
318
+ .uploader-btn-cancel {
319
+ background: var(--uploader-surface);
320
+ color: var(--uploader-text);
321
+ border: 1px solid var(--uploader-border);
322
+ border-radius: calc(var(--uploader-radius) - 2px);
323
+ padding: 8px 18px;
324
+ font-size: 0.875rem;
325
+ cursor: pointer;
326
+ transition: background var(--uploader-transition);
327
+ }
328
+
329
+ .uploader-btn-cancel:hover {
330
+ background: var(--uploader-border);
331
+ }
332
+
333
+ .uploader-btn-cancel:disabled {
334
+ opacity: 0.5;
335
+ cursor: not-allowed;
336
+ }
337
+
338
+ .uploader-btn-retry,
339
+ .uploader-btn-remove {
340
+ background: none;
341
+ border: 1px solid var(--uploader-border);
342
+ border-radius: 4px;
343
+ padding: 2px 8px;
344
+ font-size: 0.75rem;
345
+ cursor: pointer;
346
+ color: var(--uploader-text-muted);
347
+ transition: border-color var(--uploader-transition), color var(--uploader-transition);
348
+ }
349
+
350
+ .uploader-btn-retry:hover {
351
+ border-color: var(--uploader-accent);
352
+ color: var(--uploader-accent);
353
+ }
354
+
355
+ .uploader-btn-remove:hover {
356
+ border-color: var(--uploader-error);
357
+ color: var(--uploader-error);
358
+ }
359
+
360
+ /* ─── Hidden input ──────────────────────────────────────────────────────────── */
361
+
362
+ .uploader-file-input {
363
+ position: absolute;
364
+ width: 1px;
365
+ height: 1px;
366
+ padding: 0;
367
+ margin: -1px;
368
+ overflow: hidden;
369
+ clip: rect(0, 0, 0, 0);
370
+ white-space: nowrap;
371
+ border: 0;
372
+ }
373
+
374
+ /* ─── DropPane root ─────────────────────────────────────────────────────────── */
375
+
376
+ .uploader-drop-pane {
377
+ display: flex;
378
+ flex-direction: column;
379
+ gap: 12px;
380
+ font-family: var(--uploader-font);
381
+ color: var(--uploader-text);
382
+ }
383
+
384
+ .uploader-drop-pane .uploader-dropzone {
385
+ margin: 0;
386
+ }
387
+
388
+ .uploader-drop-pane .uploader-file-list {
389
+ margin: 0;
390
+ max-height: 200px;
391
+ }
392
+
393
+ .uploader-drop-pane .uploader-actions {
394
+ display: flex;
395
+ gap: 8px;
396
+ }
397
+
398
+ /* ─── Browse link (DropPane) ────────────────────────────────────────────────── */
399
+
400
+ .uploader-browse-link {
401
+ color: var(--uploader-accent);
402
+ cursor: pointer;
403
+ text-decoration: underline;
404
+ }
405
+
406
+ /* ─── Image editor (in-picker, pre-upload) ──────────────────────────────────── */
407
+
408
+ .uploader-editor {
409
+ display: flex;
410
+ flex-direction: column;
411
+ gap: 14px;
412
+ padding: 16px;
413
+ }
414
+
415
+ .uploader-editor-canvas {
416
+ position: relative;
417
+ width: 100%;
418
+ height: 60vh;
419
+ max-height: 560px;
420
+ background: #111418;
421
+ border-radius: var(--uploader-radius);
422
+ overflow: hidden;
423
+ touch-action: none;
424
+ user-select: none;
425
+ cursor: grab;
426
+ }
427
+
428
+ .uploader-editor-canvas:active {
429
+ cursor: grabbing;
430
+ }
431
+
432
+ .uploader-editor-image {
433
+ position: absolute;
434
+ left: 0;
435
+ top: 0;
436
+ /* Override global img resets (e.g. Tailwind preflight's max-width:100% /
437
+ height:auto) that would clamp width but not height → distorted aspect.
438
+ We set explicit natural width/height inline so the scale maths is exact. */
439
+ max-width: none;
440
+ max-height: none;
441
+ transform-origin: 0 0;
442
+ will-change: transform;
443
+ pointer-events: none;
444
+ -webkit-user-drag: none;
445
+ user-select: none;
446
+ }
447
+
448
+ .uploader-editor-cropbox {
449
+ position: absolute;
450
+ box-sizing: border-box;
451
+ border: 1px solid rgba(255, 255, 255, 0.85);
452
+ box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
453
+ pointer-events: none;
454
+ }
455
+
456
+ .uploader-editor-cropbox-round {
457
+ border-radius: 50%;
458
+ }
459
+
460
+ .uploader-editor-handle {
461
+ position: absolute;
462
+ width: 14px;
463
+ height: 14px;
464
+ background: #fff;
465
+ border: 1px solid rgba(0, 0, 0, 0.35);
466
+ border-radius: 2px;
467
+ pointer-events: auto;
468
+ touch-action: none;
469
+ }
470
+
471
+ .uploader-editor-hint {
472
+ margin: -6px 0 0;
473
+ font-size: 12px;
474
+ color: var(--uploader-text-muted);
475
+ }
476
+
477
+ .uploader-editor-controls {
478
+ display: flex;
479
+ flex-direction: column;
480
+ gap: 10px;
481
+ }
482
+
483
+ .uploader-editor-row {
484
+ display: flex;
485
+ align-items: center;
486
+ gap: 8px;
487
+ flex-wrap: wrap;
488
+ }
489
+
490
+ .uploader-editor-label {
491
+ font-size: 13px;
492
+ color: var(--uploader-text-muted);
493
+ min-width: 44px;
494
+ }
495
+
496
+ .uploader-editor-tool {
497
+ width: 36px;
498
+ height: 36px;
499
+ font-size: 18px;
500
+ line-height: 1;
501
+ display: inline-flex;
502
+ align-items: center;
503
+ justify-content: center;
504
+ background: var(--uploader-surface);
505
+ color: var(--uploader-text);
506
+ border: 1px solid var(--uploader-border);
507
+ border-radius: calc(var(--uploader-radius) - 2px);
508
+ cursor: pointer;
509
+ transition: background var(--uploader-transition);
510
+ }
511
+
512
+ .uploader-editor-tool:hover {
513
+ background: var(--uploader-border);
514
+ }
515
+
516
+ .uploader-editor-tool-active {
517
+ background: var(--uploader-accent);
518
+ color: #fff;
519
+ border-color: var(--uploader-accent);
520
+ }
521
+
522
+ .uploader-editor-chip {
523
+ padding: 5px 12px;
524
+ font-size: 13px;
525
+ background: var(--uploader-surface);
526
+ color: var(--uploader-text);
527
+ border: 1px solid var(--uploader-border);
528
+ border-radius: 999px;
529
+ cursor: pointer;
530
+ transition: background var(--uploader-transition);
531
+ }
532
+
533
+ .uploader-editor-chip:hover {
534
+ background: var(--uploader-border);
535
+ }
536
+
537
+ .uploader-editor-chip-active {
538
+ background: var(--uploader-accent);
539
+ color: #fff;
540
+ border-color: var(--uploader-accent);
541
+ }
542
+
543
+ .uploader-editor-slider {
544
+ flex: 1;
545
+ accent-color: var(--uploader-accent);
546
+ }
547
+
548
+ .uploader-editor-number {
549
+ width: 90px;
550
+ padding: 5px 8px;
551
+ font: inherit;
552
+ color: var(--uploader-text);
553
+ background: var(--uploader-bg);
554
+ border: 1px solid var(--uploader-border);
555
+ border-radius: calc(var(--uploader-radius) - 2px);
556
+ }
557
+
558
+ .uploader-editor-error {
559
+ font-size: 13px;
560
+ color: var(--uploader-error);
561
+ }
562
+
563
+ .uploader-editor-actions {
564
+ display: flex;
565
+ justify-content: flex-end;
566
+ gap: 8px;
567
+ }
568
+
569
+ /* Per-file "Edit" button in the file list */
570
+ .uploader-btn-edit {
571
+ background: transparent;
572
+ color: var(--uploader-accent);
573
+ border: 1px solid var(--uploader-border);
574
+ border-radius: calc(var(--uploader-radius) - 2px);
575
+ padding: 4px 10px;
576
+ font: inherit;
577
+ font-size: 13px;
578
+ cursor: pointer;
579
+ transition: background var(--uploader-transition);
580
+ }
581
+
582
+ .uploader-btn-edit:hover {
583
+ background: var(--uploader-surface);
584
+ }
585
+
586
+ .uploader-editor-chip:disabled {
587
+ opacity: 0.4;
588
+ cursor: not-allowed;
589
+ }