@tscircuit/fake-snippets 0.0.90 → 0.0.91
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/bun.lock +73 -97
- package/dist/bundle.js +2 -1
- package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +1 -0
- package/package.json +4 -8
- package/src/ContextProviders.tsx +0 -2
- package/src/components/PageSearchComponent.tsx +2 -2
- package/src/components/SearchComponent.tsx +2 -2
- package/src/components/TrendingPackagesCarousel.tsx +2 -2
- package/src/components/dialogs/import-component-dialog.tsx +25 -0
- package/src/components/package-port/CodeEditor.tsx +19 -12
- package/src/components/package-port/CodeEditorHeader.tsx +67 -10
- package/src/components/package-port/EditorNav.tsx +57 -51
- package/src/hooks/use-axios.ts +2 -2
- package/src/hooks/use-packages-base-api-url.ts +3 -0
- package/src/hooks/use-request-ai-review-mutation.ts +1 -1
- package/src/hooks/use-sign-in.ts +2 -2
- package/src/hooks/use-toast.tsx +1 -0
- package/src/hooks/useFileManagement.ts +8 -3
- package/src/main.tsx +0 -3
- package/src/pages/dashboard.tsx +2 -2
- package/src/pages/dev-login.tsx +2 -2
- package/src/pages/latest.tsx +2 -2
- package/src/pages/search.tsx +2 -2
- package/src/pages/trending.tsx +2 -2
- package/src/pages/user-profile.tsx +2 -2
- package/vite.config.ts +0 -19
- package/src/build-watcher.ts +0 -52
- package/src/global.d.ts +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/fake-snippets",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.91",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -77,16 +77,12 @@
|
|
|
77
77
|
"@tailwindcss/typography": "^0.5.16",
|
|
78
78
|
"@tscircuit/3d-viewer": "^0.0.279",
|
|
79
79
|
"@tscircuit/assembly-viewer": "^0.0.1",
|
|
80
|
-
"@tscircuit/core": "^0.0.536",
|
|
81
80
|
"@tscircuit/create-snippet-url": "^0.0.8",
|
|
82
81
|
"@tscircuit/eval": "^0.0.244",
|
|
83
|
-
"@tscircuit/footprinter": "^0.0.186",
|
|
84
82
|
"@tscircuit/layout": "^0.0.29",
|
|
85
|
-
"@tscircuit/math-utils": "^0.0.10",
|
|
86
83
|
"@tscircuit/mm": "^0.0.8",
|
|
87
84
|
"@tscircuit/pcb-viewer": "^1.11.194",
|
|
88
85
|
"@tscircuit/prompt-benchmarks": "^0.0.28",
|
|
89
|
-
"@tscircuit/props": "^0.0.246",
|
|
90
86
|
"@tscircuit/runframe": "^0.0.669",
|
|
91
87
|
"@tscircuit/schematic-viewer": "^2.0.21",
|
|
92
88
|
"@types/babel__standalone": "^7.1.7",
|
|
@@ -108,7 +104,6 @@
|
|
|
108
104
|
"@vitejs/plugin-react": "^4.3.1",
|
|
109
105
|
"autoprefixer": "^10.4.20",
|
|
110
106
|
"change-case": "^5.4.4",
|
|
111
|
-
"circuit-json": "^0.0.190",
|
|
112
107
|
"circuit-json-to-bom-csv": "^0.0.7",
|
|
113
108
|
"circuit-json-to-gerber": "^0.0.25",
|
|
114
109
|
"circuit-json-to-pnp-csv": "^0.0.7",
|
|
@@ -124,7 +119,7 @@
|
|
|
124
119
|
"date-fns": "^4.1.0",
|
|
125
120
|
"dotenv": "^16.5.0",
|
|
126
121
|
"dsn-converter": "^0.0.60",
|
|
127
|
-
"easyeda": "^0.0.
|
|
122
|
+
"easyeda": "^0.0.203",
|
|
128
123
|
"embla-carousel-react": "^8.3.0",
|
|
129
124
|
"extract-codefence": "^0.0.4",
|
|
130
125
|
"fflate": "^0.8.2",
|
|
@@ -139,7 +134,7 @@
|
|
|
139
134
|
"jose": "^5.9.3",
|
|
140
135
|
"jscad-electronics": "^0.0.25",
|
|
141
136
|
"jszip": "^3.10.1",
|
|
142
|
-
"kicad-converter": "^0.0.
|
|
137
|
+
"kicad-converter": "^0.0.17",
|
|
143
138
|
"ky": "^1.7.5",
|
|
144
139
|
"lucide-react": "^0.488.0",
|
|
145
140
|
"lz-string": "^1.5.0",
|
|
@@ -179,6 +174,7 @@
|
|
|
179
174
|
"terser": "^5.27.0",
|
|
180
175
|
"three": "^0.177.0",
|
|
181
176
|
"three-stdlib": "^2.36.0",
|
|
177
|
+
"tscircuit": "^0.0.522",
|
|
182
178
|
"tsup": "^8.5.0",
|
|
183
179
|
"typescript": "^5.6.3",
|
|
184
180
|
"use-async-memo": "^1.2.5",
|
package/src/ContextProviders.tsx
CHANGED
|
@@ -4,7 +4,6 @@ import { useEffect } from "react"
|
|
|
4
4
|
import { useGlobalStore } from "./hooks/use-global-store"
|
|
5
5
|
import { posthog } from "./lib/posthog"
|
|
6
6
|
import { Toaster } from "react-hot-toast"
|
|
7
|
-
import { Toaster as SonnerToaster } from "@/components/ui/sonner"
|
|
8
7
|
import { populateQueryCacheWithSSRData } from "./lib/populate-query-cache-with-ssr-data"
|
|
9
8
|
|
|
10
9
|
const staffGithubUsernames = [
|
|
@@ -66,7 +65,6 @@ export const ContextProviders = ({ children }: any) => {
|
|
|
66
65
|
<PostHogIdentifier />
|
|
67
66
|
{children}
|
|
68
67
|
<Toaster position="bottom-right" />
|
|
69
|
-
<SonnerToaster position="bottom-left" />
|
|
70
68
|
</HelmetProvider>
|
|
71
69
|
</QueryClientProvider>
|
|
72
70
|
)
|
|
@@ -3,7 +3,7 @@ import { useAxios } from "@/hooks/use-axios"
|
|
|
3
3
|
import { useLocation } from "wouter"
|
|
4
4
|
import React, { useState } from "react"
|
|
5
5
|
import { useQuery } from "react-query"
|
|
6
|
-
import {
|
|
6
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
7
7
|
import { Search } from "lucide-react"
|
|
8
8
|
import { Button } from "./ui/button"
|
|
9
9
|
import { PackageCardSkeleton } from "./PackageCardSkeleton"
|
|
@@ -20,7 +20,7 @@ const PageSearchComponent: React.FC<PageSearchComponentProps> = ({
|
|
|
20
20
|
}) => {
|
|
21
21
|
const [location, setLocation] = useLocation()
|
|
22
22
|
const axios = useAxios()
|
|
23
|
-
const snippetsBaseApiUrl =
|
|
23
|
+
const snippetsBaseApiUrl = usePackagesBaseApiUrl()
|
|
24
24
|
|
|
25
25
|
// Initialize search query directly from URL
|
|
26
26
|
const [searchQuery, setSearchQuery] = useState(
|
|
@@ -4,7 +4,7 @@ import { useLocation } from "wouter"
|
|
|
4
4
|
import React, { useEffect, useRef, useState } from "react"
|
|
5
5
|
import { useQuery } from "react-query"
|
|
6
6
|
import { Alert } from "./ui/alert"
|
|
7
|
-
import {
|
|
7
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
8
8
|
import { PrefetchPageLink } from "./PrefetchPageLink"
|
|
9
9
|
import { CircuitBoard } from "lucide-react"
|
|
10
10
|
import { cn } from "@/lib/utils"
|
|
@@ -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 snippetsBaseApiUrl =
|
|
63
|
+
const snippetsBaseApiUrl = usePackagesBaseApiUrl()
|
|
64
64
|
|
|
65
65
|
const { data: searchResults, isLoading } = useQuery(
|
|
66
66
|
["packageSearch", searchQuery],
|
|
@@ -4,7 +4,7 @@ import { StarFilledIcon } from "@radix-ui/react-icons"
|
|
|
4
4
|
import { Link } from "wouter"
|
|
5
5
|
import { Package } from "fake-snippets-api/lib/db/schema"
|
|
6
6
|
import { useRef, useState } from "react"
|
|
7
|
-
import {
|
|
7
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
8
8
|
|
|
9
9
|
const CarouselItem = ({
|
|
10
10
|
pkg,
|
|
@@ -36,7 +36,7 @@ export const TrendingPackagesCarousel = () => {
|
|
|
36
36
|
const axios = useAxios()
|
|
37
37
|
const scrollRef = useRef<HTMLDivElement>(null)
|
|
38
38
|
const [isHovered, setIsHovered] = useState(false)
|
|
39
|
-
const apiBaseUrl =
|
|
39
|
+
const apiBaseUrl = usePackagesBaseApiUrl()
|
|
40
40
|
|
|
41
41
|
const { data: trendingPackages } = useQuery<Package[]>(
|
|
42
42
|
"trendingPackages",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createUseDialog } from "./create-use-dialog"
|
|
2
|
+
import {
|
|
3
|
+
ComponentSearchResult,
|
|
4
|
+
ImportComponentDialog as RunframeImportComponentDialog,
|
|
5
|
+
} from "@tscircuit/runframe/runner"
|
|
6
|
+
|
|
7
|
+
export const ImportComponentDialog = ({
|
|
8
|
+
open,
|
|
9
|
+
onOpenChange,
|
|
10
|
+
onComponentSelected,
|
|
11
|
+
}: {
|
|
12
|
+
open: boolean
|
|
13
|
+
onOpenChange: (open: boolean) => any
|
|
14
|
+
onComponentSelected: (pkg: ComponentSearchResult) => any
|
|
15
|
+
}) => {
|
|
16
|
+
return (
|
|
17
|
+
<RunframeImportComponentDialog
|
|
18
|
+
isOpen={open}
|
|
19
|
+
onClose={() => onOpenChange(false)}
|
|
20
|
+
onImport={(data) => onComponentSelected(data)}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const useImportComponentDialog = createUseDialog(ImportComponentDialog)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
2
2
|
import { useHotkeyCombo } from "@/hooks/use-hotkey"
|
|
3
3
|
import { basicSetup } from "@/lib/codemirror/basic-setup"
|
|
4
4
|
import {
|
|
@@ -82,7 +82,7 @@ export const CodeEditor = ({
|
|
|
82
82
|
const viewRef = useRef<EditorView | null>(null)
|
|
83
83
|
const ataRef = useRef<ReturnType<typeof setupTypeAcquisition> | null>(null)
|
|
84
84
|
const lastReceivedTsFileTimeRef = useRef<number>(0)
|
|
85
|
-
const apiUrl =
|
|
85
|
+
const apiUrl = usePackagesBaseApiUrl()
|
|
86
86
|
const codeCompletionApi = useCodeCompletionApi()
|
|
87
87
|
const [cursorPosition, setCursorPosition] = useState<number | null>(null)
|
|
88
88
|
const [code, setCode] = useState(files[0]?.content || "")
|
|
@@ -329,17 +329,20 @@ export const CodeEditor = ({
|
|
|
329
329
|
if (aiAutocompleteEnabled) {
|
|
330
330
|
baseExtensions.push(
|
|
331
331
|
inlineCopilot(async (prefix, suffix) => {
|
|
332
|
-
const res = await fetch(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
332
|
+
const res = await fetch(
|
|
333
|
+
`${apiUrl}/autocomplete/create_autocomplete`,
|
|
334
|
+
{
|
|
335
|
+
method: "POST",
|
|
336
|
+
headers: {
|
|
337
|
+
"Content-Type": "application/json",
|
|
338
|
+
},
|
|
339
|
+
body: JSON.stringify({
|
|
340
|
+
prefix,
|
|
341
|
+
suffix,
|
|
342
|
+
language: "typescript",
|
|
343
|
+
}),
|
|
336
344
|
},
|
|
337
|
-
|
|
338
|
-
prefix,
|
|
339
|
-
suffix,
|
|
340
|
-
language: "typescript",
|
|
341
|
-
}),
|
|
342
|
-
})
|
|
345
|
+
)
|
|
343
346
|
|
|
344
347
|
const { prediction } = await res.json()
|
|
345
348
|
return prediction
|
|
@@ -661,6 +664,10 @@ export const CodeEditor = ({
|
|
|
661
664
|
{showImportAndFormatButtons && (
|
|
662
665
|
<CodeEditorHeader
|
|
663
666
|
entrypointFileName={entryPointFileName}
|
|
667
|
+
appendNewFile={(path: string, content: string) => {
|
|
668
|
+
onFileContentChanged?.(path, content)
|
|
669
|
+
}}
|
|
670
|
+
createFile={handleCreateFile}
|
|
664
671
|
fileSidebarState={
|
|
665
672
|
[sidebarOpen, setSidebarOpen] as ReturnType<
|
|
666
673
|
typeof useState<boolean>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState, useCallback } from "react"
|
|
2
2
|
import { Button } from "@/components/ui/button"
|
|
3
3
|
import { handleManualEditsImportWithSupportForMultipleFiles } from "@/lib/handleManualEditsImportWithSupportForMultipleFiles"
|
|
4
|
-
import {
|
|
4
|
+
import { useImportComponentDialog } from "@/components/dialogs/import-component-dialog"
|
|
5
5
|
import { useToast } from "@/hooks/use-toast"
|
|
6
6
|
import {
|
|
7
7
|
DropdownMenu,
|
|
@@ -19,14 +19,16 @@ import {
|
|
|
19
19
|
SelectValue,
|
|
20
20
|
} from "../ui/select"
|
|
21
21
|
import { isHiddenFile } from "../ViewPackagePage/utils/is-hidden-file"
|
|
22
|
-
import { Package } from "fake-snippets-api/lib/db/schema"
|
|
23
22
|
import {
|
|
24
23
|
Tooltip,
|
|
25
24
|
TooltipContent,
|
|
26
25
|
TooltipProvider,
|
|
27
26
|
TooltipTrigger,
|
|
28
27
|
} from "@/components/ui/tooltip"
|
|
29
|
-
import
|
|
28
|
+
import { convertRawEasyToTsx, fetchEasyEDAComponent } from "easyeda/browser"
|
|
29
|
+
import { ComponentSearchResult } from "@tscircuit/runframe/runner"
|
|
30
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
31
|
+
import { ICreateFileProps, ICreateFileResult } from "@/hooks/useFileManagement"
|
|
30
32
|
|
|
31
33
|
export type FileName = string
|
|
32
34
|
|
|
@@ -37,6 +39,8 @@ interface CodeEditorHeaderProps {
|
|
|
37
39
|
fileSidebarState: ReturnType<typeof useState<boolean>>
|
|
38
40
|
handleFileChange: (filename: FileName) => void
|
|
39
41
|
entrypointFileName?: string
|
|
42
|
+
appendNewFile: (path: string, content: string) => void
|
|
43
|
+
createFile: (props: ICreateFileProps) => ICreateFileResult
|
|
40
44
|
aiAutocompleteState: [boolean, React.Dispatch<React.SetStateAction<boolean>>]
|
|
41
45
|
}
|
|
42
46
|
|
|
@@ -44,15 +48,18 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
|
|
|
44
48
|
currentFile,
|
|
45
49
|
files,
|
|
46
50
|
updateFileContent,
|
|
51
|
+
appendNewFile,
|
|
47
52
|
fileSidebarState,
|
|
48
53
|
handleFileChange,
|
|
49
54
|
entrypointFileName = "index.tsx",
|
|
55
|
+
createFile,
|
|
50
56
|
aiAutocompleteState,
|
|
51
57
|
}) => {
|
|
52
|
-
const { Dialog:
|
|
53
|
-
|
|
54
|
-
const { toast } = useToast()
|
|
58
|
+
const { Dialog: ImportComponentDialog, openDialog: openImportDialog } =
|
|
59
|
+
useImportComponentDialog()
|
|
60
|
+
const { toast, toastLibrary } = useToast()
|
|
55
61
|
const [sidebarOpen, setSidebarOpen] = fileSidebarState
|
|
62
|
+
const API_BASE = usePackagesBaseApiUrl()
|
|
56
63
|
const [aiAutocompleteEnabled, setAiAutocompleteEnabled] = aiAutocompleteState
|
|
57
64
|
|
|
58
65
|
const handleFormatFile = useCallback(() => {
|
|
@@ -144,6 +151,49 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
|
|
|
144
151
|
}
|
|
145
152
|
}, [currentFile, files, toast, updateFileContent])
|
|
146
153
|
|
|
154
|
+
const handleComponentImport = async (component: ComponentSearchResult) => {
|
|
155
|
+
if (component.source == "tscircuit.com") {
|
|
156
|
+
const newContent = `import {} from "@tsci/${component.owner}.${component.name}"\n${files[currentFile || ""]}`
|
|
157
|
+
updateFileContent(currentFile, newContent)
|
|
158
|
+
}
|
|
159
|
+
if (component.source == "jlcpcb") {
|
|
160
|
+
const jlcpcbComponent = await fetchEasyEDAComponent("C1", {
|
|
161
|
+
fetch: ((url, options: any) => {
|
|
162
|
+
return fetch(`${API_BASE}/proxy`, {
|
|
163
|
+
...options,
|
|
164
|
+
headers: {
|
|
165
|
+
...options?.headers,
|
|
166
|
+
"X-Target-Url": url.toString(),
|
|
167
|
+
"X-Sender-Origin": options?.headers?.origin ?? "",
|
|
168
|
+
"X-Sender-Host": options?.headers?.host ?? "https://easyeda.com",
|
|
169
|
+
"X-Sender-Referer": options?.headers?.referer ?? "",
|
|
170
|
+
"X-Sender-User-Agent": options?.headers?.userAgent ?? "",
|
|
171
|
+
"X-Sender-Cookie": options?.headers?.cookie ?? "",
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
}) as typeof fetch,
|
|
175
|
+
})
|
|
176
|
+
const tsxComponent = await convertRawEasyToTsx(jlcpcbComponent)
|
|
177
|
+
let componentName = component.name.replace(/ /g, "-")
|
|
178
|
+
if (files[`${componentName}.tsx`] || files[`./${componentName}.tsx`]) {
|
|
179
|
+
componentName = `${componentName}-1`
|
|
180
|
+
}
|
|
181
|
+
const createFileResult = createFile({
|
|
182
|
+
newFileName: `${componentName}.tsx`,
|
|
183
|
+
content: tsxComponent,
|
|
184
|
+
onError: (error) => {
|
|
185
|
+
throw error
|
|
186
|
+
},
|
|
187
|
+
openFile: false,
|
|
188
|
+
})
|
|
189
|
+
if (!createFileResult.newFileCreated) {
|
|
190
|
+
throw new Error("Failed to create file")
|
|
191
|
+
}
|
|
192
|
+
const newContent = `import ${componentName.replace(/-/g, "")} from "./${componentName}.tsx"\n${files[currentFile || ""]}`
|
|
193
|
+
updateFileContent(currentFile, newContent)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
147
197
|
return (
|
|
148
198
|
<>
|
|
149
199
|
<div className="flex items-center gap-2 px-2 border-b border-gray-200">
|
|
@@ -275,10 +325,17 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
|
|
|
275
325
|
Format
|
|
276
326
|
</Button>
|
|
277
327
|
</div>
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
328
|
+
<ImportComponentDialog
|
|
329
|
+
onComponentSelected={async (component) => {
|
|
330
|
+
toastLibrary.promise(handleComponentImport(component), {
|
|
331
|
+
loading: "Importing component...",
|
|
332
|
+
success: <p>Component imported successfully!</p>,
|
|
333
|
+
error: (error) => (
|
|
334
|
+
<p>
|
|
335
|
+
Error importing component: {error.message || String(error)}
|
|
336
|
+
</p>
|
|
337
|
+
),
|
|
338
|
+
})
|
|
282
339
|
}}
|
|
283
340
|
/>
|
|
284
341
|
</div>
|
|
@@ -385,60 +385,66 @@ export default function EditorNav({
|
|
|
385
385
|
<File className="mr-2 h-3 w-3" />
|
|
386
386
|
View Files
|
|
387
387
|
</DropdownMenuItem>
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
388
|
+
{session?.github_username === pkg.owner_github_username && (
|
|
389
|
+
<>
|
|
390
|
+
<DropdownMenuSub>
|
|
391
|
+
<DropdownMenuSubTrigger
|
|
392
|
+
className="text-xs"
|
|
393
|
+
disabled={isChangingType || hasUnsavedChanges}
|
|
394
|
+
>
|
|
395
|
+
<Edit2 className="mr-2 h-3 w-3" />
|
|
396
|
+
{isChangingType ? "Changing..." : "Change Type"}
|
|
397
|
+
</DropdownMenuSubTrigger>
|
|
398
|
+
<DropdownMenuSubContent>
|
|
399
|
+
<DropdownMenuItem
|
|
400
|
+
className="text-xs"
|
|
401
|
+
disabled={currentType === "board" || isChangingType}
|
|
402
|
+
onClick={() => handleTypeChange("board")}
|
|
403
|
+
>
|
|
404
|
+
Board {currentType === "board" && "✓"}
|
|
405
|
+
</DropdownMenuItem>
|
|
406
|
+
<DropdownMenuItem
|
|
407
|
+
className="text-xs"
|
|
408
|
+
disabled={currentType === "package" || isChangingType}
|
|
409
|
+
onClick={() => handleTypeChange("package")}
|
|
410
|
+
>
|
|
411
|
+
Module {currentType === "package" && "✓"}
|
|
412
|
+
</DropdownMenuItem>
|
|
413
|
+
</DropdownMenuSubContent>
|
|
414
|
+
</DropdownMenuSub>
|
|
415
|
+
<DropdownMenuSub>
|
|
416
|
+
<DropdownMenuSubTrigger className="text-xs">
|
|
417
|
+
<Edit2 className="mr-2 h-3 w-3" />
|
|
418
|
+
Change Package Visibility
|
|
419
|
+
</DropdownMenuSubTrigger>
|
|
420
|
+
<DropdownMenuSubContent>
|
|
421
|
+
<DropdownMenuItem
|
|
422
|
+
className="text-xs"
|
|
423
|
+
disabled={isPrivate}
|
|
424
|
+
onClick={() => updatePackageVisibilityToPrivate(true)}
|
|
425
|
+
>
|
|
426
|
+
Private {isPrivate && "✓"}
|
|
427
|
+
</DropdownMenuItem>
|
|
428
|
+
<DropdownMenuItem
|
|
429
|
+
className="text-xs"
|
|
430
|
+
disabled={!isPrivate}
|
|
431
|
+
onClick={() =>
|
|
432
|
+
updatePackageVisibilityToPrivate(false)
|
|
433
|
+
}
|
|
434
|
+
>
|
|
435
|
+
Public {!isPrivate && "✓"}
|
|
436
|
+
</DropdownMenuItem>
|
|
437
|
+
</DropdownMenuSubContent>
|
|
438
|
+
</DropdownMenuSub>
|
|
397
439
|
<DropdownMenuItem
|
|
398
|
-
className="text-xs"
|
|
399
|
-
|
|
400
|
-
onClick={() => handleTypeChange("board")}
|
|
440
|
+
className="text-xs text-red-600"
|
|
441
|
+
onClick={() => openDeleteDialog()}
|
|
401
442
|
>
|
|
402
|
-
|
|
443
|
+
<Trash2 className="mr-2 h-3 w-3" />
|
|
444
|
+
Delete Package
|
|
403
445
|
</DropdownMenuItem>
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
disabled={currentType === "package" || isChangingType}
|
|
407
|
-
onClick={() => handleTypeChange("package")}
|
|
408
|
-
>
|
|
409
|
-
Module {currentType === "package" && "✓"}
|
|
410
|
-
</DropdownMenuItem>
|
|
411
|
-
</DropdownMenuSubContent>
|
|
412
|
-
</DropdownMenuSub>
|
|
413
|
-
<DropdownMenuSub>
|
|
414
|
-
<DropdownMenuSubTrigger className="text-xs">
|
|
415
|
-
<Edit2 className="mr-2 h-3 w-3" />
|
|
416
|
-
Change Package Visibility
|
|
417
|
-
</DropdownMenuSubTrigger>
|
|
418
|
-
<DropdownMenuSubContent>
|
|
419
|
-
<DropdownMenuItem
|
|
420
|
-
className="text-xs"
|
|
421
|
-
disabled={isPrivate}
|
|
422
|
-
onClick={() => updatePackageVisibilityToPrivate(true)}
|
|
423
|
-
>
|
|
424
|
-
Private {isPrivate && "✓"}
|
|
425
|
-
</DropdownMenuItem>
|
|
426
|
-
<DropdownMenuItem
|
|
427
|
-
className="text-xs"
|
|
428
|
-
disabled={!isPrivate}
|
|
429
|
-
onClick={() => updatePackageVisibilityToPrivate(false)}
|
|
430
|
-
>
|
|
431
|
-
Public {!isPrivate && "✓"}
|
|
432
|
-
</DropdownMenuItem>
|
|
433
|
-
</DropdownMenuSubContent>
|
|
434
|
-
</DropdownMenuSub>
|
|
435
|
-
<DropdownMenuItem
|
|
436
|
-
className="text-xs text-red-600"
|
|
437
|
-
onClick={() => openDeleteDialog()}
|
|
438
|
-
>
|
|
439
|
-
<Trash2 className="mr-2 h-3 w-3" />
|
|
440
|
-
Delete Package
|
|
441
|
-
</DropdownMenuItem>
|
|
446
|
+
</>
|
|
447
|
+
)}
|
|
442
448
|
<DropdownMenuItem className="text-xs text-gray-500" disabled>
|
|
443
449
|
@tscircuit/core@{tscircuitCorePkg.version}
|
|
444
450
|
</DropdownMenuItem>
|
package/src/hooks/use-axios.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import axios from "redaxios"
|
|
2
2
|
import { useMemo } from "react"
|
|
3
|
-
import { useSnippetsBaseApiUrl } from "./use-snippets-base-api-url"
|
|
4
3
|
import { useGlobalStore } from "./use-global-store"
|
|
4
|
+
import { usePackagesBaseApiUrl } from "./use-packages-base-api-url"
|
|
5
5
|
|
|
6
6
|
export const useAxios = () => {
|
|
7
|
-
const snippetsBaseApiUrl =
|
|
7
|
+
const snippetsBaseApiUrl = usePackagesBaseApiUrl()
|
|
8
8
|
const session = useGlobalStore((s) => s.session)
|
|
9
9
|
return useMemo(() => {
|
|
10
10
|
const instance = axios.create({
|
|
@@ -34,7 +34,7 @@ export const useRequestAiReviewMutation = ({
|
|
|
34
34
|
onSuccess: ({ package_release, ai_review }) => {
|
|
35
35
|
toast({
|
|
36
36
|
title: "AI review requested",
|
|
37
|
-
description: "An AI review has been
|
|
37
|
+
description: "An AI review has been requested.",
|
|
38
38
|
})
|
|
39
39
|
queryClient.invalidateQueries(["packageRelease"])
|
|
40
40
|
onSuccess?.(package_release, ai_review)
|
package/src/hooks/use-sign-in.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useGlobalStore } from "./use-global-store"
|
|
2
2
|
import { useIsUsingFakeApi } from "./use-is-using-fake-api"
|
|
3
|
-
import {
|
|
3
|
+
import { usePackagesBaseApiUrl } from "./use-packages-base-api-url"
|
|
4
4
|
|
|
5
5
|
export const useSignIn = () => {
|
|
6
|
-
const snippetsBaseApiUrl =
|
|
6
|
+
const snippetsBaseApiUrl = usePackagesBaseApiUrl()
|
|
7
7
|
const isUsingFakeApi = useIsUsingFakeApi()
|
|
8
8
|
const setSession = useGlobalStore((s) => s.setSession)
|
|
9
9
|
return () => {
|
package/src/hooks/use-toast.tsx
CHANGED
|
@@ -20,7 +20,9 @@ import { encodeFsMapToUrlHash } from "@/lib/encodeFsMapToUrlHash"
|
|
|
20
20
|
|
|
21
21
|
export interface ICreateFileProps {
|
|
22
22
|
newFileName: string
|
|
23
|
+
content?: string
|
|
23
24
|
onError: (error: Error) => void
|
|
25
|
+
openFile?: boolean
|
|
24
26
|
}
|
|
25
27
|
export interface ICreateFileResult {
|
|
26
28
|
newFileCreated: boolean
|
|
@@ -182,6 +184,8 @@ export function useFileManagement({
|
|
|
182
184
|
const createFile = ({
|
|
183
185
|
newFileName,
|
|
184
186
|
onError,
|
|
187
|
+
content,
|
|
188
|
+
openFile = true,
|
|
185
189
|
}: ICreateFileProps): ICreateFileResult => {
|
|
186
190
|
newFileName = newFileName.trim()
|
|
187
191
|
if (!newFileName) {
|
|
@@ -206,11 +210,12 @@ export function useFileManagement({
|
|
|
206
210
|
}
|
|
207
211
|
const updatedFiles = [
|
|
208
212
|
...(localFiles || []),
|
|
209
|
-
{ path: newFileName, content: "" },
|
|
213
|
+
{ path: newFileName, content: content || "" },
|
|
210
214
|
]
|
|
211
215
|
setLocalFiles(updatedFiles)
|
|
212
|
-
|
|
213
|
-
|
|
216
|
+
if (openFile) {
|
|
217
|
+
setCurrentFile(newFileName)
|
|
218
|
+
}
|
|
214
219
|
return {
|
|
215
220
|
newFileCreated: true,
|
|
216
221
|
}
|
package/src/main.tsx
CHANGED
|
@@ -6,9 +6,6 @@ if (typeof window !== "undefined" && !window.__APP_LOADED_AT) {
|
|
|
6
6
|
window.__APP_LOADED_AT = Date.now()
|
|
7
7
|
}
|
|
8
8
|
import "./index.css"
|
|
9
|
-
import { setupBuildWatcher } from "./build-watcher"
|
|
10
|
-
|
|
11
|
-
setupBuildWatcher()
|
|
12
9
|
|
|
13
10
|
createRoot(document.getElementById("root")!).render(
|
|
14
11
|
<StrictMode>
|
package/src/pages/dashboard.tsx
CHANGED
|
@@ -12,7 +12,7 @@ import { PrefetchPageLink } from "@/components/PrefetchPageLink"
|
|
|
12
12
|
import { PackagesList } from "@/components/PackagesList"
|
|
13
13
|
import { Helmet } from "react-helmet-async"
|
|
14
14
|
import { useSignIn } from "@/hooks/use-sign-in"
|
|
15
|
-
import {
|
|
15
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
16
16
|
import { useConfirmDeletePackageDialog } from "@/components/dialogs/confirm-delete-package-dialog"
|
|
17
17
|
import { PackageCardSkeleton } from "@/components/PackageCardSkeleton"
|
|
18
18
|
import { PackageCard } from "@/components/PackageCard"
|
|
@@ -81,7 +81,7 @@ export const DashboardPage = () => {
|
|
|
81
81
|
},
|
|
82
82
|
)
|
|
83
83
|
|
|
84
|
-
const baseUrl =
|
|
84
|
+
const baseUrl = usePackagesBaseApiUrl()
|
|
85
85
|
|
|
86
86
|
const handleDeleteClick = (e: React.MouseEvent, pkg: Package) => {
|
|
87
87
|
e.preventDefault() // Prevent navigation
|
package/src/pages/dev-login.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
2
|
-
import {
|
|
2
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
3
3
|
import { useState } from "react"
|
|
4
4
|
import { useLocation } from "wouter"
|
|
5
5
|
|
|
6
6
|
export const DevLoginPage = () => {
|
|
7
|
-
const snippetsBaseApiUrl =
|
|
7
|
+
const snippetsBaseApiUrl = usePackagesBaseApiUrl()
|
|
8
8
|
const [username, setUsername] = useState("")
|
|
9
9
|
const setSession = useGlobalStore((s) => s.setSession)
|
|
10
10
|
const [, setLocation] = useLocation()
|
package/src/pages/latest.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import Header from "@/components/Header"
|
|
|
6
6
|
import Footer from "@/components/Footer"
|
|
7
7
|
import { Search, Keyboard, Cpu, Layers, LucideBellElectric } from "lucide-react"
|
|
8
8
|
import { Input } from "@/components/ui/input"
|
|
9
|
-
import {
|
|
9
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
10
10
|
import {
|
|
11
11
|
Select,
|
|
12
12
|
SelectContent,
|
|
@@ -18,7 +18,7 @@ import PackageSearchResults from "@/components/PackageSearchResults"
|
|
|
18
18
|
|
|
19
19
|
const LatestPage: React.FC = () => {
|
|
20
20
|
const axios = useAxios()
|
|
21
|
-
const apiBaseUrl =
|
|
21
|
+
const apiBaseUrl = usePackagesBaseApiUrl()
|
|
22
22
|
const [searchQuery, setSearchQuery] = useState("")
|
|
23
23
|
const [category, setCategory] = useState("all")
|
|
24
24
|
|
package/src/pages/search.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import Footer from "@/components/Footer"
|
|
|
7
7
|
import { Input } from "@/components/ui/input"
|
|
8
8
|
import { Search } from "lucide-react"
|
|
9
9
|
import PackageSearchResults from "@/components/PackageSearchResults"
|
|
10
|
-
import {
|
|
10
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
11
11
|
import {
|
|
12
12
|
Select,
|
|
13
13
|
SelectContent,
|
|
@@ -19,7 +19,7 @@ import { Package } from "fake-snippets-api/lib/db/schema"
|
|
|
19
19
|
|
|
20
20
|
export const SearchPage = () => {
|
|
21
21
|
const axios = useAxios()
|
|
22
|
-
const apiBaseUrl =
|
|
22
|
+
const apiBaseUrl = usePackagesBaseApiUrl()
|
|
23
23
|
const [searchParams, setSearchParams] = useSearchParams()
|
|
24
24
|
|
|
25
25
|
const [searchQuery, setSearchQuery] = useState(searchParams.get("q") || "")
|
package/src/pages/trending.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { useAxios } from "@/hooks/use-axios"
|
|
|
4
4
|
import Header from "@/components/Header"
|
|
5
5
|
import Footer from "@/components/Footer"
|
|
6
6
|
import { useSearchParams } from "wouter"
|
|
7
|
-
import {
|
|
7
|
+
import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
|
|
8
8
|
import { Search, Keyboard, Cpu, Layers, LucideBellElectric } from "lucide-react"
|
|
9
9
|
import { Input } from "@/components/ui/input"
|
|
10
10
|
import {
|
|
@@ -19,7 +19,7 @@ import PackageSearchResults from "@/components/PackageSearchResults"
|
|
|
19
19
|
|
|
20
20
|
const TrendingPage: React.FC = () => {
|
|
21
21
|
const axios = useAxios()
|
|
22
|
-
const apiBaseUrl =
|
|
22
|
+
const apiBaseUrl = usePackagesBaseApiUrl()
|
|
23
23
|
const [searchParams, setSearchParams] = useSearchParams()
|
|
24
24
|
|
|
25
25
|
const [searchQuery, setSearchQuery] = useState(searchParams.get("q") || "")
|