@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,19 +1,17 @@
1
- import { useState } from "react"
1
+ import { useEffect, useState } from "react"
2
2
  import { useParams } from "wouter"
3
3
  import { Loader2, ChevronLeft, ChevronRight } from "lucide-react"
4
4
  import Header from "@/components/Header"
5
- import { SuspenseRunFrame } from "@/components/SuspenseRunFrame"
6
- import { TreeView } from "@/components/ui/tree-view"
7
- import { transformFilesToTreeData } from "@/lib/utils/transformFilesToTreeData"
8
5
  import { cn } from "@/lib/utils"
9
- import { PrefetchPageLink } from "@/components/PrefetchPageLink"
6
+ import { Link } from "wouter"
10
7
  import NotFoundPage from "./404"
11
8
  import { getBuildStatus } from "@/components/preview"
12
9
  import { usePackageReleaseById } from "@/hooks/use-package-release"
13
- import { usePackageFilesLoader } from "@/hooks/usePackageFilesLoader"
14
10
  import { usePackageBuild } from "@/hooks/use-package-builds"
15
11
  import { PackageBuild } from "fake-snippets-api/lib/db/schema"
16
12
  import { usePackageByName } from "@/hooks/use-package-by-package-name"
13
+ import { RunFrameStaticBuildViewer } from "@tscircuit/runframe/runner"
14
+ import { useApiBaseUrl } from "@/hooks/use-packages-base-api-url"
17
15
 
