@tscircuit/fake-snippets 0.0.107 → 0.0.109
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/generated-index.js +82 -22
- package/biome.json +7 -1
- package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +0 -15
- package/bun-tests/fake-snippets-api/routes/package_builds/list.test.ts +0 -12
- package/bun.lock +62 -19
- package/dist/bundle.js +25 -24
- package/dist/index.d.ts +26 -15
- package/dist/index.js +19 -18
- package/dist/schema.d.ts +32 -24
- package/dist/schema.js +7 -6
- package/fake-snippets-api/lib/db/db-client.ts +10 -1
- package/fake-snippets-api/lib/db/schema.ts +4 -3
- package/fake-snippets-api/lib/db/seed.ts +6 -9
- package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +0 -3
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +3 -0
- package/package.json +7 -8
- package/src/App.tsx +12 -11
- package/src/components/DownloadButtonAndMenu.tsx +133 -35
- package/src/components/FileSidebar.tsx +45 -193
- package/src/components/Footer.tsx +0 -1
- package/src/components/HeaderLogin.tsx +1 -1
- package/src/components/HiddenFilesDropdown.tsx +0 -2
- package/src/components/PackageBreadcrumb.tsx +1 -1
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -2
- package/src/components/PackageBuildsPage/build-preview-content.tsx +34 -5
- package/src/components/PackageCard.tsx +0 -1
- package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
- package/src/components/ViewPackagePage/components/important-files-view.tsx +75 -59
- package/src/components/ViewPackagePage/components/main-content-header.tsx +4 -4
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +0 -1
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +1 -2
- package/src/components/ViewPackagePage/components/package-header.tsx +14 -17
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +0 -1
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +21 -20
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +18 -2
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +1 -1
- package/src/components/ViewPackagePage/components/sidebar.tsx +0 -2
- package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +18 -17
- package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
- package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
- package/src/components/package-port/CodeAndPreview.tsx +23 -40
- package/src/components/package-port/CodeEditor.tsx +24 -1
- package/src/components/package-port/CodeEditorHeader.tsx +5 -2
- package/src/components/preview/BuildsList.tsx +20 -9
- package/src/components/preview/ConnectedPackagesList.tsx +73 -60
- package/src/components/preview/ConnectedRepoOverview.tsx +160 -154
- package/src/components/preview/PackageReleasesDashboard.tsx +41 -30
- package/src/components/preview/index.tsx +16 -153
- package/src/hooks/use-current-package-id.ts +5 -30
- package/src/hooks/use-current-package-info.ts +29 -5
- package/src/hooks/use-global-store.ts +1 -1
- package/src/hooks/useFileManagement.ts +153 -34
- package/src/hooks/useOptimizedPackageFilesLoader.ts +149 -0
- package/src/hooks/useUpdatePackageFilesMutation.ts +2 -0
- package/src/index.css +24 -0
- package/src/lib/download-fns/download-circuit-png.ts +11 -3
- package/src/lib/download-fns/download-gltf-from-circuit-json.ts +44 -0
- package/src/lib/utils/isComponentExported.ts +9 -0
- package/src/lib/utils/transformFilesToTreeData.tsx +195 -0
- package/src/pages/404.tsx +3 -5
- package/src/pages/authorize.tsx +0 -2
- package/src/pages/landing.tsx +0 -1
- package/src/pages/preview-release.tsx +279 -0
- package/src/pages/release-builds.tsx +0 -8
- package/src/pages/release-detail.tsx +17 -15
- package/src/pages/releases.tsx +5 -1
- package/src/pages/view-package.tsx +14 -13
- package/src/components/Footer2.tsx +0 -100
- package/src/components/ShippingInformationForm.tsx +0 -423
- package/src/components/StaticViewSnippetHeader.tsx +0 -70
- package/src/components/ViewPackagePage/components/file-explorer.tsx +0 -67
- package/src/components/ViewPackagePage/components/readme-view.tsx +0 -58
- package/src/components/ViewPackagePage/components/repo-header-button.tsx +0 -36
- package/src/components/ViewPackagePage/components/repo-header.tsx +0 -4
- package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +0 -31
- package/src/components/ViewSnippetHeader.tsx +0 -181
- package/src/components/ui/input-otp.tsx +0 -69
- package/src/hooks/use-snippets-base-api-url.ts +0 -3
- package/src/pages/preview-build.tsx +0 -380
- package/src/pages/settings.tsx +0 -25
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { useParams } from "wouter"
|
|
3
|
+
import { Loader2, ChevronLeft, ChevronRight } from "lucide-react"
|
|
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
|
+
import { cn } from "@/lib/utils"
|
|
9
|
+
import { PrefetchPageLink } from "@/components/PrefetchPageLink"
|
|
10
|
+
import NotFoundPage from "./404"
|
|
11
|
+
import { getBuildStatus } from "@/components/preview"
|
|
12
|
+
import { usePackageReleaseById } from "@/hooks/use-package-release"
|
|
13
|
+
import { usePackageFilesLoader } from "@/hooks/usePackageFilesLoader"
|
|
14
|
+
import { usePackageBuild } from "@/hooks/use-package-builds"
|
|
15
|
+
import { PackageBuild } from "fake-snippets-api/lib/db/schema"
|
|
16
|
+
import { usePackageByName } from "@/hooks/use-package-by-package-name"
|
|
17
|
+
import { findTargetFile } from "@/lib/utils/findTargetFile"
|
|
18
|
+
|
|
19
|
+
const StatusPill = ({ status }: { status: string }) => {
|
|
20
|
+
const color =
|
|
21
|
+
status === "success"
|
|
22
|
+
? "bg-emerald-600"
|
|
23
|
+
: status === "failed"
|
|
24
|
+
? "bg-red-600"
|
|
25
|
+
: status === "building"
|
|
26
|
+
? "bg-blue-600 animate-pulse"
|
|
27
|
+
: "bg-gray-500"
|
|
28
|
+
return <span className={cn("inline-block w-2 h-2 rounded-full", color)} />
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default function PreviewBuildPage() {
|
|
32
|
+
const params = useParams<{
|
|
33
|
+
packageReleaseId: string
|
|
34
|
+
author: string
|
|
35
|
+
packageName: string
|
|
36
|
+
}>()
|
|
37
|
+
const packageReleaseId = params?.packageReleaseId || null
|
|
38
|
+
const author = params?.author || null
|
|
39
|
+
const packageName = params?.packageName || null
|
|
40
|
+
|
|
41
|
+
const [sidebarCollapsed, setSidebarCollapsed] = useState(true)
|
|
42
|
+
const [selectedFile, setSelectedFile] = useState<string | null>(null)
|
|
43
|
+
const [selectedItemId, setSelectedItemId] = useState<string>("")
|
|
44
|
+
|
|
45
|
+
const { data: packageRelease, isLoading: isLoadingRelease } =
|
|
46
|
+
usePackageReleaseById(packageReleaseId)
|
|
47
|
+
const { data: pkg, isLoading: isLoadingPackage } = usePackageByName(
|
|
48
|
+
author && packageName ? `${author}/${packageName}` : null,
|
|
49
|
+
)
|
|
50
|
+
const { data: build, isLoading: isLoadingBuild } = usePackageBuild(
|
|
51
|
+
packageRelease?.latest_package_build_id || null,
|
|
52
|
+
)
|
|
53
|
+
const { data: buildFiles = [], isLoading: isLoadingFiles } =
|
|
54
|
+
usePackageFilesLoader(pkg)
|
|
55
|
+
|
|
56
|
+
const buildFsMap = Object.fromEntries(
|
|
57
|
+
buildFiles.map((f) => [f.path, f.content]),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const targetFile = findTargetFile(buildFiles, selectedFile)
|
|
61
|
+
const mainComponentPath = targetFile?.path ?? null
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!selectedFile && mainComponentPath) {
|
|
65
|
+
setSelectedFile(mainComponentPath)
|
|
66
|
+
}
|
|
67
|
+
}, [mainComponentPath, selectedFile])
|
|
68
|
+
|
|
69
|
+
if (!packageReleaseId) {
|
|
70
|
+
return <NotFoundPage heading="Package Release Not Found" />
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!packageRelease && !isLoadingRelease) {
|
|
74
|
+
return <NotFoundPage heading="Package Release Not Found" />
|
|
75
|
+
}
|
|
76
|
+
const isLoading =
|
|
77
|
+
isLoadingRelease || isLoadingPackage || isLoadingFiles || isLoadingBuild
|
|
78
|
+
|
|
79
|
+
if (!build && !isLoading) {
|
|
80
|
+
return <NotFoundPage heading="Package Build Not Found" />
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const { status } = getBuildStatus(build as PackageBuild)
|
|
84
|
+
|
|
85
|
+
const treeData = transformFilesToTreeData({
|
|
86
|
+
files: buildFsMap,
|
|
87
|
+
currentFile: selectedFile ?? mainComponentPath,
|
|
88
|
+
renamingFile: null,
|
|
89
|
+
handleRenameFile: () => ({ fileRenamed: false }),
|
|
90
|
+
handleDeleteFile: () => ({ fileDeleted: false }),
|
|
91
|
+
setRenamingFile: () => {},
|
|
92
|
+
onFileSelect: setSelectedFile,
|
|
93
|
+
onFolderSelect: () => {},
|
|
94
|
+
canModifyFiles: false,
|
|
95
|
+
setErrorMessage: () => {},
|
|
96
|
+
setSelectedFolderForCreation: () => {},
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<>
|
|
101
|
+
<Header />
|
|
102
|
+
<div className="flex flex-col h-screen overflow-hidden !-mt-1">
|
|
103
|
+
<div className="flex flex-1 overflow-hidden">
|
|
104
|
+
<aside
|
|
105
|
+
className={cn(
|
|
106
|
+
"relative border-r border-gray-200 rounded-r-lg z-[5] h-full transition-all duration-300 ease-in-out bg-white",
|
|
107
|
+
sidebarCollapsed ? "w-2 md:w-3" : "w-80",
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
<button
|
|
111
|
+
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
|
|
112
|
+
className="absolute top-4 -right-3 z-10 bg-white border border-gray-200 rounded-full p-1 hover:bg-gray-50"
|
|
113
|
+
>
|
|
114
|
+
{sidebarCollapsed ? (
|
|
115
|
+
<ChevronRight size={20} />
|
|
116
|
+
) : (
|
|
117
|
+
<ChevronLeft size={20} />
|
|
118
|
+
)}
|
|
119
|
+
</button>
|
|
120
|
+
|
|
121
|
+
{!sidebarCollapsed && (
|
|
122
|
+
<>
|
|
123
|
+
<div className="p-4 border-b border-gray-200">
|
|
124
|
+
<div className="space-y-3">
|
|
125
|
+
<div className="flex items-center justify-between">
|
|
126
|
+
<h2 className="text-lg font-semibold text-gray-900">
|
|
127
|
+
Deployment
|
|
128
|
+
</h2>
|
|
129
|
+
<StatusPill status={status} />
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div className="space-y-2">
|
|
133
|
+
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
|
134
|
+
<span className="text-xs text-gray-500 uppercase tracking-wide">
|
|
135
|
+
ID
|
|
136
|
+
</span>
|
|
137
|
+
<PrefetchPageLink
|
|
138
|
+
href={`/${pkg?.name}/releases/${build?.package_release_id}`}
|
|
139
|
+
title={build?.package_build_id}
|
|
140
|
+
className="font-mono text-sm truncate text-gray-900 bg-gray-100 w-full px-2 py-1 rounded"
|
|
141
|
+
>
|
|
142
|
+
{build?.package_build_id}
|
|
143
|
+
</PrefetchPageLink>
|
|
144
|
+
</div>
|
|
145
|
+
{packageRelease?.commit_message && (
|
|
146
|
+
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
|
147
|
+
<span className="text-xs text-gray-500 uppercase tracking-wide">
|
|
148
|
+
Commit
|
|
149
|
+
</span>
|
|
150
|
+
<a
|
|
151
|
+
title={packageRelease?.commit_message}
|
|
152
|
+
target="_blank"
|
|
153
|
+
rel="noopener noreferrer"
|
|
154
|
+
href={`https://github.com/${pkg?.github_repo_full_name}/commit/${packageRelease?.commit_message}`}
|
|
155
|
+
className="font-mono text-xs text-gray-600 bg-gray-50 px-2 text-right py-1 rounded truncate"
|
|
156
|
+
>
|
|
157
|
+
{packageRelease?.commit_message}
|
|
158
|
+
</a>
|
|
159
|
+
</div>
|
|
160
|
+
)}
|
|
161
|
+
|
|
162
|
+
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
|
163
|
+
<span className="text-xs text-gray-500 uppercase tracking-wide">
|
|
164
|
+
Status
|
|
165
|
+
</span>
|
|
166
|
+
<span
|
|
167
|
+
className={`text-xs font-medium px-2 py-1 w-fit rounded-full capitalize ${
|
|
168
|
+
status === "success"
|
|
169
|
+
? "bg-emerald-100 text-emerald-800"
|
|
170
|
+
: status === "error"
|
|
171
|
+
? "bg-red-100 text-red-800"
|
|
172
|
+
: status === "building"
|
|
173
|
+
? "bg-blue-100 text-blue-800"
|
|
174
|
+
: "bg-gray-100 text-gray-800"
|
|
175
|
+
}`}
|
|
176
|
+
>
|
|
177
|
+
{status}
|
|
178
|
+
</span>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<div className="flex-1 overflow-hidden">
|
|
185
|
+
<div className="px-4 py-3 border-b border-gray-200">
|
|
186
|
+
<h3 className="text-sm font-semibold text-gray-900">
|
|
187
|
+
Files
|
|
188
|
+
</h3>
|
|
189
|
+
<p className="text-xs text-gray-500 mt-1">
|
|
190
|
+
{isLoadingFiles
|
|
191
|
+
? "Loading files..."
|
|
192
|
+
: `${treeData.length} file${treeData.length !== 1 ? "s" : ""}`}
|
|
193
|
+
</p>
|
|
194
|
+
</div>
|
|
195
|
+
<div className="px-2 py-2 overflow-y-auto select-none">
|
|
196
|
+
{isLoadingFiles ? (
|
|
197
|
+
<div className="flex items-center justify-center py-8">
|
|
198
|
+
<Loader2 className="w-4 h-4 animate-spin" />
|
|
199
|
+
<span className="ml-2 text-sm text-gray-500">
|
|
200
|
+
Loading files...
|
|
201
|
+
</span>
|
|
202
|
+
</div>
|
|
203
|
+
) : (
|
|
204
|
+
<TreeView
|
|
205
|
+
selectedItemId={selectedItemId || ""}
|
|
206
|
+
setSelectedItemId={(v) => setSelectedItemId(v || "")}
|
|
207
|
+
data={treeData}
|
|
208
|
+
className="w-full"
|
|
209
|
+
onSelectChange={(item) => {
|
|
210
|
+
if (item && !item.children) {
|
|
211
|
+
setSelectedFile(item.id)
|
|
212
|
+
}
|
|
213
|
+
}}
|
|
214
|
+
/>
|
|
215
|
+
)}
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</>
|
|
219
|
+
)}
|
|
220
|
+
</aside>
|
|
221
|
+
|
|
222
|
+
<main className="flex-1 overflow-y-auto">
|
|
223
|
+
<div className="flex flex-col h-full overflow-h-hidden">
|
|
224
|
+
{isLoading ? (
|
|
225
|
+
<div className="flex-1 flex items-center justify-center">
|
|
226
|
+
<div className="flex flex-col items-center gap-3 text-gray-500">
|
|
227
|
+
<Loader2 className="w-6 h-6 animate-spin" />
|
|
228
|
+
<p>Loading package contents...</p>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
) : status === "success" && buildFiles.length > 0 ? (
|
|
232
|
+
<SuspenseRunFrame
|
|
233
|
+
fsMap={buildFsMap}
|
|
234
|
+
mainComponentPath={mainComponentPath ?? "index.tsx"}
|
|
235
|
+
showRunButton={false}
|
|
236
|
+
className="[&>div]:overflow-y-hidden"
|
|
237
|
+
/>
|
|
238
|
+
) : (
|
|
239
|
+
<div className="flex-1 flex items-center justify-center">
|
|
240
|
+
{status === "building" ? (
|
|
241
|
+
<div className="flex flex-col items-center gap-3 text-gray-500">
|
|
242
|
+
<Loader2 className="w-6 h-6 animate-spin" />
|
|
243
|
+
<p>Building…</p>
|
|
244
|
+
</div>
|
|
245
|
+
) : status === "error" ? (
|
|
246
|
+
<div className="text-center">
|
|
247
|
+
<p className="text-red-600 font-medium mb-2">
|
|
248
|
+
Build Failed
|
|
249
|
+
</p>
|
|
250
|
+
</div>
|
|
251
|
+
) : buildFiles.length === 0 ? (
|
|
252
|
+
<div className="text-center">
|
|
253
|
+
<p className="text-gray-600 font-medium mb-2">
|
|
254
|
+
No files found
|
|
255
|
+
</p>
|
|
256
|
+
<p className="text-sm text-gray-500">
|
|
257
|
+
This package release doesn't have any files to preview.
|
|
258
|
+
</p>
|
|
259
|
+
</div>
|
|
260
|
+
) : (
|
|
261
|
+
<div className="text-center p-4">
|
|
262
|
+
<p className="text-gray-600 font-medium mb-2">
|
|
263
|
+
Build Status: {status}
|
|
264
|
+
</p>
|
|
265
|
+
<p className="text-sm text-gray-500 max-w-lg">
|
|
266
|
+
Please wait while we process this build status. Try
|
|
267
|
+
refreshing the page in a few moments.
|
|
268
|
+
</p>
|
|
269
|
+
</div>
|
|
270
|
+
)}
|
|
271
|
+
</div>
|
|
272
|
+
)}
|
|
273
|
+
</div>
|
|
274
|
+
</main>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</>
|
|
278
|
+
)
|
|
279
|
+
}
|
|
@@ -41,10 +41,6 @@ export default function ReleaseBuildsPage() {
|
|
|
41
41
|
error: buildsError,
|
|
42
42
|
} = usePackageBuildsByReleaseId(params?.releaseId ?? null)
|
|
43
43
|
|
|
44
|
-
const handleSelectBuild = (build: PackageBuild) => {
|
|
45
|
-
setLocation(`/build/${build.package_build_id}`)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
44
|
if (isLoadingPackage || isLoadingRelease || isLoadingBuilds) {
|
|
49
45
|
return null
|
|
50
46
|
}
|
|
@@ -57,10 +53,6 @@ export default function ReleaseBuildsPage() {
|
|
|
57
53
|
return <NotFoundPage heading="Release Not Found" />
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
if (buildsError?.status === 404 || !builds?.length) {
|
|
61
|
-
return <NotFoundPage heading="No Builds Found for Release" />
|
|
62
|
-
}
|
|
63
|
-
|
|
64
56
|
return (
|
|
65
57
|
<>
|
|
66
58
|
<Header />
|
|
@@ -6,8 +6,7 @@ import { usePackageBuild } from "@/hooks/use-package-builds"
|
|
|
6
6
|
import { ConnectedRepoOverview } from "@/components/preview/ConnectedRepoOverview"
|
|
7
7
|
import Header from "@/components/Header"
|
|
8
8
|
import { Badge } from "@/components/ui/badge"
|
|
9
|
-
import {
|
|
10
|
-
import { Calendar, GitBranch, Hash, Copy, Check } from "lucide-react"
|
|
9
|
+
import { Calendar, GitBranch } from "lucide-react"
|
|
11
10
|
import { useState } from "react"
|
|
12
11
|
import { formatTimeAgo } from "@/lib/utils/formatTimeAgo"
|
|
13
12
|
import { PackageBreadcrumb } from "@/components/PackageBreadcrumb"
|
|
@@ -48,7 +47,7 @@ export default function ReleaseDetailPage() {
|
|
|
48
47
|
error: buildError,
|
|
49
48
|
} = usePackageBuild(packageRelease?.latest_package_build_id ?? null)
|
|
50
49
|
|
|
51
|
-
if (isLoadingPackage || isLoadingRelease
|
|
50
|
+
if (isLoadingPackage || isLoadingRelease) {
|
|
52
51
|
return null
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -60,17 +59,13 @@ export default function ReleaseDetailPage() {
|
|
|
60
59
|
return <NotFoundPage heading="Release Not Found" />
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
if (buildError?.status === 404 || !latestBuild) {
|
|
64
|
-
return <NotFoundPage heading="No Builds Found for Release" />
|
|
65
|
-
}
|
|
66
|
-
|
|
67
62
|
return (
|
|
68
63
|
<>
|
|
69
64
|
<Header />
|
|
70
65
|
<div className="min-h-screen bg-white">
|
|
71
66
|
{/* Page Header */}
|
|
72
67
|
<div className="bg-gray-50 border-b py-6">
|
|
73
|
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
68
|
+
<div className="max-w-7xl lg:flex lg:justify-between mx-auto px-4 sm:px-6 lg:px-8">
|
|
74
69
|
{/* Breadcrumb */}
|
|
75
70
|
<PackageBreadcrumb
|
|
76
71
|
author={pkg.owner_github_username || ""}
|
|
@@ -87,12 +82,18 @@ export default function ReleaseDetailPage() {
|
|
|
87
82
|
<div className="flex-1">
|
|
88
83
|
<div className="flex items-center gap-4 text-sm text-gray-600">
|
|
89
84
|
{packageRelease.is_pr_preview && (
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
<a
|
|
86
|
+
href={`https://github.com/${pkg.github_repo_full_name}/pull/${packageRelease.github_pr_number}`}
|
|
87
|
+
target="_blank"
|
|
88
|
+
rel="noopener noreferrer"
|
|
89
|
+
>
|
|
90
|
+
<div className="flex items-center gap-1">
|
|
91
|
+
<GitBranch className="w-4 h-4" />
|
|
92
|
+
<Badge variant="outline" className="text-xs">
|
|
93
|
+
PR #{packageRelease.github_pr_number}
|
|
94
|
+
</Badge>
|
|
95
|
+
</div>
|
|
96
|
+
</a>
|
|
96
97
|
)}
|
|
97
98
|
<div className="flex items-center gap-1">
|
|
98
99
|
<Calendar className="w-4 h-4" />
|
|
@@ -108,7 +109,8 @@ export default function ReleaseDetailPage() {
|
|
|
108
109
|
|
|
109
110
|
{/* Main Content */}
|
|
110
111
|
<ConnectedRepoOverview
|
|
111
|
-
|
|
112
|
+
packageBuild={latestBuild ?? null}
|
|
113
|
+
isLoadingBuild={isLoadingBuild}
|
|
112
114
|
pkg={pkg}
|
|
113
115
|
packageRelease={packageRelease}
|
|
114
116
|
/>
|
package/src/pages/releases.tsx
CHANGED
|
@@ -46,6 +46,10 @@ export default function ReleasesPage() {
|
|
|
46
46
|
// If there's no build, we still want to show the releases page
|
|
47
47
|
// The PackageReleasesDashboard will handle the case where latestBuild is null
|
|
48
48
|
return (
|
|
49
|
-
<PackageReleasesDashboard
|
|
49
|
+
<PackageReleasesDashboard
|
|
50
|
+
latestRelease={latestRelease}
|
|
51
|
+
latestBuild={latestBuild ?? null}
|
|
52
|
+
pkg={pkg}
|
|
53
|
+
/>
|
|
50
54
|
)
|
|
51
55
|
}
|
|
@@ -5,18 +5,19 @@ import { useLocation, useParams } from "wouter"
|
|
|
5
5
|
import { Helmet } from "react-helmet-async"
|
|
6
6
|
import { useEffect, useState } from "react"
|
|
7
7
|
import NotFoundPage from "./404"
|
|
8
|
-
import {
|
|
9
|
-
import { usePackage } from "@/hooks/use-package"
|
|
8
|
+
import { usePackageByName } from "@/hooks/use-package-by-package-name"
|
|
10
9
|
|
|
11
10
|
export const ViewPackagePage = () => {
|
|
12
|
-
const {
|
|
13
|
-
packageId,
|
|
14
|
-
error: packageIdError,
|
|
15
|
-
isLoading: isLoadingPackageId,
|
|
16
|
-
} = useCurrentPackageId()
|
|
17
|
-
const { data: packageInfo } = usePackage(packageId)
|
|
18
11
|
const { author, packageName } = useParams()
|
|
12
|
+
const packageNameFull = `${author}/${packageName}`
|
|
19
13
|
const [, setLocation] = useLocation()
|
|
14
|
+
|
|
15
|
+
// Get package data directly by name - this will also cache by ID
|
|
16
|
+
const {
|
|
17
|
+
data: packageInfo,
|
|
18
|
+
error: packageError,
|
|
19
|
+
isLoading: isLoadingPackage,
|
|
20
|
+
} = usePackageByName(packageNameFull)
|
|
20
21
|
const {
|
|
21
22
|
data: packageRelease,
|
|
22
23
|
error: packageReleaseError,
|
|
@@ -33,11 +34,10 @@ export const ViewPackagePage = () => {
|
|
|
33
34
|
},
|
|
34
35
|
)
|
|
35
36
|
|
|
36
|
-
const { data: packageFiles } =
|
|
37
|
-
packageRelease?.package_release_id
|
|
38
|
-
)
|
|
37
|
+
const { data: packageFiles, isFetched: arePackageFilesFetched } =
|
|
38
|
+
usePackageFiles(packageRelease?.package_release_id)
|
|
39
39
|
|
|
40
|
-
if (!
|
|
40
|
+
if (!isLoadingPackage && packageError) {
|
|
41
41
|
return <NotFoundPage heading="Package Not Found" />
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -51,7 +51,8 @@ export const ViewPackagePage = () => {
|
|
|
51
51
|
<title>{`${author}/${packageName} - tscircuit`}</title>
|
|
52
52
|
</Helmet>
|
|
53
53
|
<RepoPageContent
|
|
54
|
-
packageFiles={packageFiles
|
|
54
|
+
packageFiles={packageFiles ?? []}
|
|
55
|
+
arePackageFilesFetched={arePackageFilesFetched}
|
|
55
56
|
packageInfo={packageInfo}
|
|
56
57
|
packageRelease={packageRelease}
|
|
57
58
|
importantFilePaths={["README.md", "LICENSE", "package.json"]}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { Button } from "@/components/ui/button"
|
|
2
|
-
import { Card, CardContent } from "@/components/ui/card"
|
|
3
|
-
import { Badge } from "@/components/ui/badge"
|
|
4
|
-
import {
|
|
5
|
-
Accordion,
|
|
6
|
-
AccordionContent,
|
|
7
|
-
AccordionItem,
|
|
8
|
-
AccordionTrigger,
|
|
9
|
-
} from "@/components/ui/accordion"
|
|
10
|
-
import {
|
|
11
|
-
CircuitBoard,
|
|
12
|
-
Cpu,
|
|
13
|
-
Layers,
|
|
14
|
-
CloudLightningIcon as Lightning,
|
|
15
|
-
Maximize2,
|
|
16
|
-
Zap,
|
|
17
|
-
} from "lucide-react"
|
|
18
|
-
import { Link } from "wouter"
|
|
19
|
-
import { Header2 } from "@/components/Header2"
|
|
20
|
-
|
|
21
|
-
export const Footer2 = () => (
|
|
22
|
-
<footer className="w-full py-6 bg-background">
|
|
23
|
-
<div className="container px-4 md:px-6 mx-auto">
|
|
24
|
-
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-4">
|
|
25
|
-
<div className="space-y-4">
|
|
26
|
-
<div className="flex items-center gap-2">
|
|
27
|
-
<CircuitBoard className="h-6 w-6" />
|
|
28
|
-
<span className="text-lg font-bold">tscircuit</span>
|
|
29
|
-
</div>
|
|
30
|
-
<p className="text-sm text-muted-foreground">
|
|
31
|
-
Transforming electronic design with AI-powered tools.
|
|
32
|
-
</p>
|
|
33
|
-
</div>
|
|
34
|
-
<div className="space-y-4">
|
|
35
|
-
<h4 className="text-sm font-bold">Product</h4>
|
|
36
|
-
<ul className="space-y-2 text-sm">
|
|
37
|
-
<li>
|
|
38
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
39
|
-
Features
|
|
40
|
-
</Link>
|
|
41
|
-
</li>
|
|
42
|
-
<li>
|
|
43
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
44
|
-
Pricing
|
|
45
|
-
</Link>
|
|
46
|
-
</li>
|
|
47
|
-
<li>
|
|
48
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
49
|
-
Tutorials
|
|
50
|
-
</Link>
|
|
51
|
-
</li>
|
|
52
|
-
</ul>
|
|
53
|
-
</div>
|
|
54
|
-
<div className="space-y-4">
|
|
55
|
-
<h4 className="text-sm font-bold">Company</h4>
|
|
56
|
-
<ul className="space-y-2 text-sm">
|
|
57
|
-
<li>
|
|
58
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
59
|
-
About
|
|
60
|
-
</Link>
|
|
61
|
-
</li>
|
|
62
|
-
<li>
|
|
63
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
64
|
-
Blog
|
|
65
|
-
</Link>
|
|
66
|
-
</li>
|
|
67
|
-
<li>
|
|
68
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
69
|
-
Careers
|
|
70
|
-
</Link>
|
|
71
|
-
</li>
|
|
72
|
-
</ul>
|
|
73
|
-
</div>
|
|
74
|
-
<div className="space-y-4">
|
|
75
|
-
<h4 className="text-sm font-bold">Legal</h4>
|
|
76
|
-
<ul className="space-y-2 text-sm">
|
|
77
|
-
<li>
|
|
78
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
79
|
-
Privacy
|
|
80
|
-
</Link>
|
|
81
|
-
</li>
|
|
82
|
-
<li>
|
|
83
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
84
|
-
Terms
|
|
85
|
-
</Link>
|
|
86
|
-
</li>
|
|
87
|
-
<li>
|
|
88
|
-
<Link className="text-muted-foreground hover:underline" href="#">
|
|
89
|
-
Cookie Policy
|
|
90
|
-
</Link>
|
|
91
|
-
</li>
|
|
92
|
-
</ul>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
<div className="mt-8 border-t pt-8 text-center text-sm text-muted-foreground">
|
|
96
|
-
© {new Date().getFullYear()} tscircuit. All rights reserved.
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
</footer>
|
|
100
|
-
)
|