@tscircuit/fake-snippets 0.0.107 → 0.0.108

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 (35) hide show
  1. package/api/generated-index.js +82 -22
  2. package/biome.json +7 -1
  3. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +0 -15
  4. package/bun-tests/fake-snippets-api/routes/package_builds/list.test.ts +0 -12
  5. package/dist/bundle.js +23 -23
  6. package/dist/index.d.ts +21 -15
  7. package/dist/index.js +17 -17
  8. package/dist/schema.d.ts +24 -24
  9. package/dist/schema.js +5 -5
  10. package/fake-snippets-api/lib/db/db-client.ts +10 -1
  11. package/fake-snippets-api/lib/db/schema.ts +3 -3
  12. package/fake-snippets-api/lib/db/seed.ts +6 -9
  13. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +0 -3
  14. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +3 -0
  15. package/package.json +1 -1
  16. package/src/App.tsx +12 -9
  17. package/src/components/FileSidebar.tsx +14 -159
  18. package/src/components/PackageBreadcrumb.tsx +1 -1
  19. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +1 -1
  20. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +18 -2
  21. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +1 -1
  22. package/src/components/preview/BuildsList.tsx +20 -9
  23. package/src/components/preview/ConnectedPackagesList.tsx +73 -60
  24. package/src/components/preview/ConnectedRepoOverview.tsx +160 -154
  25. package/src/components/preview/PackageReleasesDashboard.tsx +11 -5
  26. package/src/components/preview/index.tsx +16 -153
  27. package/src/index.css +24 -0
  28. package/src/lib/utils/transformFilesToTreeData.tsx +195 -0
  29. package/src/pages/404.tsx +3 -5
  30. package/src/pages/preview-release.tsx +269 -0
  31. package/src/pages/release-builds.tsx +0 -8
  32. package/src/pages/release-detail.tsx +17 -15
  33. package/src/pages/releases.tsx +5 -1
  34. package/src/hooks/use-snippets-base-api-url.ts +0 -3
  35. package/src/pages/preview-build.tsx +0 -380
@@ -1,13 +1,14 @@
1
1
  export { ConnectedRepoOverview } from "./ConnectedRepoOverview"
2
2
  export { BuildsList } from "./BuildsList"
3
3
  export { PackageReleasesDashboard } from "./PackageReleasesDashboard"
4
- import {
5
- Package,
6
- PackageBuild,
7
- PackageRelease,
8
- } from "fake-snippets-api/lib/db/schema"
4
+ import { PackageBuild } from "fake-snippets-api/lib/db/schema"
9
5
  import { Clock, CheckCircle, AlertCircle, Loader2 } from "lucide-react"
