@roy-ui/ui 0.0.15 → 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 @@
1
+ {"version":3,"sources":["../src/components/upload-files/UploadFiles.tsx"],"names":["UploadFiles"],"mappings":"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","file":"chunk-E2VDIA6U.js","sourcesContent":["'use client';\n\nimport {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type PointerEvent as ReactPointerEvent,\n type ReactNode,\n} from 'react';\nimport { TextMorph } from '../text-morph/TextMorph';\nimport { Button } from '../button/Button';\nimport './UploadFiles.css';\n\nexport type UploadStatus = 'uploading' | 'complete' | 'error';\n\nexport interface UploadFile {\n /** Stable id — used as the React key and passed back to onRemove. */\n id: string;\n /** File name including extension; drives the type badge. */\n name: string;\n /** Total size in bytes. */\n size: number;\n /** Bytes transferred so far. Drives the \"X OF Y\" label and, when\n * `progress` is omitted, the percentage. */\n uploaded?: number;\n /** Progress 0–100. Falls back to uploaded / size when omitted. */\n progress?: number;\n /** Lifecycle state. */\n status: UploadStatus;\n /** Optional override for the file-type badge. */\n icon?: ReactNode;\n /** Source for the preview modal — an image/pdf/video URL or object URL.\n * When present, the built-in preview renders the real content; otherwise\n * it falls back to a file-info card. */\n url?: string;\n}\n\nexport type UploadTheme = 'auto' | 'light' | 'dark';\n\nexport interface UploadFilesProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** The files to render. The component is controlled — it draws this\n * list and emits events; the consumer owns the upload + progress. */\n files: UploadFile[];\n /** Panel heading. Defaults to \"Upload files\". */\n title?: ReactNode;\n /** Caption under the dropzone. Defaults to \"MAX FILE SIZE: 20 MB\". */\n maxSizeLabel?: string;\n /** Forwarded to the hidden file input's `accept`. */\n accept?: string;\n /** Allow selecting multiple files. Defaults to true. */\n multiple?: boolean;\n /** Color scheme. Dark by default; \"auto\" follows the OS. */\n theme?: UploadTheme;\n /** Words cycled (and morphed) in the per-file status while uploading.\n * Defaults to a long, varied upload vocabulary so the wait stays lively. */\n statusWords?: string[];\n /** Footer action button content. Defaults to a state-derived label\n * (\"Uploading…\" while in flight, \"Done\" otherwise). */\n actionLabel?: ReactNode;\n /** Enable the multi-select-to-delete variant. Long-press a row (touch) or\n * tap a row's trash (pointer) to enter selection mode, pick files, then\n * confirm a bulk delete. Defaults to false (each trash deletes instantly). */\n selectable?: boolean;\n /** Make filenames clickable to open a preview modal. Defaults to true. */\n previewable?: boolean;\n /** Custom body for the preview modal. Receives the clicked file; return any\n * node. When omitted, a built-in renderer shows the image / pdf / video at\n * `file.url`, or a file-info card when there's nothing to display. */\n renderPreview?: (file: UploadFile) => ReactNode;\n /** Fired with the dropped / browsed File objects. */\n onFilesSelected?: (files: File[]) => void;\n /** Fired when a single row's trash / cancel control is pressed (non-select\n * mode). */\n onRemove?: (id: string) => void;\n /** Fired when selection mode confirms a bulk delete. Falls back to calling\n * onRemove once per id when not provided. */\n onRemoveSelected?: (ids: string[]) => void;\n /** Fired by the \"Remove all\" footer control. */\n onRemoveAll?: () => void;\n /** When provided, renders the header close (×) button. */\n onClose?: () => void;\n /** Fired by the footer action button. */\n onAction?: () => void;\n /** Fired when a filename is clicked to preview — handy for lazy-loading the\n * preview URL. The built-in modal still opens. */\n onPreview?: (file: UploadFile) => void;\n}\n\nconst DEFAULT_STATUS_WORDS = [\n 'Uploading…',\n 'Transferring…',\n 'Beaming bytes…',\n 'Encrypting…',\n 'Securing…',\n 'Packing bits…',\n 'Syncing…',\n 'Crunching data…',\n 'Pushing pixels…',\n 'Almost there…',\n 'Hang tight…',\n 'Wrangling chunks…',\n 'Verifying…',\n 'Finalizing…',\n 'Just a sec…',\n];\n\nconst EXT_META: Record<string, { label: string; color: string }> = {\n pdf: { label: 'PDF', color: '#f0524b' },\n doc: { label: 'DOC', color: '#3b82f6' },\n docx: { label: 'DOCX', color: '#3b82f6' },\n fig: { label: 'FIG', color: '#a259ff' },\n png: { label: 'PNG', color: '#10b981' },\n jpg: { label: 'JPG', color: '#10b981' },\n jpeg: { label: 'JPG', color: '#10b981' },\n gif: { label: 'GIF', color: '#10b981' },\n svg: { label: 'SVG', color: '#f59e0b' },\n zip: { label: 'ZIP', color: '#f59e0b' },\n mp4: { label: 'MP4', color: '#ec4899' },\n csv: { label: 'CSV', color: '#22c55e' },\n json: { label: 'JSON', color: '#eab308' },\n default: { label: 'FILE', color: '#8b8b94' },\n};\n\nfunction fileExt(name: string) {\n return name.split('.').pop()?.toLowerCase() ?? '';\n}\n\nfunction extMeta(name: string) {\n return EXT_META[fileExt(name)] ?? EXT_META.default!;\n}\n\nfunction trimNum(n: number): string {\n return (Math.round(n * 10) / 10).toString();\n}\n\n/** Human-readable byte size, e.g. 2.7 MB / 14 MB. */\nfunction formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '0 B';\n if (bytes < 1024) return `${Math.round(bytes)} B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${trimNum(kb)} KB`;\n const mb = kb / 1024;\n if (mb < 1024) return `${trimNum(mb)} MB`;\n return `${trimNum(mb / 1024)} GB`;\n}\n\n/** Deterministic-ish shuffle (Fisher–Yates) so the word order varies per\n * session without two adjacent entries being the same word. */\nfunction shuffle<T>(input: T[]): T[] {\n const a = input.slice();\n for (let i = a.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [a[i], a[j]] = [a[j]!, a[i]!];\n }\n return a;\n}\n\nconst cn = (...classes: (string | false | undefined)[]) =>\n classes.filter(Boolean).join(' ');\n\n/* ── Icons ──────────────────────────────────────────────────────────────── */\n\nconst UploadGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M12 15V4m0 0L7.5 8.5M12 4l4.5 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M4 14v3.5A2.5 2.5 0 0 0 6.5 20h11a2.5 2.5 0 0 0 2.5-2.5V14\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nconst CloseGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nconst TrashGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"none\" aria-hidden=\"true\">\n <path\n 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\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nconst CheckGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"13\" height=\"13\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M4 12.5l5 5 11-12\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nconst CheckSmall = () => (\n <svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M5 12.5l4.5 4.5L19 6\"\n stroke=\"currentColor\"\n strokeWidth=\"2.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\n/* ── Default preview body ─────────────────────────────────────────────────── */\n\nfunction DefaultPreview({ file }: { file: UploadFile }) {\n const meta = extMeta(file.name);\n const ext = fileExt(file.name);\n const url = file.url;\n\n if (url && /^(png|jpe?g|gif|webp|svg|avif|bmp)$/.test(ext)) {\n return <img className=\"royui-upload__preview-img\" src={url} alt={file.name} />;\n }\n if (url && ext === 'pdf') {\n return (\n <iframe className=\"royui-upload__preview-frame\" src={url} title={file.name} />\n );\n }\n if (url && /^(mp4|webm|mov|ogg)$/.test(ext)) {\n return <video className=\"royui-upload__preview-video\" src={url} controls />;\n }\n\n return (\n <div className=\"royui-upload__preview-card\">\n <span\n className=\"royui-upload__preview-badge\"\n style={{ ['--royui-upload-badge' as string]: meta.color }}\n aria-hidden=\"true\"\n >\n {file.icon ?? <span className=\"royui-upload__badge-label\">{meta.label}</span>}\n </span>\n <p className=\"royui-upload__preview-name\">{file.name}</p>\n <p className=\"royui-upload__preview-sub\">\n {formatBytes(file.size)} · {meta.label}\n </p>\n {url ? (\n <a\n className=\"royui-upload__preview-download\"\n href={url}\n download={file.name}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n Open file\n </a>\n ) : (\n <p className=\"royui-upload__preview-empty\">No inline preview available.</p>\n )}\n </div>\n );\n}\n\nfunction PreviewModal({\n file,\n renderPreview,\n onClose,\n}: {\n file: UploadFile;\n renderPreview?: (file: UploadFile) => ReactNode;\n onClose: () => void;\n}) {\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n return (\n <div\n className=\"royui-upload__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Preview of ${file.name}`}\n onClick={onClose}\n >\n <div\n className=\"royui-upload__modal-panel\"\n onClick={(e) => e.stopPropagation()}\n >\n <header className=\"royui-upload__modal-head\">\n <span className=\"royui-upload__modal-title\" title={file.name}>\n {file.name}\n </span>\n <button\n type=\"button\"\n className=\"royui-upload__close\"\n aria-label=\"Close preview\"\n onClick={onClose}\n >\n <CloseGlyph />\n </button>\n </header>\n <div className=\"royui-upload__modal-body\">\n {renderPreview ? renderPreview(file) : <DefaultPreview file={file} />}\n </div>\n </div>\n </div>\n );\n}\n\n/* ── File row ───────────────────────────────────────────────────────────── */\n\nfunction FileRow({\n file,\n word,\n selectable,\n selecting,\n selected,\n previewable,\n onRemove,\n onEnterSelect,\n onToggleSelect,\n onPreview,\n}: {\n file: UploadFile;\n word: string;\n selectable: boolean;\n selecting: boolean;\n selected: boolean;\n previewable: boolean;\n onRemove?: (id: string) => void;\n onEnterSelect: (id: string) => void;\n onToggleSelect: (id: string) => void;\n onPreview: (file: UploadFile) => void;\n}) {\n const meta = extMeta(file.name);\n const pct =\n file.progress != null\n ? Math.max(0, Math.min(100, Math.round(file.progress)))\n : file.size > 0\n ? Math.max(0, Math.min(100, Math.round(((file.uploaded ?? 0) / file.size) * 100)))\n : 0;\n\n const isUploading = file.status === 'uploading';\n const isError = file.status === 'error';\n\n // Long-press (touch) to enter selection mode. A guard suppresses the click\n // that fires right after the press so it doesn't immediately toggle back.\n const pressTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const suppressClick = useRef(false);\n\n const clearPress = () => {\n if (pressTimer.current) {\n clearTimeout(pressTimer.current);\n pressTimer.current = undefined;\n }\n };\n\n const onPointerDown = (e: ReactPointerEvent) => {\n if (!selectable || selecting || e.pointerType === 'mouse') return;\n clearPress();\n pressTimer.current = setTimeout(() => {\n suppressClick.current = true;\n onEnterSelect(file.id);\n }, 450);\n };\n\n const onRowClick = () => {\n if (suppressClick.current) {\n suppressClick.current = false;\n return;\n }\n if (selecting) onToggleSelect(file.id);\n };\n\n const nameClickable = previewable && !selecting;\n\n return (\n <div\n className={cn(\n 'royui-upload__row',\n selecting && 'is-selecting',\n selected && 'is-selected',\n )}\n data-status={file.status}\n data-selected={selected || undefined}\n onPointerDown={onPointerDown}\n onPointerUp={clearPress}\n onPointerLeave={clearPress}\n onPointerMove={clearPress}\n onContextMenu={(e) => {\n if (selectable) e.preventDefault();\n }}\n onClick={onRowClick}\n >\n <span\n className=\"royui-upload__badge\"\n style={{ ['--royui-upload-badge' as string]: file.icon ? 'transparent' : meta.color }}\n aria-hidden=\"true\"\n >\n {file.icon ?? <span className=\"royui-upload__badge-label\">{meta.label}</span>}\n </span>\n\n <div className=\"royui-upload__row-main\">\n {nameClickable ? (\n <button\n type=\"button\"\n className=\"royui-upload__name royui-upload__name--button\"\n title={`Preview ${file.name}`}\n onClick={(e) => {\n e.stopPropagation();\n onPreview(file);\n }}\n >\n {file.name}\n </button>\n ) : (\n <span className=\"royui-upload__name\" title={file.name}>\n {file.name}\n </span>\n )}\n\n <div className=\"royui-upload__meta\">\n {file.status === 'complete' && (\n <>\n <span>{formatBytes(file.size)}</span>\n <span className=\"royui-upload__meta-sep\">/</span>\n <span className=\"royui-upload__complete\">\n <CheckGlyph />\n Complete\n </span>\n </>\n )}\n {isUploading && (\n <>\n <span>\n <TextMorph value={formatBytes(file.uploaded ?? 0)} /> of{' '}\n {formatBytes(file.size)}\n </span>\n <span className=\"royui-upload__meta-sep\">/</span>\n <TextMorph\n className=\"royui-upload__status\"\n value={word}\n renderText={(t) => (\n <span className=\"royui-upload__shimmer\">{t}</span>\n )}\n />\n </>\n )}\n {isError && (\n <>\n <span>{formatBytes(file.size)}</span>\n <span className=\"royui-upload__meta-sep\">/</span>\n <span className=\"royui-upload__error\">Failed</span>\n </>\n )}\n </div>\n\n {isUploading && (\n <div className=\"royui-upload__progress\">\n <div\n className=\"royui-upload__bar\"\n role=\"progressbar\"\n aria-valuenow={pct}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div className=\"royui-upload__bar-fill\" style={{ width: `${pct}%` }} />\n </div>\n <span className=\"royui-upload__pct\">{pct}%</span>\n </div>\n )}\n </div>\n\n {selecting ? (\n <span\n className={cn('royui-upload__check', selected && 'is-checked')}\n aria-hidden=\"true\"\n >\n {selected && <CheckSmall />}\n </span>\n ) : (\n <button\n type=\"button\"\n className=\"royui-upload__row-action\"\n aria-label={\n selectable\n ? `Select files to delete, starting with ${file.name}`\n : isUploading\n ? `Cancel ${file.name}`\n : `Remove ${file.name}`\n }\n onClick={(e) => {\n e.stopPropagation();\n if (selectable) onEnterSelect(file.id);\n else onRemove?.(file.id);\n }}\n >\n {isUploading ? <CloseGlyph /> : <TrashGlyph />}\n </button>\n )}\n </div>\n );\n}\n\n/* ── Component ──────────────────────────────────────────────────────────── */\n\nexport const UploadFiles = forwardRef<HTMLDivElement, UploadFilesProps>(\n function UploadFiles(\n {\n files,\n title = 'Upload files',\n maxSizeLabel = 'MAX FILE SIZE: 20 MB',\n accept,\n multiple = true,\n theme = 'dark',\n statusWords = DEFAULT_STATUS_WORDS,\n actionLabel,\n selectable = false,\n previewable = true,\n renderPreview,\n onFilesSelected,\n onRemove,\n onRemoveSelected,\n onRemoveAll,\n onClose,\n onAction,\n onPreview,\n className = '',\n ...rest\n },\n ref,\n ) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setDragging] = useState(false);\n const [tick, setTick] = useState(0);\n const [selecting, setSelecting] = useState(false);\n const [selected, setSelected] = useState<Set<string>>(() => new Set());\n const [preview, setPreview] = useState<UploadFile | null>(null);\n\n const anyUploading = files.some((f) => f.status === 'uploading');\n\n // Shuffle once per mount so the word order varies between sessions.\n const words = useMemo(\n () => (statusWords.length ? shuffle(statusWords) : DEFAULT_STATUS_WORDS),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n // Advance the shared cycle only while something is in flight.\n useEffect(() => {\n if (!anyUploading) return;\n const id = setInterval(() => setTick((t) => t + 1), 1900);\n return () => clearInterval(id);\n }, [anyUploading]);\n\n // Drop selection state once the list empties or selection is exited.\n useEffect(() => {\n if (files.length === 0 && selecting) {\n setSelecting(false);\n setSelected(new Set());\n }\n }, [files.length, selecting]);\n\n const emit = (list: FileList | null) => {\n if (!list || list.length === 0) return;\n onFilesSelected?.(Array.from(list));\n };\n\n const enterSelect = (id: string) => {\n setSelecting(true);\n setSelected(new Set([id]));\n };\n const toggleSelect = (id: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n next.has(id) ? next.delete(id) : next.add(id);\n return next;\n });\n };\n const cancelSelect = () => {\n setSelecting(false);\n setSelected(new Set());\n };\n const confirmDelete = () => {\n const ids = Array.from(selected);\n if (ids.length === 0) return;\n if (onRemoveSelected) onRemoveSelected(ids);\n else ids.forEach((id) => onRemove?.(id));\n cancelSelect();\n };\n const openPreview = (file: UploadFile) => {\n setPreview(file);\n onPreview?.(file);\n };\n\n // Morph the title between the panel name and the live selection count.\n // (Falls back to the raw node when a custom non-string title is passed.)\n const headingText = selecting\n ? `${selected.size} selected`\n : typeof title === 'string'\n ? title\n : null;\n\n const classes = cn(\n 'royui-upload',\n theme === 'dark' && 'royui-upload--dark',\n theme === 'light' && 'royui-upload--light',\n theme === 'auto' && 'royui-upload--auto',\n selecting && 'royui-upload--selecting',\n className,\n );\n\n return (\n <div ref={ref} className={classes} {...rest}>\n <header className=\"royui-upload__header\">\n <h2 className=\"royui-upload__title\">\n {headingText !== null ? <TextMorph value={headingText} /> : title}\n </h2>\n {selecting ? (\n <button\n type=\"button\"\n className=\"royui-upload__close\"\n aria-label=\"Exit selection\"\n onClick={cancelSelect}\n >\n <CloseGlyph />\n </button>\n ) : (\n onClose && (\n <button\n type=\"button\"\n className=\"royui-upload__close\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n <CloseGlyph />\n </button>\n )\n )}\n </header>\n\n <div\n className={cn('royui-upload__dropzone', isDragging && 'is-dragging')}\n onDragOver={(e) => {\n e.preventDefault();\n setDragging(true);\n }}\n onDragLeave={(e) => {\n e.preventDefault();\n setDragging(false);\n }}\n onDrop={(e) => {\n e.preventDefault();\n setDragging(false);\n emit(e.dataTransfer.files);\n }}\n >\n <span className=\"royui-upload__drop-icon\" aria-hidden=\"true\">\n <UploadGlyph />\n </span>\n <p className=\"royui-upload__drop-text\">\n Drag and drop or{' '}\n <button\n type=\"button\"\n className=\"royui-upload__browse\"\n onClick={() => inputRef.current?.click()}\n >\n browse files\n </button>\n </p>\n <p className=\"royui-upload__drop-hint\">{maxSizeLabel}</p>\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n className=\"royui-upload__input\"\n onChange={(e) => {\n emit(e.target.files);\n e.target.value = '';\n }}\n />\n </div>\n\n {files.length > 0 && (\n <div className=\"royui-upload__list\">\n {files.map((file, i) => (\n <FileRow\n key={file.id}\n file={file}\n word={words[(tick + i) % words.length]!}\n selectable={selectable}\n selecting={selecting}\n selected={selected.has(file.id)}\n previewable={previewable}\n onRemove={onRemove}\n onEnterSelect={enterSelect}\n onToggleSelect={toggleSelect}\n onPreview={openPreview}\n />\n ))}\n </div>\n )}\n\n {files.length > 0 && (\n <footer className=\"royui-upload__footer\">\n <div\n className=\"royui-upload__footer-inner\"\n key={selecting ? 'select' : 'browse'}\n >\n {selecting ? (\n <>\n <button\n type=\"button\"\n className=\"royui-upload__textbtn\"\n onClick={cancelSelect}\n >\n Cancel\n </button>\n <span className=\"royui-upload__footer-spacer\" />\n <Button\n size=\"sm\"\n className=\"royui-upload__action royui-upload__action--danger\"\n color=\"#e5484d\"\n disabled={selected.size === 0}\n onClick={confirmDelete}\n >\n Delete{selected.size > 0 ? ` (${selected.size})` : ''}\n </Button>\n </>\n ) : (\n <>\n <button\n type=\"button\"\n className=\"royui-upload__remove-all\"\n aria-label=\"Remove all files\"\n onClick={onRemoveAll}\n >\n <TrashGlyph />\n All\n </button>\n <span className=\"royui-upload__footer-spacer\" />\n <Button\n size=\"sm\"\n variant=\"secondary\"\n className=\"royui-upload__action\"\n disabled={anyUploading}\n onClick={onAction}\n >\n {actionLabel ??\n (anyUploading ? <TextMorph value=\"Uploading…\" /> : 'Done')}\n </Button>\n </>\n )}\n </div>\n </footer>\n )}\n\n {preview && (\n <PreviewModal\n file={preview}\n renderPreview={renderPreview}\n onClose={() => setPreview(null)}\n />\n )}\n </div>\n );\n },\n);\n\nUploadFiles.displayName = 'UploadFiles';\n"]}
@@ -18,6 +18,10 @@ interface UploadFile {
18
18
  status: UploadStatus;
19
19
  /** Optional override for the file-type badge. */
20
20
  icon?: ReactNode;
21
+ /** Source for the preview modal — an image/pdf/video URL or object URL.
22
+ * When present, the built-in preview renders the real content; otherwise
23
+ * it falls back to a file-info card. */
24
+ url?: string;
21
25
  }
