@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.
Files changed (25) hide show
  1. package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +38 -0
  2. package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +14 -11
  3. package/bun.lock +1 -4
  4. package/dist/bundle.js +20 -8
  5. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +11 -0
  6. package/fake-snippets-api/routes/api/package_releases/get.ts +6 -1
  7. package/fake-snippets-api/routes/api/package_releases/update.ts +4 -1
  8. package/package.json +1 -2
  9. package/src/components/DownloadButtonAndMenu.tsx +26 -8
  10. package/src/components/Header.tsx +7 -7
  11. package/src/components/PackageBuildsPage/ErrorObject.ts +12 -0
  12. package/src/components/PackageBuildsPage/LogContent.tsx +32 -0
  13. package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +62 -4
  14. package/src/components/PackageBuildsPage/build-preview-content.tsx +21 -5
  15. package/src/components/PackageBuildsPage/capitalCase.ts +4 -0
  16. package/src/components/PackageBuildsPage/collapsible-section.tsx +34 -9
  17. package/src/components/PackageBuildsPage/getColorForDisplayStatus.ts +17 -0
  18. package/src/components/PackageBuildsPage/package-build-details-panel.tsx +80 -17
  19. package/src/components/PackageBuildsPage/package-build-header.tsx +15 -30
  20. package/src/components/ViewPackagePage/components/main-content-header.tsx +1 -1
  21. package/src/components/ViewPackagePage/components/package-header.tsx +0 -1
  22. package/src/components/dialogs/pcb-download-dialog.tsx +113 -0
  23. package/src/lib/download-fns/download-pcb-svg.ts +35 -0
  24. package/src/lib/utils/timeAgo.ts +14 -3
  25. 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
- <DropdownMenu>
43
- <DropdownMenuTrigger asChild>
44
- <Button
45
- size="sm"
46
- className="bg-gray-900 text-white hover:bg-gray-800"
47
- >
48
- <Download className="w-4 h-4 mr-2" />
49
- Download
50
- <ChevronDown className="w-4 h-4 ml-2" />
51
- </Button>
52
- </DropdownMenuTrigger>
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="h-9 bg-green-600 hover:bg-green-700 dark:bg-[#238636] dark:hover:bg-[#2ea043] text-white"
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
+ }
@@ -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 = (date: Date) => {
7
- const timeAgo = new TimeAgo("en-US")
8
- return timeAgo.format(date)
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
- }