@tscircuit/fake-snippets 0.0.74 → 0.0.76
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/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +38 -0
- package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +14 -11
- package/bun.lock +1 -4
- package/dist/bundle.js +20 -8
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +11 -0
- package/fake-snippets-api/routes/api/package_releases/get.ts +6 -1
- package/fake-snippets-api/routes/api/package_releases/update.ts +4 -1
- package/package.json +1 -2
- package/src/components/DownloadButtonAndMenu.tsx +26 -8
- package/src/components/Header.tsx +7 -7
- package/src/components/PackageBuildsPage/ErrorObject.ts +12 -0
- package/src/components/PackageBuildsPage/LogContent.tsx +32 -0
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +62 -4
- package/src/components/PackageBuildsPage/build-preview-content.tsx +21 -5
- package/src/components/PackageBuildsPage/capitalCase.ts +4 -0
- package/src/components/PackageBuildsPage/collapsible-section.tsx +34 -9
- package/src/components/PackageBuildsPage/getColorForDisplayStatus.ts +17 -0
- package/src/components/PackageBuildsPage/package-build-details-panel.tsx +80 -17
- package/src/components/PackageBuildsPage/package-build-header.tsx +15 -30
- package/src/components/ViewPackagePage/components/main-content-header.tsx +1 -1
- package/src/components/ViewPackagePage/components/package-header.tsx +0 -1
- package/src/components/dialogs/pcb-download-dialog.tsx +113 -0
- package/src/lib/download-fns/download-pcb-svg.ts +35 -0
- package/src/lib/utils/timeAgo.ts +14 -3
- package/bun-tests/fake-snippets-api/fixtures/get-circuit-json.ts +0 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChevronDown, Download, Github, Link } from "lucide-react"
|
|
1
|
+
import { ChevronDown, Download, Github, Link, RefreshCw } from "lucide-react"
|
|
2
2
|
import { Button } from "@/components/ui/button"
|
|
3
3
|
import {
|
|
4
4
|
DropdownMenu,
|
|
@@ -7,9 +7,12 @@ import {
|
|
|
7
7
|
DropdownMenuTrigger,
|
|
8
8
|
} from "@/components/ui/dropdown-menu"
|
|
9
9
|
import { useParams } from "wouter"
|
|
10
|
+
import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
|
|
11
|
+
import { DownloadButtonAndMenu } from "../DownloadButtonAndMenu"
|
|
10
12
|
|
|
11
13
|
export function PackageBuildHeader() {
|
|
12
14
|
const { author, packageName } = useParams()
|
|
15
|
+
const { packageRelease } = useCurrentPackageRelease()
|
|
13
16
|
|
|
14
17
|
return (
|
|
15
18
|
<div className="border-b border-gray-200 bg-white px-6 py-4">
|
|
@@ -39,35 +42,17 @@ export function PackageBuildHeader() {
|
|
|
39
42
|
Report Issue
|
|
40
43
|
</a>
|
|
41
44
|
</Button>
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<DropdownMenuContent
|
|
54
|
-
align="end"
|
|
55
|
-
className="bg-white border-gray-200"
|
|
56
|
-
>
|
|
57
|
-
<DropdownMenuItem className="text-gray-900 hover:bg-gray-100">
|
|
58
|
-
Circuit JSON
|
|
59
|
-
</DropdownMenuItem>
|
|
60
|
-
<DropdownMenuItem className="text-gray-900 hover:bg-gray-100">
|
|
61
|
-
PCB SVG
|
|
62
|
-
</DropdownMenuItem>
|
|
63
|
-
<DropdownMenuItem className="text-gray-900 hover:bg-gray-100">
|
|
64
|
-
Schematic SVG
|
|
65
|
-
</DropdownMenuItem>
|
|
66
|
-
<DropdownMenuItem className="text-gray-900 hover:bg-gray-100">
|
|
67
|
-
3D Model (stl)
|
|
68
|
-
</DropdownMenuItem>
|
|
69
|
-
</DropdownMenuContent>
|
|
70
|
-
</DropdownMenu>
|
|
45
|
+
<Button
|
|
46
|
+
variant="outline"
|
|
47
|
+
size="sm"
|
|
48
|
+
className="border-gray-300 bg-white hover:bg-gray-50 text-xs sm:text-sm"
|
|
49
|
+
>
|
|
50
|
+
<RefreshCw className="w-3 h-3 sm:w-4 sm:h-4 mr-1 sm:mr-2" />
|
|
51
|
+
Rebuild
|
|
52
|
+
</Button>
|
|
53
|
+
<DownloadButtonAndMenu
|
|
54
|
+
snippetUnscopedName={`${author}/${packageName}`}
|
|
55
|
+
/>
|
|
71
56
|
</div>
|
|
72
57
|
</div>
|
|
73
58
|
</div>
|
|
@@ -79,7 +79,7 @@ export default function MainContentHeader({
|
|
|
79
79
|
<DropdownMenuTrigger asChild>
|
|
80
80
|
<Button
|
|
81
81
|
size="sm"
|
|
82
|
-
className="
|
|
82
|
+
className="bg-green-600 hover:bg-green-700 dark:bg-[#238636] dark:hover:bg-[#2ea043] text-white"
|
|
83
83
|
>
|
|
84
84
|
<CodeIcon className="h-4 w-4 mr-1.5" />
|
|
85
85
|
Code
|
|
@@ -76,7 +76,6 @@ export default function PackageHeader({
|
|
|
76
76
|
window.TSCIRCUIT_REGISTRY_API_BASE_URL =
|
|
77
77
|
import.meta.env.VITE_TSCIRCUIT_REGISTRY_API_URL ??
|
|
78
78
|
`${window.location.origin}/api`
|
|
79
|
-
window.TSCIRCUIT_REGISTRY_TOKEN = sessionToken ?? ""
|
|
80
79
|
// TODO: replace with production stripe checkout base url
|
|
81
80
|
window.TSCIRCUIT_STRIPE_CHECKOUT_BASE_URL =
|
|
82
81
|
import.meta.env.VITE_TSCIRCUIT_STRIPE_CHECKOUT_BASE_URL
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useState } from "react"
|
|
2
|
+
import { Button } from "../ui/button"
|
|
3
|
+
import {
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogHeader,
|
|
7
|
+
DialogTitle,
|
|
8
|
+
DialogFooter,
|
|
9
|
+
} from "../ui/dialog"
|
|
10
|
+
import { Label } from "../ui/label"
|
|
11
|
+
import {
|
|
12
|
+
Select,
|
|
13
|
+
SelectContent,
|
|
14
|
+
SelectItem,
|
|
15
|
+
SelectTrigger,
|
|
16
|
+
SelectValue,
|
|
17
|
+
} from "../ui/select"
|
|
18
|
+
import { Checkbox } from "../ui/checkbox"
|
|
19
|
+
import { AnyCircuitElement } from "circuit-json"
|
|
20
|
+
import { createUseDialog } from "./create-use-dialog"
|
|
21
|
+
import {
|
|
22
|
+
downloadPcbSvg,
|
|
23
|
+
DownloadPcbSvgOptions,
|
|
24
|
+
} from "@/lib/download-fns/download-pcb-svg"
|
|
25
|
+
|
|
26
|
+
interface PcbDownloadDialogProps {
|
|
27
|
+
open: boolean
|
|
28
|
+
onOpenChange: (open: boolean) => void
|
|
29
|
+
circuitJson: AnyCircuitElement[]
|
|
30
|
+
fileName: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const PcbDownloadDialog = ({
|
|
34
|
+
open,
|
|
35
|
+
onOpenChange,
|
|
36
|
+
circuitJson,
|
|
37
|
+
fileName,
|
|
38
|
+
}: PcbDownloadDialogProps) => {
|
|
39
|
+
const [layer, setLayer] = useState<"all" | "top" | "bottom">("all")
|
|
40
|
+
const [drawPadding, setDrawPadding] = useState(true)
|
|
41
|
+
const [transparentBg, setTransparentBg] = useState(false)
|
|
42
|
+
const [matchAspectRatio, setMatchAspectRatio] = useState(false)
|
|
43
|
+
|
|
44
|
+
const handleDownload = () => {
|
|
45
|
+
const options: DownloadPcbSvgOptions = {
|
|
46
|
+
layer,
|
|
47
|
+
drawPaddingOutsideBoard: drawPadding,
|
|
48
|
+
backgroundColor: transparentBg ? "transparent" : "#000",
|
|
49
|
+
matchAspectRatio,
|
|
50
|
+
}
|
|
51
|
+
downloadPcbSvg(circuitJson, fileName, options)
|
|
52
|
+
onOpenChange(false)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
57
|
+
<DialogContent>
|
|
58
|
+
<DialogHeader>
|
|
59
|
+
<DialogTitle>Download PCB SVG</DialogTitle>
|
|
60
|
+
</DialogHeader>
|
|
61
|
+
<div className="space-y-4 py-2">
|
|
62
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
63
|
+
<Label htmlFor="layer" className="text-right">
|
|
64
|
+
Layer
|
|
65
|
+
</Label>
|
|
66
|
+
<Select value={layer} onValueChange={(v) => setLayer(v as any)}>
|
|
67
|
+
<SelectTrigger id="layer" className="col-span-3">
|
|
68
|
+
<SelectValue placeholder="Layer" />
|
|
69
|
+
</SelectTrigger>
|
|
70
|
+
<SelectContent className="!z-[999]">
|
|
71
|
+
<SelectItem value="all">All</SelectItem>
|
|
72
|
+
<SelectItem value="top">Top</SelectItem>
|
|
73
|
+
<SelectItem value="bottom">Bottom</SelectItem>
|
|
74
|
+
</SelectContent>
|
|
75
|
+
</Select>
|
|
76
|
+
</div>
|
|
77
|
+
<div className="flex items-center space-x-2">
|
|
78
|
+
<Checkbox
|
|
79
|
+
id="padding"
|
|
80
|
+
checked={drawPadding}
|
|
81
|
+
onCheckedChange={(v) => setDrawPadding(Boolean(v))}
|
|
82
|
+
/>
|
|
83
|
+
<Label htmlFor="padding">Draw Padding and Board Outline</Label>
|
|
84
|
+
</div>
|
|
85
|
+
<div className="flex items-center space-x-2">
|
|
86
|
+
<Checkbox
|
|
87
|
+
id="transparentBg"
|
|
88
|
+
checked={transparentBg}
|
|
89
|
+
onCheckedChange={(v) => setTransparentBg(Boolean(v))}
|
|
90
|
+
/>
|
|
91
|
+
<Label htmlFor="transparentBg">Transparent Background</Label>
|
|
92
|
+
</div>
|
|
93
|
+
<div className="flex items-center space-x-2">
|
|
94
|
+
<Checkbox
|
|
95
|
+
id="matchAspectRatio"
|
|
96
|
+
checked={matchAspectRatio}
|
|
97
|
+
onCheckedChange={(v) => setMatchAspectRatio(Boolean(v))}
|
|
98
|
+
/>
|
|
99
|
+
<Label htmlFor="matchAspectRatio">Match Aspect Ratio</Label>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<DialogFooter>
|
|
103
|
+
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
104
|
+
Cancel
|
|
105
|
+
</Button>
|
|
106
|
+
<Button onClick={handleDownload}>Download</Button>
|
|
107
|
+
</DialogFooter>
|
|
108
|
+
</DialogContent>
|
|
109
|
+
</Dialog>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const usePcbDownloadDialog = createUseDialog(PcbDownloadDialog)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AnyCircuitElement } from "circuit-json"
|
|
2
|
+
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
|
|
3
|
+
import { saveAs } from "file-saver"
|
|
4
|
+
|
|
5
|
+
export interface DownloadPcbSvgOptions {
|
|
6
|
+
layer?: "all" | "top" | "bottom"
|
|
7
|
+
drawPaddingOutsideBoard?: boolean
|
|
8
|
+
backgroundColor?: string
|
|
9
|
+
matchAspectRatio?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const downloadPcbSvg = (
|
|
13
|
+
circuitJson: AnyCircuitElement[],
|
|
14
|
+
fileName: string,
|
|
15
|
+
options: DownloadPcbSvgOptions = {},
|
|
16
|
+
) => {
|
|
17
|
+
const convertOptions: any = {}
|
|
18
|
+
if (options.layer && options.layer !== "all") {
|
|
19
|
+
convertOptions.layer = options.layer
|
|
20
|
+
}
|
|
21
|
+
if (options.matchAspectRatio) {
|
|
22
|
+
convertOptions.matchBoardAspectRatio = true
|
|
23
|
+
}
|
|
24
|
+
if (typeof options.drawPaddingOutsideBoard === "boolean") {
|
|
25
|
+
convertOptions.drawPaddingOutsideBoard = options.drawPaddingOutsideBoard
|
|
26
|
+
}
|
|
27
|
+
if (options.backgroundColor) {
|
|
28
|
+
convertOptions.backgroundColor = options.backgroundColor
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const svg = convertCircuitJsonToPcbSvg(circuitJson, convertOptions)
|
|
32
|
+
|
|
33
|
+
const blob = new Blob([svg], { type: "image/svg+xml" })
|
|
34
|
+
saveAs(blob, fileName + ".svg")
|
|
35
|
+
}
|
package/src/lib/utils/timeAgo.ts
CHANGED
|
@@ -3,7 +3,18 @@ import en from "javascript-time-ago/locale/en"
|
|
|
3
3
|
|
|
4
4
|
TimeAgo.addDefaultLocale(en)
|
|
5
5
|
|
|
6
|
-
export const timeAgo = (
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export const timeAgo = (
|
|
7
|
+
date: Date | string | null | undefined,
|
|
8
|
+
fallback = "???",
|
|
9
|
+
) => {
|
|
10
|
+
if (!date) return fallback
|
|
11
|
+
if (typeof date === "string") {
|
|
12
|
+
date = new Date(date)
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const timeAgo = new TimeAgo("en-US")
|
|
16
|
+
return timeAgo.format(date)
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return fallback
|
|
19
|
+
}
|
|
9
20
|
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { AnyCircuitElement } from "circuit-json"
|
|
2
|
-
import { runTscircuitCode } from "@tscircuit/eval"
|
|
3
|
-
|
|
4
|
-
export const generateCircuitJson = async ({
|
|
5
|
-
code,
|
|
6
|
-
}: {
|
|
7
|
-
code: string
|
|
8
|
-
}): Promise<AnyCircuitElement[]> => {
|
|
9
|
-
return (await runTscircuitCode(code)) as any
|
|
10
|
-
}
|