import { createContext, ReactElement, ReactNode } from 'react' import { uuidish } from '../../utils/stringutils' /** Unique identifier assigned to each selected file. */ export type TFileId = string /** * A selected file plus metadata used by the FileUpload UI. * * Notes: * - A `fileId` is generated automatically if omitted. * - `attributes.targetFilename` is the filename shown in the queue and may be updated by extensions (e.g. rename). */ export class FileItem implements FileItem { fileId: TFileId file: File attributes: Record = {} constructor(file: File, fileId?: TFileId) { this.fileId = fileId || uuidish() this.file = file this.attributes = { targetFilename: file.name, } } } /** Internal context used by queue item operations and hidden inputs. */ export type TPktFileUploadContext = { name?: string; multiple: boolean; id?: string } export const PktFileUploadContext = createContext({} as TPktFileUploadContext) /** The value type for `PktFileUpload` (`value` / `defaultValue`). */ export type TFileItemList = Array /** * Transfer status for a file when using `uploadStrategy="custom"`. * * - `progress`: `0..1` during upload, or a state (`queued`, `done`, `error`, `canceled`) * - `showProgress`: if false, UI uses indeterminate "Laster opp..." style instead of progress bar * - `lastProgress`: used to render a "failed at X%" bar when an upload errors */ export type TFileTransfer = { fileId: TFileId progress: number | 'done' | 'error' | 'canceled' | 'queued' // i tilfelle number: 0-1 errorMessage?: string showProgress?: boolean // true = show progress bar/file size, false = show "Laster opp..."/just error message lastProgress?: number // Store progress value when error occurs (0-1) } /** Upload mode: `form` posts the files on submit, `custom` posts file IDs and uploads separately. */ export type TUploadStrategy = 'custom' | 'form' export type TFileAttribute = { get: (fileId: TFileId) => T | undefined set: (fileId: TFileId, attributeValue: T | undefined) => void } export type TFileAttributes = (attributeName: string) => TFileAttribute /** * An operation that can be attached to a queue item (rename, comment, remove, etc). * * An operation may: * - be a simple action (`onClick`) * - render inline UI (e.g. rename) * - render extended UI (e.g. comments) * - render hidden inputs for form submission (`renderHidden`) */ export type TQueueItemOperation = { title: string | ((fileItem: FileItem) => string) ariaLabel?: string | ((fileItem: FileItem) => string) onClick?: (transferItem: FileItem) => void renderInlineUI?: (fileItem: FileItem, closeOperationUi: () => void) => ReactNode renderExtendedUI?: (fileItem: FileItem, closeOperationUi: () => void) => ReactNode renderContent?: (fileItem: FileItem, activateOperation?: () => void, isOperationActive?: boolean) => ReactNode renderHidden?: (fileItem: FileItem) => ReactNode symbol: symbol } /** Factory that produces a queue item operation given access to file attributes. */ export type TQueueItemExtension = (attributes: TFileAttributes) => TQueueItemOperation export type TFileAndTransfer = FileItem & Pick export type TTransferItemInProgress = TFileAndTransfer & { progress: number } /** * Custom renderer for how a queue item is displayed (e.g. filename vs thumbnail grid). * * Must return a renderable React element (or `null`). */ export type TItemRenderer = (props: { transferItem: TFileAndTransfer queueItemOperations: Array onPreviewClick?: () => void }) => ReactElement | null