@roy-ui/ui 0.0.14 → 0.0.16

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,621 @@
1
+ "use client";
2
+ import { TextMorph } from './chunk-MO7UPMW7.js';
3
+ import { Button } from './chunk-B6LXWGX5.js';
4
+ import { forwardRef, useRef, useState, useMemo, useEffect } from 'react';
5
+ import './UploadFiles-QEAOV3R6.css';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ var DEFAULT_STATUS_WORDS = [
9
+ "Uploading\u2026",
10
+ "Transferring\u2026",
11
+ "Beaming bytes\u2026",
12
+ "Encrypting\u2026",
13
+ "Securing\u2026",
14
+ "Packing bits\u2026",
15
+ "Syncing\u2026",
16
+ "Crunching data\u2026",
17
+ "Pushing pixels\u2026",
18
+ "Almost there\u2026",
19
+ "Hang tight\u2026",
20
+ "Wrangling chunks\u2026",
21
+ "Verifying\u2026",
22
+ "Finalizing\u2026",
23
+ "Just a sec\u2026"
24
+ ];
25
+ var EXT_META = {
26
+ pdf: { label: "PDF", color: "#f0524b" },
27
+ doc: { label: "DOC", color: "#3b82f6" },
28
+ docx: { label: "DOCX", color: "#3b82f6" },
29
+ fig: { label: "FIG", color: "#a259ff" },
30
+ png: { label: "PNG", color: "#10b981" },
31
+ jpg: { label: "JPG", color: "#10b981" },
32
+ jpeg: { label: "JPG", color: "#10b981" },
33
+ gif: { label: "GIF", color: "#10b981" },
34
+ svg: { label: "SVG", color: "#f59e0b" },
35
+ zip: { label: "ZIP", color: "#f59e0b" },
36
+ mp4: { label: "MP4", color: "#ec4899" },
37
+ csv: { label: "CSV", color: "#22c55e" },
38
+ json: { label: "JSON", color: "#eab308" },
39
+ default: { label: "FILE", color: "#8b8b94" }
40
+ };
41
+ function fileExt(name) {
42
+ return name.split(".").pop()?.toLowerCase() ?? "";
43
+ }
44
+ function extMeta(name) {
45
+ return EXT_META[fileExt(name)] ?? EXT_META.default;
46
+ }
47
+ function trimNum(n) {
48
+ return (Math.round(n * 10) / 10).toString();
49
+ }
50
+ function formatBytes(bytes) {
51
+ if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
52
+ if (bytes < 1024) return `${Math.round(bytes)} B`;
53
+ const kb = bytes / 1024;
54
+ if (kb < 1024) return `${trimNum(kb)} KB`;
55
+ const mb = kb / 1024;
56
+ if (mb < 1024) return `${trimNum(mb)} MB`;
57
+ return `${trimNum(mb / 1024)} GB`;
58
+ }
59
+ function shuffle(input) {
60
+ const a = input.slice();
61
+ for (let i = a.length - 1; i > 0; i--) {
62
+ const j = Math.floor(Math.random() * (i + 1));
63
+ [a[i], a[j]] = [a[j], a[i]];
64
+ }
65
+ return a;
66
+ }
67
+ var cn = (...classes) => classes.filter(Boolean).join(" ");
68
+ var UploadGlyph = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", "aria-hidden": "true", children: [
69
+ /* @__PURE__ */ jsx(
70
+ "path",
71
+ {
72
+ d: "M12 15V4m0 0L7.5 8.5M12 4l4.5 4.5",
73
+ stroke: "currentColor",
74
+ strokeWidth: "1.6",
75
+ strokeLinecap: "round",
76
+ strokeLinejoin: "round"
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsx(
80
+ "path",
81
+ {
82
+ d: "M4 14v3.5A2.5 2.5 0 0 0 6.5 20h11a2.5 2.5 0 0 0 2.5-2.5V14",
83
+ stroke: "currentColor",
84
+ strokeWidth: "1.6",
85
+ strokeLinecap: "round"
86
+ }
87
+ )
88
+ ] });
89
+ var CloseGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
90
+ "path",
91
+ {
92
+ d: "M6 6l12 12M18 6L6 18",
93
+ stroke: "currentColor",
94
+ strokeWidth: "1.6",
95
+ strokeLinecap: "round"
96
+ }
97
+ ) });
98
+ var TrashGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "20", height: "20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
99
+ "path",
100
+ {
101
+ d: "M4 7h16M9 7V5.5A1.5 1.5 0 0 1 10.5 4h3A1.5 1.5 0 0 1 15 5.5V7m2 0v11.5A1.5 1.5 0 0 1 15.5 20h-7A1.5 1.5 0 0 1 7 18.5V7m3 3.5v6m4-6v6",
102
+ stroke: "currentColor",
103
+ strokeWidth: "1.5",
104
+ strokeLinecap: "round",
105
+ strokeLinejoin: "round"
106
+ }
107
+ ) });
108
+ var CheckGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "13", height: "13", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
109
+ "path",
110
+ {
111
+ d: "M4 12.5l5 5 11-12",
112
+ stroke: "currentColor",
113
+ strokeWidth: "2.2",
114
+ strokeLinecap: "round",
115
+ strokeLinejoin: "round"
116
+ }
117
+ ) });
118
+ var CheckSmall = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
119
+ "path",
120
+ {
121
+ d: "M5 12.5l4.5 4.5L19 6",
122
+ stroke: "currentColor",
123
+ strokeWidth: "2.6",
124
+ strokeLinecap: "round",
125
+ strokeLinejoin: "round"
126
+ }
127
+ ) });
128
+ function DefaultPreview({ file }) {
129
+ const meta = extMeta(file.name);
130
+ const ext = fileExt(file.name);
131
+ const url = file.url;
132
+ if (url && /^(png|jpe?g|gif|webp|svg|avif|bmp)$/.test(ext)) {
133
+ return /* @__PURE__ */ jsx("img", { className: "royui-upload__preview-img", src: url, alt: file.name });
134
+ }
135
+ if (url && ext === "pdf") {
136
+ return /* @__PURE__ */ jsx("iframe", { className: "royui-upload__preview-frame", src: url, title: file.name });
137
+ }
138
+ if (url && /^(mp4|webm|mov|ogg)$/.test(ext)) {
139
+ return /* @__PURE__ */ jsx("video", { className: "royui-upload__preview-video", src: url, controls: true });
140
+ }
141
+ return /* @__PURE__ */ jsxs("div", { className: "royui-upload__preview-card", children: [
142
+ /* @__PURE__ */ jsx(
143
+ "span",
144
+ {
145
+ className: "royui-upload__preview-badge",
146
+ style: { ["--royui-upload-badge"]: meta.color },
147
+ "aria-hidden": "true",
148
+ children: file.icon ?? /* @__PURE__ */ jsx("span", { className: "royui-upload__badge-label", children: meta.label })
149
+ }
150
+ ),
151
+ /* @__PURE__ */ jsx("p", { className: "royui-upload__preview-name", children: file.name }),
152
+ /* @__PURE__ */ jsxs("p", { className: "royui-upload__preview-sub", children: [
153
+ formatBytes(file.size),
154
+ " \xB7 ",
155
+ meta.label
156
+ ] }),
157
+ url ? /* @__PURE__ */ jsx(
158
+ "a",
159
+ {
160
+ className: "royui-upload__preview-download",
161
+ href: url,
162
+ download: file.name,
163
+ target: "_blank",
164
+ rel: "noreferrer",
165
+ children: "Open file"
166
+ }
167
+ ) : /* @__PURE__ */ jsx("p", { className: "royui-upload__preview-empty", children: "No inline preview available." })
168
+ ] });
169
+ }
170
+ function PreviewModal({
171
+ file,
172
+ renderPreview,
173
+ onClose
174
+ }) {
175
+ useEffect(() => {
176
+ const onKey = (e) => {
177
+ if (e.key === "Escape") onClose();
178
+ };
179
+ document.addEventListener("keydown", onKey);
180
+ return () => document.removeEventListener("keydown", onKey);
181
+ }, [onClose]);
182
+ return /* @__PURE__ */ jsx(
183
+ "div",
184
+ {
185
+ className: "royui-upload__modal",
186
+ role: "dialog",
187
+ "aria-modal": "true",
188
+ "aria-label": `Preview of ${file.name}`,
189
+ onClick: onClose,
190
+ children: /* @__PURE__ */ jsxs(
191
+ "div",
192
+ {
193
+ className: "royui-upload__modal-panel",
194
+ onClick: (e) => e.stopPropagation(),
195
+ children: [
196
+ /* @__PURE__ */ jsxs("header", { className: "royui-upload__modal-head", children: [
197
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__modal-title", title: file.name, children: file.name }),
198
+ /* @__PURE__ */ jsx(
199
+ "button",
200
+ {
201
+ type: "button",
202
+ className: "royui-upload__close",
203
+ "aria-label": "Close preview",
204
+ onClick: onClose,
205
+ children: /* @__PURE__ */ jsx(CloseGlyph, {})
206
+ }
207
+ )
208
+ ] }),
209
+ /* @__PURE__ */ jsx("div", { className: "royui-upload__modal-body", children: renderPreview ? renderPreview(file) : /* @__PURE__ */ jsx(DefaultPreview, { file }) })
210
+ ]
211
+ }
212
+ )
213
+ }
214
+ );
215
+ }
216
+ function FileRow({
217
+ file,
218
+ word,
219
+ selectable,
220
+ selecting,
221
+ selected,
222
+ previewable,
223
+ onRemove,
224
+ onEnterSelect,
225
+ onToggleSelect,
226
+ onPreview
227
+ }) {
228
+ const meta = extMeta(file.name);
229
+ const pct = file.progress != null ? Math.max(0, Math.min(100, Math.round(file.progress))) : file.size > 0 ? Math.max(0, Math.min(100, Math.round((file.uploaded ?? 0) / file.size * 100))) : 0;
230
+ const isUploading = file.status === "uploading";
231
+ const isError = file.status === "error";
232
+ const pressTimer = useRef(void 0);
233
+ const suppressClick = useRef(false);
234
+ const clearPress = () => {
235
+ if (pressTimer.current) {
236
+ clearTimeout(pressTimer.current);
237
+ pressTimer.current = void 0;
238
+ }
239
+ };
240
+ const onPointerDown = (e) => {
241
+ if (!selectable || selecting || e.pointerType === "mouse") return;
242
+ clearPress();
243
+ pressTimer.current = setTimeout(() => {
244
+ suppressClick.current = true;
245
+ onEnterSelect(file.id);
246
+ }, 450);
247
+ };
248
+ const onRowClick = () => {
249
+ if (suppressClick.current) {
250
+ suppressClick.current = false;
251
+ return;
252
+ }
253
+ if (selecting) onToggleSelect(file.id);
254
+ };
255
+ const nameClickable = previewable && !selecting;
256
+ return /* @__PURE__ */ jsxs(
257
+ "div",
258
+ {
259
+ className: cn(
260
+ "royui-upload__row",
261
+ selecting && "is-selecting",
262
+ selected && "is-selected"
263
+ ),
264
+ "data-status": file.status,
265
+ "data-selected": selected || void 0,
266
+ onPointerDown,
267
+ onPointerUp: clearPress,
268
+ onPointerLeave: clearPress,
269
+ onPointerMove: clearPress,
270
+ onContextMenu: (e) => {
271
+ if (selectable) e.preventDefault();
272
+ },
273
+ onClick: onRowClick,
274
+ children: [
275
+ /* @__PURE__ */ jsx(
276
+ "span",
277
+ {
278
+ className: "royui-upload__badge",
279
+ style: { ["--royui-upload-badge"]: file.icon ? "transparent" : meta.color },
280
+ "aria-hidden": "true",
281
+ children: file.icon ?? /* @__PURE__ */ jsx("span", { className: "royui-upload__badge-label", children: meta.label })
282
+ }
283
+ ),
284
+ /* @__PURE__ */ jsxs("div", { className: "royui-upload__row-main", children: [
285
+ nameClickable ? /* @__PURE__ */ jsx(
286
+ "button",
287
+ {
288
+ type: "button",
289
+ className: "royui-upload__name royui-upload__name--button",
290
+ title: `Preview ${file.name}`,
291
+ onClick: (e) => {
292
+ e.stopPropagation();
293
+ onPreview(file);
294
+ },
295
+ children: file.name
296
+ }
297
+ ) : /* @__PURE__ */ jsx("span", { className: "royui-upload__name", title: file.name, children: file.name }),
298
+ /* @__PURE__ */ jsxs("div", { className: "royui-upload__meta", children: [
299
+ file.status === "complete" && /* @__PURE__ */ jsxs(Fragment, { children: [
300
+ /* @__PURE__ */ jsx("span", { children: formatBytes(file.size) }),
301
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__meta-sep", children: "/" }),
302
+ /* @__PURE__ */ jsxs("span", { className: "royui-upload__complete", children: [
303
+ /* @__PURE__ */ jsx(CheckGlyph, {}),
304
+ "Complete"
305
+ ] })
306
+ ] }),
307
+ isUploading && /* @__PURE__ */ jsxs(Fragment, { children: [
308
+ /* @__PURE__ */ jsxs("span", { children: [
309
+ /* @__PURE__ */ jsx(TextMorph, { value: formatBytes(file.uploaded ?? 0) }),
310
+ " of",
311
+ " ",
312
+ formatBytes(file.size)
313
+ ] }),
314
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__meta-sep", children: "/" }),
315
+ /* @__PURE__ */ jsx(
316
+ TextMorph,
317
+ {
318
+ className: "royui-upload__status",
319
+ value: word,
320
+ renderText: (t) => /* @__PURE__ */ jsx("span", { className: "royui-upload__shimmer", children: t })
321
+ }
322
+ )
323
+ ] }),
324
+ isError && /* @__PURE__ */ jsxs(Fragment, { children: [
325
+ /* @__PURE__ */ jsx("span", { children: formatBytes(file.size) }),
326
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__meta-sep", children: "/" }),
327
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__error", children: "Failed" })
328
+ ] })
329
+ ] }),
330
+ isUploading && /* @__PURE__ */ jsxs("div", { className: "royui-upload__progress", children: [
331
+ /* @__PURE__ */ jsx(
332
+ "div",
333
+ {
334
+ className: "royui-upload__bar",
335
+ role: "progressbar",
336
+ "aria-valuenow": pct,
337
+ "aria-valuemin": 0,
338
+ "aria-valuemax": 100,
339
+ children: /* @__PURE__ */ jsx("div", { className: "royui-upload__bar-fill", style: { width: `${pct}%` } })
340
+ }
341
+ ),
342
+ /* @__PURE__ */ jsxs("span", { className: "royui-upload__pct", children: [
343
+ pct,
344
+ "%"
345
+ ] })
346
+ ] })
347
+ ] }),
348
+ selecting ? /* @__PURE__ */ jsx(
349
+ "span",
350
+ {
351
+ className: cn("royui-upload__check", selected && "is-checked"),
352
+ "aria-hidden": "true",
353
+ children: selected && /* @__PURE__ */ jsx(CheckSmall, {})
354
+ }
355
+ ) : /* @__PURE__ */ jsx(
356
+ "button",
357
+ {
358
+ type: "button",
359
+ className: "royui-upload__row-action",
360
+ "aria-label": selectable ? `Select files to delete, starting with ${file.name}` : isUploading ? `Cancel ${file.name}` : `Remove ${file.name}`,
361
+ onClick: (e) => {
362
+ e.stopPropagation();
363
+ if (selectable) onEnterSelect(file.id);
364
+ else onRemove?.(file.id);
365
+ },
366
+ children: isUploading ? /* @__PURE__ */ jsx(CloseGlyph, {}) : /* @__PURE__ */ jsx(TrashGlyph, {})
367
+ }
368
+ )
369
+ ]
370
+ }
371
+ );
372
+ }
373
+ var UploadFiles = forwardRef(
374
+ function UploadFiles2({
375
+ files,
376
+ title = "Upload files",
377
+ maxSizeLabel = "MAX FILE SIZE: 20 MB",
378
+ accept,
379
+ multiple = true,
380
+ theme = "dark",
381
+ statusWords = DEFAULT_STATUS_WORDS,
382
+ actionLabel,
383
+ selectable = false,
384
+ previewable = true,
385
+ renderPreview,
386
+ onFilesSelected,
387
+ onRemove,
388
+ onRemoveSelected,
389
+ onRemoveAll,
390
+ onClose,
391
+ onAction,
392
+ onPreview,
393
+ className = "",
394
+ ...rest
395
+ }, ref) {
396
+ const inputRef = useRef(null);
397
+ const [isDragging, setDragging] = useState(false);
398
+ const [tick, setTick] = useState(0);
399
+ const [selecting, setSelecting] = useState(false);
400
+ const [selected, setSelected] = useState(() => /* @__PURE__ */ new Set());
401
+ const [preview, setPreview] = useState(null);
402
+ const anyUploading = files.some((f) => f.status === "uploading");
403
+ const words = useMemo(
404
+ () => statusWords.length ? shuffle(statusWords) : DEFAULT_STATUS_WORDS,
405
+ // eslint-disable-next-line react-hooks/exhaustive-deps
406
+ []
407
+ );
408
+ useEffect(() => {
409
+ if (!anyUploading) return;
410
+ const id = setInterval(() => setTick((t) => t + 1), 1900);
411
+ return () => clearInterval(id);
412
+ }, [anyUploading]);
413
+ useEffect(() => {
414
+ if (files.length === 0 && selecting) {
415
+ setSelecting(false);
416
+ setSelected(/* @__PURE__ */ new Set());
417
+ }
418
+ }, [files.length, selecting]);
419
+ const emit = (list) => {
420
+ if (!list || list.length === 0) return;
421
+ onFilesSelected?.(Array.from(list));
422
+ };
423
+ const enterSelect = (id) => {
424
+ setSelecting(true);
425
+ setSelected(/* @__PURE__ */ new Set([id]));
426
+ };
427
+ const toggleSelect = (id) => {
428
+ setSelected((prev) => {
429
+ const next = new Set(prev);
430
+ next.has(id) ? next.delete(id) : next.add(id);
431
+ return next;
432
+ });
433
+ };
434
+ const cancelSelect = () => {
435
+ setSelecting(false);
436
+ setSelected(/* @__PURE__ */ new Set());
437
+ };
438
+ const confirmDelete = () => {
439
+ const ids = Array.from(selected);
440
+ if (ids.length === 0) return;
441
+ if (onRemoveSelected) onRemoveSelected(ids);
442
+ else ids.forEach((id) => onRemove?.(id));
443
+ cancelSelect();
444
+ };
445
+ const openPreview = (file) => {
446
+ setPreview(file);
447
+ onPreview?.(file);
448
+ };
449
+ const headingText = selecting ? `${selected.size} selected` : typeof title === "string" ? title : null;
450
+ const classes = cn(
451
+ "royui-upload",
452
+ theme === "dark" && "royui-upload--dark",
453
+ theme === "light" && "royui-upload--light",
454
+ theme === "auto" && "royui-upload--auto",
455
+ selecting && "royui-upload--selecting",
456
+ className
457
+ );
458
+ return /* @__PURE__ */ jsxs("div", { ref, className: classes, ...rest, children: [
459
+ /* @__PURE__ */ jsxs("header", { className: "royui-upload__header", children: [
460
+ /* @__PURE__ */ jsx("h2", { className: "royui-upload__title", children: headingText !== null ? /* @__PURE__ */ jsx(TextMorph, { value: headingText }) : title }),
461
+ selecting ? /* @__PURE__ */ jsx(
462
+ "button",
463
+ {
464
+ type: "button",
465
+ className: "royui-upload__close",
466
+ "aria-label": "Exit selection",
467
+ onClick: cancelSelect,
468
+ children: /* @__PURE__ */ jsx(CloseGlyph, {})
469
+ }
470
+ ) : onClose && /* @__PURE__ */ jsx(
471
+ "button",
472
+ {
473
+ type: "button",
474
+ className: "royui-upload__close",
475
+ "aria-label": "Close",
476
+ onClick: onClose,
477
+ children: /* @__PURE__ */ jsx(CloseGlyph, {})
478
+ }
479
+ )
480
+ ] }),
481
+ /* @__PURE__ */ jsxs(
482
+ "div",
483
+ {
484
+ className: cn("royui-upload__dropzone", isDragging && "is-dragging"),
485
+ onDragOver: (e) => {
486
+ e.preventDefault();
487
+ setDragging(true);
488
+ },
489
+ onDragLeave: (e) => {
490
+ e.preventDefault();
491
+ setDragging(false);
492
+ },
493
+ onDrop: (e) => {
494
+ e.preventDefault();
495
+ setDragging(false);
496
+ emit(e.dataTransfer.files);
497
+ },
498
+ children: [
499
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__drop-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(UploadGlyph, {}) }),
500
+ /* @__PURE__ */ jsxs("p", { className: "royui-upload__drop-text", children: [
501
+ "Drag and drop or",
502
+ " ",
503
+ /* @__PURE__ */ jsx(
504
+ "button",
505
+ {
506
+ type: "button",
507
+ className: "royui-upload__browse",
508
+ onClick: () => inputRef.current?.click(),
509
+ children: "browse files"
510
+ }
511
+ )
512
+ ] }),
513
+ /* @__PURE__ */ jsx("p", { className: "royui-upload__drop-hint", children: maxSizeLabel }),
514
+ /* @__PURE__ */ jsx(
515
+ "input",
516
+ {
517
+ ref: inputRef,
518
+ type: "file",
519
+ accept,
520
+ multiple,
521
+ className: "royui-upload__input",
522
+ onChange: (e) => {
523
+ emit(e.target.files);
524
+ e.target.value = "";
525
+ }
526
+ }
527
+ )
528
+ ]
529
+ }
530
+ ),
531
+ files.length > 0 && /* @__PURE__ */ jsx("div", { className: "royui-upload__list", children: files.map((file, i) => /* @__PURE__ */ jsx(
532
+ FileRow,
533
+ {
534
+ file,
535
+ word: words[(tick + i) % words.length],
536
+ selectable,
537
+ selecting,
538
+ selected: selected.has(file.id),
539
+ previewable,
540
+ onRemove,
541
+ onEnterSelect: enterSelect,
542
+ onToggleSelect: toggleSelect,
543
+ onPreview: openPreview
544
+ },
545
+ file.id
546
+ )) }),
547
+ files.length > 0 && /* @__PURE__ */ jsx("footer", { className: "royui-upload__footer", children: /* @__PURE__ */ jsx(
548
+ "div",
549
+ {
550
+ className: "royui-upload__footer-inner",
551
+ children: selecting ? /* @__PURE__ */ jsxs(Fragment, { children: [
552
+ /* @__PURE__ */ jsx(
553
+ "button",
554
+ {
555
+ type: "button",
556
+ className: "royui-upload__textbtn",
557
+ onClick: cancelSelect,
558
+ children: "Cancel"
559
+ }
560
+ ),
561
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__footer-spacer" }),
562
+ /* @__PURE__ */ jsxs(
563
+ Button,
564
+ {
565
+ size: "sm",
566
+ className: "royui-upload__action royui-upload__action--danger",
567
+ color: "#e5484d",
568
+ disabled: selected.size === 0,
569
+ onClick: confirmDelete,
570
+ children: [
571
+ "Delete",
572
+ selected.size > 0 ? ` (${selected.size})` : ""
573
+ ]
574
+ }
575
+ )
576
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
577
+ /* @__PURE__ */ jsxs(
578
+ "button",
579
+ {
580
+ type: "button",
581
+ className: "royui-upload__remove-all",
582
+ "aria-label": "Remove all files",
583
+ onClick: onRemoveAll,
584
+ children: [
585
+ /* @__PURE__ */ jsx(TrashGlyph, {}),
586
+ "All"
587
+ ]
588
+ }
589
+ ),
590
+ /* @__PURE__ */ jsx("span", { className: "royui-upload__footer-spacer" }),
591
+ /* @__PURE__ */ jsx(
592
+ Button,
593
+ {
594
+ size: "sm",
595
+ variant: "secondary",
596
+ className: "royui-upload__action",
597
+ disabled: anyUploading,
598
+ onClick: onAction,
599
+ children: actionLabel ?? (anyUploading ? /* @__PURE__ */ jsx(TextMorph, { value: "Uploading\u2026" }) : "Done")
600
+ }
601
+ )
602
+ ] })
603
+ },
604
+ selecting ? "select" : "browse"
605
+ ) }),
606
+ preview && /* @__PURE__ */ jsx(
607
+ PreviewModal,
608
+ {
609
+ file: preview,
610
+ renderPreview,
611
+ onClose: () => setPreview(null)
612
+ }
613
+ )
614
+ ] });
615
+ }
616
+ );
617
+ UploadFiles.displayName = "UploadFiles";
618
+
619
+ export { UploadFiles };
620
+ //# sourceMappingURL=chunk-E2VDIA6U.js.map
621
+ //# sourceMappingURL=chunk-E2VDIA6U.js.map