@tscircuit/fake-snippets 0.0.109 → 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 (181) 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 +349 -453
  34. package/bunfig.toml +2 -1
  35. package/dist/bundle.js +1253 -624
  36. package/dist/index.d.ts +291 -4
  37. package/dist/index.js +323 -23
  38. package/dist/schema.d.ts +274 -1
  39. package/dist/schema.js +52 -1
  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 +61 -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 +24 -20
  64. package/renovate.json +1 -1
  65. package/scripts/generate-sitemap.ts +1 -1
  66. package/src/App.tsx +29 -8
  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 +3 -4
  71. package/src/components/FileSidebar.tsx +11 -17
  72. package/src/components/Footer.tsx +8 -9
  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 +43 -15
  77. package/src/components/NotFound.tsx +5 -5
  78. package/src/components/PackageBreadcrumb.tsx +6 -12
  79. package/src/components/PackageSearchResults.tsx +1 -1
  80. package/src/components/PrefetchPageLink.tsx +7 -1
  81. package/src/components/ProfileRouter.tsx +32 -0
  82. package/src/components/SearchComponent.tsx +12 -8
  83. package/src/components/UserCard.tsx +80 -0
  84. package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
  85. package/src/components/ViewPackagePage/components/important-files-view.tsx +105 -34
  86. package/src/components/ViewPackagePage/components/main-content-header.tsx +10 -6
  87. package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -1
  88. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -19
  89. package/src/components/ViewPackagePage/components/package-header.tsx +25 -33
  90. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -18
  91. package/src/components/ViewPackagePage/components/repo-page-content.tsx +12 -5
  92. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
  93. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
  94. package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
  95. package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
  96. package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
  97. package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
  98. package/src/components/dialogs/import-component-dialog.tsx +16 -9
  99. package/src/components/dialogs/import-package-dialog.tsx +3 -2
  100. package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
  101. package/src/components/organization/OrganizationCard.tsx +204 -0
  102. package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
  103. package/src/components/organization/OrganizationHeader.tsx +154 -0
  104. package/src/components/organization/OrganizationMembers.tsx +146 -0
  105. package/src/components/package-port/CodeAndPreview.tsx +15 -12
  106. package/src/components/package-port/CodeEditor.tsx +4 -30
  107. package/src/components/package-port/CodeEditorHeader.tsx +123 -61
  108. package/src/components/package-port/EditorNav.tsx +32 -49
  109. package/src/components/preview/ConnectedPackagesList.tsx +8 -8
  110. package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
  111. package/src/components/preview/PackageReleasesDashboard.tsx +23 -11
  112. package/src/components/ui/tree-view.tsx +6 -3
  113. package/src/hooks/use-add-org-member-mutation.ts +51 -0
  114. package/src/hooks/use-create-org-mutation.ts +38 -0
  115. package/src/hooks/use-create-package-mutation.ts +3 -0
  116. package/src/hooks/use-current-package-release.ts +4 -3
  117. package/src/hooks/use-download-zip.ts +2 -2
  118. package/src/hooks/use-global-store.ts +6 -4
  119. package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
  120. package/src/hooks/use-list-org-members.ts +27 -0
  121. package/src/hooks/use-list-user-orgs.ts +25 -0
  122. package/src/hooks/use-org-by-github-handle.ts +26 -0
  123. package/src/hooks/use-org.ts +24 -0
  124. package/src/hooks/use-organization.ts +42 -0
  125. package/src/hooks/use-package-as-snippet.ts +4 -2
  126. package/src/hooks/use-package-builds.ts +6 -2
  127. package/src/hooks/use-package-files.ts +5 -3
  128. package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
  129. package/src/hooks/use-package-release-images.ts +105 -0
  130. package/src/hooks/use-package-release.ts +2 -2
  131. package/src/hooks/use-package-stars.ts +80 -4
  132. package/src/hooks/use-preview-images.ts +6 -3
  133. package/src/hooks/use-remove-org-member-mutation.ts +32 -0
  134. package/src/hooks/use-update-ai-description-mutation.ts +42 -0
  135. package/src/hooks/use-update-org-mutation.ts +41 -0
  136. package/src/hooks/use-warn-user-on-page-change.ts +71 -4
  137. package/src/hooks/useFileManagement.ts +51 -22
  138. package/src/hooks/useOptimizedPackageFilesLoader.ts +11 -24
  139. package/src/hooks/usePackageFilesLoader.ts +2 -2
  140. package/src/hooks/useUpdatePackageFilesMutation.ts +13 -1
  141. package/src/lib/download-fns/download-gltf-from-circuit-json.ts +1 -1
  142. package/src/lib/download-fns/download-kicad-files.ts +12 -11
  143. package/src/lib/normalize-svg-for-tile.ts +50 -0
  144. package/src/lib/posthog.ts +11 -9
  145. package/src/lib/react-query-api-failure-tracking.ts +148 -0
  146. package/src/lib/sentry.ts +14 -0
  147. package/src/lib/templates/blank-circuit-board-template.ts +0 -4
  148. package/src/lib/ts-lib-cache.ts +122 -7
  149. package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
  150. package/src/lib/utils/findTargetFile.ts +45 -10
  151. package/src/lib/utils/isComponentExported.ts +2 -1
  152. package/src/main.tsx +2 -1
  153. package/src/pages/create-organization.tsx +168 -0
  154. package/src/pages/dashboard.tsx +38 -6
  155. package/src/pages/datasheet.tsx +1 -1
  156. package/src/pages/datasheets.tsx +3 -3
  157. package/src/pages/editor.tsx +4 -6
  158. package/src/pages/landing.tsx +6 -6
  159. package/src/pages/latest.tsx +3 -0
  160. package/src/pages/organization-profile.tsx +199 -0
  161. package/src/pages/organization-settings.tsx +566 -0
  162. package/src/pages/package-editor.tsx +21 -21
  163. package/src/pages/preview-release.tsx +75 -145
  164. package/src/pages/quickstart.tsx +159 -123
  165. package/src/pages/release-detail.tsx +119 -31
  166. package/src/pages/search.tsx +192 -57
  167. package/src/pages/settings-redirect.tsx +44 -0
  168. package/src/pages/trending.tsx +29 -20
  169. package/src/pages/user-profile.tsx +58 -7
  170. package/src/pages/view-package.tsx +7 -13
  171. package/vite.config.ts +9 -0
  172. package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
  173. package/src/components/JLCPCBImportDialog.tsx +0 -280
  174. package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
  175. package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -113
  176. package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -56
  177. package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
  178. package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
  179. package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
  180. package/src/components/PageSearchComponent.tsx +0 -148
  181. package/src/pages/package-builds.tsx +0 -33
