diff --git a/src/components/DownloadButtonAndMenu.tsx b/src/components/DownloadButtonAndMenu.tsx index 80f60b62f..aed599704 100644 --- a/src/components/DownloadButtonAndMenu.tsx +++ b/src/components/DownloadButtonAndMenu.tsx @@ -3,6 +3,9 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { toast, useNotImplementedToast } from "@/hooks/use-toast" @@ -26,6 +29,7 @@ import { useState } from "react" import { useAxios } from "@/hooks/use-axios" import { useCurrentPackageId } from "@/hooks/use-current-package-id" import { downloadStepFile } from "@/lib/download-fns/download-step" +import { ImageIcon } from "lucide-react" interface DownloadButtonAndMenuProps { className?: string @@ -60,6 +64,23 @@ export function DownloadButtonAndMenu({ hasCircuitJson || (circuitJson && circuitJson.length), ) + const formatBadge = ( + label: string, + colorClassName: + | "bg-blue-500" + | "bg-green-500" + | "bg-purple-500" + | "bg-orange-500" + | "bg-emerald-500" + | "bg-teal-600", + ) => ( + + {label} + + ) + const getCircuitJson = async (): Promise => { if (circuitJson && circuitJson.length) return circuitJson if (fetchedCircuitJson && fetchedCircuitJson.length) @@ -86,6 +107,44 @@ export function DownloadButtonAndMenu({ } } + const downloadModel = async (format: "glb" | "gltf") => { + try { + const cj = await getCircuitJson() + await downloadGltfFromCircuitJson(cj, unscopedName || "circuit", { + format, + boardTextureResolution: 2048, + }) + } catch (error: any) { + toast({ + title: + format === "gltf" + ? "Error Downloading 3D Model (GLTF)" + : "Error Downloading 3D Model", + description: error.toString(), + variant: "destructive", + }) + } + } + + const downloadImage = async (format: ImageFormat) => { + await downloadPngImage({ + circuitJson: await getCircuitJson(), + unscopedName, + author, + format, + }) + } + + const downloadDefaultImage = async () => { + const desiredImageFormat = ["pcb", "schematic", "assembly", "3d"].includes( + desiredImageType, + ) + ? desiredImageType + : "pcb" + + await downloadImage(desiredImageFormat as ImageFormat) + } + if (!canDownload) { return (
@@ -125,60 +184,134 @@ export function DownloadButtonAndMenu({ > Circuit JSON - - json - - - { - try { - const cj = await getCircuitJson() - await downloadGltfFromCircuitJson( - cj, - unscopedName || "circuit", - { format: "glb", boardTextureResolution: 2048 }, - ) - } catch (error: any) { - toast({ - title: "Error Downloading 3D Model", - description: error.toString(), - variant: "destructive", - }) - } - }} - > - - 3D Model - - glb - - - { - try { - const cj = await getCircuitJson() - await downloadGltfFromCircuitJson( - cj, - unscopedName || "circuit", - { format: "gltf", boardTextureResolution: 2048 }, - ) - } catch (error: any) { - toast({ - title: "Error Downloading 3D Model (GLTF)", - description: error.toString(), - variant: "destructive", - }) - } - }} - > - - 3D Model - - gltf - + {formatBadge("json", "bg-blue-500")} + + + + + Images + + + {!offerMultipleImageFormats && ( + + + PNG + {formatBadge("png", "bg-teal-600")} + + )} + {offerMultipleImageFormats && ( + <> + downloadImage("schematic")} + > + + Schematic PNG + {formatBadge("png", "bg-teal-600")} + + downloadImage("pcb")} + > + + PCB PNG + {formatBadge("png", "bg-teal-600")} + + downloadImage("assembly")} + > + + Assembly PNG + {formatBadge("png", "bg-teal-600")} + + downloadImage("3d")} + > + + 3D PNG + {formatBadge("png", "bg-teal-600")} + + + )} + { + const cj = await getCircuitJson() + downloadSchematicSvg(cj, unscopedName || "circuit") + }} + > + + Schematic SVG + {formatBadge("svg", "bg-blue-500")} + + { + const cj = await getCircuitJson() + downloadAssemblySvg(cj, unscopedName || "circuit") + }} + > + + Assembly SVG + {formatBadge("svg", "bg-blue-500")} + + { + const cj = await getCircuitJson() + setFetchedCircuitJson(cj) + openPcbDownloadDialog() + }} + > + + PCB SVG + {formatBadge("svg", "bg-blue-500")} + + + + + + + + 3D Models + + + downloadModel("glb")} + > + + GLB + {formatBadge("glb", "bg-green-500")} + + downloadModel("gltf")} + > + + GLTF + {formatBadge("gltf", "bg-green-500")} + + { + const cj = await getCircuitJson() + downloadStepFile(cj, unscopedName || "step_file") + }} + > + + STEP + {formatBadge("STEP", "bg-emerald-500")} + + + + { @@ -199,86 +332,37 @@ export function DownloadButtonAndMenu({ > Fabrication Files - - gerber/pnp/bom/csv - - - notImplemented("kicad footprint download")} - > - - KiCad Footprint - - kicad_mod - - - { - const cj = await getCircuitJson() - downloadKicadFiles(cj, unscopedName || "kicad_project") - }} - > - - KiCad Project - - kicad_*.zip - - - { - const cj = await getCircuitJson() - downloadStepFile(cj, unscopedName || "step_file") - }} - > - - Step Format - - STEP - - - { - const cj = await getCircuitJson() - downloadSchematicSvg(cj, unscopedName || "circuit") - }} - > - - Schematic SVG - - svg - - - { - const cj = await getCircuitJson() - downloadAssemblySvg(cj, unscopedName || "circuit") - }} - > - - Assembly SVG - - svg - - - { - const cj = await getCircuitJson() - setFetchedCircuitJson(cj) - openPcbDownloadDialog() - }} - > - - PCB SVG - - svg - + {formatBadge("gerber/pnp/bom/csv", "bg-purple-500")} + + + + + KiCad + + + notImplemented("kicad footprint download")} + > + + Footprint + {formatBadge("kicad_mod", "bg-orange-500")} + + { + const cj = await getCircuitJson() + downloadKicadFiles(cj, unscopedName || "kicad_project") + }} + > + + Project + {formatBadge("kicad_*.zip", "bg-orange-500")} + + + + { @@ -288,9 +372,7 @@ export function DownloadButtonAndMenu({ > Specctra DSN - - dsn - + {formatBadge("dsn", "bg-blue-500")} Readable Netlist - - txt - + {formatBadge("txt", "bg-blue-500")} SPICE Netlist - - spice - + {formatBadge("spice", "bg-blue-500")} Simple Route JSON - - json - + {formatBadge("json", "bg-blue-500")} - - {!offerMultipleImageFormats && ( - { - const desiredImageFormat = [ - "pcb", - "schematic", - "assembly", - "3d", - ].includes(desiredImageType) - ? desiredImageType - : "pcb" - const cj = await getCircuitJson() - downloadPngImage({ - circuitJson: cj, - unscopedName, - author, - format: desiredImageFormat as ImageFormat, - }) - }} - > - - Image PNG - - png - - - )} - {offerMultipleImageFormats && ( - <> - - downloadPngImage({ - circuitJson: await getCircuitJson(), - unscopedName, - author, - format: "schematic", - }) - } - > - - Schematic PNG - - png - - - - downloadPngImage({ - circuitJson: await getCircuitJson(), - unscopedName, - author, - format: "pcb", - }) - } - > - - PCB PNG - - png - - - - downloadPngImage({ - circuitJson: await getCircuitJson(), - unscopedName, - author, - format: "assembly", - }) - } - > - - Assembly PNG - - png - - - - downloadPngImage({ - circuitJson: await getCircuitJson(), - unscopedName, - author, - format: "3d", - }) - } - > - - 3D PNG - - png - - - - )}