@tscircuit/fake-snippets 0.0.108 → 0.0.110

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 (203) hide show
  1. package/.github/workflows/bun-formatcheck.yml +2 -2
  2. package/.github/workflows/bun-pver-release.yml +3 -3
  3. package/.github/workflows/bun-test.yml +1 -1
  4. package/.github/workflows/bun-typecheck.yml +2 -2
  5. package/.github/workflows/update-snapshots.yml +1 -1
  6. package/README.md +4 -0
  7. package/api/generated-index.js +37 -3
  8. package/biome.json +2 -1
  9. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +31 -3
  10. package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
  11. package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
  12. package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
  13. package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
  14. package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
  15. package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
  16. package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
  17. package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +99 -0
  18. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
  19. package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
  20. package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
  21. package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
  22. package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
  23. package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
  24. package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
  25. package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
  26. package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
  27. package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
  28. package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
  29. package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
  30. package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
  31. package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
  32. package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
  33. package/bun.lock +389 -450
  34. package/bunfig.toml +2 -1
  35. package/dist/bundle.js +1255 -625
  36. package/dist/index.d.ts +296 -4
  37. package/dist/index.js +325 -24
  38. package/dist/schema.d.ts +282 -1
  39. package/dist/schema.js +54 -2
  40. package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
  41. package/fake-snippets-api/lib/db/db-client.ts +214 -3
  42. package/fake-snippets-api/lib/db/schema.ts +62 -0
  43. package/fake-snippets-api/lib/db/seed.ts +100 -0
  44. package/fake-snippets-api/lib/middleware/with-session-auth.ts +1 -1
  45. package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
  46. package/fake-snippets-api/lib/public-mapping/public-map-org.ts +32 -0
  47. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
  48. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
  49. package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
  50. package/fake-snippets-api/routes/api/orgs/create.ts +46 -0
  51. package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
  52. package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
  53. package/fake-snippets-api/routes/api/orgs/list_members.ts +67 -0
  54. package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
  55. package/fake-snippets-api/routes/api/orgs/update.ts +93 -0
  56. package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
  57. package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
  58. package/fake-snippets-api/routes/api/packages/create.ts +54 -10
  59. package/fake-snippets-api/routes/api/packages/get.ts +23 -0
  60. package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
  61. package/fake-snippets-api/routes/api/packages/list.ts +29 -2
  62. package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
  63. package/package.json +27 -24
  64. package/renovate.json +1 -1
  65. package/scripts/generate-sitemap.ts +1 -1
  66. package/src/App.tsx +29 -10
  67. package/src/ContextProviders.tsx +25 -2
  68. package/src/components/CircuitJsonImportDialog.tsx +1 -1
  69. package/src/components/CmdKMenu.tsx +281 -247
  70. package/src/components/DownloadButtonAndMenu.tsx +133 -36
  71. package/src/components/FileSidebar.tsx +41 -50
  72. package/src/components/Footer.tsx +8 -10
  73. package/src/components/Header.tsx +19 -32
  74. package/src/components/Header2.tsx +16 -32
  75. package/src/components/HeaderDropdown.tsx +13 -8
  76. package/src/components/HeaderLogin.tsx +44 -16
  77. package/src/components/HiddenFilesDropdown.tsx +0 -2
  78. package/src/components/NotFound.tsx +5 -5
  79. package/src/components/PackageBreadcrumb.tsx +6 -12
  80. package/src/components/PackageCard.tsx +0 -1
  81. package/src/components/PackageSearchResults.tsx +1 -1
  82. package/src/components/PrefetchPageLink.tsx +7 -1
  83. package/src/components/ProfileRouter.tsx +32 -0
  84. package/src/components/SearchComponent.tsx +12 -8
  85. package/src/components/UserCard.tsx +80 -0
  86. package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
  87. package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
  88. package/src/components/ViewPackagePage/components/important-files-view.tsx +174 -87
  89. package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -4
  90. package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -2
  91. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -20
  92. package/src/components/ViewPackagePage/components/package-header.tsx +26 -37
  93. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -19
  94. package/src/components/ViewPackagePage/components/repo-page-content.tsx +33 -25
  95. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
  96. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
  97. package/src/components/ViewPackagePage/components/sidebar.tsx +0 -2
  98. package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +18 -17
  99. package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
  100. package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
  101. package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
  102. package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
  103. package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
  104. package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
  105. package/src/components/dialogs/import-component-dialog.tsx +16 -9
  106. package/src/components/dialogs/import-package-dialog.tsx +3 -2
  107. package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
  108. package/src/components/organization/OrganizationCard.tsx +204 -0
  109. package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
  110. package/src/components/organization/OrganizationHeader.tsx +154 -0
  111. package/src/components/organization/OrganizationMembers.tsx +146 -0
  112. package/src/components/package-port/CodeAndPreview.tsx +32 -46
  113. package/src/components/package-port/CodeEditor.tsx +28 -31
  114. package/src/components/package-port/CodeEditorHeader.tsx +128 -63
  115. package/src/components/package-port/EditorNav.tsx +32 -49
  116. package/src/components/preview/ConnectedPackagesList.tsx +8 -8
  117. package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
  118. package/src/components/preview/PackageReleasesDashboard.tsx +53 -36
  119. package/src/components/ui/tree-view.tsx +6 -3
  120. package/src/hooks/use-add-org-member-mutation.ts +51 -0
  121. package/src/hooks/use-create-org-mutation.ts +38 -0
  122. package/src/hooks/use-create-package-mutation.ts +3 -0
  123. package/src/hooks/use-current-package-id.ts +5 -30
  124. package/src/hooks/use-current-package-info.ts +29 -5
  125. package/src/hooks/use-current-package-release.ts +4 -3
  126. package/src/hooks/use-download-zip.ts +2 -2
  127. package/src/hooks/use-global-store.ts +6 -4
  128. package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
  129. package/src/hooks/use-list-org-members.ts +27 -0
  130. package/src/hooks/use-list-user-orgs.ts +25 -0
  131. package/src/hooks/use-org-by-github-handle.ts +26 -0
  132. package/src/hooks/use-org.ts +24 -0
  133. package/src/hooks/use-organization.ts +42 -0
  134. package/src/hooks/use-package-as-snippet.ts +4 -2
  135. package/src/hooks/use-package-builds.ts +6 -2
  136. package/src/hooks/use-package-files.ts +5 -3
  137. package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
  138. package/src/hooks/use-package-release-images.ts +105 -0
  139. package/src/hooks/use-package-release.ts +2 -2
  140. package/src/hooks/use-package-stars.ts +80 -4
  141. package/src/hooks/use-preview-images.ts +6 -3
  142. package/src/hooks/use-remove-org-member-mutation.ts +32 -0
  143. package/src/hooks/use-update-ai-description-mutation.ts +42 -0
  144. package/src/hooks/use-update-org-mutation.ts +41 -0
  145. package/src/hooks/use-warn-user-on-page-change.ts +71 -4
  146. package/src/hooks/useFileManagement.ts +183 -35
  147. package/src/hooks/useOptimizedPackageFilesLoader.ts +136 -0
  148. package/src/hooks/usePackageFilesLoader.ts +2 -2
  149. package/src/hooks/useUpdatePackageFilesMutation.ts +15 -1
  150. package/src/lib/download-fns/download-circuit-png.ts +11 -3
  151. package/src/lib/download-fns/download-gltf-from-circuit-json.ts +44 -0
  152. package/src/lib/download-fns/download-kicad-files.ts +12 -11
  153. package/src/lib/normalize-svg-for-tile.ts +50 -0
  154. package/src/lib/posthog.ts +11 -9
  155. package/src/lib/react-query-api-failure-tracking.ts +148 -0
  156. package/src/lib/sentry.ts +14 -0
  157. package/src/lib/templates/blank-circuit-board-template.ts +0 -4
  158. package/src/lib/ts-lib-cache.ts +122 -7
  159. package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
  160. package/src/lib/utils/findTargetFile.ts +45 -10
  161. package/src/lib/utils/isComponentExported.ts +10 -0
  162. package/src/main.tsx +2 -1
  163. package/src/pages/authorize.tsx +0 -2
  164. package/src/pages/create-organization.tsx +168 -0
  165. package/src/pages/dashboard.tsx +38 -6
  166. package/src/pages/datasheet.tsx +1 -1
  167. package/src/pages/datasheets.tsx +3 -3
  168. package/src/pages/editor.tsx +4 -6
  169. package/src/pages/landing.tsx +6 -7
  170. package/src/pages/latest.tsx +3 -0
  171. package/src/pages/organization-profile.tsx +199 -0
  172. package/src/pages/organization-settings.tsx +566 -0
  173. package/src/pages/package-editor.tsx +21 -21
  174. package/src/pages/preview-release.tsx +76 -136
  175. package/src/pages/quickstart.tsx +159 -123
  176. package/src/pages/release-detail.tsx +119 -31
  177. package/src/pages/search.tsx +192 -57
  178. package/src/pages/settings-redirect.tsx +44 -0
  179. package/src/pages/trending.tsx +29 -20
  180. package/src/pages/user-profile.tsx +58 -7
  181. package/src/pages/view-package.tsx +21 -26
  182. package/vite.config.ts +9 -0
  183. package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
  184. package/src/components/Footer2.tsx +0 -100
  185. package/src/components/JLCPCBImportDialog.tsx +0 -280
  186. package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
  187. package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -115
  188. package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -27
  189. package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
  190. package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
  191. package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
  192. package/src/components/PageSearchComponent.tsx +0 -148
  193. package/src/components/ShippingInformationForm.tsx +0 -423
  194. package/src/components/StaticViewSnippetHeader.tsx +0 -70
  195. package/src/components/ViewPackagePage/components/file-explorer.tsx +0 -67
  196. package/src/components/ViewPackagePage/components/readme-view.tsx +0 -58
  197. package/src/components/ViewPackagePage/components/repo-header-button.tsx +0 -36
  198. package/src/components/ViewPackagePage/components/repo-header.tsx +0 -4
  199. package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +0 -31
  200. package/src/components/ViewSnippetHeader.tsx +0 -181
  201. package/src/components/ui/input-otp.tsx +0 -69
  202. package/src/pages/package-builds.tsx +0 -33
  203. package/src/pages/settings.tsx +0 -25
