uploaderkit 1.0.0 → 2.0.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/LICENSE +21 -0
- package/NOTICE +16 -0
- package/README.es.md +1140 -0
- package/README.md +1135 -0
- package/dist/FileViewer-ChTf7-uY.d.cts +49 -0
- package/dist/FileViewer-nuD-GEdJ.d.ts +49 -0
- package/dist/adapters/gcs.cjs +83 -0
- package/dist/adapters/gcs.cjs.map +1 -0
- package/dist/adapters/gcs.d.cts +31 -0
- package/dist/adapters/gcs.d.ts +31 -0
- package/dist/adapters/gcs.js +81 -0
- package/dist/adapters/gcs.js.map +1 -0
- package/dist/adapters/memory.cjs +27 -0
- package/dist/adapters/memory.cjs.map +1 -0
- package/dist/adapters/memory.d.cts +18 -0
- package/dist/adapters/memory.d.ts +18 -0
- package/dist/adapters/memory.js +25 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/s3.cjs +75 -0
- package/dist/adapters/s3.cjs.map +1 -0
- package/dist/adapters/s3.d.cts +27 -0
- package/dist/adapters/s3.d.ts +27 -0
- package/dist/adapters/s3.js +73 -0
- package/dist/adapters/s3.js.map +1 -0
- package/dist/chunk-3FI44IOW.js +150 -0
- package/dist/chunk-3FI44IOW.js.map +1 -0
- package/dist/chunk-H7BRW5IY.js +308 -0
- package/dist/chunk-H7BRW5IY.js.map +1 -0
- package/dist/chunk-PDKAF4GX.js +707 -0
- package/dist/chunk-PDKAF4GX.js.map +1 -0
- package/dist/chunk-PTEX7F4R.js +309 -0
- package/dist/chunk-PTEX7F4R.js.map +1 -0
- package/dist/chunk-T5YZG6JW.js +511 -0
- package/dist/chunk-T5YZG6JW.js.map +1 -0
- package/dist/index.cjs +220 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -170
- package/dist/index.d.ts +57 -170
- package/dist/index.js +1 -324
- package/dist/index.js.map +1 -1
- package/dist/presets.cjs +1665 -0
- package/dist/presets.cjs.map +1 -0
- package/dist/presets.d.cts +100 -0
- package/dist/presets.d.ts +100 -0
- package/dist/presets.js +405 -0
- package/dist/presets.js.map +1 -0
- package/dist/react.cjs +981 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +106 -0
- package/dist/react.d.ts +106 -0
- package/dist/react.js +5 -0
- package/dist/react.js.map +1 -0
- package/dist/server/express.cjs +179 -0
- package/dist/server/express.cjs.map +1 -0
- package/dist/server/express.d.cts +64 -0
- package/dist/server/express.d.ts +64 -0
- package/dist/server/express.js +111 -0
- package/dist/server/express.js.map +1 -0
- package/dist/server/next.cjs +165 -0
- package/dist/server/next.cjs.map +1 -0
- package/dist/server/next.d.cts +38 -0
- package/dist/server/next.d.ts +38 -0
- package/dist/server/next.js +107 -0
- package/dist/server/next.js.map +1 -0
- package/dist/server.cjs +550 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +19 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.js +80 -0
- package/dist/server.js.map +1 -0
- package/dist/storage-CYkSHWZX.d.cts +133 -0
- package/dist/storage-Qc9epG0G.d.ts +133 -0
- package/dist/types-BSlJJwti.d.cts +341 -0
- package/dist/types-BSlJJwti.d.ts +341 -0
- package/dist/ui.cjs +2325 -0
- package/dist/ui.cjs.map +1 -0
- package/dist/ui.d.cts +331 -0
- package/dist/ui.d.ts +331 -0
- package/dist/ui.js +749 -0
- package/dist/ui.js.map +1 -0
- package/dist/useSlottedUploader-BzT5jV8c.d.cts +139 -0
- package/dist/useSlottedUploader-IkG5RhEO.d.ts +139 -0
- package/dist/useUploader-BiBdS-7y.d.cts +117 -0
- package/dist/useUploader-CQHpj_oI.d.ts +117 -0
- package/package.json +189 -3
- package/tailwind.css +80 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/labels.ts","../src/react/UploaderProvider.tsx","../src/constants.ts","../src/file.ts","../src/validation.ts","../src/scopes.ts","../src/warn.ts","../src/react/compressImage.ts","../src/react/useUploader.ts","../src/ui/cn.ts","../src/presets/AvatarUploader.tsx","../src/presets/DropAnywhereOverlay.tsx","../src/ui/Kbd.tsx","../src/ui/useCoarsePointer.ts","../src/ui/useShortcut.ts","../src/ui/Dropzone.tsx","../src/ui/icons.tsx","../src/ui/overlayStack.ts","../src/ui/scrollLock.ts","../src/ui/useFocusTrap.ts","../src/ui/useOverlayTransition.ts","../src/ui/FileViewer.tsx","../src/presets/GalleryUploader.tsx","../src/presets/useDropAnywhere.ts"],"names":["createContext","useContext","useMemo","useState","useRef","useCallback","useEffect","jsxs","jsx","createPortal","active","Fragment"],"mappings":"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","file":"presets.cjs","sourcesContent":["/**\n * Every user-facing string the package renders, so no copy is hardcoded\n * inside a component and apps translate or reword without forking.\n *\n * English is the default so the kit ships globalized; `ES_LABELS` ships for\n * Spanish apps, selected once through `UploaderProvider language='es'`. Hooks\n * take `labels` in their options, components as a prop — always a `Partial`,\n * merged over the provider's base.\n */\nexport type UploaderLabels = {\n\t/** Prompt inside the single dropzone of `Uploader` (fine pointers). */\n\tdropPrompt: string\n\t/** Same zone on a touch device, where dragging barely exists. */\n\ttapPrompt: string\n\t/** Prompt inside the bulk dropzone of `SlottedUploader` (fine pointers). */\n\tbulkDropPrompt: string\n\t/** Same bulk zone on a touch device. */\n\tbulkTapPrompt: string\n\t/** Button that fires the batch when `uploadOn` is `'manual'`. */\n\tuploadAll: string\n\t/** Row action: preview a file. */\n\tview: string\n\t/** Row action: forget a file. */\n\tremove: string\n\t/** Row action: abort an in-flight upload. */\n\tcancel: string\n\t/** Suffix on a row the server confirmed. */\n\tready: string\n\t/**\n\t * Suffix on a row holding a picked file that has NOT been sent yet.\n\t * Distinct from {@link UploaderLabels.ready}, which means the server\n\t * confirmed it — two states, two strings.\n\t */\n\tstaged: string\n\t/** Slot action when the position is empty. */\n\tupload: string\n\t/** Slot action when the position is filled. */\n\treplace: string\n\t/** Pill shown while a file hovers over a filled slot row. */\n\tdropToReplace: string\n\t/** Viewer: aria-label of the previous-image arrow. */\n\tprevious: string\n\t/** Viewer: aria-label of the next-image arrow. */\n\tnext: string\n\t/** Fallback when a strategy rejects without a message. */\n\tuploadFailed: string\n\t/** The request never reached the server — offline, DNS, CORS preflight. */\n\tuploadNetworkFailed: string\n\t/** Message when the DELETE transport refused or failed. */\n\tremoveFailed: string\n\t/** A stored file could not be fetched for preview or for bytes. */\n\treadFailed: string\n\t/** A batch past `maxFiles`. Receives the cap. */\n\tmaxFilesReached: (max: number) => string\n\t/** A file picked for a slot whose extension the slot rejects. */\n\tslotFormatNotAllowed: (slotLabel: string, extensions: string[]) => string\n\t/** A bulk-dropped file no slot matched. */\n\tfileWithoutSlot: (fileName: string) => string\n\t/** Viewer: while the URL resolves. */\n\tviewerLoading: string\n\t/** Viewer: the URL could not be resolved (expired signature, network). */\n\tviewerError: string\n\t/** Second line of the error panel — what the reader can do about it. */\n\tviewerErrorHint: string\n\t/** Viewer: button that retries the resolution. */\n\tviewerRetry: string\n\t/** Viewer: open the file in a browser tab. */\n\topenInTab: string\n\t/** Header action; the long `download` names a file, this labels a button. */\n\tdownloadShort: string\n\t/** Viewer: close button. */\n\tclose: string\n\t/** Viewer: formats without an inline preview. */\n\tnoPreview: string\n\t/** Viewer: download button. Receives the file name. */\n\tdownload: (fileName: string) => string\n\t/** Viewer: fallback title when the file carries no name. */\n\tfilePreview: string\n\t/** Confirm dialog: affirmative button. */\n\tconfirm: string\n\t/** Confirm dialog heading before forgetting a file. */\n\tconfirmRemoveTitle: string\n\t/** Confirm dialog body before forgetting. Receives the file name. */\n\tconfirmRemoveMessage: (fileName: string) => string\n\t/** Confirm dialog heading before replacing a slot's file. */\n\tconfirmReplaceTitle: string\n\t/** Confirm dialog body before replacing. Receives current and incoming names. */\n\tconfirmReplaceMessage: (current: string, incoming: string) => string\n\t/** `DropAnywhereOverlay` heading while a drag is over the window. */\n\tdropAnywhereTitle: string\n\t/** `DropAnywhereOverlay` second line. */\n\tdropAnywhereHint: string\n\t/** `AvatarUploader`: hover label and aria-label of the picture. */\n\tavatarChange: string\n\t/** `AvatarUploader`: overlay while a file hovers the picture. */\n\tavatarDropHere: string\n\t/** `AvatarUploader`: the remove link under the picture. */\n\tavatarRemove: string\n\t/** `GalleryUploader`: caption of the add tile. */\n\tgalleryAdd: string\n\n\t// Validation — `validateFile` and everything that calls it. These run on\n\t// BOTH sides: the browser shows them, the server answers them as JSON.\n\t/** A name the extension check cannot read at all. */\n\tfileHasNoExtension: string\n\t/** The extension is not on the scope's list. Receives that list. */\n\tformatNotAllowed: (extensions: string[]) => string\n\t/** Zero bytes — a failed drag, a cancelled save. */\n\tfileIsEmpty: string\n\t/** Over the scope ceiling. Receives both sizes already formatted. */\n\tfileTooLarge: (size: string, max: string) => string\n\t/** Fewer bytes than the signature needs: a truncated transfer. */\n\tfileIncomplete: string\n\t/** The leading bytes contradict the extension — renamed, or corrupt. */\n\tcontentDoesNotMatchExtension: string\n\n\t// Server — the HTTP surface. `createStorage` and both framework adapters\n\t// resolve the same object, so one `labels` wires the whole round trip.\n\t/** 400: a route parameter or body field the handler needs is missing. */\n\trequestIncomplete: string\n\t/** 401: `getUser` answered null. */\n\tunauthorized: string\n\t/** 400: an upload arrived with no file part. */\n\tfileRequired: string\n\t/** 404: the URL named a scope the registry does not declare. */\n\tunknownScope: string\n\t/** 500: the catch-all when a handler throws something unrecognized. */\n\tprocessingFailed: string\n\t/** Download name for a key that ends in nothing usable. */\n\tunnamedFile: string\n}\n\n/** Spanish copy — select it once: `<UploaderProvider language='es'>`. */\nexport const ES_LABELS: UploaderLabels = {\n\tdropPrompt: 'Selecciona un archivo o arrástralo aquí',\n\ttapPrompt: 'Toca para elegir un archivo',\n\tbulkDropPrompt: 'Arrastra varios archivos — cada uno cae en su documento',\n\tbulkTapPrompt: 'Toca para agregar varios archivos',\n\tuploadAll: 'Subir archivos',\n\tview: 'Ver',\n\tremove: 'Quitar',\n\tcancel: 'Cancelar',\n\tready: 'Listo',\n\tstaged: 'Listo para subir',\n\tupload: 'Subir',\n\treplace: 'Reemplazar',\n\tdropToReplace: 'Suelta para reemplazar',\n\tprevious: 'Anterior',\n\tnext: 'Siguiente',\n\tuploadFailed: 'No se pudo subir el archivo',\n\tuploadNetworkFailed: 'No se pudo subir el archivo. Revisa tu conexión',\n\tremoveFailed: 'No se pudo borrar el archivo del almacenamiento',\n\treadFailed: 'No se pudo cargar el archivo',\n\tmaxFilesReached: max => `Máximo ${max} archivo(s)`,\n\tslotFormatNotAllowed: (slotLabel, extensions) =>\n\t\t`${slotLabel}: formato no permitido. Se aceptan: ${extensions.join(', ')}`,\n\tfileWithoutSlot: fileName =>\n\t\t`\"${fileName}\" no corresponde a ningún documento`,\n\tviewerLoading: 'Cargando…',\n\tviewerError: 'No se pudo cargar la vista previa',\n\tviewerErrorHint:\n\t\t'El archivo puede haberse movido o el enlace expiró. Puedes reintentar o descargarlo.',\n\tviewerRetry: 'Reintentar',\n\topenInTab: 'Abrir en pestaña',\n\tdownloadShort: 'Descargar',\n\tclose: 'Cerrar',\n\tnoPreview: 'Este formato no tiene vista previa',\n\tdownload: fileName => `Descargar ${fileName}`,\n\tfilePreview: 'Archivo',\n\tconfirm: 'Confirmar',\n\tconfirmRemoveTitle: 'Quitar archivo',\n\tconfirmRemoveMessage: fileName =>\n\t\t`¿Quitar \"${fileName}\"? Podrás subir otro después.`,\n\tconfirmReplaceTitle: 'Reemplazar archivo',\n\tconfirmReplaceMessage: (current, incoming) =>\n\t\t`¿Reemplazar \"${current}\" por \"${incoming}\"?`,\n\tdropAnywhereTitle: 'Suelta los archivos aquí',\n\tdropAnywhereHint: 'Cualquier lugar de la pantalla cuenta',\n\tavatarChange: 'Cambiar foto',\n\tavatarDropHere: 'Suelta aquí',\n\tavatarRemove: 'Quitar foto',\n\tgalleryAdd: 'Agregar',\n\n\tfileHasNoExtension: 'El archivo no tiene extensión',\n\tformatNotAllowed: extensions =>\n\t\t`Formato no permitido. Se aceptan: ${extensions.join(', ')}`,\n\tfileIsEmpty: 'El archivo está vacío',\n\tfileTooLarge: (size, max) => `El archivo pesa ${size} y el máximo es ${max}`,\n\tfileIncomplete: 'El archivo está incompleto',\n\tcontentDoesNotMatchExtension:\n\t\t'El contenido del archivo no corresponde a su extensión',\n\n\trequestIncomplete: 'Solicitud incompleta',\n\tunauthorized: 'No autorizado',\n\tfileRequired: 'Archivo requerido',\n\tunknownScope: 'Destino de archivo no válido',\n\tprocessingFailed: 'No se pudo procesar el archivo',\n\tunnamedFile: 'archivo',\n}\n\n/** English copy — the package default, so the kit ships globalized. */\nexport const DEFAULT_LABELS: UploaderLabels = {\n\tdropPrompt: 'Choose a file or drag it here',\n\ttapPrompt: 'Tap to choose a file',\n\tbulkDropPrompt: 'Drop several files — each lands on its document',\n\tbulkTapPrompt: 'Tap to add several files',\n\tuploadAll: 'Upload files',\n\tview: 'View',\n\tremove: 'Remove',\n\tcancel: 'Cancel',\n\tready: 'Done',\n\tstaged: 'Ready to upload',\n\tupload: 'Upload',\n\treplace: 'Replace',\n\tdropToReplace: 'Drop to replace',\n\tprevious: 'Previous',\n\tnext: 'Next',\n\tuploadFailed: 'The file could not be uploaded',\n\tuploadNetworkFailed: 'The file could not be uploaded. Check your connection',\n\tremoveFailed: 'The file could not be removed from storage',\n\treadFailed: 'The file could not be loaded',\n\tmaxFilesReached: max => `At most ${max} file(s)`,\n\tslotFormatNotAllowed: (slotLabel, extensions) =>\n\t\t`${slotLabel}: format not allowed. Accepted: ${extensions.join(', ')}`,\n\tfileWithoutSlot: fileName => `\"${fileName}\" does not match any document`,\n\tviewerLoading: 'Loading…',\n\tviewerError: 'The preview could not be loaded',\n\tviewerErrorHint:\n\t\t'The file may have moved or the link expired. You can retry or download it.',\n\tviewerRetry: 'Retry',\n\topenInTab: 'Open in tab',\n\tdownloadShort: 'Download',\n\tclose: 'Close',\n\tnoPreview: 'This format has no preview',\n\tdownload: fileName => `Download ${fileName}`,\n\tfilePreview: 'File',\n\tconfirm: 'Confirm',\n\tconfirmRemoveTitle: 'Remove file',\n\tconfirmRemoveMessage: fileName =>\n\t\t`Remove \"${fileName}\"? You can upload another one later.`,\n\tconfirmReplaceTitle: 'Replace file',\n\tconfirmReplaceMessage: (current, incoming) =>\n\t\t`Replace \"${current}\" with \"${incoming}\"?`,\n\tdropAnywhereTitle: 'Drop the files here',\n\tdropAnywhereHint: 'Anywhere on the screen counts',\n\tavatarChange: 'Change photo',\n\tavatarDropHere: 'Drop here',\n\tavatarRemove: 'Remove photo',\n\tgalleryAdd: 'Add',\n\n\tfileHasNoExtension: 'The file has no extension',\n\tformatNotAllowed: extensions =>\n\t\t`Format not allowed. Accepted: ${extensions.join(', ')}`,\n\tfileIsEmpty: 'The file is empty',\n\tfileTooLarge: (size, max) =>\n\t\t`The file weighs ${size} and the maximum is ${max}`,\n\tfileIncomplete: 'The file is incomplete',\n\tcontentDoesNotMatchExtension: 'The file contents do not match its extension',\n\n\trequestIncomplete: 'Incomplete request',\n\tunauthorized: 'Unauthorized',\n\tfileRequired: 'A file is required',\n\tunknownScope: 'Unknown file destination',\n\tprocessingFailed: 'The file could not be processed',\n\tunnamedFile: 'file',\n}\n\n/** The merge every entry point runs: partial overrides over the default. */\nexport const resolveLabels = (\n\tlabels?: Partial<UploaderLabels>,\n\tbase: UploaderLabels = DEFAULT_LABELS\n): UploaderLabels => (labels ? { ...base, ...labels } : base)\n\n/**\n * @deprecated English IS {@link DEFAULT_LABELS} now. A shallow copy, kept so\n * 1.x consumers passing it keep working.\n */\nexport const EN_LABELS: UploaderLabels = { ...DEFAULT_LABELS }\n","import { createContext, type ReactNode, useContext, useMemo } from 'react'\n\nimport {\n\tDEFAULT_LABELS,\n\tES_LABELS,\n\tresolveLabels,\n\ttype UploaderLabels,\n} from '../labels'\n\nconst LabelsContext = createContext<UploaderLabels>(DEFAULT_LABELS)\n\n/** The two built-in copy sets. */\nexport type UploaderLanguage = 'en' | 'es'\n\nexport type UploaderProviderProps = {\n\tchildren: ReactNode\n\t/**\n\t * Which built-in copy set every uploader under it speaks. English is the\n\t * default so the kit ships globalized; a Spanish app opts in ONCE here\n\t * instead of passing `labels` to each component.\n\t * @defaultValue 'en'\n\t */\n\tlanguage?: UploaderLanguage\n\t/** Per-key overrides on top of the selected language. */\n\tlabels?: Partial<UploaderLabels>\n}\n\n/**\n * Optional app-root provider carrying the copy. Components work without it\n * (they fall back to {@link DEFAULT_LABELS}), and a per-component `labels`\n * prop still wins for one-off rewording.\n */\nexport const UploaderProvider = ({\n\tchildren,\n\tlanguage = 'en',\n\tlabels,\n}: UploaderProviderProps) => {\n\tconst value = useMemo(\n\t\t() => resolveLabels(labels, language === 'es' ? ES_LABELS : DEFAULT_LABELS),\n\t\t[language, labels]\n\t)\n\n\treturn (\n\t\t<LabelsContext.Provider value={value}>{children}</LabelsContext.Provider>\n\t)\n}\n\n/**\n * The active copy, merged: provider base ← per-call `overrides`. What every\n * component and hook in the package reads instead of `resolveLabels` directly,\n * so a single provider re-words all of them at once.\n */\nexport const useUploaderLabels = (\n\toverrides?: Partial<UploaderLabels>\n): UploaderLabels => {\n\tconst base = useContext(LabelsContext)\n\treturn useMemo(\n\t\t() => (overrides ? { ...base, ...overrides } : base),\n\t\t[base, overrides]\n\t)\n}\n","import type { FileCategory, FileCategoryConfig, FileExtension } from './types'\n\nexport const KB = 1024\nexport const MB = 1024 * KB\nexport const GB = 1024 * MB\n\n/**\n * Leading bytes that identify a format regardless of its extension. The check\n * that uses them is the only defence against an executable renamed to `.pdf`,\n * since both the extension and the browser-reported MIME come from the client.\n */\nexport const MAGIC_NUMBERS: Partial<Record<FileExtension, number[]>> = {\n\tpng: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],\n\tjpg: [0xff, 0xd8, 0xff],\n\tjpeg: [0xff, 0xd8, 0xff],\n\tgif: [0x47, 0x49, 0x46, 0x38],\n\twebp: [0x52, 0x49, 0x46, 0x46], // RIFF; bytes 8-11 spell WEBP\n\tico: [0x00, 0x00, 0x01, 0x00],\n\n\tpdf: [0x25, 0x50, 0x44, 0x46], // %PDF\n\n\t// OOXML files are ZIP containers, so docx/xlsx share the PK signature.\n\tdocx: [0x50, 0x4b, 0x03, 0x04],\n\txlsx: [0x50, 0x4b, 0x03, 0x04],\n\tdoc: [0xd0, 0xcf, 0x11, 0xe0],\n\txls: [0xd0, 0xcf, 0x11, 0xe0],\n\n\t// DER/ASN.1 sequence header.\n\tcer: [0x30, 0x82],\n\tcrt: [0x30, 0x82],\n\tkey: [0x30, 0x82],\n\tpem: [0x2d, 0x2d, 0x2d, 0x2d, 0x2d], // -----\n\n\twebm: [0x1a, 0x45, 0xdf, 0xa3],\n\tavi: [0x52, 0x49, 0x46, 0x46],\n\tmp3: [0x49, 0x44, 0x33], // ID3\n\twav: [0x52, 0x49, 0x46, 0x46],\n\togg: [0x4f, 0x67, 0x67, 0x53],\n\taac: [0xff, 0xf1],\n}\n\nexport const MIME_TYPES: Record<FileExtension, string> = {\n\tpng: 'image/png',\n\tjpg: 'image/jpeg',\n\tjpeg: 'image/jpeg',\n\tsvg: 'image/svg+xml',\n\twebp: 'image/webp',\n\tgif: 'image/gif',\n\tico: 'image/x-icon',\n\theic: 'image/heic',\n\n\tcer: 'application/x-x509-ca-cert',\n\tcrt: 'application/x-x509-ca-cert',\n\tpem: 'application/x-pem-file',\n\tkey: 'application/x-pem-file',\n\n\tpdf: 'application/pdf',\n\tdoc: 'application/msword',\n\tdocx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n\txls: 'application/vnd.ms-excel',\n\txlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n\tcsv: 'text/csv',\n\ttxt: 'text/plain',\n\n\txml: 'application/xml',\n\tjson: 'application/json',\n\n\tmp4: 'video/mp4',\n\tmov: 'video/quicktime',\n\tavi: 'video/x-msvideo',\n\twebm: 'video/webm',\n\n\tmp3: 'audio/mpeg',\n\twav: 'audio/wav',\n\togg: 'audio/ogg',\n\taac: 'audio/aac',\n}\n\n/**\n * Defaults per category. A scope always narrows these; it can never widen the\n * extension list, which is what keeps `any` from leaking into a strict scope.\n */\nexport const FILE_CATEGORY_CONFIG: Record<FileCategory, FileCategoryConfig> = {\n\timage: {\n\t\textensions: ['png', 'jpg', 'jpeg', 'svg', 'webp', 'gif'],\n\t\tmaxBytes: 5 * MB,\n\t\tvalidateMagicNumbers: true,\n\t\tlabel: 'image',\n\t\taccept: 'image/*',\n\t},\n\tcertificate: {\n\t\textensions: ['cer', 'crt', 'pem'],\n\t\tmaxBytes: 50 * KB,\n\t\tvalidateMagicNumbers: true,\n\t\tlabel: 'certificate',\n\t\taccept: '.cer,.crt,.pem',\n\t},\n\tkey: {\n\t\textensions: ['key'],\n\t\tmaxBytes: 50 * KB,\n\t\tvalidateMagicNumbers: true,\n\t\tlabel: 'private key',\n\t\taccept: '.key',\n\t},\n\tpdf: {\n\t\textensions: ['pdf'],\n\t\tmaxBytes: 20 * MB,\n\t\tvalidateMagicNumbers: true,\n\t\tlabel: 'PDF',\n\t\taccept: '.pdf',\n\t},\n\tdocument: {\n\t\textensions: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'csv', 'txt'],\n\t\tmaxBytes: 20 * MB,\n\t\tvalidateMagicNumbers: false,\n\t\tlabel: 'document',\n\t\taccept: '.pdf,.doc,.docx,.xls,.xlsx,.csv,.txt',\n\t},\n\tdata: {\n\t\textensions: ['xml', 'json'],\n\t\tmaxBytes: 5 * MB,\n\t\tvalidateMagicNumbers: false,\n\t\tlabel: 'data file',\n\t\taccept: '.xml,.json',\n\t},\n\tvideo: {\n\t\textensions: ['mp4', 'mov', 'avi', 'webm'],\n\t\tmaxBytes: 100 * MB,\n\t\tvalidateMagicNumbers: false,\n\t\tlabel: 'video',\n\t\taccept: 'video/*',\n\t},\n\taudio: {\n\t\textensions: ['mp3', 'wav', 'ogg', 'aac'],\n\t\tmaxBytes: 20 * MB,\n\t\tvalidateMagicNumbers: false,\n\t\tlabel: 'audio',\n\t\taccept: 'audio/*',\n\t},\n\tany: {\n\t\textensions: [],\n\t\tmaxBytes: 20 * MB,\n\t\tvalidateMagicNumbers: false,\n\t\tlabel: 'file',\n\t\taccept: '*/*',\n\t},\n}\n","import { MIME_TYPES } from './constants'\nimport type { FileExtension, FileLike } from './types'\n\n/** Lower-case extension without the dot, or `''` when the name has none. */\nexport const getFileExtension = (fileName: string): string => {\n\tconst dot = fileName.lastIndexOf('.')\n\tif (dot < 1 || dot === fileName.length - 1) return ''\n\treturn fileName.slice(dot + 1).toLowerCase()\n}\n\nexport const getMimeType = (fileName: string): string => {\n\tconst ext = getFileExtension(fileName) as FileExtension\n\treturn MIME_TYPES[ext] ?? 'application/octet-stream'\n}\n\nexport const isKnownExtension = (value: string): value is FileExtension =>\n\tvalue in MIME_TYPES\n\nexport const formatFileSize = (bytes: number): string => {\n\tif (bytes < 1024) return `${bytes} B`\n\tconst units = ['KB', 'MB', 'GB', 'TB']\n\tlet size = bytes / 1024\n\tlet unit = 0\n\twhile (size >= 1024 && unit < units.length - 1) {\n\t\tsize /= 1024\n\t\tunit++\n\t}\n\treturn `${size.toFixed(size >= 10 ? 0 : 1)} ${units[unit]}`\n}\n\n/** Longest stem kept. Object stores cap the whole key and the prefix spends part of it. */\nconst MAX_STEM_LENGTH = 80\n\n/** What an all-punctuation name degrades to, so a key never ends in a bare dot. */\nconst FALLBACK_STEM = 'file'\n\nconst slugSegment = (value: string): string =>\n\tvalue\n\t\t.normalize('NFD')\n\t\t.replace(/[\\u0300-\\u036f]/g, '')\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, '-')\n\t\t.replace(/^-+|-+$/g, '')\n\n/**\n * Turns a user's file name into a safe key segment: ASCII, lower case, one\n * extension, no path syntax.\n *\n * Call it INSIDE your scope's `path()`, not around it:\n *\n * ```ts\n * path: (id, file) => `Docs/${id}/${sanitizeFileName(file.name)}`\n * ```\n *\n * `resolveKey` deliberately does not apply it for you. It would rewrite the key\n * your `path()` returned, and a client computing the same key to decide replace\n * mode would then disagree with the server. Inside `path()` both sides run the\n * one function and cannot drift.\n *\n * This exists because a macOS screenshot took an API down. `Screenshot\n * 2026-08-31 at 4.18.54 p.m..png` ends in `p.m.` + `.png`, so the raw name\n * carries `..`; the traversal guard rejected the key and the consumer dropped\n * the rejection, killing the process.\n *\n * Only the KEY is slugged — keep the original in `StoredFile.fileName`, which\n * is what a UI should render.\n */\nexport const sanitizeFileName = (fileName: string): string => {\n\t// A name arriving as a path is already an attempt, deliberate or not.\n\tconst base = fileName.split(/[/\\\\]/).pop() ?? ''\n\n\tconst dot = base.lastIndexOf('.')\n\t// A leading dot is a dotfile, not an extension: `.env` has no stem.\n\tconst hasExtension = dot > 0\n\tconst stem = slugSegment(hasExtension ? base.slice(0, dot) : base).slice(\n\t\t0,\n\t\tMAX_STEM_LENGTH\n\t)\n\tconst extension = hasExtension ? slugSegment(base.slice(dot + 1)) : ''\n\n\t// A trailing `-` can reappear when the length cut lands mid-separator.\n\tconst safeStem = stem.replace(/-+$/, '') || FALLBACK_STEM\n\n\treturn extension ? `${safeStem}.${extension}` : safeStem\n}\n\n/** Value for an `<input accept=\"…\">` built from an extension list. */\nexport const toAcceptAttribute = (extensions: FileExtension[]): string =>\n\textensions.length === 0\n\t\t? '*/*'\n\t\t: extensions.map(extension => `.${extension}`).join(',')\n\n/**\n * Adapts a multer memory-storage file to `FileLike` so server code validates\n * with the very same function the browser ran.\n */\nexport const fromMulterFile = (file: {\n\toriginalname: string\n\tsize: number\n\tmimetype: string\n\tbuffer: Uint8Array\n}): FileLike => ({\n\tname: file.originalname,\n\tsize: file.size,\n\ttype: file.mimetype,\n\tarrayBuffer: async () =>\n\t\tfile.buffer.buffer.slice(\n\t\t\tfile.buffer.byteOffset,\n\t\t\tfile.buffer.byteOffset + file.buffer.byteLength\n\t\t) as ArrayBuffer,\n})\n","import { MAGIC_NUMBERS } from './constants'\nimport { formatFileSize, getFileExtension, isKnownExtension } from './file'\nimport { resolveLabels, type UploaderLabels } from './labels'\nimport type {\n\tFileExtension,\n\tFileLike,\n\tValidationOptions,\n\tValidationResult,\n} from './types'\n\nconst ok: ValidationResult = { valid: true }\n\nconst fail = (\n\tcode: Exclude<ValidationResult, { valid: true }>['code'],\n\tmessage: string\n): ValidationResult => ({ valid: false, code, message })\n\nexport const validateExtension = (\n\tfileName: string,\n\tallowed: FileExtension[],\n\tlabels?: Partial<UploaderLabels>\n): ValidationResult => {\n\tif (allowed.length === 0) return ok\n\n\tconst copy = resolveLabels(labels)\n\tconst extension = getFileExtension(fileName)\n\tif (!extension) {\n\t\treturn fail('extension-not-allowed', copy.fileHasNoExtension)\n\t}\n\tif (!allowed.includes(extension as FileExtension)) {\n\t\treturn fail('extension-not-allowed', copy.formatNotAllowed(allowed))\n\t}\n\treturn ok\n}\n\nexport const validateSize = (\n\tsize: number,\n\tmaxBytes: number,\n\tlabels?: Partial<UploaderLabels>\n): ValidationResult => {\n\tconst copy = resolveLabels(labels)\n\tif (size === 0) return fail('empty-file', copy.fileIsEmpty)\n\tif (size > maxBytes) {\n\t\treturn fail(\n\t\t\t'too-large',\n\t\t\tcopy.fileTooLarge(formatFileSize(size), formatFileSize(maxBytes))\n\t\t)\n\t}\n\treturn ok\n}\n\n/**\n * Compares the file's leading bytes against the signature its extension\n * claims. Extensions without a known signature pass — absence of a signature\n * is not evidence of tampering.\n */\nexport const validateMagicNumbers = async (\n\tfile: FileLike,\n\tlabels?: Partial<UploaderLabels>\n): Promise<ValidationResult> => {\n\tconst copy = resolveLabels(labels)\n\tconst extension = getFileExtension(file.name)\n\tif (!isKnownExtension(extension)) return ok\n\n\tconst expected = MAGIC_NUMBERS[extension]\n\tif (!expected) return ok\n\n\tconst head = new Uint8Array(await file.arrayBuffer()).slice(\n\t\t0,\n\t\texpected.length\n\t)\n\tif (head.length < expected.length) {\n\t\treturn fail('magic-number-mismatch', copy.fileIncomplete)\n\t}\n\n\tconst matches = expected.every((byte, index) => head[index] === byte)\n\treturn matches\n\t\t? ok\n\t\t: fail('magic-number-mismatch', copy.contentDoesNotMatchExtension)\n}\n\n/**\n * Runs the checks cheapest-first so a 2 GB file is rejected on its size before\n * anything reads its bytes.\n */\nexport const validateFile = async (\n\tfile: FileLike,\n\toptions: ValidationOptions = {}\n): Promise<ValidationResult> => {\n\tconst {\n\t\tmaxBytes = Infinity,\n\t\tallowedExtensions = [],\n\t\tvalidateMagicNumbers: checkMagic = false,\n\t\tlabels,\n\t\tcustomValidation,\n\t} = options\n\n\tconst size = validateSize(file.size, maxBytes, labels)\n\tif (!size.valid) return size\n\n\tconst extension = validateExtension(file.name, allowedExtensions, labels)\n\tif (!extension.valid) return extension\n\n\tif (checkMagic) {\n\t\tconst magic = await validateMagicNumbers(file, labels)\n\t\tif (!magic.valid) return magic\n\t}\n\n\tif (customValidation) return customValidation(file)\n\n\treturn ok\n}\n\nexport type FileValidation = {\n\tfile: FileLike\n\tresult: ValidationResult\n}\n\n/** Validates every file and reports each result; never short-circuits. */\nexport const validateFiles = async (\n\tfiles: FileLike[],\n\toptions: ValidationOptions = {}\n): Promise<FileValidation[]> =>\n\tPromise.all(\n\t\tfiles.map(async file => ({\n\t\t\tfile,\n\t\t\tresult: await validateFile(file, options),\n\t\t}))\n\t)\n","import { FILE_CATEGORY_CONFIG } from './constants'\nimport { toAcceptAttribute } from './file'\nimport type { UploaderLabels } from './labels'\nimport type {\n\tFileLike,\n\tReplaceMode,\n\tScopeConfig,\n\tScopeRegistry,\n\tStorageProvider,\n\tValidationResult,\n} from './types'\nimport { validateFile } from './validation'\n\n/** Thrown for a definition or wiring mistake — never for a user's bad file. */\nexport class ScopeError extends Error {\n\toverride name = 'ScopeError'\n}\n\n/** Stand-in entity used to compare the SHAPE of two `path` callbacks. */\nconst PROBE_ENTITY = '__entity__'\n\nconst probeFile = (name: string): FileLike => ({\n\tname,\n\tsize: 0,\n\ttype: '',\n\tarrayBuffer: async () => new ArrayBuffer(0),\n})\n\n/** True when `path` returns the same key whatever the file is called. */\nexport const hasStableKey = (scope: ScopeConfig): boolean =>\n\tscope.path(PROBE_ENTITY, probeFile('a.png')) ===\n\tscope.path(PROBE_ENTITY, probeFile('b.png'))\n\n/**\n * The mode a scope runs in when it does not name one.\n *\n * @see AGENTS.md §3 — why a stable key needs no sweep and a name-carrying one does\n */\nexport const resolveReplaceMode = (scope: ScopeConfig): ReplaceMode => {\n\tif (scope.replace !== undefined) return scope.replace\n\tif ((scope.maxFiles ?? 1) > 1) return 'key'\n\treturn hasStableKey(scope) ? 'key' : 'entity'\n}\n\nconst dirname = (key: string) => {\n\tconst cut = key.lastIndexOf('/')\n\treturn cut === -1 ? '' : key.slice(0, cut)\n}\n\n/** Folder an `'entity'` replace is allowed to sweep. */\nexport const resolveScopePrefix = (\n\tscope: ScopeConfig,\n\tentityId: string\n): string =>\n\tscope.prefix?.(entityId) ??\n\tdirname(scope.path(entityId, probeFile('probe.bin')))\n\n/** `a` contains `b`, counting only whole path segments. */\nconst containsPath = (a: string, b: string) => b === a || b.startsWith(`${a}/`)\n\nconst assertDefinition = (name: string, scope: ScopeConfig): void => {\n\tif (typeof scope.path !== 'function') {\n\t\tthrow new ScopeError(`Scope \"${name}\": \"path\" must be a function`)\n\t}\n\tif (!Number.isFinite(scope.maxBytes) || scope.maxBytes <= 0) {\n\t\tthrow new ScopeError(\n\t\t\t`Scope \"${name}\": \"maxBytes\" must be a positive number`\n\t\t)\n\t}\n\tif (scope.accept.length === 0) {\n\t\tthrow new ScopeError(\n\t\t\t`Scope \"${name}\": \"accept\" cannot be empty — list the extensions this scope takes`\n\t\t)\n\t}\n\n\t// A scope narrows its category, never widens it. Otherwise a 'pdf' scope\n\t// could quietly start taking executables.\n\tif (scope.category && scope.category !== 'any') {\n\t\tconst allowed = FILE_CATEGORY_CONFIG[scope.category].extensions\n\t\tconst outside = scope.accept.filter(\n\t\t\textension => !allowed.includes(extension)\n\t\t)\n\t\tif (outside.length > 0) {\n\t\t\tthrow new ScopeError(\n\t\t\t\t`Scope \"${name}\": ${outside.join(', ')} not allowed by category \"${scope.category}\"`\n\t\t\t)\n\t\t}\n\t}\n\n\tif (scope.compress) {\n\t\tconst imageOnly = FILE_CATEGORY_CONFIG.image.extensions\n\t\tconst notImages = scope.accept.filter(\n\t\t\textension => !imageOnly.includes(extension)\n\t\t)\n\t\tif (notImages.length > 0) {\n\t\t\tthrow new ScopeError(\n\t\t\t\t`Scope \"${name}\": \"compress\" only applies to images, but it accepts ${notImages.join(', ')}`\n\t\t\t)\n\t\t}\n\t}\n\n\tif (scope.maxFiles !== undefined) {\n\t\tif (!Number.isInteger(scope.maxFiles) || scope.maxFiles < 1) {\n\t\t\tthrow new ScopeError(\n\t\t\t\t`Scope \"${name}\": \"maxFiles\" must be a positive integer, received ${String(scope.maxFiles)}`\n\t\t\t)\n\t\t}\n\t}\n\n\t// The contradiction the derived default exists to prevent: a scope that\n\t// holds a collection cannot also erase the collection on every upload.\n\tif (scope.replace === 'entity' && (scope.maxFiles ?? 1) > 1) {\n\t\tthrow new ScopeError(\n\t\t\t`Scope \"${name}\": replace \"entity\" contradicts maxFiles ${scope.maxFiles} — ` +\n\t\t\t\t'an entity-wide replace would delete the other files on the next upload. ' +\n\t\t\t\t\"Use 'key' to overwrite one slot, or false to keep every version.\"\n\t\t)\n\t}\n\n\tif (\n\t\tresolveReplaceMode(scope) === 'entity' &&\n\t\tresolveScopePrefix(scope, PROBE_ENTITY) === ''\n\t) {\n\t\tthrow new ScopeError(\n\t\t\t`Scope \"${name}\": replace \"entity\" needs a folder to sweep, but \"path\" resolves to a ` +\n\t\t\t\t'bucket-root key. Nest the key under a folder, or declare \"prefix\".'\n\t\t)\n\t}\n}\n\n/**\n * Rejects a registry where sweeping one scope would reach another's objects.\n *\n * `path` shapes are compared through a placeholder entity, so this catches the\n * real hazard — two scopes sharing a folder for the SAME entity — while two\n * scopes rooted at different entity folders stay independent. A false positive\n * is answered with an explicit `prefix`, and the message says so.\n */\nconst assertNoSweepCollision = (scopes: Record<string, ScopeConfig>): void => {\n\tconst entries = Object.entries(scopes)\n\n\tfor (const [name, scope] of entries) {\n\t\tif (resolveReplaceMode(scope) !== 'entity') continue\n\t\tconst prefix = resolveScopePrefix(scope, PROBE_ENTITY)\n\n\t\tfor (const [otherName, other] of entries) {\n\t\t\tif (otherName === name) continue\n\t\t\tconst otherKey = other.path(PROBE_ENTITY, probeFile('probe.bin'))\n\t\t\tif (!containsPath(prefix, otherKey)) continue\n\n\t\t\tthrow new ScopeError(\n\t\t\t\t`Scope \"${name}\" replaces per entity and would sweep \"${prefix}\", which also holds ` +\n\t\t\t\t\t`scope \"${otherName}\" — an upload to one would delete the other's files. ` +\n\t\t\t\t\t'Give each its own folder, or declare a narrower \"prefix\".'\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Declares every destination an app can write to. The returned registry is\n * imported by the client (to configure inputs and pre-validate) and by the\n * server (to authorize and re-validate), which is what keeps the two in sync.\n *\n * Definitions are checked eagerly: a malformed scope throws at import time,\n * not on the first upload. That includes the two replace mistakes no runtime\n * check could recover from — an entity-wide replace on a collection, and two\n * scopes whose folders overlap, where an avatar upload would delete the same\n * user's documents.\n */\nexport const defineScopes = <T extends Record<string, ScopeConfig>>(\n\tscopes: T\n): ScopeRegistry<T> => {\n\tfor (const [name, scope] of Object.entries(scopes)) {\n\t\tassertDefinition(name, scope)\n\t}\n\tassertNoSweepCollision(scopes)\n\n\tconst names = Object.keys(scopes) as (keyof T & string)[]\n\n\tconst get = (name: string): ScopeConfig => {\n\t\tconst scope = scopes[name as keyof T]\n\t\tif (!scope) {\n\t\t\tthrow new ScopeError(\n\t\t\t\t`Unknown scope \"${name}\". Declared: ${names.join(', ')}`\n\t\t\t)\n\t\t}\n\t\treturn scope\n\t}\n\n\treturn {\n\t\tscopes,\n\t\tnames,\n\t\tget,\n\t\thas: name => name in scopes,\n\t\taccept: name => toAcceptAttribute(get(name).accept),\n\t}\n}\n\n/**\n * The one validation call. Client runs it for feedback, server runs it for\n * safety, both against the same scope.\n *\n * `labels` is what keeps the two answers identical in wording as well as in\n * verdict: the hook passes the copy it renders with, `createStorage` passes\n * the copy it was configured with.\n */\nexport const validateForScope = async <T extends Record<string, ScopeConfig>>(\n\tregistry: ScopeRegistry<T>,\n\tname: string,\n\tfile: FileLike,\n\tlabels?: Partial<UploaderLabels>\n): Promise<ValidationResult> => {\n\tconst scope = registry.get(name)\n\tconst category = scope.category\n\t\t? FILE_CATEGORY_CONFIG[scope.category]\n\t\t: undefined\n\n\treturn validateFile(file, {\n\t\tmaxBytes: scope.maxBytes,\n\t\tallowedExtensions: scope.accept,\n\t\tvalidateMagicNumbers: category?.validateMagicNumbers ?? true,\n\t\tlabels,\n\t})\n}\n\n/**\n * Fails fast when a provider cannot honour what the scopes promise — a private\n * scope on a provider that cannot sign URLs is a runtime 403 waiting to happen.\n */\nexport const assertProviderSupports = <T extends Record<string, ScopeConfig>>(\n\tregistry: ScopeRegistry<T>,\n\tprovider: StorageProvider\n): void => {\n\tconst needsSigning = registry.names.filter(\n\t\tname => registry.get(name).visibility === 'private'\n\t)\n\n\tif (needsSigning.length > 0 && !provider.capabilities.signedUrl) {\n\t\tthrow new ScopeError(\n\t\t\t`Provider \"${provider.name}\" cannot sign URLs, but these scopes are private: ${needsSigning.join(', ')}`\n\t\t)\n\t}\n}\n\n/**\n * Whether a key would escape its own prefix.\n *\n * Judged per SEGMENT. A `key.includes('..')` test reads as the same check and\n * is not: `report..pdf` and `Screenshot at 4.18.54 p.m..png` carry two dots\n * without ever being traversal, and a macOS screenshot is the common case, not\n * a corner one. Traversal needs a segment that IS `..`, so that is what this\n * asks.\n */\nconst escapesPrefix = (key: string): boolean =>\n\tkey.startsWith('/') ||\n\tkey.split('/').some(segment => segment === '..' || segment === '.')\n\n/**\n * Resolves the storage key for an upload.\n *\n * The guard is a backstop, not a sanitizer: it refuses a key rather than\n * rewriting one, because a client computing the same key to decide replace\n * mode would then disagree with the server. Run {@link sanitizeFileName}\n * inside the scope's `path()` and both sides stay identical.\n */\nexport const resolveKey = <T extends Record<string, ScopeConfig>>(\n\tregistry: ScopeRegistry<T>,\n\tname: string,\n\tentityId: string,\n\tfile: FileLike\n): string => {\n\tconst key = registry.get(name).path(entityId, file)\n\tif (escapesPrefix(key)) {\n\t\tthrow new ScopeError(`Scope \"${name}\" produced an unsafe key: ${key}`)\n\t}\n\treturn key\n}\n","const seen = new Set<string>()\n\n/**\n * Dev-only warning, once per `key` — for paths that run per render or per\n * file, where the same misconfiguration would otherwise print hundreds of\n * times. Same contract as listkit's `warnDev`.\n *\n * @see AGENTS.md §3.1 — this tier vs the `ScopeError` throw\n */\nexport const warnDev = (key: string, message: string): void => {\n\tif (process.env.NODE_ENV === 'production') return\n\tif (seen.has(key)) return\n\tseen.add(key)\n\tconsole.warn(`[uploaderkit] ${message}`)\n}\n","import type { CompressOptions } from '../types'\n// Formats a canvas can re-encode. GIF would lose animation and SVG would\n// rasterize, so both pass through untouched.\nconst COMPRESSIBLE = new Set(['image/jpeg', 'image/png', 'image/webp'])\n\n/**\n * Client-side image trim before upload: downscale to the scope's box and\n * re-encode at the scope's quality. Re-encoding through a canvas drops EXIF as\n * a side effect — GPS and camera metadata never leave the device, regardless\n * of `stripExif` (a canvas cannot keep it).\n *\n * Falls back to the original file whenever it cannot help: non-compressible\n * formats, environments without `createImageBitmap`, decode failures, or a\n * \"compressed\" result that came out larger.\n */\nexport const compressImage = async (\n\tfile: File,\n\t{ maxWidth, maxHeight, quality = 0.8 }: CompressOptions\n): Promise<File> => {\n\tif (!COMPRESSIBLE.has(file.type)) return file\n\tif (typeof createImageBitmap !== 'function') return file\n\n\ttry {\n\t\tconst bitmap = await createImageBitmap(file)\n\t\tconst scale = Math.min(\n\t\t\t1,\n\t\t\t(maxWidth ?? Infinity) / bitmap.width,\n\t\t\t(maxHeight ?? Infinity) / bitmap.height\n\t\t)\n\n\t\tconst canvas = document.createElement('canvas')\n\t\tcanvas.width = Math.max(1, Math.round(bitmap.width * scale))\n\t\tcanvas.height = Math.max(1, Math.round(bitmap.height * scale))\n\t\tconst context = canvas.getContext('2d')\n\t\tif (!context) return file\n\t\tcontext.drawImage(bitmap, 0, 0, canvas.width, canvas.height)\n\t\tbitmap.close()\n\n\t\tconst blob = await new Promise<Blob | null>(resolve =>\n\t\t\tcanvas.toBlob(resolve, file.type, quality)\n\t\t)\n\t\tif (!blob || blob.size >= file.size) return file\n\n\t\treturn new File([blob], file.name, { type: file.type })\n\t} catch {\n\t\treturn file\n\t}\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { UploaderLabels } from '../labels'\nimport { validateForScope } from '../scopes'\nimport type { ScopeConfig, ScopeRegistry } from '../types'\nimport type { StoredFile } from '../types'\nimport { warnDev } from '../warn'\nimport { compressImage } from './compressImage'\nimport type { UploaderFile, UploadStrategy } from './types'\nimport { useUploaderLabels } from './UploaderProvider'\n\n/**\n * When the machine sends: `'manual'` holds files in `idle` until the app calls\n * `upload()` — the form-submit flow, where the file travels together with the\n * rest of the fields' action. `'select'` fires as soon as a valid file lands.\n */\nexport type UploadTrigger = 'select' | 'manual'\n\nexport type RetryOptions = {\n\t/** Total attempts per file, the first one included. @defaultValue 1 */\n\tattempts?: number\n\t/** Delay before the first retry; doubles on each further one. @defaultValue 500 */\n\tbackoffMs?: number\n}\n\nexport type UseUploaderOptions<T extends Record<string, ScopeConfig>> = {\n\t/** The app's registry — the same object the server authorizes against. */\n\tscopes: ScopeRegistry<T>\n\tscope: keyof T & string\n\t/** Owner of the uploads (customerId, userId, …), forwarded to the strategy. */\n\tentityId: string\n\t/** Transport. Omit for local-only selection + validation (no `upload`). */\n\tstrategy?: UploadStrategy\n\t/**\n\t * Overrides the arity derived from the scope's `maxFiles`. Rarely needed:\n\t * the registry is what the server validates against.\n\t */\n\tmultiple?: boolean\n\t/** Overrides the scope's own `maxFiles`, downward. */\n\tmaxFiles?: number\n\t/** @defaultValue 'manual' — the styled `Uploader` flips it to `'select'`. */\n\tuploadOn?: UploadTrigger\n\t/**\n\t * Fired when a batch actually starts travelling — from either trigger — with\n\t * the files it carries. The place to flip a form into its \"sending\" state.\n\t */\n\tonUploadStart?: (files: UploaderFile[]) => void\n\t/** Fired once per batch with the files the server confirmed. */\n\tonUploaded?: (stored: StoredFile[]) => void\n\tonError?: (message: string) => void\n\t/**\n\t * Re-run a failed strategy call before surfacing the error. A number is\n\t * shorthand for `{ attempts }`. Aborts never retry, and validation failures\n\t * never reach the strategy in the first place.\n\t */\n\tretry?: number | RetryOptions\n\t/** Max uploads in flight per batch; the rest queue. @defaultValue Infinity */\n\tconcurrency?: number\n\t/**\n\t * Rename each file before it enters the machine — a client-side input, a\n\t * folio, a slug. Runs before validation, so a rename that changes the\n\t * extension is rejected like any other invalid file. The stored key comes\n\t * from the scope's `path(entityId, file)`, which reads this name.\n\t */\n\trename?: (file: File) => string\n\tlabels?: Partial<UploaderLabels>\n}\n\nexport type UseUploaderReturn = {\n\tfiles: UploaderFile[]\n\t/** Ready-made value for `<input accept>`, derived from the scope. */\n\taccept: string\n\tisUploading: boolean\n\t/** `true` while any file waits in `idle` — a manual trigger has work to do. */\n\thasPending: boolean\n\taddFiles: (incoming: FileList | File[]) => Promise<void>\n\t/** Uploads every file still in `idle`. Resolves with the confirmed ones. */\n\tupload: () => Promise<StoredFile[]>\n\t/** Abort one in-flight upload, or all of them when no id is given. */\n\tabort: (id?: string) => void\n\tremoveFile: (id: string) => void\n\tclear: () => void\n}\n\nconst createId = () =>\n\ttypeof crypto !== 'undefined' && 'randomUUID' in crypto\n\t\t? crypto.randomUUID()\n\t\t: Math.random().toString(36).slice(2)\n\nconst previewOf = (file: File): string | undefined =>\n\tfile.type.startsWith('image/') &&\n\ttypeof URL !== 'undefined' &&\n\ttypeof URL.createObjectURL === 'function'\n\t\t? URL.createObjectURL(file)\n\t\t: undefined\n\nconst revokePreview = (file: UploaderFile) => {\n\tif (file.preview) URL.revokeObjectURL(file.preview)\n}\n\nconst normalizeRetry = (retry: number | RetryOptions | undefined) => {\n\tconst options =\n\t\ttypeof retry === 'number' ? { attempts: retry } : (retry ?? {})\n\treturn {\n\t\tattempts: Math.max(1, options.attempts ?? 1),\n\t\tbackoffMs: options.backoffMs ?? 500,\n\t}\n}\n\n/** Abortable sleep: the backoff between retries must die with the upload. */\nconst wait = (ms: number, signal: AbortSignal) =>\n\tnew Promise<void>((resolve, reject) => {\n\t\tconst abort = () => {\n\t\t\tclearTimeout(timer)\n\t\t\tconst error = new Error('Upload cancelled')\n\t\t\terror.name = 'AbortError'\n\t\t\treject(error)\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal.removeEventListener('abort', abort)\n\t\t\tresolve()\n\t\t}, ms)\n\t\tsignal.addEventListener('abort', abort, { once: true })\n\t})\n\n/**\n * Run `run` over every item with at most `limit` in flight. Order of results\n * matches the input; a settled slot immediately frees a worker for the next.\n */\nconst runPool = async <T, R>(\n\titems: T[],\n\tlimit: number,\n\trun: (item: T) => Promise<R>\n): Promise<R[]> => {\n\tconst results = new Array<R>(items.length)\n\tlet cursor = 0\n\tconst workers = Array.from(\n\t\t{ length: Math.min(Math.max(1, limit), items.length) },\n\t\tasync () => {\n\t\t\twhile (cursor < items.length) {\n\t\t\t\tconst index = cursor++\n\t\t\t\tresults[index] = await run(items[index]!)\n\t\t\t}\n\t\t}\n\t)\n\tawait Promise.all(workers)\n\treturn results\n}\n\n/**\n * Headless upload state machine: selection → validation → (compression) →\n * upload with progress and abort. Owns no markup — render `files` however the\n * screen needs and wire `addFiles` to an input or a drop zone.\n *\n * Validation runs here with the same `validateForScope` the server runs, so\n * the user sees the rejection before any byte leaves the machine.\n */\nexport const useUploader = <T extends Record<string, ScopeConfig>>({\n\tscopes,\n\tscope,\n\tentityId,\n\tstrategy,\n\tmultiple: multipleOption,\n\tmaxFiles: maxFilesOption,\n\tuploadOn = 'manual',\n\tonUploadStart,\n\tonUploaded,\n\tonError,\n\tretry,\n\tconcurrency = Infinity,\n\trename,\n\tlabels,\n}: UseUploaderOptions<T>): UseUploaderReturn => {\n\t// Derived from the registry, never from the call site — see AGENTS.md §3.\n\t// The props stay as a narrowing override.\n\tconst scopeMaxFiles = scopes.get(scope).maxFiles\n\tconst maxFiles = maxFilesOption ?? scopeMaxFiles\n\tconst multiple = multipleOption ?? (maxFiles !== undefined && maxFiles > 1)\n\n\tconst [files, setFiles] = useState<UploaderFile[]>([])\n\tconst controllers = useRef(new Map<string, AbortController>())\n\t// Kept in a ref so `addFiles` → auto-upload reads the batch it just built,\n\t// not the state snapshot from before the setFiles commit.\n\tconst filesRef = useRef<UploaderFile[]>([])\n\tfilesRef.current = files\n\tconst copy = useUploaderLabels(labels)\n\tconst { attempts, backoffMs } = normalizeRetry(retry)\n\n\tconst patch = useCallback((id: string, changes: Partial<UploaderFile>) => {\n\t\tsetFiles(previous =>\n\t\t\tprevious.map(file => (file.id === id ? { ...file, ...changes } : file))\n\t\t)\n\t}, [])\n\n\tconst uploadOne = useCallback(\n\t\tasync (target: UploaderFile): Promise<StoredFile | null> => {\n\t\t\tif (!strategy) {\n\t\t\t\twarnDev(\n\t\t\t\t\t'upload-without-strategy',\n\t\t\t\t\t'upload() ran without a `strategy` — files stay local. Pass `strategy` (e.g. createXhrUploadStrategy) to useUploader.'\n\t\t\t\t)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst config = scopes.get(scope)\n\n\t\t\tconst controller = new AbortController()\n\t\t\tcontrollers.current.set(target.id, controller)\n\t\t\tpatch(target.id, { status: 'uploading', progress: 0 })\n\n\t\t\ttry {\n\t\t\t\tconst payload = config.compress\n\t\t\t\t\t? await compressImage(target.file, config.compress)\n\t\t\t\t\t: target.file\n\n\t\t\t\t// Compression runs once; only the transport retries.\n\t\t\t\tfor (let attempt = 1; ; attempt++) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst stored = await strategy(payload, scope, entityId, {\n\t\t\t\t\t\t\tonProgress: percent => patch(target.id, { progress: percent }),\n\t\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t\t})\n\t\t\t\t\t\tpatch(target.id, { status: 'success', progress: 100, stored })\n\t\t\t\t\t\treturn stored\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst aborted =\n\t\t\t\t\t\t\terror instanceof Error && error.name === 'AbortError'\n\t\t\t\t\t\tif (aborted || attempt >= attempts) throw error\n\t\t\t\t\t\tpatch(target.id, { progress: 0 })\n\t\t\t\t\t\tawait wait(backoffMs * 2 ** (attempt - 1), controller.signal)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst aborted = error instanceof Error && error.name === 'AbortError'\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error && error.message\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: copy.uploadFailed\n\t\t\t\tpatch(target.id, {\n\t\t\t\t\tstatus: aborted ? 'idle' : 'error',\n\t\t\t\t\tprogress: 0,\n\t\t\t\t\t...(aborted ? {} : { error: message }),\n\t\t\t\t})\n\t\t\t\tif (!aborted) onError?.(message)\n\t\t\t\treturn null\n\t\t\t} finally {\n\t\t\t\tcontrollers.current.delete(target.id)\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tstrategy,\n\t\t\tscopes,\n\t\t\tscope,\n\t\t\tentityId,\n\t\t\tpatch,\n\t\t\tonError,\n\t\t\tattempts,\n\t\t\tbackoffMs,\n\t\t\tcopy,\n\t\t]\n\t)\n\n\tconst uploadBatch = useCallback(\n\t\tasync (targets: UploaderFile[]): Promise<StoredFile[]> => {\n\t\t\tif (targets.length === 0) return []\n\t\t\tonUploadStart?.(targets)\n\t\t\tconst results = await runPool(targets, concurrency, uploadOne)\n\t\t\tconst stored = results.filter((r): r is StoredFile => r !== null)\n\t\t\tif (stored.length > 0) onUploaded?.(stored)\n\t\t\treturn stored\n\t\t},\n\t\t[uploadOne, onUploadStart, onUploaded, concurrency]\n\t)\n\n\tconst addFiles = useCallback(\n\t\tasync (incoming: FileList | File[]) => {\n\t\t\tlet batch = Array.from(incoming)\n\t\t\tif (!multiple && batch.length > 1) {\n\t\t\t\twarnDev(\n\t\t\t\t\t'single-mode-multi-drop',\n\t\t\t\t\t`addFiles received ${batch.length} files but \\`multiple\\` is false — only the first is kept. Pass multiple: true if that is not what you meant.`\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (!multiple) batch = batch.slice(0, 1)\n\n\t\t\tif (maxFiles !== undefined) {\n\t\t\t\tconst room = maxFiles - (multiple ? filesRef.current.length : 0)\n\t\t\t\tif (batch.length > room) {\n\t\t\t\t\tbatch = batch.slice(0, Math.max(0, room))\n\t\t\t\t\tonError?.(copy.maxFilesReached(maxFiles))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (batch.length === 0) return\n\n\t\t\tif (rename) {\n\t\t\t\tbatch = batch.map(\n\t\t\t\t\tfile => new File([file], rename(file), { type: file.type })\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst next: UploaderFile[] = []\n\t\t\tfor (const file of batch) {\n\t\t\t\tconst result = await validateForScope(scopes, scope, file, copy)\n\t\t\t\tnext.push({\n\t\t\t\t\tid: createId(),\n\t\t\t\t\tfile,\n\t\t\t\t\tstatus: result.valid ? 'idle' : 'error',\n\t\t\t\t\tprogress: 0,\n\t\t\t\t\t...(result.valid\n\t\t\t\t\t\t? { preview: previewOf(file) }\n\t\t\t\t\t\t: { error: result.message }),\n\t\t\t\t})\n\t\t\t\tif (!result.valid) onError?.(next[next.length - 1]!.error!)\n\t\t\t}\n\n\t\t\tsetFiles(previous => {\n\t\t\t\tif (multiple) return [...previous, ...next]\n\t\t\t\tprevious.forEach(revokePreview)\n\t\t\t\treturn next\n\t\t\t})\n\n\t\t\tif (uploadOn === 'select') {\n\t\t\t\tawait uploadBatch(next.filter(file => file.status === 'idle'))\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tmultiple,\n\t\t\tmaxFiles,\n\t\t\tscopes,\n\t\t\tscope,\n\t\t\tuploadOn,\n\t\t\tuploadBatch,\n\t\t\tonError,\n\t\t\trename,\n\t\t\tcopy,\n\t\t]\n\t)\n\n\tconst upload = useCallback(\n\t\t() => uploadBatch(filesRef.current.filter(f => f.status === 'idle')),\n\t\t[uploadBatch]\n\t)\n\n\tconst abort = useCallback((id?: string) => {\n\t\tif (id) {\n\t\t\tcontrollers.current.get(id)?.abort()\n\t\t\treturn\n\t\t}\n\t\tcontrollers.current.forEach(controller => controller.abort())\n\t}, [])\n\n\tconst removeFile = useCallback(\n\t\t(id: string) => {\n\t\t\tabort(id)\n\t\t\tsetFiles(previous => {\n\t\t\t\tconst target = previous.find(file => file.id === id)\n\t\t\t\tif (target) revokePreview(target)\n\t\t\t\treturn previous.filter(file => file.id !== id)\n\t\t\t})\n\t\t},\n\t\t[abort]\n\t)\n\n\tconst clear = useCallback(() => {\n\t\tabort()\n\t\tsetFiles(previous => {\n\t\t\tprevious.forEach(revokePreview)\n\t\t\treturn []\n\t\t})\n\t}, [abort])\n\n\t// Object URLs leak until revoked; the unmount sweep catches whatever the\n\t// screen never removed explicitly.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tfilesRef.current.forEach(revokePreview)\n\t\t\tcontrollers.current.forEach(controller => controller.abort())\n\t\t},\n\t\t[]\n\t)\n\n\tconst accept = useMemo(() => scopes.accept(scope), [scopes, scope])\n\n\treturn {\n\t\tfiles,\n\t\taccept,\n\t\tisUploading: files.some(file => file.status === 'uploading'),\n\t\thasPending: files.some(file => file.status === 'idle'),\n\t\taddFiles,\n\t\tupload,\n\t\tabort,\n\t\tremoveFile,\n\t\tclear,\n\t}\n}\n","/** Minimal class joiner — the package has no runtime deps to spend on clsx. */\nexport const cn = (...values: (string | false | null | undefined)[]): string =>\n\tvalues.filter(Boolean).join(' ')\n","import { type DragEvent, type ReactNode, useRef, useState } from 'react'\n\nimport type { UploaderLabels } from '../labels'\nimport { useUploaderLabels } from '../react/UploaderProvider'\nimport { useUploader, type UseUploaderOptions } from '../react/useUploader'\nimport type { ScopeConfig, StoredFile } from '../types'\nimport { cn } from '../ui/cn'\n\nexport type AvatarUploaderProps<\n\tT extends Record<string, ScopeConfig> = Record<string, ScopeConfig>,\n> = Pick<\n\tUseUploaderOptions<T>,\n\t'scopes' | 'scope' | 'entityId' | 'strategy' | 'rename'\n> & {\n\t/** The stored image, if any. */\n\tsrc?: string | null\n\t/** What shows without an image — initials, an icon. */\n\tfallback?: ReactNode\n\t/** Diameter in px. @defaultValue 96 */\n\tsize?: number\n\tonUploaded: (stored: StoredFile) => void\n\t/** Offered as a link under the circle when there is an image to remove. */\n\tonRemove?: () => void\n\tonError?: (message: string) => void\n\talt?: string\n\tdisabled?: boolean\n\tlabels?: Partial<UploaderLabels>\n\tclassName?: string\n}\n\n/**\n * A picture that is its own control: click it, pick a file, watch the ring\n * close around it; or drop an image straight onto it. Uploads on select — a\n * progress ring with nothing travelling behind it would be theatre — so the\n * caller decides when the returned `StoredFile` becomes the entity's image.\n */\nexport const AvatarUploader = <T extends Record<string, ScopeConfig>>({\n\tscopes,\n\tscope,\n\tentityId,\n\tstrategy,\n\trename,\n\tsrc,\n\tfallback,\n\tsize = 96,\n\tonUploaded,\n\tonRemove,\n\tonError,\n\talt = '',\n\tdisabled = false,\n\tlabels,\n\tclassName,\n}: AvatarUploaderProps<T>) => {\n\tconst copy = useUploaderLabels(labels)\n\tconst input = useRef<HTMLInputElement>(null)\n\tconst [dropping, setDropping] = useState(false)\n\t// Depth counter, never a boolean — see AGENTS.md §6.\n\tconst depth = useRef(0)\n\n\tconst uploader = useUploader<T>({\n\t\tscopes,\n\t\tscope,\n\t\tentityId,\n\t\tstrategy,\n\t\tuploadOn: 'select',\n\t\tmaxFiles: 1,\n\t\t...(rename ? { rename } : {}),\n\t\tonUploaded: stored => {\n\t\t\tif (stored[0]) onUploaded(stored[0])\n\t\t},\n\t\tonError,\n\t\tlabels,\n\t})\n\n\tconst current = uploader.files[0]\n\tconst uploading = current?.status === 'uploading'\n\tconst failed = current?.status === 'error' ? current.error : undefined\n\tconst shown = current?.preview ?? src ?? null\n\tconst locked = disabled || uploading\n\n\tconst onDrop = (event: DragEvent) => {\n\t\tevent.preventDefault()\n\t\tdepth.current = 0\n\t\tsetDropping(false)\n\t\tif (locked) return\n\t\tconst file = event.dataTransfer.files[0]\n\t\tif (file) void uploader.addFiles([file])\n\t}\n\n\treturn (\n\t\t<div className={cn('inline-flex flex-col items-center gap-2', className)}>\n\t\t\t<div className='relative' style={{ width: size, height: size }}>\n\t\t\t\t<button\n\t\t\t\t\ttype='button'\n\t\t\t\t\tonClick={() => !locked && input.current?.click()}\n\t\t\t\t\tonDragEnter={() => {\n\t\t\t\t\t\tdepth.current += 1\n\t\t\t\t\t\tif (!locked) setDropping(true)\n\t\t\t\t\t}}\n\t\t\t\t\tonDragOver={event => event.preventDefault()}\n\t\t\t\t\tonDragLeave={() => {\n\t\t\t\t\t\tdepth.current = Math.max(0, depth.current - 1)\n\t\t\t\t\t\tif (depth.current === 0) setDropping(false)\n\t\t\t\t\t}}\n\t\t\t\t\tonDrop={onDrop}\n\t\t\t\t\tdisabled={locked}\n\t\t\t\t\taria-busy={uploading}\n\t\t\t\t\taria-label={copy.avatarChange}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'group ring-ui-border focus-visible:ring-ui-ring relative flex h-full w-full overflow-hidden rounded-full ring-2 ring-offset-2 transition-all duration-200 outline-none',\n\t\t\t\t\t\tlocked\n\t\t\t\t\t\t\t? 'cursor-not-allowed'\n\t\t\t\t\t\t\t: 'hover:ring-ui-primary cursor-pointer',\n\t\t\t\t\t\tdropping && 'ring-ui-primary cursor-copy ring-4'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{shown ? (\n\t\t\t\t\t\t<img src={shown} alt={alt} className='h-full w-full object-cover' />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span className='bg-ui-surface-muted text-ui-muted flex h-full w-full items-center justify-center text-xl font-semibold'>\n\t\t\t\t\t\t\t{fallback}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{dropping ? (\n\t\t\t\t\t\t<span className='bg-ui-primary/70 text-ui-primary-fg absolute inset-0 flex items-center justify-center text-xs font-semibold'>\n\t\t\t\t\t\t\t{copy.avatarDropHere}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : uploading ? (\n\t\t\t\t\t\t<span className='absolute inset-0 flex items-center justify-center bg-black/50 text-xs font-medium text-white'>\n\t\t\t\t\t\t\t{current.progress}%\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : locked ? null : (\n\t\t\t\t\t\t<span className='absolute inset-0 flex items-center justify-center bg-black/50 text-xs font-medium text-white opacity-0 transition-opacity duration-200 group-hover:opacity-100'>\n\t\t\t\t\t\t\t{copy.avatarChange}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\n\t\t\t\t{/* Outside the circle so it never crops it; `pathLength` makes the\n\t\t\t\t dash offset the percentage itself. */}\n\t\t\t\t{uploading ? (\n\t\t\t\t\t<svg\n\t\t\t\t\t\tviewBox='0 0 100 100'\n\t\t\t\t\t\tclassName='pointer-events-none absolute -inset-1.5 -rotate-90'\n\t\t\t\t\t\taria-hidden\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\tcx='50'\n\t\t\t\t\t\t\tcy='50'\n\t\t\t\t\t\t\tr='48'\n\t\t\t\t\t\t\tpathLength={100}\n\t\t\t\t\t\t\tfill='none'\n\t\t\t\t\t\t\tstrokeWidth={4}\n\t\t\t\t\t\t\tstrokeLinecap='round'\n\t\t\t\t\t\t\tstrokeDasharray={100}\n\t\t\t\t\t\t\tstrokeDashoffset={100 - (current?.progress ?? 0)}\n\t\t\t\t\t\t\tclassName='stroke-ui-primary transition-[stroke-dashoffset] duration-200'\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t) : null}\n\t\t\t</div>\n\n\t\t\t{failed ? (\n\t\t\t\t<p className='text-ui-danger max-w-[16rem] text-center text-xs'>\n\t\t\t\t\t{failed}\n\t\t\t\t</p>\n\t\t\t) : onRemove && src && !uploading && !disabled ? (\n\t\t\t\t<button\n\t\t\t\t\ttype='button'\n\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\tclassName='text-ui-danger cursor-pointer text-xs hover:underline'\n\t\t\t\t>\n\t\t\t\t\t{copy.avatarRemove}\n\t\t\t\t</button>\n\t\t\t) : null}\n\n\t\t\t<input\n\t\t\t\tref={input}\n\t\t\t\ttype='file'\n\t\t\t\taccept={uploader.accept}\n\t\t\t\tclassName='hidden'\n\t\t\t\tdisabled={locked}\n\t\t\t\tonChange={event => {\n\t\t\t\t\tconst file = event.target.files?.[0]\n\t\t\t\t\tif (file) void uploader.addFiles([file])\n\t\t\t\t\t// The same file twice in a row must still fire `change`.\n\t\t\t\t\tevent.target.value = ''\n\t\t\t\t}}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n","import type { ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport type { UploaderLabels } from '../labels'\nimport { useUploaderLabels } from '../react/UploaderProvider'\nimport { cn } from '../ui/cn'\n\nexport type DropAnywhereOverlayProps = {\n\t/** Usually `useDropAnywhere().dragging`. */\n\topen: boolean\n\t/** Replaces the default document glyph. */\n\ticon?: ReactNode\n\ttitle?: ReactNode\n\thint?: ReactNode\n\tlabels?: Partial<UploaderLabels>\n\tclassName?: string\n}\n\nconst DocumentGlyph = () => (\n\t<svg\n\t\twidth='40'\n\t\theight='40'\n\t\tviewBox='0 0 24 24'\n\t\tfill='none'\n\t\tstroke='currentColor'\n\t\tstrokeWidth='1.6'\n\t\tstrokeLinecap='round'\n\t\tstrokeLinejoin='round'\n\t\taria-hidden\n\t>\n\t\t<path d='M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z' />\n\t\t<path d='M14 3v5h5' />\n\t\t<path d='M12 18v-6' />\n\t\t<path d='m9.5 14.5 2.5-2.5 2.5 2.5' />\n\t</svg>\n)\n\n/**\n * The full-window invitation that pairs with {@link useDropAnywhere}. Purely\n * visual and `pointer-events-none`: the drop lands on the window, where the\n * hook delivers the files exactly once. Portals to `document.body` above the\n * kit's overlays.\n */\nexport const DropAnywhereOverlay = ({\n\topen,\n\ticon,\n\ttitle,\n\thint,\n\tlabels,\n\tclassName,\n}: DropAnywhereOverlayProps) => {\n\tconst copy = useUploaderLabels(labels)\n\tif (!open || typeof document === 'undefined') return null\n\treturn createPortal(\n\t\t<div\n\t\t\taria-hidden\n\t\t\tclassName='animate-ui-fade-in bg-ui-overlay pointer-events-none fixed inset-0 z-1010 flex items-center justify-center p-6'\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'border-ui-primary bg-ui-surface text-ui-fg rounded-ui-xl flex flex-col items-center gap-2 border-2 border-dashed px-10 py-8 shadow-2xl',\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<span className='text-ui-primary'>{icon ?? <DocumentGlyph />}</span>\n\t\t\t\t<p className='text-base font-semibold'>\n\t\t\t\t\t{title ?? copy.dropAnywhereTitle}\n\t\t\t\t</p>\n\t\t\t\t<p className='text-ui-muted text-sm'>{hint ?? copy.dropAnywhereHint}</p>\n\t\t\t</div>\n\t\t</div>,\n\t\tdocument.body\n\t)\n}\n","import type { ReactNode } from 'react'\n\n/** The little key hint every shortcut announces itself with. */\nexport const Kbd = ({ children }: { children: ReactNode }) => (\n\t<kbd className='border-ui-border bg-ui-surface text-ui-muted rounded-md border px-1.5 py-0.5 font-sans text-[10px] font-medium shadow-sm'>\n\t\t{children}\n\t</kbd>\n)\n","import { useEffect, useState } from 'react'\n\n/**\n * `true` on touch-first devices (`pointer: coarse`), where drag-and-drop\n * barely exists and the zone should read as a tap target. SSR-safe: first\n * paint assumes a fine pointer and corrects in the effect.\n */\nexport const useCoarsePointer = (): boolean => {\n\tconst [coarse, setCoarse] = useState(false)\n\n\tuseEffect(() => {\n\t\tconst query = window.matchMedia('(pointer: coarse)')\n\t\tsetCoarse(query.matches)\n\t\tconst onChange = (event: MediaQueryListEvent) => setCoarse(event.matches)\n\t\tquery.addEventListener('change', onChange)\n\t\treturn () => query.removeEventListener('change', onChange)\n\t}, [])\n\n\treturn coarse\n}\n","import { useEffect, useRef } from 'react'\n\nimport { warnDev } from '../warn'\n\ntype ShortcutSpec = {\n\tmod: boolean\n\tshift: boolean\n\talt: boolean\n\tkey: string\n}\n\n/** `'mod+u'` → ⌘U on mac, Ctrl+U elsewhere. `mod`, `shift`, `alt` + one key. */\nconst parseShortcut = (combo: string): ShortcutSpec => {\n\tconst parts = combo.toLowerCase().split('+')\n\treturn {\n\t\tmod: parts.includes('mod'),\n\t\tshift: parts.includes('shift'),\n\t\talt: parts.includes('alt'),\n\t\tkey: parts[parts.length - 1]!,\n\t}\n}\n\nconst IS_MAC =\n\ttypeof navigator !== 'undefined' && /mac/i.test(navigator.platform)\n\n/** Human hint for a combo: `'mod+u'` → `⌘U` / `Ctrl+U`. */\nexport const formatShortcut = (combo: string): string => {\n\tconst spec = parseShortcut(combo)\n\tconst key = spec.key.length === 1 ? spec.key.toUpperCase() : spec.key\n\tconst parts: string[] = []\n\tif (spec.mod) parts.push(IS_MAC ? '⌘' : 'Ctrl')\n\tif (spec.alt) parts.push(IS_MAC ? '⌥' : 'Alt')\n\tif (spec.shift) parts.push(IS_MAC ? '⇧' : 'Shift')\n\tparts.push(key)\n\treturn parts.join(IS_MAC ? '' : '+')\n}\n\n/** Combos currently bound, to catch two zones claiming the same keys. */\nconst active = new Map<string, number>()\n\n/**\n * Binds a global shortcut while mounted. Never fires from an input, textarea\n * or contenteditable — typing keeps priority — and warns in development when\n * two surfaces register the same combo at once, because only both firing or\n * an arbitrary winner can come out of that.\n */\nexport const useShortcut = (\n\tcombo: string | undefined,\n\thandler: () => void,\n\tdisabled = false\n): void => {\n\tconst handlerRef = useRef(handler)\n\thandlerRef.current = handler\n\n\tuseEffect(() => {\n\t\tif (!combo || disabled) return\n\t\tconst spec = parseShortcut(combo)\n\n\t\tactive.set(combo, (active.get(combo) ?? 0) + 1)\n\t\tif ((active.get(combo) ?? 0) > 1) {\n\t\t\twarnDev(\n\t\t\t\t`shortcut-collision:${combo}`,\n\t\t\t\t`two surfaces registered the shortcut \"${combo}\" at the same time — give each its own combo or scope one out.`\n\t\t\t)\n\t\t}\n\n\t\tconst onKey = (event: KeyboardEvent) => {\n\t\t\tif (event.repeat) return\n\t\t\t// `target` can be `window` itself; only elements can host a field.\n\t\t\tconst target = event.target\n\t\t\tif (\n\t\t\t\ttarget instanceof Element &&\n\t\t\t\ttarget.closest('input, textarea, select, [contenteditable]')\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (event.key.toLowerCase() !== spec.key) return\n\t\t\tif (spec.mod !== (event.metaKey || event.ctrlKey)) return\n\t\t\tif (spec.shift !== event.shiftKey) return\n\t\t\tif (spec.alt !== event.altKey) return\n\t\t\tevent.preventDefault()\n\t\t\thandlerRef.current()\n\t\t}\n\n\t\twindow.addEventListener('keydown', onKey)\n\t\treturn () => {\n\t\t\twindow.removeEventListener('keydown', onKey)\n\t\t\tconst count = (active.get(combo) ?? 1) - 1\n\t\t\tif (count <= 0) active.delete(combo)\n\t\t\telse active.set(combo, count)\n\t\t}\n\t}, [combo, disabled])\n}\n","import {\n\ttype ClipboardEvent,\n\ttype DragEvent,\n\ttype ReactNode,\n\tuseCallback,\n\tuseRef,\n\tuseState,\n} from 'react'\n\nimport { cn } from './cn'\nimport { Kbd } from './Kbd'\nimport { useCoarsePointer } from './useCoarsePointer'\nimport { formatShortcut, useShortcut } from './useShortcut'\n\nexport type DropzoneProps = {\n\taccept: string\n\tmultiple?: boolean\n\tdisabled?: boolean\n\t/**\n\t * Mobile camera shortcut: `'environment'` (rear) or `'user'` (front) makes\n\t * the file picker offer the camera directly on touch devices. Desktop\n\t * browsers ignore it.\n\t */\n\tcapture?: 'user' | 'environment'\n\t/** @defaultValue 'md' */\n\tsize?: 'sm' | 'md'\n\t/**\n\t * Global keyboard shortcut that opens this zone's picker, e.g. `'mod+u'`\n\t * (⌘U / Ctrl+U). A small key hint renders under the prompt on fine\n\t * pointers. With several zones on screen, give each its own combo.\n\t */\n\tshortcut?: string\n\tonFiles: (files: File[]) => void\n\tchildren: ReactNode\n\tclassName?: string\n}\n\n/**\n * The one drag-and-drop surface both uploaders share: drag state, click and\n * keyboard to browse, paste while focused (screenshots land as files), and a\n * hidden input. Presentation comes from `children`.\n */\nexport const Dropzone = ({\n\taccept,\n\tmultiple = false,\n\tdisabled = false,\n\tcapture,\n\tsize = 'md',\n\tshortcut,\n\tonFiles,\n\tchildren,\n\tclassName,\n}: DropzoneProps) => {\n\tconst inputRef = useRef<HTMLInputElement>(null)\n\tconst [dragging, setDragging] = useState(false)\n\t// Depth counter, not a boolean: entering a child fires `dragleave` on this\n\t// wrapper. See AGENTS.md §6.\n\tconst depth = useRef(0)\n\tconst coarse = useCoarsePointer()\n\tuseShortcut(shortcut, () => inputRef.current?.click(), disabled)\n\n\tconst emit = useCallback(\n\t\t(list: FileList | null) => {\n\t\t\tif (disabled || !list || list.length === 0) return\n\t\t\tonFiles(Array.from(list))\n\t\t},\n\t\t[disabled, onFiles]\n\t)\n\n\tconst onDrop = useCallback(\n\t\t(event: DragEvent) => {\n\t\t\tevent.preventDefault()\n\t\t\tdepth.current = 0\n\t\t\tsetDragging(false)\n\t\t\temit(event.dataTransfer.files)\n\t\t},\n\t\t[emit]\n\t)\n\n\tconst onPaste = useCallback(\n\t\t(event: ClipboardEvent) => {\n\t\t\t// A pasted screenshot arrives as a file; pasted text has none and\n\t\t\t// falls through untouched. Validation rejects what the scope won't.\n\t\t\tif (event.clipboardData.files.length === 0) return\n\t\t\tevent.preventDefault()\n\t\t\temit(event.clipboardData.files)\n\t\t},\n\t\t[emit]\n\t)\n\n\treturn (\n\t\t<div\n\t\t\trole='button'\n\t\t\ttabIndex={disabled ? -1 : 0}\n\t\t\taria-disabled={disabled}\n\t\t\tdata-dragging={dragging || undefined}\n\t\t\tonClick={() => !disabled && inputRef.current?.click()}\n\t\t\tonKeyDown={event => {\n\t\t\t\tif (disabled) return\n\t\t\t\tif (event.key === 'Enter' || event.key === ' ') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tinputRef.current?.click()\n\t\t\t\t}\n\t\t\t}}\n\t\t\tonDragEnter={() => {\n\t\t\t\tdepth.current += 1\n\t\t\t\tif (!disabled) setDragging(true)\n\t\t\t}}\n\t\t\tonDragOver={event => event.preventDefault()}\n\t\t\tonDragLeave={() => {\n\t\t\t\tdepth.current = Math.max(0, depth.current - 1)\n\t\t\t\tif (depth.current === 0) setDragging(false)\n\t\t\t}}\n\t\t\tonDrop={onDrop}\n\t\t\tonPaste={onPaste}\n\t\t\tclassName={cn(\n\t\t\t\t// `group/dz` + `data-dragging` let the children (the icon, the\n\t\t\t\t// prompt) react to hover and drag without owning any state.\n\t\t\t\t// `touch-manipulation` kills the 300ms tap delay; the active scale\n\t\t\t\t// is the press feedback a touch screen needs in place of hover.\n\t\t\t\t'group/dz rounded-ui-lg focus-visible:ring-ui-ring block w-full cursor-pointer touch-manipulation border-2 border-dashed text-center transition-all duration-200 focus-visible:ring-2 focus-visible:outline-none',\n\t\t\t\tsize === 'sm' ? 'p-3' : 'p-5',\n\t\t\t\tdragging\n\t\t\t\t\t? 'border-ui-primary bg-ui-primary-soft shadow-ui-primary/15 scale-[1.02] shadow-lg'\n\t\t\t\t\t: 'border-ui-border-strong hover:border-ui-primary/60 hover:bg-ui-primary-soft/40 hover:shadow-ui-primary/10 bg-ui-surface-subtle/50 hover:shadow-md',\n\t\t\t\t!disabled && 'active:scale-[0.98]',\n\t\t\t\tdisabled && 'cursor-not-allowed opacity-50',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\ttype='file'\n\t\t\t\taccept={accept}\n\t\t\t\tmultiple={multiple}\n\t\t\t\tdisabled={disabled}\n\t\t\t\t{...(capture ? { capture } : {})}\n\t\t\t\tclassName='hidden'\n\t\t\t\t// The wrapper's own `input.click()` bubbles back here and would\n\t\t\t\t// re-enter it. Load-bearing — see AGENTS.md §6.\n\t\t\t\tonClick={event => event.stopPropagation()}\n\t\t\t\tonChange={event => {\n\t\t\t\t\temit(event.target.files)\n\t\t\t\t\t// Same file picked twice must fire change again.\n\t\t\t\t\tevent.target.value = ''\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t{children}\n\t\t\t{shortcut && !coarse && (\n\t\t\t\t<span className='mt-2 block'>\n\t\t\t\t\t<Kbd>{formatShortcut(shortcut)}</Kbd>\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n","/**\n * The built-in glyphs, kept to the few the package's own chrome needs — the\n * dropzone default and the viewer's header actions, which have no text on a\n * touch screen. Consumers replace the dropzone one per uploader via the `icon`\n * prop (any ReactNode); none of these is exported, so the package never grows\n * into an icon library.\n */\nexport const UploadCloudIcon = ({ className }: { className?: string }) => (\n\t<svg\n\t\tviewBox='0 0 24 24'\n\t\tfill='none'\n\t\tstroke='currentColor'\n\t\tstrokeWidth='1.75'\n\t\tstrokeLinecap='round'\n\t\tstrokeLinejoin='round'\n\t\tclassName={className}\n\t\taria-hidden\n\t>\n\t\t<path d='M4 14.9A7 7 0 1 1 15.7 8h1.8a4.5 4.5 0 0 1 2.5 8.2' />\n\t\t<path d='M12 12v9' />\n\t\t<path d='m8 16 4-4 4 4' />\n\t</svg>\n)\n\n/** Viewer header: save the file being previewed. */\nexport const DownloadIcon = ({ className }: { className?: string }) => (\n\t<svg\n\t\tviewBox='0 0 24 24'\n\t\tfill='none'\n\t\tstroke='currentColor'\n\t\tstrokeWidth='1.75'\n\t\tstrokeLinecap='round'\n\t\tstrokeLinejoin='round'\n\t\tclassName={className}\n\t\taria-hidden\n\t>\n\t\t<path d='M12 3v12' />\n\t\t<path d='m7 11 5 5 5-5' />\n\t\t<path d='M4 20h16' />\n\t</svg>\n)\n\n/** Viewer header: open the file in its own tab. */\nexport const ExternalLinkIcon = ({ className }: { className?: string }) => (\n\t<svg\n\t\tviewBox='0 0 24 24'\n\t\tfill='none'\n\t\tstroke='currentColor'\n\t\tstrokeWidth='1.75'\n\t\tstrokeLinecap='round'\n\t\tstrokeLinejoin='round'\n\t\tclassName={className}\n\t\taria-hidden\n\t>\n\t\t<path d='M14 4h6v6' />\n\t\t<path d='M20 4 10 14' />\n\t\t<path d='M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5' />\n\t</svg>\n)\n\n/** Viewer: the preview could not be rendered. */\nexport const FileWarningIcon = ({ className }: { className?: string }) => (\n\t<svg\n\t\tviewBox='0 0 24 24'\n\t\tfill='none'\n\t\tstroke='currentColor'\n\t\tstrokeWidth='1.5'\n\t\tstrokeLinecap='round'\n\t\tstrokeLinejoin='round'\n\t\tclassName={className}\n\t\taria-hidden\n\t>\n\t\t<path d='M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z' />\n\t\t<path d='M14 3v5h5' />\n\t\t<path d='M12 11v4' />\n\t\t<path d='M12 18h.01' />\n\t</svg>\n)\n","import { useEffect, useMemo, useRef } from 'react'\n\n/**\n * Which open overlay answers a dismiss key.\n *\n * `FileViewer` and `ConfirmDialog` both claim Escape on `window` in the\n * CAPTURE phase, so they beat a host app's own dialog (a typical Modal\n * listens on `document` in bubble). But two listeners on the same node\n * in the same phase both run — `stopPropagation` only stops other NODES — so\n * a confirm opened over the viewer would close both on one press.\n *\n * Ordering by registration would not help either: that is open order, and the\n * layer that must answer is the innermost, which opened last.\n *\n * Package-local on purpose: a design system that ships its own dismiss\n * stack keeps it, and neither has to depend on the other (invariant §4).\n */\nlet sequence = 0\nconst stack: number[] = []\n\nexport type OverlayLayer = {\n\t/** `true` while this layer is the innermost open one. */\n\tisTopmost: () => boolean\n}\n\n/** Joins the stack while `active`, and leaves it on close or unmount. */\nexport const useOverlayLayer = (active: boolean): OverlayLayer => {\n\tconst idRef = useRef(0)\n\tif (idRef.current === 0) idRef.current = ++sequence\n\n\tuseEffect(() => {\n\t\tif (!active) return\n\t\tconst id = idRef.current\n\t\tstack.push(id)\n\t\treturn () => {\n\t\t\tconst at = stack.lastIndexOf(id)\n\t\t\tif (at !== -1) stack.splice(at, 1)\n\t\t}\n\t}, [active])\n\n\treturn useMemo(\n\t\t() => ({ isTopmost: () => stack[stack.length - 1] === idRef.current }),\n\t\t[]\n\t)\n}\n","/**\n * Body scroll lock, reference counted across overlays AND across packages —\n * the state lives on `globalThis` so every copy converges on one counter.\n *\n * @see AGENTS.md §4 — the key and the shape are an invariant, not a detail\n */\ntype ScrollLockState = { count: number; saved: string }\n\nconst KEY = Symbol.for('uploaderkit.bodyScrollLock')\n\nconst state = (): ScrollLockState => {\n\tconst host = globalThis as { [KEY]?: ScrollLockState }\n\treturn (host[KEY] ??= { count: 0, saved: '' })\n}\n\nexport const lockBodyScroll = (): void => {\n\tconst lock = state()\n\tif (lock.count === 0) {\n\t\tlock.saved = document.body.style.overflow\n\t\tdocument.body.style.overflow = 'hidden'\n\t}\n\tlock.count += 1\n}\n\nexport const unlockBodyScroll = (): void => {\n\tconst lock = state()\n\t// An unbalanced unlock must be a no-op — decrementing past zero would\n\t// re-apply a stale saved value onto a page nobody locked.\n\tif (lock.count === 0) return\n\tlock.count -= 1\n\tif (lock.count === 0) document.body.style.overflow = lock.saved\n}\n","import { type RefObject, useEffect } from 'react'\n\nconst FOCUSABLE =\n\t'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex=\"-1\"])'\n\n/**\n * Keeps `Tab` inside `ref` while `active`, focuses the panel (or its first\n * `[data-autofocus]`) on activation, and restores focus to whatever had it\n * before — the contract a modal owes the keyboard.\n */\nexport const useFocusTrap = (\n\tactive: boolean,\n\tref: RefObject<HTMLElement | null>\n): void => {\n\tuseEffect(() => {\n\t\tif (!active) return\n\t\tconst restoreTo = document.activeElement as HTMLElement | null\n\n\t\tconst panel = ref.current\n\t\tconst initial =\n\t\t\tpanel?.querySelector<HTMLElement>('[data-autofocus]') ?? panel\n\t\tinitial?.focus({ preventScroll: true })\n\n\t\tconst onKeyDown = (event: KeyboardEvent) => {\n\t\t\tif (event.key !== 'Tab' || !ref.current) return\n\t\t\tconst focusables = Array.from(\n\t\t\t\tref.current.querySelectorAll<HTMLElement>(FOCUSABLE)\n\t\t\t).filter(el => el.offsetParent !== null)\n\t\t\tif (focusables.length === 0) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst first = focusables[0]!\n\t\t\tconst last = focusables[focusables.length - 1]!\n\t\t\tif (event.shiftKey && document.activeElement === first) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tlast.focus()\n\t\t\t} else if (!event.shiftKey && document.activeElement === last) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tfirst.focus()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', onKeyDown)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', onKeyDown)\n\t\t\trestoreTo?.focus({ preventScroll: true })\n\t\t}\n\t}, [active, ref])\n}\n","import { useEffect, useRef, useState } from 'react'\n\n/** Kept in sync with the transition classes the overlays use. */\nconst OVERLAY_ANIMATION_MS = 200\n\nexport type OverlayTransition = {\n\t/** Render while `true` — spans the exit animation past `open = false`. */\n\tmounted: boolean\n\t/** Drives the transition classes: `false` on both edges of the animation. */\n\tentered: boolean\n}\n\n/**\n * The enter/exit choreography every overlay shares: render on open, flip\n * `entered` a frame later so the transition runs, keep rendering\n * `OVERLAY_ANIMATION_MS` past close so the exit is visible.\n *\n * @see AGENTS.md §3\n */\nexport const useOverlayTransition = (open: boolean): OverlayTransition => {\n\tconst [entered, setEntered] = useState(false)\n\tconst [exiting, setExiting] = useState(false)\n\tconst wasOpen = useRef(false)\n\n\tuseEffect(() => {\n\t\tif (open) {\n\t\t\twasOpen.current = true\n\t\t\tsetExiting(false)\n\t\t\tconst raf = requestAnimationFrame(() => setEntered(true))\n\t\t\treturn () => cancelAnimationFrame(raf)\n\t\t}\n\t\tsetEntered(false)\n\t\tif (!wasOpen.current) return\n\t\twasOpen.current = false\n\t\tsetExiting(true)\n\t\tconst timer = setTimeout(() => setExiting(false), OVERLAY_ANIMATION_MS)\n\t\treturn () => clearTimeout(timer)\n\t}, [open])\n\n\treturn { mounted: open || exiting, entered }\n}\n","import { type ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getMimeType } from '../file'\nimport type { UploaderLabels } from '../labels'\nimport { useUploaderLabels } from '../react/UploaderProvider'\nimport { cn } from './cn'\nimport { DownloadIcon, ExternalLinkIcon, FileWarningIcon } from './icons'\nimport { Kbd } from './Kbd'\nimport { useOverlayLayer } from './overlayStack'\nimport { lockBodyScroll, unlockBodyScroll } from './scrollLock'\nimport { useCoarsePointer } from './useCoarsePointer'\nimport { useFocusTrap } from './useFocusTrap'\nimport { useOverlayTransition } from './useOverlayTransition'\n\n/**\n * The viewer's empty states — failure and \"no preview\" — speak the overlay's\n * own language: no card, white on the black scrim, the same translucent\n * controls as the header. Theme tokens are deliberately absent: this component\n * ships inside many apps, and a surface-coloured panel would read as a stray\n * card from whichever one is hosting it.\n */\nconst EMPTY_STATE_CLASS = 'mx-4 flex max-w-sm flex-col items-center text-center'\nconst EMPTY_TITLE_CLASS = 'text-sm font-medium text-white'\nconst EMPTY_HINT_CLASS = 'mt-1.5 text-xs leading-relaxed text-white/60'\n/** Primary sits one step brighter than the header actions, never coloured. */\nconst EMPTY_PRIMARY_CLASS =\n\t'focus-visible:ring-ui-ring rounded-ui cursor-pointer bg-white/20 px-4 py-2 text-sm text-white transition-colors hover:bg-white/30 focus-visible:ring-2 focus-visible:outline-none'\nconst EMPTY_SECONDARY_CLASS =\n\t'focus-visible:ring-ui-ring rounded-ui cursor-pointer border border-white/20 px-4 py-2 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white focus-visible:ring-2 focus-visible:outline-none'\n\n/** Shared chrome of the header actions, so the three stay one control strip. */\nconst ACTION_CLASS =\n\t'focus-visible:ring-ui-ring rounded-ui inline-flex shrink-0 cursor-pointer items-center gap-1.5 bg-white/10 px-3 py-1.5 text-xs whitespace-nowrap text-white transition-colors hover:bg-white/20 focus-visible:ring-2 focus-visible:outline-none'\n\n/** What the viewer needs to render a file — a StoredFile satisfies it. */\nexport type ViewableFile = {\n\turl: string\n\tfileName?: string\n\tmimeType?: string\n}\n\nexport type FileViewerProps = {\n\t/** File to show; `null` keeps the viewer closed. */\n\tfile: ViewableFile | null\n\tonClose: () => void\n\t/**\n\t * The collection to browse. With more than one entry the viewer gains side\n\t * arrows and ←/→ keyboard navigation, starting at `file`'s position.\n\t */\n\tfiles?: ViewableFile[]\n\t/**\n\t * Resolve a fresh URL right before rendering — the hook for private scopes,\n\t * where the persisted signed URL may have expired and the app re-signs via\n\t * its /storage signed-url endpoint.\n\t */\n\tresolveUrl?: (file: ViewableFile) => Promise<string>\n\t/**\n\t * Replaces the built-in \"could not load\" panel. Receives the file that\n\t * failed and a `retry` that re-resolves and re-renders it, so a custom\n\t * panel keeps the recovery the default one offers.\n\t */\n\trenderError?: (context: {\n\t\tfile: ViewableFile\n\t\tretry: () => void\n\t}) => ReactNode\n\tlabels?: Partial<UploaderLabels>\n}\n\ntype Kind = 'image' | 'pdf' | 'other'\n\nconst kindOf = (file: ViewableFile): Kind => {\n\tconst mime = file.mimeType || getMimeType(file.fileName ?? file.url)\n\tif (mime.startsWith('image/')) return 'image'\n\tif (mime === 'application/pdf') return 'pdf'\n\treturn 'other'\n}\n\n/**\n * iPadOS 13+ reports itself as a Mac, so the platform string alone misses it;\n * a Mac with a touchscreen is the tell.\n */\nconst isIosWebkit = (): boolean => {\n\tconst ua = navigator.userAgent\n\treturn (\n\t\t/iPad|iPhone|iPod/.test(ua) ||\n\t\t(ua.includes('Macintosh') && navigator.maxTouchPoints > 1)\n\t)\n}\n\n/**\n * Whether an `<iframe>` will actually RENDER a PDF here.\n *\n * This used to be a `max-width: 640px` media query standing in for \"iOS\n * Safari\". It punished every narrow viewport — a half-width desktop window, a\n * phone on Chrome — with the \"no preview\" card, while iPadOS, which is wider\n * than the breakpoint AND genuinely broken, sailed past it into a blank frame.\n *\n * `pdfViewerEnabled` is the browser answering the question directly (it is\n * false on Android Chrome, which downloads instead of embedding). WebKit on iOS\n * answers yes and then paints a frozen first page, so it stays excluded by\n * name.\n */\nconst browserEmbedsPdf = (): boolean => {\n\tif (typeof navigator === 'undefined') return false\n\tif (navigator.pdfViewerEnabled === false) return false\n\treturn !isIosWebkit()\n}\n\nconst Chevron = ({ direction }: { direction: 'left' | 'right' }) => (\n\t<svg\n\t\tviewBox='0 0 24 24'\n\t\tfill='none'\n\t\tstroke='currentColor'\n\t\tstrokeWidth='2.5'\n\t\tstrokeLinecap='round'\n\t\tstrokeLinejoin='round'\n\t\tclassName='h-5 w-5'\n\t\taria-hidden\n\t>\n\t\t{direction === 'left' ? (\n\t\t\t<path d='m15 18-6-6 6-6' />\n\t\t) : (\n\t\t\t<path d='m9 18 6-6-6-6' />\n\t\t)}\n\t</svg>\n)\n\n/**\n * Full-screen file preview: images zoomed to fit, PDFs embedded, anything\n * else offered as a download — no more blind new-tab jumps. Pass `files` and\n * it becomes a gallery: side arrows, ←/→ on the keyboard, a position counter.\n * Used internally by `Uploader` and `SlottedUploader`, and exported standalone\n * so any screen can preview the `StoredFile`s it persisted.\n *\n * Portals to `<body>` so an ancestor's stacking context can never trap it,\n * and traps focus while open.\n */\nexport const FileViewer = ({\n\tfile,\n\tonClose,\n\tfiles,\n\tresolveUrl,\n\trenderError,\n\tlabels,\n}: FileViewerProps) => {\n\tconst copy = useUploaderLabels(labels)\n\tconst coarse = useCoarsePointer()\n\tconst [url, setUrl] = useState<string | null>(null)\n\tconst [failed, setFailed] = useState(false)\n\t// Bumping it re-runs the resolution — the retry button after a failure.\n\tconst [attempt, setAttempt] = useState(0)\n\tconst retry = useCallback(() => setAttempt(previous => previous + 1), [])\n\tconst panelRef = useRef<HTMLDivElement>(null)\n\tconst open = file !== null\n\tconst { mounted, entered } = useOverlayTransition(open)\n\tconst layer = useOverlayLayer(open)\n\tuseFocusTrap(open, panelRef)\n\n\t// Gallery cursor. Synced to `file`'s position whenever the viewer opens.\n\tconst list = files && files.length > 0 ? files : null\n\tconst [cursor, setCursor] = useState(0)\n\tuseEffect(() => {\n\t\tif (!file || !list) return\n\t\tconst index = list.findIndex(entry => entry.url === file.url)\n\t\tsetCursor(index >= 0 ? index : 0)\n\t\t// Only the opening file may reposition the cursor, not a list rebuild.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [file])\n\n\tconst current = open ? (list ? (list[cursor] ?? file) : file) : null\n\n\t// The exit animation still needs something to draw after `file` nulls out.\n\tconst lastViewRef = useRef<ViewableFile | null>(null)\n\tif (current) lastViewRef.current = current\n\n\tconst navigate = useCallback(\n\t\t(delta: number) => {\n\t\t\tif (!list) return\n\t\t\tsetCursor(previous =>\n\t\t\t\tMath.min(list.length - 1, Math.max(0, previous + delta))\n\t\t\t)\n\t\t},\n\t\t[list]\n\t)\n\n\t// The viewer resolves, so the viewer owns what the resolution minted: a\n\t// `createBlobUrlResolver` hands back a `blob:` whose BYTES stay alive until\n\t// something revokes it, and browsing a gallery mints one per file.\n\tconst objectUrlRef = useRef<string | null>(null)\n\tconst releaseObjectUrl = useCallback(() => {\n\t\tif (objectUrlRef.current) URL.revokeObjectURL(objectUrlRef.current)\n\t\tobjectUrlRef.current = null\n\t}, [])\n\n\t// In a ref, not the deps: callers pass an inline arrow and re-signing is a\n\t// round trip. Only the viewed file (or an explicit retry) may re-run it.\n\tconst resolveRef = useRef(resolveUrl)\n\tresolveRef.current = resolveUrl\n\tconst currentUrl = current?.url\n\n\tuseEffect(() => {\n\t\t// Before the early return: closing the viewer nulls `current`, and that\n\t\t// is exactly when the last blob has to go.\n\t\treleaseObjectUrl()\n\t\tif (!current) {\n\t\t\tsetUrl(null)\n\t\t\tsetFailed(false)\n\t\t\treturn\n\t\t}\n\t\tlet alive = true\n\t\tsetUrl(null)\n\t\tsetFailed(false)\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tconst resolve = resolveRef.current\n\t\t\t\tconst resolved = resolve ? await resolve(current) : current.url\n\t\t\t\tconst minted = resolved.startsWith('blob:')\n\t\t\t\tif (!alive) {\n\t\t\t\t\t// Superseded mid-flight: nothing will ever render it, so it has\n\t\t\t\t\t// to go now or it is unreachable AND alive.\n\t\t\t\t\tif (minted) URL.revokeObjectURL(resolved)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// A signed url belongs to the server; only a blob is ours to free.\n\t\t\t\tif (minted) objectUrlRef.current = resolved\n\t\t\t\tsetUrl(resolved)\n\t\t\t} catch {\n\t\t\t\t// An expired signature or a dropped connection must surface as a\n\t\t\t\t// retryable state, never as an eternal \"Cargando…\".\n\t\t\t\tif (alive) {\n\t\t\t\t\tsetUrl(null)\n\t\t\t\t\tsetFailed(true)\n\t\t\t\t}\n\t\t\t}\n\t\t})()\n\t\treturn () => {\n\t\t\talive = false\n\t\t}\n\t\t// `currentUrl` stands in for `current`: a rebuilt array with the same\n\t\t// entry must not re-sign.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [currentUrl, attempt])\n\n\t// The effect above frees on every change; this catches the last one.\n\tuseEffect(() => releaseObjectUrl, [releaseObjectUrl])\n\n\tconst closeRef = useRef(onClose)\n\tcloseRef.current = onClose\n\n\t// Clicking the anchors is what downloads/opens: replicating their behaviour\n\t// from a handler would mean re-deriving `download` and popup rules.\n\tconst downloadRef = useRef<HTMLAnchorElement>(null)\n\tconst openTabRef = useRef<HTMLAnchorElement>(null)\n\n\tuseEffect(() => {\n\t\tif (!open) return\n\t\tconst onKey = (event: KeyboardEvent) => {\n\t\t\t// A modifier means the key belongs to the browser (⌘D bookmarks,\n\t\t\t// ⌘O opens a file): claiming it would fire our action AND theirs.\n\t\t\tif (event.metaKey || event.ctrlKey || event.altKey) return\n\t\t\tif (event.key === 'Escape') {\n\t\t\t\t// Only the innermost overlay answers, then claims the key so a\n\t\t\t\t// host dialog underneath does not close on the same press.\n\t\t\t\tif (!layer.isTopmost()) return\n\t\t\t\tevent.stopPropagation()\n\t\t\t\tcloseRef.current()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (event.key === 'ArrowLeft') navigate(-1)\n\t\t\tif (event.key === 'ArrowRight') navigate(1)\n\t\t\t// Bare letters, like the arrows above: the viewer is modal and\n\t\t\t// traps focus, so nothing else can be listening.\n\t\t\tconst key = event.key.toLowerCase()\n\t\t\tif (key === 'd') downloadRef.current?.click()\n\t\t\tif (key === 'o') openTabRef.current?.click()\n\t\t}\n\t\t// Capture phase: it must run BEFORE any bubble-phase dialog handler.\n\t\twindow.addEventListener('keydown', onKey, true)\n\t\tlockBodyScroll()\n\t\treturn () => {\n\t\t\twindow.removeEventListener('keydown', onKey, true)\n\t\t\tunlockBodyScroll()\n\t\t}\n\t}, [open, navigate, layer])\n\n\t// Lazy initializer, not an effect: `navigator` cannot change under the\n\t// component, and starting at `true` painted one iframe frame on iOS before\n\t// correcting to the download card.\n\tconst [canEmbedPdf] = useState(browserEmbedsPdf)\n\n\tconst view = current ?? lastViewRef.current\n\tif (!mounted || !view) return null\n\tconst kind = kindOf(view)\n\t// Drives BOTH the branch and the stretch class: the iframe is the only\n\t// child that fills its container, and letting the two drift is what pinned\n\t// a failed PDF's message to the top edge.\n\tconst showsPdf = kind === 'pdf' && canEmbedPdf && !failed && !!url\n\tconst hasGallery = list !== null && list.length > 1\n\n\tconst arrow =\n\t\t'absolute top-1/2 z-10 flex h-11 w-11 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-white/10 text-white backdrop-blur-sm transition-all duration-200 hover:bg-white/25 focus-visible:ring-2 focus-visible:ring-ui-ring focus-visible:outline-none disabled:pointer-events-none disabled:opacity-25'\n\n\treturn createPortal(\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'fixed inset-0 z-1000 flex flex-col bg-black/85 transition-opacity duration-200 ease-out',\n\t\t\t\tentered ? 'opacity-100' : 'opacity-0',\n\t\t\t\t!open && 'pointer-events-none'\n\t\t\t)}\n\t\t\tonClick={onClose}\n\t\t\trole='dialog'\n\t\t\taria-modal='true'\n\t\t\taria-label={view.fileName ?? copy.filePreview}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName='flex items-center justify-between gap-2 px-3 py-2.5 sm:gap-3 sm:px-4 sm:py-3'\n\t\t\t\tonClick={event => event.stopPropagation()}\n\t\t\t>\n\t\t\t\t<p className='min-w-0 flex-1 truncate text-xs font-medium text-white sm:text-sm'>\n\t\t\t\t\t{view.fileName ?? copy.filePreview}\n\t\t\t\t</p>\n\t\t\t\t{hasGallery && (\n\t\t\t\t\t<span className='shrink-0 rounded-full bg-white/10 px-2.5 py-1 text-[11px] font-medium text-white tabular-nums'>\n\t\t\t\t\t\t{cursor + 1} / {list.length}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t{/* Three actions plus a title do not fit a phone, so a coarse\n\t\t\t\t pointer gets glyphs and the labels move to `aria-label`. */}\n\t\t\t\t{url && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tref={downloadRef}\n\t\t\t\t\t\t\thref={url}\n\t\t\t\t\t\t\tdownload={view.fileName}\n\t\t\t\t\t\t\taria-label={copy.downloadShort}\n\t\t\t\t\t\t\ttitle={copy.downloadShort}\n\t\t\t\t\t\t\tclassName={ACTION_CLASS}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{coarse ? (\n\t\t\t\t\t\t\t\t<DownloadIcon className='h-4 w-4' />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\tcopy.downloadShort\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tref={openTabRef}\n\t\t\t\t\t\t\thref={url}\n\t\t\t\t\t\t\ttarget='_blank'\n\t\t\t\t\t\t\trel='noreferrer'\n\t\t\t\t\t\t\taria-label={copy.openInTab}\n\t\t\t\t\t\t\ttitle={copy.openInTab}\n\t\t\t\t\t\t\tclassName={ACTION_CLASS}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{coarse ? (\n\t\t\t\t\t\t\t\t<ExternalLinkIcon className='h-4 w-4' />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\tcopy.openInTab\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t\t<button\n\t\t\t\t\ttype='button'\n\t\t\t\t\tonClick={onClose}\n\t\t\t\t\taria-label={copy.close}\n\t\t\t\t\ttitle={copy.close}\n\t\t\t\t\tclassName={ACTION_CLASS}\n\t\t\t\t>\n\t\t\t\t\t{coarse ? '✕' : <>✕ {copy.close}</>}\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div\n\t\t\t\tref={panelRef}\n\t\t\t\ttabIndex={-1}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'relative flex min-h-0 flex-1 items-center justify-center p-3 outline-none sm:p-4',\n\t\t\t\t\tshowsPdf && 'items-stretch'\n\t\t\t\t)}\n\t\t\t\tonClick={event => event.stopPropagation()}\n\t\t\t>\n\t\t\t\t{hasGallery && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\tonClick={() => navigate(-1)}\n\t\t\t\t\t\t\tdisabled={cursor === 0}\n\t\t\t\t\t\t\taria-label={copy.previous}\n\t\t\t\t\t\t\tclassName={cn(arrow, 'left-2 sm:left-4')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Chevron direction='left' />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\tonClick={() => navigate(1)}\n\t\t\t\t\t\t\tdisabled={cursor === list.length - 1}\n\t\t\t\t\t\t\taria-label={copy.next}\n\t\t\t\t\t\t\tclassName={cn(arrow, 'right-2 sm:right-4')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Chevron direction='right' />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{failed ? (\n\t\t\t\t\t(renderError?.({ file: view, retry }) ?? (\n\t\t\t\t\t\t<div className={EMPTY_STATE_CLASS}>\n\t\t\t\t\t\t\t<span className='mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-white/5 text-white/70 ring-1 ring-white/10'>\n\t\t\t\t\t\t\t\t<FileWarningIcon className='h-8 w-8' />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<p className={EMPTY_TITLE_CLASS}>{copy.viewerError}</p>\n\t\t\t\t\t\t\t<p className={EMPTY_HINT_CLASS}>{copy.viewerErrorHint}</p>\n\t\t\t\t\t\t\t{view.fileName && (\n\t\t\t\t\t\t\t\t<p className='mt-3 max-w-full truncate font-mono text-[11px] text-white/40'>\n\t\t\t\t\t\t\t\t\t{view.fileName}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div className='mt-5 flex flex-wrap justify-center gap-2'>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\t\t\tonClick={retry}\n\t\t\t\t\t\t\t\t\tclassName={EMPTY_PRIMARY_CLASS}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{copy.viewerRetry}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t{/* The bytes may still be reachable even when\n\t\t\t\t\t\t\t\t the preview is not — never a dead end. */}\n\t\t\t\t\t\t\t\t{url && (\n\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\thref={url}\n\t\t\t\t\t\t\t\t\t\tdownload={view.fileName}\n\t\t\t\t\t\t\t\t\t\tclassName={EMPTY_SECONDARY_CLASS}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{copy.downloadShort}\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))\n\t\t\t\t) : !url ? (\n\t\t\t\t\t<p className='text-sm text-white/70'>{copy.viewerLoading}</p>\n\t\t\t\t) : kind === 'image' ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\talt={view.fileName ?? ''}\n\t\t\t\t\t\t// A resolved url only proves the address; the object\n\t\t\t\t\t\t// behind it can still 404, and an untracked failure\n\t\t\t\t\t\t// renders as an invisible image.\n\t\t\t\t\t\tonError={() => setFailed(true)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'rounded-ui-lg max-h-full max-w-full object-contain shadow-2xl',\n\t\t\t\t\t\t\t'transition-transform duration-200 ease-out',\n\t\t\t\t\t\t\tentered ? 'scale-100' : 'scale-[0.97]'\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t) : showsPdf ? (\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\ttitle={view.fileName ?? 'PDF'}\n\t\t\t\t\t\t// Best effort: a cross-origin 404 usually renders the\n\t\t\t\t\t\t// browser's own error page inside the frame and fires\n\t\t\t\t\t\t// `load`, so this catches only the cases it can.\n\t\t\t\t\t\tonError={() => setFailed(true)}\n\t\t\t\t\t\tclassName='rounded-ui-lg h-full w-full max-w-4xl bg-white shadow-2xl'\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<div className={EMPTY_STATE_CLASS}>\n\t\t\t\t\t\t<span className='mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-white/5 text-white/70 ring-1 ring-white/10'>\n\t\t\t\t\t\t\t<FileWarningIcon className='h-8 w-8' />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<p className={EMPTY_TITLE_CLASS}>{copy.noPreview}</p>\n\t\t\t\t\t\t{view.fileName && (\n\t\t\t\t\t\t\t<p className='mt-3 max-w-full truncate font-mono text-[11px] text-white/40'>\n\t\t\t\t\t\t\t\t{view.fileName}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\thref={url}\n\t\t\t\t\t\t\tdownload={view.fileName}\n\t\t\t\t\t\t\ttarget='_blank'\n\t\t\t\t\t\t\trel='noreferrer'\n\t\t\t\t\t\t\tclassName={cn(EMPTY_PRIMARY_CLASS, 'mt-5 inline-block')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{copy.download(view.fileName ?? copy.filePreview)}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Shortcut hints — pointless on touch, so fine pointers only. */}\n\t\t\t{!coarse && (\n\t\t\t\t<div\n\t\t\t\t\tclassName='flex items-center justify-center gap-4 pb-3 text-[11px] text-white/60'\n\t\t\t\t\tonClick={event => event.stopPropagation()}\n\t\t\t\t>\n\t\t\t\t\t<span className='flex items-center gap-1.5'>\n\t\t\t\t\t\t<Kbd>Esc</Kbd> {copy.close}\n\t\t\t\t\t</span>\n\t\t\t\t\t{url && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<span className='flex items-center gap-1.5'>\n\t\t\t\t\t\t\t\t<Kbd>D</Kbd> {copy.downloadShort}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span className='flex items-center gap-1.5'>\n\t\t\t\t\t\t\t\t<Kbd>O</Kbd> {copy.openInTab}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t{hasGallery && (\n\t\t\t\t\t\t<span className='flex items-center gap-1.5'>\n\t\t\t\t\t\t\t<Kbd>←</Kbd>\n\t\t\t\t\t\t\t<Kbd>→</Kbd> {copy.previous} / {copy.next}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>,\n\t\tdocument.body\n\t)\n}\n","import { useState } from 'react'\n\nimport type { UploaderLabels } from '../labels'\nimport { useUploaderLabels } from '../react/UploaderProvider'\nimport { useUploader, type UseUploaderOptions } from '../react/useUploader'\nimport type { ScopeConfig, StoredFile } from '../types'\nimport { cn } from '../ui/cn'\nimport { Dropzone } from '../ui/Dropzone'\nimport { FileViewer, type ViewableFile } from '../ui/FileViewer'\n\nexport type GalleryUploaderProps<\n\tT extends Record<string, ScopeConfig> = Record<string, ScopeConfig>,\n> = Pick<\n\tUseUploaderOptions<T>,\n\t'scopes' | 'scope' | 'entityId' | 'strategy' | 'maxFiles' | 'rename'\n> & {\n\t/** Images already persisted, rendered as tiles ahead of the in-flight ones. */\n\tstored?: StoredFile[]\n\tonUploaded?: (stored: StoredFile[]) => void\n\t/** Offered on a stored tile; the caller forgets the reference (and sweeps). */\n\tonRemoveStored?: (file: StoredFile) => void\n\tonError?: (message: string) => void\n\t/** Re-sign or proxy a stored url right before the viewer opens it. */\n\tresolveViewUrl?: (file: ViewableFile) => Promise<string>\n\t/** Grid columns. @defaultValue 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4' */\n\tcolumnsClassName?: string\n\tdisabled?: boolean\n\tlabels?: Partial<UploaderLabels>\n\tclassName?: string\n}\n\n/**\n * A thumbnail grid over the headless hook: every tile is the file's own\n * preview, the progress washes over it while it travels, hover reveals view\n * and remove, and a click opens the full-screen viewer over the whole set.\n * The add tile IS the dropzone.\n */\nexport const GalleryUploader = <T extends Record<string, ScopeConfig>>({\n\tscopes,\n\tscope,\n\tentityId,\n\tstrategy,\n\tmaxFiles,\n\trename,\n\tstored = [],\n\tonUploaded,\n\tonRemoveStored,\n\tonError,\n\tresolveViewUrl,\n\tcolumnsClassName = 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4',\n\tdisabled = false,\n\tlabels,\n\tclassName,\n}: GalleryUploaderProps<T>) => {\n\tconst copy = useUploaderLabels(labels)\n\tconst [viewing, setViewing] = useState<ViewableFile | null>(null)\n\tconst uploader = useUploader<T>({\n\t\tscopes,\n\t\tscope,\n\t\tentityId,\n\t\tstrategy,\n\t\tmultiple: true,\n\t\t...(maxFiles !== undefined ? { maxFiles } : {}),\n\t\t...(rename ? { rename } : {}),\n\t\tuploadOn: 'select',\n\t\tonUploaded,\n\t\tonError,\n\t\tlabels,\n\t})\n\n\t// Persisted tiles come first; a file the hook already confirmed and the\n\t// caller echoed back through `stored` renders once.\n\tconst storedKeys = new Set(stored.map(file => file.key))\n\tconst inFlight = uploader.files.filter(\n\t\tfile => !(file.stored && storedKeys.has(file.stored.key))\n\t)\n\tconst viewable: ViewableFile[] = [\n\t\t...stored,\n\t\t...inFlight.flatMap(file => (file.stored ? [file.stored] : [])),\n\t]\n\n\tconst tile =\n\t\t'group animate-ui-fade-in border-ui-border bg-ui-surface-muted rounded-ui-lg relative aspect-square overflow-hidden border shadow-sm transition-shadow duration-200 hover:shadow-md'\n\tconst action =\n\t\t'bg-ui-surface/90 text-ui-fg hover:bg-ui-surface rounded-ui cursor-pointer px-2 py-1 text-[11px] font-medium shadow-sm transition-colors'\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t<div className={cn('grid gap-3', columnsClassName)}>\n\t\t\t\t{stored.map(file => (\n\t\t\t\t\t<div key={file.key} className={tile}>\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={file.url}\n\t\t\t\t\t\t\talt={file.fileName}\n\t\t\t\t\t\t\tclassName='h-full w-full object-cover transition-transform duration-300 group-hover:scale-105'\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div className='absolute inset-x-0 bottom-0 flex justify-between gap-1 bg-gradient-to-t from-black/60 to-transparent p-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100'>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\t\tonClick={() => setViewing(file)}\n\t\t\t\t\t\t\t\tclassName={action}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{copy.view}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{onRemoveStored && !disabled ? (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveStored(file)}\n\t\t\t\t\t\t\t\t\tclassName={cn(action, 'text-ui-danger')}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{copy.remove}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\n\t\t\t\t{inFlight.map(file => (\n\t\t\t\t\t<div key={file.id} className={tile}>\n\t\t\t\t\t\t{file.preview ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tsrc={file.preview}\n\t\t\t\t\t\t\t\talt={file.file.name}\n\t\t\t\t\t\t\t\tclassName='h-full w-full object-cover transition-transform duration-300 group-hover:scale-105'\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{file.status === 'uploading' ? (\n\t\t\t\t\t\t\t<div className='absolute inset-0 flex flex-col items-center justify-center gap-2 bg-black/45'>\n\t\t\t\t\t\t\t\t<span className='text-sm font-semibold text-white'>\n\t\t\t\t\t\t\t\t\t{file.progress}%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<div className='h-1 w-2/3 overflow-hidden rounded-full bg-white/30'>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName='h-full bg-white transition-all duration-150'\n\t\t\t\t\t\t\t\t\t\tstyle={{ width: `${file.progress}%` }}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{file.status === 'error' ? (\n\t\t\t\t\t\t\t<div className='bg-ui-danger/70 absolute inset-0 flex items-center justify-center p-2'>\n\t\t\t\t\t\t\t\t<p className='text-center text-[11px] leading-tight text-white'>\n\t\t\t\t\t\t\t\t\t{file.error}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{file.status !== 'uploading' ? (\n\t\t\t\t\t\t\t<div className='absolute inset-x-0 bottom-0 flex justify-between gap-1 bg-gradient-to-t from-black/60 to-transparent p-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100'>\n\t\t\t\t\t\t\t\t{file.stored ? (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\t\t\t\tonClick={() => file.stored && setViewing(file.stored)}\n\t\t\t\t\t\t\t\t\t\tclassName={action}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{copy.view}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype='button'\n\t\t\t\t\t\t\t\t\tonClick={() => uploader.removeFile(file.id)}\n\t\t\t\t\t\t\t\t\tclassName={cn(action, 'text-ui-danger')}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{copy.remove}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\n\t\t\t\t<Dropzone\n\t\t\t\t\taccept={uploader.accept}\n\t\t\t\t\tmultiple\n\t\t\t\t\tsize='sm'\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonFiles={files => void uploader.addFiles(files)}\n\t\t\t\t\tclassName='flex aspect-square flex-col items-center justify-center'\n\t\t\t\t>\n\t\t\t\t\t<span className='text-ui-muted text-3xl leading-none font-light'>\n\t\t\t\t\t\t+\n\t\t\t\t\t</span>\n\t\t\t\t\t<span className='text-ui-muted mt-1 text-xs'>{copy.galleryAdd}</span>\n\t\t\t\t</Dropzone>\n\t\t\t</div>\n\n\t\t\t<FileViewer\n\t\t\t\tfile={viewing}\n\t\t\t\tfiles={viewable}\n\t\t\t\tonClose={() => setViewing(null)}\n\t\t\t\t{...(resolveViewUrl ? { resolveUrl: resolveViewUrl } : {})}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n","import { useEffect, useRef, useState } from 'react'\n\nexport type UseDropAnywhereOptions = {\n\t/** Listen at all. Off while the surface that wants the files is closed. */\n\tenabled?: boolean\n\t/** Receives the accepted files of one drop, anywhere in the window. */\n\tonFiles: (files: File[]) => void\n\t/**\n\t * Same syntax as `<input accept>`: `.pdf,.xlsx,image/*`. Files outside it go\n\t * to `onRejected` instead of `onFiles`; omit to accept everything.\n\t */\n\taccept?: string\n\tonRejected?: (files: File[]) => void\n}\n\nexport type DropAnywhere = {\n\t/** A file drag is over the window — show the overlay. */\n\tdragging: boolean\n}\n\nconst matchesAccept = (file: File, accept: string): boolean => {\n\tconst tokens = accept\n\t\t.split(',')\n\t\t.map(token => token.trim().toLowerCase())\n\t\t.filter(Boolean)\n\tif (tokens.length === 0) return true\n\tconst name = file.name.toLowerCase()\n\tconst type = file.type.toLowerCase()\n\treturn tokens.some(token => {\n\t\tif (token.startsWith('.')) return name.endsWith(token)\n\t\tif (token.endsWith('/*')) return type.startsWith(token.slice(0, -1))\n\t\treturn type === token\n\t})\n}\n\n/**\n * The whole window as a drop target. A depth counter on `dragenter` /\n * `dragleave` at window level says when a file drag is present (a boolean\n * flickers on every child boundary — see AGENTS.md §6), and the window's\n * `drop` is the ONE place files are delivered: an overlay drawn while dragging\n * must not handle `drop` itself, or every file arrives twice.\n *\n * Pair it with {@link DropAnywhereOverlay}, or draw your own — the overlay is\n * purely visual.\n */\nexport const useDropAnywhere = ({\n\tenabled = true,\n\tonFiles,\n\taccept,\n\tonRejected,\n}: UseDropAnywhereOptions): DropAnywhere => {\n\tconst [dragging, setDragging] = useState(false)\n\n\t// In refs, not the deps: a consumer passing an inline arrow would re-run\n\t// the effect on every render, and `depth` lives INSIDE it — resetting the\n\t// counter mid-drag reintroduces exactly the flicker it exists to prevent\n\t// (AGENTS.md §3, same rule as FileViewer's resolveViewUrl).\n\tconst onFilesRef = useRef(onFiles)\n\tonFilesRef.current = onFiles\n\tconst onRejectedRef = useRef(onRejected)\n\tonRejectedRef.current = onRejected\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetDragging(false)\n\t\t\treturn\n\t\t}\n\t\tlet depth = 0\n\t\tconst onEnter = (event: DragEvent) => {\n\t\t\tif (!event.dataTransfer?.types.includes('Files')) return\n\t\t\tdepth += 1\n\t\t\tsetDragging(true)\n\t\t}\n\t\tconst onLeave = () => {\n\t\t\tdepth = Math.max(0, depth - 1)\n\t\t\tif (depth === 0) setDragging(false)\n\t\t}\n\t\tconst onOver = (event: DragEvent) => event.preventDefault()\n\t\tconst onDrop = (event: DragEvent) => {\n\t\t\tevent.preventDefault()\n\t\t\tdepth = 0\n\t\t\tsetDragging(false)\n\t\t\tconst files = Array.from(event.dataTransfer?.files ?? [])\n\t\t\tif (files.length === 0) return\n\t\t\tconst accepted = accept\n\t\t\t\t? files.filter(file => matchesAccept(file, accept))\n\t\t\t\t: files\n\t\t\tconst rejected = files.filter(file => !accepted.includes(file))\n\t\t\tif (accepted.length > 0) onFilesRef.current(accepted)\n\t\t\tif (rejected.length > 0) onRejectedRef.current?.(rejected)\n\t\t}\n\t\twindow.addEventListener('dragenter', onEnter)\n\t\twindow.addEventListener('dragleave', onLeave)\n\t\twindow.addEventListener('dragover', onOver)\n\t\twindow.addEventListener('drop', onDrop)\n\t\treturn () => {\n\t\t\twindow.removeEventListener('dragenter', onEnter)\n\t\t\twindow.removeEventListener('dragleave', onLeave)\n\t\t\twindow.removeEventListener('dragover', onOver)\n\t\t\twindow.removeEventListener('drop', onDrop)\n\t\t}\n\t\t// Only what genuinely re-binds the listeners.\n\t}, [enabled, accept])\n\n\treturn { dragging }\n}\n"]}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { d as ScopeConfig, o as StoredFile, U as UploaderLabels } from './types-BSlJJwti.cjs';
|
|
4
|
+
import { U as UseUploaderOptions } from './useUploader-BiBdS-7y.cjs';
|
|
5
|
+
import { V as ViewableFile } from './FileViewer-ChTf7-uY.cjs';
|
|
6
|
+
|
|
7
|
+
type AvatarUploaderProps<T extends Record<string, ScopeConfig> = Record<string, ScopeConfig>> = Pick<UseUploaderOptions<T>, 'scopes' | 'scope' | 'entityId' | 'strategy' | 'rename'> & {
|
|
8
|
+
/** The stored image, if any. */
|
|
9
|
+
src?: string | null;
|
|
10
|
+
/** What shows without an image — initials, an icon. */
|
|
11
|
+
fallback?: ReactNode;
|
|
12
|
+
/** Diameter in px. @defaultValue 96 */
|
|
13
|
+
size?: number;
|
|
14
|
+
onUploaded: (stored: StoredFile) => void;
|
|
15
|
+
/** Offered as a link under the circle when there is an image to remove. */
|
|
16
|
+
onRemove?: () => void;
|
|
17
|
+
onError?: (message: string) => void;
|
|
18
|
+
alt?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
labels?: Partial<UploaderLabels>;
|
|
21
|
+
className?: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A picture that is its own control: click it, pick a file, watch the ring
|
|
25
|
+
* close around it; or drop an image straight onto it. Uploads on select — a
|
|
26
|
+
* progress ring with nothing travelling behind it would be theatre — so the
|
|
27
|
+
* caller decides when the returned `StoredFile` becomes the entity's image.
|
|
28
|
+
*/
|
|
29
|
+
declare const AvatarUploader: <T extends Record<string, ScopeConfig>>({ scopes, scope, entityId, strategy, rename, src, fallback, size, onUploaded, onRemove, onError, alt, disabled, labels, className, }: AvatarUploaderProps<T>) => react.JSX.Element;
|
|
30
|
+
|
|
31
|
+
type DropAnywhereOverlayProps = {
|
|
32
|
+
/** Usually `useDropAnywhere().dragging`. */
|
|
33
|
+
open: boolean;
|
|
34
|
+
/** Replaces the default document glyph. */
|
|
35
|
+
icon?: ReactNode;
|
|
36
|
+
title?: ReactNode;
|
|
37
|
+
hint?: ReactNode;
|
|
38
|
+
labels?: Partial<UploaderLabels>;
|
|
39
|
+
className?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The full-window invitation that pairs with {@link useDropAnywhere}. Purely
|
|
43
|
+
* visual and `pointer-events-none`: the drop lands on the window, where the
|
|
44
|
+
* hook delivers the files exactly once. Portals to `document.body` above the
|
|
45
|
+
* kit's overlays.
|
|
46
|
+
*/
|
|
47
|
+
declare const DropAnywhereOverlay: ({ open, icon, title, hint, labels, className, }: DropAnywhereOverlayProps) => react.ReactPortal | null;
|
|
48
|
+
|
|
49
|
+
type GalleryUploaderProps<T extends Record<string, ScopeConfig> = Record<string, ScopeConfig>> = Pick<UseUploaderOptions<T>, 'scopes' | 'scope' | 'entityId' | 'strategy' | 'maxFiles' | 'rename'> & {
|
|
50
|
+
/** Images already persisted, rendered as tiles ahead of the in-flight ones. */
|
|
51
|
+
stored?: StoredFile[];
|
|
52
|
+
onUploaded?: (stored: StoredFile[]) => void;
|
|
53
|
+
/** Offered on a stored tile; the caller forgets the reference (and sweeps). */
|
|
54
|
+
onRemoveStored?: (file: StoredFile) => void;
|
|
55
|
+
onError?: (message: string) => void;
|
|
56
|
+
/** Re-sign or proxy a stored url right before the viewer opens it. */
|
|
57
|
+
resolveViewUrl?: (file: ViewableFile) => Promise<string>;
|
|
58
|
+
/** Grid columns. @defaultValue 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4' */
|
|
59
|
+
columnsClassName?: string;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
labels?: Partial<UploaderLabels>;
|
|
62
|
+
className?: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A thumbnail grid over the headless hook: every tile is the file's own
|
|
66
|
+
* preview, the progress washes over it while it travels, hover reveals view
|
|
67
|
+
* and remove, and a click opens the full-screen viewer over the whole set.
|
|
68
|
+
* The add tile IS the dropzone.
|
|
69
|
+
*/
|
|
70
|
+
declare const GalleryUploader: <T extends Record<string, ScopeConfig>>({ scopes, scope, entityId, strategy, maxFiles, rename, stored, onUploaded, onRemoveStored, onError, resolveViewUrl, columnsClassName, disabled, labels, className, }: GalleryUploaderProps<T>) => react.JSX.Element;
|
|
71
|
+
|
|
72
|
+
type UseDropAnywhereOptions = {
|
|
73
|
+
/** Listen at all. Off while the surface that wants the files is closed. */
|
|
74
|
+
enabled?: boolean;
|
|
75
|
+
/** Receives the accepted files of one drop, anywhere in the window. */
|
|
76
|
+
onFiles: (files: File[]) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Same syntax as `<input accept>`: `.pdf,.xlsx,image/*`. Files outside it go
|
|
79
|
+
* to `onRejected` instead of `onFiles`; omit to accept everything.
|
|
80
|
+
*/
|
|
81
|
+
accept?: string;
|
|
82
|
+
onRejected?: (files: File[]) => void;
|
|
83
|
+
};
|
|
84
|
+
type DropAnywhere = {
|
|
85
|
+
/** A file drag is over the window — show the overlay. */
|
|
86
|
+
dragging: boolean;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* The whole window as a drop target. A depth counter on `dragenter` /
|
|
90
|
+
* `dragleave` at window level says when a file drag is present (a boolean
|
|
91
|
+
* flickers on every child boundary — see AGENTS.md §6), and the window's
|
|
92
|
+
* `drop` is the ONE place files are delivered: an overlay drawn while dragging
|
|
93
|
+
* must not handle `drop` itself, or every file arrives twice.
|
|
94
|
+
*
|
|
95
|
+
* Pair it with {@link DropAnywhereOverlay}, or draw your own — the overlay is
|
|
96
|
+
* purely visual.
|
|
97
|
+
*/
|
|
98
|
+
declare const useDropAnywhere: ({ enabled, onFiles, accept, onRejected, }: UseDropAnywhereOptions) => DropAnywhere;
|
|
99
|
+
|
|
100
|
+
export { AvatarUploader, type AvatarUploaderProps, type DropAnywhere, DropAnywhereOverlay, type DropAnywhereOverlayProps, GalleryUploader, type GalleryUploaderProps, type UseDropAnywhereOptions, useDropAnywhere };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { d as ScopeConfig, o as StoredFile, U as UploaderLabels } from './types-BSlJJwti.js';
|
|
4
|
+
import { U as UseUploaderOptions } from './useUploader-CQHpj_oI.js';
|
|
5
|
+
import { V as ViewableFile } from './FileViewer-nuD-GEdJ.js';
|
|
6
|
+
|
|
7
|
+
type AvatarUploaderProps<T extends Record<string, ScopeConfig> = Record<string, ScopeConfig>> = Pick<UseUploaderOptions<T>, 'scopes' | 'scope' | 'entityId' | 'strategy' | 'rename'> & {
|
|
8
|
+
/** The stored image, if any. */
|
|
9
|
+
src?: string | null;
|
|
10
|
+
/** What shows without an image — initials, an icon. */
|
|
11
|
+
fallback?: ReactNode;
|
|
12
|
+
/** Diameter in px. @defaultValue 96 */
|
|
13
|
+
size?: number;
|
|
14
|
+
onUploaded: (stored: StoredFile) => void;
|
|
15
|
+
/** Offered as a link under the circle when there is an image to remove. */
|
|
16
|
+
onRemove?: () => void;
|
|
17
|
+
onError?: (message: string) => void;
|
|
18
|
+
alt?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
labels?: Partial<UploaderLabels>;
|
|
21
|
+
className?: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A picture that is its own control: click it, pick a file, watch the ring
|
|
25
|
+
* close around it; or drop an image straight onto it. Uploads on select — a
|
|
26
|
+
* progress ring with nothing travelling behind it would be theatre — so the
|
|
27
|
+
* caller decides when the returned `StoredFile` becomes the entity's image.
|
|
28
|
+
*/
|
|
29
|
+
declare const AvatarUploader: <T extends Record<string, ScopeConfig>>({ scopes, scope, entityId, strategy, rename, src, fallback, size, onUploaded, onRemove, onError, alt, disabled, labels, className, }: AvatarUploaderProps<T>) => react.JSX.Element;
|
|
30
|
+
|
|
31
|
+
type DropAnywhereOverlayProps = {
|
|
32
|
+
/** Usually `useDropAnywhere().dragging`. */
|
|
33
|
+
open: boolean;
|
|
34
|
+
/** Replaces the default document glyph. */
|
|
35
|
+
icon?: ReactNode;
|
|
36
|
+
title?: ReactNode;
|
|
37
|
+
hint?: ReactNode;
|
|
38
|
+
labels?: Partial<UploaderLabels>;
|
|
39
|
+
className?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The full-window invitation that pairs with {@link useDropAnywhere}. Purely
|
|
43
|
+
* visual and `pointer-events-none`: the drop lands on the window, where the
|
|
44
|
+
* hook delivers the files exactly once. Portals to `document.body` above the
|
|
45
|
+
* kit's overlays.
|
|
46
|
+
*/
|
|
47
|
+
declare const DropAnywhereOverlay: ({ open, icon, title, hint, labels, className, }: DropAnywhereOverlayProps) => react.ReactPortal | null;
|
|
48
|
+
|
|
49
|
+
type GalleryUploaderProps<T extends Record<string, ScopeConfig> = Record<string, ScopeConfig>> = Pick<UseUploaderOptions<T>, 'scopes' | 'scope' | 'entityId' | 'strategy' | 'maxFiles' | 'rename'> & {
|
|
50
|
+
/** Images already persisted, rendered as tiles ahead of the in-flight ones. */
|
|
51
|
+
stored?: StoredFile[];
|
|
52
|
+
onUploaded?: (stored: StoredFile[]) => void;
|
|
53
|
+
/** Offered on a stored tile; the caller forgets the reference (and sweeps). */
|
|
54
|
+
onRemoveStored?: (file: StoredFile) => void;
|
|
55
|
+
onError?: (message: string) => void;
|
|
56
|
+
/** Re-sign or proxy a stored url right before the viewer opens it. */
|
|
57
|
+
resolveViewUrl?: (file: ViewableFile) => Promise<string>;
|
|
58
|
+
/** Grid columns. @defaultValue 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4' */
|
|
59
|
+
columnsClassName?: string;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
labels?: Partial<UploaderLabels>;
|
|
62
|
+
className?: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A thumbnail grid over the headless hook: every tile is the file's own
|
|
66
|
+
* preview, the progress washes over it while it travels, hover reveals view
|
|
67
|
+
* and remove, and a click opens the full-screen viewer over the whole set.
|
|
68
|
+
* The add tile IS the dropzone.
|
|
69
|
+
*/
|
|
70
|
+
declare const GalleryUploader: <T extends Record<string, ScopeConfig>>({ scopes, scope, entityId, strategy, maxFiles, rename, stored, onUploaded, onRemoveStored, onError, resolveViewUrl, columnsClassName, disabled, labels, className, }: GalleryUploaderProps<T>) => react.JSX.Element;
|
|
71
|
+
|
|
72
|
+
type UseDropAnywhereOptions = {
|
|
73
|
+
/** Listen at all. Off while the surface that wants the files is closed. */
|
|
74
|
+
enabled?: boolean;
|
|
75
|
+
/** Receives the accepted files of one drop, anywhere in the window. */
|
|
76
|
+
onFiles: (files: File[]) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Same syntax as `<input accept>`: `.pdf,.xlsx,image/*`. Files outside it go
|
|
79
|
+
* to `onRejected` instead of `onFiles`; omit to accept everything.
|
|
80
|
+
*/
|
|
81
|
+
accept?: string;
|
|
82
|
+
onRejected?: (files: File[]) => void;
|
|
83
|
+
};
|
|
84
|
+
type DropAnywhere = {
|
|
85
|
+
/** A file drag is over the window — show the overlay. */
|
|
86
|
+
dragging: boolean;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* The whole window as a drop target. A depth counter on `dragenter` /
|
|
90
|
+
* `dragleave` at window level says when a file drag is present (a boolean
|
|
91
|
+
* flickers on every child boundary — see AGENTS.md §6), and the window's
|
|
92
|
+
* `drop` is the ONE place files are delivered: an overlay drawn while dragging
|
|
93
|
+
* must not handle `drop` itself, or every file arrives twice.
|
|
94
|
+
*
|
|
95
|
+
* Pair it with {@link DropAnywhereOverlay}, or draw your own — the overlay is
|
|
96
|
+
* purely visual.
|
|
97
|
+
*/
|
|
98
|
+
declare const useDropAnywhere: ({ enabled, onFiles, accept, onRejected, }: UseDropAnywhereOptions) => DropAnywhere;
|
|
99
|
+
|
|
100
|
+
export { AvatarUploader, type AvatarUploaderProps, type DropAnywhere, DropAnywhereOverlay, type DropAnywhereOverlayProps, GalleryUploader, type GalleryUploaderProps, type UseDropAnywhereOptions, useDropAnywhere };
|