@uploadista/vue 1.0.0-beta.3 → 1.0.0-beta.4

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.
Files changed (39) hide show
  1. package/dist/components/index.d.mts +2 -3
  2. package/dist/components/index.mjs +1 -1
  3. package/dist/components-D8w-zvVb.mjs +2 -0
  4. package/dist/components-D8w-zvVb.mjs.map +1 -0
  5. package/dist/composables/index.d.mts +1 -1
  6. package/dist/composables/index.mjs +1 -1
  7. package/dist/{useUploadMetrics-CJesoLV7.mjs → composables-CH4pv7yG.mjs} +2 -2
  8. package/dist/composables-CH4pv7yG.mjs.map +1 -0
  9. package/dist/{useUploadMetrics-DEdjOjLp.d.mts → index-BlM5dmy_.d.mts} +49 -53
  10. package/dist/index-BlM5dmy_.d.mts.map +1 -0
  11. package/dist/{index-CxdtdMrD.d.mts → index-DCyePMQF.d.mts} +45 -46
  12. package/dist/index-DCyePMQF.d.mts.map +1 -0
  13. package/dist/{UploadistaProvider.vue-_qDn5Gvp.d.mts → index-DcNYDFLL.d.mts} +5 -7
  14. package/dist/index-DcNYDFLL.d.mts.map +1 -0
  15. package/dist/index.d.mts +4 -7
  16. package/dist/index.mjs +1 -1
  17. package/dist/providers/index.d.mts +1 -1
  18. package/dist/providers/index.mjs +1 -1
  19. package/dist/{UploadistaProvider-DU4YVCy4.mjs → providers-Dhq5W5tR.mjs} +2 -2
  20. package/dist/providers-Dhq5W5tR.mjs.map +1 -0
  21. package/dist/{upload-y0K2veej.css → style.css} +0 -5
  22. package/dist/{useUploadistaClient-C3qbTB18.mjs → useUploadistaClient-CgabcTy6.mjs} +1 -1
  23. package/dist/{useUploadistaClient-C3qbTB18.mjs.map → useUploadistaClient-CgabcTy6.mjs.map} +1 -1
  24. package/dist/utils/index.d.mts.map +1 -1
  25. package/dist/utils/index.mjs +1 -1
  26. package/dist/utils/index.mjs.map +1 -1
  27. package/package.json +9 -8
  28. package/tsconfig.json +0 -1
  29. package/tsdown.config.ts +3 -1
  30. package/dist/UploadistaProvider-DU4YVCy4.mjs.map +0 -1
  31. package/dist/UploadistaProvider.vue-_qDn5Gvp.d.mts.map +0 -1
  32. package/dist/index-CxdtdMrD.d.mts.map +0 -1
  33. package/dist/is-browser-file-CN7ymiO5.mjs +0 -2
  34. package/dist/is-browser-file-CN7ymiO5.mjs.map +0 -1
  35. package/dist/upload-BJHmqKbp.mjs +0 -2
  36. package/dist/upload-BJHmqKbp.mjs.map +0 -1
  37. package/dist/upload-y0K2veej.css.map +0 -1
  38. package/dist/useUploadMetrics-CJesoLV7.mjs.map +0 -1
  39. package/dist/useUploadMetrics-DEdjOjLp.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composables-CH4pv7yG.mjs","names":["initialState","initialState"],"sources":["../src/composables/useFlowManagerContext.ts","../src/composables/useFlow.ts","../src/composables/useDragDrop.ts","../src/composables/eventUtils.ts","../src/composables/useFlowEvents.ts","../src/composables/useUploadEvents.ts","../src/composables/useUploadistaEvents.ts","../src/composables/useMultiFlowUpload.ts","../src/composables/useMultiUpload.ts","../src/composables/useUpload.ts","../src/composables/useUploadMetrics.ts"],"sourcesContent":["import type {\n FlowManager,\n FlowManagerCallbacks,\n FlowUploadOptions,\n} from \"@uploadista/client-core\";\nimport { inject } from \"vue\";\n\n/**\n * Context value providing access to flow managers\n */\ninterface FlowManagerContextValue {\n getManager: (\n flowId: string,\n callbacks: FlowManagerCallbacks,\n options: FlowUploadOptions,\n ) => FlowManager<unknown>;\n releaseManager: (flowId: string) => void;\n}\n\n/**\n * Composable to access the FlowManager context.\n * Must be used within a FlowManagerProvider.\n *\n * @returns FlowManager context value with getManager and releaseManager functions\n * @throws Error if used outside of FlowManagerProvider\n *\n * @example\n * ```ts\n * function setup() {\n * const { getManager, releaseManager } = useFlowManagerContext();\n * // Use to create managers...\n * }\n * ```\n */\nexport function useFlowManagerContext(): FlowManagerContextValue {\n const context = inject<FlowManagerContextValue>(\"flowManagerContext\");\n\n if (!context) {\n throw new Error(\n \"useFlowManagerContext must be used within a FlowManagerProvider. \" +\n \"Make sure to wrap your component tree with <FlowManagerProvider>.\",\n );\n }\n\n return context;\n}\n","import type { FlowUploadOptions } from \"@uploadista/client-browser\";\nimport type {\n FlowManager,\n FlowUploadState,\n FlowUploadStatus,\n InputExecutionState,\n} from \"@uploadista/client-core\";\nimport type { TypedOutput } from \"@uploadista/core/flow\";\nimport {\n computed,\n onMounted,\n onUnmounted,\n type Ref,\n readonly,\n ref,\n shallowReadonly,\n} from \"vue\";\nimport { useFlowManagerContext } from \"./useFlowManagerContext\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\n// Re-export types from core for convenience\nexport type { FlowUploadState, FlowUploadStatus, InputExecutionState };\n\n/**\n * Input metadata discovered from the flow\n */\nexport interface FlowInputMetadata {\n /** Input node ID */\n nodeId: string;\n /** Human-readable node name */\n nodeName: string;\n /** Node description explaining what input is needed */\n nodeDescription: string;\n /** Input type ID from inputTypeRegistry - describes how clients interact with this node */\n inputTypeId?: string;\n /** Whether this input is required */\n required: boolean;\n}\n\n/**\n * Return value from the useFlow composable with upload control methods and state.\n *\n * @property state - Complete flow upload state with progress and outputs\n * @property inputMetadata - Metadata about discovered input nodes (null until discovered)\n * @property inputStates - Per-input execution state for multi-input flows\n * @property inputs - Current input values set via setInput()\n * @property setInput - Set an input value for a specific node (for progressive provision)\n * @property execute - Execute the flow with current inputs (auto-detects types)\n * @property upload - Convenience method for single-file upload (same as execute with one file input)\n * @property abort - Cancel the current upload and flow execution\n * @property pause - Pause the current upload\n * @property reset - Reset state to idle (clears all data)\n * @property isUploading - True when upload or processing is active\n * @property isUploadingFile - True only during file upload phase\n * @property isProcessing - True only during flow processing phase\n * @property isDiscoveringInputs - True while discovering flow inputs\n */\nexport interface UseFlowReturn {\n /**\n * Current upload state\n */\n state: Readonly<Ref<FlowUploadState>>;\n\n /**\n * Discovered input nodes metadata (null until discovery completes)\n */\n inputMetadata: Readonly<Ref<FlowInputMetadata[] | null>>;\n\n /**\n * Per-input execution state for multi-input flows\n */\n inputStates: Readonly<Ref<ReadonlyMap<string, InputExecutionState>>>;\n\n /**\n * Current inputs set via setInput()\n */\n inputs: Readonly<Ref<Record<string, unknown>>>;\n\n /**\n * Set an input value for a specific node.\n * For progressive input provision before calling execute().\n *\n * @param nodeId - The input node ID\n * @param value - The input value (File, URL string, or structured data)\n */\n setInput: (nodeId: string, value: unknown) => void;\n\n /**\n * Execute the flow with current inputs.\n * Automatically detects input types and routes appropriately.\n * For single input, uses standard upload path.\n * For multiple inputs, requires multiInputUploadFn.\n */\n execute: () => Promise<void>;\n\n /**\n * Upload a single file through the flow (convenience method).\n * Equivalent to setInput(firstNodeId, file) + execute().\n *\n * @param file - File or Blob to upload\n */\n upload: (file: File | Blob) => Promise<void>;\n\n /**\n * Abort the current upload\n */\n abort: () => Promise<void>;\n\n /**\n * Pause the current upload\n */\n pause: () => Promise<void>;\n\n /**\n * Resume a paused upload\n */\n resume: () => Promise<void>;\n\n /**\n * Reset the upload state and clear all inputs\n */\n reset: () => void;\n\n /**\n * Whether an upload or flow execution is in progress (uploading OR processing)\n */\n isUploading: Readonly<Ref<boolean>>;\n\n /**\n * Whether the file is currently being uploaded (chunks being sent)\n */\n isUploadingFile: Readonly<Ref<boolean>>;\n\n /**\n * Whether the flow is currently processing (after upload completes)\n */\n isProcessing: Readonly<Ref<boolean>>;\n\n /**\n * Whether the hook is discovering flow inputs\n */\n isDiscoveringInputs: Readonly<Ref<boolean>>;\n\n /**\n * Whether the flow is currently paused\n */\n isPaused: Readonly<Ref<boolean>>;\n}\n\nconst initialState: FlowUploadState = {\n status: \"idle\",\n progress: 0,\n bytesUploaded: 0,\n totalBytes: null,\n error: null,\n jobId: null,\n flowStarted: false,\n currentNodeName: null,\n currentNodeType: null,\n flowOutputs: null,\n pausedAtNodeId: null,\n};\n\n/**\n * Vue composable for executing flows with single or multiple inputs.\n * Automatically discovers input nodes and detects input types (File, URL, structured data).\n * Supports progressive input provision via setInput() and execute().\n *\n * This is the unified flow composable that replaces useFlowUpload for advanced use cases.\n * It provides:\n * - Auto-discovery of flow input nodes\n * - Automatic input type detection (file -> upload, string -> URL, object -> data)\n * - Progressive input provision via setInput()\n * - Multi-input support with parallel coordination\n * - Per-input state tracking\n *\n * Must be used within FlowManagerProvider (which must be within UploadistaProvider).\n * Flow events are automatically routed by the provider to the appropriate manager.\n *\n * @param options - Flow upload configuration including flow ID and event handlers\n * @returns Flow upload state and control methods\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useFlow } from '@uploadista/vue';\n *\n * // Single file upload (simple case)\n * const flow = useFlow({\n * flowConfig: {\n * flowId: \"image-optimization\",\n * storageId: \"s3-images\",\n * },\n * onSuccess: (outputs) => {\n * console.log(\"Flow outputs:\", outputs);\n * },\n * });\n *\n * const handleFileChange = (event: Event) => {\n * const file = (event.target as HTMLInputElement).files?.[0];\n * if (file) flow.upload(file);\n * };\n * </script>\n *\n * <template>\n * <div>\n * <input type=\"file\" @change=\"handleFileChange\" />\n * <div v-if=\"flow.isUploading.value\">Progress: {{ flow.state.value.progress }}%</div>\n * </div>\n * </template>\n * ```\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useFlow } from '@uploadista/vue';\n *\n * // Multi-input with progressive provision\n * const flow = useFlow({\n * flowConfig: {\n * flowId: \"multi-source-processing\",\n * storageId: \"default\",\n * },\n * });\n *\n * const handleInputChange = (nodeId: string, event: Event) => {\n * const target = event.target as HTMLInputElement;\n * if (target.type === 'file') {\n * const file = target.files?.[0];\n * if (file) flow.setInput(nodeId, file);\n * } else {\n * flow.setInput(nodeId, target.value);\n * }\n * };\n * </script>\n *\n * <template>\n * <div v-if=\"flow.inputMetadata.value\">\n * <div v-for=\"input in flow.inputMetadata.value\" :key=\"input.nodeId\">\n * <label>{{ input.nodeName }}</label>\n * <input\n * v-if=\"input.inputTypeId === 'streaming-input-v1'\"\n * type=\"file\"\n * @change=\"(e) => handleInputChange(input.nodeId, e)\"\n * />\n * <input\n * v-else\n * type=\"url\"\n * @change=\"(e) => handleInputChange(input.nodeId, e)\"\n * />\n * </div>\n * <button @click=\"flow.execute\" :disabled=\"flow.isUploading.value\">\n * Execute Flow\n * </button>\n * </div>\n * </template>\n * ```\n *\n * @see {@link useFlowUpload} for a simpler file-only upload composable\n */\nexport function useFlow(options: FlowUploadOptions): UseFlowReturn {\n const { client } = useUploadistaClient();\n const { getManager, releaseManager } = useFlowManagerContext();\n\n const state = ref<FlowUploadState>(initialState);\n const inputMetadata = ref<FlowInputMetadata[] | null>(null);\n const isDiscoveringInputs = ref(false);\n const inputs = ref<Record<string, unknown>>({});\n const inputStates = ref<ReadonlyMap<string, InputExecutionState>>(new Map());\n\n let manager: FlowManager<unknown> | null = null;\n\n // Store latest options in a ref to access in callbacks\n const optionsRef = ref(options);\n let pollInterval: ReturnType<typeof setInterval> | null = null;\n\n // Auto-discover flow inputs on mount\n onMounted(async () => {\n // Discover inputs\n isDiscoveringInputs.value = true;\n try {\n const { flow } = await client.getFlow(options.flowConfig.flowId);\n\n // Find all input nodes\n const inputNodes = flow.nodes.filter((node) => node.type === \"input\");\n\n const metadata: FlowInputMetadata[] = inputNodes.map((node) => ({\n nodeId: node.id,\n nodeName: node.name,\n nodeDescription: node.description,\n inputTypeId: node.inputTypeId,\n // TODO: Add required field to node schema to determine if input is required\n required: true,\n }));\n\n inputMetadata.value = metadata;\n } catch (error) {\n console.error(\"Failed to discover flow inputs:\", error);\n } finally {\n isDiscoveringInputs.value = false;\n }\n\n // Create stable callback wrappers\n const stableCallbacks = {\n onStateChange: (newState: FlowUploadState) => {\n state.value = newState;\n },\n onProgress: (\n uploadId: string,\n bytesUploaded: number,\n totalBytes: number | null,\n ) => {\n optionsRef.value.onProgress?.(uploadId, bytesUploaded, totalBytes);\n },\n onChunkComplete: (\n chunkSize: number,\n bytesAccepted: number,\n bytesTotal: number | null,\n ) => {\n optionsRef.value.onChunkComplete?.(\n chunkSize,\n bytesAccepted,\n bytesTotal,\n );\n },\n onFlowComplete: (outputs: TypedOutput[]) => {\n optionsRef.value.onFlowComplete?.(outputs);\n },\n onSuccess: (outputs: TypedOutput[]) => {\n optionsRef.value.onSuccess?.(outputs);\n },\n onError: (error: Error) => {\n optionsRef.value.onError?.(error);\n },\n onAbort: () => {\n optionsRef.value.onAbort?.();\n },\n };\n\n // Get manager from context\n manager = getManager(options.flowConfig.flowId, stableCallbacks, options);\n\n // Set up interval to poll input states for multi-input flows\n pollInterval = setInterval(() => {\n if (manager) {\n const states = manager.getInputStates();\n if (states.size > 0) {\n inputStates.value = new Map(states);\n }\n }\n }, 100); // Poll every 100ms\n });\n\n // Cleanup on unmount\n onUnmounted(() => {\n if (pollInterval) {\n clearInterval(pollInterval);\n pollInterval = null;\n }\n if (manager) {\n releaseManager(options.flowConfig.flowId);\n manager = null;\n }\n });\n\n // Set an input value\n const setInput = (nodeId: string, value: unknown) => {\n inputs.value = { ...inputs.value, [nodeId]: value };\n };\n\n // Execute flow with current inputs\n const execute = async () => {\n if (!manager) {\n throw new Error(\"FlowManager not initialized\");\n }\n\n if (Object.keys(inputs.value).length === 0) {\n throw new Error(\n \"No inputs provided. Use setInput() to provide inputs before calling execute()\",\n );\n }\n\n await manager.executeFlow(inputs.value);\n };\n\n // Convenience method for single file upload\n const upload = async (file: File | Blob) => {\n if (!manager) {\n throw new Error(\"FlowManager not initialized\");\n }\n\n // If we have input metadata, use the first input node\n // Otherwise, let the manager discover it\n if (inputMetadata.value && inputMetadata.value.length > 0) {\n const firstInputNode = inputMetadata.value[0];\n if (!firstInputNode) {\n throw new Error(\"No input nodes found\");\n }\n inputs.value = { [firstInputNode.nodeId]: file };\n await manager.executeFlow({ [firstInputNode.nodeId]: file });\n } else {\n // Fall back to direct upload (manager will handle discovery)\n await manager.upload(file);\n }\n };\n\n const abort = async () => {\n await manager?.abort();\n };\n\n const pause = async () => {\n await manager?.pause();\n };\n\n const resume = async () => {\n await manager?.resume();\n };\n\n const reset = () => {\n manager?.reset();\n inputs.value = {};\n inputStates.value = new Map();\n };\n\n // Derive computed values from state\n const isUploading = computed(\n () =>\n state.value.status === \"uploading\" || state.value.status === \"processing\",\n );\n const isUploadingFile = computed(() => state.value.status === \"uploading\");\n const isProcessing = computed(() => state.value.status === \"processing\");\n const isPaused = computed(() => state.value.status === \"paused\");\n\n return {\n state: shallowReadonly(state),\n inputMetadata: shallowReadonly(inputMetadata),\n inputStates: shallowReadonly(inputStates),\n inputs: shallowReadonly(inputs),\n setInput,\n execute,\n upload,\n abort,\n pause,\n resume,\n reset,\n isUploading: readonly(isUploading),\n isUploadingFile: readonly(isUploadingFile),\n isProcessing: readonly(isProcessing),\n isDiscoveringInputs: readonly(isDiscoveringInputs),\n isPaused: readonly(isPaused),\n };\n}\n","import { computed, readonly, ref } from \"vue\";\n\nexport interface DragDropOptions {\n /**\n * Accept specific file types (MIME types or file extensions)\n */\n accept?: string[];\n\n /**\n * Maximum number of files allowed\n */\n maxFiles?: number;\n\n /**\n * Maximum file size in bytes\n */\n maxFileSize?: number;\n\n /**\n * Whether to allow multiple files\n */\n multiple?: boolean;\n\n /**\n * Custom validation function for files\n */\n validator?: (files: File[]) => string[] | null;\n\n /**\n * Called when files are dropped or selected\n */\n onFilesReceived?: (files: File[]) => void;\n\n /**\n * Called when validation fails\n */\n onValidationError?: (errors: string[]) => void;\n\n /**\n * Called when drag state changes\n */\n onDragStateChange?: (isDragging: boolean) => void;\n}\n\nexport interface DragDropState {\n /**\n * Whether files are currently being dragged over the drop zone\n */\n readonly isDragging: boolean;\n\n /**\n * Whether the drag is currently over the drop zone\n */\n readonly isOver: boolean;\n\n /**\n * Whether the dragged items are valid files\n */\n readonly isValid: boolean;\n\n /**\n * Current validation errors\n */\n readonly errors: readonly string[];\n}\n\nconst initialState: DragDropState = {\n isDragging: false,\n isOver: false,\n isValid: true,\n errors: [],\n};\n\n/**\n * Vue composable for handling drag and drop file uploads with validation.\n * Provides drag state management, file validation, and file picker integration.\n *\n * @param options - Configuration and event handlers\n * @returns Drag and drop state and handlers\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useDragDrop } from '@uploadista/vue';\n * import { ref } from 'vue';\n *\n * const inputRef = ref<HTMLInputElement>();\n *\n * const dragDrop = useDragDrop({\n * accept: ['image/*', '.pdf'],\n * maxFiles: 5,\n * maxFileSize: 10 * 1024 * 1024, // 10MB\n * multiple: true,\n * onFilesReceived: (files) => {\n * console.log('Received files:', files);\n * // Process files with upload composables\n * },\n * onValidationError: (errors) => {\n * console.error('Validation errors:', errors);\n * },\n * });\n *\n * const openFilePicker = () => {\n * inputRef.value?.click();\n * };\n * </script>\n *\n * <template>\n * <div>\n * <div\n * @dragenter=\"dragDrop.onDragEnter\"\n * @dragover=\"dragDrop.onDragOver\"\n * @dragleave=\"dragDrop.onDragLeave\"\n * @drop=\"dragDrop.onDrop\"\n * @click=\"openFilePicker\"\n * :style=\"{\n * border: dragDrop.state.isDragging ? '2px dashed #007bff' : '2px dashed #ccc',\n * backgroundColor: dragDrop.state.isOver ? '#f8f9fa' : 'transparent',\n * padding: '2rem',\n * textAlign: 'center',\n * cursor: 'pointer',\n * }\"\n * >\n * <p v-if=\"dragDrop.state.isDragging\">Drop files here...</p>\n * <p v-else>Drag files here or click to select</p>\n *\n * <div v-if=\"dragDrop.state.errors.length > 0\" style=\"color: red; margin-top: 1rem\">\n * <p v-for=\"(error, index) in dragDrop.state.errors\" :key=\"index\">{{ error }}</p>\n * </div>\n * </div>\n *\n * <input\n * ref=\"inputRef\"\n * type=\"file\"\n * :multiple=\"dragDrop.inputProps.multiple\"\n * :accept=\"dragDrop.inputProps.accept\"\n * @change=\"dragDrop.onInputChange\"\n * style=\"display: none\"\n * />\n * </div>\n * </template>\n * ```\n */\nexport function useDragDrop(options: DragDropOptions = {}) {\n const {\n accept,\n maxFiles,\n maxFileSize,\n multiple = true,\n validator,\n onFilesReceived,\n onValidationError,\n onDragStateChange,\n } = options;\n\n const state = ref<DragDropState>({ ...initialState });\n const dragCounter = ref(0);\n\n const updateState = (update: Partial<DragDropState>) => {\n state.value = { ...state.value, ...update };\n };\n\n const validateFiles = (files: File[]): string[] => {\n const errors: string[] = [];\n\n // Check file count\n if (maxFiles && files.length > maxFiles) {\n errors.push(\n `Maximum ${maxFiles} files allowed. You selected ${files.length} files.`,\n );\n }\n\n // Check individual files\n for (const file of files) {\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n const maxSizeMB = (maxFileSize / (1024 * 1024)).toFixed(1);\n const fileSizeMB = (file.size / (1024 * 1024)).toFixed(1);\n errors.push(\n `File \"${file.name}\" (${fileSizeMB}MB) exceeds maximum size of ${maxSizeMB}MB.`,\n );\n }\n\n // Check file type\n if (accept && accept.length > 0) {\n const isAccepted = 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 if (!isAccepted) {\n errors.push(\n `File \"${file.name}\" type \"${file.type}\" is not accepted. Accepted types: ${accept.join(\", \")}.`,\n );\n }\n }\n }\n\n // Run custom validator\n if (validator) {\n const customErrors = validator(files);\n if (customErrors) {\n errors.push(...customErrors);\n }\n }\n\n return errors;\n };\n\n const processFiles = (files: File[]) => {\n const fileArray = Array.from(files);\n const errors = validateFiles(fileArray);\n\n if (errors.length > 0) {\n updateState({ errors, isValid: false });\n onValidationError?.(errors);\n } else {\n updateState({ errors: [], isValid: true });\n onFilesReceived?.(fileArray);\n }\n };\n\n const getFilesFromDataTransfer = (dataTransfer: DataTransfer): File[] => {\n const files: File[] = [];\n\n if (dataTransfer.items) {\n // Use DataTransferItemList interface\n for (let i = 0; i < dataTransfer.items.length; i++) {\n const item = dataTransfer.items[i];\n if (item && item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n files.push(file);\n }\n }\n }\n } else {\n // Fallback to DataTransfer.files\n for (let i = 0; i < dataTransfer.files.length; i++) {\n const file = dataTransfer.files[i];\n if (file) {\n files.push(file);\n }\n }\n }\n\n return files;\n };\n\n const onDragEnter = (event: DragEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n dragCounter.value++;\n\n if (dragCounter.value === 1) {\n updateState({ isDragging: true, isOver: true });\n onDragStateChange?.(true);\n }\n };\n\n const onDragOver = (event: DragEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n // Set dropEffect to indicate what operation is allowed\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = \"copy\";\n }\n };\n\n const onDragLeave = (event: DragEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n dragCounter.value--;\n\n if (dragCounter.value === 0) {\n updateState({ isDragging: false, isOver: false, errors: [] });\n onDragStateChange?.(false);\n }\n };\n\n const onDrop = (event: DragEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n dragCounter.value = 0;\n updateState({ isDragging: false, isOver: false });\n onDragStateChange?.(false);\n\n if (event.dataTransfer) {\n const files = getFilesFromDataTransfer(event.dataTransfer);\n if (files.length > 0) {\n processFiles(files);\n }\n }\n };\n\n const onInputChange = (event: Event) => {\n const input = event.target as HTMLInputElement;\n if (input.files && input.files.length > 0) {\n const files = Array.from(input.files);\n processFiles(files);\n }\n\n // Reset input value to allow selecting the same files again\n input.value = \"\";\n };\n\n const reset = () => {\n state.value = { ...initialState };\n dragCounter.value = 0;\n };\n\n const inputProps = computed(() => ({\n type: \"file\" as const,\n multiple,\n accept: accept?.join(\", \"),\n }));\n\n return {\n state: readonly(state),\n onDragEnter,\n onDragOver,\n onDragLeave,\n onDrop,\n onInputChange,\n inputProps,\n processFiles,\n reset,\n };\n}\n","import { EventType, type FlowEvent } from \"@uploadista/core/flow\";\nimport { type UploadEvent, UploadEventType } from \"@uploadista/core/types\";\n\n/**\n * Type guard to check if an event is a flow event\n */\nexport function isFlowEvent(event: unknown): event is FlowEvent {\n if (typeof event !== \"object\" || event === null) return false;\n if (!(\"eventType\" in event)) return false;\n const e = event as { eventType: unknown };\n return (\n e.eventType === EventType.JobStart ||\n e.eventType === EventType.JobEnd ||\n e.eventType === EventType.FlowStart ||\n e.eventType === EventType.FlowEnd ||\n e.eventType === EventType.FlowError ||\n e.eventType === EventType.FlowPause ||\n e.eventType === EventType.FlowCancel ||\n e.eventType === EventType.NodeStart ||\n e.eventType === EventType.NodeEnd ||\n e.eventType === EventType.NodePause ||\n e.eventType === EventType.NodeResume ||\n e.eventType === EventType.NodeError ||\n e.eventType === EventType.NodeStream ||\n e.eventType === EventType.NodeResponse\n );\n}\n\n/**\n * Type guard to check if an event is an upload event\n */\nexport function isUploadEvent(event: unknown): event is UploadEvent {\n if (typeof event !== \"object\" || event === null) return false;\n if (!(\"type\" in event)) return false;\n const e = event as { type: unknown };\n return (\n e.type === UploadEventType.UPLOAD_STARTED ||\n e.type === UploadEventType.UPLOAD_PROGRESS ||\n e.type === UploadEventType.UPLOAD_COMPLETE ||\n e.type === UploadEventType.UPLOAD_FAILED ||\n e.type === UploadEventType.UPLOAD_VALIDATION_SUCCESS ||\n e.type === UploadEventType.UPLOAD_VALIDATION_FAILED ||\n e.type === UploadEventType.UPLOAD_VALIDATION_WARNING\n );\n}\n","import type { UploadistaEvent } from \"@uploadista/client-browser\";\nimport type {\n FlowEventFlowCancel,\n FlowEventFlowEnd,\n FlowEventFlowError,\n FlowEventFlowPause,\n FlowEventFlowStart,\n FlowEventJobEnd,\n FlowEventJobStart,\n FlowEventNodeEnd,\n FlowEventNodeError,\n FlowEventNodePause,\n FlowEventNodeResume,\n FlowEventNodeStart,\n} from \"@uploadista/core/flow\";\nimport { EventType } from \"@uploadista/core/flow\";\nimport { onBeforeUnmount, onMounted } from \"vue\";\nimport { isFlowEvent } from \"./eventUtils\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\n/**\n * Options for handling flow execution events.\n *\n * All callbacks are optional - only provide handlers for events you care about.\n */\nexport interface UseFlowEventsOptions {\n /** Called when a job starts execution */\n onJobStart?: (event: FlowEventJobStart) => void;\n /** Called when a job completes (success or failure) */\n onJobEnd?: (event: FlowEventJobEnd) => void;\n /** Called when a flow begins execution */\n onFlowStart?: (event: FlowEventFlowStart) => void;\n /** Called when a flow completes successfully */\n onFlowEnd?: (event: FlowEventFlowEnd) => void;\n /** Called when a flow encounters an error */\n onFlowError?: (event: FlowEventFlowError) => void;\n /** Called when a flow is paused by user request */\n onFlowPause?: (event: FlowEventFlowPause) => void;\n /** Called when a flow is cancelled by user request */\n onFlowCancel?: (event: FlowEventFlowCancel) => void;\n /** Called when a node starts processing */\n onNodeStart?: (event: FlowEventNodeStart) => void;\n /** Called when a node completes successfully */\n onNodeEnd?: (event: FlowEventNodeEnd) => void;\n /** Called when a node pauses (waiting for additional data) */\n onNodePause?: (event: FlowEventNodePause) => void;\n /** Called when a paused node resumes execution */\n onNodeResume?: (event: FlowEventNodeResume) => void;\n /** Called when a node encounters an error */\n onNodeError?: (event: FlowEventNodeError) => void;\n}\n\n/**\n * Structured composable for handling flow execution events with type-safe callbacks.\n *\n * This composable provides a clean API for listening to specific flow events without\n * needing to manually filter events or use type guards.\n *\n * Must be used within UploadistaProvider.\n *\n * @param options - Object with optional callbacks for each flow event type\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useFlowEvents } from '@uploadista/vue';\n *\n * useFlowEvents({\n * onFlowStart: (event) => {\n * console.log('Flow started:', event.flowId);\n * },\n * onNodeStart: (event) => {\n * console.log('Node started:', event.nodeName);\n * },\n * onNodeEnd: (event) => {\n * console.log('Node completed:', event.nodeName, event.result);\n * },\n * onFlowEnd: (event) => {\n * console.log('Flow completed with outputs:', event.outputs);\n * },\n * onFlowError: (event) => {\n * console.error('Flow failed:', event.error);\n * },\n * });\n * </script>\n *\n * <template>\n * <div>Monitoring flow execution...</div>\n * </template>\n * ```\n */\nexport function useFlowEvents(options: UseFlowEventsOptions): void {\n const { subscribeToEvents } = useUploadistaClient();\n let unsubscribe: (() => void) | null = null;\n\n onMounted(() => {\n unsubscribe = subscribeToEvents((event: UploadistaEvent) => {\n // Only handle flow events\n if (!isFlowEvent(event)) return;\n\n // Route to appropriate callback based on event type\n switch (event.eventType) {\n case EventType.JobStart:\n options.onJobStart?.(event);\n break;\n case EventType.JobEnd:\n options.onJobEnd?.(event);\n break;\n case EventType.FlowStart:\n options.onFlowStart?.(event);\n break;\n case EventType.FlowEnd:\n options.onFlowEnd?.(event);\n break;\n case EventType.FlowError:\n options.onFlowError?.(event);\n break;\n case EventType.FlowPause:\n options.onFlowPause?.(event);\n break;\n case EventType.FlowCancel:\n options.onFlowCancel?.(event);\n break;\n case EventType.NodeStart:\n options.onNodeStart?.(event);\n break;\n case EventType.NodeEnd:\n options.onNodeEnd?.(event);\n break;\n case EventType.NodePause:\n options.onNodePause?.(event);\n break;\n case EventType.NodeResume:\n options.onNodeResume?.(event);\n break;\n case EventType.NodeError:\n options.onNodeError?.(event);\n break;\n }\n });\n });\n\n onBeforeUnmount(() => {\n unsubscribe?.();\n });\n}\n","import type { UploadistaEvent } from \"@uploadista/client-browser\";\nimport { UploadEventType } from \"@uploadista/core/types\";\nimport { onBeforeUnmount, onMounted } from \"vue\";\nimport { isUploadEvent } from \"./eventUtils\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\n/**\n * Upload progress event data\n */\nexport interface UploadProgressEventData {\n id: string;\n progress: number;\n total: number;\n flow?: {\n flowId: string;\n nodeId: string;\n jobId: string;\n };\n}\n\n/**\n * Upload started/complete event data (contains full UploadFile)\n */\nexport interface UploadFileEventData {\n // This will contain the full UploadFile schema\n [key: string]: unknown;\n flow?: {\n flowId: string;\n nodeId: string;\n jobId: string;\n };\n}\n\n/**\n * Upload failed event data\n */\nexport interface UploadFailedEventData {\n id: string;\n error: string;\n flow?: {\n flowId: string;\n nodeId: string;\n jobId: string;\n };\n}\n\n/**\n * Upload validation success event data\n */\nexport interface UploadValidationSuccessEventData {\n id: string;\n validationType: \"checksum\" | \"mimetype\";\n algorithm?: string;\n flow?: {\n flowId: string;\n nodeId: string;\n jobId: string;\n };\n}\n\n/**\n * Upload validation failed event data\n */\nexport interface UploadValidationFailedEventData {\n id: string;\n reason: string;\n expected: string;\n actual: string;\n flow?: {\n flowId: string;\n nodeId: string;\n jobId: string;\n };\n}\n\n/**\n * Upload validation warning event data\n */\nexport interface UploadValidationWarningEventData {\n id: string;\n message: string;\n flow?: {\n flowId: string;\n nodeId: string;\n jobId: string;\n };\n}\n\n/**\n * Options for handling upload events.\n *\n * All callbacks are optional - only provide handlers for events you care about.\n */\nexport interface UseUploadEventsOptions {\n /** Called when an upload starts */\n onUploadStarted?: (data: UploadFileEventData) => void;\n /** Called with upload progress updates */\n onUploadProgress?: (data: UploadProgressEventData) => void;\n /** Called when an upload completes successfully */\n onUploadComplete?: (data: UploadFileEventData) => void;\n /** Called when an upload fails */\n onUploadFailed?: (data: UploadFailedEventData) => void;\n /** Called when upload validation succeeds */\n onUploadValidationSuccess?: (data: UploadValidationSuccessEventData) => void;\n /** Called when upload validation fails */\n onUploadValidationFailed?: (data: UploadValidationFailedEventData) => void;\n /** Called when upload validation produces a warning */\n onUploadValidationWarning?: (data: UploadValidationWarningEventData) => void;\n}\n\n/**\n * Structured composable for handling upload events with type-safe callbacks.\n *\n * This composable provides a clean API for listening to specific upload events without\n * needing to manually filter events or use type guards.\n *\n * Must be used within UploadistaProvider.\n *\n * @param options - Object with optional callbacks for each upload event type\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useUploadEvents } from '@uploadista/vue';\n *\n * useUploadEvents({\n * onUploadStarted: (data) => {\n * console.log('Upload started:', data.id);\n * },\n * onUploadProgress: (data) => {\n * const percent = (data.progress / data.total) * 100;\n * console.log(`Upload progress: ${percent}%`);\n * },\n * onUploadComplete: (data) => {\n * console.log('Upload completed:', data);\n * },\n * onUploadFailed: (data) => {\n * console.error('Upload failed:', data.error);\n * },\n * });\n * </script>\n *\n * <template>\n * <div>Monitoring uploads...</div>\n * </template>\n * ```\n */\nexport function useUploadEvents(options: UseUploadEventsOptions): void {\n const { subscribeToEvents } = useUploadistaClient();\n let unsubscribe: (() => void) | null = null;\n\n onMounted(() => {\n unsubscribe = subscribeToEvents((event: UploadistaEvent) => {\n // Only handle upload events\n if (!isUploadEvent(event)) return;\n\n // Route to appropriate callback based on event type\n // Note: flow context is at the top level of the event, not inside data\n const flowContext = \"flow\" in event ? event.flow : undefined;\n\n switch (event.type) {\n case UploadEventType.UPLOAD_STARTED:\n options.onUploadStarted?.({\n ...(event.data as unknown as Omit<UploadFileEventData, \"flow\">),\n flow: flowContext,\n });\n break;\n case UploadEventType.UPLOAD_PROGRESS:\n options.onUploadProgress?.({\n ...(event.data as unknown as Omit<UploadProgressEventData, \"flow\">),\n flow: flowContext,\n });\n break;\n case UploadEventType.UPLOAD_COMPLETE:\n options.onUploadComplete?.({\n ...(event.data as unknown as Omit<UploadFileEventData, \"flow\">),\n flow: flowContext,\n });\n break;\n case UploadEventType.UPLOAD_FAILED:\n options.onUploadFailed?.({\n ...(event.data as unknown as Omit<UploadFailedEventData, \"flow\">),\n flow: flowContext,\n });\n break;\n case UploadEventType.UPLOAD_VALIDATION_SUCCESS:\n options.onUploadValidationSuccess?.({\n ...(event.data as unknown as Omit<\n UploadValidationSuccessEventData,\n \"flow\"\n >),\n flow: flowContext,\n });\n break;\n case UploadEventType.UPLOAD_VALIDATION_FAILED:\n options.onUploadValidationFailed?.({\n ...(event.data as unknown as Omit<\n UploadValidationFailedEventData,\n \"flow\"\n >),\n flow: flowContext,\n });\n break;\n case UploadEventType.UPLOAD_VALIDATION_WARNING:\n options.onUploadValidationWarning?.({\n ...(event.data as unknown as Omit<\n UploadValidationWarningEventData,\n \"flow\"\n >),\n flow: flowContext,\n });\n break;\n }\n });\n });\n\n onBeforeUnmount(() => {\n unsubscribe?.();\n });\n}\n","import type { UploadistaEvent } from \"@uploadista/client-browser\";\nimport { onBeforeUnmount, onMounted } from \"vue\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\n/**\n * Simple composable that subscribes to all Uploadista events (both flow and upload events).\n *\n * This is a low-level composable that provides access to all events. For more structured\n * event handling, consider using `useFlowEvents` or `useUploadEvents` instead.\n *\n * Must be used within UploadistaProvider.\n *\n * @param callback - Function called for every event emitted by the Uploadista client\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useUploadistaEvents, isFlowEvent, isUploadEvent } from '@uploadista/vue';\n *\n * useUploadistaEvents((event) => {\n * if (isFlowEvent(event)) {\n * console.log('Flow event:', event.eventType);\n * } else if (isUploadEvent(event)) {\n * console.log('Upload event:', event.type);\n * }\n * });\n * </script>\n *\n * <template>\n * <div>Listening to all events...</div>\n * </template>\n * ```\n */\nexport function useUploadistaEvents(\n callback: (event: UploadistaEvent) => void,\n): void {\n const { subscribeToEvents } = useUploadistaClient();\n let unsubscribe: (() => void) | null = null;\n\n onMounted(() => {\n unsubscribe = subscribeToEvents(callback);\n });\n\n onBeforeUnmount(() => {\n unsubscribe?.();\n });\n}\n","import type {\n BrowserUploadInput,\n FlowUploadItem,\n MultiFlowUploadOptions,\n MultiFlowUploadState,\n} from \"@uploadista/client-browser\";\nimport { computed, readonly, ref } from \"vue\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\n/**\n * Vue composable for uploading multiple files through a flow.\n *\n * Must be used within a component tree that has the Uploadista plugin installed.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useMultiFlowUpload } from '@uploadista/vue';\n *\n * const multiFlowUpload = useMultiFlowUpload({\n * flowConfig: {\n * flowId: \"batch-upload-flow\",\n * inputNodeId: \"upload-node\",\n * storageId: \"my-storage\",\n * },\n * maxConcurrent: 3,\n * onComplete: (items) => {\n * console.log(\"All uploads complete:\", items);\n * },\n * });\n *\n * const handleFileChange = (event: Event) => {\n * const files = (event.target as HTMLInputElement).files;\n * if (files) {\n * multiFlowUpload.addFiles(files);\n * multiFlowUpload.startUpload();\n * }\n * };\n * </script>\n *\n * <template>\n * <div>\n * <input type=\"file\" multiple @change=\"handleFileChange\" />\n *\n * <div v-for=\"item in multiFlowUpload.state.items\" :key=\"item.id\">\n * <span>{{ item.file.name }}</span>\n * <progress :value=\"item.progress\" :max=\"100\" />\n * <button\n * v-if=\"item.status === 'uploading'\"\n * @click=\"multiFlowUpload.abortUpload(item.id)\"\n * >\n * Cancel\n * </button>\n * </div>\n * </div>\n * </template>\n * ```\n */\nexport function useMultiFlowUpload(\n options: MultiFlowUploadOptions<BrowserUploadInput>,\n) {\n const client = useUploadistaClient();\n const items = ref<FlowUploadItem<BrowserUploadInput>[]>([]);\n const abortFns = ref<Map<string, () => void>>(new Map());\n const queue = ref<string[]>([]);\n const activeCount = ref(0);\n\n const maxConcurrent = options.maxConcurrent ?? 3;\n\n const calculateTotalProgress = (\n items: FlowUploadItem<BrowserUploadInput>[],\n ) => {\n if (items.length === 0) return 0;\n const totalProgress = items.reduce((sum, item) => sum + item.progress, 0);\n return Math.round(totalProgress / items.length);\n };\n\n const processQueue = async () => {\n if (activeCount.value >= maxConcurrent || queue.value.length === 0) {\n return;\n }\n\n const itemId = queue.value.shift();\n if (!itemId) return;\n\n const item = items.value.find((i) => i.id === itemId);\n if (!item || item.status !== \"pending\") {\n processQueue();\n return;\n }\n\n activeCount.value++;\n\n items.value = items.value.map((i) =>\n i.id === itemId ? { ...i, status: \"uploading\" as const } : i,\n );\n\n try {\n const { abort, jobId } = await client.client.uploadWithFlow(\n item.file,\n options.flowConfig,\n {\n onJobStart: (jobId: string) => {\n items.value = items.value.map((i) =>\n i.id === itemId ? { ...i, jobId } : i,\n );\n },\n onProgress: (\n _uploadId: string,\n bytesUploaded: number,\n totalBytes: number | null,\n ) => {\n const progress = totalBytes\n ? Math.round((bytesUploaded / totalBytes) * 100)\n : 0;\n\n items.value = items.value.map((i) => {\n if (i.id === itemId) {\n const updated = {\n ...i,\n progress,\n bytesUploaded,\n totalBytes: totalBytes || 0,\n };\n options.onItemProgress?.(updated);\n return updated;\n }\n return i;\n });\n },\n onSuccess: (outputs) => {\n items.value = items.value.map((i) => {\n if (i.id === itemId) {\n const updated = {\n ...i,\n status: \"success\" as const,\n result: outputs,\n progress: 100,\n };\n options.onItemSuccess?.(updated);\n return updated;\n }\n return i;\n });\n\n // Check if all uploads are complete\n const allComplete = items.value.every(\n (i) =>\n i.status === \"success\" ||\n i.status === \"error\" ||\n i.status === \"aborted\",\n );\n if (allComplete) {\n options.onComplete?.(items.value);\n }\n\n abortFns.value.delete(itemId);\n activeCount.value--;\n processQueue();\n },\n onError: (error: Error) => {\n items.value = items.value.map((i) => {\n if (i.id === itemId) {\n const updated = { ...i, status: \"error\" as const, error };\n options.onItemError?.(updated, error);\n return updated;\n }\n return i;\n });\n\n // Check if all uploads are complete\n const allComplete = items.value.every(\n (i) =>\n i.status === \"success\" ||\n i.status === \"error\" ||\n i.status === \"aborted\",\n );\n if (allComplete) {\n options.onComplete?.(items.value);\n }\n\n abortFns.value.delete(itemId);\n activeCount.value--;\n processQueue();\n },\n onShouldRetry: options.onShouldRetry,\n },\n );\n\n abortFns.value.set(itemId, abort);\n\n items.value = items.value.map((i) =>\n i.id === itemId ? { ...i, jobId } : i,\n );\n } catch (error) {\n items.value = items.value.map((i) =>\n i.id === itemId\n ? { ...i, status: \"error\" as const, error: error as Error }\n : i,\n );\n\n activeCount.value--;\n processQueue();\n }\n };\n\n const addFiles = (files: File[] | FileList) => {\n const fileArray = Array.from(files);\n const newItems: FlowUploadItem<BrowserUploadInput>[] = fileArray.map(\n (file) => ({\n id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n file,\n status: \"pending\",\n progress: 0,\n bytesUploaded: 0,\n totalBytes: file.size,\n error: null,\n result: null,\n jobId: null,\n }),\n );\n\n items.value = [...items.value, ...newItems];\n };\n\n const removeFile = (id: string) => {\n const abortFn = abortFns.value.get(id);\n if (abortFn) {\n abortFn();\n abortFns.value.delete(id);\n }\n\n items.value = items.value.filter((item) => item.id !== id);\n queue.value = queue.value.filter((queueId) => queueId !== id);\n };\n\n const startUpload = () => {\n const pendingItems = items.value.filter(\n (item) => item.status === \"pending\",\n );\n queue.value.push(...pendingItems.map((item) => item.id));\n\n for (let i = 0; i < maxConcurrent; i++) {\n processQueue();\n }\n };\n\n const abortUpload = (id: string) => {\n const abortFn = abortFns.value.get(id);\n if (abortFn) {\n abortFn();\n abortFns.value.delete(id);\n\n items.value = items.value.map((item) =>\n item.id === id ? { ...item, status: \"aborted\" as const } : item,\n );\n\n activeCount.value--;\n processQueue();\n }\n };\n\n const abortAll = () => {\n for (const abortFn of abortFns.value.values()) {\n abortFn();\n }\n abortFns.value.clear();\n queue.value = [];\n activeCount.value = 0;\n\n items.value = items.value.map((item) =>\n item.status === \"uploading\"\n ? { ...item, status: \"aborted\" as const }\n : item,\n );\n };\n\n const clear = () => {\n abortAll();\n items.value = [];\n };\n\n const retryUpload = (id: string) => {\n items.value = items.value.map((item) =>\n item.id === id\n ? {\n ...item,\n status: \"pending\" as const,\n progress: 0,\n bytesUploaded: 0,\n error: null,\n }\n : item,\n );\n\n queue.value.push(id);\n processQueue();\n };\n\n const state = computed<MultiFlowUploadState<BrowserUploadInput>>(() => ({\n items: items.value,\n totalProgress: calculateTotalProgress(items.value),\n activeUploads: items.value.filter((item) => item.status === \"uploading\")\n .length,\n completedUploads: items.value.filter((item) => item.status === \"success\")\n .length,\n failedUploads: items.value.filter((item) => item.status === \"error\").length,\n }));\n\n return {\n state: readonly(state),\n addFiles,\n removeFile,\n startUpload,\n abortUpload,\n abortAll,\n clear,\n retryUpload,\n isUploading: computed(() => state.value.activeUploads > 0),\n };\n}\n","import type { UploadOptions } from \"@uploadista/client-browser\";\nimport type { UploadMetrics } from \"@uploadista/client-core\";\nimport type { UploadFile } from \"@uploadista/core/types\";\nimport { computed, readonly, ref } from \"vue\";\nimport type { UploadInput, UploadState, UploadStatus } from \"./useUpload\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\nexport interface UploadItem {\n id: string;\n file: UploadInput;\n state: UploadState;\n}\n\nexport interface MultiUploadOptions\n extends Omit<UploadOptions, \"onSuccess\" | \"onError\" | \"onProgress\"> {\n /**\n * Maximum number of concurrent uploads\n */\n maxConcurrent?: number;\n\n /**\n * Called when an individual file upload starts\n */\n onUploadStart?: (item: UploadItem) => void;\n\n /**\n * Called when an individual file upload progresses\n */\n onUploadProgress?: (\n item: UploadItem,\n progress: number,\n bytesUploaded: number,\n totalBytes: number | null,\n ) => void;\n\n /**\n * Called when an individual file upload succeeds\n */\n onUploadSuccess?: (item: UploadItem, result: UploadFile) => void;\n\n /**\n * Called when an individual file upload fails\n */\n onUploadError?: (item: UploadItem, error: Error) => void;\n\n /**\n * Called when all uploads complete (successfully or with errors)\n */\n onComplete?: (results: {\n successful: UploadItem[];\n failed: UploadItem[];\n total: number;\n }) => void;\n}\n\nexport interface MultiUploadState {\n /**\n * Total number of uploads\n */\n total: number;\n\n /**\n * Number of completed uploads (successful + failed)\n */\n completed: number;\n\n /**\n * Number of successful uploads\n */\n successful: number;\n\n /**\n * Number of failed uploads\n */\n failed: number;\n\n /**\n * Number of currently uploading files\n */\n uploading: number;\n\n /**\n * Overall progress as a percentage (0-100)\n */\n progress: number;\n\n /**\n * Total bytes uploaded across all files\n */\n totalBytesUploaded: number;\n\n /**\n * Total bytes to upload across all files\n */\n totalBytes: number;\n\n /**\n * Whether any uploads are currently active\n */\n isUploading: boolean;\n\n /**\n * Whether all uploads have completed\n */\n isComplete: boolean;\n}\n\n/**\n * Vue composable for managing multiple file uploads with queue management,\n * concurrent upload limits, and batch operations.\n *\n * Must be used within a component tree that has the Uploadista plugin installed.\n *\n * @param options - Multi-upload configuration and event handlers\n * @returns Multi-upload state and control methods\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useMultiUpload } from '@uploadista/vue';\n *\n * const multiUpload = useMultiUpload({\n * maxConcurrent: 3,\n * onUploadSuccess: (item, result) => {\n * console.log(`${item.file.name} uploaded successfully`);\n * },\n * onComplete: (results) => {\n * console.log(`Upload batch complete: ${results.successful.length}/${results.total} successful`);\n * },\n * });\n *\n * const handleFileChange = (event: Event) => {\n * const files = (event.target as HTMLInputElement).files;\n * if (files) {\n * multiUpload.addFiles(Array.from(files));\n * }\n * };\n * </script>\n *\n * <template>\n * <div>\n * <input type=\"file\" multiple @change=\"handleFileChange\" />\n *\n * <div>Progress: {{ multiUpload.state.progress }}%</div>\n * <div>\n * {{ multiUpload.state.uploading }} uploading,\n * {{ multiUpload.state.successful }} successful,\n * {{ multiUpload.state.failed }} failed\n * </div>\n *\n * <button @click=\"multiUpload.startAll\" :disabled=\"multiUpload.state.isUploading\">\n * Start All\n * </button>\n * <button @click=\"multiUpload.abortAll\" :disabled=\"!multiUpload.state.isUploading\">\n * Abort All\n * </button>\n * <button @click=\"multiUpload.retryFailed\" :disabled=\"multiUpload.state.failed === 0\">\n * Retry Failed\n * </button>\n *\n * <div v-for=\"item in multiUpload.items\" :key=\"item.id\">\n * {{ item.file.name }}: {{ item.state.status }} ({{ item.state.progress }}%)\n * </div>\n * </div>\n * </template>\n * ```\n */\nexport function useMultiUpload(options: MultiUploadOptions = {}) {\n const uploadClient = useUploadistaClient();\n const { maxConcurrent = 3 } = options;\n const items = ref<UploadItem[]>([]);\n const nextId = ref(0);\n const activeUploads = ref(new Set<string>());\n\n // Store abort controllers for each upload\n const abortControllers = ref<Map<string, { abort: () => void }>>(new Map());\n\n // Generate a unique ID for each upload item\n const generateId = () => {\n return `upload-${Date.now()}-${nextId.value++}`;\n };\n\n // State update callback for individual uploads\n const onStateUpdate = (id: string, state: Partial<UploadState>) => {\n items.value = items.value.map((item) =>\n item.id === id ? { ...item, state: { ...item.state, ...state } } : item,\n );\n };\n\n // Check if all uploads are complete and trigger completion callback\n const checkForCompletion = () => {\n const allComplete = items.value.every((item) =>\n [\"success\", \"error\", \"aborted\"].includes(item.state.status),\n );\n\n if (allComplete && items.value.length > 0) {\n const successful = items.value.filter(\n (item) => item.state.status === \"success\",\n );\n const failed = items.value.filter((item) =>\n [\"error\", \"aborted\"].includes(item.state.status),\n );\n\n options.onComplete?.({\n successful,\n failed,\n total: items.value.length,\n });\n }\n };\n\n // Start the next available upload if we have capacity\n const startNextUpload = async () => {\n if (activeUploads.value.size >= maxConcurrent) {\n return;\n }\n\n const nextItem = items.value.find(\n (item) =>\n item.state.status === \"idle\" && !activeUploads.value.has(item.id),\n );\n\n if (!nextItem) {\n return;\n }\n\n activeUploads.value.add(nextItem.id);\n options.onUploadStart?.(nextItem);\n\n // Update state to uploading\n onStateUpdate(nextItem.id, { status: \"uploading\" });\n\n try {\n const controller = await uploadClient.client.upload(nextItem.file, {\n metadata: options.metadata,\n uploadLengthDeferred: options.uploadLengthDeferred,\n uploadSize: options.uploadSize,\n\n onProgress: (\n _uploadId: string,\n bytesUploaded: number,\n totalBytes: number | null,\n ) => {\n const progress = totalBytes\n ? Math.round((bytesUploaded / totalBytes) * 100)\n : 0;\n\n onStateUpdate(nextItem.id, {\n progress,\n bytesUploaded,\n totalBytes,\n });\n\n options.onUploadProgress?.(\n nextItem,\n progress,\n bytesUploaded,\n totalBytes,\n );\n },\n\n onChunkComplete: () => {\n // Optional: could expose this as an option\n },\n\n onSuccess: (result: UploadFile) => {\n onStateUpdate(nextItem.id, {\n status: \"success\",\n result,\n progress: 100,\n });\n\n const updatedItem = {\n ...nextItem,\n state: { ...nextItem.state, status: \"success\" as const, result },\n };\n options.onUploadSuccess?.(updatedItem, result);\n\n // Mark complete and start next\n activeUploads.value.delete(nextItem.id);\n abortControllers.value.delete(nextItem.id);\n startNextUpload();\n checkForCompletion();\n },\n\n onError: (error: Error) => {\n onStateUpdate(nextItem.id, {\n status: \"error\",\n error,\n });\n\n const updatedItem = {\n ...nextItem,\n state: { ...nextItem.state, status: \"error\" as const, error },\n };\n options.onUploadError?.(updatedItem, error);\n\n // Mark complete and start next\n activeUploads.value.delete(nextItem.id);\n abortControllers.value.delete(nextItem.id);\n startNextUpload();\n checkForCompletion();\n },\n\n onShouldRetry: options.onShouldRetry,\n });\n\n // Store abort controller\n abortControllers.value.set(nextItem.id, controller);\n } catch (error) {\n onStateUpdate(nextItem.id, {\n status: \"error\",\n error: error as Error,\n });\n\n const updatedItem = {\n ...nextItem,\n state: {\n ...nextItem.state,\n status: \"error\" as const,\n error: error as Error,\n },\n };\n options.onUploadError?.(updatedItem, error as Error);\n\n // Mark complete and start next\n activeUploads.value.delete(nextItem.id);\n abortControllers.value.delete(nextItem.id);\n startNextUpload();\n checkForCompletion();\n }\n };\n\n // Calculate overall state\n const state = computed<MultiUploadState>(() => {\n const itemsList = items.value;\n return {\n total: itemsList.length,\n completed: itemsList.filter((item) =>\n [\"success\", \"error\", \"aborted\"].includes(item.state.status),\n ).length,\n successful: itemsList.filter((item) => item.state.status === \"success\")\n .length,\n failed: itemsList.filter((item) =>\n [\"error\", \"aborted\"].includes(item.state.status),\n ).length,\n uploading: itemsList.filter((item) => item.state.status === \"uploading\")\n .length,\n progress:\n itemsList.length > 0\n ? Math.round(\n itemsList.reduce((sum, item) => sum + item.state.progress, 0) /\n itemsList.length,\n )\n : 0,\n totalBytesUploaded: itemsList.reduce(\n (sum, item) => sum + item.state.bytesUploaded,\n 0,\n ),\n totalBytes: itemsList.reduce(\n (sum, item) => sum + (item.state.totalBytes || 0),\n 0,\n ),\n isUploading: itemsList.some((item) => item.state.status === \"uploading\"),\n isComplete:\n itemsList.length > 0 &&\n itemsList.every((item) =>\n [\"success\", \"error\", \"aborted\"].includes(item.state.status),\n ),\n };\n });\n\n const addFiles = (files: UploadInput[]) => {\n const newItems: UploadItem[] = files.map((file) => {\n const id = generateId();\n return {\n id,\n file,\n state: {\n status: \"idle\",\n progress: 0,\n bytesUploaded: 0,\n totalBytes: file instanceof File ? file.size : null,\n error: null,\n result: null,\n },\n };\n });\n\n items.value = [...items.value, ...newItems];\n };\n\n const removeItem = (id: string) => {\n const item = items.value.find((i) => i.id === id);\n if (item && item.state.status === \"uploading\") {\n // Abort before removing\n const controller = abortControllers.value.get(id);\n if (controller) {\n controller.abort();\n abortControllers.value.delete(id);\n }\n }\n\n items.value = items.value.filter((item) => item.id !== id);\n activeUploads.value.delete(id);\n };\n\n const abortUpload = (id: string) => {\n const item = items.value.find((i) => i.id === id);\n if (item && item.state.status === \"uploading\") {\n const controller = abortControllers.value.get(id);\n if (controller) {\n controller.abort();\n abortControllers.value.delete(id);\n }\n\n activeUploads.value.delete(id);\n\n items.value = items.value.map((i) =>\n i.id === id\n ? { ...i, state: { ...i.state, status: \"aborted\" as const } }\n : i,\n );\n\n // Try to start next upload in queue\n startNextUpload();\n }\n };\n\n const retryUpload = (id: string) => {\n const item = items.value.find((i) => i.id === id);\n if (item && [\"error\", \"aborted\"].includes(item.state.status)) {\n items.value = items.value.map((i) =>\n i.id === id\n ? {\n ...i,\n state: { ...i.state, status: \"idle\" as const, error: null },\n }\n : i,\n );\n\n // Auto-start the upload\n setTimeout(() => startNextUpload(), 0);\n }\n };\n\n const startAll = () => {\n // Start as many uploads as we can up to the concurrent limit\n const idleItems = items.value.filter(\n (item) => item.state.status === \"idle\",\n );\n const slotsAvailable = maxConcurrent - activeUploads.value.size;\n const itemsToStart = idleItems.slice(0, slotsAvailable);\n\n for (const _item of itemsToStart) {\n startNextUpload();\n }\n };\n\n const abortAll = () => {\n items.value\n .filter((item) => item.state.status === \"uploading\")\n .forEach((item) => {\n const controller = abortControllers.value.get(item.id);\n if (controller) {\n controller.abort();\n abortControllers.value.delete(item.id);\n }\n });\n\n activeUploads.value.clear();\n\n // Update all uploading items to aborted status\n items.value = items.value.map((item) =>\n item.state.status === \"uploading\"\n ? { ...item, state: { ...item.state, status: \"aborted\" as const } }\n : item,\n );\n };\n\n const retryFailed = () => {\n const failedItems = items.value.filter((item) =>\n [\"error\", \"aborted\"].includes(item.state.status),\n );\n\n if (failedItems.length > 0) {\n items.value = items.value.map((item) =>\n failedItems.some((f) => f.id === item.id)\n ? {\n ...item,\n state: { ...item.state, status: \"idle\" as const, error: null },\n }\n : item,\n );\n\n // Auto-start uploads if we have capacity\n setTimeout(startAll, 0);\n }\n };\n\n const clearCompleted = () => {\n items.value = items.value.filter(\n (item) => ![\"success\", \"error\", \"aborted\"].includes(item.state.status),\n );\n };\n\n const clearAll = () => {\n abortAll();\n items.value = [];\n activeUploads.value.clear();\n };\n\n const getItemsByStatus = (status: UploadStatus) => {\n return items.value.filter((item) => item.state.status === status);\n };\n\n // Create aggregated metrics object that delegates to the upload client\n const metrics: UploadMetrics = {\n getInsights: () => uploadClient.client.getChunkingInsights(),\n exportMetrics: () => uploadClient.client.exportMetrics(),\n getNetworkMetrics: () => uploadClient.client.getNetworkMetrics(),\n getNetworkCondition: () => uploadClient.client.getNetworkCondition(),\n resetMetrics: () => uploadClient.client.resetMetrics(),\n };\n\n return {\n state: readonly(state),\n items: readonly(items),\n addFiles,\n removeItem,\n removeFile: removeItem, // Alias for consistency\n startAll,\n abortUpload,\n abortAll,\n retryUpload,\n retryFailed,\n clearCompleted,\n clearAll,\n getItemsByStatus,\n metrics,\n };\n}\n","import type {\n ChunkMetrics,\n PerformanceInsights,\n UploadSessionMetrics,\n} from \"@uploadista/client-browser\";\nimport type {\n UploadFunction,\n UploadMetrics,\n UploadOptions,\n} from \"@uploadista/client-core\";\nimport {\n UploadManager,\n type UploadState,\n type UploadStatus,\n} from \"@uploadista/client-core\";\nimport { computed, onUnmounted, ref } from \"vue\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\n// Re-export types from core for convenience\nexport type { UploadState, UploadStatus };\nexport type UploadInput = File | Blob;\nexport type { ChunkMetrics, PerformanceInsights, UploadSessionMetrics };\n\nconst initialState: UploadState = {\n status: \"idle\",\n progress: 0,\n bytesUploaded: 0,\n totalBytes: null,\n error: null,\n result: null,\n};\n\n/**\n * Vue composable for managing individual file uploads with full state management.\n * Provides upload progress tracking, error handling, abort functionality, and retry logic.\n *\n * Must be used within a component tree that has the Uploadista plugin installed.\n *\n * @param options - Upload configuration and event handlers\n * @returns Upload state and control methods\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useUpload } from '@uploadista/vue';\n *\n * const upload = useUpload({\n * onSuccess: (result) => console.log('Upload complete:', result),\n * onError: (error) => console.error('Upload failed:', error),\n * onProgress: (progress) => console.log('Progress:', progress + '%'),\n * });\n *\n * const handleFileChange = (event: Event) => {\n * const file = (event.target as HTMLInputElement).files?.[0];\n * if (file) upload.upload(file);\n * };\n * </script>\n *\n * <template>\n * <div>\n * <input type=\"file\" @change=\"handleFileChange\" />\n * <div v-if=\"upload.isUploading\">Progress: {{ upload.state.progress }}%</div>\n * <div v-if=\"upload.state.error\">Error: {{ upload.state.error.message }}</div>\n * <button v-if=\"upload.canRetry\" @click=\"upload.retry\">Retry</button>\n * <button @click=\"upload.abort\" :disabled=\"!upload.isUploading\">Abort</button>\n * </div>\n * </template>\n * ```\n */\nexport function useUpload(options: UploadOptions = {}) {\n const uploadistaClient = useUploadistaClient();\n const state = ref<UploadState>({ ...initialState });\n let manager: UploadManager | null = null;\n\n // Wrap the client's upload method to match UploadFunction signature\n const uploadFn: UploadFunction<UploadInput> = (\n input: UploadInput,\n opts: UploadOptions,\n ) => uploadistaClient.client.upload(input, opts);\n\n // Create UploadManager instance\n manager = new UploadManager(\n uploadFn,\n {\n onStateChange: (newState: UploadState) => {\n state.value = newState;\n },\n onProgress: options.onProgress,\n onChunkComplete: options.onChunkComplete,\n onSuccess: options.onSuccess,\n onError: options.onError,\n onAbort: options.onAbort,\n },\n options,\n );\n\n // Clean up manager when component unmounts\n onUnmounted(() => {\n manager?.cleanup();\n });\n\n // Upload function\n const upload = (file: UploadInput) => {\n manager?.upload(file);\n };\n\n // Abort function\n const abort = () => {\n manager?.abort();\n };\n\n // Reset function\n const reset = () => {\n manager?.reset();\n };\n\n // Retry function\n const retry = () => {\n manager?.retry();\n };\n\n // Computed properties\n const isUploading = computed(() => state.value.status === \"uploading\");\n const canRetry = computed(() => manager?.canRetry() ?? false);\n\n // Create metrics object that delegates to the upload client\n const metrics: UploadMetrics = {\n getInsights: () => uploadistaClient.client.getChunkingInsights(),\n exportMetrics: () => uploadistaClient.client.exportMetrics(),\n getNetworkMetrics: () => uploadistaClient.client.getNetworkMetrics(),\n getNetworkCondition: () => uploadistaClient.client.getNetworkCondition(),\n resetMetrics: () => uploadistaClient.client.resetMetrics(),\n };\n\n return {\n state,\n upload,\n abort,\n reset,\n retry,\n isUploading,\n canRetry,\n metrics,\n };\n}\n","import type {\n ChunkMetrics,\n PerformanceInsights,\n UploadSessionMetrics,\n} from \"@uploadista/client-browser\";\nimport { onUnmounted, readonly, ref } from \"vue\";\nimport { useUploadistaClient } from \"./useUploadistaClient\";\n\nexport interface UploadMetrics {\n /**\n * Total bytes uploaded across all files\n */\n totalBytesUploaded: number;\n\n /**\n * Total bytes to upload across all files\n */\n totalBytes: number;\n\n /**\n * Overall upload speed in bytes per second\n */\n averageSpeed: number;\n\n /**\n * Current upload speed in bytes per second\n */\n currentSpeed: number;\n\n /**\n * Estimated time remaining in milliseconds\n */\n estimatedTimeRemaining: number | null;\n\n /**\n * Total number of files being tracked\n */\n totalFiles: number;\n\n /**\n * Number of files completed\n */\n completedFiles: number;\n\n /**\n * Number of files currently uploading\n */\n activeUploads: number;\n\n /**\n * Overall progress as percentage (0-100)\n */\n progress: number;\n\n /**\n * Peak upload speed achieved\n */\n peakSpeed: number;\n\n /**\n * Start time of the first upload\n */\n startTime: number | null;\n\n /**\n * End time of the last completed upload\n */\n endTime: number | null;\n\n /**\n * Total duration of all uploads\n */\n totalDuration: number | null;\n\n /**\n * Detailed performance insights from the upload client\n */\n insights: PerformanceInsights;\n\n /**\n * Session metrics for completed uploads\n */\n sessionMetrics: Partial<UploadSessionMetrics>[];\n\n /**\n * Detailed chunk metrics from recent uploads\n */\n chunkMetrics: ChunkMetrics[];\n}\n\nexport interface FileUploadMetrics {\n id: string;\n filename: string;\n size: number;\n bytesUploaded: number;\n progress: number;\n speed: number;\n startTime: number;\n endTime: number | null;\n duration: number | null;\n isComplete: boolean;\n}\n\nexport interface UseUploadMetricsOptions {\n /**\n * Interval for calculating current speed (in milliseconds)\n */\n speedCalculationInterval?: number;\n\n /**\n * Number of speed samples to keep for average calculation\n */\n speedSampleSize?: number;\n\n /**\n * Called when metrics are updated\n */\n onMetricsUpdate?: (metrics: UploadMetrics) => void;\n\n /**\n * Called when a file upload starts\n */\n onFileStart?: (fileMetrics: FileUploadMetrics) => void;\n\n /**\n * Called when a file upload progresses\n */\n onFileProgress?: (fileMetrics: FileUploadMetrics) => void;\n\n /**\n * Called when a file upload completes\n */\n onFileComplete?: (fileMetrics: FileUploadMetrics) => void;\n}\n\nconst initialMetrics: UploadMetrics = {\n totalBytesUploaded: 0,\n totalBytes: 0,\n averageSpeed: 0,\n currentSpeed: 0,\n estimatedTimeRemaining: null,\n totalFiles: 0,\n completedFiles: 0,\n activeUploads: 0,\n progress: 0,\n peakSpeed: 0,\n startTime: null,\n endTime: null,\n totalDuration: null,\n insights: {\n overallEfficiency: 0,\n chunkingEffectiveness: 0,\n networkStability: 0,\n recommendations: [],\n optimalChunkSizeRange: { min: 256 * 1024, max: 2 * 1024 * 1024 },\n },\n sessionMetrics: [],\n chunkMetrics: [],\n};\n\n/**\n * Vue composable for tracking detailed upload metrics and performance statistics.\n * Provides comprehensive monitoring of upload progress, speed, and timing data.\n *\n * @param options - Configuration and event handlers\n * @returns Upload metrics state and control methods\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useUploadMetrics } from '@uploadista/vue';\n *\n * const uploadMetrics = useUploadMetrics({\n * speedCalculationInterval: 1000, // Update speed every second\n * speedSampleSize: 10, // Keep last 10 speed samples for average\n * onMetricsUpdate: (metrics) => {\n * console.log(`Overall progress: ${metrics.progress}%`);\n * console.log(`Speed: ${(metrics.currentSpeed / 1024).toFixed(1)} KB/s`);\n * console.log(`ETA: ${metrics.estimatedTimeRemaining}ms`);\n * },\n * onFileComplete: (fileMetrics) => {\n * console.log(`${fileMetrics.filename} completed in ${fileMetrics.duration}ms`);\n * },\n * });\n *\n * // Start tracking a file\n * const handleFileStart = (file: File) => {\n * uploadMetrics.startFileUpload(file.name, file.name, file.size);\n * };\n *\n * // Update progress during upload\n * const handleProgress = (fileId: string, bytesUploaded: number) => {\n * uploadMetrics.updateFileProgress(fileId, bytesUploaded);\n * };\n * </script>\n *\n * <template>\n * <div>\n * <div>Overall Progress: {{ uploadMetrics.metrics.progress }}%</div>\n * <div>Speed: {{ (uploadMetrics.metrics.currentSpeed / 1024).toFixed(1) }} KB/s</div>\n * <div>Files: {{ uploadMetrics.metrics.completedFiles }}/{{ uploadMetrics.metrics.totalFiles }}</div>\n *\n * <div v-if=\"uploadMetrics.metrics.estimatedTimeRemaining\">\n * ETA: {{ Math.round(uploadMetrics.metrics.estimatedTimeRemaining / 1000) }}s\n * </div>\n *\n * <div v-for=\"file in uploadMetrics.fileMetrics\" :key=\"file.id\">\n * {{ file.filename }}: {{ file.progress }}% ({{ (file.speed / 1024).toFixed(1) }} KB/s)\n * </div>\n * </div>\n * </template>\n * ```\n */\nexport function useUploadMetrics(options: UseUploadMetricsOptions = {}) {\n const {\n speedCalculationInterval = 1000,\n speedSampleSize = 10,\n onMetricsUpdate,\n onFileStart,\n onFileProgress,\n onFileComplete,\n } = options;\n\n const uploadClient = useUploadistaClient();\n\n const metrics = ref<UploadMetrics>({ ...initialMetrics });\n const fileMetrics = ref<FileUploadMetrics[]>([]);\n\n const speedSamples = ref<Array<{ time: number; bytes: number }>>([]);\n const lastUpdate = ref<number>(0);\n const interval = ref<ReturnType<typeof setInterval> | null>(null);\n\n const calculateSpeed = (currentTime: number, totalBytesUploaded: number) => {\n const sample = { time: currentTime, bytes: totalBytesUploaded };\n speedSamples.value.push(sample);\n\n // Keep only recent samples\n if (speedSamples.value.length > speedSampleSize) {\n speedSamples.value = speedSamples.value.slice(-speedSampleSize);\n }\n\n // Calculate current speed (bytes per second)\n let currentSpeed = 0;\n if (speedSamples.value.length >= 2) {\n const recent = speedSamples.value[speedSamples.value.length - 1];\n const previous = speedSamples.value[speedSamples.value.length - 2];\n if (recent && previous) {\n const timeDiff = (recent.time - previous.time) / 1000; // Convert to seconds\n const bytesDiff = recent.bytes - previous.bytes;\n currentSpeed = timeDiff > 0 ? bytesDiff / timeDiff : 0;\n }\n }\n\n // Calculate average speed\n let averageSpeed = 0;\n if (speedSamples.value.length >= 2) {\n const first = speedSamples.value[0];\n const last = speedSamples.value[speedSamples.value.length - 1];\n if (first && last) {\n const totalTime = (last.time - first.time) / 1000; // Convert to seconds\n const totalBytes = last.bytes - first.bytes;\n averageSpeed = totalTime > 0 ? totalBytes / totalTime : 0;\n }\n }\n\n return { currentSpeed, averageSpeed };\n };\n\n const updateMetrics = () => {\n const now = Date.now();\n\n // Calculate totals from file metrics\n const totalBytes = fileMetrics.value.reduce(\n (sum, file) => sum + file.size,\n 0,\n );\n const totalBytesUploaded = fileMetrics.value.reduce(\n (sum, file) => sum + file.bytesUploaded,\n 0,\n );\n const completedFiles = fileMetrics.value.filter(\n (file) => file.isComplete,\n ).length;\n const activeUploads = fileMetrics.value.filter(\n (file) => !file.isComplete && file.bytesUploaded > 0,\n ).length;\n\n // Calculate speeds\n const { currentSpeed, averageSpeed } = calculateSpeed(\n now,\n totalBytesUploaded,\n );\n\n // Calculate progress\n const progress =\n totalBytes > 0 ? Math.round((totalBytesUploaded / totalBytes) * 100) : 0;\n\n // Calculate estimated time remaining\n let estimatedTimeRemaining: number | null = null;\n if (currentSpeed > 0) {\n const remainingBytes = totalBytes - totalBytesUploaded;\n estimatedTimeRemaining = (remainingBytes / currentSpeed) * 1000; // Convert to milliseconds\n }\n\n // Find start and end times\n const activeTimes = fileMetrics.value.filter((file) => file.startTime > 0);\n const startTime =\n activeTimes.length > 0\n ? Math.min(...activeTimes.map((file) => file.startTime))\n : null;\n\n const completedTimes = fileMetrics.value.filter(\n (file) => file.endTime !== null,\n );\n const endTime =\n completedTimes.length > 0 && completedFiles === fileMetrics.value.length\n ? Math.max(\n ...(completedTimes\n .map((file) => file.endTime)\n .filter((time) => time !== null) as number[]),\n )\n : null;\n\n const totalDuration = startTime && endTime ? endTime - startTime : null;\n\n const newMetrics: UploadMetrics = {\n totalBytesUploaded,\n totalBytes,\n averageSpeed,\n currentSpeed,\n estimatedTimeRemaining,\n totalFiles: fileMetrics.value.length,\n completedFiles,\n activeUploads,\n progress,\n peakSpeed: Math.max(metrics.value.peakSpeed, currentSpeed),\n startTime,\n endTime,\n totalDuration,\n insights: uploadClient.client.getChunkingInsights(),\n sessionMetrics: [uploadClient.client.exportMetrics().session],\n chunkMetrics: uploadClient.client.exportMetrics().chunks,\n };\n\n metrics.value = newMetrics;\n onMetricsUpdate?.(newMetrics);\n };\n\n // Set up periodic speed calculations\n const setupSpeedCalculation = () => {\n if (interval.value) {\n clearInterval(interval.value);\n }\n\n interval.value = setInterval(() => {\n if (\n fileMetrics.value.some(\n (file) => !file.isComplete && file.bytesUploaded > 0,\n )\n ) {\n updateMetrics();\n }\n }, speedCalculationInterval);\n };\n\n const startFileUpload = (id: string, filename: string, size: number) => {\n const now = Date.now();\n\n const fileMetric: FileUploadMetrics = {\n id,\n filename,\n size,\n bytesUploaded: 0,\n progress: 0,\n speed: 0,\n startTime: now,\n endTime: null,\n duration: null,\n isComplete: false,\n };\n\n const existing = fileMetrics.value.find((file) => file.id === id);\n if (existing) {\n fileMetrics.value = fileMetrics.value.map((file) =>\n file.id === id ? fileMetric : file,\n );\n } else {\n fileMetrics.value = [...fileMetrics.value, fileMetric];\n }\n\n onFileStart?.(fileMetric);\n\n // Start speed calculation if this is the first active upload\n if (fileMetrics.value.filter((file) => !file.isComplete).length === 1) {\n setupSpeedCalculation();\n }\n };\n\n const updateFileProgress = (id: string, bytesUploaded: number) => {\n const now = Date.now();\n\n fileMetrics.value = fileMetrics.value.map((file) => {\n if (file.id !== id) return file;\n\n const timeDiff = (now - file.startTime) / 1000; // seconds\n const speed = timeDiff > 0 ? bytesUploaded / timeDiff : 0;\n const progress =\n file.size > 0 ? Math.round((bytesUploaded / file.size) * 100) : 0;\n\n const updatedFile = {\n ...file,\n bytesUploaded,\n progress,\n speed,\n };\n\n onFileProgress?.(updatedFile);\n return updatedFile;\n });\n\n // Trigger metrics update\n setTimeout(updateMetrics, 0);\n };\n\n const completeFileUpload = (id: string) => {\n const now = Date.now();\n\n fileMetrics.value = fileMetrics.value.map((file) => {\n if (file.id !== id) return file;\n\n const duration = now - file.startTime;\n const speed = duration > 0 ? (file.size / duration) * 1000 : 0; // bytes per second\n\n const completedFile = {\n ...file,\n bytesUploaded: file.size,\n progress: 100,\n speed,\n endTime: now,\n duration,\n isComplete: true,\n };\n\n onFileComplete?.(completedFile);\n return completedFile;\n });\n\n // Trigger metrics update\n setTimeout(updateMetrics, 0);\n };\n\n const removeFile = (id: string) => {\n fileMetrics.value = fileMetrics.value.filter((file) => file.id !== id);\n setTimeout(updateMetrics, 0);\n };\n\n const reset = () => {\n if (interval.value) {\n clearInterval(interval.value);\n interval.value = null;\n }\n\n metrics.value = { ...initialMetrics };\n fileMetrics.value = [];\n speedSamples.value = [];\n lastUpdate.value = 0;\n };\n\n const getFileMetrics = (id: string) => {\n return fileMetrics.value.find((file) => file.id === id);\n };\n\n const exportMetrics = () => {\n return {\n overall: metrics.value,\n files: fileMetrics.value,\n exportTime: Date.now(),\n };\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n if (interval.value) {\n clearInterval(interval.value);\n }\n });\n\n return {\n metrics: readonly(metrics),\n fileMetrics: readonly(fileMetrics),\n startFileUpload,\n updateFileProgress,\n completeFileUpload,\n removeFile,\n reset,\n getFileMetrics,\n exportMetrics,\n };\n}\n"],"mappings":"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"}