@@ -1,280 +0,0 @@
1
- import React, { useState } from "react"
2
- import {
3
- Dialog,
4
- DialogContent,
5
- DialogHeader,
6
- DialogTitle,
7
- DialogFooter,
8
- DialogDescription,
9
- } from "@/components/ui/dialog"
10
- import { Button } from "@/components/ui/button"
11
- import { Input } from "@/components/ui/input"
12
- import { useAxios } from "@/hooks/use-axios"
13
- import { useToast } from "@/hooks/use-toast"
14
- import { useLocation } from "wouter"
15
- import { useGlobalStore } from "@/hooks/use-global-store"
16
- import { PrefetchPageLink } from "./PrefetchPageLink"
17
-
18
- interface JLCPCBImportDialogProps {
19
- open: boolean
20
- onOpenChange: (open: boolean) => void
21
- }
22
-
23
- interface ImportState {
24
- isLoading: boolean
25
- error: string | null
26
- existingComponent: {
27
- partNumber: string
28
- username: string
29
- } | null
30
- }
31
-
32
- interface JLCPCBResponse {
33
- ok: boolean
34
- package: {
35
- package_id: string
36
- }
37
- }
38
-
39
- interface APIError {
40
- status: number
41
- data?: {
42
- message?: string
43
- existing_part_number?: string
44
- part_number?: string
45
- error?: {
46
- message?: string
47
- }
48
- }
49
- }
50
-
51
- const extractErrorMessage = (error: APIError): string => {
52
- return (
53
- error?.data?.message ||
54
- error?.data?.error?.message ||
55
- "An unexpected error occurred"
56
- )
57
- }
58
-
59
- const extractExistingPartNumber = (
60
- error: APIError,
61
- fallback: string,
62
- ): string => {
63
- return error?.data?.message || error?.data?.error?.message || fallback
64
- }
65
-
66
- const useJLCPCBImport = () => {
67
- const [state, setState] = useState<ImportState>({
68
- isLoading: false,
69
- error: null,
70
- existingComponent: null,
71
- })
72
-
73
- const axios = useAxios()
74
- const { toast } = useToast()
75
- const [, navigate] = useLocation()
76
- const session = useGlobalStore((s) => s.session)
77
-
78
- const resetState = () => {
79
- setState({
80
- isLoading: false,
81
- error: null,
82
- existingComponent: null,
83
- })
84
- }
85
-
86
- const importComponent = async (partNumber: string) => {
87
- if (!partNumber.startsWith("C") || partNumber.length < 2) {
88
- toast({
89
- title: "Invalid Part Number",
90
- description:
91
- "JLCPCB part numbers should start with 'C' and be at least 2 characters long.",
92
- variant: "destructive",
93
- })
94
- return { success: false }
95
- }
96
-
97
- setState((prev) => ({
98
- ...prev,
99
- isLoading: true,
100
- error: null,
101
- existingComponent: null,
102
- }))
103
-
104
- try {
105
- const response = await axios.post<JLCPCBResponse>(
106
- "/packages/generate_from_jlcpcb",
107
- {
108
- jlcpcb_part_number: partNumber,
109
- },
110
- )
111
-
112
- if (!response.data.ok) {
113
- setState((prev) => ({
114
- ...prev,
115
- isLoading: false,
116
- error: "Failed to generate package from JLCPCB part",
117
- }))
118
- return { success: false }
119
- }
120
-
121
- const { package: generatedPackage } = response.data
122
-
123
- toast({
124
- title: "Import Successful",
125
- description: "JLCPCB component has been imported successfully.",
126
- })
127
-
128
- navigate(`/editor?package_id=${generatedPackage.package_id}`)
129
- return { success: true }
130
- } catch (error: any) {
131
- const apiError = error as APIError
132
-
133
- if (apiError.status === 404) {
134
- setState((prev) => ({
135
- ...prev,
136
- isLoading: false,
137
- error: `Component with JLCPCB part number ${partNumber} not found`,
138
- }))
139
- } else if (apiError.status === 409) {
140
- const existingPartNumber = extractExistingPartNumber(
141
- apiError,
142
- partNumber,
143
- )
144
- setState((prev) => ({
145
- ...prev,
146
- isLoading: false,
147
- existingComponent: {
148
- partNumber: existingPartNumber,
149
- username: session?.github_username || "",
150
- },
151
- }))
152
- } else {
153
- const errorMessage = extractErrorMessage(apiError)
154
- setState((prev) => ({ ...prev, isLoading: false, error: errorMessage }))
155
-
156
- toast({
157
- title: "Import Failed",
158
- description: errorMessage,
159
- variant: "destructive",
160
- })
161
- }
162
-
163
- return { success: false }
164
- }
165
- }
166
-
167
- return {
168
- ...state,
169
- importComponent,
170
- resetState,
171
- }
172
- }
173
-
174
- export function JLCPCBImportDialog({
175
- open,
176
- onOpenChange,
177
- }: JLCPCBImportDialogProps) {
178
- const [partNumber, setPartNumber] = useState("")
179
- const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
180
-
181
- const { isLoading, error, existingComponent, importComponent, resetState } =
182
- useJLCPCBImport()
183
-
184
- const handleImport = async () => {
185
- const result = await importComponent(partNumber)
186
- if (result.success) {
187
- onOpenChange(false)
188
- }
189
- }
190
-
191
- const handleInputChange = (value: string) => {
192
- setPartNumber(value)
193
- resetState()
194
- }
195
-
196
- const createGitHubIssue = () => {
197
- const issueTitle = `[${partNumber}] Failed to import from JLCPCB`
198
- const issueBody = `I tried to import the part number ${partNumber} from JLCPCB, but it failed. Here's the error I got:\n\`\`\`\n${error}\n\`\`\`\n\nCould be an issue in \`fetchEasyEDAComponent\` or \`convertRawEasyEdaToTs\``
199
- const issueLabels = "snippets,good first issue"
200
- const url = `https://github.com/tscircuit/easyeda-converter/issues/new?title=${encodeURIComponent(
201
- issueTitle,
202
- )}&body=${encodeURIComponent(issueBody)}&labels=${encodeURIComponent(issueLabels)}`
203
- window.open(url, "_blank")
204
- }
205
-
206
- return (
207
- <Dialog open={open} onOpenChange={onOpenChange}>
208
- <DialogContent>
209
- <DialogHeader>
210
- <DialogTitle>Import from JLCPCB</DialogTitle>
211
- <DialogDescription>
212
- Enter the JLCPCB part number to import the component.
213
- </DialogDescription>
214
- </DialogHeader>
215
-
216
- <div className="py-4 text-center">
217
- <a
218
- href="https://yaqwsx.github.io/jlcparts/#/"
219
- target="_blank"
220
- rel="noopener noreferrer"
221
- className="text-blue-500 hover:underline opacity-80"
222
- >
223
- JLCPCB Part Search
224
- </a>
225
-
226
- <Input
227
- className="mt-3"
228
- placeholder="Enter JLCPCB part number (e.g., C46749)"
229
- value={partNumber}
230
- disabled={isLoading}
231
- onChange={(e) => handleInputChange(e.target.value)}
232
- onKeyDown={(e) => {
233
- if (
234
- e.key === "Enter" &&
235
- !isLoading &&
236
- isLoggedIn &&
237
- partNumber.trim()
238
- ) {
239
- handleImport()
240
- }
241
- }}
242
- />
243
-
244
- {error && !existingComponent && (
245
- <>
246
- <p className="bg-red-100 p-2 mt-2 pre-wrap">{error}</p>
247
- <div className="flex justify-end mt-2">
248
- <Button variant="default" onClick={createGitHubIssue}>
249
- File Issue on GitHub (prefilled)
250
- </Button>
251
- </div>
252
- </>
253
- )}
254
-
255
- {existingComponent && (
256
- <p className="p-2 mt-2 pre-wrap text-md text-green-600">
257
- This part number has already been imported to your profile.{" "}
258
- <PrefetchPageLink
259
- className="text-blue-500 hover:underline"
260
- href={`/${existingComponent.username}/${existingComponent.partNumber}`}
261
- >
262
- View it here
263
- </PrefetchPageLink>
264
- </p>
265
- )}
266
- </div>
267
-
268
- <DialogFooter>
269
- <Button onClick={handleImport} disabled={isLoading || !isLoggedIn}>
270
- {!isLoggedIn
271
- ? "You must be logged in to import from JLCPCB"
272
- : isLoading
273
- ? "Importing..."
274
- : "Import"}
275
- </Button>
276
- </DialogFooter>
277
- </DialogContent>
278
- </Dialog>
279
- )
280
- }
@@ -1,72 +0,0 @@
1
- type ErrorObject =
2
- | {
3
- message: string
4
- }
5
- | string
6
-
7
- const getErrorText = (error: ErrorObject | string) => {
8
- if (typeof error === "string") {
9
- return error
10
- }
11
- return error.message
12
- }
13
-
14
- export const LogContent = ({
15
- logs,
16
- error,
17
- }: {
18
- logs: Array<{
19
- type?: "info" | "success" | "error"
20
- msg?: string
21
- message?: string
22
- timestamp?: string | number
23
- [key: string]: unknown
24
- }>
25
- error?: ErrorObject | string | null
26
- }) => {
27
- return (
28
- <div className="font-mono text-xs space-y-1 min-w-0">
29
- {logs.map((log, i) => {
30
- const { type, msg, message, timestamp, ...rest } = log
31
- const text = msg ?? message
32
- if (!text) return null
33
-
34
- return (
35
- <div
36
- key={i}
37
- className={`break-words whitespace-pre-wrap ${
38
- type === "error"
39
- ? "text-red-600"
40
- : type === "success"
41
- ? "text-green-600"
42
- : "text-gray-600"
43
- }`}
44
- >
45
- {timestamp !== undefined && (
46
- <span className="text-gray-500 whitespace-nowrap">
47
- {new Date(Number(timestamp)).toLocaleTimeString()}
48
- </span>
49
- )}
50
- {timestamp !== undefined && " "}
51
- <span className="break-all">{text}</span>
52
- {Object.keys(rest).filter((k) => k !== "package_release_id")
53
- .length > 0 && (
54
- <span className="text-gray-500">
55
- {" "}
56
- {Object.entries(rest)
57
- .filter(([key]) => key !== "package_release_id")
58
- .map(([key, value]) => `${key}: ${String(value)}`)
59
- .join(" ")}
60
- </span>
61
- )}
62
- </div>
63
- )
64
- })}
65
- {error && (
66
- <div className="text-red-600 break-words whitespace-pre-wrap">
67
- {getErrorText(error)}
68
- </div>
69
- )}
70
- </div>
71
- )
72
- }
@@ -1,115 +0,0 @@
1
- "use client"
2
-
3
- import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
4
- import { PackageRelease } from "fake-snippets-api/lib/db/schema"
5
- import { useState } from "react"
6
- import { LogContent } from "./LogContent"
7
- import { BuildPreviewContent } from "./build-preview-content"
8
- import { CollapsibleSection } from "./collapsible-section"
9
- import { PackageBuildDetailsPanel } from "./package-build-details-panel"
10
- import { PackageBuildHeader } from "./package-build-header"
11
-
12
- function computeDuration(
13
- startedAt: string | null | undefined,
14
- completedAt: string | null | undefined,
15
- ) {
16
- if (!startedAt || !completedAt) return ""
17
- return `${Math.floor((new Date(completedAt).getTime() - new Date(startedAt).getTime()) / 1000)}s`
18
- }
19
-
20
- export const PackageBuildDetailsPage = () => {
21
- const { packageRelease } = useCurrentPackageRelease({
22
- include_logs: true,
23
- refetchInterval: 2000,
24
- })
25
- const [openSections, setOpenSections] = useState<Record<string, boolean>>({})
26
-
27
- const {
28
- circuit_json_build_logs,
29
- circuit_json_build_completed_at,
30
- circuit_json_build_in_progress,
31
- circuit_json_build_is_stale,
32
- circuit_json_build_started_at,
33
- circuit_json_build_error,
34
- circuit_json_build_error_last_updated_at,
35
- transpilation_completed_at,
36
- transpilation_in_progress,
37
- transpilation_is_stale,
38
- transpilation_logs,
39
- transpilation_started_at,
40
- circuit_json_build_display_status,
41
- transpilation_display_status,
42
- transpilation_error,
43
- } = packageRelease ?? ({} as Partial<PackageRelease>)
44
-
45
- const toggleSection = (section: string) => {
46
- setOpenSections((prev) => ({
47
- ...prev,
48
- [section]: !prev[section],
49
- }))
50
- }
51
-
52
- return (
53
- <div className="min-h-screen bg-gray-50 text-gray-900">
54
- <PackageBuildHeader />
55
-
56
- <div className="px-4 sm:px-6 py-4 sm:py-6 container mx-auto max-w-7xl">
57
- {/* Main Content */}
58
- <div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6 mb-6 sm:mb-8 items-start">
59
- {/* Preview Section */}
60
- <div className="lg:col-span-2">
61
- <div className="bg-white border border-gray-200 rounded-lg p-4 flex items-center justify-center min-h-[280px] sm:min-h-[340px] lg:max-h-[420px]">
62
- <BuildPreviewContent />
63
- </div>
64
- </div>
65
-
66
- {/* Details Panel */}
67
- <PackageBuildDetailsPanel />
68
- </div>
69
-
70
- {/* Collapsible Sections */}
71
- <div className="space-y-4 mb-6 sm:mb-8">
72
- <CollapsibleSection
73
- title="Transpilation Logs"
74
- duration={computeDuration(
75
- transpilation_started_at,
76
- transpilation_completed_at,
77
- )}
78
- displayStatus={transpilation_display_status}
79
- isOpen={openSections.summary}
80
- onToggle={() => toggleSection("summary")}
81
- >
82
- <LogContent
83
- logs={
84
- transpilation_logs ?? [
85
- { msg: "No transpilation logs available" },
86
- ]
87
- }
88
- error={transpilation_error}
89
- />
90
- </CollapsibleSection>
91
-
92
- <CollapsibleSection
93
- title="Circuit JSON Build Logs"
94
- duration={computeDuration(
95
- circuit_json_build_started_at,
96
- circuit_json_build_completed_at,
97
- )}
98
- displayStatus={circuit_json_build_display_status}
99
- isOpen={openSections.logs}
100
- onToggle={() => toggleSection("logs")}
101
- >
102
- <LogContent
103
- logs={
104
- circuit_json_build_logs ?? [
105
- { msg: "No Circuit JSON logs available" },
106
- ]
107
- }
108
- error={circuit_json_build_error!}
109
- />
110
- </CollapsibleSection>
111
- </div>
112
- </div>
113
- </div>
114
- )
115
- }
@@ -1,27 +0,0 @@
1
- import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
2
- import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
3
-
4
- export function BuildPreviewContent() {
5
- const { packageRelease } = useCurrentPackageRelease({ refetchInterval: 2000 })
6
- const { packageInfo } = useCurrentPackageInfo()
7
-
8
- if (!packageRelease) {
9
- return (
10
- <div className="flex items-center justify-center w-full h-full">
11
- <div className="w-32 h-32 sm:w-48 sm:h-48 bg-gray-200 rounded animate-pulse-slow"></div>
12
- </div>
13
- )
14
- }
15
-
16
- return (
17
- <div className="flex items-center justify-center w-full h-full">
18
- <div className="rounded overflow-hidden w-full max-w-full">
19
- <img
20
- src={`https://api.tscircuit.com/packages/images/${packageInfo?.name}/pcb.png`}
21
- alt="Package build preview"
22
- className="object-contain rounded w-full h-auto max-h-[240px] sm:max-h-[300px] lg:max-h-[360px]"
23
- />
24
- </div>
25
- </div>
26
- )
27
- }
@@ -1,63 +0,0 @@
1
- import type React from "react"
2
- import { ChevronRight } from "lucide-react"
3
- import {
4
- Collapsible,
5
- CollapsibleContent,
6
- CollapsibleTrigger,
7
- } from "@/components/ui/collapsible"
8
- import { getColorForDisplayStatus } from "./getColorForDisplayStatus"
9
- import { PackageRelease } from "fake-snippets-api/lib/db/schema"
10
- import { ErrorObjectOrString } from "./ErrorObject"
11
- import { capitalCase } from "./capitalCase"
12
-
13
- interface CollapsibleSectionProps {
14
- title: string
15
- duration?: string
16
- error?: ErrorObjectOrString | null
17
- displayStatus?: PackageRelease["display_status"]
18
- isOpen: boolean
19
- onToggle: () => void
20
- children?: React.ReactNode
21
- }
22
-
23
- export function CollapsibleSection({
24
- title,
25
- duration,
26
- displayStatus,
27
- isOpen,
28
- onToggle,
29
- children,
30
- }: CollapsibleSectionProps) {
31
- return (
32
- <Collapsible open={isOpen} onOpenChange={onToggle}>
33
- <CollapsibleTrigger asChild>
34
- <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 p-4 bg-white border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-100">
35
- <div className="flex items-center gap-2 min-w-0">
36
- <ChevronRight
37
- className={`w-4 h-4 flex-shrink-0 transition-transform ${isOpen ? "rotate-90" : ""}`}
38
- />
39
- <span className="font-medium truncate">{title}</span>
40
- </div>
41
- <div className="flex items-center gap-2 flex-shrink-0 ml-6 sm:ml-0">
42
- {duration && (
43
- <span className="text-sm text-gray-600 whitespace-nowrap">
44
- {duration}
45
- </span>
46
- )}
47
- <div
48
- className={`w-2 h-2 rounded-lg flex-shrink-0 ${getColorForDisplayStatus(displayStatus)}`}
49
- />
50
- <div className="text-gray-600 text-xs font-medium whitespace-nowrap">
51
- {capitalCase(displayStatus) || "???"}
52
- </div>
53
- </div>
54
- </div>
55
- </CollapsibleTrigger>
56
- <CollapsibleContent>
57
- <div className="bg-white border-x border-b border-gray-200 rounded-b-lg overflow-hidden">
58
- <div className="p-4 overflow-x-auto max-w-full">{children}</div>
59
- </div>
60
- </CollapsibleContent>
61
- </Collapsible>
62
- )
63
- }