@@ -12,7 +12,7 @@ import { Lock, Globe } from "lucide-react"
12
12
  import { GitFork, Package, Star } from "lucide-react"
13
13
 
14
14
  import { useForkPackageMutation } from "@/hooks/use-fork-package-mutation"
15
- import { usePackageStarMutationByName } from "@/hooks/use-package-stars"
15
+ import { usePackageStarringByName } from "@/hooks/use-package-stars"
16
16
  import { useOrderDialog } from "@tscircuit/runframe"
17
17
  import { useGlobalStore } from "@/hooks/use-global-store"
18
18
  import { Package as PackageType } from "fake-snippets-api/lib/db/schema"
@@ -29,7 +29,7 @@ export default function PackageHeader({
29
29
  isPrivate = false,
30
30
  isCurrentUserAuthor = false,
31
31
  }: PackageHeaderProps) {
32
- const author = packageInfo?.owner_github_username
32
+ const accountName = packageInfo?.owner_github_username
33
33
  const packageName = packageInfo?.unscoped_name
34
34
  const sessionToken = useGlobalStore((s) => s.session?.token)
35
35
  const isOwner =
@@ -43,8 +43,8 @@ export default function PackageHeader({
43
43
  packageReleaseId: packageInfo?.latest_package_release_id ?? "",
44
44
  })
45
45
 
46
- const { addStar, removeStar } = usePackageStarMutationByName(
47
- packageInfo?.name ?? "",
46
+ const { isStarred, starCount, toggleStar } = usePackageStarringByName(
47
+ packageInfo?.name ?? null,
48
48
  )
49
49
 
50
50
  const { mutateAsync: forkPackage, isLoading: isForkLoading } =
@@ -52,12 +52,7 @@ export default function PackageHeader({
52
52
 
53
53
  const handleStarClick = async () => {
54
54
  if (!packageInfo?.name || !isLoggedIn) return
55
-
56
- if (packageInfo?.is_starred) {
57
- await removeStar.mutateAsync()
58
- } else {
59
- await addStar.mutateAsync()
60
- }
55
+ await toggleStar()
61
56
  }
62
57
 
63
58
  const handleForkClick = async () => {
@@ -65,8 +60,6 @@ export default function PackageHeader({
65
60
  await forkPackage(packageInfo.package_id)
66
61
  }
67
62
 
68
- const isStarLoading = addStar.isLoading || removeStar.isLoading
69
-
70
63
  useEffect(() => {
71
64
  window.TSCIRCUIT_REGISTRY_API_BASE_URL =
72
65
  import.meta.env.VITE_TSCIRCUIT_REGISTRY_API_URL ??
@@ -81,18 +74,18 @@ export default function PackageHeader({
81
74
  <div className="max-w-[1200px] mx-auto px-4">
82
75
  <div className="flex items-center justify-between flex-wrap gap-y-2">
83
76
  <div className="flex items-center min-w-0 flex-wrap">
84
- {author && packageName ? (
77
+ {accountName && packageName ? (
85
78
  <>
86
79
  <h1 className="text-lg md:text-xl font-bold mr-2 break-words">
87
80
  <Link
88
- href={`/${author}`}
81
+ href={`/${accountName}`}
89
82
  className="text-blue-600 hover:underline"
90
83
  >
91
- {author}
84
+ {accountName}
92
85
  </Link>
93
86
  <span className="px-1 text-gray-500">/</span>
94
87
  <Link
95
- href={`/${author}/${packageName}`}
88
+ href={`/${accountName}/${packageName}`}
96
89
  className="text-blue-600 hover:underline"
97
90
  >
98
91
  {packageName}
@@ -126,7 +119,12 @@ export default function PackageHeader({
126
119
  </div>
127
120
 
128
121
  <div className="hidden md:flex items-center space-x-2">
129
- <Button variant="outline" size="sm" onClick={open}>
122
+ <Button
123
+ variant="outline"
124
+ size="sm"
125
+ onClick={open}
126
+ disabled={!packageInfo?.latest_package_release_id}
127
+ >
130
128
  <Package className="w-4 h-4 mr-2" />
131
129
  Order
132
130
  </Button>
@@ -144,21 +142,17 @@ export default function PackageHeader({
144
142
  : ""
145
143
  }
146
144
  onClick={handleStarClick}
147
- disabled={
148
- isStarLoading || !packageInfo?.name || !isLoggedIn
149
- }
145
+ disabled={!packageInfo?.name || !isLoggedIn}
150
146
  >
151
147
  <Star
152
148
  className={`w-4 h-4 mr-2 ${
153
- packageInfo?.is_starred
154
- ? "fill-yellow-500 text-yellow-500"
155
- : ""
149
+ isStarred ? "fill-yellow-500 text-yellow-500" : ""
156
150
  }`}
157
151
  />
158
- {packageInfo?.is_starred ? "Starred" : "Star"}
159
- {(packageInfo?.star_count ?? 0) > 0 && (
152
+ {isStarred ? "Starred" : "Star"}
153
+ {(starCount ?? 0) > 0 && (
160
154
  <span className="ml-1.5 bg-gray-100 text-gray-700 rounded-full px-1.5 py-0.5 text-xs font-medium">
161
- {packageInfo?.star_count}
155
+ {starCount}
162
156
  </span>
163
157
  )}
164
158
  </Button>
@@ -220,19 +214,17 @@ export default function PackageHeader({
220
214
  : ""
221
215
  }
222
216
  onClick={handleStarClick}
223
- disabled={isStarLoading || !packageInfo?.name}
217
+ disabled={!packageInfo?.name || !isLoggedIn}
224
218
  >
225
219
  <Star
226
220
  className={`w-4 h-4 mr-2 ${
227
- packageInfo?.is_starred
228
- ? "fill-yellow-500 text-yellow-500"
229
- : ""
221
+ isStarred ? "fill-yellow-500 text-yellow-500" : ""
230
222
  }`}
231
223
  />
232
- {packageInfo?.is_starred ? "Starred" : "Star"}
233
- {(packageInfo?.star_count ?? 0) > 0 && (
224
+ {isStarred ? "Starred" : "Star"}
225
+ {(starCount ?? 0) > 0 && (
234
226
  <span className="ml-1.5 bg-gray-100 text-gray-700 rounded-full px-1.5 py-0.5 text-xs font-medium">
235
- {packageInfo?.star_count}
227
+ {starCount}
236
228
  </span>
237
229
  )}
238
230
  </Button>
@@ -1,9 +1,11 @@
1
- import { Skeleton } from "@/components/ui/skeleton"
2
1
  import { usePreviewImages } from "@/hooks/use-preview-images"
3
2
  import type { Package } from "fake-snippets-api/lib/db/schema"
4
3
 
5
4
  interface ViewPlaceholdersProps {
6
- packageInfo?: Pick<Package, "name" | "latest_package_release_fs_sha">
5
+ packageInfo?: Pick<
6
+ Package,
7
+ "name" | "latest_package_release_fs_sha" | "latest_package_release_id"
8
+ >
7
9
  onViewChange?: (view: "3d" | "pcb" | "schematic") => void
8
10
  }
9
11
 
@@ -15,7 +17,6 @@ export default function PreviewImageSquares({
15
17
  packageName: packageInfo?.name,
16
18
  fsMapHash: packageInfo?.latest_package_release_fs_sha ?? "",
17
19
  })
18
-
19
20
  const handleViewClick = (viewId: string) => {
20
21
  onViewChange?.(viewId as "3d" | "pcb" | "schematic")
21
22
  }
@@ -25,24 +26,16 @@ export default function PreviewImageSquares({
25
26
  {availableViews.map((view) => (
26
27
  <button
27
28
  key={view.id}
28
- className={`aspect-square bg-gray-100 dark:bg-[#161b22] rounded-lg border border-gray-200 dark:border-[#30363d] hover:bg-gray-200 dark:hover:bg-[#21262d] flex items-center justify-center transition-colors overflow-hidden mb-6`}
29
+ className={`aspect-square ${view.status == "loading" ? "bg-slate-900/10 animate-pulse" : (view.backgroundClass ?? "bg-gray-100")} rounded-lg border border-gray-200 dark:border-[#30363d] flex items-center justify-center transition-colors overflow-hidden mb-6`}
29
30
  onClick={() => handleViewClick(view.id)}
30
31
  >
31
32
  {view.imageUrl && (
32
- <>
33
- {view.status === "loading" && (
34
- <Skeleton className="w-full h-full rounded-lg" />
35
- )}
36
- <img
37
- src={view.imageUrl}
38
- alt={view.label}
39
- className={`w-full h-full object-cover rounded-lg ${
40
- view.status === "loaded" ? "block" : "hidden"
41
- }`}
42
- onLoad={view.onLoad}
43
- onError={view.onError}
44
- />
45
- </>
33
+ <img
34
+ src={view.imageUrl}
35
+ className="w-full h-full object-cover rounded-lg"
36
+ onLoad={view.onLoad}
37
+ onError={view.onError}
38
+ />
46
39
  )}
47
40
  </button>
48
41
  ))}
@@ -18,12 +18,12 @@ import Header from "@/components/Header"
18
18
  import Footer from "@/components/Footer"
19
19
  import PackageHeader from "./package-header"
20
20
  import { useGlobalStore } from "@/hooks/use-global-store"
21
- import { useLocation } from "wouter"
22
21
  import type {
23
22
  Package,
24
23
  PackageFile as ApiPackageFile,
25
24
  } from "fake-snippets-api/lib/db/schema"
26
25
  import { useRequestAiReviewMutation } from "@/hooks/use-request-ai-review-mutation"
26
+ import { useUpdateAiDescriptionMutation } from "@/hooks/use-update-ai-description-mutation"
27
27
  import { useAiReview } from "@/hooks/use-ai-review"
28
28
  import { useQueryClient } from "react-query"
29
29
  import SidebarReleasesSection from "./sidebar-releases-section"
@@ -81,6 +81,9 @@ export default function RepoPageContent({
81
81
  },
82
82
  })
83
83
 
84
+ const { mutate: updateAiDescription, isLoading: isUpdatingAiDescription } =
85
+ useUpdateAiDescriptionMutation()
86
+
84
87
  const aiReviewRequested =
85
88
  Boolean(packageRelease?.ai_review_requested) ||
86
89
  Boolean(pendingAiReviewId) ||
@@ -212,15 +215,12 @@ export default function RepoPageContent({
212
215
 
213
216
  {/* Dynamic Content based on active view */}
214
217
  {renderContent()}
215
-
216
218
  {/* Important Files View - Always shown */}
217
219
  <ImportantFilesView
218
220
  importantFiles={importantFiles}
219
221
  isFetched={arePackageFilesFetched}
222
+ pkg={packageInfo}
220
223
  onEditClicked={onEditClicked}
221
- packageAuthorOwner={packageInfo?.owner_github_username}
222
- aiDescription={packageInfo?.ai_description ?? ""}
223
- aiUsageInstructions={packageInfo?.ai_usage_instructions ?? ""}
224
224
  aiReviewText={packageRelease?.ai_review_text ?? null}
225
225
  aiReviewRequested={aiReviewRequested}
226
226
  onRequestAiReview={() => {
@@ -230,6 +230,13 @@ export default function RepoPageContent({
230
230
  })
231
231
  }
232
232
  }}
233
+ onRequestAiDescriptionUpdate={() => {
234
+ if (packageInfo) {
235
+ updateAiDescription({
236
+ package_id: packageInfo.package_id,
237
+ })
238
+ }
239
+ }}
233
240
  onLicenseFileRequested={licenseFileRequested}
234
241
  />
235
242
  </div>
@@ -2,12 +2,12 @@ import { Badge } from "@/components/ui/badge"
2
2
  import { GitFork, Star, Settings, LinkIcon, Github, Plus } from "lucide-react"
3
3
  import { Skeleton } from "@/components/ui/skeleton"
4
4
  import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
5
- import { usePackageReleaseById } from "@/hooks/use-package-release"
5
+ import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
6
6
  import { useGlobalStore } from "@/hooks/use-global-store"
7
7
  import { Button } from "@/components/ui/button"
8
8
  import { useEditPackageDetailsDialog } from "@/components/dialogs/edit-package-details-dialog"
9
9
  import { useState, useEffect, useMemo } from "react"
10
- import { usePackageFile } from "@/hooks/use-package-files"
10
+ import { usePackageFileById, usePackageFiles } from "@/hooks/use-package-files"
11
11
  import { getLicenseFromLicenseContent } from "@/lib/getLicenseFromLicenseContent"
12
12
  import { PackageInfo } from "@/lib/types"
13
13
 
@@ -21,23 +21,29 @@ export default function SidebarAboutSection({
21
21
  onLicenseClick,
22
22
  }: SidebarAboutSectionProps = {}) {
23
23
  const { packageInfo, refetch: refetchPackageInfo } = useCurrentPackageInfo()
24
- const { data: packageRelease } = usePackageReleaseById(
24
+ const { packageRelease } = useCurrentPackageRelease({
25
+ include_ai_review: true,
26
+ })
27
+
28
+ const { data: releaseFiles } = usePackageFiles(
25
29
  packageInfo?.latest_package_release_id,
26
30
  )
27
-
28
- const { data: licenseFileMeta, refetch: refetchLicense } = usePackageFile({
29
- package_release_id: packageInfo?.latest_package_release_id ?? "",
30
- file_path: "LICENSE",
31
- })
31
+ const licenseFileId = useMemo(() => {
32
+ return (
33
+ releaseFiles?.find((f) => f.file_path === "LICENSE")?.package_file_id ||
34
+ null
35
+ )
36
+ }, [releaseFiles])
37
+ const { data: licenseFileMeta } = usePackageFileById(licenseFileId)
32
38
  const currentLicense = useMemo(() => {
33
39
  if (packageInfo?.latest_license) {
34
40
  return packageInfo?.latest_license
35
41
  }
36
42
  if (licenseFileMeta?.content_text) {
37
- return getLicenseFromLicenseContent(licenseFileMeta?.content_text)
43
+ return getLicenseFromLicenseContent(licenseFileMeta.content_text)
38
44
  }
39
45
  return null
40
- }, [licenseFileMeta])
46
+ }, [licenseFileMeta, packageInfo?.latest_license])
41
47
  const topics = packageInfo?.is_package ? ["Package"] : ["Board"]
42
48
  const isLoading = !packageInfo || !packageRelease
43
49
  const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
@@ -1,12 +1,12 @@
1
1
  import { Tag, Clock } from "lucide-react"
2
2
  import { Skeleton } from "@/components/ui/skeleton"
3
3
  import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
4
- import { usePackageReleaseById } from "@/hooks/use-package-release"
4
+ import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
5
5
  import { timeAgo } from "@/lib/utils/timeAgo"
6
6
  import { BuildStatus, BuildStep } from "./build-status"
7
7
  import type { PackageRelease } from "fake-snippets-api/lib/db/schema"
8
8
  import { getBuildStatus, StatusIcon } from "@/components/preview"
9
- import { PrefetchPageLink } from "@/components/PrefetchPageLink"
9
+ import { Link } from "wouter"
10
10
  import { usePackageBuild } from "@/hooks/use-package-builds"
11
11
 
12
12
  function getTranspilationStatus(
@@ -39,9 +39,9 @@ function getCircuitJsonStatus(pr?: PackageRelease | null): BuildStep["status"] {
39
39
 
40
40
  export default function SidebarReleasesSection() {
41
41
  const { packageInfo } = useCurrentPackageInfo()
42
- const { data: packageRelease } = usePackageReleaseById(
43
- packageInfo?.latest_package_release_id,
44
- )
42
+ const { packageRelease } = useCurrentPackageRelease({
43
+ include_ai_review: true,
44
+ })
45
45
  const { data: latestBuild } = usePackageBuild(
46
46
  packageRelease?.latest_package_build_id ?? null,
47
47
  )
@@ -80,21 +80,21 @@ export default function SidebarReleasesSection() {
80
80
  return (
81
81
  <div className="mb-6">
82
82
  <h2 className="text-lg font-semibold mb-2">
83
- <PrefetchPageLink
83
+ <Link
84
84
  href={`/${packageInfo?.owner_github_username}/${packageInfo?.unscoped_name}/releases`}
85
85
  className="hover:underline"
86
86
  >
87
87
  Releases
88
- </PrefetchPageLink>
88
+ </Link>
89
89
  </h2>
90
90
  <div className="flex flex-col space-y-2">
91
- <PrefetchPageLink
91
+ <Link
92
92
  href={`/${packageInfo?.owner_github_username}/${packageInfo?.unscoped_name}/releases`}
93
93
  className="flex items-center hover:underline"
94
94
  >
95
95
  <Tag className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
96
96
  <span className="text-sm font-medium">v{packageRelease.version}</span>
97
- </PrefetchPageLink>
97
+ </Link>
98
98
  <div className="flex items-center">
99
99
  <Clock className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
100
100
  <span className="text-sm text-gray-500 dark:text-[#8b949e]">
@@ -109,13 +109,13 @@ export default function SidebarReleasesSection() {
109
109
  />
110
110
  ))}
111
111
  {latestBuild && (
112
- <PrefetchPageLink
112
+ <Link
113
113
  href={`/${packageInfo?.name}/releases`}
114
114
  className="flex items-center gap-2 text-sm text-gray-500 dark:text-[#8b949e]"
115
115
  >
116
116
  <StatusIcon status={status} />
117
117
  <span>Package Preview {label}</span>
118
- </PrefetchPageLink>
118
+ </Link>
119
119
  )}
120
120
  </div>
121
121
  {/* <a href="#" className="text-blue-600 dark:text-[#58a6ff] hover:underline text-sm">
@@ -1,6 +1,4 @@
1
- import { usePackageFile, usePackageFileByPath } from "@/hooks/use-package-files"
2
1
  import { PcbViewerWithContainerHeight } from "@/components/PcbViewerWithContainerHeight"
3
- import { useEffect, useState } from "react"
4
2
  import { useCurrentPackageCircuitJson } from "../../hooks/use-current-package-circuit-json"
5
3
 
6
4
  export default function PCBView() {
@@ -27,6 +25,7 @@ export default function PCBView() {
27
25
  return (
28
26
  <div className="border border-gray-200 dark:border-[#30363d] rounded-md p-4 mb-4 bg-white dark:bg-[#0d1117]">
29
27
  <PcbViewerWithContainerHeight
28
+ disablePcbGroups
30
29
  clickToInteractEnabled
31
30
  circuitJson={circuitJson}
32
31
  containerClassName="w-full h-[620px]"
@@ -1,5 +1,5 @@
1
1
  import { useCurrentPackageCircuitJson } from "../../hooks/use-current-package-circuit-json"
2
- import { SchematicViewer } from "@tscircuit/runframe"
2
+ import { SchematicViewer } from "@tscircuit/schematic-viewer"
3
3
 
4
4
  export default function SchematicView() {
5
5
  const { circuitJson, isLoading, error } = useCurrentPackageCircuitJson()
@@ -26,6 +26,7 @@ export default function SchematicView() {
26
26
  return (
27
27
  <div className="h-[620px]">
28
28
  <SchematicViewer
29
+ disableGroups
29
30
  clickToInteractEnabled
30
31
  circuitJson={circuitJson}
31
32
  containerStyle={{
@@ -6,6 +6,7 @@ import {
6
6
  CommandGroup,
7
7
  CommandInput,
8
8
  CommandItem,
9
+ CommandList,
9
10
  } from "@/components/ui/command"
10
11
  import {
11
12
  Popover,
@@ -203,63 +204,69 @@ export const GitHubRepositorySelector = ({
203
204
  <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
204
205
  </Button>
205
206
  </PopoverTrigger>
206
- <PopoverContent className="w-full p-0 z-[999]">
207
+ <PopoverContent
208
+ className="w-[var(--radix-popover-trigger-width)] p-0 z-[999]"
209
+ align="start"
210
+ >
207
211
  <Command shouldFilter={false}>
208
212
  <CommandInput
209
213
  value={searchValue}
210
214
  onValueChange={setSearchValue}
211
215
  placeholder="Search repositories..."
212
216
  />
213
- <CommandEmpty className="text-sm text-slate-500 py-6">
214
- No repositories found.
215
- </CommandEmpty>
216
- <CommandGroup className="max-h-[400px] overflow-y-auto">
217
- {filteredOptions.map((option) => (
218
- <CommandItem
219
- key={option.value}
220
- onSelect={() => handleComboboxSelect(option.value)}
221
- className="cursor-pointer"
222
- >
223
- <div className="flex items-center space-x-2 w-full">
224
- {option.type === "repo" ? (
225
- <>
226
- <Check
227
- className={cn(
228
- "mr-2 h-4 w-4",
229
- selectedRepository === option.value
230
- ? "opacity-100"
231
- : "opacity-0",
217
+ <CommandList className="max-h-[400px] overflow-y-auto">
218
+ <CommandEmpty className="text-sm text-slate-500 py-6 pl-4">
219
+ No repositories found.
220
+ </CommandEmpty>
221
+ <CommandGroup>
222
+ {filteredOptions.map((option) => (
223
+ <CommandItem
224
+ key={option.value}
225
+ value={option.value}
226
+ onSelect={() => handleComboboxSelect(option.value)}
227
+ className="cursor-pointer hover:bg-slate-100"
228
+ >
229
+ <div className="flex items-center space-x-2 w-full">
230
+ {option.type === "repo" ? (
231
+ <>
232
+ <Check
233
+ className={cn(
234
+ "mr-2 h-4 w-4",
235
+ selectedRepository === option.value
236
+ ? "opacity-100"
237
+ : "opacity-0",
238
+ )}
239
+ />
240
+ <span>{option.label}</span>
241
+ {option.isPrivate && (
242
+ <span className="text-xs text-muted-foreground">
243
+ (private)
244
+ </span>
245
+ )}
246
+ </>
247
+ ) : (
248
+ <>
249
+ {option.icon === "plus" ? (
250
+ <Plus className="w-3 h-3 text-blue-600" />
251
+ ) : (
252
+ <Minus className="w-3 h-3 text-red-600" />
232
253
  )}
233
- />
234
- <span>{option.label}</span>
235
- {option.isPrivate && (
236
- <span className="text-xs text-muted-foreground">
237
- (private)
254
+ <span
255
+ className={
256
+ option.icon === "plus"
257
+ ? "text-blue-600"
258
+ : "text-red-600"
259
+ }
260
+ >
261
+ {option.label}
238
262
  </span>
239
- )}
240
- </>
241
- ) : (
242
- <>
243
- {option.icon === "plus" ? (
244
- <Plus className="w-3 h-3 text-blue-600" />
245
- ) : (
246
- <Minus className="w-3 h-3 text-red-600" />
247
- )}
248
- <span
249
- className={
250
- option.icon === "plus"
251
- ? "text-blue-600"
252
- : "text-red-600"
253
- }
254
- >
255
- {option.label}
256
- </span>
257
- </>
258
- )}
259
- </div>
260
- </CommandItem>
261
- ))}
262
- </CommandGroup>
263
+ </>
264
+ )}
265
+ </div>
266
+ </CommandItem>
267
+ ))}
268
+ </CommandGroup>
269
+ </CommandList>
263
270
  </Command>
264
271
  </PopoverContent>
265
272
  </Popover>
@@ -133,8 +133,10 @@ export const EditPackageDetailsDialog = ({
133
133
  if (response.status !== 200)
134
134
  throw new Error("Failed to update package details")
135
135
 
136
- const filesRes = await axios.post("/package_files/list", {
137
- package_name_with_version: `${packageAuthor}/${formData.unscopedPackageName}`,
136
+ const filesRes = await axios.get("/package_files/list", {
137
+ params: {
138
+ package_name_with_version: `${packageAuthor}/${formData.unscopedPackageName}`,
139
+ },
138
140
  })
139
141
  const packageFiles: string[] =
140
142
  filesRes.status === 200
@@ -194,10 +196,7 @@ export const EditPackageDetailsDialog = ({
194
196
  onSuccess: (data) => {
195
197
  onUpdate?.(data.description, data.website, data.license, data.defaultView)
196
198
  onOpenChange(false)
197
- qc.invalidateQueries([
198
- "packageFile",
199
- { package_release_id: packageReleaseId },
200
- ])
199
+ qc.invalidateQueries("packageFile")
201
200
  qc.invalidateQueries(["packageFiles", packageReleaseId])
202
201
  toast({
203
202
  title: "Package details updated",
@@ -1,23 +1,30 @@
1
1
  import { createUseDialog } from "./create-use-dialog"
2
2
  import {
3
- ComponentSearchResult,
4
- ImportComponentDialog as RunframeImportComponentDialog,
3
+ ImportComponentDialog2 as RunframeImportComponentDialog,
4
+ type ImportComponentDialog2Props,
5
5
  } from "@tscircuit/runframe/runner"
6
6
 
7
+ export type ImportComponentDialogProps = {
8
+ open: boolean
9
+ onOpenChange: (open: boolean) => void
10
+ } & Pick<
11
+ ImportComponentDialog2Props,
12
+ | "onTscircuitPackageSelected"
13
+ | "onJlcpcbComponentTsxLoaded"
14
+ | "onKicadStringSelected"
15
+ | "jlcpcbProxyRequestHeaders"
16
+ >
17
+
7
18
  export const ImportComponentDialog = ({
8
19
  open,
9
20
  onOpenChange,
10
- onComponentSelected,
11
- }: {
12
- open: boolean
13
- onOpenChange: (open: boolean) => any
14
- onComponentSelected: (pkg: ComponentSearchResult) => any
15
- }) => {
21
+ ...rest
22
+ }: ImportComponentDialogProps) => {
16
23
  return (
17
24
  <RunframeImportComponentDialog
18
25
  isOpen={open}
19
26
  onClose={() => onOpenChange(false)}
20
- onImport={(data) => onComponentSelected(data)}
27
+ {...rest}
21
28
  />
22
29
  )
23
30
  }
@@ -7,6 +7,7 @@ import { Button } from "../ui/button"
7
7
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog"
8
8
  import { Input } from "../ui/input"
9
9
  import { createUseDialog } from "./create-use-dialog"
10
+ import { Link } from "wouter"
10
11
 
11
12
  export const ImportPackageDialog = ({
12
13
  open,
@@ -55,13 +56,13 @@ export const ImportPackageDialog = ({
55
56
  className="flex flex-col sm:flex-row items-start sm:items-center my-2 text-sm w-full"
56
57
  key={pkg.package_id}
57
58
  >
58
- <a
59
+ <Link
59
60
  href={`/${pkg.name}`}
60
61
  target="_blank"
61
62
  className="text-blue-500 hover:underline cursor-pointer flex-shrink-0 mb-1 sm:mb-0 sm:mr-2"
62
63
  >
63
64
  {pkg.name}
64
- </a>
65
+ </Link>
65
66
  <div className="text-gray-500 flex-grow overflow-hidden text-ellipsis whitespace-nowrap mb-1 sm:mb-0">
66
67
  {pkg.description}
67
68
  </div>