@tscircuit/fake-snippets 0.0.26 → 0.0.28

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 (58) hide show
  1. package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +5 -6
  2. package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +3 -0
  3. package/bun-tests/fake-snippets-api/routes/packages/list-2.test.ts +2 -0
  4. package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +5 -3
  5. package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +8 -5
  6. package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +1 -1
  7. package/bun.lock +110 -5
  8. package/dist/bundle.js +62 -11
  9. package/dist/index.d.ts +5 -0
  10. package/dist/index.js +4 -2
  11. package/fake-snippets-api/lib/db/autoload-snippets.json +4 -0
  12. package/fake-snippets-api/lib/db/db-client.ts +2 -1
  13. package/fake-snippets-api/lib/db/schema.ts +1 -0
  14. package/fake-snippets-api/lib/public-mapping/public-map-package.ts +1 -0
  15. package/fake-snippets-api/routes/api/package_files/list.ts +6 -3
  16. package/fake-snippets-api/routes/api/package_releases/get.ts +67 -1
  17. package/fake-snippets-api/routes/api/packages/create.ts +2 -1
  18. package/fake-snippets-api/routes/api/snippets/create.ts +1 -0
  19. package/package.json +2 -1
  20. package/public/placeholder-logo.png +0 -0
  21. package/public/placeholder-logo.svg +1 -0
  22. package/public/placeholder-user.jpg +0 -0
  23. package/public/placeholder.jpg +0 -0
  24. package/public/placeholder.svg +1 -0
  25. package/src/App.tsx +6 -0
  26. package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +50 -0
  27. package/src/components/ViewPackagePage/components/file-explorer.tsx +118 -0
  28. package/src/components/ViewPackagePage/components/important-files-view.tsx +231 -0
  29. package/src/components/ViewPackagePage/components/main-content-header.tsx +172 -0
  30. package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +106 -0
  31. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +130 -0
  32. package/src/components/ViewPackagePage/components/package-header.tsx +107 -0
  33. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +63 -0
  34. package/src/components/ViewPackagePage/components/readme-view.tsx +58 -0
  35. package/src/components/ViewPackagePage/components/repo-header-button.tsx +36 -0
  36. package/src/components/ViewPackagePage/components/repo-header.tsx +4 -0
  37. package/src/components/ViewPackagePage/components/repo-page-content.tsx +213 -0
  38. package/src/components/ViewPackagePage/components/repo-tab-header.tsx +12 -0
  39. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +103 -0
  40. package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +31 -0
  41. package/src/components/ViewPackagePage/components/sidebar-packages-section.tsx +16 -0
  42. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +44 -0
  43. package/src/components/ViewPackagePage/components/sidebar.tsx +40 -0
  44. package/src/components/ViewPackagePage/components/tab-views/3d-view.tsx +9 -0
  45. package/src/components/ViewPackagePage/components/tab-views/bom-view.tsx +9 -0
  46. package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +166 -0
  47. package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +9 -0
  48. package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +9 -0
  49. package/src/components/ViewPackagePage/components/theme-toggle.tsx +42 -0
  50. package/src/components/ViewPackagePage/hooks/use-mobile.tsx +19 -0
  51. package/src/components/ViewPackagePage/hooks/use-toast.ts +191 -0
  52. package/src/components/ViewPackagePage/simulate-page.tsx +120 -0
  53. package/src/components/ViewPackagePage/utils/is-package-file-important.ts +21 -0
  54. package/src/hooks/use-package-files.ts +29 -0
  55. package/src/hooks/use-package-release.ts +22 -0
  56. package/src/index.css +15 -0
  57. package/src/pages/beta.tsx +282 -99
  58. package/src/pages/view-package.tsx +38 -0
@@ -0,0 +1,21 @@
1
+ const importanceMap = {
2
+ "readme.md": 200,
3
+ license: 100,
4
+ "license.md": 100,
5
+ "index.ts": 90,
6
+ "index.tsx": 90,
7
+ "circuit.tsx": 90,
8
+ }
9
+
10
+ export const scorePackageFileImportance = (filePath: string) => {
11
+ for (const [key, value] of Object.entries(importanceMap)) {
12
+ if (filePath.endsWith(key)) {
13
+ return value
14
+ }
15
+ }
16
+ return 0
17
+ }
18
+
19
+ export const isPackageFileImportant = (filePath: string) => {
20
+ return scorePackageFileImportance(filePath) > 0
21
+ }
@@ -82,3 +82,32 @@ export const usePackageFileByRelease = (
82
82
  : null,
83
83
  )