22
26
  type UploadTheme = 'auto' | 'light' | 'dark';
23
27
  interface UploadFilesProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
@@ -40,16 +44,33 @@ interface UploadFilesProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>
40
44
  /** Footer action button content. Defaults to a state-derived label
41
45
  * ("Uploading…" while in flight, "Done" otherwise). */
42
46
  actionLabel?: ReactNode;
47
+ /** Enable the multi-select-to-delete variant. Long-press a row (touch) or
48
+ * tap a row's trash (pointer) to enter selection mode, pick files, then
49
+ * confirm a bulk delete. Defaults to false (each trash deletes instantly). */
50
+ selectable?: boolean;
51
+ /** Make filenames clickable to open a preview modal. Defaults to true. */
52
+ previewable?: boolean;
53
+ /** Custom body for the preview modal. Receives the clicked file; return any
54
+ * node. When omitted, a built-in renderer shows the image / pdf / video at
55
+ * `file.url`, or a file-info card when there's nothing to display. */
56
+ renderPreview?: (file: UploadFile) => ReactNode;
43
57
  /** Fired with the dropped / browsed File objects. */
44
58
  onFilesSelected?: (files: File[]) => void;
45
- /** Fired when a single row's trash / cancel control is pressed. */
59
+ /** Fired when a single row's trash / cancel control is pressed (non-select
60
+ * mode). */
46
61
  onRemove?: (id: string) => void;
