@neo4j-ndl/react
Version:
React implementation of Neo4j Design System
107 lines • 6.04 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { XMarkIcon } from '@heroicons/react/24/solid';
import { Dropzone, FilledButton, Typography } from '@neo4j-ndl/react';
import { useCallback, useState } from 'react';
// Configuration constants
const CONFIG = {
MAX_FILES: 3,
MAX_FILE_SIZE: 5 * 1024 * 1024, // 5MB
PROGRESS_INCREMENT: 5,
UPDATE_INTERVAL: 100,
ACCEPTED_EXTENSIONS: ['.txt', '.json'],
};
var UploadState;
(function (UploadState) {
UploadState["Idle"] = "idle";
UploadState["Uploading"] = "uploading";
UploadState["Success"] = "success";
UploadState["Error"] = "error";
})(UploadState || (UploadState = {}));
const Component = () => {
const [uploadData, setUploadData] = useState({
errors: [],
files: [],
progress: 0,
state: UploadState.Idle,
});
const resetUpload = useCallback(() => {
setUploadData({
errors: [],
files: [],
progress: 0,
state: UploadState.Idle,
});
}, []);
const simulateUpload = useCallback((files) => {
setUploadData((prev) => (Object.assign(Object.assign({}, prev), { state: UploadState.Uploading, files, progress: 0 })));
const interval = setInterval(() => {
setUploadData((prev) => {
const newProgress = prev.progress + CONFIG.PROGRESS_INCREMENT;
if (newProgress >= 100) {
clearInterval(interval);
setTimeout(() => setUploadData((current) => (Object.assign(Object.assign({}, current), { state: UploadState.Success }))), 500);
return Object.assign(Object.assign({}, prev), { progress: 100 });
}
return Object.assign(Object.assign({}, prev), { progress: newProgress });
});
}, CONFIG.UPDATE_INTERVAL);
}, []);
const handleDrop = useCallback((acceptedFiles, rejectedFiles, event) => {
console.info('Drop event:', { acceptedFiles, event, rejectedFiles });
if (acceptedFiles.length > 0) {
simulateUpload(acceptedFiles);
}
}, [simulateUpload]);
const handleDropRejected = useCallback((rejectedFiles) => {
const errors = rejectedFiles.map((file) => `${file.file.name}: ${file.errors.map((e) => e.message).join(', ')}`);
setUploadData((prev) => (Object.assign(Object.assign({}, prev), { state: UploadState.Error, errors })));
}, []);
const handleError = useCallback((error) => {
console.error('Dropzone error:', error);
setUploadData((prev) => (Object.assign(Object.assign({}, prev), { state: UploadState.Error, errors: [error.message] })));
}, []);
const renderStatusContent = () => {
const { state, progress, files, errors } = uploadData;
switch (state) {
case UploadState.Uploading:
return (_jsx(Dropzone.LoadingProgressBar, { progressBarPrecentage: Math.round(progress) }));
case UploadState.Success:
return (_jsxs("div", { className: "n-flex n-flex-col n-justify-center n-items-center n-gap-y-token-32", children: [_jsx(Typography, { variant: "title-4", className: "n-text-success-text n-font-semibold", children: "Upload Complete!" }), _jsxs(Typography, { variant: "body-small", className: "n-text-neutral-text-weak", children: ["Successfully uploaded: ", files.map((file) => file.name).join(', ')] }), _jsx(FilledButton, { onClick: resetUpload, children: "Upload More Files" })] }));
case UploadState.Error:
return (_jsxs("div", { className: "n-flex n-flex-col n-justify-center n-items-center n-gap-y-token-32", children: [_jsx(XMarkIcon, { className: "n-w-token-32 n-h-token-32 n-text-danger-text" }), _jsx("div", { className: "n-flex n-flex-col n-gap-y-token-2", children: errors.map((message, index) => (_jsx(Typography, { variant: "label", className: "n-text-danger-text n-font-semibold", htmlAttributes: { role: 'alert' }, children: message }, index))) }), _jsx(FilledButton, { onClick: resetUpload, children: "Try Again" })] }));
default:
return undefined;
}
};
return (_jsx(Dropzone, { dropZoneOptions: {
disabled: uploadData.state === UploadState.Uploading,
maxFiles: CONFIG.MAX_FILES,
maxSize: CONFIG.MAX_FILE_SIZE,
multiple: true,
onDrop: handleDrop,
onDropRejected: handleDropRejected,
onError: handleError,
}, supportedFilesDescription: _jsxs("div", { className: "n-text-center n-flex n-flex-col n-gap-y-token-2", children: [_jsx(Typography, { variant: "body-small", className: "n-text-neutral-text-weak", children: "Supports: Text files (.txt, .json) only" }), _jsxs(Typography, { variant: "body-small", className: "n-text-neutral-text-weak", children: ["Max ", CONFIG.MAX_FILES, " files \u2022", ' ', CONFIG.MAX_FILE_SIZE / (1024 * 1024), "MB per file"] })] }), acceptedFileExtensions: CONFIG.ACCEPTED_EXTENSIONS, loadingElement: renderStatusContent(), rejectedText: "Error: Please make sure to only upload .json or .txt files", heading: "Drag & Drop your files" }));
};
export default Component;
//# sourceMappingURL=dropzone-full.story.js.map