84
84
  }
85
+
86
+ // Hook to list all files for a package release
87
+ export const usePackageFiles = (packageReleaseId?: string | null) => {
88
+ const axios = useAxios()
89
+
90
+ return useQuery<PackageFile[], Error & { status: number }>(
91
+ ["packageFiles", packageReleaseId],
92
+ async () => {
93
+ if (!packageReleaseId) return []
94
+
95
+ try {
96
+ const { data } = await axios.post("/package_files/list", {
97
+ package_release_id: packageReleaseId,
98
+ })
99
+
100
+ if (!data.package_files) {
101
+ return []
102
+ }
103
+
104
+ return data.package_files
105
+ } catch (error) {
106
+ throw error
107
+ }
108
+ },
109
+ {
110
+ enabled: Boolean(packageReleaseId),
111
+ },
112
+ )
113
+ }
@@ -9,6 +9,14 @@ type PackageReleaseQuery =
9
9
  | {
10
10
  package_name_with_version: string
11
11
  }
12
+ | {
13
+ package_name: string
14
+ is_latest: boolean
15
+ }
16
+ | {
17
+ package_id: string
18
+ is_latest: boolean
19
+ }
12
20
 
13
21
  export const usePackageRelease = (query: PackageReleaseQuery | null) => {
14
22
  const axios = useAxios()
@@ -49,3 +57,17 @@ export const usePackageReleaseByNameAndVersion = (
49
57
  : null,
50
58
  )
51
59
  }
60
+
61
+ export const useLatestPackageRelease = (
62
+ packageId?: string | null,
63
+ packageName?: string | null,
64
+ ) => {
65
+ // Prioritize packageName if both are provided
66
+ const query = packageName
67
+ ? { package_name: packageName, is_latest: true }
68
+ : packageId
69
+ ? { package_id: packageId, is_latest: true }
70
+ : null
71
+
72
+ return usePackageRelease(query)
73
+ }
package/src/index.css CHANGED
@@ -19,3 +19,18 @@
19
19
  .animate-fadeIn {
20
20
  animation: fadeIn 0.3s ease-in-out;
21
21
  }
22
+
23
+ .shiki code {
24
+ counter-reset: step;
25
+ counter-increment: step 0;
26
+ }
27
+
28
+ .shiki code .line::before {
29
+ content: counter(step);
30
+ counter-increment: step;
31
+ width: 1rem;
32
+ margin-right: 1.5rem;
33
+ display: inline-block;
34
+ text-align: right;
35
+ color: rgba(115, 138, 148, 0.4);
36
+ }
@@ -3,16 +3,81 @@ import { useCreatePackageMutation } from "@/hooks/use-create-package-mutation"
3
3
  import { useCreatePackageReleaseMutation } from "@/hooks/use-create-package-release-mutation"
4
4
  import { useForkPackageMutation } from "@/hooks/use-fork-package-mutation"
5
5
  import { usePackageById } from "@/hooks/use-package-by-package-id"
6
- import { usePackageFile } from "@/hooks/use-package-files"
7
- import { usePackageRelease } from "@/hooks/use-package-release"
8
- import { useState } from "react"
6
+ import { usePackageByName } from "@/hooks/use-package-by-package-name"
7
+ import { usePackageFile, usePackageFiles } from "@/hooks/use-package-files"
8
+ import {
9
+ useLatestPackageRelease,
10
+ usePackageRelease,
11
+ usePackageReleaseByNameAndVersion,
12
+ } from "@/hooks/use-package-release"
13
+ import { useEffect, useState } from "react"
14
+ import { useLocation } from "wouter"
9
15
 
