@tscircuit/fake-snippets 0.0.106 → 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 (43) hide show
  1. package/CLAUDE.md +92 -0
  2. package/api/generated-index.js +84 -25
  3. package/biome.json +7 -1
  4. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +0 -15
  5. package/bun-tests/fake-snippets-api/routes/package_builds/list.test.ts +0 -12
  6. package/dist/bundle.js +360 -434
  7. package/dist/index.d.ts +26 -15
  8. package/dist/index.js +40 -21
  9. package/dist/schema.d.ts +32 -24
  10. package/dist/schema.js +7 -5
  11. package/fake-snippets-api/lib/db/db-client.ts +19 -1
  12. package/fake-snippets-api/lib/db/schema.ts +6 -3
  13. package/fake-snippets-api/lib/db/seed.ts +23 -12
  14. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +0 -3
  15. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +3 -0
  16. package/fake-snippets-api/routes/api/package_builds/list.ts +0 -1
  17. package/package.json +3 -2
  18. package/src/App.tsx +27 -9
  19. package/src/components/FileSidebar.tsx +14 -159
  20. package/src/components/PackageBreadcrumb.tsx +111 -0
  21. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +1 -1
  22. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +18 -2
  23. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +18 -8
  24. package/src/components/preview/BuildsList.tsx +84 -167
  25. package/src/components/preview/ConnectedPackagesList.tsx +92 -62
  26. package/src/components/preview/ConnectedRepoOverview.tsx +171 -155
  27. package/src/components/preview/{ConnectedRepoDashboard.tsx → PackageReleasesDashboard.tsx} +31 -69
  28. package/src/components/preview/index.tsx +20 -154
  29. package/src/hooks/use-package-builds.ts +0 -48
  30. package/src/hooks/use-package-release-by-id-or-version.ts +36 -0
  31. package/src/hooks/use-package-release.ts +32 -0
  32. package/src/index.css +24 -0
  33. package/src/lib/utils/isUuid.ts +5 -0
  34. package/src/lib/utils/transformFilesToTreeData.tsx +195 -0
  35. package/src/pages/404.tsx +3 -5
  36. package/src/pages/preview-release.tsx +269 -0
  37. package/src/pages/release-builds.tsx +99 -0
  38. package/src/pages/release-detail.tsx +120 -0
  39. package/src/pages/releases.tsx +55 -0
  40. package/fake-snippets-api/routes/api/package_builds/latest.ts +0 -109
  41. package/src/hooks/use-snippets-base-api-url.ts +0 -3
  42. package/src/pages/preview-build.tsx +0 -380
  43. package/src/pages/view-connected-repo.tsx +0 -49
@@ -1,57 +1,50 @@
1
- import { useState } from "react"
2
1
  import { Button } from "@/components/ui/button"
3
2
  import { Badge } from "@/components/ui/badge"
4
- import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
5
3
  import {
6
4
  DropdownMenu,
7
5
  DropdownMenuContent,
8
6
  DropdownMenuItem,
9
7
  DropdownMenuTrigger,
10
8
  } from "@/components/ui/dropdown-menu"
11
- import {
12
- Activity,
13
- List,
14
- Github,
15
- MoreHorizontal,
16
- Zap,
17
- Clock,
18
- GitBranch,
19
- Eye,
20
- } from "lucide-react"
9
+ import { MoreHorizontal, Clock, GitBranch, Eye } from "lucide-react"
10
+ import { GitHubLogoIcon } from "@radix-ui/react-icons"
21
11
  import { useLocation } from "wouter"
22
- import { ConnectedRepoOverview } from "./ConnectedRepoOverview"
23
12
  import { BuildsList } from "./BuildsList"
24
13
  import Header from "../Header"
25
14
  import { formatTimeAgo } from "@/lib/utils/formatTimeAgo"
26
15
  import { getBuildStatus } from "."
27
16
  import { PrefetchPageLink } from "../PrefetchPageLink"
17
+ import { PackageBreadcrumb } from "../PackageBreadcrumb"
28
18
  import {
29
19
  Package,
30
20
  PackageBuild,
31
21
  PackageRelease,
32
22
  } from "fake-snippets-api/lib/db/schema"
33
23
 