@@ -1,12 +1,8 @@
1
- import * as vue from "vue";
2
1
  import { App, InjectionKey, Ref } from "vue";
3
- import * as _uploadista_client_browser0 from "@uploadista/client-browser";
4
2
  import { BrowserUploadInput, ChunkMetrics, ChunkMetrics as ChunkMetrics$1, FlowUploadOptions, MultiFlowUploadOptions, PerformanceInsights, PerformanceInsights as PerformanceInsights$1, UploadOptions, UploadSessionMetrics, UploadSessionMetrics as UploadSessionMetrics$1, UploadistaClientOptions, UploadistaEvent, createUploadistaClient } from "@uploadista/client-browser";
5
3
  import { FlowEvent, FlowEventFlowCancel, FlowEventFlowEnd, FlowEventFlowError, FlowEventFlowPause, FlowEventFlowStart, FlowEventJobEnd, FlowEventJobStart, FlowEventNodeEnd, FlowEventNodeError, FlowEventNodePause, FlowEventNodeResume, FlowEventNodeStart } from "@uploadista/core/flow";
6
4
  import { UploadEvent, UploadFile } from "@uploadista/core/types";
7
- import * as _uploadista_client_core0 from "@uploadista/client-core";
8
5
  import { FlowUploadState, FlowUploadStatus as FlowUploadStatus$1, InputExecutionState, UploadMetrics, UploadOptions as UploadOptions$1, UploadState, UploadStatus } from "@uploadista/client-core";