18
16
  const StatusPill = ({ status }: { status: string }) => {
19
17
  const color =
@@ -27,6 +25,17 @@ const StatusPill = ({ status }: { status: string }) => {
27
25
  return <span className={cn("inline-block w-2 h-2 rounded-full", color)} />
28
26
  }
29
27
 
28
+ const fetchCircuitJson = async (fileRef: {
29
+ filePath: string
30
+ fileStaticAssetUrl: string
31
+ }): Promise<object> => {
32
+ const res = await fetch(String(fileRef.fileStaticAssetUrl))
33
+ const resJson = await res.json()
34
+ const circuitJson = JSON.parse(resJson.package_file.content_text)
35
+ console.log(circuitJson)
36
+ return circuitJson
37
+ }
38
+
30
39
  export default function PreviewBuildPage() {
31
40
  const params = useParams<{
32
41
  packageReleaseId: string
@@ -38,9 +47,8 @@ export default function PreviewBuildPage() {
38
47
  const packageName = params?.packageName || null
39
48
 
40
49
  const [sidebarCollapsed, setSidebarCollapsed] = useState(true)
41
- const [selectedFile, setSelectedFile] = useState<string | null>("index.tsx")
42
- const [selectedItemId, setSelectedItemId] = useState<string>("")
43
50
 
51
+ const apiUrl = useApiBaseUrl()
44
52
  const { data: packageRelease, isLoading: isLoadingRelease } =
45
53
  usePackageReleaseById(packageReleaseId)
46
54
  const { data: pkg, isLoading: isLoadingPackage } = usePackageByName(
@@ -49,12 +57,8 @@ export default function PreviewBuildPage() {
49
57
  const { data: build, isLoading: isLoadingBuild } = usePackageBuild(
50
58
  packageRelease?.latest_package_build_id || null,
51
59
  )
52
- const { data: buildFiles = [], isLoading: isLoadingFiles } =
53
- usePackageFilesLoader(pkg)
54
60
 
55
- const buildFsMap = Object.fromEntries(
56
- buildFiles.map((f) => [f.path, f.content]),
57
- )
61
+ const isLoading = isLoadingRelease || isLoadingPackage || isLoadingBuild
58
62
 
59
63
  if (!packageReleaseId) {
60
64
  return <NotFoundPage heading="Package Release Not Found" />
@@ -63,29 +67,8 @@ export default function PreviewBuildPage() {
63
67
  if (!packageRelease && !isLoadingRelease) {
64
68
  return <NotFoundPage heading="Package Release Not Found" />
65
69
  }
66
- const isLoading =
67
- isLoadingRelease || isLoadingPackage || isLoadingFiles || isLoadingBuild
68
-
69
- if (!build && !isLoading) {
70
- return <NotFoundPage heading="Package Build Not Found" />
71
- }
72
-
73
70
  const { status } = getBuildStatus(build as PackageBuild)
74
71
 
75
- const treeData = transformFilesToTreeData({
76
- files: buildFsMap,
77
- currentFile: selectedFile,
78
- renamingFile: null,
79
- handleRenameFile: () => ({ fileRenamed: false }),
80
- handleDeleteFile: () => ({ fileDeleted: false }),
81
- setRenamingFile: () => {},
82
- onFileSelect: setSelectedFile,
83
- onFolderSelect: () => {},
84
- canModifyFiles: false,
85
- setErrorMessage: () => {},
86
- setSelectedFolderForCreation: () => {},
87
- })
88
-
89
72
  return (
90
73
  <>
91
74
  <Header />
@@ -109,103 +92,66 @@ export default function PreviewBuildPage() {
109
92
  </button>
110
93
 
111
94
  {!sidebarCollapsed && (
112
- <>
113
- <div className="p-4 border-b border-gray-200">
114
- <div className="space-y-3">
115
- <div className="flex items-center justify-between">
116
- <h2 className="text-lg font-semibold text-gray-900">
117
- Deployment
118
- </h2>
119
- <StatusPill status={status} />
120
- </div>
95
+ <div className="p-4">
96
+ <div className="space-y-3">
97
+ <div className="flex items-center justify-between">
98
+ <h2 className="text-lg font-semibold text-gray-900">
99
+ Deployment
100
+ </h2>
101
+ <StatusPill status={status} />
102
+ </div>
121
103
 
122
- <div className="space-y-2">
104
+ <div className="space-y-2">
105
+ <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
106
+ <span className="text-xs text-gray-500 uppercase tracking-wide">
107
+ ID
108
+ </span>
109
+ <Link
110
+ href={`/${pkg?.name}/releases/${build?.package_release_id}`}
111
+ title={build?.package_build_id}
112
+ className="font-mono text-sm truncate text-gray-900 bg-gray-100 w-full px-2 py-1 rounded"
113
+ >
114
+ {build?.package_build_id}
115
+ </Link>
116
+ </div>
117
+ {packageRelease?.commit_message && (
123
118
  <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
124
119
  <span className="text-xs text-gray-500 uppercase tracking-wide">
125
- ID
120
+ Commit
126
121
  </span>
127
- <PrefetchPageLink
128
- href={`/${pkg?.name}/releases/${build?.package_release_id}`}
129
- title={build?.package_build_id}
130
- className="font-mono text-sm truncate text-gray-900 bg-gray-100 w-full px-2 py-1 rounded"
122
+ <a
123
+ title={packageRelease?.commit_message}
124
+ target="_blank"
125
+ rel="noopener noreferrer"
126
+ href={`https://github.com/${pkg?.github_repo_full_name}/commit/${packageRelease?.commit_message}`}
127
+ className="font-mono text-xs text-gray-600 bg-gray-50 px-2 text-right py-1 rounded truncate"
131
128
  >
132
- {build?.package_build_id}
133
- </PrefetchPageLink>
129
+ {packageRelease?.commit_message}
130
+ </a>
134
131
  </div>
135
- {packageRelease?.commit_message && (
136
- <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
137
- <span className="text-xs text-gray-500 uppercase tracking-wide">
138
- Commit
139
- </span>
140
- <a
141
- title={packageRelease?.commit_message}
142
- target="_blank"
143
- rel="noopener noreferrer"
144
- href={`https://github.com/${pkg?.github_repo_full_name}/commit/${packageRelease?.commit_message}`}
145
- className="font-mono text-xs text-gray-600 bg-gray-50 px-2 text-right py-1 rounded truncate"
146
- >
147
- {packageRelease?.commit_message}
148
- </a>
149
- </div>
150
- )}
132
+ )}
151
133
 
152
- <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
153
- <span className="text-xs text-gray-500 uppercase tracking-wide">
154
- Status
155
- </span>
156
- <span
157
- className={`text-xs font-medium px-2 py-1 w-fit rounded-full capitalize ${
158
- status === "success"
159
- ? "bg-emerald-100 text-emerald-800"
160
- : status === "error"
161
- ? "bg-red-100 text-red-800"
162
- : status === "building"
163
- ? "bg-blue-100 text-blue-800"
164
- : "bg-gray-100 text-gray-800"
165
- }`}
166
- >
167
- {status}
168
- </span>
169
- </div>
134
+ <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
135
+ <span className="text-xs text-gray-500 uppercase tracking-wide">
136
+ Status
137
+ </span>
138
+ <span
139
+ className={`text-xs font-medium px-2 py-1 w-fit rounded-full capitalize ${
140
+ status === "success"
141
+ ? "bg-emerald-100 text-emerald-800"
142
+ : status === "error"
143
+ ? "bg-red-100 text-red-800"
144
+ : status === "building"
145
+ ? "bg-blue-100 text-blue-800"
146
+ : "bg-gray-100 text-gray-800"
147
+ }`}
148
+ >
149
+ {status}
150
+ </span>
170
151
  </div>
171
152
  </div>
172
153
  </div>
173
-
174
- <div className="flex-1 overflow-hidden">
175
- <div className="px-4 py-3 border-b border-gray-200">
176
- <h3 className="text-sm font-semibold text-gray-900">
177
- Files
178
- </h3>
179
- <p className="text-xs text-gray-500 mt-1">
180
- {isLoadingFiles
181
- ? "Loading files..."
182
- : `${treeData.length} file${treeData.length !== 1 ? "s" : ""}`}
183
- </p>
184
- </div>
185
- <div className="px-2 py-2 overflow-y-auto select-none">
186
- {isLoadingFiles ? (
187
- <div className="flex items-center justify-center py-8">
188
- <Loader2 className="w-4 h-4 animate-spin" />
189
- <span className="ml-2 text-sm text-gray-500">
190
- Loading files...
191
- </span>
192
- </div>
193
- ) : (
194
- <TreeView
195
- selectedItemId={selectedItemId || ""}
196
- setSelectedItemId={(v) => setSelectedItemId(v || "")}
197
- data={treeData}
198
- className="w-full"
199
- onSelectChange={(item) => {
200
- if (item && !item.children) {
201
- setSelectedFile(item.id)
202
- }
203
- }}
204
- />
205
- )}
206
- </div>
207
- </div>
208
- </>
154
+ </div>
209
155
  )}
210
156
  </aside>
211
157
 
@@ -218,12 +164,15 @@ export default function PreviewBuildPage() {
218
164
  <p>Loading package contents...</p>
219
165
  </div>
220
166
  </div>
221
- ) : status === "success" && buildFiles.length > 0 ? (
222
- <SuspenseRunFrame
223
- fsMap={buildFsMap}
224
- mainComponentPath={selectedFile ?? "index.tsx"}
225
- showRunButton={false}
226
- className="[&>div]:overflow-y-hidden"
167
+ ) : status === "success" ? (
168
+ <RunFrameStaticBuildViewer
169
+ files={[
170
+ {
171
+ filePath: "dist/circuit.json",
172
+ fileStaticAssetUrl: `${apiUrl}/package_files/get?file_path=dist/circuit.json&package_release_id=${build?.package_release_id}`,
173
+ },
174
+ ]}
175
+ onFetchFile={fetchCircuitJson as any}
227
176
  />
228
177
  ) : (
229
178
  <div className="flex-1 flex items-center justify-center">
@@ -238,15 +187,6 @@ export default function PreviewBuildPage() {
238
187
  Build Failed
239
188
  </p>
240
189
  </div>
241
- ) : buildFiles.length === 0 ? (
242
- <div className="text-center">
243
- <p className="text-gray-600 font-medium mb-2">
244
- No files found
245
- </p>
246
- <p className="text-sm text-gray-500">
247
- This package release doesn't have any files to preview.
248
- </p>
249
- </div>
250
190
  ) : (
251
191
  <div className="text-center p-4">
252
192
  <p className="text-gray-600 font-medium mb-2">
@@ -1,5 +1,5 @@
1
- import React, { useState } from "react"
2
- import { useQuery } from "react-query"
1
+ import { useCallback, useEffect, useMemo, useState } from "react"
2
+ import { useQuery, useQueryClient } from "react-query"
3
3
  import { useAxios } from "@/hooks/use-axios"
4
4
  import Header from "@/components/Header"
5
5
  import Footer from "@/components/Footer"
@@ -7,35 +7,64 @@ import { Package } from "fake-snippets-api/lib/db/schema"
7
7
  import { Button } from "@/components/ui/button"
8
8
  import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
9
9
  import { TypeBadge } from "@/components/TypeBadge"
10
- import { JLCPCBImportDialog } from "@/components/JLCPCBImportDialog"
11
10
  import { CircuitJsonImportDialog } from "@/components/CircuitJsonImportDialog"
12
- import { useNotImplementedToast } from "@/hooks/use-toast"
13
11
  import { useGlobalStore } from "@/hooks/use-global-store"
12
+ import { useImportComponentDialog } from "@/components/dialogs/import-component-dialog"
13
+ import { useJlcpcbComponentImport } from "@/hooks/use-jlcpcb-component-import"
14
+ import { JlcpcbComponentTsxLoadedPayload } from "@tscircuit/runframe/runner"
14
15
  import { cn } from "@/lib/utils"
15
- import { PrefetchPageLink } from "@/components/PrefetchPageLink"
16
+ import { Link } from "wouter"
17
+ import { Loader2 } from "lucide-react"
16
18
 
17
19
  export const QuickstartPage = () => {
18
20
  const axios = useAxios()
19
- const [isJLCPCBDialogOpen, setIsJLCPCBDialogOpen] = useState(false)
21
+ const queryClient = useQueryClient()
20
22
  const [isCircuitJsonImportDialogOpen, setIsCircuitJsonImportDialogOpen] =
21
23
  useState(false)
22
- const toastNotImplemented = useNotImplementedToast()
23
- const currentUser = useGlobalStore((s) => s.session?.github_username)
24
+ const session = useGlobalStore((s) => s.session)
25
+ const currentUser = session?.github_username
26
+ const isLoggedIn = Boolean(currentUser)
27
+ const { Dialog: ImportComponentDialog, openDialog: openImportDialog } =
28
+ useImportComponentDialog()
29
+ const { importComponent: importJlcpcbComponent } = useJlcpcbComponentImport()
30
+ const jlcpcbProxyRequestHeaders = useMemo(
31
+ () =>
32
+ session?.token
33
+ ? {
34
+ Authorization: `Bearer ${session.token}`,
35
+ }
36
+ : undefined,
37
+ [session?.token],
38
+ )
39
+ const handleJlcpcbComponentSelected = useCallback(
40
+ async (payload: JlcpcbComponentTsxLoadedPayload) => {
41
+ await importJlcpcbComponent(payload)
42
+ },
43
+ [importJlcpcbComponent],
44
+ )
45
+ useEffect(() => {
46
+ queryClient.removeQueries("userPackages")
47
+ }, [queryClient])
24
48
  const { data: myPackages, isLoading } = useQuery<Package[]>(
25
- "userPackages",
49
+ ["userPackages", currentUser],
26
50
  async () => {
27
51
  const response = await axios.post(`/packages/list`, {
28
52
  owner_github_username: currentUser,
29
53
  })
30
54
  return response.data.packages
31
55
  },
56
+ {
57
+ enabled: isLoggedIn,
58
+ },
32
59
  )
33
60
 
34
- const blankTemplates = [
61
+ const blankTemplates: Array<{
62
+ name: string
63
+ type: string
64
+ disabled?: boolean
65
+ }> = [
35
66
  { name: "Blank Circuit Board", type: "board" },
36
67
  { name: "Blank Circuit Module", type: "package" },
37
- { name: "Blank 3D Model", type: "model", disabled: true },
38
- { name: "Blank Footprint", type: "footprint", disabled: true },
39
68
  ]
40
69
 
41
70
  const templates = [
@@ -44,51 +73,63 @@ export const QuickstartPage = () => {
44
73
  ]
45
74
 
46
75
  return (
47
- <div>
76
+ <div className="min-h-screen">
48
77
  <Header />
49
- <div className="container mx-auto px-4 py-8">
50
- <div className="mb-8 hidden md:block">
51
- <h2 className="text-xl font-semibold mb-4">Recent Packages</h2>
52
- {isLoading ? (
53
- <div>Loading...</div>
54
- ) : (
55
- <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
56
- {myPackages
57
- ?.sort(
58
- (a, b) =>
59
- new Date(b.created_at).getTime() -
60
- new Date(a.created_at).getTime(),
61
- )
62
- .slice(0, 4)
63
- .map((pkg) => (
64
- <PrefetchPageLink
65
- key={pkg.package_id}
66
- href={`/editor?package_id=${pkg.package_id}`}
67
- >
68
- <Card className="hover:shadow-md transition-shadow rounded-md flex flex-col h-full">
69
- <CardHeader className="pb-0 p-4">
70
- <CardTitle className="text-md">
71
- {pkg.unscoped_name}
72
- </CardTitle>
73
- </CardHeader>
74
- <CardContent className="p-4 pt-0 mt-auto">
75
- <p className="text-sm text-gray-500">
76
- Last edited:{" "}
77
- {new Date(pkg.updated_at).toLocaleDateString()}
78
- </p>
79
- </CardContent>
80
- </Card>
81
- </PrefetchPageLink>
82
- ))}
78
+ <div className="container mx-auto px-6 py-12">
79
+ {isLoggedIn && (
80
+ <div className="mb-16 hidden md:block">
81
+ <div className="mb-8">
82
+ <h2 className="text-2xl font-semibold text-slate-900">
83
+ Recent Packages
84
+ </h2>
83
85
  </div>
84
- )}
85
- </div>
86
+ {isLoading ? (
87
+ <div className="flex items-center justify-center py-12">
88
+ <Loader2 className="w-10 h-10 animate-spin text-blue-500 mb-4" />
89
+ </div>
90
+ ) : (
91
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
92
+ {myPackages
93
+ ?.sort(
94
+ (a, b) =>
95
+ new Date(b.created_at).getTime() -
96
+ new Date(a.created_at).getTime(),
97
+ )
98
+ .slice(0, 4)
99
+ .map((pkg) => (
100
+ <Link
101
+ key={pkg.package_id}
102
+ href={`/editor?package_id=${pkg.package_id}`}
103
+ >
104
+ <Card className="hover:shadow-md border bg-white shadow-sm transition-shadow flex flex-col h-full rounded-md">
105
+ <CardHeader>
106
+ <CardTitle className="text-lg font-semibold text-slate-900">
107
+ {pkg.unscoped_name}
108
+ </CardTitle>
109
+ </CardHeader>
110
+ <CardContent className="-mt-4">
111
+ <p className="text-sm text-slate-500">
112
+ Last edited{" "}
113
+ {new Date(pkg.updated_at).toLocaleDateString()}
114
+ </p>
115
+ </CardContent>
116
+ </Card>
117
+ </Link>
118
+ ))}
119
+ </div>
120
+ )}
121
+ </div>
122
+ )}
86
123
 
87
- <div className="mb-8">
88
- <h2 className="text-xl font-semibold mb-4">Start Blank Packages</h2>
89
- <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
124
+ <div className="mb-16">
125
+ <div className="mb-8">
126
+ <h2 className="text-2xl font-semibold text-slate-900">
127
+ Start Blank
128
+ </h2>
129
+ </div>
130
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
90
131
  {blankTemplates.map((template, index) => (
91
- <PrefetchPageLink
132
+ <Link
92
133
  key={index}
93
134
  href={
94
135
  template.disabled
@@ -100,90 +141,81 @@ export const QuickstartPage = () => {
100
141
  >
101
142
  <Card
102
143
  className={cn(
103
- "hover:shadow-md transition-shadow rounded-md h-full flex flex-col",
144
+ "hover:shadow-md border bg-white transition-shadow h-full flex flex-col rounded-md",
104
145
  template.disabled && "opacity-50 cursor-not-allowed",
105
146
  )}
106
147
  >
107
- <CardHeader className="p-4 flex-grow flex flex-col justify-between">
108
- <CardTitle className="text-md">{template.name}</CardTitle>
109
- <div className="mt-2 flex">
110
- <TypeBadge type={template.type as any} />
148
+ <CardHeader className="p-6 flex-grow flex flex-col justify-between">
149
+ <div>
150
+ <CardTitle className="text-lg font-semibold text-slate-900 mb-3">
151
+ {template.name}
152
+ </CardTitle>
153
+ <div className="flex justify-between items-center">
154
+ <TypeBadge type={template.type as any} />
155
+ </div>
111
156
  </div>
112
157
  </CardHeader>
113
158
  </Card>
114
- </PrefetchPageLink>
159
+ </Link>
115
160
  ))}
116
161
  </div>
117
162
  </div>
118
163
 
119
- <div className="mt-12">
120
- <h2 className="text-xl font-semibold mb-4">Import as Package</h2>
121
- <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4">
122
- {/* {[
123
- { name: "KiCad Footprint", type: "footprint" },
124
- { name: "KiCad Project", type: "board" },
125
- { name: "KiCad Module", type: "package" },
126
- ].map((template, index) => (
127
- <Card
128
- key={index}
129
- className="hover:shadow-md transition-shadow rounded-md opacity-50 flex flex-col"
130
- >
131
- <CardHeader className="p-4 pb-0">
132
- <CardTitle className="text-lg flex items-center justify-between">
133
- {template.name}
134
- <TypeBadge type={template.type as any} className="ml-2" />
164
+ <div className="mb-16">
165
+ <div className="mb-8">
166
+ <h2 className="text-2xl font-semibold text-slate-900">
167
+ Import Components
168
+ </h2>
169
+ </div>
170
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
171
+ <Card className="hover:shadow-md border bg-white transition-shadow flex flex-col rounded-md">
172
+ <CardHeader className="p-6 pb-4">
173
+ <div className="flex items-center justify-between mb-2">
174
+ <CardTitle className="text-lg font-semibold text-slate-900">
175
+ JLCPCB Component
135
176
  </CardTitle>
136
- </CardHeader>
137
- <CardContent className="p-4 mt-auto">
138
- <Button
139
- className="w-full"
140
- onClick={() => {
141
- toastNotImplemented("Kicad Imports")
142
- }}
143
- >
144
- Import {template.name}
145
- </Button>
146
- </CardContent>
147
- </Card>
148
- ))} */}
149
- <Card className="hover:shadow-md transition-shadow rounded-md flex flex-col">
150
- <CardHeader className="p-4 pb-0">
151
- <CardTitle className="text-lg flex items-center justify-between">
152
- JLCPCB Component
153
- <TypeBadge type="package" className="ml-2" />
154
- </CardTitle>
177
+ <TypeBadge type="package" />
178
+ </div>
179
+ <p className="text-sm text-slate-500">
180
+ Import components from JLCPCB library
181
+ </p>
155
182
  </CardHeader>
156
- <CardContent className="p-4 mt-auto">
183
+ <CardContent className="p-6 pt-0 mt-auto">
157
184
  <Button
158
- className="w-full"
159
- onClick={() => setIsJLCPCBDialogOpen(true)}
185
+ className="w-full text-white"
186
+ onClick={() => openImportDialog()}
160
187
  >
161
- Import JLCPCB Component
188
+ Import JLCPCB
162
189
  </Button>
163
190
  </CardContent>
164
191
  </Card>
165
- <Card className="hover:shadow-md transition-shadow rounded-md flex flex-col">
166
- <CardHeader className="p-4 pb-0">
167
- <CardTitle className="text-lg flex items-center justify-between">
168
- Circuit Json
169
- <TypeBadge type="package" className="ml-2" />
170
- </CardTitle>
192
+ <Card className="hover:shadow-md border bg-white transition-shadow flex flex-col rounded-md">
193
+ <CardHeader className="p-6 pb-4">
194
+ <div className="flex items-center justify-between mb-2">
195
+ <CardTitle className="text-lg font-semibold text-slate-900">
196
+ Circuit JSON
197
+ </CardTitle>
198
+ <TypeBadge type="package" />
199
+ </div>
200
+ <p className="text-sm text-slate-500">
201
+ Import from Circuit JSON format
202
+ </p>
171
203
  </CardHeader>
172
- <CardContent className="p-4 mt-auto">
204
+ <CardContent className="p-6 pt-0 mt-auto">
173
205
  <Button
174
- className="w-full"
206
+ className="w-full text-white"
175
207
  onClick={() => setIsCircuitJsonImportDialogOpen(true)}
176
208
  >
177
- Import Circuit JSON
209
+ Import JSON
178
210
  </Button>
179
211
  </CardContent>
180
212
  </Card>
181
213
  </div>
182
214
  </div>
183
215
 
184
- <JLCPCBImportDialog
185
- open={isJLCPCBDialogOpen}
186
- onOpenChange={setIsJLCPCBDialogOpen}
216
+ <ImportComponentDialog
217
+ onJlcpcbComponentTsxLoaded={handleJlcpcbComponentSelected}
218
+ jlcpcbProxyRequestHeaders={jlcpcbProxyRequestHeaders}
187
219
  />
188
220
 
189
221
  <CircuitJsonImportDialog
@@ -191,27 +223,31 @@ export const QuickstartPage = () => {
191
223
  onOpenChange={setIsCircuitJsonImportDialogOpen}
192
224
  />
193
225
 
194
- <div>
195
- <h2 className="text-xl font-semibold mb-4 mt-12">
196
- Start from a Template
197
- </h2>
198
- <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
226
+ <div className="mb-16">
227
+ <div className="mb-8">
228
+ <h2 className="text-2xl font-semibold text-slate-900">
229
+ Popular Templates
230
+ </h2>
231
+ </div>
232
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
199
233
  {templates.map((template, index) => (
200
- <PrefetchPageLink
234
+ <Link
201
235
  key={index}
202
236
  href={`/editor?template=${template.name
203
237
  .toLowerCase()
204
238
  .replace(/ /g, "-")}`}
205
239
  >
206
- <Card className="hover:shadow-md transition-shadow rounded-md">
207
- <CardHeader className="p-4">
208
- <CardTitle className="text-lg flex items-center justify-between">
209
- {template.name}
210
- <TypeBadge type={template.type as any} className="ml-2" />
211
- </CardTitle>
240
+ <Card className="hover:shadow-md border bg-white transition-shadow rounded-md">
241
+ <CardHeader className="p-6">
242
+ <div className="flex items-center justify-between ">
243
+ <CardTitle className="text-lg font-semibold text-slate-900">
244
+ {template.name}
245
+ </CardTitle>
246
+ <TypeBadge type={template.type as any} />
247
+ </div>
212
248
  </CardHeader>
213
249
  </Card>
214
- </PrefetchPageLink>
250
+ </Link>
215
251
  ))}
216
252
  </div>
217
253
  </div>