62
+ /** Fired when selection mode confirms a bulk delete. Falls back to calling
63
+ * onRemove once per id when not provided. */
64
+ onRemoveSelected?: (ids: string[]) => void;
47
65
  /** Fired by the "Remove all" footer control. */
48
66
  onRemoveAll?: () => void;
49
67
  /** When provided, renders the header close (×) button. */
50
68
  onClose?: () => void;
51
69
  /** Fired by the footer action button. */
52
70
  onAction?: () => void;
71
+ /** Fired when a filename is clicked to preview — handy for lazy-loading the
72
+ * preview URL. The built-in modal still opens. */
73
+ onPreview?: (file: UploadFile) => void;
53
74
  }
54
75
  declare const UploadFiles: react.ForwardRefExoticComponent<UploadFilesProps & react.RefAttributes<HTMLDivElement>>;
55
76
 
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- export { UploadFiles } from '../../chunk-BM6TW5ZZ.js';
2
+ export { UploadFiles } from '../../chunk-E2VDIA6U.js';
3
3
  import '../../chunk-MO7UPMW7.js';
4
4
  import '../../chunk-B6LXWGX5.js';
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  export { Popover } from './chunk-C5X3TE5U.js';
3
3
  import './chunk-DAA5LXWQ.js';
4
4
  export { TreeNav, TreeNavItem } from './chunk-M6HB6BMA.js';
