@tscircuit/fake-snippets 0.0.109 → 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 +349 -453
- package/bunfig.toml +2 -1
- package/dist/bundle.js +1253 -624
- package/dist/index.d.ts +291 -4
- package/dist/index.js +323 -23
- package/dist/schema.d.ts +274 -1
- package/dist/schema.js +52 -1
- 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 +61 -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 +24 -20
- package/renovate.json +1 -1
- package/scripts/generate-sitemap.ts +1 -1
- package/src/App.tsx +29 -8
- 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 +3 -4
- package/src/components/FileSidebar.tsx +11 -17
- package/src/components/Footer.tsx +8 -9
- 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 +43 -15
- package/src/components/NotFound.tsx +5 -5
- package/src/components/PackageBreadcrumb.tsx +6 -12
- 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/build-status.tsx +1 -1
- package/src/components/ViewPackagePage/components/important-files-view.tsx +105 -34
- package/src/components/ViewPackagePage/components/main-content-header.tsx +10 -6
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -1
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -19
- package/src/components/ViewPackagePage/components/package-header.tsx +25 -33
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -18
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +12 -5
- 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/tab-views/pcb-view.tsx +1 -2
- package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -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 +15 -12
- package/src/components/package-port/CodeEditor.tsx +4 -30
- package/src/components/package-port/CodeEditorHeader.tsx +123 -61
- 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 +23 -11
- 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-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 +51 -22
- package/src/hooks/useOptimizedPackageFilesLoader.ts +11 -24
- package/src/hooks/usePackageFilesLoader.ts +2 -2
- package/src/hooks/useUpdatePackageFilesMutation.ts +13 -1
- package/src/lib/download-fns/download-gltf-from-circuit-json.ts +1 -1
- 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 +2 -1
- package/src/main.tsx +2 -1
- 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 -6
- 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 +75 -145
- 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 +7 -13
- package/vite.config.ts +9 -0
- package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
- package/src/components/JLCPCBImportDialog.tsx +0 -280
- package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -113
- package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -56
- 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/pages/package-builds.tsx +0 -33
|
@@ -65,9 +65,8 @@ export function DownloadButtonAndMenu({
|
|
|
65
65
|
return fetchedCircuitJson
|
|
66
66
|
setIsFetchingCircuitJson(true)
|
|
67
67
|
try {
|
|
68
|
-
const { data } = await axios.
|
|
69
|
-
package_id: packageId,
|
|
70
|
-
file_path: "dist/circuit.json",
|
|
68
|
+
const { data } = await axios.get("/package_files/get", {
|
|
69
|
+
params: { package_id: packageId, file_path: "dist/circuit.json" },
|
|
71
70
|
})
|
|
72
71
|
const content = data?.package_file?.content_text
|
|
73
72
|
if (!content) throw new Error("Circuit JSON not found")
|
|
@@ -108,7 +107,7 @@ export function DownloadButtonAndMenu({
|
|
|
108
107
|
<DropdownMenuTrigger asChild>
|
|
109
108
|
<Button
|
|
110
109
|
size="sm"
|
|
111
|
-
className="bg-white shadow-none text-gray-900 hover:bg-gray-100 border border-gray-300 px-1 pl-2"
|
|
110
|
+
className="bg-white shadow-none text-gray-900 hover:bg-gray-100 border border-gray-300 px-1 pl-2 select-none"
|
|
112
111
|
>
|
|
113
112
|
<Download className="w-4 h-4 mr-2" />
|
|
114
113
|
Download
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from "react"
|
|
1
|
+
import React, { useMemo, useState } from "react"
|
|
2
2
|
import { cn } from "@/lib/utils"
|
|
3
3
|
import { PanelRightOpen, Plus, Loader2 } from "lucide-react"
|
|
4
4
|
import { TreeView } from "@/components/ui/tree-view"
|
|
@@ -42,6 +42,7 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
|
|
|
42
42
|
handleRenameFile,
|
|
43
43
|
isCreatingFile,
|
|
44
44
|
setIsCreatingFile,
|
|
45
|
+
pkg,
|
|
45
46
|
isLoadingFiles = true,
|
|
46
47
|
loadingProgress = null,
|
|
47
48
|
}) => {
|
|
@@ -52,10 +53,8 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
|
|
|
52
53
|
const [selectedFolderForCreation, setSelectedFolderForCreation] = useState<
|
|
53
54
|
string | null
|
|
54
55
|
>(null)
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
)
|
|
58
|
-
const canModifyFiles = true
|
|
56
|
+
const selectedItemId = useMemo(() => currentFile || "", [currentFile])
|
|
57
|
+
const canModifyFiles = Boolean(pkg) && !isLoadingFiles
|
|
59
58
|
|
|
60
59
|
const onFolderSelect = (folderPath: string) => {
|
|
61
60
|
setSelectedFolderForCreation(folderPath)
|
|
@@ -137,7 +136,6 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
|
|
|
137
136
|
setNewFileName("")
|
|
138
137
|
setErrorMessage("")
|
|
139
138
|
onFileSelect(finalFileName)
|
|
140
|
-
setSelectedItemId(finalFileName)
|
|
141
139
|
setSelectedFolderForCreation(null)
|
|
142
140
|
}
|
|
143
141
|
}
|
|
@@ -169,7 +167,7 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
|
|
|
169
167
|
className,
|
|
170
168
|
)}
|
|
171
169
|
>
|
|
172
|
-
<div className="flex items-center justify-between px-2
|
|
170
|
+
<div className="flex items-center justify-between px-2 py-2">
|
|
173
171
|
<button
|
|
174
172
|
onClick={toggleSidebar}
|
|
175
173
|
className={`text-gray-400 scale-90 transition-opacity duration-200 ${!sidebarOpen ? "opacity-0 pointer-events-none" : "opacity-100"}`}
|
|
@@ -250,18 +248,14 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
|
|
|
250
248
|
</div>
|
|
251
249
|
</div>
|
|
252
250
|
)}
|
|
253
|
-
<div
|
|
254
|
-
onClick={(e) => {
|
|
255
|
-
if (e.target === e.currentTarget) {
|
|
256
|
-
setSelectedFolderForCreation(null)
|
|
257
|
-
setSelectedItemId("")
|
|
258
|
-
}
|
|
259
|
-
}}
|
|
260
|
-
className="flex-1 border-2 h-full"
|
|
261
|
-
>
|
|
251
|
+
<div className="flex-1 border-t h-full">
|
|
262
252
|
<TreeView
|
|
263
253
|
data={treeData}
|
|
264
|
-
setSelectedItemId={(value) =>
|
|
254
|
+
setSelectedItemId={(value) => {
|
|
255
|
+
if (value && files[value]) {
|
|
256
|
+
onFileSelect(value)
|
|
257
|
+
}
|
|
258
|
+
}}
|
|
265
259
|
selectedItemId={selectedItemId}
|
|
266
260
|
onSelectChange={(item) => {
|
|
267
261
|
if (item?.onClick) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
2
2
|
import { CircuitBoard } from "lucide-react"
|
|
3
3
|
import { Link } from "wouter"
|
|
4
|
-
import { PrefetchPageLink } from "./PrefetchPageLink"
|
|
5
4
|
|
|
6
5
|
export default function Footer() {
|
|
7
6
|
const session = useGlobalStore((s) => s.session)
|
|
@@ -34,13 +33,13 @@ export default function Footer() {
|
|
|
34
33
|
]
|
|
35
34
|
.filter((item) => !item.hidden)
|
|
36
35
|
.map((item) => (
|
|
37
|
-
<
|
|
36
|
+
<Link
|
|
38
37
|
key={item.name}
|
|
39
38
|
href={item.href}
|
|
40
39
|
className="hover:underline"
|
|
41
40
|
>
|
|
42
41
|
{item.name}
|
|
43
|
-
</
|
|
42
|
+
</Link>
|
|
44
43
|
))}
|
|
45
44
|
<a
|
|
46
45
|
href="https://chat.tscircuit.com"
|
|
@@ -55,15 +54,15 @@ export default function Footer() {
|
|
|
55
54
|
<div className="space-y-4">
|
|
56
55
|
<h3 className="font-semibold uppercase">Explore</h3>
|
|
57
56
|
<footer className="flex flex-col space-y-2">
|
|
58
|
-
<
|
|
57
|
+
<Link href="/latest" className="hover:underline">
|
|
59
58
|
Latest Packages
|
|
60
|
-
</
|
|
61
|
-
<
|
|
59
|
+
</Link>
|
|
60
|
+
<Link href="/trending" className="hover:underline">
|
|
62
61
|
Trending Packages
|
|
63
|
-
</
|
|
64
|
-
<
|
|
62
|
+
</Link>
|
|
63
|
+
<Link href="/search" className="hover:underline">
|
|
65
64
|
Search Packages
|
|
66
|
-
</
|
|
65
|
+
</Link>
|
|
67
66
|
<a href="https://docs.tscircuit.com" className="hover:underline">
|
|
68
67
|
Docs
|
|
69
68
|
</a>
|
|
@@ -6,7 +6,7 @@ import { GitHubLogoIcon, DiscordLogoIcon } from "@radix-ui/react-icons"
|
|
|
6
6
|
import { Menu, X } from "lucide-react"
|
|
7
7
|
import React, { useEffect, useState } from "react"
|
|
8
8
|
import { useLocation } from "wouter"
|
|
9
|
-
import {
|
|
9
|
+
import { Link } from "wouter"
|
|
10
10
|
import CmdKMenu from "./CmdKMenu"
|
|
11
11
|
import HeaderDropdown from "./HeaderDropdown"
|
|
12
12
|
import SearchComponent from "./SearchComponent"
|
|
@@ -27,23 +27,23 @@ const HeaderButton = ({
|
|
|
27
27
|
|
|
28
28
|
if (location === href || location === alsoHighlightForUrl) {
|
|
29
29
|
return (
|
|
30
|
-
<
|
|
30
|
+
<Link className={cn("header-button", className)} href={href}>
|
|
31
31
|
<Button
|
|
32
32
|
variant="ghost"
|
|
33
33
|
className={`border-b-2 rounded-none border-blue-600 header-button ${className}`}
|
|
34
34
|
>
|
|
35
35
|
{children}
|
|
36
36
|
</Button>
|
|
37
|
-
</
|
|
37
|
+
</Link>
|
|
38
38
|
)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
|
-
<
|
|
42
|
+
<Link className={cn("header-button", className)} href={href}>
|
|
43
43
|
<Button className={className} variant="ghost">
|
|
44
44
|
{children}
|
|
45
45
|
</Button>
|
|
46
|
-
</
|
|
46
|
+
</Link>
|
|
47
47
|
)
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -59,14 +59,14 @@ export default function Header() {
|
|
|
59
59
|
return (
|
|
60
60
|
<header className="px-4 py-3">
|
|
61
61
|
<div className="flex items-center">
|
|
62
|
-
<
|
|
62
|
+
<Link
|
|
63
63
|
href="/"
|
|
64
|
-
className="text-lg font-semibold whitespace-nowrap"
|
|
64
|
+
className="text-lg font-semibold whitespace-nowrap select-none"
|
|
65
65
|
>
|
|
66
66
|
<span className="bg-blue-500 px-2 py-1 rounded-md text-white">
|
|
67
67
|
tscircuit
|
|
68
68
|
</span>
|
|
69
|
-
</
|
|
69
|
+
</Link>
|
|
70
70
|
<div className="hidden md:flex items-center space-x-4">
|
|
71
71
|
<nav>
|
|
72
72
|
<ul className="flex items-center gap-2 ml-2">
|
|
@@ -80,9 +80,6 @@ export default function Header() {
|
|
|
80
80
|
Editor
|
|
81
81
|
</HeaderButton>
|
|
82
82
|
</li>
|
|
83
|
-
<li>
|
|
84
|
-
<HeaderButton href="/datasheets">Datasheets</HeaderButton>
|
|
85
|
-
</li>
|
|
86
83
|
<li>
|
|
87
84
|
<a href="https://chat.tscircuit.com">
|
|
88
85
|
<Button variant="ghost">AI</Button>
|
|
@@ -93,28 +90,26 @@ export default function Header() {
|
|
|
93
90
|
<Button variant="ghost">Docs</Button>
|
|
94
91
|
</a>
|
|
95
92
|
</li>
|
|
96
|
-
<li>
|
|
97
|
-
<a
|
|
98
|
-
href="https://tscircuit.com/join"
|
|
99
|
-
target="_blank"
|
|
100
|
-
className="mr-2"
|
|
101
|
-
>
|
|
102
|
-
<Button variant="ghost">
|
|
103
|
-
<DiscordLogoIcon className="text-gray-400 hover:text-gray-600 transition-colors w-4 h-4" />
|
|
104
|
-
</Button>
|
|
105
|
-
</a>
|
|
106
|
-
</li>
|
|
107
93
|
</ul>
|
|
108
94
|
</nav>
|
|
109
95
|
</div>
|
|
110
96
|
<div className="flex-grow"></div>
|
|
97
|
+
<a
|
|
98
|
+
href="https://tscircuit.com/join"
|
|
99
|
+
target="_blank"
|
|
100
|
+
className="lg:mr-2"
|
|
101
|
+
>
|
|
102
|
+
<Button variant="ghost">
|
|
103
|
+
<DiscordLogoIcon className="text-gray-400 hidden lg:block hover:text-gray-600 transition-colors w-4 h-4" />
|
|
104
|
+
</Button>
|
|
105
|
+
</a>
|
|
111
106
|
<a
|
|
112
107
|
href="https://github.com/tscircuit/tscircuit"
|
|
113
108
|
target="_blank"
|
|
114
|
-
className="mr-4"
|
|
109
|
+
className="lg:mr-4"
|
|
115
110
|
aria-label="View TSCircuit on GitHub"
|
|
116
111
|
>
|
|
117
|
-
<GitHubLogoIcon className="text-gray-400 hover:text-gray-600 transition-colors" />
|
|
112
|
+
<GitHubLogoIcon className="hidden lg:block text-gray-400 hover:text-gray-600 transition-colors" />
|
|
118
113
|
</a>
|
|
119
114
|
{/* <a href="https://tscircuit.com/join" target="_blank" className="mr-2">
|
|
120
115
|
<DiscordLogoIcon className="text-gray-400 hover:text-gray-600 transition-colors" />
|
|
@@ -155,14 +150,6 @@ export default function Header() {
|
|
|
155
150
|
Editor
|
|
156
151
|
</HeaderButton>
|
|
157
152
|
</li>
|
|
158
|
-
<li>
|
|
159
|
-
<HeaderButton
|
|
160
|
-
className="w-full justify-start"
|
|
161
|
-
href="/datasheets"
|
|
162
|
-
>
|
|
163
|
-
Datasheets
|
|
164
|
-
</HeaderButton>
|
|
165
|
-
</li>
|
|
166
153
|
<li>
|
|
167
154
|
<HeaderButton
|
|
168
155
|
className="w-full justify-start"
|
|
@@ -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
|
|
@@ -44,32 +44,60 @@ export const HeaderLogin = () => {
|
|
|
44
44
|
</Avatar>
|
|
45
45
|
</DropdownMenuTrigger>
|
|
46
46
|
<DropdownMenuContent className="ml-1 mr-1 md:ml-0 md:mr-1">
|
|
47
|
-
<DropdownMenuItem asChild className="text-gray-500 text-xs" disabled>
|
|
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>
|
|
@@ -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
|