34
- export const ConnectedRepoDashboard = ({
24
+ export const PackageReleasesDashboard = ({
25
+ latestRelease,
35
26
  latestBuild,
36
27
  pkg,
37
- packageRelease,
38
28
  }: {
39
- latestBuild: PackageBuild
29
+ latestRelease: PackageRelease
30
+ latestBuild: PackageBuild | null
40
31
  pkg: Package
41
- packageRelease: PackageRelease
42
32
  }) => {
43
- const [activeTab, setActiveTab] = useState("overview")
44
33
  const [, setLocation] = useLocation()
45
- const handleSelectBuild = (build: PackageBuild) => {
46
- setLocation(`/build/${build.package_build_id}`)
47
- setActiveTab("overview")
48
- }
49
34
  const { status, label } = getBuildStatus(latestBuild)
50
35
 
51
36
  return (
52
37
  <>
53
38
  <Header />
54
39
  <div className="min-h-screen bg-white">
40
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pt-4">
41
+ <PackageBreadcrumb
42
+ author={pkg.name.split("/")[0]}
43
+ packageName={pkg.name}
44
+ unscopedName={pkg.unscoped_name}
45
+ currentPage="releases"
46
+ />
47
+ </div>
55
48
  {/* Project Header */}
56
49
  <div className="bg-gray-50 border-b md:py-10">
57
50
  <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
@@ -70,7 +63,7 @@ export const ConnectedRepoDashboard = ({
70
63
  href={"/" + pkg.name}
71
64
  className="text-2xl font-bold text-gray-900 truncate"
72
65
  >
73
- {pkg.unscoped_name}
66
+ {pkg.name}
74
67
  </PrefetchPageLink>
75
68
  <Badge
76
69
  variant={
@@ -101,22 +94,26 @@ export const ConnectedRepoDashboard = ({
101
94
  className="flex cursor-pointer items-center gap-1"
102
95
  onClick={() =>
103
96
  window?.open(
104
- `https://github.com/${pkg.github_repo_full_name}/tree/${latestBuild.branch_name || "main"}`,
97
+ `https://github.com/${pkg.github_repo_full_name}/tree/${latestRelease?.branch_name || "main"}`,
105
98
  "_blank",
106
99
  )
107
100
  }
108
101
  >
109
102
  <GitBranch className="w-4 h-4 flex-shrink-0" />
110
103
  <span className="truncate">
111
- {latestBuild.branch_name || "main"}
104
+ {latestRelease?.branch_name || "main"}
112
105
  </span>
113
106
  </div>
114
107
  <div className="flex items-center gap-1">
115
108
  <Clock className="w-4 h-4 flex-shrink-0" />
116
109
  <span>
117
- <time dateTime={latestBuild.created_at}>
118
- Last built {formatTimeAgo(latestBuild.created_at)}
119
- </time>
110
+ {latestBuild?.created_at ? (
111
+ <time dateTime={latestBuild.created_at}>
112
+ Last built {formatTimeAgo(latestBuild.created_at)}
113
+ </time>
114
+ ) : (
115
+ "No builds yet"
116
+ )}
120
117
  </span>
121
118
  </div>
122
119
  </div>
@@ -135,18 +132,18 @@ export const ConnectedRepoDashboard = ({
135
132
  )
136
133
  }
137
134
  >
138
- <Github className="w-4 h-4" />
135
+ <GitHubLogoIcon className="w-4 h-4" />
139
136
  <span className="hidden sm:inline">Repository</span>
140
137
  <span className="sm:hidden">Repository</span>
141
138
  </Button>
142
- {latestBuild.preview_url && (
139
+ {latestBuild && (
143
140
  <Button
144
141
  variant="outline"
145
142
  size="sm"
146
143
  className="flex items-center gap-2 justify-center min-w-[120px] h-9"
147
144
  onClick={() =>
148
145
  window.open(
149
- `/build/${latestBuild.package_build_id}/preview`,
146
+ `/${pkg.name}/releases/${latestBuild?.package_release_id}/preview`,
150
147
  "_blank",
151
148
  )
152
149
  }
@@ -156,14 +153,6 @@ export const ConnectedRepoDashboard = ({
156
153
  <span className="sm:hidden">Preview</span>
157
154
  </Button>
158
155
  )}
159
- <Button
160
- size="sm"
161
- className="flex items-center gap-2 justify-center min-w-[120px] h-9 bg-black text-white"
162
- >
163
- <Zap className="w-4 h-4" />
164
- <span className="hidden sm:inline">Rebuild</span>
165
- <span className="sm:hidden">Rebuild</span>
166
- </Button>
167
156
  <DropdownMenu>
168
157
  <DropdownMenuTrigger asChild>
169
158
  <Button
@@ -212,36 +201,9 @@ export const ConnectedRepoDashboard = ({
212
201
 
213
202
  {/* Main Content */}
214
203
  <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
215
- <Tabs
216
- value={activeTab}
217
- onValueChange={setActiveTab}
218
- className="space-y-6"
219
- >
220
- <TabsList className="grid w-full grid-cols-2 lg:w-auto lg:grid-cols-2">
221
- <TabsTrigger value="overview" className="flex items-center gap-2">
222
- <Activity className="w-4 h-4" />
223
- Overview
224
- </TabsTrigger>
225
- <TabsTrigger value="builds" className="flex items-center gap-2">
226
- <List className="w-4 h-4" />
227
- Builds
228
- </TabsTrigger>
229
- </TabsList>
230
-
231
- <TabsContent value="overview" className="space-y-6">
232
- {latestBuild && (
233
- <ConnectedRepoOverview
234
- build={latestBuild}
235
- pkg={pkg}
236
- packageRelease={packageRelease}
237
- />
238
- )}
239
- </TabsContent>
240
-
241
- <TabsContent value="builds" className="space-y-6">
242
- <BuildsList pkg={pkg} onSelectBuild={handleSelectBuild} />
243
- </TabsContent>
244
- </Tabs>
204
+ <div className="space-y-6">
205
+ <BuildsList pkg={pkg} />
206
+ </div>
245
207
  </div>
246
208
  </div>
247
209
  </>
@@ -1,13 +1,17 @@
1
1
  export { ConnectedRepoOverview } from "./ConnectedRepoOverview"
2
2
  export { BuildsList } from "./BuildsList"
3
- export { ConnectedRepoDashboard } from "./ConnectedRepoDashboard"
4
- import {
5
- Package,
6
- PackageBuild,
7
- PackageRelease,
8
- } from "fake-snippets-api/lib/db/schema"
3
+ export { PackageReleasesDashboard } from "./PackageReleasesDashboard"
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) => {
6
+ export const getBuildStatus = (
7
+ build?: PackageBuild | null,
8
+ ): {
9
+ status: "pending" | "building" | "success" | "error" | "queued"
10
+ label: string
11
+ } => {
12
+ if (!build) {
13
+ return { status: "pending", label: "No builds" }
14
+ }
11
15
  if (
12
16
  build?.build_error ||
13
17
  build?.transpilation_error ||
@@ -22,154 +26,20 @@ export const getBuildStatus = (build: PackageBuild) => {
22
26
  ) {
23
27
  return { status: "building", label: "Building" }
24
28
  }
25
- 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
+ ) {
26
38
  return { status: "success", label: "Ready" }
27
39
  }
28
40
  return { status: "queued", label: "Queued" }
29
41
  }
30
42
 
31
- export const MOCK_DEPLOYMENTS: PackageBuild[] = [
32
- {
33
- package_build_id: "pb_1a2b3c4d",
34
- package_release_id: "pr_5e6f7g8h",
35
- created_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
36
- transpilation_in_progress: false,
37
- transpilation_started_at: new Date(
38
- Date.now() - 1000 * 60 * 35,
39
- ).toISOString(),
40
- transpilation_completed_at: new Date(
41
- Date.now() - 1000 * 60 * 32,
42
- ).toISOString(),
43
- transpilation_logs: [],
44
- transpilation_error: null,
45
- circuit_json_build_in_progress: false,
46
- circuit_json_build_started_at: new Date(
47
- Date.now() - 1000 * 60 * 32,
48
- ).toISOString(),
49
- circuit_json_build_completed_at: new Date(
50
- Date.now() - 1000 * 60 * 30,
51
- ).toISOString(),
52
- circuit_json_build_logs: [],
53
- circuit_json_build_error: null,
54
- build_in_progress: false,
55
- build_started_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
56
- build_completed_at: new Date(Date.now() - 1000 * 60 * 25).toISOString(),
57
- build_error: null,
58
- build_error_last_updated_at: new Date(
59
- Date.now() - 1000 * 60 * 25,
60
- ).toISOString(),
61
- build_logs: null,
62
- preview_url: "https://preview.tscircuit.com/pb_1a2b3c4d",
63
- branch_name: "main",
64
- commit_message: "Add new LED component with improved brightness control",
65
- commit_author: "john.doe",
66
- },
67
- {
68
- package_build_id: "pb_9i8j7k6l",
69
- package_release_id: "pr_5m4n3o2p",
70
- created_at: new Date(Date.now() - 1000 * 60 * 60 * 2).toISOString(),
71
- transpilation_in_progress: false,
72
- transpilation_started_at: new Date(
73
- Date.now() - 1000 * 60 * 60 * 2,
74
- ).toISOString(),
75
- transpilation_completed_at: new Date(
76
- Date.now() - 1000 * 60 * 60 * 2 + 1000 * 60 * 3,
77
- ).toISOString(),
78
- transpilation_logs: [],
79
- transpilation_error: null,
80
- circuit_json_build_in_progress: true,
81
- circuit_json_build_started_at: new Date(
82
- Date.now() - 1000 * 60 * 5,
83
- ).toISOString(),
84
- circuit_json_build_completed_at: null,
85
- circuit_json_build_logs: [],
86
- circuit_json_build_error: null,
87
- build_in_progress: false,
88
- build_started_at: null,
89
- build_completed_at: null,
90
- build_error: null,
91
- build_error_last_updated_at: new Date(
92
- Date.now() - 1000 * 60 * 60 * 2,
93
- ).toISOString(),
94
- build_logs: null,
95
- preview_url: null,
96
- branch_name: "feature/resistor-update",
97
- commit_message: "Update resistor component with new tolerance values",
98
- commit_author: "jane.smith",
99
- },
100
- {
101
- package_build_id: "pb_1q2w3e4r",
102
- package_release_id: "pr_5t6y7u8i",
103
- created_at: new Date(Date.now() - 1000 * 60 * 60 * 6).toISOString(),
104
- transpilation_in_progress: false,
105
- transpilation_started_at: new Date(
106
- Date.now() - 1000 * 60 * 60 * 6,
107
- ).toISOString(),
108
- transpilation_completed_at: new Date(
109
- Date.now() - 1000 * 60 * 60 * 6 + 1000 * 60 * 2,
110
- ).toISOString(),
111
- transpilation_logs: [],
112
- transpilation_error:
113
- "TypeScript compilation failed: Cannot find module 'missing-dependency'",
114
- circuit_json_build_in_progress: false,
115
- circuit_json_build_started_at: null,
116
- circuit_json_build_completed_at: null,
117
- circuit_json_build_logs: [],
118
- circuit_json_build_error: null,
119
- build_in_progress: false,
120
- build_started_at: null,
121
- build_completed_at: null,
122
- build_error: null,
123
- build_error_last_updated_at: new Date(
124
- Date.now() - 1000 * 60 * 60 * 6,
125
- ).toISOString(),
126
- build_logs: null,
127
- preview_url: null,
128
- branch_name: "hotfix/critical-bug",
129
- commit_message: "Fix critical issue with capacitor placement",
130
- commit_author: "alex.wilson",
131
- },
132
- {
133
- package_build_id: "pb_9o8i7u6y",
134
- package_release_id: "pr_5t4r3e2w",
135
- created_at: new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString(),
136
- transpilation_in_progress: false,
137
- transpilation_started_at: new Date(
138
- Date.now() - 1000 * 60 * 60 * 24,
139
- ).toISOString(),
140
- transpilation_completed_at: new Date(
141
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 4,
142
- ).toISOString(),
143
- transpilation_logs: [],
144
- transpilation_error: null,
145
- circuit_json_build_in_progress: false,
146
- circuit_json_build_started_at: new Date(
147
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 4,
148
- ).toISOString(),
149
- circuit_json_build_completed_at: new Date(
150
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 8,
151
- ).toISOString(),
152
- circuit_json_build_logs: [],
153
- circuit_json_build_error: null,
154
- build_in_progress: false,
155
- build_started_at: new Date(
156
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 8,
157
- ).toISOString(),
158
- build_completed_at: new Date(
159
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 12,
160
- ).toISOString(),
161
- build_error: null,
162
- build_error_last_updated_at: new Date(
163
- Date.now() - 1000 * 60 * 60 * 24 + 1000 * 60 * 12,
164
- ).toISOString(),
165
- build_logs: null,
166
- preview_url: "https://preview.tscircuit.com/pb_9o8i7u6y",
167
- branch_name: "main",
168
- commit_message: "Initial project setup with basic components",
169
- commit_author: "sarah.johnson",
170
- },
171
- ]
172
-
173
43
  export const StatusIcon = ({ status }: { status: string }) => {
174
44
  switch (status) {
175
45
  case "success":
@@ -182,7 +52,3 @@ export const StatusIcon = ({ status }: { status: string }) => {
182
52
  return <Clock className="w-4 h-4 text-gray-500" />
183
53
  }
184
54
  }
185
-
186
- export const getLatestBuildForPackage = (pkg: Package): PackageBuild => {
187
- return MOCK_DEPLOYMENTS[0]
188
- }
@@ -85,51 +85,3 @@ export const usePackageBuild = (packageBuildId: string | null) => {
85
85
  },
86
86
  )
87
87
  }
88
-
89
- export const useLatestPackageBuild = (
90
- params: { package_id?: string; package_release_id?: string } | null,
91
- ) => {
92
- const axios = useAxios()
93
-
94
- return useQuery<PackageBuild | null, Error & { status: number }>(
95
- ["latestPackageBuild", params],
96
- async () => {
97
- if (!params || (!params.package_id && !params.package_release_id)) {
98
- throw new Error(
99
- "Either package_id or package_release_id must be provided",
100
- )
101
- }
102
-
103
- const { data } = await axios.get<{ package_build: PackageBuild }>(
104
- "/package_builds/latest",
105
- {
106
- params: {
107
- ...(params.package_id ? { package_id: params.package_id } : {}),
108
- ...(params.package_release_id
109
- ? { package_release_id: params.package_release_id }
110
- : {}),
111
- },
112
- },
113
- )
114
-
115
- return data.package_build
116
- },
117
- {
118
- enabled: Boolean(
119
- params && (params.package_id || params.package_release_id),
120
- ),
121
- retry: false,
122
- refetchOnWindowFocus: false,
123
- },
124
- )
125
- }
126
-
127
- export const useLatestPackageBuildByPackageId = (packageId: string | null) => {
128
- return useLatestPackageBuild(packageId ? { package_id: packageId } : null)
129
- }
130
-
131
- export const useLatestPackageBuildByReleaseId = (releaseId?: string | null) => {
132
- return useLatestPackageBuild(
133
- releaseId ? { package_release_id: releaseId } : null,
134
- )
135
- }
@@ -0,0 +1,36 @@
1
+ import {
2
+ usePackageReleaseById,
3
+ usePackageReleaseByNameAndVersion,
4
+ } from "./use-package-release"
5
+ import { isUuid } from "@/lib/utils/isUuid"
6
+
7
+ export const usePackageReleaseByIdOrVersion = (
8
+ releaseIdOrVersion: string | null,
9
+ packageName?: string | null,
10
+ ) => {
11
+ const isReleaseIdUuid = releaseIdOrVersion
12
+ ? isUuid(releaseIdOrVersion)
13
+ : false
14
+
15
+ // If it's a UUID, use the ID-based hook
16
+ const releaseByIdQuery = usePackageReleaseById(
17
+ isReleaseIdUuid ? releaseIdOrVersion : null,
18
+ )
19
+
20
+ // If it's not a UUID and we have a package name, construct the version-based query
21
+ const packageNameWithVersion =
22
+ !isReleaseIdUuid && packageName && releaseIdOrVersion
23
+ ? `${packageName}@${releaseIdOrVersion}`
24
+ : null
25
+
26
+ const releaseByVersionQuery = usePackageReleaseByNameAndVersion(
27
+ packageNameWithVersion,
28
+ )
29
+
30
+ // Return the appropriate query result
31
+ if (isReleaseIdUuid) {
32
+ return releaseByIdQuery
33
+ } else {
34
+ return releaseByVersionQuery
35
+ }
36
+ }
@@ -90,3 +90,35 @@ export const useLatestPackageRelease = (
90
90
 
91
91
  return usePackageRelease(query)
92
92
  }
93
+
94
+ export const usePackageReleasesByPackageId = (packageId: string | null) => {
95
+ const axios = useAxios()
96
+
97
+ return useQuery<PackageRelease[], Error & { status: number }>(
98
+ ["packageReleases", packageId],
99
+ async () => {
100
+ if (!packageId) {
101
+ throw new Error("package_id is required")
102
+ }
103
+
104
+ const { data } = await axios.post<{ package_releases: PackageRelease[] }>(
105
+ "/package_releases/list",
106
+ {
107
+ package_id: packageId,
108
+ },
109
+ )
110
+
111
+ if (!data.package_releases) {
112
+ return []
113
+ }
114
+
115
+ return data.package_releases
116
+ },
117
+ {
118
+ enabled: Boolean(packageId),
119
+ retry: false,
120
+ refetchOnWindowFocus: false,
121
+ staleTime: 0,
122
+ },
123
+ )
124
+ }
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,5 @@
1
+ export function isUuid(value: string): boolean {
2
+ const uuidRegex =
3
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
4
+ return uuidRegex.test(value) || value.startsWith("package_release_")
5
+ }