5
- export { UploadFiles } from './chunk-BM6TW5ZZ.js';
5
+ export { UploadFiles } from './chunk-E2VDIA6U.js';
6
6
  export { TextMorph } from './chunk-MO7UPMW7.js';
7
7
  export { Card, ImageCarousel } from './chunk-TBBQRMCG.js';
8
8
  import './chunk-ORTCK34Y.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roy-ui/ui",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Free, animated React components built with TypeScript. Zero config, RSC-safe, sub-12 KB. Gradient button, popover, text morph and more.",
5
5
  "keywords": [
6
6
  "react",
@@ -1,364 +0,0 @@
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-HTUESAEP.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 extMeta(name) {
42
- const ext = name.split(".").pop()?.toLowerCase() ?? "";
43
- return EXT_META[ext] ?? EXT_META.default;
44
- }
45
- function trimNum(n) {
46
- return (Math.round(n * 10) / 10).toString();
47
- }
48
- function formatBytes(bytes) {
49
- if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
50
- if (bytes < 1024) return `${Math.round(bytes)} B`;
51
- const kb = bytes / 1024;
52
- if (kb < 1024) return `${trimNum(kb)} KB`;
53
- const mb = kb / 1024;
54
- if (mb < 1024) return `${trimNum(mb)} MB`;
55
- return `${trimNum(mb / 1024)} GB`;
56
- }
57
- function shuffle(input) {
58
- const a = input.slice();
59
- for (let i = a.length - 1; i > 0; i--) {
60
- const j = Math.floor(Math.random() * (i + 1));
61
- [a[i], a[j]] = [a[j], a[i]];
62
- }
63
- return a;
64
- }
65
- var cn = (...classes) => classes.filter(Boolean).join(" ");
66
- var UploadGlyph = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", "aria-hidden": "true", children: [
67
- /* @__PURE__ */ jsx(
68
- "path",
69
- {
70
- d: "M12 15V4m0 0L7.5 8.5M12 4l4.5 4.5",
71
- stroke: "currentColor",
72
- strokeWidth: "1.6",
73
- strokeLinecap: "round",
74
- strokeLinejoin: "round"
75
- }
76
- ),
77
- /* @__PURE__ */ jsx(
78
- "path",
79
- {
80
- d: "M4 14v3.5A2.5 2.5 0 0 0 6.5 20h11a2.5 2.5 0 0 0 2.5-2.5V14",
81
- stroke: "currentColor",
82
- strokeWidth: "1.6",
83
- strokeLinecap: "round"
84
- }
85
- )
86
- ] });
87
- var CloseGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
88
- "path",
89
- {
90
- d: "M6 6l12 12M18 6L6 18",
91
- stroke: "currentColor",
92
- strokeWidth: "1.6",
93
- strokeLinecap: "round"
94
- }
95
- ) });
96
- var TrashGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "20", height: "20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
97
- "path",
98
- {
99
- 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",
100
- stroke: "currentColor",
101
- strokeWidth: "1.5",
102
- strokeLinecap: "round",
103
- strokeLinejoin: "round"
104
- }
105
- ) });
106
- var CheckGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "13", height: "13", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
107
- "path",
108
- {
109
- d: "M4 12.5l5 5 11-12",
110
- stroke: "currentColor",
111
- strokeWidth: "2.2",
112
- strokeLinecap: "round",
113
- strokeLinejoin: "round"
114
- }
115
- ) });
116
- var KebabGlyph = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "currentColor", "aria-hidden": "true", children: [
117
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1.7" }),
118
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.7" }),
119
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "1.7" })
120
- ] });
121
- function FileRow({
122
- file,
123
- word,
124
- onRemove
125
- }) {
126
- const meta = extMeta(file.name);
127
- 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;
128
- const isUploading = file.status === "uploading";
129
- const isError = file.status === "error";
130
- return /* @__PURE__ */ jsxs("div", { className: "royui-upload__row", "data-status": file.status, children: [
131
- /* @__PURE__ */ jsx(
132
- "span",
133
- {
134
- className: "royui-upload__badge",
135
- style: { ["--royui-upload-badge"]: file.icon ? "transparent" : meta.color },
136
- "aria-hidden": "true",
137
- children: file.icon ?? /* @__PURE__ */ jsx("span", { className: "royui-upload__badge-label", children: meta.label })
138
- }
139
- ),
140
- /* @__PURE__ */ jsxs("div", { className: "royui-upload__row-main", children: [
141
- /* @__PURE__ */ jsxs("div", { className: "royui-upload__row-top", children: [
142
- /* @__PURE__ */ jsx("span", { className: "royui-upload__name", title: file.name, children: file.name }),
143
- /* @__PURE__ */ jsx(
144
- "button",
145
- {
146
- type: "button",
147
- className: "royui-upload__row-action",
148
- "aria-label": isUploading ? `Cancel ${file.name}` : `Remove ${file.name}`,
149
- onClick: () => onRemove?.(file.id),
150
- children: isUploading ? /* @__PURE__ */ jsx(CloseGlyph, {}) : /* @__PURE__ */ jsx(TrashGlyph, {})
151
- }
152
- )
153
- ] }),
154
- /* @__PURE__ */ jsxs("div", { className: "royui-upload__meta", children: [
155
- file.status === "complete" && /* @__PURE__ */ jsxs(Fragment, { children: [
156
- /* @__PURE__ */ jsx("span", { children: formatBytes(file.size) }),
157
- /* @__PURE__ */ jsx("span", { className: "royui-upload__meta-sep", children: "/" }),
158
- /* @__PURE__ */ jsxs("span", { className: "royui-upload__complete", children: [
159
- /* @__PURE__ */ jsx(CheckGlyph, {}),
160
- "Complete"
161
- ] })
162
- ] }),
163
- isUploading && /* @__PURE__ */ jsxs(Fragment, { children: [
164
- /* @__PURE__ */ jsxs("span", { children: [
165
- /* @__PURE__ */ jsx(TextMorph, { value: formatBytes(file.uploaded ?? 0) }),
166
- " of",
167
- " ",
168
- formatBytes(file.size)
169
- ] }),
170
- /* @__PURE__ */ jsx("span", { className: "royui-upload__meta-sep", children: "/" }),
171
- /* @__PURE__ */ jsx(
172
- TextMorph,
173
- {
174
- className: "royui-upload__status",
175
- value: word,
176
- renderText: (t) => /* @__PURE__ */ jsx("span", { className: "royui-upload__shimmer", children: t })
177
- }
178
- )
179
- ] }),
180
- isError && /* @__PURE__ */ jsxs(Fragment, { children: [
181
- /* @__PURE__ */ jsx("span", { children: formatBytes(file.size) }),
182
- /* @__PURE__ */ jsx("span", { className: "royui-upload__meta-sep", children: "/" }),
183
- /* @__PURE__ */ jsx("span", { className: "royui-upload__error", children: "Failed" })
184
- ] })
185
- ] }),
186
- isUploading && /* @__PURE__ */ jsxs("div", { className: "royui-upload__progress", children: [
187
- /* @__PURE__ */ jsx(
188
- "div",
189
- {
190
- className: "royui-upload__bar",
191
- role: "progressbar",
192
- "aria-valuenow": pct,
193
- "aria-valuemin": 0,
194
- "aria-valuemax": 100,
195
- children: /* @__PURE__ */ jsx("div", { className: "royui-upload__bar-fill", style: { width: `${pct}%` } })
196
- }
197
- ),
198
- /* @__PURE__ */ jsxs("span", { className: "royui-upload__pct", children: [
199
- pct,
200
- "%"
201
- ] })
202
- ] })
203
- ] })
204
- ] });
205
- }
206
- var UploadFiles = forwardRef(
207
- function UploadFiles2({
208
- files,
209
- title = "Upload files",
210
- maxSizeLabel = "MAX FILE SIZE: 20 MB",
211
- accept,
212
- multiple = true,
213
- theme = "dark",
214
- statusWords = DEFAULT_STATUS_WORDS,
215
- actionLabel,
216
- onFilesSelected,
217
- onRemove,
218
- onRemoveAll,
219
- onClose,
220
- onAction,
221
- className = "",
222
- ...rest
223
- }, ref) {
224
- const inputRef = useRef(null);
225
- const [isDragging, setDragging] = useState(false);
226
- const [tick, setTick] = useState(0);
227
- const anyUploading = files.some((f) => f.status === "uploading");
228
- const words = useMemo(
229
- () => statusWords.length ? shuffle(statusWords) : DEFAULT_STATUS_WORDS,
230
- // eslint-disable-next-line react-hooks/exhaustive-deps
231
- []
232
- );
233
- useEffect(() => {
234
- if (!anyUploading) return;
235
- const id = setInterval(() => setTick((t) => t + 1), 1900);
236
- return () => clearInterval(id);
237
- }, [anyUploading]);
238
- const emit = (list) => {
239
- if (!list || list.length === 0) return;
240
- onFilesSelected?.(Array.from(list));
241
- };
242
- const classes = cn(
243
- "royui-upload",
244
- theme === "dark" && "royui-upload--dark",
245
- theme === "light" && "royui-upload--light",
246
- theme === "auto" && "royui-upload--auto",
247
- className
248
- );
249
- return /* @__PURE__ */ jsxs("div", { ref, className: classes, ...rest, children: [
250
- /* @__PURE__ */ jsxs("header", { className: "royui-upload__header", children: [
251
- /* @__PURE__ */ jsx("h2", { className: "royui-upload__title", children: title }),
252
- onClose && /* @__PURE__ */ jsx(
253
- "button",
254
- {
255
- type: "button",
256
- className: "royui-upload__close",
257
- "aria-label": "Close",
258
- onClick: onClose,
259
- children: /* @__PURE__ */ jsx(CloseGlyph, {})
260
- }
261
- )
262
- ] }),
263
- /* @__PURE__ */ jsxs(
264
- "div",
265
- {
266
- className: cn("royui-upload__dropzone", isDragging && "is-dragging"),
267
- onDragOver: (e) => {
268
- e.preventDefault();
269
- setDragging(true);
270
- },
271
- onDragLeave: (e) => {
272
- e.preventDefault();
273
- setDragging(false);
274
- },
275
- onDrop: (e) => {
276
- e.preventDefault();
277
- setDragging(false);
278
- emit(e.dataTransfer.files);
279
- },
280
- children: [
281
- /* @__PURE__ */ jsx("span", { className: "royui-upload__drop-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(UploadGlyph, {}) }),
282
- /* @__PURE__ */ jsxs("p", { className: "royui-upload__drop-text", children: [
283
- "Drag and drop or",
284
- " ",
285
- /* @__PURE__ */ jsx(
286
- "button",
287
- {
288
- type: "button",
289
- className: "royui-upload__browse",
290
- onClick: () => inputRef.current?.click(),
291
- children: "browse files"
292
- }
293
- )
294
- ] }),
295
- /* @__PURE__ */ jsx("p", { className: "royui-upload__drop-hint", children: maxSizeLabel }),
296
- /* @__PURE__ */ jsx(
297
- "input",
298
- {
299
- ref: inputRef,
300
- type: "file",
301
- accept,
302
- multiple,
303
- className: "royui-upload__input",
304
- onChange: (e) => {
305
- emit(e.target.files);
306
- e.target.value = "";
307
- }
308
- }
309
- )
310
- ]
311
- }
312
- ),
313
- files.length > 0 && /* @__PURE__ */ jsx("div", { className: "royui-upload__list", children: files.map((file, i) => /* @__PURE__ */ jsx(
314
- FileRow,
315
- {
316
- file,
317
- word: words[(tick + i) % words.length],
318
- onRemove
319
- },
320
- file.id
321
- )) }),
322
- files.length > 0 && /* @__PURE__ */ jsxs("footer", { className: "royui-upload__footer", children: [
323
- /* @__PURE__ */ jsx(
324
- "button",
325
- {
326
- type: "button",
327
- className: "royui-upload__icon-btn",
328
- "aria-label": "More options",
329
- children: /* @__PURE__ */ jsx(KebabGlyph, {})
330
- }
331
- ),
332
- /* @__PURE__ */ jsxs(
333
- "button",
334
- {
335
- type: "button",
336
- className: "royui-upload__remove-all",
337
- onClick: onRemoveAll,
338
- children: [
339
- /* @__PURE__ */ jsx(TrashGlyph, {}),
340
- "Remove all"
341
- ]
342
- }
343
- ),
344
- /* @__PURE__ */ jsx("span", { className: "royui-upload__footer-spacer" }),
345
- /* @__PURE__ */ jsx(
346
- Button,
347
- {
348
- size: "sm",
349
- variant: "secondary",
350
- className: "royui-upload__action",
351
- disabled: anyUploading,
352
- onClick: onAction,
353
- children: actionLabel ?? (anyUploading ? /* @__PURE__ */ jsx(TextMorph, { value: "Uploading\u2026" }) : "Done")
354
- }
355
- )
356
- ] })
357
- ] });
358
- }
359
- );
360
- UploadFiles.displayName = "UploadFiles";
361
-
362
- export { UploadFiles };
363
- //# sourceMappingURL=chunk-BM6TW5ZZ.js.map
364
- //# sourceMappingURL=chunk-BM6TW5ZZ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/upload-files/UploadFiles.tsx"],"names":["UploadFiles"],"mappings":"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","file":"chunk-BM6TW5ZZ.js","sourcesContent":["'use client';\n\nimport {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { TextMorph } from '../text-morph/TextMorph';\nimport { Button } from '../button/Button';\nimport './UploadFiles.css';\n\nexport type UploadStatus = 'uploading' | 'complete' | 'error';\n\nexport interface UploadFile {\n /** Stable id — used as the React key and passed back to onRemove. */\n id: string;\n /** File name including extension; drives the type badge. */\n name: string;\n /** Total size in bytes. */\n size: number;\n /** Bytes transferred so far. Drives the \"X OF Y\" label and, when\n * `progress` is omitted, the percentage. */\n uploaded?: number;\n /** Progress 0–100. Falls back to uploaded / size when omitted. */\n progress?: number;\n /** Lifecycle state. */\n status: UploadStatus;\n /** Optional override for the file-type badge. */\n icon?: ReactNode;\n}\n\nexport type UploadTheme = 'auto' | 'light' | 'dark';\n\nexport interface UploadFilesProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** The files to render. The component is controlled — it draws this\n * list and emits events; the consumer owns the upload + progress. */\n files: UploadFile[];\n /** Panel heading. Defaults to \"Upload files\". */\n title?: ReactNode;\n /** Caption under the dropzone. Defaults to \"MAX FILE SIZE: 20 MB\". */\n maxSizeLabel?: string;\n /** Forwarded to the hidden file input's `accept`. */\n accept?: string;\n /** Allow selecting multiple files. Defaults to true. */\n multiple?: boolean;\n /** Color scheme. Dark by default; \"auto\" follows the OS. */\n theme?: UploadTheme;\n /** Words cycled (and morphed) in the per-file status while uploading.\n * Defaults to a long, varied upload vocabulary so the wait stays lively. */\n statusWords?: string[];\n /** Footer action button content. Defaults to a state-derived label\n * (\"Uploading…\" while in flight, \"Done\" otherwise). */\n actionLabel?: ReactNode;\n /** Fired with the dropped / browsed File objects. */\n onFilesSelected?: (files: File[]) => void;\n /** Fired when a single row's trash / cancel control is pressed. */\n onRemove?: (id: string) => void;\n /** Fired by the \"Remove all\" footer control. */\n onRemoveAll?: () => void;\n /** When provided, renders the header close (×) button. */\n onClose?: () => void;\n /** Fired by the footer action button. */\n onAction?: () => void;\n}\n\nconst DEFAULT_STATUS_WORDS = [\n 'Uploading…',\n 'Transferring…',\n 'Beaming bytes…',\n 'Encrypting…',\n 'Securing…',\n 'Packing bits…',\n 'Syncing…',\n 'Crunching data…',\n 'Pushing pixels…',\n 'Almost there…',\n 'Hang tight…',\n 'Wrangling chunks…',\n 'Verifying…',\n 'Finalizing…',\n 'Just a sec…',\n];\n\nconst EXT_META: Record<string, { label: string; color: string }> = {\n pdf: { label: 'PDF', color: '#f0524b' },\n doc: { label: 'DOC', color: '#3b82f6' },\n docx: { label: 'DOCX', color: '#3b82f6' },\n fig: { label: 'FIG', color: '#a259ff' },\n png: { label: 'PNG', color: '#10b981' },\n jpg: { label: 'JPG', color: '#10b981' },\n jpeg: { label: 'JPG', color: '#10b981' },\n gif: { label: 'GIF', color: '#10b981' },\n svg: { label: 'SVG', color: '#f59e0b' },\n zip: { label: 'ZIP', color: '#f59e0b' },\n mp4: { label: 'MP4', color: '#ec4899' },\n csv: { label: 'CSV', color: '#22c55e' },\n json: { label: 'JSON', color: '#eab308' },\n default: { label: 'FILE', color: '#8b8b94' },\n};\n\nfunction extMeta(name: string) {\n const ext = name.split('.').pop()?.toLowerCase() ?? '';\n return EXT_META[ext] ?? EXT_META.default!;\n}\n\nfunction trimNum(n: number): string {\n return (Math.round(n * 10) / 10).toString();\n}\n\n/** Human-readable byte size, e.g. 2.7 MB / 14 MB. */\nfunction formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '0 B';\n if (bytes < 1024) return `${Math.round(bytes)} B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${trimNum(kb)} KB`;\n const mb = kb / 1024;\n if (mb < 1024) return `${trimNum(mb)} MB`;\n return `${trimNum(mb / 1024)} GB`;\n}\n\n/** Deterministic-ish shuffle (Fisher–Yates) so the word order varies per\n * session without two adjacent entries being the same word. */\nfunction shuffle<T>(input: T[]): T[] {\n const a = input.slice();\n for (let i = a.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [a[i], a[j]] = [a[j]!, a[i]!];\n }\n return a;\n}\n\nconst cn = (...classes: (string | false | undefined)[]) =>\n classes.filter(Boolean).join(' ');\n\n/* ── Icons ──────────────────────────────────────────────────────────────── */\n\nconst UploadGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M12 15V4m0 0L7.5 8.5M12 4l4.5 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M4 14v3.5A2.5 2.5 0 0 0 6.5 20h11a2.5 2.5 0 0 0 2.5-2.5V14\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nconst CloseGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nconst TrashGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"none\" aria-hidden=\"true\">\n <path\n 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\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nconst CheckGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"13\" height=\"13\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M4 12.5l5 5 11-12\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nconst KebabGlyph = () => (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"5\" r=\"1.7\" />\n <circle cx=\"12\" cy=\"12\" r=\"1.7\" />\n <circle cx=\"12\" cy=\"19\" r=\"1.7\" />\n </svg>\n);\n\n/* ── File row ───────────────────────────────────────────────────────────── */\n\nfunction FileRow({\n file,\n word,\n onRemove,\n}: {\n file: UploadFile;\n word: string;\n onRemove?: (id: string) => void;\n}) {\n const meta = extMeta(file.name);\n const pct =\n file.progress != null\n ? Math.max(0, Math.min(100, Math.round(file.progress)))\n : file.size > 0\n ? Math.max(0, Math.min(100, Math.round(((file.uploaded ?? 0) / file.size) * 100)))\n : 0;\n\n const isUploading = file.status === 'uploading';\n const isError = file.status === 'error';\n\n return (\n <div className=\"royui-upload__row\" data-status={file.status}>\n <span\n className=\"royui-upload__badge\"\n style={{ ['--royui-upload-badge' as string]: file.icon ? 'transparent' : meta.color }}\n aria-hidden=\"true\"\n >\n {file.icon ?? <span className=\"royui-upload__badge-label\">{meta.label}</span>}\n </span>\n\n <div className=\"royui-upload__row-main\">\n <div className=\"royui-upload__row-top\">\n <span className=\"royui-upload__name\" title={file.name}>\n {file.name}\n </span>\n <button\n type=\"button\"\n className=\"royui-upload__row-action\"\n aria-label={isUploading ? `Cancel ${file.name}` : `Remove ${file.name}`}\n onClick={() => onRemove?.(file.id)}\n >\n {isUploading ? <CloseGlyph /> : <TrashGlyph />}\n </button>\n </div>\n\n <div className=\"royui-upload__meta\">\n {file.status === 'complete' && (\n <>\n <span>{formatBytes(file.size)}</span>\n <span className=\"royui-upload__meta-sep\">/</span>\n <span className=\"royui-upload__complete\">\n <CheckGlyph />\n Complete\n </span>\n </>\n )}\n {isUploading && (\n <>\n <span>\n <TextMorph value={formatBytes(file.uploaded ?? 0)} /> of{' '}\n {formatBytes(file.size)}\n </span>\n <span className=\"royui-upload__meta-sep\">/</span>\n <TextMorph\n className=\"royui-upload__status\"\n value={word}\n renderText={(t) => (\n <span className=\"royui-upload__shimmer\">{t}</span>\n )}\n />\n </>\n )}\n {isError && (\n <>\n <span>{formatBytes(file.size)}</span>\n <span className=\"royui-upload__meta-sep\">/</span>\n <span className=\"royui-upload__error\">Failed</span>\n </>\n )}\n </div>\n\n {isUploading && (\n <div className=\"royui-upload__progress\">\n <div\n className=\"royui-upload__bar\"\n role=\"progressbar\"\n aria-valuenow={pct}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div className=\"royui-upload__bar-fill\" style={{ width: `${pct}%` }} />\n </div>\n <span className=\"royui-upload__pct\">{pct}%</span>\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Component ──────────────────────────────────────────────────────────── */\n\nexport const UploadFiles = forwardRef<HTMLDivElement, UploadFilesProps>(\n function UploadFiles(\n {\n files,\n title = 'Upload files',\n maxSizeLabel = 'MAX FILE SIZE: 20 MB',\n accept,\n multiple = true,\n theme = 'dark',\n statusWords = DEFAULT_STATUS_WORDS,\n actionLabel,\n onFilesSelected,\n onRemove,\n onRemoveAll,\n onClose,\n onAction,\n className = '',\n ...rest\n },\n ref,\n ) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setDragging] = useState(false);\n const [tick, setTick] = useState(0);\n\n const anyUploading = files.some((f) => f.status === 'uploading');\n\n // Shuffle once per mount so the word order varies between sessions.\n const words = useMemo(\n () => (statusWords.length ? shuffle(statusWords) : DEFAULT_STATUS_WORDS),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n // Advance the shared cycle only while something is in flight.\n useEffect(() => {\n if (!anyUploading) return;\n const id = setInterval(() => setTick((t) => t + 1), 1900);\n return () => clearInterval(id);\n }, [anyUploading]);\n\n const emit = (list: FileList | null) => {\n if (!list || list.length === 0) return;\n onFilesSelected?.(Array.from(list));\n };\n\n const classes = cn(\n 'royui-upload',\n theme === 'dark' && 'royui-upload--dark',\n theme === 'light' && 'royui-upload--light',\n theme === 'auto' && 'royui-upload--auto',\n className,\n );\n\n return (\n <div ref={ref} className={classes} {...rest}>\n <header className=\"royui-upload__header\">\n <h2 className=\"royui-upload__title\">{title}</h2>\n {onClose && (\n <button\n type=\"button\"\n className=\"royui-upload__close\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n <CloseGlyph />\n </button>\n )}\n </header>\n\n <div\n className={cn('royui-upload__dropzone', isDragging && 'is-dragging')}\n onDragOver={(e) => {\n e.preventDefault();\n setDragging(true);\n }}\n onDragLeave={(e) => {\n e.preventDefault();\n setDragging(false);\n }}\n onDrop={(e) => {\n e.preventDefault();\n setDragging(false);\n emit(e.dataTransfer.files);\n }}\n >\n <span className=\"royui-upload__drop-icon\" aria-hidden=\"true\">\n <UploadGlyph />\n </span>\n <p className=\"royui-upload__drop-text\">\n Drag and drop or{' '}\n <button\n type=\"button\"\n className=\"royui-upload__browse\"\n onClick={() => inputRef.current?.click()}\n >\n browse files\n </button>\n </p>\n <p className=\"royui-upload__drop-hint\">{maxSizeLabel}</p>\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n className=\"royui-upload__input\"\n onChange={(e) => {\n emit(e.target.files);\n e.target.value = '';\n }}\n />\n </div>\n\n {files.length > 0 && (\n <div className=\"royui-upload__list\">\n {files.map((file, i) => (\n <FileRow\n key={file.id}\n file={file}\n word={words[(tick + i) % words.length]!}\n onRemove={onRemove}\n />\n ))}\n </div>\n )}\n\n {files.length > 0 && (\n <footer className=\"royui-upload__footer\">\n <button\n type=\"button\"\n className=\"royui-upload__icon-btn\"\n aria-label=\"More options\"\n >\n <KebabGlyph />\n </button>\n <button\n type=\"button\"\n className=\"royui-upload__remove-all\"\n onClick={onRemoveAll}\n >\n <TrashGlyph />\n Remove all\n </button>\n <span className=\"royui-upload__footer-spacer\" />\n <Button\n size=\"sm\"\n variant=\"secondary\"\n className=\"royui-upload__action\"\n disabled={anyUploading}\n onClick={onAction}\n >\n {actionLabel ??\n (anyUploading ? (\n <TextMorph value=\"Uploading…\" />\n ) : (\n 'Done'\n ))}\n </Button>\n </footer>\n )}\n </div>\n );\n },\n);\n\nUploadFiles.displayName = 'UploadFiles';\n"]}