10
- export const getBuildStatus = (build: PackageBuild | null) => {
6
+ export const getBuildStatus = (
7
+ build?: PackageBuild | null,
8
+ ): {
9
+ status: "pending" | "building" | "success" | "error" | "queued"
10
+ label: string
11
+ } => {
11
12
  if (!build) {
12
13
  return { status: "pending", label: "No builds" }
13
14
  }
@@ -25,154 +26,20 @@ export const getBuildStatus = (build: PackageBuild | null) => {
25
26
  ) {
26
27
  return { status: "building", label: "Building" }
27
28
  }
28
- if (build?.build_completed_at && build?.transpilation_completed_at) {
29
+ if (
30
+ !build?.build_error &&
31
+ !build?.transpilation_error &&
32
+ !build?.circuit_json_build_error &&
33
+ !build?.build_in_progress &&
34
+ !build?.transpilation_in_progress &&
35
+ !build?.circuit_json_build_in_progress &&
36
+ build?.transpilation_completed_at
37
+ ) {
29
38
  return { status: "success", label: "Ready" }
30
39
  }
31
40
  return { status: "queued", label: "Queued" }
32
41
  }
33
42
 
34
- export const MOCK_PACKAGE_BUILDS: PackageBuild[] = [
35
- {
36
- package_build_id: "pb_1a2b3c4d",
37
- package_release_id: "pr_5e6f7g8h",
38
- created_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
39
- transpilation_in_progress: false,
40
- transpilation_started_at: new Date(
41
- Date.now() - 1000 * 60 * 35,
42
- ).toISOString(),
43
- transpilation_completed_at: new Date(
44
- Date.now() - 1000 * 60 * 32,
45
- ).toISOString(),
46
- transpilation_logs: [],
47
- transpilation_error: null,
48
- circuit_json_build_in_progress: false,
49
- circuit_json_build_started_at: new Date(
50
- Date.now() - 1000 * 60 * 32,
51
- ).toISOString(),
52
- circuit_json_build_completed_at: new Date(
53
- Date.now() - 1000 * 60 * 30,
54
- ).toISOString(),
55
- circuit_json_build_logs: [],
56
- circuit_json_build_error: null,
57
- build_in_progress: false,
58
- build_started_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
59
- build_completed_at: new Date(Date.now() - 1000 * 60 * 25).toISOString(),
60
- build_error: null,
61
- build_error_last_updated_at: new Date(
62
- Date.now() - 1000 * 60 * 25,
63
- ).toISOString(),
64
- build_logs: null,
65
- preview_url: "https://preview.tscircuit.com/pb_1a2b3c4d",
66
- branch_name: "main",
67
- commit_message: "Add new LED component with improved brightness control",
68
- commit_author: "john.doe",
69
- },
70
- {
71
- package_build_id: "pb_9i8j7k6l",
72
- package_release_id: "pr_5m4n3o2p",
73
- created_at: new Date(Date.now() - 1000 * 60 * 60 * 2).toISOString(),
74
- transpilation_in_progress: false,
75
- transpilation_started_at: new Date(
76
- Date.now() - 1000 * 60 * 60 * 2,
77
- ).toISOString(),
78
- transpilation_completed_at: new Date(
79
- Date.now() - 1000 * 60 * 60 * 2 + 1000 * 60 * 3,
80
- ).toISOString(),
81
- transpilation_logs: [],
82
- transpilation_error: null,
83
- circuit_json_build_in_progress: true,
84
- circuit_json_build_started_at: new Date(
85
- Date.now() - 1000 * 60 * 5,
86
- ).toISOString(),
87
- circuit_json_build_completed_at: null,
88
- circuit_json_build_logs: [],
89
- circuit_json_build_error: null,
90
- build_in_progress: false,
91
- build_started_at: null,
92
- build_completed_at: null,
93
- build_error: null,
94
- build_error_last_updated_at: new Date(
95
- Date.now() - 1000 * 60 * 60 * 2,
96
- ).toISOString(),
97
- build_logs: null,
98
- preview_url: null,
99
- branch_name: "feature/resistor-update",
100
- commit_message: "Update resistor component with new tolerance values",
101
- commit_author: "jane.smith",
102
- },
103
- {
104
- package_build_id: "pb_1q2w3e4r",
105
- package_release_id: "pr_5t6y7u8i",
106
- created_at: new Date(Date.now() - 1000 * 60 * 60 * 6).toISOString(),
107
- transpilation_in_progress: false,
108
- transpilation_started_at: new Date(
109
- Date.now() - 1000 * 60 * 60 * 6,
110
- ).toISOString(),
111
- transpilation_completed_at: new Date(
112
- Date.now() - 1000 * 60 * 60 * 6 + 1000 * 60 * 2,
113
- ).toISOString(),
114
- transpilation_logs: [],
115
- transpilation_error:
116
- "TypeScript compilation failed: Cannot find module 'missing-dependency'",
117
- circuit_json_build_in_progress: false,
118
- circuit_json_build_started_at: null,
119
- circuit_json_build_completed_at: null,
120
- circuit_json_build_logs: [],
121
- circuit_json_build_error: null,
122
- build_in_progress: false,
123
- build_started_at: null,
124
- build_completed_at: null,
125
- build_error: null,
126
- build_error_last_updated_at: new Date(
127
- Date.now() - 1000 * 60 * 60 * 6,
128
- ).toISOString(),
129
- build_logs: null,
130
- preview_url: null,
131
- branch_name: "hotfix/critical-bug",
132
- commit_message: "Fix critical issue with capacitor placement",
133
- commit_author: "alex.wilson",
134
- },
135
- {
136
- package_build_id: "pb_9o8i7u6y",
137
- package_release_id: "pr_5t4r3e2w",
138
- created_at: new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString(),
139
- transpilation_in_progress: false,
140
- transpilation_started_at: new Date(
141
- Date.now() - 1000 * 60 * 60 * 24,
142
- ).toISOString(),
143
- transpilation_completed_at: new Date(
144
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 4,
145
- ).toISOString(),
146
- transpilation_logs: [],
147
- transpilation_error: null,
148
- circuit_json_build_in_progress: false,
149
- circuit_json_build_started_at: new Date(
150
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 4,
151
- ).toISOString(),
152
- circuit_json_build_completed_at: new Date(
153
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 8,
154
- ).toISOString(),
155
- circuit_json_build_logs: [],
156
- circuit_json_build_error: null,
157
- build_in_progress: false,
158
- build_started_at: new Date(
159
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 8,
160
- ).toISOString(),
161
- build_completed_at: new Date(
162
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 12,
163
- ).toISOString(),
164
- build_error: null,
165
- build_error_last_updated_at: new Date(
166
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 12,
167
- ).toISOString(),
168
- build_logs: null,
169
- preview_url: "https://preview.tscircuit.com/pb_9o8i7u6y",
170
- branch_name: "main",
171
- commit_message: "Initial project setup with basic components",
172
- commit_author: "sarah.johnson",
173
- },
174
- ]
175
-
176
43
  export const StatusIcon = ({ status }: { status: string }) => {
177
44
  switch (status) {
178
45
  case "success":
@@ -185,7 +52,3 @@ export const StatusIcon = ({ status }: { status: string }) => {
185
52
  return <Clock className="w-4 h-4 text-gray-500" />
186
53
  }
187
54
  }
188
-
189
- export const getLatestBuildForPackage = (pkg: Package): PackageBuild => {
190
- return MOCK_PACKAGE_BUILDS[0]
191
- }
package/src/index.css CHANGED
@@ -1,6 +1,7 @@
1
1
  @tailwind base;
2
2
  @tailwind components;
3
3
  @tailwind utilities;
4
+
4
5
  @layer base {
5
6
  :root {
6
7
  --radius: 0.5rem;
@@ -18,6 +19,10 @@
18
19
  -ms-overflow-style: none; /* IE and Edge */
19
20
  scrollbar-width: none; /* Firefox */
20
21
  }
22
+
23
+ .shiki {
24
+ @apply no-scrollbar;
25
+ }
21
26
  }
22
27
 
23
28
  .shiki {
@@ -82,3 +87,22 @@
82
87
  body {
83
88
  overflow-x: hidden;
84
89
  }
90
+
91
+ /* Subtle scrollbar styling for html and body */
92
+ html::-webkit-scrollbar,
93
+ body::-webkit-scrollbar {
94
+ width: 6px;
95
+ background-color: transparent;
96
+ }
97
+
98
+ html::-webkit-scrollbar-thumb,
99
+ body::-webkit-scrollbar-thumb {
100
+ background-color: rgba(215, 215, 215, 0.564);
101
+ border-radius: 8px;
102
+ transition: background-color 0.2s;
103
+ }
104
+
105
+ html::-webkit-scrollbar-thumb:hover,
106
+ body::-webkit-scrollbar-thumb:hover {
107
+ background-color: rgba(193, 193, 193, 0.455);
108
+ }
@@ -0,0 +1,195 @@
1
+ import type { TreeDataItem } from "@/components/ui/tree-view"
2
+ import type {
3
+ IRenameFileProps,
4
+ IDeleteFileProps,
5
+ } from "@/hooks/useFileManagement"
6
+ import { isHiddenFile } from "@/components/ViewPackagePage/utils/is-hidden-file"
7
+ import { File, Folder, MoreVertical, Pencil, Trash2 } from "lucide-react"
8
+ import {
9
+ DropdownMenu,
10
+ DropdownMenuContent,
11
+ DropdownMenuGroup,
12
+ DropdownMenuItem,
13
+ DropdownMenuTrigger,
14
+ } from "@/components/ui/dropdown-menu"
15
+ import { useToast } from "@/hooks/use-toast"
16
+
17
+ type FileName = string
18
+ type TreeNode = Omit<TreeDataItem, "children"> & {
19
+ children?: Record<string, TreeNode>
20
+ }
21
+ interface TransformFilesToTreeDataProps {
22
+ files: Record<FileName, string>
23
+ currentFile: FileName | null
24
+ renamingFile: string | null
25
+ handleRenameFile: (props: IRenameFileProps) => { fileRenamed: boolean }
26
+ handleDeleteFile: (props: IDeleteFileProps) => { fileDeleted: boolean }
27
+ setRenamingFile: (filename: string | null) => void
28
+ onFileSelect: (filename: FileName) => void
29
+ onFolderSelect: (folderPath: string) => void
30
+ canModifyFiles: boolean
31
+ setErrorMessage: (message: string) => void
32
+ setSelectedFolderForCreation: (folder: string | null) => void
33
+ }
34
+
35
+ export const transformFilesToTreeData = ({
36
+ files,
37
+ currentFile,
38
+ renamingFile,
39
+ handleRenameFile,
40
+ handleDeleteFile,
41
+ setRenamingFile,
42
+ onFileSelect,
43
+ onFolderSelect,
44
+ canModifyFiles,
45
+ setErrorMessage,
46
+ setSelectedFolderForCreation,
47
+ }: TransformFilesToTreeDataProps): TreeDataItem[] => {
48
+ const { toast } = useToast()
49
+ const root: Record<string, TreeNode> = {}
50
+
51
+ Object.keys(files).forEach((filePath) => {
52
+ const hasLeadingSlash = filePath.startsWith("/")
53
+ const pathSegments = (hasLeadingSlash ? filePath.slice(1) : filePath)
54
+ .trim()
55
+ .split("/")
56
+ let currentNode: Record<string, TreeNode> = root
57
+
58
+ pathSegments.forEach((segment, segmentIndex) => {
59
+ const isLeafNode = segmentIndex === pathSegments.length - 1
60
+ const ancestorPath = pathSegments.slice(0, segmentIndex).join("/")
61
+ const relativePath = ancestorPath ? `${ancestorPath}/${segment}` : segment
62
+ const absolutePath = hasLeadingSlash ? `/${relativePath}` : relativePath
63
+ const itemId = absolutePath
64
+
65
+ if (
66
+ !currentNode[segment] &&
67
+ (!isHiddenFile(relativePath) ||
68
+ isHiddenFile(
69
+ currentFile?.startsWith("/")
70
+ ? currentFile.slice(1)
71
+ : currentFile || "",
72
+ ))
73
+ ) {
74
+ currentNode[segment] = {
75
+ id: itemId,
76
+ name: segment,
77
+ isRenaming: renamingFile === itemId,
78
+ onRename: (newFilename: string) => {
79
+ const oldPath = itemId
80
+ const pathParts = oldPath.split("/").filter((part) => part !== "")
81
+ let newPath: string
82
+
83
+ if (pathParts.length > 1) {
84
+ const folderPath = pathParts.slice(0, -1).join("/")
85
+ newPath = folderPath + "/" + newFilename
86
+ } else {
87
+ newPath = newFilename
88
+ }
89
+
90
+ if (oldPath.startsWith("/") && !newPath.startsWith("/")) {
91
+ newPath = "/" + newPath
92
+ }
93
+
94
+ const { fileRenamed } = handleRenameFile({
95
+ oldFilename: itemId,
96
+ newFilename: newPath,
97
+ onError: (error) => {
98
+ toast({
99
+ title: `Error renaming file`,
100
+ description: error.message,
101
+ variant: "destructive",
102
+ })
103
+ },
104
+ })
105
+ if (fileRenamed) {
106
+ setRenamingFile(null)
107
+ }
108
+ },
109
+ onCancelRename: () => {
110
+ setRenamingFile(null)
111
+ },
112
+ icon: isLeafNode ? File : Folder,
113
+ onClick: isLeafNode
114
+ ? () => {
115
+ onFileSelect(absolutePath)
116
+ setSelectedFolderForCreation(null)
117
+ }
118
+ : () => onFolderSelect(absolutePath),
119
+ draggable: false,
120
+ droppable: !isLeafNode,
121
+ children: isLeafNode ? undefined : {},
122
+ actions: canModifyFiles ? (
123
+ <>
124
+ <DropdownMenu key={itemId}>
125
+ <DropdownMenuTrigger asChild>
126
+ <MoreVertical className="w-4 h-4 text-gray-500 hover:text-gray-700" />
127
+ </DropdownMenuTrigger>
128
+ <DropdownMenuContent
129
+ className="w-fit bg-white shadow-lg rounded-md border-4 z-[100] border-white"
130
+ style={{
131
+ position: "absolute",
132
+ top: "100%",
133
+ left: "0",
134
+ marginTop: "0.5rem",
135
+ width: "8rem",
136
+ padding: "0.01rem",
137
+ }}
138
+ >
139
+ <DropdownMenuGroup>
140
+ {isLeafNode && (
141
+ <DropdownMenuItem
142
+ onClick={() => {
143
+ setRenamingFile(itemId)
144
+ }}
145
+ className="flex items-center px-3 py-1 text-xs text-black hover:bg-gray-100 cursor-pointer"
146
+ >
147
+ <Pencil className="mr-2 h-3 w-3" />
148
+ Rename
149
+ </DropdownMenuItem>
150
+ )}
151
+ <DropdownMenuItem
152
+ onClick={() => {
153
+ const { fileDeleted } = handleDeleteFile({
154
+ filename: itemId,
155
+ onError: (error) => {
156
+ toast({
157
+ title: `Error deleting file ${itemId}`,
158
+ description: error.message,
159
+ })
160
+ },
161
+ })
162
+ if (fileDeleted) {
163
+ setErrorMessage("")
164
+ }
165
+ }}
166
+ className="flex items-center px-3 py-1 text-xs text-red-600 hover:bg-gray-100 cursor-pointer"
167
+ >
168
+ <Trash2 className="mr-2 h-3 w-3" />
169
+ Delete
170
+ </DropdownMenuItem>
171
+ </DropdownMenuGroup>
172
+ </DropdownMenuContent>
173
+ </DropdownMenu>
174
+ </>
175
+ ) : undefined,
176
+ }
177
+ }
178
+
179
+ if (!isLeafNode && currentNode[segment]?.children) {
180
+ currentNode = currentNode[segment].children
181
+ }
182
+ })
183
+ })
184
+
185
+ const convertToArray = (items: Record<string, TreeNode>): TreeDataItem[] => {
186
+ return Object.values(items).map((item) => ({
187
+ ...item,
188
+ children: item.children ? convertToArray(item.children) : undefined,
189
+ }))
190
+ }
191
+ return convertToArray(root).filter((x) => {
192
+ if (x.children?.length === 0) return false
193
+ return true
194
+ })
195
+ }
package/src/pages/404.tsx CHANGED
@@ -5,15 +5,13 @@ import { NotFound } from "@/components/NotFound"
5
5
 
6
6
  export function NotFoundPage({
7
7
  heading = "Page Not Found",
8
- }: { heading?: string }) {
8
+ subtitle = "The page you're looking for doesn't exist.",
9
+ }: { heading?: string; subtitle?: string }) {
9
10
  return (
10
11
  <div className="flex min-h-screen flex-col">
11
12
  <Helmet>
12
13
  <title>404 - {heading} | tscircuit</title>
13
- <meta
14
- name="description"
15
- content="The page you're looking for doesn't exist."
16
- />
14
+ <meta name="description" content={subtitle} />
17
15
  </Helmet>
18
16
  <Header2 />
19
17
  <NotFound heading={heading} />