@better-s3/react 3.1045.2 → 3.1047.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/api.d.ts +30 -0
  2. package/dist/helpers/build-object-key.d.ts +20 -0
  3. package/dist/helpers/format-eta.d.ts +12 -0
  4. package/dist/helpers/format-file-size.d.ts +11 -0
  5. package/dist/helpers/format-speed.d.ts +8 -0
  6. package/dist/helpers/format-upload-progress.d.ts +17 -0
  7. package/dist/helpers/get-file-extension.d.ts +13 -0
  8. package/dist/helpers/index.d.ts +10 -0
  9. package/dist/helpers/parse-content-disposition.d.ts +18 -0
  10. package/dist/helpers/speed-tracker.d.ts +17 -0
  11. package/dist/helpers/truncate-filename.d.ts +9 -0
  12. package/dist/helpers/validate-file.d.ts +22 -0
  13. package/dist/hooks/index.d.ts +7 -0
  14. package/dist/{use-delete.d.ts → hooks/use-delete.d.ts} +4 -3
  15. package/dist/{use-download.d.ts → hooks/use-download.d.ts} +5 -10
  16. package/dist/hooks/use-fetch-download.d.ts +23 -0
  17. package/dist/hooks/use-multi-upload-controls.d.ts +33 -0
  18. package/dist/{use-multi-upload.d.ts → hooks/use-multi-upload.d.ts} +4 -3
  19. package/dist/hooks/use-upload-controls.d.ts +44 -0
  20. package/dist/hooks/use-upload.d.ts +75 -0
  21. package/dist/index.d.ts +13 -8
  22. package/dist/index.js +581 -186
  23. package/dist/index.js.map +1 -1
  24. package/dist/internal-helpers.d.ts +9 -0
  25. package/dist/s3-provider.d.ts +47 -0
  26. package/dist/store/index.d.ts +3 -0
  27. package/dist/store/local-storage-store.d.ts +9 -0
  28. package/dist/store/memory-store.d.ts +14 -0
  29. package/dist/types/download.d.ts +19 -2
  30. package/dist/types/error.d.ts +14 -0
  31. package/dist/types/index.d.ts +3 -0
  32. package/dist/types/s3-api.d.ts +158 -0
  33. package/dist/types/upload-store.d.ts +54 -0
  34. package/dist/types/upload.d.ts +56 -0
  35. package/dist/upload/constants.d.ts +1 -1
  36. package/dist/upload/multipart.d.ts +4 -3
  37. package/dist/upload/retry.d.ts +2 -1
  38. package/dist/upload/upload-file.d.ts +5 -1
  39. package/dist/upload/upload-files.d.ts +1 -1
  40. package/package.json +3 -6
  41. package/dist/helpers.d.ts +0 -7
  42. package/dist/use-fetch-download.d.ts +0 -33
  43. package/dist/use-upload-controls.d.ts +0 -63
  44. package/dist/use-upload.d.ts +0 -19