10
16
  export const BetaPage = () => {
17
+ // Get the current path and extract author/packageName
18
+ const [location] = useLocation()
19
+ const pathParts = location.split("/")
20
+ const author = pathParts[2]
21
+ const urlPackageName = pathParts[3]
22
+ const packageNameWithVersion =
23
+ author && urlPackageName ? `${author}/${urlPackageName}` : null
24
+
25
+ // States for package creation flow
11
26
  const [createdPackageId, setCreatedPackageId] = useState<string | null>(null)
12
27
  const [createdReleaseId, setCreatedReleaseId] = useState<string | null>(null)
13
28
  const [createdFileId, setCreatedFileId] = useState<string | null>(null)
14
29
  const [forkedPackageId, setForkedPackageId] = useState<string | null>(null)
15
30
  const [packageName, setPackageName] = useState("")
31
+ const [selectedFileId, setSelectedFileId] = useState<string | null>(null)
32
+ const [isLoading, setIsLoading] = useState(!!packageNameWithVersion)
33
+
34
+ // Load existing package if URL params are provided
35
+ const { data: existingPackage, isSuccess: packageLoaded } = usePackageByName(
36
+ packageNameWithVersion,
37
+ )
38
+ // Use the new hook instead of usePackageReleaseByNameAndVersion
39
+ const { data: existingRelease, isSuccess: releaseLoaded } =
40
+ useLatestPackageRelease(existingPackage?.package_id)
41
+
42
+ // Log for debugging
43
+ console.log("Location path:", location)
44
+ console.log("Author:", author, "Package:", urlPackageName)
45
+ console.log("Package name with version:", packageNameWithVersion)
46
+ console.log("Existing package:", existingPackage)
47
+ console.log("Existing release:", existingRelease)
48
+
49
+ // Set IDs from existing package when they're loaded
50
+ useEffect(() => {
51
+ if (existingPackage) {
52
+ console.log("Setting package ID:", existingPackage.package_id)
53
+ setCreatedPackageId(existingPackage.package_id)
54
+ setPackageName(existingPackage.name)
55
+ }
56
+ }, [existingPackage])
57
+
58
+ useEffect(() => {
59
+ if (existingRelease) {
60
+ console.log("Setting release ID:", existingRelease.package_release_id)
61
+ setCreatedReleaseId(existingRelease.package_release_id)
62
+
63
+ // Force refetch package files by setting a dummy state to trigger useEffect
64
+ setTimeout(() => {
65
+ console.log("Triggering files refetch...")
66
+ setIsLoading(false)
67
+ }, 500)
68
+ }
69
+ }, [existingRelease])
70
+
71
+ // Update loading state
72
+ useEffect(() => {
73
+ if (packageNameWithVersion) {
74
+ if (packageLoaded && releaseLoaded) {
75
+ setIsLoading(false)
76
+ }
77
+ } else {
78
+ setIsLoading(false)
79
+ }
80
+ }, [packageNameWithVersion, packageLoaded, releaseLoaded])
16
81
 
17
82
  // Demo data
18
83
  const demoData = {
@@ -58,122 +123,240 @@ export const BetaPage = () => {
58
123
  onSuccess: (forkedPackage) => setForkedPackageId(forkedPackage.package_id),
59
124
  })
60
125
 
126
+ // Package data
61
127
  const { data: packageData } = usePackageById(createdPackageId)
62
- const { data: releaseData } = usePackageRelease(
63
- createdReleaseId ? { package_release_id: createdReleaseId } : null,
128
+
129
+ // Package release data
130
+ const { data: releaseData } = useLatestPackageRelease(createdPackageId, null)
131
+
132
+ // All package files for the release
133
+ const { data: packageFiles, isLoading: filesLoading } =
134
+ usePackageFiles(createdReleaseId)
135
+
136
+ // Log the files data for debugging
137
+ console.log(
138
+ "Package files:",
139
+ packageFiles,
140
+ "createdReleaseId:",
141
+ createdReleaseId,
64
142
  )
65
- const { data: fileData } = usePackageFile(
66
- createdFileId ? { package_file_id: createdFileId } : null,
143
+
144
+ // Individual file data when selected
145
+ const { data: selectedFileData } = usePackageFile(
146
+ selectedFileId ? { package_file_id: selectedFileId } : null,
67
147
  )
148
+
68
149
  const { data: forkedPackageData } = usePackageById(forkedPackageId)
69
150
 
151
+ if (isLoading) {
152
+ return (
153
+ <div className="p-4">
154
+ <h2 className="text-lg font-semibold mb-4">Loading package data...</h2>
155
+ </div>
156
+ )
157
+ }
158
+
70
159
  return (
71
160
  <div className="p-4">
72
- <h1 className="text-xl font-bold mb-4">Package Management Demo</h1>
73
- <div className="mb-4">
74
- <div className="flex items-center gap-2">
75
- <input
76
- type="text"
77
- value={packageName}
78
- onChange={(e) => setPackageName(e.target.value)}
79
- placeholder="test-package"
80
- className="flex-1 px-3 py-2 border rounded text-sm"
81
- disabled={Boolean(createdPackageId)}
82
- />
161
+ <h1 className="text-xl font-bold mb-4">
162
+ {packageNameWithVersion
163
+ ? `Package: ${packageNameWithVersion}`
164
+ : "Package Management Demo"}
165
+ </h1>
166
+ {!packageNameWithVersion && (
167
+ <div className="mb-4">
168
+ <div className="flex items-center gap-2">
169
+ <input
170
+ type="text"
171
+ value={packageName}
172
+ onChange={(e) => setPackageName(e.target.value)}
173
+ placeholder="test-package"
174
+ className="flex-1 px-3 py-2 border rounded text-sm"
175
+ disabled={Boolean(createdPackageId)}
176
+ />
177
+ </div>
83
178
  </div>
84
- </div>
85
- <div className="grid grid-cols-4 gap-4">
86
- {/* Package Creation */}
87
- <div className="bg-white p-4 rounded-lg shadow">
88
- <div className="flex items-center justify-between mb-2">
89
- <h2 className="font-semibold">1. Create Package</h2>
90
- <button
91
- onClick={() => createPackage(demoData.package)}
92
- disabled={
93
- isCreatingPackage || Boolean(createdPackageId) || !packageName
94
- }
95
- className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
96
- >
97
- {createdPackageId ? "✓" : "Create"}
98
- </button>
179
+ )}
180
+
181
+ {/* Package creation UI only shown when not viewing an existing package */}
182
+ {!packageNameWithVersion && (
183
+ <div className="grid grid-cols-4 gap-4 mb-4">
184
+ {/* Package Creation */}
185
+ <div className="bg-white p-4 rounded-lg shadow">
186
+ <div className="flex items-center justify-between mb-2">
187
+ <h2 className="font-semibold">1. Create Package</h2>
188
+ <button
189
+ onClick={() => createPackage(demoData.package)}
190
+ disabled={
191
+ isCreatingPackage || Boolean(createdPackageId) || !packageName
192
+ }
193
+ className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
194
+ >
195
+ {createdPackageId ? "✓" : "Create"}
196
+ </button>
197
+ </div>
198
+ {packageData && (
199
+ <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-32">
200
+ {JSON.stringify(packageData, null, 2)}
201
+ </pre>
202
+ )}
203
+ </div>
204
+
205
+ {/* Release Creation */}
206
+ <div className="bg-white p-4 rounded-lg shadow">
207
+ <div className="flex items-center justify-between mb-2">
208
+ <h2 className="font-semibold">2. Create Release</h2>
209
+ <button
210
+ onClick={() =>
211
+ createdPackageId &&
212
+ createRelease({
213
+ package_id: createdPackageId,
214
+ ...demoData.release,
215
+ })
216
+ }
217
+ disabled={!createdPackageId || Boolean(createdReleaseId)}
218
+ className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
219
+ >
220
+ {createdReleaseId ? "✓" : "Create"}
221
+ </button>
222
+ </div>
223
+ {releaseData && (
224
+ <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-32">
225
+ {JSON.stringify(releaseData, null, 2)}
226
+ </pre>
227
+ )}
228
+ </div>
229
+
230
+ {/* File Creation */}
231
+ <div className="bg-white p-4 rounded-lg shadow">
232
+ <div className="flex items-center justify-between mb-2">
233
+ <h2 className="font-semibold">3. Create Files</h2>
234
+ <button
235
+ onClick={() =>
236
+ createdReleaseId &&
237
+ Promise.all(
238
+ demoData.files.map((file) =>
239
+ createFile({
240
+ package_release_id: createdReleaseId,
241
+ ...file,
242
+ }),
243
+ ),
244
+ )
245
+ }
246
+ disabled={!createdReleaseId || Boolean(createdFileId)}
247
+ className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
248
+ >
249
+ {createdFileId ? "✓" : "Create"}
250
+ </button>
251
+ </div>
252
+ </div>
253
+
254
+ {/* Fork Package */}
255
+ <div className="bg-white p-4 rounded-lg shadow">
256
+ <div className="flex items-center justify-between mb-2">
257
+ <h2 className="font-semibold">4. Fork Package</h2>
258
+ <button
259
+ onClick={() =>
260
+ createdPackageId && forkPackage(createdPackageId)
261
+ }
262
+ disabled={!createdPackageId || isForking}
263
+ className="bg-green-500 text-white px-3 py-1 text-sm rounded hover:bg-green-600 disabled:bg-green-300"
264
+ >
265
+ {forkedPackageId ? "✓" : "Fork"}
266
+ </button>
267
+ </div>
268
+ {forkedPackageData && (
269
+ <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-32">
270
+ {JSON.stringify(forkedPackageData, null, 2)}
271
+ </pre>
272
+ )}
99
273
  </div>
100
- {packageData && (
101
- <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-40">
102
- {JSON.stringify(packageData, null, 2)}
103
- </pre>
104
- )}
105
274
  </div>
275
+ )}
106
276
 
107
- {/* Release Creation */}
108
- <div className="bg-white p-4 rounded-lg shadow">
109
- <div className="flex items-center justify-between mb-2">
110
- <h2 className="font-semibold">2. Create Release</h2>
111
- <button
112
- onClick={() =>
113
- createdPackageId &&
114
- createRelease({
115
- package_id: createdPackageId,
116
- ...demoData.release,
117
- })
118
- }
119
- disabled={!createdPackageId || Boolean(createdReleaseId)}
120
- className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
121
- >
122
- {createdReleaseId ? "✓" : "Create"}
123
- </button>
277
+ {/* Package info section shown when viewing an existing package */}
278
+ {packageNameWithVersion && packageData && (
279
+ <div className="bg-white p-4 rounded-lg shadow mb-4">
280
+ <h2 className="font-semibold mb-3">Package Information</h2>
281
+ <div className="grid grid-cols-2 gap-4">
282
+ <div>
283
+ <div className="text-sm font-medium mb-1">ID:</div>
284
+ <div className="text-sm text-gray-700">
285
+ {packageData.package_id}
286
+ </div>
287
+ </div>
288
+ <div>
289
+ <div className="text-sm font-medium mb-1">Name:</div>
290
+ <div className="text-sm text-gray-700">{packageData.name}</div>
291
+ </div>
292
+ <div>
293
+ <div className="text-sm font-medium mb-1">Description:</div>
294
+ <div className="text-sm text-gray-700">
295
+ {packageData.description || "No description"}
296
+ </div>
297
+ </div>
298
+ <div>
299
+ <div className="text-sm font-medium mb-1">Visibility:</div>
300
+ <div className="text-sm text-gray-700">
301
+ {packageData.is_private ? "Private" : "Public"}
302
+ </div>
303
+ </div>
124
304
  </div>
125
- {releaseData && (
126
- <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-40">
127
- {JSON.stringify(releaseData, null, 2)}
128
- </pre>
129
- )}
130
305
  </div>
306
+ )}
131
307
 
132
- {/* File Creation */}
308
+ {/* Second row: package data exploration */}
309
+ <div className="grid grid-cols-2 gap-6">
310
+ {/* Package Files List */}
133
311
  <div className="bg-white p-4 rounded-lg shadow">
134
- <div className="flex items-center justify-between mb-2">
135
- <h2 className="font-semibold">3. Create Files</h2>
136
- <button
137
- onClick={() =>
138
- createdReleaseId &&
139
- Promise.all(
140
- demoData.files.map((file) =>
141
- createFile({
142
- package_release_id: createdReleaseId,
143
- ...file,
144
- }),
145
- ),
146
- )
147
- }
148
- disabled={!createdReleaseId || Boolean(createdFileId)}
149
- className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
150
- >
151
- {createdFileId ? "✓" : "Create"}
152
- </button>
312
+ <h2 className="font-semibold mb-3">Package Files</h2>
313
+ <div className="text-xs text-gray-600 mb-2">
314
+ Release ID: {createdReleaseId || "None"}
153
315
  </div>
154
- {fileData && (
155
- <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-40">
156
- {JSON.stringify(fileData, null, 2)}
157
- </pre>
316
+ {filesLoading ? (
317
+ <div className="text-sm text-gray-500">Loading files...</div>
318
+ ) : packageFiles && packageFiles.length > 0 ? (
319
+ <div className="divide-y">
320
+ {packageFiles.map((file) => (
321
+ <button
322
+ key={file.package_file_id}
323
+ onClick={() => setSelectedFileId(file.package_file_id)}
324
+ className={`text-left w-full py-2 px-1 text-sm hover:bg-gray-50 ${
325
+ selectedFileId === file.package_file_id ? "bg-blue-50" : ""
326
+ }`}
327
+ >
328
+ {file.file_path}
329
+ </button>
330
+ ))}
331
+ </div>
332
+ ) : (
333
+ <div className="text-sm text-gray-500">
334
+ {createdReleaseId
335
+ ? "No files found. Files array length: " +
336
+ (packageFiles ? packageFiles.length : "undefined")
337
+ : "Create a release and files first"}
338
+ </div>
158
339
  )}
159
340
  </div>
160
341
 
161
- {/* Fork Package */}
342
+ {/* Selected File Content */}
162
343
  <div className="bg-white p-4 rounded-lg shadow">
163
- <div className="flex items-center justify-between mb-2">
164
- <h2 className="font-semibold">4. Fork Package</h2>
165
- <button
166
- onClick={() => createdPackageId && forkPackage(createdPackageId)}
167
- disabled={!createdPackageId || isForking}
168
- className="bg-green-500 text-white px-3 py-1 text-sm rounded hover:bg-green-600 disabled:bg-green-300"
169
- >
170
- {forkedPackageId ? "✓" : "Fork"}
171
- </button>
172
- </div>
173
- {forkedPackageData && (
174
- <pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-40">
175
- {JSON.stringify(forkedPackageData, null, 2)}
176
- </pre>
344
+ <h2 className="font-semibold mb-3">File Content</h2>
345
+ {selectedFileData ? (
346
+ <div>
347
+ <div className="text-xs text-gray-500 mb-2">
348
+ {selectedFileData.file_path}
349
+ </div>
350
+ <pre className="text-xs bg-gray-50 p-3 rounded overflow-auto border max-h-80">
351
+ {selectedFileData.content_text}
352
+ </pre>
353
+ </div>
354
+ ) : (
355
+ <div className="text-sm text-gray-500">
356
+ {packageFiles && packageFiles.length > 0
357
+ ? "Select a file to view its content"
358
+ : "Create files first"}
359
+ </div>
177
360
  )}
178
361
  </div>
179
362
  </div>
@@ -0,0 +1,38 @@
1
+ import RepoPageContent from "@/components/ViewPackagePage/components/repo-page-content"
2
+ import SimulatePage from "@/components/ViewPackagePage/simulate-page"
3
+ import { usePackageByName } from "@/hooks/use-package-by-package-name"
4
+ import { usePackageFiles } from "@/hooks/use-package-files"
5
+ import { usePackageRelease } from "@/hooks/use-package-release"
6
+ import { useLocation } from "wouter"
7
+
8
+ export const ViewPackagePage = () => {
9
+ // Get the current path and extract author/packageName
10
+ const [location] = useLocation()
11
+ const pathParts = location.split("/")
12
+ const author = pathParts[2]
13
+ const urlPackageName = pathParts[3]
14
+ const fullPackageName = `${author}/${urlPackageName}`
15
+
16
+ const { data: packageInfo } = usePackageByName(fullPackageName)
17
+
18
+ const { data: packageRelease } = usePackageRelease({
19
+ is_latest: true,
20
+ package_name: fullPackageName,
21
+ })
22
+
23
+ const { data: packageFiles } = usePackageFiles(
24
+ packageRelease?.package_release_id,
25
+ )
26
+
27
+ return (
28
+ <RepoPageContent
29
+ packageFiles={packageFiles as any}
30
+ packageInfo={packageInfo as any}
31
+ importantFilePaths={["README.md", "LICENSE", "package.json"]}
32
+ onFileClicked={() => {}}
33
+ onDirectoryClicked={() => {}}
34
+ onExportClicked={() => {}}
35
+ onEditClicked={() => {}}
36
+ />
37
+ )
38
+ }