@uploadista/react 0.0.20 → 0.1.0-beta.5
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/dist/components/index.d.mts +3 -3
- package/dist/components/index.mjs +1 -1
- package/dist/index.d.mts +4 -548
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/upload-zone-CH8B2-hl.mjs +2 -0
- package/dist/upload-zone-CH8B2-hl.mjs.map +1 -0
- package/dist/{uploadista-provider-Cb13AK7Z.d.mts → uploadista-provider-DwKXudoT.d.mts} +558 -15
- package/dist/uploadista-provider-DwKXudoT.d.mts.map +1 -0
- package/dist/use-upload-BgaJmdwF.mjs.map +1 -1
- package/dist/use-uploadista-client-CkzVVmFT.d.mts.map +1 -1
- package/dist/use-uploadista-events-KhJ4knam.mjs.map +1 -1
- package/package.json +12 -9
- package/src/__tests__/event-utils.test.ts +179 -0
- package/src/__tests__/setup.ts +40 -0
- package/src/__tests__/uploadista-provider.test.tsx +316 -0
- package/src/__tests__/use-drag-drop.test.tsx +476 -0
- package/src/__tests__/use-upload.test.tsx +317 -0
- package/src/__tests__/use-uploadista-client.test.tsx +208 -0
- package/src/components/flow-primitives.tsx +3 -8
- package/src/components/index.tsx +37 -6
- package/src/components/upload-primitives.tsx +22 -19
- package/src/components/upload-zone.tsx +1 -2
- package/src/hooks/event-utils.ts +1 -1
- package/src/hooks/use-upload-events.ts +2 -5
- package/src/index.ts +89 -96
- package/vitest.config.ts +16 -0
- package/dist/flow-upload-list-BJSCZ4Ty.mjs +0 -2
- package/dist/flow-upload-list-BJSCZ4Ty.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/uploadista-provider-Cb13AK7Z.d.mts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flow-upload-list-BJSCZ4Ty.mjs","names":["contextValue: FlowContextValue","contextValue: FlowInputContextValue","errors: string[]"],"sources":["../src/components/flow-primitives.tsx","../src/components/upload-list.tsx","../src/components/upload-zone.tsx","../src/components/flow-upload-list.tsx"],"sourcesContent":["\"use client\";\n\nimport type { FlowUploadOptions } from \"@uploadista/client-browser\";\nimport type {\n FlowUploadState,\n FlowUploadStatus,\n InputExecutionState,\n} from \"@uploadista/client-core\";\nimport type { TypedOutput } from \"@uploadista/core/flow\";\nimport {\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n} from \"react\";\nimport {\n type DragDropState,\n type UseDragDropReturn,\n useDragDrop,\n} from \"../hooks/use-drag-drop\";\nimport { type FlowInputMetadata, useFlow } from \"../hooks/use-flow\";\n\n// Re-export types for convenience\nexport type {\n FlowUploadState,\n FlowUploadStatus,\n InputExecutionState,\n FlowInputMetadata,\n};\n\n// ============ FLOW CONTEXT ============\n\n/**\n * Context value provided by the Flow component root.\n * Contains all flow state and actions.\n */\nexport interface FlowContextValue {\n /** Current upload state */\n state: FlowUploadState;\n /** Discovered input nodes metadata (null until discovery completes) */\n inputMetadata: FlowInputMetadata[] | null;\n /** Current input values set via setInput() */\n inputs: Record<string, unknown>;\n /** Per-input execution state for multi-input flows */\n inputStates: ReadonlyMap<string, InputExecutionState>;\n\n /** Set an input value for a specific node */\n setInput: (nodeId: string, value: unknown) => void;\n /** Execute the flow with current inputs */\n execute: () => Promise<void>;\n /** Upload a single file through the flow */\n upload: (file: File | Blob) => Promise<void>;\n /** Abort the current upload */\n abort: () => void;\n /** Pause the current upload */\n pause: () => void;\n /** Reset the upload state and clear all inputs */\n reset: () => void;\n\n /** Whether an upload or flow execution is in progress */\n isUploading: boolean;\n /** Whether the file is currently being uploaded */\n isUploadingFile: boolean;\n /** Whether the flow is currently processing */\n isProcessing: boolean;\n /** Whether the hook is discovering flow inputs */\n isDiscoveringInputs: boolean;\n}\n\nconst FlowContext = createContext<FlowContextValue | null>(null);\n\n/**\n * Hook to access flow context from within a Flow component.\n * @throws Error if used outside of a Flow component\n */\nexport function useFlowContext(): FlowContextValue {\n const context = useContext(FlowContext);\n if (!context) {\n throw new Error(\n \"useFlowContext must be used within a <Flow> component. \" +\n \"Wrap your component tree with <Flow flowId=\\\"...\\\" storageId=\\\"...\\\">\",\n );\n }\n return context;\n}\n\n// ============ FLOW INPUT CONTEXT ============\n\n/**\n * Context value for a specific input node within a Flow.\n */\nexport interface FlowInputContextValue {\n /** Input node ID */\n nodeId: string;\n /** Input metadata from flow discovery */\n metadata: FlowInputMetadata;\n /** Current value for this input */\n value: unknown;\n /** Set the value for this input */\n setValue: (value: unknown) => void;\n /** Per-input execution state (if available) */\n state: InputExecutionState | undefined;\n}\n\nconst FlowInputContext = createContext<FlowInputContextValue | null>(null);\n\n/**\n * Hook to access flow input context from within a Flow.Input component.\n * @throws Error if used outside of a Flow.Input component\n */\nexport function useFlowInputContext(): FlowInputContextValue {\n const context = useContext(FlowInputContext);\n if (!context) {\n throw new Error(\n \"useFlowInputContext must be used within a <Flow.Input> component. \" +\n \"Wrap your component with <Flow.Input nodeId=\\\"...\\\">\",\n );\n }\n return context;\n}\n\n// ============ FLOW ROOT COMPONENT ============\n\n/**\n * Props for the Flow root component.\n */\nexport interface FlowProps {\n /** Flow ID to execute */\n flowId: string;\n /** Storage ID for file uploads */\n storageId: string;\n /** Optional output node ID to wait for */\n outputNodeId?: string;\n /** Optional metadata to include with the flow execution */\n metadata?: Record<string, string>;\n /** Called when flow completes successfully */\n onSuccess?: (outputs: TypedOutput[]) => void;\n /** Called when flow fails */\n onError?: (error: Error) => void;\n /** Called on upload progress */\n onProgress?: (\n uploadId: string,\n bytesUploaded: number,\n totalBytes: number | null,\n ) => void;\n /** Called when flow completes with all outputs */\n onFlowComplete?: (outputs: TypedOutput[]) => void;\n /** Called when upload is aborted */\n onAbort?: () => void;\n /** Children to render */\n children: ReactNode;\n}\n\n/**\n * Root component for flow-based uploads.\n * Provides context for all Flow sub-components.\n *\n * @example\n * ```tsx\n * <Flow flowId=\"image-optimizer\" storageId=\"s3\" onSuccess={handleSuccess}>\n * <Flow.DropZone accept=\"image/*\">\n * {({ isDragging, getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * {isDragging ? \"Drop here\" : \"Drag or click\"}\n * </div>\n * )}\n * </Flow.DropZone>\n * </Flow>\n * ```\n */\nfunction FlowRoot({\n flowId,\n storageId,\n outputNodeId,\n metadata,\n onSuccess,\n onError,\n onProgress,\n onFlowComplete,\n onAbort,\n children,\n}: FlowProps) {\n const options: FlowUploadOptions = {\n flowConfig: {\n flowId,\n storageId,\n outputNodeId,\n metadata,\n },\n onSuccess,\n onError,\n onProgress,\n onFlowComplete,\n onAbort,\n };\n\n const flow = useFlow(options);\n\n const contextValue: FlowContextValue = {\n state: flow.state,\n inputMetadata: flow.inputMetadata,\n inputs: flow.inputs,\n inputStates: flow.inputStates,\n setInput: flow.setInput,\n execute: flow.execute,\n upload: flow.upload,\n abort: flow.abort,\n pause: flow.pause,\n reset: flow.reset,\n isUploading: flow.isUploading,\n isUploadingFile: flow.isUploadingFile,\n isProcessing: flow.isProcessing,\n isDiscoveringInputs: flow.isDiscoveringInputs,\n };\n\n return (\n <FlowContext.Provider value={contextValue}>{children}</FlowContext.Provider>\n );\n}\n\n// ============ DROP ZONE PRIMITIVE ============\n\n/**\n * Render props for Flow.DropZone component.\n */\nexport interface FlowDropZoneRenderProps {\n /** Whether files are being dragged over */\n isDragging: boolean;\n /** Whether drag is over the zone */\n isOver: boolean;\n /** Upload progress (0-100) */\n progress: number;\n /** Current flow status */\n status: FlowUploadStatus;\n /** Props to spread on the drop zone container */\n getRootProps: () => UseDragDropReturn[\"dragHandlers\"];\n /** Props to spread on the hidden file input */\n getInputProps: () => UseDragDropReturn[\"inputProps\"];\n /** Open file picker programmatically */\n openFilePicker: () => void;\n /** Current drag-drop state */\n dragDropState: DragDropState;\n}\n\n/**\n * Props for Flow.DropZone component.\n */\nexport interface FlowDropZoneProps {\n /** Accepted file types (e.g., \"image/*\", \".pdf\") */\n accept?: string;\n /** Maximum file size in bytes */\n maxFileSize?: number;\n /** Render function receiving drop zone state */\n children: (props: FlowDropZoneRenderProps) => ReactNode;\n}\n\n/**\n * Drop zone for single-file uploads within a Flow.\n * Automatically calls flow.upload() when a file is dropped.\n *\n * @example\n * ```tsx\n * <Flow.DropZone accept=\"image/*\">\n * {({ isDragging, progress, getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * {isDragging ? \"Drop here\" : `Progress: ${progress}%`}\n * </div>\n * )}\n * </Flow.DropZone>\n * ```\n */\nfunction FlowDropZone({ accept, maxFileSize, children }: FlowDropZoneProps) {\n const flow = useFlowContext();\n\n const dragDrop = useDragDrop({\n onFilesReceived: (files) => {\n const file = files[0];\n if (file) {\n flow.upload(file);\n }\n },\n accept: accept ? accept.split(\",\").map((t) => t.trim()) : undefined,\n maxFileSize,\n multiple: false,\n });\n\n const renderProps: FlowDropZoneRenderProps = {\n isDragging: dragDrop.state.isDragging,\n isOver: dragDrop.state.isOver,\n progress: flow.state.progress,\n status: flow.state.status,\n getRootProps: () => dragDrop.dragHandlers,\n getInputProps: () => dragDrop.inputProps,\n openFilePicker: dragDrop.openFilePicker,\n dragDropState: dragDrop.state,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ INPUTS DISCOVERY PRIMITIVE ============\n\n/**\n * Render props for Flow.Inputs component.\n */\nexport interface FlowInputsRenderProps {\n /** Discovered input metadata */\n inputs: FlowInputMetadata[];\n /** Whether inputs are still being discovered */\n isLoading: boolean;\n}\n\n/**\n * Props for Flow.Inputs component.\n */\nexport interface FlowInputsProps {\n /** Render function receiving discovered inputs */\n children: (props: FlowInputsRenderProps) => ReactNode;\n}\n\n/**\n * Auto-discovers flow input nodes and provides them via render props.\n *\n * @example\n * ```tsx\n * <Flow.Inputs>\n * {({ inputs, isLoading }) => (\n * isLoading ? <Spinner /> : (\n * inputs.map(input => (\n * <Flow.Input key={input.nodeId} nodeId={input.nodeId}>\n * ...\n * </Flow.Input>\n * ))\n * )\n * )}\n * </Flow.Inputs>\n * ```\n */\nfunction FlowInputs({ children }: FlowInputsProps) {\n const flow = useFlowContext();\n\n const renderProps: FlowInputsRenderProps = {\n inputs: flow.inputMetadata ?? [],\n isLoading: flow.isDiscoveringInputs,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ INPUT PRIMITIVE ============\n\n/**\n * Props for Flow.Input component.\n */\nexport interface FlowInputProps {\n /** Input node ID */\n nodeId: string;\n /** Children (can be render function or regular children) */\n children: ReactNode | ((props: FlowInputContextValue) => ReactNode);\n}\n\n/**\n * Scoped input context provider for a specific input node.\n * Children can access input-specific state via useFlowInputContext().\n *\n * @example\n * ```tsx\n * <Flow.Input nodeId=\"video-input\">\n * {({ metadata, value, setValue }) => (\n * <div>\n * <label>{metadata.nodeName}</label>\n * <Flow.Input.DropZone>...</Flow.Input.DropZone>\n * </div>\n * )}\n * </Flow.Input>\n * ```\n */\nfunction FlowInput({ nodeId, children }: FlowInputProps) {\n const flow = useFlowContext();\n\n const metadata = flow.inputMetadata?.find((m) => m.nodeId === nodeId);\n\n if (!metadata) {\n // Input not yet discovered or doesn't exist\n return null;\n }\n\n const contextValue: FlowInputContextValue = {\n nodeId,\n metadata,\n value: flow.inputs[nodeId],\n setValue: (value) => flow.setInput(nodeId, value),\n state: flow.inputStates.get(nodeId),\n };\n\n return (\n <FlowInputContext.Provider value={contextValue}>\n {typeof children === \"function\" ? children(contextValue) : children}\n </FlowInputContext.Provider>\n );\n}\n\n// ============ INPUT DROP ZONE PRIMITIVE ============\n\n/**\n * Render props for Flow.Input.DropZone component.\n */\nexport interface FlowInputDropZoneRenderProps {\n /** Whether files are being dragged over */\n isDragging: boolean;\n /** Whether drag is over the zone */\n isOver: boolean;\n /** Current value for this input */\n value: unknown;\n /** Per-input progress (if available) */\n progress: number;\n /** Per-input status (if available) */\n status: string;\n /** Props to spread on the drop zone container */\n getRootProps: () => UseDragDropReturn[\"dragHandlers\"];\n /** Props to spread on the hidden file input */\n getInputProps: () => UseDragDropReturn[\"inputProps\"];\n /** Open file picker programmatically */\n openFilePicker: () => void;\n /** Current drag-drop state */\n dragDropState: DragDropState;\n}\n\n/**\n * Props for Flow.Input.DropZone component.\n */\nexport interface FlowInputDropZoneProps {\n /** Accepted file types (e.g., \"image/*\", \".pdf\") */\n accept?: string;\n /** Maximum file size in bytes */\n maxFileSize?: number;\n /** Render function receiving drop zone state */\n children: (props: FlowInputDropZoneRenderProps) => ReactNode;\n}\n\n/**\n * Drop zone for a specific input within a Flow.Input.\n * Sets the input value but does NOT trigger upload until Flow.Submit is clicked.\n */\nfunction FlowInputDropZone({\n accept,\n maxFileSize,\n children,\n}: FlowInputDropZoneProps) {\n const input = useFlowInputContext();\n\n const dragDrop = useDragDrop({\n onFilesReceived: (files) => {\n const file = files[0];\n if (file) {\n input.setValue(file);\n }\n },\n accept: accept ? accept.split(\",\").map((t) => t.trim()) : undefined,\n maxFileSize,\n multiple: false,\n });\n\n const renderProps: FlowInputDropZoneRenderProps = {\n isDragging: dragDrop.state.isDragging,\n isOver: dragDrop.state.isOver,\n value: input.value,\n progress: input.state?.progress ?? 0,\n status: input.state?.status ?? \"idle\",\n getRootProps: () => dragDrop.dragHandlers,\n getInputProps: () => dragDrop.inputProps,\n openFilePicker: dragDrop.openFilePicker,\n dragDropState: dragDrop.state,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ INPUT URL FIELD PRIMITIVE ============\n\n/**\n * Props for Flow.Input.UrlField component.\n */\nexport interface FlowInputUrlFieldProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"onChange\" | \"type\"\n > {\n /** Placeholder text */\n placeholder?: string;\n}\n\n/**\n * URL input field for a specific input within a Flow.Input.\n * Automatically binds to the input context value.\n */\nfunction FlowInputUrlField({\n placeholder = \"https://example.com/file\",\n ...props\n}: FlowInputUrlFieldProps) {\n const input = useFlowInputContext();\n const isUrl = typeof input.value === \"string\";\n\n return (\n <input\n type=\"url\"\n value={isUrl ? (input.value as string) : \"\"}\n onChange={(e) => input.setValue(e.target.value)}\n placeholder={placeholder}\n {...props}\n />\n );\n}\n\n// ============ INPUT PREVIEW PRIMITIVE ============\n\n/**\n * Render props for Flow.Input.Preview component.\n */\nexport interface FlowInputPreviewRenderProps {\n /** Current value */\n value: unknown;\n /** Whether value is a File */\n isFile: boolean;\n /** Whether value is a URL string */\n isUrl: boolean;\n /** File name (if value is File) */\n fileName: string | null;\n /** File size in bytes (if value is File) */\n fileSize: number | null;\n /** Clear the input value */\n clear: () => void;\n}\n\n/**\n * Props for Flow.Input.Preview component.\n */\nexport interface FlowInputPreviewProps {\n /** Render function receiving preview state */\n children: (props: FlowInputPreviewRenderProps) => ReactNode;\n}\n\n/**\n * Preview component for showing the selected value within a Flow.Input.\n */\nfunction FlowInputPreview({ children }: FlowInputPreviewProps) {\n const input = useFlowInputContext();\n\n const isFile = input.value instanceof File;\n const isUrl = typeof input.value === \"string\" && input.value.length > 0;\n\n const renderProps: FlowInputPreviewRenderProps = {\n value: input.value,\n isFile,\n isUrl,\n fileName: isFile ? (input.value as File).name : null,\n fileSize: isFile ? (input.value as File).size : null,\n clear: () => input.setValue(undefined),\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ PROGRESS PRIMITIVE ============\n\n/**\n * Render props for Flow.Progress component.\n */\nexport interface FlowProgressRenderProps {\n /** Progress percentage (0-100) */\n progress: number;\n /** Bytes uploaded so far */\n bytesUploaded: number;\n /** Total bytes to upload (null if unknown) */\n totalBytes: number | null;\n /** Current status */\n status: FlowUploadStatus;\n}\n\n/**\n * Props for Flow.Progress component.\n */\nexport interface FlowProgressProps {\n /** Render function receiving progress state */\n children: (props: FlowProgressRenderProps) => ReactNode;\n}\n\n/**\n * Progress display component within a Flow.\n */\nfunction FlowProgress({ children }: FlowProgressProps) {\n const flow = useFlowContext();\n\n const renderProps: FlowProgressRenderProps = {\n progress: flow.state.progress,\n bytesUploaded: flow.state.bytesUploaded,\n totalBytes: flow.state.totalBytes,\n status: flow.state.status,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ STATUS PRIMITIVE ============\n\n/**\n * Render props for Flow.Status component.\n */\nexport interface FlowStatusRenderProps {\n /** Current status */\n status: FlowUploadStatus;\n /** Current node being processed (if any) */\n currentNodeName: string | null;\n /** Current node type (if any) */\n currentNodeType: string | null;\n /** Error (if status is error) */\n error: Error | null;\n /** Job ID (if started) */\n jobId: string | null;\n /** Whether flow has started */\n flowStarted: boolean;\n /** Flow outputs (if completed) */\n flowOutputs: TypedOutput[] | null;\n}\n\n/**\n * Props for Flow.Status component.\n */\nexport interface FlowStatusProps {\n /** Render function receiving status state */\n children: (props: FlowStatusRenderProps) => ReactNode;\n}\n\n/**\n * Status display component within a Flow.\n */\nfunction FlowStatus({ children }: FlowStatusProps) {\n const flow = useFlowContext();\n\n const renderProps: FlowStatusRenderProps = {\n status: flow.state.status,\n currentNodeName: flow.state.currentNodeName,\n currentNodeType: flow.state.currentNodeType,\n error: flow.state.error,\n jobId: flow.state.jobId,\n flowStarted: flow.state.flowStarted,\n flowOutputs: flow.state.flowOutputs,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ ERROR PRIMITIVE ============\n\n/**\n * Render props for Flow.Error component.\n */\nexport interface FlowErrorRenderProps {\n /** Error object (null if no error) */\n error: Error | null;\n /** Whether there is an error */\n hasError: boolean;\n /** Error message */\n message: string | null;\n /** Reset the flow */\n reset: () => void;\n}\n\n/**\n * Props for Flow.Error component.\n */\nexport interface FlowErrorProps {\n /** Render function receiving error state */\n children: (props: FlowErrorRenderProps) => ReactNode;\n}\n\n/**\n * Error display component within a Flow.\n */\nfunction FlowError({ children }: FlowErrorProps) {\n const flow = useFlowContext();\n\n const renderProps: FlowErrorRenderProps = {\n error: flow.state.error,\n hasError: flow.state.status === \"error\",\n message: flow.state.error?.message ?? null,\n reset: flow.reset,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ ACTION PRIMITIVES ============\n\n/**\n * Props for Flow.Submit component.\n */\nexport interface FlowSubmitProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Submit button that executes the flow with current inputs.\n * Automatically disabled when uploading.\n */\nfunction FlowSubmit({ children, disabled, ...props }: FlowSubmitProps) {\n const flow = useFlowContext();\n\n const handleClick = useCallback(() => {\n flow.execute();\n }, [flow]);\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || flow.isUploading}\n {...props}\n >\n {children}\n </button>\n );\n}\n\n/**\n * Props for Flow.Cancel component.\n */\nexport interface FlowCancelProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Cancel button that aborts the current upload.\n */\nfunction FlowCancel({ children, ...props }: FlowCancelProps) {\n const flow = useFlowContext();\n\n const handleClick = useCallback(() => {\n flow.abort();\n }, [flow]);\n\n return (\n <button type=\"button\" onClick={handleClick} {...props}>\n {children}\n </button>\n );\n}\n\n/**\n * Props for Flow.Reset component.\n */\nexport interface FlowResetProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Reset button that clears all inputs and resets to idle state.\n */\nfunction FlowReset({ children, ...props }: FlowResetProps) {\n const flow = useFlowContext();\n\n const handleClick = useCallback(() => {\n flow.reset();\n }, [flow]);\n\n return (\n <button type=\"button\" onClick={handleClick} {...props}>\n {children}\n </button>\n );\n}\n\n// ============ COMPOUND COMPONENT EXPORT ============\n\n/**\n * Flow compound component for flow-based file uploads.\n *\n * Provides a composable, headless API for building flow upload interfaces.\n * All sub-components use render props for complete UI control.\n *\n * @example Simple Drop Zone\n * ```tsx\n * <Flow flowId=\"image-optimizer\" storageId=\"s3\" onSuccess={handleSuccess}>\n * <Flow.DropZone accept=\"image/*\">\n * {({ isDragging, progress, getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * {isDragging ? \"Drop here\" : \"Drag or click\"}\n * {progress > 0 && <progress value={progress} max={100} />}\n * </div>\n * )}\n * </Flow.DropZone>\n * </Flow>\n * ```\n *\n * @example Multi-Input Flow\n * ```tsx\n * <Flow flowId=\"video-processor\" storageId=\"s3\">\n * <Flow.Inputs>\n * {({ inputs }) => inputs.map(input => (\n * <Flow.Input key={input.nodeId} nodeId={input.nodeId}>\n * {({ metadata }) => (\n * <div>\n * <label>{metadata.nodeName}</label>\n * <Flow.Input.DropZone accept=\"video/*\">\n * {({ getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * </div>\n * )}\n * </Flow.Input.DropZone>\n * </div>\n * )}\n * </Flow.Input>\n * ))}\n * </Flow.Inputs>\n * <Flow.Submit>Process</Flow.Submit>\n * </Flow>\n * ```\n */\nexport const Flow = Object.assign(FlowRoot, {\n DropZone: FlowDropZone,\n Inputs: FlowInputs,\n Input: Object.assign(FlowInput, {\n DropZone: FlowInputDropZone,\n UrlField: FlowInputUrlField,\n Preview: FlowInputPreview,\n }),\n Progress: FlowProgress,\n Status: FlowStatus,\n Error: FlowError,\n Submit: FlowSubmit,\n Cancel: FlowCancel,\n Reset: FlowReset,\n});\n","import type React from \"react\";\nimport type {\n UploadItem,\n UseMultiUploadReturn,\n} from \"../hooks/use-multi-upload\";\nimport type { UploadStatus } from \"../hooks/use-upload\";\n\n/**\n * Render props passed to the UploadList children function.\n * Provides organized access to upload items, status groupings, and actions.\n *\n * @property items - All upload items (filtered and sorted if configured)\n * @property itemsByStatus - Upload items grouped by their current status\n * @property multiUpload - Complete multi-upload hook instance\n * @property actions - Helper functions for common item operations\n * @property actions.removeItem - Remove an item from the list\n * @property actions.retryItem - Retry a failed upload\n * @property actions.abortItem - Cancel an active upload\n * @property actions.startItem - Begin uploading an idle item\n */\nexport interface UploadListRenderProps {\n /**\n * All upload items\n */\n items: UploadItem[];\n\n /**\n * Items filtered by status\n */\n itemsByStatus: {\n idle: UploadItem[];\n uploading: UploadItem[];\n success: UploadItem[];\n error: UploadItem[];\n aborted: UploadItem[];\n };\n\n /**\n * Multi-upload state and controls\n */\n multiUpload: UseMultiUploadReturn;\n\n /**\n * Helper functions for item management\n */\n actions: {\n removeItem: (id: string) => void;\n retryItem: (item: UploadItem) => void;\n abortItem: (item: UploadItem) => void;\n startItem: (item: UploadItem) => void;\n };\n}\n\n/**\n * Props for the UploadList component.\n *\n * @property multiUpload - Multi-upload hook instance to display\n * @property filter - Optional function to filter which items to show\n * @property sortBy - Optional comparator function to sort items\n * @property children - Render function receiving list state and actions\n */\nexport interface UploadListProps {\n /**\n * Multi-upload instance from useMultiUpload hook\n */\n multiUpload: UseMultiUploadReturn;\n\n /**\n * Optional filter for which items to display\n */\n filter?: (item: UploadItem) => boolean;\n\n /**\n * Optional sorting function for items\n */\n sortBy?: (a: UploadItem, b: UploadItem) => number;\n\n /**\n * Render prop that receives upload list state and actions\n */\n children: (props: UploadListRenderProps) => React.ReactNode;\n}\n\n/**\n * Headless upload list component that provides flexible rendering for upload items.\n * Uses render props pattern to give full control over how upload items are displayed.\n *\n * @param props - Upload list configuration and render prop\n * @returns Rendered upload list using the provided render prop\n *\n * @example\n * ```tsx\n * // Basic upload list with progress bars\n * <UploadList multiUpload={multiUpload}>\n * {({ items, actions }) => (\n * <div>\n * <h3>Upload Queue ({items.length} files)</h3>\n * {items.map((item) => (\n * <div key={item.id} style={{\n * padding: '1rem',\n * border: '1px solid #ccc',\n * marginBottom: '0.5rem',\n * borderRadius: '4px'\n * }}>\n * <div style={{ display: 'flex', justifyContent: 'space-between' }}>\n * <span>{item.file.name}</span>\n * <span>{item.state.status}</span>\n * </div>\n *\n * {item.state.status === 'uploading' && (\n * <div>\n * <progress value={item.state.progress} max={100} />\n * <span>{item.state.progress}%</span>\n * <button onClick={() => actions.abortItem(item)}>Cancel</button>\n * </div>\n * )}\n *\n * {item.state.status === 'error' && (\n * <div>\n * <p style={{ color: 'red' }}>Error: {item.state.error?.message}</p>\n * <button onClick={() => actions.retryItem(item)}>Retry</button>\n * <button onClick={() => actions.removeItem(item.id)}>Remove</button>\n * </div>\n * )}\n *\n * {item.state.status === 'success' && (\n * <div>\n * <p style={{ color: 'green' }}>✓ Uploaded successfully</p>\n * <button onClick={() => actions.removeItem(item.id)}>Remove</button>\n * </div>\n * )}\n *\n * {item.state.status === 'idle' && (\n * <div>\n * <button onClick={() => actions.startItem(item)}>Start Upload</button>\n * <button onClick={() => actions.removeItem(item.id)}>Remove</button>\n * </div>\n * )}\n * </div>\n * ))}\n * </div>\n * )}\n * </UploadList>\n *\n * // Upload list with status filtering and sorting\n * <UploadList\n * multiUpload={multiUpload}\n * filter={(item) => item.state.status !== 'success'} // Hide successful uploads\n * sortBy={(a, b) => {\n * // Sort by status priority, then by filename\n * const statusPriority = { error: 0, uploading: 1, idle: 2, success: 3, aborted: 4 };\n * const aPriority = statusPriority[a.state.status];\n * const bPriority = statusPriority[b.state.status];\n *\n * if (aPriority !== bPriority) {\n * return aPriority - bPriority;\n * }\n *\n * return a.file.name.localeCompare(b.file.name);\n * }}\n * >\n * {({ items, itemsByStatus, multiUpload, actions }) => (\n * <div>\n * {itemsByStatus.error.length > 0 && (\n * <div>\n * <h4 style={{ color: 'red' }}>Failed Uploads ({itemsByStatus.error.length})</h4>\n * {itemsByStatus.error.map((item) => (\n * <UploadListItem key={item.id} item={item} actions={actions} />\n * ))}\n * </div>\n * )}\n *\n * {itemsByStatus.uploading.length > 0 && (\n * <div>\n * <h4>Uploading ({itemsByStatus.uploading.length})</h4>\n * {itemsByStatus.uploading.map((item) => (\n * <UploadListItem key={item.id} item={item} actions={actions} />\n * ))}\n * </div>\n * )}\n *\n * {itemsByStatus.idle.length > 0 && (\n * <div>\n * <h4>Pending ({itemsByStatus.idle.length})</h4>\n * {itemsByStatus.idle.map((item) => (\n * <UploadListItem key={item.id} item={item} actions={actions} />\n * ))}\n * </div>\n * )}\n * </div>\n * )}\n * </UploadList>\n * ```\n */\nexport function UploadList({\n multiUpload,\n filter,\n sortBy,\n children,\n}: UploadListProps) {\n // Apply filtering\n let items = multiUpload.items;\n if (filter) {\n items = items.filter(filter);\n }\n\n // Apply sorting\n if (sortBy) {\n items = [...items].sort(sortBy);\n }\n\n // Group items by status\n const itemsByStatus = {\n idle: items.filter((item) => item.state.status === \"idle\"),\n uploading: items.filter((item) => item.state.status === \"uploading\"),\n success: items.filter((item) => item.state.status === \"success\"),\n error: items.filter((item) => item.state.status === \"error\"),\n aborted: items.filter((item) => item.state.status === \"aborted\"),\n };\n\n // Create action helpers\n const actions = {\n removeItem: (id: string) => {\n multiUpload.removeItem(id);\n },\n retryItem: (_item: UploadItem) => {\n // Retry failed uploads using multiUpload method\n multiUpload.retryFailed();\n },\n abortItem: (item: UploadItem) => {\n // Remove the item to effectively abort it\n multiUpload.removeItem(item.id);\n },\n startItem: (_item: UploadItem) => {\n // Start all pending uploads\n multiUpload.startAll();\n },\n };\n\n // Create render props object\n const renderProps: UploadListRenderProps = {\n items,\n itemsByStatus,\n multiUpload,\n actions,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n/**\n * Props for the SimpleUploadListItem component.\n *\n * @property item - The upload item to display\n * @property actions - Action functions from UploadList render props\n * @property className - Additional CSS class name\n * @property style - Inline styles for the item container\n * @property showDetails - Whether to display file size and upload details\n */\nexport interface SimpleUploadListItemProps {\n /**\n * The upload item to render\n */\n item: UploadItem;\n\n /**\n * Actions from UploadList render props\n */\n actions: UploadListRenderProps[\"actions\"];\n\n /**\n * Additional CSS class name\n */\n className?: string;\n\n /**\n * Inline styles\n */\n style?: React.CSSProperties;\n\n /**\n * Whether to show detailed information (file size, speed, etc.)\n */\n showDetails?: boolean;\n}\n\n/**\n * Pre-styled upload list item component with status indicators and action buttons.\n * Displays file info, progress, errors, and contextual actions based on upload status.\n *\n * Features:\n * - Status-specific color coding and icons\n * - Progress bar for active uploads\n * - Error message display\n * - File size formatting\n * - Contextual action buttons (start, cancel, retry, remove)\n *\n * @param props - Upload item and configuration\n * @returns Styled upload list item component\n *\n * @example\n * ```tsx\n * // Use with UploadList\n * <UploadList multiUpload={multiUpload}>\n * {({ items, actions }) => (\n * <div>\n * {items.map((item) => (\n * <SimpleUploadListItem\n * key={item.id}\n * item={item}\n * actions={actions}\n * showDetails={true}\n * />\n * ))}\n * </div>\n * )}\n * </UploadList>\n *\n * // Custom styling\n * <SimpleUploadListItem\n * item={uploadItem}\n * actions={actions}\n * className=\"my-upload-item\"\n * style={{ borderRadius: '12px', margin: '1rem' }}\n * showDetails={true}\n * />\n * ```\n */\nexport function SimpleUploadListItem({\n item,\n actions,\n className = \"\",\n style = {},\n showDetails = true,\n}: SimpleUploadListItemProps) {\n const getStatusColor = (status: UploadStatus) => {\n switch (status) {\n case \"idle\":\n return \"#6c757d\";\n case \"uploading\":\n return \"#007bff\";\n case \"success\":\n return \"#28a745\";\n case \"error\":\n return \"#dc3545\";\n case \"aborted\":\n return \"#6c757d\";\n default:\n return \"#6c757d\";\n }\n };\n\n const getStatusIcon = (status: UploadStatus) => {\n switch (status) {\n case \"idle\":\n return \"⏳\";\n case \"uploading\":\n return \"📤\";\n case \"success\":\n return \"✅\";\n case \"error\":\n return \"❌\";\n case \"aborted\":\n return \"⏹️\";\n default:\n return \"❓\";\n }\n };\n\n const formatFileSize = (bytes: number) => {\n if (bytes === 0) return \"0 Bytes\";\n const k = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;\n };\n\n return (\n <div\n className={`upload-list-item upload-list-item--${item.state.status} ${className}`}\n style={{\n padding: \"12px\",\n border: \"1px solid #e0e0e0\",\n borderRadius: \"6px\",\n marginBottom: \"8px\",\n backgroundColor: \"#fff\",\n transition: \"all 0.2s ease\",\n ...style,\n }}\n >\n {/* Header with filename and status */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: \"8px\",\n }}\n >\n <div\n style={{ display: \"flex\", alignItems: \"center\", gap: \"8px\", flex: 1 }}\n >\n <span style={{ fontSize: \"16px\" }}>\n {getStatusIcon(item.state.status)}\n </span>\n <span style={{ fontWeight: \"500\", flex: 1 }}>\n {item.file instanceof File ? item.file.name : \"File\"}\n </span>\n </div>\n <span\n style={{\n fontSize: \"12px\",\n color: getStatusColor(item.state.status),\n fontWeight: \"500\",\n textTransform: \"uppercase\",\n }}\n >\n {item.state.status}\n </span>\n </div>\n\n {/* Progress bar for uploading items */}\n {item.state.status === \"uploading\" && (\n <div style={{ marginBottom: \"8px\" }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: \"4px\",\n }}\n >\n <span style={{ fontSize: \"12px\", color: \"#666\" }}>\n {item.state.progress}%\n </span>\n {showDetails && item.state.totalBytes && (\n <span style={{ fontSize: \"12px\", color: \"#666\" }}>\n {formatFileSize(item.state.bytesUploaded)} /{\" \"}\n {formatFileSize(item.state.totalBytes)}\n </span>\n )}\n </div>\n <div\n style={{\n width: \"100%\",\n height: \"6px\",\n backgroundColor: \"#e0e0e0\",\n borderRadius: \"3px\",\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n width: `${item.state.progress}%`,\n height: \"100%\",\n backgroundColor: \"#007bff\",\n transition: \"width 0.2s ease\",\n }}\n />\n </div>\n </div>\n )}\n\n {/* Details section */}\n {showDetails && (\n <div style={{ fontSize: \"12px\", color: \"#666\", marginBottom: \"8px\" }}>\n {item.state.totalBytes && (\n <span>{formatFileSize(item.state.totalBytes)}</span>\n )}\n {item.state.status === \"uploading\" && item.state.progress > 0 && (\n <span> • Progress: {item.state.progress}%</span>\n )}\n {item.state.status === \"error\" && item.state.error && (\n <div style={{ color: \"#dc3545\", marginTop: \"4px\" }}>\n {item.state.error.message}\n </div>\n )}\n </div>\n )}\n\n {/* Action buttons */}\n <div style={{ display: \"flex\", gap: \"8px\", flexWrap: \"wrap\" }}>\n {item.state.status === \"idle\" && (\n <>\n <button\n type=\"button\"\n onClick={() => actions.startItem(item)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #007bff\",\n backgroundColor: \"#007bff\",\n color: \"white\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Start\n </button>\n <button\n type=\"button\"\n onClick={() => actions.removeItem(item.id)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #6c757d\",\n backgroundColor: \"transparent\",\n color: \"#6c757d\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Remove\n </button>\n </>\n )}\n\n {item.state.status === \"uploading\" && (\n <button\n type=\"button\"\n onClick={() => actions.abortItem(item)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #dc3545\",\n backgroundColor: \"transparent\",\n color: \"#dc3545\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Cancel\n </button>\n )}\n\n {item.state.status === \"error\" && (\n <>\n <button\n type=\"button\"\n onClick={() => actions.retryItem(item)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #28a745\",\n backgroundColor: \"#28a745\",\n color: \"white\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Retry\n </button>\n <button\n type=\"button\"\n onClick={() => actions.removeItem(item.id)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #6c757d\",\n backgroundColor: \"transparent\",\n color: \"#6c757d\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Remove\n </button>\n </>\n )}\n\n {item.state.status === \"success\" && (\n <button\n type=\"button\"\n onClick={() => actions.removeItem(item.id)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #6c757d\",\n backgroundColor: \"transparent\",\n color: \"#6c757d\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Remove\n </button>\n )}\n\n {item.state.status === \"aborted\" && (\n <>\n <button\n type=\"button\"\n onClick={() => actions.retryItem(item)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #007bff\",\n backgroundColor: \"#007bff\",\n color: \"white\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Retry\n </button>\n <button\n type=\"button\"\n onClick={() => actions.removeItem(item.id)}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n border: \"1px solid #6c757d\",\n backgroundColor: \"transparent\",\n color: \"#6c757d\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n }}\n >\n Remove\n </button>\n </>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Upload Zone Components\n *\n * Enhanced error handling features:\n * - MIME type validation with detailed error messages\n * - File count validation (single vs multiple mode)\n * - Custom validation error callbacks\n * - Built-in error display in SimpleUploadZone\n * - Configurable error styling\n */\n\nimport type React from \"react\";\nimport { useCallback } from \"react\";\nimport type {\n DragDropOptions,\n UseDragDropReturn,\n} from \"../hooks/use-drag-drop\";\nimport { useDragDrop } from \"../hooks/use-drag-drop\";\nimport type {\n MultiUploadOptions,\n UseMultiUploadReturn,\n} from \"../hooks/use-multi-upload\";\nimport { useMultiUpload } from \"../hooks/use-multi-upload\";\nimport type { UseUploadOptions, UseUploadReturn } from \"../hooks/use-upload\";\nimport { useUpload } from \"../hooks/use-upload\";\n\n/**\n * Render props passed to the UploadZone children function.\n * Provides access to drag-drop state, upload controls, and helper functions.\n *\n * @property dragDrop - Complete drag-and-drop state and event handlers\n * @property upload - Single upload hook (null when multiple=true)\n * @property multiUpload - Multi-upload hook (null when multiple=false)\n * @property openFilePicker - Programmatically trigger file selection dialog\n * @property isActive - True when dragging over zone or files selected\n * @property isProcessing - True when uploads are in progress\n */\nexport interface UploadZoneRenderProps {\n /**\n * Drag and drop state and handlers\n */\n dragDrop: UseDragDropReturn;\n\n /**\n * Single upload functionality (if not using multi-upload)\n */\n upload: UseUploadReturn | null;\n\n /**\n * Multi-upload functionality (if using multi-upload)\n */\n multiUpload: UseMultiUploadReturn | null;\n\n /**\n * Helper function to open file picker\n */\n openFilePicker: () => void;\n\n /**\n * Whether the zone is currently active (dragging or uploading)\n */\n isActive: boolean;\n\n /**\n * Whether files are being processed\n */\n isProcessing: boolean;\n}\n\n/**\n * Props for the UploadZone component.\n * Combines drag-drop options with upload configuration.\n *\n * @property multiple - Enable multi-file selection and upload (default: true)\n * @property multiUploadOptions - Configuration for multi-upload mode\n * @property uploadOptions - Configuration for single-upload mode\n * @property children - Render function receiving upload zone state\n * @property onUploadStart - Called when files pass validation and upload begins\n * @property onValidationError - Called when file validation fails\n * @property accept - Accepted file types (e.g., ['image/*', '.pdf'])\n * @property maxFiles - Maximum number of files allowed\n * @property maxFileSize - Maximum file size in bytes\n * @property validator - Custom validation function\n */\nexport interface UploadZoneProps\n extends Omit<DragDropOptions, \"onFilesReceived\"> {\n /**\n * Whether to enable multi-file upload mode\n */\n multiple?: boolean;\n\n /**\n * Multi-upload specific options (only used when multiple=true)\n */\n multiUploadOptions?: MultiUploadOptions;\n\n /**\n * Single upload specific options (only used when multiple=false)\n */\n uploadOptions?: UseUploadOptions;\n\n /**\n * Render prop that receives upload zone state and handlers\n */\n children: (props: UploadZoneRenderProps) => React.ReactNode;\n\n /**\n * Called when files are processed and uploads begin\n */\n onUploadStart?: (files: File[]) => void;\n\n /**\n * Called when validation errors occur\n */\n onValidationError?: (errors: string[]) => void;\n}\n\n/**\n * Headless upload zone component that combines drag and drop functionality\n * with upload management. Uses render props pattern for maximum flexibility.\n * Includes enhanced error handling for MIME type validation and file count validation.\n *\n * @param props - Upload zone configuration and render prop\n * @returns Rendered upload zone using the provided render prop\n *\n * @example\n * ```tsx\n * // Single file upload zone with error handling\n * <UploadZone\n * multiple={false}\n * accept={['image/*']}\n * maxFileSize={5 * 1024 * 1024}\n * onValidationError={(errors) => {\n * console.error('Validation errors:', errors);\n * }}\n * uploadOptions={{\n * onSuccess: (result) => console.log('Upload complete:', result),\n * onError: (error) => console.error('Upload failed:', error),\n * }}\n * >\n * {({ dragDrop, upload, openFilePicker, isActive }) => (\n * <div {...dragDrop.dragHandlers} onClick={openFilePicker}>\n * {dragDrop.state.isDragging ? (\n * <p>Drop file here...</p>\n * ) : upload?.isUploading ? (\n * <p>Uploading... {upload.state.progress}%</p>\n * ) : (\n * <p>Drag a file here or click to select</p>\n * )}\n *\n * {dragDrop.state.errors.length > 0 && (\n * <div style={{ color: 'red' }}>\n * {dragDrop.state.errors.map((error, index) => (\n * <p key={index}>{error}</p>\n * ))}\n * </div>\n * )}\n *\n * <input {...dragDrop.inputProps} />\n * </div>\n * )}\n * </UploadZone>\n * ```\n */\nexport function UploadZone({\n children,\n multiple = true,\n multiUploadOptions = {},\n uploadOptions = {},\n onUploadStart,\n onValidationError,\n ...dragDropOptions\n}: UploadZoneProps) {\n // Always initialize both hooks, but only use the appropriate one\n const singleUpload = useUpload(uploadOptions);\n const multiUpload = useMultiUpload(multiUploadOptions);\n\n // Enhanced validation function for better error handling\n const enhancedValidator = useCallback(\n (files: File[]): string[] | null => {\n const errors: string[] = [];\n\n // Check file count based on multiple setting\n if (!multiple && files.length > 1) {\n errors.push(\n `Single file mode is enabled. Please select only one file. You selected ${files.length} files.`,\n );\n }\n\n // Enhanced MIME type validation with better error messages\n if (dragDropOptions.accept && dragDropOptions.accept.length > 0) {\n const invalidFiles = files.filter((file) => {\n return !dragDropOptions.accept?.some((acceptType) => {\n if (acceptType.startsWith(\".\")) {\n // File extension check\n return file.name.toLowerCase().endsWith(acceptType.toLowerCase());\n } else {\n // MIME type check (supports wildcards like image/*)\n if (acceptType.endsWith(\"/*\")) {\n const baseType = acceptType.slice(0, -2);\n return file.type.startsWith(baseType);\n } else {\n return file.type === acceptType;\n }\n }\n });\n });\n\n if (invalidFiles.length > 0) {\n const fileNames = invalidFiles\n .map((f) => `\"${f.name}\" (${f.type})`)\n .join(\", \");\n const acceptedTypes = dragDropOptions.accept.join(\", \");\n errors.push(\n `Invalid file type(s): ${fileNames}. Accepted types: ${acceptedTypes}.`,\n );\n }\n }\n\n return errors.length > 0 ? errors : null;\n },\n [multiple, dragDropOptions.accept],\n );\n\n // Handle file processing\n const handleFilesReceived = (files: File[]) => {\n onUploadStart?.(files);\n\n if (multiple && multiUpload) {\n // Add files to multi-upload queue\n multiUpload.addFiles(files);\n\n // Auto-start uploads if configured to do so\n // Note: This could be made configurable with an autoStart prop\n setTimeout(() => multiUpload.startAll(), 0);\n } else if (!multiple && singleUpload && files.length > 0 && files[0]) {\n // Start single file upload\n singleUpload.upload(files[0]);\n }\n };\n\n // Handle validation errors\n const handleValidationError = useCallback(\n (errors: string[]) => {\n console.error(\"Upload zone validation errors:\", errors);\n // Call the custom error handler if provided\n onValidationError?.(errors);\n },\n [onValidationError],\n );\n\n // Initialize drag and drop with enhanced validation\n const dragDrop = useDragDrop({\n ...dragDropOptions,\n multiple,\n validator: enhancedValidator,\n onFilesReceived: handleFilesReceived,\n onValidationError: handleValidationError,\n });\n\n // Determine active state\n const isActive = dragDrop.state.isDragging || dragDrop.state.isOver;\n\n // Determine processing state\n const isProcessing = multiple\n ? (multiUpload?.state.isUploading ?? false)\n : (singleUpload?.isUploading ?? false);\n\n // Create render props object\n const renderProps: UploadZoneRenderProps = {\n dragDrop,\n upload: singleUpload,\n multiUpload,\n openFilePicker: dragDrop.openFilePicker,\n isActive,\n isProcessing,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n/**\n * Props for the SimpleUploadZone component with built-in styling.\n *\n * @property className - CSS class name for custom styling\n * @property style - Inline styles for the upload zone container\n * @property text - Custom text labels for different states\n * @property text.idle - Text shown when zone is idle\n * @property text.dragging - Text shown when dragging files over zone\n * @property text.uploading - Text shown during upload\n * @property errorStyle - Custom styles for validation error display\n */\nexport interface SimpleUploadZoneProps extends UploadZoneProps {\n /**\n * Additional CSS class name for styling\n */\n className?: string;\n\n /**\n * Inline styles for the upload zone\n */\n style?: React.CSSProperties;\n\n /**\n * Custom text to display in different states\n */\n text?: {\n idle?: string;\n dragging?: string;\n uploading?: string;\n };\n\n /**\n * Custom error message styling\n */\n errorStyle?: React.CSSProperties;\n}\n\n/**\n * Simple pre-styled upload zone component with built-in UI and error handling.\n * Provides a ready-to-use drag-and-drop upload interface with minimal configuration.\n *\n * Features:\n * - Built-in drag-and-drop visual feedback\n * - Automatic progress display\n * - File validation error display\n * - Customizable text and styling\n * - Keyboard accessible\n *\n * @param props - Upload zone configuration with styling options\n * @returns Styled upload zone component\n *\n * @example\n * ```tsx\n * // Multi-file upload with validation\n * <SimpleUploadZone\n * multiple={true}\n * accept={['image/*', '.pdf']}\n * maxFiles={5}\n * maxFileSize={10 * 1024 * 1024} // 10MB\n * onUploadStart={(files) => console.log('Starting uploads:', files.length)}\n * onValidationError={(errors) => {\n * errors.forEach(err => console.error(err));\n * }}\n * multiUploadOptions={{\n * maxConcurrent: 3,\n * onComplete: (results) => {\n * console.log(`${results.successful.length}/${results.total} uploaded`);\n * },\n * }}\n * style={{\n * width: '400px',\n * height: '200px',\n * margin: '20px auto',\n * }}\n * text={{\n * idle: 'Drop your files here or click to browse',\n * dragging: 'Release to upload',\n * uploading: 'Uploading files...',\n * }}\n * errorStyle={{\n * backgroundColor: '#fff3cd',\n * borderColor: '#ffeaa7',\n * }}\n * />\n *\n * // Single file upload\n * <SimpleUploadZone\n * multiple={false}\n * accept={['image/*']}\n * uploadOptions={{\n * onSuccess: (result) => console.log('Uploaded:', result),\n * onError: (error) => console.error('Failed:', error),\n * }}\n * text={{\n * idle: 'Click or drag an image to upload',\n * }}\n * />\n * ```\n */\nexport function SimpleUploadZone({\n className = \"\",\n style = {},\n text = {},\n errorStyle = {},\n children,\n ...uploadZoneProps\n}: SimpleUploadZoneProps) {\n const defaultText = {\n idle: uploadZoneProps.multiple\n ? \"Drag files here or click to select\"\n : \"Drag a file here or click to select\",\n dragging: uploadZoneProps.multiple\n ? \"Drop files here...\"\n : \"Drop file here...\",\n uploading: \"Uploading...\",\n };\n\n const displayText = { ...defaultText, ...text };\n\n // If children render prop is provided, use UploadZone directly\n if (children) {\n return <UploadZone {...uploadZoneProps}>{children}</UploadZone>;\n }\n\n // Otherwise, provide default UI\n return (\n <UploadZone {...uploadZoneProps}>\n {({\n dragDrop,\n upload,\n multiUpload,\n openFilePicker,\n isActive,\n isProcessing,\n }) => (\n <button\n type=\"button\"\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n openFilePicker();\n }\n }}\n onKeyUp={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n openFilePicker();\n }\n }}\n {...dragDrop.dragHandlers}\n onClick={openFilePicker}\n className={`upload-zone ${isActive ? \"upload-zone--active\" : \"\"} ${isProcessing ? \"upload-zone--processing\" : \"\"} ${className}`}\n style={{\n border: isActive ? \"2px dashed #007bff\" : \"2px dashed #ccc\",\n borderRadius: \"8px\",\n padding: \"2rem\",\n textAlign: \"center\",\n cursor: \"pointer\",\n backgroundColor: isActive ? \"#f8f9fa\" : \"transparent\",\n transition: \"all 0.2s ease\",\n minHeight: \"120px\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n ...style,\n }}\n >\n {dragDrop.state.isDragging ? (\n <p style={{ margin: 0, fontSize: \"16px\", color: \"#007bff\" }}>\n {displayText.dragging}\n </p>\n ) : isProcessing ? (\n <div style={{ textAlign: \"center\" }}>\n <p style={{ margin: \"0 0 10px 0\", fontSize: \"14px\" }}>\n {displayText.uploading}\n </p>\n {upload && (\n <div>\n <progress\n value={upload.state.progress}\n max={100}\n style={{ width: \"200px\", height: \"8px\" }}\n />\n <p\n style={{\n margin: \"5px 0 0 0\",\n fontSize: \"12px\",\n color: \"#666\",\n }}\n >\n {upload.state.progress}%\n </p>\n </div>\n )}\n {multiUpload && (\n <div>\n <progress\n value={multiUpload.state.progress}\n max={100}\n style={{ width: \"200px\", height: \"8px\" }}\n />\n <p\n style={{\n margin: \"5px 0 0 0\",\n fontSize: \"12px\",\n color: \"#666\",\n }}\n >\n {multiUpload.state.progress}% ({multiUpload.state.uploading}{\" \"}\n uploading, {multiUpload.state.successful} completed)\n </p>\n </div>\n )}\n </div>\n ) : (\n <p style={{ margin: 0, fontSize: \"16px\", color: \"#666\" }}>\n {displayText.idle}\n </p>\n )}\n\n {dragDrop.state.errors.length > 0 && (\n <div\n style={{\n marginTop: \"10px\",\n padding: \"8px 12px\",\n backgroundColor: \"#f8d7da\",\n border: \"1px solid #f5c6cb\",\n borderRadius: \"4px\",\n maxWidth: \"100%\",\n ...errorStyle,\n }}\n >\n <p\n style={{\n margin: \"0 0 5px 0\",\n fontSize: \"12px\",\n fontWeight: \"bold\",\n color: \"#721c24\",\n }}\n >\n Validation Errors:\n </p>\n {dragDrop.state.errors.map((error, index) => (\n <p\n // biome-ignore lint/suspicious/noArrayIndexKey: index is used as key\n key={index}\n style={{\n color: \"#721c24\",\n fontSize: \"11px\",\n margin: \"2px 0\",\n lineHeight: \"1.3\",\n }}\n >\n • {error}\n </p>\n ))}\n </div>\n )}\n\n <input {...dragDrop.inputProps} />\n </button>\n )}\n </UploadZone>\n );\n}\n","import type {\n BrowserUploadInput,\n FlowUploadConfig,\n FlowUploadItem,\n MultiFlowUploadOptions,\n} from \"@uploadista/client-browser\";\nimport type { ReactNode } from \"react\";\nimport { useMultiFlowUpload } from \"../hooks/use-multi-flow-upload\";\n\n/**\n * Render props passed to the FlowUploadList children function.\n * Provides access to upload items, aggregate statistics, and control methods.\n *\n * @property items - All flow upload items in the queue\n * @property totalProgress - Average progress across all uploads (0-100)\n * @property activeUploads - Count of currently uploading items\n * @property completedUploads - Count of successfully completed uploads\n * @property failedUploads - Count of failed uploads\n * @property isUploading - True when any uploads are in progress\n * @property addFiles - Add new files to the upload queue\n * @property removeFile - Remove a specific file from the queue\n * @property startUpload - Begin uploading all pending files\n * @property abortUpload - Cancel a specific active upload\n * @property abortAll - Cancel all active uploads\n * @property clear - Remove all items from the queue\n * @property retryUpload - Retry a specific failed upload\n */\nexport interface FlowUploadListRenderProps {\n /**\n * List of upload items\n */\n items: FlowUploadItem<BrowserUploadInput>[];\n\n /**\n * Total progress across all uploads\n */\n totalProgress: number;\n\n /**\n * Number of active uploads\n */\n activeUploads: number;\n\n /**\n * Number of completed uploads\n */\n completedUploads: number;\n\n /**\n * Number of failed uploads\n */\n failedUploads: number;\n\n /**\n * Whether any uploads are in progress\n */\n isUploading: boolean;\n\n /**\n * Add files to the upload queue\n */\n addFiles: (files: File[] | FileList) => void;\n\n /**\n * Remove a file from the queue\n */\n removeFile: (id: string) => void;\n\n /**\n * Start uploading all pending files\n */\n startUpload: () => void;\n\n /**\n * Abort a specific upload\n */\n abortUpload: (id: string) => void;\n\n /**\n * Abort all uploads\n */\n abortAll: () => void;\n\n /**\n * Clear all items\n */\n clear: () => void;\n\n /**\n * Retry a failed upload\n */\n retryUpload: (id: string) => void;\n}\n\n/**\n * Props for the FlowUploadList component.\n *\n * @property flowConfig - Flow execution configuration (flowId, storageId, etc.)\n * @property options - Multi-flow upload options (callbacks, concurrency, etc.)\n * @property children - Render function receiving flow upload list state\n */\nexport interface FlowUploadListProps {\n /**\n * Flow configuration\n */\n flowConfig: FlowUploadConfig;\n\n /**\n * Multi-upload options\n */\n options?: Omit<MultiFlowUploadOptions<BrowserUploadInput>, \"flowConfig\">;\n\n /**\n * Render function for the upload list\n */\n children: (props: FlowUploadListRenderProps) => ReactNode;\n}\n\n/**\n * Headless flow upload list component for managing batch file uploads through a flow.\n * Uses render props pattern to provide complete control over the UI while handling\n * concurrent uploads and flow processing.\n *\n * Each file is uploaded and processed independently through the specified flow,\n * with automatic queue management and concurrency control.\n *\n * Must be used within an UploadistaProvider.\n *\n * @param props - Flow upload list configuration and render prop\n * @returns Rendered flow upload list using the provided render prop\n *\n * @example\n * ```tsx\n * // Batch image processing with custom UI\n * <FlowUploadList\n * flowConfig={{\n * flowId: \"image-batch-processing\",\n * storageId: \"s3-images\",\n * outputNodeId: \"optimized\",\n * }}\n * options={{\n * maxConcurrent: 3,\n * onItemSuccess: (item) => {\n * console.log(`${item.file.name} processed successfully`);\n * },\n * onComplete: (items) => {\n * const successful = items.filter(i => i.status === 'success');\n * console.log(`Batch complete: ${successful.length}/${items.length} successful`);\n * },\n * }}\n * >\n * {({\n * items,\n * totalProgress,\n * activeUploads,\n * completedUploads,\n * failedUploads,\n * addFiles,\n * startUpload,\n * abortUpload,\n * retryUpload,\n * clear,\n * }) => (\n * <div>\n * <input\n * type=\"file\"\n * multiple\n * accept=\"image/*\"\n * onChange={(e) => {\n * if (e.target.files) {\n * addFiles(e.target.files);\n * startUpload();\n * }\n * }}\n * />\n *\n * <div style={{ marginTop: '1rem' }}>\n * <h3>Upload Progress</h3>\n * <div>Overall: {totalProgress}%</div>\n * <div>\n * Active: {activeUploads}, Completed: {completedUploads}, Failed: {failedUploads}\n * </div>\n * <button onClick={clear}>Clear All</button>\n * </div>\n *\n * <ul style={{ listStyle: 'none', padding: 0 }}>\n * {items.map((item) => (\n * <li key={item.id} style={{\n * padding: '1rem',\n * border: '1px solid #ccc',\n * marginBottom: '0.5rem'\n * }}>\n * <div>{item.file instanceof File ? item.file.name : 'File'}</div>\n * <div>Status: {item.status}</div>\n *\n * {item.status === \"uploading\" && (\n * <div>\n * <progress value={item.progress} max={100} style={{ width: '100%' }} />\n * <div>{item.progress}%</div>\n * <button onClick={() => abortUpload(item.id)}>Cancel</button>\n * </div>\n * )}\n *\n * {item.status === \"error\" && (\n * <div>\n * <div style={{ color: 'red' }}>{item.error?.message}</div>\n * <button onClick={() => retryUpload(item.id)}>Retry</button>\n * </div>\n * )}\n *\n * {item.status === \"success\" && (\n * <div style={{ color: 'green' }}>✓ Complete</div>\n * )}\n * </li>\n * ))}\n * </ul>\n * </div>\n * )}\n * </FlowUploadList>\n * ```\n *\n * @see {@link SimpleFlowUploadList} for a pre-styled version\n * @see {@link useMultiFlowUpload} for the underlying hook\n */\nexport function FlowUploadList({\n flowConfig,\n options,\n children,\n}: FlowUploadListProps) {\n const multiUpload = useMultiFlowUpload({\n ...options,\n flowConfig,\n });\n\n return (\n <>\n {children({\n items: multiUpload.state.items,\n totalProgress: multiUpload.state.totalProgress,\n activeUploads: multiUpload.state.activeUploads,\n completedUploads: multiUpload.state.completedUploads,\n failedUploads: multiUpload.state.failedUploads,\n isUploading: multiUpload.isUploading,\n addFiles: multiUpload.addFiles,\n removeFile: multiUpload.removeFile,\n startUpload: multiUpload.startUpload,\n abortUpload: multiUpload.abortUpload,\n abortAll: multiUpload.abortAll,\n clear: multiUpload.clear,\n retryUpload: multiUpload.retryUpload,\n })}\n </>\n );\n}\n\n/**\n * Props for the SimpleFlowUploadListItem component.\n *\n * @property item - The flow upload item to display\n * @property onAbort - Called when the abort button is clicked\n * @property onRetry - Called when the retry button is clicked\n * @property onRemove - Called when the remove button is clicked\n */\nexport interface SimpleFlowUploadListItemProps {\n /**\n * Upload item\n */\n item: FlowUploadItem<BrowserUploadInput>;\n\n /**\n * Abort the upload\n */\n onAbort: () => void;\n\n /**\n * Retry the upload\n */\n onRetry: () => void;\n\n /**\n * Remove the item\n */\n onRemove: () => void;\n}\n\n/**\n * Pre-styled flow upload list item component with status indicators.\n * Displays file name, upload progress, status, and contextual action buttons.\n *\n * Features:\n * - Status-specific icons and colors\n * - Progress bar with percentage and byte count\n * - Error message display\n * - Contextual action buttons (cancel, retry, remove)\n *\n * @param props - Upload item and callback functions\n * @returns Styled flow upload list item component\n *\n * @example\n * ```tsx\n * <SimpleFlowUploadListItem\n * item={uploadItem}\n * onAbort={() => console.log('Abort')}\n * onRetry={() => console.log('Retry')}\n * onRemove={() => console.log('Remove')}\n * />\n * ```\n */\nexport function SimpleFlowUploadListItem({\n item,\n onAbort,\n onRetry,\n onRemove,\n}: SimpleFlowUploadListItemProps) {\n const getStatusIcon = () => {\n switch (item.status) {\n case \"success\":\n return \"✓\";\n case \"error\":\n return \"✗\";\n case \"uploading\":\n return \"⟳\";\n case \"aborted\":\n return \"⊘\";\n default:\n return \"○\";\n }\n };\n\n const getStatusColor = () => {\n switch (item.status) {\n case \"success\":\n return \"green\";\n case \"error\":\n return \"red\";\n case \"uploading\":\n return \"blue\";\n case \"aborted\":\n return \"gray\";\n default:\n return \"black\";\n }\n };\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"12px\",\n padding: \"8px\",\n borderBottom: \"1px solid #eee\",\n }}\n >\n <span style={{ color: getStatusColor(), fontSize: \"18px\" }}>\n {getStatusIcon()}\n </span>\n\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontSize: \"14px\",\n fontWeight: 500,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {item.file instanceof File ? item.file.name : \"Upload\"}\n </div>\n\n {item.status === \"uploading\" && (\n <div style={{ marginTop: \"4px\" }}>\n <progress\n value={item.progress}\n max={100}\n style={{ width: \"100%\", height: \"4px\" }}\n />\n <div style={{ fontSize: \"12px\", color: \"#666\", marginTop: \"2px\" }}>\n {item.progress}% • {Math.round(item.bytesUploaded / 1024)} KB /{\" \"}\n {Math.round(item.totalBytes / 1024)} KB\n </div>\n </div>\n )}\n\n {item.status === \"error\" && (\n <div style={{ fontSize: \"12px\", color: \"red\", marginTop: \"2px\" }}>\n {item.error?.message || \"Upload failed\"}\n </div>\n )}\n\n {item.status === \"success\" && (\n <div style={{ fontSize: \"12px\", color: \"green\", marginTop: \"2px\" }}>\n Upload complete\n </div>\n )}\n </div>\n\n <div style={{ display: \"flex\", gap: \"8px\" }}>\n {item.status === \"uploading\" && (\n <button\n type=\"button\"\n onClick={onAbort}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n borderRadius: \"4px\",\n border: \"1px solid #ccc\",\n backgroundColor: \"#fff\",\n cursor: \"pointer\",\n }}\n >\n Cancel\n </button>\n )}\n\n {item.status === \"error\" && (\n <button\n type=\"button\"\n onClick={onRetry}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n borderRadius: \"4px\",\n border: \"1px solid #ccc\",\n backgroundColor: \"#fff\",\n cursor: \"pointer\",\n }}\n >\n Retry\n </button>\n )}\n\n {(item.status === \"pending\" ||\n item.status === \"error\" ||\n item.status === \"aborted\") && (\n <button\n type=\"button\"\n onClick={onRemove}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n borderRadius: \"4px\",\n border: \"1px solid #ccc\",\n backgroundColor: \"#fff\",\n cursor: \"pointer\",\n }}\n >\n Remove\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Props for the SimpleFlowUploadList component.\n *\n * @property flowConfig - Flow execution configuration\n * @property options - Multi-flow upload options (callbacks, concurrency)\n * @property className - CSS class name for the container\n * @property showFileInput - Whether to display the file input (default: true)\n * @property accept - Accepted file types for the file input\n */\nexport interface SimpleFlowUploadListProps {\n /**\n * Flow configuration\n */\n flowConfig: FlowUploadConfig;\n\n /**\n * Multi-upload options\n */\n options?: Omit<MultiFlowUploadOptions<BrowserUploadInput>, \"flowConfig\">;\n\n /**\n * CSS class for the container\n */\n className?: string;\n\n /**\n * Show file input\n */\n showFileInput?: boolean;\n\n /**\n * File input accept attribute\n */\n accept?: string;\n}\n\n/**\n * Simple pre-styled flow upload list component with built-in UI.\n * Provides a ready-to-use interface for batch file uploads with flow processing.\n *\n * Features:\n * - Built-in file input\n * - Overall progress display\n * - Individual item progress tracking\n * - Status indicators and action buttons\n * - Automatic upload start on file selection\n *\n * @param props - Flow upload list configuration with styling options\n * @returns Styled flow upload list component\n *\n * @example\n * ```tsx\n * // Basic batch image upload\n * <SimpleFlowUploadList\n * flowConfig={{\n * flowId: \"image-batch-processing\",\n * storageId: \"s3-images\",\n * }}\n * options={{\n * maxConcurrent: 3,\n * onItemSuccess: (item) => {\n * console.log(`${item.file.name} processed`);\n * },\n * onComplete: (items) => {\n * console.log(\"Batch complete:\", items.length);\n * },\n * }}\n * accept=\"image/*\"\n * className=\"my-upload-list\"\n * />\n *\n * // Without file input (add files programmatically)\n * <SimpleFlowUploadList\n * flowConfig={{\n * flowId: \"document-processing\",\n * storageId: \"docs\",\n * }}\n * showFileInput={false}\n * options={{\n * maxConcurrent: 2,\n * }}\n * />\n * ```\n *\n * @see {@link FlowUploadList} for the headless version with full control\n */\nexport function SimpleFlowUploadList({\n flowConfig,\n options,\n className = \"\",\n showFileInput = true,\n accept,\n}: SimpleFlowUploadListProps) {\n return (\n <FlowUploadList flowConfig={flowConfig} options={options}>\n {({\n items,\n addFiles,\n startUpload,\n abortUpload,\n retryUpload,\n removeFile,\n totalProgress,\n }) => (\n <div className={className}>\n {showFileInput && (\n <div style={{ marginBottom: \"16px\" }}>\n <input\n type=\"file\"\n multiple\n accept={accept}\n onChange={(e) => {\n if (e.target.files) {\n addFiles(e.target.files);\n startUpload();\n }\n }}\n style={{\n padding: \"8px\",\n border: \"1px solid #ccc\",\n borderRadius: \"4px\",\n }}\n />\n </div>\n )}\n\n {items.length > 0 && (\n <div>\n <div\n style={{ marginBottom: \"8px\", fontSize: \"14px\", color: \"#666\" }}\n >\n Total Progress: {totalProgress}%\n </div>\n\n <div\n style={{\n border: \"1px solid #eee\",\n borderRadius: \"8px\",\n overflow: \"hidden\",\n }}\n >\n {items.map((item) => (\n <SimpleFlowUploadListItem\n key={item.id}\n item={item}\n onAbort={() => abortUpload(item.id)}\n onRetry={() => retryUpload(item.id)}\n onRemove={() => removeFile(item.id)}\n />\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </FlowUploadList>\n );\n}\n"],"mappings":"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"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["contextValue: UploadContextValue","contextValue: UploadItemContextValue","status: \"idle\" | \"uploading\" | \"success\" | \"error\""],"sources":["../src/components/upload-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BrowserUploadInput } from \"@uploadista/client-browser\";\nimport type { UploadFile } from \"@uploadista/core/types\";\nimport {\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n} from \"react\";\nimport {\n type DragDropState,\n type UseDragDropReturn,\n useDragDrop,\n} from \"../hooks/use-drag-drop\";\nimport {\n type MultiUploadState,\n type UploadItem,\n useMultiUpload,\n} from \"../hooks/use-multi-upload\";\nimport type { UploadState, UploadStatus } from \"../hooks/use-upload\";\n\n// Re-export types for convenience\nexport type { UploadState, UploadStatus, UploadItem, MultiUploadState };\n\n// ============ UPLOAD CONTEXT ============\n\n/**\n * Context value provided by the Upload component root.\n * Contains all upload state and actions.\n */\nexport interface UploadContextValue {\n /** Whether in multi-file mode */\n mode: \"single\" | \"multi\";\n /** Current multi-upload state (aggregate) */\n state: MultiUploadState;\n /** All upload items */\n items: UploadItem[];\n /** Whether auto-start is enabled */\n autoStart: boolean;\n\n /** Add files to the upload queue */\n addFiles: (files: BrowserUploadInput[]) => void;\n /** Remove an item from the queue */\n removeItem: (id: string) => void;\n /** Start all pending uploads */\n startAll: () => void;\n /** Abort a specific upload by ID */\n abortUpload: (id: string) => void;\n /** Abort all active uploads */\n abortAll: () => void;\n /** Retry a specific failed upload by ID */\n retryUpload: (id: string) => void;\n /** Retry all failed uploads */\n retryFailed: () => void;\n /** Clear all completed uploads */\n clearCompleted: () => void;\n /** Clear all items and reset state */\n clearAll: () => void;\n\n /** Internal handler for files received from drop zone */\n handleFilesReceived: (files: File[]) => void;\n}\n\nconst UploadContext = createContext<UploadContextValue | null>(null);\n\n/**\n * Hook to access upload context from within an Upload component.\n * @throws Error if used outside of an Upload component\n */\nexport function useUploadContext(): UploadContextValue {\n const context = useContext(UploadContext);\n if (!context) {\n throw new Error(\n \"useUploadContext must be used within an <Upload> component. \" +\n 'Wrap your component tree with <Upload onSuccess={...}>',\n );\n }\n return context;\n}\n\n// ============ UPLOAD ITEM CONTEXT ============\n\n/**\n * Context value for a specific upload item within an Upload.\n */\nexport interface UploadItemContextValue {\n /** Item ID */\n id: string;\n /** The file being uploaded */\n file: BrowserUploadInput;\n /** Current upload state */\n state: UploadState;\n /** Abort this upload */\n abort: () => void;\n /** Retry this upload */\n retry: () => void;\n /** Remove this item from the queue */\n remove: () => void;\n}\n\nconst UploadItemContext = createContext<UploadItemContextValue | null>(null);\n\n/**\n * Hook to access upload item context from within an Upload.Item component.\n * @throws Error if used outside of an Upload.Item component\n */\nexport function useUploadItemContext(): UploadItemContextValue {\n const context = useContext(UploadItemContext);\n if (!context) {\n throw new Error(\n \"useUploadItemContext must be used within an <Upload.Item> component. \" +\n 'Wrap your component with <Upload.Item id=\"...\">',\n );\n }\n return context;\n}\n\n// ============ UPLOAD ROOT COMPONENT ============\n\n/**\n * Props for the Upload root component.\n */\nexport interface UploadProps {\n /** Whether to allow multiple file uploads (default: false) */\n multiple?: boolean;\n /** Maximum concurrent uploads (default: 3, only used in multi mode) */\n maxConcurrent?: number;\n /** Whether to auto-start uploads when files are received (default: true) */\n autoStart?: boolean;\n /** Metadata to attach to uploads */\n metadata?: Record<string, string>;\n /** Called when a single file upload succeeds (single mode) */\n onSuccess?: (result: UploadFile) => void;\n /** Called when an upload fails */\n onError?: (error: Error, item?: UploadItem) => void;\n /** Called when all uploads complete (multi mode) */\n onComplete?: (results: {\n successful: UploadItem[];\n failed: UploadItem[];\n total: number;\n }) => void;\n /** Called when an individual upload starts */\n onUploadStart?: (item: UploadItem) => void;\n /** Called on upload progress */\n onProgress?: (\n item: UploadItem,\n progress: number,\n bytesUploaded: number,\n totalBytes: number | null,\n ) => void;\n /** Children to render */\n children: ReactNode;\n}\n\n/**\n * Root component for file uploads.\n * Provides context for all Upload sub-components.\n * Supports both single-file and multi-file modes via the `multiple` prop.\n *\n * @example Single file upload\n * ```tsx\n * <Upload onSuccess={handleSuccess}>\n * <Upload.DropZone accept=\"image/*\">\n * {({ isDragging, getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * {isDragging ? \"Drop here\" : \"Drag or click\"}\n * </div>\n * )}\n * </Upload.DropZone>\n * <Upload.Progress>\n * {({ progress }) => <progress value={progress} max={100} />}\n * </Upload.Progress>\n * </Upload>\n * ```\n *\n * @example Multi-file upload\n * ```tsx\n * <Upload multiple maxConcurrent={3} onComplete={handleComplete}>\n * <Upload.DropZone>\n * {(props) => ...}\n * </Upload.DropZone>\n * <Upload.Items>\n * {({ items }) => items.map(item => (\n * <Upload.Item key={item.id} id={item.id}>\n * {({ file, state, abort, remove }) => (\n * <div>{file.name}: {state.progress}%</div>\n * )}\n * </Upload.Item>\n * ))}\n * </Upload.Items>\n * <Upload.StartAll>Upload All</Upload.StartAll>\n * </Upload>\n * ```\n */\nfunction UploadRoot({\n multiple = false,\n maxConcurrent = 3,\n autoStart = true,\n metadata,\n onSuccess,\n onError,\n onComplete,\n onUploadStart,\n onProgress,\n children,\n}: UploadProps) {\n const multiUpload = useMultiUpload({\n maxConcurrent,\n metadata,\n onUploadStart,\n onUploadProgress: onProgress,\n onUploadSuccess: (item, result) => {\n // In single mode, call onSuccess directly\n if (!multiple) {\n onSuccess?.(result);\n }\n },\n onUploadError: (item, error) => {\n onError?.(error, item);\n },\n onComplete,\n });\n\n const handleFilesReceived = useCallback(\n (files: File[]) => {\n if (!multiple) {\n // Single mode: clear existing and add new file\n multiUpload.clearAll();\n }\n multiUpload.addFiles(files);\n if (autoStart) {\n // Use setTimeout to ensure state is updated before starting\n setTimeout(() => multiUpload.startAll(), 0);\n }\n },\n [multiple, autoStart, multiUpload],\n );\n\n const contextValue: UploadContextValue = {\n mode: multiple ? \"multi\" : \"single\",\n state: multiUpload.state,\n items: multiUpload.items,\n autoStart,\n addFiles: multiUpload.addFiles,\n removeItem: multiUpload.removeItem,\n startAll: multiUpload.startAll,\n abortUpload: multiUpload.abortUpload,\n abortAll: multiUpload.abortAll,\n retryUpload: multiUpload.retryUpload,\n retryFailed: multiUpload.retryFailed,\n clearCompleted: multiUpload.clearCompleted,\n clearAll: multiUpload.clearAll,\n handleFilesReceived,\n };\n\n return (\n <UploadContext.Provider value={contextValue}>\n {children}\n </UploadContext.Provider>\n );\n}\n\n// ============ DROP ZONE PRIMITIVE ============\n\n/**\n * Render props for Upload.DropZone component.\n */\nexport interface UploadDropZoneRenderProps {\n /** Whether files are being dragged over */\n isDragging: boolean;\n /** Whether drag is over the zone */\n isOver: boolean;\n /** Validation errors */\n errors: string[];\n /** Props to spread on the drop zone container */\n getRootProps: () => UseDragDropReturn[\"dragHandlers\"];\n /** Props to spread on the hidden file input */\n getInputProps: () => UseDragDropReturn[\"inputProps\"];\n /** Open file picker programmatically */\n openFilePicker: () => void;\n /** Current drag-drop state */\n dragDropState: DragDropState;\n}\n\n/**\n * Props for Upload.DropZone component.\n */\nexport interface UploadDropZoneProps {\n /** Accepted file types (e.g., \"image/*\", \".pdf\") */\n accept?: string;\n /** Maximum file size in bytes */\n maxFileSize?: number;\n /** Maximum number of files (only in multi mode) */\n maxFiles?: number;\n /** Render function receiving drop zone state */\n children: (props: UploadDropZoneRenderProps) => ReactNode;\n}\n\n/**\n * Drop zone for file uploads within an Upload component.\n * Handles drag-and-drop and click-to-select file selection.\n *\n * @example\n * ```tsx\n * <Upload.DropZone accept=\"image/*\">\n * {({ isDragging, getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * {isDragging ? \"Drop here\" : \"Click or drag\"}\n * </div>\n * )}\n * </Upload.DropZone>\n * ```\n */\nfunction UploadDropZone({\n accept,\n maxFileSize,\n maxFiles,\n children,\n}: UploadDropZoneProps) {\n const upload = useUploadContext();\n\n const dragDrop = useDragDrop({\n onFilesReceived: upload.handleFilesReceived,\n accept: accept ? accept.split(\",\").map((t) => t.trim()) : undefined,\n maxFileSize,\n maxFiles: upload.mode === \"multi\" ? maxFiles : 1,\n multiple: upload.mode === \"multi\",\n });\n\n const renderProps: UploadDropZoneRenderProps = {\n isDragging: dragDrop.state.isDragging,\n isOver: dragDrop.state.isOver,\n errors: dragDrop.state.errors,\n getRootProps: () => dragDrop.dragHandlers,\n getInputProps: () => dragDrop.inputProps,\n openFilePicker: dragDrop.openFilePicker,\n dragDropState: dragDrop.state,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ ITEMS PRIMITIVE ============\n\n/**\n * Render props for Upload.Items component.\n */\nexport interface UploadItemsRenderProps {\n /** All upload items */\n items: UploadItem[];\n /** Whether there are any items */\n hasItems: boolean;\n /** Whether items array is empty */\n isEmpty: boolean;\n}\n\n/**\n * Props for Upload.Items component.\n */\nexport interface UploadItemsProps {\n /** Render function receiving items */\n children: (props: UploadItemsRenderProps) => ReactNode;\n}\n\n/**\n * Renders the list of upload items via render props.\n *\n * @example\n * ```tsx\n * <Upload.Items>\n * {({ items, isEmpty }) => (\n * isEmpty ? <p>No files</p> : (\n * items.map(item => (\n * <Upload.Item key={item.id} id={item.id}>\n * {(props) => ...}\n * </Upload.Item>\n * ))\n * )\n * )}\n * </Upload.Items>\n * ```\n */\nfunction UploadItems({ children }: UploadItemsProps) {\n const upload = useUploadContext();\n\n const renderProps: UploadItemsRenderProps = {\n items: upload.items,\n hasItems: upload.items.length > 0,\n isEmpty: upload.items.length === 0,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ ITEM PRIMITIVE ============\n\n/**\n * Props for Upload.Item component.\n */\nexport interface UploadItemProps {\n /** Item ID */\n id: string;\n /** Children (can be render function or regular children) */\n children: ReactNode | ((props: UploadItemContextValue) => ReactNode);\n}\n\n/**\n * Scoped context provider for a specific upload item.\n * Children can access item-specific state via useUploadItemContext().\n *\n * @example\n * ```tsx\n * <Upload.Item id={item.id}>\n * {({ file, state, abort, remove }) => (\n * <div>\n * <span>{file.name}</span>\n * <progress value={state.progress} max={100} />\n * <button onClick={abort}>Cancel</button>\n * <button onClick={remove}>Remove</button>\n * </div>\n * )}\n * </Upload.Item>\n * ```\n */\nfunction UploadItem({ id, children }: UploadItemProps) {\n const upload = useUploadContext();\n\n const item = upload.items.find((i) => i.id === id);\n\n if (!item) {\n // Item not found\n return null;\n }\n\n const contextValue: UploadItemContextValue = {\n id,\n file: item.file,\n state: item.state,\n abort: () => upload.abortUpload(id),\n retry: () => upload.retryUpload(id),\n remove: () => upload.removeItem(id),\n };\n\n return (\n <UploadItemContext.Provider value={contextValue}>\n {typeof children === \"function\" ? children(contextValue) : children}\n </UploadItemContext.Provider>\n );\n}\n\n// ============ PROGRESS PRIMITIVE ============\n\n/**\n * Render props for Upload.Progress component.\n */\nexport interface UploadProgressRenderProps {\n /** Progress percentage (0-100) */\n progress: number;\n /** Bytes uploaded so far */\n bytesUploaded: number;\n /** Total bytes to upload */\n totalBytes: number;\n /** Whether any uploads are active */\n isUploading: boolean;\n}\n\n/**\n * Props for Upload.Progress component.\n */\nexport interface UploadProgressProps {\n /** Render function receiving progress state */\n children: (props: UploadProgressRenderProps) => ReactNode;\n}\n\n/**\n * Progress display component within an Upload.\n *\n * @example\n * ```tsx\n * <Upload.Progress>\n * {({ progress, isUploading }) => (\n * isUploading && <progress value={progress} max={100} />\n * )}\n * </Upload.Progress>\n * ```\n */\nfunction UploadProgress({ children }: UploadProgressProps) {\n const upload = useUploadContext();\n\n const renderProps: UploadProgressRenderProps = {\n progress: upload.state.progress,\n bytesUploaded: upload.state.totalBytesUploaded,\n totalBytes: upload.state.totalBytes,\n isUploading: upload.state.isUploading,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ STATUS PRIMITIVE ============\n\n/**\n * Render props for Upload.Status component.\n */\nexport interface UploadStatusRenderProps {\n /** Overall status */\n status: \"idle\" | \"uploading\" | \"success\" | \"error\";\n /** Whether idle (no uploads active or completed) */\n isIdle: boolean;\n /** Whether uploading */\n isUploading: boolean;\n /** Whether all uploads succeeded */\n isSuccess: boolean;\n /** Whether any upload failed */\n isError: boolean;\n /** Whether all uploads completed (success or failure) */\n isComplete: boolean;\n /** Number of total items */\n total: number;\n /** Number of successful uploads */\n successful: number;\n /** Number of failed uploads */\n failed: number;\n /** Number of currently uploading */\n uploading: number;\n}\n\n/**\n * Props for Upload.Status component.\n */\nexport interface UploadStatusProps {\n /** Render function receiving status state */\n children: (props: UploadStatusRenderProps) => ReactNode;\n}\n\n/**\n * Status display component within an Upload.\n *\n * @example\n * ```tsx\n * <Upload.Status>\n * {({ status, total, successful, failed }) => (\n * <div>\n * Status: {status}\n * ({successful}/{total} uploaded, {failed} failed)\n * </div>\n * )}\n * </Upload.Status>\n * ```\n */\nfunction UploadStatus({ children }: UploadStatusProps) {\n const upload = useUploadContext();\n const { state } = upload;\n\n // Derive overall status\n let status: \"idle\" | \"uploading\" | \"success\" | \"error\" = \"idle\";\n if (state.isUploading) {\n status = \"uploading\";\n } else if (state.isComplete) {\n status = state.failed > 0 ? \"error\" : \"success\";\n }\n\n const renderProps: UploadStatusRenderProps = {\n status,\n isIdle: status === \"idle\",\n isUploading: state.isUploading,\n isSuccess: state.isComplete && state.failed === 0,\n isError: state.failed > 0,\n isComplete: state.isComplete,\n total: state.total,\n successful: state.successful,\n failed: state.failed,\n uploading: state.uploading,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ ERROR PRIMITIVE ============\n\n/**\n * Render props for Upload.Error component.\n */\nexport interface UploadErrorRenderProps {\n /** Whether there are any errors */\n hasError: boolean;\n /** Number of failed uploads */\n failedCount: number;\n /** Failed items */\n failedItems: UploadItem[];\n /** Reset/clear all errors */\n reset: () => void;\n}\n\n/**\n * Props for Upload.Error component.\n */\nexport interface UploadErrorProps {\n /** Render function receiving error state */\n children: (props: UploadErrorRenderProps) => ReactNode;\n}\n\n/**\n * Error display component within an Upload.\n *\n * @example\n * ```tsx\n * <Upload.Error>\n * {({ hasError, failedItems, reset }) => (\n * hasError && (\n * <div>\n * {failedItems.map(item => (\n * <p key={item.id}>{item.file.name}: {item.state.error?.message}</p>\n * ))}\n * <button onClick={reset}>Clear</button>\n * </div>\n * )\n * )}\n * </Upload.Error>\n * ```\n */\nfunction UploadError({ children }: UploadErrorProps) {\n const upload = useUploadContext();\n\n const failedItems = upload.items.filter((item) =>\n [\"error\", \"aborted\"].includes(item.state.status),\n );\n\n const renderProps: UploadErrorRenderProps = {\n hasError: failedItems.length > 0,\n failedCount: failedItems.length,\n failedItems,\n reset: upload.clearCompleted,\n };\n\n return <>{children(renderProps)}</>;\n}\n\n// ============ ACTION PRIMITIVES ============\n\n/**\n * Props for Upload.Cancel component.\n */\nexport interface UploadCancelProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Cancel button that aborts all active uploads.\n * Automatically disabled when no uploads are active.\n */\nfunction UploadCancel({ children, disabled, ...props }: UploadCancelProps) {\n const upload = useUploadContext();\n\n const handleClick = useCallback(() => {\n upload.abortAll();\n }, [upload]);\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || !upload.state.isUploading}\n {...props}\n >\n {children}\n </button>\n );\n}\n\n/**\n * Props for Upload.Retry component.\n */\nexport interface UploadRetryProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Retry button that retries all failed uploads.\n * Automatically disabled when no failed uploads exist.\n */\nfunction UploadRetry({ children, disabled, ...props }: UploadRetryProps) {\n const upload = useUploadContext();\n\n const handleClick = useCallback(() => {\n upload.retryFailed();\n }, [upload]);\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || upload.state.failed === 0}\n {...props}\n >\n {children}\n </button>\n );\n}\n\n/**\n * Props for Upload.Reset component.\n */\nexport interface UploadResetProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Reset button that clears all items and resets state.\n */\nfunction UploadReset({ children, ...props }: UploadResetProps) {\n const upload = useUploadContext();\n\n const handleClick = useCallback(() => {\n upload.clearAll();\n }, [upload]);\n\n return (\n <button type=\"button\" onClick={handleClick} {...props}>\n {children}\n </button>\n );\n}\n\n/**\n * Props for Upload.StartAll component.\n */\nexport interface UploadStartAllProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Start all button that begins all queued uploads.\n * Primarily useful when autoStart is disabled.\n * Automatically disabled when uploads are already active.\n */\nfunction UploadStartAll({ children, disabled, ...props }: UploadStartAllProps) {\n const upload = useUploadContext();\n\n const handleClick = useCallback(() => {\n upload.startAll();\n }, [upload]);\n\n // Count idle items\n const idleCount = upload.items.filter(\n (item) => item.state.status === \"idle\",\n ).length;\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || upload.state.isUploading || idleCount === 0}\n {...props}\n >\n {children}\n </button>\n );\n}\n\n/**\n * Props for Upload.ClearCompleted component.\n */\nexport interface UploadClearCompletedProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n /** Button content */\n children: ReactNode;\n}\n\n/**\n * Clear completed button that removes all finished uploads from the list.\n * Automatically disabled when no completed uploads exist.\n */\nfunction UploadClearCompleted({\n children,\n disabled,\n ...props\n}: UploadClearCompletedProps) {\n const upload = useUploadContext();\n\n const handleClick = useCallback(() => {\n upload.clearCompleted();\n }, [upload]);\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || upload.state.completed === 0}\n {...props}\n >\n {children}\n </button>\n );\n}\n\n// ============ COMPOUND COMPONENT EXPORT ============\n\n/**\n * Upload compound component for file uploads.\n *\n * Provides a composable, headless API for building upload interfaces.\n * Supports both single-file and multi-file modes via the `multiple` prop.\n * All sub-components use render props for complete UI control.\n *\n * @example Single file upload\n * ```tsx\n * <Upload onSuccess={handleSuccess}>\n * <Upload.DropZone accept=\"image/*\">\n * {({ isDragging, getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * {isDragging ? \"Drop here\" : \"Drag or click\"}\n * </div>\n * )}\n * </Upload.DropZone>\n * <Upload.Progress>\n * {({ progress }) => <progress value={progress} max={100} />}\n * </Upload.Progress>\n * </Upload>\n * ```\n *\n * @example Multi-file upload\n * ```tsx\n * <Upload multiple maxConcurrent={3} onComplete={handleComplete}>\n * <Upload.DropZone>\n * {({ getRootProps, getInputProps }) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * Drop files here\n * </div>\n * )}\n * </Upload.DropZone>\n * <Upload.Items>\n * {({ items }) => items.map(item => (\n * <Upload.Item key={item.id} id={item.id}>\n * {({ file, state, abort, remove }) => (\n * <div>\n * {file.name}: {state.progress}%\n * <button onClick={abort}>Cancel</button>\n * <button onClick={remove}>Remove</button>\n * </div>\n * )}\n * </Upload.Item>\n * ))}\n * </Upload.Items>\n * <Upload.StartAll>Upload All</Upload.StartAll>\n * <Upload.Cancel>Cancel All</Upload.Cancel>\n * <Upload.ClearCompleted>Clear Completed</Upload.ClearCompleted>\n * </Upload>\n * ```\n */\nexport const Upload = Object.assign(UploadRoot, {\n DropZone: UploadDropZone,\n Items: UploadItems,\n Item: UploadItem,\n Progress: UploadProgress,\n Status: UploadStatus,\n Error: UploadError,\n Cancel: UploadCancel,\n Retry: UploadRetry,\n Reset: UploadReset,\n StartAll: UploadStartAll,\n ClearCompleted: UploadClearCompleted,\n});\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"uploadista-provider-Cb13AK7Z.d.mts","names":[],"sources":["../src/components/flow-primitives.tsx","../src/components/flow-upload-list.tsx","../src/components/upload-list.tsx","../src/components/upload-zone.tsx","../src/components/uploadista-provider.tsx"],"sourcesContent":[],"mappings":"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"}
|