@maas/payload-plugin-media-cloud 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/dist/adapter/handleDelete.d.ts +20 -0
- package/dist/adapter/handleDelete.js +70 -0
- package/dist/adapter/handleDelete.js.map +1 -0
- package/dist/adapter/handleUpload.d.ts +12 -0
- package/dist/adapter/handleUpload.js +29 -0
- package/dist/adapter/handleUpload.js.map +1 -0
- package/dist/adapter/staticHandler.d.ts +17 -0
- package/dist/adapter/staticHandler.js +64 -0
- package/dist/adapter/staticHandler.js.map +1 -0
- package/dist/adapter/storageAdapter.d.ts +23 -0
- package/dist/adapter/storageAdapter.js +30 -0
- package/dist/adapter/storageAdapter.js.map +1 -0
- package/dist/collections/mediaCollection.d.ts +16 -0
- package/dist/collections/mediaCollection.js +139 -0
- package/dist/collections/mediaCollection.js.map +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +5 -0
- package/dist/components/mux-preview/index.d.ts +2 -0
- package/dist/components/mux-preview/index.js +3 -0
- package/dist/components/mux-preview/mux-preview.d.ts +14 -0
- package/dist/components/mux-preview/mux-preview.js +38 -0
- package/dist/components/mux-preview/mux-preview.js.map +1 -0
- package/dist/components/upload-handler/index.d.ts +2 -0
- package/dist/components/upload-handler/index.js +3 -0
- package/dist/components/upload-handler/upload-handler.d.ts +22 -0
- package/dist/components/upload-handler/upload-handler.js +178 -0
- package/dist/components/upload-handler/upload-handler.js.map +1 -0
- package/dist/components/upload-manager/index.d.ts +2 -0
- package/dist/components/upload-manager/index.js +3 -0
- package/dist/components/upload-manager/upload-manager-DN4RrmYB.css +204 -0
- package/dist/components/upload-manager/upload-manager-DN4RrmYB.css.map +1 -0
- package/dist/components/upload-manager/upload-manager.css +201 -0
- package/dist/components/upload-manager/upload-manager.d.ts +42 -0
- package/dist/components/upload-manager/upload-manager.js +315 -0
- package/dist/components/upload-manager/upload-manager.js.map +1 -0
- package/dist/components/upload-manager/upload-manager2.js +0 -0
- package/dist/endpoints/muxAssetHandler.d.ts +11 -0
- package/dist/endpoints/muxAssetHandler.js +59 -0
- package/dist/endpoints/muxAssetHandler.js.map +1 -0
- package/dist/endpoints/muxCreateUploadHandler.d.ts +13 -0
- package/dist/endpoints/muxCreateUploadHandler.js +40 -0
- package/dist/endpoints/muxCreateUploadHandler.js.map +1 -0
- package/dist/endpoints/muxWebhookHandler.d.ts +11 -0
- package/dist/endpoints/muxWebhookHandler.js +49 -0
- package/dist/endpoints/muxWebhookHandler.js.map +1 -0
- package/dist/hooks/useEmitter.d.ts +48 -0
- package/dist/hooks/useEmitter.js +19 -0
- package/dist/hooks/useEmitter.js.map +1 -0
- package/dist/hooks/useErrorHandler.d.ts +11 -0
- package/dist/hooks/useErrorHandler.js +19 -0
- package/dist/hooks/useErrorHandler.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/plugin.d.ts +15 -0
- package/dist/plugin.js +242 -0
- package/dist/plugin.js.map +1 -0
- package/dist/tus/stores/s3/expiration-manager.d.ts +36 -0
- package/dist/tus/stores/s3/expiration-manager.js +76 -0
- package/dist/tus/stores/s3/expiration-manager.js.map +1 -0
- package/dist/tus/stores/s3/file-operations.d.ts +66 -0
- package/dist/tus/stores/s3/file-operations.js +90 -0
- package/dist/tus/stores/s3/file-operations.js.map +1 -0
- package/dist/tus/stores/s3/log.d.ts +5 -0
- package/dist/tus/stores/s3/log.js +8 -0
- package/dist/tus/stores/s3/log.js.map +1 -0
- package/dist/tus/stores/s3/metadata-manager.d.ts +85 -0
- package/dist/tus/stores/s3/metadata-manager.js +135 -0
- package/dist/tus/stores/s3/metadata-manager.js.map +1 -0
- package/dist/tus/stores/s3/parts-manager.d.ts +130 -0
- package/dist/tus/stores/s3/parts-manager.js +328 -0
- package/dist/tus/stores/s3/parts-manager.js.map +1 -0
- package/dist/tus/stores/s3/s3-store.d.ts +110 -0
- package/dist/tus/stores/s3/s3-store.js +342 -0
- package/dist/tus/stores/s3/s3-store.js.map +1 -0
- package/dist/tus/stores/s3/semaphore.d.ts +16 -0
- package/dist/tus/stores/s3/semaphore.js +32 -0
- package/dist/tus/stores/s3/semaphore.js.map +1 -0
- package/dist/types/errors.d.ts +26 -0
- package/dist/types/errors.js +28 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +73 -0
- package/dist/types/index.js +0 -0
- package/dist/utils/file.d.ts +30 -0
- package/dist/utils/file.js +84 -0
- package/dist/utils/file.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { MediaCloudError } from "../../types/errors.js";
|
|
5
|
+
import { useErrorHandler } from "../../hooks/useErrorHandler.js";
|
|
6
|
+
import { getFileType, isVideo, sanitizeFilename } from "../../utils/file.js";
|
|
7
|
+
import { emitter } from "../../hooks/useEmitter.js";
|
|
8
|
+
import * as upchunk from "@mux/upchunk";
|
|
9
|
+
import * as tus from "tus-js-client";
|
|
10
|
+
import { toast } from "@payloadcms/ui";
|
|
11
|
+
import { createClientUploadHandler } from "@payloadcms/plugin-cloud-storage/client";
|
|
12
|
+
|
|
13
|
+
//#region src/components/upload-handler/upload-handler.tsx
|
|
14
|
+
const { logError, throwError } = useErrorHandler();
|
|
15
|
+
const MUX_CHUNK_SIZE = 30720;
|
|
16
|
+
const TUS_CHUNK_SIZE = 1024 * 1024;
|
|
17
|
+
const TUS_RETRY_DELAYS = [
|
|
18
|
+
0,
|
|
19
|
+
1e3,
|
|
20
|
+
2e3,
|
|
21
|
+
5e3
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Utility function to parse upload ID from URL
|
|
25
|
+
* @param uploadUrl - The upload URL to parse
|
|
26
|
+
* @returns The extracted upload ID or empty string if parsing fails
|
|
27
|
+
*/
|
|
28
|
+
function parseUploadId(uploadUrl) {
|
|
29
|
+
if (!uploadUrl) {
|
|
30
|
+
logError(MediaCloudError.UPLOAD_NO_URL);
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
const url = new URL(uploadUrl);
|
|
34
|
+
return url.pathname.split("/").pop() || "";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Handles Mux video upload with progress tracking
|
|
38
|
+
* @param args - The upload arguments including file, server URL, and callbacks
|
|
39
|
+
* @returns Promise that resolves to upload result or null if upload fails
|
|
40
|
+
*/
|
|
41
|
+
async function muxUpload(args) {
|
|
42
|
+
const { file, serverURL, apiRoute, mimeType, updateFilename } = args;
|
|
43
|
+
const filename = sanitizeFilename(file.name);
|
|
44
|
+
const getUploadUrlEndpoint = `${serverURL}${apiRoute}/mux/upload`;
|
|
45
|
+
const getAssetEndpoint = `${serverURL}${apiRoute}/mux/asset`;
|
|
46
|
+
updateFilename(filename);
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch(getUploadUrlEndpoint, {
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
filename,
|
|
51
|
+
mimeType
|
|
52
|
+
}),
|
|
53
|
+
credentials: "include",
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: { "Content-Type": "application/json" }
|
|
56
|
+
});
|
|
57
|
+
const { url, uploadId } = await response.json();
|
|
58
|
+
const uploader = await upchunk.createUpload({
|
|
59
|
+
endpoint: url,
|
|
60
|
+
file,
|
|
61
|
+
chunkSize: MUX_CHUNK_SIZE
|
|
62
|
+
});
|
|
63
|
+
emitter.emit("add-upload", {
|
|
64
|
+
id: uploadId,
|
|
65
|
+
filename,
|
|
66
|
+
polling: false,
|
|
67
|
+
pollingUrl: getAssetEndpoint
|
|
68
|
+
});
|
|
69
|
+
uploader.on("error", () => {
|
|
70
|
+
logError(MediaCloudError.MUX_UPLOAD_ERROR);
|
|
71
|
+
toast.error("Video upload failed");
|
|
72
|
+
emitter.emit("remove-upload", { id: uploadId });
|
|
73
|
+
});
|
|
74
|
+
uploader.on("progress", (progress) => {
|
|
75
|
+
emitter.emit("update-upload", {
|
|
76
|
+
id: uploadId,
|
|
77
|
+
progress: progress.detail
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
uploader.on("success", () => {
|
|
81
|
+
emitter.emit("upload-completed", { id: uploadId });
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
uploadId,
|
|
85
|
+
mimeType,
|
|
86
|
+
storage: "mux"
|
|
87
|
+
};
|
|
88
|
+
} catch (_error) {
|
|
89
|
+
logError(MediaCloudError.MUX_DIRECT_UPLOAD_ERROR);
|
|
90
|
+
toast.error("Video upload failed");
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Handles TUS file upload with resumable capabilities
|
|
96
|
+
* @param args - The upload arguments including file, server URL, and callbacks
|
|
97
|
+
* @returns Promise that resolves to upload result or null if upload fails
|
|
98
|
+
*/
|
|
99
|
+
async function tusUpload(args) {
|
|
100
|
+
const { apiRoute, serverURL, file, mimeType, updateFilename } = args;
|
|
101
|
+
const filename = file.name;
|
|
102
|
+
const filetype = file.type;
|
|
103
|
+
const filesize = file.size.toString();
|
|
104
|
+
return new Promise((resolve) => {
|
|
105
|
+
const upload = new tus.Upload(file, {
|
|
106
|
+
endpoint: `${serverURL}${apiRoute}/uploads`,
|
|
107
|
+
retryDelays: TUS_RETRY_DELAYS,
|
|
108
|
+
chunkSize: TUS_CHUNK_SIZE,
|
|
109
|
+
metadata: {
|
|
110
|
+
filename,
|
|
111
|
+
filetype,
|
|
112
|
+
filesize,
|
|
113
|
+
contentType: filetype,
|
|
114
|
+
contentDisposition: "inline",
|
|
115
|
+
contentLength: filesize
|
|
116
|
+
},
|
|
117
|
+
onError: () => {
|
|
118
|
+
logError(MediaCloudError.TUS_UPLOAD_ERROR);
|
|
119
|
+
toast.error("File upload failed");
|
|
120
|
+
resolve(null);
|
|
121
|
+
},
|
|
122
|
+
onProgress: (bytesUploaded, bytesTotal) => {
|
|
123
|
+
const percentage = Math.round(bytesUploaded / bytesTotal * 100);
|
|
124
|
+
const uploadId = parseUploadId(upload?.url);
|
|
125
|
+
emitter.emit("update-upload", {
|
|
126
|
+
id: uploadId,
|
|
127
|
+
progress: percentage
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
onSuccess: () => {
|
|
131
|
+
const uploadId = parseUploadId(upload?.url);
|
|
132
|
+
emitter.emit("upload-completed", { id: uploadId });
|
|
133
|
+
},
|
|
134
|
+
onUploadUrlAvailable: () => {
|
|
135
|
+
const uploadId = parseUploadId(upload?.url);
|
|
136
|
+
updateFilename(uploadId);
|
|
137
|
+
emitter.emit("add-upload", {
|
|
138
|
+
id: uploadId,
|
|
139
|
+
filename
|
|
140
|
+
});
|
|
141
|
+
resolve({
|
|
142
|
+
uploadId,
|
|
143
|
+
mimeType,
|
|
144
|
+
storage: "s3"
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
upload.start();
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
const UploadHandler = createClientUploadHandler({ handler: async (args) => {
|
|
152
|
+
const { serverURL, apiRoute, file, updateFilename } = args;
|
|
153
|
+
try {
|
|
154
|
+
const mimeType = await getFileType(file);
|
|
155
|
+
if (!mimeType) {
|
|
156
|
+
throwError(MediaCloudError.FILE_TYPE_UNKNOWN);
|
|
157
|
+
throw new Error();
|
|
158
|
+
}
|
|
159
|
+
const isVideoFile = await isVideo(file);
|
|
160
|
+
const uploadArgs = {
|
|
161
|
+
file,
|
|
162
|
+
serverURL,
|
|
163
|
+
apiRoute,
|
|
164
|
+
mimeType,
|
|
165
|
+
updateFilename
|
|
166
|
+
};
|
|
167
|
+
if (isVideoFile) return await muxUpload(uploadArgs);
|
|
168
|
+
else return await tusUpload(uploadArgs);
|
|
169
|
+
} catch (_error) {
|
|
170
|
+
logError(MediaCloudError.UPLOAD_HANDLER_ERROR);
|
|
171
|
+
toast.error("Upload failed");
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
} });
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
export { UploadHandler };
|
|
178
|
+
//# sourceMappingURL=upload-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-handler.js","names":["uploadUrl?: string | null","args: UploadArgs","uploadArgs: UploadArgs"],"sources":["../../../src/components/upload-handler/upload-handler.tsx"],"sourcesContent":["'use client'\n\nimport * as upchunk from '@mux/upchunk'\nimport * as tus from 'tus-js-client'\n\nimport { toast } from '@payloadcms/ui'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\n\nimport { MediaCloudError } from '../../types/errors'\nimport { emitter } from '../../hooks/useEmitter'\nimport { useErrorHandler } from '../../hooks/useErrorHandler'\nimport { isVideo, getFileType, sanitizeFilename } from '../../utils/file'\n\ninterface UploadArgs {\n serverURL: string\n apiRoute: string\n file: File\n mimeType: string\n updateFilename: (filename: string) => void\n}\n\ninterface UploadResult {\n uploadId: string\n mimeType: string\n storage: 'mux' | 's3'\n}\n\ninterface MuxCreateUploadResponse {\n url: string\n uploadId: string\n}\n\nconst { logError, throwError } = useErrorHandler()\n\nconst MUX_CHUNK_SIZE = 30720\nconst TUS_CHUNK_SIZE = 1024 * 1024\nconst TUS_RETRY_DELAYS = [0, 1000, 2000, 5000]\n\n/**\n * Utility function to parse upload ID from URL\n * @param uploadUrl - The upload URL to parse\n * @returns The extracted upload ID or empty string if parsing fails\n */\nfunction parseUploadId(uploadUrl?: string | null): string {\n if (!uploadUrl) {\n logError(MediaCloudError.UPLOAD_NO_URL)\n return ''\n }\n const url = new URL(uploadUrl)\n return url.pathname.split('/').pop() || ''\n}\n\n/**\n * Handles Mux video upload with progress tracking\n * @param args - The upload arguments including file, server URL, and callbacks\n * @returns Promise that resolves to upload result or null if upload fails\n */\nasync function muxUpload(args: UploadArgs): Promise<UploadResult | null> {\n const { file, serverURL, apiRoute, mimeType, updateFilename } = args\n\n const filename = sanitizeFilename(file.name)\n const getUploadUrlEndpoint = `${serverURL}${apiRoute}/mux/upload`\n const getAssetEndpoint = `${serverURL}${apiRoute}/mux/asset`\n\n updateFilename(filename)\n\n try {\n // Request upload URL from Mux\n const response = await fetch(getUploadUrlEndpoint, {\n body: JSON.stringify({ filename, mimeType }),\n credentials: 'include',\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n\n const { url, uploadId } = (await response.json()) as MuxCreateUploadResponse\n\n // Create upchunk uploader\n const uploader = await upchunk.createUpload({\n endpoint: url,\n file,\n chunkSize: MUX_CHUNK_SIZE,\n })\n\n // Add upload to tracker\n emitter.emit('add-upload', {\n id: uploadId,\n filename,\n polling: false,\n pollingUrl: getAssetEndpoint,\n })\n\n // Set up event handlers\n uploader.on('error', () => {\n logError(MediaCloudError.MUX_UPLOAD_ERROR)\n toast.error('Video upload failed')\n emitter.emit('remove-upload', { id: uploadId })\n })\n\n uploader.on('progress', (progress) => {\n emitter.emit('update-upload', {\n id: uploadId,\n progress: progress.detail,\n })\n })\n\n uploader.on('success', () => {\n emitter.emit('upload-completed', { id: uploadId })\n })\n\n return {\n uploadId,\n mimeType,\n storage: 'mux',\n }\n } catch (_error) {\n logError(MediaCloudError.MUX_DIRECT_UPLOAD_ERROR)\n toast.error('Video upload failed')\n return null\n }\n}\n\n/**\n * Handles TUS file upload with resumable capabilities\n * @param args - The upload arguments including file, server URL, and callbacks\n * @returns Promise that resolves to upload result or null if upload fails\n */\nasync function tusUpload(args: UploadArgs): Promise<UploadResult | null> {\n const { apiRoute, serverURL, file, mimeType, updateFilename } = args\n\n const filename = file.name\n const filetype = file.type\n const filesize = file.size.toString()\n\n return new Promise((resolve) => {\n const upload = new tus.Upload(file, {\n endpoint: `${serverURL}${apiRoute}/uploads`,\n retryDelays: TUS_RETRY_DELAYS,\n chunkSize: TUS_CHUNK_SIZE,\n metadata: {\n filename,\n filetype,\n filesize,\n contentType: filetype,\n contentDisposition: 'inline',\n contentLength: filesize,\n },\n onError: () => {\n logError(MediaCloudError.TUS_UPLOAD_ERROR)\n toast.error('File upload failed')\n resolve(null)\n },\n onProgress: (bytesUploaded, bytesTotal) => {\n const percentage = Math.round((bytesUploaded / bytesTotal) * 100)\n const uploadId = parseUploadId(upload?.url)\n emitter.emit('update-upload', {\n id: uploadId,\n progress: percentage,\n })\n },\n onSuccess: () => {\n const uploadId = parseUploadId(upload?.url)\n emitter.emit('upload-completed', { id: uploadId })\n },\n onUploadUrlAvailable: () => {\n const uploadId = parseUploadId(upload?.url)\n updateFilename(uploadId)\n emitter.emit('add-upload', { id: uploadId, filename })\n resolve({\n uploadId,\n mimeType,\n storage: 's3',\n })\n },\n })\n\n upload.start()\n })\n}\n\nexport const UploadHandler = createClientUploadHandler({\n handler: async (args) => {\n const { serverURL, apiRoute, file, updateFilename } = args\n\n try {\n const mimeType = await getFileType(file)\n\n if (!mimeType) {\n throwError(MediaCloudError.FILE_TYPE_UNKNOWN)\n throw new Error() // This will never execute but satisfies TypeScript\n }\n\n const isVideoFile = await isVideo(file)\n\n const uploadArgs: UploadArgs = {\n file,\n serverURL,\n apiRoute,\n mimeType,\n updateFilename,\n }\n\n if (isVideoFile) {\n return await muxUpload(uploadArgs)\n } else {\n return await tusUpload(uploadArgs)\n }\n } catch (_error) {\n logError(MediaCloudError.UPLOAD_HANDLER_ERROR)\n toast.error('Upload failed')\n return null\n }\n },\n})\n"],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
@keyframes pulse {
|
|
2
|
+
0% {
|
|
3
|
+
opacity: 0.6;
|
|
4
|
+
}
|
|
5
|
+
50% {
|
|
6
|
+
opacity: 1;
|
|
7
|
+
}
|
|
8
|
+
100% {
|
|
9
|
+
opacity: 0.6;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@keyframes shimmer {
|
|
14
|
+
0% {
|
|
15
|
+
background-position: -200% 0;
|
|
16
|
+
}
|
|
17
|
+
100% {
|
|
18
|
+
background-position: 200% 0;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.upload-manager {
|
|
23
|
+
position: fixed;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
bottom: 0;
|
|
26
|
+
left: 50%;
|
|
27
|
+
transform: translateX(-50%);
|
|
28
|
+
width: 400px;
|
|
29
|
+
max-height: 500px;
|
|
30
|
+
margin: 2.25rem;
|
|
31
|
+
background: var(--theme-bg);
|
|
32
|
+
border: 1px solid var(--theme-elevation-100);
|
|
33
|
+
border-radius: var(--style-radius-m);
|
|
34
|
+
box-shadow: var(--box-shadow-lg);
|
|
35
|
+
z-index: 1024;
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.upload-manager__header {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: space-between;
|
|
44
|
+
padding: 0.75rem 1rem;
|
|
45
|
+
border-bottom: 1px solid var(--theme-elevation-100);
|
|
46
|
+
background: var(--theme-elevation-50);
|
|
47
|
+
|
|
48
|
+
& h4 {
|
|
49
|
+
margin: 0;
|
|
50
|
+
font-size: 0.875rem;
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
color: var(--theme-text);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.upload-manager__tabs {
|
|
57
|
+
display: flex;
|
|
58
|
+
border-bottom: 1px solid var(--theme-elevation-100);
|
|
59
|
+
background: var(--theme-elevation-25);
|
|
60
|
+
|
|
61
|
+
& .upload-tab {
|
|
62
|
+
flex: 1;
|
|
63
|
+
padding: 0.5rem 0.75rem;
|
|
64
|
+
background: none;
|
|
65
|
+
border: none;
|
|
66
|
+
color: var(--theme-text-dim);
|
|
67
|
+
font-size: 0.75rem;
|
|
68
|
+
font-weight: 500;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
transition: all 0.15s ease;
|
|
71
|
+
border-bottom: 2px solid transparent;
|
|
72
|
+
|
|
73
|
+
&:hover {
|
|
74
|
+
background: var(--theme-elevation-50);
|
|
75
|
+
color: var(--theme-text);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&[data-active='true'] {
|
|
79
|
+
color: var(--theme-success-500);
|
|
80
|
+
border-bottom-color: var(--theme-success-500);
|
|
81
|
+
background: var(--theme-bg);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.upload-manager__content {
|
|
87
|
+
flex: 1;
|
|
88
|
+
overflow-y: auto;
|
|
89
|
+
max-height: 300px;
|
|
90
|
+
padding: 0;
|
|
91
|
+
|
|
92
|
+
& ul {
|
|
93
|
+
list-style: none;
|
|
94
|
+
margin: 0;
|
|
95
|
+
padding: 0;
|
|
96
|
+
|
|
97
|
+
& li {
|
|
98
|
+
padding: 0.75rem 1rem;
|
|
99
|
+
border-bottom: 1px solid var(--theme-elevation-50);
|
|
100
|
+
|
|
101
|
+
&:last-child {
|
|
102
|
+
border-bottom: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&[data-status='uploading'] {
|
|
106
|
+
background: var(--theme-bg);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&[data-status='processing'] {
|
|
110
|
+
background: var(--theme-warning-50);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&[data-status='completed'] {
|
|
114
|
+
background: var(--theme-success-50);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
& .upload-empty-state {
|
|
120
|
+
padding: 2rem 1rem;
|
|
121
|
+
text-align: center;
|
|
122
|
+
color: var(--theme-text-dim);
|
|
123
|
+
font-size: 0.875rem;
|
|
124
|
+
margin: 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.upload-progress-bar {
|
|
129
|
+
height: 3px;
|
|
130
|
+
background: var(--theme-elevation-100);
|
|
131
|
+
border-radius: 2px;
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
position: relative;
|
|
134
|
+
|
|
135
|
+
& .upload-progress {
|
|
136
|
+
height: 100%;
|
|
137
|
+
background: var(--theme-success-500);
|
|
138
|
+
width: calc(var(--progress) * 100%);
|
|
139
|
+
transition: width 0.3s ease;
|
|
140
|
+
border-radius: inherit;
|
|
141
|
+
|
|
142
|
+
&[data-active='true'] {
|
|
143
|
+
background: var(--theme-warning-500);
|
|
144
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
145
|
+
width: 100%;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.upload-info {
|
|
151
|
+
display: flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
justify-content: space-between;
|
|
154
|
+
margin-bottom: 0.5rem;
|
|
155
|
+
|
|
156
|
+
& .upload-filename {
|
|
157
|
+
font-size: 0.875rem;
|
|
158
|
+
font-weight: 500;
|
|
159
|
+
color: var(--theme-text);
|
|
160
|
+
flex: 1;
|
|
161
|
+
margin-right: 0.5rem;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
text-overflow: ellipsis;
|
|
164
|
+
white-space: nowrap;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
& .upload-meta {
|
|
168
|
+
font-size: 0.75rem;
|
|
169
|
+
color: var(--theme-text-dim);
|
|
170
|
+
font-weight: 500;
|
|
171
|
+
flex-shrink: 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.upload-manager__file {
|
|
176
|
+
& .upload-manager__file--polling {
|
|
177
|
+
animation: pulse 2s ease-in-out infinite;
|
|
178
|
+
background: linear-gradient(90deg, #3b82f6, #8b5cf6, #3b82f6);
|
|
179
|
+
background-size: 200% 100%;
|
|
180
|
+
animation:
|
|
181
|
+
pulse 2s ease-in-out infinite,
|
|
182
|
+
shimmer 3s ease-in-out infinite;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.upload-manager__footer {
|
|
187
|
+
padding: 0.75rem 1rem;
|
|
188
|
+
border-top: 1px solid var(--theme-elevation-100);
|
|
189
|
+
background: var(--theme-elevation-50);
|
|
190
|
+
display: flex;
|
|
191
|
+
justify-content: center;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Responsive adjustments
|
|
195
|
+
@media (max-width: 768px) {
|
|
196
|
+
.upload-manager {
|
|
197
|
+
width: calc(100vw - 2rem);
|
|
198
|
+
right: 1rem;
|
|
199
|
+
left: 1rem;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
/*# sourceMappingURL=upload-manager-DN4RrmYB.css.map*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-manager-DN4RrmYB.css","names":[],"sources":["../../../src/components/upload-manager/upload-manager.css"],"sourcesContent":["@keyframes pulse {\n 0% {\n opacity: 0.6;\n }\n 50% {\n opacity: 1;\n }\n 100% {\n opacity: 0.6;\n }\n}\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n.upload-manager {\n position: fixed;\n overflow: hidden;\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n width: 400px;\n max-height: 500px;\n margin: 2.25rem;\n background: var(--theme-bg);\n border: 1px solid var(--theme-elevation-100);\n border-radius: var(--style-radius-m);\n box-shadow: var(--box-shadow-lg);\n z-index: 1024;\n display: flex;\n flex-direction: column;\n}\n\n.upload-manager__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--theme-elevation-100);\n background: var(--theme-elevation-50);\n\n & h4 {\n margin: 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--theme-text);\n }\n}\n\n.upload-manager__tabs {\n display: flex;\n border-bottom: 1px solid var(--theme-elevation-100);\n background: var(--theme-elevation-25);\n\n & .upload-tab {\n flex: 1;\n padding: 0.5rem 0.75rem;\n background: none;\n border: none;\n color: var(--theme-text-dim);\n font-size: 0.75rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border-bottom: 2px solid transparent;\n\n &:hover {\n background: var(--theme-elevation-50);\n color: var(--theme-text);\n }\n\n &[data-active='true'] {\n color: var(--theme-success-500);\n border-bottom-color: var(--theme-success-500);\n background: var(--theme-bg);\n }\n }\n}\n\n.upload-manager__content {\n flex: 1;\n overflow-y: auto;\n max-height: 300px;\n padding: 0;\n\n & ul {\n list-style: none;\n margin: 0;\n padding: 0;\n\n & li {\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--theme-elevation-50);\n\n &:last-child {\n border-bottom: none;\n }\n\n &[data-status='uploading'] {\n background: var(--theme-bg);\n }\n\n &[data-status='processing'] {\n background: var(--theme-warning-50);\n }\n\n &[data-status='completed'] {\n background: var(--theme-success-50);\n }\n }\n }\n\n & .upload-empty-state {\n padding: 2rem 1rem;\n text-align: center;\n color: var(--theme-text-dim);\n font-size: 0.875rem;\n margin: 0;\n }\n}\n\n.upload-progress-bar {\n height: 3px;\n background: var(--theme-elevation-100);\n border-radius: 2px;\n overflow: hidden;\n position: relative;\n\n & .upload-progress {\n height: 100%;\n background: var(--theme-success-500);\n width: calc(var(--progress) * 100%);\n transition: width 0.3s ease;\n border-radius: inherit;\n\n &[data-active='true'] {\n background: var(--theme-warning-500);\n animation: pulse 1.5s ease-in-out infinite;\n width: 100%;\n }\n }\n}\n\n.upload-info {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n\n & .upload-filename {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--theme-text);\n flex: 1;\n margin-right: 0.5rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n & .upload-meta {\n font-size: 0.75rem;\n color: var(--theme-text-dim);\n font-weight: 500;\n flex-shrink: 0;\n }\n}\n\n.upload-manager__file {\n & .upload-manager__file--polling {\n animation: pulse 2s ease-in-out infinite;\n background: linear-gradient(90deg, #3b82f6, #8b5cf6, #3b82f6);\n background-size: 200% 100%;\n animation:\n pulse 2s ease-in-out infinite,\n shimmer 3s ease-in-out infinite;\n }\n}\n\n.upload-manager__footer {\n padding: 0.75rem 1rem;\n border-top: 1px solid var(--theme-elevation-100);\n background: var(--theme-elevation-50);\n display: flex;\n justify-content: center;\n}\n\n// Responsive adjustments\n@media (max-width: 768px) {\n .upload-manager {\n width: calc(100vw - 2rem);\n right: 1rem;\n left: 1rem;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
@keyframes pulse {
|
|
2
|
+
0% {
|
|
3
|
+
opacity: 0.6;
|
|
4
|
+
}
|
|
5
|
+
50% {
|
|
6
|
+
opacity: 1;
|
|
7
|
+
}
|
|
8
|
+
100% {
|
|
9
|
+
opacity: 0.6;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@keyframes shimmer {
|
|
14
|
+
0% {
|
|
15
|
+
background-position: -200% 0;
|
|
16
|
+
}
|
|
17
|
+
100% {
|
|
18
|
+
background-position: 200% 0;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.upload-manager {
|
|
23
|
+
position: fixed;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
bottom: 0;
|
|
26
|
+
left: 50%;
|
|
27
|
+
transform: translateX(-50%);
|
|
28
|
+
width: 400px;
|
|
29
|
+
max-height: 500px;
|
|
30
|
+
margin: 2.25rem;
|
|
31
|
+
background: var(--theme-bg);
|
|
32
|
+
border: 1px solid var(--theme-elevation-100);
|
|
33
|
+
border-radius: var(--style-radius-m);
|
|
34
|
+
box-shadow: var(--box-shadow-lg);
|
|
35
|
+
z-index: 1024;
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.upload-manager__header {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: space-between;
|
|
44
|
+
padding: 0.75rem 1rem;
|
|
45
|
+
border-bottom: 1px solid var(--theme-elevation-100);
|
|
46
|
+
background: var(--theme-elevation-50);
|
|
47
|
+
|
|
48
|
+
& h4 {
|
|
49
|
+
margin: 0;
|
|
50
|
+
font-size: 0.875rem;
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
color: var(--theme-text);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.upload-manager__tabs {
|
|
57
|
+
display: flex;
|
|
58
|
+
border-bottom: 1px solid var(--theme-elevation-100);
|
|
59
|
+
background: var(--theme-elevation-25);
|
|
60
|
+
|
|
61
|
+
& .upload-tab {
|
|
62
|
+
flex: 1;
|
|
63
|
+
padding: 0.5rem 0.75rem;
|
|
64
|
+
background: none;
|
|
65
|
+
border: none;
|
|
66
|
+
color: var(--theme-text-dim);
|
|
67
|
+
font-size: 0.75rem;
|
|
68
|
+
font-weight: 500;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
transition: all 0.15s ease;
|
|
71
|
+
border-bottom: 2px solid transparent;
|
|
72
|
+
|
|
73
|
+
&:hover {
|
|
74
|
+
background: var(--theme-elevation-50);
|
|
75
|
+
color: var(--theme-text);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&[data-active='true'] {
|
|
79
|
+
color: var(--theme-success-500);
|
|
80
|
+
border-bottom-color: var(--theme-success-500);
|
|
81
|
+
background: var(--theme-bg);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.upload-manager__content {
|
|
87
|
+
flex: 1;
|
|
88
|
+
overflow-y: auto;
|
|
89
|
+
max-height: 300px;
|
|
90
|
+
padding: 0;
|
|
91
|
+
|
|
92
|
+
& ul {
|
|
93
|
+
list-style: none;
|
|
94
|
+
margin: 0;
|
|
95
|
+
padding: 0;
|
|
96
|
+
|
|
97
|
+
& li {
|
|
98
|
+
padding: 0.75rem 1rem;
|
|
99
|
+
border-bottom: 1px solid var(--theme-elevation-50);
|
|
100
|
+
|
|
101
|
+
&:last-child {
|
|
102
|
+
border-bottom: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&[data-status='uploading'] {
|
|
106
|
+
background: var(--theme-bg);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&[data-status='processing'] {
|
|
110
|
+
background: var(--theme-warning-50);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&[data-status='completed'] {
|
|
114
|
+
background: var(--theme-success-50);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
& .upload-empty-state {
|
|
120
|
+
padding: 2rem 1rem;
|
|
121
|
+
text-align: center;
|
|
122
|
+
color: var(--theme-text-dim);
|
|
123
|
+
font-size: 0.875rem;
|
|
124
|
+
margin: 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.upload-progress-bar {
|
|
129
|
+
height: 3px;
|
|
130
|
+
background: var(--theme-elevation-100);
|
|
131
|
+
border-radius: 2px;
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
position: relative;
|
|
134
|
+
|
|
135
|
+
& .upload-progress {
|
|
136
|
+
height: 100%;
|
|
137
|
+
background: var(--theme-success-500);
|
|
138
|
+
width: calc(var(--progress) * 100%);
|
|
139
|
+
transition: width 0.3s ease;
|
|
140
|
+
border-radius: inherit;
|
|
141
|
+
|
|
142
|
+
&[data-active='true'] {
|
|
143
|
+
background: var(--theme-warning-500);
|
|
144
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
145
|
+
width: 100%;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.upload-info {
|
|
151
|
+
display: flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
justify-content: space-between;
|
|
154
|
+
margin-bottom: 0.5rem;
|
|
155
|
+
|
|
156
|
+
& .upload-filename {
|
|
157
|
+
font-size: 0.875rem;
|
|
158
|
+
font-weight: 500;
|
|
159
|
+
color: var(--theme-text);
|
|
160
|
+
flex: 1;
|
|
161
|
+
margin-right: 0.5rem;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
text-overflow: ellipsis;
|
|
164
|
+
white-space: nowrap;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
& .upload-meta {
|
|
168
|
+
font-size: 0.75rem;
|
|
169
|
+
color: var(--theme-text-dim);
|
|
170
|
+
font-weight: 500;
|
|
171
|
+
flex-shrink: 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.upload-manager__file {
|
|
176
|
+
& .upload-manager__file--polling {
|
|
177
|
+
animation: pulse 2s ease-in-out infinite;
|
|
178
|
+
background: linear-gradient(90deg, #3b82f6, #8b5cf6, #3b82f6);
|
|
179
|
+
background-size: 200% 100%;
|
|
180
|
+
animation:
|
|
181
|
+
pulse 2s ease-in-out infinite,
|
|
182
|
+
shimmer 3s ease-in-out infinite;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.upload-manager__footer {
|
|
187
|
+
padding: 0.75rem 1rem;
|
|
188
|
+
border-top: 1px solid var(--theme-elevation-100);
|
|
189
|
+
background: var(--theme-elevation-50);
|
|
190
|
+
display: flex;
|
|
191
|
+
justify-content: center;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Responsive adjustments
|
|
195
|
+
@media (max-width: 768px) {
|
|
196
|
+
.upload-manager {
|
|
197
|
+
width: calc(100vw - 2rem);
|
|
198
|
+
right: 1rem;
|
|
199
|
+
left: 1rem;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/upload-manager/upload-manager.d.ts
|
|
4
|
+
interface Upload {
|
|
5
|
+
id: string;
|
|
6
|
+
filename: string;
|
|
7
|
+
progress: number;
|
|
8
|
+
error?: string;
|
|
9
|
+
polling?: boolean;
|
|
10
|
+
pollingUrl?: string;
|
|
11
|
+
status?: 'uploading' | 'processing' | 'completed';
|
|
12
|
+
}
|
|
13
|
+
interface UploadManagerContextType {
|
|
14
|
+
showUploadManager?: boolean;
|
|
15
|
+
activeUploads: Upload[];
|
|
16
|
+
addUpload: (args: AddUploadArgs) => void;
|
|
17
|
+
updateUpload: (args: UpdateUploadArgs) => void;
|
|
18
|
+
}
|
|
19
|
+
interface UploadManagerProviderArgs {
|
|
20
|
+
children: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
interface AddUploadArgs {
|
|
23
|
+
id: string;
|
|
24
|
+
filename: string;
|
|
25
|
+
polling?: boolean;
|
|
26
|
+
pollingUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
interface UpdateUploadArgs {
|
|
29
|
+
id: string;
|
|
30
|
+
progress: number;
|
|
31
|
+
polling?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Provider component for upload management context
|
|
35
|
+
* @param args - Arguments including children to wrap
|
|
36
|
+
* @returns JSX element providing upload management context
|
|
37
|
+
*/
|
|
38
|
+
declare function UploadManagerProvider(args: UploadManagerProviderArgs): React.JSX.Element;
|
|
39
|
+
declare const useUploadManagerContext: () => UploadManagerContextType;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { UploadManagerProvider, useUploadManagerContext };
|
|
42
|
+
//# sourceMappingURL=upload-manager.d.ts.map
|