In this article, I will modify . The changes are marked between // Append start and // Append end for clarity.
...
// Append start
import JSZip from 'jszip';
// Append end
...
export const EditorPanel = memo(
({
files,
unsavedFiles,
editorDocument,
selectedFile,
isStreaming,
onFileSelect,
onEditorChange,
onEditorScroll,
onFileSave,
onFileReset,
}: EditorPanelProps) => {
...
// Append start
const handleDownloadZip = useCallback(async () => {
const zip = new JSZip();
const files = workbenchStore.files.get();
// Check if there are files to download
if (Object.keys(files).length === 0) {
toast.error('No files to download');
return;
}
try {
// Add files to the ZIP, maintaining relative paths from WORK_DIR
Object.entries(files).forEach(([path, content]) => {
if (content && content.content) {
const relativePath = path.startsWith(WORK_DIR)
? path.slice(WORK_DIR.length + 1)
: path;
zip.file(relativePath, content.content);
}
});
const zipBlob = await zip.generateAsync({ type: 'blob' });
const downloadLink = document.createElement('a');
downloadLink.href = URL.createObjectURL(zipBlob);
// Use the project name from `package.json` if available
const projectName = files[`${WORK_DIR}/package.json`]?.content
? JSON.parse(files[`${WORK_DIR}/package.json`].content).name
: 'project';
downloadLink.download = `${projectName}.zip`;
downloadLink.click();
URL.revokeObjectURL(downloadLink.href);
toast.success('Files downloaded successfully');
} catch (error) {
toast.error('Failed to create zip file');
console.error(error);
}
}, []);
// Append end
return (
<PanelGroup direction="vertical">
<Panel defaultSize={showTerminal ? DEFAULT_EDITOR_SIZE : 100} minSize={20}>
<PanelGroup direction="horizontal">
<Panel defaultSize={20} minSize={10} collapsible>
<div className="flex flex-col border-r border-bolt-elements-borderColor h-full">
<PanelHeader>
<div className="i-ph:tree-structure-duotone shrink-0" />
Files
{/* Append start */}
<div className="flex-1" />
<button
className="px-2 py-1 rounded-md text-bolt-elements-item-contentDefault bg-transparent enabled:hover:text-bolt-elements-item-contentActive enabled:hover:bg-bolt-elements-item-backgroundActive"
onClick={handleDownloadZip}
title="Download as ZIP"
>
<div className="i-ph:download-simple text-xl" />
</button>
{/* Append end */}
</PanelHeader>
...
Explanation of Changes
Added
JSZipimport:
This library is used to generate the ZIP archive.
handleDownloadZipfunction:
- Retrieves files from the
workbenchStore.
- Creates a ZIP file with relative paths from
WORK_DIR.
- Automatically names the ZIP file using the project name from
package.json, if available.
- Retrieves files from the
Download button in the interface:
- A button is added to the
Filespanel header to trigger the ZIP download process.
- Styled and includes a tooltip for user clarity.
- A button is added to the
With this change, users can download the project files as a ZIP archive directly from the interface.
Updating package.json
To use the JSZip library for generating ZIP archives, add it to the dependencies in
- Download the Project Files: Click the download button and download the ZIP file.
SOCIAL SHARE CARD GENERATOR