@tscircuit/fake-snippets 0.0.108 → 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.
- package/.github/workflows/bun-formatcheck.yml +2 -2
- package/.github/workflows/bun-pver-release.yml +3 -3
- package/.github/workflows/bun-test.yml +1 -1
- package/.github/workflows/bun-typecheck.yml +2 -2
- package/.github/workflows/update-snapshots.yml +1 -1
- package/README.md +4 -0
- package/api/generated-index.js +37 -3
- package/biome.json +2 -1
- package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +31 -3
- package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
- package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
- package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
- package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
- package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
- package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +99 -0
- package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
- package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
- package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
- package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
- package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
- package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
- package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
- package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
- package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
- package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
- package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
- package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
- package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
- package/bun.lock +389 -450
- package/bunfig.toml +2 -1
- package/dist/bundle.js +1255 -625
- package/dist/index.d.ts +296 -4
- package/dist/index.js +325 -24
- package/dist/schema.d.ts +282 -1
- package/dist/schema.js +54 -2
- package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
- package/fake-snippets-api/lib/db/db-client.ts +214 -3
- package/fake-snippets-api/lib/db/schema.ts +62 -0
- package/fake-snippets-api/lib/db/seed.ts +100 -0
- package/fake-snippets-api/lib/middleware/with-session-auth.ts +1 -1
- package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
- package/fake-snippets-api/lib/public-mapping/public-map-org.ts +32 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
- package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
- package/fake-snippets-api/routes/api/orgs/create.ts +46 -0
- package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
- package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
- package/fake-snippets-api/routes/api/orgs/list_members.ts +67 -0
- package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
- package/fake-snippets-api/routes/api/orgs/update.ts +93 -0
- package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
- package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
- package/fake-snippets-api/routes/api/packages/create.ts +54 -10
- package/fake-snippets-api/routes/api/packages/get.ts +23 -0
- package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
- package/fake-snippets-api/routes/api/packages/list.ts +29 -2
- package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
- package/package.json +27 -24
- package/renovate.json +1 -1
- package/scripts/generate-sitemap.ts +1 -1
- package/src/App.tsx +29 -10
- package/src/ContextProviders.tsx +25 -2
- package/src/components/CircuitJsonImportDialog.tsx +1 -1
- package/src/components/CmdKMenu.tsx +281 -247
- package/src/components/DownloadButtonAndMenu.tsx +133 -36
- package/src/components/FileSidebar.tsx +41 -50
- package/src/components/Footer.tsx +8 -10
- package/src/components/Header.tsx +19 -32
- package/src/components/Header2.tsx +16 -32
- package/src/components/HeaderDropdown.tsx +13 -8
- package/src/components/HeaderLogin.tsx +44 -16
- package/src/components/HiddenFilesDropdown.tsx +0 -2
- package/src/components/NotFound.tsx +5 -5
- package/src/components/PackageBreadcrumb.tsx +6 -12
- package/src/components/PackageCard.tsx +0 -1
- package/src/components/PackageSearchResults.tsx +1 -1
- package/src/components/PrefetchPageLink.tsx +7 -1
- package/src/components/ProfileRouter.tsx +32 -0
- package/src/components/SearchComponent.tsx +12 -8
- package/src/components/UserCard.tsx +80 -0
- package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
- package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
- package/src/components/ViewPackagePage/components/important-files-view.tsx +174 -87
- package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -4
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -2
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -20
- package/src/components/ViewPackagePage/components/package-header.tsx +26 -37
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -19
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +33 -25
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
- 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/tab-views/pcb-view.tsx +1 -2
- package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
- package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
- package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
- package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
- package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
- package/src/components/dialogs/import-component-dialog.tsx +16 -9
- package/src/components/dialogs/import-package-dialog.tsx +3 -2
- package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
- package/src/components/organization/OrganizationCard.tsx +204 -0
- package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
- package/src/components/organization/OrganizationHeader.tsx +154 -0
- package/src/components/organization/OrganizationMembers.tsx +146 -0
- package/src/components/package-port/CodeAndPreview.tsx +32 -46
- package/src/components/package-port/CodeEditor.tsx +28 -31
- package/src/components/package-port/CodeEditorHeader.tsx +128 -63
- package/src/components/package-port/EditorNav.tsx +32 -49
- package/src/components/preview/ConnectedPackagesList.tsx +8 -8
- package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
- package/src/components/preview/PackageReleasesDashboard.tsx +53 -36
- package/src/components/ui/tree-view.tsx +6 -3
- package/src/hooks/use-add-org-member-mutation.ts +51 -0
- package/src/hooks/use-create-org-mutation.ts +38 -0
- package/src/hooks/use-create-package-mutation.ts +3 -0
- package/src/hooks/use-current-package-id.ts +5 -30
- package/src/hooks/use-current-package-info.ts +29 -5
- package/src/hooks/use-current-package-release.ts +4 -3
- package/src/hooks/use-download-zip.ts +2 -2
- package/src/hooks/use-global-store.ts +6 -4
- package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
- package/src/hooks/use-list-org-members.ts +27 -0
- package/src/hooks/use-list-user-orgs.ts +25 -0
- package/src/hooks/use-org-by-github-handle.ts +26 -0
- package/src/hooks/use-org.ts +24 -0
- package/src/hooks/use-organization.ts +42 -0
- package/src/hooks/use-package-as-snippet.ts +4 -2
- package/src/hooks/use-package-builds.ts +6 -2
- package/src/hooks/use-package-files.ts +5 -3
- package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
- package/src/hooks/use-package-release-images.ts +105 -0
- package/src/hooks/use-package-release.ts +2 -2
- package/src/hooks/use-package-stars.ts +80 -4
- package/src/hooks/use-preview-images.ts +6 -3
- package/src/hooks/use-remove-org-member-mutation.ts +32 -0
- package/src/hooks/use-update-ai-description-mutation.ts +42 -0
- package/src/hooks/use-update-org-mutation.ts +41 -0
- package/src/hooks/use-warn-user-on-page-change.ts +71 -4
- package/src/hooks/useFileManagement.ts +183 -35
- package/src/hooks/useOptimizedPackageFilesLoader.ts +136 -0
- package/src/hooks/usePackageFilesLoader.ts +2 -2
- package/src/hooks/useUpdatePackageFilesMutation.ts +15 -1
- 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/download-fns/download-kicad-files.ts +12 -11
- package/src/lib/normalize-svg-for-tile.ts +50 -0
- package/src/lib/posthog.ts +11 -9
- package/src/lib/react-query-api-failure-tracking.ts +148 -0
- package/src/lib/sentry.ts +14 -0
- package/src/lib/templates/blank-circuit-board-template.ts +0 -4
- package/src/lib/ts-lib-cache.ts +122 -7
- package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
- package/src/lib/utils/findTargetFile.ts +45 -10
- package/src/lib/utils/isComponentExported.ts +10 -0
- package/src/main.tsx +2 -1
- package/src/pages/authorize.tsx +0 -2
- package/src/pages/create-organization.tsx +168 -0
- package/src/pages/dashboard.tsx +38 -6
- package/src/pages/datasheet.tsx +1 -1
- package/src/pages/datasheets.tsx +3 -3
- package/src/pages/editor.tsx +4 -6
- package/src/pages/landing.tsx +6 -7
- package/src/pages/latest.tsx +3 -0
- package/src/pages/organization-profile.tsx +199 -0
- package/src/pages/organization-settings.tsx +566 -0
- package/src/pages/package-editor.tsx +21 -21
- package/src/pages/preview-release.tsx +76 -136
- package/src/pages/quickstart.tsx +159 -123
- package/src/pages/release-detail.tsx +119 -31
- package/src/pages/search.tsx +192 -57
- package/src/pages/settings-redirect.tsx +44 -0
- package/src/pages/trending.tsx +29 -20
- package/src/pages/user-profile.tsx +58 -7
- package/src/pages/view-package.tsx +21 -26
- package/vite.config.ts +9 -0
- package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
- package/src/components/Footer2.tsx +0 -100
- package/src/components/JLCPCBImportDialog.tsx +0 -280
- package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -115
- package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -27
- package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
- package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
- package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
- package/src/components/PageSearchComponent.tsx +0 -148
- 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/pages/package-builds.tsx +0 -33
- package/src/pages/settings.tsx +0 -25
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Button } from "@/components/ui/button"
|
|
2
|
-
import {
|
|
2
|
+
import { Search, Menu, X } from "lucide-react"
|
|
3
3
|
import { Link } from "wouter"
|
|
4
|
-
import { PrefetchPageLink } from "./PrefetchPageLink"
|
|
5
4
|
import { HeaderLogin } from "./HeaderLogin"
|
|
6
5
|
import SearchComponent from "./SearchComponent"
|
|
7
6
|
import HeaderDropdown from "./HeaderDropdown"
|
|
@@ -60,36 +59,28 @@ export const Header2 = () => {
|
|
|
60
59
|
<>
|
|
61
60
|
<header className="sticky top-0 z-50 w-full border-b bg-white md:bg-white/80 md:backdrop-blur supports-[backdrop-filter]:md:bg-white/60">
|
|
62
61
|
<div className="container mx-auto flex h-16 items-center justify-between px-2 md:px-6">
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<span className="text-lg font-bold">tscircuit</span>
|
|
69
|
-
</PrefetchPageLink>
|
|
62
|
+
<Link href="/" className="flex select-none items-center">
|
|
63
|
+
<span className="bg-blue-500 px-2 py-1 rounded-md text-white text-sm font-semibold sm:text-base">
|
|
64
|
+
tscircuit
|
|
65
|
+
</span>
|
|
66
|
+
</Link>
|
|
70
67
|
|
|
71
68
|
{/* Desktop Navigation */}
|
|
72
69
|
<nav className="hidden md:flex gap-6">
|
|
73
70
|
{isLoggedIn && (
|
|
74
|
-
<
|
|
71
|
+
<Link
|
|
75
72
|
className="text-sm font-medium hover:underline underline-offset-4"
|
|
76
73
|
href="/dashboard"
|
|
77
74
|
>
|
|
78
75
|
Dashboard
|
|
79
|
-
</
|
|
76
|
+
</Link>
|
|
80
77
|
)}
|
|
81
|
-
<
|
|
78
|
+
<Link
|
|
82
79
|
className="text-sm font-medium hover:underline underline-offset-4"
|
|
83
80
|
href="/quickstart"
|
|
84
81
|
>
|
|
85
82
|
Editor
|
|
86
|
-
</
|
|
87
|
-
<PrefetchPageLink
|
|
88
|
-
className="text-sm font-medium hover:underline underline-offset-4"
|
|
89
|
-
href="/datasheets"
|
|
90
|
-
>
|
|
91
|
-
Datasheets
|
|
92
|
-
</PrefetchPageLink>
|
|
83
|
+
</Link>
|
|
93
84
|
<a
|
|
94
85
|
className="text-sm font-medium hover:underline underline-offset-4"
|
|
95
86
|
href="https://docs.tscircuit.com"
|
|
@@ -131,11 +122,11 @@ export const Header2 = () => {
|
|
|
131
122
|
{isLoggedIn ? (
|
|
132
123
|
<HeaderLogin />
|
|
133
124
|
) : (
|
|
134
|
-
<
|
|
125
|
+
<Link href="/quickstart">
|
|
135
126
|
<Button size="sm" className="text-xs px-3 py-1">
|
|
136
127
|
Get Started
|
|
137
128
|
</Button>
|
|
138
|
-
</
|
|
129
|
+
</Link>
|
|
139
130
|
)}
|
|
140
131
|
<button
|
|
141
132
|
className="p-2"
|
|
@@ -154,28 +145,21 @@ export const Header2 = () => {
|
|
|
154
145
|
<nav className="mb-4">
|
|
155
146
|
<div className="flex flex-col items-center gap-1">
|
|
156
147
|
{isLoggedIn && (
|
|
157
|
-
<
|
|
148
|
+
<Link
|
|
158
149
|
className="text-sm font-medium hover:underline underline-offset-4 py-2 w-full text-center"
|
|
159
150
|
href="/dashboard"
|
|
160
151
|
onClick={() => setMobileMenuOpen(false)}
|
|
161
152
|
>
|
|
162
153
|
Dashboard
|
|
163
|
-
</
|
|
154
|
+
</Link>
|
|
164
155
|
)}
|
|
165
|
-
<
|
|
156
|
+
<Link
|
|
166
157
|
className="text-sm font-medium hover:underline underline-offset-4 py-2 w-full text-center"
|
|
167
158
|
href="/quickstart"
|
|
168
159
|
onClick={() => setMobileMenuOpen(false)}
|
|
169
160
|
>
|
|
170
161
|
Editor
|
|
171
|
-
</
|
|
172
|
-
<PrefetchPageLink
|
|
173
|
-
className="text-sm font-medium hover:underline underline-offset-4 py-2 w-full text-center"
|
|
174
|
-
href="/datasheets"
|
|
175
|
-
onClick={() => setMobileMenuOpen(false)}
|
|
176
|
-
>
|
|
177
|
-
Datasheets
|
|
178
|
-
</PrefetchPageLink>
|
|
162
|
+
</Link>
|
|
179
163
|
<a
|
|
180
164
|
className="text-sm font-medium hover:underline underline-offset-4 py-2 w-full text-center"
|
|
181
165
|
href="https://docs.tscircuit.com"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useState } from "react"
|
|
1
2
|
import { Button } from "@/components/ui/button"
|
|
2
3
|
import {
|
|
3
4
|
DropdownMenu,
|
|
@@ -7,9 +8,10 @@ import {
|
|
|
7
8
|
} from "@/components/ui/dropdown-menu"
|
|
8
9
|
import { cn } from "@/lib/utils"
|
|
9
10
|
import { ChevronDown, FileUp, Upload, Zap } from "lucide-react"
|
|
10
|
-
import {
|
|
11
|
+
import { Link } from "wouter"
|
|
11
12
|
|
|
12
13
|
export default function HeaderDropdown() {
|
|
14
|
+
const [open, setOpen] = useState(false)
|
|
13
15
|
const blankTemplates = [
|
|
14
16
|
{ name: "Blank Circuit Board", type: "board", badgeColor: "bg-blue-500" },
|
|
15
17
|
{
|
|
@@ -32,7 +34,7 @@ export default function HeaderDropdown() {
|
|
|
32
34
|
]
|
|
33
35
|
|
|
34
36
|
return (
|
|
35
|
-
<DropdownMenu>
|
|
37
|
+
<DropdownMenu open={open} onOpenChange={setOpen}>
|
|
36
38
|
<DropdownMenuTrigger asChild>
|
|
37
39
|
<Button
|
|
38
40
|
size="sm"
|
|
@@ -44,38 +46,41 @@ export default function HeaderDropdown() {
|
|
|
44
46
|
</DropdownMenuTrigger>
|
|
45
47
|
<DropdownMenuContent className="w-fit">
|
|
46
48
|
<DropdownMenuItem asChild>
|
|
47
|
-
<
|
|
49
|
+
<Link
|
|
48
50
|
href="/quickstart"
|
|
49
51
|
className="flex items-center cursor-pointer"
|
|
52
|
+
onClick={() => setOpen(false)}
|
|
50
53
|
>
|
|
51
54
|
<Zap className="mr-2 h-3 w-3" />
|
|
52
55
|
Quickstart Templates
|
|
53
|
-
</
|
|
56
|
+
</Link>
|
|
54
57
|
</DropdownMenuItem>
|
|
55
58
|
{blankTemplates.map((template, index) => (
|
|
56
59
|
<DropdownMenuItem key={index} asChild disabled={template.disabled}>
|
|
57
|
-
<
|
|
60
|
+
<Link
|
|
58
61
|
href={`/editor?template=${template.name.toLowerCase().replace(/ /g, "-")}`}
|
|
59
62
|
className={cn(
|
|
60
63
|
"flex items-center cursor-pointer",
|
|
61
64
|
template.disabled && "opacity-50 cursor-not-allowed",
|
|
62
65
|
)}
|
|
66
|
+
onClick={() => !template.disabled && setOpen(false)}
|
|
63
67
|
>
|
|
64
68
|
<span
|
|
65
69
|
className={`w-2 h-2 rounded-full mr-2 ${template.badgeColor}`}
|
|
66
70
|
/>
|
|
67
71
|
{template.name}
|
|
68
|
-
</
|
|
72
|
+
</Link>
|
|
69
73
|
</DropdownMenuItem>
|
|
70
74
|
))}
|
|
71
75
|
<DropdownMenuItem asChild>
|
|
72
|
-
<
|
|
76
|
+
<Link
|
|
73
77
|
href="/quickstart"
|
|
74
78
|
className="flex items-center cursor-pointer"
|
|
79
|
+
onClick={() => setOpen(false)}
|
|
75
80
|
>
|
|
76
81
|
<Upload className="mr-2 h-3 w-3" />
|
|
77
82
|
Import Part
|
|
78
|
-
</
|
|
83
|
+
</Link>
|
|
79
84
|
</DropdownMenuItem>
|
|
80
85
|
</DropdownMenuContent>
|
|
81
86
|
</DropdownMenu>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from "react"
|
|
2
1
|
import { Button } from "@/components/ui/button"
|
|
3
2
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
|
4
3
|
import {
|
|
@@ -9,15 +8,16 @@ import {
|
|
|
9
8
|
} from "@/components/ui/dropdown-menu"
|
|
10
9
|
import { User } from "lucide-react"
|
|
11
10
|
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
12
|
-
import { useAccountBalance } from "@/hooks/use-account-balance"
|
|
13
11
|
import { useSignIn } from "@/hooks/use-sign-in"
|
|
12
|
+
import { Link } from "wouter"
|
|
13
|
+
import { useState } from "react"
|
|
14
14
|
|
|
15
15
|
export const HeaderLogin = () => {
|
|
16
16
|
const session = useGlobalStore((s) => s.session)
|
|
17
17
|
const isLoggedIn = Boolean(session)
|
|
18
18
|
const setSession = useGlobalStore((s) => s.setSession)
|
|
19
19
|
const signIn = useSignIn()
|
|
20
|
-
const
|
|
20
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
21
21
|
|
|
22
22
|
if (!isLoggedIn) {
|
|
23
23
|
return (
|
|
@@ -31,7 +31,7 @@ export const HeaderLogin = () => {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return (
|
|
34
|
-
<DropdownMenu>
|
|
34
|
+
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
|
|
35
35
|
<DropdownMenuTrigger asChild>
|
|
36
36
|
<Avatar className="w-8 h-8 login-avatar">
|
|
37
37
|
<AvatarImage
|
|
@@ -43,33 +43,61 @@ export const HeaderLogin = () => {
|
|
|
43
43
|
</AvatarFallback>
|
|
44
44
|
</Avatar>
|
|
45
45
|
</DropdownMenuTrigger>
|
|
46
|
-
<DropdownMenuContent className="ml-1 md:ml-0 md:mr-1">
|
|
47
|
-
<DropdownMenuItem asChild className="text-gray-500 text-xs" disabled>
|
|
46
|
+
<DropdownMenuContent className="ml-1 mr-1 md:ml-0 md:mr-1">
|
|
47
|
+
{/* <DropdownMenuItem asChild className="text-gray-500 text-xs" disabled>
|
|
48
48
|
<div>
|
|
49
49
|
AI Usage $
|
|
50
50
|
{accountBalance?.monthly_ai_budget_used_usd.toFixed(2) ?? "0.00"} /
|
|
51
51
|
$5.00
|
|
52
52
|
</div>
|
|
53
|
-
</DropdownMenuItem>
|
|
53
|
+
</DropdownMenuItem> */}
|
|
54
54
|
<DropdownMenuItem asChild>
|
|
55
|
-
<
|
|
55
|
+
<Link
|
|
56
|
+
href={`/${session?.github_username}`}
|
|
57
|
+
className="cursor-pointer"
|
|
58
|
+
onClick={() => setIsOpen(false)}
|
|
59
|
+
>
|
|
56
60
|
My Profile
|
|
57
|
-
</
|
|
61
|
+
</Link>
|
|
58
62
|
</DropdownMenuItem>
|
|
59
63
|
<DropdownMenuItem asChild>
|
|
60
|
-
<
|
|
64
|
+
<Link
|
|
65
|
+
href="/dashboard"
|
|
66
|
+
className="cursor-pointer"
|
|
67
|
+
onClick={() => setIsOpen(false)}
|
|
68
|
+
>
|
|
61
69
|
Dashboard
|
|
62
|
-
</
|
|
70
|
+
</Link>
|
|
63
71
|
</DropdownMenuItem>
|
|
64
72
|
<DropdownMenuItem asChild>
|
|
65
|
-
<
|
|
73
|
+
<Link
|
|
74
|
+
href={`/${session?.github_username}/settings`}
|
|
75
|
+
className="cursor-pointer"
|
|
76
|
+
onClick={() => setIsOpen(false)}
|
|
77
|
+
>
|
|
66
78
|
Settings
|
|
67
|
-
</
|
|
79
|
+
</Link>
|
|
80
|
+
</DropdownMenuItem>
|
|
81
|
+
<DropdownMenuItem asChild>
|
|
82
|
+
<Link
|
|
83
|
+
href="/orgs/new"
|
|
84
|
+
className="cursor-pointer"
|
|
85
|
+
onClick={() => setIsOpen(false)}
|
|
86
|
+
>
|
|
87
|
+
Create Organization
|
|
88
|
+
</Link>
|
|
68
89
|
</DropdownMenuItem>
|
|
69
|
-
<DropdownMenuItem asChild
|
|
70
|
-
<
|
|
90
|
+
<DropdownMenuItem asChild>
|
|
91
|
+
<Link
|
|
92
|
+
href="/"
|
|
93
|
+
className="cursor-pointer"
|
|
94
|
+
onClick={() => {
|
|
95
|
+
setSession(null)
|
|
96
|
+
setIsOpen(false)
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
71
99
|
Sign Out
|
|
72
|
-
</
|
|
100
|
+
</Link>
|
|
73
101
|
</DropdownMenuItem>
|
|
74
102
|
</DropdownMenuContent>
|
|
75
103
|
</DropdownMenu>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Button } from "@/components/ui/button"
|
|
2
|
-
import {
|
|
2
|
+
import { Link } from "wouter"
|
|
3
3
|
|
|
4
4
|
export function NotFound({ heading = "Page not found" }: { heading?: string }) {
|
|
5
5
|
return (
|
|
@@ -20,16 +20,16 @@ export function NotFound({ heading = "Page not found" }: { heading?: string }) {
|
|
|
20
20
|
address.
|
|
21
21
|
</p>
|
|
22
22
|
<div className="flex flex-col sm:flex-row gap-4">
|
|
23
|
-
<
|
|
23
|
+
<Link href="/">
|
|
24
24
|
<Button size="lg" className="bg-blue-500 hover:bg-blue-600">
|
|
25
25
|
Return Home
|
|
26
26
|
</Button>
|
|
27
|
-
</
|
|
28
|
-
<
|
|
27
|
+
</Link>
|
|
28
|
+
<Link href="/search">
|
|
29
29
|
<Button size="lg" variant="outline">
|
|
30
30
|
Search Packages
|
|
31
31
|
</Button>
|
|
32
|
-
</
|
|
32
|
+
</Link>
|
|
33
33
|
</div>
|
|
34
34
|
</div>
|
|
35
35
|
</section>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Link } from "wouter"
|
|
2
2
|
import {
|
|
3
3
|
Breadcrumb,
|
|
4
4
|
BreadcrumbList,
|
|
@@ -29,7 +29,7 @@ export function PackageBreadcrumb({
|
|
|
29
29
|
{/* Author */}
|
|
30
30
|
<BreadcrumbItem>
|
|
31
31
|
<BreadcrumbLink asChild>
|
|
32
|
-
<
|
|
32
|
+
<Link href={`/${author}`}>{author}</Link>
|
|
33
33
|
</BreadcrumbLink>
|
|
34
34
|
</BreadcrumbItem>
|
|
35
35
|
<BreadcrumbSeparator>
|
|
@@ -39,9 +39,7 @@ export function PackageBreadcrumb({
|
|
|
39
39
|
{/* Package */}
|
|
40
40
|
<BreadcrumbItem>
|
|
41
41
|
<BreadcrumbLink asChild>
|
|
42
|
-
<
|
|
43
|
-
{unscopedName || packageName}
|
|
44
|
-
</PrefetchPageLink>
|
|
42
|
+
<Link href={`/${packageName}`}>{unscopedName || packageName}</Link>
|
|
45
43
|
</BreadcrumbLink>
|
|
46
44
|
</BreadcrumbItem>
|
|
47
45
|
<BreadcrumbSeparator>
|
|
@@ -58,9 +56,7 @@ export function PackageBreadcrumb({
|
|
|
58
56
|
<BreadcrumbPage>releases</BreadcrumbPage>
|
|
59
57
|
) : (
|
|
60
58
|
<BreadcrumbLink asChild>
|
|
61
|
-
<
|
|
62
|
-
releases
|
|
63
|
-
</PrefetchPageLink>
|
|
59
|
+
<Link href={`/${packageName}/releases`}>releases</Link>
|
|
64
60
|
</BreadcrumbLink>
|
|
65
61
|
)}
|
|
66
62
|
</BreadcrumbItem>
|
|
@@ -76,11 +72,9 @@ export function PackageBreadcrumb({
|
|
|
76
72
|
<BreadcrumbItem>
|
|
77
73
|
{currentPage === "builds" ? (
|
|
78
74
|
<BreadcrumbLink asChild>
|
|
79
|
-
<
|
|
80
|
-
href={`/${packageName}/releases/${releaseVersion}`}
|
|
81
|
-
>
|
|
75
|
+
<Link href={`/${packageName}/releases/${releaseVersion}`}>
|
|
82
76
|
{releaseVersion}
|
|
83
|
-
</
|
|
77
|
+
</Link>
|
|
84
78
|
</BreadcrumbLink>
|
|
85
79
|
) : (
|
|
86
80
|
<BreadcrumbPage>{releaseVersion}</BreadcrumbPage>
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
} from "@/components/ui/dropdown-menu"
|
|
20
20
|
import { SnippetType, SnippetTypeIcon } from "./SnippetTypeIcon"
|
|
21
21
|
import { timeAgo } from "@/lib/utils/timeAgo"
|
|
22
|
-
import { ImageWithFallback } from "./ImageWithFallback"
|
|
23
22
|
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"
|
|
24
23
|
|
|
25
24
|
export interface PackageCardProps {
|
|
@@ -101,7 +101,13 @@ export const PrefetchPageLink = ({
|
|
|
101
101
|
}, [inView, href])
|
|
102
102
|
|
|
103
103
|
return (
|
|
104
|
-
<Link
|
|
104
|
+
<Link
|
|
105
|
+
{...props}
|
|
106
|
+
href={href}
|
|
107
|
+
className={className}
|
|
108
|
+
draggable={false}
|
|
109
|
+
ref={ref}
|
|
110
|
+
>
|
|
105
111
|
{children}
|
|
106
112
|
</Link>
|
|
107
113
|
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { useParams } from "wouter"
|
|
3
|
+
import { useOrgByGithubHandle } from "@/hooks/use-org-by-github-handle"
|
|
4
|
+
import { OrganizationProfilePageContent } from "@/pages/organization-profile"
|
|
5
|
+
import { UserProfilePage } from "@/pages/user-profile"
|
|
6
|
+
import NotFoundPage from "@/pages/404"
|
|
7
|
+
import { FullPageLoader } from "@/App"
|
|
8
|
+
|
|
9
|
+
const ProfileRouter: React.FC = () => {
|
|
10
|
+
const { username } = useParams()
|
|
11
|
+
const {
|
|
12
|
+
data: organization,
|
|
13
|
+
isLoading,
|
|
14
|
+
error,
|
|
15
|
+
} = useOrgByGithubHandle(username || null)
|
|
16
|
+
|
|
17
|
+
if (!username) {
|
|
18
|
+
return <NotFoundPage heading="Username Not Provided" />
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (isLoading) {
|
|
22
|
+
return <FullPageLoader />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (organization && !organization.is_personal_org && !error) {
|
|
26
|
+
return <OrganizationProfilePageContent org={organization} />
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return <UserProfilePage />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default ProfileRouter
|
|
@@ -5,7 +5,7 @@ import React, { useEffect, useRef, useState } from "react"
|
|
|
5
5
|
import { useQuery } from "react-query"
|
|
6
6
|
import { Alert } from "./ui/alert"
|
|
7
7
|
import { useApiBaseUrl } from "@/hooks/use-packages-base-api-url"
|
|
8
|
-
import {
|
|
8
|
+
import { Link } from "wouter"
|
|
9
9
|
import { CircuitBoard } from "lucide-react"
|
|
10
10
|
import { cn } from "@/lib/utils"
|
|
11
11
|
|
|
@@ -42,9 +42,9 @@ const LinkWithNewTabHandling = ({
|
|
|
42
42
|
)
|
|
43
43
|
}
|
|
44
44
|
return (
|
|
45
|
-
<
|
|
45
|
+
<Link onClick={onClick} className={className} href={href}>
|
|
46
46
|
{children}
|
|
47
|
-
</
|
|
47
|
+
</Link>
|
|
48
48
|
)
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -60,7 +60,7 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
60
60
|
const resultsRef = useRef<HTMLDivElement>(null)
|
|
61
61
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
62
62
|
const [location, setLocation] = useLocation()
|
|
63
|
-
const
|
|
63
|
+
const apiBaseUrl = useApiBaseUrl()
|
|
64
64
|
|
|
65
65
|
const { data: searchResults, isLoading } = useQuery(
|
|
66
66
|
["packageSearch", searchQuery],
|
|
@@ -137,10 +137,13 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
137
137
|
<Input
|
|
138
138
|
autoComplete="off"
|
|
139
139
|
spellCheck={false}
|
|
140
|
+
autoCorrect="off"
|
|
141
|
+
autoCapitalize="off"
|
|
140
142
|
ref={inputRef}
|
|
141
143
|
type="search"
|
|
144
|
+
aria-autocomplete="none"
|
|
142
145
|
placeholder="Search"
|
|
143
|
-
className="pl-4 focus:border-blue-500 placeholder-gray-400 text-sm"
|
|
146
|
+
className="pl-4 focus:border-blue-500 placeholder-gray-400 text-sm select-none"
|
|
144
147
|
value={searchQuery}
|
|
145
148
|
onChange={(e) => {
|
|
146
149
|
setSearchQuery(e.target.value)
|
|
@@ -195,10 +198,10 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
195
198
|
{showResults && searchResults && (
|
|
196
199
|
<div
|
|
197
200
|
ref={resultsRef}
|
|
198
|
-
className="absolute top-full md:left-0 right-0 mt-2 bg-white shadow-lg rounded-md z-50 w-80 max-h-screen overflow-y-auto overflow-x-visible"
|
|
201
|
+
className="absolute top-full md:left-0 right-0 no-scrollbar mt-2 bg-white shadow-lg rounded-md z-50 w-80 max-h-screen overflow-y-auto overflow-x-visible"
|
|
199
202
|
>
|
|
200
203
|
{searchResults.length > 0 ? (
|
|
201
|
-
<ul className="divide-y divide-gray-200">
|
|
204
|
+
<ul className="divide-y divide-gray-200 no-scrollbar">
|
|
202
205
|
{searchResults.map((pkg: any, index: number) => (
|
|
203
206
|
<li
|
|
204
207
|
key={pkg.package_id}
|
|
@@ -222,8 +225,9 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
222
225
|
>
|
|
223
226
|
<div className="w-12 h-12 overflow-hidden mr-2 flex-shrink-0 rounded-sm bg-gray-50 border flex items-center justify-center">
|
|
224
227
|
<img
|
|
225
|
-
src={`${
|
|
228
|
+
src={`${apiBaseUrl}/packages/images/${pkg.name}/pcb.svg`}
|
|
226
229
|
alt={`PCB preview for ${pkg.name}`}
|
|
230
|
+
draggable={false}
|
|
227
231
|
className="w-12 h-12 object-contain p-1 scale-[4] rotate-45"
|
|
228
232
|
onError={(e) => {
|
|
229
233
|
e.currentTarget.style.display = "none"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { Link } from "wouter"
|
|
3
|
+
import { Account } from "fake-snippets-api/lib/db/schema"
|
|
4
|
+
import { User } from "lucide-react"
|
|
5
|
+
|
|
6
|
+
export interface UserCardProps {
|
|
7
|
+
/** The account data to display */
|
|
8
|
+
account: Account | Omit<Account, "account_id">
|
|
9
|
+
/** Whether to render the card with a link to the user profile page */
|
|
10
|
+
withLink?: boolean
|
|
11
|
+
/** Custom class name for the card container */
|
|
12
|
+
className?: string
|
|
13
|
+
/** Custom onClick handler */
|
|
14
|
+
onClick?: (account: Account | Omit<Account, "account_id">) => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const UserCard: React.FC<UserCardProps> = ({
|
|
18
|
+
account,
|
|
19
|
+
withLink = true,
|
|
20
|
+
className = "",
|
|
21
|
+
onClick,
|
|
22
|
+
}) => {
|
|
23
|
+
const handleClick = () => {
|
|
24
|
+
if (onClick) {
|
|
25
|
+
onClick(account)
|
|
26
|
+
} else if (!withLink) {
|
|
27
|
+
window.location.href = `/${account.github_username}`
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const cardContent = (
|
|
32
|
+
<div
|
|
33
|
+
className={`border p-4 rounded-md hover:shadow-md transition-shadow flex flex-col gap-4 cursor-pointer ${className}`}
|
|
34
|
+
onClick={!withLink ? handleClick : undefined}
|
|
35
|
+
>
|
|
36
|
+
<div className="flex items-start gap-4">
|
|
37
|
+
<div className="w-16 h-16 flex-shrink-0 rounded-md overflow-hidden bg-gray-50 border flex items-center justify-center">
|
|
38
|
+
<img
|
|
39
|
+
src={`https://github.com/${account.github_username}.png`}
|
|
40
|
+
alt={`${account.github_username} avatar`}
|
|
41
|
+
className="object-cover h-full w-full transition-transform duration-300 hover:scale-110"
|
|
42
|
+
onError={(e) => {
|
|
43
|
+
const target = e.target as HTMLImageElement
|
|
44
|
+
target.style.display = "none"
|
|
45
|
+
target.nextElementSibling?.classList.remove("hidden")
|
|
46
|
+
target.nextElementSibling?.classList.add("flex")
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
<div className="hidden items-center justify-center h-full w-full">
|
|
50
|
+
<User className="w-6 h-6 text-gray-300" />
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="flex-1 min-w-0 flex flex-col justify-center my-auto">
|
|
54
|
+
<div className="flex justify-between items-start">
|
|
55
|
+
<h2 className="text-md font-semibold truncate pr-[30px]">
|
|
56
|
+
<span className="text-gray-900">{account.github_username}</span>
|
|
57
|
+
</h2>
|
|
58
|
+
</div>
|
|
59
|
+
<p className="text-sm text-gray-500 truncate max-w-xs">
|
|
60
|
+
@{account.github_username}
|
|
61
|
+
</p>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if (withLink) {
|
|
68
|
+
return (
|
|
69
|
+
<Link
|
|
70
|
+
key={account.github_username}
|
|
71
|
+
href={`/${account.github_username}`}
|
|
72
|
+
onClick={onClick ? () => onClick(account) : undefined}
|
|
73
|
+
>
|
|
74
|
+
{cardContent}
|
|
75
|
+
</Link>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return cardContent
|
|
80
|
+
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { useShikiHighlighter } from "@/hooks/use-shiki-highlighter"
|
|
2
|
-
import {
|
|
3
|
-
import { useQuery } from "react-query"
|
|
2
|
+
import { useMemo } from "react"
|
|
4
3
|
import { Skeleton } from "@/components/ui/skeleton"
|
|
5
4
|
|
|
6
5
|
// Pre-randomized array to avoid flickering on re-renders
|
|
7
|
-
const SKELETON_WIDTHS = [
|
|
8
|
-
|
|
6
|
+
export const SKELETON_WIDTHS = [
|
|
7
|
+
"w-2/3",
|
|
8
|
+
"w-1/4",
|
|
9
|
+
"w-5/6",
|
|
10
|
+
"w-1/3",
|
|
11
|
+
"w-1/2",
|
|
12
|
+
"w-3/4",
|
|
13
|
+
]
|
|
14
|
+
const PLACEHOLDER_SHIKI_HTML = `<pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0"><code><span class="line"></span></code></pre>`
|
|
9
15
|
export const ShikiCodeViewer = ({
|
|
10
16
|
code,
|
|
11
17
|
filePath,
|
|
@@ -24,17 +30,20 @@ export const ShikiCodeViewer = ({
|
|
|
24
30
|
[filePath, code, highlighter],
|
|
25
31
|
)
|
|
26
32
|
|
|
27
|
-
if (
|
|
33
|
+
if (html && html?.trim() !== PLACEHOLDER_SHIKI_HTML) {
|
|
28
34
|
return (
|
|
29
|
-
<div
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
</div>
|
|
35
|
+
<div
|
|
36
|
+
className="text-sm shiki"
|
|
37
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
|
38
|
+
/>
|
|
34
39
|
)
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
return (
|
|
38
|
-
<div className="text-sm
|
|
43
|
+
<div className="text-sm p-4">
|
|
44
|
+
{SKELETON_WIDTHS.map((w, i) => (
|
|
45
|
+
<Skeleton key={i} className={`h-4 mb-2 ${w}`} />
|
|
46
|
+
))}
|
|
47
|
+
</div>
|
|
39
48
|
)
|
|
40
49
|
}
|
|
@@ -14,7 +14,7 @@ export interface BuildStatusProps {
|
|
|
14
14
|
|
|
15
15
|
export const BuildStatus = ({ step, packageReleaseId }: BuildStatusProps) => {
|
|
16
16
|
const { author, packageName } = useParams()
|
|
17
|
-
const href = `/${author}/${packageName}/
|
|
17
|
+
const href = `/${author}/${packageName}/releases/${packageReleaseId}`
|
|
18
18
|
|
|
19
19
|
return (
|
|
20
20
|
<Link href={href} className="flex items-center gap-2">
|