9
- import * as _uploadista_core0 from "@uploadista/core";
10
6
 
11
7
  //#region src/composables/useFlow.d.ts
12
8
  /**
@@ -341,7 +337,7 @@ interface DragDropState {
341
337
  * ```
342
338
  */
343
339
  declare function useDragDrop(options?: DragDropOptions): {
344
- state: Readonly<vue.Ref<{
340
+ state: Readonly<import("vue").Ref<{
345
341
  readonly isDragging: boolean;
346
342
  readonly isOver: boolean;
347
343
  readonly isValid: boolean;
@@ -357,7 +353,7 @@ declare function useDragDrop(options?: DragDropOptions): {
357
353
  onDragLeave: (event: DragEvent) => void;
358
354
  onDrop: (event: DragEvent) => void;
359
355
  onInputChange: (event: Event) => void;
360
- inputProps: vue.ComputedRef<{
356
+ inputProps: import("vue").ComputedRef<{
361
357
  type: "file";
362
358
  multiple: boolean;
363
359
  accept: string | undefined;
@@ -709,7 +705,7 @@ declare function createUploadistaPlugin(options: UploadistaPluginOptions): {
709
705
  * ```
710
706
  */
711
707
  declare function useMultiFlowUpload(options: MultiFlowUploadOptions<BrowserUploadInput>): {
712
- state: Readonly<vue.Ref<{
708
+ state: Readonly<import("vue").Ref<{
713
709
  readonly items: readonly {
714
710
  readonly id: string;
715
711
  readonly file: {
@@ -855,7 +851,7 @@ declare function useMultiFlowUpload(options: MultiFlowUploadOptions<BrowserUploa
855
851
  abortAll: () => void;
856
852
  clear: () => void;
857
853
  retryUpload: (id: string) => void;
858
- isUploading: vue.ComputedRef<boolean>;
854
+ isUploading: import("vue").ComputedRef<boolean>;
859
855
  };
860
856
  //#endregion
861
857
  //#region src/composables/useUpload.d.ts
@@ -898,7 +894,7 @@ type UploadInput = File | Blob;
898
894
  * ```
899
895
  */
900
896
  declare function useUpload(options?: UploadOptions$1): {
901
- state: vue.Ref<{
897
+ state: import("vue").Ref<{
902
898
  status: UploadStatus;
903
899
  progress: number;
904
900
  bytesUploaded: number;
@@ -925,7 +921,7 @@ declare function useUpload(options?: UploadOptions$1): {
925
921
  jobId: string;
926
922
  } | undefined;
927
923
  size?: number | undefined | undefined;
928
- metadata?: Record<string, _uploadista_core0.JsonValue> | undefined;
924
+ metadata?: Record<string, import("@uploadista/core").JsonValue> | undefined;
929
925
  creationDate?: string | undefined | undefined;
930
926
  url?: string | undefined | undefined;
931
927
  sizeIsDeferred?: boolean | undefined | undefined;
@@ -964,7 +960,7 @@ declare function useUpload(options?: UploadOptions$1): {
964
960
  jobId: string;
965
961
  } | undefined;
966
962
  size?: number | undefined | undefined;
967
- metadata?: Record<string, _uploadista_core0.JsonValue> | undefined;
963
+ metadata?: Record<string, import("@uploadista/core").JsonValue> | undefined;
968
964
  creationDate?: string | undefined | undefined;
969
965
  url?: string | undefined | undefined;
970
966
  sizeIsDeferred?: boolean | undefined | undefined;
@@ -981,8 +977,8 @@ declare function useUpload(options?: UploadOptions$1): {
981
977
  abort: () => void;
982
978
  reset: () => void;
983
979
  retry: () => void;
984
- isUploading: vue.ComputedRef<boolean>;
985
- canRetry: vue.ComputedRef<boolean>;
980
+ isUploading: import("vue").ComputedRef<boolean>;
981
+ canRetry: import("vue").ComputedRef<boolean>;
986
982
  metrics: UploadMetrics;
987
983
  };
988
984
  //#endregion
@@ -1125,7 +1121,7 @@ interface MultiUploadState {
1125
1121
  * ```
1126
1122
  */
1127
1123
  declare function useMultiUpload(options?: MultiUploadOptions): {
1128
- state: Readonly<vue.Ref<{
1124
+ state: Readonly<import("vue").Ref<{
1129
1125
  readonly total: number;
1130
1126
  readonly completed: number;
1131
1127
  readonly successful: number;
@@ -1148,7 +1144,7 @@ declare function useMultiUpload(options?: MultiUploadOptions): {
1148
1144
  readonly isUploading: boolean;
1149
1145
  readonly isComplete: boolean;
1150
1146
  }>>;
1151
- items: Readonly<vue.Ref<readonly {
1147
+ items: Readonly<import("vue").Ref<readonly {
1152
1148
  readonly id: string;
1153
1149
  readonly file: {
1154
1150
  readonly lastModified: number;
@@ -1336,7 +1332,7 @@ declare function useMultiUpload(options?: MultiUploadOptions): {
1336
1332
  jobId: string;
1337
1333
  } | undefined;
1338
1334
  size?: number | undefined | undefined;
1339
- metadata?: Record<string, _uploadista_core0.JsonValue> | undefined;
1335
+ metadata?: Record<string, import("@uploadista/core").JsonValue> | undefined;
1340
1336
  creationDate?: string | undefined | undefined;
1341
1337
  url?: string | undefined | undefined;
1342
1338
  sizeIsDeferred?: boolean | undefined | undefined;
@@ -1382,7 +1378,7 @@ declare function useMultiUpload(options?: MultiUploadOptions): {
1382
1378
  */
1383
1379
  declare function useUploadistaClient(): {
1384
1380
  client: {
1385
- upload: (file: _uploadista_client_browser0.BrowserUploadInput, {
1381
+ upload: (file: import("@uploadista/client-browser").BrowserUploadInput, {
1386
1382
  uploadLengthDeferred,
1387
1383
  uploadSize,
1388
1384
  onProgress,
@@ -1390,10 +1386,10 @@ declare function useUploadistaClient(): {
1390
1386
  onSuccess,
1391
1387
  onShouldRetry,
1392
1388
  onError
1393
- }?: _uploadista_client_core0.UploadistaUploadOptions) => Promise<{
1389
+ }?: import("@uploadista/client-core").UploadistaUploadOptions) => Promise<{
1394
1390
  abort: () => void;
1395
1391
  }>;
1396
- uploadWithFlow: (file: _uploadista_client_browser0.BrowserUploadInput, flowConfig: _uploadista_client_core0.FlowUploadConfig, {
1392
+ uploadWithFlow: (file: import("@uploadista/client-browser").BrowserUploadInput, flowConfig: import("@uploadista/client-core").FlowUploadConfig, {
1397
1393
  onProgress,
1398
1394
  onChunkComplete,
1399
1395
  onSuccess,
@@ -1401,7 +1397,7 @@ declare function useUploadistaClient(): {
1401
1397
  onJobStart,
1402
1398
  onError,
1403
1399
  onAbort
1404
- }?: Omit<_uploadista_client_core0.UploadistaUploadOptions, "uploadLengthDeferred" | "uploadSize" | "metadata"> & {
1400
+ }?: Omit<import("@uploadista/client-core").UploadistaUploadOptions, "uploadLengthDeferred" | "uploadSize" | "metadata"> & {
1405
1401
  onAbort?: () => void;
1406
1402
  }) => Promise<{
1407
1403
  abort: () => Promise<void>;
@@ -1409,7 +1405,7 @@ declare function useUploadistaClient(): {
1409
1405
  resume: () => Promise<void>;
1410
1406
  jobId: string;
1411
1407
  }>;
1412
- multiInputFlowUpload: (inputs: Record<string, unknown>, flowConfig: _uploadista_client_core0.FlowUploadConfig, {
1408
+ multiInputFlowUpload: (inputs: Record<string, unknown>, flowConfig: import("@uploadista/client-core").FlowUploadConfig, {
1413
1409
  onProgress,
1414
1410
  onChunkComplete,
1415
1411
  onShouldRetry,
@@ -1418,7 +1414,7 @@ declare function useUploadistaClient(): {
1418
1414
  onInputProgress,
1419
1415
  onInputComplete,
1420
1416
  onInputError
1421
- }?: Omit<_uploadista_client_core0.UploadistaUploadOptions, "uploadLengthDeferred" | "uploadSize" | "metadata"> & {
1417
+ }?: Omit<import("@uploadista/client-core").UploadistaUploadOptions, "uploadLengthDeferred" | "uploadSize" | "metadata"> & {
1422
1418
  onInputProgress?: (nodeId: string, progress: number, bytesUploaded: number, totalBytes: number | null) => void;
1423
1419
  onInputComplete?: (nodeId: string) => void;
1424
1420
  onInputError?: (nodeId: string, error: Error) => void;
@@ -1441,17 +1437,17 @@ declare function useUploadistaClient(): {
1441
1437
  }: {
1442
1438
  uploadId: string;
1443
1439
  uploadIdStorageKey: string | undefined;
1444
- retryTimeout: _uploadista_client_core0.Timeout | null;
1440
+ retryTimeout: import("@uploadista/client-core").Timeout | null;
1445
1441
  shouldTerminate: boolean;
1446
- abortController: _uploadista_client_core0.AbortControllerLike;
1447
- uploadistaApi: _uploadista_client_core0.UploadistaApi;
1448
- platformService: _uploadista_client_core0.PlatformService;
1442
+ abortController: import("@uploadista/client-core").AbortControllerLike;
1443
+ uploadistaApi: import("@uploadista/client-core").UploadistaApi;
1444
+ platformService: import("@uploadista/client-core").PlatformService;
1449
1445
  retryDelays?: number[];
1450
- clientStorage: _uploadista_client_core0.ClientStorage;
1446
+ clientStorage: import("@uploadista/client-core").ClientStorage;
1451
1447
  }) => Promise<void>>[0]) => Promise<void>;
1452
1448
  getFlow: (flowId: string) => Promise<{
1453
1449
  status: number;
1454
- flow: _uploadista_core0.FlowData;
1450
+ flow: import("@uploadista/core").FlowData;
1455
1451
  }>;
1456
1452
  runFlow: ({
1457
1453
  flowId,
@@ -1463,7 +1459,7 @@ declare function useUploadistaClient(): {
1463
1459
  storageId?: string;
1464
1460
  }) => Promise<{
1465
1461
  status: number;
1466
- job: _uploadista_core0.FlowJob;
1462
+ job: import("@uploadista/core").FlowJob;
1467
1463
  }>;
1468
1464
  resumeFlow: ({
1469
1465
  jobId,
@@ -1475,13 +1471,13 @@ declare function useUploadistaClient(): {
1475
1471
  nodeId: string;
1476
1472
  newData: unknown;
1477
1473
  contentType?: "application/json" | "application/octet-stream";
1478
- }) => Promise<_uploadista_core0.FlowJob>;
1479
- pauseFlow: (jobId: string) => Promise<_uploadista_core0.FlowJob>;
1480
- cancelFlow: (jobId: string) => Promise<_uploadista_core0.FlowJob>;
1474
+ }) => Promise<import("@uploadista/core").FlowJob>;
1475
+ pauseFlow: (jobId: string) => Promise<import("@uploadista/core").FlowJob>;
1476
+ cancelFlow: (jobId: string) => Promise<import("@uploadista/core").FlowJob>;
1481
1477
  findInputNode: (flowId: string) => Promise<{
1482
1478
  inputNodes: {
1483
1479
  id: string;
1484
- type: _uploadista_core0.NodeType;
1480
+ type: import("@uploadista/core").NodeType;
1485
1481
  name: string;
1486
1482
  }[];
1487
1483
  single: boolean;
@@ -1491,12 +1487,12 @@ declare function useUploadistaClient(): {
1491
1487
  onJobStart?: (jobId: string) => void;
1492
1488
  }) => Promise<{
1493
1489
  status: number;
1494
- job: _uploadista_core0.FlowJob;
1490
+ job: import("@uploadista/core").FlowJob;
1495
1491
  }>;
1496
- getJobStatus: (jobId: string) => Promise<_uploadista_core0.FlowJob>;
1497
- openUploadWebSocket: (uploadId: string) => Promise<_uploadista_client_core0.WebSocketLike>;
1498
- openFlowWebSocket: (jobId: string) => Promise<_uploadista_client_core0.WebSocketLike>;
1499
- openWebSocket: (id: string) => Promise<_uploadista_client_core0.WebSocketLike>;
1492
+ getJobStatus: (jobId: string) => Promise<import("@uploadista/core").FlowJob>;
1493
+ openUploadWebSocket: (uploadId: string) => Promise<import("@uploadista/client-core").WebSocketLike>;
1494
+ openFlowWebSocket: (jobId: string) => Promise<import("@uploadista/client-core").WebSocketLike>;
1495
+ openWebSocket: (id: string) => Promise<import("@uploadista/client-core").WebSocketLike>;
1500
1496
  closeWebSocket: (id: string) => void;
1501
1497
  closeAllWebSockets: () => void;
1502
1498
  sendPing: (jobId: string) => boolean;
@@ -1507,16 +1503,16 @@ declare function useUploadistaClient(): {
1507
1503
  flow: number;
1508
1504
  total: number;
1509
1505
  };
1510
- getNetworkMetrics: () => _uploadista_client_core0.NetworkMetrics;
1511
- getNetworkCondition: () => _uploadista_client_core0.NetworkCondition;
1512
- getChunkingInsights: () => _uploadista_client_core0.PerformanceInsights;
1506
+ getNetworkMetrics: () => import("@uploadista/client-core").NetworkMetrics;
1507
+ getNetworkCondition: () => import("@uploadista/client-core").NetworkCondition;
1508
+ getChunkingInsights: () => import("@uploadista/client-core").PerformanceInsights;
1513
1509
  exportMetrics: () => {
1514
- session: Partial<_uploadista_client_core0.UploadSessionMetrics>;
1515
- chunks: _uploadista_client_core0.ChunkMetrics[];
1516
- insights: _uploadista_client_core0.PerformanceInsights;
1510
+ session: Partial<import("@uploadista/client-core").UploadSessionMetrics>;
1511
+ chunks: import("@uploadista/client-core").ChunkMetrics[];
1512
+ insights: import("@uploadista/client-core").PerformanceInsights;
1517
1513
  };
1518
- getConnectionMetrics: () => _uploadista_client_core0.ConnectionMetrics;
1519
- getDetailedConnectionMetrics: () => _uploadista_client_core0.DetailedConnectionMetrics;
1514
+ getConnectionMetrics: () => import("@uploadista/client-core").ConnectionMetrics;
1515
+ getDetailedConnectionMetrics: () => import("@uploadista/client-core").DetailedConnectionMetrics;
1520
1516
  warmupConnections: (urls: string[]) => Promise<void>;
1521
1517
  getConnectionPoolingInsights: () => Promise<{
1522
1518
  isOptimized: boolean;
@@ -1525,18 +1521,18 @@ declare function useUploadistaClient(): {
1525
1521
  connectionOverhead: number;
1526
1522
  }>;
1527
1523
  resetMetrics: () => Promise<void>;
1528
- validateConfiguration: (options: _uploadista_client_core0.UploadistaClientOptions<_uploadista_client_browser0.BrowserUploadInput>) => {
1524
+ validateConfiguration: (options: import("@uploadista/client-core").UploadistaClientOptions<import("@uploadista/client-browser").BrowserUploadInput>) => {
1529
1525
  valid: boolean;
1530
1526
  errors: string[];
1531
1527
  warnings: string[];
1532
1528
  };
1533
- validateConfigurationAsync: (options: _uploadista_client_core0.UploadistaClientOptions<_uploadista_client_browser0.BrowserUploadInput>) => Promise<{
1529
+ validateConfigurationAsync: (options: import("@uploadista/client-core").UploadistaClientOptions<import("@uploadista/client-browser").BrowserUploadInput>) => Promise<{
1534
1530
  valid: boolean;
1535
1531
  errors: string[];
1536
1532
  warnings: string[];
1537
- capabilities: _uploadista_core0.DataStoreCapabilities;
1533
+ capabilities: import("@uploadista/core").DataStoreCapabilities;
1538
1534
  }>;
1539
- getCapabilities: () => Promise<_uploadista_core0.DataStoreCapabilities>;
1535
+ getCapabilities: () => Promise<import("@uploadista/core").DataStoreCapabilities>;
1540
1536
  };
1541
1537
  subscribeToEvents: (handler: (event: UploadistaEvent) => void) => () => void;
1542
1538
  };
@@ -1701,7 +1697,7 @@ interface UseUploadMetricsOptions {
1701
1697
  * ```
1702
1698
  */
1703
1699
  declare function useUploadMetrics(options?: UseUploadMetricsOptions): {
1704
- metrics: Readonly<vue.Ref<{
1700
+ metrics: Readonly<import("vue").Ref<{
1705
1701
  readonly totalBytesUploaded: number;
1706
1702
  readonly totalBytes: number;
1707
1703
  readonly averageSpeed: number;
@@ -1802,7 +1798,7 @@ declare function useUploadMetrics(options?: UseUploadMetricsOptions): {
1802
1798
  readonly chunkingStrategy?: string | undefined;
1803
1799
  }[];
1804
1800
  }>>;
1805
- fileMetrics: Readonly<vue.Ref<readonly {
1801
+ fileMetrics: Readonly<import("vue").Ref<readonly {
1806
1802
  readonly id: string;
1807
1803
  readonly filename: string;
1808
1804
  readonly size: number;
@@ -1911,4 +1907,4 @@ declare function useUploadMetrics(options?: UseUploadMetricsOptions): {
1911
1907
  };
1912
1908
  //#endregion
1913
1909
  export { UseFlowEventsOptions as A, InputExecutionState as B, UploadFileEventData as C, UploadValidationWarningEventData as D, UploadValidationSuccessEventData as E, DragDropState as F, useFlow as H, useDragDrop as I, FlowInputMetadata as L, isFlowEvent as M, isUploadEvent as N, UseUploadEventsOptions as O, DragDropOptions as P, FlowUploadState as R, UploadFailedEventData as S, UploadValidationFailedEventData as T, UseFlowReturn as V, useMultiFlowUpload as _, useUploadistaClient as a, createUploadistaPlugin as b, UploadItem as c, PerformanceInsights$1 as d, UploadInput as f, useUpload as g, UploadStatus as h, UseUploadistaClientReturn as i, useFlowEvents as j, useUploadEvents as k, useMultiUpload as l, UploadState as m, UseUploadMetricsOptions as n, MultiUploadOptions as o, UploadSessionMetrics$1 as p, useUploadMetrics as r, MultiUploadState as s, FileUploadMetrics as t, ChunkMetrics$1 as u, UPLOADISTA_CLIENT_KEY as v, UploadProgressEventData as w, useUploadistaEvents as x, UploadistaPluginOptions as y, FlowUploadStatus$1 as z };
1914
- //# sourceMappingURL=useUploadMetrics-DEdjOjLp.d.mts.map
1910
+ //# sourceMappingURL=index-BlM5dmy_.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BlM5dmy_.d.mts","names":[],"sources":["../src/composables/useFlow.ts","../src/composables/useDragDrop.ts","../src/composables/eventUtils.ts","../src/composables/useFlowEvents.ts","../src/composables/useUploadEvents.ts","../src/composables/useUploadistaEvents.ts","../src/composables/plugin.ts","../src/composables/useMultiFlowUpload.ts","../src/composables/useUpload.ts","../src/composables/useMultiUpload.ts","../src/composables/useUploadistaClient.ts","../src/composables/useUploadMetrics.ts"],"mappings":"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"}