package/dist/api.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Client-side factory for the better-s3 presign API.
3
+ *
4
+ * Accepts an `S3Api` object — implement each method to call your own backend
5
+ * endpoint, tRPC mutation, GraphQL query, or anything else. The object is
6
+ * returned as-is; `createS3Client` just enforces the type contract.
7
+ *
8
+ * If you are using `@better-s3/server`, use `createS3Api` from that package
9
+ * instead — it builds a standard fetch client from a base path.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { createS3Client } from "@better-s3/react";
14
+ *
15
+ * export const s3Client = createS3Client({
16
+ * async upload(payload) {
17
+ * return fetch("/api/storage/presign", { method: "POST", body: JSON.stringify(payload) })
18
+ * .then(r => r.json());
19
+ * },
20
+ * async confirm(payload) { ... },
21
+ * async download(key, options) { ... },
22
+ * async delete(key) { ... },
23
+ * multipart: { init, signPart, listParts, complete, abort },
24
+ * });
25
+ * ```
26
+ */
27
+ import type { S3Api } from "./types/s3-api";
28
+ export declare function createS3Client(input: S3Api): S3Api;
29
+ /** @deprecated Use {@link createS3Client} instead. */
30
+ export declare const createS3Api: typeof createS3Client;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Builds an S3 object key by joining path segments with `/`.
3
+ *
4
+ * Trims leading/trailing slashes from each segment and removes empty ones,
5
+ * so you can safely pass optional parts without worrying about double-slashes.
6
+ *
7
+ * Follows the recommended better-s3 key convention:
8
+ * - Personal mode: `buildObjectKey(userId, `${nanoid()}.${ext}`)` → `"user_123/abc.png"`
9
+ * - Org mode: `buildObjectKey(orgId, userId, `${nanoid()}.${ext}`)` → `"org_1/user_123/abc.png"`
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * buildObjectKey("user_123", "uploads", "photo.png")
14
+ * // → "user_123/uploads/photo.png"
15
+ *
16
+ * buildObjectKey("org_1", "", "user_123", "doc.pdf")
17
+ * // → "org_1/user_123/doc.pdf"
18
+ * ```
19
+ */
20
+ export declare function buildObjectKey(...parts: string[]): string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Formats an estimated remaining time given the remaining bytes and current speed.
3
+ *
4
+ * Returns `null` when speed is 0 or nothing remains (not yet calculable).
5
+ *
6
+ * @example
7
+ * formatEta(4_400_000, 450_000) // → "9s"
8
+ * formatEta(4_400_000, 75_000) // → "58s"
9
+ * formatEta(90_000_000, 1_500_000) // → "1m"
10
+ * formatEta(5_400_000_000, 500_000) // → "3h"
11
+ */
12
+ export declare function formatEta(remainingBytes: number, bytesPerSecond: number): string | null;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Formats a byte count into a human-readable string.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * formatFileSize(0) // "0 B"
7
+ * formatFileSize(1500) // "1.5 KB"
8
+ * formatFileSize(1048576) // "1.0 MB"
9
+ * ```
10
+ */
11
+ export declare function formatFileSize(bytes: number): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formats a transfer speed (bytes/second) as a human-readable string.
3
+ *
4
+ * @example
5
+ * formatSpeed(1_200_000) // → "1.2 MB/s"
6
+ * formatSpeed(512) // → "512 B/s"
7
+ */
8
+ export declare function formatSpeed(bytesPerSecond: number): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Formats upload progress as a human-readable transfer string.
3
+ *
4
+ * @param loaded Bytes transferred so far.
5
+ * @param total Total bytes to transfer (0 means unknown).
6
+ * @param percent Transfer percentage (0–100).
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * formatUploadProgress(1_200_000, 5_600_000, 21)
11
+ * // → "1.2 MB / 5.6 MB (21%)"
12
+ *
13
+ * formatUploadProgress(1_200_000, 0, 0)
14
+ * // → "1.2 MB"
15
+ * ```
16
+ */
17
+ export declare function formatUploadProgress(loaded: number, total: number, percent: number): string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Extracts the lowercase file extension (without the dot) from a filename.
3
+ *
4
+ * Returns an empty string when the filename has no extension.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * getFileExtension("photo.JPG") // "jpg"
9
+ * getFileExtension("archive.tar.gz") // "gz"
10
+ * getFileExtension("README") // ""
11
+ * ```
12
+ */
13
+ export declare function getFileExtension(filename: string): string;
@@ -0,0 +1,10 @@
1
+ export { formatFileSize } from "./format-file-size";
2
+ export { validateFile } from "./validate-file";
3
+ export { parseContentDispositionFilename } from "./parse-content-disposition";
4
+ export { formatUploadProgress } from "./format-upload-progress";
5
+ export { formatSpeed } from "./format-speed";
6
+ export { formatEta } from "./format-eta";
7
+ export { buildObjectKey } from "./build-object-key";
8
+ export { getFileExtension } from "./get-file-extension";
9
+ export { truncateFilename } from "./truncate-filename";
10
+ export { createSpeedTracker, type SpeedTracker } from "./speed-tracker";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Extracts a display filename from a `Content-Disposition` response header.
3
+ *
4
+ * Prefers the RFC 5987 `filename*=UTF-8''…` encoding (full Unicode support)
5
+ * over the plain ASCII `filename="…"` fallback.
6
+ *
7
+ * @param header The raw `Content-Disposition` header value (or `null`).
8
+ * @param fallback Returned when no filename can be extracted.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const name = parseContentDispositionFilename(
13
+ * response.headers.get("content-disposition"),
14
+ * "download",
15
+ * );
16
+ * ```
17
+ */
18
+ export declare function parseContentDispositionFilename(header: string | null, fallback: string): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Creates a sliding-window transfer speed calculator.
3
+ *
4
+ * Tracks bytes transferred over a rolling time window to produce a smooth,
5
+ * instantaneous speed reading in bytes/second.
6
+ *
7
+ * @param windowMs Rolling window duration in milliseconds. @default 3000
8
+ */
9
+ export declare function createSpeedTracker(windowMs?: number): {
10
+ /**
11
+ * Record the latest cumulative `loaded` byte count.
12
+ * Returns the current speed in bytes/second (0 until at least 2 samples exist).
13
+ */
14
+ update(loaded: number): number;
15
+ reset(): void;
16
+ };
17
+ export type SpeedTracker = ReturnType<typeof createSpeedTracker>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Truncates a filename while always preserving the file extension.
3
+ * The cut happens before the extension so the extension is always visible.
4
+ *
5
+ * truncateFilename("namenamenamenamename.pdf", 20) → "namenamename… .pdf"
6
+ * truncateFilename("short.pdf", 20) → "short.pdf"
7
+ * truncateFilename(".gitignore", 8) → ".gitigno…"
8
+ */
9
+ export declare function truncateFilename(name: string, maxChars?: number): string;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Validates a `File` against accept-list and size constraints.
3
+ *
4
+ * Returns a human-readable error string when validation fails,
5
+ * or `null` when the file is valid.
6
+ *
7
+ * Mirrors the server-side `validateFile` so you can apply the same
8
+ * rules on the client before initiating an upload.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const error = validateFile(file, {
13
+ * accept: ["image/*", ".pdf"],
14
+ * maxFileSize: 10 * 1024 * 1024, // 10 MB
15
+ * });
16
+ * if (error) toast.error(error);
17
+ * ```
18
+ */
19
+ export declare function validateFile(file: File, options: {
20
+ accept?: string[];
21
+ maxFileSize?: number;
22
+ }): string | null;
@@ -0,0 +1,7 @@
1
+ export { useUpload, type UseUploadOptions, type UseUploadState, type UseUploadReturn, } from "./use-upload";
2
+ export { useMultiUpload, type UseMultiUploadOptions, type UseMultiUploadState, type UseMultiUploadReturn, } from "./use-multi-upload";
3
+ export { useUploadControls, type UseUploadControlsOptions, type UseUploadControlsReturn, } from "./use-upload-controls";
4
+ export { useMultiUploadControls, type UseMultiUploadControlsOptions, type UseMultiUploadControlsReturn, } from "./use-multi-upload-controls";
5
+ export { useDownload, type DownloadPhase, type DownloadHooks, type UseDownloadOptions, type UseDownloadState, type UseDownloadReturn, } from "./use-download";
6
+ export { useFetchDownload, type FetchDownloadPhase, type FetchDownloadProgress, type FetchDownloadHooks, type UseFetchDownloadOptions, type UseFetchDownloadState, type UseFetchDownloadReturn, } from "./use-fetch-download";
7
+ export { useDelete, type UseDeleteOptions, type UseDeleteState, type UseDeleteReturn, } from "./use-delete";
@@ -1,7 +1,8 @@
1
- import type { S3Api } from "@better-s3/server";
2
- import type { DeletePhase, DeleteHooks } from "./types";
1
+ import type { S3Api } from "../types/s3-api";
2
+ import type { DeletePhase, DeleteHooks } from "../types";
3
3
  export type UseDeleteOptions = DeleteHooks & {
4
- api: S3Api;
4
+ /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */
5
+ api?: S3Api;
5
6
  /** Target bucket (overrides server default) */
6
7
  bucket?: string;
7
8
  };
@@ -1,14 +1,9 @@
1
- import type { S3Api } from "@better-s3/server";
2
- /** "presigning" = fetching the presigned URL from the server; download itself is native */
3
- export type DownloadPhase = "idle" | "presigning" | "error";
4
- export type DownloadHooks = {
5
- beforeDownload?: (key: string) => Promise<boolean> | boolean;
6
- /** Fires as soon as the browser has been handed the URL — not when download completes. */
7
- onInitiated?: (key: string) => void;
8
- onError?: (key: string, error: unknown) => void;
9
- };
1
+ import type { S3Api } from "../types/s3-api";
2
+ export type { DownloadPhase, DownloadHooks } from "../types/download";
3
+ import type { DownloadPhase, DownloadHooks } from "../types/download";
10
4
  export type UseDownloadOptions = DownloadHooks & {
11
- api: S3Api;
5
+ /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */
6
+ api?: S3Api;
12
7
  /** Target bucket (overrides server default) */
13
8
  bucket?: string;
14
9
  };
@@ -0,0 +1,23 @@
1
+ import type { S3Api } from "../types/s3-api";
2
+ import type { FetchDownloadPhase, FetchDownloadHooks } from "../types/download";
3
+ import type { UploadProgress } from "../types/upload";
4
+ export type { FetchDownloadPhase, FetchDownloadProgress, FetchDownloadHooks, } from "../types/download";
5
+ export type UseFetchDownloadOptions = FetchDownloadHooks & {
6
+ /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */
7
+ api?: S3Api;
8
+ /** Target bucket (overrides server default) */
9
+ bucket?: string;
10
+ };
11
+ export type UseFetchDownloadState = {
12
+ phase: FetchDownloadPhase;
13
+ progress: UploadProgress;
14
+ error: string | null;
15
+ fileName: string | null;
16
+ fileSize: number | null;
17
+ };
18
+ export type UseFetchDownloadReturn = UseFetchDownloadState & {
19
+ download: (key: string, downloadName?: string) => Promise<void>;
20
+ cancel: () => void;
21
+ reset: () => void;
22
+ };
23
+ export declare function useFetchDownload(options: UseFetchDownloadOptions): UseFetchDownloadReturn;
@@ -0,0 +1,33 @@
1
+ import type { UploadProgress, MultiUploadFileState, MultiUploadPhase } from "../types";
2
+ import { type UseMultiUploadOptions } from "./use-multi-upload";
3
+ export type UseMultiUploadControlsOptions = UseMultiUploadOptions & {
4
+ objectKey: string | ((file: File) => string);
5
+ };
6
+ export type UseMultiUploadControlsReturn = {
7
+ phase: MultiUploadPhase;
8
+ /** Per-file upload states. */
9
+ files: MultiUploadFileState[];
10
+ /** Aggregated progress across all files. */
11
+ totalProgress: UploadProgress;
12
+ error: string | null;
13
+ isUploading: boolean;
14
+ handleFiles: (files: FileList | null) => void;
15
+ openFilePicker: () => void;
16
+ cancel: () => void;
17
+ reset: () => void;
18
+ /** Spread on a hidden `<input>` element. */
19
+ inputProps: {
20
+ ref: React.RefObject<HTMLInputElement | null>;
21
+ type: "file";
22
+ multiple: true;
23
+ accept?: string;
24
+ hidden: true;
25
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
26
+ };
27
+ /** Spread on a container to enable drag-and-drop. */
28
+ dropHandlers: {
29
+ onDragOver: (e: React.DragEvent) => void;
30
+ onDrop: (e: React.DragEvent) => void;
31
+ };
32
+ };
33
+ export declare function useMultiUploadControls(options: UseMultiUploadControlsOptions): UseMultiUploadControlsReturn;
@@ -1,7 +1,8 @@
1
- import type { S3Api } from "@better-s3/server";
2
- import type { UploadConfig, UploadProgress, UploadRequestOptions, MultiUploadPhase, MultiUploadFileState, MultiUploadHooks } from "./types";
1
+ import type { S3Api } from "../types/s3-api";
2
+ import type { UploadConfig, UploadProgress, UploadRequestOptions, MultiUploadPhase, MultiUploadFileState, MultiUploadHooks } from "../types";
3
3
  export type UseMultiUploadOptions = UploadConfig & MultiUploadHooks & {
4
- api: S3Api;
4
+ /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */
5
+ api?: S3Api;
5
6
  /** Static request options applied to all files */
6
7
  uploadOptions?: UploadRequestOptions;
7
8
  /** Per-file request options (overrides uploadOptions) */
@@ -0,0 +1,44 @@
1
+ import type { UploadPhase, UploadProgress, UploadRequestOptions } from "../types";
2
+ import { type UseUploadOptions } from "./use-upload";
3
+ export type UseUploadControlsOptions = UseUploadOptions & {
4
+ objectKey: string | ((file: File) => string);
5
+ /** Static request options applied to the upload. */
6
+ uploadOptions?: UploadRequestOptions;
7
+ /** Per-upload request options override. */
8
+ getUploadOptions?: (file: File) => UploadRequestOptions;
9
+ };
10
+ export type UseUploadControlsReturn = {
11
+ phase: UploadPhase;
12
+ /** Info about the selected file. */
13
+ fileInfo: {
14
+ name: string;
15
+ size: number;
16
+ } | null;
17
+ progress: UploadProgress;
18
+ error: string | null;
19
+ isUploading: boolean;
20
+ handleFiles: (files: FileList | null) => void;
21
+ openFilePicker: () => void;
22
+ cancel: () => void;
23
+ /**
24
+ * Soft-stop: preserves S3 parts and store entry so a future `upload()` can
25
+ * resume. For non-resumable uploads, identical to `cancel()`.
26
+ * See `UseUploadReturn.detach` for full semantics.
27
+ */
28
+ detach: () => void;
29
+ reset: () => void;
30
+ /** Spread on a hidden `<input>` element. */
31
+ inputProps: {
32
+ ref: React.RefObject<HTMLInputElement | null>;
33
+ type: "file";
34
+ accept?: string;
35
+ hidden: true;
36
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
37
+ };
38
+ /** Spread on a container to enable drag-and-drop. */
39
+ dropHandlers: {
40
+ onDragOver: (e: React.DragEvent) => void;
41
+ onDrop: (e: React.DragEvent) => void;
42
+ };
43
+ };
44
+ export declare function useUploadControls(options: UseUploadControlsOptions): UseUploadControlsReturn;
@@ -0,0 +1,75 @@
1
+ import type { S3Api } from "../types/s3-api";
2
+ import type { UploadConfig, UploadHooks, UploadPhase, UploadProgress, UploadResult, UploadRequestOptions } from "../types";
3
+ export type UseUploadOptions = UploadConfig & UploadHooks & {
4
+ /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */
5
+ api?: S3Api;
6
+ };
7
+ export type UseUploadState = {
8
+ phase: UploadPhase;
9
+ progress: UploadProgress;
10
+ error: string | null;
11
+ result: UploadResult | null;
12
+ fileName: string | null;
13
+ fileSize: number | null;
14
+ };
15
+ export type UseUploadReturn = UseUploadState & {
16
+ /**
17
+ * Start an upload.
18
+ *
19
+ * Safe to call again after `success`, `error`, or `cancel` — state is reset
20
+ * automatically before the new upload begins.
21
+ *
22
+ * If `uploadStore` is configured and a previous upload for the same
23
+ * `objectKey` was interrupted (e.g. via `detach()`), the engine will find
24
+ * the stored `uploadId`, call `listParts`, and resume from the last completed
25
+ * part rather than starting a new multipart upload.
26
+ */
27
+ upload: (file: File, objectKey: string, requestOptions?: UploadRequestOptions) => Promise<void>;
28
+ /**
29
+ * Abort the upload and fully clean up all resources.
30
+ *
31
+ * - Stops the in-flight network request immediately.
32
+ * - For multipart uploads: calls `AbortMultipartUpload` on S3 so incomplete
33
+ * parts are freed right away (instead of waiting for the bucket lifecycle
34
+ * policy to expire them).
35
+ * - Removes the `uploadStore` entry if one was provided.
36
+ * - Resets state to `idle`.
37
+ *
38
+ * Use this for a "Cancel" button that the user explicitly clicks to abandon
39
+ * the upload entirely.
40
+ */
41
+ cancel: () => void;
42
+ /**
43
+ * Stop the upload and — when multipart with `uploadStore` is active —
44
+ * preserve S3 parts and the store entry for a future resume.
45
+ *
46
+ * Compared to `cancel()`:
47
+ * - Does **not** call `AbortMultipartUpload` (parts stay on S3).
48
+ * - Does **not** remove the `uploadStore` entry.
49
+ * - Does **not** fire the `onCancel` callback.
50
+ *
51
+ * The next call to `upload(sameFile, sameKey)` will detect the stored
52
+ * `uploadId`, verify the existing parts via `listParts`, and continue
53
+ * uploading from where it stopped.
54
+ *
55
+ * For **simple uploads** or multipart **without** `uploadStore`, this is
56
+ * identical to `cancel()` — there is no S3 state worth preserving.
57
+ *
58
+ * Intended for custom UIs that want to offer a "save for later / resume"
59
+ * workflow. The built-in UI components always use `cancel()`.
60
+ */
61
+ detach: () => void;
62
+ /**
63
+ * Reset UI state to `idle` without touching any S3 or store resources.
64
+ *
65
+ * - Stops the in-flight network request if one is active.
66
+ * - Does **not** call `AbortMultipartUpload`.
67
+ * - Does **not** modify `uploadStore`.
68
+ * - Does **not** fire `onCancel`.
69
+ *
70
+ * Use this to clear an error or success state from the UI, or when you
71
+ * handle cleanup yourself outside this hook.
72
+ */
73
+ reset: () => void;
74
+ };
75
+ export declare function useUpload(options: UseUploadOptions): UseUploadReturn;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  export * from "./types";
2
- export { formatFileSize } from "./helpers";
2
+ export { createS3Client, createS3Api } from "./api";
3
+ /** @deprecated Use {@link createS3Client} instead. */
4
+ export { createS3Api as createPresignApi } from "./api";
5
+ export { S3Provider, useS3Client, S3Context } from "./s3-provider";
6
+ export { createLocalStorageStore, createMemoryStore } from "./store";
3
7
  export { uploadFile, uploadFiles, type UploadEngineCallbacks, type FileItem, type FileItemStatus, type MultiUploadCallbacks, } from "./upload";
4
- export { createS3Api, createS3Api as createPresignApi, validateFile, type S3Api, type S3Api as PresignApi, type PresignResponse, type PresignedPostResponse, type MultipartInitResponse, type MultipartPartResponse, type UploadConfirmResponse, } from "@better-s3/server";
5
- export { useUpload, type UseUploadOptions, type UseUploadState, type UseUploadReturn, } from "./use-upload";
6
- export { useMultiUpload, type UseMultiUploadOptions, type UseMultiUploadState, type UseMultiUploadReturn, } from "./use-multi-upload";
7
- export { useUploadControls, type UseUploadControlsOptions, type UseUploadControlsReturn, } from "./use-upload-controls";
8
- export { useDownload, type DownloadPhase, type DownloadHooks, type UseDownloadOptions, type UseDownloadState, type UseDownloadReturn, } from "./use-download";
9
- export { useFetchDownload, type FetchDownloadPhase, type FetchDownloadProgress, type FetchDownloadHooks, type UseFetchDownloadOptions, type UseFetchDownloadState, type UseFetchDownloadReturn, } from "./use-fetch-download";
10
- export { useDelete, type UseDeleteOptions, type UseDeleteState, type UseDeleteReturn, } from "./use-delete";
8
+ export { formatFileSize, validateFile, parseContentDispositionFilename, formatUploadProgress, formatSpeed, formatEta, buildObjectKey, getFileExtension, truncateFilename, createSpeedTracker, type SpeedTracker, } from "./helpers";
9
+ export { useUpload, type UseUploadOptions, type UseUploadState, type UseUploadReturn, } from "./hooks/use-upload";
10
+ export { useMultiUpload, type UseMultiUploadOptions, type UseMultiUploadState, type UseMultiUploadReturn, } from "./hooks/use-multi-upload";
11
+ export { useUploadControls, type UseUploadControlsOptions, type UseUploadControlsReturn, } from "./hooks/use-upload-controls";
12
+ export { useMultiUploadControls, type UseMultiUploadControlsOptions, type UseMultiUploadControlsReturn, } from "./hooks/use-multi-upload-controls";
13
+ export { useDownload, type DownloadPhase, type DownloadHooks, type UseDownloadOptions, type UseDownloadState, type UseDownloadReturn, } from "./hooks/use-download";
14
+ export { useFetchDownload, type FetchDownloadPhase, type FetchDownloadProgress, type FetchDownloadHooks, type UseFetchDownloadOptions, type UseFetchDownloadState, type UseFetchDownloadReturn, } from "./hooks/use-fetch-download";
15
+ export { useDelete, type UseDeleteOptions, type UseDeleteState, type UseDeleteReturn, } from "./hooks/use-delete";